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