]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
Clean up the private GUID definition in module Level.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / EfiKey.c
... / ...
CommitLineData
1/** @file\r
2 USB Keyboard Driver that manages USB keyboard and produces Simple Text Input\r
3 Protocol and Simple Text Input Ex Protocol.\r
4\r
5Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
6This 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
14**/\r
15\r
16#include "EfiKey.h"\r
17#include "KeyBoard.h"\r
18\r
19//\r
20// USB Keyboard Driver Global Variables\r
21//\r
22EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {\r
23 USBKeyboardDriverBindingSupported,\r
24 USBKeyboardDriverBindingStart,\r
25 USBKeyboardDriverBindingStop,\r
26 0xa,\r
27 NULL,\r
28 NULL\r
29};\r
30\r
31/**\r
32 Entrypoint of USB Keyboard Driver.\r
33\r
34 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding\r
35 Protocols together with Component Name Protocols.\r
36\r
37 @param ImageHandle The firmware allocated handle for the EFI image.\r
38 @param SystemTable A pointer to the EFI System Table.\r
39\r
40 @retval EFI_SUCCESS The entry point is executed successfully.\r
41\r
42**/\r
43EFI_STATUS\r
44EFIAPI\r
45USBKeyboardDriverBindingEntryPoint (\r
46 IN EFI_HANDLE ImageHandle,\r
47 IN EFI_SYSTEM_TABLE *SystemTable\r
48 )\r
49{\r
50 EFI_STATUS Status;\r
51\r
52 Status = EfiLibInstallDriverBindingComponentName2 (\r
53 ImageHandle,\r
54 SystemTable,\r
55 &gUsbKeyboardDriverBinding,\r
56 ImageHandle,\r
57 &gUsbKeyboardComponentName,\r
58 &gUsbKeyboardComponentName2\r
59 );\r
60 ASSERT_EFI_ERROR (Status);\r
61\r
62 return EFI_SUCCESS;\r
63}\r
64\r
65/**\r
66 Check whether USB keyboard driver supports this device.\r
67\r
68 @param This The USB keyboard driver binding protocol.\r
69 @param Controller The controller handle to check.\r
70 @param RemainingDevicePath The remaining device path.\r
71\r
72 @retval EFI_SUCCESS The driver supports this controller.\r
73 @retval other This device isn't supported.\r
74\r
75**/\r
76EFI_STATUS\r
77EFIAPI\r
78USBKeyboardDriverBindingSupported (\r
79 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
80 IN EFI_HANDLE Controller,\r
81 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
82 )\r
83{\r
84 EFI_STATUS Status;\r
85 EFI_USB_IO_PROTOCOL *UsbIo;\r
86\r
87 //\r
88 // Check if USB I/O Protocol is attached on the controller handle.\r
89 //\r
90 Status = gBS->OpenProtocol (\r
91 Controller,\r
92 &gEfiUsbIoProtocolGuid,\r
93 (VOID **) &UsbIo,\r
94 This->DriverBindingHandle,\r
95 Controller,\r
96 EFI_OPEN_PROTOCOL_BY_DRIVER\r
97 );\r
98 if (EFI_ERROR (Status)) {\r
99 return Status;\r
100 }\r
101\r
102 //\r
103 // Use the USB I/O Protocol interface to check whether Controller is\r
104 // a keyboard device that can be managed by this driver.\r
105 //\r
106 Status = EFI_SUCCESS;\r
107\r
108 if (!IsUSBKeyboard (UsbIo)) {\r
109 Status = EFI_UNSUPPORTED;\r
110 }\r
111\r
112 gBS->CloseProtocol (\r
113 Controller,\r
114 &gEfiUsbIoProtocolGuid,\r
115 This->DriverBindingHandle,\r
116 Controller\r
117 );\r
118\r
119 return Status;\r
120}\r
121\r
122/**\r
123 Starts the keyboard device with this driver.\r
124\r
125 This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol,\r
126 initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage\r
127 this keyboard device.\r
128\r
129 @param This The USB keyboard driver binding instance.\r
130 @param Controller Handle of device to bind driver to.\r
131 @param RemainingDevicePath Optional parameter use to pick a specific child\r
132 device to start.\r
133\r
134 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.\r
135 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.\r
136 @retval Other This controller cannot be started.\r
137\r
138**/\r
139EFI_STATUS\r
140EFIAPI\r
141USBKeyboardDriverBindingStart (\r
142 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
143 IN EFI_HANDLE Controller,\r
144 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
145 )\r
146{\r
147 EFI_STATUS Status;\r
148 EFI_USB_IO_PROTOCOL *UsbIo;\r
149 USB_KB_DEV *UsbKeyboardDevice;\r
150 UINT8 EndpointNumber;\r
151 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;\r
152 UINT8 Index;\r
153 UINT8 EndpointAddr;\r
154 UINT8 PollingInterval;\r
155 UINT8 PacketSize;\r
156 BOOLEAN Found;\r
157 EFI_TPL OldTpl;\r
158\r
159 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
160 //\r
161 // Open USB I/O Protocol\r
162 //\r
163 Status = gBS->OpenProtocol (\r
164 Controller,\r
165 &gEfiUsbIoProtocolGuid,\r
166 (VOID **) &UsbIo,\r
167 This->DriverBindingHandle,\r
168 Controller,\r
169 EFI_OPEN_PROTOCOL_BY_DRIVER\r
170 );\r
171 if (EFI_ERROR (Status)) {\r
172 goto ErrorExit1;\r
173 }\r
174\r
175 UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));\r
176 ASSERT (UsbKeyboardDevice != NULL);\r
177\r
178 //\r
179 // Get the Device Path Protocol on Controller's handle\r
180 //\r
181 Status = gBS->OpenProtocol (\r
182 Controller,\r
183 &gEfiDevicePathProtocolGuid,\r
184 (VOID **) &UsbKeyboardDevice->DevicePath,\r
185 This->DriverBindingHandle,\r
186 Controller,\r
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
188 );\r
189\r
190 if (EFI_ERROR (Status)) {\r
191 goto ErrorExit;\r
192 }\r
193 //\r
194 // Report that the USB keyboard is being enabled\r
195 //\r
196 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
197 EFI_PROGRESS_CODE,\r
198 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE),\r
199 UsbKeyboardDevice->DevicePath\r
200 );\r
201\r
202 //\r
203 // This is pretty close to keyboard detection, so log progress\r
204 //\r
205 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
206 EFI_PROGRESS_CODE,\r
207 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT),\r
208 UsbKeyboardDevice->DevicePath\r
209 );\r
210\r
211 UsbKeyboardDevice->UsbIo = UsbIo;\r
212\r
213 //\r
214 // Get interface & endpoint descriptor\r
215 //\r
216 UsbIo->UsbGetInterfaceDescriptor (\r
217 UsbIo,\r
218 &UsbKeyboardDevice->InterfaceDescriptor\r
219 );\r
220\r
221 EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;\r
222\r
223 //\r
224 // Traverse endpoints to find interrupt endpoint\r
225 //\r
226 Found = FALSE;\r
227 for (Index = 0; Index < EndpointNumber; Index++) {\r
228\r
229 UsbIo->UsbGetEndpointDescriptor (\r
230 UsbIo,\r
231 Index,\r
232 &EndpointDescriptor\r
233 );\r
234\r
235 if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {\r
236 //\r
237 // We only care interrupt endpoint here\r
238 //\r
239 CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
240 Found = TRUE;\r
241 break;\r
242 }\r
243 }\r
244\r
245 if (!Found) {\r
246 //\r
247 // No interrupt endpoint found, then return unsupported.\r
248 //\r
249 Status = EFI_UNSUPPORTED;\r
250 goto ErrorExit;\r
251 }\r
252\r
253 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
254 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
255 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
256\r
257 UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;\r
258 UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;\r
259 UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;\r
260 UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;\r
261 UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;\r
262 \r
263 InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
264 \r
265 Status = gBS->CreateEvent (\r
266 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
267 TPL_NOTIFY,\r
268 USBKeyboardTimerHandler,\r
269 UsbKeyboardDevice,\r
270 &UsbKeyboardDevice->TimerEvent\r
271 );\r
272 if (!EFI_ERROR (Status)) {\r
273 Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL);\r
274 }\r
275 if (EFI_ERROR (Status)) {\r
276 goto ErrorExit;\r
277 }\r
278\r
279 Status = gBS->CreateEvent (\r
280 EVT_NOTIFY_WAIT,\r
281 TPL_NOTIFY,\r
282 USBKeyboardWaitForKey,\r
283 UsbKeyboardDevice,\r
284 &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
285 );\r
286\r
287 if (EFI_ERROR (Status)) {\r
288 goto ErrorExit;\r
289 }\r
290\r
291 Status = gBS->CreateEvent (\r
292 EVT_NOTIFY_WAIT,\r
293 TPL_NOTIFY,\r
294 USBKeyboardWaitForKey,\r
295 UsbKeyboardDevice,\r
296 &(UsbKeyboardDevice->SimpleInput.WaitForKey)\r
297 );\r
298 if (EFI_ERROR (Status)) {\r
299 goto ErrorExit;\r
300 }\r
301\r
302 //\r
303 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol\r
304 // for the USB keyboard device.\r
305 // USB keyboard is a hot plug device, and expected to work immediately\r
306 // when plugging into system, other conventional console devices could\r
307 // distinguish it by its device path.\r
308 //\r
309 Status = gBS->InstallMultipleProtocolInterfaces (\r
310 &Controller,\r
311 &gEfiSimpleTextInProtocolGuid,\r
312 &UsbKeyboardDevice->SimpleInput,\r
313 &gEfiSimpleTextInputExProtocolGuid,\r
314 &UsbKeyboardDevice->SimpleInputEx,\r
315 NULL\r
316 );\r
317 if (EFI_ERROR (Status)) {\r
318 goto ErrorExit;\r
319 }\r
320\r
321 UsbKeyboardDevice->ControllerHandle = Controller;\r
322 Status = InitKeyboardLayout (UsbKeyboardDevice);\r
323 if (EFI_ERROR (Status)) {\r
324 gBS->UninstallMultipleProtocolInterfaces (\r
325 Controller,\r
326 &gEfiSimpleTextInProtocolGuid,\r
327 &UsbKeyboardDevice->SimpleInput,\r
328 &gEfiSimpleTextInputExProtocolGuid,\r
329 &UsbKeyboardDevice->SimpleInputEx,\r
330 NULL\r
331 );\r
332 goto ErrorExit;\r
333 }\r
334\r
335\r
336 //\r
337 // Reset USB Keyboard Device exhaustively.\r
338 //\r
339 Status = UsbKeyboardDevice->SimpleInputEx.Reset (\r
340 &UsbKeyboardDevice->SimpleInputEx,\r
341 TRUE\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344 gBS->UninstallMultipleProtocolInterfaces (\r
345 Controller,\r
346 &gEfiSimpleTextInProtocolGuid,\r
347 &UsbKeyboardDevice->SimpleInput,\r
348 &gEfiSimpleTextInputExProtocolGuid,\r
349 &UsbKeyboardDevice->SimpleInputEx,\r
350 NULL\r
351 );\r
352 goto ErrorExit;\r
353 }\r
354\r
355 //\r
356 // Submit Asynchronous Interrupt Transfer to manage this device.\r
357 //\r
358 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;\r
359 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;\r
360 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
361\r
362 Status = UsbIo->UsbAsyncInterruptTransfer (\r
363 UsbIo,\r
364 EndpointAddr,\r
365 TRUE,\r
366 PollingInterval,\r
367 PacketSize,\r
368 KeyboardHandler,\r
369 UsbKeyboardDevice\r
370 );\r
371\r
372 if (EFI_ERROR (Status)) {\r
373 gBS->UninstallMultipleProtocolInterfaces (\r
374 Controller,\r
375 &gEfiSimpleTextInProtocolGuid,\r
376 &UsbKeyboardDevice->SimpleInput,\r
377 &gEfiSimpleTextInputExProtocolGuid,\r
378 &UsbKeyboardDevice->SimpleInputEx,\r
379 NULL\r
380 );\r
381 goto ErrorExit;\r
382 }\r
383\r
384 UsbKeyboardDevice->ControllerNameTable = NULL;\r
385 AddUnicodeString2 (\r
386 "eng",\r
387 gUsbKeyboardComponentName.SupportedLanguages,\r
388 &UsbKeyboardDevice->ControllerNameTable,\r
389 L"Generic Usb Keyboard",\r
390 TRUE\r
391 );\r
392 AddUnicodeString2 (\r
393 "en",\r
394 gUsbKeyboardComponentName2.SupportedLanguages,\r
395 &UsbKeyboardDevice->ControllerNameTable,\r
396 L"Generic Usb Keyboard",\r
397 FALSE\r
398 );\r
399\r
400 gBS->RestoreTPL (OldTpl);\r
401 return EFI_SUCCESS;\r
402\r
403//\r
404// Error handler\r
405//\r
406ErrorExit:\r
407 if (UsbKeyboardDevice != NULL) {\r
408 if (UsbKeyboardDevice->TimerEvent != NULL) {\r
409 gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
410 }\r
411 if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
412 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
413 }\r
414 if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
415 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
416 }\r
417 if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) {\r
418 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
419 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
420 }\r
421 FreePool (UsbKeyboardDevice);\r
422 UsbKeyboardDevice = NULL;\r
423 }\r
424 gBS->CloseProtocol (\r
425 Controller,\r
426 &gEfiUsbIoProtocolGuid,\r
427 This->DriverBindingHandle,\r
428 Controller\r
429 );\r
430\r
431ErrorExit1:\r
432 gBS->RestoreTPL (OldTpl);\r
433\r
434 return Status;\r
435\r
436}\r
437\r
438\r
439/**\r
440 Stop the USB keyboard device handled by this driver.\r
441\r
442 @param This The USB keyboard driver binding protocol.\r
443 @param Controller The controller to release.\r
444 @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
445 @param ChildHandleBuffer The array of child handle.\r
446\r
447 @retval EFI_SUCCESS The device was stopped.\r
448 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol\r
449 is not installed on Controller.\r
450 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
451 @retval Others Fail to uninstall protocols attached on the device.\r
452\r
453**/\r
454EFI_STATUS\r
455EFIAPI\r
456USBKeyboardDriverBindingStop (\r
457 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
458 IN EFI_HANDLE Controller,\r
459 IN UINTN NumberOfChildren,\r
460 IN EFI_HANDLE *ChildHandleBuffer\r
461 )\r
462{\r
463 EFI_STATUS Status;\r
464 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
465 USB_KB_DEV *UsbKeyboardDevice;\r
466\r
467 Status = gBS->OpenProtocol (\r
468 Controller,\r
469 &gEfiSimpleTextInProtocolGuid,\r
470 (VOID **) &SimpleInput,\r
471 This->DriverBindingHandle,\r
472 Controller,\r
473 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
474 );\r
475 if (EFI_ERROR (Status)) {\r
476 return EFI_UNSUPPORTED;\r
477 }\r
478\r
479 Status = gBS->OpenProtocol (\r
480 Controller,\r
481 &gEfiSimpleTextInputExProtocolGuid,\r
482 NULL,\r
483 This->DriverBindingHandle,\r
484 Controller,\r
485 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
486 );\r
487 if (EFI_ERROR (Status)) {\r
488 return EFI_UNSUPPORTED;\r
489 }\r
490\r
491 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
492\r
493 //\r
494 // The key data input from this device will be disabled.\r
495 //\r
496 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
497 EFI_PROGRESS_CODE,\r
498 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE),\r
499 UsbKeyboardDevice->DevicePath\r
500 );\r
501\r
502 //\r
503 // Delete the Asynchronous Interrupt Transfer from this device\r
504 //\r
505 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (\r
506 UsbKeyboardDevice->UsbIo,\r
507 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
508 FALSE,\r
509 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
510 0,\r
511 NULL,\r
512 NULL\r
513 );\r
514\r
515 gBS->CloseProtocol (\r
516 Controller,\r
517 &gEfiUsbIoProtocolGuid,\r
518 This->DriverBindingHandle,\r
519 Controller\r
520 );\r
521\r
522 Status = gBS->UninstallMultipleProtocolInterfaces (\r
523 Controller,\r
524 &gEfiSimpleTextInProtocolGuid,\r
525 &UsbKeyboardDevice->SimpleInput,\r
526 &gEfiSimpleTextInputExProtocolGuid,\r
527 &UsbKeyboardDevice->SimpleInputEx,\r
528 NULL\r
529 );\r
530 //\r
531 // Free all resources.\r
532 //\r
533 gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
534 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
535 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
536 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
537 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
538 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);\r
539\r
540 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
541 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
542\r
543 if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
544 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
545 }\r
546\r
547 DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);\r
548 DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);\r
549 \r
550 FreePool (UsbKeyboardDevice);\r
551\r
552 return Status;\r
553}\r
554\r
555/**\r
556 Internal function to read the next keystroke from the keyboard buffer.\r
557\r
558 @param UsbKeyboardDevice USB keyboard's private structure.\r
559 @param KeyData A pointer to buffer to hold the keystroke\r
560 data for the key that was pressed.\r
561\r
562 @retval EFI_SUCCESS The keystroke information was returned.\r
563 @retval EFI_NOT_READY There was no keystroke data availiable.\r
564 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
565 hardware errors.\r
566 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
567 @retval Others Fail to translate keycode into EFI_INPUT_KEY\r
568\r
569**/\r
570EFI_STATUS\r
571USBKeyboardReadKeyStrokeWorker (\r
572 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
573 OUT EFI_KEY_DATA *KeyData\r
574 )\r
575{\r
576 if (KeyData == NULL) {\r
577 return EFI_INVALID_PARAMETER;\r
578 }\r
579\r
580 if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
581 return EFI_NOT_READY;\r
582 }\r
583\r
584 Dequeue (&UsbKeyboardDevice->EfiKeyQueue, KeyData, sizeof (*KeyData));\r
585\r
586 return EFI_SUCCESS;\r
587}\r
588\r
589/**\r
590 Reset the input device and optionally run diagnostics\r
591\r
592 There are 2 types of reset for USB keyboard.\r
593 For non-exhaustive reset, only keyboard buffer is cleared.\r
594 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status\r
595 is also re-initialized.\r
596\r
597 @param This Protocol instance pointer.\r
598 @param ExtendedVerification Driver may perform diagnostics on reset.\r
599\r
600 @retval EFI_SUCCESS The device was reset.\r
601 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.\r
602\r
603**/\r
604EFI_STATUS\r
605EFIAPI\r
606USBKeyboardReset (\r
607 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
608 IN BOOLEAN ExtendedVerification\r
609 )\r
610{\r
611 EFI_STATUS Status;\r
612 USB_KB_DEV *UsbKeyboardDevice;\r
613\r
614 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
615\r
616 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
617 EFI_PROGRESS_CODE,\r
618 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET),\r
619 UsbKeyboardDevice->DevicePath\r
620 );\r
621\r
622 //\r
623 // Non-exhaustive reset:\r
624 // only reset private data structures.\r
625 //\r
626 if (!ExtendedVerification) {\r
627 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
628 EFI_PROGRESS_CODE,\r
629 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER),\r
630 UsbKeyboardDevice->DevicePath\r
631 );\r
632 //\r
633 // Clear the key buffer of this USB keyboard\r
634 //\r
635 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));\r
636 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));\r
637\r
638 return EFI_SUCCESS;\r
639 }\r
640\r
641 //\r
642 // Exhaustive reset\r
643 //\r
644 Status = InitUSBKeyboard (UsbKeyboardDevice);\r
645 if (EFI_ERROR (Status)) {\r
646 return EFI_DEVICE_ERROR;\r
647 }\r
648\r
649 return EFI_SUCCESS;\r
650}\r
651\r
652\r
653/**\r
654 Reads the next keystroke from the input device.\r
655\r
656 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
657 @param Key A pointer to a buffer that is filled in with the keystroke\r
658 information for the key that was pressed.\r
659\r
660 @retval EFI_SUCCESS The keystroke information was returned.\r
661 @retval EFI_NOT_READY There was no keystroke data availiable.\r
662 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
663 hardware errors.\r
664\r
665**/\r
666EFI_STATUS\r
667EFIAPI\r
668USBKeyboardReadKeyStroke (\r
669 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
670 OUT EFI_INPUT_KEY *Key\r
671 )\r
672{\r
673 USB_KB_DEV *UsbKeyboardDevice;\r
674 EFI_STATUS Status;\r
675 EFI_KEY_DATA KeyData;\r
676\r
677 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
678\r
679 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
680 if (EFI_ERROR (Status)) {\r
681 return Status;\r
682 }\r
683\r
684 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
685\r
686 return EFI_SUCCESS;\r
687}\r
688\r
689\r
690/**\r
691 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx\r
692 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.\r
693\r
694 @param Event Event to be signaled when a key is pressed.\r
695 @param Context Points to USB_KB_DEV instance.\r
696\r
697**/\r
698VOID\r
699EFIAPI\r
700USBKeyboardWaitForKey (\r
701 IN EFI_EVENT Event,\r
702 IN VOID *Context\r
703 )\r
704{\r
705 USB_KB_DEV *UsbKeyboardDevice;\r
706\r
707 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
708\r
709 if (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
710 //\r
711 // If there is pending key, signal the event.\r
712 //\r
713 gBS->SignalEvent (Event);\r
714 }\r
715}\r
716\r
717/**\r
718 Timer handler to convert the key from USB.\r
719\r
720 @param Event Indicates the event that invoke this function.\r
721 @param Context Indicates the calling context.\r
722**/\r
723VOID\r
724EFIAPI\r
725USBKeyboardTimerHandler (\r
726 IN EFI_EVENT Event,\r
727 IN VOID *Context\r
728 )\r
729{\r
730 EFI_STATUS Status;\r
731 USB_KB_DEV *UsbKeyboardDevice;\r
732 UINT8 KeyCode;\r
733 EFI_KEY_DATA KeyData;\r
734\r
735 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
736 \r
737 //\r
738 // Fetch raw data from the USB keyboard buffer,\r
739 // and translate it into USB keycode.\r
740 //\r
741 Status = USBParseKey (UsbKeyboardDevice, &KeyCode);\r
742 if (EFI_ERROR (Status)) {\r
743 return ;\r
744 }\r
745\r
746 //\r
747 // Translate saved USB keycode into EFI_INPUT_KEY\r
748 //\r
749 Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData);\r
750 if (EFI_ERROR (Status)) {\r
751 return ;\r
752 }\r
753\r
754 //\r
755 // Insert to the EFI Key queue\r
756 //\r
757 Enqueue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (KeyData));\r
758}\r
759\r
760/**\r
761 Free keyboard notify list.\r
762\r
763 @param NotifyList The keyboard notify list to free.\r
764\r
765 @retval EFI_SUCCESS Free the notify list successfully.\r
766 @retval EFI_INVALID_PARAMETER NotifyList is NULL.\r
767\r
768**/\r
769EFI_STATUS\r
770KbdFreeNotifyList (\r
771 IN OUT LIST_ENTRY *NotifyList\r
772 )\r
773{\r
774 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
775 LIST_ENTRY *Link;\r
776\r
777 if (NotifyList == NULL) {\r
778 return EFI_INVALID_PARAMETER;\r
779 }\r
780 while (!IsListEmpty (NotifyList)) {\r
781 Link = GetFirstNode (NotifyList);\r
782 NotifyNode = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
783 RemoveEntryList (Link);\r
784 FreePool (NotifyNode);\r
785 }\r
786 \r
787 return EFI_SUCCESS;\r
788}\r
789\r
790/**\r
791 Check whether the pressed key matches a registered key or not.\r
792\r
793 @param RegsiteredData A pointer to keystroke data for the key that was registered.\r
794 @param InputData A pointer to keystroke data for the key that was pressed.\r
795\r
796 @retval TRUE Key pressed matches a registered key.\r
797 @retval FLASE Key pressed does not matches a registered key.\r
798\r
799**/\r
800BOOLEAN\r
801IsKeyRegistered (\r
802 IN EFI_KEY_DATA *RegsiteredData,\r
803 IN EFI_KEY_DATA *InputData\r
804 )\r
805{\r
806 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
807 \r
808 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
809 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
810 return FALSE; \r
811 } \r
812 \r
813 //\r
814 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
815 //\r
816 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
817 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
818 return FALSE; \r
819 } \r
820 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
821 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
822 return FALSE; \r
823 } \r
824 \r
825 return TRUE;\r
826}\r
827\r
828//\r
829// Simple Text Input Ex protocol functions \r
830//\r
831/**\r
832 Resets the input device hardware.\r
833\r
834 The Reset() function resets the input device hardware. As part\r
835 of initialization process, the firmware/device will make a quick\r
836 but reasonable attempt to verify that the device is functioning.\r
837 If the ExtendedVerification flag is TRUE the firmware may take\r
838 an extended amount of time to verify the device is operating on\r
839 reset. Otherwise the reset operation is to occur as quickly as\r
840 possible. The hardware verification process is not defined by\r
841 this specification and is left up to the platform firmware or\r
842 driver to implement.\r
843\r
844 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.\r
845\r
846 @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
847 verification operation of the device during reset.\r
848\r
849 @retval EFI_SUCCESS The device was reset.\r
850 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.\r
851\r
852**/\r
853EFI_STATUS\r
854EFIAPI\r
855USBKeyboardResetEx (\r
856 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
857 IN BOOLEAN ExtendedVerification\r
858 )\r
859{\r
860 EFI_STATUS Status;\r
861 USB_KB_DEV *UsbKeyboardDevice;\r
862\r
863 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
864\r
865 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
866 if (EFI_ERROR (Status)) {\r
867 return EFI_DEVICE_ERROR;\r
868 }\r
869\r
870 return EFI_SUCCESS;\r
871\r
872}\r
873\r
874/**\r
875 Reads the next keystroke from the input device.\r
876\r
877 @param This Protocol instance pointer.\r
878 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
879 state data for the key that was pressed.\r
880\r
881 @retval EFI_SUCCESS The keystroke information was returned.\r
882 @retval EFI_NOT_READY There was no keystroke data available.\r
883 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
884 hardware errors.\r
885 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
886\r
887**/\r
888EFI_STATUS\r
889EFIAPI\r
890USBKeyboardReadKeyStrokeEx (\r
891 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
892 OUT EFI_KEY_DATA *KeyData\r
893 )\r
894{\r
895 USB_KB_DEV *UsbKeyboardDevice;\r
896\r
897 if (KeyData == NULL) {\r
898 return EFI_INVALID_PARAMETER;\r
899 }\r
900\r
901 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
902\r
903 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
904 \r
905}\r
906\r
907/**\r
908 Set certain state for the input device.\r
909\r
910 @param This Protocol instance pointer.\r
911 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
912 state for the input device.\r
913\r
914 @retval EFI_SUCCESS The device state was set appropriately.\r
915 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could\r
916 not have the setting adjusted.\r
917 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.\r
918 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
919\r
920**/\r
921EFI_STATUS\r
922EFIAPI\r
923USBKeyboardSetState (\r
924 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
925 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
926 )\r
927{\r
928 USB_KB_DEV *UsbKeyboardDevice;\r
929\r
930 if (KeyToggleState == NULL) {\r
931 return EFI_INVALID_PARAMETER;\r
932 }\r
933\r
934 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
935\r
936 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
937 return EFI_UNSUPPORTED;\r
938 }\r
939\r
940 //\r
941 // Update the status light\r
942 //\r
943\r
944 UsbKeyboardDevice->ScrollOn = FALSE;\r
945 UsbKeyboardDevice->NumLockOn = FALSE;\r
946 UsbKeyboardDevice->CapsOn = FALSE;\r
947 \r
948 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
949 UsbKeyboardDevice->ScrollOn = TRUE;\r
950 }\r
951 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
952 UsbKeyboardDevice->NumLockOn = TRUE;\r
953 }\r
954 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
955 UsbKeyboardDevice->CapsOn = TRUE;\r
956 }\r
957\r
958 SetKeyLED (UsbKeyboardDevice);\r
959\r
960 return EFI_SUCCESS;\r
961 \r
962}\r
963\r
964/**\r
965 Register a notification function for a particular keystroke for the input device.\r
966\r
967 @param This Protocol instance pointer.\r
968 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
969 information data for the key that was pressed.\r
970 @param KeyNotificationFunction Points to the function to be called when the key\r
971 sequence is typed specified by KeyData.\r
972 @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
973\r
974 @retval EFI_SUCCESS The notification function was registered successfully.\r
975 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.\r
976 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
977\r
978**/\r
979EFI_STATUS\r
980EFIAPI\r
981USBKeyboardRegisterKeyNotify (\r
982 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
983 IN EFI_KEY_DATA *KeyData,\r
984 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
985 OUT EFI_HANDLE *NotifyHandle\r
986 )\r
987{\r
988 USB_KB_DEV *UsbKeyboardDevice;\r
989 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
990 LIST_ENTRY *Link;\r
991 LIST_ENTRY *NotifyList;\r
992 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
993\r
994 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
995 return EFI_INVALID_PARAMETER;\r
996 }\r
997\r
998 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
999\r
1000 //\r
1001 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
1002 //\r
1003 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1004 \r
1005 for (Link = GetFirstNode (NotifyList);\r
1006 !IsNull (NotifyList, Link);\r
1007 Link = GetNextNode (NotifyList, Link)) {\r
1008 CurrentNotify = CR (\r
1009 Link, \r
1010 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1011 NotifyEntry, \r
1012 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1013 );\r
1014 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
1015 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
1016 *NotifyHandle = CurrentNotify->NotifyHandle; \r
1017 return EFI_SUCCESS;\r
1018 }\r
1019 }\r
1020 }\r
1021 \r
1022 //\r
1023 // Allocate resource to save the notification function\r
1024 // \r
1025 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
1026 if (NewNotify == NULL) {\r
1027 return EFI_OUT_OF_RESOURCES;\r
1028 }\r
1029\r
1030 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
1031 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
1032 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
1033 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
1034 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
1035\r
1036\r
1037 *NotifyHandle = NewNotify->NotifyHandle; \r
1038 \r
1039 return EFI_SUCCESS;\r
1040 \r
1041}\r
1042\r
1043/**\r
1044 Remove a registered notification function from a particular keystroke.\r
1045\r
1046 @param This Protocol instance pointer.\r
1047 @param NotificationHandle The handle of the notification function being unregistered.\r
1048\r
1049 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
1050 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid\r
1051\r
1052**/\r
1053EFI_STATUS\r
1054EFIAPI\r
1055USBKeyboardUnregisterKeyNotify (\r
1056 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1057 IN EFI_HANDLE NotificationHandle\r
1058 )\r
1059{\r
1060 USB_KB_DEV *UsbKeyboardDevice;\r
1061 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1062 LIST_ENTRY *Link;\r
1063 LIST_ENTRY *NotifyList;\r
1064\r
1065 if (NotificationHandle == NULL) {\r
1066 return EFI_INVALID_PARAMETER;\r
1067 } \r
1068\r
1069 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
1070 return EFI_INVALID_PARAMETER;\r
1071 } \r
1072 \r
1073 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1074 \r
1075 //\r
1076 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.\r
1077 //\r
1078 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1079 for (Link = GetFirstNode (NotifyList);\r
1080 !IsNull (NotifyList, Link);\r
1081 Link = GetNextNode (NotifyList, Link)) {\r
1082 CurrentNotify = CR (\r
1083 Link, \r
1084 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1085 NotifyEntry, \r
1086 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1087 ); \r
1088 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
1089 //\r
1090 // Remove the notification function from NotifyList and free resources\r
1091 //\r
1092 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
1093\r
1094 FreePool (CurrentNotify); \r
1095 return EFI_SUCCESS;\r
1096 }\r
1097 }\r
1098\r
1099 //\r
1100 // Cannot find the matching entry in database.\r
1101 //\r
1102 return EFI_INVALID_PARAMETER; \r
1103}\r
1104\r