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