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