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