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