]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouse.c
Update EdkShellBinPkg to integrate a bug fix in Shell r45
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMouseDxe / UsbMouse.c
CommitLineData
ed838d0c 1/** @file\r
29129ce4 2 USB Mouse Driver that manages USB mouse and produces Simple Pointer Protocol.\r
bb80e3b2 3\r
cd5ebaa0
HT
4Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
ed838d0c 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
ed838d0c 13**/\r
14\r
15#include "UsbMouse.h"\r
16\r
ed838d0c 17EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding = {\r
18 USBMouseDriverBindingSupported,\r
19 USBMouseDriverBindingStart,\r
20 USBMouseDriverBindingStop,\r
21 0xa,\r
22 NULL,\r
23 NULL\r
24};\r
25\r
bb80e3b2 26/**\r
29129ce4 27 Entrypoint of USB Mouse Driver.\r
bb80e3b2 28\r
29129ce4 29 This function is the entrypoint of USB Mouse Driver. It installs Driver Binding\r
30 Protocols together with Component Name Protocols.\r
bb80e3b2 31\r
29129ce4 32 @param ImageHandle The firmware allocated handle for the EFI image.\r
33 @param SystemTable A pointer to the EFI System Table.\r
bb80e3b2 34\r
29129ce4 35 @retval EFI_SUCCESS The entry point is executed successfully.\r
bb80e3b2 36\r
37**/\r
ed838d0c 38EFI_STATUS\r
39EFIAPI\r
40USBMouseDriverBindingEntryPoint (\r
41 IN EFI_HANDLE ImageHandle,\r
42 IN EFI_SYSTEM_TABLE *SystemTable\r
43 )\r
ed838d0c 44{\r
29129ce4 45 EFI_STATUS Status;\r
46\r
47 Status = EfiLibInstallDriverBindingComponentName2 (\r
48 ImageHandle,\r
49 SystemTable,\r
50 &gUsbMouseDriverBinding,\r
51 ImageHandle,\r
52 &gUsbMouseComponentName,\r
53 &gUsbMouseComponentName2\r
54 );\r
55 ASSERT_EFI_ERROR (Status);\r
56\r
57 return EFI_SUCCESS;\r
ed838d0c 58}\r
59\r
60\r
61/**\r
29129ce4 62 Check whether USB mouse driver supports this device.\r
ed838d0c 63\r
29129ce4 64 @param This The USB mouse driver binding protocol.\r
65 @param Controller The controller handle to check.\r
66 @param RemainingDevicePath The remaining device path.\r
ed838d0c 67\r
29129ce4 68 @retval EFI_SUCCESS The driver supports this controller.\r
69 @retval other This device isn't supported.\r
ed838d0c 70\r
71**/\r
72EFI_STATUS\r
73EFIAPI\r
74USBMouseDriverBindingSupported (\r
75 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
76 IN EFI_HANDLE Controller,\r
77 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
78 )\r
79{\r
ed838d0c 80 EFI_STATUS Status;\r
29129ce4 81 EFI_USB_IO_PROTOCOL *UsbIo;\r
ed838d0c 82\r
29129ce4 83 Status = gBS->OpenProtocol (\r
84 Controller,\r
85 &gEfiUsbIoProtocolGuid,\r
86 (VOID **) &UsbIo,\r
87 This->DriverBindingHandle,\r
88 Controller,\r
89 EFI_OPEN_PROTOCOL_BY_DRIVER\r
90 );\r
91 if (EFI_ERROR (Status)) {\r
92 return Status;\r
ed838d0c 93 }\r
94\r
95 //\r
29129ce4 96 // Use the USB I/O Protocol interface to check whether Controller is\r
97 // a mouse device that can be managed by this driver.\r
ed838d0c 98 //\r
99 Status = EFI_SUCCESS;\r
100 if (!IsUsbMouse (UsbIo)) {\r
101 Status = EFI_UNSUPPORTED;\r
102 }\r
103\r
104 gBS->CloseProtocol (\r
105 Controller,\r
106 &gEfiUsbIoProtocolGuid,\r
107 This->DriverBindingHandle,\r
108 Controller\r
109 );\r
29129ce4 110\r
ed838d0c 111 return Status;\r
112}\r
113\r
114\r
115/**\r
29129ce4 116 Starts the mouse device with this driver.\r
117\r
118 This function consumes USB I/O Portocol, intializes USB mouse device,\r
119 installs Simple Pointer Protocol, and submits Asynchronous Interrupt\r
120 Transfer to manage the USB mouse device.\r
ed838d0c 121\r
29129ce4 122 @param This The USB mouse driver binding instance.\r
123 @param Controller Handle of device to bind driver to.\r
124 @param RemainingDevicePath Optional parameter use to pick a specific child\r
125 device to start.\r
ed838d0c 126\r
127 @retval EFI_SUCCESS This driver supports this device.\r
128 @retval EFI_UNSUPPORTED This driver does not support this device.\r
bb80e3b2 129 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.\r
130 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.\r
d7db0902 131 @retval EFI_ALREADY_STARTED This driver has been started.\r
ed838d0c 132\r
133**/\r
134EFI_STATUS\r
135EFIAPI\r
136USBMouseDriverBindingStart (\r
137 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
138 IN EFI_HANDLE Controller,\r
139 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
140 )\r
141{\r
142 EFI_STATUS Status;\r
143 EFI_USB_IO_PROTOCOL *UsbIo;\r
ed838d0c 144 USB_MOUSE_DEV *UsbMouseDevice;\r
145 UINT8 EndpointNumber;\r
29129ce4 146 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;\r
ed838d0c 147 UINT8 Index;\r
148 UINT8 EndpointAddr;\r
149 UINT8 PollingInterval;\r
150 UINT8 PacketSize;\r
29129ce4 151 BOOLEAN Found;\r
15cc67e6 152 EFI_TPL OldTpl;\r
ed838d0c 153\r
15cc67e6 154 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
29129ce4 155 //\r
156 // Open USB I/O Protocol\r
157 //\r
ed838d0c 158 Status = gBS->OpenProtocol (\r
159 Controller,\r
160 &gEfiUsbIoProtocolGuid,\r
c52fa98c 161 (VOID **) &UsbIo,\r
ed838d0c 162 This->DriverBindingHandle,\r
163 Controller,\r
164 EFI_OPEN_PROTOCOL_BY_DRIVER\r
165 );\r
166 if (EFI_ERROR (Status)) {\r
15cc67e6 167 goto ErrorExit1;\r
ed838d0c 168 }\r
169\r
170 UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV));\r
29129ce4 171 ASSERT (UsbMouseDevice != NULL);\r
ed838d0c 172\r
29129ce4 173 UsbMouseDevice->UsbIo = UsbIo;\r
174 UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE;\r
ed838d0c 175\r
ed838d0c 176 //\r
177 // Get the Device Path Protocol on Controller's handle\r
178 //\r
179 Status = gBS->OpenProtocol (\r
180 Controller,\r
181 &gEfiDevicePathProtocolGuid,\r
182 (VOID **) &UsbMouseDevice->DevicePath,\r
183 This->DriverBindingHandle,\r
184 Controller,\r
185 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
186 );\r
187\r
188 if (EFI_ERROR (Status)) {\r
189 goto ErrorExit;\r
190 }\r
191 //\r
192 // Get interface & endpoint descriptor\r
193 //\r
194 UsbIo->UsbGetInterfaceDescriptor (\r
29129ce4 195 UsbIo,\r
196 &UsbMouseDevice->InterfaceDescriptor\r
197 );\r
ed838d0c 198\r
29129ce4 199 EndpointNumber = UsbMouseDevice->InterfaceDescriptor.NumEndpoints;\r
ed838d0c 200\r
29129ce4 201 //\r
202 // Traverse endpoints to find interrupt endpoint\r
203 //\r
204 Found = FALSE;\r
ed838d0c 205 for (Index = 0; Index < EndpointNumber; Index++) {\r
206 UsbIo->UsbGetEndpointDescriptor (\r
29129ce4 207 UsbIo,\r
208 Index,\r
209 &EndpointDescriptor\r
210 );\r
ed838d0c 211\r
29129ce4 212 if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {\r
ed838d0c 213 //\r
214 // We only care interrupt endpoint here\r
215 //\r
29129ce4 216 CopyMem(&UsbMouseDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
217 Found = TRUE;\r
218 break;\r
ed838d0c 219 }\r
220 }\r
221\r
29129ce4 222 if (!Found) {\r
ed838d0c 223 //\r
29129ce4 224 // No interrupt endpoint found, then return unsupported.\r
ed838d0c 225 //\r
226 Status = EFI_UNSUPPORTED;\r
227 goto ErrorExit;\r
228 }\r
229\r
230 Status = InitializeUsbMouseDevice (UsbMouseDevice);\r
231 if (EFI_ERROR (Status)) {\r
29129ce4 232 //\r
233 // Fail to initialize USB mouse device.\r
234 //\r
235 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 236 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
f9876ecf 237 (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR),\r
29129ce4 238 UsbMouseDevice->DevicePath\r
ed838d0c 239 );\r
240\r
241 goto ErrorExit;\r
242 }\r
243\r
29129ce4 244 //\r
245 // Initialize and install EFI Simple Pointer Protocol.\r
246 //\r
ed838d0c 247 UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState;\r
248 UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset;\r
249 UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode;\r
250\r
251 Status = gBS->CreateEvent (\r
252 EVT_NOTIFY_WAIT,\r
253 TPL_NOTIFY,\r
254 UsbMouseWaitForInput,\r
255 UsbMouseDevice,\r
256 &((UsbMouseDevice->SimplePointerProtocol).WaitForInput)\r
257 );\r
258 if (EFI_ERROR (Status)) {\r
259 goto ErrorExit;\r
260 }\r
261\r
262 Status = gBS->InstallProtocolInterface (\r
263 &Controller,\r
264 &gEfiSimplePointerProtocolGuid,\r
265 EFI_NATIVE_INTERFACE,\r
266 &UsbMouseDevice->SimplePointerProtocol\r
267 );\r
268\r
269 if (EFI_ERROR (Status)) {\r
ed838d0c 270 goto ErrorExit;\r
271 }\r
272\r
273 //\r
29129ce4 274 // The next step would be submitting Asynchronous Interrupt Transfer on this mouse device.\r
275 // After that we will be able to get key data from it. Thus this is deemed as\r
276 // the enable action of the mouse, so report status code accordingly.\r
ed838d0c 277 //\r
29129ce4 278 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 279 EFI_PROGRESS_CODE,\r
f9876ecf 280 (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE),\r
29129ce4 281 UsbMouseDevice->DevicePath\r
ed838d0c 282 );\r
283\r
284 //\r
29129ce4 285 // Submit Asynchronous Interrupt Transfer to manage this device.\r
ed838d0c 286 //\r
29129ce4 287 EndpointAddr = UsbMouseDevice->IntEndpointDescriptor.EndpointAddress;\r
288 PollingInterval = UsbMouseDevice->IntEndpointDescriptor.Interval;\r
289 PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor.MaxPacketSize);\r
ed838d0c 290\r
291 Status = UsbIo->UsbAsyncInterruptTransfer (\r
292 UsbIo,\r
293 EndpointAddr,\r
294 TRUE,\r
295 PollingInterval,\r
296 PacketSize,\r
297 OnMouseInterruptComplete,\r
298 UsbMouseDevice\r
299 );\r
300\r
29129ce4 301 if (EFI_ERROR (Status)) {\r
302 //\r
303 // If submit error, uninstall that interface\r
304 //\r
305 gBS->UninstallProtocolInterface (\r
306 Controller,\r
307 &gEfiSimplePointerProtocolGuid,\r
308 &UsbMouseDevice->SimplePointerProtocol\r
309 );\r
310 goto ErrorExit;\r
ed838d0c 311 }\r
29129ce4 312 \r
313 UsbMouseDevice->ControllerNameTable = NULL;\r
314 AddUnicodeString2 (\r
315 "eng",\r
316 gUsbMouseComponentName.SupportedLanguages,\r
317 &UsbMouseDevice->ControllerNameTable,\r
318 L"Generic Usb Mouse",\r
319 TRUE\r
320 );\r
321 AddUnicodeString2 (\r
322 "en",\r
323 gUsbMouseComponentName2.SupportedLanguages,\r
324 &UsbMouseDevice->ControllerNameTable,\r
325 L"Generic Usb Mouse",\r
326 FALSE\r
327 );\r
ed838d0c 328\r
15cc67e6 329 gBS->RestoreTPL (OldTpl);\r
330\r
29129ce4 331 return EFI_SUCCESS;\r
ed838d0c 332\r
29129ce4 333//\r
334// Error handler\r
335//\r
ed838d0c 336ErrorExit:\r
337 if (EFI_ERROR (Status)) {\r
338 gBS->CloseProtocol (\r
339 Controller,\r
340 &gEfiUsbIoProtocolGuid,\r
341 This->DriverBindingHandle,\r
342 Controller\r
343 );\r
344\r
345 if (UsbMouseDevice != NULL) {\r
ed838d0c 346 if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) {\r
347 gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput);\r
348 }\r
349\r
29129ce4 350 FreePool (UsbMouseDevice);\r
ed838d0c 351 UsbMouseDevice = NULL;\r
352 }\r
353 }\r
354\r
15cc67e6 355ErrorExit1:\r
356 gBS->RestoreTPL (OldTpl);\r
ed838d0c 357 return Status;\r
358}\r
359\r
360\r
361/**\r
29129ce4 362 Stop the USB mouse device handled by this driver.\r
ed838d0c 363\r
29129ce4 364 @param This The USB mouse driver binding protocol.\r
365 @param Controller The controller to release.\r
366 @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
367 @param ChildHandleBuffer The array of child handle.\r
ed838d0c 368\r
29129ce4 369 @retval EFI_SUCCESS The device was stopped.\r
370 @retval EFI_UNSUPPORTED Simple Pointer Protocol is not installed on Controller.\r
371 @retval Others Fail to uninstall protocols attached on the device.\r
ed838d0c 372\r
373**/\r
374EFI_STATUS\r
375EFIAPI\r
376USBMouseDriverBindingStop (\r
377 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
378 IN EFI_HANDLE Controller,\r
379 IN UINTN NumberOfChildren,\r
380 IN EFI_HANDLE *ChildHandleBuffer\r
381 )\r
382{\r
383 EFI_STATUS Status;\r
384 USB_MOUSE_DEV *UsbMouseDevice;\r
385 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;\r
386 EFI_USB_IO_PROTOCOL *UsbIo;\r
387\r
ed838d0c 388 Status = gBS->OpenProtocol (\r
389 Controller,\r
390 &gEfiSimplePointerProtocolGuid,\r
c52fa98c 391 (VOID **) &SimplePointerProtocol,\r
ed838d0c 392 This->DriverBindingHandle,\r
393 Controller,\r
394 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
395 );\r
396\r
397 if (EFI_ERROR (Status)) {\r
398 return EFI_UNSUPPORTED;\r
399 }\r
400\r
401 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol);\r
402\r
ed838d0c 403 UsbIo = UsbMouseDevice->UsbIo;\r
404\r
405 //\r
29129ce4 406 // The key data input from this device will be disabled.\r
ed838d0c 407 //\r
29129ce4 408 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 409 EFI_PROGRESS_CODE,\r
f9876ecf 410 (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE),\r
29129ce4 411 UsbMouseDevice->DevicePath\r
ed838d0c 412 );\r
413\r
414 //\r
29129ce4 415 // Delete the Asynchronous Interrupt Transfer from this device\r
ed838d0c 416 //\r
417 UsbIo->UsbAsyncInterruptTransfer (\r
29129ce4 418 UsbIo,\r
419 UsbMouseDevice->IntEndpointDescriptor.EndpointAddress,\r
420 FALSE,\r
421 UsbMouseDevice->IntEndpointDescriptor.Interval,\r
422 0,\r
423 NULL,\r
424 NULL\r
425 );\r
ed838d0c 426\r
427 Status = gBS->UninstallProtocolInterface (\r
428 Controller,\r
429 &gEfiSimplePointerProtocolGuid,\r
430 &UsbMouseDevice->SimplePointerProtocol\r
431 );\r
432 if (EFI_ERROR (Status)) {\r
433 return Status;\r
434 }\r
435\r
436 gBS->CloseProtocol (\r
29129ce4 437 Controller,\r
438 &gEfiUsbIoProtocolGuid,\r
439 This->DriverBindingHandle,\r
440 Controller\r
441 );\r
442\r
443 //\r
444 // Free all resources.\r
445 //\r
446 gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput);\r
ed838d0c 447\r
29129ce4 448 if (UsbMouseDevice->DelayedRecoveryEvent != NULL) {\r
449 gBS->CloseEvent (UsbMouseDevice->DelayedRecoveryEvent);\r
450 UsbMouseDevice->DelayedRecoveryEvent = NULL;\r
451 }\r
ed838d0c 452\r
bb80e3b2 453 if (UsbMouseDevice->ControllerNameTable != NULL) {\r
ed838d0c 454 FreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable);\r
455 }\r
456\r
29129ce4 457 FreePool (UsbMouseDevice);\r
ed838d0c 458\r
459 return EFI_SUCCESS;\r
460\r
461}\r
462\r
463\r
464/**\r
29129ce4 465 Uses USB I/O to check whether the device is a USB mouse device.\r
ed838d0c 466\r
29129ce4 467 @param UsbIo Pointer to a USB I/O protocol instance.\r
ed838d0c 468\r
29129ce4 469 @retval TRUE Device is a USB mouse device.\r
470 @retval FALSE Device is a not USB mouse device.\r
ed838d0c 471\r
472**/\r
473BOOLEAN\r
474IsUsbMouse (\r
475 IN EFI_USB_IO_PROTOCOL *UsbIo\r
476 )\r
477{\r
478 EFI_STATUS Status;\r
479 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
480\r
481 //\r
29129ce4 482 // Get the default interface descriptor\r
ed838d0c 483 //\r
484 Status = UsbIo->UsbGetInterfaceDescriptor (\r
485 UsbIo,\r
486 &InterfaceDescriptor\r
487 );\r
488\r
489 if (EFI_ERROR (Status)) {\r
490 return FALSE;\r
491 }\r
492\r
493 if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&\r
494 (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&\r
495 (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)\r
496 ) {\r
497 return TRUE;\r
498 }\r
499\r
500 return FALSE;\r
501}\r
502\r
503\r
504/**\r
29129ce4 505 Initialize the USB mouse device.\r
506\r
507 This function retrieves and parses HID report descriptor, and\r
508 initializes state of USB_MOUSE_DEV. Then it sets indefinite idle\r
509 rate for the device. Finally it creates event for delayed recovery,\r
510 which deals with device error.\r
ed838d0c 511\r
bb80e3b2 512 @param UsbMouseDev Device instance to be initialized.\r
ed838d0c 513\r
29129ce4 514 @retval EFI_SUCCESS USB mouse device successfully initialized..\r
515 @retval EFI_UNSUPPORTED HID descriptor type is not report descriptor.\r
516 @retval Other USB mouse device was not initialized successfully.\r
ed838d0c 517\r
518**/\r
ed838d0c 519EFI_STATUS\r
520InitializeUsbMouseDevice (\r
29129ce4 521 IN OUT USB_MOUSE_DEV *UsbMouseDev\r
ed838d0c 522 )\r
523{\r
524 EFI_USB_IO_PROTOCOL *UsbIo;\r
525 UINT8 Protocol;\r
526 EFI_STATUS Status;\r
527 EFI_USB_HID_DESCRIPTOR MouseHidDesc;\r
528 UINT8 *ReportDesc;\r
29129ce4 529 UINT8 ReportId;\r
530 UINT8 Duration;\r
ed838d0c 531\r
532 UsbIo = UsbMouseDev->UsbIo;\r
533\r
534 //\r
535 // Get HID descriptor\r
536 //\r
537 Status = UsbGetHidDescriptor (\r
29129ce4 538 UsbIo,\r
539 UsbMouseDev->InterfaceDescriptor.InterfaceNumber,\r
540 &MouseHidDesc\r
541 );\r
ed838d0c 542 if (EFI_ERROR (Status)) {\r
543 return Status;\r
544 }\r
545\r
546 //\r
29129ce4 547 // Get report descriptor\r
ed838d0c 548 //\r
29129ce4 549 if (MouseHidDesc.HidClassDesc[0].DescriptorType != USB_DESC_TYPE_REPORT) {\r
ed838d0c 550 return EFI_UNSUPPORTED;\r
551 }\r
552\r
553 ReportDesc = AllocateZeroPool (MouseHidDesc.HidClassDesc[0].DescriptorLength);\r
29129ce4 554 ASSERT (ReportDesc != NULL);\r
ed838d0c 555\r
556 Status = UsbGetReportDescriptor (\r
29129ce4 557 UsbIo,\r
558 UsbMouseDev->InterfaceDescriptor.InterfaceNumber,\r
559 MouseHidDesc.HidClassDesc[0].DescriptorLength,\r
560 ReportDesc\r
561 );\r
ed838d0c 562\r
563 if (EFI_ERROR (Status)) {\r
29129ce4 564 FreePool (ReportDesc);\r
ed838d0c 565 return Status;\r
566 }\r
567\r
568 //\r
569 // Parse report descriptor\r
570 //\r
571 Status = ParseMouseReportDescriptor (\r
29129ce4 572 UsbMouseDev,\r
573 ReportDesc,\r
574 MouseHidDesc.HidClassDesc[0].DescriptorLength\r
575 );\r
ed838d0c 576\r
577 if (EFI_ERROR (Status)) {\r
29129ce4 578 FreePool (ReportDesc);\r
ed838d0c 579 return Status;\r
580 }\r
581\r
29129ce4 582 //\r
583 // Check the presence of left and right buttons,\r
584 // and initialize fields of EFI_SIMPLE_POINTER_MODE.\r
585 //\r
ed838d0c 586 if (UsbMouseDev->NumberOfButtons >= 1) {\r
587 UsbMouseDev->Mode.LeftButton = TRUE;\r
588 }\r
ed838d0c 589 if (UsbMouseDev->NumberOfButtons > 1) {\r
590 UsbMouseDev->Mode.RightButton = TRUE;\r
591 }\r
ed838d0c 592 UsbMouseDev->Mode.ResolutionX = 8;\r
593 UsbMouseDev->Mode.ResolutionY = 8;\r
594 UsbMouseDev->Mode.ResolutionZ = 0;\r
29129ce4 595\r
ed838d0c 596 //\r
29129ce4 597 // Set boot protocol for the USB mouse.\r
598 // This driver only supports boot protocol.\r
ed838d0c 599 //\r
600 UsbGetProtocolRequest (\r
601 UsbIo,\r
29129ce4 602 UsbMouseDev->InterfaceDescriptor.InterfaceNumber,\r
ed838d0c 603 &Protocol\r
604 );\r
ed838d0c 605 if (Protocol != BOOT_PROTOCOL) {\r
606 Status = UsbSetProtocolRequest (\r
29129ce4 607 UsbIo,\r
608 0,\r
609 BOOT_PROTOCOL\r
610 );\r
ed838d0c 611\r
612 if (EFI_ERROR (Status)) {\r
29129ce4 613 FreePool (ReportDesc);\r
614 return Status;\r
ed838d0c 615 }\r
616 }\r
617\r
618 //\r
29129ce4 619 // ReportId is zero, which means the idle rate applies to all input reports.\r
620 //\r
621 ReportId = 0;\r
ed838d0c 622 //\r
29129ce4 623 // Duration is zero, which means the duration is infinite.\r
624 // so the endpoint will inhibit reporting forever,\r
625 // and only reporting when a change is detected in the report data.\r
626 //\r
627 Duration = 0;\r
ed838d0c 628 UsbSetIdleRequest (\r
629 UsbIo,\r
29129ce4 630 UsbMouseDev->InterfaceDescriptor.InterfaceNumber,\r
631 ReportId,\r
632 Duration\r
ed838d0c 633 );\r
634\r
29129ce4 635 FreePool (ReportDesc);\r
ed838d0c 636\r
29129ce4 637 //\r
638 // Create event for delayed recovery, which deals with device error.\r
639 //\r
bb80e3b2 640 if (UsbMouseDev->DelayedRecoveryEvent != NULL) {\r
ed838d0c 641 gBS->CloseEvent (UsbMouseDev->DelayedRecoveryEvent);\r
642 UsbMouseDev->DelayedRecoveryEvent = 0;\r
643 }\r
644\r
29129ce4 645 gBS->CreateEvent (\r
646 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
647 TPL_NOTIFY,\r
648 USBMouseRecoveryHandler,\r
649 UsbMouseDev,\r
650 &UsbMouseDev->DelayedRecoveryEvent\r
651 );\r
ed838d0c 652\r
653 return EFI_SUCCESS;\r
654}\r
655\r
656\r
657/**\r
29129ce4 658 Handler function for USB mouse's asynchronous interrupt transfer.\r
659\r
660 This function is the handler function for USB mouse's asynchronous interrupt transfer\r
661 to manage the mouse. It parses data returned from asynchronous interrupt transfer, and\r
662 get button and movement state.\r
ed838d0c 663\r
29129ce4 664 @param Data A pointer to a buffer that is filled with key data which is\r
665 retrieved via asynchronous interrupt transfer.\r
666 @param DataLength Indicates the size of the data buffer.\r
667 @param Context Pointing to USB_KB_DEV instance.\r
668 @param Result Indicates the result of the asynchronous interrupt transfer.\r
ed838d0c 669\r
29129ce4 670 @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.\r
671 @retval EFI_DEVICE_ERROR Hardware error occurs.\r
ed838d0c 672\r
673**/\r
ed838d0c 674EFI_STATUS\r
675EFIAPI\r
676OnMouseInterruptComplete (\r
677 IN VOID *Data,\r
678 IN UINTN DataLength,\r
679 IN VOID *Context,\r
680 IN UINT32 Result\r
681 )\r
682{\r
683 USB_MOUSE_DEV *UsbMouseDevice;\r
684 EFI_USB_IO_PROTOCOL *UsbIo;\r
685 UINT8 EndpointAddr;\r
686 UINT32 UsbResult;\r
687\r
688 UsbMouseDevice = (USB_MOUSE_DEV *) Context;\r
689 UsbIo = UsbMouseDevice->UsbIo;\r
690\r
691 if (Result != EFI_USB_NOERROR) {\r
692 //\r
693 // Some errors happen during the process\r
694 //\r
29129ce4 695 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 696 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
f9876ecf 697 (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR),\r
29129ce4 698 UsbMouseDevice->DevicePath\r
ed838d0c 699 );\r
700\r
701 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
29129ce4 702 EndpointAddr = UsbMouseDevice->IntEndpointDescriptor.EndpointAddress;\r
ed838d0c 703\r
704 UsbClearEndpointHalt (\r
705 UsbIo,\r
706 EndpointAddr,\r
707 &UsbResult\r
708 );\r
709 }\r
710\r
29129ce4 711 //\r
712 // Delete & Submit this interrupt again\r
713 // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt. \r
714 //\r
ed838d0c 715 UsbIo->UsbAsyncInterruptTransfer (\r
29129ce4 716 UsbIo,\r
717 UsbMouseDevice->IntEndpointDescriptor.EndpointAddress,\r
718 FALSE,\r
719 0,\r
720 0,\r
721 NULL,\r
722 NULL\r
723 );\r
724 //\r
725 // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.\r
726 //\r
ed838d0c 727 gBS->SetTimer (\r
29129ce4 728 UsbMouseDevice->DelayedRecoveryEvent,\r
729 TimerRelative,\r
730 EFI_USB_INTERRUPT_DELAY\r
731 );\r
ed838d0c 732 return EFI_DEVICE_ERROR;\r
733 }\r
734\r
29129ce4 735 //\r
736 // If no error and no data, just return EFI_SUCCESS.\r
737 //\r
ed838d0c 738 if (DataLength == 0 || Data == NULL) {\r
739 return EFI_SUCCESS;\r
740 }\r
741\r
742 UsbMouseDevice->StateChanged = TRUE;\r
743\r
744 //\r
745 // Check mouse Data\r
29129ce4 746 // USB HID Specification specifies following data format:\r
747 // Byte Bits Description\r
748 // 0 0 Button 1\r
749 // 1 Button 2\r
750 // 2 Button 3\r
751 // 4 to 7 Device-specific\r
752 // 1 0 to 7 X displacement\r
753 // 2 0 to 7 Y displacement\r
754 // 3 to n 0 to 7 Device specific (optional)\r
755 //\r
756 UsbMouseDevice->State.LeftButton = (BOOLEAN) ((*(UINT8 *) Data & BIT0) != 0);\r
757 UsbMouseDevice->State.RightButton = (BOOLEAN) ((*(UINT8 *) Data & BIT1) != 0);\r
ed838d0c 758 UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1);\r
759 UsbMouseDevice->State.RelativeMovementY += *((INT8 *) Data + 2);\r
760\r
761 if (DataLength > 3) {\r
762 UsbMouseDevice->State.RelativeMovementZ += *((INT8 *) Data + 3);\r
763 }\r
764\r
765 return EFI_SUCCESS;\r
766}\r
767\r
ed838d0c 768/**\r
29129ce4 769 Retrieves the current state of a pointer device.\r
770 \r
771 @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance. \r
772 @param MouseState A pointer to the state information on the pointer device.\r
773 \r
774 @retval EFI_SUCCESS The state of the pointer device was returned in State.\r
775 @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to\r
776 GetState(). \r
777 @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's\r
778 current state. \r
779 @retval EFI_INVALID_PARAMETER MouseState is NULL. \r
ed838d0c 780\r
781**/\r
ed838d0c 782EFI_STATUS\r
783EFIAPI\r
784GetMouseState (\r
785 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
786 OUT EFI_SIMPLE_POINTER_STATE *MouseState\r
787 )\r
788{\r
789 USB_MOUSE_DEV *MouseDev;\r
790\r
791 if (MouseState == NULL) {\r
29129ce4 792 return EFI_INVALID_PARAMETER;\r
ed838d0c 793 }\r
794\r
795 MouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);\r
796\r
797 if (!MouseDev->StateChanged) {\r
798 return EFI_NOT_READY;\r
799 }\r
800\r
29129ce4 801 //\r
802 // Retrieve mouse state from USB_MOUSE_DEV, which was filled by OnMouseInterruptComplete()\r
803 //\r
ed838d0c 804 CopyMem (\r
805 MouseState,\r
806 &MouseDev->State,\r
807 sizeof (EFI_SIMPLE_POINTER_STATE)\r
808 );\r
809\r
810 //\r
811 // Clear previous move state\r
812 //\r
813 MouseDev->State.RelativeMovementX = 0;\r
814 MouseDev->State.RelativeMovementY = 0;\r
815 MouseDev->State.RelativeMovementZ = 0;\r
816\r
817 MouseDev->StateChanged = FALSE;\r
818\r
819 return EFI_SUCCESS;\r
820}\r
821\r
822\r
29129ce4 823/** \r
824 Resets the pointer device hardware.\r
825 \r
826 @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance.\r
827 @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
828 verification operation of the device during reset.\r
829 \r
830 @retval EFI_SUCCESS The device was reset.\r
831 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.\r
ed838d0c 832\r
833**/\r
ed838d0c 834EFI_STATUS\r
835EFIAPI\r
836UsbMouseReset (\r
837 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
838 IN BOOLEAN ExtendedVerification\r
839 )\r
840{\r
841 USB_MOUSE_DEV *UsbMouseDevice;\r
ed838d0c 842\r
843 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);\r
844\r
29129ce4 845 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
ed838d0c 846 EFI_PROGRESS_CODE,\r
f9876ecf 847 (EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET),\r
29129ce4 848 UsbMouseDevice->DevicePath\r
ed838d0c 849 );\r
850\r
29129ce4 851 //\r
852 // Clear mouse state.\r
853 //\r
ed838d0c 854 ZeroMem (\r
855 &UsbMouseDevice->State,\r
856 sizeof (EFI_SIMPLE_POINTER_STATE)\r
857 );\r
858 UsbMouseDevice->StateChanged = FALSE;\r
859\r
860 return EFI_SUCCESS;\r
861}\r
862\r
ed838d0c 863/**\r
7772b176 864 Event notification function for EFI_SIMPLE_POINTER_PROTOCOL.WaitForInput event.\r
ed838d0c 865\r
29129ce4 866 @param Event Event to be signaled when there's input from mouse.\r
867 @param Context Points to USB_MOUSE_DEV instance.\r
bb80e3b2 868 \r
ed838d0c 869**/\r
ed838d0c 870VOID\r
871EFIAPI\r
872UsbMouseWaitForInput (\r
873 IN EFI_EVENT Event,\r
874 IN VOID *Context\r
875 )\r
876{\r
877 USB_MOUSE_DEV *UsbMouseDev;\r
878\r
879 UsbMouseDev = (USB_MOUSE_DEV *) Context;\r
880\r
881 //\r
29129ce4 882 // If there's input from mouse, signal the event.\r
ed838d0c 883 //\r
884 if (UsbMouseDev->StateChanged) {\r
885 gBS->SignalEvent (Event);\r
886 }\r
887}\r
888\r
ed838d0c 889/**\r
29129ce4 890 Handler for Delayed Recovery event.\r
ed838d0c 891\r
29129ce4 892 This function is the handler for Delayed Recovery event triggered\r
893 by timer.\r
894 After a device error occurs, the event would be triggered\r
895 with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY\r
896 is defined in USB standard for error handling.\r
ed838d0c 897\r
29129ce4 898 @param Event The Delayed Recovery event.\r
899 @param Context Points to the USB_MOUSE_DEV instance.\r
ed838d0c 900\r
901**/\r
902VOID\r
903EFIAPI\r
904USBMouseRecoveryHandler (\r
905 IN EFI_EVENT Event,\r
906 IN VOID *Context\r
907 )\r
908{\r
909 USB_MOUSE_DEV *UsbMouseDev;\r
910 EFI_USB_IO_PROTOCOL *UsbIo;\r
911\r
912 UsbMouseDev = (USB_MOUSE_DEV *) Context;\r
913\r
914 UsbIo = UsbMouseDev->UsbIo;\r
915\r
29129ce4 916 //\r
917 // Re-submit Asynchronous Interrupt Transfer for recovery.\r
918 //\r
ed838d0c 919 UsbIo->UsbAsyncInterruptTransfer (\r
29129ce4 920 UsbIo,\r
921 UsbMouseDev->IntEndpointDescriptor.EndpointAddress,\r
922 TRUE,\r
923 UsbMouseDev->IntEndpointDescriptor.Interval,\r
924 UsbMouseDev->IntEndpointDescriptor.MaxPacketSize,\r
925 OnMouseInterruptComplete,\r
926 UsbMouseDev\r
927 );\r
ed838d0c 928}\r