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