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