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