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