]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbKbDxe/EfiKey.c
GenFds will try to deduce 'Target_Toolchain_Arch' KeyStringList for GUIDed section.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / EfiKey.c
CommitLineData
ed838d0c 1/** @file\r
a7022cec 2 USB Keyboard Driver that includes the implementation of interface.\r
3\r
813acf3a 4Copyright (c) 2004 - 2008, Intel Corporation\r
ed838d0c 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
a7022cec 13**/\r
ed838d0c 14\r
a7022cec 15#include "EfiKey.h"\r
16#include "KeyBoard.h"\r
ed838d0c 17\r
ed838d0c 18//\r
19// USB Keyboard Driver Global Variables\r
20//\r
21EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {\r
22 USBKeyboardDriverBindingSupported,\r
23 USBKeyboardDriverBindingStart,\r
24 USBKeyboardDriverBindingStop,\r
25 0xa,\r
26 NULL,\r
27 NULL\r
28};\r
29\r
a7022cec 30/**\r
5899f27e 31 Entrypoint of USB Keyboard Driver.\r
32\r
33 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding\r
34 Protocols together with Component Name Protocols.\r
a7022cec 35\r
5899f27e 36 @param ImageHandle The firmware allocated handle for the EFI image.\r
37 @param SystemTable A pointer to the EFI System Table.\r
a7022cec 38\r
5899f27e 39 @retval EFI_SUCCESS The entry point is executed successfully.\r
a7022cec 40\r
41**/\r
ed838d0c 42EFI_STATUS\r
43EFIAPI\r
44USBKeyboardDriverBindingEntryPoint (\r
45 IN EFI_HANDLE ImageHandle,\r
46 IN EFI_SYSTEM_TABLE *SystemTable\r
47 )\r
ed838d0c 48{\r
5899f27e 49 EFI_STATUS Status;\r
50\r
51 Status = EfiLibInstallDriverBindingComponentName2 (\r
52 ImageHandle,\r
53 SystemTable,\r
54 &gUsbKeyboardDriverBinding,\r
55 ImageHandle,\r
56 &gUsbKeyboardComponentName,\r
57 &gUsbKeyboardComponentName2\r
58 );\r
59 ASSERT_EFI_ERROR (Status);\r
60\r
61 return EFI_SUCCESS;\r
ed838d0c 62}\r
63\r
ed838d0c 64/**\r
5899f27e 65 Check whether USB keyboard driver supports this device.\r
ed838d0c 66\r
a7022cec 67 @param This The USB keyboard driver binding protocol.\r
68 @param Controller The controller handle to check.\r
69 @param RemainingDevicePath The remaining device path.\r
ed838d0c 70\r
a7022cec 71 @retval EFI_SUCCESS The driver supports this controller.\r
5899f27e 72 @retval other This device isn't supported.\r
73\r
ed838d0c 74**/\r
75EFI_STATUS\r
76EFIAPI\r
77USBKeyboardDriverBindingSupported (\r
78 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
79 IN EFI_HANDLE Controller,\r
80 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
81 )\r
82{\r
ed838d0c 83 EFI_STATUS Status;\r
5899f27e 84 EFI_USB_IO_PROTOCOL *UsbIo;\r
ed838d0c 85\r
86 //\r
5899f27e 87 // Check if USB I/O Protocol is attached on the controller handle.\r
ed838d0c 88 //\r
5899f27e 89 Status = gBS->OpenProtocol (\r
90 Controller,\r
91 &gEfiUsbIoProtocolGuid,\r
92 (VOID **) &UsbIo,\r
93 This->DriverBindingHandle,\r
94 Controller,\r
95 EFI_OPEN_PROTOCOL_BY_DRIVER\r
96 );\r
97 if (EFI_ERROR (Status)) {\r
98 return Status;\r
ed838d0c 99 }\r
100\r
101 //\r
5899f27e 102 // Use the USB I/O Protocol interface to check whether the Controller is\r
ed838d0c 103 // the Keyboard controller that can be managed by this driver.\r
104 //\r
105 Status = EFI_SUCCESS;\r
106\r
107 if (!IsUSBKeyboard (UsbIo)) {\r
108 Status = EFI_UNSUPPORTED;\r
109 }\r
110\r
111 gBS->CloseProtocol (\r
5899f27e 112 Controller,\r
113 &gEfiUsbIoProtocolGuid,\r
114 This->DriverBindingHandle,\r
115 Controller\r
116 );\r
ed838d0c 117\r
118 return Status;\r
119}\r
120\r
ed838d0c 121/**\r
a7022cec 122 Start running driver on the controller.\r
ed838d0c 123\r
a7022cec 124 @param This The USB keyboard driver binding instance.\r
5899f27e 125 @param Controller Handle of device to bind driver to.\r
126 @param RemainingDevicePath Optional parameter use to pick a specific child\r
127 device to start.\r
ed838d0c 128\r
a7022cec 129 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.\r
5899f27e 130 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.\r
131 @retval Other The keyboard driver cannot support this controller.\r
ed838d0c 132\r
133**/\r
134EFI_STATUS\r
135EFIAPI\r
136USBKeyboardDriverBindingStart (\r
137 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
138 IN EFI_HANDLE Controller,\r
139 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
140 )\r
141{\r
142 EFI_STATUS Status;\r
143 EFI_USB_IO_PROTOCOL *UsbIo;\r
144 USB_KB_DEV *UsbKeyboardDevice;\r
145 UINT8 EndpointNumber;\r
146 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;\r
147 UINT8 Index;\r
148 UINT8 EndpointAddr;\r
149 UINT8 PollingInterval;\r
150 UINT8 PacketSize;\r
151 BOOLEAN Found;\r
152\r
ed838d0c 153 //\r
5899f27e 154 // Open USB I/O Protocol\r
ed838d0c 155 //\r
156 Status = gBS->OpenProtocol (\r
157 Controller,\r
158 &gEfiUsbIoProtocolGuid,\r
c52fa98c 159 (VOID **) &UsbIo,\r
ed838d0c 160 This->DriverBindingHandle,\r
161 Controller,\r
162 EFI_OPEN_PROTOCOL_BY_DRIVER\r
163 );\r
164 if (EFI_ERROR (Status)) {\r
165 return Status;\r
166 }\r
167\r
168 UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));\r
5899f27e 169 ASSERT (UsbKeyboardDevice != NULL);\r
170\r
ed838d0c 171 //\r
172 // Get the Device Path Protocol on Controller's handle\r
173 //\r
174 Status = gBS->OpenProtocol (\r
175 Controller,\r
176 &gEfiDevicePathProtocolGuid,\r
177 (VOID **) &UsbKeyboardDevice->DevicePath,\r
178 This->DriverBindingHandle,\r
179 Controller,\r
180 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
181 );\r
182\r
183 if (EFI_ERROR (Status)) {\r
5899f27e 184 goto ErrorExit;\r
ed838d0c 185 }\r
186 //\r
5899f27e 187 // Report that the USB keyboard is being enabled\r
ed838d0c 188 //\r
5899f27e 189 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 190 EFI_PROGRESS_CODE,\r
5899f27e 191 PcdGet32 (PcdStatusCodeValueKeyboardEnable),\r
192 UsbKeyboardDevice->DevicePath\r
ed838d0c 193 );\r
194\r
195 //\r
196 // This is pretty close to keyboard detection, so log progress\r
197 //\r
5899f27e 198 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 199 EFI_PROGRESS_CODE,\r
5899f27e 200 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect),\r
201 UsbKeyboardDevice->DevicePath\r
ed838d0c 202 );\r
203\r
204 //\r
205 // Initialize UsbKeyboardDevice\r
206 //\r
207 UsbKeyboardDevice->UsbIo = UsbIo;\r
208\r
209 //\r
210 // Get interface & endpoint descriptor\r
211 //\r
212 UsbIo->UsbGetInterfaceDescriptor (\r
5899f27e 213 UsbIo,\r
214 &UsbKeyboardDevice->InterfaceDescriptor\r
215 );\r
ed838d0c 216\r
217 EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;\r
218\r
5899f27e 219 //\r
220 // Traverse endpoints to find interrupt endpoints\r
221 //\r
222 Found = FALSE;\r
ed838d0c 223 for (Index = 0; Index < EndpointNumber; Index++) {\r
224\r
225 UsbIo->UsbGetEndpointDescriptor (\r
5899f27e 226 UsbIo,\r
227 Index,\r
228 &EndpointDescriptor\r
229 );\r
ed838d0c 230\r
5899f27e 231 if ((EndpointDescriptor.Attributes & 0x03) == USB_ENDPOINT_INTERRUPT) {\r
ed838d0c 232 //\r
233 // We only care interrupt endpoint here\r
234 //\r
84b5c78e 235 CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
ed838d0c 236 Found = TRUE;\r
5899f27e 237 break;\r
ed838d0c 238 }\r
239 }\r
240\r
241 if (!Found) {\r
242 //\r
243 // No interrupt endpoint found, then return unsupported.\r
244 //\r
5899f27e 245 Status = EFI_UNSUPPORTED;\r
246 goto ErrorExit;\r
ed838d0c 247 }\r
248\r
249 UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
250 UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
251 UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
66aa04e4 252\r
253 UsbKeyboardDevice->SimpleInputEx.Reset = USBKeyboardResetEx;\r
254 UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;\r
255 UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;\r
256 UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;\r
257 UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify; \r
258 \r
259 InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
260 \r
261 Status = gBS->CreateEvent (\r
262 EVT_NOTIFY_WAIT,\r
263 TPL_NOTIFY,\r
264 USBKeyboardWaitForKey,\r
265 UsbKeyboardDevice,\r
266 &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
267 );\r
268\r
269 if (EFI_ERROR (Status)) {\r
270 goto ErrorExit;\r
271 }\r
272\r
ed838d0c 273 Status = gBS->CreateEvent (\r
274 EVT_NOTIFY_WAIT,\r
275 TPL_NOTIFY,\r
276 USBKeyboardWaitForKey,\r
277 UsbKeyboardDevice,\r
278 &(UsbKeyboardDevice->SimpleInput.WaitForKey)\r
279 );\r
280\r
281 if (EFI_ERROR (Status)) {\r
5899f27e 282 goto ErrorExit;\r
283 }\r
284\r
285 Status = InitKeyboardLayout (UsbKeyboardDevice);\r
286 if (EFI_ERROR (Status)) {\r
287 goto ErrorExit;\r
ed838d0c 288 }\r
289\r
290 //\r
5899f27e 291 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol\r
292 // for the USB keyboard device.\r
293 // USB keyboard is a hot plug device, and expected to work immediately\r
ed838d0c 294 // when plugging into system, so a HotPlugDeviceGuid is installed onto\r
295 // the usb keyboard device handle, to distinguish it from other conventional\r
296 // console devices.\r
297 //\r
298 Status = gBS->InstallMultipleProtocolInterfaces (\r
299 &Controller,\r
300 &gEfiSimpleTextInProtocolGuid,\r
301 &UsbKeyboardDevice->SimpleInput,\r
66aa04e4 302 &gEfiSimpleTextInputExProtocolGuid,\r
303 &UsbKeyboardDevice->SimpleInputEx,\r
ed838d0c 304 &gEfiHotPlugDeviceGuid,\r
305 NULL,\r
306 NULL\r
307 );\r
308 if (EFI_ERROR (Status)) {\r
5899f27e 309 goto ErrorExit;\r
ed838d0c 310 }\r
311\r
312 //\r
5899f27e 313 // Reset USB Keyboard Device exhaustively.\r
ed838d0c 314 //\r
315 Status = UsbKeyboardDevice->SimpleInput.Reset (\r
316 &UsbKeyboardDevice->SimpleInput,\r
317 TRUE\r
318 );\r
319 if (EFI_ERROR (Status)) {\r
320 gBS->UninstallMultipleProtocolInterfaces (\r
66aa04e4 321 Controller,\r
322 &gEfiSimpleTextInProtocolGuid,\r
323 &UsbKeyboardDevice->SimpleInput,\r
324 &gEfiSimpleTextInputExProtocolGuid,\r
325 &UsbKeyboardDevice->SimpleInputEx,\r
326 &gEfiHotPlugDeviceGuid,\r
327 NULL,\r
328 NULL\r
329 );\r
5899f27e 330 goto ErrorExit;\r
ed838d0c 331 }\r
5899f27e 332\r
ed838d0c 333 //\r
5899f27e 334 // Submit Asynchronous Interrupt Transfer to manage this device.\r
ed838d0c 335 //\r
336 EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;\r
337 PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;\r
338 PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);\r
339\r
340 Status = UsbIo->UsbAsyncInterruptTransfer (\r
341 UsbIo,\r
342 EndpointAddr,\r
343 TRUE,\r
344 PollingInterval,\r
345 PacketSize,\r
346 KeyboardHandler,\r
347 UsbKeyboardDevice\r
348 );\r
349\r
350 if (EFI_ERROR (Status)) {\r
ed838d0c 351 gBS->UninstallMultipleProtocolInterfaces (\r
66aa04e4 352 Controller,\r
353 &gEfiSimpleTextInProtocolGuid,\r
354 &UsbKeyboardDevice->SimpleInput,\r
355 &gEfiSimpleTextInputExProtocolGuid,\r
356 &UsbKeyboardDevice->SimpleInputEx,\r
357 &gEfiHotPlugDeviceGuid,\r
358 NULL,\r
359 NULL\r
360 );\r
5899f27e 361 goto ErrorExit;\r
ed838d0c 362 }\r
363\r
364 UsbKeyboardDevice->ControllerNameTable = NULL;\r
62b9bb55 365 AddUnicodeString2 (\r
ed838d0c 366 "eng",\r
367 gUsbKeyboardComponentName.SupportedLanguages,\r
368 &UsbKeyboardDevice->ControllerNameTable,\r
62b9bb55 369 L"Generic Usb Keyboard",\r
370 TRUE\r
ed838d0c 371 );\r
62b9bb55 372 AddUnicodeString2 (\r
373 "en",\r
374 gUsbKeyboardComponentName2.SupportedLanguages,\r
375 &UsbKeyboardDevice->ControllerNameTable,\r
376 L"Generic Usb Keyboard",\r
377 FALSE\r
378 );\r
379\r
ed838d0c 380 return EFI_SUCCESS;\r
66aa04e4 381\r
5899f27e 382//\r
383// Error handler\r
384//\r
66aa04e4 385ErrorExit:\r
386 if (UsbKeyboardDevice != NULL) {\r
387 if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
388 gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
389 }\r
390 if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
391 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
392 }\r
66aa04e4 393 gBS->FreePool (UsbKeyboardDevice);\r
394 UsbKeyboardDevice = NULL;\r
395 }\r
396 gBS->CloseProtocol (\r
397 Controller,\r
398 &gEfiUsbIoProtocolGuid,\r
399 This->DriverBindingHandle,\r
400 Controller\r
401 );\r
402 return Status;\r
403\r
ed838d0c 404}\r
405\r
406\r
ed838d0c 407/**\r
5899f27e 408 Stop handling the controller by this USB keyboard driver.\r
ed838d0c 409\r
a7022cec 410 @param This The USB keyboard driver binding protocol.\r
411 @param Controller The controller to release.\r
412 @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
413 @param ChildHandleBuffer The array of child handle.\r
ed838d0c 414\r
a7022cec 415 @retval EFI_SUCCESS The controller or children are stopped.\r
5899f27e 416 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol\r
417 is not installed on Controller.\r
a7022cec 418 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
ed838d0c 419\r
420**/\r
421EFI_STATUS\r
422EFIAPI\r
423USBKeyboardDriverBindingStop (\r
424 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
425 IN EFI_HANDLE Controller,\r
426 IN UINTN NumberOfChildren,\r
427 IN EFI_HANDLE *ChildHandleBuffer\r
428 )\r
429{\r
5899f27e 430 EFI_STATUS Status;\r
ed838d0c 431 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
5899f27e 432 USB_KB_DEV *UsbKeyboardDevice;\r
ed838d0c 433\r
434 Status = gBS->OpenProtocol (\r
435 Controller,\r
436 &gEfiSimpleTextInProtocolGuid,\r
c52fa98c 437 (VOID **) &SimpleInput,\r
ed838d0c 438 This->DriverBindingHandle,\r
439 Controller,\r
bcb9d421 440 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
ed838d0c 441 );\r
442 if (EFI_ERROR (Status)) {\r
443 return EFI_UNSUPPORTED;\r
444 }\r
5899f27e 445\r
66aa04e4 446 Status = gBS->OpenProtocol (\r
447 Controller,\r
448 &gEfiSimpleTextInputExProtocolGuid,\r
449 NULL,\r
450 This->DriverBindingHandle,\r
451 Controller,\r
452 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
453 );\r
454 if (EFI_ERROR (Status)) {\r
455 return EFI_UNSUPPORTED;\r
456 }\r
ed838d0c 457 //\r
458 // Get USB_KB_DEV instance.\r
459 //\r
460 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
461\r
ed838d0c 462 //\r
5899f27e 463 // The key data input from this device will be disabled.\r
ed838d0c 464 //\r
5899f27e 465 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 466 EFI_PROGRESS_CODE,\r
5899f27e 467 PcdGet32 (PcdStatusCodeValueKeyboardDisable),\r
468 UsbKeyboardDevice->DevicePath\r
ed838d0c 469 );\r
470\r
471 //\r
5899f27e 472 // Delete the Asynchronous Interrupt Transfer from this device\r
ed838d0c 473 //\r
474 UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (\r
475 UsbKeyboardDevice->UsbIo,\r
476 UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,\r
477 FALSE,\r
478 UsbKeyboardDevice->IntEndpointDescriptor.Interval,\r
479 0,\r
480 NULL,\r
481 NULL\r
482 );\r
483\r
484 gBS->CloseProtocol (\r
5899f27e 485 Controller,\r
486 &gEfiUsbIoProtocolGuid,\r
487 This->DriverBindingHandle,\r
488 Controller\r
489 );\r
ed838d0c 490\r
491 Status = gBS->UninstallMultipleProtocolInterfaces (\r
492 Controller,\r
493 &gEfiSimpleTextInProtocolGuid,\r
494 &UsbKeyboardDevice->SimpleInput,\r
66aa04e4 495 &gEfiSimpleTextInputExProtocolGuid,\r
496 &UsbKeyboardDevice->SimpleInputEx,\r
ed838d0c 497 &gEfiHotPlugDeviceGuid,\r
498 NULL,\r
499 NULL\r
500 );\r
501 //\r
5899f27e 502 // Free all resources.\r
ed838d0c 503 //\r
504 gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
505 gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
506 gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);\r
66aa04e4 507 gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); \r
508 KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
ed838d0c 509\r
813acf3a 510 ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
511 gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
512\r
ed838d0c 513 if (UsbKeyboardDevice->ControllerNameTable != NULL) {\r
514 FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
515 }\r
516\r
517 gBS->FreePool (UsbKeyboardDevice);\r
518\r
519 return Status;\r
ed838d0c 520}\r
521\r
a7022cec 522/**\r
5899f27e 523 Internal function to read the next keystroke from the input device.\r
a7022cec 524\r
525 @param UsbKeyboardDevice Usb keyboard's private structure.\r
526 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
527 state data for the key that was pressed.\r
528\r
529 @return EFI_SUCCESS The keystroke information was returned.\r
530 @return EFI_NOT_READY There was no keystroke data availiable.\r
531 @return EFI_DEVICE_ERROR The keystroke information was not returned due to\r
532 hardware errors.\r
533 @return EFI_INVALID_PARAMETER KeyData is NULL.\r
534\r
535**/\r
66aa04e4 536EFI_STATUS\r
a7022cec 537EFIAPI\r
66aa04e4 538USBKeyboardReadKeyStrokeWorker (\r
539 IN USB_KB_DEV *UsbKeyboardDevice,\r
540 OUT EFI_KEY_DATA *KeyData\r
541 )\r
66aa04e4 542{\r
66aa04e4 543 EFI_STATUS Status;\r
544 UINT8 KeyChar; \r
545 LIST_ENTRY *Link;\r
546 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
547 EFI_KEY_DATA OriginalKeyData;\r
ed838d0c 548\r
66aa04e4 549 if (KeyData == NULL) {\r
550 return EFI_INVALID_PARAMETER;\r
551 }\r
552\r
553 //\r
5899f27e 554 // If there is no saved ASCII byte, fetch it\r
66aa04e4 555 // by calling USBKeyboardCheckForKey().\r
556 //\r
557 if (UsbKeyboardDevice->CurKeyChar == 0) {\r
558 Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
559 if (EFI_ERROR (Status)) {\r
5899f27e 560 return EFI_NOT_READY;\r
66aa04e4 561 }\r
562 }\r
563\r
564 KeyData->Key.UnicodeChar = 0;\r
565 KeyData->Key.ScanCode = SCAN_NULL;\r
566\r
5899f27e 567 //\r
568 // Store the key char read by USBKeyboardCheckForKey() and clear it.\r
569 //\r
66aa04e4 570 KeyChar = UsbKeyboardDevice->CurKeyChar;\r
66aa04e4 571 UsbKeyboardDevice->CurKeyChar = 0;\r
572\r
573 //\r
574 // Translate saved ASCII byte into EFI_INPUT_KEY\r
575 //\r
5899f27e 576 Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyChar, &KeyData->Key);\r
66aa04e4 577 if (EFI_ERROR (Status)) {\r
578 return Status;\r
579 }\r
580\r
5899f27e 581 //\r
582 // Get current state of various toggled attributes as well as input modifier values,\r
583 // and set them as valid.\r
584 //\r
66aa04e4 585 CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));\r
586 \r
587 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
588 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
589\r
590 //\r
5899f27e 591 // Switch the control value to their original characters.\r
592 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to \r
593 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),\r
594 // here switch them back for notification function.\r
66aa04e4 595 //\r
596 CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
a7022cec 597 if (UsbKeyboardDevice->CtrlOn != 0) {\r
66aa04e4 598 if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
a7022cec 599 if (UsbKeyboardDevice->CapsOn != 0) {\r
66aa04e4 600 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);\r
601 } else {\r
602 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);\r
603 } \r
604 }\r
605 }\r
606 \r
607 //\r
5899f27e 608 // Invoke notification functions if the key is registered.\r
66aa04e4 609 //\r
5899f27e 610 for (Link = GetFirstNode (&UsbKeyboardDevice->NotifyList);\r
611 !IsNull (&UsbKeyboardDevice->NotifyList, Link);\r
612 Link = GetNextNode (&UsbKeyboardDevice->NotifyList, Link)) {\r
613 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
66aa04e4 614 if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
615 CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
616 }\r
617 }\r
618\r
619 return EFI_SUCCESS;\r
620 \r
621}\r
a7022cec 622\r
623/**\r
5899f27e 624 Reset USB Keyboard.\r
625\r
626 There are 2 types of reset for USB keyboard.\r
627 For non-exhaustive reset, only keyboard buffer is cleared.\r
628 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status\r
629 is also re-initialized.\r
a7022cec 630\r
631 @param This The protocol instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
5899f27e 632 @param ExtendedVerification Indicates if exhaustive reset is used.\r
633 TRUE for exhaustive reset.\r
634 FALSE for non-exhaustive reset.\r
a7022cec 635\r
5899f27e 636 @retval EFI_SUCCESS Keyboard is reset successfully.\r
637 @retval EFI_DEVICE_ERROR Failed to reset keyboard.\r
a7022cec 638\r
639**/\r
ed838d0c 640EFI_STATUS\r
641EFIAPI\r
642USBKeyboardReset (\r
643 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
5899f27e 644 IN BOOLEAN ExtendedVerification\r
ed838d0c 645 )\r
646{\r
647 EFI_STATUS Status;\r
648 USB_KB_DEV *UsbKeyboardDevice;\r
ed838d0c 649\r
650 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
651\r
5899f27e 652 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 653 EFI_PROGRESS_CODE,\r
5899f27e 654 PcdGet32 (PcdStatusCodeValueKeyboardReset),\r
655 UsbKeyboardDevice->DevicePath\r
ed838d0c 656 );\r
657\r
658 //\r
5899f27e 659 // Non-exhaustive reset:\r
ed838d0c 660 // only reset private data structures.\r
661 //\r
662 if (!ExtendedVerification) {\r
5899f27e 663 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 664 EFI_PROGRESS_CODE,\r
5899f27e 665 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer),\r
666 UsbKeyboardDevice->DevicePath\r
ed838d0c 667 );\r
5899f27e 668 //\r
669 // Clear the key buffer of this USB keyboard\r
670 //\r
ed838d0c 671 InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
672 UsbKeyboardDevice->CurKeyChar = 0;\r
5899f27e 673\r
ed838d0c 674 return EFI_SUCCESS;\r
675 }\r
676\r
677 //\r
678 // Exhaustive reset\r
679 //\r
5899f27e 680 Status = InitUSBKeyboard (UsbKeyboardDevice);\r
ed838d0c 681 UsbKeyboardDevice->CurKeyChar = 0;\r
682 if (EFI_ERROR (Status)) {\r
683 return EFI_DEVICE_ERROR;\r
684 }\r
685\r
686 return EFI_SUCCESS;\r
687}\r
688\r
689\r
690/**\r
691 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.\r
692\r
a7022cec 693 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
694 @param Key A pointer to a buffer that is filled in with the keystroke\r
695 information for the key that was pressed.\r
ed838d0c 696\r
a7022cec 697 @retval EFI_SUCCESS Read key stroke successfully.\r
698 @retval Other Read key stroke failed.\r
ed838d0c 699\r
700**/\r
ed838d0c 701EFI_STATUS\r
702EFIAPI\r
703USBKeyboardReadKeyStroke (\r
704 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
5899f27e 705 OUT EFI_INPUT_KEY *Key\r
ed838d0c 706 )\r
707{\r
66aa04e4 708 USB_KB_DEV *UsbKeyboardDevice;\r
709 EFI_STATUS Status;\r
710 EFI_KEY_DATA KeyData;\r
ed838d0c 711\r
712 UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
713\r
66aa04e4 714 Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
715 if (EFI_ERROR (Status)) {\r
716 return Status;\r
ed838d0c 717 }\r
718\r
66aa04e4 719 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
ed838d0c 720\r
66aa04e4 721 return EFI_SUCCESS;\r
ed838d0c 722\r
723}\r
724\r
725\r
726/**\r
727 Handler function for WaitForKey event.\r
728\r
a7022cec 729 @param Event Event to be signaled when a key is pressed.\r
730 @param Context Points to USB_KB_DEV instance.\r
ed838d0c 731\r
732**/\r
ed838d0c 733VOID\r
734EFIAPI\r
735USBKeyboardWaitForKey (\r
736 IN EFI_EVENT Event,\r
737 IN VOID *Context\r
738 )\r
739{\r
740 USB_KB_DEV *UsbKeyboardDevice;\r
741\r
742 UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
743\r
744 if (UsbKeyboardDevice->CurKeyChar == 0) {\r
ed838d0c 745 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {\r
5899f27e 746 //\r
747 // If no pending key, simply return.\r
748 //\r
ed838d0c 749 return ;\r
750 }\r
751 }\r
752 //\r
5899f27e 753 // If there is pending key, signal the event.\r
ed838d0c 754 //\r
755 gBS->SignalEvent (Event);\r
756}\r
757\r
758\r
ed838d0c 759/**\r
760 Check whether there is key pending.\r
761\r
a7022cec 762 @param UsbKeyboardDevice The USB_KB_DEV instance.\r
ed838d0c 763\r
5899f27e 764 @retval EFI_SUCCESS There is pending key to read.\r
765 @retval EFI_NOT_READY No pending key to read.\r
ed838d0c 766\r
767**/\r
ed838d0c 768EFI_STATUS\r
a7022cec 769EFIAPI\r
ed838d0c 770USBKeyboardCheckForKey (\r
771 IN USB_KB_DEV *UsbKeyboardDevice\r
772 )\r
773{\r
774 EFI_STATUS Status;\r
775 UINT8 KeyChar;\r
776\r
777 //\r
778 // Fetch raw data from the USB keyboard input,\r
779 // and translate it into ASCII data.\r
780 //\r
781 Status = USBParseKey (UsbKeyboardDevice, &KeyChar);\r
782 if (EFI_ERROR (Status)) {\r
5899f27e 783 return EFI_NOT_READY;\r
ed838d0c 784 }\r
785\r
786 UsbKeyboardDevice->CurKeyChar = KeyChar;\r
787 return EFI_SUCCESS;\r
788}\r
789\r
a7022cec 790/**\r
791 Free keyboard notify list.\r
66aa04e4 792\r
a7022cec 793 @param ListHead The list head.\r
66aa04e4 794\r
a7022cec 795 @retval EFI_SUCCESS Free the notify list successfully.\r
796 @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
66aa04e4 797\r
a7022cec 798**/\r
799EFI_STATUS\r
800EFIAPI\r
801KbdFreeNotifyList (\r
802 IN OUT LIST_ENTRY *ListHead\r
803 )\r
66aa04e4 804{\r
805 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
806\r
807 if (ListHead == NULL) {\r
808 return EFI_INVALID_PARAMETER;\r
809 }\r
810 while (!IsListEmpty (ListHead)) {\r
811 NotifyNode = CR (\r
812 ListHead->ForwardLink, \r
813 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
814 NotifyEntry, \r
815 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
816 );\r
817 RemoveEntryList (ListHead->ForwardLink);\r
818 gBS->FreePool (NotifyNode);\r
819 }\r
820 \r
821 return EFI_SUCCESS;\r
822}\r
823\r
a7022cec 824/**\r
825 Whether the pressed key matches a registered key or not.\r
826\r
827 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke\r
828 state data for the key that was registered.\r
829 @param InputData A pointer to a buffer that is filled in with the keystroke\r
830 state data for the key that was pressed.\r
831\r
832 @retval TRUE Key pressed matches a registered key.\r
833 @retval FLASE Match failed.\r
834\r
835**/\r
66aa04e4 836BOOLEAN\r
a7022cec 837EFIAPI\r
66aa04e4 838IsKeyRegistered (\r
839 IN EFI_KEY_DATA *RegsiteredData,\r
840 IN EFI_KEY_DATA *InputData\r
841 )\r
66aa04e4 842{\r
843 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
844 \r
845 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
846 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
847 return FALSE; \r
848 } \r
849 \r
850 //\r
851 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
852 //\r
853 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
854 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
855 return FALSE; \r
856 } \r
857 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
858 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
859 return FALSE; \r
860 } \r
861 \r
862 return TRUE;\r
863\r
864}\r
865\r
866//\r
867// Simple Text Input Ex protocol functions \r
868//\r
a7022cec 869/**\r
870 The extension routine to reset the input device.\r
871\r
872 @param This Protocol instance pointer.\r
873 @param ExtendedVerification Driver may perform diagnostics on reset.\r
874\r
875 @retval EFI_SUCCESS The device was reset.\r
876 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
877 not be reset.\r
878\r
879**/\r
66aa04e4 880EFI_STATUS\r
881EFIAPI\r
882USBKeyboardResetEx (\r
883 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
884 IN BOOLEAN ExtendedVerification\r
885 )\r
66aa04e4 886{\r
887 EFI_STATUS Status;\r
888 USB_KB_DEV *UsbKeyboardDevice;\r
889 EFI_TPL OldTpl;\r
890 \r
891\r
892 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
893\r
894 Status = UsbKeyboardDevice->SimpleInput.Reset (&UsbKeyboardDevice->SimpleInput, ExtendedVerification);\r
895 if (EFI_ERROR (Status)) {\r
896 return EFI_DEVICE_ERROR;\r
897 }\r
898\r
899 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
900 UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
901 UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
902 gBS->RestoreTPL (OldTpl);\r
903\r
904 return EFI_SUCCESS;\r
905\r
906}\r
907\r
a7022cec 908/**\r
909 Reads the next keystroke from the input device. The WaitForKey Event can\r
910 be used to test for existance of a keystroke via WaitForEvent () call.\r
911\r
912 @param This Protocol instance pointer.\r
913 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
914 state data for the key that was pressed.\r
915\r
916 @return EFI_SUCCESS The keystroke information was returned successfully.\r
917 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
918 @retval Other Read key stroke information failed.\r
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
947 @retval EFI_SUCCESS The device state was set successfully.\r
948 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
949 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
950\r
951**/\r
66aa04e4 952EFI_STATUS\r
953EFIAPI\r
954USBKeyboardSetState (\r
955 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
956 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
957 )\r
66aa04e4 958{\r
959 USB_KB_DEV *UsbKeyboardDevice;\r
960\r
961 if (KeyToggleState == NULL) {\r
962 return EFI_INVALID_PARAMETER;\r
963 }\r
964\r
965 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
966\r
967 if (((UsbKeyboardDevice->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
968 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
969 return EFI_UNSUPPORTED;\r
970 }\r
971\r
972 //\r
973 // Update the status light\r
974 //\r
975\r
976 UsbKeyboardDevice->ScrollOn = 0;\r
977 UsbKeyboardDevice->NumLockOn = 0;\r
978 UsbKeyboardDevice->CapsOn = 0;\r
979 \r
980 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
981 UsbKeyboardDevice->ScrollOn = 1;\r
982 }\r
983 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
984 UsbKeyboardDevice->NumLockOn = 1;\r
985 }\r
986 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
987 UsbKeyboardDevice->CapsOn = 1;\r
988 }\r
989\r
990 SetKeyLED (UsbKeyboardDevice);\r
991\r
992 UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
993\r
994 return EFI_SUCCESS;\r
995 \r
996}\r
997\r
a7022cec 998/**\r
999 Register a notification function for a particular keystroke for the input device.\r
1000\r
1001 @param This Protocol instance pointer.\r
1002 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
1003 information data for the key that was pressed.\r
1004 @param KeyNotificationFunction Points to the function to be called when the key\r
1005 sequence is typed specified by KeyData.\r
1006 @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
1007\r
1008 @retval EFI_SUCCESS The notification function was registered successfully.\r
1009 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
1010 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
1011\r
1012**/\r
66aa04e4 1013EFI_STATUS\r
1014EFIAPI\r
1015USBKeyboardRegisterKeyNotify (\r
1016 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1017 IN EFI_KEY_DATA *KeyData,\r
1018 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
a7022cec 1019 OUT EFI_HANDLE *NotifyHandle\r
66aa04e4 1020 )\r
66aa04e4 1021{\r
1022 USB_KB_DEV *UsbKeyboardDevice;\r
1023 EFI_STATUS Status;\r
1024 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
1025 LIST_ENTRY *Link;\r
1026 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
1027\r
1028 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
1029 return EFI_INVALID_PARAMETER;\r
1030 }\r
1031\r
1032 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1033\r
1034 //\r
1035 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
1036 //\r
5899f27e 1037 for (Link = GetFirstNode (&UsbKeyboardDevice->NotifyList);\r
1038 !IsNull (&UsbKeyboardDevice->NotifyList, Link);\r
1039 Link = GetNextNode (&UsbKeyboardDevice->NotifyList, Link)) {\r
66aa04e4 1040 CurrentNotify = CR (\r
1041 Link, \r
1042 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1043 NotifyEntry, \r
1044 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1045 );\r
1046 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
1047 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
1048 *NotifyHandle = CurrentNotify->NotifyHandle; \r
1049 return EFI_SUCCESS;\r
1050 }\r
1051 }\r
1052 }\r
1053 \r
1054 //\r
1055 // Allocate resource to save the notification function\r
1056 // \r
1057 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
1058 if (NewNotify == NULL) {\r
1059 return EFI_OUT_OF_RESOURCES;\r
1060 }\r
1061\r
1062 NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
1063 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
1064 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
1065 InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
1066\r
1067 //\r
1068 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
1069 // \r
1070 Status = gBS->InstallMultipleProtocolInterfaces (\r
1071 &NewNotify->NotifyHandle,\r
1072 &gSimpleTextInExNotifyGuid,\r
1073 NULL,\r
1074 NULL\r
1075 );\r
1076 ASSERT_EFI_ERROR (Status);\r
1077 \r
1078 *NotifyHandle = NewNotify->NotifyHandle; \r
1079 \r
1080 return EFI_SUCCESS;\r
1081 \r
1082}\r
1083\r
a7022cec 1084/**\r
1085 Remove a registered notification function from a particular keystroke.\r
1086\r
1087 @param This Protocol instance pointer.\r
1088 @param NotificationHandle The handle of the notification function being unregistered.\r
1089\r
1090 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
1091 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid or opening gSimpleTextInExNotifyGuid\r
1092 on NotificationHandle fails.\r
1093 @retval EFI_NOT_FOUND Can not find the matching entry in database.\r
1094\r
1095**/\r
66aa04e4 1096EFI_STATUS\r
1097EFIAPI\r
1098USBKeyboardUnregisterKeyNotify (\r
1099 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
1100 IN EFI_HANDLE NotificationHandle\r
1101 )\r
66aa04e4 1102{\r
1103 USB_KB_DEV *UsbKeyboardDevice;\r
1104 EFI_STATUS Status;\r
1105 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1106 LIST_ENTRY *Link;\r
1107\r
1108 if (NotificationHandle == NULL) {\r
1109 return EFI_INVALID_PARAMETER;\r
1110 } \r
1111 \r
1112 UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
1113 \r
5899f27e 1114 //\r
1115 // Check if NotificationHandle is returned from RegisterKeyNotify().\r
1116 //\r
66aa04e4 1117 Status = gBS->OpenProtocol (\r
1118 NotificationHandle,\r
1119 &gSimpleTextInExNotifyGuid,\r
1120 NULL,\r
1121 NULL,\r
1122 NULL,\r
1123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1124 );\r
1125 if (EFI_ERROR (Status)) {\r
1126 return EFI_INVALID_PARAMETER;\r
1127 }\r
1128\r
5899f27e 1129 //\r
1130 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.\r
1131 //\r
1132 for (Link = GetFirstNode (&UsbKeyboardDevice->NotifyList);\r
1133 !IsNull (&UsbKeyboardDevice->NotifyList, Link);\r
1134 Link = GetNextNode (&UsbKeyboardDevice->NotifyList, Link)) {\r
66aa04e4 1135 CurrentNotify = CR (\r
1136 Link, \r
1137 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1138 NotifyEntry, \r
1139 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1140 ); \r
1141 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
1142 //\r
1143 // Remove the notification function from NotifyList and free resources\r
1144 //\r
1145 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
1146 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1147 CurrentNotify->NotifyHandle,\r
1148 &gSimpleTextInExNotifyGuid,\r
1149 NULL,\r
1150 NULL\r
1151 );\r
1152 ASSERT_EFI_ERROR (Status);\r
1153 gBS->FreePool (CurrentNotify); \r
1154 return EFI_SUCCESS;\r
1155 }\r
1156 }\r
1157\r
1158 return EFI_NOT_FOUND; \r
1159}\r
1160\r