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