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