ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @file
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * UsbMouse - USB Human Interface Device Emulation (Mouse).
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2007-2012 Oracle Corporation
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * available from http://www.virtualbox.org. This file is free software;
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * General Public License (GPL) as published by the Free Software
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Header Files *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
b6cba2c351e97805b97998ebe48e03ecef16b59avboxsync#define LOG_GROUP LOG_GROUP_USB_MOUSE
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/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>
3fe24a3690526efc4cceece3819d628caadf3140vboxsync#include "VBoxDD.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
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync#define USBHID_STR_ID_PRODUCT_MT 4
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @} */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @name USB HID specific descriptor types
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @{ */
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync#define DT_IF_HID_DESCRIPTOR 0x21
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
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync#define USBHID_PID_MULTI_TOUCH 0x0022
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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * The device reporting mode.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @todo Use an interface instead of an enum and switches.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsynctypedef enum USBHIDMODE
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Relative. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync USBHIDMODE_RELATIVE = 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Absolute. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync USBHIDMODE_ABSOLUTE,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Multi-touch. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync USBHIDMODE_MULTI_TOUCH
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync} USBHIDMODE;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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{
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync union
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync {
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync struct
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync {
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint32_t fButtons;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync int32_t dx;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync int32_t dy;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync int32_t dz;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync } Relative;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync struct
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync {
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync uint32_t fButtons;
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync int32_t dz;
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync int32_t dw;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint32_t x;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint32_t y;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync } Absolute;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync } u;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDM_ACCUM, *PUSBHIDM_ACCUM;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACTS_PER_REPORT 5
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_MAX_COUNT 10
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_F_IN_CONTACT 0x01
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_F_IN_RANGE 0x02
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_S_ACTIVE 0x01 /* Contact must be reported to the guest. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_S_CANCELLED 0x02 /* Contact loss must be reported to the guest. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_S_REUSED 0x04 /* Report contact loss for the oldId and then new contact for the id. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define MT_CONTACT_S_DIRTY 0x08 /* Temporary flag used to track already processed elements. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsynctypedef struct MTCONTACT
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint16_t x;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint16_t y;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t id;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t flags;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t status;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t oldId; /* Valid only if MT_CONTACT_S_REUSED is set. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync} MTCONTACT;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * The USB HID instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHID
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /** Pointer back to the PDM USB Device instance structure. */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync 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;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Someone is waiting on the done queue. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fHaveDoneQueueWaiter;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /** If device has pending changes. */
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync bool fHasPendingChanges;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Is this a relative, absolute or multi-touch pointing device? */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync USBHIDMODE enmMode;
6cd65034f702d9b4122249011835e9639a7bc660vboxsync /** Tablet coordinate shift factor for old and broken operating systems. */
6cd65034f702d9b4122249011835e9639a7bc660vboxsync uint8_t u8CoordShift;
6cd65034f702d9b4122249011835e9639a7bc660vboxsync
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
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT aCurrentContactState[MT_CONTACT_MAX_COUNT];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT aReportingContactState[MT_CONTACT_MAX_COUNT];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint32_t u32LastTouchScanTime;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync bool fTouchReporting;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync bool fTouchStateUpdated;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHID;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Pointer to the USB HID instance data. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef USBHID *PUSBHID;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#pragma pack(1)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * The USB HID report structure for relative device.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct USBHIDM_REPORT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint8_t fButtons;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int8_t dx;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int8_t dy;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int8_t dz;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} USBHIDM_REPORT, *PUSBHIDM_REPORT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
33f7a1bbfb625f3401368928cd5e9317ca04881dvboxsync * The USB HID report structure for absolute device.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsynctypedef struct USBHIDT_REPORT
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync uint8_t fButtons;
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync int8_t dz;
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync int8_t dw;
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync uint8_t padding;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint16_t x;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint16_t y;
8112e0942f1128329b99b22a20b395963d4abceavboxsync} USBHIDT_REPORT, *PUSBHIDT_REPORT;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/**
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * The combined USB HID report union for relative and absolute
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * devices.
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsynctypedef union USBHIDTM_REPORT
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync USBHIDM_REPORT m;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync USBHIDT_REPORT t;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync} USBHIDTM_REPORT, *PUSBHIDTM_REPORT;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/**
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * The USB HID report structure for the multi-touch device.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsynctypedef struct USBHIDMT_REPORT
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t idReport;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t cContacts;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync struct
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t fContact;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t cContact;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint16_t x;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint16_t y;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync } aContacts[MT_CONTACTS_PER_REPORT];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint32_t u32ScanTime;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync} USBHIDMT_REPORT, *PUSBHIDMT_REPORT;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsynctypedef struct USBHIDMT_REPORT_POINTER
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync{
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync uint8_t idReport;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync uint8_t fButtons;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync uint16_t x;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync uint16_t y;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync} USBHIDMT_REPORT_POINTER;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#pragma pack()
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Global Variables *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic const PDMUSBDESCCACHESTRING g_aUsbHidStrings_en_US[] =
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync { USBHID_STR_ID_MANUFACTURER, "VirtualBox" },
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync { USBHID_STR_ID_PRODUCT_M, "USB Mouse" },
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync { USBHID_STR_ID_PRODUCT_T, "USB Tablet" },
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync { USBHID_STR_ID_PRODUCT_MT, "USB Multi-Touch" },
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 */,
bdb156ae57bc9879b27543b8fbaac7e239f7ef2avboxsync /* .wMaxPacketSize = */ 8,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .bInterval = */ 10,
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvMore = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvClass = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cbClass = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsyncstatic const VUSBDESCENDPOINTEX g_aUsbHidMTEndpointDescs[] =
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .bLength = */ sizeof(VUSBDESCENDPOINT),
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .bmAttributes = */ 3 /* interrupt */,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .wMaxPacketSize = */ 64,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .bInterval = */ 10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync },
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .pvMore = */ NULL,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .pvClass = */ NULL,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .cbClass = */ 0
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync },
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync};
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
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 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Usage Maximum */ 0x29, 0x05, /* Button 5 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Logical Minimum */ 0x15, 0x00, /* 0 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Logical Maximum */ 0x25, 0x01, /* 1 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Report Count */ 0x95, 0x05, /* 5 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Size */ 0x75, 0x01, /* 1 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Report Count */ 0x95, 0x01, /* 1 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Report Size */ 0x75, 0x03, /* 3 (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 */
7808943002d119e1d00b500cc4228d48dc2976cfvboxsync /* 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). */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync/* NB: The layout is far from random. Having the buttons and Z axis grouped
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * together avoids alignment issues. Also, if X/Y is reported first, followed
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * by buttons/Z, Windows gets phantom Z movement. That is likely a bug in Windows
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * as OS X shows no such problem. When X/Y is reported last, Windows behaves
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync * properly.
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync */
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync
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, 0x09, /* Button */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Usage Minimum */ 0x19, 0x01, /* Button 1 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Usage Maximum */ 0x29, 0x05, /* Button 5 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Minimum */ 0x15, 0x00, /* 0 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Logical Maximum */ 0x25, 0x01, /* 1 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Report Count */ 0x95, 0x05, /* 5 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Size */ 0x75, 0x01, /* 1 */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Report Count */ 0x95, 0x01, /* 1 */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync /* Report Size */ 0x75, 0x03, /* 3 (padding bits) */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Usage */ 0x09, 0x38, /* Z (wheel) */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Logical Minimum */ 0x15, 0x81, /* -127 */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Logical Maximum */ 0x25, 0x7F, /* +127 */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Report Size */ 0x75, 0x08, /* 8 */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Report Count */ 0x95, 0x01, /* 1 */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Usage Page */ 0x05, 0x0C, /* Consumer Devices */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Usage */ 0x0A, 0x38, 0x02,/* AC Pan (horizontal wheel) */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Report Count */ 0x95, 0x01, /* 1 */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Report Size */ 0x75, 0x08, /* 8 (padding byte) */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Report Count */ 0x95, 0x01, /* 1 */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Usage */ 0x09, 0x30, /* X */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Usage */ 0x09, 0x31, /* Y */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Logical Minimum */ 0x15, 0x00, /* 0 */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Logical Maximum */ 0x26, 0xFF,0x7F,/* 0x7fff */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Physical Minimum */ 0x35, 0x00, /* 0 */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Report Size */ 0x75, 0x10, /* 16 */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Report Count */ 0x95, 0x02, /* 2 */
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* End Collection */ 0xC0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* End Collection */ 0xC0,
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/*
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * Multi-touch device implementation based on "Windows Pointer Device Data Delivery Protocol"
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * specification.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define REPORTID_TOUCH_POINTER 1
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define REPORTID_TOUCH_EVENT 2
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define REPORTID_TOUCH_MAX_COUNT 3
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define REPORTID_TOUCH_QABLOB 4
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define REPORTID_TOUCH_DEVCONFIG 5
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsyncstatic const uint8_t g_UsbHidMTReportDesc[] =
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Touch Screen) */ 0x09, 0x04,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Application) */ 0xA1, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report ID */ 0x85, REPORTID_TOUCH_EVENT,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Contact count) */ 0x09, 0x54,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (12) */ 0x25, 0x0C,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* MT_CONTACTS_PER_REPORT structs u8TipSwitch, u8ContactIdentifier, u16X, u16Y */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* 1 of 5 */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Finger) */ 0x09, 0x22,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Logical) */ 0xA1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Tip Switch) */ 0x09, 0x42,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (In Range) */ 0x09, 0x32,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (6) */ 0x95, 0x06,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Cnst,Var) */ 0x81, 0x03,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Contact identifier) */ 0x09, 0x51,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32) */ 0x25, 0x20,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (16) */ 0x75, 0x10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (X) */ 0x09, 0x30,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Y) */ 0x09, 0x31,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* 2 of 5 */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Finger) */ 0x09, 0x22,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Logical) */ 0xA1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Tip Switch) */ 0x09, 0x42,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (In Range) */ 0x09, 0x32,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (6) */ 0x95, 0x06,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Cnst,Var) */ 0x81, 0x03,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Contact identifier) */ 0x09, 0x51,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32) */ 0x25, 0x20,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (16) */ 0x75, 0x10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (X) */ 0x09, 0x30,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Y) */ 0x09, 0x31,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* 3 of 5 */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Finger) */ 0x09, 0x22,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Logical) */ 0xA1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Tip Switch) */ 0x09, 0x42,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (In Range) */ 0x09, 0x32,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (6) */ 0x95, 0x06,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Cnst,Var) */ 0x81, 0x03,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Contact identifier) */ 0x09, 0x51,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32) */ 0x25, 0x20,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (16) */ 0x75, 0x10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (X) */ 0x09, 0x30,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Y) */ 0x09, 0x31,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* 4 of 5 */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Finger) */ 0x09, 0x22,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Logical) */ 0xA1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Tip Switch) */ 0x09, 0x42,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (In Range) */ 0x09, 0x32,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (6) */ 0x95, 0x06,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Cnst,Var) */ 0x81, 0x03,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Contact identifier) */ 0x09, 0x51,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32) */ 0x25, 0x20,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (16) */ 0x75, 0x10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (X) */ 0x09, 0x30,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Y) */ 0x09, 0x31,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* 5 of 5 */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Finger) */ 0x09, 0x22,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Logical) */ 0xA1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Tip Switch) */ 0x09, 0x42,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (In Range) */ 0x09, 0x32,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (6) */ 0x95, 0x06,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Cnst,Var) */ 0x81, 0x03,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Contact identifier) */ 0x09, 0x51,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32) */ 0x25, 0x20,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (16) */ 0x75, 0x10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (X) */ 0x09, 0x30,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Y) */ 0x09, 0x31,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Note: "Scan time" usage is required for all touch devices (in 100microseconds units). */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x17, 0x00, 0x00, 0x00, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (2147483647) */ 0x27, 0xFF, 0xFF, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (32) */ 0x75, 0x20,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Unit Exponent (0) */ 0x55, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Unit (None) */ 0x65, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Scan time) */ 0x09, 0x56,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report ID */ 0x85, REPORTID_TOUCH_MAX_COUNT,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage (Contact count maximum) */ 0x09, 0x55,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage (Device identifier) */ 0x09, 0x53,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Report Size (8) */ 0x75, 0x08,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Report Count (2) */ 0x95, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (255) */ 0x26, 0xFF, 0x00,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Feature (Var) */ 0xB1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Vendor-Defined 1) */ 0x06, 0x00, 0xFF,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (QA blob) */ 0x09, 0xC5,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report ID */ 0x85, REPORTID_TOUCH_QABLOB,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (255) */ 0x26, 0xFF, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (8) */ 0x75, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (256) */ 0x96, 0x00, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Feature (Var) */ 0xB1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Note: the pointer report is required by specification:
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * "The report descriptor for a multiple input device must include at least
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * one top-level collection for the primary device and a separate top-level
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * collection for the mouse."
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Pointer) */ 0x09, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Application) */ 0xA1, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report ID */ 0x85, REPORTID_TOUCH_POINTER,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Pointer) */ 0x09, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Collection (Logical) */ 0xA1, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Button) */ 0x05, 0x09,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Minimum (Button 1) */ 0x19, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Maximum (Button 2) */ 0x29, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x15, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (1) */ 0x25, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (2) */ 0x95, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (1) */ 0x75, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (1) */ 0x95, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (6) */ 0x75, 0x06,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Cnst,Ary,Abs) */ 0x81, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage Page (Generic Desktop) */ 0x05, 0x01,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (X) */ 0x09, 0x30,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Usage (Y) */ 0x09, 0x31,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Minimum (0) */ 0x16, 0x00, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Physical Minimum (0) */ 0x36, 0x00, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Physical Maximum (32K) */ 0x46, 0xFF, 0x7F,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Unit (None) */ 0x66, 0x00, 0x00,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Size (16) */ 0x75, 0x10,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Report Count (2) */ 0x95, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* Input (Var) */ 0x81, 0x02,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage Page (Digitizer) */ 0x05, 0x0D,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage (Device configuration) */ 0x09, 0x0E,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Collection (Application) */ 0xA1, 0x01,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Report ID */ 0x85, REPORTID_TOUCH_DEVCONFIG,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage (Device settings) */ 0x09, 0x23,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Collection (Logical) */ 0xA1, 0x02,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage (Device mode) */ 0x09, 0x52,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Usage (Device identifier) */ 0x09, 0x53,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Logical Minimum (0) */ 0x15, 0x00,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Logical Maximum (10) */ 0x25, 0x0A,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Report Size (8) */ 0x75, 0x08,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Report Count (2) */ 0x95, 0x02,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* Feature (Var) */ 0xB1, 0x02,
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync/* End Collection */ 0xC0,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync/* End Collection */ 0xC0
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync};
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/** @todo Do these really have to all be duplicated three times? */
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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/* Additional HID class interface descriptor. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const uint8_t g_UsbHidMTIfHidDesc[] =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bLength = */ 0x09,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDescriptorType = */ 0x21, /* HID */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* .bcdHID = */ 0x10, 0x02, /* 2.1 */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bCountryCode = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bNumDescriptors = */ 1,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDescriptorType = */ 0x22, /* Report */
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync /* .wDescriptorLength = */ (uint8_t)(sizeof(g_UsbHidMTReportDesc) & 0xFF),
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync (uint8_t)((sizeof(g_UsbHidMTReportDesc) >> 8) & 0xFF)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync};
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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),
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync &g_aUsbHidMEndpointDescs[0],
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync /* .pIAD = */ NULL,
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync /* .cbIAD = */ 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 */,
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync /* .bInterfaceSubClass = */ 0 /* No subclass - no boot interface. */,
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync /* .bInterfaceProtocol = */ 0 /* No protocol - no boot interface. */,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .iInterface = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync },
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvMore = */ NULL,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .pvClass = */ &g_UsbHidTIfHidDesc,
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* .cbClass = */ sizeof(g_UsbHidTIfHidDesc),
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync &g_aUsbHidTEndpointDescs[0],
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync /* .pIAD = */ NULL,
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync /* .cbIAD = */ 0
8112e0942f1128329b99b22a20b395963d4abceavboxsync};
8112e0942f1128329b99b22a20b395963d4abceavboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBDESCINTERFACEEX g_UsbHidMTInterfaceDesc =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bLength = */ sizeof(VUSBDESCINTERFACE),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDescriptorType = */ VUSB_DT_INTERFACE,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceNumber = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bAlternateSetting = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bNumEndpoints = */ 1,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceClass = */ 3 /* HID */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceSubClass = */ 0 /* No subclass - no boot interface. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bInterfaceProtocol = */ 0 /* No protocol - no boot interface. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .iInterface = */ 0
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync },
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .pvMore = */ NULL,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .pvClass = */ &g_UsbHidMTIfHidDesc,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .cbClass = */ sizeof(g_UsbHidMTIfHidDesc),
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync &g_aUsbHidMTEndpointDescs[0],
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .pIAD = */ NULL,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .cbIAD = */ 0
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync};
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBINTERFACE g_aUsbHidMTInterfaces[] =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync { &g_UsbHidMTInterfaceDesc, /* .cSettings = */ 1 },
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync};
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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 },
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync NULL, /* pvMore */
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync &g_aUsbHidMInterfaces[0],
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync NULL /* pvOriginal */
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 },
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync NULL, /* pvMore */
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync &g_aUsbHidTInterfaces[0],
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync NULL /* pvOriginal */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBDESCCONFIGEX g_UsbHidMTConfigDesc =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bLength = */ sizeof(VUSBDESCCONFIG),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDescriptorType = */ VUSB_DT_CONFIG,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .wTotalLength = */ 0 /* recalculated on read */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidMTInterfaces),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bConfigurationValue =*/ 1,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .iConfiguration = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bmAttributes = */ RT_BIT(7),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .MaxPower = */ 50 /* 100mA */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync },
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync NULL, /* pvMore */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync &g_aUsbHidMTInterfaces[0],
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync NULL /* pvOriginal */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync};
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const VUSBDESCDEVICE g_UsbHidMTDeviceDesc =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bLength = */ sizeof(g_UsbHidMTDeviceDesc),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDescriptorType = */ VUSB_DT_DEVICE,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bcdUsb = */ 0x110, /* 1.1 */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bMaxPacketSize0 = */ 8,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .idVendor = */ VBOX_USB_VENDOR,
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync /* .idProduct = */ USBHID_PID_MULTI_TOUCH,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bcdDevice = */ 0x0100, /* 1.0 */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync /* .iProduct = */ USBHID_STR_ID_PRODUCT_MT,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .iSerialNumber = */ 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .bNumConfigurations = */ 1
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync};
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic const PDMUSBDESCCACHE g_UsbHidMTDescCache =
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .pDevice = */ &g_UsbHidMTDeviceDesc,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .paConfigs = */ &g_UsbHidMTConfigDesc,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .paLanguages = */ g_aUsbHidLanguages,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .fUseCachedDescriptors = */ true,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* .fUseCachedStringsDescriptors = */ true
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync};
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
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)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pQueue->pHead = pUrb->Dev.pNext;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (!pUrb->Dev.pNext)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pQueue->ppTail = &pQueue->pHead;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
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;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (!pUrb->Dev.pNext)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pQueue->ppTail = &pCur->Dev.pNext;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb->Dev.pNext = NULL;
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{
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync 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 {
c0b47c53336892431c7a2d8666600ffed91c11f1vboxsync pThis->aEps[0].fHalted = true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->aEps[1].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{
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pUrb->enmStatus = VUSBSTATUS_OK;
87d9823b393efbc674b3f3b0ff96998ca89e89b7vboxsync pUrb->cbData = (uint32_t)cbData;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidLinkDone(pThis, pUrb);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync * usbHidHandleDefaultPipe.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns VBox status code.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis The HID instance.
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync * @param pUrb Set when usbHidHandleDefaultPipe 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;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync pThis->fHasPendingChanges = false;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync pThis->fTouchStateUpdated = false;
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
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic int8_t clamp_i8(int32_t val)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (val > 127) {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync val = 127;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync } else if (val < -127) {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync val = -127;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return val;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/**
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * Create a USB HID report report based on the currently accumulated data.
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic size_t usbHidFillReport(PUSBHIDTM_REPORT pReport,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PUSBHIDM_ACCUM pAccumulated, USBHIDMODE enmMode)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync size_t cbCopy;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync switch (enmMode)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_ABSOLUTE:
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->t.fButtons = pAccumulated->u.Absolute.fButtons;
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync pReport->t.dz = clamp_i8(pAccumulated->u.Absolute.dz);
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync pReport->t.dw = clamp_i8(pAccumulated->u.Absolute.dw);
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync pReport->t.padding = 0;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->t.x = pAccumulated->u.Absolute.x;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->t.y = pAccumulated->u.Absolute.y;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync cbCopy = sizeof(pReport->t);
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync LogRel3(("Abs event, x=%d, y=%d, fButtons=%02x, report size %d\n",
02973eaf12e421595fcc3bbee4dd355d495ecfe6vboxsync pReport->t.x, pReport->t.y, pReport->t.fButtons,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync cbCopy));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_RELATIVE:
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.fButtons = pAccumulated->u.Relative.fButtons;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.dx = clamp_i8(pAccumulated->u.Relative.dx);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.dy = clamp_i8(pAccumulated->u.Relative.dy);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.dz = clamp_i8(pAccumulated->u.Relative.dz);
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync cbCopy = sizeof(pReport->m);
7808943002d119e1d00b500cc4228d48dc2976cfvboxsync LogRel3(("Rel event, dx=%d, dy=%d, dz=%d, fButtons=%02x, report size %d\n",
7808943002d119e1d00b500cc4228d48dc2976cfvboxsync pReport->m.dx, pReport->m.dy, pReport->m.dz,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pReport->m.fButtons, cbCopy));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync default:
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync AssertFailed(); /* Unexpected here. */
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync cbCopy = 0;
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Clear the accumulated movement. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RT_ZERO(*pAccumulated);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return cbCopy;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsyncDECLINLINE(MTCONTACT *) usbHidFindMTContact(MTCONTACT *paContacts, size_t cContacts,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t u8Mask, uint8_t u8Value)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync size_t i;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < cContacts; i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if ((paContacts[i].status & u8Mask) == u8Value)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return &paContacts[i];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return NULL;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync}
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsyncstatic int usbHidSendMultiTouchReport(PUSBHID pThis, PVUSBURB pUrb)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t i;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT *pRepContact;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT *pCurContact;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Number of contacts to be reported. In hybrid mode the first report contains
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * total number of contacts and subsequent reports contain 0.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t cContacts = 0;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync Assert(pThis->fHasPendingChanges);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (!pThis->fTouchReporting)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->fTouchReporting = true;
8db04577ed24e818f397035fe2c81cca113a069dvboxsync pThis->fTouchStateUpdated = false;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Update the reporting state with the new current state.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * Also mark all active contacts in reporting state as dirty,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * that is they must be reported to the guest.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < MT_CONTACT_MAX_COUNT; i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact = &pThis->aReportingContactState[i];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact = &pThis->aCurrentContactState[i];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact->status & MT_CONTACT_S_ACTIVE)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact->status & MT_CONTACT_S_REUSED)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status &= ~MT_CONTACT_S_REUSED;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Keep x,y. Will report lost contact at this point. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->id = pCurContact->oldId;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->flags = 0;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status = MT_CONTACT_S_REUSED;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else if (pThis->aCurrentContactState[i].status & MT_CONTACT_S_CANCELLED)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status &= ~(MT_CONTACT_S_CANCELLED | MT_CONTACT_S_ACTIVE);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Keep x,y. Will report lost contact at this point. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->id = pCurContact->id;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->flags = 0;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status = 0;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact->flags == 0)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status &= ~MT_CONTACT_S_ACTIVE; /* Contact disapeared. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->x = pCurContact->x;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->y = pCurContact->y;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->id = pCurContact->id;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->flags = pCurContact->flags;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status = 0;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync cContacts++;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status |= MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status = 0;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Report current state. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&pUrb->abData[0];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync RT_ZERO(*p);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->idReport = REPORTID_TOUCH_EVENT;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->cContacts = cContacts;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t iReportedContact;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (iReportedContact = 0; iReportedContact < MT_CONTACTS_PER_REPORT; iReportedContact++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Find the next not reported contact. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact = usbHidFindMTContact(pThis->aReportingContactState, RT_ELEMENTS(pThis->aReportingContactState),
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (!pRepContact)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRel3(("usbHid: no more touch contacts to report\n"));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync break;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pRepContact->status & MT_CONTACT_S_REUSED)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Do not clear DIRTY flag for contacts which were reused.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * Because two reports must be generated:
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * one for old contact off, and the second for new contact on.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status &= ~MT_CONTACT_S_REUSED;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact->status &= ~MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->aContacts[iReportedContact].fContact = pRepContact->flags;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->aContacts[iReportedContact].cContact = pRepContact->id;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync p->u32ScanTime = pThis->u32LastTouchScanTime * 10;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync Assert(iReportedContact > 0);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Reset TouchReporting if all contacts reported. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pRepContact = usbHidFindMTContact(pThis->aReportingContactState, RT_ELEMENTS(pThis->aReportingContactState),
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (!pRepContact)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRel3(("usbHid: all touch contacts reported\n"));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->fTouchReporting = false;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync pThis->fHasPendingChanges = pThis->fTouchStateUpdated;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->fHasPendingChanges = true;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", sizeof(USBHIDMT_REPORT), p));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(USBHIDMT_REPORT));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync}
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/**
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * Sends a state report to the host if there is a pending URB.
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic int usbHidSendReport(PUSBHID pThis)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pThis->enmMode == USBHIDMODE_MULTI_TOUCH)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* This device uses a different reporting method and fHasPendingChanges maintenance. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pUrb)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return usbHidSendMultiTouchReport(pThis, pUrb);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return VINF_SUCCESS;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pUrb)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PUSBHIDTM_REPORT pReport = (PUSBHIDTM_REPORT)&pUrb->abData[0];
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync size_t cbCopy;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbCopy = usbHidFillReport(pReport, &pThis->PtrDelta, pThis->enmMode);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync pThis->fHasPendingChanges = false;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return usbHidCompleteOk(pThis, pUrb, cbCopy);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync else
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("No available URB for USB mouse\n"));
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync pThis->fHasPendingChanges = true;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return VINF_EOF;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
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
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * @interface_method_impl{PDMIMOUSEPORT,pfnPutEvent}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsyncstatic DECLCALLBACK(int) usbHidMousePutEvent(PPDMIMOUSEPORT pInterface,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync int32_t dx, int32_t dy, int32_t dz,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync int32_t dw, uint32_t fButtons)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTCritSectEnter(&pThis->CritSect);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Accumulate movement - the events from the front end may arrive
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * at a much higher rate than USB can handle.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Relative.fButtons = fButtons;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Relative.dx += dx;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Relative.dy += dy;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Relative.dz -= dz; /* Inverted! */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Send a report if possible. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync usbHidSendReport(pThis);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTCritSectLeave(&pThis->CritSect);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventAbs}
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsyncstatic DECLCALLBACK(int) usbHidMousePutEventAbs(PPDMIMOUSEPORT pInterface,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint32_t x, uint32_t y,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync int32_t dz, int32_t dw,
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync uint32_t fButtons)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTCritSectEnter(&pThis->CritSect);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(pThis->enmMode == USBHIDMODE_ABSOLUTE);
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
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * when only the Z axis is relative (X/Y movement isn't technically
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * accumulated and only the last value is used).
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Absolute.fButtons = fButtons;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Absolute.x = x >> pThis->u8CoordShift;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync pThis->PtrDelta.u.Absolute.y = y >> pThis->u8CoordShift;
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync pThis->PtrDelta.u.Absolute.dz -= dz; /* Inverted! */
0ddb8d1d457c326e713f6afb589fec72df6a7550vboxsync pThis->PtrDelta.u.Absolute.dw -= dw; /* Inverted! */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync /* Send a report if possible. */
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync usbHidSendReport(pThis);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync RTCritSectLeave(&pThis->CritSect);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync return VINF_SUCCESS;
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync}
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync/**
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMultiTouch}
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsyncstatic DECLCALLBACK(int) usbHidMousePutEventMultiTouch(PPDMIMOUSEPORT pInterface,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t cContacts,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync const uint64_t *pau64Contacts,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint32_t u32ScanTime)
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t i;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t j;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Make a copy of new contacts */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT *paNewContacts = (MTCONTACT *)RTMemTmpAlloc(sizeof(MTCONTACT) * cContacts);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (!paNewContacts)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return VERR_NO_MEMORY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < cContacts; i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync uint32_t u32Lo = RT_LO_U32(pau64Contacts[i]);
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync uint32_t u32Hi = RT_HI_U32(pau64Contacts[i]);
b139fff8c1f5fecf291d1315c83b2043c6ec6e37vboxsync paNewContacts[i].x = (uint16_t)u32Lo;
b139fff8c1f5fecf291d1315c83b2043c6ec6e37vboxsync paNewContacts[i].y = (uint16_t)(u32Lo >> 16);
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync paNewContacts[i].id = RT_BYTE1(u32Hi);
dd0f1b7925a57b9976df733c4203f995bdcb170dvboxsync paNewContacts[i].flags = RT_BYTE2(u32Hi) & (MT_CONTACT_F_IN_CONTACT | MT_CONTACT_F_IN_RANGE);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync paNewContacts[i].status = MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync paNewContacts[i].oldId = 0; /* Not used. */
36ff42fdbb32d6d77173b33d25aeb6a4e44ea1bcvboxsync if (paNewContacts[i].flags & MT_CONTACT_F_IN_CONTACT)
36ff42fdbb32d6d77173b33d25aeb6a4e44ea1bcvboxsync {
36ff42fdbb32d6d77173b33d25aeb6a4e44ea1bcvboxsync paNewContacts[i].flags |= MT_CONTACT_F_IN_RANGE;
36ff42fdbb32d6d77173b33d25aeb6a4e44ea1bcvboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT *pCurContact = NULL;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MTCONTACT *pNewContact = NULL;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync RTCritSectEnter(&pThis->CritSect);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync Assert(pThis->enmMode == USBHIDMODE_MULTI_TOUCH);
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Maintain a state of all current contacts.
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync * Intr URBs will be completed according to the state.
aa327535f5ce61d8851bf6495ca1b507f013252bvboxsync */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Mark all existing contacts as dirty. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].status |= MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Update existing contacts and mark new contacts. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < cContacts; i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact = &paNewContacts[i];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Find existing contact with the same id. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact = NULL;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (j = 0; j < RT_ELEMENTS(pThis->aCurrentContactState); j++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if ( (pThis->aCurrentContactState[j].status & MT_CONTACT_S_ACTIVE) != 0
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync && pThis->aCurrentContactState[j].id == pNewContact->id)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact = &pThis->aCurrentContactState[j];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync break;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->status &= ~MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->x = pNewContact->x;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->y = pNewContact->y;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact->flags == 0) /* Contact disappeared already. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->oldId = pCurContact->id;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->flags = pNewContact->flags;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status &= ~MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Append new contacts (the dirty one in the paNewContacts). */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < cContacts; i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact = &paNewContacts[i];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pNewContact->status & MT_CONTACT_S_DIRTY)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* It is a new contact, copy is to one of not ACTIVE or not updated existing contacts. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact = usbHidFindMTContact(pThis->aCurrentContactState, RT_ELEMENTS(pThis->aCurrentContactState),
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MT_CONTACT_S_ACTIVE, 0);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync *pCurContact = *pNewContact;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status = MT_CONTACT_S_ACTIVE; /* Reset status. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Dirty existing contacts can be reused. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact = usbHidFindMTContact(pThis->aCurrentContactState, RT_ELEMENTS(pThis->aCurrentContactState),
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->x = pNewContact->x;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->y = pNewContact->y;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->oldId = pCurContact->id;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->flags = pNewContact->flags;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status &= ~MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRel3(("usbHid: dropped new contact: %d,%d id %d flags %RX8 status %RX8 oldId %d\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->x,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->y,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->id,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->flags,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->status,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pNewContact->oldId
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync ));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Mark still dirty existing contacts as cancelled, because a new set of contacts does not include them. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact = &pThis->aCurrentContactState[i];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pCurContact->status & MT_CONTACT_S_DIRTY)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status |= MT_CONTACT_S_CANCELLED;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pCurContact->status &= ~MT_CONTACT_S_DIRTY;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->u32LastTouchScanTime = u32ScanTime;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRel3(("usbHid: scanTime (ms): %d\n", pThis->u32LastTouchScanTime));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRel3(("usbHid: contact state[%d]: %d,%d id %d flags %RX8 status %RX8 oldId %d\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync i,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].x,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].y,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].id,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].flags,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].status,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->aCurrentContactState[i].oldId
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync ));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync pThis->fTouchStateUpdated = true;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->fHasPendingChanges = true;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Send a report if possible. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync usbHidSendReport(pThis);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTCritSectLeave(&pThis->CritSect);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync RTMemTmpFree(paNewContacts);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUrbReap
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
fdd17dc68230654ee0796918863927fca10a9f0avboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync LogFlowFunc(("pUsbIns=%p cMillies=%u\n", pUsbIns, cMillies));
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync
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)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pUrb->pszDesc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pUrb;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync/**
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync * @copydoc PDMUSBREG::pfnWakeup
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync */
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsyncstatic DECLCALLBACK(int) usbHidWakeup(PPDMUSBINS pUsbIns)
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync{
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync return RTSemEventSignal(pThis->hEvtDoneQueue);
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUrbCancel
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync{
3fe24a3690526efc4cceece3819d628caadf3140vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync 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();
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Status transfer.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case USBHIDREQSTATE_STATUS:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertFailed();
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("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);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb, pUrb->pszDesc));
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* If a report is pending, send it right away. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->fHasPendingChanges)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync usbHidSendReport(pThis);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Bad states, stall.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->enmState, pUrb->cbData));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define GET_REPORT 0x01
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define GET_IDLE 0x02
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define GET_PROTOCOL 0x03
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define SET_REPORT 0x09
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define SET_IDLE 0x0A
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync#define SET_PROTOCOL 0x0B
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsyncstatic uint8_t sau8QASampleBlob[256] =
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x07, 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x2e, 0x84, 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x47, 0x70, 0x1b, 0x59, 0x6f, 0x74, 0x43, 0xc4,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xc7, 0x95, 0x0e, 0x31, 0x55, 0x21, 0xd3, 0xb5,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x3e, 0xb3, 0xaf, 0x75, 0x81, 0x9d, 0x53, 0xb9,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d, 0xa7, 0x26,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0, 0x2a,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x0b, 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xe8, 0x8a, 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x2b, 0x53, 0x5c, 0x69, 0x52, 0xd5, 0xc8, 0x73,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x05, 0xd8, 0x2b, 0x79, 0x9a, 0xe2, 0x34, 0x60,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x80, 0xe3, 0x0f, 0xbd, 0x65, 0x20, 0x08, 0x13,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe, 0x31, 0x48,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a, 0xe4,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync 0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync};
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsyncstatic int usbHidRequestClass(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync{
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pThis->enmMode != USBHIDMODE_MULTI_TOUCH)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->wIndex, pSetup->wLength));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported class req");
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync int rc = VINF_SUCCESS;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync switch (pSetup->bRequest)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync case SET_REPORT:
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync case GET_REPORT:
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t u8ReportType = RT_HI_U8(pSetup->wValue);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint8_t u8ReportID = RT_LO_U8(pSetup->wValue);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRelFlow(("usbHid: %s: type %d, ID %d, data\n%.*Rhxd\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->bRequest == GET_REPORT? "GET_REPORT": "SET_REPORT",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync u8ReportType, u8ReportID,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb->cbData - sizeof(VUSBSETUP), &pUrb->abData[sizeof(VUSBSETUP)]));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if (pSetup->bRequest == GET_REPORT)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync uint32_t cbData = 0; /* 0 means that the report is unsupported. */
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync if (u8ReportType == 1 && u8ReportID == REPORTID_TOUCH_POINTER)
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync USBHIDMT_REPORT_POINTER *p = (USBHIDMT_REPORT_POINTER *)&pUrb->abData[sizeof(VUSBSETUP)];
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync /* The actual state should be reported here. */
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync p->idReport = REPORTID_TOUCH_POINTER;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync p->fButtons = 0;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync p->x = 0;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync p->y = 0;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync cbData = sizeof(USBHIDMT_REPORT_POINTER);
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync else if (u8ReportType == 1 && u8ReportID == REPORTID_TOUCH_EVENT)
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&pUrb->abData[sizeof(VUSBSETUP)];
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync /* The actual state should be reported here. */
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync RT_ZERO(*p);
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync p->idReport = REPORTID_TOUCH_EVENT;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync cbData = sizeof(USBHIDMT_REPORT);
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_MAX_COUNT)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_MAX_COUNT;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb->abData[sizeof(VUSBSETUP) + 1] = MT_CONTACT_MAX_COUNT; /* Contact count maximum. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb->abData[sizeof(VUSBSETUP) + 2] = 0; /* Device identifier */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync cbData = 3;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_QABLOB)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync uint32_t cbLeft = pUrb->cbData;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_QABLOB; /* Report Id. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync memcpy(&pUrb->abData[sizeof(VUSBSETUP) + 1],
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync sau8QASampleBlob, sizeof(sau8QASampleBlob));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync cbData = sizeof(sau8QASampleBlob) + 1;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_DEVCONFIG)
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_DEVCONFIG;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync pUrb->abData[sizeof(VUSBSETUP) + 1] = 2; /* Device mode:
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync * "HID touch device supporting contact
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync * identifier and contact count maximum."
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync */
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync pUrb->abData[sizeof(VUSBSETUP) + 2] = 0; /* Device identifier */
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync cbData = 3;
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync if (cbData > 0)
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync rc = usbHidCompleteOk(pThis, pUrb, sizeof(VUSBSETUP) + cbData);
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync else
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync rc = usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported GET_REPORT MT");
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync else
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync {
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync /* SET_REPORT */
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync rc = usbHidCompleteOk(pThis, pUrb, pUrb->cbData);
2f9ed1ea91dcb6c529fa86c69d38b965b1c70b67vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync } break;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync default:
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->wIndex, pSetup->wLength));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync rc = usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported class req MT");
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return rc;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync}
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:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync 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 {
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync uint32_t cbCopy;
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync uint32_t cbDesc;
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync const uint8_t *pDesc;
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync case DT_IF_HID_DESCRIPTOR:
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync switch (pThis->enmMode)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_ABSOLUTE:
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync cbDesc = sizeof(g_UsbHidTIfHidDesc);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync pDesc = (const uint8_t *)&g_UsbHidTIfHidDesc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_RELATIVE:
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync cbDesc = sizeof(g_UsbHidMIfHidDesc);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync pDesc = (const uint8_t *)&g_UsbHidMIfHidDesc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_MULTI_TOUCH:
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbDesc = sizeof(g_UsbHidMTIfHidDesc);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pDesc = (const uint8_t *)&g_UsbHidMTIfHidDesc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync default:
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync cbDesc = 0;
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync pDesc = 0;
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync /* Returned data is written after the setup message. */
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync cbCopy = pUrb->cbData - sizeof(*pSetup);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync cbCopy = RT_MIN(cbCopy, cbDesc);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidMouse: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbCopy=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wValue, pSetup->wIndex,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync cbCopy));
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case DT_IF_HID_REPORT:
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync switch (pThis->enmMode)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_ABSOLUTE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbDesc = sizeof(g_UsbHidTReportDesc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pDesc = (const uint8_t *)&g_UsbHidTReportDesc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_RELATIVE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbDesc = sizeof(g_UsbHidMReportDesc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pDesc = (const uint8_t *)&g_UsbHidMReportDesc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_MULTI_TOUCH:
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbDesc = sizeof(g_UsbHidMTReportDesc);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pDesc = (const uint8_t *)&g_UsbHidMTReportDesc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync break;
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync default:
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync cbDesc = 0;
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync pDesc = 0;
f35e566b1f8f9c4ee26c478ab749325ff8d761b3vboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Returned data is written after the setup message. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbCopy = pUrb->cbData - sizeof(*pSetup);
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbCopy = RT_MIN(cbCopy, cbDesc);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wValue, pSetup->wIndex,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync cbCopy));
8112e0942f1128329b99b22a20b395963d4abceavboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wValue, pSetup->wIndex));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync default:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->bmRequestType));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_REQ_GET_STATUS:
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync uint16_t wRet = 0;
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync if (pSetup->wLength != 2)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Bad GET_STATUS req: wLength=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wLength));
8865816a3d875ec1a036af307fbb484af107f014vboxsync break;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync Assert(pSetup->wValue == 0);
8865816a3d875ec1a036af307fbb484af107f014vboxsync switch (pSetup->bmRequestType)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync Assert(pSetup->wIndex == 0);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_STATUS (device)\n"));
8865816a3d875ec1a036af307fbb484af107f014vboxsync wRet = 0; /* Not self-powered, no remote wakeup. */
8865816a3d875ec1a036af307fbb484af107f014vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pSetup->wIndex == 0)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync else
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_STATUS (interface) invalid, wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wIndex));
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync break;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
8865816a3d875ec1a036af307fbb484af107f014vboxsync memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync else
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: GET_STATUS (endpoint) invalid, wIndex=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wIndex));
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync break;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync default:
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Bad GET_STATUS req: bmRequestType=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->bmRequestType));
8865816a3d875ec1a036af307fbb484af107f014vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync break;
8865816a3d875ec1a036af307fbb484af107f014vboxsync }
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync case VUSB_REQ_CLEAR_FEATURE:
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** @todo implement this. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wIndex, pSetup->wLength));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync /* Only VUSB_TO_INTERFACE is allowed. */
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync if ((pSetup->bmRequestType & VUSB_RECIP_MASK) == VUSB_TO_INTERFACE)
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync {
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return usbHidRequestClass(pThis, pEp, pUrb);
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync LogRelFlow(("usbHid: invalid recipient of class req: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pSetup->wIndex, pSetup->wLength));
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Invalid recip");
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHid: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pSetup->wIndex, pSetup->wLength));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return usbHidCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUrbQueue
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync 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
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync{
3fe24a3690526efc4cceece3819d628caadf3140vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pUsbIns->iInstance, uEndpoint));
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
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
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
3fe24a3690526efc4cceece3819d628caadf3140vboxsync * @copydoc PDMUSBREG::pfnUsbSetInterface
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync{
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
3fe24a3690526efc4cceece3819d628caadf3140vboxsync Assert(bAlternateSetting == 0);
3fe24a3690526efc4cceece3819d628caadf3140vboxsync return VINF_SUCCESS;
3fe24a3690526efc4cceece3819d628caadf3140vboxsync}
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUsbSetConfiguration
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n",
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync 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)
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->bConfigurationValue = bConfigurationValue;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync /*
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Set received event type to absolute or relative.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis->Lun0.pDrv->pfnReportModes(pThis->Lun0.pDrv,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis->enmMode == USBHIDMODE_RELATIVE,
7a185f1e2bf2e6deb246ff1a4e1c9380aa50b40evboxsync pThis->enmMode == USBHIDMODE_ABSOLUTE,
7a185f1e2bf2e6deb246ff1a4e1c9380aa50b40evboxsync pThis->enmMode == USBHIDMODE_MULTI_TOUCH);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTCritSectLeave(&pThis->CritSect);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
3fe24a3690526efc4cceece3819d628caadf3140vboxsync * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
fdd17dc68230654ee0796918863927fca10a9f0avboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync switch (pThis->enmMode)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_ABSOLUTE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync return &g_UsbHidTDescCache;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_RELATIVE:
8112e0942f1128329b99b22a20b395963d4abceavboxsync return &g_UsbHidMDescCache;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync case USBHIDMODE_MULTI_TOUCH:
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync return &g_UsbHidMTDescCache;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync default:
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync return NULL;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnUsbReset
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync{
3fe24a3690526efc4cceece3819d628caadf3140vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("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
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnDestruct
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic void usbHidDestruct(PPDMUSBINS pUsbIns)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync{
3fe24a3690526efc4cceece3819d628caadf3140vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
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
3fe24a3690526efc4cceece3819d628caadf3140vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * @copydoc PDMUSBREG::pfnConstruct
3fe24a3690526efc4cceece3819d628caadf3140vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) usbHidConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync{
3fe24a3690526efc4cceece3819d628caadf3140vboxsync PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync char szMode[64];
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogRelFlow(("usbHidConstruct/#%u:\n", iInstance));
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Perform the basic structure initialization first so the destructor
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * will not misbehave.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync 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 */
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync rc = CFGMR3ValidateConfig(pCfg, "/", "Mode|CoordShift", "Config", "UsbHid", iInstance);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync rc = CFGMR3QueryStringDef(pCfg, "Mode", szMode, sizeof(szMode), "relative");
fdd17dc68230654ee0796918863927fca10a9f0avboxsync if (RT_FAILURE(rc))
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync if (!RTStrCmp(szMode, "relative"))
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync pThis->enmMode = USBHIDMODE_RELATIVE;
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync else if (!RTStrCmp(szMode, "absolute"))
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync pThis->enmMode = USBHIDMODE_ABSOLUTE;
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync else if (!RTStrCmp(szMode, "multitouch"))
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync pThis->enmMode = USBHIDMODE_MULTI_TOUCH;
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync else
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS,
81df7e626b7bf4c65b5e3215e6cf83093ee671efvboxsync N_("Invalid HID device mode"));
fdd17dc68230654ee0796918863927fca10a9f0avboxsync
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync LogRelFlow(("usbHidConstruct/#%u: mode '%s'\n", iInstance, szMode));
4fa6d2a2ac7d62a1815bcb6d6565ae7cdf775cdbvboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.IPort.pfnPutEvent = usbHidMousePutEvent;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.IPort.pfnPutEventAbs = usbHidMousePutEventAbs;
c9a52d0e2159c4f4bd272a727406e47562ae82b4vboxsync pThis->Lun0.IPort.pfnPutEventMultiTouch = usbHidMousePutEventMultiTouch;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Attach the mouse driver.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Mouse Port");
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync if (RT_FAILURE(rc))
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach mouse driver"));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIMOUSECONNECTOR);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync if (!pThis->Lun0.pDrv)
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query mouse interface"));
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = CFGMR3QueryU8Def(pCfg, "CoordShift", &pThis->u8CoordShift, 1);
6cd65034f702d9b4122249011835e9639a7bc660vboxsync if (RT_FAILURE(rc))
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query shift factor"));
6cd65034f702d9b4122249011835e9639a7bc660vboxsync
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 */
ad48e47654d22f79b025dc4b21cb162cb123801avboxsync ~0U,
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,
1256c6853363727c70b1b5075e5a747510858b94vboxsync /* pfnUsbGetDescriptorCache */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbGetDescriptorCache,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetConfiguration */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbSetConfiguration,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbSetInterface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbSetInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUsbClearHaltedEndpoint */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUsbClearHaltedEndpoint,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbNew */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL/*usbHidUrbNew*/,
1ab072338283b0c700d1ef4958511296a4d0ca41vboxsync /* pfnUrbQueue */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidQueue,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbCancel */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUrbCancel,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnUrbReap */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync usbHidUrbReap,
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync /* pfnWakeup */
d0e467f88aeb4288b409908dbe1b96d07c7133b2vboxsync usbHidWakeup,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32TheEnd */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_USBREG_VERSION
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};