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