TianoCore EDK2 master
Loading...
Searching...
No Matches
EfiKey.c
Go to the documentation of this file.
1
10#include "EfiKey.h"
11#include "KeyBoard.h"
12
13//
14// USB Keyboard Driver Global Variables
15//
16EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {
20 0xa,
21 NULL,
22 NULL
23};
24
38EFIAPI
40 IN EFI_HANDLE ImageHandle,
41 IN EFI_SYSTEM_TABLE *SystemTable
42 )
43{
44 EFI_STATUS Status;
45
47 ImageHandle,
48 SystemTable,
49 &gUsbKeyboardDriverBinding,
50 ImageHandle,
51 &gUsbKeyboardComponentName,
52 &gUsbKeyboardComponentName2
53 );
54 ASSERT_EFI_ERROR (Status);
55
56 return EFI_SUCCESS;
57}
58
71EFIAPI
74 IN EFI_HANDLE Controller,
75 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
76 )
77{
78 EFI_STATUS Status;
80
81 //
82 // Check if USB I/O Protocol is attached on the controller handle.
83 //
84 Status = gBS->OpenProtocol (
85 Controller,
86 &gEfiUsbIoProtocolGuid,
87 (VOID **)&UsbIo,
88 This->DriverBindingHandle,
89 Controller,
90 EFI_OPEN_PROTOCOL_BY_DRIVER
91 );
92 if (EFI_ERROR (Status)) {
93 return Status;
94 }
95
96 //
97 // Use the USB I/O Protocol interface to check whether Controller is
98 // a keyboard device that can be managed by this driver.
99 //
100 Status = EFI_SUCCESS;
101
102 if (!IsUSBKeyboard (UsbIo)) {
103 Status = EFI_UNSUPPORTED;
104 }
105
106 gBS->CloseProtocol (
107 Controller,
108 &gEfiUsbIoProtocolGuid,
109 This->DriverBindingHandle,
110 Controller
111 );
112
113 return Status;
114}
115
134EFIAPI
137 IN EFI_HANDLE Controller,
138 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
139 )
140{
141 EFI_STATUS Status;
142 EFI_USB_IO_PROTOCOL *UsbIo;
143 USB_KB_DEV *UsbKeyboardDevice;
144 UINT8 EndpointNumber;
145 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
146 UINT8 Index;
147 UINT8 EndpointAddr;
148 UINT8 PollingInterval;
149 UINT8 PacketSize;
150 BOOLEAN Found;
151 EFI_TPL OldTpl;
152
153 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
154 //
155 // Open USB I/O Protocol
156 //
157 Status = gBS->OpenProtocol (
158 Controller,
159 &gEfiUsbIoProtocolGuid,
160 (VOID **)&UsbIo,
161 This->DriverBindingHandle,
162 Controller,
163 EFI_OPEN_PROTOCOL_BY_DRIVER
164 );
165 if (EFI_ERROR (Status)) {
166 goto ErrorExit1;
167 }
168
169 UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));
170 ASSERT (UsbKeyboardDevice != NULL);
171
172 //
173 // Get the Device Path Protocol on Controller's handle
174 //
175 Status = gBS->OpenProtocol (
176 Controller,
177 &gEfiDevicePathProtocolGuid,
178 (VOID **)&UsbKeyboardDevice->DevicePath,
179 This->DriverBindingHandle,
180 Controller,
181 EFI_OPEN_PROTOCOL_GET_PROTOCOL
182 );
183
184 if (EFI_ERROR (Status)) {
185 goto ErrorExit;
186 }
187
188 //
189 // Report that the USB keyboard is being enabled
190 //
193 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE),
194 UsbKeyboardDevice->DevicePath
195 );
196
197 //
198 // This is pretty close to keyboard detection, so log progress
199 //
202 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT),
203 UsbKeyboardDevice->DevicePath
204 );
205
206 UsbKeyboardDevice->UsbIo = UsbIo;
207
208 //
209 // Get interface & endpoint descriptor
210 //
211 UsbIo->UsbGetInterfaceDescriptor (
212 UsbIo,
213 &UsbKeyboardDevice->InterfaceDescriptor
214 );
215
216 EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
217
218 //
219 // Traverse endpoints to find interrupt endpoint IN
220 //
221 Found = FALSE;
222 for (Index = 0; Index < EndpointNumber; Index++) {
223 UsbIo->UsbGetEndpointDescriptor (
224 UsbIo,
225 Index,
226 &EndpointDescriptor
227 );
228
229 if (((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) &&
230 ((EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) != 0))
231 {
232 //
233 // We only care interrupt endpoint here
234 //
235 CopyMem (&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));
236 Found = TRUE;
237 break;
238 }
239 }
240
241 if (!Found) {
242 //
243 // Report Status Code to indicate that there is no USB keyboard
244 //
246 EFI_ERROR_CODE | EFI_ERROR_MINOR,
247 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED)
248 );
249 //
250 // No interrupt endpoint found, then return unsupported.
251 //
252 Status = EFI_UNSUPPORTED;
253 goto ErrorExit;
254 }
255
258 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED),
259 UsbKeyboardDevice->DevicePath
260 );
261
262 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
263 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
264 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
265
266 UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;
267 UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;
268 UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;
269 UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;
270 UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;
271
272 InitializeListHead (&UsbKeyboardDevice->NotifyList);
273
274 Status = gBS->CreateEvent (
275 EVT_TIMER | EVT_NOTIFY_SIGNAL,
276 TPL_NOTIFY,
278 UsbKeyboardDevice,
279 &UsbKeyboardDevice->TimerEvent
280 );
281 if (!EFI_ERROR (Status)) {
282 Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL);
283 }
284
285 if (EFI_ERROR (Status)) {
286 goto ErrorExit;
287 }
288
289 Status = gBS->CreateEvent (
290 EVT_NOTIFY_WAIT,
291 TPL_NOTIFY,
293 UsbKeyboardDevice,
294 &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)
295 );
296
297 if (EFI_ERROR (Status)) {
298 goto ErrorExit;
299 }
300
301 Status = gBS->CreateEvent (
302 EVT_NOTIFY_WAIT,
303 TPL_NOTIFY,
305 UsbKeyboardDevice,
306 &(UsbKeyboardDevice->SimpleInput.WaitForKey)
307 );
308 if (EFI_ERROR (Status)) {
309 goto ErrorExit;
310 }
311
312 Status = gBS->CreateEvent (
313 EVT_NOTIFY_SIGNAL,
314 TPL_CALLBACK,
316 UsbKeyboardDevice,
317 &UsbKeyboardDevice->KeyNotifyProcessEvent
318 );
319 if (EFI_ERROR (Status)) {
320 goto ErrorExit;
321 }
322
323 //
324 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
325 // for the USB keyboard device.
326 // USB keyboard is a hot plug device, and expected to work immediately
327 // when plugging into system, other conventional console devices could
328 // distinguish it by its device path.
329 //
330 Status = gBS->InstallMultipleProtocolInterfaces (
331 &Controller,
332 &gEfiSimpleTextInProtocolGuid,
333 &UsbKeyboardDevice->SimpleInput,
334 &gEfiSimpleTextInputExProtocolGuid,
335 &UsbKeyboardDevice->SimpleInputEx,
336 NULL
337 );
338 if (EFI_ERROR (Status)) {
339 goto ErrorExit;
340 }
341
342 UsbKeyboardDevice->ControllerHandle = Controller;
343 Status = InitKeyboardLayout (UsbKeyboardDevice);
344 if (EFI_ERROR (Status)) {
345 gBS->UninstallMultipleProtocolInterfaces (
346 Controller,
347 &gEfiSimpleTextInProtocolGuid,
348 &UsbKeyboardDevice->SimpleInput,
349 &gEfiSimpleTextInputExProtocolGuid,
350 &UsbKeyboardDevice->SimpleInputEx,
351 NULL
352 );
353 goto ErrorExit;
354 }
355
356 //
357 // Reset USB Keyboard Device exhaustively.
358 //
359 Status = UsbKeyboardDevice->SimpleInputEx.Reset (
360 &UsbKeyboardDevice->SimpleInputEx,
361 TRUE
362 );
363 if (EFI_ERROR (Status)) {
364 gBS->UninstallMultipleProtocolInterfaces (
365 Controller,
366 &gEfiSimpleTextInProtocolGuid,
367 &UsbKeyboardDevice->SimpleInput,
368 &gEfiSimpleTextInputExProtocolGuid,
369 &UsbKeyboardDevice->SimpleInputEx,
370 NULL
371 );
372 goto ErrorExit;
373 }
374
375 //
376 // Submit Asynchronous Interrupt Transfer to manage this device.
377 //
378 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;
379 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;
380 PacketSize = (UINT8)(UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
381
382 Status = UsbIo->UsbAsyncInterruptTransfer (
383 UsbIo,
384 EndpointAddr,
385 TRUE,
386 PollingInterval,
387 PacketSize,
389 UsbKeyboardDevice
390 );
391
392 if (EFI_ERROR (Status)) {
393 gBS->UninstallMultipleProtocolInterfaces (
394 Controller,
395 &gEfiSimpleTextInProtocolGuid,
396 &UsbKeyboardDevice->SimpleInput,
397 &gEfiSimpleTextInputExProtocolGuid,
398 &UsbKeyboardDevice->SimpleInputEx,
399 NULL
400 );
401 goto ErrorExit;
402 }
403
404 UsbKeyboardDevice->ControllerNameTable = NULL;
406 "eng",
407 gUsbKeyboardComponentName.SupportedLanguages,
408 &UsbKeyboardDevice->ControllerNameTable,
409 L"Generic Usb Keyboard",
410 TRUE
411 );
413 "en",
414 gUsbKeyboardComponentName2.SupportedLanguages,
415 &UsbKeyboardDevice->ControllerNameTable,
416 L"Generic Usb Keyboard",
417 FALSE
418 );
419
420 gBS->RestoreTPL (OldTpl);
421 return EFI_SUCCESS;
422
423 //
424 // Error handler
425 //
426ErrorExit:
427 if (UsbKeyboardDevice != NULL) {
428 if (UsbKeyboardDevice->TimerEvent != NULL) {
429 gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);
430 }
431
432 if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {
433 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
434 }
435
436 if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {
437 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
438 }
439
440 if (UsbKeyboardDevice->KeyNotifyProcessEvent != NULL) {
441 gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);
442 }
443
444 if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) {
445 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
446 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
447 }
448
449 FreePool (UsbKeyboardDevice);
450 UsbKeyboardDevice = NULL;
451 }
452
453 gBS->CloseProtocol (
454 Controller,
455 &gEfiUsbIoProtocolGuid,
456 This->DriverBindingHandle,
457 Controller
458 );
459
460ErrorExit1:
461 gBS->RestoreTPL (OldTpl);
462
463 return Status;
464}
465
482EFIAPI
485 IN EFI_HANDLE Controller,
486 IN UINTN NumberOfChildren,
487 IN EFI_HANDLE *ChildHandleBuffer
488 )
489{
490 EFI_STATUS Status;
492 USB_KB_DEV *UsbKeyboardDevice;
493
494 Status = gBS->OpenProtocol (
495 Controller,
496 &gEfiSimpleTextInProtocolGuid,
497 (VOID **)&SimpleInput,
498 This->DriverBindingHandle,
499 Controller,
500 EFI_OPEN_PROTOCOL_GET_PROTOCOL
501 );
502 if (EFI_ERROR (Status)) {
503 return EFI_UNSUPPORTED;
504 }
505
506 Status = gBS->OpenProtocol (
507 Controller,
508 &gEfiSimpleTextInputExProtocolGuid,
509 NULL,
510 This->DriverBindingHandle,
511 Controller,
512 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
513 );
514 if (EFI_ERROR (Status)) {
515 return EFI_UNSUPPORTED;
516 }
517
518 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);
519
520 //
521 // The key data input from this device will be disabled.
522 //
525 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE),
526 UsbKeyboardDevice->DevicePath
527 );
528
529 //
530 // Delete the Asynchronous Interrupt Transfer from this device
531 //
532 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (
533 UsbKeyboardDevice->UsbIo,
534 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
535 FALSE,
536 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
537 0,
538 NULL,
539 NULL
540 );
541
542 gBS->CloseProtocol (
543 Controller,
544 &gEfiUsbIoProtocolGuid,
545 This->DriverBindingHandle,
546 Controller
547 );
548
549 Status = gBS->UninstallMultipleProtocolInterfaces (
550 Controller,
551 &gEfiSimpleTextInProtocolGuid,
552 &UsbKeyboardDevice->SimpleInput,
553 &gEfiSimpleTextInputExProtocolGuid,
554 &UsbKeyboardDevice->SimpleInputEx,
555 NULL
556 );
557 //
558 // Free all resources.
559 //
560 gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);
561 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
562 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
563 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
564 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
565 gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);
566 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
567
568 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
569 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
570
571 if (UsbKeyboardDevice->ControllerNameTable != NULL) {
572 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
573 }
574
575 DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);
576 DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);
577 DestroyQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify);
578
579 FreePool (UsbKeyboardDevice);
580
581 return Status;
582}
583
601 IN OUT USB_KB_DEV *UsbKeyboardDevice,
602 OUT EFI_KEY_DATA *KeyData
603 )
604{
605 if (KeyData == NULL) {
606 return EFI_INVALID_PARAMETER;
607 }
608
609 if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {
610 ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
611 InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);
612 return EFI_NOT_READY;
613 }
614
615 Dequeue (&UsbKeyboardDevice->EfiKeyQueue, KeyData, sizeof (*KeyData));
616
617 return EFI_SUCCESS;
618}
619
636EFIAPI
639 IN BOOLEAN ExtendedVerification
640 )
641{
642 EFI_STATUS Status;
643 USB_KB_DEV *UsbKeyboardDevice;
644
645 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
646
649 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET),
650 UsbKeyboardDevice->DevicePath
651 );
652
653 //
654 // Non-exhaustive reset:
655 // only reset private data structures.
656 //
657 if (!ExtendedVerification) {
660 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER),
661 UsbKeyboardDevice->DevicePath
662 );
663 //
664 // Clear the key buffer of this USB keyboard
665 //
666 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));
667 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));
668 InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));
669
670 return EFI_SUCCESS;
671 }
672
673 //
674 // Exhaustive reset
675 //
676 Status = InitUSBKeyboard (UsbKeyboardDevice);
677 if (EFI_ERROR (Status)) {
678 return EFI_DEVICE_ERROR;
679 }
680
681 return EFI_SUCCESS;
682}
683
699EFIAPI
702 OUT EFI_INPUT_KEY *Key
703 )
704{
705 USB_KB_DEV *UsbKeyboardDevice;
706 EFI_STATUS Status;
707 EFI_KEY_DATA KeyData;
708
709 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
710
711 //
712 // Considering if the partial keystroke is enabled, there maybe a partial
713 // keystroke in the queue, so here skip the partial keystroke and get the
714 // next key from the queue
715 //
716 while (1) {
717 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);
718 if (EFI_ERROR (Status)) {
719 return Status;
720 }
721
722 //
723 // SimpleTextIn Protocol doesn't support partial keystroke;
724 //
725 if ((KeyData.Key.ScanCode == CHAR_NULL) && (KeyData.Key.UnicodeChar == SCAN_NULL)) {
726 continue;
727 }
728
729 //
730 // Translate the CTRL-Alpha characters to their corresponding control value
731 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
732 //
733 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
734 if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) {
735 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'a' + 1);
736 } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) {
737 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'A' + 1);
738 }
739 }
740
741 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
742 return EFI_SUCCESS;
743 }
744}
745
754VOID
755EFIAPI
757 IN EFI_EVENT Event,
758 IN VOID *Context
759 )
760{
761 USB_KB_DEV *UsbKeyboardDevice;
762 EFI_KEY_DATA KeyData;
763 EFI_TPL OldTpl;
764
765 UsbKeyboardDevice = (USB_KB_DEV *)Context;
766
767 //
768 // Enter critical section
769 //
770 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
771
772 //
773 // WaitforKey doesn't support the partial key.
774 // Considering if the partial keystroke is enabled, there maybe a partial
775 // keystroke in the queue, so here skip the partial keystroke and get the
776 // next key from the queue
777 //
778 while (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {
779 //
780 // If there is pending key, signal the event.
781 //
782 CopyMem (
783 &KeyData,
784 UsbKeyboardDevice->EfiKeyQueue.Buffer[UsbKeyboardDevice->EfiKeyQueue.Head],
785 sizeof (EFI_KEY_DATA)
786 );
787 if ((KeyData.Key.ScanCode == SCAN_NULL) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {
788 Dequeue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (EFI_KEY_DATA));
789 continue;
790 }
791
792 gBS->SignalEvent (Event);
793 break;
794 }
795
796 //
797 // Leave critical section and return
798 //
799 gBS->RestoreTPL (OldTpl);
800}
801
808VOID
809EFIAPI
811 IN EFI_EVENT Event,
812 IN VOID *Context
813 )
814{
815 EFI_STATUS Status;
816 USB_KB_DEV *UsbKeyboardDevice;
817 UINT8 KeyCode;
818 EFI_KEY_DATA KeyData;
819
820 UsbKeyboardDevice = (USB_KB_DEV *)Context;
821
822 //
823 // Fetch raw data from the USB keyboard buffer,
824 // and translate it into USB keycode.
825 //
826 Status = USBParseKey (UsbKeyboardDevice, &KeyCode);
827 if (EFI_ERROR (Status)) {
828 return;
829 }
830
831 //
832 // Translate saved USB keycode into EFI_INPUT_KEY
833 //
834 Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData);
835 if (EFI_ERROR (Status)) {
836 return;
837 }
838
839 //
840 // Insert to the EFI Key queue
841 //
842 Enqueue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (KeyData));
843}
844
856 IN OUT LIST_ENTRY *NotifyList
857 )
858{
860 LIST_ENTRY *Link;
861
862 if (NotifyList == NULL) {
863 return EFI_INVALID_PARAMETER;
864 }
865
866 while (!IsListEmpty (NotifyList)) {
867 Link = GetFirstNode (NotifyList);
868 NotifyNode = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
869 RemoveEntryList (Link);
870 FreePool (NotifyNode);
871 }
872
873 return EFI_SUCCESS;
874}
875
886BOOLEAN
888 IN EFI_KEY_DATA *RegsiteredData,
889 IN EFI_KEY_DATA *InputData
890 )
891{
892 ASSERT (RegsiteredData != NULL && InputData != NULL);
893
894 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
895 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar))
896 {
897 return FALSE;
898 }
899
900 //
901 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
902 //
903 if ((RegsiteredData->KeyState.KeyShiftState != 0) &&
904 (RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState))
905 {
906 return FALSE;
907 }
908
909 if ((RegsiteredData->KeyState.KeyToggleState != 0) &&
910 (RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState))
911 {
912 return FALSE;
913 }
914
915 return TRUE;
916}
917
918//
919// Simple Text Input Ex protocol functions
920//
921
945EFIAPI
948 IN BOOLEAN ExtendedVerification
949 )
950{
951 EFI_STATUS Status;
952 USB_KB_DEV *UsbKeyboardDevice;
953
954 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
955
956 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);
957 if (EFI_ERROR (Status)) {
958 return EFI_DEVICE_ERROR;
959 }
960
961 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
962 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
963
964 return EFI_SUCCESS;
965}
966
983EFIAPI
986 OUT EFI_KEY_DATA *KeyData
987 )
988{
989 USB_KB_DEV *UsbKeyboardDevice;
990
991 if (KeyData == NULL) {
992 return EFI_INVALID_PARAMETER;
993 }
994
995 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
996
997 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);
998}
999
1015EFIAPI
1018 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
1019 )
1020{
1021 USB_KB_DEV *UsbKeyboardDevice;
1022
1023 if (KeyToggleState == NULL) {
1024 return EFI_INVALID_PARAMETER;
1025 }
1026
1027 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1028
1029 if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
1030 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID))
1031 {
1032 return EFI_UNSUPPORTED;
1033 }
1034
1035 //
1036 // Update the status light
1037 //
1038
1039 UsbKeyboardDevice->ScrollOn = FALSE;
1040 UsbKeyboardDevice->NumLockOn = FALSE;
1041 UsbKeyboardDevice->CapsOn = FALSE;
1042 UsbKeyboardDevice->IsSupportPartialKey = FALSE;
1043
1044 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
1045 UsbKeyboardDevice->ScrollOn = TRUE;
1046 }
1047
1048 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
1049 UsbKeyboardDevice->NumLockOn = TRUE;
1050 }
1051
1052 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
1053 UsbKeyboardDevice->CapsOn = TRUE;
1054 }
1055
1056 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
1057 UsbKeyboardDevice->IsSupportPartialKey = TRUE;
1058 }
1059
1060 SetKeyLED (UsbKeyboardDevice);
1061
1062 UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;
1063
1064 return EFI_SUCCESS;
1065}
1066
1087EFIAPI
1090 IN EFI_KEY_DATA *KeyData,
1091 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
1092 OUT VOID **NotifyHandle
1093 )
1094{
1095 USB_KB_DEV *UsbKeyboardDevice;
1097 LIST_ENTRY *Link;
1098 LIST_ENTRY *NotifyList;
1099 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1100
1101 if ((KeyData == NULL) || (NotifyHandle == NULL) || (KeyNotificationFunction == NULL)) {
1102 return EFI_INVALID_PARAMETER;
1103 }
1104
1105 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1106
1107 //
1108 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1109 //
1110 NotifyList = &UsbKeyboardDevice->NotifyList;
1111
1112 for (Link = GetFirstNode (NotifyList);
1113 !IsNull (NotifyList, Link);
1114 Link = GetNextNode (NotifyList, Link))
1115 {
1116 CurrentNotify = CR (
1117 Link,
1119 NotifyEntry,
1120 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1121 );
1122 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
1123 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
1124 *NotifyHandle = CurrentNotify;
1125 return EFI_SUCCESS;
1126 }
1127 }
1128 }
1129
1130 //
1131 // Allocate resource to save the notification function
1132 //
1134 if (NewNotify == NULL) {
1135 return EFI_OUT_OF_RESOURCES;
1136 }
1137
1138 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
1139 NewNotify->KeyNotificationFn = KeyNotificationFunction;
1140 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
1141 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);
1142
1143 *NotifyHandle = NewNotify;
1144
1145 return EFI_SUCCESS;
1146}
1147
1159EFIAPI
1162 IN VOID *NotificationHandle
1163 )
1164{
1165 USB_KB_DEV *UsbKeyboardDevice;
1166 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1167 LIST_ENTRY *Link;
1168 LIST_ENTRY *NotifyList;
1169
1170 if (NotificationHandle == NULL) {
1171 return EFI_INVALID_PARAMETER;
1172 }
1173
1174 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1175
1176 //
1177 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1178 //
1179 NotifyList = &UsbKeyboardDevice->NotifyList;
1180 for (Link = GetFirstNode (NotifyList);
1181 !IsNull (NotifyList, Link);
1182 Link = GetNextNode (NotifyList, Link))
1183 {
1184 CurrentNotify = CR (
1185 Link,
1187 NotifyEntry,
1188 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1189 );
1190 if (CurrentNotify == NotificationHandle) {
1191 //
1192 // Remove the notification function from NotifyList and free resources
1193 //
1194 RemoveEntryList (&CurrentNotify->NotifyEntry);
1195
1196 FreePool (CurrentNotify);
1197 return EFI_SUCCESS;
1198 }
1199 }
1200
1201 //
1202 // Cannot find the matching entry in database.
1203 //
1204 return EFI_INVALID_PARAMETER;
1205}
1206
1213VOID
1214EFIAPI
1216 IN EFI_EVENT Event,
1217 IN VOID *Context
1218 )
1219{
1220 EFI_STATUS Status;
1221 USB_KB_DEV *UsbKeyboardDevice;
1222 EFI_KEY_DATA KeyData;
1223 LIST_ENTRY *Link;
1224 LIST_ENTRY *NotifyList;
1225 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1226 EFI_TPL OldTpl;
1227
1228 UsbKeyboardDevice = (USB_KB_DEV *)Context;
1229
1230 //
1231 // Invoke notification functions.
1232 //
1233 NotifyList = &UsbKeyboardDevice->NotifyList;
1234 while (TRUE) {
1235 //
1236 // Enter critical section
1237 //
1238 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1239 Status = Dequeue (&UsbKeyboardDevice->EfiKeyQueueForNotify, &KeyData, sizeof (KeyData));
1240 //
1241 // Leave critical section
1242 //
1243 gBS->RestoreTPL (OldTpl);
1244 if (EFI_ERROR (Status)) {
1245 break;
1246 }
1247
1248 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
1249 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
1250 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
1251 CurrentNotify->KeyNotificationFn (&KeyData);
1252 }
1253 }
1254 }
1255}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS USBKeyboardReadKeyStrokeWorker(IN OUT USB_KB_DEV *UsbKeyboardDevice, OUT EFI_KEY_DATA *KeyData)
Definition: EfiKey.c:600
EFI_STATUS EFIAPI USBKeyboardDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: EfiKey.c:72
VOID EFIAPI KeyNotifyProcessHandler(IN EFI_EVENT Event, IN VOID *Context)
Definition: EfiKey.c:1215
EFI_STATUS EFIAPI USBKeyboardUnregisterKeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN VOID *NotificationHandle)
Definition: EfiKey.c:1160
EFI_STATUS EFIAPI USBKeyboardResetEx(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: EfiKey.c:946
EFI_STATUS EFIAPI USBKeyboardRegisterKeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN EFI_KEY_DATA *KeyData, IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, OUT VOID **NotifyHandle)
Definition: EfiKey.c:1088
EFI_STATUS EFIAPI USBKeyboardDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition: EfiKey.c:483
EFI_STATUS EFIAPI USBKeyboardDriverBindingEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: EfiKey.c:39
VOID EFIAPI USBKeyboardWaitForKey(IN EFI_EVENT Event, IN VOID *Context)
Definition: EfiKey.c:756
EFI_STATUS EFIAPI USBKeyboardSetState(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN EFI_KEY_TOGGLE_STATE *KeyToggleState)
Definition: EfiKey.c:1016
VOID EFIAPI USBKeyboardTimerHandler(IN EFI_EVENT Event, IN VOID *Context)
Definition: EfiKey.c:810
EFI_STATUS EFIAPI USBKeyboardDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: EfiKey.c:135
EFI_STATUS KbdFreeNotifyList(IN OUT LIST_ENTRY *NotifyList)
Definition: EfiKey.c:855
EFI_STATUS EFIAPI USBKeyboardReset(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: EfiKey.c:637
EFI_STATUS EFIAPI USBKeyboardReadKeyStrokeEx(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, OUT EFI_KEY_DATA *KeyData)
Definition: EfiKey.c:984
EFI_STATUS EFIAPI USBKeyboardReadKeyStroke(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, OUT EFI_INPUT_KEY *Key)
Definition: EfiKey.c:700
BOOLEAN IsKeyRegistered(IN EFI_KEY_DATA *RegsiteredData, IN EFI_KEY_DATA *InputData)
Definition: EfiKey.c:887
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI KeyboardHandler(IN VOID *Data, IN UINTN DataLength, IN VOID *Context, IN UINT32 Result)
Definition: KeyBoard.c:950
VOID SetKeyLED(IN USB_KB_DEV *UsbKeyboardDevice)
Definition: KeyBoard.c:1859
VOID DestroyQueue(IN OUT USB_SIMPLE_QUEUE *Queue)
Definition: KeyBoard.c:1743
EFI_STATUS InitUSBKeyboard(IN OUT USB_KB_DEV *UsbKeyboardDevice)
Definition: KeyBoard.c:803
VOID ReleaseKeyboardLayoutResources(IN OUT USB_KB_DEV *UsbKeyboardDevice)
Definition: KeyBoard.c:698
EFI_STATUS USBParseKey(IN OUT USB_KB_DEV *UsbKeyboardDevice, OUT UINT8 *KeyCode)
Definition: KeyBoard.c:1250
VOID InitQueue(IN OUT USB_SIMPLE_QUEUE *Queue, IN UINTN ItemSize)
Definition: KeyBoard.c:1714
BOOLEAN IsUSBKeyboard(IN EFI_USB_IO_PROTOCOL *UsbIo)
Definition: KeyBoard.c:367
EFI_STATUS UsbKeyCodeToEfiInputKey(IN USB_KB_DEV *UsbKeyboardDevice, IN UINT8 KeyCode, OUT EFI_KEY_DATA *KeyData)
Definition: KeyBoard.c:1564
EFI_STATUS InitKeyboardLayout(OUT USB_KB_DEV *UsbKeyboardDevice)
Definition: KeyBoard.c:737
BOOLEAN IsQueueEmpty(IN USB_SIMPLE_QUEUE *Queue)
Definition: KeyBoard.c:1760
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
#define REPORT_STATUS_CODE(Type, Value)
#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type, Value, DevicePathParameter)
#define EFI_ERROR_MINOR
Definition: PiStatusCode.h:58
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
#define EFI_P_KEYBOARD_PC_CLEAR_BUFFER
Definition: PiStatusCode.h:392
UINT8 EFI_KEY_TOGGLE_STATE
EFI_STATUS(EFIAPI * EFI_KEY_NOTIFY_FUNCTION)(IN EFI_KEY_DATA *KeyData)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI AddUnicodeString2(IN CONST CHAR8 *Language, IN CONST CHAR8 *SupportedLanguages, IN OUT EFI_UNICODE_STRING_TABLE **UnicodeStringTable, IN CONST CHAR16 *UnicodeString, IN BOOLEAN Iso639Language)
Definition: UefiLib.c:1087
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
EFI_STATUS EFIAPI FreeUnicodeStringTable(IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable)
Definition: UefiLib.c:1257
@ TimerPeriodic
Definition: UefiSpec.h:535
EFI_STATUS Dequeue(IN SIMPLE_QUEUE *Queue, IN EFI_KEY_DATA *KeyData)
EFI_STATUS Enqueue(IN SIMPLE_QUEUE *Queue, IN EFI_KEY_DATA *KeyData)
VOID InitializeKeyState(IN GRAPHICS_PRIVATE_DATA *Private, IN EFI_KEY_STATE *KeyState)
Definition: WinGopInput.c:168
EFI_KEY_TOGGLE_STATE KeyToggleState
UINT32 KeyShiftState
EFI_INPUT_KEY Key
EFI_KEY_STATE KeyState
Definition: EfiKey.h:52