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