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