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