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