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