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