]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
Add missing break and add comment to non-necessary break.
[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
402e4a9d 327 OUT VOID **NotifyHandle\r
4bc6ad39
RN
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
402e4a9d 355 *NotifyHandle = CurrentNotify;\r
4bc6ad39
RN
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
b8a605d0 371 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
4bc6ad39
RN
372 InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);\r
373\r
402e4a9d 374 *NotifyHandle = NewNotify;\r
4bc6ad39
RN
375\r
376 return EFI_SUCCESS;\r
377}\r
378\r
379\r
380/**\r
381 Remove a registered notification function from a particular keystroke.\r
382\r
383 @param This Protocol instance pointer.\r
384 @param NotificationHandle The handle of the notification function being\r
385 unregistered.\r
386\r
387 @retval EFI_SUCCESS The notification function was unregistered\r
388 successfully.\r
389 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
390\r
391**/\r
392EFI_STATUS\r
393EFIAPI\r
394TerminalConInUnregisterKeyNotify (\r
395 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
402e4a9d 396 IN VOID *NotificationHandle\r
4bc6ad39
RN
397 )\r
398{\r
399 TERMINAL_DEV *TerminalDevice;\r
400 LIST_ENTRY *Link;\r
401 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
402 LIST_ENTRY *NotifyList;\r
403\r
404 if (NotificationHandle == NULL) {\r
405 return EFI_INVALID_PARAMETER;\r
406 }\r
407\r
4bc6ad39
RN
408 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
409\r
410 NotifyList = &TerminalDevice->NotifyList;\r
411 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
412 CurrentNotify = CR (\r
413 Link,\r
414 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
415 NotifyEntry,\r
416 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
417 );\r
402e4a9d 418 if (CurrentNotify == NotificationHandle) {\r
4bc6ad39
RN
419 //\r
420 // Remove the notification function from NotifyList and free resources\r
421 //\r
422 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
423\r
424 gBS->FreePool (CurrentNotify);\r
425 return EFI_SUCCESS;\r
426 }\r
427 }\r
428\r
429 //\r
430 // Can not find the matching entry in database.\r
431 //\r
432 return EFI_INVALID_PARAMETER;\r
433}\r
434\r
435/**\r
436 Translate raw data into Unicode (according to different encode), and\r
437 translate Unicode into key information. (according to different standard).\r
438\r
439 @param TerminalDevice Terminal driver private structure.\r
440\r
441**/\r
442VOID\r
443TranslateRawDataToEfiKey (\r
444 IN TERMINAL_DEV *TerminalDevice\r
445 )\r
446{\r
447 switch (TerminalDevice->TerminalType) {\r
448\r
449 case PCANSITYPE:\r
450 case VT100TYPE:\r
451 case VT100PLUSTYPE:\r
452 AnsiRawDataToUnicode (TerminalDevice);\r
453 UnicodeToEfiKey (TerminalDevice);\r
454 break;\r
455\r
456 case VTUTF8TYPE:\r
457 //\r
458 // Process all the raw data in the RawFIFO,\r
459 // put the processed key into UnicodeFIFO.\r
460 //\r
461 VTUTF8RawDataToUnicode (TerminalDevice);\r
462\r
463 //\r
464 // Translate all the Unicode data in the UnicodeFIFO to Efi key,\r
465 // then put into EfiKeyFIFO.\r
466 //\r
467 UnicodeToEfiKey (TerminalDevice);\r
468\r
469 break;\r
470 }\r
471}\r
472\r
473/**\r
474 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event\r
475 Signal the event if there is key available\r
476\r
477 @param Event Indicates the event that invoke this function.\r
478 @param Context Indicates the calling context.\r
479\r
480**/\r
481VOID\r
482EFIAPI\r
483TerminalConInWaitForKey (\r
484 IN EFI_EVENT Event,\r
485 IN VOID *Context\r
486 )\r
487{\r
488 //\r
489 // Someone is waiting on the keystroke event, if there's\r
490 // a key pending, signal the event\r
491 //\r
492 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) {\r
493\r
494 gBS->SignalEvent (Event);\r
495 }\r
496}\r
497\r
498/**\r
499 Timer handler to poll the key from serial.\r
500\r
501 @param Event Indicates the event that invoke this function.\r
502 @param Context Indicates the calling context.\r
503**/\r
504VOID\r
505EFIAPI\r
506TerminalConInTimerHandler (\r
507 IN EFI_EVENT Event,\r
508 IN VOID *Context\r
509 )\r
510{\r
511 EFI_STATUS Status;\r
512 TERMINAL_DEV *TerminalDevice;\r
59d88f42 513 UINT32 Control;\r
4bc6ad39
RN
514 UINT8 Input;\r
515 EFI_SERIAL_IO_MODE *Mode;\r
516 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
517 UINTN SerialInTimeOut;\r
518\r
519 TerminalDevice = (TERMINAL_DEV *) Context;\r
520\r
521 SerialIo = TerminalDevice->SerialIo;\r
522 if (SerialIo == NULL) {\r
523 return ;\r
524 }\r
525 //\r
526 // if current timeout value for serial device is not identical with\r
527 // the value saved in TERMINAL_DEV structure, then recalculate the\r
528 // timeout value again and set serial attribute according to this value.\r
529 //\r
530 Mode = SerialIo->Mode;\r
531 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {\r
532\r
533 SerialInTimeOut = 0;\r
534 if (Mode->BaudRate != 0) {\r
535 //\r
536 // According to BAUD rate to calculate the timeout value.\r
537 //\r
538 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
539 }\r
540\r
541 Status = SerialIo->SetAttributes (\r
542 SerialIo,\r
543 Mode->BaudRate,\r
544 Mode->ReceiveFifoDepth,\r
545 (UINT32) SerialInTimeOut,\r
546 (EFI_PARITY_TYPE) (Mode->Parity),\r
547 (UINT8) Mode->DataBits,\r
548 (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
549 );\r
550\r
551 if (EFI_ERROR (Status)) {\r
552 TerminalDevice->SerialInTimeOut = 0;\r
553 } else {\r
554 TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
555 }\r
556 }\r
4bc6ad39 557 //\r
59d88f42 558 // Check whether serial buffer is empty.\r
4bc6ad39 559 //\r
59d88f42 560 Status = SerialIo->GetControl (SerialIo, &Control);\r
4bc6ad39 561\r
59d88f42
RN
562 if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0) {\r
563 //\r
564 // Fetch all the keys in the serial buffer,\r
565 // and insert the byte stream into RawFIFO.\r
566 //\r
567 while (!IsRawFiFoFull (TerminalDevice)) {\r
568\r
569 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);\r
570\r
571 if (EFI_ERROR (Status)) {\r
572 if (Status == EFI_DEVICE_ERROR) {\r
573 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
574 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
575 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),\r
576 TerminalDevice->DevicePath\r
577 );\r
578 }\r
579 break;\r
4bc6ad39 580 }\r
4bc6ad39 581\r
59d88f42
RN
582 RawFiFoInsertOneKey (TerminalDevice, Input);\r
583 }\r
4bc6ad39
RN
584 }\r
585\r
586 //\r
587 // Translate all the raw data in RawFIFO into EFI Key,\r
588 // according to different terminal type supported.\r
589 //\r
590 TranslateRawDataToEfiKey (TerminalDevice);\r
591}\r
592\r
593/**\r
594 Get one key out of serial buffer.\r
595\r
596 @param SerialIo Serial I/O protocol attached to the serial device.\r
597 @param Output The fetched key.\r
598\r
599 @retval EFI_NOT_READY If serial buffer is empty.\r
600 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.\r
601 @retval EFI_SUCCESS If reading serial buffer successfully, put\r
602 the fetched key to the parameter output.\r
603\r
604**/\r
605EFI_STATUS\r
606GetOneKeyFromSerial (\r
607 EFI_SERIAL_IO_PROTOCOL *SerialIo,\r
608 UINT8 *Output\r
609 )\r
610{\r
611 EFI_STATUS Status;\r
612 UINTN Size;\r
613\r
614 Size = 1;\r
615 *Output = 0;\r
616\r
617 //\r
618 // Read one key from serial I/O device.\r
619 //\r
620 Status = SerialIo->Read (SerialIo, &Size, Output);\r
621\r
622 if (EFI_ERROR (Status)) {\r
623\r
624 if (Status == EFI_TIMEOUT) {\r
625 return EFI_NOT_READY;\r
626 }\r
627\r
628 return EFI_DEVICE_ERROR;\r
629\r
630 }\r
631\r
632 if (*Output == 0) {\r
633 return EFI_NOT_READY;\r
634 }\r
635\r
636 return EFI_SUCCESS;\r
637}\r
638\r
639/**\r
640 Insert one byte raw data into the Raw Data FIFO.\r
641\r
642 @param TerminalDevice Terminal driver private structure.\r
643 @param Input The key will be input.\r
644\r
645 @retval TRUE If insert successfully.\r
646 @retval FLASE If Raw Data buffer is full before key insertion,\r
647 and the key is lost.\r
648\r
649**/\r
650BOOLEAN\r
651RawFiFoInsertOneKey (\r
652 TERMINAL_DEV *TerminalDevice,\r
653 UINT8 Input\r
654 )\r
655{\r
656 UINT8 Tail;\r
657\r
658 Tail = TerminalDevice->RawFiFo->Tail;\r
659\r
660 if (IsRawFiFoFull (TerminalDevice)) {\r
661 //\r
662 // Raw FIFO is full\r
663 //\r
664 return FALSE;\r
665 }\r
666\r
667 TerminalDevice->RawFiFo->Data[Tail] = Input;\r
668\r
669 TerminalDevice->RawFiFo->Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
670\r
671 return TRUE;\r
672}\r
673\r
674/**\r
675 Remove one pre-fetched key out of the Raw Data FIFO.\r
676\r
677 @param TerminalDevice Terminal driver private structure.\r
678 @param Output The key will be removed.\r
679\r
680 @retval TRUE If insert successfully.\r
681 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.\r
682\r
683**/\r
684BOOLEAN\r
685RawFiFoRemoveOneKey (\r
686 TERMINAL_DEV *TerminalDevice,\r
687 UINT8 *Output\r
688 )\r
689{\r
690 UINT8 Head;\r
691\r
692 Head = TerminalDevice->RawFiFo->Head;\r
693\r
694 if (IsRawFiFoEmpty (TerminalDevice)) {\r
695 //\r
696 // FIFO is empty\r
697 //\r
698 *Output = 0;\r
699 return FALSE;\r
700 }\r
701\r
702 *Output = TerminalDevice->RawFiFo->Data[Head];\r
703\r
704 TerminalDevice->RawFiFo->Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
705\r
706 return TRUE;\r
707}\r
708\r
709/**\r
710 Clarify whether Raw Data FIFO buffer is empty.\r
711\r
712 @param TerminalDevice Terminal driver private structure\r
713\r
714 @retval TRUE If Raw Data FIFO buffer is empty.\r
715 @retval FLASE If Raw Data FIFO buffer is not empty.\r
716\r
717**/\r
718BOOLEAN\r
719IsRawFiFoEmpty (\r
720 TERMINAL_DEV *TerminalDevice\r
721 )\r
722{\r
723 if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {\r
724 return TRUE;\r
725 } else {\r
726 return FALSE;\r
727 }\r
728}\r
729\r
730/**\r
731 Clarify whether Raw Data FIFO buffer is full.\r
732\r
733 @param TerminalDevice Terminal driver private structure\r
734\r
735 @retval TRUE If Raw Data FIFO buffer is full.\r
736 @retval FLASE If Raw Data FIFO buffer is not full.\r
737\r
738**/\r
739BOOLEAN\r
740IsRawFiFoFull (\r
741 TERMINAL_DEV *TerminalDevice\r
742 )\r
743{\r
744 UINT8 Tail;\r
745 UINT8 Head;\r
746\r
747 Tail = TerminalDevice->RawFiFo->Tail;\r
748 Head = TerminalDevice->RawFiFo->Head;\r
749\r
750 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {\r
751\r
752 return TRUE;\r
753 }\r
754\r
755 return FALSE;\r
756}\r
757\r
758/**\r
759 Insert one pre-fetched key into the FIFO buffer.\r
760\r
761 @param TerminalDevice Terminal driver private structure.\r
762 @param Key The key will be input.\r
763\r
764 @retval TRUE If insert successfully.\r
765 @retval FLASE If FIFO buffer is full before key insertion,\r
766 and the key is lost.\r
767\r
768**/\r
769BOOLEAN\r
770EfiKeyFiFoInsertOneKey (\r
771 TERMINAL_DEV *TerminalDevice,\r
772 EFI_INPUT_KEY *Key\r
773 )\r
774{\r
775 UINT8 Tail;\r
776 LIST_ENTRY *Link;\r
777 LIST_ENTRY *NotifyList;\r
778 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
779 EFI_KEY_DATA KeyData;\r
780\r
781 Tail = TerminalDevice->EfiKeyFiFo->Tail;\r
782\r
783 CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));\r
784 KeyData.KeyState.KeyShiftState = 0;\r
785 KeyData.KeyState.KeyToggleState = 0;\r
786\r
787 //\r
788 // Invoke notification functions if exist\r
789 //\r
790 NotifyList = &TerminalDevice->NotifyList;\r
791 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
792 CurrentNotify = CR (\r
793 Link,\r
794 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
795 NotifyEntry,\r
796 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
797 );\r
798 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
799 CurrentNotify->KeyNotificationFn (&KeyData);\r
800 }\r
801 }\r
802 if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
803 //\r
804 // Efi Key FIFO is full\r
805 //\r
806 return FALSE;\r
807 }\r
808\r
809 CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));\r
810\r
811 TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
812\r
813 return TRUE;\r
814}\r
815\r
816/**\r
817 Remove one pre-fetched key out of the FIFO buffer.\r
818\r
819 @param TerminalDevice Terminal driver private structure.\r
820 @param Output The key will be removed.\r
821\r
822 @retval TRUE If insert successfully.\r
823 @retval FLASE If FIFO buffer is empty before remove operation.\r
824\r
825**/\r
826BOOLEAN\r
827EfiKeyFiFoRemoveOneKey (\r
828 TERMINAL_DEV *TerminalDevice,\r
829 EFI_INPUT_KEY *Output\r
830 )\r
831{\r
832 UINT8 Head;\r
833\r
834 Head = TerminalDevice->EfiKeyFiFo->Head;\r
835 ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
836\r
837 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
838 //\r
839 // FIFO is empty\r
840 //\r
841 Output->ScanCode = SCAN_NULL;\r
842 Output->UnicodeChar = 0;\r
843 return FALSE;\r
844 }\r
845\r
846 *Output = TerminalDevice->EfiKeyFiFo->Data[Head];\r
847\r
848 TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
849\r
850 return TRUE;\r
851}\r
852\r
853/**\r
854 Clarify whether FIFO buffer is empty.\r
855\r
856 @param TerminalDevice Terminal driver private structure\r
857\r
858 @retval TRUE If FIFO buffer is empty.\r
859 @retval FLASE If FIFO buffer is not empty.\r
860\r
861**/\r
862BOOLEAN\r
863IsEfiKeyFiFoEmpty (\r
864 TERMINAL_DEV *TerminalDevice\r
865 )\r
866{\r
867 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {\r
868 return TRUE;\r
869 } else {\r
870 return FALSE;\r
871 }\r
872}\r
873\r
874/**\r
875 Clarify whether FIFO buffer is full.\r
876\r
877 @param TerminalDevice Terminal driver private structure\r
878\r
879 @retval TRUE If FIFO buffer is full.\r
880 @retval FLASE If FIFO buffer is not full.\r
881\r
882**/\r
883BOOLEAN\r
884IsEfiKeyFiFoFull (\r
885 TERMINAL_DEV *TerminalDevice\r
886 )\r
887{\r
888 UINT8 Tail;\r
889 UINT8 Head;\r
890\r
891 Tail = TerminalDevice->EfiKeyFiFo->Tail;\r
892 Head = TerminalDevice->EfiKeyFiFo->Head;\r
893\r
894 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
895\r
896 return TRUE;\r
897 }\r
898\r
899 return FALSE;\r
900}\r
901\r
902/**\r
903 Insert one pre-fetched key into the Unicode FIFO buffer.\r
904\r
905 @param TerminalDevice Terminal driver private structure.\r
906 @param Input The key will be input.\r
907\r
908 @retval TRUE If insert successfully.\r
909 @retval FLASE If Unicode FIFO buffer is full before key insertion,\r
910 and the key is lost.\r
911\r
912**/\r
913BOOLEAN\r
914UnicodeFiFoInsertOneKey (\r
915 TERMINAL_DEV *TerminalDevice,\r
916 UINT16 Input\r
917 )\r
918{\r
919 UINT8 Tail;\r
920\r
921 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
922 ASSERT (Tail < FIFO_MAX_NUMBER + 1);\r
923\r
924\r
925 if (IsUnicodeFiFoFull (TerminalDevice)) {\r
926 //\r
927 // Unicode FIFO is full\r
928 //\r
929 return FALSE;\r
930 }\r
931\r
932 TerminalDevice->UnicodeFiFo->Data[Tail] = Input;\r
933\r
934 TerminalDevice->UnicodeFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
935\r
936 return TRUE;\r
937}\r
938\r
939/**\r
940 Remove one pre-fetched key out of the Unicode FIFO buffer.\r
941\r
942 @param TerminalDevice Terminal driver private structure.\r
943 @param Output The key will be removed.\r
944\r
945 @retval TRUE If insert successfully.\r
946 @retval FLASE If Unicode FIFO buffer is empty before remove operation.\r
947\r
948**/\r
949BOOLEAN\r
950UnicodeFiFoRemoveOneKey (\r
951 TERMINAL_DEV *TerminalDevice,\r
952 UINT16 *Output\r
953 )\r
954{\r
955 UINT8 Head;\r
956\r
957 Head = TerminalDevice->UnicodeFiFo->Head;\r
958 ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
959\r
960 if (IsUnicodeFiFoEmpty (TerminalDevice)) {\r
961 //\r
962 // FIFO is empty\r
963 //\r
964 Output = NULL;\r
965 return FALSE;\r
966 }\r
967\r
968 *Output = TerminalDevice->UnicodeFiFo->Data[Head];\r
969\r
970 TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
971\r
972 return TRUE;\r
973}\r
974\r
975/**\r
976 Clarify whether Unicode FIFO buffer is empty.\r
977\r
978 @param TerminalDevice Terminal driver private structure\r
979\r
980 @retval TRUE If Unicode FIFO buffer is empty.\r
981 @retval FLASE If Unicode FIFO buffer is not empty.\r
982\r
983**/\r
984BOOLEAN\r
985IsUnicodeFiFoEmpty (\r
986 TERMINAL_DEV *TerminalDevice\r
987 )\r
988{\r
989 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {\r
990 return TRUE;\r
991 } else {\r
992 return FALSE;\r
993 }\r
994}\r
995\r
996/**\r
997 Clarify whether Unicode FIFO buffer is full.\r
998\r
999 @param TerminalDevice Terminal driver private structure\r
1000\r
1001 @retval TRUE If Unicode FIFO buffer is full.\r
1002 @retval FLASE If Unicode FIFO buffer is not full.\r
1003\r
1004**/\r
1005BOOLEAN\r
1006IsUnicodeFiFoFull (\r
1007 TERMINAL_DEV *TerminalDevice\r
1008 )\r
1009{\r
1010 UINT8 Tail;\r
1011 UINT8 Head;\r
1012\r
1013 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
1014 Head = TerminalDevice->UnicodeFiFo->Head;\r
1015\r
1016 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
1017\r
1018 return TRUE;\r
1019 }\r
1020\r
1021 return FALSE;\r
1022}\r
1023\r
1024/**\r
1025 Count Unicode FIFO buffer.\r
1026\r
1027 @param TerminalDevice Terminal driver private structure\r
1028\r
1029 @return The count in bytes of Unicode FIFO.\r
1030\r
1031**/\r
1032UINT8\r
1033UnicodeFiFoGetKeyCount (\r
1034 TERMINAL_DEV *TerminalDevice\r
1035 )\r
1036{\r
1037 UINT8 Tail;\r
1038 UINT8 Head;\r
1039\r
1040 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
1041 Head = TerminalDevice->UnicodeFiFo->Head;\r
1042\r
1043 if (Tail >= Head) {\r
1044 return (UINT8) (Tail - Head);\r
1045 } else {\r
1046 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);\r
1047 }\r
1048}\r
1049\r
1050/**\r
1051 Update the Unicode characters from a terminal input device into EFI Keys FIFO.\r
1052\r
1053 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys\r
1054\r
1055**/\r
1056VOID\r
1057UnicodeToEfiKeyFlushState (\r
1058 IN TERMINAL_DEV *TerminalDevice\r
1059 )\r
1060{\r
1061 EFI_INPUT_KEY Key;\r
1062 UINT32 InputState;\r
1063\r
1064 InputState = TerminalDevice->InputState;\r
1065\r
1066 if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
1067 return;\r
1068 }\r
1069\r
1070 if ((InputState & INPUT_STATE_ESC) != 0) {\r
1071 Key.ScanCode = SCAN_ESC;\r
1072 Key.UnicodeChar = 0;\r
1073 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1074 }\r
1075\r
1076 if ((InputState & INPUT_STATE_CSI) != 0) {\r
1077 Key.ScanCode = SCAN_NULL;\r
1078 Key.UnicodeChar = CSI;\r
1079 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1080 }\r
1081\r
1082 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {\r
1083 Key.ScanCode = SCAN_NULL;\r
1084 Key.UnicodeChar = LEFTOPENBRACKET;\r
1085 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1086 }\r
1087\r
1088 if ((InputState & INPUT_STATE_O) != 0) {\r
1089 Key.ScanCode = SCAN_NULL;\r
1090 Key.UnicodeChar = 'O';\r
1091 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1092 }\r
1093\r
1094 if ((InputState & INPUT_STATE_2) != 0) {\r
1095 Key.ScanCode = SCAN_NULL;\r
1096 Key.UnicodeChar = '2';\r
1097 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1098 }\r
1099\r
1100 //\r
1101 // Cancel the timer.\r
1102 //\r
1103 gBS->SetTimer (\r
1104 TerminalDevice->TwoSecondTimeOut,\r
1105 TimerCancel,\r
1106 0\r
1107 );\r
1108\r
1109 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1110}\r
1111\r
1112\r
1113/**\r
1114 Converts a stream of Unicode characters from a terminal input device into EFI Keys that\r
1115 can be read through the Simple Input Protocol.\r
1116\r
1117 The table below shows the keyboard input mappings that this function supports.\r
1118 If the ESC sequence listed in one of the columns is presented, then it is translated\r
1119 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw\r
1120 key strokes are converted into EFI Keys.\r
1121\r
1122 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not\r
1123 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are\r
1124 converted into EFI Keys.\r
1125 There is one special input sequence that will force the system to reset.\r
1126 This is ESC R ESC r ESC R.\r
1127\r
1128 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100. \r
1129 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /\r
1130 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.\r
1131 \r
1132 Symbols used in table below\r
1133 ===========================\r
1134 ESC = 0x1B\r
1135 CSI = 0x9B\r
1136 DEL = 0x7f\r
1137 ^ = CTRL\r
1138\r
1139 +=========+======+===========+==========+==========+\r
1140 | | EFI | UEFI 2.0 | | |\r
1141 | | Scan | | VT100+ | |\r
1142 | KEY | Code | PC ANSI | VTUTF8 | VT100 |\r
1143 +=========+======+===========+==========+==========+\r
1144 | NULL | 0x00 | | | |\r
1145 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |\r
1146 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |\r
1147 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |\r
1148 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |\r
1149 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |\r
1150 | END | 0x06 | ESC [ F | ESC k | ESC [ K |\r
1151 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |\r
1152 | | | ESC [ L | | ESC [ L |\r
1153 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |\r
1154 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |\r
1155 | | | | | ESC [ ? |\r
1156 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |\r
1157 | | | | | ESC [ / |\r
1158 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |\r
1159 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |\r
1160 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |\r
1161 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |\r
1162 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |\r
1163 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |\r
1164 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |\r
1165 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |\r
1166 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |\r
1167 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |\r
1168 | Escape | 0x17 | ESC | ESC | ESC |\r
1169 | F11 | 0x15 | | ESC ! | |\r
1170 | F12 | 0x16 | | ESC @ | |\r
1171 +=========+======+===========+==========+==========+\r
1172\r
1173 Special Mappings\r
1174 ================\r
1175 ESC R ESC r ESC R = Reset System\r
1176\r
1177 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys\r
1178\r
1179**/\r
1180VOID\r
1181UnicodeToEfiKey (\r
1182 IN TERMINAL_DEV *TerminalDevice\r
1183 )\r
1184{\r
1185 EFI_STATUS Status;\r
1186 EFI_STATUS TimerStatus;\r
1187 UINT16 UnicodeChar;\r
1188 EFI_INPUT_KEY Key;\r
1189 BOOLEAN SetDefaultResetState;\r
1190\r
1191 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
1192\r
1193 if (!EFI_ERROR (TimerStatus)) {\r
1194 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1195 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1196 }\r
1197\r
1198 while (!IsUnicodeFiFoEmpty (TerminalDevice) && !IsEfiKeyFiFoFull (TerminalDevice)) {\r
1199\r
1200 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
1201 //\r
1202 // Check to see if the 2 seconds timer has expired\r
1203 //\r
1204 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
1205 if (!EFI_ERROR (TimerStatus)) {\r
1206 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1207 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1208 }\r
1209 }\r
1210\r
1211 //\r
1212 // Fetch one Unicode character from the Unicode FIFO\r
1213 //\r
1214 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);\r
1215\r
1216 SetDefaultResetState = TRUE;\r
1217\r
1218 switch (TerminalDevice->InputState) {\r
1219 case INPUT_STATE_DEFAULT:\r
1220\r
1221 break;\r
1222\r
1223 case INPUT_STATE_ESC:\r
1224\r
1225 if (UnicodeChar == LEFTOPENBRACKET) {\r
1226 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;\r
1227 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1228 continue;\r
1229 }\r
1230\r
1231 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {\r
1232 TerminalDevice->InputState |= INPUT_STATE_O;\r
1233 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1234 continue;\r
1235 }\r
1236\r
1237 Key.ScanCode = SCAN_NULL;\r
1238\r
1239 if (TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
1240 TerminalDevice->TerminalType == VTUTF8TYPE) {\r
1241 switch (UnicodeChar) {\r
1242 case '1':\r
1243 Key.ScanCode = SCAN_F1;\r
1244 break;\r
1245 case '2':\r
1246 Key.ScanCode = SCAN_F2;\r
1247 break;\r
1248 case '3':\r
1249 Key.ScanCode = SCAN_F3;\r
1250 break;\r
1251 case '4':\r
1252 Key.ScanCode = SCAN_F4;\r
1253 break;\r
1254 case '5':\r
1255 Key.ScanCode = SCAN_F5;\r
1256 break;\r
1257 case '6':\r
1258 Key.ScanCode = SCAN_F6;\r
1259 break;\r
1260 case '7':\r
1261 Key.ScanCode = SCAN_F7;\r
1262 break;\r
1263 case '8':\r
1264 Key.ScanCode = SCAN_F8;\r
1265 break;\r
1266 case '9':\r
1267 Key.ScanCode = SCAN_F9;\r
1268 break;\r
1269 case '0':\r
1270 Key.ScanCode = SCAN_F10;\r
1271 break;\r
1272 case '!':\r
1273 Key.ScanCode = SCAN_F11;\r
1274 break;\r
1275 case '@':\r
1276 Key.ScanCode = SCAN_F12;\r
1277 break;\r
1278 case 'h':\r
1279 Key.ScanCode = SCAN_HOME;\r
1280 break;\r
1281 case 'k':\r
1282 Key.ScanCode = SCAN_END;\r
1283 break;\r
1284 case '+':\r
1285 Key.ScanCode = SCAN_INSERT;\r
1286 break;\r
1287 case '-':\r
1288 Key.ScanCode = SCAN_DELETE;\r
1289 break;\r
1290 case '/':\r
1291 Key.ScanCode = SCAN_PAGE_DOWN;\r
1292 break;\r
1293 case '?':\r
1294 Key.ScanCode = SCAN_PAGE_UP;\r
1295 break;\r
1296 default :\r
1297 break;\r
1298 }\r
1299 }\r
1300\r
1301 switch (UnicodeChar) {\r
1302 case 'R':\r
1303 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {\r
1304 TerminalDevice->ResetState = RESET_STATE_ESC_R;\r
1305 SetDefaultResetState = FALSE;\r
1306 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) {\r
1307 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1308 }\r
1309 Key.ScanCode = SCAN_NULL;\r
1310 break;\r
1311 case 'r':\r
1312 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {\r
1313 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R;\r
1314 SetDefaultResetState = FALSE;\r
1315 }\r
1316 Key.ScanCode = SCAN_NULL;\r
1317 break;\r
1318 default :\r
1319 break;\r
1320 }\r
1321\r
1322 if (SetDefaultResetState) {\r
1323 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1324 }\r
1325\r
1326 if (Key.ScanCode != SCAN_NULL) {\r
1327 Key.UnicodeChar = 0;\r
1328 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1329 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1330 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1331 continue;\r
1332 }\r
1333\r
1334 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1335\r
1336 break;\r
1337\r
1338 case INPUT_STATE_ESC | INPUT_STATE_O:\r
1339\r
1340 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1341\r
1342 Key.ScanCode = SCAN_NULL;\r
1343\r
1344 if (TerminalDevice->TerminalType == VT100TYPE) {\r
1345 switch (UnicodeChar) {\r
1346 case 'P':\r
1347 Key.ScanCode = SCAN_F1;\r
1348 break;\r
1349 case 'Q':\r
1350 Key.ScanCode = SCAN_F2;\r
1351 break;\r
1352 case 'w':\r
1353 Key.ScanCode = SCAN_F3;\r
1354 break;\r
1355 case 'x':\r
1356 Key.ScanCode = SCAN_F4;\r
1357 break;\r
1358 case 't':\r
1359 Key.ScanCode = SCAN_F5;\r
1360 break;\r
1361 case 'u':\r
1362 Key.ScanCode = SCAN_F6;\r
1363 break;\r
1364 case 'q':\r
1365 Key.ScanCode = SCAN_F7;\r
1366 break;\r
1367 case 'r':\r
1368 Key.ScanCode = SCAN_F8;\r
1369 break;\r
1370 case 'p':\r
1371 Key.ScanCode = SCAN_F9;\r
1372 break;\r
1373 case 'M':\r
1374 Key.ScanCode = SCAN_F10;\r
1375 break;\r
1376 default :\r
1377 break;\r
1378 }\r
1379 }\r
1380\r
1381 if (Key.ScanCode != SCAN_NULL) {\r
1382 Key.UnicodeChar = 0;\r
1383 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1384 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1385 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1386 continue;\r
1387 }\r
1388\r
1389 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1390\r
1391 break;\r
1392\r
1393 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:\r
1394\r
1395 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1396\r
1397 Key.ScanCode = SCAN_NULL;\r
1398\r
1399 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1400 TerminalDevice->TerminalType == VT100TYPE ||\r
1401 TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
1402 TerminalDevice->TerminalType == VTUTF8TYPE) {\r
1403 switch (UnicodeChar) {\r
1404 case 'A':\r
1405 Key.ScanCode = SCAN_UP;\r
1406 break;\r
1407 case 'B':\r
1408 Key.ScanCode = SCAN_DOWN;\r
1409 break;\r
1410 case 'C':\r
1411 Key.ScanCode = SCAN_RIGHT;\r
1412 break;\r
1413 case 'D':\r
1414 Key.ScanCode = SCAN_LEFT;\r
1415 break;\r
1416 case 'H':\r
1417 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1418 TerminalDevice->TerminalType == VT100TYPE) {\r
1419 Key.ScanCode = SCAN_HOME;\r
1420 }\r
1421 break;\r
1422 case 'F':\r
1423 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1424 Key.ScanCode = SCAN_END;\r
1425 }\r
1426 break;\r
1427 case 'K':\r
1428 if (TerminalDevice->TerminalType == VT100TYPE) {\r
1429 Key.ScanCode = SCAN_END;\r
1430 }\r
1431 break;\r
1432 case 'L':\r
1433 case '@':\r
1434 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1435 TerminalDevice->TerminalType == VT100TYPE) {\r
1436 Key.ScanCode = SCAN_INSERT;\r
1437 }\r
1438 break;\r
1439 case 'X':\r
1440 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1441 Key.ScanCode = SCAN_DELETE;\r
1442 }\r
1443 break;\r
1444 case 'P':\r
1445 if (TerminalDevice->TerminalType == VT100TYPE) {\r
1446 Key.ScanCode = SCAN_DELETE;\r
1447 } else if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1448 Key.ScanCode = SCAN_F4;\r
1449 }\r
1450 break;\r
1451 case 'I':\r
1452 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1453 Key.ScanCode = SCAN_PAGE_UP;\r
1454 }\r
1455 break;\r
1456 case 'V':\r
1457 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1458 Key.ScanCode = SCAN_F10;\r
1459 }\r
bd07919c 1460 break;\r
4bc6ad39
RN
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
bd07919c 1475 break;\r
4bc6ad39
RN
1476 case '/':\r
1477 if (TerminalDevice->TerminalType == VT100TYPE) {\r
1478 Key.ScanCode = SCAN_PAGE_DOWN;\r
1479 }\r
1480 break;\r
1481 case 'M':\r
1482 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1483 Key.ScanCode = SCAN_F1;\r
1484 }\r
1485 break;\r
1486 case 'N':\r
1487 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1488 Key.ScanCode = SCAN_F2;\r
1489 }\r
1490 break;\r
1491 case 'O':\r
1492 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1493 Key.ScanCode = SCAN_F3;\r
1494 }\r
1495 break;\r
1496 case 'Q':\r
1497 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1498 Key.ScanCode = SCAN_F5;\r
1499 }\r
1500 break;\r
1501 case 'R':\r
1502 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1503 Key.ScanCode = SCAN_F6;\r
1504 }\r
1505 break;\r
1506 case 'S':\r
1507 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1508 Key.ScanCode = SCAN_F7;\r
1509 }\r
1510 break;\r
1511 case 'T':\r
1512 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
1513 Key.ScanCode = SCAN_F8;\r
1514 }\r
1515 break;\r
1516 default :\r
1517 break;\r
1518 }\r
1519 }\r
1520\r
1521 if (Key.ScanCode != SCAN_NULL) {\r
1522 Key.UnicodeChar = 0;\r
1523 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1524 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1525 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1526 continue;\r
1527 }\r
1528\r
1529 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1530\r
1531 break;\r
1532\r
1533\r
1534 default:\r
1535 //\r
1536 // Invalid state. This should never happen.\r
1537 //\r
1538 ASSERT (FALSE);\r
1539\r
1540 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1541\r
1542 break;\r
1543 }\r
1544\r
1545 if (UnicodeChar == ESC) {\r
1546 TerminalDevice->InputState = INPUT_STATE_ESC;\r
1547 }\r
1548\r
1549 if (UnicodeChar == CSI) {\r
1550 TerminalDevice->InputState = INPUT_STATE_CSI;\r
1551 }\r
1552\r
1553 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
1554 Status = gBS->SetTimer(\r
1555 TerminalDevice->TwoSecondTimeOut,\r
1556 TimerRelative,\r
1557 (UINT64)20000000\r
1558 );\r
1559 ASSERT_EFI_ERROR (Status);\r
1560 continue;\r
1561 }\r
1562\r
1563 if (SetDefaultResetState) {\r
1564 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1565 }\r
1566\r
1567 if (UnicodeChar == DEL) {\r
1568 Key.ScanCode = SCAN_DELETE;\r
1569 Key.UnicodeChar = 0;\r
1570 } else {\r
1571 Key.ScanCode = SCAN_NULL;\r
1572 Key.UnicodeChar = UnicodeChar;\r
1573 }\r
1574\r
1575 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);\r
1576 }\r
1577}\r