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