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