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