UsbMouse.cpp revision aa327535f5ce61d8851bf6495ca1b507f013252b
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * UsbMouse - USB Human Interface Device Emulation (Mouse).
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2007-2012 Oracle Corporation
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * available from http://www.virtualbox.org. This file is free software;
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * General Public License (GPL) as published by the Free Software
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
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. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * The device reporting mode.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @todo Use an interface instead of an enum and switches.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Relative. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Absolute. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Multi-touch. */
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
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /** 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. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /** If device has pending changes. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Is this a relative, absolute or multi-touch pointing device? */
6cd65034f702d9b4122249011835e9639a7bc660vboxsync /** Tablet coordinate shift factor for old and broken operating systems. */
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.
33f7a1bbfb625f3401368928cd5e9317ca04881dvboxsync * The USB HID report structure for absolute device.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * The USB HID report structure for the multi-touch device.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * The combined USB HID report union for relative, absolute and multi-touch
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 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Report Size */ 0x75, 0x03, /* 3 (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 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Report Size */ 0x75, 0x03, /* 3 (padding bits) */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync /* Report Count */ 0x95, 0x01, /* 1 (padding byte) */
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync /* Usage */ 0x09, 0x55, /* Contact Count Maximum */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Feature */ 0xB1, 0x03, /* Constant, Value, Absolute, Bit field */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/** @todo Do these really have to all be duplicated three times? */
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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/* Additional HID class interface descriptor. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bCountryCode = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .wDescriptorLength = */ sizeof(g_UsbHidMTReportDesc), 0x00
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidMInterfaceDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceNumber = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bAlternateSetting = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iInterface = */ 0
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync /* .cbIAD = */ 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
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync /* .cbIAD = */ 0
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidMTInterfaceDesc =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceNumber = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bAlternateSetting = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceSubClass = */ 0 /* No subclass - no boot interface. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceProtocol = */ 0 /* No protocol - no boot interface. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .iInterface = */ 0
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .cbIAD = */ 0
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBINTERFACE g_aUsbHidMTInterfaces[] =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync { &g_UsbHidMTInterfaceDesc, /* .cSettings = */ 1 },
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,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBDESCCONFIGEX g_UsbHidMTConfigDesc =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .wTotalLength = */ 0 /* recalculated on read */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidMTInterfaces),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .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,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .fUseCachedDescriptors = */ true,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .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)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync 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)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync * usbHidHandleDefaultPipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns VBox status code.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis The HID instance.
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync * @param pUrb Set when usbHidHandleDefaultPipe 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)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * Create a USB HID report report based on the currently accumulated data.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic size_t usbHidFillReport(PUSBHIDTM_REPORT pReport,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->t.fButtons = pAccumulated->u.Absolute.fButtons;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->t.dz = clamp_i8(pAccumulated->u.Absolute.dz);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync LogRel3(("Abs event, x=%d, y=%d, dz=%d, fButtons=%02x, report size %d\n",
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->t.x, pReport->t.y, pReport->t.dz, pReport->t.fButtons,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.fButtons = pAccumulated->u.Relative.fButtons;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.dx = clamp_i8(pAccumulated->u.Relative.dx);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.dy = clamp_i8(pAccumulated->u.Relative.dy);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.dz = clamp_i8(pAccumulated->u.Relative.dz);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync LogRel3(("Rel event, dx=%d, dy=%d, dz=%d, fButtons=%02x, report size %d\n",
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->mt.idContact = pAccumulated->u.MultiTouch.cContact;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->mt.fButton = pAccumulated->u.MultiTouch.fContact;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync LogRel3(("Multi-touch event, x=%u, y=%u, report size %d\n",
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Clear the accumulated movement. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * Sends a state report to the host if there is a pending URB.
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PUSBHIDTM_REPORT pReport = (PUSBHIDTM_REPORT)&pUrb->abData[0];
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbCopy = usbHidFillReport(pReport, &pThis->PtrDelta, pThis->enmMode);
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);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * @interface_method_impl{PDMIMOUSEPORT,pfnPutEvent}
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsyncstatic DECLCALLBACK(int) usbHidMousePutEvent(PPDMIMOUSEPORT pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Accumulate movement - the events from the front end may arrive
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * at a much higher rate than USB can handle.
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Relative.dz -= dz; /* Inverted! */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Send a report if possible. */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventAbs}
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsyncstatic DECLCALLBACK(int) usbHidMousePutEventAbs(PPDMIMOUSEPORT pInterface,
8112e0942f1128329b99b22a20b395963d4abceavboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
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
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * when only the Z axis is relative (X/Y movement isn't technically
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * accumulated and only the last value is used).
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Absolute.x = x >> pThis->u8CoordShift;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Absolute.y = y >> pThis->u8CoordShift;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Absolute.dz -= dz; /* Inverted! */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync /* Send a report if possible. */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMT}
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsyncstatic DECLCALLBACK(int) usbHidMousePutEventMT(PPDMIMOUSEPORT pInterface,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync /* Accumulate movement - the events from the front end may arrive
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * at a much higher rate than USB can handle. Probably not a real issue
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * when only the Z axis is relative (X/Y movement isn't technically
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * accumulated and only the last value is used).
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Send a report if possible. */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUrbReap
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb,
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUrbCancel
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb,
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.
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Status transfer.
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: Entering READY\n"));
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* If a report is pending, send it right away. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Bad states, stall.
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n",
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:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync /* Returned data is written after the setup message. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidMouse: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbCopy=%#x\n",
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Returned data is written after the setup message. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Bad GET_STATUS req: wLength=%#x\n",
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
8865816a3d875ec1a036af307fbb484af107f014vboxsync wRet = 0; /* Not self-powered, no remote wakeup. */
8865816a3d875ec1a036af307fbb484af107f014vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
8865816a3d875ec1a036af307fbb484af107f014vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_STATUS (interface) invalid, wIndex=%#x\n",
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
8865816a3d875ec1a036af307fbb484af107f014vboxsync wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
8865816a3d875ec1a036af307fbb484af107f014vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_STATUS (endpoint) invalid, wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Bad GET_STATUS req: bmRequestType=%#x\n",
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo implement this. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
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)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleDefaultPipe: Bulk-Only Mass Storage Reset\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidResetWorker(pThis, pUrb, false /*fSetConfig*/);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUrbQueue
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Parse on a per end-point basis.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = usbHidHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], pUrb);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
3fe24a3690526efc4cceece3819d628caadf3140vboxsync * @copydoc PDMUSBREG::pfnUsbSetInterface
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUsbSetConfiguration
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * If the same config is applied more than once, it's a kind of reset.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->bConfigurationValue == bConfigurationValue)
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Set received event type to absolute or relative.
3fe24a3690526efc4cceece3819d628caadf3140vboxsync * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUsbReset
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnDestruct
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnConstruct
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic 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.
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = CFGMR3ValidateConfig(pCfg, "/", "Absolute|CoordShift", "Config", "UsbHid", iInstance);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = CFGMR3QueryBoolDef(pCfg, "Absolute", &isAbsolute, false);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis->enmMode = isAbsolute ? USBHIDMODE_ABSOLUTE : USBHIDMODE_RELATIVE;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.IPort.pfnPutEvent = usbHidMousePutEvent;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.IPort.pfnPutEventAbs = usbHidMousePutEventAbs;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Attach the mouse driver.
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Mouse Port");
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach mouse driver"));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIMOUSECONNECTOR);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query mouse interface"));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = CFGMR3QueryU8Def(pCfg, "CoordShift", &pThis->u8CoordShift, 1);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query shift factor"));
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 */
1256c6853363727c70b1b5075e5a747510858b94vboxsync /* pfnUsbGetDescriptorCache */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetConfiguration */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetInterface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbClearHaltedEndpoint */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbNew */
1ab072338283b0c700d1ef4958511296a4d0ca41vboxsync /* pfnUrbQueue */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbCancel */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbReap */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32TheEnd */