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