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