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