]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbMouseSimulateTouchPadDxe/UsbMouseSimulateTouchPad.c
add UsbMouseSimulateTouchPad driver to verify the correction of dispatching AbsoluteP...
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMouseSimulateTouchPadDxe / UsbMouseSimulateTouchPad.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 UsbMouseSimulateTouchPad.c
15
16 Abstract:
17
18
19 **/
20
21 #include "UsbMouseSimulateTouchPad.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 USBMouseSimulateTouchPadDriverBindingEntryPoint (
35 IN EFI_HANDLE ImageHandle,
36 IN EFI_SYSTEM_TABLE *SystemTable
37 );
38
39 EFI_STATUS
40 EFIAPI
41 USBMouseSimulateTouchPadDriverBindingSupported (
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 USBMouseSimulateTouchPadDriverBindingStart (
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 USBMouseSimulateTouchPadDriverBindingStop (
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 gEfiUsbMouseSimulateTouchPadDriverGuid = {
65 0xa579f729, 0xa71d, 0x4b45, { 0xbe, 0xd7, 0xd, 0xb0, 0xa8, 0x7c, 0x3e, 0x8d }
66 };
67
68 EFI_DRIVER_BINDING_PROTOCOL gUsbMouseSimulateTouchPadDriverBinding = {
69 USBMouseSimulateTouchPadDriverBindingSupported,
70 USBMouseSimulateTouchPadDriverBindingStart,
71 USBMouseSimulateTouchPadDriverBindingStop,
72 0x1,
73 NULL,
74 NULL
75 };
76
77 //
78 // helper functions
79 //
80 STATIC
81 BOOLEAN
82 IsUsbMouseSimulateTouchPad (
83 IN EFI_USB_IO_PROTOCOL *UsbIo
84 );
85
86 STATIC
87 EFI_STATUS
88 InitializeUsbMouseSimulateTouchPadDevice (
89 IN USB_MOUSE_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDev
90 );
91
92 STATIC
93 VOID
94 EFIAPI
95 UsbMouseSimulateTouchPadWaitForInput (
96 IN EFI_EVENT Event,
97 IN VOID *Context
98 );
99
100 //
101 // Mouse interrupt handler
102 //
103 STATIC
104 EFI_STATUS
105 EFIAPI
106 OnMouseSimulateTouchPadInterruptComplete (
107 IN VOID *Data,
108 IN UINTN DataLength,
109 IN VOID *Context,
110 IN UINT32 Result
111 );
112
113 //
114 // Mouse simulate TouchPad, Using AbsolutePointer Protocol
115 //
116 STATIC
117 EFI_STATUS
118 EFIAPI
119 GetMouseSimulateTouchPadState (
120 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
121 OUT EFI_ABSOLUTE_POINTER_STATE *MouseSimulateTouchPadState
122 );
123
124 STATIC
125 EFI_STATUS
126 EFIAPI
127 UsbMouseSimulateTouchPadReset (
128 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
129 IN BOOLEAN ExtendedVerification
130 );
131
132 //
133 // Driver start here
134 //
135 EFI_STATUS
136 EFIAPI
137 USBMouseSimulateTouchPadDriverBindingEntryPoint (
138 IN EFI_HANDLE ImageHandle,
139 IN EFI_SYSTEM_TABLE *SystemTable
140 )
141 /*++
142
143 Routine Description:
144 Entry point for EFI drivers.
145
146 Arguments:
147 ImageHandle - EFI_HANDLE
148 SystemTable - EFI_SYSTEM_TABLE
149 Returns:
150 EFI_SUCCESS
151 others
152
153 --*/
154 {
155 return EfiLibInstallDriverBindingComponentName2 (
156 ImageHandle,
157 SystemTable,
158 &gUsbMouseSimulateTouchPadDriverBinding,
159 ImageHandle,
160 &gUsbMouseSimulateTouchPadComponentName,
161 &gUsbMouseSimulateTouchPadComponentName2
162 );
163 }
164
165
166 /**
167 Test to see if this driver supports ControllerHandle. Any ControllerHandle
168 that has UsbHcProtocol installed will be supported.
169
170 @param This Protocol instance pointer.
171 @param Controller Handle of device to test
172 @param RemainingDevicePath Not used
173
174 @retval EFI_SUCCESS This driver supports this device.
175 @retval EFI_UNSUPPORTED This driver does not support this device.
176
177 **/
178 EFI_STATUS
179 EFIAPI
180 USBMouseSimulateTouchPadDriverBindingSupported (
181 IN EFI_DRIVER_BINDING_PROTOCOL *This,
182 IN EFI_HANDLE Controller,
183 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
184 )
185 {
186 EFI_STATUS OpenStatus;
187 EFI_USB_IO_PROTOCOL *UsbIo;
188 EFI_STATUS Status;
189
190 OpenStatus = gBS->OpenProtocol (
191 Controller,
192 &gEfiUsbIoProtocolGuid,
193 (VOID **) &UsbIo,
194 This->DriverBindingHandle,
195 Controller,
196 EFI_OPEN_PROTOCOL_BY_DRIVER
197 );
198 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
199 return EFI_UNSUPPORTED;
200 }
201
202 if (OpenStatus == EFI_ALREADY_STARTED) {
203 return EFI_ALREADY_STARTED;
204 }
205
206 //
207 // Use the USB I/O protocol interface to see the Controller is
208 // the Mouse controller that can be managed by this driver.
209 //
210 Status = EFI_SUCCESS;
211 if (!IsUsbMouseSimulateTouchPad (UsbIo)) {
212 Status = EFI_UNSUPPORTED;
213 }
214
215 gBS->CloseProtocol (
216 Controller,
217 &gEfiUsbIoProtocolGuid,
218 This->DriverBindingHandle,
219 Controller
220 );
221
222 return Status;
223 }
224
225
226 /**
227 Starting the Usb Bus Driver
228
229 @param This Protocol instance pointer.
230 @param Controller Handle of device to test
231 @param RemainingDevicePath Not used
232
233 @retval EFI_SUCCESS This driver supports this device.
234 @retval EFI_UNSUPPORTED This driver does not support this device.
235 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error
236 EFI_OUT_OF_RESOURCES- Can't allocate memory
237 resources
238 @retval EFI_ALREADY_STARTED Thios driver has been started
239
240 **/
241 EFI_STATUS
242 EFIAPI
243 USBMouseSimulateTouchPadDriverBindingStart (
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_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDevice;
253 UINT8 EndpointNumber;
254 UINT8 Index;
255 UINT8 EndpointAddr;
256 UINT8 PollingInterval;
257 UINT8 PacketSize;
258
259 UsbMouseSimulateTouchPadDevice = 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 UsbMouseSimulateTouchPadDevice = AllocateZeroPool (sizeof (USB_MOUSE_SIMULATE_TOUCHPAD_DEV));
275 if (UsbMouseSimulateTouchPadDevice == NULL) {
276 Status = EFI_OUT_OF_RESOURCES;
277 goto ErrorExit;
278 }
279
280 UsbMouseSimulateTouchPadDevice->UsbIo = UsbIo;
281
282 UsbMouseSimulateTouchPadDevice->Signature = USB_MOUSE_SIMULATE_TOUCHPAD_DEV_SIGNATURE;
283
284 UsbMouseSimulateTouchPadDevice->InterfaceDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
285 if (UsbMouseSimulateTouchPadDevice->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 **) &UsbMouseSimulateTouchPadDevice->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 UsbMouseSimulateTouchPadDevice->InterfaceDescriptor
316 );
317
318 EndpointNumber = UsbMouseSimulateTouchPadDevice->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 UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor = EndpointDesc;
333 }
334 }
335
336 if (UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor == NULL) {
337 //
338 // No interrupt endpoint, then error
339 //
340 Status = EFI_UNSUPPORTED;
341 goto ErrorExit;
342 }
343
344 Status = InitializeUsbMouseSimulateTouchPadDevice (UsbMouseSimulateTouchPadDevice);
345 if (EFI_ERROR (Status)) {
346 MouseSimulateTouchPadReportStatusCode (
347 UsbMouseSimulateTouchPadDevice->DevicePath,
348 EFI_ERROR_CODE | EFI_ERROR_MINOR,
349 PcdGet32 (PcdStatusCodeValueMouseInterfaceError)
350 );
351
352 goto ErrorExit;
353 }
354
355 UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol.GetState = GetMouseSimulateTouchPadState;
356 UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol.Reset = UsbMouseSimulateTouchPadReset;
357 UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol.Mode = &UsbMouseSimulateTouchPadDevice->AbsolutePointerMode;
358
359 Status = gBS->CreateEvent (
360 EVT_NOTIFY_WAIT,
361 TPL_NOTIFY,
362 UsbMouseSimulateTouchPadWaitForInput,
363 UsbMouseSimulateTouchPadDevice,
364 &((UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol).WaitForInput)
365 );
366 if (EFI_ERROR (Status)) {
367 goto ErrorExit;
368 }
369
370 Status = gBS->InstallProtocolInterface (
371 &Controller,
372 &gEfiAbsolutePointerProtocolGuid,
373 EFI_NATIVE_INTERFACE,
374 &UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol
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 MouseSimulateTouchPadReportStatusCode (
389 UsbMouseSimulateTouchPadDevice->DevicePath,
390 EFI_PROGRESS_CODE,
391 PcdGet32 (PcdStatusCodeValueMouseEnable)
392 );
393
394 //
395 // submit async interrupt transfer
396 //
397 EndpointAddr = UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->EndpointAddress;
398 PollingInterval = UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->Interval;
399 PacketSize = (UINT8) (UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->MaxPacketSize);
400
401 Status = UsbIo->UsbAsyncInterruptTransfer (
402 UsbIo,
403 EndpointAddr,
404 TRUE,
405 PollingInterval,
406 PacketSize,
407 OnMouseSimulateTouchPadInterruptComplete,
408 UsbMouseSimulateTouchPadDevice
409 );
410
411 if (!EFI_ERROR (Status)) {
412
413 UsbMouseSimulateTouchPadDevice->ControllerNameTable = NULL;
414 AddUnicodeString2 (
415 "eng",
416 gUsbMouseSimulateTouchPadComponentName.SupportedLanguages,
417 &UsbMouseSimulateTouchPadDevice->ControllerNameTable,
418 L"Generic Usb Mouse Simulate TouchPad",
419 TRUE
420 );
421 AddUnicodeString2 (
422 "en",
423 gUsbMouseSimulateTouchPadComponentName2.SupportedLanguages,
424 &UsbMouseSimulateTouchPadDevice->ControllerNameTable,
425 L"Generic Usb Mouse Simulate TouchPad2",
426 FALSE
427 );
428
429 return EFI_SUCCESS;
430 }
431
432 //
433 // If submit error, uninstall that interface
434 //
435 Status = EFI_DEVICE_ERROR;
436
437 gBS->UninstallProtocolInterface (
438 Controller,
439 &gEfiAbsolutePointerProtocolGuid,
440 &UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol
441 );
442
443 ErrorExit:
444 DEBUG ((EFI_D_ERROR, __FUNCTION__ " driver start fail\n"));
445 if (EFI_ERROR (Status)) {
446 gBS->CloseProtocol (
447 Controller,
448 &gEfiUsbIoProtocolGuid,
449 This->DriverBindingHandle,
450 Controller
451 );
452
453 if (UsbMouseSimulateTouchPadDevice != NULL) {
454 if (UsbMouseSimulateTouchPadDevice->InterfaceDescriptor != NULL) {
455 gBS->FreePool (UsbMouseSimulateTouchPadDevice->InterfaceDescriptor);
456 }
457
458 if (UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor != NULL) {
459 gBS->FreePool (UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor);
460 }
461
462 if ((UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol).WaitForInput != NULL) {
463 gBS->CloseEvent ((UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol).WaitForInput);
464 }
465
466 gBS->FreePool (UsbMouseSimulateTouchPadDevice);
467 UsbMouseSimulateTouchPadDevice = 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 USBMouseSimulateTouchPadDriverBindingStop (
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_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDevice;
500 EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol;
501 EFI_USB_IO_PROTOCOL *UsbIo;
502
503 //
504 // Get our context back.
505 //
506 Status = gBS->OpenProtocol (
507 Controller,
508 &gEfiAbsolutePointerProtocolGuid,
509 (VOID **) &AbsolutePointerProtocol,
510 This->DriverBindingHandle,
511 Controller,
512 EFI_OPEN_PROTOCOL_GET_PROTOCOL
513 );
514
515 if (EFI_ERROR (Status)) {
516 return EFI_UNSUPPORTED;
517 }
518 UsbMouseSimulateTouchPadDevice = USB_MOUSE_SIMULATE_TOUCHPAD_DEV_FROM_MOUSE_PROTOCOL (AbsolutePointerProtocol);
519
520 gBS->CloseProtocol (
521 Controller,
522 &gEfiAbsolutePointerProtocolGuid,
523 This->DriverBindingHandle,
524 Controller
525 );
526
527 UsbIo = UsbMouseSimulateTouchPadDevice->UsbIo;
528
529 //
530 // Uninstall the Asyn Interrupt Transfer from this device
531 // will disable the mouse data input from this device
532 //
533 MouseSimulateTouchPadReportStatusCode (
534 UsbMouseSimulateTouchPadDevice->DevicePath,
535 EFI_PROGRESS_CODE,
536 PcdGet32 (PcdStatusCodeValueMouseDisable)
537 );
538
539 //
540 // Delete Mouse Async Interrupt Transfer
541 //
542 UsbIo->UsbAsyncInterruptTransfer (
543 UsbIo,
544 UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->EndpointAddress,
545 FALSE,
546 UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->Interval,
547 0,
548 NULL,
549 NULL
550 );
551
552 gBS->CloseEvent (UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol.WaitForInput);
553
554 if (UsbMouseSimulateTouchPadDevice->DelayedRecoveryEvent) {
555 gBS->CloseEvent (UsbMouseSimulateTouchPadDevice->DelayedRecoveryEvent);
556 UsbMouseSimulateTouchPadDevice->DelayedRecoveryEvent = 0;
557 }
558
559 Status = gBS->UninstallProtocolInterface (
560 Controller,
561 &gEfiAbsolutePointerProtocolGuid,
562 &UsbMouseSimulateTouchPadDevice->AbsolutePointerProtocol
563 );
564 if (EFI_ERROR (Status)) {
565 return Status;
566 }
567
568 gBS->CloseProtocol (
569 Controller,
570 &gEfiUsbIoProtocolGuid,
571 This->DriverBindingHandle,
572 Controller
573 );
574
575 gBS->FreePool (UsbMouseSimulateTouchPadDevice->InterfaceDescriptor);
576 gBS->FreePool (UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor);
577
578 if (UsbMouseSimulateTouchPadDevice->ControllerNameTable) {
579 FreeUnicodeStringTable (UsbMouseSimulateTouchPadDevice->ControllerNameTable);
580 }
581
582 gBS->FreePool (UsbMouseSimulateTouchPadDevice);
583
584 return EFI_SUCCESS;
585
586 }
587
588
589 /**
590 Tell if a Usb Controller is a mouse
591
592 @param UsbIo Protocol instance pointer.
593
594 @retval TRUE It is a mouse
595 @retval FALSE It is not a mouse
596
597 **/
598 BOOLEAN
599 IsUsbMouseSimulateTouchPad (
600 IN EFI_USB_IO_PROTOCOL *UsbIo
601 )
602 {
603 EFI_STATUS Status;
604 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
605
606 //
607 // Get the Default interface descriptor, now we only
608 // suppose it is interface 1
609 //
610 Status = UsbIo->UsbGetInterfaceDescriptor (
611 UsbIo,
612 &InterfaceDescriptor
613 );
614
615 if (EFI_ERROR (Status)) {
616 return FALSE;
617 }
618
619 if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&
620 (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&
621 (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)
622 ) {
623
624 return TRUE;
625 }
626
627 return FALSE;
628 }
629
630
631 /**
632 Initialize the Usb Mouse Simulate TouchPad Device.
633
634 @param UsbMouseSimulateTouchPadDev 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 InitializeUsbMouseSimulateTouchPadDevice (
644 IN USB_MOUSE_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDev
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 = UsbMouseSimulateTouchPadDev->UsbIo;
654
655 //
656 // Get HID descriptor
657 //
658 Status = UsbGetHidDescriptor (
659 UsbIo,
660 UsbMouseSimulateTouchPadDev->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 UsbMouseSimulateTouchPadDev->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 UsbMouseSimulateTouchPadDev,
697 ReportDesc,
698 MouseHidDesc.HidClassDesc[0].DescriptorLength
699 );
700
701 if (EFI_ERROR (Status)) {
702 gBS->FreePool (ReportDesc);
703 return Status;
704 }
705
706 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.AbsoluteMaxX = 1024;
707 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.AbsoluteMaxY = 1024;
708 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.AbsoluteMaxZ = 0;
709 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.AbsoluteMinX = 0;
710 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.AbsoluteMinY = 0;
711 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.AbsoluteMinZ = 0;
712 UsbMouseSimulateTouchPadDev->AbsolutePointerMode.Attributes = 0x3;
713
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 (UsbMouseSimulateTouchPadDev->DelayedRecoveryEvent) {
749 gBS->CloseEvent (UsbMouseSimulateTouchPadDev->DelayedRecoveryEvent);
750 UsbMouseSimulateTouchPadDev->DelayedRecoveryEvent = 0;
751 }
752
753 Status = gBS->CreateEvent (
754 EVT_TIMER | EVT_NOTIFY_SIGNAL,
755 TPL_NOTIFY,
756 USBMouseSimulateTouchPadRecoveryHandler,
757 UsbMouseSimulateTouchPadDev,
758 &UsbMouseSimulateTouchPadDev->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
775 @return EFI_DEVICE_ERROR
776
777 **/
778 STATIC
779 EFI_STATUS
780 EFIAPI
781 OnMouseSimulateTouchPadInterruptComplete (
782 IN VOID *Data,
783 IN UINTN DataLength,
784 IN VOID *Context,
785 IN UINT32 Result
786 )
787 {
788 USB_MOUSE_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDevice;
789 EFI_USB_IO_PROTOCOL *UsbIo;
790 UINT8 EndpointAddr;
791 UINT32 UsbResult;
792
793 UsbMouseSimulateTouchPadDevice = (USB_MOUSE_SIMULATE_TOUCHPAD_DEV *) Context;
794 UsbIo = UsbMouseSimulateTouchPadDevice->UsbIo;
795
796 if (Result != EFI_USB_NOERROR) {
797 //
798 // Some errors happen during the process
799 //
800 MouseSimulateTouchPadReportStatusCode (
801 UsbMouseSimulateTouchPadDevice->DevicePath,
802 EFI_ERROR_CODE | EFI_ERROR_MINOR,
803 PcdGet32 (PcdStatusCodeValueMouseInputError)
804 );
805
806 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
807 EndpointAddr = UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->EndpointAddress;
808
809 UsbClearEndpointHalt (
810 UsbIo,
811 EndpointAddr,
812 &UsbResult
813 );
814 }
815
816 UsbIo->UsbAsyncInterruptTransfer (
817 UsbIo,
818 UsbMouseSimulateTouchPadDevice->IntEndpointDescriptor->EndpointAddress,
819 FALSE,
820 0,
821 0,
822 NULL,
823 NULL
824 );
825
826 gBS->SetTimer (
827 UsbMouseSimulateTouchPadDevice->DelayedRecoveryEvent,
828 TimerRelative,
829 EFI_USB_INTERRUPT_DELAY
830 );
831 return EFI_DEVICE_ERROR;
832 }
833
834 if (DataLength == 0 || Data == NULL) {
835 return EFI_SUCCESS;
836 }
837
838 //
839 //Check mouse Data
840 //
841 UsbMouseSimulateTouchPadDevice->AbsolutePointerStateChanged = TRUE;
842 UsbMouseSimulateTouchPadDevice->AbsolutePointerState.CurrentX += *((INT8 *) Data + 1);
843 UsbMouseSimulateTouchPadDevice->AbsolutePointerState.CurrentY += *((INT8 *) Data + 2);
844 if (DataLength > 3) {
845 UsbMouseSimulateTouchPadDevice->AbsolutePointerState.CurrentZ += *((INT8 *) Data + 3);
846 }
847 UsbMouseSimulateTouchPadDevice->AbsolutePointerState.ActiveButtons = *(UINT8 *)Data & 0x3;
848
849 return EFI_SUCCESS;
850 }
851
852 /**
853 Get the mouse state, see ABSOLUTE POINTER PROTOCOL.
854
855 @param This Protocol instance pointer.
856 @param MouseState Current mouse state
857
858 @return EFI_SUCCESS
859 @return EFI_DEVICE_ERROR
860 @return EFI_NOT_READY
861
862 **/
863 STATIC
864 EFI_STATUS
865 EFIAPI
866 GetMouseSimulateTouchPadState (
867 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
868 OUT EFI_ABSOLUTE_POINTER_STATE *MouseSimulateTouchPadState
869 )
870 {
871 USB_MOUSE_SIMULATE_TOUCHPAD_DEV *MouseSimulateTouchPadDev;
872
873 if (MouseSimulateTouchPadState == NULL) {
874 return EFI_DEVICE_ERROR;
875 }
876
877 MouseSimulateTouchPadDev = USB_MOUSE_SIMULATE_TOUCHPAD_DEV_FROM_MOUSE_PROTOCOL (This);
878
879 if (!MouseSimulateTouchPadDev->AbsolutePointerStateChanged) {
880 return EFI_NOT_READY;
881 }
882
883 CopyMem (
884 MouseSimulateTouchPadState,
885 &MouseSimulateTouchPadDev->AbsolutePointerState,
886 sizeof (EFI_ABSOLUTE_POINTER_STATE)
887 );
888
889 //
890 // Clear previous move state
891 //
892 MouseSimulateTouchPadDev->AbsolutePointerState.CurrentX = 0;
893 MouseSimulateTouchPadDev->AbsolutePointerState.CurrentY = 0;
894 MouseSimulateTouchPadDev->AbsolutePointerState.CurrentZ = 0;
895 MouseSimulateTouchPadDev->AbsolutePointerState.ActiveButtons = 0;
896
897 MouseSimulateTouchPadDev->AbsolutePointerStateChanged = FALSE;
898
899 return EFI_SUCCESS;
900 }
901
902
903 /**
904 Reset the mouse device, see ABSOLUTE POINTER PROTOCOL.
905
906 @param This Protocol instance pointer.
907 @param ExtendedVerification Ignored here/
908
909 @return EFI_SUCCESS
910
911 **/
912 STATIC
913 EFI_STATUS
914 EFIAPI
915 UsbMouseSimulateTouchPadReset (
916 IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
917 IN BOOLEAN ExtendedVerification
918 )
919 {
920 USB_MOUSE_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDevice;
921
922 UsbMouseSimulateTouchPadDevice = USB_MOUSE_SIMULATE_TOUCHPAD_DEV_FROM_MOUSE_PROTOCOL (This);
923
924 MouseSimulateTouchPadReportStatusCode (
925 UsbMouseSimulateTouchPadDevice->DevicePath,
926 EFI_PROGRESS_CODE,
927 PcdGet32 (PcdStatusCodeValueMouseReset)
928 );
929
930 ZeroMem (
931 &UsbMouseSimulateTouchPadDevice->AbsolutePointerState,
932 sizeof (EFI_ABSOLUTE_POINTER_STATE)
933 );
934 UsbMouseSimulateTouchPadDevice->AbsolutePointerStateChanged = FALSE;
935
936 return EFI_SUCCESS;
937 }
938
939 /**
940 Event notification function for ABSOLUTE_POINTER.WaitForInput event
941 Signal the event if there is input from mouse
942
943 @param Event Wait Event
944 @param Context Passed parameter to event handler
945 VOID
946
947 **/
948 STATIC
949 VOID
950 EFIAPI
951 UsbMouseSimulateTouchPadWaitForInput (
952 IN EFI_EVENT Event,
953 IN VOID *Context
954 )
955 {
956 USB_MOUSE_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDev;
957
958 UsbMouseSimulateTouchPadDev = (USB_MOUSE_SIMULATE_TOUCHPAD_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 (UsbMouseSimulateTouchPadDev->AbsolutePointerStateChanged) {
965 gBS->SignalEvent (Event);
966 }
967 }
968
969 /**
970 Timer handler for Delayed Recovery timer.
971
972 @param Event The Delayed Recovery event.
973 @param Context Points to the USB_KB_DEV instance.
974
975
976 **/
977 VOID
978 EFIAPI
979 USBMouseSimulateTouchPadRecoveryHandler (
980 IN EFI_EVENT Event,
981 IN VOID *Context
982 )
983 {
984 USB_MOUSE_SIMULATE_TOUCHPAD_DEV *UsbMouseSimulateTouchPadDev;
985 EFI_USB_IO_PROTOCOL *UsbIo;
986
987 UsbMouseSimulateTouchPadDev = (USB_MOUSE_SIMULATE_TOUCHPAD_DEV *) Context;
988
989 UsbIo = UsbMouseSimulateTouchPadDev->UsbIo;
990
991 UsbIo->UsbAsyncInterruptTransfer (
992 UsbIo,
993 UsbMouseSimulateTouchPadDev->IntEndpointDescriptor->EndpointAddress,
994 TRUE,
995 UsbMouseSimulateTouchPadDev->IntEndpointDescriptor->Interval,
996 UsbMouseSimulateTouchPadDev->IntEndpointDescriptor->MaxPacketSize,
997 OnMouseSimulateTouchPadInterruptComplete,
998 UsbMouseSimulateTouchPadDev
999 );
1000 }
1001
1002
1003 /**
1004 Report Status Code in Usb Bot Driver
1005
1006 @param DevicePath Use this to get Device Path
1007 @param CodeType Status Code Type
1008 @param CodeValue Status Code Value
1009
1010 @return None
1011
1012 **/
1013 VOID
1014 MouseSimulateTouchPadReportStatusCode (
1015 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1016 IN EFI_STATUS_CODE_TYPE CodeType,
1017 IN EFI_STATUS_CODE_VALUE Value
1018 )
1019 {
1020 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1021 CodeType,
1022 Value,
1023 DevicePath
1024 );
1025 }