UsbMouse.cpp revision ae26c174345e4ed5710e3f9138b9166b4a160abd
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * UsbMouse - USB Human Interface Device Emulation (Mouse).
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (C) 2007-2010 Sun Microsystems, Inc.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Sun Microsystems, Inc. confidential
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * All rights reserved
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Header Files *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Defined Constants And Macros *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID string IDs
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID specific descriptor types
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID vendor and product IDs
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Structures and Typedefs *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB HID request state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Invalid status. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Ready to receive a new read request. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Have (more) data for the host. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Waiting to supply status information to the host. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The end of the valid states. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Endpoint status data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHIDEP
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to the endpoint status. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * A URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The head pointer. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Where to insert the next entry. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to a URB queue. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to a const URB queue. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Mouse movement accumulator.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB HID instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHID
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer back to the PDM USB Device instance structure. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Critical section protecting the device state. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The current configuration.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * (0 - default, 1 - the one supported configuration, i.e configured.) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The state of the HID (state machine).*/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer movement accumulator. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pending to-host queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The URBs waiting here are waiting for data to become available.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Done queue
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The URBs stashed here are waiting to be reaped. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * is set. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Someone is waiting on the done queue. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /** Is this an absolute pointing device (tablet)? Relative (mouse) otherwise. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Mouse port - LUN#0.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIBASE
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIMOUSEPORT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The base interface for the mouse port. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The mouse port base interface. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The base interface of the attached mouse driver. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The mouse interface of the attached mouse driver. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to the USB HID instance data. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync * The USB HID report structure for relative device.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * The USB HID report structure for relative device.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Global Variables *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic const PDMUSBDESCCACHESTRING g_aUsbHidStrings_en_US[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic const PDMUSBDESCCACHELANG g_aUsbHidLanguages[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync { 0x0409, RT_ELEMENTS(g_aUsbHidStrings_en_US), g_aUsbHidStrings_en_US }
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCENDPOINTEX g_aUsbHidMEndpointDescs[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .cbClass = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCENDPOINTEX g_aUsbHidTEndpointDescs[] =
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cbClass = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* HID report descriptor (mouse). */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Size */ 0x75, 0x05, /* 5 (padding bits) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* HID report descriptor (tablet). */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync/* NB: The layout is far from random. Having the buttons and Z axis grouped
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * together avoids alignment issues. Also, if X/Y is reported first, followed
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * by buttons/Z, Windows gets phantom Z movement. That is likely a bug in Windows
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * as OS X shows no such problem. When X/Y is reported last, Windows behaves
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * properly.
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Size */ 0x75, 0x05, /* 5 (padding bits) */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* Additional HID class interface descriptor. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bCountryCode = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wDescriptorLength = */ sizeof(g_UsbHidMReportDesc), 0x00
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* Additional HID class interface descriptor. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bCountryCode = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wDescriptorLength = */ sizeof(g_UsbHidTReportDesc), 0x00
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidMInterfaceDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceNumber = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bAlternateSetting = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iInterface = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidTInterfaceDesc =
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterfaceNumber = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bAlternateSetting = */ 0,
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync /* .bInterfaceSubClass = */ 0 /* No subclass - no boot interface. */,
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync /* .bInterfaceProtocol = */ 0 /* No protocol - no boot interface. */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iInterface = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wTotalLength = */ 0 /* recalculated on read */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidMInterfaces),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iConfiguration = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .wTotalLength = */ 0 /* recalculated on read */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidTInterfaces),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iConfiguration = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iSerialNumber = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iSerialNumber = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .fUseCachedDescriptors = */ true,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .fUseCachedStringsDescriptors = */ true
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .fUseCachedDescriptors = */ true,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .fUseCachedStringsDescriptors = */ true
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Internal Functions *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Initializes an URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Inserts an URB at the end of the queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb The URB to insert.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Unlinks the head of the queue and returns it.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns The head entry.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Removes an URB from anywhere in the queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns true if found, false if not.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb The URB to remove.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Checks if the queue is empty or not.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns true if it is, false if it isn't.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Links an URB into the done queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis The HID instance.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb The URB.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Completes the URB with a stalled state, halting the pipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo figure out if the stall is global or pipe-specific or both. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Completes the URB with a OK state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * usbHidUrbHandleDefaultPipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns VBox status code.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis The HID instance.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb Set when usbHidUrbHandleDefaultPipe is the
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param fSetConfig Set when usbHidUsbSetConfiguration is the
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Wait for the any command currently executing to complete before
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * resetting. (We cannot cancel its execution.) How we do this depends
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * on the reset method.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Reset the device state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pUrb && !fSetConfig) /* (only device reset) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Ditch all pending URBs.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void *) usbHidMouseQueryInterface(PPDMIBASE pInterface, const char *pszIID)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IBase);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThis->Lun0.IPort);
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Relative mouse event handler.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns VBox status code.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pInterface Pointer to the mouse port interface (KBDState::Mouse.iPort).
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param i32DeltaX The X delta.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param i32DeltaY The Y delta.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param i32DeltaZ The Z delta.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param i32DeltaW The W delta.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param fButtonStates The button states.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidMousePutEvent(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync// int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync// AssertReleaseRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* If we aren't in the expected mode, switch. This should only really need to be done once. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync// if (pThis->isAbsolute)
8112e0942f1128329b99b22a20b395963d4abceavboxsync// pThis->Lun0.pDrv->pfnAbsModeChange(pThis->Lun0.pDrv, pThis->isAbsolute);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Accumulate movement - the events from the front end may arrive
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * at a much higher rate than USB can handle.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Check if there's a URB waiting. If so, send a report.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Clear the accumulated movement. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->PtrDelta.dX = pThis->PtrDelta.dY = pThis->PtrDelta.dZ = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Complete the URB. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync// LogRel(("Rel movement, dX=%d, dY=%d, dZ=%d, btn=%02x, report size %d\n", report.dx, report.dy, report.dz, report.btn, cbCopy));
8112e0942f1128329b99b22a20b395963d4abceavboxsync// PDMCritSectLeave(&pThis->CritSect);
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Absolute mouse event handler.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @returns VBox status code.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pInterface Pointer to the mouse port interface (KBDState::Mouse.iPort).
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param u32X The X coordinate.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param u32Y The Y coordinate.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param i32DeltaZ The Z delta.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param i32DeltaW The W delta.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param fButtonStates The button states.
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) usbHidMousePutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t u32X, uint32_t u32Y, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
8112e0942f1128329b99b22a20b395963d4abceavboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
8112e0942f1128329b99b22a20b395963d4abceavboxsync// int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
8112e0942f1128329b99b22a20b395963d4abceavboxsync// AssertReleaseRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Accumulate movement - the events from the front end may arrive
8112e0942f1128329b99b22a20b395963d4abceavboxsync * at a much higher rate than USB can handle. Probably not a real issue
8112e0942f1128329b99b22a20b395963d4abceavboxsync * when only the Z axis is relative.
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Check if there's a URB waiting. If so, send a report.
8112e0942f1128329b99b22a20b395963d4abceavboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Clear the accumulated movement. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Complete the URB. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync// LogRel(("Abs movement, X=%d, Y=%d, dZ=%d, btn=%02x, report size %d\n", report.cx, report.cy, report.dz, report.btn, cbCopy));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync// PDMCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUrbReap
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUrbCancel
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Remove the URB from the to-host queue and move it onto the done queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Handles request sent to the inbound (device to host) interrupt pipe. This is
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * rather different from bulk requests because an interrupt read URB may complete
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * after arbitrarily long time.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Stall the request if the pipe is halted.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, NULL, pUrb, "Halted pipe");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Deal with the URB according to the state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * We've data left to transfer to the host.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Status transfer.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleIntrDevToHost: Entering READY\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n", pUrb, pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Bad states, stall.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n", pThis->enmState, pUrb->cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Handles request sent to the default control pipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidHandleDefaultPipe(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Returned data is written after the setup message. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n", pSetup->wValue, pSetup->wIndex, cbCopy));
8112e0942f1128329b99b22a20b395963d4abceavboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pSetup->bmRequestType));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo implement this. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* 3.1 Bulk-Only Mass Storage Reset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if ( pSetup->bmRequestType == (VUSB_REQ_CLASS | VUSB_TO_INTERFACE)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleDefaultPipe: Bulk-Only Mass Storage Reset\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidResetWorker(pThis, pUrb, false /*fSetConfig*/);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnQueue
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Parse on a per end-point basis.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = usbHidHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbSetInterface
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbSetConfiguration
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * If the same config is applied more than once, it's a kind of reset.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->bConfigurationValue == bConfigurationValue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Set received event type to absolute or relative.
ae26c174345e4ed5710e3f9138b9166b4a160abdvboxsync pThis->Lun0.pDrv->pfnReportModes(pThis->Lun0.pDrv, !pThis->isAbsolute,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbReset
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnDestruct
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnConstruct
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Perform the basic structure initialization first so the destructor
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * will not misbehave.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Validate and read the configuration.
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3ValidateConfig(pCfg, "/", "Absolute", "Config", "UsbHid", iInstance);
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3QueryBoolDef(pCfg, "Absolute", &pThis->isAbsolute, false);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->Lun0.IPort.pfnPutEvent = usbHidMousePutEvent;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->Lun0.IPort.pfnPutEventAbs = usbHidMousePutEventAbs;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Attach the mouse driver.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pUsbIns->pHlpR3->pfnDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Mouse Port");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach mouse driver"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIMOUSECONNECTOR);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query mouse interface"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB Human Interface Device (HID) Mouse registration record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32Version */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szName */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "HidMouse",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pszDescription */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "USB HID Mouse.",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fFlags */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cMaxInstances */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cbInstance */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnConstruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDestruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMInitComplete */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMPowerOn */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMSuspend */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMResume */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMPowerOff */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnHotPlugged */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnHotUnplugged */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDriverAttach */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDriverDetach */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnQueryInterface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbGetCachedDescriptors */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetConfiguration */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetInterface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbClearHaltedEndpoint */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbNew */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnQueue */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbCancel */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbReap */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32TheEnd */