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