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