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