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