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