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