]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
Install default keyboard layout package in USB keyboard driver.
[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
813acf3a 5Copyright (c) 2004 - 2008, Intel Corporation\r
ed838d0c 6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
a7022cec 14**/\r
ed838d0c 15\r
a7022cec 16#include "EfiKey.h"\r
17#include "KeyBoard.h"\r
ed838d0c 18\r
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
5899f27e 196 PcdGet32 (PcdStatusCodeValueKeyboardEnable),\r
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
5899f27e 205 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect),\r
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
323 Status = UsbKeyboardDevice->SimpleInput.Reset (\r
324 &UsbKeyboardDevice->SimpleInput,\r
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
c92e277d 397 FreePool (UsbKeyboardDevice);\r
66aa04e4 398 UsbKeyboardDevice = NULL;\r
399 }\r
400 gBS->CloseProtocol (\r
401 Controller,\r
402 &gEfiUsbIoProtocolGuid,\r
403 This->DriverBindingHandle,\r
404 Controller\r
405 );\r
406 return Status;\r
407\r
ed838d0c 408}\r
409\r
410\r
ed838d0c 411/**\r
b4e73a63 412 Stop the USB keyboard device handled by this driver.\r
ed838d0c 413\r
a7022cec 414 @param This The USB keyboard driver binding protocol.\r
415 @param Controller The controller to release.\r
416 @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
417 @param ChildHandleBuffer The array of child handle.\r
ed838d0c 418\r
b4e73a63 419 @retval EFI_SUCCESS The device was stopped.\r
5899f27e 420 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol\r
421 is not installed on Controller.\r
b4e73a63 422 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
423 @retval Others Fail to uninstall protocols attached on the device.\r
ed838d0c 424\r
425**/\r
426EFI_STATUS\r
427EFIAPI\r
428USBKeyboardDriverBindingStop (\r
429 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
430 IN EFI_HANDLE Controller,\r
431 IN UINTN NumberOfChildren,\r
432 IN EFI_HANDLE *ChildHandleBuffer\r
433 )\r
434{\r
5899f27e 435 EFI_STATUS Status;\r
ed838d0c 436 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
5899f27e 437 USB_KB_DEV *UsbKeyboardDevice;\r
ed838d0c 438\r
439 Status = gBS->OpenProtocol (\r
440 Controller,\r
441 &gEfiSimpleTextInProtocolGuid,\r
c52fa98c 442 (VOID **) &SimpleInput,\r
ed838d0c 443 This->DriverBindingHandle,\r
444 Controller,\r
bcb9d421 445 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
ed838d0c 446 );\r
447 if (EFI_ERROR (Status)) {\r
448 return EFI_UNSUPPORTED;\r
449 }\r
5899f27e 450\r
66aa04e4 451 Status = gBS->OpenProtocol (\r
452 Controller,\r
453 &gEfiSimpleTextInputExProtocolGuid,\r
454 NULL,\r
455 This->DriverBindingHandle,\r
456 Controller,\r
457 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
458 );\r
459 if (EFI_ERROR (Status)) {\r
460 return EFI_UNSUPPORTED;\r
461 }\r
b4e73a63 462\r
ed838d0c 463 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
464\r
ed838d0c 465 //\r
5899f27e 466 // The key data input from this device will be disabled.\r
ed838d0c 467 //\r
5899f27e 468 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 469 EFI_PROGRESS_CODE,\r
5899f27e 470 PcdGet32 (PcdStatusCodeValueKeyboardDisable),\r
471 UsbKeyboardDevice->DevicePath\r
ed838d0c 472 );\r
473\r
474 //\r
5899f27e 475 // Delete the Asynchronous Interrupt Transfer from this device\r
ed838d0c 476 //\r
477 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (\r
478 UsbKeyboardDevice->UsbIo,\r
479 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
480 FALSE,\r
481 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
482 0,\r
483 NULL,\r
484 NULL\r
485 );\r
486\r
487 gBS->CloseProtocol (\r
5899f27e 488 Controller,\r
489 &gEfiUsbIoProtocolGuid,\r
490 This->DriverBindingHandle,\r
491 Controller\r
492 );\r
ed838d0c 493\r
494 Status = gBS->UninstallMultipleProtocolInterfaces (\r
495 Controller,\r
496 &gEfiSimpleTextInProtocolGuid,\r
497 &UsbKeyboardDevice->SimpleInput,\r
66aa04e4 498 &gEfiSimpleTextInputExProtocolGuid,\r
499 &UsbKeyboardDevice->SimpleInputEx,\r
ed838d0c 500 NULL\r
501 );\r
502 //\r
5899f27e 503 // Free all resources.\r
ed838d0c 504 //\r
505 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
506 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
507 gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);\r
66aa04e4 508 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); \r
509 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
ed838d0c 510\r
813acf3a 511 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
512 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
513\r
ed838d0c 514 if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
515 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
516 }\r
517\r
c92e277d 518 FreePool (UsbKeyboardDevice);\r
ed838d0c 519\r
520 return Status;\r
ed838d0c 521}\r
522\r
a7022cec 523/**\r
b4e73a63 524 Internal function to read the next keystroke from the keyboard buffer.\r
a7022cec 525\r
b4e73a63 526 @param UsbKeyboardDevice USB keyboard's private structure.\r
527 @param KeyData A pointer to buffer to hold the keystroke\r
528 data for the key that was pressed.\r
a7022cec 529\r
b4e73a63 530 @retval EFI_SUCCESS The keystroke information was returned.\r
531 @retval EFI_NOT_READY There was no keystroke data availiable.\r
532 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
a7022cec 533 hardware errors.\r
b4e73a63 534 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
535 @retval Others Fail to translate keycode into EFI_INPUT_KEY\r
a7022cec 536\r
537**/\r
66aa04e4 538EFI_STATUS\r
a7022cec 539EFIAPI\r
66aa04e4 540USBKeyboardReadKeyStrokeWorker (\r
b4e73a63 541 IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
542 OUT EFI_KEY_DATA *KeyData\r
66aa04e4 543 )\r
66aa04e4 544{\r
66aa04e4 545 EFI_STATUS Status;\r
b4e73a63 546 UINT8 KeyCode; \r
66aa04e4 547 LIST_ENTRY *Link;\r
e15c65a3 548 LIST_ENTRY *NotifyList;\r
66aa04e4 549 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
550 EFI_KEY_DATA OriginalKeyData;\r
ed838d0c 551\r
66aa04e4 552 if (KeyData == NULL) {\r
553 return EFI_INVALID_PARAMETER;\r
554 }\r
555\r
556 //\r
b4e73a63 557 // If there is no saved USB keycode, fetch it\r
66aa04e4 558 // by calling USBKeyboardCheckForKey().\r
559 //\r
b4e73a63 560 if (UsbKeyboardDevice->CurKeyCode == 0) {\r
66aa04e4 561 Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
562 if (EFI_ERROR (Status)) {\r
5899f27e 563 return EFI_NOT_READY;\r
66aa04e4 564 }\r
565 }\r
566\r
567 KeyData->Key.UnicodeChar = 0;\r
568 KeyData->Key.ScanCode = SCAN_NULL;\r
569\r
5899f27e 570 //\r
b4e73a63 571 // Store the current keycode and clear it.\r
5899f27e 572 //\r
b4e73a63 573 KeyCode = UsbKeyboardDevice->CurKeyCode;\r
574 UsbKeyboardDevice->CurKeyCode = 0;\r
66aa04e4 575\r
576 //\r
b4e73a63 577 // Translate saved USB keycode into EFI_INPUT_KEY\r
66aa04e4 578 //\r
b4e73a63 579 Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData->Key);\r
66aa04e4 580 if (EFI_ERROR (Status)) {\r
581 return Status;\r
582 }\r
583\r
5899f27e 584 //\r
585 // Get current state of various toggled attributes as well as input modifier values,\r
586 // and set them as valid.\r
587 //\r
66aa04e4 588 CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));\r
589 \r
590 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
591 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
592\r
593 //\r
5899f27e 594 // Switch the control value to their original characters.\r
595 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to \r
596 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),\r
597 // here switch them back for notification function.\r
66aa04e4 598 //\r
599 CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
b4e73a63 600 if (UsbKeyboardDevice->CtrlOn) {\r
66aa04e4 601 if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
b4e73a63 602 if (UsbKeyboardDevice->CapsOn) {\r
66aa04e4 603 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);\r
604 } else {\r
605 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);\r
606 } \r
607 }\r
608 }\r
609 \r
610 //\r
5899f27e 611 // Invoke notification functions if the key is registered.\r
66aa04e4 612 //\r
e15c65a3 613 NotifyList = &UsbKeyboardDevice->NotifyList;\r
614 for (Link = GetFirstNode (NotifyList);\r
615 !IsNull (NotifyList, Link);\r
616 Link = GetNextNode (NotifyList, Link)) {\r
5899f27e 617 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
66aa04e4 618 if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
619 CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
620 }\r
621 }\r
622\r
623 return EFI_SUCCESS;\r
66aa04e4 624}\r
a7022cec 625\r
626/**\r
e15c65a3 627 Reset the input device and optionally run diagnostics\r
5899f27e 628\r
629 There are 2 types of reset for USB keyboard.\r
630 For non-exhaustive reset, only keyboard buffer is cleared.\r
631 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status\r
632 is also re-initialized.\r
a7022cec 633\r
b4e73a63 634 @param This Protocol instance pointer.\r
635 @param ExtendedVerification Driver may perform diagnostics on reset.\r
a7022cec 636\r
b4e73a63 637 @retval EFI_SUCCESS The device was reset.\r
638 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.\r
a7022cec 639\r
640**/\r
ed838d0c 641EFI_STATUS\r
642EFIAPI\r
643USBKeyboardReset (\r
644 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
5899f27e 645 IN BOOLEAN ExtendedVerification\r
ed838d0c 646 )\r
647{\r
648 EFI_STATUS Status;\r
649 USB_KB_DEV *UsbKeyboardDevice;\r
ed838d0c 650\r
651 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
652\r
5899f27e 653 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 654 EFI_PROGRESS_CODE,\r
5899f27e 655 PcdGet32 (PcdStatusCodeValueKeyboardReset),\r
656 UsbKeyboardDevice->DevicePath\r
ed838d0c 657 );\r
658\r
659 //\r
5899f27e 660 // Non-exhaustive reset:\r
ed838d0c 661 // only reset private data structures.\r
662 //\r
663 if (!ExtendedVerification) {\r
5899f27e 664 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 665 EFI_PROGRESS_CODE,\r
5899f27e 666 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer),\r
667 UsbKeyboardDevice->DevicePath\r
ed838d0c 668 );\r
5899f27e 669 //\r
670 // Clear the key buffer of this USB keyboard\r
671 //\r
ed838d0c 672 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
b4e73a63 673 UsbKeyboardDevice->CurKeyCode = 0;\r
5899f27e 674\r
ed838d0c 675 return EFI_SUCCESS;\r
676 }\r
677\r
678 //\r
679 // Exhaustive reset\r
680 //\r
5899f27e 681 Status = InitUSBKeyboard (UsbKeyboardDevice);\r
b4e73a63 682 UsbKeyboardDevice->CurKeyCode = 0;\r
ed838d0c 683 if (EFI_ERROR (Status)) {\r
684 return EFI_DEVICE_ERROR;\r
685 }\r
686\r
687 return EFI_SUCCESS;\r
688}\r
689\r
690\r
691/**\r
b4e73a63 692 Reads the next keystroke from the input device.\r
ed838d0c 693\r
a7022cec 694 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
695 @param Key A pointer to a buffer that is filled in with the keystroke\r
696 information for the key that was pressed.\r
ed838d0c 697\r
b4e73a63 698 @retval EFI_SUCCESS The keystroke information was returned.\r
699 @retval EFI_NOT_READY There was no keystroke data availiable.\r
e15c65a3 700 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
b4e73a63 701 hardware errors.\r
ed838d0c 702\r
703**/\r
ed838d0c 704EFI_STATUS\r
705EFIAPI\r
706USBKeyboardReadKeyStroke (\r
707 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
5899f27e 708 OUT EFI_INPUT_KEY *Key\r
ed838d0c 709 )\r
710{\r
66aa04e4 711 USB_KB_DEV *UsbKeyboardDevice;\r
712 EFI_STATUS Status;\r
713 EFI_KEY_DATA KeyData;\r
ed838d0c 714\r
715 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
716\r
66aa04e4 717 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
718 if (EFI_ERROR (Status)) {\r
719 return Status;\r
ed838d0c 720 }\r
721\r
66aa04e4 722 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
ed838d0c 723\r
66aa04e4 724 return EFI_SUCCESS;\r
ed838d0c 725}\r
726\r
727\r
728/**\r
b4e73a63 729 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx\r
730 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.\r
ed838d0c 731\r
a7022cec 732 @param Event Event to be signaled when a key is pressed.\r
733 @param Context Points to USB_KB_DEV instance.\r
ed838d0c 734\r
735**/\r
ed838d0c 736VOID\r
737EFIAPI\r
738USBKeyboardWaitForKey (\r
739 IN EFI_EVENT Event,\r
740 IN VOID *Context\r
741 )\r
742{\r
743 USB_KB_DEV *UsbKeyboardDevice;\r
744\r
745 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
746\r
b4e73a63 747 if (UsbKeyboardDevice->CurKeyCode == 0) {\r
ed838d0c 748 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {\r
5899f27e 749 //\r
750 // If no pending key, simply return.\r
751 //\r
ed838d0c 752 return ;\r
753 }\r
754 }\r
755 //\r
5899f27e 756 // If there is pending key, signal the event.\r
ed838d0c 757 //\r
758 gBS->SignalEvent (Event);\r
759}\r
760\r
761\r
ed838d0c 762/**\r
b4e73a63 763 Check whether there is key pending in the keyboard buffer.\r
ed838d0c 764\r
a7022cec 765 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
ed838d0c 766\r
5899f27e 767 @retval EFI_SUCCESS There is pending key to read.\r
768 @retval EFI_NOT_READY No pending key to read.\r
ed838d0c 769\r
770**/\r
ed838d0c 771EFI_STATUS\r
a7022cec 772EFIAPI\r
ed838d0c 773USBKeyboardCheckForKey (\r
b4e73a63 774 IN OUT USB_KB_DEV *UsbKeyboardDevice\r
ed838d0c 775 )\r
776{\r
777 EFI_STATUS Status;\r
b4e73a63 778 UINT8 KeyCode;\r
ed838d0c 779\r
780 //\r
b4e73a63 781 // Fetch raw data from the USB keyboard buffer,\r
782 // and translate it into USB keycode.\r
ed838d0c 783 //\r
b4e73a63 784 Status = USBParseKey (UsbKeyboardDevice, &KeyCode);\r
ed838d0c 785 if (EFI_ERROR (Status)) {\r
5899f27e 786 return EFI_NOT_READY;\r
ed838d0c 787 }\r
788\r
b4e73a63 789 UsbKeyboardDevice->CurKeyCode = KeyCode;\r
ed838d0c 790 return EFI_SUCCESS;\r
791}\r
792\r
a7022cec 793/**\r
794 Free keyboard notify list.\r
66aa04e4 795\r
b4e73a63 796 @param NotifyList The keyboard notify list to free.\r
66aa04e4 797\r
a7022cec 798 @retval EFI_SUCCESS Free the notify list successfully.\r
b4e73a63 799 @retval EFI_INVALID_PARAMETER NotifyList is NULL.\r
66aa04e4 800\r
a7022cec 801**/\r
802EFI_STATUS\r
803EFIAPI\r
804KbdFreeNotifyList (\r
b4e73a63 805 IN OUT LIST_ENTRY *NotifyList\r
a7022cec 806 )\r
66aa04e4 807{\r
808 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
b4e73a63 809 LIST_ENTRY *Link;\r
66aa04e4 810\r
b4e73a63 811 if (NotifyList == NULL) {\r
66aa04e4 812 return EFI_INVALID_PARAMETER;\r
813 }\r
b4e73a63 814 while (!IsListEmpty (NotifyList)) {\r
815 Link = GetFirstNode (NotifyList);\r
816 NotifyNode = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
817 RemoveEntryList (Link);\r
c92e277d 818 FreePool (NotifyNode);\r
66aa04e4 819 }\r
820 \r
821 return EFI_SUCCESS;\r
822}\r
823\r
a7022cec 824/**\r
b4e73a63 825 Check whether the pressed key matches a registered key or not.\r
a7022cec 826\r
b4e73a63 827 @param RegsiteredData A pointer to keystroke data for the key that was registered.\r
828 @param InputData A pointer to keystroke data for the key that was pressed.\r
a7022cec 829\r
830 @retval TRUE Key pressed matches a registered key.\r
e15c65a3 831 @retval FLASE Key pressed does not matches a registered key.\r
a7022cec 832\r
833**/\r
66aa04e4 834BOOLEAN\r
a7022cec 835EFIAPI\r
66aa04e4 836IsKeyRegistered (\r
837 IN EFI_KEY_DATA *RegsiteredData,\r
838 IN EFI_KEY_DATA *InputData\r
839 )\r
66aa04e4 840{\r
841 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
842 \r
843 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
844 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
845 return FALSE; \r
846 } \r
847 \r
848 //\r
849 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
850 //\r
851 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
852 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
853 return FALSE; \r
854 } \r
855 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
856 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
857 return FALSE; \r
858 } \r
859 \r
860 return TRUE;\r
66aa04e4 861}\r
862\r
863//\r
864// Simple Text Input Ex protocol functions \r
865//\r
a7022cec 866/**\r
b4e73a63 867 Resets the input device hardware.\r
868\r
869 The Reset() function resets the input device hardware. As part\r
870 of initialization process, the firmware/device will make a quick\r
871 but reasonable attempt to verify that the device is functioning.\r
872 If the ExtendedVerification flag is TRUE the firmware may take\r
873 an extended amount of time to verify the device is operating on\r
874 reset. Otherwise the reset operation is to occur as quickly as\r
875 possible. The hardware verification process is not defined by\r
876 this specification and is left up to the platform firmware or\r
877 driver to implement.\r
a7022cec 878\r
b4e73a63 879 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.\r
a7022cec 880\r
b4e73a63 881 @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
882 verification operation of the device during reset.\r
883\r
884 @retval EFI_SUCCESS The device was reset.\r
885 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.\r
a7022cec 886\r
887**/\r
66aa04e4 888EFI_STATUS\r
889EFIAPI\r
890USBKeyboardResetEx (\r
891 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
892 IN BOOLEAN ExtendedVerification\r
893 )\r
66aa04e4 894{\r
895 EFI_STATUS Status;\r
896 USB_KB_DEV *UsbKeyboardDevice;\r
897 EFI_TPL OldTpl;\r
898 \r
899\r
900 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
901\r
902 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
903 if (EFI_ERROR (Status)) {\r
904 return EFI_DEVICE_ERROR;\r
905 }\r
906\r
907 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
908 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
909 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
910 gBS->RestoreTPL (OldTpl);\r
911\r
912 return EFI_SUCCESS;\r
913\r
914}\r
915\r
a7022cec 916/**\r
b4e73a63 917 Reads the next keystroke from the input device.\r
a7022cec 918\r
b4e73a63 919 @param This Protocol instance pointer.\r
920 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
921 state data for the key that was pressed.\r
a7022cec 922\r
b4e73a63 923 @retval EFI_SUCCESS The keystroke information was returned.\r
924 @retval EFI_NOT_READY There was no keystroke data available.\r
925 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
926 hardware errors.\r
927 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
a7022cec 928\r
929**/\r
66aa04e4 930EFI_STATUS\r
931EFIAPI\r
932USBKeyboardReadKeyStrokeEx (\r
933 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
934 OUT EFI_KEY_DATA *KeyData\r
935 )\r
66aa04e4 936{\r
937 USB_KB_DEV *UsbKeyboardDevice;\r
938\r
939 if (KeyData == NULL) {\r
940 return EFI_INVALID_PARAMETER;\r
941 }\r
942\r
943 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
944\r
945 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
946 \r
947}\r
948\r
a7022cec 949/**\r
950 Set certain state for the input device.\r
951\r
952 @param This Protocol instance pointer.\r
953 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
954 state for the input device.\r
955\r
b4e73a63 956 @retval EFI_SUCCESS The device state was set appropriately.\r
957 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could\r
958 not have the setting adjusted.\r
959 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.\r
a7022cec 960 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
961\r
962**/\r
66aa04e4 963EFI_STATUS\r
964EFIAPI\r
965USBKeyboardSetState (\r
966 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
967 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
968 )\r
66aa04e4 969{\r
970 USB_KB_DEV *UsbKeyboardDevice;\r
971\r
972 if (KeyToggleState == NULL) {\r
973 return EFI_INVALID_PARAMETER;\r
974 }\r
975\r
976 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
977\r
978 if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
979 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
980 return EFI_UNSUPPORTED;\r
981 }\r
982\r
983 //\r
984 // Update the status light\r
985 //\r
986\r
b4e73a63 987 UsbKeyboardDevice->ScrollOn = FALSE;\r
988 UsbKeyboardDevice->NumLockOn = FALSE;\r
989 UsbKeyboardDevice->CapsOn = FALSE;\r
66aa04e4 990 \r
991 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
b4e73a63 992 UsbKeyboardDevice->ScrollOn = TRUE;\r
66aa04e4 993 }\r
994 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
b4e73a63 995 UsbKeyboardDevice->NumLockOn = TRUE;\r
66aa04e4 996 }\r
997 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
b4e73a63 998 UsbKeyboardDevice->CapsOn = TRUE;\r
66aa04e4 999 }\r
1000\r
1001 SetKeyLED (UsbKeyboardDevice);\r
1002\r
1003 UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
1004\r
1005 return EFI_SUCCESS;\r
1006 \r
1007}\r
1008\r
a7022cec 1009/**\r
1010 Register a notification function for a particular keystroke for the input device.\r
1011\r
1012 @param This Protocol instance pointer.\r
1013 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
1014 information data for the key that was pressed.\r
1015 @param KeyNotificationFunction Points to the function to be called when the key\r
1016 sequence is typed specified by KeyData.\r
1017 @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
1018\r
1019 @retval EFI_SUCCESS The notification function was registered successfully.\r
e15c65a3 1020 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.\r
b4e73a63 1021 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
a7022cec 1022\r
1023**/\r
66aa04e4 1024EFI_STATUS\r
1025EFIAPI\r
1026USBKeyboardRegisterKeyNotify (\r
1027 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1028 IN EFI_KEY_DATA *KeyData,\r
1029 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
a7022cec 1030 OUT EFI_HANDLE *NotifyHandle\r
66aa04e4 1031 )\r
66aa04e4 1032{\r
1033 USB_KB_DEV *UsbKeyboardDevice;\r
66aa04e4 1034 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
1035 LIST_ENTRY *Link;\r
e15c65a3 1036 LIST_ENTRY *NotifyList;\r
66aa04e4 1037 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
1038\r
1039 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
1040 return EFI_INVALID_PARAMETER;\r
1041 }\r
1042\r
1043 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1044\r
1045 //\r
1046 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
1047 //\r
e15c65a3 1048 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1049 \r
1050 for (Link = GetFirstNode (NotifyList);\r
1051 !IsNull (NotifyList, Link);\r
1052 Link = GetNextNode (NotifyList, Link)) {\r
66aa04e4 1053 CurrentNotify = CR (\r
1054 Link, \r
1055 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1056 NotifyEntry, \r
1057 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1058 );\r
1059 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
1060 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
1061 *NotifyHandle = CurrentNotify->NotifyHandle; \r
1062 return EFI_SUCCESS;\r
1063 }\r
1064 }\r
1065 }\r
1066 \r
1067 //\r
1068 // Allocate resource to save the notification function\r
1069 // \r
1070 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
1071 if (NewNotify == NULL) {\r
1072 return EFI_OUT_OF_RESOURCES;\r
1073 }\r
1074\r
1075 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
1076 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
7fc80d44 1077 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
66aa04e4 1078 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
1079 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
1080\r
7fc80d44 1081\r
66aa04e4 1082 *NotifyHandle = NewNotify->NotifyHandle; \r
1083 \r
1084 return EFI_SUCCESS;\r
1085 \r
1086}\r
1087\r
a7022cec 1088/**\r
1089 Remove a registered notification function from a particular keystroke.\r
1090\r
1091 @param This Protocol instance pointer.\r
1092 @param NotificationHandle The handle of the notification function being unregistered.\r
1093\r
1094 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
b4e73a63 1095 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid\r
a7022cec 1096\r
1097**/\r
66aa04e4 1098EFI_STATUS\r
1099EFIAPI\r
1100USBKeyboardUnregisterKeyNotify (\r
1101 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1102 IN EFI_HANDLE NotificationHandle\r
1103 )\r
66aa04e4 1104{\r
1105 USB_KB_DEV *UsbKeyboardDevice;\r
66aa04e4 1106 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1107 LIST_ENTRY *Link;\r
e15c65a3 1108 LIST_ENTRY *NotifyList;\r
66aa04e4 1109\r
1110 if (NotificationHandle == NULL) {\r
1111 return EFI_INVALID_PARAMETER;\r
1112 } \r
0dc99784 1113\r
1114 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
1115 return EFI_INVALID_PARAMETER;\r
1116 } \r
66aa04e4 1117 \r
1118 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1119 \r
5899f27e 1120 //\r
1121 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.\r
1122 //\r
e15c65a3 1123 NotifyList = &UsbKeyboardDevice->NotifyList;\r
1124 for (Link = GetFirstNode (NotifyList);\r
1125 !IsNull (NotifyList, Link);\r
1126 Link = GetNextNode (NotifyList, Link)) {\r
66aa04e4 1127 CurrentNotify = CR (\r
1128 Link, \r
1129 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1130 NotifyEntry, \r
1131 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1132 ); \r
1133 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
1134 //\r
1135 // Remove the notification function from NotifyList and free resources\r
1136 //\r
1137 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
7fc80d44 1138\r
c92e277d 1139 FreePool (CurrentNotify); \r
66aa04e4 1140 return EFI_SUCCESS;\r
1141 }\r
1142 }\r
1143\r
8a67d804 1144 //\r
1145 // Cannot find the matching entry in database.\r
1146 //\r
1147 return EFI_INVALID_PARAMETER; \r
66aa04e4 1148}\r
1149\r