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