]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
modify coding style to pass ecc tool
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / EfiKey.c
1 /** @file
2
3 USB Keyboard Driver that includes the implementation of interface.
4
5 Copyright (c) 2004 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "EfiKey.h"
17 #include "KeyBoard.h"
18
19 /**
20 The Usb Keyboard Driver Entry Point.
21
22 @param ImageHandle The driver image handle.
23 @param SystemTable The system table.
24
25 @return EFI_SUCCESS The component name protocol is installed.
26 @return Others Failed to install.
27
28 **/
29 EFI_STATUS
30 EFIAPI
31 USBKeyboardDriverBindingEntryPoint (
32 IN EFI_HANDLE ImageHandle,
33 IN EFI_SYSTEM_TABLE *SystemTable
34 );
35
36 /**
37 Check whether USB keyboard driver support this device.
38
39 @param This The USB keyboard driver binding protocol.
40 @param Controller The controller handle to check.
41 @param RemainingDevicePath The remaining device path.
42
43 @retval EFI_SUCCESS The driver supports this controller.
44 @retval EFI_UNSUPPORTED This device isn't supported.
45 **/
46 EFI_STATUS
47 EFIAPI
48 USBKeyboardDriverBindingSupported (
49 IN EFI_DRIVER_BINDING_PROTOCOL *This,
50 IN EFI_HANDLE Controller,
51 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
52 );
53
54 /**
55 Start running driver on the controller.
56
57 @param This The USB keyboard driver binding instance.
58 @param Controller The controller to check.
59 @param RemainingDevicePath The remaining device patch.
60
61 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
62 @return Other The keyboard driver doesn't support this controller.
63
64 **/
65 EFI_STATUS
66 EFIAPI
67 USBKeyboardDriverBindingStart (
68 IN EFI_DRIVER_BINDING_PROTOCOL *This,
69 IN EFI_HANDLE Controller,
70 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
71 );
72
73 /**
74 Stop handle the controller by this USB keyboard driver.
75
76 @param This The USB keyboard driver binding protocol.
77 @param Controller The controller to release.
78 @param NumberOfChildren The number of handles in ChildHandleBuffer.
79 @param ChildHandleBuffer The array of child handle.
80
81 @retval EFI_SUCCESS The controller or children are stopped.
82 @retval EFI_DEVICE_ERROR Failed to stop the driver.
83
84 **/
85 EFI_STATUS
86 EFIAPI
87 USBKeyboardDriverBindingStop (
88 IN EFI_DRIVER_BINDING_PROTOCOL *This,
89 IN EFI_HANDLE Controller,
90 IN UINTN NumberOfChildren,
91 IN EFI_HANDLE *ChildHandleBuffer
92 );
93
94 /**
95 Reset Usb Keyboard.
96
97 @param This The protocol instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
98 @param ExtendedVerification Whether completely reset keyboard or not.
99
100 @retval EFI_SUCCESS Reset keyboard successfully.
101 @retval EFI_DEVICE_ERROR Reset keyboard failed.
102
103 **/
104 EFI_STATUS
105 EFIAPI
106 USBKeyboardReset (
107 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
108 IN BOOLEAN ExtendedVerification
109 );
110
111 /**
112 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.
113
114 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
115 @param Key A pointer to a buffer that is filled in with the keystroke
116 information for the key that was pressed.
117
118 @retval EFI_SUCCESS Read key stroke successfully.
119 @retval Other Read key stroke failed.
120
121 **/
122 EFI_STATUS
123 EFIAPI
124 USBKeyboardReadKeyStroke (
125 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
126 OUT EFI_INPUT_KEY *Key
127 );
128
129 /**
130 Handler function for WaitForKey event.
131
132 @param Event Event to be signaled when a key is pressed.
133 @param Context Points to USB_KB_DEV instance.
134
135 @return None.
136 **/
137 VOID
138 EFIAPI
139 USBKeyboardWaitForKey (
140 IN EFI_EVENT Event,
141 IN VOID *Context
142 );
143
144 /**
145 Check whether there is key pending.
146
147 @param UsbKeyboardDevice The USB_KB_DEV instance.
148
149 @retval EFI_SUCCESS Have key pending to read.
150 @retval Other Parse key failed.
151
152 **/
153 EFI_STATUS
154 EFIAPI
155 USBKeyboardCheckForKey (
156 IN USB_KB_DEV *UsbKeyboardDevice
157 );
158
159 EFI_GUID gEfiUsbKeyboardDriverGuid = {
160 0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}
161 };
162
163 /**
164 Free keyboard notify list.
165
166 @param ListHead The list head.
167
168 @retval EFI_SUCCESS Free the notify list successfully.
169 @retval EFI_INVALID_PARAMETER ListHead is invalid.
170
171 **/
172 EFI_STATUS
173 EFIAPI
174 KbdFreeNotifyList (
175 IN OUT LIST_ENTRY *ListHead
176 );
177
178 /**
179 Whether the pressed key matches a registered key or not.
180
181 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
182 state data for the key that was registered.
183 @param InputData A pointer to a buffer that is filled in with the keystroke
184 state data for the key that was pressed.
185
186 @retval TRUE Key pressed matches a registered key.
187 @retval FLASE Match failed.
188
189 **/
190 BOOLEAN
191 EFIAPI
192 IsKeyRegistered (
193 IN EFI_KEY_DATA *RegsiteredData,
194 IN EFI_KEY_DATA *InputData
195 );
196
197
198 //
199 // USB Keyboard Driver Global Variables
200 //
201 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {
202 USBKeyboardDriverBindingSupported,
203 USBKeyboardDriverBindingStart,
204 USBKeyboardDriverBindingStop,
205 0xa,
206 NULL,
207 NULL
208 };
209
210 /**
211 The Usb Keyboard Driver Entry Point.
212
213 @param ImageHandle The driver image handle.
214 @param SystemTable The system table.
215
216 @return EFI_SUCCESS The component name protocol is installed.
217 @return Others Failed to install.
218
219 **/
220 EFI_STATUS
221 EFIAPI
222 USBKeyboardDriverBindingEntryPoint (
223 IN EFI_HANDLE ImageHandle,
224 IN EFI_SYSTEM_TABLE *SystemTable
225 )
226 {
227 return EfiLibInstallDriverBindingComponentName2 (
228 ImageHandle,
229 SystemTable,
230 &gUsbKeyboardDriverBinding,
231 ImageHandle,
232 &gUsbKeyboardComponentName,
233 &gUsbKeyboardComponentName2
234 );
235 }
236
237 /**
238 Check whether USB keyboard driver support this device.
239
240 @param This The USB keyboard driver binding protocol.
241 @param Controller The controller handle to check.
242 @param RemainingDevicePath The remaining device path.
243
244 @retval EFI_SUCCESS The driver supports this controller.
245 @retval EFI_UNSUPPORTED This device isn't supported.
246 **/
247 EFI_STATUS
248 EFIAPI
249 USBKeyboardDriverBindingSupported (
250 IN EFI_DRIVER_BINDING_PROTOCOL *This,
251 IN EFI_HANDLE Controller,
252 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
253 )
254 {
255 EFI_STATUS OpenStatus;
256 EFI_USB_IO_PROTOCOL *UsbIo;
257 EFI_STATUS Status;
258
259 //
260 // Check if USB_IO protocol is attached on the controller handle.
261 //
262 OpenStatus = gBS->OpenProtocol (
263 Controller,
264 &gEfiUsbIoProtocolGuid,
265 (VOID **) &UsbIo,
266 This->DriverBindingHandle,
267 Controller,
268 EFI_OPEN_PROTOCOL_BY_DRIVER
269 );
270 if (EFI_ERROR (OpenStatus)) {
271 return OpenStatus;
272 }
273
274 //
275 // Use the USB I/O protocol interface to check whether the Controller is
276 // the Keyboard controller that can be managed by this driver.
277 //
278 Status = EFI_SUCCESS;
279
280 if (!IsUSBKeyboard (UsbIo)) {
281 Status = EFI_UNSUPPORTED;
282 }
283
284 gBS->CloseProtocol (
285 Controller,
286 &gEfiUsbIoProtocolGuid,
287 This->DriverBindingHandle,
288 Controller
289 );
290
291 return Status;
292 }
293
294 /**
295 Start running driver on the controller.
296
297 @param This The USB keyboard driver binding instance.
298 @param Controller The controller to check.
299 @param RemainingDevicePath The remaining device patch.
300
301 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
302 @return Other The keyboard driver doesn't support this controller.
303
304 **/
305 EFI_STATUS
306 EFIAPI
307 USBKeyboardDriverBindingStart (
308 IN EFI_DRIVER_BINDING_PROTOCOL *This,
309 IN EFI_HANDLE Controller,
310 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
311 )
312 {
313 EFI_STATUS Status;
314 EFI_USB_IO_PROTOCOL *UsbIo;
315 USB_KB_DEV *UsbKeyboardDevice;
316 UINT8 EndpointNumber;
317 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
318 UINT8 Index;
319 UINT8 EndpointAddr;
320 UINT8 PollingInterval;
321 UINT8 PacketSize;
322 BOOLEAN Found;
323
324 UsbKeyboardDevice = NULL;
325 Found = FALSE;
326
327 //
328 // Open USB_IO Protocol
329 //
330 Status = gBS->OpenProtocol (
331 Controller,
332 &gEfiUsbIoProtocolGuid,
333 (VOID **) &UsbIo,
334 This->DriverBindingHandle,
335 Controller,
336 EFI_OPEN_PROTOCOL_BY_DRIVER
337 );
338 if (EFI_ERROR (Status)) {
339 return Status;
340 }
341
342 UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));
343 if (UsbKeyboardDevice == NULL) {
344 gBS->CloseProtocol (
345 Controller,
346 &gEfiUsbIoProtocolGuid,
347 This->DriverBindingHandle,
348 Controller
349 );
350 return EFI_OUT_OF_RESOURCES;
351 }
352 //
353 // Get the Device Path Protocol on Controller's handle
354 //
355 Status = gBS->OpenProtocol (
356 Controller,
357 &gEfiDevicePathProtocolGuid,
358 (VOID **) &UsbKeyboardDevice->DevicePath,
359 This->DriverBindingHandle,
360 Controller,
361 EFI_OPEN_PROTOCOL_GET_PROTOCOL
362 );
363
364 if (EFI_ERROR (Status)) {
365 gBS->FreePool (UsbKeyboardDevice);
366 gBS->CloseProtocol (
367 Controller,
368 &gEfiUsbIoProtocolGuid,
369 This->DriverBindingHandle,
370 Controller
371 );
372 return Status;
373 }
374 //
375 // Report that the usb keyboard is being enabled
376 //
377 KbdReportStatusCode (
378 UsbKeyboardDevice->DevicePath,
379 EFI_PROGRESS_CODE,
380 PcdGet32 (PcdStatusCodeValueKeyboardEnable)
381 );
382
383 //
384 // This is pretty close to keyboard detection, so log progress
385 //
386 KbdReportStatusCode (
387 UsbKeyboardDevice->DevicePath,
388 EFI_PROGRESS_CODE,
389 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect)
390 );
391
392 //
393 // Initialize UsbKeyboardDevice
394 //
395 UsbKeyboardDevice->UsbIo = UsbIo;
396
397 //
398 // Get interface & endpoint descriptor
399 //
400 UsbIo->UsbGetInterfaceDescriptor (
401 UsbIo,
402 &UsbKeyboardDevice->InterfaceDescriptor
403 );
404
405 EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
406
407 for (Index = 0; Index < EndpointNumber; Index++) {
408
409 UsbIo->UsbGetEndpointDescriptor (
410 UsbIo,
411 Index,
412 &EndpointDescriptor
413 );
414
415 if ((EndpointDescriptor.Attributes & 0x03) == 0x03) {
416 //
417 // We only care interrupt endpoint here
418 //
419 CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
420 Found = TRUE;
421 }
422 }
423
424 if (!Found) {
425 //
426 // No interrupt endpoint found, then return unsupported.
427 //
428 gBS->FreePool (UsbKeyboardDevice);
429 gBS->CloseProtocol (
430 Controller,
431 &gEfiUsbIoProtocolGuid,
432 This->DriverBindingHandle,
433 Controller
434 );
435 return EFI_UNSUPPORTED;
436 }
437
438 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
439 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
440 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
441
442 UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;
443 UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;
444 UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;
445 UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;
446 UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;
447
448 InitializeListHead (&UsbKeyboardDevice->NotifyList);
449
450 Status = gBS->CreateEvent (
451 EVT_NOTIFY_WAIT,
452 TPL_NOTIFY,
453 USBKeyboardWaitForKey,
454 UsbKeyboardDevice,
455 &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)
456 );
457
458 if (EFI_ERROR (Status)) {
459 goto ErrorExit;
460 }
461
462 Status = InitKeyboardLayout (UsbKeyboardDevice);
463 if (EFI_ERROR (Status)) {
464 goto ErrorExit;
465 }
466
467 Status = gBS->CreateEvent (
468 EVT_NOTIFY_WAIT,
469 TPL_NOTIFY,
470 USBKeyboardWaitForKey,
471 UsbKeyboardDevice,
472 &(UsbKeyboardDevice->SimpleInput.WaitForKey)
473 );
474
475 if (EFI_ERROR (Status)) {
476 gBS->FreePool (UsbKeyboardDevice);
477 gBS->CloseProtocol (
478 Controller,
479 &gEfiUsbIoProtocolGuid,
480 This->DriverBindingHandle,
481 Controller
482 );
483 return Status;
484 }
485
486 //
487 // Install simple txt in protocol interface
488 // for the usb keyboard device.
489 // Usb keyboard is a hot plug device, and expected to work immediately
490 // when plugging into system, so a HotPlugDeviceGuid is installed onto
491 // the usb keyboard device handle, to distinguish it from other conventional
492 // console devices.
493 //
494 Status = gBS->InstallMultipleProtocolInterfaces (
495 &Controller,
496 &gEfiSimpleTextInProtocolGuid,
497 &UsbKeyboardDevice->SimpleInput,
498 &gEfiSimpleTextInputExProtocolGuid,
499 &UsbKeyboardDevice->SimpleInputEx,
500 &gEfiHotPlugDeviceGuid,
501 NULL,
502 NULL
503 );
504 if (EFI_ERROR (Status)) {
505 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
506 gBS->FreePool (UsbKeyboardDevice);
507 gBS->CloseProtocol (
508 Controller,
509 &gEfiUsbIoProtocolGuid,
510 This->DriverBindingHandle,
511 Controller
512 );
513 return Status;
514 }
515
516 //
517 // Reset USB Keyboard Device
518 //
519 Status = UsbKeyboardDevice->SimpleInput.Reset (
520 &UsbKeyboardDevice->SimpleInput,
521 TRUE
522 );
523 if (EFI_ERROR (Status)) {
524 gBS->UninstallMultipleProtocolInterfaces (
525 Controller,
526 &gEfiSimpleTextInProtocolGuid,
527 &UsbKeyboardDevice->SimpleInput,
528 &gEfiSimpleTextInputExProtocolGuid,
529 &UsbKeyboardDevice->SimpleInputEx,
530 &gEfiHotPlugDeviceGuid,
531 NULL,
532 NULL
533 );
534 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
535 gBS->FreePool (UsbKeyboardDevice);
536 gBS->CloseProtocol (
537 Controller,
538 &gEfiUsbIoProtocolGuid,
539 This->DriverBindingHandle,
540 Controller
541 );
542 return Status;
543 }
544 //
545 // submit async interrupt transfer
546 //
547 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;
548 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;
549 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
550
551 Status = UsbIo->UsbAsyncInterruptTransfer (
552 UsbIo,
553 EndpointAddr,
554 TRUE,
555 PollingInterval,
556 PacketSize,
557 KeyboardHandler,
558 UsbKeyboardDevice
559 );
560
561 if (EFI_ERROR (Status)) {
562
563 gBS->UninstallMultipleProtocolInterfaces (
564 Controller,
565 &gEfiSimpleTextInProtocolGuid,
566 &UsbKeyboardDevice->SimpleInput,
567 &gEfiSimpleTextInputExProtocolGuid,
568 &UsbKeyboardDevice->SimpleInputEx,
569 &gEfiHotPlugDeviceGuid,
570 NULL,
571 NULL
572 );
573 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
574 gBS->FreePool (UsbKeyboardDevice);
575 gBS->CloseProtocol (
576 Controller,
577 &gEfiUsbIoProtocolGuid,
578 This->DriverBindingHandle,
579 Controller
580 );
581 return Status;
582 }
583
584 UsbKeyboardDevice->ControllerNameTable = NULL;
585 AddUnicodeString2 (
586 "eng",
587 gUsbKeyboardComponentName.SupportedLanguages,
588 &UsbKeyboardDevice->ControllerNameTable,
589 L"Generic Usb Keyboard",
590 TRUE
591 );
592 AddUnicodeString2 (
593 "en",
594 gUsbKeyboardComponentName2.SupportedLanguages,
595 &UsbKeyboardDevice->ControllerNameTable,
596 L"Generic Usb Keyboard",
597 FALSE
598 );
599
600
601 return EFI_SUCCESS;
602
603 ErrorExit:
604 if (UsbKeyboardDevice != NULL) {
605 if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {
606 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
607 }
608 if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {
609 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
610 }
611 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
612 gBS->FreePool (UsbKeyboardDevice);
613 UsbKeyboardDevice = NULL;
614 }
615 gBS->CloseProtocol (
616 Controller,
617 &gEfiUsbIoProtocolGuid,
618 This->DriverBindingHandle,
619 Controller
620 );
621 return Status;
622
623 }
624
625
626 /**
627 Stop handle the controller by this USB keyboard driver.
628
629 @param This The USB keyboard driver binding protocol.
630 @param Controller The controller to release.
631 @param NumberOfChildren The number of handles in ChildHandleBuffer.
632 @param ChildHandleBuffer The array of child handle.
633
634 @retval EFI_SUCCESS The controller or children are stopped.
635 @retval EFI_DEVICE_ERROR Failed to stop the driver.
636
637 **/
638 EFI_STATUS
639 EFIAPI
640 USBKeyboardDriverBindingStop (
641 IN EFI_DRIVER_BINDING_PROTOCOL *This,
642 IN EFI_HANDLE Controller,
643 IN UINTN NumberOfChildren,
644 IN EFI_HANDLE *ChildHandleBuffer
645 )
646 {
647 EFI_STATUS Status;
648 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;
649 USB_KB_DEV *UsbKeyboardDevice;
650
651 Status = gBS->OpenProtocol (
652 Controller,
653 &gEfiSimpleTextInProtocolGuid,
654 (VOID **) &SimpleInput,
655 This->DriverBindingHandle,
656 Controller,
657 EFI_OPEN_PROTOCOL_GET_PROTOCOL
658 );
659 if (EFI_ERROR (Status)) {
660 return EFI_UNSUPPORTED;
661 }
662 Status = gBS->OpenProtocol (
663 Controller,
664 &gEfiSimpleTextInputExProtocolGuid,
665 NULL,
666 This->DriverBindingHandle,
667 Controller,
668 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
669 );
670 if (EFI_ERROR (Status)) {
671 return EFI_UNSUPPORTED;
672 }
673 //
674 // Get USB_KB_DEV instance.
675 //
676 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);
677
678 gBS->CloseProtocol (
679 Controller,
680 &gEfiSimpleTextInProtocolGuid,
681 This->DriverBindingHandle,
682 Controller
683 );
684
685 //
686 // Uninstall the Asyn Interrupt Transfer from this device
687 // will disable the key data input from this device
688 //
689 KbdReportStatusCode (
690 UsbKeyboardDevice->DevicePath,
691 EFI_PROGRESS_CODE,
692 PcdGet32 (PcdStatusCodeValueKeyboardDisable)
693 );
694
695 //
696 // Destroy asynchronous interrupt transfer
697 //
698 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (
699 UsbKeyboardDevice->UsbIo,
700 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
701 FALSE,
702 UsbKeyboardDevice->IntEndpointDescriptor.Interval,
703 0,
704 NULL,
705 NULL
706 );
707
708 gBS->CloseProtocol (
709 Controller,
710 &gEfiUsbIoProtocolGuid,
711 This->DriverBindingHandle,
712 Controller
713 );
714
715 Status = gBS->UninstallMultipleProtocolInterfaces (
716 Controller,
717 &gEfiSimpleTextInProtocolGuid,
718 &UsbKeyboardDevice->SimpleInput,
719 &gEfiSimpleTextInputExProtocolGuid,
720 &UsbKeyboardDevice->SimpleInputEx,
721 &gEfiHotPlugDeviceGuid,
722 NULL,
723 NULL
724 );
725 //
726 // free all the resources.
727 //
728 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
729 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
730 gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);
731 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);
732 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);
733
734 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);
735 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);
736
737 if (UsbKeyboardDevice->ControllerNameTable != NULL) {
738 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
739 }
740
741 gBS->FreePool (UsbKeyboardDevice);
742
743 return Status;
744
745 }
746
747 /**
748 Reads the next keystroke from the input device. The WaitForKey Event can
749 be used to test for existance of a keystroke via WaitForEvent () call.
750
751 @param UsbKeyboardDevice Usb keyboard's private structure.
752 @param KeyData A pointer to a buffer that is filled in with the keystroke
753 state data for the key that was pressed.
754
755 @return EFI_SUCCESS The keystroke information was returned.
756 @return EFI_NOT_READY There was no keystroke data availiable.
757 @return EFI_DEVICE_ERROR The keystroke information was not returned due to
758 hardware errors.
759 @return EFI_INVALID_PARAMETER KeyData is NULL.
760
761 **/
762 EFI_STATUS
763 EFIAPI
764 USBKeyboardReadKeyStrokeWorker (
765 IN USB_KB_DEV *UsbKeyboardDevice,
766 OUT EFI_KEY_DATA *KeyData
767 )
768 {
769
770 EFI_STATUS Status;
771 UINT8 KeyChar;
772 LIST_ENTRY *Link;
773 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
774 EFI_KEY_DATA OriginalKeyData;
775
776 if (KeyData == NULL) {
777 return EFI_INVALID_PARAMETER;
778 }
779
780 //
781 // if there is no saved ASCII byte, fetch it
782 // by calling USBKeyboardCheckForKey().
783 //
784 if (UsbKeyboardDevice->CurKeyChar == 0) {
785 Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
786 if (EFI_ERROR (Status)) {
787 return Status;
788 }
789 }
790
791 KeyData->Key.UnicodeChar = 0;
792 KeyData->Key.ScanCode = SCAN_NULL;
793
794 KeyChar = UsbKeyboardDevice->CurKeyChar;
795
796 UsbKeyboardDevice->CurKeyChar = 0;
797
798 //
799 // Translate saved ASCII byte into EFI_INPUT_KEY
800 //
801 Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);
802 if (EFI_ERROR (Status)) {
803 return Status;
804 }
805
806 CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));
807
808 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
809 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
810
811 //
812 //Switch the control value to their original characters. In USBKeyCodeToEFIScanCode() the CTRL-Alpha characters have been switched to
813 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.
814 //
815 CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));
816 if (UsbKeyboardDevice->CtrlOn != 0) {
817 if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {
818 if (UsbKeyboardDevice->CapsOn != 0) {
819 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);
820 } else {
821 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);
822 }
823 }
824 }
825
826 //
827 // Invoke notification functions if exist
828 //
829 for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
830 CurrentNotify = CR (
831 Link,
832 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
833 NotifyEntry,
834 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
835 );
836 if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) {
837 CurrentNotify->KeyNotificationFn (&OriginalKeyData);
838 }
839 }
840
841 return EFI_SUCCESS;
842
843 }
844
845 /**
846 Reset Usb Keyboard.
847
848 @param This The protocol instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
849 @param ExtendedVerification Whether completely reset keyboard or not.
850
851 @retval EFI_SUCCESS Reset keyboard successfully.
852 @retval EFI_DEVICE_ERROR Reset keyboard failed.
853
854 **/
855 EFI_STATUS
856 EFIAPI
857 USBKeyboardReset (
858 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
859 IN BOOLEAN ExtendedVerification
860 )
861 {
862 EFI_STATUS Status;
863 USB_KB_DEV *UsbKeyboardDevice;
864
865 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
866
867 KbdReportStatusCode (
868 UsbKeyboardDevice->DevicePath,
869 EFI_PROGRESS_CODE,
870 PcdGet32 (PcdStatusCodeValueKeyboardReset)
871 );
872
873 //
874 // Non Exhaustive reset:
875 // only reset private data structures.
876 //
877 if (!ExtendedVerification) {
878 //
879 // Clear the key buffer of this Usb keyboard
880 //
881 KbdReportStatusCode (
882 UsbKeyboardDevice->DevicePath,
883 EFI_PROGRESS_CODE,
884 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer)
885 );
886
887 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
888 UsbKeyboardDevice->CurKeyChar = 0;
889 return EFI_SUCCESS;
890 }
891
892 //
893 // Exhaustive reset
894 //
895 Status = InitUSBKeyboard (UsbKeyboardDevice);
896 UsbKeyboardDevice->CurKeyChar = 0;
897 if (EFI_ERROR (Status)) {
898 return EFI_DEVICE_ERROR;
899 }
900
901 return EFI_SUCCESS;
902 }
903
904
905 /**
906 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.
907
908 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
909 @param Key A pointer to a buffer that is filled in with the keystroke
910 information for the key that was pressed.
911
912 @retval EFI_SUCCESS Read key stroke successfully.
913 @retval Other Read key stroke failed.
914
915 **/
916 EFI_STATUS
917 EFIAPI
918 USBKeyboardReadKeyStroke (
919 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
920 OUT EFI_INPUT_KEY *Key
921 )
922 {
923 USB_KB_DEV *UsbKeyboardDevice;
924 EFI_STATUS Status;
925 EFI_KEY_DATA KeyData;
926
927 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
928
929 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);
930 if (EFI_ERROR (Status)) {
931 return Status;
932 }
933
934 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
935
936 return EFI_SUCCESS;
937
938 }
939
940
941 /**
942 Handler function for WaitForKey event.
943
944 @param Event Event to be signaled when a key is pressed.
945 @param Context Points to USB_KB_DEV instance.
946
947 @return None.
948 **/
949 VOID
950 EFIAPI
951 USBKeyboardWaitForKey (
952 IN EFI_EVENT Event,
953 IN VOID *Context
954 )
955 {
956 USB_KB_DEV *UsbKeyboardDevice;
957
958 UsbKeyboardDevice = (USB_KB_DEV *) Context;
959
960 if (UsbKeyboardDevice->CurKeyChar == 0) {
961
962 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {
963 return ;
964 }
965 }
966 //
967 // If has key pending, signal the event.
968 //
969 gBS->SignalEvent (Event);
970 }
971
972
973 /**
974 Check whether there is key pending.
975
976 @param UsbKeyboardDevice The USB_KB_DEV instance.
977
978 @retval EFI_SUCCESS Have key pending to read.
979 @retval Other Parse key failed.
980
981 **/
982 EFI_STATUS
983 EFIAPI
984 USBKeyboardCheckForKey (
985 IN USB_KB_DEV *UsbKeyboardDevice
986 )
987 {
988 EFI_STATUS Status;
989 UINT8 KeyChar;
990
991 //
992 // Fetch raw data from the USB keyboard input,
993 // and translate it into ASCII data.
994 //
995 Status = USBParseKey (UsbKeyboardDevice, &KeyChar);
996 if (EFI_ERROR (Status)) {
997 return Status;
998 }
999
1000 UsbKeyboardDevice->CurKeyChar = KeyChar;
1001 return EFI_SUCCESS;
1002 }
1003
1004 /**
1005 Report Status Code in Usb Keyboard Driver.
1006
1007 @param DevicePath Use this to get Device Path.
1008 @param CodeType Status Code Type.
1009 @param CodeValue Status Code Value.
1010
1011 @return None.
1012
1013 **/
1014 VOID
1015 EFIAPI
1016 KbdReportStatusCode (
1017 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1018 IN EFI_STATUS_CODE_TYPE CodeType,
1019 IN EFI_STATUS_CODE_VALUE Value
1020 )
1021 {
1022
1023 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1024 CodeType,
1025 Value,
1026 DevicePath
1027 );
1028 }
1029
1030 /**
1031 Free keyboard notify list.
1032
1033 @param ListHead The list head.
1034
1035 @retval EFI_SUCCESS Free the notify list successfully.
1036 @retval EFI_INVALID_PARAMETER ListHead is invalid.
1037
1038 **/
1039 EFI_STATUS
1040 EFIAPI
1041 KbdFreeNotifyList (
1042 IN OUT LIST_ENTRY *ListHead
1043 )
1044 {
1045 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
1046
1047 if (ListHead == NULL) {
1048 return EFI_INVALID_PARAMETER;
1049 }
1050 while (!IsListEmpty (ListHead)) {
1051 NotifyNode = CR (
1052 ListHead->ForwardLink,
1053 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
1054 NotifyEntry,
1055 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1056 );
1057 RemoveEntryList (ListHead->ForwardLink);
1058 gBS->FreePool (NotifyNode);
1059 }
1060
1061 return EFI_SUCCESS;
1062 }
1063
1064 /**
1065 Whether the pressed key matches a registered key or not.
1066
1067 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
1068 state data for the key that was registered.
1069 @param InputData A pointer to a buffer that is filled in with the keystroke
1070 state data for the key that was pressed.
1071
1072 @retval TRUE Key pressed matches a registered key.
1073 @retval FLASE Match failed.
1074
1075 **/
1076 BOOLEAN
1077 EFIAPI
1078 IsKeyRegistered (
1079 IN EFI_KEY_DATA *RegsiteredData,
1080 IN EFI_KEY_DATA *InputData
1081 )
1082 {
1083 ASSERT (RegsiteredData != NULL && InputData != NULL);
1084
1085 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
1086 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
1087 return FALSE;
1088 }
1089
1090 //
1091 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
1092 //
1093 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
1094 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
1095 return FALSE;
1096 }
1097 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
1098 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
1099 return FALSE;
1100 }
1101
1102 return TRUE;
1103
1104 }
1105
1106 //
1107 // Simple Text Input Ex protocol functions
1108 //
1109 /**
1110 The extension routine to reset the input device.
1111
1112 @param This Protocol instance pointer.
1113 @param ExtendedVerification Driver may perform diagnostics on reset.
1114
1115 @retval EFI_SUCCESS The device was reset.
1116 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
1117 not be reset.
1118
1119 **/
1120 EFI_STATUS
1121 EFIAPI
1122 USBKeyboardResetEx (
1123 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1124 IN BOOLEAN ExtendedVerification
1125 )
1126 {
1127 EFI_STATUS Status;
1128 USB_KB_DEV *UsbKeyboardDevice;
1129 EFI_TPL OldTpl;
1130
1131
1132 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1133
1134 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);
1135 if (EFI_ERROR (Status)) {
1136 return EFI_DEVICE_ERROR;
1137 }
1138
1139 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1140 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
1141 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
1142 gBS->RestoreTPL (OldTpl);
1143
1144 return EFI_SUCCESS;
1145
1146 }
1147
1148 /**
1149 Reads the next keystroke from the input device. The WaitForKey Event can
1150 be used to test for existance of a keystroke via WaitForEvent () call.
1151
1152 @param This Protocol instance pointer.
1153 @param KeyData A pointer to a buffer that is filled in with the keystroke
1154 state data for the key that was pressed.
1155
1156 @return EFI_SUCCESS The keystroke information was returned successfully.
1157 @retval EFI_INVALID_PARAMETER KeyData is NULL.
1158 @retval Other Read key stroke information failed.
1159
1160 **/
1161 EFI_STATUS
1162 EFIAPI
1163 USBKeyboardReadKeyStrokeEx (
1164 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1165 OUT EFI_KEY_DATA *KeyData
1166 )
1167 {
1168 USB_KB_DEV *UsbKeyboardDevice;
1169
1170 if (KeyData == NULL) {
1171 return EFI_INVALID_PARAMETER;
1172 }
1173
1174 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1175
1176 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);
1177
1178 }
1179
1180 /**
1181 Set certain state for the input device.
1182
1183 @param This Protocol instance pointer.
1184 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
1185 state for the input device.
1186
1187 @retval EFI_SUCCESS The device state was set successfully.
1188 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
1189 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
1190
1191 **/
1192 EFI_STATUS
1193 EFIAPI
1194 USBKeyboardSetState (
1195 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1196 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
1197 )
1198 {
1199 USB_KB_DEV *UsbKeyboardDevice;
1200
1201 if (KeyToggleState == NULL) {
1202 return EFI_INVALID_PARAMETER;
1203 }
1204
1205 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1206
1207 if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
1208 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {
1209 return EFI_UNSUPPORTED;
1210 }
1211
1212 //
1213 // Update the status light
1214 //
1215
1216 UsbKeyboardDevice->ScrollOn = 0;
1217 UsbKeyboardDevice->NumLockOn = 0;
1218 UsbKeyboardDevice->CapsOn = 0;
1219
1220 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
1221 UsbKeyboardDevice->ScrollOn = 1;
1222 }
1223 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
1224 UsbKeyboardDevice->NumLockOn = 1;
1225 }
1226 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
1227 UsbKeyboardDevice->CapsOn = 1;
1228 }
1229
1230 SetKeyLED (UsbKeyboardDevice);
1231
1232 UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;
1233
1234 return EFI_SUCCESS;
1235
1236 }
1237
1238 /**
1239 Register a notification function for a particular keystroke for the input device.
1240
1241 @param This Protocol instance pointer.
1242 @param KeyData A pointer to a buffer that is filled in with the keystroke
1243 information data for the key that was pressed.
1244 @param KeyNotificationFunction Points to the function to be called when the key
1245 sequence is typed specified by KeyData.
1246 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1247
1248 @retval EFI_SUCCESS The notification function was registered successfully.
1249 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
1250 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
1251
1252 **/
1253 EFI_STATUS
1254 EFIAPI
1255 USBKeyboardRegisterKeyNotify (
1256 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1257 IN EFI_KEY_DATA *KeyData,
1258 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
1259 OUT EFI_HANDLE *NotifyHandle
1260 )
1261 {
1262 USB_KB_DEV *UsbKeyboardDevice;
1263 EFI_STATUS Status;
1264 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
1265 LIST_ENTRY *Link;
1266 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1267
1268 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
1269 return EFI_INVALID_PARAMETER;
1270 }
1271
1272 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1273
1274 //
1275 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1276 //
1277 for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
1278 CurrentNotify = CR (
1279 Link,
1280 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
1281 NotifyEntry,
1282 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1283 );
1284 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
1285 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
1286 *NotifyHandle = CurrentNotify->NotifyHandle;
1287 return EFI_SUCCESS;
1288 }
1289 }
1290 }
1291
1292 //
1293 // Allocate resource to save the notification function
1294 //
1295 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
1296 if (NewNotify == NULL) {
1297 return EFI_OUT_OF_RESOURCES;
1298 }
1299
1300 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
1301 NewNotify->KeyNotificationFn = KeyNotificationFunction;
1302 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
1303 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);
1304
1305 //
1306 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
1307 //
1308 Status = gBS->InstallMultipleProtocolInterfaces (
1309 &NewNotify->NotifyHandle,
1310 &gSimpleTextInExNotifyGuid,
1311 NULL,
1312 NULL
1313 );
1314 ASSERT_EFI_ERROR (Status);
1315
1316 *NotifyHandle = NewNotify->NotifyHandle;
1317
1318 return EFI_SUCCESS;
1319
1320 }
1321
1322 /**
1323 Remove a registered notification function from a particular keystroke.
1324
1325 @param This Protocol instance pointer.
1326 @param NotificationHandle The handle of the notification function being unregistered.
1327
1328 @retval EFI_SUCCESS The notification function was unregistered successfully.
1329 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid or opening gSimpleTextInExNotifyGuid
1330 on NotificationHandle fails.
1331 @retval EFI_NOT_FOUND Can not find the matching entry in database.
1332
1333 **/
1334 EFI_STATUS
1335 EFIAPI
1336 USBKeyboardUnregisterKeyNotify (
1337 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
1338 IN EFI_HANDLE NotificationHandle
1339 )
1340 {
1341 USB_KB_DEV *UsbKeyboardDevice;
1342 EFI_STATUS Status;
1343 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1344 LIST_ENTRY *Link;
1345
1346 if (NotificationHandle == NULL) {
1347 return EFI_INVALID_PARAMETER;
1348 }
1349
1350 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);
1351
1352 Status = gBS->OpenProtocol (
1353 NotificationHandle,
1354 &gSimpleTextInExNotifyGuid,
1355 NULL,
1356 NULL,
1357 NULL,
1358 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1359 );
1360 if (EFI_ERROR (Status)) {
1361 return EFI_INVALID_PARAMETER;
1362 }
1363
1364 for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {
1365 CurrentNotify = CR (
1366 Link,
1367 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
1368 NotifyEntry,
1369 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1370 );
1371 if (CurrentNotify->NotifyHandle == NotificationHandle) {
1372 //
1373 // Remove the notification function from NotifyList and free resources
1374 //
1375 RemoveEntryList (&CurrentNotify->NotifyEntry);
1376 Status = gBS->UninstallMultipleProtocolInterfaces (
1377 CurrentNotify->NotifyHandle,
1378 &gSimpleTextInExNotifyGuid,
1379 NULL,
1380 NULL
1381 );
1382 ASSERT_EFI_ERROR (Status);
1383 gBS->FreePool (CurrentNotify);
1384 return EFI_SUCCESS;
1385 }
1386 }
1387
1388 return EFI_NOT_FOUND;
1389 }
1390