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