]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouse.c
Rename file to use recommended file naming conventions.
[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 EfiLibInstallDriverBindingComponentName2 (
158 ImageHandle,
159 SystemTable,
160 &gUsbMouseDriverBinding,
161 ImageHandle,
162 &gUsbMouseComponentName,
163 &gUsbMouseComponentName2
164 );
165 }
166
167
168 /**
169 Test to see if this driver supports ControllerHandle. Any ControllerHandle
170 that has UsbHcProtocol installed will be supported.
171
172 @param This Protocol instance pointer.
173 @param Controller Handle of device to test
174 @param RemainingDevicePath Not used
175
176 @retval EFI_SUCCESS This driver supports this device.
177 @retval EFI_UNSUPPORTED This driver does not support this device.
178
179 **/
180 EFI_STATUS
181 EFIAPI
182 USBMouseDriverBindingSupported (
183 IN EFI_DRIVER_BINDING_PROTOCOL *This,
184 IN EFI_HANDLE Controller,
185 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
186 )
187 {
188 EFI_STATUS OpenStatus;
189 EFI_USB_IO_PROTOCOL *UsbIo;
190 EFI_STATUS Status;
191
192 OpenStatus = gBS->OpenProtocol (
193 Controller,
194 &gEfiUsbIoProtocolGuid,
195 (VOID **) &UsbIo,
196 This->DriverBindingHandle,
197 Controller,
198 EFI_OPEN_PROTOCOL_BY_DRIVER
199 );
200 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
201 return EFI_UNSUPPORTED;
202 }
203
204 if (OpenStatus == EFI_ALREADY_STARTED) {
205 return EFI_ALREADY_STARTED;
206 }
207
208 //
209 // Use the USB I/O protocol interface to see the Controller is
210 // the Mouse controller that can be managed by this driver.
211 //
212 Status = EFI_SUCCESS;
213 if (!IsUsbMouse (UsbIo)) {
214 Status = EFI_UNSUPPORTED;
215 }
216
217 gBS->CloseProtocol (
218 Controller,
219 &gEfiUsbIoProtocolGuid,
220 This->DriverBindingHandle,
221 Controller
222 );
223 return Status;
224 }
225
226
227 /**
228 Starting the Usb Bus Driver
229
230 @param This Protocol instance pointer.
231 @param Controller Handle of device to test
232 @param RemainingDevicePath Not used
233
234 @retval EFI_SUCCESS This driver supports this device.
235 @retval EFI_UNSUPPORTED This driver does not support this device.
236 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error
237 EFI_OUT_OF_RESOURCES- Can't allocate memory
238 resources
239 @retval EFI_ALREADY_STARTED Thios driver has been started
240
241 **/
242 EFI_STATUS
243 EFIAPI
244 USBMouseDriverBindingStart (
245 IN EFI_DRIVER_BINDING_PROTOCOL *This,
246 IN EFI_HANDLE Controller,
247 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
248 )
249 {
250 EFI_STATUS Status;
251 EFI_USB_IO_PROTOCOL *UsbIo;
252 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;
253 USB_MOUSE_DEV *UsbMouseDevice;
254 UINT8 EndpointNumber;
255 UINT8 Index;
256 UINT8 EndpointAddr;
257 UINT8 PollingInterval;
258 UINT8 PacketSize;
259
260 UsbMouseDevice = NULL;
261 Status = EFI_SUCCESS;
262
263 Status = gBS->OpenProtocol (
264 Controller,
265 &gEfiUsbIoProtocolGuid,
266 (VOID **) &UsbIo,
267 This->DriverBindingHandle,
268 Controller,
269 EFI_OPEN_PROTOCOL_BY_DRIVER
270 );
271 if (EFI_ERROR (Status)) {
272 goto ErrorExit;
273 }
274
275 UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV));
276 if (UsbMouseDevice == NULL) {
277 Status = EFI_OUT_OF_RESOURCES;
278 goto ErrorExit;
279 }
280
281 UsbMouseDevice->UsbIo = UsbIo;
282
283 UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE;
284
285 UsbMouseDevice->InterfaceDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
286 if (UsbMouseDevice->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 **) &UsbMouseDevice->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 UsbMouseDevice->InterfaceDescriptor
317 );
318
319 EndpointNumber = UsbMouseDevice->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 UsbMouseDevice->IntEndpointDescriptor = EndpointDesc;
334 }
335 }
336
337 if (UsbMouseDevice->IntEndpointDescriptor == NULL) {
338 //
339 // No interrupt endpoint, then error
340 //
341 Status = EFI_UNSUPPORTED;
342 goto ErrorExit;
343 }
344
345 Status = InitializeUsbMouseDevice (UsbMouseDevice);
346 if (EFI_ERROR (Status)) {
347 MouseReportStatusCode (
348 UsbMouseDevice->DevicePath,
349 EFI_ERROR_CODE | EFI_ERROR_MINOR,
350 PcdGet32 (PcdStatusCodeValueMouseInterfaceError)
351 );
352
353 goto ErrorExit;
354 }
355
356 UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState;
357 UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset;
358 UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode;
359
360 Status = gBS->CreateEvent (
361 EVT_NOTIFY_WAIT,
362 TPL_NOTIFY,
363 UsbMouseWaitForInput,
364 UsbMouseDevice,
365 &((UsbMouseDevice->SimplePointerProtocol).WaitForInput)
366 );
367 if (EFI_ERROR (Status)) {
368 goto ErrorExit;
369 }
370
371 Status = gBS->InstallProtocolInterface (
372 &Controller,
373 &gEfiSimplePointerProtocolGuid,
374 EFI_NATIVE_INTERFACE,
375 &UsbMouseDevice->SimplePointerProtocol
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 MouseReportStatusCode (
390 UsbMouseDevice->DevicePath,
391 EFI_PROGRESS_CODE,
392 PcdGet32 (PcdStatusCodeValueMouseEnable)
393 );
394
395 //
396 // submit async interrupt transfer
397 //
398 EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress;
399 PollingInterval = UsbMouseDevice->IntEndpointDescriptor->Interval;
400 PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor->MaxPacketSize);
401
402 Status = UsbIo->UsbAsyncInterruptTransfer (
403 UsbIo,
404 EndpointAddr,
405 TRUE,
406 PollingInterval,
407 PacketSize,
408 OnMouseInterruptComplete,
409 UsbMouseDevice
410 );
411
412 if (!EFI_ERROR (Status)) {
413
414 UsbMouseDevice->ControllerNameTable = NULL;
415 AddUnicodeString2 (
416 "eng",
417 gUsbMouseComponentName.SupportedLanguages,
418 &UsbMouseDevice->ControllerNameTable,
419 L"Generic Usb Mouse",
420 TRUE
421 );
422 AddUnicodeString2 (
423 "en",
424 gUsbMouseComponentName2.SupportedLanguages,
425 &UsbMouseDevice->ControllerNameTable,
426 L"Generic Usb Mouse",
427 FALSE
428 );
429
430
431 return EFI_SUCCESS;
432 }
433
434 //
435 // If submit error, uninstall that interface
436 //
437 Status = EFI_DEVICE_ERROR;
438 gBS->UninstallProtocolInterface (
439 Controller,
440 &gEfiSimplePointerProtocolGuid,
441 &UsbMouseDevice->SimplePointerProtocol
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 (UsbMouseDevice != NULL) {
454 if (UsbMouseDevice->InterfaceDescriptor != NULL) {
455 gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);
456 }
457
458 if (UsbMouseDevice->IntEndpointDescriptor != NULL) {
459 gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);
460 }
461
462 if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) {
463 gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput);
464 }
465
466 gBS->FreePool (UsbMouseDevice);
467 UsbMouseDevice = 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 USBMouseDriverBindingStop (
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_DEV *UsbMouseDevice;
500 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;
501 EFI_USB_IO_PROTOCOL *UsbIo;
502
503 //
504 // Get our context back.
505 //
506 Status = gBS->OpenProtocol (
507 Controller,
508 &gEfiSimplePointerProtocolGuid,
509 (VOID **) &SimplePointerProtocol,
510 This->DriverBindingHandle,
511 Controller,
512 EFI_OPEN_PROTOCOL_GET_PROTOCOL
513 );
514
515 if (EFI_ERROR (Status)) {
516 return EFI_UNSUPPORTED;
517 }
518
519 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol);
520
521 gBS->CloseProtocol (
522 Controller,
523 &gEfiSimplePointerProtocolGuid,
524 This->DriverBindingHandle,
525 Controller
526 );
527
528 UsbIo = UsbMouseDevice->UsbIo;
529
530 //
531 // Uninstall the Asyn Interrupt Transfer from this device
532 // will disable the mouse data input from this device
533 //
534 MouseReportStatusCode (
535 UsbMouseDevice->DevicePath,
536 EFI_PROGRESS_CODE,
537 PcdGet32 (PcdStatusCodeValueMouseDisable)
538 );
539
540 //
541 // Delete Mouse Async Interrupt Transfer
542 //
543 UsbIo->UsbAsyncInterruptTransfer (
544 UsbIo,
545 UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,
546 FALSE,
547 UsbMouseDevice->IntEndpointDescriptor->Interval,
548 0,
549 NULL,
550 NULL
551 );
552
553 gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput);
554
555 if (UsbMouseDevice->DelayedRecoveryEvent) {
556 gBS->CloseEvent (UsbMouseDevice->DelayedRecoveryEvent);
557 UsbMouseDevice->DelayedRecoveryEvent = 0;
558 }
559
560 Status = gBS->UninstallProtocolInterface (
561 Controller,
562 &gEfiSimplePointerProtocolGuid,
563 &UsbMouseDevice->SimplePointerProtocol
564 );
565 if (EFI_ERROR (Status)) {
566 return Status;
567 }
568
569 gBS->CloseProtocol (
570 Controller,
571 &gEfiUsbIoProtocolGuid,
572 This->DriverBindingHandle,
573 Controller
574 );
575
576 gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);
577 gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);
578
579 if (UsbMouseDevice->ControllerNameTable) {
580 FreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable);
581 }
582
583 gBS->FreePool (UsbMouseDevice);
584
585 return EFI_SUCCESS;
586
587 }
588
589
590 /**
591 Tell if a Usb Controller is a mouse
592
593 @param UsbIo Protocol instance pointer.
594
595 @retval TRUE It is a mouse
596 @retval FALSE It is not a mouse
597
598 **/
599 BOOLEAN
600 IsUsbMouse (
601 IN EFI_USB_IO_PROTOCOL *UsbIo
602 )
603 {
604 EFI_STATUS Status;
605 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
606
607 //
608 // Get the Default interface descriptor, now we only
609 // suppose it is interface 1
610 //
611 Status = UsbIo->UsbGetInterfaceDescriptor (
612 UsbIo,
613 &InterfaceDescriptor
614 );
615
616 if (EFI_ERROR (Status)) {
617 return FALSE;
618 }
619
620 if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&
621 (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&
622 (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)
623 ) {
624 return TRUE;
625 }
626
627 return FALSE;
628 }
629
630
631 /**
632 Initialize the Usb Mouse Device.
633
634 @param UsbMouseDev 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 InitializeUsbMouseDevice (
644 IN USB_MOUSE_DEV *UsbMouseDev
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 = UsbMouseDev->UsbIo;
654
655 //
656 // Get HID descriptor
657 //
658 Status = UsbGetHidDescriptor (
659 UsbIo,
660 UsbMouseDev->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 UsbMouseDev->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 UsbMouseDev,
697 ReportDesc,
698 MouseHidDesc.HidClassDesc[0].DescriptorLength
699 );
700
701 if (EFI_ERROR (Status)) {
702 gBS->FreePool (ReportDesc);
703 return Status;
704 }
705
706 if (UsbMouseDev->NumberOfButtons >= 1) {
707 UsbMouseDev->Mode.LeftButton = TRUE;
708 }
709
710 if (UsbMouseDev->NumberOfButtons > 1) {
711 UsbMouseDev->Mode.RightButton = TRUE;
712 }
713
714 UsbMouseDev->Mode.ResolutionX = 8;
715 UsbMouseDev->Mode.ResolutionY = 8;
716 UsbMouseDev->Mode.ResolutionZ = 0;
717 //
718 // Here we just assume interface 0 is the mouse interface
719 //
720 UsbGetProtocolRequest (
721 UsbIo,
722 0,
723 &Protocol
724 );
725
726 if (Protocol != BOOT_PROTOCOL) {
727 Status = UsbSetProtocolRequest (
728 UsbIo,
729 0,
730 BOOT_PROTOCOL
731 );
732
733 if (EFI_ERROR (Status)) {
734 gBS->FreePool (ReportDesc);
735 return EFI_DEVICE_ERROR;
736 }
737 }
738
739 //
740 // Set indefinite Idle rate for USB Mouse
741 //
742 UsbSetIdleRequest (
743 UsbIo,
744 0,
745 0,
746 0
747 );
748
749 gBS->FreePool (ReportDesc);
750
751 if (UsbMouseDev->DelayedRecoveryEvent) {
752 gBS->CloseEvent (UsbMouseDev->DelayedRecoveryEvent);
753 UsbMouseDev->DelayedRecoveryEvent = 0;
754 }
755
756 Status = gBS->CreateEvent (
757 EVT_TIMER | EVT_NOTIFY_SIGNAL,
758 TPL_NOTIFY,
759 USBMouseRecoveryHandler,
760 UsbMouseDev,
761 &UsbMouseDev->DelayedRecoveryEvent
762 );
763
764 return EFI_SUCCESS;
765 }
766
767
768 /**
769 It is called whenever there is data received from async interrupt
770 transfer.
771
772 @param Data Data received.
773 @param DataLength Length of Data
774 @param Context Passed in context
775 @param Result Async Interrupt Transfer result
776
777 @return EFI_SUCCESS
778 @return EFI_DEVICE_ERROR
779
780 **/
781 STATIC
782 EFI_STATUS
783 EFIAPI
784 OnMouseInterruptComplete (
785 IN VOID *Data,
786 IN UINTN DataLength,
787 IN VOID *Context,
788 IN UINT32 Result
789 )
790 {
791 USB_MOUSE_DEV *UsbMouseDevice;
792 EFI_USB_IO_PROTOCOL *UsbIo;
793 UINT8 EndpointAddr;
794 UINT32 UsbResult;
795
796 UsbMouseDevice = (USB_MOUSE_DEV *) Context;
797 UsbIo = UsbMouseDevice->UsbIo;
798
799 if (Result != EFI_USB_NOERROR) {
800 //
801 // Some errors happen during the process
802 //
803 MouseReportStatusCode (
804 UsbMouseDevice->DevicePath,
805 EFI_ERROR_CODE | EFI_ERROR_MINOR,
806 PcdGet32 (PcdStatusCodeValueMouseInputError)
807 );
808
809 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
810 EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress;
811
812 UsbClearEndpointHalt (
813 UsbIo,
814 EndpointAddr,
815 &UsbResult
816 );
817 }
818
819 UsbIo->UsbAsyncInterruptTransfer (
820 UsbIo,
821 UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,
822 FALSE,
823 0,
824 0,
825 NULL,
826 NULL
827 );
828
829 gBS->SetTimer (
830 UsbMouseDevice->DelayedRecoveryEvent,
831 TimerRelative,
832 EFI_USB_INTERRUPT_DELAY
833 );
834 return EFI_DEVICE_ERROR;
835 }
836
837 if (DataLength == 0 || Data == NULL) {
838 return EFI_SUCCESS;
839 }
840
841 UsbMouseDevice->StateChanged = TRUE;
842
843 //
844 // Check mouse Data
845 //
846 UsbMouseDevice->State.LeftButton = (BOOLEAN) (*(UINT8 *) Data & 0x01);
847 UsbMouseDevice->State.RightButton = (BOOLEAN) (*(UINT8 *) Data & 0x02);
848 UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1);
849 UsbMouseDevice->State.RelativeMovementY += *((INT8 *) Data + 2);
850
851 if (DataLength > 3) {
852 UsbMouseDevice->State.RelativeMovementZ += *((INT8 *) Data + 3);
853 }
854
855 return EFI_SUCCESS;
856 }
857
858 /*
859 STATIC VOID
860 PrintMouseState(
861 IN EFI_MOUSE_STATE *MouseState
862 )
863 {
864 Aprint("(%x: %x, %x)\n",
865 MouseState->ButtonStates,
866 MouseState->dx,
867 MouseState->dy
868 );
869 }
870 */
871
872 /**
873 Get the mouse state, see SIMPLE POINTER PROTOCOL.
874
875 @param This Protocol instance pointer.
876 @param MouseState Current mouse state
877
878 @return EFI_SUCCESS
879 @return EFI_DEVICE_ERROR
880 @return EFI_NOT_READY
881
882 **/
883 STATIC
884 EFI_STATUS
885 EFIAPI
886 GetMouseState (
887 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
888 OUT EFI_SIMPLE_POINTER_STATE *MouseState
889 )
890 {
891 USB_MOUSE_DEV *MouseDev;
892
893 if (MouseState == NULL) {
894 return EFI_DEVICE_ERROR;
895 }
896
897 MouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);
898
899 if (!MouseDev->StateChanged) {
900 return EFI_NOT_READY;
901 }
902
903 CopyMem (
904 MouseState,
905 &MouseDev->State,
906 sizeof (EFI_SIMPLE_POINTER_STATE)
907 );
908
909 //
910 // Clear previous move state
911 //
912 MouseDev->State.RelativeMovementX = 0;
913 MouseDev->State.RelativeMovementY = 0;
914 MouseDev->State.RelativeMovementZ = 0;
915
916 MouseDev->StateChanged = FALSE;
917
918 return EFI_SUCCESS;
919 }
920
921
922 /**
923 Reset the mouse device, see SIMPLE POINTER PROTOCOL.
924
925 @param This Protocol instance pointer.
926 @param ExtendedVerification Ignored here/
927
928 @return EFI_SUCCESS
929
930 **/
931 STATIC
932 EFI_STATUS
933 EFIAPI
934 UsbMouseReset (
935 IN EFI_SIMPLE_POINTER_PROTOCOL *This,
936 IN BOOLEAN ExtendedVerification
937 )
938 {
939 USB_MOUSE_DEV *UsbMouseDevice;
940
941 UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);
942
943 MouseReportStatusCode (
944 UsbMouseDevice->DevicePath,
945 EFI_PROGRESS_CODE,
946 PcdGet32 (PcdStatusCodeValueMouseReset)
947
948 );
949
950 ZeroMem (
951 &UsbMouseDevice->State,
952 sizeof (EFI_SIMPLE_POINTER_STATE)
953 );
954 UsbMouseDevice->StateChanged = FALSE;
955
956 return EFI_SUCCESS;
957 }
958
959
960 /**
961 Event notification function for SIMPLE_POINTER.WaitForInput event
962 Signal the event if there is input from mouse
963
964 @param Event Wait Event
965 @param Context Passed parameter to event handler
966 VOID
967
968 **/
969 STATIC
970 VOID
971 EFIAPI
972 UsbMouseWaitForInput (
973 IN EFI_EVENT Event,
974 IN VOID *Context
975 )
976 {
977 USB_MOUSE_DEV *UsbMouseDev;
978
979 UsbMouseDev = (USB_MOUSE_DEV *) Context;
980
981 //
982 // Someone is waiting on the mouse event, if there's
983 // input from mouse, signal the event
984 //
985 if (UsbMouseDev->StateChanged) {
986 gBS->SignalEvent (Event);
987 }
988 }
989
990
991 /**
992 Timer handler for Delayed Recovery timer.
993
994 @param Event The Delayed Recovery event.
995 @param Context Points to the USB_KB_DEV instance.
996
997
998 **/
999 VOID
1000 EFIAPI
1001 USBMouseRecoveryHandler (
1002 IN EFI_EVENT Event,
1003 IN VOID *Context
1004 )
1005 {
1006 USB_MOUSE_DEV *UsbMouseDev;
1007 EFI_USB_IO_PROTOCOL *UsbIo;
1008
1009 UsbMouseDev = (USB_MOUSE_DEV *) Context;
1010
1011 UsbIo = UsbMouseDev->UsbIo;
1012
1013 UsbIo->UsbAsyncInterruptTransfer (
1014 UsbIo,
1015 UsbMouseDev->IntEndpointDescriptor->EndpointAddress,
1016 TRUE,
1017 UsbMouseDev->IntEndpointDescriptor->Interval,
1018 UsbMouseDev->IntEndpointDescriptor->MaxPacketSize,
1019 OnMouseInterruptComplete,
1020 UsbMouseDev
1021 );
1022 }
1023
1024
1025 /**
1026 Report Status Code in Usb Bot Driver
1027
1028 @param DevicePath Use this to get Device Path
1029 @param CodeType Status Code Type
1030 @param CodeValue Status Code Value
1031
1032 @return None
1033
1034 **/
1035 VOID
1036 MouseReportStatusCode (
1037 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1038 IN EFI_STATUS_CODE_TYPE CodeType,
1039 IN EFI_STATUS_CODE_VALUE Value
1040 )
1041 {
1042 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1043 CodeType,
1044 Value,
1045 DevicePath
1046 );
1047 }