]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
apply for doxgen format.
[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
fb0b259e 3\r
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
95276127 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
fb0b259e 27 Reads the next keystroke from the input device. The WaitForKey Event can\r
66aa04e4 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
fb0b259e 32 KeyData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 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
fb0b259e 38 EFI_DEVICE_ERROR - The keystroke information was not returned due to\r
66aa04e4 39 hardware errors.\r
fb0b259e 40 EFI_INVALID_PARAMETER - KeyData is NULL.\r
66aa04e4 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
fb0b259e 50 }\r
66aa04e4 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
fb0b259e 75 Link,\r
76 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
77 NotifyEntry,\r
66aa04e4 78 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
79 );\r
fb0b259e 80 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
66aa04e4 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
fb0b259e 98\r
95276127 99 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().\r
fb0b259e 100 This driver only perform dependent serial device reset regardless of\r
95276127 101 the value of ExtendeVerification\r
fb0b259e 102\r
95276127 103 Arguments:\r
fb0b259e 104\r
95276127 105 This - Indicates the calling context.\r
fb0b259e 106\r
95276127 107 ExtendedVerification - Skip by this driver.\r
fb0b259e 108\r
95276127 109 Returns:\r
fb0b259e 110\r
95276127 111 EFI_SUCCESS\r
fb0b259e 112 The reset operation succeeds.\r
113\r
95276127 114 EFI_DEVICE_ERROR\r
115 The dependent serial port reset fails.\r
fb0b259e 116\r
95276127 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
fb0b259e 161\r
95276127 162 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().\r
fb0b259e 163\r
95276127 164 Arguments:\r
fb0b259e 165\r
95276127 166 This - Indicates the calling context.\r
fb0b259e 167\r
95276127 168 Key - A pointer to a buffer that is filled in with the keystroke\r
fb0b259e 169 information for the key that was sent from terminal.\r
170\r
95276127 171 Returns:\r
fb0b259e 172\r
95276127 173 EFI_SUCCESS\r
174 The keystroke information is returned successfully.\r
fb0b259e 175\r
95276127 176 EFI_NOT_READY\r
177 There is no keystroke data available.\r
fb0b259e 178\r
95276127 179 EFI_DEVICE_ERROR\r
180 The dependent serial device encounters error.\r
fb0b259e 181\r
95276127 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
fb0b259e 216 RegsiteredData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 217 state data for the key that was registered.\r
fb0b259e 218 InputData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 219 state data for the key that was pressed.\r
220\r
221Returns:\r
222 TRUE - Key be pressed matches a registered key.\r
fb0b259e 223 FLASE - Match failed.\r
224\r
66aa04e4 225--*/\r
226{\r
227 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
fb0b259e 228\r
66aa04e4 229 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
230 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
fb0b259e 231 return FALSE;\r
232 }\r
233\r
66aa04e4 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
fb0b259e 246\r
66aa04e4 247 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
fb0b259e 248 Signal the event if there is key available\r
249\r
66aa04e4 250 Arguments:\r
fb0b259e 251\r
66aa04e4 252 Event - Indicates the event that invoke this function.\r
fb0b259e 253\r
66aa04e4 254 Context - Indicates the calling context.\r
fb0b259e 255\r
66aa04e4 256 Returns:\r
fb0b259e 257\r
66aa04e4 258 N/A\r
fb0b259e 259\r
66aa04e4 260--*/\r
261{\r
262 TERMINAL_DEV *TerminalDevice;\r
fb0b259e 263\r
66aa04e4 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
fb0b259e 291 EFI_DEVICE_ERROR - The device is not functioning properly and could\r
66aa04e4 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
fb0b259e 307\r
66aa04e4 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
fb0b259e 319 Reads the next keystroke from the input device. The WaitForKey Event can\r
66aa04e4 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
fb0b259e 324 KeyData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 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
fb0b259e 330 EFI_DEVICE_ERROR - The keystroke information was not returned due to\r
66aa04e4 331 hardware errors.\r
fb0b259e 332 EFI_INVALID_PARAMETER - KeyData is NULL.\r
66aa04e4 333\r
334--*/\r
335{\r
336 TERMINAL_DEV *TerminalDevice;\r
337\r
338 if (KeyData == NULL) {\r
339 return EFI_INVALID_PARAMETER;\r
fb0b259e 340 }\r
66aa04e4 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
fb0b259e 361 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
66aa04e4 362 state for the input device.\r
fb0b259e 363\r
364 Returns:\r
66aa04e4 365 EFI_SUCCESS - The device state was set successfully.\r
fb0b259e 366 EFI_DEVICE_ERROR - The device is not functioning correctly and could\r
66aa04e4 367 not have the setting adjusted.\r
368 EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
fb0b259e 369 EFI_INVALID_PARAMETER - KeyToggleState is NULL.\r
66aa04e4 370\r
fb0b259e 371--*/\r
66aa04e4 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
fb0b259e 395 KeyData - A pointer to a buffer that is filled in with the keystroke\r
66aa04e4 396 information data for the key that was pressed.\r
fb0b259e 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
66aa04e4 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
fb0b259e 404 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.\r
405\r
406--*/\r
66aa04e4 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
fb0b259e 412 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
66aa04e4 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
fb0b259e 425 Link,\r
426 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
427 NotifyEntry,\r
66aa04e4 428 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
429 );\r
fb0b259e 430 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
66aa04e4 431 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
fb0b259e 432 *NotifyHandle = CurrentNotify->NotifyHandle;\r
66aa04e4 433 return EFI_SUCCESS;\r
434 }\r
435 }\r
436 }\r
437\r
438 //\r
439 // Allocate resource to save the notification function\r
fb0b259e 440 //\r
66aa04e4 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
fb0b259e 444 }\r
66aa04e4 445\r
fb0b259e 446 NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
66aa04e4 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
fb0b259e 452 //\r
66aa04e4 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
fb0b259e 460 *NotifyHandle = NewNotify->NotifyHandle;\r
66aa04e4 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
fb0b259e 477 This - Protocol instance pointer.\r
66aa04e4 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
fb0b259e 483 EFI_NOT_FOUND - Can not find the matching entry in database.\r
484\r
485--*/\r
66aa04e4 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
fb0b259e 494 }\r
495\r
66aa04e4 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
fb0b259e 512 Link,\r
513 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
514 NotifyEntry,\r
66aa04e4 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
fb0b259e 521 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
66aa04e4 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
fb0b259e 529 gBS->FreePool (CurrentNotify);\r
66aa04e4 530 return EFI_SUCCESS;\r
531 }\r
532 }\r
fb0b259e 533\r
534 return EFI_NOT_FOUND;\r
66aa04e4 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
fb0b259e 544 Step2: Translate Unicode into key information.\r
95276127 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
fb0b259e 582\r
95276127 583 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event\r
fb0b259e 584 Signal the event if there is key available\r
585\r
95276127 586 Arguments:\r
fb0b259e 587\r
95276127 588 Event - Indicates the event that invoke this function.\r
fb0b259e 589\r
95276127 590 Context - Indicates the calling context.\r
fb0b259e 591\r
95276127 592 Returns:\r
fb0b259e 593\r
95276127 594 N/A\r
fb0b259e 595\r
95276127 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
fb0b259e 616\r
95276127 617 Check for a pending key in the Efi Key FIFO or Serial device buffer.\r
fb0b259e 618\r
95276127 619 Arguments:\r
fb0b259e 620\r
95276127 621 This - Indicates the calling context.\r
fb0b259e 622\r
95276127 623 Returns:\r
fb0b259e 624\r
95276127 625 EFI_SUCCESS\r
fb0b259e 626 There is key pending.\r
627\r
95276127 628 EFI_NOT_READY\r
629 There is no key pending.\r
fb0b259e 630\r
95276127 631 EFI_DEVICE_ERROR\r
fb0b259e 632\r
95276127 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
fb0b259e 744 if reading serial buffer successfully, put the fetched key to\r
95276127 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
fb0b259e 1133\r
95276127 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
fb0b259e 1136 input mappings that this function supports. If the ESC sequence listed in one of the\r
95276127 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
fb0b259e 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
95276127 1142 converted into EFI Keys.\r
fb0b259e 1143\r
1144 There is one special input sequence that will force the system to reset.\r
95276127 1145 This is ESC R ESC r ESC R.\r
fb0b259e 1146\r
95276127 1147 Arguments:\r
1148\r
1149 TerminaDevice : The terminal device to use to translate raw input into EFI Keys\r
fb0b259e 1150\r
95276127 1151 Returns:\r
1152\r
1153 None\r
1154\r
1155Symbols used in table below\r
1156===========================\r
fb0b259e 1157 ESC = 0x1B\r
1158 CSI = 0x9B\r
1159 DEL = 0x7f\r
95276127 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
fb0b259e 1170| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |\r
95276127 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
fb0b259e 1207\r
95276127 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
fb0b259e 1216\r
95276127 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
fb0b259e 1255\r
1256 if (TerminalDevice->TerminalType == VT100PlusType ||\r
95276127 1257 TerminalDevice->TerminalType == VTUTF8Type) {\r
1258 switch (UnicodeChar) {\r
fb0b259e 1259 case '1':\r
1260 Key.ScanCode = SCAN_F1;\r
95276127 1261 break;\r
fb0b259e 1262 case '2':\r
1263 Key.ScanCode = SCAN_F2;\r
95276127 1264 break;\r
fb0b259e 1265 case '3':\r
1266 Key.ScanCode = SCAN_F3;\r
95276127 1267 break;\r
fb0b259e 1268 case '4':\r
1269 Key.ScanCode = SCAN_F4;\r
95276127 1270 break;\r
fb0b259e 1271 case '5':\r
1272 Key.ScanCode = SCAN_F5;\r
95276127 1273 break;\r
fb0b259e 1274 case '6':\r
1275 Key.ScanCode = SCAN_F6;\r
95276127 1276 break;\r
fb0b259e 1277 case '7':\r
1278 Key.ScanCode = SCAN_F7;\r
95276127 1279 break;\r
fb0b259e 1280 case '8':\r
1281 Key.ScanCode = SCAN_F8;\r
95276127 1282 break;\r
fb0b259e 1283 case '9':\r
1284 Key.ScanCode = SCAN_F9;\r
95276127 1285 break;\r
fb0b259e 1286 case '0':\r
1287 Key.ScanCode = SCAN_F10;\r
95276127 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
95276127 1294 break;\r
fb0b259e 1295 case 'h':\r
1296 Key.ScanCode = SCAN_HOME;\r
95276127 1297 break;\r
fb0b259e 1298 case 'k':\r
1299 Key.ScanCode = SCAN_END;\r
95276127 1300 break;\r
fb0b259e 1301 case '+':\r
1302 Key.ScanCode = SCAN_INSERT;\r
95276127 1303 break;\r
fb0b259e 1304 case '-':\r
1305 Key.ScanCode = SCAN_DELETE;\r
95276127 1306 break;\r
fb0b259e 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
95276127 1314 break;\r
1315 }\r
1316 }\r
fb0b259e 1317\r
95276127 1318 switch (UnicodeChar) {\r
fb0b259e 1319 case 'R':\r
95276127 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
fb0b259e 1328 case 'r':\r
95276127 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
fb0b259e 1335 default :\r
95276127 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
fb0b259e 1360\r
95276127 1361 if (TerminalDevice->TerminalType == VT100Type) {\r
1362 switch (UnicodeChar) {\r
fb0b259e 1363 case 'P':\r
1364 Key.ScanCode = SCAN_F1;\r
95276127 1365 break;\r
fb0b259e 1366 case 'Q':\r
1367 Key.ScanCode = SCAN_F2;\r
95276127 1368 break;\r
fb0b259e 1369 case 'w':\r
1370 Key.ScanCode = SCAN_F3;\r
95276127 1371 break;\r
fb0b259e 1372 case 'x':\r
1373 Key.ScanCode = SCAN_F4;\r
95276127 1374 break;\r
fb0b259e 1375 case 't':\r
1376 Key.ScanCode = SCAN_F5;\r
95276127 1377 break;\r
fb0b259e 1378 case 'u':\r
1379 Key.ScanCode = SCAN_F6;\r
95276127 1380 break;\r
fb0b259e 1381 case 'q':\r
1382 Key.ScanCode = SCAN_F7;\r
95276127 1383 break;\r
fb0b259e 1384 case 'r':\r
1385 Key.ScanCode = SCAN_F8;\r
95276127 1386 break;\r
fb0b259e 1387 case 'p':\r
1388 Key.ScanCode = SCAN_F9;\r
95276127 1389 break;\r
fb0b259e 1390 case 'M':\r
1391 Key.ScanCode = SCAN_F10;\r
95276127 1392 break;\r
fb0b259e 1393 default :\r
95276127 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
fb0b259e 1411\r
95276127 1412 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
fb0b259e 1413\r
95276127 1414 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1415\r
95276127 1416 if (TerminalDevice->TerminalType == PcAnsiType ||\r
1417 TerminalDevice->TerminalType == VT100Type ||\r
fb0b259e 1418 TerminalDevice->TerminalType == VT100PlusType ||\r
95276127 1419 TerminalDevice->TerminalType == VTUTF8Type) {\r
1420 switch (UnicodeChar) {\r
fb0b259e 1421 case 'A':\r
1422 Key.ScanCode = SCAN_UP;\r
95276127 1423 break;\r
fb0b259e 1424 case 'B':\r
1425 Key.ScanCode = SCAN_DOWN;\r
95276127 1426 break;\r
fb0b259e 1427 case 'C':\r
1428 Key.ScanCode = SCAN_RIGHT;\r
95276127 1429 break;\r
fb0b259e 1430 case 'D':\r
1431 Key.ScanCode = SCAN_LEFT;\r
95276127 1432 break;\r
fb0b259e 1433 case 'H':\r
95276127 1434 if (TerminalDevice->TerminalType == PcAnsiType ||\r
1435 TerminalDevice->TerminalType == VT100Type) {\r
fb0b259e 1436 Key.ScanCode = SCAN_HOME;\r
95276127 1437 }\r
1438 break;\r
fb0b259e 1439 case 'F':\r
95276127 1440 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1441 Key.ScanCode = SCAN_END;\r
1442 }\r
1443 break;\r
fb0b259e 1444 case 'K':\r
95276127 1445 if (TerminalDevice->TerminalType == VT100Type) {\r
fb0b259e 1446 Key.ScanCode = SCAN_END;\r
95276127 1447 }\r
1448 break;\r
fb0b259e 1449 case 'L':\r
1450 case '@':\r
95276127 1451 if (TerminalDevice->TerminalType == PcAnsiType ||\r
1452 TerminalDevice->TerminalType == VT100Type) {\r
fb0b259e 1453 Key.ScanCode = SCAN_INSERT;\r
95276127 1454 }\r
1455 break;\r
fb0b259e 1456 case 'X':\r
95276127 1457 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1458 Key.ScanCode = SCAN_DELETE;\r
1459 }\r
1460 break;\r
fb0b259e 1461 case 'P':\r
95276127 1462 if (TerminalDevice->TerminalType == VT100Type) {\r
fb0b259e 1463 Key.ScanCode = SCAN_DELETE;\r
95276127 1464 } else if (TerminalDevice->TerminalType == PcAnsiType) {\r
1465 Key.ScanCode = SCAN_F4;\r
1466 }\r
1467 break;\r
fb0b259e 1468 case 'I':\r
95276127 1469 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1470 Key.ScanCode = SCAN_PAGE_UP;\r
1471 }\r
fb0b259e 1472 break;\r
1473 case 'V':\r
95276127 1474 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1475 Key.ScanCode = SCAN_F10;\r
fb0b259e 1476 }\r
1477 case '?':\r
95276127 1478 if (TerminalDevice->TerminalType == VT100Type) {\r
fb0b259e 1479 Key.ScanCode = SCAN_PAGE_UP;\r
95276127 1480 }\r
1481 break;\r
fb0b259e 1482 case 'G':\r
95276127 1483 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1484 Key.ScanCode = SCAN_PAGE_DOWN;\r
1485 }\r
fb0b259e 1486 break;\r
1487 case 'U':\r
95276127 1488 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1489 Key.ScanCode = SCAN_F9;\r
1490 }\r
fb0b259e 1491 case '/':\r
95276127 1492 if (TerminalDevice->TerminalType == VT100Type) {\r
fb0b259e 1493 Key.ScanCode = SCAN_PAGE_DOWN;\r
95276127 1494 }\r
1495 break;\r
fb0b259e 1496 case 'M':\r
95276127 1497 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1498 Key.ScanCode = SCAN_F1;\r
1499 }\r
fb0b259e 1500 break;\r
1501 case 'N':\r
95276127 1502 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1503 Key.ScanCode = SCAN_F2;\r
1504 }\r
fb0b259e 1505 break;\r
1506 case 'O':\r
95276127 1507 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1508 Key.ScanCode = SCAN_F3;\r
1509 }\r
fb0b259e 1510 break;\r
1511 case 'Q':\r
95276127 1512 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1513 Key.ScanCode = SCAN_F5;\r
1514 }\r
fb0b259e 1515 break;\r
1516 case 'R':\r
95276127 1517 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1518 Key.ScanCode = SCAN_F6;\r
1519 }\r
fb0b259e 1520 break;\r
1521 case 'S':\r
95276127 1522 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1523 Key.ScanCode = SCAN_F7;\r
1524 }\r
fb0b259e 1525 break;\r
1526 case 'T':\r
95276127 1527 if (TerminalDevice->TerminalType == PcAnsiType) {\r
1528 Key.ScanCode = SCAN_F8;\r
1529 }\r
fb0b259e 1530 break;\r
1531 default :\r
95276127 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
fb0b259e 1548\r
95276127 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
fb0b259e 1567\r
95276127 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