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