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