]> 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
813acf3a 3Copyright (c) 2004 - 2008, Intel Corporation\r
ed838d0c 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
813acf3a 385 Status = InitKeyboardLayout (UsbKeyboardDevice);\r
386 if (EFI_ERROR (Status)) {\r
387 goto ErrorExit;\r
388 }\r
389\r
ed838d0c 390 Status = gBS->CreateEvent (\r
391 EVT_NOTIFY_WAIT,\r
392 TPL_NOTIFY,\r
393 USBKeyboardWaitForKey,\r
394 UsbKeyboardDevice,\r
395 &(UsbKeyboardDevice->SimpleInput.WaitForKey)\r
396 );\r
397\r
398 if (EFI_ERROR (Status)) {\r
399 gBS->FreePool (UsbKeyboardDevice);\r
400 gBS->CloseProtocol (\r
401 Controller,\r
402 &gEfiUsbIoProtocolGuid,\r
403 This->DriverBindingHandle,\r
404 Controller\r
405 );\r
406 return Status;\r
407 }\r
408\r
409 //\r
410 // Install simple txt in protocol interface\r
411 // for the usb keyboard device.\r
412 // Usb keyboard is a hot plug device, and expected to work immediately\r
413 // when plugging into system, so a HotPlugDeviceGuid is installed onto\r
414 // the usb keyboard device handle, to distinguish it from other conventional\r
415 // console devices.\r
416 //\r
417 Status = gBS->InstallMultipleProtocolInterfaces (\r
418 &Controller,\r
419 &gEfiSimpleTextInProtocolGuid,\r
420 &UsbKeyboardDevice->SimpleInput,\r
66aa04e4 421 &gEfiSimpleTextInputExProtocolGuid,\r
422 &UsbKeyboardDevice->SimpleInputEx,\r
ed838d0c 423 &gEfiHotPlugDeviceGuid,\r
424 NULL,\r
425 NULL\r
426 );\r
427 if (EFI_ERROR (Status)) {\r
428 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
429 gBS->FreePool (UsbKeyboardDevice);\r
430 gBS->CloseProtocol (\r
431 Controller,\r
432 &gEfiUsbIoProtocolGuid,\r
433 This->DriverBindingHandle,\r
434 Controller\r
435 );\r
436 return Status;\r
437 }\r
438\r
439 //\r
440 // Reset USB Keyboard Device\r
441 //\r
442 Status = UsbKeyboardDevice->SimpleInput.Reset (\r
443 &UsbKeyboardDevice->SimpleInput,\r
444 TRUE\r
445 );\r
446 if (EFI_ERROR (Status)) {\r
447 gBS->UninstallMultipleProtocolInterfaces (\r
66aa04e4 448 Controller,\r
449 &gEfiSimpleTextInProtocolGuid,\r
450 &UsbKeyboardDevice->SimpleInput,\r
451 &gEfiSimpleTextInputExProtocolGuid,\r
452 &UsbKeyboardDevice->SimpleInputEx,\r
453 &gEfiHotPlugDeviceGuid,\r
454 NULL,\r
455 NULL\r
456 );\r
ed838d0c 457 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
458 gBS->FreePool (UsbKeyboardDevice);\r
459 gBS->CloseProtocol (\r
460 Controller,\r
461 &gEfiUsbIoProtocolGuid,\r
462 This->DriverBindingHandle,\r
463 Controller\r
464 );\r
465 return Status;\r
466 }\r
467 //\r
468 // submit async interrupt transfer\r
469 //\r
470 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;\r
471 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;\r
472 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
473\r
474 Status = UsbIo->UsbAsyncInterruptTransfer (\r
475 UsbIo,\r
476 EndpointAddr,\r
477 TRUE,\r
478 PollingInterval,\r
479 PacketSize,\r
480 KeyboardHandler,\r
481 UsbKeyboardDevice\r
482 );\r
483\r
484 if (EFI_ERROR (Status)) {\r
485\r
486 gBS->UninstallMultipleProtocolInterfaces (\r
66aa04e4 487 Controller,\r
488 &gEfiSimpleTextInProtocolGuid,\r
489 &UsbKeyboardDevice->SimpleInput,\r
490 &gEfiSimpleTextInputExProtocolGuid,\r
491 &UsbKeyboardDevice->SimpleInputEx,\r
492 &gEfiHotPlugDeviceGuid,\r
493 NULL,\r
494 NULL\r
495 );\r
ed838d0c 496 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
497 gBS->FreePool (UsbKeyboardDevice);\r
498 gBS->CloseProtocol (\r
499 Controller,\r
500 &gEfiUsbIoProtocolGuid,\r
501 This->DriverBindingHandle,\r
502 Controller\r
503 );\r
504 return Status;\r
505 }\r
506\r
507 UsbKeyboardDevice->ControllerNameTable = NULL;\r
62b9bb55 508 AddUnicodeString2 (\r
ed838d0c 509 "eng",\r
510 gUsbKeyboardComponentName.SupportedLanguages,\r
511 &UsbKeyboardDevice->ControllerNameTable,\r
62b9bb55 512 L"Generic Usb Keyboard",\r
513 TRUE\r
ed838d0c 514 );\r
62b9bb55 515 AddUnicodeString2 (\r
516 "en",\r
517 gUsbKeyboardComponentName2.SupportedLanguages,\r
518 &UsbKeyboardDevice->ControllerNameTable,\r
519 L"Generic Usb Keyboard",\r
520 FALSE\r
521 );\r
522\r
ed838d0c 523\r
524 return EFI_SUCCESS;\r
66aa04e4 525\r
526ErrorExit:\r
527 if (UsbKeyboardDevice != NULL) {\r
528 if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
529 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
530 }\r
531 if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
532 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
533 }\r
534 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
535 gBS->FreePool (UsbKeyboardDevice);\r
536 UsbKeyboardDevice = NULL;\r
537 }\r
538 gBS->CloseProtocol (\r
539 Controller,\r
540 &gEfiUsbIoProtocolGuid,\r
541 This->DriverBindingHandle,\r
542 Controller\r
543 );\r
544 return Status;\r
545\r
ed838d0c 546}\r
547\r
548\r
549\r
550/**\r
551 Stop.\r
552\r
553 @param This EFI_DRIVER_BINDING_PROTOCOL\r
554 @param Controller Controller handle\r
555 @param NumberOfChildren Child handle number\r
556 @param ChildHandleBuffer Child handle buffer\r
557\r
558 @retval EFI_SUCCESS Success\r
559 @retval EFI_UNSUPPORTED Can't support\r
560\r
561**/\r
562EFI_STATUS\r
563EFIAPI\r
564USBKeyboardDriverBindingStop (\r
565 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
566 IN EFI_HANDLE Controller,\r
567 IN UINTN NumberOfChildren,\r
568 IN EFI_HANDLE *ChildHandleBuffer\r
569 )\r
570{\r
571 EFI_STATUS Status;\r
572 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
573 USB_KB_DEV *UsbKeyboardDevice;\r
ed838d0c 574\r
575 Status = gBS->OpenProtocol (\r
576 Controller,\r
577 &gEfiSimpleTextInProtocolGuid,\r
c52fa98c 578 (VOID **) &SimpleInput,\r
ed838d0c 579 This->DriverBindingHandle,\r
580 Controller,\r
bcb9d421 581 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
ed838d0c 582 );\r
583 if (EFI_ERROR (Status)) {\r
584 return EFI_UNSUPPORTED;\r
585 }\r
66aa04e4 586 Status = gBS->OpenProtocol (\r
587 Controller,\r
588 &gEfiSimpleTextInputExProtocolGuid,\r
589 NULL,\r
590 This->DriverBindingHandle,\r
591 Controller,\r
592 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
593 );\r
594 if (EFI_ERROR (Status)) {\r
595 return EFI_UNSUPPORTED;\r
596 }\r
ed838d0c 597 //\r
598 // Get USB_KB_DEV instance.\r
599 //\r
600 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
601\r
602 gBS->CloseProtocol (\r
603 Controller,\r
604 &gEfiSimpleTextInProtocolGuid,\r
605 This->DriverBindingHandle,\r
606 Controller\r
607 );\r
608\r
ed838d0c 609 //\r
610 // Uninstall the Asyn Interrupt Transfer from this device\r
611 // will disable the key data input from this device\r
612 //\r
613 KbdReportStatusCode (\r
614 UsbKeyboardDevice->DevicePath,\r
615 EFI_PROGRESS_CODE,\r
616 PcdGet32 (PcdStatusCodeValueKeyboardDisable)\r
617 );\r
618\r
619 //\r
620 // Destroy asynchronous interrupt transfer\r
621 //\r
622 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (\r
623 UsbKeyboardDevice->UsbIo,\r
624 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
625 FALSE,\r
626 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
627 0,\r
628 NULL,\r
629 NULL\r
630 );\r
631\r
632 gBS->CloseProtocol (\r
633 Controller,\r
634 &gEfiUsbIoProtocolGuid,\r
635 This->DriverBindingHandle,\r
636 Controller\r
637 );\r
638\r
639 Status = gBS->UninstallMultipleProtocolInterfaces (\r
640 Controller,\r
641 &gEfiSimpleTextInProtocolGuid,\r
642 &UsbKeyboardDevice->SimpleInput,\r
66aa04e4 643 &gEfiSimpleTextInputExProtocolGuid,\r
644 &UsbKeyboardDevice->SimpleInputEx,\r
ed838d0c 645 &gEfiHotPlugDeviceGuid,\r
646 NULL,\r
647 NULL\r
648 );\r
649 //\r
650 // free all the resources.\r
651 //\r
652 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
653 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
654 gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);\r
66aa04e4 655 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); \r
656 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
ed838d0c 657\r
813acf3a 658 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
659 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
660\r
ed838d0c 661 if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
662 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
663 }\r
664\r
665 gBS->FreePool (UsbKeyboardDevice);\r
666\r
667 return Status;\r
668\r
669}\r
670\r
66aa04e4 671STATIC\r
672EFI_STATUS\r
673USBKeyboardReadKeyStrokeWorker (\r
674 IN USB_KB_DEV *UsbKeyboardDevice,\r
675 OUT EFI_KEY_DATA *KeyData\r
676 )\r
677/*++\r
678\r
679 Routine Description:\r
680 Reads the next keystroke from the input device. The WaitForKey Event can \r
681 be used to test for existance of a keystroke via WaitForEvent () call.\r
ed838d0c 682\r
66aa04e4 683 Arguments:\r
684 UsbKeyboardDevice - Usb keyboard private structure.\r
685 KeyData - A pointer to a buffer that is filled in with the keystroke \r
686 state data for the key that was pressed.\r
ed838d0c 687\r
66aa04e4 688 Returns:\r
689 EFI_SUCCESS - The keystroke information was returned.\r
690 EFI_NOT_READY - There was no keystroke data availiable.\r
691 EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
692 hardware errors.\r
693 EFI_INVALID_PARAMETER - KeyData is NULL. \r
ed838d0c 694\r
66aa04e4 695--*/\r
696{\r
ed838d0c 697\r
66aa04e4 698 EFI_STATUS Status;\r
699 UINT8 KeyChar; \r
700 LIST_ENTRY *Link;\r
701 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
702 EFI_KEY_DATA OriginalKeyData;\r
ed838d0c 703\r
66aa04e4 704 if (KeyData == NULL) {\r
705 return EFI_INVALID_PARAMETER;\r
706 }\r
707\r
708 //\r
709 // if there is no saved ASCII byte, fetch it\r
710 // by calling USBKeyboardCheckForKey().\r
711 //\r
712 if (UsbKeyboardDevice->CurKeyChar == 0) {\r
713 Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
714 if (EFI_ERROR (Status)) {\r
715 return Status;\r
716 }\r
717 }\r
718\r
719 KeyData->Key.UnicodeChar = 0;\r
720 KeyData->Key.ScanCode = SCAN_NULL;\r
721\r
722 KeyChar = UsbKeyboardDevice->CurKeyChar;\r
723\r
724 UsbKeyboardDevice->CurKeyChar = 0;\r
725\r
726 //\r
727 // Translate saved ASCII byte into EFI_INPUT_KEY\r
728 //\r
729 Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);\r
730 if (EFI_ERROR (Status)) {\r
731 return Status;\r
732 }\r
733\r
734 CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));\r
735 \r
736 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
737 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
738\r
739 //\r
740 //Switch the control value to their original characters. In USBKeyCodeToEFIScanCode() the CTRL-Alpha characters have been switched to \r
741 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.\r
742 //\r
743 CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
744 if (UsbKeyboardDevice->CtrlOn) {\r
745 if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
746 if (UsbKeyboardDevice->CapsOn) {\r
747 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);\r
748 } else {\r
749 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);\r
750 } \r
751 }\r
752 }\r
753 \r
754 //\r
755 // Invoke notification functions if exist\r
756 //\r
757 for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
758 CurrentNotify = CR (\r
759 Link, \r
760 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
761 NotifyEntry, \r
762 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
763 );\r
764 if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
765 CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
766 }\r
767 }\r
768\r
769 return EFI_SUCCESS;\r
770 \r
771}\r
ed838d0c 772EFI_STATUS\r
773EFIAPI\r
774USBKeyboardReset (\r
775 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
776 IN BOOLEAN ExtendedVerification\r
777 )\r
778{\r
779 EFI_STATUS Status;\r
780 USB_KB_DEV *UsbKeyboardDevice;\r
ed838d0c 781\r
782 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
783\r
ed838d0c 784 KbdReportStatusCode (\r
785 UsbKeyboardDevice->DevicePath,\r
786 EFI_PROGRESS_CODE,\r
787 PcdGet32 (PcdStatusCodeValueKeyboardReset)\r
788 );\r
789\r
790 //\r
791 // Non Exhaustive reset:\r
792 // only reset private data structures.\r
793 //\r
794 if (!ExtendedVerification) {\r
795 //\r
796 // Clear the key buffer of this Usb keyboard\r
797 //\r
798 KbdReportStatusCode (\r
799 UsbKeyboardDevice->DevicePath,\r
800 EFI_PROGRESS_CODE,\r
801 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer)\r
802 );\r
803\r
804 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
805 UsbKeyboardDevice->CurKeyChar = 0;\r
806 return EFI_SUCCESS;\r
807 }\r
808\r
809 //\r
810 // Exhaustive reset\r
811 //\r
812 Status = InitUSBKeyboard (UsbKeyboardDevice);\r
813 UsbKeyboardDevice->CurKeyChar = 0;\r
814 if (EFI_ERROR (Status)) {\r
815 return EFI_DEVICE_ERROR;\r
816 }\r
817\r
818 return EFI_SUCCESS;\r
819}\r
820\r
821\r
822/**\r
823 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.\r
824\r
825 This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
826 Key A pointer to a buffer that is filled in with the keystroke\r
827 information for the key that was pressed.\r
828\r
829 @retval EFI_SUCCESS Success\r
830\r
831**/\r
832STATIC\r
833EFI_STATUS\r
834EFIAPI\r
835USBKeyboardReadKeyStroke (\r
836 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
837 OUT EFI_INPUT_KEY *Key\r
838 )\r
839{\r
66aa04e4 840 USB_KB_DEV *UsbKeyboardDevice;\r
841 EFI_STATUS Status;\r
842 EFI_KEY_DATA KeyData;\r
ed838d0c 843\r
844 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
845\r
66aa04e4 846 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
847 if (EFI_ERROR (Status)) {\r
848 return Status;\r
ed838d0c 849 }\r
850\r
66aa04e4 851 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
ed838d0c 852\r
66aa04e4 853 return EFI_SUCCESS;\r
ed838d0c 854\r
855}\r
856\r
857\r
858/**\r
859 Handler function for WaitForKey event.\r
860\r
861 Event Event to be signaled when a key is pressed.\r
862 Context Points to USB_KB_DEV instance.\r
863\r
864 @return VOID\r
865\r
866**/\r
867STATIC\r
868VOID\r
869EFIAPI\r
870USBKeyboardWaitForKey (\r
871 IN EFI_EVENT Event,\r
872 IN VOID *Context\r
873 )\r
874{\r
875 USB_KB_DEV *UsbKeyboardDevice;\r
876\r
877 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
878\r
879 if (UsbKeyboardDevice->CurKeyChar == 0) {\r
880\r
881 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {\r
882 return ;\r
883 }\r
884 }\r
885 //\r
886 // If has key pending, signal the event.\r
887 //\r
888 gBS->SignalEvent (Event);\r
889}\r
890\r
891\r
892\r
893/**\r
894 Check whether there is key pending.\r
895\r
896 UsbKeyboardDevice The USB_KB_DEV instance.\r
897\r
898 @retval EFI_SUCCESS Success\r
899\r
900**/\r
901STATIC\r
902EFI_STATUS\r
903USBKeyboardCheckForKey (\r
904 IN USB_KB_DEV *UsbKeyboardDevice\r
905 )\r
906{\r
907 EFI_STATUS Status;\r
908 UINT8 KeyChar;\r
909\r
910 //\r
911 // Fetch raw data from the USB keyboard input,\r
912 // and translate it into ASCII data.\r
913 //\r
914 Status = USBParseKey (UsbKeyboardDevice, &KeyChar);\r
915 if (EFI_ERROR (Status)) {\r
916 return Status;\r
917 }\r
918\r
919 UsbKeyboardDevice->CurKeyChar = KeyChar;\r
920 return EFI_SUCCESS;\r
921}\r
922\r
923\r
924/**\r
925 Report Status Code in Usb Bot Driver\r
926\r
927 @param DevicePath Use this to get Device Path\r
928 @param CodeType Status Code Type\r
929 @param CodeValue Status Code Value\r
930\r
931 @return None\r
932\r
933**/\r
934VOID\r
935KbdReportStatusCode (\r
936 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
937 IN EFI_STATUS_CODE_TYPE CodeType,\r
938 IN EFI_STATUS_CODE_VALUE Value\r
939 )\r
940{\r
941\r
942 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
943 CodeType,\r
944 Value,\r
945 DevicePath\r
946 );\r
947}\r
66aa04e4 948STATIC\r
949EFI_STATUS\r
950KbdFreeNotifyList (\r
951 IN OUT LIST_ENTRY *ListHead\r
952 )\r
953/*++\r
954\r
955Routine Description:\r
956\r
957Arguments:\r
958\r
959 ListHead - The list head\r
960\r
961Returns:\r
962\r
963 EFI_SUCCESS - Free the notify list successfully\r
964 EFI_INVALID_PARAMETER - ListHead is invalid.\r
965\r
966--*/\r
967{\r
968 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
969\r
970 if (ListHead == NULL) {\r
971 return EFI_INVALID_PARAMETER;\r
972 }\r
973 while (!IsListEmpty (ListHead)) {\r
974 NotifyNode = CR (\r
975 ListHead->ForwardLink, \r
976 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
977 NotifyEntry, \r
978 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
979 );\r
980 RemoveEntryList (ListHead->ForwardLink);\r
981 gBS->FreePool (NotifyNode);\r
982 }\r
983 \r
984 return EFI_SUCCESS;\r
985}\r
986\r
987STATIC\r
988BOOLEAN\r
989IsKeyRegistered (\r
990 IN EFI_KEY_DATA *RegsiteredData,\r
991 IN EFI_KEY_DATA *InputData\r
992 )\r
993/*++\r
994\r
995Routine Description:\r
996\r
997Arguments:\r
998\r
999 RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
1000 state data for the key that was registered.\r
1001 InputData - A pointer to a buffer that is filled in with the keystroke \r
1002 state data for the key that was pressed.\r
1003\r
1004Returns:\r
1005 TRUE - Key be pressed matches a registered key.\r
1006 FLASE - Match failed. \r
1007 \r
1008--*/\r
1009{\r
1010 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
1011 \r
1012 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
1013 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
1014 return FALSE; \r
1015 } \r
1016 \r
1017 //\r
1018 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
1019 //\r
1020 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
1021 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
1022 return FALSE; \r
1023 } \r
1024 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
1025 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
1026 return FALSE; \r
1027 } \r
1028 \r
1029 return TRUE;\r
1030\r
1031}\r
1032\r
1033//\r
1034// Simple Text Input Ex protocol functions \r
1035//\r
1036EFI_STATUS\r
1037EFIAPI\r
1038USBKeyboardResetEx (\r
1039 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1040 IN BOOLEAN ExtendedVerification\r
1041 )\r
1042/*++\r
1043\r
1044 Routine Description:\r
1045 Reset the input device and optionaly run diagnostics\r
1046\r
1047 Arguments:\r
1048 This - Protocol instance pointer.\r
1049 ExtendedVerification - Driver may perform diagnostics on reset.\r
1050\r
1051 Returns:\r
1052 EFI_SUCCESS - The device was reset.\r
1053 EFI_DEVICE_ERROR - The device is not functioning properly and could \r
1054 not be reset.\r
1055\r
1056--*/\r
1057{\r
1058 EFI_STATUS Status;\r
1059 USB_KB_DEV *UsbKeyboardDevice;\r
1060 EFI_TPL OldTpl;\r
1061 \r
1062\r
1063 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1064\r
1065 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
1066 if (EFI_ERROR (Status)) {\r
1067 return EFI_DEVICE_ERROR;\r
1068 }\r
1069\r
1070 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1071 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
1072 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
1073 gBS->RestoreTPL (OldTpl);\r
1074\r
1075 return EFI_SUCCESS;\r
1076\r
1077}\r
1078\r
1079EFI_STATUS\r
1080EFIAPI\r
1081USBKeyboardReadKeyStrokeEx (\r
1082 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1083 OUT EFI_KEY_DATA *KeyData\r
1084 )\r
1085/*++\r
1086\r
1087 Routine Description:\r
1088 Reads the next keystroke from the input device. The WaitForKey Event can \r
1089 be used to test for existance of a keystroke via WaitForEvent () call.\r
1090\r
1091 Arguments:\r
1092 This - Protocol instance pointer.\r
1093 KeyData - A pointer to a buffer that is filled in with the keystroke \r
1094 state data for the key that was pressed.\r
1095\r
1096 Returns:\r
1097 EFI_SUCCESS - The keystroke information was returned.\r
1098 EFI_NOT_READY - There was no keystroke data availiable.\r
1099 EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
1100 hardware errors.\r
1101 EFI_INVALID_PARAMETER - KeyData is NULL. \r
1102\r
1103--*/\r
1104{\r
1105 USB_KB_DEV *UsbKeyboardDevice;\r
1106\r
1107 if (KeyData == NULL) {\r
1108 return EFI_INVALID_PARAMETER;\r
1109 }\r
1110\r
1111 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1112\r
1113 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
1114 \r
1115}\r
1116\r
1117EFI_STATUS\r
1118EFIAPI\r
1119USBKeyboardSetState (\r
1120 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1121 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
1122 )\r
1123/*++\r
1124\r
1125 Routine Description:\r
1126 Set certain state for the input device.\r
1127\r
1128 Arguments:\r
1129 This - Protocol instance pointer.\r
1130 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
1131 state for the input device.\r
1132 \r
1133 Returns: \r
1134 EFI_SUCCESS - The device state was set successfully.\r
1135 EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
1136 not have the setting adjusted.\r
1137 EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
1138 EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
1139\r
1140--*/ \r
1141{\r
1142 USB_KB_DEV *UsbKeyboardDevice;\r
1143\r
1144 if (KeyToggleState == NULL) {\r
1145 return EFI_INVALID_PARAMETER;\r
1146 }\r
1147\r
1148 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1149\r
1150 if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
1151 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
1152 return EFI_UNSUPPORTED;\r
1153 }\r
1154\r
1155 //\r
1156 // Update the status light\r
1157 //\r
1158\r
1159 UsbKeyboardDevice->ScrollOn = 0;\r
1160 UsbKeyboardDevice->NumLockOn = 0;\r
1161 UsbKeyboardDevice->CapsOn = 0;\r
1162 \r
1163 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
1164 UsbKeyboardDevice->ScrollOn = 1;\r
1165 }\r
1166 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
1167 UsbKeyboardDevice->NumLockOn = 1;\r
1168 }\r
1169 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
1170 UsbKeyboardDevice->CapsOn = 1;\r
1171 }\r
1172\r
1173 SetKeyLED (UsbKeyboardDevice);\r
1174\r
1175 UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
1176\r
1177 return EFI_SUCCESS;\r
1178 \r
1179}\r
1180\r
1181EFI_STATUS\r
1182EFIAPI\r
1183USBKeyboardRegisterKeyNotify (\r
1184 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1185 IN EFI_KEY_DATA *KeyData,\r
1186 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
1187 OUT EFI_HANDLE *NotifyHandle\r
1188 )\r
1189/*++\r
1190\r
1191 Routine Description:\r
1192 Register a notification function for a particular keystroke for the input device.\r
1193\r
1194 Arguments:\r
1195 This - Protocol instance pointer.\r
1196 KeyData - A pointer to a buffer that is filled in with the keystroke \r
1197 information data for the key that was pressed.\r
1198 KeyNotificationFunction - Points to the function to be called when the key \r
1199 sequence is typed specified by KeyData. \r
1200 NotifyHandle - Points to the unique handle assigned to the registered notification. \r
1201\r
1202 Returns:\r
1203 EFI_SUCCESS - The notification function was registered successfully.\r
1204 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
1205 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
1206 \r
1207--*/ \r
1208{\r
1209 USB_KB_DEV *UsbKeyboardDevice;\r
1210 EFI_STATUS Status;\r
1211 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
1212 LIST_ENTRY *Link;\r
1213 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
1214\r
1215 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
1216 return EFI_INVALID_PARAMETER;\r
1217 }\r
1218\r
1219 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1220\r
1221 //\r
1222 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
1223 //\r
1224 for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
1225 CurrentNotify = CR (\r
1226 Link, \r
1227 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1228 NotifyEntry, \r
1229 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1230 );\r
1231 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
1232 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
1233 *NotifyHandle = CurrentNotify->NotifyHandle; \r
1234 return EFI_SUCCESS;\r
1235 }\r
1236 }\r
1237 }\r
1238 \r
1239 //\r
1240 // Allocate resource to save the notification function\r
1241 // \r
1242 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
1243 if (NewNotify == NULL) {\r
1244 return EFI_OUT_OF_RESOURCES;\r
1245 }\r
1246\r
1247 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
1248 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
1249 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
1250 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
1251\r
1252 //\r
1253 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
1254 // \r
1255 Status = gBS->InstallMultipleProtocolInterfaces (\r
1256 &NewNotify->NotifyHandle,\r
1257 &gSimpleTextInExNotifyGuid,\r
1258 NULL,\r
1259 NULL\r
1260 );\r
1261 ASSERT_EFI_ERROR (Status);\r
1262 \r
1263 *NotifyHandle = NewNotify->NotifyHandle; \r
1264 \r
1265 return EFI_SUCCESS;\r
1266 \r
1267}\r
1268\r
1269EFI_STATUS\r
1270EFIAPI\r
1271USBKeyboardUnregisterKeyNotify (\r
1272 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1273 IN EFI_HANDLE NotificationHandle\r
1274 )\r
1275/*++\r
1276\r
1277 Routine Description:\r
1278 Remove a registered notification function from a particular keystroke.\r
1279\r
1280 Arguments:\r
1281 This - Protocol instance pointer. \r
1282 NotificationHandle - The handle of the notification function being unregistered.\r
1283\r
1284 Returns:\r
1285 EFI_SUCCESS - The notification function was unregistered successfully.\r
1286 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
1287 EFI_NOT_FOUND - Can not find the matching entry in database. \r
1288 \r
1289--*/ \r
1290{\r
1291 USB_KB_DEV *UsbKeyboardDevice;\r
1292 EFI_STATUS Status;\r
1293 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1294 LIST_ENTRY *Link;\r
1295\r
1296 if (NotificationHandle == NULL) {\r
1297 return EFI_INVALID_PARAMETER;\r
1298 } \r
1299 \r
1300 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1301 \r
1302 Status = gBS->OpenProtocol (\r
1303 NotificationHandle,\r
1304 &gSimpleTextInExNotifyGuid,\r
1305 NULL,\r
1306 NULL,\r
1307 NULL,\r
1308 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1309 );\r
1310 if (EFI_ERROR (Status)) {\r
1311 return EFI_INVALID_PARAMETER;\r
1312 }\r
1313\r
1314 for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
1315 CurrentNotify = CR (\r
1316 Link, \r
1317 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1318 NotifyEntry, \r
1319 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1320 ); \r
1321 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
1322 //\r
1323 // Remove the notification function from NotifyList and free resources\r
1324 //\r
1325 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
1326 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1327 CurrentNotify->NotifyHandle,\r
1328 &gSimpleTextInExNotifyGuid,\r
1329 NULL,\r
1330 NULL\r
1331 );\r
1332 ASSERT_EFI_ERROR (Status);\r
1333 gBS->FreePool (CurrentNotify); \r
1334 return EFI_SUCCESS;\r
1335 }\r
1336 }\r
1337\r
1338 return EFI_NOT_FOUND; \r
1339}\r
1340\r