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