1 /** @file 2 3 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 WinNtGopInput.c 15 16 Abstract: 17 18 This file produces the Simple Text In for an Gop window. 19 20 This stuff is linked at the hip to the Window, since the window 21 processing is done in a thread kicked off in WinNtGopImplementation.c 22 23 Since the window information is processed in an other thread we need 24 a keyboard Queue to pass data about. The Simple Text In code just 25 takes data off the Queue. The WinProc message loop takes keyboard input 26 and places it in the Queue. 27 28 29 **/ 30 31 32 #include "WinNtGop.h" 33 34 35 /** 36 TODO: Add function description 37 38 @param Private TODO: add argument description 39 40 @retval EFI_SUCCESS TODO: Add description for return value 41 42 **/ 43 EFI_STATUS 44 GopPrivateCreateQ ( 45 IN GOP_PRIVATE_DATA *Private, 46 IN GOP_QUEUE_FIXED *Queue 47 ) 48 { 49 Private->WinNtThunk->InitializeCriticalSection (&Queue->Cs); 50 Queue->Front = 0; 51 Queue->Rear = 0; 52 return EFI_SUCCESS; 53 } 54 55 56 /** 57 TODO: Add function description 58 59 @param Private TODO: add argument description 60 61 @retval EFI_SUCCESS TODO: Add description for return value 62 63 **/ 64 EFI_STATUS 65 GopPrivateDestroyQ ( 66 IN GOP_PRIVATE_DATA *Private, 67 IN GOP_QUEUE_FIXED *Queue 68 ) 69 { 70 Queue->Front = 0; 71 Queue->Rear = 0; 72 Private->WinNtThunk->DeleteCriticalSection (&Queue->Cs); 73 return EFI_SUCCESS; 74 } 75 76 77 /** 78 TODO: Add function description 79 80 @param Private TODO: add argument description 81 @param Key TODO: add argument description 82 83 @retval EFI_NOT_READY TODO: Add description for return value 84 @retval EFI_SUCCESS TODO: Add description for return value 85 86 **/ 87 EFI_STATUS 88 GopPrivateAddQ ( 89 IN GOP_PRIVATE_DATA *Private, 90 IN GOP_QUEUE_FIXED *Queue, 91 IN EFI_KEY_DATA *KeyData 92 ) 93 { 94 Private->WinNtThunk->EnterCriticalSection (&Queue->Cs); 95 96 if ((Queue->Rear + 1) % MAX_Q == Queue->Front) { 97 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); 98 return EFI_NOT_READY; 99 } 100 101 CopyMem (&Queue->Q[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA)); 102 Queue->Rear = (Queue->Rear + 1) % MAX_Q; 103 104 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); 105 return EFI_SUCCESS; 106 } 107 108 109 /** 110 TODO: Add function description 111 112 @param Private TODO: add argument description 113 @param Key TODO: add argument description 114 115 @retval EFI_NOT_READY TODO: Add description for return value 116 @retval EFI_SUCCESS TODO: Add description for return value 117 118 **/ 119 EFI_STATUS 120 GopPrivateDeleteQ ( 121 IN GOP_PRIVATE_DATA *Private, 122 IN GOP_QUEUE_FIXED *Queue, 123 OUT EFI_KEY_DATA *Key 124 ) 125 { 126 Private->WinNtThunk->EnterCriticalSection (&Queue->Cs); 127 128 if (Queue->Front == Queue->Rear) { 129 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); 130 return EFI_NOT_READY; 131 } 132 133 CopyMem (Key, &Queue->Q[Queue->Front], sizeof (EFI_KEY_DATA)); 134 Queue->Front = (Queue->Front + 1) % MAX_Q; 135 136 if (Key->Key.ScanCode == SCAN_NULL && Key->Key.UnicodeChar == CHAR_NULL) { 137 if (!Private->IsPartialKeySupport) { 138 // 139 // If partial keystrok is not enabled, don't return the partial keystroke. 140 // 141 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); 142 ZeroMem (Key, sizeof (EFI_KEY_DATA)); 143 return EFI_NOT_READY; 144 } 145 } 146 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs); 147 return EFI_SUCCESS; 148 } 149 150 151 /** 152 TODO: Add function description 153 154 @param Private TODO: add argument description 155 156 @retval EFI_NOT_READY TODO: Add description for return value 157 @retval EFI_SUCCESS TODO: Add description for return value 158 159 **/ 160 EFI_STATUS 161 GopPrivateCheckQ ( 162 IN GOP_QUEUE_FIXED *Queue 163 ) 164 { 165 if (Queue->Front == Queue->Rear) { 166 return EFI_NOT_READY; 167 } 168 169 return EFI_SUCCESS; 170 } 171 172 BOOLEAN 173 GopPrivateIsKeyRegistered ( 174 IN EFI_KEY_DATA *RegsiteredData, 175 IN EFI_KEY_DATA *InputData 176 ) 177 /*++ 178 179 Routine Description: 180 181 Arguments: 182 183 RegsiteredData - A pointer to a buffer that is filled in with the keystroke 184 state data for the key that was registered. 185 InputData - A pointer to a buffer that is filled in with the keystroke 186 state data for the key that was pressed. 187 188 Returns: 189 TRUE - Key be pressed matches a registered key. 190 FLASE - Match failed. 191 192 --*/ 193 { 194 ASSERT (RegsiteredData != NULL && InputData != NULL); 195 196 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || 197 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) { 198 return FALSE; 199 } 200 201 // 202 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored. 203 // 204 if (RegsiteredData->KeyState.KeyShiftState != 0 && 205 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) { 206 return FALSE; 207 } 208 if (RegsiteredData->KeyState.KeyToggleState != 0 && 209 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) { 210 return FALSE; 211 } 212 213 return TRUE; 214 215 } 216 217 218 VOID 219 GopPrivateInvokeRegisteredFunction ( 220 IN GOP_PRIVATE_DATA *Private, 221 IN EFI_KEY_DATA *KeyData 222 ) 223 /*++ 224 225 Routine Description: 226 227 This function updates the status light of NumLock, ScrollLock and CapsLock. 228 229 Arguments: 230 231 Private - The private structure of WinNt Gop device. 232 KeyData - A pointer to a buffer that is filled in with the keystroke 233 state data for the key that was pressed. 234 235 Returns: 236 237 EFI_SUCCESS - The status light is updated successfully. 238 239 --*/ 240 { 241 LIST_ENTRY *Link; 242 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; 243 244 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { 245 CurrentNotify = CR ( 246 Link, 247 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, 248 NotifyEntry, 249 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE 250 ); 251 if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { 252 CurrentNotify->KeyNotificationFn (KeyData); 253 } 254 } 255 } 256 257 VOID 258 WinNtGopSimpleTextInTimerHandler ( 259 IN EFI_EVENT Event, 260 IN VOID *Context 261 ) 262 { 263 GOP_PRIVATE_DATA *Private; 264 EFI_KEY_DATA KeyData; 265 266 Private = (GOP_PRIVATE_DATA *)Context; 267 while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == EFI_SUCCESS) { 268 GopPrivateInvokeRegisteredFunction (Private, &KeyData); 269 } 270 } 271 272 /** 273 TODO: Add function description 274 275 @param Private TODO: add argument description 276 @param Key TODO: add argument description 277 278 @retval EFI_NOT_READY TODO: Add description for return value 279 @retval EFI_SUCCESS TODO: Add description for return value 280 281 **/ 282 EFI_STATUS 283 GopPrivateAddKey ( 284 IN GOP_PRIVATE_DATA *Private, 285 IN EFI_INPUT_KEY Key 286 ) 287 { 288 EFI_KEY_DATA KeyData; 289 290 KeyData.Key = Key; 291 292 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; 293 KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; 294 295 // 296 // Record Key shift state and toggle state 297 // 298 if (Private->LeftCtrl) { 299 KeyData.KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED; 300 } 301 if (Private->RightCtrl) { 302 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED; 303 } 304 if (Private->LeftAlt) { 305 KeyData.KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED; 306 } 307 if (Private->RightAlt) { 308 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED; 309 } 310 if (Private->LeftShift) { 311 KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; 312 } 313 if (Private->RightShift) { 314 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; 315 } 316 if (Private->LeftLogo) { 317 KeyData.KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED; 318 } 319 if (Private->RightLogo) { 320 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED; 321 } 322 if (Private->Menu) { 323 KeyData.KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED; 324 } 325 if (Private->SysReq) { 326 KeyData.KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED; 327 } 328 if (Private->CapsLock) { 329 KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE; 330 } 331 if (Private->NumLock) { 332 KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE; 333 } 334 if (Private->ScrollLock) { 335 KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE; 336 } 337 if (Private->IsPartialKeySupport) { 338 KeyData.KeyState.KeyToggleState |= EFI_KEY_STATE_EXPOSED; 339 } 340 341 // 342 // Convert Ctrl+[1-26] to Ctrl+[A-Z] 343 // 344 if ((Private->LeftCtrl || Private->RightCtrl) && 345 (KeyData.Key.UnicodeChar >= 1) && (KeyData.Key.UnicodeChar <= 26) 346 ) { 347 if ((Private->LeftShift || Private->RightShift) == Private->CapsLock) { 348 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'a' - 1); 349 } else { 350 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'A' - 1); 351 } 352 } 353 354 // 355 // Unmask the Shift bit for printable char 356 // 357 if (((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) || 358 ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) 359 ) { 360 KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED); 361 } 362 363 GopPrivateAddQ (Private, &Private->QueueForNotify, &KeyData); 364 365 GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData); 366 367 return EFI_SUCCESS; 368 } 369 370 EFI_STATUS 371 GopPrivateUpdateStatusLight ( 372 IN GOP_PRIVATE_DATA *Private 373 ) 374 /*++ 375 376 Routine Description: 377 378 This function updates the status light of NumLock, ScrollLock and CapsLock. 379 380 Arguments: 381 382 Private - The private structure of WinNt console In/Out. 383 384 Returns: 385 386 EFI_SUCCESS - The status light is updated successfully. 387 388 --*/ 389 { 390 // 391 // BUGBUG:Only SendInput/keybd_event function can toggle 392 // NumLock, CapsLock and ScrollLock keys. 393 // Neither of these functions is included in EFI_WIN_NT_THUNK_PROTOCOL. 394 // Thus, return immediately without operation. 395 // 396 return EFI_SUCCESS; 397 398 } 399 400 401 EFI_STATUS 402 GopPrivateResetWorker ( 403 IN GOP_PRIVATE_DATA *Private 404 ) 405 /*++ 406 407 Routine Description: 408 409 This function is a worker function for SimpleTextIn/SimpleTextInEx.Reset(). 410 411 Arguments: 412 413 Private - WinNT GOP private structure 414 415 Returns: 416 417 EFI_SUCCESS - Reset successfully 418 419 --*/ 420 { 421 EFI_KEY_DATA KeyData; 422 EFI_TPL OldTpl; 423 424 // 425 // Enter critical section 426 // 427 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 428 429 // 430 // A reset is draining the Queue 431 // 432 while (GopPrivateDeleteQ (Private, &Private->QueueForRead, &KeyData) == EFI_SUCCESS) 433 ; 434 while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == EFI_SUCCESS) 435 ; 436 437 Private->LeftShift = FALSE; 438 Private->RightShift = FALSE; 439 Private->LeftAlt = FALSE; 440 Private->RightAlt = FALSE; 441 Private->LeftCtrl = FALSE; 442 Private->RightCtrl = FALSE; 443 Private->LeftLogo = FALSE; 444 Private->RightLogo = FALSE; 445 Private->Menu = FALSE; 446 Private->SysReq = FALSE; 447 448 Private->CapsLock = FALSE; 449 Private->NumLock = FALSE; 450 Private->ScrollLock = FALSE; 451 Private->IsPartialKeySupport = FALSE; 452 453 Private->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; 454 Private->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; 455 456 // 457 // Leave critical section and return 458 // 459 gBS->RestoreTPL (OldTpl); 460 461 return EFI_SUCCESS; 462 } 463 464 EFI_STATUS 465 GopPrivateReadKeyStrokeWorker ( 466 IN GOP_PRIVATE_DATA *Private, 467 OUT EFI_KEY_DATA *KeyData 468 ) 469 /*++ 470 471 Routine Description: 472 Reads the next keystroke from the input device. The WaitForKey Event can 473 be used to test for existance of a keystroke via WaitForEvent () call. 474 475 Arguments: 476 Private - The private structure of WinNt Gop device. 477 KeyData - A pointer to a buffer that is filled in with the keystroke 478 state data for the key that was pressed. 479 480 Returns: 481 EFI_SUCCESS - The keystroke information was returned. 482 EFI_NOT_READY - There was no keystroke data availiable. 483 EFI_DEVICE_ERROR - The keystroke information was not returned due to 484 hardware errors. 485 EFI_INVALID_PARAMETER - KeyData is NULL. 486 487 --*/ 488 { 489 EFI_STATUS Status; 490 EFI_TPL OldTpl; 491 492 if (KeyData == NULL) { 493 return EFI_INVALID_PARAMETER; 494 } 495 496 // 497 // Enter critical section 498 // 499 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 500 501 // 502 // Call hot key callback before telling caller there is a key available 503 // 504 WinNtGopSimpleTextInTimerHandler (NULL, Private); 505 506 Status = GopPrivateCheckQ (&Private->QueueForRead); 507 if (!EFI_ERROR (Status)) { 508 // 509 // If a Key press exists try and read it. 510 // 511 Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData); 512 if (!EFI_ERROR (Status)) { 513 // 514 // If partial keystroke is not enabled, check whether it is value key. If not return 515 // EFI_NOT_READY. 516 // 517 if (!Private->IsPartialKeySupport) { 518 if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) { 519 Status = EFI_NOT_READY; 520 } 521 } 522 } 523 } 524 525 // 526 // Leave critical section and return 527 // 528 gBS->RestoreTPL (OldTpl); 529 530 return Status; 531 532 } 533 534 535 // 536 // Simple Text In implementation. 537 // 538 539 540 /** 541 TODO: Add function description 542 543 @param This TODO: add argument description 544 @param ExtendedVerification TODO: add argument description 545 546 @retval EFI_SUCCESS TODO: Add description for return value 547 548 **/ 549 EFI_STATUS 550 EFIAPI 551 WinNtGopSimpleTextInReset ( 552 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, 553 IN BOOLEAN ExtendedVerification 554 ) 555 { 556 GOP_PRIVATE_DATA *Private; 557 558 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); 559 560 return GopPrivateResetWorker (Private); 561 } 562 563 564 /** 565 TODO: Add function description 566 567 @param This TODO: add argument description 568 @param Key TODO: add argument description 569 570 @return TODO: add return values 571 572 **/ 573 EFI_STATUS 574 EFIAPI 575 WinNtGopSimpleTextInReadKeyStroke ( 576 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, 577 OUT EFI_INPUT_KEY *Key 578 ) 579 { 580 GOP_PRIVATE_DATA *Private; 581 EFI_STATUS Status; 582 EFI_KEY_DATA KeyData; 583 584 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); 585 // 586 // Considering if the partial keystroke is enabled, there maybe a partial 587 // keystroke in the queue, so here skip the partial keystroke and get the 588 // next key from the queue 589 // 590 while (1) { 591 Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData); 592 if (EFI_ERROR (Status)) { 593 return Status; 594 } 595 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) { 596 continue; 597 } 598 // 599 // Convert Ctrl+[A-Z] to Ctrl+[1-26] 600 // 601 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) { 602 if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) { 603 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1); 604 } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) { 605 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1); 606 } 607 } 608 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); 609 return EFI_SUCCESS; 610 } 611 } 612 613 614 /** 615 TODO: Add function description 616 617 @param Event TODO: add argument description 618 @param Context TODO: add argument description 619 620 @return TODO: add return values 621 622 **/ 623 VOID 624 EFIAPI 625 WinNtGopSimpleTextInWaitForKey ( 626 IN EFI_EVENT Event, 627 IN VOID *Context 628 ) 629 { 630 GOP_PRIVATE_DATA *Private; 631 EFI_STATUS Status; 632 EFI_TPL OldTpl; 633 EFI_KEY_DATA KeyData; 634 635 Private = (GOP_PRIVATE_DATA *) Context; 636 637 // 638 // Enter critical section 639 // 640 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 641 642 // 643 // Call hot key callback before telling caller there is a key available 644 // 645 WinNtGopSimpleTextInTimerHandler (NULL, Private); 646 647 // 648 // WaitforKey doesn't suppor the partial key. 649 // Considering if the partial keystroke is enabled, there maybe a partial 650 // keystroke in the queue, so here skip the partial keystroke and get the 651 // next key from the queue 652 // 653 while (1) { 654 Status = GopPrivateCheckQ (&Private->QueueForRead); 655 if (!EFI_ERROR (Status)) { 656 // 657 // If a there is a key in the queue and it is not partial keystroke, signal event. 658 // 659 if (Private->QueueForRead.Q[Private->QueueForRead.Front].Key.ScanCode == SCAN_NULL && 660 Private->QueueForRead.Q[Private->QueueForRead.Front].Key.UnicodeChar == CHAR_NULL) { 661 GopPrivateDeleteQ (Private,&Private->QueueForRead,&KeyData); 662 continue; 663 } 664 gBS->SignalEvent (Event); 665 } else { 666 // 667 // We need to sleep or NT will schedule this thread with such high 668 // priority that WinProc thread will never run and we will not see 669 // keyboard input. This Sleep makes the syste run 10x faster, so don't 670 // remove it. 671 // 672 Private->WinNtThunk->Sleep (1); 673 } 674 break; 675 } 676 677 // 678 // Leave critical section and return 679 // 680 gBS->RestoreTPL (OldTpl); 681 } 682 683 // 684 // Simple Text Input Ex protocol functions 685 // 686 687 EFI_STATUS 688 EFIAPI 689 WinNtGopSimpleTextInExResetEx ( 690 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 691 IN BOOLEAN ExtendedVerification 692 ) 693 /*++ 694 695 Routine Description: 696 Reset the input device and optionaly run diagnostics 697 698 Arguments: 699 This - Protocol instance pointer. 700 ExtendedVerification - Driver may perform diagnostics on reset. 701 702 Returns: 703 EFI_SUCCESS - The device was reset. 704 705 --*/ 706 { 707 GOP_PRIVATE_DATA *Private; 708 709 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); 710 711 return GopPrivateResetWorker (Private); 712 } 713 714 EFI_STATUS 715 EFIAPI 716 WinNtGopSimpleTextInExReadKeyStrokeEx ( 717 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 718 OUT EFI_KEY_DATA *KeyData 719 ) 720 /*++ 721 722 Routine Description: 723 Reads the next keystroke from the input device. The WaitForKey Event can 724 be used to test for existance of a keystroke via WaitForEvent () call. 725 726 Arguments: 727 This - Protocol instance pointer. 728 KeyData - A pointer to a buffer that is filled in with the keystroke 729 state data for the key that was pressed. 730 731 Returns: 732 EFI_SUCCESS - The keystroke information was returned. 733 EFI_NOT_READY - There was no keystroke data availiable. 734 EFI_DEVICE_ERROR - The keystroke information was not returned due to 735 hardware errors. 736 EFI_INVALID_PARAMETER - KeyData is NULL. 737 738 --*/ 739 { 740 GOP_PRIVATE_DATA *Private; 741 742 if (KeyData == NULL) { 743 return EFI_INVALID_PARAMETER; 744 } 745 746 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); 747 748 return GopPrivateReadKeyStrokeWorker (Private, KeyData); 749 750 } 751 752 EFI_STATUS 753 EFIAPI 754 WinNtGopSimpleTextInExSetState ( 755 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 756 IN EFI_KEY_TOGGLE_STATE *KeyToggleState 757 ) 758 /*++ 759 760 Routine Description: 761 Set certain state for the input device. 762 763 Arguments: 764 This - Protocol instance pointer. 765 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the 766 state for the input device. 767 768 Returns: 769 EFI_SUCCESS - The device state was set successfully. 770 EFI_DEVICE_ERROR - The device is not functioning correctly and could 771 not have the setting adjusted. 772 EFI_UNSUPPORTED - The device does not have the ability to set its state. 773 EFI_INVALID_PARAMETER - KeyToggleState is NULL. 774 775 --*/ 776 { 777 EFI_STATUS Status; 778 GOP_PRIVATE_DATA *Private; 779 780 if (KeyToggleState == NULL) { 781 return EFI_INVALID_PARAMETER; 782 } 783 784 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); 785 786 if (((Private->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) || 787 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) { 788 return EFI_UNSUPPORTED; 789 } 790 791 Private->ScrollLock = FALSE; 792 Private->NumLock = FALSE; 793 Private->CapsLock = FALSE; 794 Private->IsPartialKeySupport = FALSE; 795 796 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) { 797 Private->ScrollLock = TRUE; 798 } 799 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) { 800 Private->NumLock = TRUE; 801 } 802 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) { 803 Private->CapsLock = TRUE; 804 } 805 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) { 806 Private->IsPartialKeySupport = TRUE; 807 } 808 809 Status = GopPrivateUpdateStatusLight (Private); 810 if (EFI_ERROR (Status)) { 811 return EFI_DEVICE_ERROR; 812 } 813 814 Private->KeyState.KeyToggleState = *KeyToggleState; 815 return EFI_SUCCESS; 816 817 } 818 819 EFI_STATUS 820 EFIAPI 821 WinNtGopSimpleTextInExRegisterKeyNotify ( 822 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 823 IN EFI_KEY_DATA *KeyData, 824 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, 825 OUT VOID **NotifyHandle 826 ) 827 /*++ 828 829 Routine Description: 830 Register a notification function for a particular keystroke for the input device. 831 832 Arguments: 833 This - Protocol instance pointer. 834 KeyData - A pointer to a buffer that is filled in with the keystroke 835 information data for the key that was pressed. 836 KeyNotificationFunction - Points to the function to be called when the key 837 sequence is typed specified by KeyData. 838 NotifyHandle - Points to the unique handle assigned to the registered notification. 839 840 Returns: 841 EFI_SUCCESS - The notification function was registered successfully. 842 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures. 843 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. 844 845 --*/ 846 { 847 GOP_PRIVATE_DATA *Private; 848 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; 849 LIST_ENTRY *Link; 850 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NewNotify; 851 852 if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL) { 853 return EFI_INVALID_PARAMETER; 854 } 855 856 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); 857 858 // 859 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered. 860 // 861 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { 862 CurrentNotify = CR ( 863 Link, 864 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, 865 NotifyEntry, 866 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE 867 ); 868 if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { 869 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { 870 *NotifyHandle = CurrentNotify; 871 return EFI_SUCCESS; 872 } 873 } 874 } 875 876 // 877 // Allocate resource to save the notification function 878 // 879 NewNotify = (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY)); 880 if (NewNotify == NULL) { 881 return EFI_OUT_OF_RESOURCES; 882 } 883 884 NewNotify->Signature = WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE; 885 NewNotify->KeyNotificationFn = KeyNotificationFunction; 886 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); 887 InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry); 888 889 *NotifyHandle = NewNotify; 890 891 return EFI_SUCCESS; 892 893 } 894 895 EFI_STATUS 896 EFIAPI 897 WinNtGopSimpleTextInExUnregisterKeyNotify ( 898 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 899 IN VOID *NotificationHandle 900 ) 901 /*++ 902 903 Routine Description: 904 Remove a registered notification function from a particular keystroke. 905 906 Arguments: 907 This - Protocol instance pointer. 908 NotificationHandle - The handle of the notification function being unregistered. 909 910 Returns: 911 EFI_SUCCESS - The notification function was unregistered successfully. 912 EFI_INVALID_PARAMETER - The NotificationHandle is invalid. 913 914 --*/ 915 { 916 GOP_PRIVATE_DATA *Private; 917 LIST_ENTRY *Link; 918 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify; 919 920 if (NotificationHandle == NULL) { 921 return EFI_INVALID_PARAMETER; 922 } 923 924 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This); 925 926 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) { 927 CurrentNotify = CR ( 928 Link, 929 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY, 930 NotifyEntry, 931 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE 932 ); 933 if (CurrentNotify == NotificationHandle) { 934 // 935 // Remove the notification function from NotifyList and free resources 936 // 937 RemoveEntryList (&CurrentNotify->NotifyEntry); 938 939 gBS->FreePool (CurrentNotify); 940 return EFI_SUCCESS; 941 } 942 } 943 944 // 945 // Can not find the specified Notification Handle 946 // 947 return EFI_INVALID_PARAMETER; 948 } 949 950 951 /** 952 TODO: Add function description 953 954 @param Private TODO: add argument description 955 956 @return TODO: add return values 957 958 **/ 959 EFI_STATUS 960 WinNtGopInitializeSimpleTextInForWindow ( 961 IN GOP_PRIVATE_DATA *Private 962 ) 963 { 964 EFI_STATUS Status; 965 966 GopPrivateCreateQ (Private, &Private->QueueForRead); 967 GopPrivateCreateQ (Private, &Private->QueueForNotify); 968 969 // 970 // Initialize Simple Text In protoocol 971 // 972 Private->SimpleTextIn.Reset = WinNtGopSimpleTextInReset; 973 Private->SimpleTextIn.ReadKeyStroke = WinNtGopSimpleTextInReadKeyStroke; 974 975 Status = gBS->CreateEvent ( 976 EVT_NOTIFY_WAIT, 977 TPL_NOTIFY, 978 WinNtGopSimpleTextInWaitForKey, 979 Private, 980 &Private->SimpleTextIn.WaitForKey 981 ); 982 983 984 Private->SimpleTextInEx.Reset = WinNtGopSimpleTextInExResetEx; 985 Private->SimpleTextInEx.ReadKeyStrokeEx = WinNtGopSimpleTextInExReadKeyStrokeEx; 986 Private->SimpleTextInEx.SetState = WinNtGopSimpleTextInExSetState; 987 Private->SimpleTextInEx.RegisterKeyNotify = WinNtGopSimpleTextInExRegisterKeyNotify; 988 Private->SimpleTextInEx.UnregisterKeyNotify = WinNtGopSimpleTextInExUnregisterKeyNotify; 989 990 Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE); 991 992 InitializeListHead (&Private->NotifyList); 993 994 Status = gBS->CreateEvent ( 995 EVT_NOTIFY_WAIT, 996 TPL_NOTIFY, 997 WinNtGopSimpleTextInWaitForKey, 998 Private, 999 &Private->SimpleTextInEx.WaitForKeyEx 1000 ); 1001 ASSERT_EFI_ERROR (Status); 1002 1003 // 1004 // Create the Timer to trigger hot key notifications 1005 // 1006 Status = gBS->CreateEvent ( 1007 EVT_TIMER | EVT_NOTIFY_SIGNAL, 1008 TPL_NOTIFY, 1009 WinNtGopSimpleTextInTimerHandler, 1010 Private, 1011 &Private->TimerEvent 1012 ); 1013 ASSERT_EFI_ERROR (Status); 1014 1015 Status = gBS->SetTimer ( 1016 Private->TimerEvent, 1017 TimerPeriodic, 1018 KEYBOARD_TIMER_INTERVAL 1019 ); 1020 ASSERT_EFI_ERROR (Status); 1021 1022 return Status; 1023 } 1024 1025 1026 1027 /** 1028 TODO: Add function description 1029 1030 @param Private TODO: add argument description 1031 1032 @retval EFI_SUCCESS TODO: Add description for return value 1033 1034 **/ 1035 EFI_STATUS 1036 WinNtGopDestroySimpleTextInForWindow ( 1037 IN GOP_PRIVATE_DATA *Private 1038 ) 1039 { 1040 gBS->CloseEvent (Private->TimerEvent); 1041 1042 GopPrivateDestroyQ (Private, &Private->QueueForRead); 1043 GopPrivateDestroyQ (Private, &Private->QueueForNotify); 1044 1045 return EFI_SUCCESS; 1046 } 1047