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