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