]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
MdeModulePkg/UsbKb: ReadKeyStrokeEx always return key state
[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 - 2018, 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 // Report Status Code to indicate that there is no USB keyboard\r
248 //\r
249 REPORT_STATUS_CODE (\r
250 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
251 (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED)\r
252 );\r
253 //\r
254 // No interrupt endpoint found, then return unsupported.\r
255 //\r
256 Status = EFI_UNSUPPORTED;\r
257 goto ErrorExit;\r
258 }\r
259\r
260 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
261 EFI_PROGRESS_CODE,\r
262 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED),\r
263 UsbKeyboardDevice->DevicePath\r
264 );\r
265\r
266 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
267 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
268 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
269\r
270 UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;\r
271 UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;\r
272 UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;\r
273 UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;\r
274 UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;\r
275\r
276 InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
277\r
278 Status = gBS->CreateEvent (\r
279 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
280 TPL_NOTIFY,\r
281 USBKeyboardTimerHandler,\r
282 UsbKeyboardDevice,\r
283 &UsbKeyboardDevice->TimerEvent\r
284 );\r
285 if (!EFI_ERROR (Status)) {\r
286 Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL);\r
287 }\r
288 if (EFI_ERROR (Status)) {\r
289 goto ErrorExit;\r
290 }\r
291\r
292 Status = gBS->CreateEvent (\r
293 EVT_NOTIFY_WAIT,\r
294 TPL_NOTIFY,\r
295 USBKeyboardWaitForKey,\r
296 UsbKeyboardDevice,\r
297 &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
298 );\r
299\r
300 if (EFI_ERROR (Status)) {\r
301 goto ErrorExit;\r
302 }\r
303\r
304 Status = gBS->CreateEvent (\r
305 EVT_NOTIFY_WAIT,\r
306 TPL_NOTIFY,\r
307 USBKeyboardWaitForKey,\r
308 UsbKeyboardDevice,\r
309 &(UsbKeyboardDevice->SimpleInput.WaitForKey)\r
310 );\r
311 if (EFI_ERROR (Status)) {\r
312 goto ErrorExit;\r
313 }\r
314\r
315 Status = gBS->CreateEvent (\r
316 EVT_NOTIFY_SIGNAL,\r
317 TPL_CALLBACK,\r
318 KeyNotifyProcessHandler,\r
319 UsbKeyboardDevice,\r
320 &UsbKeyboardDevice->KeyNotifyProcessEvent\r
321 );\r
322 if (EFI_ERROR (Status)) {\r
323 goto ErrorExit;\r
324 }\r
325\r
326 //\r
327 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol\r
328 // for the USB keyboard device.\r
329 // USB keyboard is a hot plug device, and expected to work immediately\r
330 // when plugging into system, other conventional console devices could\r
331 // distinguish it by its device path.\r
332 //\r
333 Status = gBS->InstallMultipleProtocolInterfaces (\r
334 &Controller,\r
335 &gEfiSimpleTextInProtocolGuid,\r
336 &UsbKeyboardDevice->SimpleInput,\r
337 &gEfiSimpleTextInputExProtocolGuid,\r
338 &UsbKeyboardDevice->SimpleInputEx,\r
339 NULL\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
342 goto ErrorExit;\r
343 }\r
344\r
345 UsbKeyboardDevice->ControllerHandle = Controller;\r
346 Status = InitKeyboardLayout (UsbKeyboardDevice);\r
347 if (EFI_ERROR (Status)) {\r
348 gBS->UninstallMultipleProtocolInterfaces (\r
349 Controller,\r
350 &gEfiSimpleTextInProtocolGuid,\r
351 &UsbKeyboardDevice->SimpleInput,\r
352 &gEfiSimpleTextInputExProtocolGuid,\r
353 &UsbKeyboardDevice->SimpleInputEx,\r
354 NULL\r
355 );\r
356 goto ErrorExit;\r
357 }\r
358\r
359\r
360 //\r
361 // Reset USB Keyboard Device exhaustively.\r
362 //\r
363 Status = UsbKeyboardDevice->SimpleInputEx.Reset (\r
364 &UsbKeyboardDevice->SimpleInputEx,\r
365 TRUE\r
366 );\r
367 if (EFI_ERROR (Status)) {\r
368 gBS->UninstallMultipleProtocolInterfaces (\r
369 Controller,\r
370 &gEfiSimpleTextInProtocolGuid,\r
371 &UsbKeyboardDevice->SimpleInput,\r
372 &gEfiSimpleTextInputExProtocolGuid,\r
373 &UsbKeyboardDevice->SimpleInputEx,\r
374 NULL\r
375 );\r
376 goto ErrorExit;\r
377 }\r
378\r
379 //\r
380 // Submit Asynchronous Interrupt Transfer to manage this device.\r
381 //\r
382 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;\r
383 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;\r
384 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
385\r
386 Status = UsbIo->UsbAsyncInterruptTransfer (\r
387 UsbIo,\r
388 EndpointAddr,\r
389 TRUE,\r
390 PollingInterval,\r
391 PacketSize,\r
392 KeyboardHandler,\r
393 UsbKeyboardDevice\r
394 );\r
395\r
396 if (EFI_ERROR (Status)) {\r
397 gBS->UninstallMultipleProtocolInterfaces (\r
398 Controller,\r
399 &gEfiSimpleTextInProtocolGuid,\r
400 &UsbKeyboardDevice->SimpleInput,\r
401 &gEfiSimpleTextInputExProtocolGuid,\r
402 &UsbKeyboardDevice->SimpleInputEx,\r
403 NULL\r
404 );\r
405 goto ErrorExit;\r
406 }\r
407\r
408 UsbKeyboardDevice->ControllerNameTable = NULL;\r
409 AddUnicodeString2 (\r
410 "eng",\r
411 gUsbKeyboardComponentName.SupportedLanguages,\r
412 &UsbKeyboardDevice->ControllerNameTable,\r
413 L"Generic Usb Keyboard",\r
414 TRUE\r
415 );\r
416 AddUnicodeString2 (\r
417 "en",\r
418 gUsbKeyboardComponentName2.SupportedLanguages,\r
419 &UsbKeyboardDevice->ControllerNameTable,\r
420 L"Generic Usb Keyboard",\r
421 FALSE\r
422 );\r
423\r
424 gBS->RestoreTPL (OldTpl);\r
425 return EFI_SUCCESS;\r
426\r
427//\r
428// Error handler\r
429//\r
430ErrorExit:\r
431 if (UsbKeyboardDevice != NULL) {\r
432 if (UsbKeyboardDevice->TimerEvent != NULL) {\r
433 gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
434 }\r
435 if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
436 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
437 }\r
438 if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
439 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
440 }\r
441 if (UsbKeyboardDevice->KeyNotifyProcessEvent != NULL) {\r
442 gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
443 }\r
444 if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) {\r
445 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
446 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
447 }\r
448 FreePool (UsbKeyboardDevice);\r
449 UsbKeyboardDevice = NULL;\r
450 }\r
451 gBS->CloseProtocol (\r
452 Controller,\r
453 &gEfiUsbIoProtocolGuid,\r
454 This->DriverBindingHandle,\r
455 Controller\r
456 );\r
457\r
458ErrorExit1:\r
459 gBS->RestoreTPL (OldTpl);\r
460\r
461 return Status;\r
462\r
463}\r
464\r
465\r
466/**\r
467 Stop the USB keyboard device handled by this driver.\r
468\r
469 @param This The USB keyboard driver binding protocol.\r
470 @param Controller The controller to release.\r
471 @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
472 @param ChildHandleBuffer The array of child handle.\r
473\r
474 @retval EFI_SUCCESS The device was stopped.\r
475 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol\r
476 is not installed on Controller.\r
477 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
478 @retval Others Fail to uninstall protocols attached on the device.\r
479\r
480**/\r
481EFI_STATUS\r
482EFIAPI\r
483USBKeyboardDriverBindingStop (\r
484 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
485 IN EFI_HANDLE Controller,\r
486 IN UINTN NumberOfChildren,\r
487 IN EFI_HANDLE *ChildHandleBuffer\r
488 )\r
489{\r
490 EFI_STATUS Status;\r
491 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
492 USB_KB_DEV *UsbKeyboardDevice;\r
493\r
494 Status = gBS->OpenProtocol (\r
495 Controller,\r
496 &gEfiSimpleTextInProtocolGuid,\r
497 (VOID **) &SimpleInput,\r
498 This->DriverBindingHandle,\r
499 Controller,\r
500 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
501 );\r
502 if (EFI_ERROR (Status)) {\r
503 return EFI_UNSUPPORTED;\r
504 }\r
505\r
506 Status = gBS->OpenProtocol (\r
507 Controller,\r
508 &gEfiSimpleTextInputExProtocolGuid,\r
509 NULL,\r
510 This->DriverBindingHandle,\r
511 Controller,\r
512 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
513 );\r
514 if (EFI_ERROR (Status)) {\r
515 return EFI_UNSUPPORTED;\r
516 }\r
517\r
518 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
519\r
520 //\r
521 // The key data input from this device will be disabled.\r
522 //\r
523 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
524 EFI_PROGRESS_CODE,\r
525 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE),\r
526 UsbKeyboardDevice->DevicePath\r
527 );\r
528\r
529 //\r
530 // Delete the Asynchronous Interrupt Transfer from this device\r
531 //\r
532 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (\r
533 UsbKeyboardDevice->UsbIo,\r
534 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
535 FALSE,\r
536 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
537 0,\r
538 NULL,\r
539 NULL\r
540 );\r
541\r
542 gBS->CloseProtocol (\r
543 Controller,\r
544 &gEfiUsbIoProtocolGuid,\r
545 This->DriverBindingHandle,\r
546 Controller\r
547 );\r
548\r
549 Status = gBS->UninstallMultipleProtocolInterfaces (\r
550 Controller,\r
551 &gEfiSimpleTextInProtocolGuid,\r
552 &UsbKeyboardDevice->SimpleInput,\r
553 &gEfiSimpleTextInputExProtocolGuid,\r
554 &UsbKeyboardDevice->SimpleInputEx,\r
555 NULL\r
556 );\r
557 //\r
558 // Free all resources.\r
559 //\r
560 gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
561 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
562 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
563 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
564 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
565 gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
566 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);\r
567\r
568 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
569 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
570\r
571 if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
572 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
573 }\r
574\r
575 DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);\r
576 DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);\r
577 DestroyQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify);\r
578\r
579 FreePool (UsbKeyboardDevice);\r
580\r
581 return Status;\r
582}\r
583\r
584/**\r
585 Internal function to read the next keystroke from the keyboard buffer.\r
586\r
587 @param UsbKeyboardDevice USB keyboard's private structure.\r
588 @param KeyData A pointer to buffer to hold the keystroke\r
589 data for the key that was pressed.\r
590\r
591 @retval EFI_SUCCESS The keystroke information was returned.\r
592 @retval EFI_NOT_READY There was no keystroke data availiable.\r
593 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
594 hardware errors.\r
595 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
596 @retval Others Fail to translate keycode into EFI_INPUT_KEY\r
597\r
598**/\r
599EFI_STATUS\r
600USBKeyboardReadKeyStrokeWorker (\r
601 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
602 OUT EFI_KEY_DATA *KeyData\r
603 )\r
604{\r
605 if (KeyData == NULL) {\r
606 return EFI_INVALID_PARAMETER;\r
607 }\r
608\r
609 if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
610 ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
611 InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);\r
612 return EFI_NOT_READY;\r
613 }\r
614\r
615 Dequeue (&UsbKeyboardDevice->EfiKeyQueue, KeyData, sizeof (*KeyData));\r
616\r
617 return EFI_SUCCESS;\r
618}\r
619\r
620/**\r
621 Reset the input device and optionally run diagnostics\r
622\r
623 There are 2 types of reset for USB keyboard.\r
624 For non-exhaustive reset, only keyboard buffer is cleared.\r
625 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status\r
626 is also re-initialized.\r
627\r
628 @param This Protocol instance pointer.\r
629 @param ExtendedVerification Driver may perform diagnostics on reset.\r
630\r
631 @retval EFI_SUCCESS The device was reset.\r
632 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.\r
633\r
634**/\r
635EFI_STATUS\r
636EFIAPI\r
637USBKeyboardReset (\r
638 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
639 IN BOOLEAN ExtendedVerification\r
640 )\r
641{\r
642 EFI_STATUS Status;\r
643 USB_KB_DEV *UsbKeyboardDevice;\r
644\r
645 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
646\r
647 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
648 EFI_PROGRESS_CODE,\r
649 (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET),\r
650 UsbKeyboardDevice->DevicePath\r
651 );\r
652\r
653 //\r
654 // Non-exhaustive reset:\r
655 // only reset private data structures.\r
656 //\r
657 if (!ExtendedVerification) {\r
658 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
659 EFI_PROGRESS_CODE,\r
660 (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER),\r
661 UsbKeyboardDevice->DevicePath\r
662 );\r
663 //\r
664 // Clear the key buffer of this USB keyboard\r
665 //\r
666 InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));\r
667 InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));\r
668 InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));\r
669\r
670 return EFI_SUCCESS;\r
671 }\r
672\r
673 //\r
674 // Exhaustive reset\r
675 //\r
676 Status = InitUSBKeyboard (UsbKeyboardDevice);\r
677 if (EFI_ERROR (Status)) {\r
678 return EFI_DEVICE_ERROR;\r
679 }\r
680\r
681 return EFI_SUCCESS;\r
682}\r
683\r
684\r
685/**\r
686 Reads the next keystroke from the input device.\r
687\r
688 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
689 @param Key A pointer to a buffer that is filled in with the keystroke\r
690 information for the key that was pressed.\r
691\r
692 @retval EFI_SUCCESS The keystroke information was returned.\r
693 @retval EFI_NOT_READY There was no keystroke data availiable.\r
694 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
695 hardware errors.\r
696\r
697**/\r
698EFI_STATUS\r
699EFIAPI\r
700USBKeyboardReadKeyStroke (\r
701 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
702 OUT EFI_INPUT_KEY *Key\r
703 )\r
704{\r
705 USB_KB_DEV *UsbKeyboardDevice;\r
706 EFI_STATUS Status;\r
707 EFI_KEY_DATA KeyData;\r
708\r
709 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
710\r
711 //\r
712 // Considering if the partial keystroke is enabled, there maybe a partial\r
713 // keystroke in the queue, so here skip the partial keystroke and get the\r
714 // next key from the queue\r
715 //\r
716 while (1) {\r
717 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
718 if (EFI_ERROR (Status)) {\r
719 return Status;\r
720 }\r
721 //\r
722 // SimpleTextIn Protocol doesn't support partial keystroke;\r
723 //\r
724 if (KeyData.Key.ScanCode == CHAR_NULL && KeyData.Key.UnicodeChar == SCAN_NULL) {\r
725 continue;\r
726 }\r
727 //\r
728 // Translate the CTRL-Alpha characters to their corresponding control value\r
729 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
730 //\r
731 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
732 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
733 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
734 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
735 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
736 }\r
737 }\r
738\r
739 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
740 return EFI_SUCCESS;\r
741 }\r
742}\r
743\r
744\r
745/**\r
746 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx\r
747 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.\r
748\r
749 @param Event Event to be signaled when a key is pressed.\r
750 @param Context Points to USB_KB_DEV instance.\r
751\r
752**/\r
753VOID\r
754EFIAPI\r
755USBKeyboardWaitForKey (\r
756 IN EFI_EVENT Event,\r
757 IN VOID *Context\r
758 )\r
759{\r
760 USB_KB_DEV *UsbKeyboardDevice;\r
761 EFI_KEY_DATA KeyData;\r
762 EFI_TPL OldTpl;\r
763\r
764 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
765\r
766 //\r
767 // Enter critical section\r
768 // \r
769 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
770 \r
771 //\r
772 // WaitforKey doesn't suppor the partial key.\r
773 // Considering if the partial keystroke is enabled, there maybe a partial\r
774 // keystroke in the queue, so here skip the partial keystroke and get the\r
775 // next key from the queue\r
776 //\r
777 while (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
778 //\r
779 // If there is pending key, signal the event.\r
780 //\r
781 CopyMem (\r
782 &KeyData,\r
783 UsbKeyboardDevice->EfiKeyQueue.Buffer[UsbKeyboardDevice->EfiKeyQueue.Head],\r
784 sizeof (EFI_KEY_DATA)\r
785 );\r
786 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {\r
787 Dequeue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (EFI_KEY_DATA));\r
788 continue;\r
789 }\r
790 gBS->SignalEvent (Event);\r
791 break;\r
792 }\r
793 //\r
794 // Leave critical section and return\r
795 //\r
796 gBS->RestoreTPL (OldTpl);\r
797}\r
798\r
799/**\r
800 Timer handler to convert the key from USB.\r
801\r
802 @param Event Indicates the event that invoke this function.\r
803 @param Context Indicates the calling context.\r
804**/\r
805VOID\r
806EFIAPI\r
807USBKeyboardTimerHandler (\r
808 IN EFI_EVENT Event,\r
809 IN VOID *Context\r
810 )\r
811{\r
812 EFI_STATUS Status;\r
813 USB_KB_DEV *UsbKeyboardDevice;\r
814 UINT8 KeyCode;\r
815 EFI_KEY_DATA KeyData;\r
816\r
817 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
818\r
819 //\r
820 // Fetch raw data from the USB keyboard buffer,\r
821 // and translate it into USB keycode.\r
822 //\r
823 Status = USBParseKey (UsbKeyboardDevice, &KeyCode);\r
824 if (EFI_ERROR (Status)) {\r
825 return ;\r
826 }\r
827\r
828 //\r
829 // Translate saved USB keycode into EFI_INPUT_KEY\r
830 //\r
831 Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData);\r
832 if (EFI_ERROR (Status)) {\r
833 return ;\r
834 }\r
835\r
836 //\r
837 // Insert to the EFI Key queue\r
838 //\r
839 Enqueue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (KeyData));\r
840}\r
841\r
842/**\r
843 Free keyboard notify list.\r
844\r
845 @param NotifyList The keyboard notify list to free.\r
846\r
847 @retval EFI_SUCCESS Free the notify list successfully.\r
848 @retval EFI_INVALID_PARAMETER NotifyList is NULL.\r
849\r
850**/\r
851EFI_STATUS\r
852KbdFreeNotifyList (\r
853 IN OUT LIST_ENTRY *NotifyList\r
854 )\r
855{\r
856 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
857 LIST_ENTRY *Link;\r
858\r
859 if (NotifyList == NULL) {\r
860 return EFI_INVALID_PARAMETER;\r
861 }\r
862 while (!IsListEmpty (NotifyList)) {\r
863 Link = GetFirstNode (NotifyList);\r
864 NotifyNode = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
865 RemoveEntryList (Link);\r
866 FreePool (NotifyNode);\r
867 }\r
868\r
869 return EFI_SUCCESS;\r
870}\r
871\r
872/**\r
873 Check whether the pressed key matches a registered key or not.\r
874\r
875 @param RegsiteredData A pointer to keystroke data for the key that was registered.\r
876 @param InputData A pointer to keystroke data for the key that was pressed.\r
877\r
878 @retval TRUE Key pressed matches a registered key.\r
879 @retval FLASE Key pressed does not matches a registered key.\r
880\r
881**/\r
882BOOLEAN\r
883IsKeyRegistered (\r
884 IN EFI_KEY_DATA *RegsiteredData,\r
885 IN EFI_KEY_DATA *InputData\r
886 )\r
887{\r
888 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
889\r
890 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
891 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
892 return FALSE;\r
893 }\r
894\r
895 //\r
896 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
897 //\r
898 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
899 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
900 return FALSE;\r
901 }\r
902 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
903 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
904 return FALSE;\r
905 }\r
906\r
907 return TRUE;\r
908}\r
909\r
910//\r
911// Simple Text Input Ex protocol functions\r
912//\r
913/**\r
914 Resets the input device hardware.\r
915\r
916 The Reset() function resets the input device hardware. As part\r
917 of initialization process, the firmware/device will make a quick\r
918 but reasonable attempt to verify that the device is functioning.\r
919 If the ExtendedVerification flag is TRUE the firmware may take\r
920 an extended amount of time to verify the device is operating on\r
921 reset. Otherwise the reset operation is to occur as quickly as\r
922 possible. The hardware verification process is not defined by\r
923 this specification and is left up to the platform firmware or\r
924 driver to implement.\r
925\r
926 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.\r
927\r
928 @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
929 verification operation of the device during reset.\r
930\r
931 @retval EFI_SUCCESS The device was reset.\r
932 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.\r
933\r
934**/\r
935EFI_STATUS\r
936EFIAPI\r
937USBKeyboardResetEx (\r
938 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
939 IN BOOLEAN ExtendedVerification\r
940 )\r
941{\r
942 EFI_STATUS Status;\r
943 USB_KB_DEV *UsbKeyboardDevice;\r
944\r
945 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
946\r
947 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
948 if (EFI_ERROR (Status)) {\r
949 return EFI_DEVICE_ERROR;\r
950 }\r
951\r
952 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
953 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
954\r
955 return EFI_SUCCESS;\r
956\r
957}\r
958\r
959/**\r
960 Reads the next keystroke from the input device.\r
961\r
962 @param This Protocol instance pointer.\r
963 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
964 state data for the key that was pressed.\r
965\r
966 @retval EFI_SUCCESS The keystroke information was returned.\r
967 @retval EFI_NOT_READY There was no keystroke data available.\r
968 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
969 hardware errors.\r
970 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
971\r
972**/\r
973EFI_STATUS\r
974EFIAPI\r
975USBKeyboardReadKeyStrokeEx (\r
976 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
977 OUT EFI_KEY_DATA *KeyData\r
978 )\r
979{\r
980 USB_KB_DEV *UsbKeyboardDevice;\r
981\r
982 if (KeyData == NULL) {\r
983 return EFI_INVALID_PARAMETER;\r
984 }\r
985\r
986 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
987\r
988 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
989\r
990}\r
991\r
992/**\r
993 Set certain state for the input device.\r
994\r
995 @param This Protocol instance pointer.\r
996 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
997 state for the input device.\r
998\r
999 @retval EFI_SUCCESS The device state was set appropriately.\r
1000 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could\r
1001 not have the setting adjusted.\r
1002 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.\r
1003 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
1004\r
1005**/\r
1006EFI_STATUS\r
1007EFIAPI\r
1008USBKeyboardSetState (\r
1009 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1010 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
1011 )\r
1012{\r
1013 USB_KB_DEV *UsbKeyboardDevice;\r
1014\r
1015 if (KeyToggleState == NULL) {\r
1016 return EFI_INVALID_PARAMETER;\r
1017 }\r
1018\r
1019 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1020\r
1021 if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
1022 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
1023 return EFI_UNSUPPORTED;\r
1024 }\r
1025\r
1026 //\r
1027 // Update the status light\r
1028 //\r
1029\r
1030 UsbKeyboardDevice->ScrollOn = FALSE;\r
1031 UsbKeyboardDevice->NumLockOn = FALSE;\r
1032 UsbKeyboardDevice->CapsOn = FALSE;\r
1033 UsbKeyboardDevice->IsSupportPartialKey = FALSE;\r
1034\r
1035 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
1036 UsbKeyboardDevice->ScrollOn = TRUE;\r
1037 }\r
1038 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
1039 UsbKeyboardDevice->NumLockOn = TRUE;\r
1040 }\r
1041 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
1042 UsbKeyboardDevice->CapsOn = TRUE;\r
1043 }\r
1044 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {\r
1045 UsbKeyboardDevice->IsSupportPartialKey = TRUE;\r
1046 }\r
1047\r
1048 SetKeyLED (UsbKeyboardDevice);\r
1049\r
1050 UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
1051\r
1052 return EFI_SUCCESS;\r
1053\r
1054}\r
1055\r
1056/**\r
1057 Register a notification function for a particular keystroke for the input device.\r
1058\r
1059 @param This Protocol instance pointer.\r
1060 @param KeyData A pointer to a buffer that is filled in with\r
1061 the keystroke information for the key that was\r
1062 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState\r
1063 and KeyData.KeyState.KeyShiftState are 0, then any incomplete\r
1064 keystroke will trigger a notification of the KeyNotificationFunction.\r
1065 @param KeyNotificationFunction Points to the function to be called when the key\r
1066 sequence is typed specified by KeyData. This notification function\r
1067 should be called at <=TPL_CALLBACK.\r
1068 @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
1069\r
1070 @retval EFI_SUCCESS The notification function was registered successfully.\r
1071 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.\r
1072 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
1073\r
1074**/\r
1075EFI_STATUS\r
1076EFIAPI\r
1077USBKeyboardRegisterKeyNotify (\r
1078 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1079 IN EFI_KEY_DATA *KeyData,\r
1080 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
1081 OUT VOID **NotifyHandle\r
1082 )\r
1083{\r
1084 USB_KB_DEV *UsbKeyboardDevice;\r
1085 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
1086 LIST_ENTRY *Link;\r
1087 LIST_ENTRY *NotifyList;\r
1088 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1089\r
1090 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
1091 return EFI_INVALID_PARAMETER;\r
1092 }\r
1093\r
1094 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1095\r
1096 //\r
1097 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
1098 //\r
1099 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1100\r
1101 for (Link = GetFirstNode (NotifyList);\r
1102 !IsNull (NotifyList, Link);\r
1103 Link = GetNextNode (NotifyList, Link)) {\r
1104 CurrentNotify = CR (\r
1105 Link,\r
1106 KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
1107 NotifyEntry,\r
1108 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1109 );\r
1110 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
1111 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
1112 *NotifyHandle = CurrentNotify;\r
1113 return EFI_SUCCESS;\r
1114 }\r
1115 }\r
1116 }\r
1117\r
1118 //\r
1119 // Allocate resource to save the notification function\r
1120 //\r
1121 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
1122 if (NewNotify == NULL) {\r
1123 return EFI_OUT_OF_RESOURCES;\r
1124 }\r
1125\r
1126 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
1127 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
1128 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
1129 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
1130\r
1131\r
1132 *NotifyHandle = NewNotify;\r
1133\r
1134 return EFI_SUCCESS;\r
1135\r
1136}\r
1137\r
1138/**\r
1139 Remove a registered notification function from a particular keystroke.\r
1140\r
1141 @param This Protocol instance pointer.\r
1142 @param NotificationHandle The handle of the notification function being unregistered.\r
1143\r
1144 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
1145 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid\r
1146\r
1147**/\r
1148EFI_STATUS\r
1149EFIAPI\r
1150USBKeyboardUnregisterKeyNotify (\r
1151 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1152 IN VOID *NotificationHandle\r
1153 )\r
1154{\r
1155 USB_KB_DEV *UsbKeyboardDevice;\r
1156 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1157 LIST_ENTRY *Link;\r
1158 LIST_ENTRY *NotifyList;\r
1159\r
1160 if (NotificationHandle == NULL) {\r
1161 return EFI_INVALID_PARAMETER;\r
1162 }\r
1163\r
1164 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1165\r
1166 //\r
1167 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.\r
1168 //\r
1169 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1170 for (Link = GetFirstNode (NotifyList);\r
1171 !IsNull (NotifyList, Link);\r
1172 Link = GetNextNode (NotifyList, Link)) {\r
1173 CurrentNotify = CR (\r
1174 Link,\r
1175 KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
1176 NotifyEntry,\r
1177 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1178 );\r
1179 if (CurrentNotify == NotificationHandle) {\r
1180 //\r
1181 // Remove the notification function from NotifyList and free resources\r
1182 //\r
1183 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
1184\r
1185 FreePool (CurrentNotify);\r
1186 return EFI_SUCCESS;\r
1187 }\r
1188 }\r
1189\r
1190 //\r
1191 // Cannot find the matching entry in database.\r
1192 //\r
1193 return EFI_INVALID_PARAMETER;\r
1194}\r
1195\r
1196/**\r
1197 Process key notify.\r
1198\r
1199 @param Event Indicates the event that invoke this function.\r
1200 @param Context Indicates the calling context.\r
1201**/\r
1202VOID\r
1203EFIAPI\r
1204KeyNotifyProcessHandler (\r
1205 IN EFI_EVENT Event,\r
1206 IN VOID *Context\r
1207 )\r
1208{\r
1209 EFI_STATUS Status;\r
1210 USB_KB_DEV *UsbKeyboardDevice;\r
1211 EFI_KEY_DATA KeyData;\r
1212 LIST_ENTRY *Link;\r
1213 LIST_ENTRY *NotifyList;\r
1214 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1215 EFI_TPL OldTpl;\r
1216\r
1217 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
1218\r
1219 //\r
1220 // Invoke notification functions.\r
1221 //\r
1222 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1223 while (TRUE) {\r
1224 //\r
1225 // Enter critical section\r
1226 // \r
1227 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1228 Status = Dequeue (&UsbKeyboardDevice->EfiKeyQueueForNotify, &KeyData, sizeof (KeyData));\r
1229 //\r
1230 // Leave critical section\r
1231 //\r
1232 gBS->RestoreTPL (OldTpl);\r
1233 if (EFI_ERROR (Status)) {\r
1234 break;\r
1235 }\r
1236 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
1237 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
1238 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
1239 CurrentNotify->KeyNotificationFn (&KeyData);\r
1240 }\r
1241 }\r
1242 }\r
1243}\r
1244\r