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