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