3 Copyright (c) 2006, 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
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.
23 EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding
= {
24 USBMouseDriverBindingSupported
,
25 USBMouseDriverBindingStart
,
26 USBMouseDriverBindingStop
,
38 IN EFI_USB_IO_PROTOCOL
*UsbIo
43 InitializeUsbMouseDevice (
44 IN USB_MOUSE_DEV
*UsbMouseDev
50 UsbMouseWaitForInput (
56 // Mouse interrupt handler
61 OnMouseInterruptComplete (
75 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
76 OUT EFI_SIMPLE_POINTER_STATE
*MouseState
83 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
84 IN BOOLEAN ExtendedVerification
89 USBMouseDriverBindingSupported (
90 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
91 IN EFI_HANDLE Controller
,
92 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
97 Test to see if this driver supports ControllerHandle. Any ControllerHandle
98 that has UsbHcProtocol installed will be supported.
101 This - Protocol instance pointer.
102 Controller - Handle of device to test
103 RemainingDevicePath - Not used
106 EFI_SUCCESS - This driver supports this device.
107 EFI_UNSUPPORTED - This driver does not support this device.
111 EFI_STATUS OpenStatus
;
112 EFI_USB_IO_PROTOCOL
*UsbIo
;
115 OpenStatus
= gBS
->OpenProtocol (
117 &gEfiUsbIoProtocolGuid
,
119 This
->DriverBindingHandle
,
121 EFI_OPEN_PROTOCOL_BY_DRIVER
123 if (EFI_ERROR (OpenStatus
) && (OpenStatus
!= EFI_ALREADY_STARTED
)) {
124 return EFI_UNSUPPORTED
;
127 if (OpenStatus
== EFI_ALREADY_STARTED
) {
128 return EFI_ALREADY_STARTED
;
132 // Use the USB I/O protocol interface to see the Controller is
133 // the Mouse controller that can be managed by this driver.
135 Status
= EFI_SUCCESS
;
136 if (!IsUsbMouse (UsbIo
)) {
137 Status
= EFI_UNSUPPORTED
;
142 &gEfiUsbIoProtocolGuid
,
143 This
->DriverBindingHandle
,
151 USBMouseDriverBindingStart (
152 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
153 IN EFI_HANDLE Controller
,
154 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
159 Starting the Usb Bus Driver
162 This - Protocol instance pointer.
163 Controller - Handle of device to test
164 RemainingDevicePath - Not used
167 EFI_SUCCESS - This driver supports this device.
168 EFI_UNSUPPORTED - This driver does not support this device.
169 EFI_DEVICE_ERROR - This driver cannot be started due to device
171 EFI_OUT_OF_RESOURCES- Can't allocate memory resources
172 EFI_ALREADY_STARTED - Thios driver has been started
176 EFI_USB_IO_PROTOCOL
*UsbIo
;
177 EFI_USB_ENDPOINT_DESCRIPTOR
*EndpointDesc
;
178 USB_MOUSE_DEV
*UsbMouseDevice
;
179 UINT8 EndpointNumber
;
182 UINT8 PollingInterval
;
185 UsbMouseDevice
= NULL
;
186 Status
= EFI_SUCCESS
;
188 Status
= gBS
->OpenProtocol (
190 &gEfiUsbIoProtocolGuid
,
192 This
->DriverBindingHandle
,
194 EFI_OPEN_PROTOCOL_BY_DRIVER
196 if (EFI_ERROR (Status
)) {
200 UsbMouseDevice
= AllocateZeroPool (sizeof (USB_MOUSE_DEV
));
201 if (UsbMouseDevice
== NULL
) {
202 Status
= EFI_OUT_OF_RESOURCES
;
206 UsbMouseDevice
->UsbIo
= UsbIo
;
208 UsbMouseDevice
->Signature
= USB_MOUSE_DEV_SIGNATURE
;
210 UsbMouseDevice
->InterfaceDescriptor
= AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
211 if (UsbMouseDevice
->InterfaceDescriptor
== NULL
) {
212 Status
= EFI_OUT_OF_RESOURCES
;
216 EndpointDesc
= AllocatePool (sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
));
217 if (EndpointDesc
== NULL
) {
218 Status
= EFI_OUT_OF_RESOURCES
;
222 // Get the Device Path Protocol on Controller's handle
224 Status
= gBS
->OpenProtocol (
226 &gEfiDevicePathProtocolGuid
,
227 (VOID
**) &UsbMouseDevice
->DevicePath
,
228 This
->DriverBindingHandle
,
230 EFI_OPEN_PROTOCOL_GET_PROTOCOL
233 if (EFI_ERROR (Status
)) {
237 // Get interface & endpoint descriptor
239 UsbIo
->UsbGetInterfaceDescriptor (
241 UsbMouseDevice
->InterfaceDescriptor
244 EndpointNumber
= UsbMouseDevice
->InterfaceDescriptor
->NumEndpoints
;
246 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
247 UsbIo
->UsbGetEndpointDescriptor (
253 if ((EndpointDesc
->Attributes
& 0x03) == 0x03) {
256 // We only care interrupt endpoint here
258 UsbMouseDevice
->IntEndpointDescriptor
= EndpointDesc
;
262 if (UsbMouseDevice
->IntEndpointDescriptor
== NULL
) {
264 // No interrupt endpoint, then error
266 Status
= EFI_UNSUPPORTED
;
270 Status
= InitializeUsbMouseDevice (UsbMouseDevice
);
271 if (EFI_ERROR (Status
)) {
272 MouseReportStatusCode (
273 UsbMouseDevice
->DevicePath
,
274 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
275 (EFI_PERIPHERAL_MOUSE
| EFI_P_EC_INTERFACE_ERROR
)
281 UsbMouseDevice
->SimplePointerProtocol
.GetState
= GetMouseState
;
282 UsbMouseDevice
->SimplePointerProtocol
.Reset
= UsbMouseReset
;
283 UsbMouseDevice
->SimplePointerProtocol
.Mode
= &UsbMouseDevice
->Mode
;
285 Status
= gBS
->CreateEvent (
286 EFI_EVENT_NOTIFY_WAIT
,
288 UsbMouseWaitForInput
,
290 &((UsbMouseDevice
->SimplePointerProtocol
).WaitForInput
)
292 if (EFI_ERROR (Status
)) {
296 Status
= gBS
->InstallProtocolInterface (
298 &gEfiSimplePointerProtocolGuid
,
299 EFI_NATIVE_INTERFACE
,
300 &UsbMouseDevice
->SimplePointerProtocol
303 if (EFI_ERROR (Status
)) {
304 Status
= EFI_DEVICE_ERROR
;
309 // After Enabling Async Interrupt Transfer on this mouse Device
310 // we will be able to get key data from it. Thus this is deemed as
311 // the enable action of the mouse
314 MouseReportStatusCode (
315 UsbMouseDevice
->DevicePath
,
317 (EFI_PERIPHERAL_MOUSE
| EFI_P_PC_ENABLE
)
321 // submit async interrupt transfer
323 EndpointAddr
= UsbMouseDevice
->IntEndpointDescriptor
->EndpointAddress
;
324 PollingInterval
= UsbMouseDevice
->IntEndpointDescriptor
->Interval
;
325 PacketSize
= (UINT8
) (UsbMouseDevice
->IntEndpointDescriptor
->MaxPacketSize
);
327 Status
= UsbIo
->UsbAsyncInterruptTransfer (
333 OnMouseInterruptComplete
,
337 if (!EFI_ERROR (Status
)) {
339 UsbMouseDevice
->ControllerNameTable
= NULL
;
342 gUsbMouseComponentName
.SupportedLanguages
,
343 &UsbMouseDevice
->ControllerNameTable
,
344 (CHAR16
*) L
"Generic Usb Mouse"
351 // If submit error, uninstall that interface
353 Status
= EFI_DEVICE_ERROR
;
354 gBS
->UninstallProtocolInterface (
356 &gEfiSimplePointerProtocolGuid
,
357 &UsbMouseDevice
->SimplePointerProtocol
361 if (EFI_ERROR (Status
)) {
364 &gEfiUsbIoProtocolGuid
,
365 This
->DriverBindingHandle
,
369 if (UsbMouseDevice
!= NULL
) {
370 if (UsbMouseDevice
->InterfaceDescriptor
!= NULL
) {
371 gBS
->FreePool (UsbMouseDevice
->InterfaceDescriptor
);
374 if (UsbMouseDevice
->IntEndpointDescriptor
!= NULL
) {
375 gBS
->FreePool (UsbMouseDevice
->IntEndpointDescriptor
);
378 if ((UsbMouseDevice
->SimplePointerProtocol
).WaitForInput
!= NULL
) {
379 gBS
->CloseEvent ((UsbMouseDevice
->SimplePointerProtocol
).WaitForInput
);
382 gBS
->FreePool (UsbMouseDevice
);
383 UsbMouseDevice
= NULL
;
392 USBMouseDriverBindingStop (
393 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
394 IN EFI_HANDLE Controller
,
395 IN UINTN NumberOfChildren
,
396 IN EFI_HANDLE
*ChildHandleBuffer
401 Stop this driver on ControllerHandle. Support stoping any child handles
402 created by this driver.
405 This - Protocol instance pointer.
406 Controller - Handle of device to stop driver on
407 NumberOfChildren - Number of Children in the ChildHandleBuffer
408 ChildHandleBuffer - List of handles for the children we need to stop.
418 USB_MOUSE_DEV
*UsbMouseDevice
;
419 EFI_SIMPLE_POINTER_PROTOCOL
*SimplePointerProtocol
;
420 EFI_USB_IO_PROTOCOL
*UsbIo
;
423 // Get our context back.
425 Status
= gBS
->OpenProtocol (
427 &gEfiSimplePointerProtocolGuid
,
428 (VOID
**) &SimplePointerProtocol
,
429 This
->DriverBindingHandle
,
431 EFI_OPEN_PROTOCOL_GET_PROTOCOL
434 if (EFI_ERROR (Status
)) {
435 return EFI_UNSUPPORTED
;
438 UsbMouseDevice
= USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol
);
442 &gEfiSimplePointerProtocolGuid
,
443 This
->DriverBindingHandle
,
447 UsbIo
= UsbMouseDevice
->UsbIo
;
450 // Uninstall the Asyn Interrupt Transfer from this device
451 // will disable the mouse data input from this device
453 MouseReportStatusCode (
454 UsbMouseDevice
->DevicePath
,
456 (EFI_PERIPHERAL_MOUSE
| EFI_P_PC_DISABLE
)
460 // Delete Mouse Async Interrupt Transfer
462 UsbIo
->UsbAsyncInterruptTransfer (
464 UsbMouseDevice
->IntEndpointDescriptor
->EndpointAddress
,
466 UsbMouseDevice
->IntEndpointDescriptor
->Interval
,
472 gBS
->CloseEvent (UsbMouseDevice
->SimplePointerProtocol
.WaitForInput
);
474 if (UsbMouseDevice
->DelayedRecoveryEvent
) {
475 gBS
->CloseEvent (UsbMouseDevice
->DelayedRecoveryEvent
);
476 UsbMouseDevice
->DelayedRecoveryEvent
= 0;
479 Status
= gBS
->UninstallProtocolInterface (
481 &gEfiSimplePointerProtocolGuid
,
482 &UsbMouseDevice
->SimplePointerProtocol
484 if (EFI_ERROR (Status
)) {
490 &gEfiUsbIoProtocolGuid
,
491 This
->DriverBindingHandle
,
495 gBS
->FreePool (UsbMouseDevice
->InterfaceDescriptor
);
496 gBS
->FreePool (UsbMouseDevice
->IntEndpointDescriptor
);
498 if (UsbMouseDevice
->ControllerNameTable
) {
499 FreeUnicodeStringTable (UsbMouseDevice
->ControllerNameTable
);
502 gBS
->FreePool (UsbMouseDevice
);
510 IN EFI_USB_IO_PROTOCOL
*UsbIo
515 Tell if a Usb Controller is a mouse
518 UsbIo - Protocol instance pointer.
522 FALSE - It is not a mouse
526 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
529 // Get the Default interface descriptor, now we only
530 // suppose it is interface 1
532 Status
= UsbIo
->UsbGetInterfaceDescriptor (
537 if (EFI_ERROR (Status
)) {
541 if ((InterfaceDescriptor
.InterfaceClass
== CLASS_HID
) &&
542 (InterfaceDescriptor
.InterfaceSubClass
== SUBCLASS_BOOT
) &&
543 (InterfaceDescriptor
.InterfaceProtocol
== PROTOCOL_MOUSE
)
553 InitializeUsbMouseDevice (
554 IN USB_MOUSE_DEV
*UsbMouseDev
559 Initialize the Usb Mouse Device.
562 UsbMouseDev - Device instance to be initialized
565 EFI_SUCCESS - Success
566 EFI_DEVICE_ERROR - Init error.
567 EFI_OUT_OF_RESOURCES- Can't allocate memory
570 EFI_USB_IO_PROTOCOL
*UsbIo
;
573 EFI_USB_HID_DESCRIPTOR MouseHidDesc
;
576 UsbIo
= UsbMouseDev
->UsbIo
;
579 // Get HID descriptor
581 Status
= UsbGetHidDescriptor (
583 UsbMouseDev
->InterfaceDescriptor
->InterfaceNumber
,
587 if (EFI_ERROR (Status
)) {
592 // Get Report descriptor
594 if (MouseHidDesc
.HidClassDesc
[0].DescriptorType
!= 0x22) {
595 return EFI_UNSUPPORTED
;
598 ReportDesc
= AllocateZeroPool (MouseHidDesc
.HidClassDesc
[0].DescriptorLength
);
599 if (ReportDesc
== NULL
) {
600 return EFI_OUT_OF_RESOURCES
;
603 Status
= UsbGetReportDescriptor (
605 UsbMouseDev
->InterfaceDescriptor
->InterfaceNumber
,
606 MouseHidDesc
.HidClassDesc
[0].DescriptorLength
,
610 if (EFI_ERROR (Status
)) {
611 gBS
->FreePool (ReportDesc
);
616 // Parse report descriptor
618 Status
= ParseMouseReportDescriptor (
621 MouseHidDesc
.HidClassDesc
[0].DescriptorLength
624 if (EFI_ERROR (Status
)) {
625 gBS
->FreePool (ReportDesc
);
629 if (UsbMouseDev
->NumberOfButtons
>= 1) {
630 UsbMouseDev
->Mode
.LeftButton
= TRUE
;
633 if (UsbMouseDev
->NumberOfButtons
> 1) {
634 UsbMouseDev
->Mode
.RightButton
= TRUE
;
637 UsbMouseDev
->Mode
.ResolutionX
= 8;
638 UsbMouseDev
->Mode
.ResolutionY
= 8;
639 UsbMouseDev
->Mode
.ResolutionZ
= 0;
641 // Here we just assume interface 0 is the mouse interface
643 UsbGetProtocolRequest (
649 if (Protocol
!= BOOT_PROTOCOL
) {
650 Status
= UsbSetProtocolRequest (
656 if (EFI_ERROR (Status
)) {
657 gBS
->FreePool (ReportDesc
);
658 return EFI_DEVICE_ERROR
;
663 // Set indefinite Idle rate for USB Mouse
672 gBS
->FreePool (ReportDesc
);
674 if (UsbMouseDev
->DelayedRecoveryEvent
) {
675 gBS
->CloseEvent (UsbMouseDev
->DelayedRecoveryEvent
);
676 UsbMouseDev
->DelayedRecoveryEvent
= 0;
679 Status
= gBS
->CreateEvent (
680 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
682 USBMouseRecoveryHandler
,
684 &UsbMouseDev
->DelayedRecoveryEvent
693 OnMouseInterruptComplete (
702 It is called whenever there is data received from async interrupt
706 Data - Data received.
707 DataLength - Length of Data
708 Context - Passed in context
709 Result - Async Interrupt Transfer result
717 USB_MOUSE_DEV
*UsbMouseDevice
;
718 EFI_USB_IO_PROTOCOL
*UsbIo
;
722 UsbMouseDevice
= (USB_MOUSE_DEV
*) Context
;
723 UsbIo
= UsbMouseDevice
->UsbIo
;
725 if (Result
!= EFI_USB_NOERROR
) {
727 // Some errors happen during the process
729 MouseReportStatusCode (
730 UsbMouseDevice
->DevicePath
,
731 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
732 (EFI_PERIPHERAL_MOUSE
| EFI_P_EC_INPUT_ERROR
)
735 if ((Result
& EFI_USB_ERR_STALL
) == EFI_USB_ERR_STALL
) {
736 EndpointAddr
= UsbMouseDevice
->IntEndpointDescriptor
->EndpointAddress
;
738 UsbClearEndpointHalt (
745 UsbIo
->UsbAsyncInterruptTransfer (
747 UsbMouseDevice
->IntEndpointDescriptor
->EndpointAddress
,
756 UsbMouseDevice
->DelayedRecoveryEvent
,
758 EFI_USB_INTERRUPT_DELAY
760 return EFI_DEVICE_ERROR
;
763 if (DataLength
== 0 || Data
== NULL
) {
767 UsbMouseDevice
->StateChanged
= TRUE
;
772 UsbMouseDevice
->State
.LeftButton
= (BOOLEAN
) (*(UINT8
*) Data
& 0x01);
773 UsbMouseDevice
->State
.RightButton
= (BOOLEAN
) (*(UINT8
*) Data
& 0x02);
774 UsbMouseDevice
->State
.RelativeMovementX
+= *((INT8
*) Data
+ 1);
775 UsbMouseDevice
->State
.RelativeMovementY
+= *((INT8
*) Data
+ 2);
777 if (DataLength
> 3) {
778 UsbMouseDevice
->State
.RelativeMovementZ
+= *((INT8
*) Data
+ 3);
787 IN EFI_MOUSE_STATE *MouseState
790 Aprint("(%x: %x, %x)\n",
791 MouseState->ButtonStates,
801 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
802 OUT EFI_SIMPLE_POINTER_STATE
*MouseState
807 Get the mouse state, see SIMPLE POINTER PROTOCOL.
810 This - Protocol instance pointer.
811 MouseState - Current mouse state
820 USB_MOUSE_DEV
*MouseDev
;
822 if (MouseState
== NULL
) {
823 return EFI_DEVICE_ERROR
;
826 MouseDev
= USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This
);
828 if (!MouseDev
->StateChanged
) {
829 return EFI_NOT_READY
;
835 sizeof (EFI_SIMPLE_POINTER_STATE
)
839 // Clear previous move state
841 MouseDev
->State
.RelativeMovementX
= 0;
842 MouseDev
->State
.RelativeMovementY
= 0;
843 MouseDev
->State
.RelativeMovementZ
= 0;
845 MouseDev
->StateChanged
= FALSE
;
854 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
855 IN BOOLEAN ExtendedVerification
860 Reset the mouse device, see SIMPLE POINTER PROTOCOL.
863 This - Protocol instance pointer.
864 ExtendedVerification - Ignored here/
871 USB_MOUSE_DEV
*UsbMouseDevice
;
873 UsbMouseDevice
= USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This
);
875 MouseReportStatusCode (
876 UsbMouseDevice
->DevicePath
,
878 (EFI_PERIPHERAL_MOUSE
| EFI_P_PC_RESET
)
882 &UsbMouseDevice
->State
,
883 sizeof (EFI_SIMPLE_POINTER_STATE
)
885 UsbMouseDevice
->StateChanged
= FALSE
;
893 UsbMouseWaitForInput (
901 Event notification function for SIMPLE_POINTER.WaitForInput event
902 Signal the event if there is input from mouse
906 Context - Passed parameter to event handler
911 USB_MOUSE_DEV
*UsbMouseDev
;
913 UsbMouseDev
= (USB_MOUSE_DEV
*) Context
;
916 // Someone is waiting on the mouse event, if there's
917 // input from mouse, signal the event
919 if (UsbMouseDev
->StateChanged
) {
920 gBS
->SignalEvent (Event
);
926 USBMouseRecoveryHandler (
933 Timer handler for Delayed Recovery timer.
936 Event - The Delayed Recovery event.
937 Context - Points to the USB_KB_DEV instance.
943 USB_MOUSE_DEV
*UsbMouseDev
;
944 EFI_USB_IO_PROTOCOL
*UsbIo
;
946 UsbMouseDev
= (USB_MOUSE_DEV
*) Context
;
948 UsbIo
= UsbMouseDev
->UsbIo
;
950 UsbIo
->UsbAsyncInterruptTransfer (
952 UsbMouseDev
->IntEndpointDescriptor
->EndpointAddress
,
954 UsbMouseDev
->IntEndpointDescriptor
->Interval
,
955 UsbMouseDev
->IntEndpointDescriptor
->MaxPacketSize
,
956 OnMouseInterruptComplete
,
962 MouseReportStatusCode (
963 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
964 IN EFI_STATUS_CODE_TYPE CodeType
,
965 IN EFI_STATUS_CODE_VALUE Value
970 Report Status Code in Usb Bot Driver
973 DevicePath - Use this to get Device Path
974 CodeType - Status Code Type
975 CodeValue - Status Code Value
983 REPORT_STATUS_CODE_WITH_DEVICE_PATH (