]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMouseDxe/usbmouse.c
1. Sync Tcp4 protocol definitions to match UEFI 2.1
[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
ed838d0c 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
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
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
181EFI_STATUS\r
182EFIAPI\r
183USBMouseDriverBindingSupported (\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
c52fa98c 196 (VOID **) &UsbIo,\r
ed838d0c 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
243EFI_STATUS\r
244EFIAPI\r
245USBMouseDriverBindingStart (\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
c52fa98c 267 (VOID **) &UsbIo,\r
ed838d0c 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
436ErrorExit:\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
481EFI_STATUS\r
482EFIAPI\r
483USBMouseDriverBindingStop (\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
c52fa98c 501 (VOID **) &SimplePointerProtocol,\r
ed838d0c 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
591BOOLEAN\r
592IsUsbMouse (\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
633STATIC\r
634EFI_STATUS\r
635InitializeUsbMouseDevice (\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
773STATIC\r
774EFI_STATUS\r
775EFIAPI\r
776OnMouseInterruptComplete (\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
851STATIC VOID\r
852PrintMouseState(\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
875STATIC\r
876EFI_STATUS\r
877EFIAPI\r
878GetMouseState (\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
923STATIC\r
924EFI_STATUS\r
925EFIAPI\r
926UsbMouseReset (\r
927 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
928 IN BOOLEAN ExtendedVerification\r
929 )\r
930{\r
931 USB_MOUSE_DEV *UsbMouseDevice;\r
ed838d0c 932\r
933 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);\r
934\r
ed838d0c 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
961STATIC\r
962VOID\r
963EFIAPI\r
964UsbMouseWaitForInput (\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
991VOID\r
992EFIAPI\r
993USBMouseRecoveryHandler (\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
1027VOID\r
1028MouseReportStatusCode (\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