UsbMouse.cpp revision 8112e0942f1128329b99b22a20b395963d4abcea
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @file
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * UsbMouse - USB Human Interface Device Emulation (Mouse).
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (C) 2007-2010 Sun Microsystems, Inc.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Sun Microsystems, Inc. confidential
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * All rights reserved
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Header Files *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define LOG_GROUP LOG_GROUP_USB_MSD
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/pdmusb.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/log.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/err.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/assert.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/critsect.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/mem.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/semaphore.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/string.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/uuid.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include "../Builtins.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Defined Constants And Macros *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID string IDs
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @{ */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define USBHID_STR_ID_MANUFACTURER 1
8112e0942f1128329b99b22a20b395963d4abceavboxsync#define USBHID_STR_ID_PRODUCT_M 2
8112e0942f1128329b99b22a20b395963d4abceavboxsync#define USBHID_STR_ID_PRODUCT_T 3
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @} */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID specific descriptor types
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @{ */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define DT_IF_HID_REPORT 0x22
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @} */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID vendor and product IDs
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @{ */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define VBOX_USB_VENDOR 0x80EE
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define USBHID_PID_MOUSE 0x0020
8112e0942f1128329b99b22a20b395963d4abceavboxsync#define USBHID_PID_TABLET 0x0021
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @} */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Structures and Typedefs *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB HID request state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef enum USBHIDREQSTATE
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Invalid status. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDREQSTATE_INVALID = 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Ready to receive a new read request. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDREQSTATE_READY,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Have (more) data for the host. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDREQSTATE_DATA_TO_HOST,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Waiting to supply status information to the host. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDREQSTATE_STATUS,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The end of the valid states. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDREQSTATE_END
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDREQSTATE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Endpoint status data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHIDEP
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fHalted;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDEP;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to the endpoint status. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef USBHIDEP *PUSBHIDEP;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * A URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHIDURBQUEUE
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The head pointer. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pHead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Where to insert the next entry. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB *ppTail;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDURBQUEUE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to a URB queue. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef USBHIDURBQUEUE *PUSBHIDURBQUEUE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to a const URB queue. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef USBHIDURBQUEUE const *PCUSBHIDURBQUEUE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Mouse movement accumulator.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHIDM_ACCUM
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t btn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int32_t dX;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int32_t dY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int32_t dZ;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDM_ACCUM, *PUSBHIDM_ACCUM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB HID instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHID
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer back to the PDM USB Device instance structure. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMUSBINS pUsbIns;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Critical section protecting the device state. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCRITSECT CritSect;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The current configuration.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * (0 - default, 1 - the one supported configuration, i.e configured.) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint8_t bConfigurationValue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDEP aEps[2];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The state of the HID (state machine).*/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDREQSTATE enmState;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer movement accumulator. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDM_ACCUM PtrDelta;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pending to-host queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The URBs waiting here are waiting for data to become available.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDURBQUEUE ToHostQueue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Done queue
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The URBs stashed here are waiting to be reaped. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync USBHIDURBQUEUE DoneQueue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * is set. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSEMEVENT hEvtDoneQueue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Someone is waiting on the done queue. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fHaveDoneQueueWaiter;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /** Is this an absolute pointing device (tablet)? Relative (mouse) otherwise. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync bool isAbsolute;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Mouse port - LUN#0.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIBASE
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIMOUSEPORT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync struct
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The base interface for the mouse port. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE IBase;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The mouse port base interface. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIMOUSEPORT IPort;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The base interface of the attached mouse driver. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync R3PTRTYPE(PPDMIBASE) pDrvBase;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The mouse interface of the attached mouse driver. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync R3PTRTYPE(PPDMIMOUSECONNECTOR) pDrv;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync } Lun0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHID;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to the USB HID instance data. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef USBHID *PUSBHID;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * The USB HID report structure for relative device.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHIDM_REPORT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint8_t btn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int8_t dx;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int8_t dy;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int8_t dz;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDM_REPORT, *PUSBHIDM_REPORT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * The USB HID report structure for relative device.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsynctypedef struct USBHIDT_REPORT
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint16_t cx;
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint16_t cy;
8112e0942f1128329b99b22a20b395963d4abceavboxsync int8_t dz;
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint8_t btn;
8112e0942f1128329b99b22a20b395963d4abceavboxsync} USBHIDT_REPORT, *PUSBHIDT_REPORT;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Global Variables *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic const PDMUSBDESCCACHESTRING g_aUsbHidStrings_en_US[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync { USBHID_STR_ID_MANUFACTURER, "VirtualBox" },
8112e0942f1128329b99b22a20b395963d4abceavboxsync { USBHID_STR_ID_PRODUCT_M, "USB Mouse" },
8112e0942f1128329b99b22a20b395963d4abceavboxsync { USBHID_STR_ID_PRODUCT_T, "USB Tablet" },
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic const PDMUSBDESCCACHELANG g_aUsbHidLanguages[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync { 0x0409, RT_ELEMENTS(g_aUsbHidStrings_en_US), g_aUsbHidStrings_en_US }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCENDPOINTEX g_aUsbHidMEndpointDescs[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bLength = */ sizeof(VUSBDESCENDPOINT),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bmAttributes = */ 3 /* interrupt */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .wMaxPacketSize = */ 4,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterval = */ 10,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync },
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .pvMore = */ NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .pvClass = */ NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .cbClass = */ 0
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync },
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCENDPOINTEX g_aUsbHidTEndpointDescs[] =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bLength = */ sizeof(VUSBDESCENDPOINT),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bmAttributes = */ 3 /* interrupt */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wMaxPacketSize = */ 6,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterval = */ 10,
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvMore = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvClass = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cbClass = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* HID report descriptor (mouse). */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const uint8_t g_UsbHidMReportDesc[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage */ 0x09, 0x02, /* Mouse */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Collection */ 0xA1, 0x01, /* Application */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage */ 0x09, 0x01, /* Pointer */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Collection */ 0xA1, 0x00, /* Physical */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage Page */ 0x05, 0x09, /* Button */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage Minimum */ 0x19, 0x01, /* Button 1 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage Maximum */ 0x29, 0x03, /* Button 3 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Logical Minimum */ 0x15, 0x00, /* 0 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Logical Maximum */ 0x25, 0x01, /* 1 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Count */ 0x95, 0x03, /* 3 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Size */ 0x75, 0x01, /* 1 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Count */ 0x95, 0x01, /* 1 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Size */ 0x75, 0x05, /* 5 (padding bits) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage */ 0x09, 0x30, /* X */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage */ 0x09, 0x31, /* Y */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Usage */ 0x09, 0x38, /* Z (wheel) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Logical Minimum */ 0x15, 0x81, /* -127 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Logical Maximum */ 0x25, 0x7F, /* +127 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Size */ 0x75, 0x08, /* 8 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Count */ 0x95, 0x03, /* 3 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* End Collection */ 0xC0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* End Collection */ 0xC0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* HID report descriptor (tablet). */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const uint8_t g_UsbHidTReportDesc[] =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage */ 0x09, 0x02, /* Mouse */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Collection */ 0xA1, 0x01, /* Application */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage */ 0x09, 0x01, /* Pointer */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Collection */ 0xA1, 0x00, /* Physical */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage */ 0x09, 0x30, /* X */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage */ 0x09, 0x31, /* Y */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Minimum */ 0x15, 0x00, /* 0 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Maximum */ 0x26, 0xFF,0x7F,/* 0x7fff */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Physical Minimum */ 0x35, 0x00, /* 0 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Size */ 0x75, 0x10, /* 16 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Count */ 0x95, 0x02, /* 2 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage */ 0x09, 0x38, /* Z (wheel) */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Minimum */ 0x15, 0x81, /* -127 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Maximum */ 0x25, 0x7F, /* +127 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Size */ 0x75, 0x08, /* 8 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Count */ 0x95, 0x01, /* 1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Page */ 0x05, 0x09, /* Button */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Minimum */ 0x19, 0x01, /* Button 1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Maximum */ 0x29, 0x03, /* Button 3 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Minimum */ 0x15, 0x00, /* 0 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Maximum */ 0x25, 0x01, /* 1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Count */ 0x95, 0x03, /* 3 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Size */ 0x75, 0x01, /* 1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Count */ 0x95, 0x01, /* 1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Size */ 0x75, 0x05, /* 5 (padding bits) */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* End Collection */ 0xC0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* End Collection */ 0xC0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* Additional HID class interface descriptor. */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const uint8_t g_UsbHidMIfHidDesc[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bLength = */ 0x09,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDescriptorType = */ 0x21, /* HID */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bCountryCode = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bNumDescriptors = */ 1,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDescriptorType = */ 0x22, /* Report */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wDescriptorLength = */ sizeof(g_UsbHidMReportDesc), 0x00
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* Additional HID class interface descriptor. */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const uint8_t g_UsbHidTIfHidDesc[] =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bLength = */ 0x09,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDescriptorType = */ 0x21, /* HID */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bCountryCode = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumDescriptors = */ 1,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDescriptorType = */ 0x22, /* Report */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wDescriptorLength = */ sizeof(g_UsbHidTReportDesc), 0x00
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidMInterfaceDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bLength = */ sizeof(VUSBDESCINTERFACE),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDescriptorType = */ VUSB_DT_INTERFACE,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceNumber = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bAlternateSetting = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bNumEndpoints = */ 1,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceClass = */ 3 /* HID */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bInterfaceProtocol = */ 2 /* Mouse */,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iInterface = */ 0
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync },
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .pvMore = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvClass = */ &g_UsbHidMIfHidDesc,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cbClass = */ sizeof(g_UsbHidMIfHidDesc),
8112e0942f1128329b99b22a20b395963d4abceavboxsync &g_aUsbHidMEndpointDescs[0]
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidTInterfaceDesc =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bLength = */ sizeof(VUSBDESCINTERFACE),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDescriptorType = */ VUSB_DT_INTERFACE,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterfaceNumber = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bAlternateSetting = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumEndpoints = */ 1,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterfaceClass = */ 3 /* HID */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterfaceProtocol = */ 2 /* Mouse */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iInterface = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvMore = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvClass = */ &g_UsbHidTIfHidDesc,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cbClass = */ sizeof(g_UsbHidTIfHidDesc),
8112e0942f1128329b99b22a20b395963d4abceavboxsync &g_aUsbHidTEndpointDescs[0]
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBINTERFACE g_aUsbHidMInterfaces[] =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync { &g_UsbHidMInterfaceDesc, /* .cSettings = */ 1 },
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBINTERFACE g_aUsbHidTInterfaces[] =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync { &g_UsbHidTInterfaceDesc, /* .cSettings = */ 1 },
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCCONFIGEX g_UsbHidMConfigDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bLength = */ sizeof(VUSBDESCCONFIG),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDescriptorType = */ VUSB_DT_CONFIG,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .wTotalLength = */ 0 /* recalculated on read */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidMInterfaces),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bConfigurationValue =*/ 1,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iConfiguration = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bmAttributes = */ RT_BIT(7),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .MaxPower = */ 50 /* 100mA */
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync &g_aUsbHidMInterfaces[0]
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCCONFIGEX g_UsbHidTConfigDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bLength = */ sizeof(VUSBDESCCONFIG),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDescriptorType = */ VUSB_DT_CONFIG,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .wTotalLength = */ 0 /* recalculated on read */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidTInterfaces),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bConfigurationValue =*/ 1,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iConfiguration = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bmAttributes = */ RT_BIT(7),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .MaxPower = */ 50 /* 100mA */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync },
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync &g_aUsbHidTInterfaces[0]
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCDEVICE g_UsbHidMDeviceDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bLength = */ sizeof(g_UsbHidMDeviceDesc),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bDescriptorType = */ VUSB_DT_DEVICE,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bcdUsb = */ 0x110, /* 1.1 */
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 /* .bMaxPacketSize0 = */ 8,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .idVendor = */ VBOX_USB_VENDOR,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .idProduct = */ USBHID_PID_MOUSE,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bcdDevice = */ 0x0100, /* 1.0 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iProduct = */ USBHID_STR_ID_PRODUCT_M,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .iSerialNumber = */ 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .bNumConfigurations = */ 1
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const VUSBDESCDEVICE g_UsbHidTDeviceDesc =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bLength = */ sizeof(g_UsbHidTDeviceDesc),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bDescriptorType = */ VUSB_DT_DEVICE,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bcdUsb = */ 0x110, /* 1.1 */
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 /* .bMaxPacketSize0 = */ 8,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .idVendor = */ VBOX_USB_VENDOR,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .idProduct = */ USBHID_PID_TABLET,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bcdDevice = */ 0x0100, /* 1.0 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iProduct = */ USBHID_STR_ID_PRODUCT_T,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iSerialNumber = */ 0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bNumConfigurations = */ 1
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const PDMUSBDESCCACHE g_UsbHidMDescCache =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pDevice = */ &g_UsbHidMDeviceDesc,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .paConfigs = */ &g_UsbHidMConfigDesc,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .paLanguages = */ g_aUsbHidLanguages,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .fUseCachedDescriptors = */ true,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .fUseCachedStringsDescriptors = */ true
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic const PDMUSBDESCCACHE g_UsbHidTDescCache =
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pDevice = */ &g_UsbHidTDeviceDesc,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .paConfigs = */ &g_UsbHidTConfigDesc,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .paLanguages = */ g_aUsbHidLanguages,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .fUseCachedDescriptors = */ true,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* .fUseCachedStringsDescriptors = */ true
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Internal Functions *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Initializes an URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void usbHidQueueInit(PUSBHIDURBQUEUE pQueue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->pHead = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->ppTail = &pQueue->pHead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Inserts an URB at the end of the queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb The URB to insert.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb->Dev.pNext = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *pQueue->ppTail = pUrb;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->ppTail = &pUrb->Dev.pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Unlinks the head of the queue and returns it.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns The head entry.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pUrb = pQueue->pHead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pNext = pUrb->Dev.pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->pHead = pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pNext)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->ppTail = &pQueue->pHead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb->Dev.pNext = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pUrb;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Removes an URB from anywhere in the queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns true if found, false if not.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb The URB to remove.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pCur = pQueue->pHead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pCur == pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->pHead = pUrb->Dev.pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (pCur)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pCur->Dev.pNext == pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCur->Dev.pNext = pUrb->Dev.pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCur = pCur->Dev.pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pCur)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pUrb->Dev.pNext)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->ppTail = &pQueue->pHead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Checks if the queue is empty or not.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns true if it is, false if it isn't.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pQueue The URB queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncDECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pQueue->pHead == NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Links an URB into the done queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis The HID instance.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb The URB.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidQueueAddTail(&pThis->DoneQueue, pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fHaveDoneQueueWaiter)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Completes the URB with a stalled state, halting the pipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb->enmStatus = VUSBSTATUS_STALL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo figure out if the stall is global or pipe-specific or both. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pEp)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pEp->fHalted = true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->aEps[1].fHalted = true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->aEps[2].fHalted = true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidLinkDone(pThis, pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Completes the URB with a OK state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb->enmStatus = VUSBSTATUS_OK;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb->cbData = cbData;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidLinkDone(pThis, pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * usbHidUrbHandleDefaultPipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns VBox status code.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis The HID instance.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pUrb Set when usbHidUrbHandleDefaultPipe is the
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * caller.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param fSetConfig Set when usbHidUsbSetConfiguration is the
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * caller.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
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 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Reset the device state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->enmState = USBHIDREQSTATE_READY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->aEps[i].fHalted = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pUrb && !fSetConfig) /* (only device reset) */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->bConfigurationValue = 0; /* default */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Ditch all pending URBs.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pCurUrb;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pCurUrb->enmStatus = VUSBSTATUS_CRC;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidLinkDone(pThis, pCurUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void *) usbHidMouseQueryInterface(PPDMIBASE pInterface, const char *pszIID)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
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);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int8_t clamp_i8(int32_t val)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (val > 127) {
5045ab9ca39fa0b301f4020b7a072406eb0ecea2vboxsync val = 127;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync } else if (val < -127) {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync val = -127;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return val;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Relative mouse event handler.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
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.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidMousePutEvent(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync// int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync// AssertReleaseRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
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);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Accumulate movement - the events from the front end may arrive
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * at a much higher rate than USB can handle.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->PtrDelta.btn = fButtonStates;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->PtrDelta.dX += i32DeltaX;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->PtrDelta.dY += i32DeltaY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->PtrDelta.dZ -= i32DeltaZ; /* Inverted! */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Check if there's a URB waiting. If so, send a report.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbCopy;
8112e0942f1128329b99b22a20b395963d4abceavboxsync USBHIDM_REPORT report;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync //@todo: fix/extend
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync report.btn = pThis->PtrDelta.btn;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync report.dx = clamp_i8(pThis->PtrDelta.dX);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync report.dy = clamp_i8(pThis->PtrDelta.dY);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync report.dz = clamp_i8(pThis->PtrDelta.dZ);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbCopy = sizeof(report);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync memcpy(&pUrb->abData[0], &report, cbCopy);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Clear the accumulated movement. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->PtrDelta.dX = pThis->PtrDelta.dY = pThis->PtrDelta.dZ = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Complete the URB. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync usbHidCompleteOk(pThis, pUrb, cbCopy);
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 }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync// PDMCritSectLeave(&pThis->CritSect);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Absolute mouse event handler.
8112e0942f1128329b99b22a20b395963d4abceavboxsync *
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.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) usbHidMousePutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t u32X, uint32_t u32Y, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
8112e0942f1128329b99b22a20b395963d4abceavboxsync// int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
8112e0942f1128329b99b22a20b395963d4abceavboxsync// AssertReleaseRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(pThis->isAbsolute);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
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 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->PtrDelta.btn = fButtonStates;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->PtrDelta.dZ -= i32DeltaZ; /* Inverted! */
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Check if there's a URB waiting. If so, send a report.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pUrb)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbCopy;
8112e0942f1128329b99b22a20b395963d4abceavboxsync USBHIDT_REPORT report;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync report.btn = pThis->PtrDelta.btn;
8112e0942f1128329b99b22a20b395963d4abceavboxsync report.cx = u32X / 2;
8112e0942f1128329b99b22a20b395963d4abceavboxsync report.cy = u32Y / 2;
8112e0942f1128329b99b22a20b395963d4abceavboxsync report.dz = clamp_i8(pThis->PtrDelta.dZ);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbCopy = sizeof(report);
8112e0942f1128329b99b22a20b395963d4abceavboxsync memcpy(&pUrb->abData[0], &report, cbCopy);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Clear the accumulated movement. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->PtrDelta.dZ = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Complete the URB. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync usbHidCompleteOk(pThis, pUrb, cbCopy);
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 }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync// PDMCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUrbReap
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pUrb && cMillies)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Wait */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->fHaveDoneQueueWaiter = true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->fHaveDoneQueueWaiter = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pUrb;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUrbCancel
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Remove the URB from the to-host queue and move it onto the done queue.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (usbHidQueueRemove(&pThis->ToHostQueue, pUrb))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidLinkDone(pThis, pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
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.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Stall the request if the pipe is halted.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_UNLIKELY(pEp->fHalted))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, NULL, pUrb, "Halted pipe");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Deal with the URB according to the state.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (pThis->enmState)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * We've data left to transfer to the host.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case USBHIDREQSTATE_DATA_TO_HOST:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertFailed();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Status transfer.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case USBHIDREQSTATE_STATUS:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertFailed();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleIntrDevToHost: Entering READY\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->enmState = USBHIDREQSTATE_READY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case USBHIDREQSTATE_READY:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidQueueAddTail(&pThis->ToHostQueue, pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n", pUrb, pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Bad states, stall.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n", pThis->enmState, pUrb->cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Handles request sent to the default control pipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int usbHidHandleDefaultPipe(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (pSetup->bRequest)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_REQ_GET_DESCRIPTOR:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (pSetup->bmRequestType)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (pSetup->wValue >> 8)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_DT_STRING:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (pSetup->wValue >> 8)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case DT_IF_HID_REPORT:
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint32_t cbCopy;
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint32_t cbDesc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync const uint8_t *pDesc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pThis->isAbsolute)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbDesc = sizeof(g_UsbHidTReportDesc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pDesc = (const uint8_t *)&g_UsbHidTReportDesc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbDesc = sizeof(g_UsbHidMReportDesc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pDesc = (const uint8_t *)&g_UsbHidMReportDesc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Returned data is written after the setup message. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbCopy = pUrb->cbData - sizeof(*pSetup);
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbCopy = RT_MIN(cbCopy, cbDesc);
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 default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pSetup->bmRequestType));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_REQ_CLEAR_FEATURE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
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
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* 3.1 Bulk-Only Mass Storage Reset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if ( pSetup->bmRequestType == (VUSB_REQ_CLASS | VUSB_TO_INTERFACE)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && pSetup->bRequest == 0xff
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && !pSetup->wValue
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && !pSetup->wLength
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && pSetup->wIndex == 0)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidHandleDefaultPipe: Bulk-Only Mass Storage Reset\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidResetWorker(pThis, pUrb, false /*fSetConfig*/);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
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 }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnQueue
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Parse on a per end-point basis.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync switch (pUrb->EndPt)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case 0:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = usbHidHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case 0x81:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertFailed();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case 0x01:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbSetInterface
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(bAlternateSetting == 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbSetConfiguration
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(bConfigurationValue == 1);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * If the same config is applied more than once, it's a kind of reset.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->bConfigurationValue == bConfigurationValue)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->bConfigurationValue = bConfigurationValue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /*
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Set received event type to absolute or relative.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->Lun0.pDrv->pfnAbsModeChange(pThis->Lun0.pDrv, pThis->isAbsolute);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pThis->isAbsolute) {
8112e0942f1128329b99b22a20b395963d4abceavboxsync return &g_UsbHidTDescCache;
8112e0942f1128329b99b22a20b395963d4abceavboxsync } else {
8112e0942f1128329b99b22a20b395963d4abceavboxsync return &g_UsbHidMDescCache;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnUsbReset
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnDestruct
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void usbHidDestruct(PPDMUSBINS pUsbIns)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RTCritSectIsInitialized(&pThis->CritSect))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectEnter(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectDelete(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSemEventDestroy(pThis->hEvtDoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc PDMUSBREG::pfnConstruct
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) usbHidConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Log(("usbHidConstruct/#%u:\n", iInstance));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Perform the basic structure initialization first so the destructor
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * will not misbehave.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->pUsbIns = pUsbIns;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidQueueInit(&pThis->ToHostQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidQueueInit(&pThis->DoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = RTCritSectInit(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRCReturn(rc, rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRCReturn(rc, rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Validate and read the configuration.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3ValidateConfig(pCfg, "/", "Absolute", "Config", "UsbHid", iInstance);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3QueryBoolDef(pCfg, "Absolute", &pThis->isAbsolute, false);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->Lun0.IPort.pfnPutEvent = usbHidMousePutEvent;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->Lun0.IPort.pfnPutEventAbs = usbHidMousePutEventAbs;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Attach the mouse driver.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pUsbIns->pHlpR3->pfnDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Mouse Port");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach mouse driver"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIMOUSECONNECTOR);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!pThis->Lun0.pDrv)
8112e0942f1128329b99b22a20b395963d4abceavboxsync return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query mouse interface"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB Human Interface Device (HID) Mouse registration record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncconst PDMUSBREG g_UsbHidMou =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32Version */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_USBREG_VERSION,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szName */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "HidMouse",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pszDescription */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "USB HID Mouse.",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fFlags */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cMaxInstances */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ~0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cbInstance */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync sizeof(USBHID),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnConstruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidConstruct,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDestruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidDestruct,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMInitComplete */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMPowerOn */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMSuspend */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMResume */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnVMPowerOff */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnHotPlugged */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnHotUnplugged */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDriverAttach */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDriverDetach */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnQueryInterface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbReset,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbGetCachedDescriptors */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbGetDescriptorCache,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetConfiguration */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbSetConfiguration,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetInterface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbSetInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbClearHaltedEndpoint */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbClearHaltedEndpoint,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbNew */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL/*usbHidUrbNew*/,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnQueue */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidQueue,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbCancel */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUrbCancel,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbReap */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUrbReap,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32TheEnd */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_USBREG_VERSION
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};