]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
ECC cleanup: Non-Boolean comparisons should use a compare operator (==, !=, >, <...
[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
95276127 869\r
870 if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
871 //\r
872 // Efi Key FIFO is full\r
873 //\r
874 return FALSE;\r
875 }\r
876\r
5c998646 877 TerminalDevice->EfiKeyFiFo->Data[Tail] = Key;\r
95276127 878\r
5c998646 879 TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 880\r
881 return TRUE;\r
882}\r
883\r
e49ef433 884/**\r
885 Remove one pre-fetched key out of the FIFO buffer.\r
886\r
887 @param TerminalDevice Terminal driver private structure.\r
888 @param Output The key will be removed.\r
889\r
00bfdbe1 890 @retval TRUE If insert successfully.\r
891 @retval FLASE If FIFO buffer is empty before remove operation.\r
e49ef433 892\r
893**/\r
95276127 894BOOLEAN\r
895EfiKeyFiFoRemoveOneKey (\r
896 TERMINAL_DEV *TerminalDevice,\r
897 EFI_INPUT_KEY *Output\r
898 )\r
95276127 899{\r
900 UINT8 Head;\r
901\r
5c998646 902 Head = TerminalDevice->EfiKeyFiFo->Head;\r
95276127 903\r
904 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
905 //\r
906 // FIFO is empty\r
907 //\r
908 Output->ScanCode = SCAN_NULL;\r
909 Output->UnicodeChar = 0;\r
910 return FALSE;\r
911 }\r
912\r
5c998646 913 *Output = TerminalDevice->EfiKeyFiFo->Data[Head];\r
95276127 914\r
5c998646 915 TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 916\r
917 return TRUE;\r
918}\r
919\r
e49ef433 920/**\r
921 Clarify whether FIFO buffer is empty.\r
922\r
923 @param TerminalDevice Terminal driver private structure\r
924\r
00bfdbe1 925 @retval TRUE If FIFO buffer is empty.\r
926 @retval FLASE If FIFO buffer is not empty.\r
e49ef433 927\r
928**/\r
95276127 929BOOLEAN\r
930IsEfiKeyFiFoEmpty (\r
931 TERMINAL_DEV *TerminalDevice\r
932 )\r
95276127 933{\r
5c998646 934 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {\r
95276127 935 return TRUE;\r
936 } else {\r
937 return FALSE;\r
938 }\r
939}\r
940\r
e49ef433 941/**\r
942 Clarify whether FIFO buffer is full.\r
943\r
944 @param TerminalDevice Terminal driver private structure\r
945\r
00bfdbe1 946 @retval TRUE If FIFO buffer is full.\r
947 @retval FLASE If FIFO buffer is not full.\r
e49ef433 948\r
949**/\r
95276127 950BOOLEAN\r
951IsEfiKeyFiFoFull (\r
952 TERMINAL_DEV *TerminalDevice\r
953 )\r
95276127 954{\r
955 UINT8 Tail;\r
956 UINT8 Head;\r
957\r
5c998646 958 Tail = TerminalDevice->EfiKeyFiFo->Tail;\r
959 Head = TerminalDevice->EfiKeyFiFo->Head;\r
95276127 960\r
961 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
962\r
963 return TRUE;\r
964 }\r
965\r
966 return FALSE;\r
967}\r
968\r
e49ef433 969/**\r
970 Insert one pre-fetched key into the Unicode FIFO buffer.\r
971\r
972 @param TerminalDevice Terminal driver private structure.\r
973 @param Input The key will be input.\r
974\r
00bfdbe1 975 @retval TRUE If insert successfully.\r
976 @retval FLASE If Unicode FIFO buffer is full before key insertion,\r
e49ef433 977 and the key is lost.\r
978\r
979**/\r
95276127 980BOOLEAN\r
981UnicodeFiFoInsertOneKey (\r
982 TERMINAL_DEV *TerminalDevice,\r
983 UINT16 Input\r
984 )\r
95276127 985{\r
986 UINT8 Tail;\r
987\r
5c998646 988 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
95276127 989\r
990 if (IsUnicodeFiFoFull (TerminalDevice)) {\r
991 //\r
992 // Unicode FIFO is full\r
993 //\r
994 return FALSE;\r
995 }\r
996\r
5c998646 997 TerminalDevice->UnicodeFiFo->Data[Tail] = Input;\r
95276127 998\r
5c998646 999 TerminalDevice->UnicodeFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 1000\r
1001 return TRUE;\r
1002}\r
1003\r
e49ef433 1004/**\r
1005 Remove one pre-fetched key out of the Unicode FIFO buffer.\r
1006\r
1007 @param TerminalDevice Terminal driver private structure.\r
1008 @param Output The key will be removed.\r
1009\r
00bfdbe1 1010 @retval TRUE If insert successfully.\r
1011 @retval FLASE If Unicode FIFO buffer is empty before remove operation.\r
e49ef433 1012\r
1013**/\r
95276127 1014BOOLEAN\r
1015UnicodeFiFoRemoveOneKey (\r
1016 TERMINAL_DEV *TerminalDevice,\r
1017 UINT16 *Output\r
1018 )\r
95276127 1019{\r
1020 UINT8 Head;\r
1021\r
5c998646 1022 Head = TerminalDevice->UnicodeFiFo->Head;\r
95276127 1023\r
1024 if (IsUnicodeFiFoEmpty (TerminalDevice)) {\r
1025 //\r
1026 // FIFO is empty\r
1027 //\r
1028 Output = NULL;\r
1029 return FALSE;\r
1030 }\r
1031\r
5c998646 1032 *Output = TerminalDevice->UnicodeFiFo->Data[Head];\r
95276127 1033\r
5c998646 1034 TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 1035\r
1036 return TRUE;\r
1037}\r
1038\r
e49ef433 1039/**\r
1040 Clarify whether Unicode FIFO buffer is empty.\r
1041\r
1042 @param TerminalDevice Terminal driver private structure\r
1043\r
00bfdbe1 1044 @retval TRUE If Unicode FIFO buffer is empty.\r
1045 @retval FLASE If Unicode FIFO buffer is not empty.\r
e49ef433 1046\r
1047**/\r
95276127 1048BOOLEAN\r
1049IsUnicodeFiFoEmpty (\r
1050 TERMINAL_DEV *TerminalDevice\r
1051 )\r
95276127 1052{\r
5c998646 1053 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {\r
95276127 1054 return TRUE;\r
1055 } else {\r
1056 return FALSE;\r
1057 }\r
1058}\r
1059\r
e49ef433 1060/**\r
1061 Clarify whether Unicode FIFO buffer is full.\r
1062\r
1063 @param TerminalDevice Terminal driver private structure\r
1064\r
00bfdbe1 1065 @retval TRUE If Unicode FIFO buffer is full.\r
1066 @retval FLASE If Unicode FIFO buffer is not full.\r
e49ef433 1067\r
1068**/\r
95276127 1069BOOLEAN\r
1070IsUnicodeFiFoFull (\r
1071 TERMINAL_DEV *TerminalDevice\r
1072 )\r
95276127 1073{\r
1074 UINT8 Tail;\r
1075 UINT8 Head;\r
1076\r
5c998646 1077 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
1078 Head = TerminalDevice->UnicodeFiFo->Head;\r
95276127 1079\r
1080 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
1081\r
1082 return TRUE;\r
1083 }\r
1084\r
1085 return FALSE;\r
1086}\r
1087\r
8fd98315 1088/**\r
1089 Count Unicode FIFO buffer.\r
1090\r
1091 @param TerminalDevice Terminal driver private structure\r
1092\r
1093 @return The count in bytes of Unicode FIFO.\r
1094\r
1095**/\r
95276127 1096UINT8\r
1097UnicodeFiFoGetKeyCount (\r
1098 TERMINAL_DEV *TerminalDevice\r
1099 )\r
1100{\r
1101 UINT8 Tail;\r
1102 UINT8 Head;\r
1103\r
5c998646 1104 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
1105 Head = TerminalDevice->UnicodeFiFo->Head;\r
95276127 1106\r
1107 if (Tail >= Head) {\r
1108 return (UINT8) (Tail - Head);\r
1109 } else {\r
1110 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);\r
1111 }\r
1112}\r
1113\r
8fd98315 1114/**\r
1115 Update the Unicode characters from a terminal input device into EFI Keys FIFO.\r
5c998646 1116\r
8fd98315 1117 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys\r
1118\r
8fd98315 1119**/\r
95276127 1120VOID\r
1121UnicodeToEfiKeyFlushState (\r
1122 IN TERMINAL_DEV *TerminalDevice\r
1123 )\r
1124{\r
1125 EFI_INPUT_KEY Key;\r
11baadb6 1126 UINT32 InputState;\r
5c998646 1127\r
11baadb6 1128 InputState = TerminalDevice->InputState;\r
5c998646 1129\r
11baadb6 1130 if ((InputState & INPUT_STATE_ESC) != 0) {\r
95276127 1131 Key.ScanCode = SCAN_ESC;\r
1132 Key.UnicodeChar = 0;\r
1133 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1134 }\r
1135\r
11baadb6 1136 if ((InputState & INPUT_STATE_CSI) != 0) {\r
95276127 1137 Key.ScanCode = SCAN_NULL;\r
1138 Key.UnicodeChar = CSI;\r
1139 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1140 }\r
1141\r
11baadb6 1142 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {\r
95276127 1143 Key.ScanCode = SCAN_NULL;\r
1144 Key.UnicodeChar = LEFTOPENBRACKET;\r
1145 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1146 }\r
1147\r
11baadb6 1148 if ((InputState & INPUT_STATE_O) != 0) {\r
95276127 1149 Key.ScanCode = SCAN_NULL;\r
1150 Key.UnicodeChar = 'O';\r
1151 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1152 }\r
1153\r
11baadb6 1154 if ((InputState & INPUT_STATE_2) != 0) {\r
95276127 1155 Key.ScanCode = SCAN_NULL;\r
1156 Key.UnicodeChar = '2';\r
1157 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1158 }\r
1159\r
ab76200c 1160 //\r
1161 // Cancel the timer.\r
1162 //\r
95276127 1163 gBS->SetTimer (\r
1164 TerminalDevice->TwoSecondTimeOut,\r
1165 TimerCancel,\r
1166 0\r
1167 );\r
1168\r
1169 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1170}\r
1171\r
e49ef433 1172\r
1173/**\r
1174 Converts a stream of Unicode characters from a terminal input device into EFI Keys that\r
5c998646 1175 can be read through the Simple Input Protocol.\r
1176\r
8fd98315 1177 The table below shows the keyboard input mappings that this function supports.\r
1178 If the ESC sequence listed in one of the columns is presented, then it is translated\r
11baadb6 1179 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw\r
8fd98315 1180 key strokes are converted into EFI Keys.\r
1181\r
e49ef433 1182 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not\r
1183 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are\r
1184 converted into EFI Keys.\r
1185 There is one special input sequence that will force the system to reset.\r
1186 This is ESC R ESC r ESC R.\r
1187\r
1188 Symbols used in table below\r
1189 ===========================\r
1190 ESC = 0x1B\r
1191 CSI = 0x9B\r
1192 DEL = 0x7f\r
1193 ^ = CTRL\r
8fd98315 1194\r
e49ef433 1195 +=========+======+===========+==========+==========+\r
1196 | | EFI | UEFI 2.0 | | |\r
1197 | | Scan | | VT100+ | |\r
1198 | KEY | Code | PC ANSI | VTUTF8 | VT100 |\r
1199 +=========+======+===========+==========+==========+\r
1200 | NULL | 0x00 | | | |\r
1201 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |\r
1202 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |\r
1203 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |\r
1204 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |\r
1205 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |\r
1206 | END | 0x06 | ESC [ F | ESC k | ESC [ K |\r
1207 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |\r
1208 | | | ESC [ L | | ESC [ L |\r
1209 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |\r
1210 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |\r
1211 | | | | | ESC [ ? |\r
1212 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |\r
1213 | | | | | ESC [ / |\r
1214 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |\r
1215 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |\r
1216 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |\r
1217 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |\r
1218 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |\r
1219 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |\r
1220 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |\r
1221 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |\r
1222 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |\r
1223 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |\r
1224 | Escape | 0x17 | ESC | ESC | ESC |\r
1225 | F11 | 0x15 | | ESC ! | |\r
1226 | F12 | 0x16 | | ESC @ | |\r
1227 +=========+======+===========+==========+==========+\r
8fd98315 1228\r
e49ef433 1229 Special Mappings\r
1230 ================\r
1231 ESC R ESC r ESC R = Reset System\r
1232\r
e49ef433 1233 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys\r
1234\r
e49ef433 1235**/\r
95276127 1236VOID\r
1237UnicodeToEfiKey (\r
1238 IN TERMINAL_DEV *TerminalDevice\r
1239 )\r
95276127 1240{\r
1241 EFI_STATUS Status;\r
1242 EFI_STATUS TimerStatus;\r
1243 UINT16 UnicodeChar;\r
1244 EFI_INPUT_KEY Key;\r
1245 BOOLEAN SetDefaultResetState;\r
fb0b259e 1246\r
95276127 1247 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
1248\r
1249 if (!EFI_ERROR (TimerStatus)) {\r
1250 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1251 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1252 }\r
1253\r
1254 while (!IsUnicodeFiFoEmpty(TerminalDevice)) {\r
fb0b259e 1255\r
95276127 1256 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
1257 //\r
1258 // Check to see if the 2 second timer has expired\r
1259 //\r
1260 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
1261 if (!EFI_ERROR (TimerStatus)) {\r
1262 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1263 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1264 }\r
1265 }\r
1266\r
1267 //\r
1268 // Fetch one Unicode character from the Unicode FIFO\r
1269 //\r
8fd98315 1270 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);\r
95276127 1271\r
1272 SetDefaultResetState = TRUE;\r
1273\r
1274 switch (TerminalDevice->InputState) {\r
1275 case INPUT_STATE_DEFAULT:\r
1276\r
1277 break;\r
1278\r
1279 case INPUT_STATE_ESC:\r
1280\r
1281 if (UnicodeChar == LEFTOPENBRACKET) {\r
1282 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;\r
1283 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1284 continue;\r
1285 }\r
1286\r
e49ef433 1287 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {\r
95276127 1288 TerminalDevice->InputState |= INPUT_STATE_O;\r
1289 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1290 continue;\r
1291 }\r
1292\r
1293 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1294\r
e49ef433 1295 if (TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
1296 TerminalDevice->TerminalType == VTUTF8TYPE) {\r
95276127 1297 switch (UnicodeChar) {\r
fb0b259e 1298 case '1':\r
1299 Key.ScanCode = SCAN_F1;\r
95276127 1300 break;\r
fb0b259e 1301 case '2':\r
1302 Key.ScanCode = SCAN_F2;\r
95276127 1303 break;\r
fb0b259e 1304 case '3':\r
1305 Key.ScanCode = SCAN_F3;\r
95276127 1306 break;\r
fb0b259e 1307 case '4':\r
1308 Key.ScanCode = SCAN_F4;\r
95276127 1309 break;\r
fb0b259e 1310 case '5':\r
1311 Key.ScanCode = SCAN_F5;\r
95276127 1312 break;\r
fb0b259e 1313 case '6':\r
1314 Key.ScanCode = SCAN_F6;\r
95276127 1315 break;\r
fb0b259e 1316 case '7':\r
1317 Key.ScanCode = SCAN_F7;\r
95276127 1318 break;\r
fb0b259e 1319 case '8':\r
1320 Key.ScanCode = SCAN_F8;\r
95276127 1321 break;\r
fb0b259e 1322 case '9':\r
1323 Key.ScanCode = SCAN_F9;\r
95276127 1324 break;\r
fb0b259e 1325 case '0':\r
1326 Key.ScanCode = SCAN_F10;\r
95276127 1327 break;\r
66aa04e4 1328 case '!':\r
1329 Key.ScanCode = SCAN_F11;\r
1330 break;\r
1331 case '@':\r
1332 Key.ScanCode = SCAN_F12;\r
95276127 1333 break;\r
fb0b259e 1334 case 'h':\r
1335 Key.ScanCode = SCAN_HOME;\r
95276127 1336 break;\r
fb0b259e 1337 case 'k':\r
1338 Key.ScanCode = SCAN_END;\r
95276127 1339 break;\r
fb0b259e 1340 case '+':\r
1341 Key.ScanCode = SCAN_INSERT;\r
95276127 1342 break;\r
fb0b259e 1343 case '-':\r
1344 Key.ScanCode = SCAN_DELETE;\r
95276127 1345 break;\r
fb0b259e 1346 case '/':\r
1347 Key.ScanCode = SCAN_PAGE_DOWN;\r
1348 break;\r
1349 case '?':\r
1350 Key.ScanCode = SCAN_PAGE_UP;\r
1351 break;\r
1352 default :\r
95276127 1353 break;\r
1354 }\r
1355 }\r
fb0b259e 1356\r
95276127 1357 switch (UnicodeChar) {\r
fb0b259e 1358 case 'R':\r
95276127 1359 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {\r
1360 TerminalDevice->ResetState = RESET_STATE_ESC_R;\r
1361 SetDefaultResetState = FALSE;\r
1362 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {\r
1363 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1364 }\r
1365 Key.ScanCode = SCAN_NULL;\r
1366 break;\r
fb0b259e 1367 case 'r':\r
95276127 1368 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {\r
1369 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;\r
1370 SetDefaultResetState = FALSE;\r
1371 }\r
1372 Key.ScanCode = SCAN_NULL;\r
1373 break;\r
fb0b259e 1374 default :\r
95276127 1375 break;\r
1376 }\r
1377\r
1378 if (SetDefaultResetState) {\r
1379 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1380 }\r
1381\r
1382 if (Key.ScanCode != SCAN_NULL) {\r
1383 Key.UnicodeChar = 0;\r
1384 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1385 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1386 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1387 continue;\r
1388 }\r
1389\r
1390 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1391\r
1392 break;\r
1393\r
1394 case INPUT_STATE_ESC | INPUT_STATE_O:\r
1395\r
1396 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1397\r
1398 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1399\r
e49ef433 1400 if (TerminalDevice->TerminalType == VT100TYPE) {\r
95276127 1401 switch (UnicodeChar) {\r
fb0b259e 1402 case 'P':\r
1403 Key.ScanCode = SCAN_F1;\r
95276127 1404 break;\r
fb0b259e 1405 case 'Q':\r
1406 Key.ScanCode = SCAN_F2;\r
95276127 1407 break;\r
fb0b259e 1408 case 'w':\r
1409 Key.ScanCode = SCAN_F3;\r
95276127 1410 break;\r
fb0b259e 1411 case 'x':\r
1412 Key.ScanCode = SCAN_F4;\r
95276127 1413 break;\r
fb0b259e 1414 case 't':\r
1415 Key.ScanCode = SCAN_F5;\r
95276127 1416 break;\r
fb0b259e 1417 case 'u':\r
1418 Key.ScanCode = SCAN_F6;\r
95276127 1419 break;\r
fb0b259e 1420 case 'q':\r
1421 Key.ScanCode = SCAN_F7;\r
95276127 1422 break;\r
fb0b259e 1423 case 'r':\r
1424 Key.ScanCode = SCAN_F8;\r
95276127 1425 break;\r
fb0b259e 1426 case 'p':\r
1427 Key.ScanCode = SCAN_F9;\r
95276127 1428 break;\r
fb0b259e 1429 case 'M':\r
1430 Key.ScanCode = SCAN_F10;\r
95276127 1431 break;\r
fb0b259e 1432 default :\r
95276127 1433 break;\r
1434 }\r
1435 }\r
1436\r
1437 if (Key.ScanCode != SCAN_NULL) {\r
1438 Key.UnicodeChar = 0;\r
1439 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1440 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1441 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1442 continue;\r
1443 }\r
1444\r
1445 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1446\r
1447 break;\r
1448\r
1449 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:\r
fb0b259e 1450\r
95276127 1451 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
fb0b259e 1452\r
95276127 1453 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1454\r
e49ef433 1455 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1456 TerminalDevice->TerminalType == VT100TYPE ||\r
1457 TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
1458 TerminalDevice->TerminalType == VTUTF8TYPE) {\r
95276127 1459 switch (UnicodeChar) {\r
fb0b259e 1460 case 'A':\r
1461 Key.ScanCode = SCAN_UP;\r
95276127 1462 break;\r
fb0b259e 1463 case 'B':\r
1464 Key.ScanCode = SCAN_DOWN;\r
95276127 1465 break;\r
fb0b259e 1466 case 'C':\r
1467 Key.ScanCode = SCAN_RIGHT;\r
95276127 1468 break;\r
fb0b259e 1469 case 'D':\r
1470 Key.ScanCode = SCAN_LEFT;\r
95276127 1471 break;\r
fb0b259e 1472 case 'H':\r
e49ef433 1473 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1474 TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1475 Key.ScanCode = SCAN_HOME;\r
95276127 1476 }\r
1477 break;\r
fb0b259e 1478 case 'F':\r
e49ef433 1479 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1480 Key.ScanCode = SCAN_END;\r
1481 }\r
1482 break;\r
fb0b259e 1483 case 'K':\r
e49ef433 1484 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1485 Key.ScanCode = SCAN_END;\r
95276127 1486 }\r
1487 break;\r
fb0b259e 1488 case 'L':\r
1489 case '@':\r
e49ef433 1490 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1491 TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1492 Key.ScanCode = SCAN_INSERT;\r
95276127 1493 }\r
1494 break;\r
fb0b259e 1495 case 'X':\r
e49ef433 1496 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1497 Key.ScanCode = SCAN_DELETE;\r
1498 }\r
1499 break;\r
fb0b259e 1500 case 'P':\r
e49ef433 1501 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1502 Key.ScanCode = SCAN_DELETE;\r
e49ef433 1503 } else if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1504 Key.ScanCode = SCAN_F4;\r
1505 }\r
1506 break;\r
fb0b259e 1507 case 'I':\r
e49ef433 1508 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1509 Key.ScanCode = SCAN_PAGE_UP;\r
1510 }\r
fb0b259e 1511 break;\r
1512 case 'V':\r
e49ef433 1513 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1514 Key.ScanCode = SCAN_F10;\r
fb0b259e 1515 }\r
1516 case '?':\r
e49ef433 1517 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1518 Key.ScanCode = SCAN_PAGE_UP;\r
95276127 1519 }\r
1520 break;\r
fb0b259e 1521 case 'G':\r
e49ef433 1522 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1523 Key.ScanCode = SCAN_PAGE_DOWN;\r
1524 }\r
fb0b259e 1525 break;\r
1526 case 'U':\r
e49ef433 1527 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1528 Key.ScanCode = SCAN_F9;\r
1529 }\r
fb0b259e 1530 case '/':\r
e49ef433 1531 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1532 Key.ScanCode = SCAN_PAGE_DOWN;\r
95276127 1533 }\r
1534 break;\r
fb0b259e 1535 case 'M':\r
e49ef433 1536 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1537 Key.ScanCode = SCAN_F1;\r
1538 }\r
fb0b259e 1539 break;\r
1540 case 'N':\r
e49ef433 1541 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1542 Key.ScanCode = SCAN_F2;\r
1543 }\r
fb0b259e 1544 break;\r
1545 case 'O':\r
e49ef433 1546 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1547 Key.ScanCode = SCAN_F3;\r
1548 }\r
fb0b259e 1549 break;\r
1550 case 'Q':\r
e49ef433 1551 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1552 Key.ScanCode = SCAN_F5;\r
1553 }\r
fb0b259e 1554 break;\r
1555 case 'R':\r
e49ef433 1556 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1557 Key.ScanCode = SCAN_F6;\r
1558 }\r
fb0b259e 1559 break;\r
1560 case 'S':\r
e49ef433 1561 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1562 Key.ScanCode = SCAN_F7;\r
1563 }\r
fb0b259e 1564 break;\r
1565 case 'T':\r
e49ef433 1566 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1567 Key.ScanCode = SCAN_F8;\r
1568 }\r
fb0b259e 1569 break;\r
1570 default :\r
95276127 1571 break;\r
1572 }\r
1573 }\r
1574\r
1575 if (Key.ScanCode != SCAN_NULL) {\r
1576 Key.UnicodeChar = 0;\r
1577 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1578 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1579 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1580 continue;\r
1581 }\r
1582\r
1583 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1584\r
1585 break;\r
1586\r
fb0b259e 1587\r
95276127 1588 default:\r
1589 //\r
1590 // Invalid state. This should never happen.\r
1591 //\r
1592 ASSERT (FALSE);\r
1593\r
1594 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1595\r
1596 break;\r
1597 }\r
1598\r
1599 if (UnicodeChar == ESC) {\r
1600 TerminalDevice->InputState = INPUT_STATE_ESC;\r
1601 }\r
66aa04e4 1602\r
1603 if (UnicodeChar == CSI) {\r
1604 TerminalDevice->InputState = INPUT_STATE_CSI;\r
1605 }\r
fb0b259e 1606\r
95276127 1607 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
1608 Status = gBS->SetTimer(\r
1609 TerminalDevice->TwoSecondTimeOut,\r
1610 TimerRelative,\r
1611 (UINT64)20000000\r
1612 );\r
1613 ASSERT_EFI_ERROR (Status);\r
1614 continue;\r
1615 }\r
1616\r
1617 if (SetDefaultResetState) {\r
1618 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1619 }\r
1620\r
1621 if (UnicodeChar == DEL) {\r
1622 Key.ScanCode = SCAN_DELETE;\r
1623 Key.UnicodeChar = 0;\r
1624 } else {\r
1625 Key.ScanCode = SCAN_NULL;\r
1626 Key.UnicodeChar = UnicodeChar;\r
1627 }\r
1628\r
1629 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1630 }\r
1631}\r