TerminalConIn.c revision 4bc6ad3935d7b57e5eacda5e6e70b32d786d43dd
1/** @file 2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol. 3 4Copyright (c) 2006 - 2011, 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 return EFI_SUCCESS; 299} 300 301 302/** 303 Register a notification function for a particular keystroke for the input device. 304 305 @param This Protocol instance pointer. 306 @param KeyData A pointer to a buffer that is filled in with the 307 keystroke information data for the key that was 308 pressed. 309 @param KeyNotificationFunction Points to the function to be called when the key 310 sequence is typed specified by KeyData. 311 @param NotifyHandle Points to the unique handle assigned to the 312 registered notification. 313 314 @retval EFI_SUCCESS The notification function was registered 315 successfully. 316 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data 317 structures. 318 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL. 319 320**/ 321EFI_STATUS 322EFIAPI 323TerminalConInRegisterKeyNotify ( 324 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 325 IN EFI_KEY_DATA *KeyData, 326 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, 327 OUT EFI_HANDLE *NotifyHandle 328 ) 329{ 330 TERMINAL_DEV *TerminalDevice; 331 TERMINAL_CONSOLE_IN_EX_NOTIFY *NewNotify; 332 LIST_ENTRY *Link; 333 LIST_ENTRY *NotifyList; 334 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify; 335 336 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) { 337 return EFI_INVALID_PARAMETER; 338 } 339 340 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This); 341 342 // 343 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. 344 // 345 NotifyList = &TerminalDevice->NotifyList; 346 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) { 347 CurrentNotify = CR ( 348 Link, 349 TERMINAL_CONSOLE_IN_EX_NOTIFY, 350 NotifyEntry, 351 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE 352 ); 353 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { 354 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { 355 *NotifyHandle = CurrentNotify->NotifyHandle; 356 return EFI_SUCCESS; 357 } 358 } 359 } 360 361 // 362 // Allocate resource to save the notification function 363 // 364 NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY)); 365 if (NewNotify == NULL) { 366 return EFI_OUT_OF_RESOURCES; 367 } 368 369 NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE; 370 NewNotify->KeyNotificationFn = KeyNotificationFunction; 371 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify; 372 CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData)); 373 InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry); 374 375 *NotifyHandle = NewNotify->NotifyHandle; 376 377 return EFI_SUCCESS; 378} 379 380 381/** 382 Remove a registered notification function from a particular keystroke. 383 384 @param This Protocol instance pointer. 385 @param NotificationHandle The handle of the notification function being 386 unregistered. 387 388 @retval EFI_SUCCESS The notification function was unregistered 389 successfully. 390 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid. 391 392**/ 393EFI_STATUS 394EFIAPI 395TerminalConInUnregisterKeyNotify ( 396 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 397 IN EFI_HANDLE NotificationHandle 398 ) 399{ 400 TERMINAL_DEV *TerminalDevice; 401 LIST_ENTRY *Link; 402 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify; 403 LIST_ENTRY *NotifyList; 404 405 if (NotificationHandle == NULL) { 406 return EFI_INVALID_PARAMETER; 407 } 408 409 if (((TERMINAL_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE) { 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->NotifyHandle == 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 AnsiRawDataToUnicode (TerminalDevice); 458 UnicodeToEfiKey (TerminalDevice); 459 break; 460 461 case VTUTF8TYPE: 462 // 463 // Process all the raw data in the RawFIFO, 464 // put the processed key into UnicodeFIFO. 465 // 466 VTUTF8RawDataToUnicode (TerminalDevice); 467 468 // 469 // Translate all the Unicode data in the UnicodeFIFO to Efi key, 470 // then put into EfiKeyFIFO. 471 // 472 UnicodeToEfiKey (TerminalDevice); 473 474 break; 475 } 476} 477 478/** 479 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event 480 Signal the event if there is key available 481 482 @param Event Indicates the event that invoke this function. 483 @param Context Indicates the calling context. 484 485**/ 486VOID 487EFIAPI 488TerminalConInWaitForKey ( 489 IN EFI_EVENT Event, 490 IN VOID *Context 491 ) 492{ 493 // 494 // Someone is waiting on the keystroke event, if there's 495 // a key pending, signal the event 496 // 497 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) { 498 499 gBS->SignalEvent (Event); 500 } 501} 502 503/** 504 Timer handler to poll the key from serial. 505 506 @param Event Indicates the event that invoke this function. 507 @param Context Indicates the calling context. 508**/ 509VOID 510EFIAPI 511TerminalConInTimerHandler ( 512 IN EFI_EVENT Event, 513 IN VOID *Context 514 ) 515{ 516 EFI_STATUS Status; 517 TERMINAL_DEV *TerminalDevice; 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 // 563 // Fetch all the keys in the serial buffer, 564 // and insert the byte stream into RawFIFO. 565 // 566 while (!IsRawFiFoFull (TerminalDevice)) { 567 568 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input); 569 570 if (EFI_ERROR (Status)) { 571 if (Status == EFI_DEVICE_ERROR) { 572 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 573 EFI_ERROR_CODE | EFI_ERROR_MINOR, 574 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR), 575 TerminalDevice->DevicePath 576 ); 577 } 578 break; 579 } 580 581 RawFiFoInsertOneKey (TerminalDevice, Input); 582 } 583 584 // 585 // Translate all the raw data in RawFIFO into EFI Key, 586 // according to different terminal type supported. 587 // 588 TranslateRawDataToEfiKey (TerminalDevice); 589} 590 591/** 592 Get one key out of serial buffer. 593 594 @param SerialIo Serial I/O protocol attached to the serial device. 595 @param Output The fetched key. 596 597 @retval EFI_NOT_READY If serial buffer is empty. 598 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error. 599 @retval EFI_SUCCESS If reading serial buffer successfully, put 600 the fetched key to the parameter output. 601 602**/ 603EFI_STATUS 604GetOneKeyFromSerial ( 605 EFI_SERIAL_IO_PROTOCOL *SerialIo, 606 UINT8 *Output 607 ) 608{ 609 EFI_STATUS Status; 610 UINTN Size; 611 612 Size = 1; 613 *Output = 0; 614 615 // 616 // Read one key from serial I/O device. 617 // 618 Status = SerialIo->Read (SerialIo, &Size, Output); 619 620 if (EFI_ERROR (Status)) { 621 622 if (Status == EFI_TIMEOUT) { 623 return EFI_NOT_READY; 624 } 625 626 return EFI_DEVICE_ERROR; 627 628 } 629 630 if (*Output == 0) { 631 return EFI_NOT_READY; 632 } 633 634 return EFI_SUCCESS; 635} 636 637/** 638 Insert one byte raw data into the Raw Data FIFO. 639 640 @param TerminalDevice Terminal driver private structure. 641 @param Input The key will be input. 642 643 @retval TRUE If insert successfully. 644 @retval FLASE If Raw Data buffer is full before key insertion, 645 and the key is lost. 646 647**/ 648BOOLEAN 649RawFiFoInsertOneKey ( 650 TERMINAL_DEV *TerminalDevice, 651 UINT8 Input 652 ) 653{ 654 UINT8 Tail; 655 656 Tail = TerminalDevice->RawFiFo->Tail; 657 658 if (IsRawFiFoFull (TerminalDevice)) { 659 // 660 // Raw FIFO is full 661 // 662 return FALSE; 663 } 664 665 TerminalDevice->RawFiFo->Data[Tail] = Input; 666 667 TerminalDevice->RawFiFo->Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)); 668 669 return TRUE; 670} 671 672/** 673 Remove one pre-fetched key out of the Raw Data FIFO. 674 675 @param TerminalDevice Terminal driver private structure. 676 @param Output The key will be removed. 677 678 @retval TRUE If insert successfully. 679 @retval FLASE If Raw Data FIFO buffer is empty before remove operation. 680 681**/ 682BOOLEAN 683RawFiFoRemoveOneKey ( 684 TERMINAL_DEV *TerminalDevice, 685 UINT8 *Output 686 ) 687{ 688 UINT8 Head; 689 690 Head = TerminalDevice->RawFiFo->Head; 691 692 if (IsRawFiFoEmpty (TerminalDevice)) { 693 // 694 // FIFO is empty 695 // 696 *Output = 0; 697 return FALSE; 698 } 699 700 *Output = TerminalDevice->RawFiFo->Data[Head]; 701 702 TerminalDevice->RawFiFo->Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1)); 703 704 return TRUE; 705} 706 707/** 708 Clarify whether Raw Data FIFO buffer is empty. 709 710 @param TerminalDevice Terminal driver private structure 711 712 @retval TRUE If Raw Data FIFO buffer is empty. 713 @retval FLASE If Raw Data FIFO buffer is not empty. 714 715**/ 716BOOLEAN 717IsRawFiFoEmpty ( 718 TERMINAL_DEV *TerminalDevice 719 ) 720{ 721 if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) { 722 return TRUE; 723 } else { 724 return FALSE; 725 } 726} 727 728/** 729 Clarify whether Raw Data FIFO buffer is full. 730 731 @param TerminalDevice Terminal driver private structure 732 733 @retval TRUE If Raw Data FIFO buffer is full. 734 @retval FLASE If Raw Data FIFO buffer is not full. 735 736**/ 737BOOLEAN 738IsRawFiFoFull ( 739 TERMINAL_DEV *TerminalDevice 740 ) 741{ 742 UINT8 Tail; 743 UINT8 Head; 744 745 Tail = TerminalDevice->RawFiFo->Tail; 746 Head = TerminalDevice->RawFiFo->Head; 747 748 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) { 749 750 return TRUE; 751 } 752 753 return FALSE; 754} 755 756/** 757 Insert one pre-fetched key into the FIFO buffer. 758 759 @param TerminalDevice Terminal driver private structure. 760 @param Key The key will be input. 761 762 @retval TRUE If insert successfully. 763 @retval FLASE If FIFO buffer is full before key insertion, 764 and the key is lost. 765 766**/ 767BOOLEAN 768EfiKeyFiFoInsertOneKey ( 769 TERMINAL_DEV *TerminalDevice, 770 EFI_INPUT_KEY *Key 771 ) 772{ 773 UINT8 Tail; 774 LIST_ENTRY *Link; 775 LIST_ENTRY *NotifyList; 776 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify; 777 EFI_KEY_DATA KeyData; 778 779 Tail = TerminalDevice->EfiKeyFiFo->Tail; 780 781 CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY)); 782 KeyData.KeyState.KeyShiftState = 0; 783 KeyData.KeyState.KeyToggleState = 0; 784 785 // 786 // Invoke notification functions if exist 787 // 788 NotifyList = &TerminalDevice->NotifyList; 789 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) { 790 CurrentNotify = CR ( 791 Link, 792 TERMINAL_CONSOLE_IN_EX_NOTIFY, 793 NotifyEntry, 794 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE 795 ); 796 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { 797 CurrentNotify->KeyNotificationFn (&KeyData); 798 } 799 } 800 if (IsEfiKeyFiFoFull (TerminalDevice)) { 801 // 802 // Efi Key FIFO is full 803 // 804 return FALSE; 805 } 806 807 CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY)); 808 809 TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1)); 810 811 return TRUE; 812} 813 814/** 815 Remove one pre-fetched key out of the FIFO buffer. 816 817 @param TerminalDevice Terminal driver private structure. 818 @param Output The key will be removed. 819 820 @retval TRUE If insert successfully. 821 @retval FLASE If FIFO buffer is empty before remove operation. 822 823**/ 824BOOLEAN 825EfiKeyFiFoRemoveOneKey ( 826 TERMINAL_DEV *TerminalDevice, 827 EFI_INPUT_KEY *Output 828 ) 829{ 830 UINT8 Head; 831 832 Head = TerminalDevice->EfiKeyFiFo->Head; 833 ASSERT (Head < FIFO_MAX_NUMBER + 1); 834 835 if (IsEfiKeyFiFoEmpty (TerminalDevice)) { 836 // 837 // FIFO is empty 838 // 839 Output->ScanCode = SCAN_NULL; 840 Output->UnicodeChar = 0; 841 return FALSE; 842 } 843 844 *Output = TerminalDevice->EfiKeyFiFo->Data[Head]; 845 846 TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); 847 848 return TRUE; 849} 850 851/** 852 Clarify whether FIFO buffer is empty. 853 854 @param TerminalDevice Terminal driver private structure 855 856 @retval TRUE If FIFO buffer is empty. 857 @retval FLASE If FIFO buffer is not empty. 858 859**/ 860BOOLEAN 861IsEfiKeyFiFoEmpty ( 862 TERMINAL_DEV *TerminalDevice 863 ) 864{ 865 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) { 866 return TRUE; 867 } else { 868 return FALSE; 869 } 870} 871 872/** 873 Clarify whether FIFO buffer is full. 874 875 @param TerminalDevice Terminal driver private structure 876 877 @retval TRUE If FIFO buffer is full. 878 @retval FLASE If FIFO buffer is not full. 879 880**/ 881BOOLEAN 882IsEfiKeyFiFoFull ( 883 TERMINAL_DEV *TerminalDevice 884 ) 885{ 886 UINT8 Tail; 887 UINT8 Head; 888 889 Tail = TerminalDevice->EfiKeyFiFo->Tail; 890 Head = TerminalDevice->EfiKeyFiFo->Head; 891 892 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) { 893 894 return TRUE; 895 } 896 897 return FALSE; 898} 899 900/** 901 Insert one pre-fetched key into the Unicode FIFO buffer. 902 903 @param TerminalDevice Terminal driver private structure. 904 @param Input The key will be input. 905 906 @retval TRUE If insert successfully. 907 @retval FLASE If Unicode FIFO buffer is full before key insertion, 908 and the key is lost. 909 910**/ 911BOOLEAN 912UnicodeFiFoInsertOneKey ( 913 TERMINAL_DEV *TerminalDevice, 914 UINT16 Input 915 ) 916{ 917 UINT8 Tail; 918 919 Tail = TerminalDevice->UnicodeFiFo->Tail; 920 ASSERT (Tail < FIFO_MAX_NUMBER + 1); 921 922 923 if (IsUnicodeFiFoFull (TerminalDevice)) { 924 // 925 // Unicode FIFO is full 926 // 927 return FALSE; 928 } 929 930 TerminalDevice->UnicodeFiFo->Data[Tail] = Input; 931 932 TerminalDevice->UnicodeFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1)); 933 934 return TRUE; 935} 936 937/** 938 Remove one pre-fetched key out of the Unicode FIFO buffer. 939 940 @param TerminalDevice Terminal driver private structure. 941 @param Output The key will be removed. 942 943 @retval TRUE If insert successfully. 944 @retval FLASE If Unicode FIFO buffer is empty before remove operation. 945 946**/ 947BOOLEAN 948UnicodeFiFoRemoveOneKey ( 949 TERMINAL_DEV *TerminalDevice, 950 UINT16 *Output 951 ) 952{ 953 UINT8 Head; 954 955 Head = TerminalDevice->UnicodeFiFo->Head; 956 ASSERT (Head < FIFO_MAX_NUMBER + 1); 957 958 if (IsUnicodeFiFoEmpty (TerminalDevice)) { 959 // 960 // FIFO is empty 961 // 962 Output = NULL; 963 return FALSE; 964 } 965 966 *Output = TerminalDevice->UnicodeFiFo->Data[Head]; 967 968 TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); 969 970 return TRUE; 971} 972 973/** 974 Clarify whether Unicode FIFO buffer is empty. 975 976 @param TerminalDevice Terminal driver private structure 977 978 @retval TRUE If Unicode FIFO buffer is empty. 979 @retval FLASE If Unicode FIFO buffer is not empty. 980 981**/ 982BOOLEAN 983IsUnicodeFiFoEmpty ( 984 TERMINAL_DEV *TerminalDevice 985 ) 986{ 987 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) { 988 return TRUE; 989 } else { 990 return FALSE; 991 } 992} 993 994/** 995 Clarify whether Unicode FIFO buffer is full. 996 997 @param TerminalDevice Terminal driver private structure 998 999 @retval TRUE If Unicode FIFO buffer is full. 1000 @retval FLASE If Unicode FIFO buffer is not full. 1001 1002**/ 1003BOOLEAN 1004IsUnicodeFiFoFull ( 1005 TERMINAL_DEV *TerminalDevice 1006 ) 1007{ 1008 UINT8 Tail; 1009 UINT8 Head; 1010 1011 Tail = TerminalDevice->UnicodeFiFo->Tail; 1012 Head = TerminalDevice->UnicodeFiFo->Head; 1013 1014 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) { 1015 1016 return TRUE; 1017 } 1018 1019 return FALSE; 1020} 1021 1022/** 1023 Count Unicode FIFO buffer. 1024 1025 @param TerminalDevice Terminal driver private structure 1026 1027 @return The count in bytes of Unicode FIFO. 1028 1029**/ 1030UINT8 1031UnicodeFiFoGetKeyCount ( 1032 TERMINAL_DEV *TerminalDevice 1033 ) 1034{ 1035 UINT8 Tail; 1036 UINT8 Head; 1037 1038 Tail = TerminalDevice->UnicodeFiFo->Tail; 1039 Head = TerminalDevice->UnicodeFiFo->Head; 1040 1041 if (Tail >= Head) { 1042 return (UINT8) (Tail - Head); 1043 } else { 1044 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head); 1045 } 1046} 1047 1048/** 1049 Update the Unicode characters from a terminal input device into EFI Keys FIFO. 1050 1051 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys 1052 1053**/ 1054VOID 1055UnicodeToEfiKeyFlushState ( 1056 IN TERMINAL_DEV *TerminalDevice 1057 ) 1058{ 1059 EFI_INPUT_KEY Key; 1060 UINT32 InputState; 1061 1062 InputState = TerminalDevice->InputState; 1063 1064 if (IsEfiKeyFiFoFull (TerminalDevice)) { 1065 return; 1066 } 1067 1068 if ((InputState & INPUT_STATE_ESC) != 0) { 1069 Key.ScanCode = SCAN_ESC; 1070 Key.UnicodeChar = 0; 1071 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1072 } 1073 1074 if ((InputState & INPUT_STATE_CSI) != 0) { 1075 Key.ScanCode = SCAN_NULL; 1076 Key.UnicodeChar = CSI; 1077 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1078 } 1079 1080 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) { 1081 Key.ScanCode = SCAN_NULL; 1082 Key.UnicodeChar = LEFTOPENBRACKET; 1083 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1084 } 1085 1086 if ((InputState & INPUT_STATE_O) != 0) { 1087 Key.ScanCode = SCAN_NULL; 1088 Key.UnicodeChar = 'O'; 1089 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1090 } 1091 1092 if ((InputState & INPUT_STATE_2) != 0) { 1093 Key.ScanCode = SCAN_NULL; 1094 Key.UnicodeChar = '2'; 1095 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1096 } 1097 1098 // 1099 // Cancel the timer. 1100 // 1101 gBS->SetTimer ( 1102 TerminalDevice->TwoSecondTimeOut, 1103 TimerCancel, 1104 0 1105 ); 1106 1107 TerminalDevice->InputState = INPUT_STATE_DEFAULT; 1108} 1109 1110 1111/** 1112 Converts a stream of Unicode characters from a terminal input device into EFI Keys that 1113 can be read through the Simple Input Protocol. 1114 1115 The table below shows the keyboard input mappings that this function supports. 1116 If the ESC sequence listed in one of the columns is presented, then it is translated 1117 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw 1118 key strokes are converted into EFI Keys. 1119 1120 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not 1121 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are 1122 converted into EFI Keys. 1123 There is one special input sequence that will force the system to reset. 1124 This is ESC R ESC r ESC R. 1125 1126 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100. 1127 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 / 1128 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example. 1129 1130 Symbols used in table below 1131 =========================== 1132 ESC = 0x1B 1133 CSI = 0x9B 1134 DEL = 0x7f 1135 ^ = CTRL 1136 1137 +=========+======+===========+==========+==========+ 1138 | | EFI | UEFI 2.0 | | | 1139 | | Scan | | VT100+ | | 1140 | KEY | Code | PC ANSI | VTUTF8 | VT100 | 1141 +=========+======+===========+==========+==========+ 1142 | NULL | 0x00 | | | | 1143 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A | 1144 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B | 1145 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C | 1146 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D | 1147 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H | 1148 | END | 0x06 | ESC [ F | ESC k | ESC [ K | 1149 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ | 1150 | | | ESC [ L | | ESC [ L | 1151 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P | 1152 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V | 1153 | | | | | ESC [ ? | 1154 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U | 1155 | | | | | ESC [ / | 1156 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P | 1157 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q | 1158 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w | 1159 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x | 1160 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t | 1161 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u | 1162 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q | 1163 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r | 1164 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p | 1165 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M | 1166 | Escape | 0x17 | ESC | ESC | ESC | 1167 | F11 | 0x15 | | ESC ! | | 1168 | F12 | 0x16 | | ESC @ | | 1169 +=========+======+===========+==========+==========+ 1170 1171 Special Mappings 1172 ================ 1173 ESC R ESC r ESC R = Reset System 1174 1175 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys 1176 1177**/ 1178VOID 1179UnicodeToEfiKey ( 1180 IN TERMINAL_DEV *TerminalDevice 1181 ) 1182{ 1183 EFI_STATUS Status; 1184 EFI_STATUS TimerStatus; 1185 UINT16 UnicodeChar; 1186 EFI_INPUT_KEY Key; 1187 BOOLEAN SetDefaultResetState; 1188 1189 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut); 1190 1191 if (!EFI_ERROR (TimerStatus)) { 1192 UnicodeToEfiKeyFlushState (TerminalDevice); 1193 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1194 } 1195 1196 while (!IsUnicodeFiFoEmpty (TerminalDevice) && !IsEfiKeyFiFoFull (TerminalDevice)) { 1197 1198 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) { 1199 // 1200 // Check to see if the 2 seconds timer has expired 1201 // 1202 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut); 1203 if (!EFI_ERROR (TimerStatus)) { 1204 UnicodeToEfiKeyFlushState (TerminalDevice); 1205 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1206 } 1207 } 1208 1209 // 1210 // Fetch one Unicode character from the Unicode FIFO 1211 // 1212 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar); 1213 1214 SetDefaultResetState = TRUE; 1215 1216 switch (TerminalDevice->InputState) { 1217 case INPUT_STATE_DEFAULT: 1218 1219 break; 1220 1221 case INPUT_STATE_ESC: 1222 1223 if (UnicodeChar == LEFTOPENBRACKET) { 1224 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET; 1225 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1226 continue; 1227 } 1228 1229 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) { 1230 TerminalDevice->InputState |= INPUT_STATE_O; 1231 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1232 continue; 1233 } 1234 1235 Key.ScanCode = SCAN_NULL; 1236 1237 if (TerminalDevice->TerminalType == VT100PLUSTYPE || 1238 TerminalDevice->TerminalType == VTUTF8TYPE) { 1239 switch (UnicodeChar) { 1240 case '1': 1241 Key.ScanCode = SCAN_F1; 1242 break; 1243 case '2': 1244 Key.ScanCode = SCAN_F2; 1245 break; 1246 case '3': 1247 Key.ScanCode = SCAN_F3; 1248 break; 1249 case '4': 1250 Key.ScanCode = SCAN_F4; 1251 break; 1252 case '5': 1253 Key.ScanCode = SCAN_F5; 1254 break; 1255 case '6': 1256 Key.ScanCode = SCAN_F6; 1257 break; 1258 case '7': 1259 Key.ScanCode = SCAN_F7; 1260 break; 1261 case '8': 1262 Key.ScanCode = SCAN_F8; 1263 break; 1264 case '9': 1265 Key.ScanCode = SCAN_F9; 1266 break; 1267 case '0': 1268 Key.ScanCode = SCAN_F10; 1269 break; 1270 case '!': 1271 Key.ScanCode = SCAN_F11; 1272 break; 1273 case '@': 1274 Key.ScanCode = SCAN_F12; 1275 break; 1276 case 'h': 1277 Key.ScanCode = SCAN_HOME; 1278 break; 1279 case 'k': 1280 Key.ScanCode = SCAN_END; 1281 break; 1282 case '+': 1283 Key.ScanCode = SCAN_INSERT; 1284 break; 1285 case '-': 1286 Key.ScanCode = SCAN_DELETE; 1287 break; 1288 case '/': 1289 Key.ScanCode = SCAN_PAGE_DOWN; 1290 break; 1291 case '?': 1292 Key.ScanCode = SCAN_PAGE_UP; 1293 break; 1294 default : 1295 break; 1296 } 1297 } 1298 1299 switch (UnicodeChar) { 1300 case 'R': 1301 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) { 1302 TerminalDevice->ResetState = RESET_STATE_ESC_R; 1303 SetDefaultResetState = FALSE; 1304 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) { 1305 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); 1306 } 1307 Key.ScanCode = SCAN_NULL; 1308 break; 1309 case 'r': 1310 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) { 1311 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R; 1312 SetDefaultResetState = FALSE; 1313 } 1314 Key.ScanCode = SCAN_NULL; 1315 break; 1316 default : 1317 break; 1318 } 1319 1320 if (SetDefaultResetState) { 1321 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1322 } 1323 1324 if (Key.ScanCode != SCAN_NULL) { 1325 Key.UnicodeChar = 0; 1326 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1327 TerminalDevice->InputState = INPUT_STATE_DEFAULT; 1328 UnicodeToEfiKeyFlushState (TerminalDevice); 1329 continue; 1330 } 1331 1332 UnicodeToEfiKeyFlushState (TerminalDevice); 1333 1334 break; 1335 1336 case INPUT_STATE_ESC | INPUT_STATE_O: 1337 1338 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1339 1340 Key.ScanCode = SCAN_NULL; 1341 1342 if (TerminalDevice->TerminalType == VT100TYPE) { 1343 switch (UnicodeChar) { 1344 case 'P': 1345 Key.ScanCode = SCAN_F1; 1346 break; 1347 case 'Q': 1348 Key.ScanCode = SCAN_F2; 1349 break; 1350 case 'w': 1351 Key.ScanCode = SCAN_F3; 1352 break; 1353 case 'x': 1354 Key.ScanCode = SCAN_F4; 1355 break; 1356 case 't': 1357 Key.ScanCode = SCAN_F5; 1358 break; 1359 case 'u': 1360 Key.ScanCode = SCAN_F6; 1361 break; 1362 case 'q': 1363 Key.ScanCode = SCAN_F7; 1364 break; 1365 case 'r': 1366 Key.ScanCode = SCAN_F8; 1367 break; 1368 case 'p': 1369 Key.ScanCode = SCAN_F9; 1370 break; 1371 case 'M': 1372 Key.ScanCode = SCAN_F10; 1373 break; 1374 default : 1375 break; 1376 } 1377 } 1378 1379 if (Key.ScanCode != SCAN_NULL) { 1380 Key.UnicodeChar = 0; 1381 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key); 1382 TerminalDevice->InputState = INPUT_STATE_DEFAULT; 1383 UnicodeToEfiKeyFlushState (TerminalDevice); 1384 continue; 1385 } 1386 1387 UnicodeToEfiKeyFlushState (TerminalDevice); 1388 1389 break; 1390 1391 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET: 1392 1393 TerminalDevice->ResetState = RESET_STATE_DEFAULT; 1394 1395 Key.ScanCode = SCAN_NULL; 1396 1397 if (TerminalDevice->TerminalType == PCANSITYPE || 1398 TerminalDevice->TerminalType == VT100TYPE || 1399 TerminalDevice->TerminalType == VT100PLUSTYPE || 1400 TerminalDevice->TerminalType == VTUTF8TYPE) { 1401 switch (UnicodeChar) { 1402 case 'A': 1403 Key.ScanCode = SCAN_UP; 1404 break; 1405 case 'B': 1406 Key.ScanCode = SCAN_DOWN; 1407 break; 1408 case 'C': 1409 Key.ScanCode = SCAN_RIGHT; 1410 break; 1411 case 'D': 1412 Key.ScanCode = SCAN_LEFT; 1413 break; 1414 case 'H': 1415 if (TerminalDevice->TerminalType == PCANSITYPE || 1416 TerminalDevice->TerminalType == VT100TYPE) { 1417 Key.ScanCode = SCAN_HOME; 1418 } 1419 break; 1420 case 'F': 1421 if (TerminalDevice->TerminalType == PCANSITYPE) { 1422 Key.ScanCode = SCAN_END; 1423 } 1424 break; 1425 case 'K': 1426 if (TerminalDevice->TerminalType == VT100TYPE) { 1427 Key.ScanCode = SCAN_END; 1428 } 1429 break; 1430 case 'L': 1431 case '@': 1432 if (TerminalDevice->TerminalType == PCANSITYPE || 1433 TerminalDevice->TerminalType == VT100TYPE) { 1434 Key.ScanCode = SCAN_INSERT; 1435 } 1436 break; 1437 case 'X': 1438 if (TerminalDevice->TerminalType == PCANSITYPE) { 1439 Key.ScanCode = SCAN_DELETE; 1440 } 1441 break; 1442 case 'P': 1443 if (TerminalDevice->TerminalType == VT100TYPE) { 1444 Key.ScanCode = SCAN_DELETE; 1445 } else if (TerminalDevice->TerminalType == PCANSITYPE) { 1446 Key.ScanCode = SCAN_F4; 1447 } 1448 break; 1449 case 'I': 1450 if (TerminalDevice->TerminalType == PCANSITYPE) { 1451 Key.ScanCode = SCAN_PAGE_UP; 1452 } 1453 break; 1454 case 'V': 1455 if (TerminalDevice->TerminalType == PCANSITYPE) { 1456 Key.ScanCode = SCAN_F10; 1457 } 1458 case '?': 1459 if (TerminalDevice->TerminalType == VT100TYPE) { 1460 Key.ScanCode = SCAN_PAGE_UP; 1461 } 1462 break; 1463 case 'G': 1464 if (TerminalDevice->TerminalType == PCANSITYPE) { 1465 Key.ScanCode = SCAN_PAGE_DOWN; 1466 } 1467 break; 1468 case 'U': 1469 if (TerminalDevice->TerminalType == PCANSITYPE) { 1470 Key.ScanCode = SCAN_F9; 1471 } 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