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