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