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