]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c
Add some definitions for efi event in Uefi/UefiSpec.h to follow spec.
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbMouse / Dxe / usbmouse.c
CommitLineData
878ddf1f 1/*++\r
2\r
93b0fbc8 3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
878ddf1f 11\r
12 Module Name:\r
13\r
14 UsbMouse.c\r
15\r
16 Abstract:\r
17\r
18--*/\r
19\r
20#include "usbmouse.h"\r
21#include "mousehid.h"\r
22\r
878ddf1f 23EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding = {\r
24 USBMouseDriverBindingSupported,\r
25 USBMouseDriverBindingStart,\r
26 USBMouseDriverBindingStop,\r
61fb1657 27 0xa,\r
878ddf1f 28 NULL,\r
29 NULL\r
30};\r
31\r
32//\r
33// helper functions\r
34//\r
35STATIC\r
36BOOLEAN\r
37IsUsbMouse (\r
38 IN EFI_USB_IO_PROTOCOL *UsbIo\r
39 );\r
40\r
41STATIC\r
42EFI_STATUS\r
43InitializeUsbMouseDevice (\r
44 IN USB_MOUSE_DEV *UsbMouseDev\r
45 );\r
46\r
47STATIC\r
48VOID\r
49EFIAPI\r
50UsbMouseWaitForInput (\r
51 IN EFI_EVENT Event,\r
52 IN VOID *Context\r
53 );\r
54\r
55//\r
56// Mouse interrupt handler\r
57//\r
58STATIC\r
59EFI_STATUS\r
60EFIAPI\r
61OnMouseInterruptComplete (\r
62 IN VOID *Data,\r
63 IN UINTN DataLength,\r
64 IN VOID *Context,\r
65 IN UINT32 Result\r
66 );\r
67\r
68//\r
69// Mouse Protocol\r
70//\r
71STATIC\r
72EFI_STATUS\r
73EFIAPI\r
74GetMouseState (\r
75 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
76 OUT EFI_SIMPLE_POINTER_STATE *MouseState\r
77 );\r
78\r
79STATIC\r
80EFI_STATUS\r
81EFIAPI\r
82UsbMouseReset (\r
83 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
84 IN BOOLEAN ExtendedVerification\r
85 );\r
86\r
87EFI_STATUS\r
88EFIAPI\r
89USBMouseDriverBindingSupported (\r
90 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
91 IN EFI_HANDLE Controller,\r
92 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
93 )\r
94/*++\r
95\r
96 Routine Description:\r
97 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
98 that has UsbHcProtocol installed will be supported.\r
99\r
100 Arguments:\r
101 This - Protocol instance pointer.\r
102 Controller - Handle of device to test\r
103 RemainingDevicePath - Not used\r
104\r
105 Returns:\r
106 EFI_SUCCESS - This driver supports this device.\r
107 EFI_UNSUPPORTED - This driver does not support this device.\r
108\r
109--*/\r
110{\r
111 EFI_STATUS OpenStatus;\r
112 EFI_USB_IO_PROTOCOL *UsbIo;\r
113 EFI_STATUS Status;\r
114\r
115 OpenStatus = gBS->OpenProtocol (\r
116 Controller,\r
117 &gEfiUsbIoProtocolGuid,\r
118 (VOID **) &UsbIo,\r
119 This->DriverBindingHandle,\r
120 Controller,\r
121 EFI_OPEN_PROTOCOL_BY_DRIVER\r
122 );\r
123 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {\r
124 return EFI_UNSUPPORTED;\r
125 }\r
126\r
127 if (OpenStatus == EFI_ALREADY_STARTED) {\r
128 return EFI_ALREADY_STARTED;\r
129 }\r
93b0fbc8 130\r
878ddf1f 131 //\r
132 // Use the USB I/O protocol interface to see the Controller is\r
133 // the Mouse controller that can be managed by this driver.\r
134 //\r
135 Status = EFI_SUCCESS;\r
136 if (!IsUsbMouse (UsbIo)) {\r
137 Status = EFI_UNSUPPORTED;\r
138 }\r
139\r
140 gBS->CloseProtocol (\r
141 Controller,\r
142 &gEfiUsbIoProtocolGuid,\r
143 This->DriverBindingHandle,\r
144 Controller\r
145 );\r
146 return Status;\r
147}\r
148\r
149EFI_STATUS\r
150EFIAPI\r
151USBMouseDriverBindingStart (\r
152 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
153 IN EFI_HANDLE Controller,\r
154 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
155 )\r
156/*++\r
157\r
158 Routine Description:\r
159 Starting the Usb Bus Driver\r
160\r
161 Arguments:\r
162 This - Protocol instance pointer.\r
163 Controller - Handle of device to test\r
164 RemainingDevicePath - Not used\r
165\r
166 Returns:\r
167 EFI_SUCCESS - This driver supports this device.\r
168 EFI_UNSUPPORTED - This driver does not support this device.\r
169 EFI_DEVICE_ERROR - This driver cannot be started due to device\r
170 Error\r
171 EFI_OUT_OF_RESOURCES- Can't allocate memory resources\r
172 EFI_ALREADY_STARTED - Thios driver has been started\r
173--*/\r
174{\r
175 EFI_STATUS Status;\r
176 EFI_USB_IO_PROTOCOL *UsbIo;\r
177 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;\r
178 USB_MOUSE_DEV *UsbMouseDevice;\r
179 UINT8 EndpointNumber;\r
180 UINT8 Index;\r
181 UINT8 EndpointAddr;\r
182 UINT8 PollingInterval;\r
183 UINT8 PacketSize;\r
184\r
185 UsbMouseDevice = NULL;\r
186 Status = EFI_SUCCESS;\r
187\r
188 Status = gBS->OpenProtocol (\r
189 Controller,\r
190 &gEfiUsbIoProtocolGuid,\r
191 (VOID **) &UsbIo,\r
192 This->DriverBindingHandle,\r
193 Controller,\r
194 EFI_OPEN_PROTOCOL_BY_DRIVER\r
195 );\r
196 if (EFI_ERROR (Status)) {\r
197 goto ErrorExit;\r
198 }\r
199\r
200 UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV));\r
201 if (UsbMouseDevice == NULL) {\r
202 Status = EFI_OUT_OF_RESOURCES;\r
203 goto ErrorExit;\r
204 }\r
205\r
206 UsbMouseDevice->UsbIo = UsbIo;\r
207\r
208 UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE;\r
209\r
210 UsbMouseDevice->InterfaceDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
211 if (UsbMouseDevice->InterfaceDescriptor == NULL) {\r
212 Status = EFI_OUT_OF_RESOURCES;\r
213 goto ErrorExit;\r
214 }\r
215\r
216 EndpointDesc = AllocatePool (sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));\r
217 if (EndpointDesc == NULL) {\r
218 Status = EFI_OUT_OF_RESOURCES;\r
219 goto ErrorExit;\r
220 }\r
221 //\r
222 // Get the Device Path Protocol on Controller's handle\r
223 //\r
224 Status = gBS->OpenProtocol (\r
225 Controller,\r
226 &gEfiDevicePathProtocolGuid,\r
227 (VOID **) &UsbMouseDevice->DevicePath,\r
228 This->DriverBindingHandle,\r
229 Controller,\r
230 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
231 );\r
232\r
233 if (EFI_ERROR (Status)) {\r
234 goto ErrorExit;\r
235 }\r
236 //\r
237 // Get interface & endpoint descriptor\r
238 //\r
239 UsbIo->UsbGetInterfaceDescriptor (\r
240 UsbIo,\r
241 UsbMouseDevice->InterfaceDescriptor\r
242 );\r
243\r
244 EndpointNumber = UsbMouseDevice->InterfaceDescriptor->NumEndpoints;\r
245\r
246 for (Index = 0; Index < EndpointNumber; Index++) {\r
247 UsbIo->UsbGetEndpointDescriptor (\r
248 UsbIo,\r
249 Index,\r
250 EndpointDesc\r
251 );\r
252\r
253 if ((EndpointDesc->Attributes & 0x03) == 0x03) {\r
254\r
255 //\r
256 // We only care interrupt endpoint here\r
257 //\r
258 UsbMouseDevice->IntEndpointDescriptor = EndpointDesc;\r
259 }\r
260 }\r
261\r
262 if (UsbMouseDevice->IntEndpointDescriptor == NULL) {\r
263 //\r
264 // No interrupt endpoint, then error\r
265 //\r
266 Status = EFI_UNSUPPORTED;\r
267 goto ErrorExit;\r
268 }\r
269\r
270 Status = InitializeUsbMouseDevice (UsbMouseDevice);\r
271 if (EFI_ERROR (Status)) {\r
272 MouseReportStatusCode (\r
273 UsbMouseDevice->DevicePath,\r
274 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
275 (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR)\r
276 );\r
277\r
278 goto ErrorExit;\r
279 }\r
280\r
281 UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState;\r
282 UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset;\r
283 UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode;\r
284\r
285 Status = gBS->CreateEvent (\r
93b0fbc8 286 EVT_NOTIFY_WAIT,\r
287 TPL_NOTIFY,\r
878ddf1f 288 UsbMouseWaitForInput,\r
289 UsbMouseDevice,\r
290 &((UsbMouseDevice->SimplePointerProtocol).WaitForInput)\r
291 );\r
292 if (EFI_ERROR (Status)) {\r
293 goto ErrorExit;\r
294 }\r
295\r
296 Status = gBS->InstallProtocolInterface (\r
297 &Controller,\r
298 &gEfiSimplePointerProtocolGuid,\r
299 EFI_NATIVE_INTERFACE,\r
300 &UsbMouseDevice->SimplePointerProtocol\r
301 );\r
302\r
303 if (EFI_ERROR (Status)) {\r
304 Status = EFI_DEVICE_ERROR;\r
305 goto ErrorExit;\r
306 }\r
93b0fbc8 307\r
878ddf1f 308 //\r
309 // After Enabling Async Interrupt Transfer on this mouse Device\r
310 // we will be able to get key data from it. Thus this is deemed as\r
311 // the enable action of the mouse\r
312 //\r
93b0fbc8 313\r
878ddf1f 314 MouseReportStatusCode (\r
315 UsbMouseDevice->DevicePath,\r
316 EFI_PROGRESS_CODE,\r
317 (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE)\r
318 );\r
319\r
320 //\r
321 // submit async interrupt transfer\r
322 //\r
323 EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress;\r
324 PollingInterval = UsbMouseDevice->IntEndpointDescriptor->Interval;\r
325 PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor->MaxPacketSize);\r
326\r
327 Status = UsbIo->UsbAsyncInterruptTransfer (\r
328 UsbIo,\r
329 EndpointAddr,\r
330 TRUE,\r
331 PollingInterval,\r
332 PacketSize,\r
333 OnMouseInterruptComplete,\r
334 UsbMouseDevice\r
335 );\r
336\r
337 if (!EFI_ERROR (Status)) {\r
338\r
339 UsbMouseDevice->ControllerNameTable = NULL;\r
340 AddUnicodeString (\r
341 "eng",\r
342 gUsbMouseComponentName.SupportedLanguages,\r
343 &UsbMouseDevice->ControllerNameTable,\r
344 (CHAR16 *) L"Generic Usb Mouse"\r
345 );\r
346\r
347 return EFI_SUCCESS;\r
348 }\r
349\r
350 //\r
351 // If submit error, uninstall that interface\r
352 //\r
353 Status = EFI_DEVICE_ERROR;\r
354 gBS->UninstallProtocolInterface (\r
355 Controller,\r
356 &gEfiSimplePointerProtocolGuid,\r
357 &UsbMouseDevice->SimplePointerProtocol\r
358 );\r
359\r
360ErrorExit:\r
361 if (EFI_ERROR (Status)) {\r
362 gBS->CloseProtocol (\r
363 Controller,\r
364 &gEfiUsbIoProtocolGuid,\r
365 This->DriverBindingHandle,\r
366 Controller\r
367 );\r
368\r
369 if (UsbMouseDevice != NULL) {\r
370 if (UsbMouseDevice->InterfaceDescriptor != NULL) {\r
371 gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);\r
372 }\r
373\r
374 if (UsbMouseDevice->IntEndpointDescriptor != NULL) {\r
375 gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);\r
376 }\r
377\r
378 if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) {\r
379 gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput);\r
380 }\r
381\r
382 gBS->FreePool (UsbMouseDevice);\r
383 UsbMouseDevice = NULL;\r
384 }\r
385 }\r
386\r
387 return Status;\r
388}\r
389\r
390EFI_STATUS\r
391EFIAPI\r
392USBMouseDriverBindingStop (\r
393 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
394 IN EFI_HANDLE Controller,\r
395 IN UINTN NumberOfChildren,\r
396 IN EFI_HANDLE *ChildHandleBuffer\r
397 )\r
398/*++\r
399\r
400 Routine Description:\r
401 Stop this driver on ControllerHandle. Support stoping any child handles\r
402 created by this driver.\r
403\r
404 Arguments:\r
405 This - Protocol instance pointer.\r
406 Controller - Handle of device to stop driver on\r
407 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
408 ChildHandleBuffer - List of handles for the children we need to stop.\r
409\r
410 Returns:\r
411 EFI_SUCCESS\r
412 EFI_DEVICE_ERROR\r
413 others\r
414\r
415--*/\r
416{\r
417 EFI_STATUS Status;\r
418 USB_MOUSE_DEV *UsbMouseDevice;\r
419 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;\r
420 EFI_USB_IO_PROTOCOL *UsbIo;\r
421\r
422 //\r
423 // Get our context back.\r
424 //\r
425 Status = gBS->OpenProtocol (\r
426 Controller,\r
427 &gEfiSimplePointerProtocolGuid,\r
428 (VOID **) &SimplePointerProtocol,\r
429 This->DriverBindingHandle,\r
430 Controller,\r
431 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
432 );\r
433\r
434 if (EFI_ERROR (Status)) {\r
435 return EFI_UNSUPPORTED;\r
436 }\r
437\r
438 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol);\r
439\r
440 gBS->CloseProtocol (\r
441 Controller,\r
442 &gEfiSimplePointerProtocolGuid,\r
443 This->DriverBindingHandle,\r
444 Controller\r
445 );\r
446\r
447 UsbIo = UsbMouseDevice->UsbIo;\r
448\r
449 //\r
450 // Uninstall the Asyn Interrupt Transfer from this device\r
451 // will disable the mouse data input from this device\r
452 //\r
453 MouseReportStatusCode (\r
454 UsbMouseDevice->DevicePath,\r
455 EFI_PROGRESS_CODE,\r
456 (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE)\r
457 );\r
458\r
459 //\r
460 // Delete Mouse Async Interrupt Transfer\r
461 //\r
462 UsbIo->UsbAsyncInterruptTransfer (\r
463 UsbIo,\r
464 UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,\r
465 FALSE,\r
466 UsbMouseDevice->IntEndpointDescriptor->Interval,\r
467 0,\r
468 NULL,\r
469 NULL\r
470 );\r
471\r
472 gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput);\r
473\r
474 if (UsbMouseDevice->DelayedRecoveryEvent) {\r
475 gBS->CloseEvent (UsbMouseDevice->DelayedRecoveryEvent);\r
476 UsbMouseDevice->DelayedRecoveryEvent = 0;\r
477 }\r
478\r
479 Status = gBS->UninstallProtocolInterface (\r
480 Controller,\r
481 &gEfiSimplePointerProtocolGuid,\r
482 &UsbMouseDevice->SimplePointerProtocol\r
483 );\r
484 if (EFI_ERROR (Status)) {\r
485 return Status;\r
486 }\r
487\r
488 gBS->CloseProtocol (\r
489 Controller,\r
490 &gEfiUsbIoProtocolGuid,\r
491 This->DriverBindingHandle,\r
492 Controller\r
493 );\r
494\r
495 gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);\r
496 gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);\r
497\r
498 if (UsbMouseDevice->ControllerNameTable) {\r
499 FreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable);\r
500 }\r
501\r
502 gBS->FreePool (UsbMouseDevice);\r
503\r
504 return EFI_SUCCESS;\r
505\r
506}\r
507\r
508BOOLEAN\r
509IsUsbMouse (\r
510 IN EFI_USB_IO_PROTOCOL *UsbIo\r
511 )\r
512/*++\r
513\r
514 Routine Description:\r
515 Tell if a Usb Controller is a mouse\r
516\r
517 Arguments:\r
518 UsbIo - Protocol instance pointer.\r
519\r
520 Returns:\r
521 TRUE - It is a mouse\r
522 FALSE - It is not a mouse\r
523--*/\r
524{\r
525 EFI_STATUS Status;\r
526 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;\r
527\r
528 //\r
529 // Get the Default interface descriptor, now we only\r
530 // suppose it is interface 1\r
531 //\r
532 Status = UsbIo->UsbGetInterfaceDescriptor (\r
533 UsbIo,\r
534 &InterfaceDescriptor\r
535 );\r
536\r
537 if (EFI_ERROR (Status)) {\r
538 return FALSE;\r
539 }\r
540\r
541 if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&\r
542 (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&\r
543 (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)\r
544 ) {\r
545 return TRUE;\r
546 }\r
547\r
548 return FALSE;\r
549}\r
550\r
551STATIC\r
552EFI_STATUS\r
553InitializeUsbMouseDevice (\r
554 IN USB_MOUSE_DEV *UsbMouseDev\r
555 )\r
556/*++\r
557\r
558 Routine Description:\r
559 Initialize the Usb Mouse Device.\r
560\r
561 Arguments:\r
562 UsbMouseDev - Device instance to be initialized\r
563\r
564 Returns:\r
565 EFI_SUCCESS - Success\r
566 EFI_DEVICE_ERROR - Init error.\r
567 EFI_OUT_OF_RESOURCES- Can't allocate memory\r
568--*/\r
569{\r
570 EFI_USB_IO_PROTOCOL *UsbIo;\r
571 UINT8 Protocol;\r
572 EFI_STATUS Status;\r
573 EFI_USB_HID_DESCRIPTOR MouseHidDesc;\r
574 UINT8 *ReportDesc;\r
575\r
576 UsbIo = UsbMouseDev->UsbIo;\r
577\r
578 //\r
579 // Get HID descriptor\r
580 //\r
581 Status = UsbGetHidDescriptor (\r
582 UsbIo,\r
583 UsbMouseDev->InterfaceDescriptor->InterfaceNumber,\r
584 &MouseHidDesc\r
585 );\r
586\r
587 if (EFI_ERROR (Status)) {\r
588 return Status;\r
589 }\r
590\r
591 //\r
592 // Get Report descriptor\r
593 //\r
594 if (MouseHidDesc.HidClassDesc[0].DescriptorType != 0x22) {\r
595 return EFI_UNSUPPORTED;\r
596 }\r
597\r
598 ReportDesc = AllocateZeroPool (MouseHidDesc.HidClassDesc[0].DescriptorLength);\r
599 if (ReportDesc == NULL) {\r
600 return EFI_OUT_OF_RESOURCES;\r
601 }\r
602\r
603 Status = UsbGetReportDescriptor (\r
604 UsbIo,\r
605 UsbMouseDev->InterfaceDescriptor->InterfaceNumber,\r
606 MouseHidDesc.HidClassDesc[0].DescriptorLength,\r
607 ReportDesc\r
608 );\r
609\r
610 if (EFI_ERROR (Status)) {\r
611 gBS->FreePool (ReportDesc);\r
612 return Status;\r
613 }\r
614\r
615 //\r
616 // Parse report descriptor\r
617 //\r
618 Status = ParseMouseReportDescriptor (\r
619 UsbMouseDev,\r
620 ReportDesc,\r
621 MouseHidDesc.HidClassDesc[0].DescriptorLength\r
622 );\r
623\r
624 if (EFI_ERROR (Status)) {\r
625 gBS->FreePool (ReportDesc);\r
626 return Status;\r
627 }\r
628\r
629 if (UsbMouseDev->NumberOfButtons >= 1) {\r
630 UsbMouseDev->Mode.LeftButton = TRUE;\r
631 }\r
632\r
633 if (UsbMouseDev->NumberOfButtons > 1) {\r
634 UsbMouseDev->Mode.RightButton = TRUE;\r
635 }\r
636\r
637 UsbMouseDev->Mode.ResolutionX = 8;\r
638 UsbMouseDev->Mode.ResolutionY = 8;\r
639 UsbMouseDev->Mode.ResolutionZ = 0;\r
640 //\r
641 // Here we just assume interface 0 is the mouse interface\r
642 //\r
643 UsbGetProtocolRequest (\r
644 UsbIo,\r
645 0,\r
646 &Protocol\r
647 );\r
648\r
649 if (Protocol != BOOT_PROTOCOL) {\r
650 Status = UsbSetProtocolRequest (\r
651 UsbIo,\r
652 0,\r
653 BOOT_PROTOCOL\r
654 );\r
655\r
656 if (EFI_ERROR (Status)) {\r
657 gBS->FreePool (ReportDesc);\r
658 return EFI_DEVICE_ERROR;\r
659 }\r
660 }\r
661\r
662 //\r
663 // Set indefinite Idle rate for USB Mouse\r
664 //\r
665 UsbSetIdleRequest (\r
666 UsbIo,\r
667 0,\r
668 0,\r
669 0\r
670 );\r
671\r
672 gBS->FreePool (ReportDesc);\r
673\r
674 if (UsbMouseDev->DelayedRecoveryEvent) {\r
675 gBS->CloseEvent (UsbMouseDev->DelayedRecoveryEvent);\r
676 UsbMouseDev->DelayedRecoveryEvent = 0;\r
677 }\r
678\r
679 Status = gBS->CreateEvent (\r
93b0fbc8 680 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
681 TPL_NOTIFY,\r
878ddf1f 682 USBMouseRecoveryHandler,\r
683 UsbMouseDev,\r
684 &UsbMouseDev->DelayedRecoveryEvent\r
685 );\r
686\r
687 return EFI_SUCCESS;\r
688}\r
689\r
690STATIC\r
691EFI_STATUS\r
692EFIAPI\r
693OnMouseInterruptComplete (\r
694 IN VOID *Data,\r
695 IN UINTN DataLength,\r
696 IN VOID *Context,\r
697 IN UINT32 Result\r
698 )\r
699/*++\r
700\r
701 Routine Description:\r
702 It is called whenever there is data received from async interrupt\r
703 transfer.\r
704\r
705 Arguments:\r
706 Data - Data received.\r
707 DataLength - Length of Data\r
708 Context - Passed in context\r
709 Result - Async Interrupt Transfer result\r
710\r
711 Returns:\r
712 EFI_SUCCESS\r
713 EFI_DEVICE_ERROR\r
714\r
715--*/\r
716{\r
717 USB_MOUSE_DEV *UsbMouseDevice;\r
718 EFI_USB_IO_PROTOCOL *UsbIo;\r
719 UINT8 EndpointAddr;\r
720 UINT32 UsbResult;\r
721\r
722 UsbMouseDevice = (USB_MOUSE_DEV *) Context;\r
723 UsbIo = UsbMouseDevice->UsbIo;\r
724\r
725 if (Result != EFI_USB_NOERROR) {\r
726 //\r
727 // Some errors happen during the process\r
728 //\r
729 MouseReportStatusCode (\r
730 UsbMouseDevice->DevicePath,\r
731 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
732 (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR)\r
733 );\r
734\r
735 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
736 EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress;\r
737\r
738 UsbClearEndpointHalt (\r
739 UsbIo,\r
740 EndpointAddr,\r
741 &UsbResult\r
742 );\r
743 }\r
744\r
745 UsbIo->UsbAsyncInterruptTransfer (\r
746 UsbIo,\r
747 UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,\r
748 FALSE,\r
749 0,\r
750 0,\r
751 NULL,\r
752 NULL\r
753 );\r
754\r
755 gBS->SetTimer (\r
756 UsbMouseDevice->DelayedRecoveryEvent,\r
757 TimerRelative,\r
758 EFI_USB_INTERRUPT_DELAY\r
759 );\r
760 return EFI_DEVICE_ERROR;\r
761 }\r
762\r
763 if (DataLength == 0 || Data == NULL) {\r
764 return EFI_SUCCESS;\r
765 }\r
766\r
767 UsbMouseDevice->StateChanged = TRUE;\r
768\r
769 //\r
770 // Check mouse Data\r
771 //\r
772 UsbMouseDevice->State.LeftButton = (BOOLEAN) (*(UINT8 *) Data & 0x01);\r
773 UsbMouseDevice->State.RightButton = (BOOLEAN) (*(UINT8 *) Data & 0x02);\r
774 UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1);\r
775 UsbMouseDevice->State.RelativeMovementY += *((INT8 *) Data + 2);\r
776\r
777 if (DataLength > 3) {\r
778 UsbMouseDevice->State.RelativeMovementZ += *((INT8 *) Data + 3);\r
779 }\r
780\r
781 return EFI_SUCCESS;\r
782}\r
783\r
784/*\r
785STATIC VOID\r
786PrintMouseState(\r
787 IN EFI_MOUSE_STATE *MouseState\r
788 )\r
789{\r
790 Aprint("(%x: %x, %x)\n",\r
791 MouseState->ButtonStates,\r
792 MouseState->dx,\r
793 MouseState->dy\r
794 );\r
795}\r
796*/\r
797STATIC\r
798EFI_STATUS\r
799EFIAPI\r
800GetMouseState (\r
801 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
802 OUT EFI_SIMPLE_POINTER_STATE *MouseState\r
803 )\r
804/*++\r
805\r
806 Routine Description:\r
807 Get the mouse state, see SIMPLE POINTER PROTOCOL.\r
93b0fbc8 808\r
878ddf1f 809 Arguments:\r
810 This - Protocol instance pointer.\r
811 MouseState - Current mouse state\r
93b0fbc8 812\r
878ddf1f 813 Returns:\r
814 EFI_SUCCESS\r
815 EFI_DEVICE_ERROR\r
816 EFI_NOT_READY\r
817\r
818--*/\r
819{\r
820 USB_MOUSE_DEV *MouseDev;\r
821\r
822 if (MouseState == NULL) {\r
823 return EFI_DEVICE_ERROR;\r
824 }\r
825\r
826 MouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);\r
827\r
828 if (!MouseDev->StateChanged) {\r
829 return EFI_NOT_READY;\r
830 }\r
831\r
832 CopyMem (\r
833 MouseState,\r
834 &MouseDev->State,\r
835 sizeof (EFI_SIMPLE_POINTER_STATE)\r
836 );\r
837\r
838 //\r
839 // Clear previous move state\r
840 //\r
841 MouseDev->State.RelativeMovementX = 0;\r
842 MouseDev->State.RelativeMovementY = 0;\r
843 MouseDev->State.RelativeMovementZ = 0;\r
844\r
845 MouseDev->StateChanged = FALSE;\r
846\r
847 return EFI_SUCCESS;\r
848}\r
849\r
850STATIC\r
851EFI_STATUS\r
852EFIAPI\r
853UsbMouseReset (\r
854 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
855 IN BOOLEAN ExtendedVerification\r
856 )\r
857/*++\r
858\r
859 Routine Description:\r
860 Reset the mouse device, see SIMPLE POINTER PROTOCOL.\r
93b0fbc8 861\r
878ddf1f 862 Arguments:\r
863 This - Protocol instance pointer.\r
864 ExtendedVerification - Ignored here/\r
93b0fbc8 865\r
878ddf1f 866 Returns:\r
867 EFI_SUCCESS\r
868\r
869--*/\r
870{\r
871 USB_MOUSE_DEV *UsbMouseDevice;\r
878ddf1f 872\r
873 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);\r
874\r
878ddf1f 875 MouseReportStatusCode (\r
876 UsbMouseDevice->DevicePath,\r
877 EFI_PROGRESS_CODE,\r
878 (EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET)\r
879 );\r
880\r
881 ZeroMem (\r
882 &UsbMouseDevice->State,\r
883 sizeof (EFI_SIMPLE_POINTER_STATE)\r
884 );\r
885 UsbMouseDevice->StateChanged = FALSE;\r
886\r
887 return EFI_SUCCESS;\r
888}\r
889\r
890STATIC\r
891VOID\r
892EFIAPI\r
893UsbMouseWaitForInput (\r
894 IN EFI_EVENT Event,\r
895 IN VOID *Context\r
896 )\r
897/*++\r
898\r
899Routine Description:\r
900\r
901 Event notification function for SIMPLE_POINTER.WaitForInput event\r
902 Signal the event if there is input from mouse\r
903\r
904Arguments:\r
905 Event - Wait Event\r
906 Context - Passed parameter to event handler\r
907Returns:\r
908 VOID\r
909--*/\r
910{\r
911 USB_MOUSE_DEV *UsbMouseDev;\r
912\r
913 UsbMouseDev = (USB_MOUSE_DEV *) Context;\r
914\r
915 //\r
916 // Someone is waiting on the mouse event, if there's\r
917 // input from mouse, signal the event\r
918 //\r
919 if (UsbMouseDev->StateChanged) {\r
920 gBS->SignalEvent (Event);\r
921 }\r
922}\r
923\r
924VOID\r
925EFIAPI\r
926USBMouseRecoveryHandler (\r
927 IN EFI_EVENT Event,\r
928 IN VOID *Context\r
929 )\r
930/*++\r
93b0fbc8 931\r
878ddf1f 932 Routine Description:\r
933 Timer handler for Delayed Recovery timer.\r
93b0fbc8 934\r
878ddf1f 935 Arguments:\r
936 Event - The Delayed Recovery event.\r
937 Context - Points to the USB_KB_DEV instance.\r
93b0fbc8 938\r
878ddf1f 939 Returns:\r
93b0fbc8 940\r
941--*/\r
878ddf1f 942{\r
943 USB_MOUSE_DEV *UsbMouseDev;\r
944 EFI_USB_IO_PROTOCOL *UsbIo;\r
945\r
946 UsbMouseDev = (USB_MOUSE_DEV *) Context;\r
947\r
948 UsbIo = UsbMouseDev->UsbIo;\r
949\r
950 UsbIo->UsbAsyncInterruptTransfer (\r
951 UsbIo,\r
952 UsbMouseDev->IntEndpointDescriptor->EndpointAddress,\r
953 TRUE,\r
954 UsbMouseDev->IntEndpointDescriptor->Interval,\r
955 UsbMouseDev->IntEndpointDescriptor->MaxPacketSize,\r
956 OnMouseInterruptComplete,\r
957 UsbMouseDev\r
958 );\r
959}\r
960\r
961VOID\r
962MouseReportStatusCode (\r
963 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
964 IN EFI_STATUS_CODE_TYPE CodeType,\r
965 IN EFI_STATUS_CODE_VALUE Value\r
966 )\r
967/*++\r
968\r
969 Routine Description:\r
970 Report Status Code in Usb Bot Driver\r
971\r
972 Arguments:\r
973 DevicePath - Use this to get Device Path\r
974 CodeType - Status Code Type\r
975 CodeValue - Status Code Value\r
976\r
977 Returns:\r
978 None\r
979\r
980--*/\r
981{\r
982\r
983 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
984 CodeType,\r
985 Value,\r
986 DevicePath\r
987 );\r
988}\r