]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
Retired gSimpleTextInExNotifyGuid, used local structure address to be notify handle.
[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 - 2008, 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 /**
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 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),
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 PcdGet32 (PcdStatusCodeValueRemoteConsoleError),
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 @retval EFI_NOT_FOUND Can not find the matching entry in database.
430
431 **/
432 EFI_STATUS
433 EFIAPI
434 TerminalConInUnregisterKeyNotify (
435 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
436 IN EFI_HANDLE NotificationHandle
437 )
438 {
439 TERMINAL_DEV *TerminalDevice;
440 LIST_ENTRY *Link;
441 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
442 LIST_ENTRY *NotifyList;
443
444 if (NotificationHandle == NULL) {
445 return EFI_INVALID_PARAMETER;
446 }
447
448 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
449
450 NotifyList = &TerminalDevice->NotifyList;
451 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
452 CurrentNotify = CR (
453 Link,
454 TERMINAL_CONSOLE_IN_EX_NOTIFY,
455 NotifyEntry,
456 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
457 );
458 if (CurrentNotify->NotifyHandle == NotificationHandle) {
459 //
460 // Remove the notification function from NotifyList and free resources
461 //
462 RemoveEntryList (&CurrentNotify->NotifyEntry);
463
464 gBS->FreePool (CurrentNotify);
465 return EFI_SUCCESS;
466 }
467 }
468
469 return EFI_NOT_FOUND;
470 }
471
472 /**
473 Translate raw data into Unicode (according to different encode), and
474 translate Unicode into key information. (according to different standard).
475
476 @param TerminalDevice Terminal driver private structure.
477
478 **/
479 VOID
480 TranslateRawDataToEfiKey (
481 IN TERMINAL_DEV *TerminalDevice
482 )
483 {
484 switch (TerminalDevice->TerminalType) {
485
486 case PCANSITYPE:
487 case VT100TYPE:
488 case VT100PLUSTYPE:
489 AnsiRawDataToUnicode (TerminalDevice);
490 UnicodeToEfiKey (TerminalDevice);
491 break;
492
493 case VTUTF8TYPE:
494 //
495 // Process all the raw data in the RawFIFO,
496 // put the processed key into UnicodeFIFO.
497 //
498 VTUTF8RawDataToUnicode (TerminalDevice);
499
500 //
501 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
502 // then put into EfiKeyFIFO.
503 //
504 UnicodeToEfiKey (TerminalDevice);
505
506 break;
507 }
508 }
509
510 /**
511 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
512 Signal the event if there is key available
513
514 @param Event Indicates the event that invoke this function.
515 @param Context Indicates the calling context.
516
517 **/
518 VOID
519 EFIAPI
520 TerminalConInWaitForKey (
521 IN EFI_EVENT Event,
522 IN VOID *Context
523 )
524 {
525 //
526 // Someone is waiting on the keystroke event, if there's
527 // a key pending, signal the event
528 //
529 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
530 //
531 if (!EFI_ERROR (TerminalConInCheckForKey (Context))) {
532
533 gBS->SignalEvent (Event);
534 }
535 }
536
537
538 /**
539 Check for a pending key in the Efi Key FIFO or Serial device buffer.
540
541 @param This Indicates the calling context.
542
543 @retval EFI_SUCCESS There is key pending.
544 @retval EFI_NOT_READY There is no key pending.
545 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
546
547 **/
548 EFI_STATUS
549 TerminalConInCheckForKey (
550 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
551 )
552 {
553 EFI_STATUS Status;
554 TERMINAL_DEV *TerminalDevice;
555 UINT32 Control;
556 UINT8 Input;
557 EFI_SERIAL_IO_MODE *Mode;
558 EFI_SERIAL_IO_PROTOCOL *SerialIo;
559 UINTN SerialInTimeOut;
560
561 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
562
563 SerialIo = TerminalDevice->SerialIo;
564 if (SerialIo == NULL) {
565 return EFI_DEVICE_ERROR;
566 }
567 //
568 // if current timeout value for serial device is not identical with
569 // the value saved in TERMINAL_DEV structure, then recalculate the
570 // timeout value again and set serial attribute according to this value.
571 //
572 Mode = SerialIo->Mode;
573 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
574
575 SerialInTimeOut = 0;
576 if (Mode->BaudRate != 0) {
577 //
578 // According to BAUD rate to calculate the timeout value.
579 //
580 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;
581 }
582
583 Status = SerialIo->SetAttributes (
584 SerialIo,
585 Mode->BaudRate,
586 Mode->ReceiveFifoDepth,
587 (UINT32) SerialInTimeOut,
588 (EFI_PARITY_TYPE) (Mode->Parity),
589 (UINT8) Mode->DataBits,
590 (EFI_STOP_BITS_TYPE) (Mode->StopBits)
591 );
592
593 if (EFI_ERROR (Status)) {
594 TerminalDevice->SerialInTimeOut = 0;
595 } else {
596 TerminalDevice->SerialInTimeOut = SerialInTimeOut;
597 }
598 }
599 //
600 // Check whether serial buffer is empty.
601 //
602 Status = SerialIo->GetControl (SerialIo, &Control);
603
604 if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {
605 //
606 // Translate all the raw data in RawFIFO into EFI Key,
607 // according to different terminal type supported.
608 //
609 TranslateRawDataToEfiKey (TerminalDevice);
610
611 //
612 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
613 // return directly.
614 //
615 if (!IsEfiKeyFiFoEmpty (TerminalDevice)) {
616 return EFI_SUCCESS;
617 } else {
618 return EFI_NOT_READY;
619 }
620 }
621 //
622 // Fetch all the keys in the serial buffer,
623 // and insert the byte stream into RawFIFO.
624 //
625 do {
626
627 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
628
629 if (EFI_ERROR (Status)) {
630 if (Status == EFI_DEVICE_ERROR) {
631 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
632 EFI_ERROR_CODE | EFI_ERROR_MINOR,
633 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError),
634 TerminalDevice->DevicePath
635 );
636 }
637 break;
638 }
639
640 RawFiFoInsertOneKey (TerminalDevice, Input);
641 } while (TRUE);
642
643 //
644 // Translate all the raw data in RawFIFO into EFI Key,
645 // according to different terminal type supported.
646 //
647 TranslateRawDataToEfiKey (TerminalDevice);
648
649 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
650 return EFI_NOT_READY;
651 }
652
653 return EFI_SUCCESS;
654 }
655
656 /**
657 Get one key out of serial buffer.
658
659 @param SerialIo Serial I/O protocol attached to the serial device.
660 @param Output The fetched key.
661
662 @retval EFI_NOT_READY If serial buffer is empty.
663 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
664 @retval EFI_SUCCESS If reading serial buffer successfully, put
665 the fetched key to the parameter output.
666
667 **/
668 EFI_STATUS
669 GetOneKeyFromSerial (
670 EFI_SERIAL_IO_PROTOCOL *SerialIo,
671 UINT8 *Output
672 )
673 {
674 EFI_STATUS Status;
675 UINTN Size;
676
677 Size = 1;
678 *Output = 0;
679
680 //
681 // Read one key from serial I/O device.
682 //
683 Status = SerialIo->Read (SerialIo, &Size, Output);
684
685 if (EFI_ERROR (Status)) {
686
687 if (Status == EFI_TIMEOUT) {
688 return EFI_NOT_READY;
689 }
690
691 return EFI_DEVICE_ERROR;
692
693 }
694
695 if (*Output == 0) {
696 return EFI_NOT_READY;
697 }
698
699 return EFI_SUCCESS;
700 }
701
702 /**
703 Insert one byte raw data into the Raw Data FIFO.
704
705 @param TerminalDevice Terminal driver private structure.
706 @param Input The key will be input.
707
708 @retval TRUE If insert successfully.
709 @retval FLASE If Raw Data buffer is full before key insertion,
710 and the key is lost.
711
712 **/
713 BOOLEAN
714 RawFiFoInsertOneKey (
715 TERMINAL_DEV *TerminalDevice,
716 UINT8 Input
717 )
718 {
719 UINT8 Tail;
720
721 Tail = TerminalDevice->RawFiFo->Tail;
722
723 if (IsRawFiFoFull (TerminalDevice)) {
724 //
725 // Raw FIFO is full
726 //
727 return FALSE;
728 }
729
730 TerminalDevice->RawFiFo->Data[Tail] = Input;
731
732 TerminalDevice->RawFiFo->Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
733
734 return TRUE;
735 }
736
737 /**
738 Remove one pre-fetched key out of the Raw Data FIFO.
739
740 @param TerminalDevice Terminal driver private structure.
741 @param Output The key will be removed.
742
743 @retval TRUE If insert successfully.
744 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.
745
746 **/
747 BOOLEAN
748 RawFiFoRemoveOneKey (
749 TERMINAL_DEV *TerminalDevice,
750 UINT8 *Output
751 )
752 {
753 UINT8 Head;
754
755 Head = TerminalDevice->RawFiFo->Head;
756
757 if (IsRawFiFoEmpty (TerminalDevice)) {
758 //
759 // FIFO is empty
760 //
761 *Output = 0;
762 return FALSE;
763 }
764
765 *Output = TerminalDevice->RawFiFo->Data[Head];
766
767 TerminalDevice->RawFiFo->Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
768
769 return TRUE;
770 }
771
772 /**
773 Clarify whether Raw Data FIFO buffer is empty.
774
775 @param TerminalDevice Terminal driver private structure
776
777 @retval TRUE If Raw Data FIFO buffer is empty.
778 @retval FLASE If Raw Data FIFO buffer is not empty.
779
780 **/
781 BOOLEAN
782 IsRawFiFoEmpty (
783 TERMINAL_DEV *TerminalDevice
784 )
785 {
786 if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {
787 return TRUE;
788 } else {
789 return FALSE;
790 }
791 }
792
793 /**
794 Clarify whether Raw Data FIFO buffer is full.
795
796 @param TerminalDevice Terminal driver private structure
797
798 @retval TRUE If Raw Data FIFO buffer is full.
799 @retval FLASE If Raw Data FIFO buffer is not full.
800
801 **/
802 BOOLEAN
803 IsRawFiFoFull (
804 TERMINAL_DEV *TerminalDevice
805 )
806 {
807 UINT8 Tail;
808 UINT8 Head;
809
810 Tail = TerminalDevice->RawFiFo->Tail;
811 Head = TerminalDevice->RawFiFo->Head;
812
813 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
814
815 return TRUE;
816 }
817
818 return FALSE;
819 }
820
821 /**
822 Insert one pre-fetched key into the FIFO buffer.
823
824 @param TerminalDevice Terminal driver private structure.
825 @param Key The key will be input.
826
827 @retval TRUE If insert successfully.
828 @retval FLASE If FIFO buffer is full before key insertion,
829 and the key is lost.
830
831 **/
832 BOOLEAN
833 EfiKeyFiFoInsertOneKey (
834 TERMINAL_DEV *TerminalDevice,
835 EFI_INPUT_KEY Key
836 )
837 {
838 UINT8 Tail;
839
840 Tail = TerminalDevice->EfiKeyFiFo->Tail;
841 ASSERT (Tail < FIFO_MAX_NUMBER + 1);
842
843 if (IsEfiKeyFiFoFull (TerminalDevice)) {
844 //
845 // Efi Key FIFO is full
846 //
847 return FALSE;
848 }
849
850 TerminalDevice->EfiKeyFiFo->Data[Tail] = Key;
851
852 TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
853
854 return TRUE;
855 }
856
857 /**
858 Remove one pre-fetched key out of the FIFO buffer.
859
860 @param TerminalDevice Terminal driver private structure.
861 @param Output The key will be removed.
862
863 @retval TRUE If insert successfully.
864 @retval FLASE If FIFO buffer is empty before remove operation.
865
866 **/
867 BOOLEAN
868 EfiKeyFiFoRemoveOneKey (
869 TERMINAL_DEV *TerminalDevice,
870 EFI_INPUT_KEY *Output
871 )
872 {
873 UINT8 Head;
874
875 Head = TerminalDevice->EfiKeyFiFo->Head;
876 ASSERT (Head < FIFO_MAX_NUMBER + 1);
877
878 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
879 //
880 // FIFO is empty
881 //
882 Output->ScanCode = SCAN_NULL;
883 Output->UnicodeChar = 0;
884 return FALSE;
885 }
886
887 *Output = TerminalDevice->EfiKeyFiFo->Data[Head];
888
889 TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
890
891 return TRUE;
892 }
893
894 /**
895 Clarify whether FIFO buffer is empty.
896
897 @param TerminalDevice Terminal driver private structure
898
899 @retval TRUE If FIFO buffer is empty.
900 @retval FLASE If FIFO buffer is not empty.
901
902 **/
903 BOOLEAN
904 IsEfiKeyFiFoEmpty (
905 TERMINAL_DEV *TerminalDevice
906 )
907 {
908 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {
909 return TRUE;
910 } else {
911 return FALSE;
912 }
913 }
914
915 /**
916 Clarify whether FIFO buffer is full.
917
918 @param TerminalDevice Terminal driver private structure
919
920 @retval TRUE If FIFO buffer is full.
921 @retval FLASE If FIFO buffer is not full.
922
923 **/
924 BOOLEAN
925 IsEfiKeyFiFoFull (
926 TERMINAL_DEV *TerminalDevice
927 )
928 {
929 UINT8 Tail;
930 UINT8 Head;
931
932 Tail = TerminalDevice->EfiKeyFiFo->Tail;
933 Head = TerminalDevice->EfiKeyFiFo->Head;
934
935 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
936
937 return TRUE;
938 }
939
940 return FALSE;
941 }
942
943 /**
944 Insert one pre-fetched key into the Unicode FIFO buffer.
945
946 @param TerminalDevice Terminal driver private structure.
947 @param Input The key will be input.
948
949 @retval TRUE If insert successfully.
950 @retval FLASE If Unicode FIFO buffer is full before key insertion,
951 and the key is lost.
952
953 **/
954 BOOLEAN
955 UnicodeFiFoInsertOneKey (
956 TERMINAL_DEV *TerminalDevice,
957 UINT16 Input
958 )
959 {
960 UINT8 Tail;
961
962 Tail = TerminalDevice->UnicodeFiFo->Tail;
963 ASSERT (Tail < FIFO_MAX_NUMBER + 1);
964
965
966 if (IsUnicodeFiFoFull (TerminalDevice)) {
967 //
968 // Unicode FIFO is full
969 //
970 return FALSE;
971 }
972
973 TerminalDevice->UnicodeFiFo->Data[Tail] = Input;
974
975 TerminalDevice->UnicodeFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
976
977 return TRUE;
978 }
979
980 /**
981 Remove one pre-fetched key out of the Unicode FIFO buffer.
982
983 @param TerminalDevice Terminal driver private structure.
984 @param Output The key will be removed.
985
986 @retval TRUE If insert successfully.
987 @retval FLASE If Unicode FIFO buffer is empty before remove operation.
988
989 **/
990 BOOLEAN
991 UnicodeFiFoRemoveOneKey (
992 TERMINAL_DEV *TerminalDevice,
993 UINT16 *Output
994 )
995 {
996 UINT8 Head;
997
998 Head = TerminalDevice->UnicodeFiFo->Head;
999 ASSERT (Head < FIFO_MAX_NUMBER + 1);
1000
1001 if (IsUnicodeFiFoEmpty (TerminalDevice)) {
1002 //
1003 // FIFO is empty
1004 //
1005 Output = NULL;
1006 return FALSE;
1007 }
1008
1009 *Output = TerminalDevice->UnicodeFiFo->Data[Head];
1010
1011 TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
1012
1013 return TRUE;
1014 }
1015
1016 /**
1017 Clarify whether Unicode FIFO buffer is empty.
1018
1019 @param TerminalDevice Terminal driver private structure
1020
1021 @retval TRUE If Unicode FIFO buffer is empty.
1022 @retval FLASE If Unicode FIFO buffer is not empty.
1023
1024 **/
1025 BOOLEAN
1026 IsUnicodeFiFoEmpty (
1027 TERMINAL_DEV *TerminalDevice
1028 )
1029 {
1030 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {
1031 return TRUE;
1032 } else {
1033 return FALSE;
1034 }
1035 }
1036
1037 /**
1038 Clarify whether Unicode FIFO buffer is full.
1039
1040 @param TerminalDevice Terminal driver private structure
1041
1042 @retval TRUE If Unicode FIFO buffer is full.
1043 @retval FLASE If Unicode FIFO buffer is not full.
1044
1045 **/
1046 BOOLEAN
1047 IsUnicodeFiFoFull (
1048 TERMINAL_DEV *TerminalDevice
1049 )
1050 {
1051 UINT8 Tail;
1052 UINT8 Head;
1053
1054 Tail = TerminalDevice->UnicodeFiFo->Tail;
1055 Head = TerminalDevice->UnicodeFiFo->Head;
1056
1057 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
1058
1059 return TRUE;
1060 }
1061
1062 return FALSE;
1063 }
1064
1065 /**
1066 Count Unicode FIFO buffer.
1067
1068 @param TerminalDevice Terminal driver private structure
1069
1070 @return The count in bytes of Unicode FIFO.
1071
1072 **/
1073 UINT8
1074 UnicodeFiFoGetKeyCount (
1075 TERMINAL_DEV *TerminalDevice
1076 )
1077 {
1078 UINT8 Tail;
1079 UINT8 Head;
1080
1081 Tail = TerminalDevice->UnicodeFiFo->Tail;
1082 Head = TerminalDevice->UnicodeFiFo->Head;
1083
1084 if (Tail >= Head) {
1085 return (UINT8) (Tail - Head);
1086 } else {
1087 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);
1088 }
1089 }
1090
1091 /**
1092 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1093
1094 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1095
1096 **/
1097 VOID
1098 UnicodeToEfiKeyFlushState (
1099 IN TERMINAL_DEV *TerminalDevice
1100 )
1101 {
1102 EFI_INPUT_KEY Key;
1103 UINT32 InputState;
1104
1105 InputState = TerminalDevice->InputState;
1106
1107 if ((InputState & INPUT_STATE_ESC) != 0) {
1108 Key.ScanCode = SCAN_ESC;
1109 Key.UnicodeChar = 0;
1110 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1111 }
1112
1113 if ((InputState & INPUT_STATE_CSI) != 0) {
1114 Key.ScanCode = SCAN_NULL;
1115 Key.UnicodeChar = CSI;
1116 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1117 }
1118
1119 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {
1120 Key.ScanCode = SCAN_NULL;
1121 Key.UnicodeChar = LEFTOPENBRACKET;
1122 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1123 }
1124
1125 if ((InputState & INPUT_STATE_O) != 0) {
1126 Key.ScanCode = SCAN_NULL;
1127 Key.UnicodeChar = 'O';
1128 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1129 }
1130
1131 if ((InputState & INPUT_STATE_2) != 0) {
1132 Key.ScanCode = SCAN_NULL;
1133 Key.UnicodeChar = '2';
1134 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
1135 }
1136
1137 //
1138 // Cancel the timer.
1139 //
1140 gBS->SetTimer (
1141 TerminalDevice->TwoSecondTimeOut,
1142 TimerCancel,
1143 0
1144 );
1145
1146 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1147 }
1148
1149
1150 /**
1151 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1152 can be read through the Simple Input Protocol.
1153
1154 The table below shows the keyboard input mappings that this function supports.
1155 If the ESC sequence listed in one of the columns is presented, then it is translated
1156 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1157 key strokes are converted into EFI Keys.
1158
1159 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1160 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1161 converted into EFI Keys.
1162 There is one special input sequence that will force the system to reset.
1163 This is ESC R ESC r ESC R.
1164
1165 Symbols used in table below
1166 ===========================
1167 ESC = 0x1B
1168 CSI = 0x9B
1169 DEL = 0x7f
1170 ^ = CTRL
1171
1172 +=========+======+===========+==========+==========+
1173 | | EFI | UEFI 2.0 | | |
1174 | | Scan | | VT100+ | |
1175 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1176 +=========+======+===========+==========+==========+
1177 | NULL | 0x00 | | | |
1178 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1179 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1180 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1181 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1182 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1183 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1184 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1185 | | | ESC [ L | | ESC [ L |
1186 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1187 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1188 | | | | | ESC [ ? |
1189 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1190 | | | | | ESC [ / |
1191 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1192 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1193 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1194 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1195 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1196 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1197 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1198 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1199 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1200 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1201 | Escape | 0x17 | ESC | ESC | ESC |
1202 | F11 | 0x15 | | ESC ! | |
1203 | F12 | 0x16 | | ESC @ | |
1204 +=========+======+===========+==========+==========+
1205
1206 Special Mappings
1207 ================
1208 ESC R ESC r ESC R = Reset System
1209
1210 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1211
1212 **/
1213 VOID
1214 UnicodeToEfiKey (
1215 IN TERMINAL_DEV *TerminalDevice
1216 )
1217 {
1218 EFI_STATUS Status;
1219 EFI_STATUS TimerStatus;
1220 UINT16 UnicodeChar;
1221 EFI_INPUT_KEY Key;
1222 BOOLEAN SetDefaultResetState;
1223
1224 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1225
1226 if (!EFI_ERROR (TimerStatus)) {
1227 UnicodeToEfiKeyFlushState (TerminalDevice);
1228 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1229 }
1230
1231 while (!IsUnicodeFiFoEmpty(TerminalDevice)) {
1232
1233 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1234 //
1235 // Check to see if the 2 seconds timer has expired
1236 //
1237 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1238 if (!EFI_ERROR (TimerStatus)) {
1239 UnicodeToEfiKeyFlushState (TerminalDevice);
1240 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1241 }
1242 }
1243
1244 //
1245 // Fetch one Unicode character from the Unicode FIFO
1246 //
1247 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);
1248
1249 SetDefaultResetState = TRUE;
1250
1251 switch (TerminalDevice->InputState) {
1252 case INPUT_STATE_DEFAULT:
1253
1254 break;
1255
1256 case INPUT_STATE_ESC:
1257
1258 if (UnicodeChar == LEFTOPENBRACKET) {
1259 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
1260 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1261 continue;
1262 }
1263
1264 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {
1265 TerminalDevice->InputState |= INPUT_STATE_O;
1266 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1267 continue;
1268 }
1269
1270 Key.ScanCode = SCAN_NULL;
1271
1272 if (TerminalDevice->TerminalType == VT100PLUSTYPE ||
1273 TerminalDevice->TerminalType == VTUTF8TYPE) {
1274 switch (UnicodeChar) {
1275 case '1':
1276 Key.ScanCode = SCAN_F1;
1277 break;
1278 case '2':
1279 Key.ScanCode = SCAN_F2;
1280 break;
1281 case '3':
1282 Key.ScanCode = SCAN_F3;
1283 break;
1284 case '4':
1285 Key.ScanCode = SCAN_F4;
1286 break;
1287 case '5':
1288 Key.ScanCode = SCAN_F5;
1289 break;
1290 case '6':
1291 Key.ScanCode = SCAN_F6;
1292 break;
1293 case '7':
1294 Key.ScanCode = SCAN_F7;
1295 break;
1296 case '8':
1297 Key.ScanCode = SCAN_F8;
1298 break;
1299 case '9':
1300 Key.ScanCode = SCAN_F9;
1301 break;
1302 case '0':
1303 Key.ScanCode = SCAN_F10;
1304 break;
1305 case '!':
1306 Key.ScanCode = SCAN_F11;
1307 break;
1308 case '@':
1309 Key.ScanCode = SCAN_F12;
1310 break;
1311 case 'h':
1312 Key.ScanCode = SCAN_HOME;
1313 break;
1314 case 'k':
1315 Key.ScanCode = SCAN_END;
1316 break;
1317 case '+':
1318 Key.ScanCode = SCAN_INSERT;
1319 break;
1320 case '-':
1321 Key.ScanCode = SCAN_DELETE;
1322 break;
1323 case '/':
1324 Key.ScanCode = SCAN_PAGE_DOWN;
1325 break;
1326 case '?':
1327 Key.ScanCode = SCAN_PAGE_UP;
1328 break;
1329 default :
1330 break;
1331 }
1332 }
1333
1334 switch (UnicodeChar) {
1335 case 'R':
1336 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
1337 TerminalDevice->ResetState = RESET_STATE_ESC_R;
1338 SetDefaultResetState = FALSE;
1339 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {
1340 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1341 }
1342 Key.ScanCode = SCAN_NULL;
1343 break;
1344 case 'r':
1345 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
1346 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;
1347 SetDefaultResetState = FALSE;
1348 }
1349 Key.ScanCode = SCAN_NULL;
1350 break;
1351 default :
1352 break;
1353 }
1354
1355 if (SetDefaultResetState) {
1356 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1357 }
1358
1359 if (Key.ScanCode != SCAN_NULL) {
1360 Key.UnicodeChar = 0;
1361 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1362 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1363 UnicodeToEfiKeyFlushState (TerminalDevice);
1364 continue;
1365 }
1366
1367 UnicodeToEfiKeyFlushState (TerminalDevice);
1368
1369 break;
1370
1371 case INPUT_STATE_ESC | INPUT_STATE_O:
1372
1373 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1374
1375 Key.ScanCode = SCAN_NULL;
1376
1377 if (TerminalDevice->TerminalType == VT100TYPE) {
1378 switch (UnicodeChar) {
1379 case 'P':
1380 Key.ScanCode = SCAN_F1;
1381 break;
1382 case 'Q':
1383 Key.ScanCode = SCAN_F2;
1384 break;
1385 case 'w':
1386 Key.ScanCode = SCAN_F3;
1387 break;
1388 case 'x':
1389 Key.ScanCode = SCAN_F4;
1390 break;
1391 case 't':
1392 Key.ScanCode = SCAN_F5;
1393 break;
1394 case 'u':
1395 Key.ScanCode = SCAN_F6;
1396 break;
1397 case 'q':
1398 Key.ScanCode = SCAN_F7;
1399 break;
1400 case 'r':
1401 Key.ScanCode = SCAN_F8;
1402 break;
1403 case 'p':
1404 Key.ScanCode = SCAN_F9;
1405 break;
1406 case 'M':
1407 Key.ScanCode = SCAN_F10;
1408 break;
1409 default :
1410 break;
1411 }
1412 }
1413
1414 if (Key.ScanCode != SCAN_NULL) {
1415 Key.UnicodeChar = 0;
1416 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1417 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1418 UnicodeToEfiKeyFlushState (TerminalDevice);
1419 continue;
1420 }
1421
1422 UnicodeToEfiKeyFlushState (TerminalDevice);
1423
1424 break;
1425
1426 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
1427
1428 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1429
1430 Key.ScanCode = SCAN_NULL;
1431
1432 if (TerminalDevice->TerminalType == PCANSITYPE ||
1433 TerminalDevice->TerminalType == VT100TYPE ||
1434 TerminalDevice->TerminalType == VT100PLUSTYPE ||
1435 TerminalDevice->TerminalType == VTUTF8TYPE) {
1436 switch (UnicodeChar) {
1437 case 'A':
1438 Key.ScanCode = SCAN_UP;
1439 break;
1440 case 'B':
1441 Key.ScanCode = SCAN_DOWN;
1442 break;
1443 case 'C':
1444 Key.ScanCode = SCAN_RIGHT;
1445 break;
1446 case 'D':
1447 Key.ScanCode = SCAN_LEFT;
1448 break;
1449 case 'H':
1450 if (TerminalDevice->TerminalType == PCANSITYPE ||
1451 TerminalDevice->TerminalType == VT100TYPE) {
1452 Key.ScanCode = SCAN_HOME;
1453 }
1454 break;
1455 case 'F':
1456 if (TerminalDevice->TerminalType == PCANSITYPE) {
1457 Key.ScanCode = SCAN_END;
1458 }
1459 break;
1460 case 'K':
1461 if (TerminalDevice->TerminalType == VT100TYPE) {
1462 Key.ScanCode = SCAN_END;
1463 }
1464 break;
1465 case 'L':
1466 case '@':
1467 if (TerminalDevice->TerminalType == PCANSITYPE ||
1468 TerminalDevice->TerminalType == VT100TYPE) {
1469 Key.ScanCode = SCAN_INSERT;
1470 }
1471 break;
1472 case 'X':
1473 if (TerminalDevice->TerminalType == PCANSITYPE) {
1474 Key.ScanCode = SCAN_DELETE;
1475 }
1476 break;
1477 case 'P':
1478 if (TerminalDevice->TerminalType == VT100TYPE) {
1479 Key.ScanCode = SCAN_DELETE;
1480 } else if (TerminalDevice->TerminalType == PCANSITYPE) {
1481 Key.ScanCode = SCAN_F4;
1482 }
1483 break;
1484 case 'I':
1485 if (TerminalDevice->TerminalType == PCANSITYPE) {
1486 Key.ScanCode = SCAN_PAGE_UP;
1487 }
1488 break;
1489 case 'V':
1490 if (TerminalDevice->TerminalType == PCANSITYPE) {
1491 Key.ScanCode = SCAN_F10;
1492 }
1493 case '?':
1494 if (TerminalDevice->TerminalType == VT100TYPE) {
1495 Key.ScanCode = SCAN_PAGE_UP;
1496 }
1497 break;
1498 case 'G':
1499 if (TerminalDevice->TerminalType == PCANSITYPE) {
1500 Key.ScanCode = SCAN_PAGE_DOWN;
1501 }
1502 break;
1503 case 'U':
1504 if (TerminalDevice->TerminalType == PCANSITYPE) {
1505 Key.ScanCode = SCAN_F9;
1506 }
1507 case '/':
1508 if (TerminalDevice->TerminalType == VT100TYPE) {
1509 Key.ScanCode = SCAN_PAGE_DOWN;
1510 }
1511 break;
1512 case 'M':
1513 if (TerminalDevice->TerminalType == PCANSITYPE) {
1514 Key.ScanCode = SCAN_F1;
1515 }
1516 break;
1517 case 'N':
1518 if (TerminalDevice->TerminalType == PCANSITYPE) {
1519 Key.ScanCode = SCAN_F2;
1520 }
1521 break;
1522 case 'O':
1523 if (TerminalDevice->TerminalType == PCANSITYPE) {
1524 Key.ScanCode = SCAN_F3;
1525 }
1526 break;
1527 case 'Q':
1528 if (TerminalDevice->TerminalType == PCANSITYPE) {
1529 Key.ScanCode = SCAN_F5;
1530 }
1531 break;
1532 case 'R':
1533 if (TerminalDevice->TerminalType == PCANSITYPE) {
1534 Key.ScanCode = SCAN_F6;
1535 }
1536 break;
1537 case 'S':
1538 if (TerminalDevice->TerminalType == PCANSITYPE) {
1539 Key.ScanCode = SCAN_F7;
1540 }
1541 break;
1542 case 'T':
1543 if (TerminalDevice->TerminalType == PCANSITYPE) {
1544 Key.ScanCode = SCAN_F8;
1545 }
1546 break;
1547 default :
1548 break;
1549 }
1550 }
1551
1552 if (Key.ScanCode != SCAN_NULL) {
1553 Key.UnicodeChar = 0;
1554 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1555 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1556 UnicodeToEfiKeyFlushState (TerminalDevice);
1557 continue;
1558 }
1559
1560 UnicodeToEfiKeyFlushState (TerminalDevice);
1561
1562 break;
1563
1564
1565 default:
1566 //
1567 // Invalid state. This should never happen.
1568 //
1569 ASSERT (FALSE);
1570
1571 UnicodeToEfiKeyFlushState (TerminalDevice);
1572
1573 break;
1574 }
1575
1576 if (UnicodeChar == ESC) {
1577 TerminalDevice->InputState = INPUT_STATE_ESC;
1578 }
1579
1580 if (UnicodeChar == CSI) {
1581 TerminalDevice->InputState = INPUT_STATE_CSI;
1582 }
1583
1584 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1585 Status = gBS->SetTimer(
1586 TerminalDevice->TwoSecondTimeOut,
1587 TimerRelative,
1588 (UINT64)20000000
1589 );
1590 ASSERT_EFI_ERROR (Status);
1591 continue;
1592 }
1593
1594 if (SetDefaultResetState) {
1595 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1596 }
1597
1598 if (UnicodeChar == DEL) {
1599 Key.ScanCode = SCAN_DELETE;
1600 Key.UnicodeChar = 0;
1601 } else {
1602 Key.ScanCode = SCAN_NULL;
1603 Key.UnicodeChar = UnicodeChar;
1604 }
1605
1606 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
1607 }
1608 }