]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
4b3eb370237499f882ca953c2f7dfbbddb3d8af3
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConIn.c
1 /**@file
2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
3
4 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Terminal.h"
16
17
18 STATIC
19 EFI_STATUS
20 ReadKeyStrokeWorker (
21 IN TERMINAL_DEV *TerminalDevice,
22 OUT EFI_KEY_DATA *KeyData
23 )
24 /*++
25
26 Routine Description:
27 Reads the next keystroke from the input device. The WaitForKey Event can
28 be used to test for existance of a keystroke via WaitForEvent () call.
29
30 Arguments:
31 TerminalDevice - Terminal driver private structure
32 KeyData - A pointer to a buffer that is filled in with the keystroke
33 state data for the key that was pressed.
34
35 Returns:
36 EFI_SUCCESS - The keystroke information was returned.
37 EFI_NOT_READY - There was no keystroke data availiable.
38 EFI_DEVICE_ERROR - The keystroke information was not returned due to
39 hardware errors.
40 EFI_INVALID_PARAMETER - KeyData is NULL.
41
42 --*/
43 {
44 EFI_STATUS Status;
45 LIST_ENTRY *Link;
46 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
47
48 if (KeyData == NULL) {
49 return EFI_INVALID_PARAMETER;
50 }
51
52 //
53 // Initialize *Key to nonsense value.
54 //
55 KeyData->Key.ScanCode = SCAN_NULL;
56 KeyData->Key.UnicodeChar = 0;
57
58 Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput);
59 if (EFI_ERROR (Status)) {
60 return EFI_NOT_READY;
61 }
62
63 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {
64 return EFI_NOT_READY;
65 }
66
67 KeyData->KeyState.KeyShiftState = 0;
68 KeyData->KeyState.KeyToggleState = 0;
69
70 //
71 // Invoke notification functions if exist
72 //
73 for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {
74 CurrentNotify = CR (
75 Link,
76 TERMINAL_CONSOLE_IN_EX_NOTIFY,
77 NotifyEntry,
78 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
79 );
80 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
81 CurrentNotify->KeyNotificationFn (KeyData);
82 }
83 }
84
85 return EFI_SUCCESS;
86
87 }
88
89
90 EFI_STATUS
91 EFIAPI
92 TerminalConInReset (
93 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
94 IN BOOLEAN ExtendedVerification
95 )
96 /*++
97 Routine Description:
98
99 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
100 This driver only perform dependent serial device reset regardless of
101 the value of ExtendeVerification
102
103 Arguments:
104
105 This - Indicates the calling context.
106
107 ExtendedVerification - Skip by this driver.
108
109 Returns:
110
111 EFI_SUCCESS
112 The reset operation succeeds.
113
114 EFI_DEVICE_ERROR
115 The dependent serial port reset fails.
116
117 --*/
118 {
119 EFI_STATUS Status;
120 TERMINAL_DEV *TerminalDevice;
121
122 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
123
124 //
125 // Report progress code here
126 //
127 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
128 EFI_PROGRESS_CODE,
129 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),
130 TerminalDevice->DevicePath
131 );
132
133 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
134
135 //
136 // clear all the internal buffer for keys
137 //
138 InitializeRawFiFo (TerminalDevice);
139 InitializeUnicodeFiFo (TerminalDevice);
140 InitializeEfiKeyFiFo (TerminalDevice);
141
142 if (EFI_ERROR (Status)) {
143 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
144 EFI_ERROR_CODE | EFI_ERROR_MINOR,
145 PcdGet32 (PcdStatusCodeValueRemoteConsoleError),
146 TerminalDevice->DevicePath
147 );
148 }
149
150 return Status;
151 }
152
153 EFI_STATUS
154 EFIAPI
155 TerminalConInReadKeyStroke (
156 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
157 OUT EFI_INPUT_KEY *Key
158 )
159 /*++
160 Routine Description:
161
162 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
163
164 Arguments:
165
166 This - Indicates the calling context.
167
168 Key - A pointer to a buffer that is filled in with the keystroke
169 information for the key that was sent from terminal.
170
171 Returns:
172
173 EFI_SUCCESS
174 The keystroke information is returned successfully.
175
176 EFI_NOT_READY
177 There is no keystroke data available.
178
179 EFI_DEVICE_ERROR
180 The dependent serial device encounters error.
181
182 --*/
183 {
184 TERMINAL_DEV *TerminalDevice;
185 EFI_STATUS Status;
186 EFI_KEY_DATA KeyData;
187
188 //
189 // get TERMINAL_DEV from "This" parameter.
190 //
191 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
192
193 Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);
194 if (EFI_ERROR (Status)) {
195 return Status;
196 }
197
198 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
199
200 return EFI_SUCCESS;
201
202 }
203
204
205 BOOLEAN
206 IsKeyRegistered (
207 IN EFI_KEY_DATA *RegsiteredData,
208 IN EFI_KEY_DATA *InputData
209 )
210 /*++
211
212 Routine Description:
213
214 Arguments:
215
216 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
217 state data for the key that was registered.
218 InputData - A pointer to a buffer that is filled in with the keystroke
219 state data for the key that was pressed.
220
221 Returns:
222 TRUE - Key be pressed matches a registered key.
223 FLASE - Match failed.
224
225 --*/
226 {
227 ASSERT (RegsiteredData != NULL && InputData != NULL);
228
229 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
230 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
231 return FALSE;
232 }
233
234 return TRUE;
235 }
236
237
238 VOID
239 EFIAPI
240 TerminalConInWaitForKeyEx (
241 IN EFI_EVENT Event,
242 IN VOID *Context
243 )
244 /*++
245 Routine Description:
246
247 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
248 Signal the event if there is key available
249
250 Arguments:
251
252 Event - Indicates the event that invoke this function.
253
254 Context - Indicates the calling context.
255
256 Returns:
257
258 N/A
259
260 --*/
261 {
262 TERMINAL_DEV *TerminalDevice;
263
264 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context);
265
266 TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput);
267
268 }
269
270 //
271 // Simple Text Input Ex protocol functions
272 //
273
274 EFI_STATUS
275 EFIAPI
276 TerminalConInResetEx (
277 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
278 IN BOOLEAN ExtendedVerification
279 )
280 /*++
281
282 Routine Description:
283 Reset the input device and optionaly run diagnostics
284
285 Arguments:
286 This - Protocol instance pointer.
287 ExtendedVerification - Driver may perform diagnostics on reset.
288
289 Returns:
290 EFI_SUCCESS - The device was reset.
291 EFI_DEVICE_ERROR - The device is not functioning properly and could
292 not be reset.
293
294 --*/
295 {
296 EFI_STATUS Status;
297 TERMINAL_DEV *TerminalDevice;
298
299 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
300
301 Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);
302 if (EFI_ERROR (Status)) {
303 return EFI_DEVICE_ERROR;
304 }
305
306 return EFI_SUCCESS;
307
308 }
309
310 EFI_STATUS
311 EFIAPI
312 TerminalConInReadKeyStrokeEx (
313 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
314 OUT EFI_KEY_DATA *KeyData
315 )
316 /*++
317
318 Routine Description:
319 Reads the next keystroke from the input device. The WaitForKey Event can
320 be used to test for existance of a keystroke via WaitForEvent () call.
321
322 Arguments:
323 This - Protocol instance pointer.
324 KeyData - A pointer to a buffer that is filled in with the keystroke
325 state data for the key that was pressed.
326
327 Returns:
328 EFI_SUCCESS - The keystroke information was returned.
329 EFI_NOT_READY - There was no keystroke data availiable.
330 EFI_DEVICE_ERROR - The keystroke information was not returned due to
331 hardware errors.
332 EFI_INVALID_PARAMETER - KeyData is NULL.
333
334 --*/
335 {
336 TERMINAL_DEV *TerminalDevice;
337
338 if (KeyData == NULL) {
339 return EFI_INVALID_PARAMETER;
340 }
341
342 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
343
344 return ReadKeyStrokeWorker (TerminalDevice, KeyData);
345
346 }
347
348 EFI_STATUS
349 EFIAPI
350 TerminalConInSetState (
351 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
352 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
353 )
354 /*++
355
356 Routine Description:
357 Set certain state for the input device.
358
359 Arguments:
360 This - Protocol instance pointer.
361 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
362 state for the input device.
363
364 Returns:
365 EFI_SUCCESS - The device state was set successfully.
366 EFI_DEVICE_ERROR - The device is not functioning correctly and could
367 not have the setting adjusted.
368 EFI_UNSUPPORTED - The device does not have the ability to set its state.
369 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
370
371 --*/
372 {
373 if (KeyToggleState == NULL) {
374 return EFI_INVALID_PARAMETER;
375 }
376
377 return EFI_SUCCESS;
378 }
379
380 EFI_STATUS
381 EFIAPI
382 TerminalConInRegisterKeyNotify (
383 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
384 IN EFI_KEY_DATA *KeyData,
385 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
386 OUT EFI_HANDLE *NotifyHandle
387 )
388 /*++
389
390 Routine Description:
391 Register a notification function for a particular keystroke for the input device.
392
393 Arguments:
394 This - Protocol instance pointer.
395 KeyData - A pointer to a buffer that is filled in with the keystroke
396 information data for the key that was pressed.
397 KeyNotificationFunction - Points to the function to be called when the key
398 sequence is typed specified by KeyData.
399 NotifyHandle - Points to the unique handle assigned to the registered notification.
400
401 Returns:
402 EFI_SUCCESS - The notification function was registered successfully.
403 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
404 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
405
406 --*/
407 {
408 EFI_STATUS Status;
409 TERMINAL_DEV *TerminalDevice;
410 TERMINAL_CONSOLE_IN_EX_NOTIFY *NewNotify;
411 LIST_ENTRY *Link;
412 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
413
414 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
415 return EFI_INVALID_PARAMETER;
416 }
417
418 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
419
420 //
421 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
422 //
423 for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {
424 CurrentNotify = CR (
425 Link,
426 TERMINAL_CONSOLE_IN_EX_NOTIFY,
427 NotifyEntry,
428 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
429 );
430 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
431 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
432 *NotifyHandle = CurrentNotify->NotifyHandle;
433 return EFI_SUCCESS;
434 }
435 }
436 }
437
438 //
439 // Allocate resource to save the notification function
440 //
441 NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));
442 if (NewNotify == NULL) {
443 return EFI_OUT_OF_RESOURCES;
444 }
445
446 NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
447 NewNotify->KeyNotificationFn = KeyNotificationFunction;
448 CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));
449 InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);
450 //
451 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
452 //
453 Status = gBS->InstallMultipleProtocolInterfaces (
454 &NewNotify->NotifyHandle,
455 &gSimpleTextInExNotifyGuid,
456 NULL,
457 NULL
458 );
459 ASSERT_EFI_ERROR (Status);
460 *NotifyHandle = NewNotify->NotifyHandle;
461
462 return EFI_SUCCESS;
463 }
464
465 EFI_STATUS
466 EFIAPI
467 TerminalConInUnregisterKeyNotify (
468 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
469 IN EFI_HANDLE NotificationHandle
470 )
471 /*++
472
473 Routine Description:
474 Remove a registered notification function from a particular keystroke.
475
476 Arguments:
477 This - Protocol instance pointer.
478 NotificationHandle - The handle of the notification function being unregistered.
479
480 Returns:
481 EFI_SUCCESS - The notification function was unregistered successfully.
482 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
483 EFI_NOT_FOUND - Can not find the matching entry in database.
484
485 --*/
486 {
487 EFI_STATUS Status;
488 TERMINAL_DEV *TerminalDevice;
489 LIST_ENTRY *Link;
490 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
491
492 if (NotificationHandle == NULL) {
493 return EFI_INVALID_PARAMETER;
494 }
495
496 Status = gBS->OpenProtocol (
497 NotificationHandle,
498 &gSimpleTextInExNotifyGuid,
499 NULL,
500 NULL,
501 NULL,
502 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
503 );
504 if (EFI_ERROR (Status)) {
505 return EFI_INVALID_PARAMETER;
506 }
507
508 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
509
510 for (Link = TerminalDevice->NotifyList.ForwardLink; Link != &TerminalDevice->NotifyList; Link = Link->ForwardLink) {
511 CurrentNotify = CR (
512 Link,
513 TERMINAL_CONSOLE_IN_EX_NOTIFY,
514 NotifyEntry,
515 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
516 );
517 if (CurrentNotify->NotifyHandle == NotificationHandle) {
518 //
519 // Remove the notification function from NotifyList and free resources
520 //
521 RemoveEntryList (&CurrentNotify->NotifyEntry);
522 Status = gBS->UninstallMultipleProtocolInterfaces (
523 CurrentNotify->NotifyHandle,
524 &gSimpleTextInExNotifyGuid,
525 NULL,
526 NULL
527 );
528 ASSERT_EFI_ERROR (Status);
529 gBS->FreePool (CurrentNotify);
530 return EFI_SUCCESS;
531 }
532 }
533
534 return EFI_NOT_FOUND;
535 }
536
537
538 VOID
539 TranslateRawDataToEfiKey (
540 IN TERMINAL_DEV *TerminalDevice
541 )
542 /*++
543 Step1: Turn raw data into Unicode (according to different encode).
544 Step2: Translate Unicode into key information.
545 (according to different terminal standard).
546 --*/
547 {
548 switch (TerminalDevice->TerminalType) {
549
550 case PcAnsiType:
551 case VT100Type:
552 case VT100PlusType:
553 AnsiRawDataToUnicode (TerminalDevice);
554 UnicodeToEfiKey (TerminalDevice);
555 break;
556
557 case VTUTF8Type:
558 //
559 // Process all the raw data in the RawFIFO,
560 // put the processed key into UnicodeFIFO.
561 //
562 VTUTF8RawDataToUnicode (TerminalDevice);
563
564 //
565 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
566 // then put into EfiKeyFIFO.
567 //
568 UnicodeToEfiKey (TerminalDevice);
569
570 break;
571 }
572 }
573
574 VOID
575 EFIAPI
576 TerminalConInWaitForKey (
577 IN EFI_EVENT Event,
578 IN VOID *Context
579 )
580 /*++
581 Routine Description:
582
583 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
584 Signal the event if there is key available
585
586 Arguments:
587
588 Event - Indicates the event that invoke this function.
589
590 Context - Indicates the calling context.
591
592 Returns:
593
594 N/A
595
596 --*/
597 {
598 //
599 // Someone is waiting on the keystroke event, if there's
600 // a key pending, signal the event
601 //
602 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
603 //
604 if (!EFI_ERROR (TerminalConInCheckForKey (Context))) {
605
606 gBS->SignalEvent (Event);
607 }
608 }
609
610 EFI_STATUS
611 TerminalConInCheckForKey (
612 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
613 )
614 /*++
615 Routine Description:
616
617 Check for a pending key in the Efi Key FIFO or Serial device buffer.
618
619 Arguments:
620
621 This - Indicates the calling context.
622
623 Returns:
624
625 EFI_SUCCESS
626 There is key pending.
627
628 EFI_NOT_READY
629 There is no key pending.
630
631 EFI_DEVICE_ERROR
632
633 --*/
634 {
635 EFI_STATUS Status;
636 TERMINAL_DEV *TerminalDevice;
637 UINT32 Control;
638 UINT8 Input;
639 EFI_SERIAL_IO_MODE *Mode;
640 EFI_SERIAL_IO_PROTOCOL *SerialIo;
641 UINTN SerialInTimeOut;
642
643 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
644
645 SerialIo = TerminalDevice->SerialIo;
646 if (SerialIo == NULL) {
647 return EFI_DEVICE_ERROR;
648 }
649 //
650 // if current timeout value for serial device is not identical with
651 // the value saved in TERMINAL_DEV structure, then recalculate the
652 // timeout value again and set serial attribute according to this value.
653 //
654 Mode = SerialIo->Mode;
655 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
656
657 SerialInTimeOut = 0;
658 if (Mode->BaudRate != 0) {
659 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
660 }
661
662 Status = SerialIo->SetAttributes (
663 SerialIo,
664 Mode->BaudRate,
665 Mode->ReceiveFifoDepth,
666 (UINT32) SerialInTimeOut,
667 (EFI_PARITY_TYPE) (Mode->Parity),
668 (UINT8) Mode->DataBits,
669 (EFI_STOP_BITS_TYPE) (Mode->StopBits)
670 );
671
672 if (EFI_ERROR (Status)) {
673 TerminalDevice->SerialInTimeOut = 0;
674 } else {
675 TerminalDevice->SerialInTimeOut = SerialInTimeOut;
676 }
677 }
678 //
679 // check whether serial buffer is empty
680 //
681 Status = SerialIo->GetControl (SerialIo, &Control);
682
683 if (Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) {
684 //
685 // Translate all the raw data in RawFIFO into EFI Key,
686 // according to different terminal type supported.
687 //
688 TranslateRawDataToEfiKey (TerminalDevice);
689
690 //
691 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
692 // return directly.
693 //
694 if (!IsEfiKeyFiFoEmpty (TerminalDevice)) {
695 return EFI_SUCCESS;
696 } else {
697 return EFI_NOT_READY;
698 }
699 }
700 //
701 // Fetch all the keys in the serial buffer,
702 // and insert the byte stream into RawFIFO.
703 //
704 do {
705
706 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
707
708 if (EFI_ERROR (Status)) {
709 if (Status == EFI_DEVICE_ERROR) {
710 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
711 EFI_ERROR_CODE | EFI_ERROR_MINOR,
712 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError),
713 TerminalDevice->DevicePath
714 );
715 }
716 break;
717 }
718
719 RawFiFoInsertOneKey (TerminalDevice, Input);
720 } while (TRUE);
721
722 //
723 // Translate all the raw data in RawFIFO into EFI Key,
724 // according to different terminal type supported.
725 //
726 TranslateRawDataToEfiKey (TerminalDevice);
727
728 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
729 return EFI_NOT_READY;
730 }
731
732 return EFI_SUCCESS;
733 }
734
735 EFI_STATUS
736 GetOneKeyFromSerial (
737 EFI_SERIAL_IO_PROTOCOL *SerialIo,
738 UINT8 *Input
739 )
740 /*++
741 Get one key out of serial buffer.
742 If serial buffer is empty, return EFI_NOT_READY;
743 if reading serial buffer encounter error, returns EFI_DEVICE_ERROR;
744 if reading serial buffer successfully, put the fetched key to
745 the parameter "Input", and return EFI_SUCCESS.
746 --*/
747 {
748 EFI_STATUS Status;
749 UINTN Size;
750
751 Size = 1;
752 *Input = 0;
753
754 Status = SerialIo->Read (SerialIo, &Size, Input);
755
756 if (EFI_ERROR (Status)) {
757
758 if (Status == EFI_TIMEOUT) {
759 return EFI_NOT_READY;
760 }
761
762 return EFI_DEVICE_ERROR;
763
764 }
765
766 if (*Input == 0) {
767 return EFI_NOT_READY;
768 }
769
770 return EFI_SUCCESS;
771 }
772
773 BOOLEAN
774 RawFiFoInsertOneKey (
775 TERMINAL_DEV *TerminalDevice,
776 UINT8 Input
777 )
778 /*++
779 Insert one byte raw data into the Raw Data FIFO.
780 If FIFO is FULL before data insertion,
781 return FALSE, and the key is lost.
782 --*/
783 {
784 UINT8 Tail;
785
786 Tail = TerminalDevice->RawFiFo.Tail;
787
788 if (IsRawFiFoFull (TerminalDevice)) {
789 //
790 // Raw FIFO is full
791 //
792 return FALSE;
793 }
794
795 TerminalDevice->RawFiFo.Data[Tail] = Input;
796
797 TerminalDevice->RawFiFo.Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
798
799 return TRUE;
800 }
801
802 BOOLEAN
803 RawFiFoRemoveOneKey (
804 TERMINAL_DEV *TerminalDevice,
805 UINT8 *Output
806 )
807 /*++
808 Remove one byte raw data out of the Raw Data FIFO.
809 If FIFO buffer is empty before remove operation,
810 return FALSE.
811 --*/
812 {
813 UINT8 Head;
814
815 Head = TerminalDevice->RawFiFo.Head;
816
817 if (IsRawFiFoEmpty (TerminalDevice)) {
818 //
819 // FIFO is empty
820 //
821 *Output = 0;
822 return FALSE;
823 }
824
825 *Output = TerminalDevice->RawFiFo.Data[Head];
826
827 TerminalDevice->RawFiFo.Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
828
829 return TRUE;
830 }
831
832 BOOLEAN
833 IsRawFiFoEmpty (
834 TERMINAL_DEV *TerminalDevice
835 )
836 /*++
837 Clarify whether FIFO buffer is empty.
838 --*/
839 {
840 if (TerminalDevice->RawFiFo.Head == TerminalDevice->RawFiFo.Tail) {
841 return TRUE;
842 } else {
843 return FALSE;
844 }
845 }
846
847 BOOLEAN
848 IsRawFiFoFull (
849 TERMINAL_DEV *TerminalDevice
850 )
851 /*++
852 Clarify whether FIFO buffer is full.
853 --*/
854 {
855 UINT8 Tail;
856 UINT8 Head;
857
858 Tail = TerminalDevice->RawFiFo.Tail;
859 Head = TerminalDevice->RawFiFo.Head;
860
861 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
862
863 return TRUE;
864 }
865
866 return FALSE;
867 }
868
869 BOOLEAN
870 EfiKeyFiFoInsertOneKey (
871 TERMINAL_DEV *TerminalDevice,
872 EFI_INPUT_KEY Key
873 )
874 /*++
875 Insert one pre-fetched key into the FIFO buffer.
876 If FIFO buffer is FULL before key insertion,
877 return FALSE, and the key is lost.
878 --*/
879 {
880 UINT8 Tail;
881
882 Tail = TerminalDevice->EfiKeyFiFo.Tail;
883
884 if (IsEfiKeyFiFoFull (TerminalDevice)) {
885 //
886 // Efi Key FIFO is full
887 //
888 return FALSE;
889 }
890
891 TerminalDevice->EfiKeyFiFo.Data[Tail] = Key;
892
893 TerminalDevice->EfiKeyFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
894
895 return TRUE;
896 }
897
898 BOOLEAN
899 EfiKeyFiFoRemoveOneKey (
900 TERMINAL_DEV *TerminalDevice,
901 EFI_INPUT_KEY *Output
902 )
903 /*++
904 Remove one pre-fetched key out of the FIFO buffer.
905 If FIFO buffer is empty before remove operation,
906 return FALSE.
907 --*/
908 {
909 UINT8 Head;
910
911 Head = TerminalDevice->EfiKeyFiFo.Head;
912
913 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
914 //
915 // FIFO is empty
916 //
917 Output->ScanCode = SCAN_NULL;
918 Output->UnicodeChar = 0;
919 return FALSE;
920 }
921
922 *Output = TerminalDevice->EfiKeyFiFo.Data[Head];
923
924 TerminalDevice->EfiKeyFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
925
926 return TRUE;
927 }
928
929 BOOLEAN
930 IsEfiKeyFiFoEmpty (
931 TERMINAL_DEV *TerminalDevice
932 )
933 /*++
934 Clarify whether FIFO buffer is empty.
935 --*/
936 {
937 if (TerminalDevice->EfiKeyFiFo.Head == TerminalDevice->EfiKeyFiFo.Tail) {
938 return TRUE;
939 } else {
940 return FALSE;
941 }
942 }
943
944 BOOLEAN
945 IsEfiKeyFiFoFull (
946 TERMINAL_DEV *TerminalDevice
947 )
948 /*++
949 Clarify whether FIFO buffer is full.
950 --*/
951 {
952 UINT8 Tail;
953 UINT8 Head;
954
955 Tail = TerminalDevice->EfiKeyFiFo.Tail;
956 Head = TerminalDevice->EfiKeyFiFo.Head;
957
958 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
959
960 return TRUE;
961 }
962
963 return FALSE;
964 }
965
966 BOOLEAN
967 UnicodeFiFoInsertOneKey (
968 TERMINAL_DEV *TerminalDevice,
969 UINT16 Input
970 )
971 /*++
972 Insert one pre-fetched key into the FIFO buffer.
973 If FIFO buffer is FULL before key insertion,
974 return FALSE, and the key is lost.
975 --*/
976 {
977 UINT8 Tail;
978
979 Tail = TerminalDevice->UnicodeFiFo.Tail;
980
981 if (IsUnicodeFiFoFull (TerminalDevice)) {
982 //
983 // Unicode FIFO is full
984 //
985 return FALSE;
986 }
987
988 TerminalDevice->UnicodeFiFo.Data[Tail] = Input;
989
990 TerminalDevice->UnicodeFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
991
992 return TRUE;
993 }
994
995 BOOLEAN
996 UnicodeFiFoRemoveOneKey (
997 TERMINAL_DEV *TerminalDevice,
998 UINT16 *Output
999 )
1000 /*++
1001 Remove one pre-fetched key out of the FIFO buffer.
1002 If FIFO buffer is empty before remove operation,
1003 return FALSE.
1004 --*/
1005 {
1006 UINT8 Head;
1007
1008 Head = TerminalDevice->UnicodeFiFo.Head;
1009
1010 if (IsUnicodeFiFoEmpty (TerminalDevice)) {
1011 //
1012 // FIFO is empty
1013 //
1014 Output = NULL;
1015 return FALSE;
1016 }
1017
1018 *Output = TerminalDevice->UnicodeFiFo.Data[Head];
1019
1020 TerminalDevice->UnicodeFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
1021
1022 return TRUE;
1023 }
1024
1025 BOOLEAN
1026 IsUnicodeFiFoEmpty (
1027 TERMINAL_DEV *TerminalDevice
1028 )
1029 /*++
1030 Clarify whether FIFO buffer is empty.
1031 --*/
1032 {
1033 if (TerminalDevice->UnicodeFiFo.Head == TerminalDevice->UnicodeFiFo.Tail) {
1034 return TRUE;
1035 } else {
1036 return FALSE;
1037 }
1038 }
1039
1040 BOOLEAN
1041 IsUnicodeFiFoFull (
1042 TERMINAL_DEV *TerminalDevice
1043 )
1044 /*++
1045 Clarify whether FIFO buffer is full.
1046 --*/
1047 {
1048 UINT8 Tail;
1049 UINT8 Head;
1050
1051 Tail = TerminalDevice->UnicodeFiFo.Tail;
1052 Head = TerminalDevice->UnicodeFiFo.Head;
1053
1054 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
1055
1056 return TRUE;
1057 }
1058
1059 return FALSE;
1060 }
1061
1062 UINT8
1063 UnicodeFiFoGetKeyCount (
1064 TERMINAL_DEV *TerminalDevice
1065 )
1066 {
1067 UINT8 Tail;
1068 UINT8 Head;
1069
1070 Tail = TerminalDevice->UnicodeFiFo.Tail;
1071 Head = TerminalDevice->UnicodeFiFo.Head;
1072
1073 if (Tail >= Head) {
1074 return (UINT8) (Tail - Head);
1075 } else {
1076 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);
1077 }
1078 }
1079
1080 STATIC
1081 VOID
1082 UnicodeToEfiKeyFlushState (
1083 IN TERMINAL_DEV *TerminalDevice
1084 )
1085 {
1086 EFI_INPUT_KEY Key;
1087
1088 if (TerminalDevice->InputState & INPUT_STATE_ESC) {
1089 Key.ScanCode = SCAN_ESC;
1090 Key.UnicodeChar = 0;
1091 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1092 }
1093
1094 if (TerminalDevice->InputState & INPUT_STATE_CSI) {
1095 Key.ScanCode = SCAN_NULL;
1096 Key.UnicodeChar = CSI;
1097 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1098 }
1099
1100 if (TerminalDevice->InputState & INPUT_STATE_LEFTOPENBRACKET) {
1101 Key.ScanCode = SCAN_NULL;
1102 Key.UnicodeChar = LEFTOPENBRACKET;
1103 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1104 }
1105
1106 if (TerminalDevice->InputState & INPUT_STATE_O) {
1107 Key.ScanCode = SCAN_NULL;
1108 Key.UnicodeChar = 'O';
1109 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1110 }
1111
1112 if (TerminalDevice->InputState & INPUT_STATE_2) {
1113 Key.ScanCode = SCAN_NULL;
1114 Key.UnicodeChar = '2';
1115 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1116 }
1117
1118 gBS->SetTimer (
1119 TerminalDevice->TwoSecondTimeOut,
1120 TimerCancel,
1121 0
1122 );
1123
1124 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1125 }
1126
1127 VOID
1128 UnicodeToEfiKey (
1129 IN TERMINAL_DEV *TerminalDevice
1130 )
1131 /*++
1132 Routine Description:
1133
1134 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1135 can be read through the Simple Input Protocol. The table below shows the keyboard
1136 input mappings that this function supports. If the ESC sequence listed in one of the
1137 columns is presented, then it is translated into the coorespoding EFI Scan Code. If a
1138 matching sequence is not found, then the raw key strokes are converted into EFI Keys.
1139
1140 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1141 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1142 converted into EFI Keys.
1143
1144 There is one special input sequence that will force the system to reset.
1145 This is ESC R ESC r ESC R.
1146
1147 Arguments:
1148
1149 TerminaDevice : The terminal device to use to translate raw input into EFI Keys
1150
1151 Returns:
1152
1153 None
1154
1155 Symbols used in table below
1156 ===========================
1157 ESC = 0x1B
1158 CSI = 0x9B
1159 DEL = 0x7f
1160 ^ = CTRL
1161
1162 +=========+======+===========+==========+==========+
1163 | | EFI | EFI 1.10 | | |
1164 | | Scan | | VT100+ | |
1165 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1166 +=========+======+===========+==========+==========+
1167 | NULL | 0x00 | | | |
1168 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1169 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1170 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1171 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1172 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1173 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1174 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1175 | | | ESC [ L | | ESC [ L |
1176 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1177 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1178 | | | | | ESC [ ? |
1179 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1180 | | | | | ESC [ / |
1181 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1182 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1183 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1184 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1185 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1186 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1187 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1188 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1189 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1190 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1191 | Escape | 0x17 | ESC | ESC | ESC |
1192 | F11 | 0x15 | | ESC ! | |
1193 | F12 | 0x16 | | ESC @ | |
1194 +=========+======+===========+==========+==========+
1195
1196 Special Mappings
1197 ================
1198 ESC R ESC r ESC R = Reset System
1199
1200 --*/
1201 {
1202 EFI_STATUS Status;
1203 EFI_STATUS TimerStatus;
1204 UINT16 UnicodeChar;
1205 EFI_INPUT_KEY Key;
1206 BOOLEAN SetDefaultResetState;
1207
1208 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1209
1210 if (!EFI_ERROR (TimerStatus)) {
1211 UnicodeToEfiKeyFlushState (TerminalDevice);
1212 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1213 }
1214
1215 while (!IsUnicodeFiFoEmpty(TerminalDevice)) {
1216
1217 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1218 //
1219 // Check to see if the 2 second timer has expired
1220 //
1221 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1222 if (!EFI_ERROR (TimerStatus)) {
1223 UnicodeToEfiKeyFlushState (TerminalDevice);
1224 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1225 }
1226 }
1227
1228 //
1229 // Fetch one Unicode character from the Unicode FIFO
1230 //
1231 UnicodeFiFoRemoveOneKey (TerminalDevice,&UnicodeChar);
1232
1233 SetDefaultResetState = TRUE;
1234
1235 switch (TerminalDevice->InputState) {
1236 case INPUT_STATE_DEFAULT:
1237
1238 break;
1239
1240 case INPUT_STATE_ESC:
1241
1242 if (UnicodeChar == LEFTOPENBRACKET) {
1243 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
1244 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1245 continue;
1246 }
1247
1248 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100Type) {
1249 TerminalDevice->InputState |= INPUT_STATE_O;
1250 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1251 continue;
1252 }
1253
1254 Key.ScanCode = SCAN_NULL;
1255
1256 if (TerminalDevice->TerminalType == VT100PlusType ||
1257 TerminalDevice->TerminalType == VTUTF8Type) {
1258 switch (UnicodeChar) {
1259 case '1':
1260 Key.ScanCode = SCAN_F1;
1261 break;
1262 case '2':
1263 Key.ScanCode = SCAN_F2;
1264 break;
1265 case '3':
1266 Key.ScanCode = SCAN_F3;
1267 break;
1268 case '4':
1269 Key.ScanCode = SCAN_F4;
1270 break;
1271 case '5':
1272 Key.ScanCode = SCAN_F5;
1273 break;
1274 case '6':
1275 Key.ScanCode = SCAN_F6;
1276 break;
1277 case '7':
1278 Key.ScanCode = SCAN_F7;
1279 break;
1280 case '8':
1281 Key.ScanCode = SCAN_F8;
1282 break;
1283 case '9':
1284 Key.ScanCode = SCAN_F9;
1285 break;
1286 case '0':
1287 Key.ScanCode = SCAN_F10;
1288 break;
1289 case '!':
1290 Key.ScanCode = SCAN_F11;
1291 break;
1292 case '@':
1293 Key.ScanCode = SCAN_F12;
1294 break;
1295 case 'h':
1296 Key.ScanCode = SCAN_HOME;
1297 break;
1298 case 'k':
1299 Key.ScanCode = SCAN_END;
1300 break;
1301 case '+':
1302 Key.ScanCode = SCAN_INSERT;
1303 break;
1304 case '-':
1305 Key.ScanCode = SCAN_DELETE;
1306 break;
1307 case '/':
1308 Key.ScanCode = SCAN_PAGE_DOWN;
1309 break;
1310 case '?':
1311 Key.ScanCode = SCAN_PAGE_UP;
1312 break;
1313 default :
1314 break;
1315 }
1316 }
1317
1318 switch (UnicodeChar) {
1319 case 'R':
1320 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
1321 TerminalDevice->ResetState = RESET_STATE_ESC_R;
1322 SetDefaultResetState = FALSE;
1323 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {
1324 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1325 }
1326 Key.ScanCode = SCAN_NULL;
1327 break;
1328 case 'r':
1329 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
1330 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;
1331 SetDefaultResetState = FALSE;
1332 }
1333 Key.ScanCode = SCAN_NULL;
1334 break;
1335 default :
1336 break;
1337 }
1338
1339 if (SetDefaultResetState) {
1340 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1341 }
1342
1343 if (Key.ScanCode != SCAN_NULL) {
1344 Key.UnicodeChar = 0;
1345 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1346 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1347 UnicodeToEfiKeyFlushState (TerminalDevice);
1348 continue;
1349 }
1350
1351 UnicodeToEfiKeyFlushState (TerminalDevice);
1352
1353 break;
1354
1355 case INPUT_STATE_ESC | INPUT_STATE_O:
1356
1357 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1358
1359 Key.ScanCode = SCAN_NULL;
1360
1361 if (TerminalDevice->TerminalType == VT100Type) {
1362 switch (UnicodeChar) {
1363 case 'P':
1364 Key.ScanCode = SCAN_F1;
1365 break;
1366 case 'Q':
1367 Key.ScanCode = SCAN_F2;
1368 break;
1369 case 'w':
1370 Key.ScanCode = SCAN_F3;
1371 break;
1372 case 'x':
1373 Key.ScanCode = SCAN_F4;
1374 break;
1375 case 't':
1376 Key.ScanCode = SCAN_F5;
1377 break;
1378 case 'u':
1379 Key.ScanCode = SCAN_F6;
1380 break;
1381 case 'q':
1382 Key.ScanCode = SCAN_F7;
1383 break;
1384 case 'r':
1385 Key.ScanCode = SCAN_F8;
1386 break;
1387 case 'p':
1388 Key.ScanCode = SCAN_F9;
1389 break;
1390 case 'M':
1391 Key.ScanCode = SCAN_F10;
1392 break;
1393 default :
1394 break;
1395 }
1396 }
1397
1398 if (Key.ScanCode != SCAN_NULL) {
1399 Key.UnicodeChar = 0;
1400 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1401 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1402 UnicodeToEfiKeyFlushState (TerminalDevice);
1403 continue;
1404 }
1405
1406 UnicodeToEfiKeyFlushState (TerminalDevice);
1407
1408 break;
1409
1410 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
1411
1412 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1413
1414 Key.ScanCode = SCAN_NULL;
1415
1416 if (TerminalDevice->TerminalType == PcAnsiType ||
1417 TerminalDevice->TerminalType == VT100Type ||
1418 TerminalDevice->TerminalType == VT100PlusType ||
1419 TerminalDevice->TerminalType == VTUTF8Type) {
1420 switch (UnicodeChar) {
1421 case 'A':
1422 Key.ScanCode = SCAN_UP;
1423 break;
1424 case 'B':
1425 Key.ScanCode = SCAN_DOWN;
1426 break;
1427 case 'C':
1428 Key.ScanCode = SCAN_RIGHT;
1429 break;
1430 case 'D':
1431 Key.ScanCode = SCAN_LEFT;
1432 break;
1433 case 'H':
1434 if (TerminalDevice->TerminalType == PcAnsiType ||
1435 TerminalDevice->TerminalType == VT100Type) {
1436 Key.ScanCode = SCAN_HOME;
1437 }
1438 break;
1439 case 'F':
1440 if (TerminalDevice->TerminalType == PcAnsiType) {
1441 Key.ScanCode = SCAN_END;
1442 }
1443 break;
1444 case 'K':
1445 if (TerminalDevice->TerminalType == VT100Type) {
1446 Key.ScanCode = SCAN_END;
1447 }
1448 break;
1449 case 'L':
1450 case '@':
1451 if (TerminalDevice->TerminalType == PcAnsiType ||
1452 TerminalDevice->TerminalType == VT100Type) {
1453 Key.ScanCode = SCAN_INSERT;
1454 }
1455 break;
1456 case 'X':
1457 if (TerminalDevice->TerminalType == PcAnsiType) {
1458 Key.ScanCode = SCAN_DELETE;
1459 }
1460 break;
1461 case 'P':
1462 if (TerminalDevice->TerminalType == VT100Type) {
1463 Key.ScanCode = SCAN_DELETE;
1464 } else if (TerminalDevice->TerminalType == PcAnsiType) {
1465 Key.ScanCode = SCAN_F4;
1466 }
1467 break;
1468 case 'I':
1469 if (TerminalDevice->TerminalType == PcAnsiType) {
1470 Key.ScanCode = SCAN_PAGE_UP;
1471 }
1472 break;
1473 case 'V':
1474 if (TerminalDevice->TerminalType == PcAnsiType) {
1475 Key.ScanCode = SCAN_F10;
1476 }
1477 case '?':
1478 if (TerminalDevice->TerminalType == VT100Type) {
1479 Key.ScanCode = SCAN_PAGE_UP;
1480 }
1481 break;
1482 case 'G':
1483 if (TerminalDevice->TerminalType == PcAnsiType) {
1484 Key.ScanCode = SCAN_PAGE_DOWN;
1485 }
1486 break;
1487 case 'U':
1488 if (TerminalDevice->TerminalType == PcAnsiType) {
1489 Key.ScanCode = SCAN_F9;
1490 }
1491 case '/':
1492 if (TerminalDevice->TerminalType == VT100Type) {
1493 Key.ScanCode = SCAN_PAGE_DOWN;
1494 }
1495 break;
1496 case 'M':
1497 if (TerminalDevice->TerminalType == PcAnsiType) {
1498 Key.ScanCode = SCAN_F1;
1499 }
1500 break;
1501 case 'N':
1502 if (TerminalDevice->TerminalType == PcAnsiType) {
1503 Key.ScanCode = SCAN_F2;
1504 }
1505 break;
1506 case 'O':
1507 if (TerminalDevice->TerminalType == PcAnsiType) {
1508 Key.ScanCode = SCAN_F3;
1509 }
1510 break;
1511 case 'Q':
1512 if (TerminalDevice->TerminalType == PcAnsiType) {
1513 Key.ScanCode = SCAN_F5;
1514 }
1515 break;
1516 case 'R':
1517 if (TerminalDevice->TerminalType == PcAnsiType) {
1518 Key.ScanCode = SCAN_F6;
1519 }
1520 break;
1521 case 'S':
1522 if (TerminalDevice->TerminalType == PcAnsiType) {
1523 Key.ScanCode = SCAN_F7;
1524 }
1525 break;
1526 case 'T':
1527 if (TerminalDevice->TerminalType == PcAnsiType) {
1528 Key.ScanCode = SCAN_F8;
1529 }
1530 break;
1531 default :
1532 break;
1533 }
1534 }
1535
1536 if (Key.ScanCode != SCAN_NULL) {
1537 Key.UnicodeChar = 0;
1538 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1539 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1540 UnicodeToEfiKeyFlushState (TerminalDevice);
1541 continue;
1542 }
1543
1544 UnicodeToEfiKeyFlushState (TerminalDevice);
1545
1546 break;
1547
1548
1549 default:
1550 //
1551 // Invalid state. This should never happen.
1552 //
1553 ASSERT (FALSE);
1554
1555 UnicodeToEfiKeyFlushState (TerminalDevice);
1556
1557 break;
1558 }
1559
1560 if (UnicodeChar == ESC) {
1561 TerminalDevice->InputState = INPUT_STATE_ESC;
1562 }
1563
1564 if (UnicodeChar == CSI) {
1565 TerminalDevice->InputState = INPUT_STATE_CSI;
1566 }
1567
1568 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1569 Status = gBS->SetTimer(
1570 TerminalDevice->TwoSecondTimeOut,
1571 TimerRelative,
1572 (UINT64)20000000
1573 );
1574 ASSERT_EFI_ERROR (Status);
1575 continue;
1576 }
1577
1578 if (SetDefaultResetState) {
1579 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1580 }
1581
1582 if (UnicodeChar == DEL) {
1583 Key.ScanCode = SCAN_DELETE;
1584 Key.UnicodeChar = 0;
1585 } else {
1586 Key.ScanCode = SCAN_NULL;
1587 Key.UnicodeChar = UnicodeChar;
1588 }
1589
1590 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1591 }
1592 }