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