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