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