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