VirtualBox

Changeset 95271 in vbox


Ignore:
Timestamp:
Jun 14, 2022 9:52:49 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151852
Message:

Touchpad: First part of touchpad support, PDM interface and device emulation (see bugref:9891).

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmifs.h

    r93115 r95271  
    330330                                              uint32_t fButtons));
    331331    /**
    332      * Puts a multi-touch event.
     332     * Puts a multi-touch absolute (touchscreen) event.
    333333     *
    334334     * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
     
    350350     *                              time between event is important.
    351351     */
    352     DECLR3CALLBACKMEMBER(int, pfnPutEventMultiTouch,(PPDMIMOUSEPORT pInterface,
    353                                                      uint8_t cContacts,
    354                                                      const uint64_t *pau64Contacts,
    355                                                      uint32_t u32ScanTime));
     352    DECLR3CALLBACKMEMBER(int, pfnPutEventTouchScreen,(PPDMIMOUSEPORT pInterface,
     353                                                      uint8_t cContacts,
     354                                                      const uint64_t *pau64Contacts,
     355                                                      uint32_t u32ScanTime));
     356
     357    /**
     358     * Puts a multi-touch relative (touchpad) event.
     359     *
     360     * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
     361     *          event now and want it to be repeated at a later point.
     362     *
     363     * @param   pInterface          Pointer to this interface structure.
     364     * @param   cContacts           How many touch contacts in this event.
     365     * @param   pau64Contacts       Pointer to array of packed contact information.
     366     *                              Each 64bit element contains:
     367     *                              Bits 0..15:  Normalized X coordinate (range: 0 - 0xffff).
     368     *                              Bits 16..31: Normalized Y coordinate (range: 0 - 0xffff).
     369     *                              Bits 32..39: contact identifier.
     370     *                              Bit 40:      "in contact" flag, which indicates that
     371     *                                           there is a contact with the touch surface.
     372     *                              All other bits are reserved for future use and must be set to 0.
     373     * @param   u32ScanTime         Timestamp of this event in milliseconds. Only relative
     374     *                              time between event is important.
     375     */
     376
     377    DECLR3CALLBACKMEMBER(int, pfnPutEventTouchPad,(PPDMIMOUSEPORT pInterface,
     378                                                   uint8_t cContacts,
     379                                                   const uint64_t *pau64Contacts,
     380                                                   uint32_t u32ScanTime));
    356381} PDMIMOUSEPORT;
    357382/** PDMIMOUSEPORT interface ID. */
    358 #define PDMIMOUSEPORT_IID                       "359364f0-9fa3-4490-a6b4-7ed771901c93"
     383#define PDMIMOUSEPORT_IID                       "d2bb54b7-d877-441b-9d25-d2d3329465c2"
    359384
    360385/** Mouse button defines for PDMIMOUSEPORT::pfnPutEvent.
     
    383408     * @param   fRelative       Whether relative mode is currently supported.
    384409     * @param   fAbsolute       Whether absolute mode is currently supported.
    385      * @param   fMultiTouch     Whether multi-touch mode is currently supported.
    386      */
    387     DECLR3CALLBACKMEMBER(void, pfnReportModes,(PPDMIMOUSECONNECTOR pInterface, bool fRelative, bool fAbsolute, bool fMultiTouch));
     410     * @param   fMTAbsolute     Whether absolute multi-touch mode is currently supported.
     411     * @param   fMTRelative     Whether relative multi-touch mode is currently supported.
     412     */
     413    DECLR3CALLBACKMEMBER(void, pfnReportModes,(PPDMIMOUSECONNECTOR pInterface, bool fRelative, bool fAbsolute, bool fMTAbsolute, bool fMTRelative));
    388414
    389415    /**
  • trunk/src/VBox/Devices/Input/DevPS2M.cpp

    r93115 r95271  
    213213    PPDMIMOUSECONNECTOR pDrv = pThisCC->Mouse.pDrv;
    214214    if (pDrv)
    215         pDrv->pfnReportModes(pDrv, fEnabled, false, false);
     215        pDrv->pfnReportModes(pDrv, fEnabled, false, false, false);
    216216}
    217217
     
    895895
    896896/**
    897  * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMultiTouch}
    898  */
    899 static DECLCALLBACK(int) ps2mR3MousePort_PutEventMT(PPDMIMOUSEPORT pInterface, uint8_t cContacts,
    900                                                     const uint64_t *pau64Contacts, uint32_t u32ScanTime)
     897 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchScreen}
     898 */
     899static DECLCALLBACK(int) ps2mR3MousePort_PutEventMTAbs(PPDMIMOUSEPORT pInterface, uint8_t cContacts,
     900                                                       const uint64_t *pau64Contacts, uint32_t u32ScanTime)
     901{
     902    AssertFailedReturn(VERR_NOT_SUPPORTED);
     903    NOREF(pInterface); NOREF(cContacts); NOREF(pau64Contacts); NOREF(u32ScanTime);
     904}
     905
     906/**
     907 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchPad}
     908 */
     909static DECLCALLBACK(int) ps2mR3MousePort_PutEventMTRel(PPDMIMOUSEPORT pInterface, uint8_t cContacts,
     910                                                       const uint64_t *pau64Contacts, uint32_t u32ScanTime)
    901911{
    902912    AssertFailedReturn(VERR_NOT_SUPPORTED);
     
    10721082     * Initialize the state.
    10731083     */
    1074     pThisCC->pDevIns                           = pDevIns;
    1075     pThisCC->Mouse.IBase.pfnQueryInterface     = ps2mR3QueryInterface;
    1076     pThisCC->Mouse.IPort.pfnPutEvent           = ps2mR3MousePort_PutEvent;
    1077     pThisCC->Mouse.IPort.pfnPutEventAbs        = ps2mR3MousePort_PutEventAbs;
    1078     pThisCC->Mouse.IPort.pfnPutEventMultiTouch = ps2mR3MousePort_PutEventMT;
     1084    pThisCC->pDevIns                            = pDevIns;
     1085    pThisCC->Mouse.IBase.pfnQueryInterface      = ps2mR3QueryInterface;
     1086    pThisCC->Mouse.IPort.pfnPutEvent            = ps2mR3MousePort_PutEvent;
     1087    pThisCC->Mouse.IPort.pfnPutEventAbs         = ps2mR3MousePort_PutEventAbs;
     1088    pThisCC->Mouse.IPort.pfnPutEventTouchScreen = ps2mR3MousePort_PutEventMTAbs;
     1089    pThisCC->Mouse.IPort.pfnPutEventTouchPad    = ps2mR3MousePort_PutEventMTRel;
    10791090
    10801091    /*
  • trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp

    r93115 r95271  
    174174
    175175
    176 static DECLCALLBACK(int) drvMouseQueuePutEventMultiTouch(PPDMIMOUSEPORT pInterface,
     176static DECLCALLBACK(int) drvMouseQueuePutEventMTAbs(PPDMIMOUSEPORT pInterface,
    177177                                                         uint8_t cContacts,
    178178                                                         const uint64_t *pau64Contacts,
     
    180180{
    181181    PDRVMOUSEQUEUE pThis = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
    182     return pThis->pUpPort->pfnPutEventMultiTouch(pThis->pUpPort, cContacts, pau64Contacts, u32ScanTime);
     182    return pThis->pUpPort->pfnPutEventTouchScreen(pThis->pUpPort, cContacts, pau64Contacts, u32ScanTime);
     183}
     184
     185static DECLCALLBACK(int) drvMouseQueuePutEventMTRel(PPDMIMOUSEPORT pInterface,
     186                                                         uint8_t cContacts,
     187                                                         const uint64_t *pau64Contacts,
     188                                                         uint32_t u32ScanTime)
     189{
     190    PDRVMOUSEQUEUE pThis = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface);
     191    return pThis->pUpPort->pfnPutEventTouchPad(pThis->pUpPort, cContacts, pau64Contacts, u32ScanTime);
    183192}
    184193
     
    195204 * @param   fRel        Is relative reporting supported?
    196205 * @param   fAbs        Is absolute reporting supported?
    197  * @param   fMT         Is multi-touch reporting supported?
    198  */
    199 static DECLCALLBACK(void) drvMousePassThruReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMT)
     206 * @param   fMTAbs      Is absolute multi-touch reporting supported?
     207 * @param   fMTRel         Is relative multi-touch reporting supported?
     208 */
     209static DECLCALLBACK(void) drvMousePassThruReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMTAbs, bool fMTRel)
    200210{
    201211    PDRVMOUSEQUEUE pDrv = PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface);
    202     pDrv->pDownConnector->pfnReportModes(pDrv->pDownConnector, fRel, fAbs, fMT);
     212    pDrv->pDownConnector->pfnReportModes(pDrv->pDownConnector, fRel, fAbs, fMTAbs, fMTRel);
    203213}
    204214
     
    351361    pDrv->IPort.pfnPutEvent                 = drvMouseQueuePutEvent;
    352362    pDrv->IPort.pfnPutEventAbs              = drvMouseQueuePutEventAbs;
    353     pDrv->IPort.pfnPutEventMultiTouch       = drvMouseQueuePutEventMultiTouch;
     363    pDrv->IPort.pfnPutEventTouchScreen      = drvMouseQueuePutEventMTAbs;
     364    pDrv->IPort.pfnPutEventTouchPad         = drvMouseQueuePutEventMTRel;
    354365
    355366    /*
  • trunk/src/VBox/Devices/Input/UsbMouse.cpp

    r93115 r95271  
    4242#define USBHID_STR_ID_PRODUCT_T     3
    4343#define USBHID_STR_ID_PRODUCT_MT    4
     44#define USBHID_STR_ID_PRODUCT_TP    5
    4445/** @} */
    4546
     
    5556#define USBHID_PID_MOUSE            0x0020
    5657#define USBHID_PID_TABLET           0x0021
    57 #define USBHID_PID_MULTI_TOUCH      0x0022
     58#define USBHID_PID_MT_TOUCHSCREEN   0x0022
     59#define USBHID_PID_MT_TOUCHPAD      0x0023
    5860/** @} */
    5961
     
    9092    /** Absolute. */
    9193    USBHIDMODE_ABSOLUTE,
    92     /** Multi-touch. */
    93     USBHIDMODE_MULTI_TOUCH
     94    /** Multi-touch Touchscreen. */
     95    USBHIDMODE_MT_ABSOLUTE,
     96    /** Multi-touch Touchpad. */
     97    USBHIDMODE_MT_RELATIVE,
    9498} USBHIDMODE;
    9599
     
    150154
    151155#define MT_CONTACT_MAX_COUNT 10
     156#define TPAD_CONTACT_MAX_COUNT 5
    152157
    153158#define MT_CONTACT_F_IN_CONTACT 0x01
    154159#define MT_CONTACT_F_IN_RANGE   0x02
     160#define MT_CONTACT_F_CONFIDENCE 0x04
    155161
    156162#define MT_CONTACT_S_ACTIVE    0x01 /* Contact must be reported to the guest. */
     
    236242    bool fTouchReporting;
    237243    bool fTouchStateUpdated;
     244
     245    struct
     246    {
     247        MTCONTACT aCurrentContactState[TPAD_CONTACT_MAX_COUNT];
     248        MTCONTACT aReportingContactState[TPAD_CONTACT_MAX_COUNT];
     249        uint32_t u32LastTouchScanTime;
     250        bool fTouchReporting;
     251        bool fTouchStateUpdated;
     252    } tpad;
    238253} USBHID;
    239254/** Pointer to the USB HID instance data. */
     
    301316} USBHIDMT_REPORT_POINTER;
    302317
     318/**
     319 * The USB HID report structure for the touchpad device.
     320 */
     321typedef struct USBHIDTP_REPORT
     322{
     323    uint8_t     idReport;
     324    uint8_t     cContacts;
     325    struct
     326    {
     327        uint8_t     fContact;
     328        uint8_t     cContact;
     329        uint16_t    x;
     330        uint16_t    y;
     331    } aContacts[MT_CONTACTS_PER_REPORT];
     332    uint32_t    u32ScanTime;
     333    uint8_t     buttons;
     334} USBHIDTP_REPORT, *PUSBHIDTP_REPORT;
     335
    303336typedef union USBHIDALL_REPORT
    304337{
     
    307340    USBHIDMT_REPORT         mt;
    308341    USBHIDMT_REPORT_POINTER mp;
     342    USBHIDTP_REPORT         tp;
    309343} USBHIDALL_REPORT, *PUSBHIDALL_REPORT;
    310344
     
    321355    { USBHID_STR_ID_PRODUCT_T,      "USB Tablet"      },
    322356    { USBHID_STR_ID_PRODUCT_MT,     "USB Multi-Touch" },
     357    { USBHID_STR_ID_PRODUCT_TP,     "USB Touchpad"    },
    323358};
    324359
     
    363398
    364399static const VUSBDESCENDPOINTEX g_aUsbHidMTEndpointDescs[] =
     400{
     401    {
     402        {
     403            /* .bLength = */            sizeof(VUSBDESCENDPOINT),
     404            /* .bDescriptorType = */    VUSB_DT_ENDPOINT,
     405            /* .bEndpointAddress = */   0x81 /* ep=1, in */,
     406            /* .bmAttributes = */       3 /* interrupt */,
     407            /* .wMaxPacketSize = */     64,
     408            /* .bInterval = */          10,
     409        },
     410        /* .pvMore = */     NULL,
     411        /* .pvClass = */    NULL,
     412        /* .cbClass = */    0
     413    },
     414};
     415
     416static const VUSBDESCENDPOINTEX g_aUsbHidTPEndpointDescs[] =
    365417{
    366418    {
     
    738790};
    739791
     792
     793#define TOUCHPAD_REPORT_FINGER_USAGE \
     794/*     Usage Page (Digitizer)            */ 0x05, 0x0D, \
     795/*     Usage (Finger)                    */ 0x09, 0x22, \
     796/*     Collection (Logical)              */ 0xA1, 0x02, \
     797/*         Usage (Tip Switch)            */ 0x09, 0x42, \
     798/*         Logical Minimum (0)           */ 0x15, 0x00, \
     799/*         Logical Maximum (1)           */ 0x25, 0x01, \
     800/*         Report Size (1)               */ 0x75, 0x01, \
     801/*         Report Count (1)              */ 0x95, 0x01, \
     802/*         Input (Var)                   */ 0x81, 0x02, \
     803                                                        \
     804/*         Note: In Range not required   */             \
     805/*         Report Count (1)              */ 0x95, 0x01, \
     806/*         Input (Cnst,Var)              */ 0x81, 0x03, \
     807                                                        \
     808/*         Usage (Confidence)            */ 0x09, 0x47, \
     809/*         Logical Minimum (0)           */ 0x15, 0x00, \
     810/*         Logical Maximum (1)           */ 0x25, 0x01, \
     811/*         Report Size (1)               */ 0x75, 0x01, \
     812/*         Report Count (1)              */ 0x95, 0x01, \
     813/*         Input (Var)                   */ 0x81, 0x02, \
     814                                                        \
     815/*         Report Count (5)              */ 0x95, 0x05, \
     816/*         Input (Cnst,Var)              */ 0x81, 0x03, \
     817                                                        \
     818/*         Report Size (8)               */ 0x75, 0x08, \
     819/*         Usage (Contact identifier)    */ 0x09, 0x51, \
     820/*         Report Count (1)              */ 0x95, 0x01, \
     821/*         Logical Minimum (0)           */ 0x15, 0x00, \
     822/*         Logical Maximum (32)          */ 0x25, 0x20, \
     823/*         Input (Var)                   */ 0x81, 0x02, \
     824                                                        \
     825/*         Usage Page (Generic Desktop)  */ 0x05, 0x01, \
     826/*         Logical Minimum (0)           */ 0x15, 0x00, \
     827/*         Logical Maximum (65535)       */ 0x27, 0xFF, 0xFF, 0x00, 0x00, \
     828/*         Report Size (16)              */ 0x75, 0x10, \
     829/*         Unit Exponent (-2)            */ 0x55, 0x0e, \
     830/*         Unit (Eng Lin: Length (in))   */ 0x65, 0x13, \
     831/*         Usage (X)                     */ 0x09, 0x30, \
     832/*         Physical Minimum (0)          */ 0x35, 0x00, \
     833/*         Physical Maximum (461)        */ 0x46, 0xcd, 0x01, \
     834/*         Report Count (1)              */ 0x95, 0x01, \
     835/*         Input (Var)                   */ 0x81, 0x02, \
     836/*         Usage (Y)                     */ 0x09, 0x31, \
     837/*         Physical Maximum (346)        */ 0x46, 0x5a, 0x01, \
     838/*         Input (Var)                   */ 0x81, 0x02, \
     839/*     End Collection                    */ 0xC0,
     840
     841static const uint8_t g_UsbHidTPReportDesc[] =
     842    {
     843/* Usage Page (Digitizer)                */ 0x05, 0x0D,
     844/* Usage (Touch Pad)                     */ 0x09, 0x05,
     845/* Collection (Application)              */ 0xA1, 0x01,
     846/*     Report ID                         */ 0x85, REPORTID_TOUCH_EVENT,
     847/*     Usage Page (Digitizer)            */ 0x05, 0x0D,
     848/*     Usage (Contact count)             */ 0x09, 0x54,
     849/*     Report Size (8)                   */ 0x75, 0x08,
     850/*     Logical Minimum (0)               */ 0x15, 0x00,
     851/*     Logical Maximum (12)              */ 0x25, 0x0C,
     852/*     Report Count (1)                  */ 0x95, 0x01,
     853/*     Input (Var)                       */ 0x81, 0x02,
     854
     855/* MT_CONTACTS_PER_REPORT structs u8TipSwitch, u8ContactIdentifier, u16X, u16Y */
     856TOUCHPAD_REPORT_FINGER_USAGE
     857TOUCHPAD_REPORT_FINGER_USAGE
     858TOUCHPAD_REPORT_FINGER_USAGE
     859TOUCHPAD_REPORT_FINGER_USAGE
     860TOUCHPAD_REPORT_FINGER_USAGE
     861
     862/* Note: "Scan time" usage is required for all touch devices (in 100microseconds units). */
     863/*     Usage Page (Digitizer)            */ 0x05, 0x0D,
     864/*     Logical Minimum (0)               */ 0x17, 0x00, 0x00, 0x00, 0x00,
     865/*     Logical Maximum (2147483647)      */ 0x27, 0xFF, 0xFF, 0xFF, 0x7F,
     866/*     Report Size (32)                  */ 0x75, 0x20,
     867/*     Report Count (1)                  */ 0x95, 0x01,
     868/*     Unit Exponent (0)                 */ 0x55, 0x00,
     869/*     Unit (None)                       */ 0x65, 0x00,
     870/*     Usage (Scan time)                 */ 0x09, 0x56,
     871/*     Input (Var)                       */ 0x81, 0x02,
     872
     873/* Note: Button required by Windows 10 Precision Touchpad */
     874/*     Usage Page (Button)               */ 0x05, 0x09,
     875/*     Usage (Button 1)                  */ 0x09, 0x01,
     876/*     Logical Maximum (1)               */ 0x25, 0x01,
     877/*     Report Size (1)                   */ 0x75, 0x01,
     878/*     Report Count (1)                  */ 0x95, 0x01,
     879/*     Input (Var)                       */ 0x81, 0x02,
     880/*     Report Count (7)                  */ 0x95, 0x07,
     881/*     Input (Cnst,Var)                  */ 0x81, 0x03,
     882
     883/*     Usage Page (Digitizer)            */ 0x05, 0x0D,
     884/*     Report ID                         */ 0x85, REPORTID_TOUCH_MAX_COUNT,
     885/*     Usage (Contact count maximum)     */ 0x09, 0x55,
     886/*     Usage (Device identifier)         */ 0x09, 0x53,
     887/*     Report Size (8)                   */ 0x75, 0x08,
     888/*     Report Count (2)                  */ 0x95, 0x02,
     889/*     Logical Maximum (255)             */ 0x26, 0xFF, 0x00,
     890/*     Feature (Var)                     */ 0xB1, 0x02,
     891
     892/*     Usage Page (Vendor-Defined 1)     */ 0x06, 0x00, 0xFF,
     893/*     Usage (QA blob)                   */ 0x09, 0xC5,
     894/*     Report ID                         */ 0x85, REPORTID_TOUCH_QABLOB,
     895/*     Logical Minimum (0)               */ 0x15, 0x00,
     896/*     Logical Maximum (255)             */ 0x26, 0xFF, 0x00,
     897/*     Report Size (8)                   */ 0x75, 0x08,
     898/*     Report Count (256)                */ 0x96, 0x00, 0x01,
     899/*     Feature (Var)                     */ 0xB1, 0x02,
     900/* End Collection                        */ 0xC0,
     901
     902/* Note: the pointer report is required by specification:
     903 * "The report descriptor for a multiple input device must include at least
     904 * one top-level collection for the primary device and a separate top-level
     905 * collection for the mouse."
     906 */
     907/* Usage Page (Generic Desktop)          */ 0x05, 0x01,
     908/* Usage (Pointer)                       */ 0x09, 0x01,
     909/* Collection (Application)              */ 0xA1, 0x01,
     910/*     Report ID                         */ 0x85, REPORTID_TOUCH_POINTER,
     911/*     Usage (Pointer)                   */ 0x09, 0x01,
     912/*     Collection (Logical)              */ 0xA1, 0x02,
     913/*         Usage Page (Button)           */ 0x05, 0x09,
     914/*         Usage Minimum (Button 1)      */ 0x19, 0x01,
     915/*         Usage Maximum (Button 2)      */ 0x29, 0x02,
     916/*         Logical Minimum (0)           */ 0x15, 0x00,
     917/*         Logical Maximum (1)           */ 0x25, 0x01,
     918/*         Report Count (2)              */ 0x95, 0x02,
     919/*         Report Size (1)               */ 0x75, 0x01,
     920/*         Input (Var)                   */ 0x81, 0x02,
     921/*         Report Count (1)              */ 0x95, 0x01,
     922/*         Report Size (6)               */ 0x75, 0x06,
     923/*         Input (Cnst,Ary,Abs)          */ 0x81, 0x01,
     924/*         Usage Page (Generic Desktop)  */ 0x05, 0x01,
     925/*         Usage (X)                     */ 0x09, 0x30,
     926/*         Usage (Y)                     */ 0x09, 0x31,
     927/*         Logical Minimum (0)           */ 0x16, 0x00, 0x00,
     928/*         Logical Maximum (32K)         */ 0x26, 0xFF, 0x7F,
     929/*         Physical Minimum (0)          */ 0x36, 0x00, 0x00,
     930/*         Physical Maximum (32K)        */ 0x46, 0xFF, 0x7F,
     931/*         Unit (None)                   */ 0x66, 0x00, 0x00,
     932/*         Report Size (16)              */ 0x75, 0x10,
     933/*         Report Count (2)              */ 0x95, 0x02,
     934/*         Input (Var)                   */ 0x81, 0x02,
     935/*     End Collection                    */ 0xC0,
     936/* End Collection                        */ 0xC0,
     937
     938/* Usage Page (Digitizer)                */ 0x05, 0x0D,
     939/* Usage (Device configuration)          */ 0x09, 0x0E,
     940/* Collection (Application)              */ 0xA1, 0x01,
     941/*     Report ID                         */ 0x85, REPORTID_TOUCH_DEVCONFIG,
     942/*     Usage (Device settings)           */ 0x09, 0x23,
     943/*     Collection (Logical)              */ 0xA1, 0x02,
     944/*         Usage (Device mode)           */ 0x09, 0x52,
     945/*         Usage (Device identifier)     */ 0x09, 0x53,
     946/*         Logical Minimum (0)           */ 0x15, 0x00,
     947/*         Logical Maximum (10)          */ 0x25, 0x0A,
     948/*         Report Size (8)               */ 0x75, 0x08,
     949/*         Report Count (2)              */ 0x95, 0x02,
     950/*         Feature (Var)                 */ 0xB1, 0x02,
     951/*     End Collection                    */ 0xC0,
     952/* End Collection                        */ 0xC0
     953    };
     954
     955
    740956/** @todo Do these really have to all be duplicated three times? */
    741957/* Additional HID class interface descriptor. */
     
    774990    /* .wDescriptorLength = */      (uint8_t)(sizeof(g_UsbHidMTReportDesc) & 0xFF),
    775991                                    (uint8_t)((sizeof(g_UsbHidMTReportDesc) >> 8) & 0xFF)
     992};
     993
     994/* Additional HID class interface descriptor. */
     995static const uint8_t g_UsbHidTPIfHidDesc[] =
     996{
     997    /* .bLength = */                0x09,
     998    /* .bDescriptorType = */        0x21,       /* HID */
     999    /* .bcdHID = */                 0x10, 0x02, /* 2.1 */
     1000    /* .bCountryCode = */           0,
     1001    /* .bNumDescriptors = */        1,
     1002    /* .bDescriptorType = */        0x22,       /* Report */
     1003    /* .wDescriptorLength = */      (uint8_t)(sizeof(g_UsbHidTPReportDesc) & 0xFF),
     1004                                    (uint8_t)((sizeof(g_UsbHidTPReportDesc) >> 8) & 0xFF)
    7761005};
    7771006
     
    8391068};
    8401069
     1070static const VUSBDESCINTERFACEEX g_UsbHidTPInterfaceDesc =
     1071{
     1072    {
     1073        /* .bLength = */                sizeof(VUSBDESCINTERFACE),
     1074        /* .bDescriptorType = */        VUSB_DT_INTERFACE,
     1075        /* .bInterfaceNumber = */       0,
     1076        /* .bAlternateSetting = */      0,
     1077        /* .bNumEndpoints = */          1,
     1078        /* .bInterfaceClass = */        3 /* HID */,
     1079        /* .bInterfaceSubClass = */     0 /* No subclass - no boot interface. */,
     1080        /* .bInterfaceProtocol = */     0 /* No protocol - no boot interface. */,
     1081        /* .iInterface = */             0
     1082    },
     1083    /* .pvMore = */     NULL,
     1084    /* .pvClass = */    &g_UsbHidTPIfHidDesc,
     1085    /* .cbClass = */    sizeof(g_UsbHidTPIfHidDesc),
     1086    &g_aUsbHidTPEndpointDescs[0],
     1087    /* .pIAD = */ NULL,
     1088    /* .cbIAD = */ 0
     1089};
     1090
    8411091static const VUSBINTERFACE g_aUsbHidMInterfaces[] =
    8421092{
     
    8521102{
    8531103    { &g_UsbHidMTInterfaceDesc, /* .cSettings = */ 1 },
     1104};
     1105
     1106static const VUSBINTERFACE g_aUsbHidTPInterfaces[] =
     1107{
     1108    { &g_UsbHidTPInterfaceDesc, /* .cSettings = */ 1 },
    8541109};
    8551110
     
    9111166};
    9121167
     1168static const VUSBDESCCONFIGEX g_UsbHidTPConfigDesc =
     1169{
     1170    {
     1171        /* .bLength = */            sizeof(VUSBDESCCONFIG),
     1172        /* .bDescriptorType = */    VUSB_DT_CONFIG,
     1173        /* .wTotalLength = */       0 /* recalculated on read */,
     1174        /* .bNumInterfaces = */     RT_ELEMENTS(g_aUsbHidTPInterfaces),
     1175        /* .bConfigurationValue =*/ 1,
     1176        /* .iConfiguration = */     0,
     1177        /* .bmAttributes = */       RT_BIT(7),
     1178        /* .MaxPower = */           50 /* 100mA */
     1179    },
     1180    NULL,                           /* pvMore */
     1181    NULL,                           /* pvClass */
     1182    0,                              /* cbClass */
     1183    &g_aUsbHidTPInterfaces[0],
     1184    NULL                            /* pvOriginal */
     1185};
     1186
    9131187static const VUSBDESCDEVICE g_UsbHidMDeviceDesc =
    9141188{
     
    9571231    /* .bMaxPacketSize0 = */        8,
    9581232    /* .idVendor = */               VBOX_USB_VENDOR,
    959     /* .idProduct = */              USBHID_PID_MULTI_TOUCH,
     1233    /* .idProduct = */              USBHID_PID_MT_TOUCHSCREEN,
    9601234    /* .bcdDevice = */              0x0100, /* 1.0 */
    9611235    /* .iManufacturer = */          USBHID_STR_ID_MANUFACTURER,
     
    9641238    /* .bNumConfigurations = */     1
    9651239};
     1240
     1241static const VUSBDESCDEVICE g_UsbHidTPDeviceDesc =
     1242{
     1243    /* .bLength = */                sizeof(g_UsbHidTPDeviceDesc),
     1244    /* .bDescriptorType = */        VUSB_DT_DEVICE,
     1245    /* .bcdUsb = */                 0x110,  /* 1.1 */
     1246    /* .bDeviceClass = */           0 /* Class specified in the interface desc. */,
     1247    /* .bDeviceSubClass = */        0 /* Subclass specified in the interface desc. */,
     1248    /* .bDeviceProtocol = */        0 /* Protocol specified in the interface desc. */,
     1249    /* .bMaxPacketSize0 = */        8,
     1250    /* .idVendor = */               VBOX_USB_VENDOR,
     1251    /* .idProduct = */              USBHID_PID_MT_TOUCHPAD,
     1252    /* .bcdDevice = */              0x0100, /* 1.0 */
     1253    /* .iManufacturer = */          USBHID_STR_ID_MANUFACTURER,
     1254    /* .iProduct = */               USBHID_STR_ID_PRODUCT_TP,
     1255    /* .iSerialNumber = */          0,
     1256    /* .bNumConfigurations = */     1
     1257};
     1258
    9661259
    9671260static const PDMUSBDESCCACHE g_UsbHidMDescCache =
     
    9891282    /* .pDevice = */                &g_UsbHidMTDeviceDesc,
    9901283    /* .paConfigs = */              &g_UsbHidMTConfigDesc,
     1284    /* .paLanguages = */            g_aUsbHidLanguages,
     1285    /* .cLanguages = */             RT_ELEMENTS(g_aUsbHidLanguages),
     1286    /* .fUseCachedDescriptors = */  true,
     1287    /* .fUseCachedStringsDescriptors = */ true
     1288};
     1289
     1290static const PDMUSBDESCCACHE g_UsbHidTPDescCache =
     1291{
     1292    /* .pDevice = */                &g_UsbHidTPDeviceDesc,
     1293    /* .paConfigs = */              &g_UsbHidTPConfigDesc,
    9911294    /* .paLanguages = */            g_aUsbHidLanguages,
    9921295    /* .cLanguages = */             RT_ELEMENTS(g_aUsbHidLanguages),
     
    12161519    pThis->fHasPendingChanges = false;
    12171520    pThis->fTouchStateUpdated = false;
     1521    pThis->tpad.fTouchStateUpdated = false;
    12181522
    12191523    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
     
    14441748}
    14451749
     1750
     1751static int usbHidSendTouchPadReport(PUSBHID pThis, PVUSBURB pUrb)
     1752{
     1753    uint8_t i;
     1754    MTCONTACT *pRepContact;
     1755    MTCONTACT *pCurContact;
     1756
     1757    /* Number of contacts to be reported. In hybrid mode the first report contains
     1758     * total number of contacts and subsequent reports contain 0.
     1759     */
     1760    uint8_t cContacts = 0;
     1761
     1762    Assert(pThis->fHasPendingChanges);
     1763
     1764    if (!pThis->tpad.fTouchReporting)
     1765    {
     1766        pThis->tpad.fTouchReporting = true;
     1767        pThis->tpad.fTouchStateUpdated = false;
     1768
     1769        /* Update the reporting state with the new current state.
     1770         * Also mark all active contacts in reporting state as dirty,
     1771         * that is they must be reported to the guest.
     1772         */
     1773        for (i = 0; i < TPAD_CONTACT_MAX_COUNT; i++)
     1774        {
     1775            pRepContact = &pThis->tpad.aReportingContactState[i];
     1776            pCurContact = &pThis->tpad.aCurrentContactState[i];
     1777
     1778            if (pCurContact->status & MT_CONTACT_S_ACTIVE)
     1779            {
     1780                if (pCurContact->status & MT_CONTACT_S_REUSED)
     1781                {
     1782                    pCurContact->status &= ~MT_CONTACT_S_REUSED;
     1783
     1784                    /* Keep x,y. Will report lost contact at this point. */
     1785                    pRepContact->id     = pCurContact->oldId;
     1786                    pRepContact->flags  = 0;
     1787                    pRepContact->status = MT_CONTACT_S_REUSED;
     1788                }
     1789                else if (pThis->tpad.aCurrentContactState[i].status & MT_CONTACT_S_CANCELLED)
     1790                {
     1791                    pCurContact->status &= ~(MT_CONTACT_S_CANCELLED | MT_CONTACT_S_ACTIVE);
     1792
     1793                    /* Keep x,y. Will report lost contact at this point. */
     1794                    pRepContact->id     = pCurContact->id;
     1795                    pRepContact->flags  = 0;
     1796                    pRepContact->status = 0;
     1797                }
     1798                else
     1799                {
     1800                    if (pCurContact->flags == 0)
     1801                    {
     1802                        pCurContact->status &= ~MT_CONTACT_S_ACTIVE; /* Contact disapeared. */
     1803                    }
     1804
     1805                    pRepContact->x      = pCurContact->x;
     1806                    pRepContact->y      = pCurContact->y;
     1807                    pRepContact->id     = pCurContact->id;
     1808                    pRepContact->flags  = pCurContact->flags;
     1809                    pRepContact->status = 0;
     1810                }
     1811
     1812                cContacts++;
     1813
     1814                pRepContact->status |= MT_CONTACT_S_DIRTY;
     1815            }
     1816            else
     1817            {
     1818                pRepContact->status = 0;
     1819            }
     1820        }
     1821    }
     1822
     1823    /* Report current state. */
     1824    USBHIDTP_REPORT r;
     1825    USBHIDTP_REPORT *p = &r;
     1826    RT_ZERO(*p);
     1827
     1828    p->idReport = REPORTID_TOUCH_EVENT;
     1829    p->cContacts = cContacts;
     1830    p->buttons = 0;
     1831
     1832    uint8_t iReportedContact;
     1833    for (iReportedContact = 0; iReportedContact < MT_CONTACTS_PER_REPORT; iReportedContact++)
     1834    {
     1835        /* Find the next not reported contact. */
     1836        pRepContact = usbHidFindMTContact(pThis->tpad.aReportingContactState, RT_ELEMENTS(pThis->tpad.aReportingContactState),
     1837                                          MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY);
     1838
     1839        if (!pRepContact)
     1840        {
     1841            LogRel3(("usbHid: no more touch contacts to report\n"));
     1842            break;
     1843        }
     1844
     1845        if (pRepContact->status & MT_CONTACT_S_REUSED)
     1846        {
     1847            /* Do not clear DIRTY flag for contacts which were reused.
     1848             * Because two reports must be generated:
     1849             * one for old contact off, and the second for new contact on.
     1850             */
     1851            pRepContact->status &= ~MT_CONTACT_S_REUSED;
     1852        }
     1853        else
     1854        {
     1855            pRepContact->status &= ~MT_CONTACT_S_DIRTY;
     1856        }
     1857
     1858        /* TODO: Parse touch confidence in Qt frontend */
     1859        p->aContacts[iReportedContact].fContact = pRepContact->flags | MT_CONTACT_F_CONFIDENCE;
     1860        p->aContacts[iReportedContact].cContact = pRepContact->id;
     1861        p->aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift;
     1862        p->aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift;
     1863    }
     1864
     1865    p->u32ScanTime = pThis->tpad.u32LastTouchScanTime * 10;
     1866
     1867    Assert(iReportedContact > 0);
     1868
     1869    /* Reset TouchReporting if all contacts reported. */
     1870    pRepContact = usbHidFindMTContact(pThis->tpad.aReportingContactState, RT_ELEMENTS(pThis->tpad.aReportingContactState),
     1871                                      MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY);
     1872
     1873    if (!pRepContact)
     1874    {
     1875        LogRel3(("usbHid: all touch contacts reported\n"));
     1876        pThis->tpad.fTouchReporting = false;
     1877        pThis->fHasPendingChanges = pThis->tpad.fTouchStateUpdated;
     1878    }
     1879    else
     1880    {
     1881        pThis->fHasPendingChanges = true;
     1882    }
     1883
     1884    LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", sizeof(USBHIDTP_REPORT), p));
     1885    return usbHidCompleteOk(pThis, pUrb, p, sizeof(USBHIDTP_REPORT));
     1886}
     1887
    14461888/**
    14471889 * Sends a state report to the host if there is a pending URB.
     
    14511893    PVUSBURB    pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
    14521894
    1453     if (pThis->enmMode == USBHIDMODE_MULTI_TOUCH)
     1895    if (pThis->enmMode == USBHIDMODE_MT_ABSOLUTE)
    14541896    {
    14551897        /* This device uses a different reporting method and fHasPendingChanges maintenance. */
    14561898        if (pUrb)
    14571899            return usbHidSendMultiTouchReport(pThis, pUrb);
     1900        return VINF_SUCCESS;
     1901    }
     1902    if (pThis->enmMode == USBHIDMODE_MT_RELATIVE)
     1903    {
     1904        /* This device uses a different reporting method and fHasPendingChanges maintenance. */
     1905        if (pUrb)
     1906            return usbHidSendTouchPadReport(pThis, pUrb);
    14581907        return VINF_SUCCESS;
    14591908    }
     
    15451994
    15461995/**
    1547  * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMultiTouch}
    1548  */
    1549 static DECLCALLBACK(int) usbHidMousePutEventMultiTouch(PPDMIMOUSEPORT pInterface,
     1996 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchScreen}
     1997 */
     1998static DECLCALLBACK(int) usbHidMousePutEventTouchScreen(PPDMIMOUSEPORT pInterface,
    15501999                                                       uint8_t cContacts,
    15512000                                                       const uint64_t *pau64Contacts,
     
    15822031    RTCritSectEnter(&pThis->CritSect);
    15832032
    1584     Assert(pThis->enmMode == USBHIDMODE_MULTI_TOUCH);
     2033    Assert(pThis->enmMode == USBHIDMODE_MT_ABSOLUTE);
    15852034
    15862035    /* Maintain a state of all current contacts.
     
    17062155
    17072156    pThis->fTouchStateUpdated = true;
     2157    pThis->fHasPendingChanges = true;
     2158
     2159    /* Send a report if possible. */
     2160    usbHidSendReport(pThis);
     2161
     2162    RTCritSectLeave(&pThis->CritSect);
     2163
     2164    RTMemTmpFree(paNewContacts);
     2165    return VINF_SUCCESS;
     2166}
     2167
     2168/**
     2169 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchPad}
     2170 */
     2171static DECLCALLBACK(int) usbHidMousePutEventTouchPad(PPDMIMOUSEPORT pInterface,
     2172                                                       uint8_t cContacts,
     2173                                                       const uint64_t *pau64Contacts,
     2174                                                       uint32_t u32ScanTime)
     2175{
     2176    uint8_t i;
     2177    uint8_t j;
     2178
     2179    /* Make a copy of new contacts */
     2180    MTCONTACT *paNewContacts = (MTCONTACT *)RTMemTmpAlloc(sizeof(MTCONTACT) * cContacts);
     2181    if (!paNewContacts)
     2182        return VERR_NO_MEMORY;
     2183
     2184    for (i = 0; i < cContacts; i++)
     2185    {
     2186        uint32_t u32Lo = RT_LO_U32(pau64Contacts[i]);
     2187        uint32_t u32Hi = RT_HI_U32(pau64Contacts[i]);
     2188        paNewContacts[i].x      = (uint16_t)u32Lo;
     2189        paNewContacts[i].y      = (uint16_t)(u32Lo >> 16);
     2190        paNewContacts[i].id     = RT_BYTE1(u32Hi);
     2191        paNewContacts[i].flags  = RT_BYTE2(u32Hi) & MT_CONTACT_F_IN_CONTACT;
     2192        paNewContacts[i].status = MT_CONTACT_S_DIRTY;
     2193        paNewContacts[i].oldId  = 0; /* Not used. */
     2194    }
     2195
     2196    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
     2197    MTCONTACT *pCurContact = NULL;
     2198    MTCONTACT *pNewContact = NULL;
     2199
     2200    RTCritSectEnter(&pThis->CritSect);
     2201
     2202    Assert(pThis->enmMode == USBHIDMODE_MT_RELATIVE);
     2203
     2204    /* Maintain a state of all current contacts.
     2205     * Intr URBs will be completed according to the state.
     2206     */
     2207
     2208    /* Mark all existing contacts as dirty. */
     2209    for (i = 0; i < RT_ELEMENTS(pThis->tpad.aCurrentContactState); i++)
     2210        pThis->tpad.aCurrentContactState[i].status |= MT_CONTACT_S_DIRTY;
     2211
     2212    /* Update existing contacts and mark new contacts. */
     2213    for (i = 0; i < cContacts; i++)
     2214    {
     2215        pNewContact = &paNewContacts[i];
     2216
     2217        /* Find existing contact with the same id. */
     2218        pCurContact = NULL;
     2219        for (j = 0; j < RT_ELEMENTS(pThis->tpad.aCurrentContactState); j++)
     2220        {
     2221            if (   (pThis->tpad.aCurrentContactState[j].status & MT_CONTACT_S_ACTIVE) != 0
     2222                && pThis->tpad.aCurrentContactState[j].id == pNewContact->id)
     2223            {
     2224                pCurContact = &pThis->tpad.aCurrentContactState[j];
     2225                break;
     2226            }
     2227        }
     2228
     2229        if (pCurContact)
     2230        {
     2231            pNewContact->status &= ~MT_CONTACT_S_DIRTY;
     2232
     2233            pCurContact->x = pNewContact->x;
     2234            pCurContact->y = pNewContact->y;
     2235            if (pCurContact->flags == 0) /* Contact disappeared already. */
     2236            {
     2237                if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0)
     2238                {
     2239                    pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */
     2240                    pCurContact->oldId = pCurContact->id;
     2241                }
     2242            }
     2243            pCurContact->flags = pNewContact->flags;
     2244            pCurContact->status &= ~MT_CONTACT_S_DIRTY;
     2245        }
     2246    }
     2247
     2248    /* Append new contacts (the dirty one in the paNewContacts). */
     2249    for (i = 0; i < cContacts; i++)
     2250    {
     2251        pNewContact = &paNewContacts[i];
     2252
     2253        if (pNewContact->status & MT_CONTACT_S_DIRTY)
     2254        {
     2255            /* It is a new contact, copy is to one of not ACTIVE or not updated existing contacts. */
     2256            pCurContact = usbHidFindMTContact(pThis->tpad.aCurrentContactState, RT_ELEMENTS(pThis->tpad.aCurrentContactState),
     2257                                              MT_CONTACT_S_ACTIVE, 0);
     2258
     2259            if (pCurContact)
     2260            {
     2261                *pCurContact = *pNewContact;
     2262                pCurContact->status = MT_CONTACT_S_ACTIVE; /* Reset status. */
     2263            }
     2264            else
     2265            {
     2266                /* Dirty existing contacts can be reused. */
     2267                pCurContact = usbHidFindMTContact(pThis->tpad.aCurrentContactState, RT_ELEMENTS(pThis->tpad.aCurrentContactState),
     2268                                                  MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY,
     2269                                                  MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY);
     2270
     2271                if (pCurContact)
     2272                {
     2273                    pCurContact->x = pNewContact->x;
     2274                    pCurContact->y = pNewContact->y;
     2275                    if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0)
     2276                    {
     2277                        pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */
     2278                        pCurContact->oldId = pCurContact->id;
     2279                    }
     2280                    pCurContact->flags = pNewContact->flags;
     2281                    pCurContact->status &= ~MT_CONTACT_S_DIRTY;
     2282                }
     2283                else
     2284                {
     2285                    LogRel3(("usbHid: dropped new contact: %d,%d id %d flags %RX8 status %RX8 oldId %d\n",
     2286                             pNewContact->x,
     2287                             pNewContact->y,
     2288                             pNewContact->id,
     2289                             pNewContact->flags,
     2290                             pNewContact->status,
     2291                             pNewContact->oldId
     2292                           ));
     2293                }
     2294            }
     2295        }
     2296    }
     2297
     2298    /* Mark still dirty existing contacts as cancelled, because a new set of contacts does not include them. */
     2299    for (i = 0; i < RT_ELEMENTS(pThis->tpad.aCurrentContactState); i++)
     2300    {
     2301        pCurContact = &pThis->tpad.aCurrentContactState[i];
     2302        if (pCurContact->status & MT_CONTACT_S_DIRTY)
     2303        {
     2304            pCurContact->status |= MT_CONTACT_S_CANCELLED;
     2305            pCurContact->status &= ~MT_CONTACT_S_DIRTY;
     2306        }
     2307    }
     2308
     2309    pThis->tpad.u32LastTouchScanTime = u32ScanTime;
     2310
     2311    LogRel3(("usbHid: scanTime (ms): %d\n", pThis->tpad.u32LastTouchScanTime));
     2312    for (i = 0; i < RT_ELEMENTS(pThis->tpad.aCurrentContactState); i++)
     2313    {
     2314        LogRel3(("usbHid: contact state[%d]: %d,%d id %d flags %RX8 status %RX8 oldId %d\n",
     2315                  i,
     2316                  pThis->tpad.aCurrentContactState[i].x,
     2317                  pThis->tpad.aCurrentContactState[i].y,
     2318                  pThis->tpad.aCurrentContactState[i].id,
     2319                  pThis->tpad.aCurrentContactState[i].flags,
     2320                  pThis->tpad.aCurrentContactState[i].status,
     2321                  pThis->tpad.aCurrentContactState[i].oldId
     2322                ));
     2323    }
     2324
     2325    pThis->tpad.fTouchStateUpdated = true;
    17082326    pThis->fHasPendingChanges = true;
    17092327
     
    18882506    PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
    18892507
    1890     if (pThis->enmMode != USBHIDMODE_MULTI_TOUCH)
     2508    if ((pThis->enmMode != USBHIDMODE_MT_ABSOLUTE) && (pThis->enmMode != USBHIDMODE_MT_RELATIVE))
    18912509    {
    18922510        LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
     
    19272545                else if (u8ReportType == 1 && u8ReportID == REPORTID_TOUCH_EVENT)
    19282546                {
    1929                     USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&abData;
    1930                     /* The actual state should be reported here. */
    1931                     RT_ZERO(*p);
    1932                     p->idReport = REPORTID_TOUCH_EVENT;
    1933                     cbData = sizeof(USBHIDMT_REPORT);
     2547                    switch (pThis->enmMode)
     2548                    {
     2549                        case USBHIDMODE_MT_ABSOLUTE:
     2550                        {
     2551                            USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&abData;
     2552                            /* The actual state should be reported here. */
     2553                            RT_ZERO(*p);
     2554                            p->idReport = REPORTID_TOUCH_EVENT;
     2555                            cbData = sizeof(USBHIDMT_REPORT);
     2556                            break;
     2557                        }
     2558                        case USBHIDMODE_MT_RELATIVE:
     2559                        {
     2560                            USBHIDTP_REPORT *p = (USBHIDTP_REPORT *)&abData;
     2561                            /* The actual state should be reported here. */
     2562                            RT_ZERO(*p);
     2563                            p->idReport = REPORTID_TOUCH_EVENT;
     2564                            cbData = sizeof(USBHIDTP_REPORT);
     2565                            break;
     2566                        }
     2567                        default:
     2568                            AssertMsgFailed(("Invalid HID mode %d\n", pThis->enmMode));
     2569                            break;
     2570                    }
    19342571                }
    19352572                else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_MAX_COUNT)
    19362573                {
     2574                    uint8_t cMaxContacts = 0;
     2575                    switch (pThis->enmMode)
     2576                    {
     2577                        case USBHIDMODE_MT_ABSOLUTE:
     2578                            cMaxContacts = MT_CONTACT_MAX_COUNT;
     2579                            break;
     2580                        case USBHIDMODE_MT_RELATIVE:
     2581                            cMaxContacts = TPAD_CONTACT_MAX_COUNT;
     2582                            break;
     2583                        default:
     2584                            AssertMsgFailed(("Invalid HID mode %d\n", pThis->enmMode));
     2585                            break;
     2586                    }
    19372587                    abData[0] = REPORTID_TOUCH_MAX_COUNT;
    1938                     abData[1] = MT_CONTACT_MAX_COUNT;   /* Contact count maximum. */
     2588                    abData[1] = cMaxContacts;           /* Contact count maximum. */
    19392589                    abData[2] = 0;                      /* Device identifier */
    19402590                    cbData = 3;
     
    20352685                                        pDesc = (const uint8_t *)&g_UsbHidMIfHidDesc;
    20362686                                        break;
    2037                                     case USBHIDMODE_MULTI_TOUCH:
     2687                                    case USBHIDMODE_MT_ABSOLUTE:
    20382688                                        cbDesc = sizeof(g_UsbHidMTIfHidDesc);
    20392689                                        pDesc = (const uint8_t *)&g_UsbHidMTIfHidDesc;
     2690                                        break;
     2691                                    case USBHIDMODE_MT_RELATIVE:
     2692                                        cbDesc = sizeof(g_UsbHidTPIfHidDesc);
     2693                                        pDesc = (const uint8_t *)&g_UsbHidTPIfHidDesc;
    20402694                                        break;
    20412695                                    default:
     
    20642718                                        pDesc = (const uint8_t *)&g_UsbHidMReportDesc;
    20652719                                        break;
    2066                                     case USBHIDMODE_MULTI_TOUCH:
     2720                                    case USBHIDMODE_MT_ABSOLUTE:
    20672721                                        cbDesc = sizeof(g_UsbHidMTReportDesc);
    20682722                                        pDesc = (const uint8_t *)&g_UsbHidMTReportDesc;
     2723                                        break;
     2724                                    case USBHIDMODE_MT_RELATIVE:
     2725                                        cbDesc = sizeof(g_UsbHidTPReportDesc);
     2726                                        pDesc = (const uint8_t *)&g_UsbHidTPReportDesc;
    20692727                                        break;
    20702728                                    default:
     
    22792937                                     pThis->enmMode == USBHIDMODE_RELATIVE,
    22802938                                     pThis->enmMode == USBHIDMODE_ABSOLUTE,
    2281                                      pThis->enmMode == USBHIDMODE_MULTI_TOUCH);
     2939                                     pThis->enmMode == USBHIDMODE_MT_ABSOLUTE,
     2940                                     pThis->enmMode == USBHIDMODE_MT_RELATIVE);
    22822941
    22832942    RTCritSectLeave(&pThis->CritSect);
     
    22992958        case USBHIDMODE_RELATIVE:
    23002959            return &g_UsbHidMDescCache;
    2301         case USBHIDMODE_MULTI_TOUCH:
     2960        case USBHIDMODE_MT_ABSOLUTE:
    23022961            return &g_UsbHidMTDescCache;
     2962        case USBHIDMODE_MT_RELATIVE:
     2963            return &g_UsbHidTPDescCache;
    23032964        default:
    23042965            return NULL;
     
    23182979
    23192980    /* We can not handle any input until device is configured again. */
    2320     pThis->Lun0.pDrv->pfnReportModes(pThis->Lun0.pDrv, false, false, false);
     2981    pThis->Lun0.pDrv->pfnReportModes(pThis->Lun0.pDrv, false, false, false, false);
    23212982
    23222983    int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
     
    23933054        pThis->enmMode = USBHIDMODE_ABSOLUTE;
    23943055    else if (!RTStrCmp(szMode, "multitouch"))
    2395         pThis->enmMode = USBHIDMODE_MULTI_TOUCH;
     3056        pThis->enmMode = USBHIDMODE_MT_ABSOLUTE;
     3057    else if (!RTStrCmp(szMode, "touchpad"))
     3058        pThis->enmMode = USBHIDMODE_MT_RELATIVE;
    23963059    else
    23973060        return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS,
     
    24003063    LogRelFlow(("usbHidConstruct/#%u: mode '%s'\n", iInstance, szMode));
    24013064
    2402     pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
    2403     pThis->Lun0.IPort.pfnPutEvent       = usbHidMousePutEvent;
    2404     pThis->Lun0.IPort.pfnPutEventAbs    = usbHidMousePutEventAbs;
    2405     pThis->Lun0.IPort.pfnPutEventMultiTouch = usbHidMousePutEventMultiTouch;
     3065    pThis->Lun0.IBase.pfnQueryInterface      = usbHidMouseQueryInterface;
     3066    pThis->Lun0.IPort.pfnPutEvent            = usbHidMousePutEvent;
     3067    pThis->Lun0.IPort.pfnPutEventAbs         = usbHidMousePutEventAbs;
     3068    pThis->Lun0.IPort.pfnPutEventTouchScreen = usbHidMousePutEventTouchScreen;
     3069    pThis->Lun0.IPort.pfnPutEventTouchPad    = usbHidMousePutEventTouchPad;
    24063070
    24073071    /*
  • trunk/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp

    r93115 r95271  
    4949    /** Is absolute mode currently supported? */
    5050    bool                        fAbs;
    51     /** Is multi-touch mode currently supported? */
    52     bool                        fMT;
     51    /** Is absolute multi-touch mode currently supported? */
     52    bool                        fMTAbs;
     53    /** Is relative multi-touch mode currently supported? */
     54    bool                        fMTRel;
    5355} DRVTSTMOUSE;
    5456typedef DRVTSTMOUSE *PDRVTSTMOUSE;
     
    106108 */
    107109static DECLCALLBACK(void) tstMouseReportModes(PPDMIMOUSECONNECTOR pInterface,
    108                                               bool fRel, bool fAbs, bool fMT)
     110                                              bool fRel, bool fAbs,
     111                                              bool fMTAbs, bool fMTRel)
    109112{
    110113    PDRVTSTMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVTSTMOUSE, IConnector);
    111114    pDrv->fRel = fRel;
    112115    pDrv->fAbs = fAbs;
    113     pDrv->fMT  = fMT;
     116    pDrv->fMTAbs  = fMTAbs;
     117    pDrv->fMTRel  = fMTRel;
    114118}
    115119
  • trunk/src/VBox/Main/include/MouseImpl.h

    r93115 r95271  
    9494
    9595    static DECLCALLBACK(void *) i_drvQueryInterface(PPDMIBASE pInterface, const char *pszIID);
    96     static DECLCALLBACK(void)   i_mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMT);
     96    static DECLCALLBACK(void)   i_mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRel, bool fAbs, bool fMTAbs, bool fMTRel);
    9797    static DECLCALLBACK(int)    i_drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags);
    9898    static DECLCALLBACK(void)   i_drvDestruct(PPDMDRVINS pDrvIns);
  • trunk/src/VBox/Main/src-client/MouseImpl.cpp

    r94924 r95271  
    189189    /** The mouse device can do absolute reporting */
    190190    MOUSE_DEVCAP_ABSOLUTE = 2,
    191     /** The mouse device can do absolute reporting */
    192     MOUSE_DEVCAP_MULTI_TOUCH = 4
     191    /** The mouse device can do absolute multi-touch reporting */
     192    MOUSE_DEVCAP_MT_ABSOLUTE = 4,
     193    /** The mouse device can do relative multi-touch reporting */
     194    MOUSE_DEVCAP_MT_RELATIVE = 8,
    193195};
    194196/** @} */
     
    573575        {
    574576            if (   mpDrv[i]
    575                 && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MULTI_TOUCH))
     577                && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MT_ABSOLUTE))
    576578            {
    577579                pUpPort = mpDrv[i]->pUpPort;
     
    583585    if (pUpPort)
    584586    {
    585         int vrc = pUpPort->pfnPutEventMultiTouch(pUpPort, cContacts, pau64Contacts, u32ScanTime);
     587        int vrc = pUpPort->pfnPutEventTouchScreen(pUpPort, cContacts, pau64Contacts, u32ScanTime);
    586588        if (RT_FAILURE(vrc))
    587589            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
     
    10791081           if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_RELATIVE)
    10801082               fRelDev = true;
    1081            if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MULTI_TOUCH)
     1083           if (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MT_ABSOLUTE)
    10821084               fMTDev  = true;
    10831085        }
     
    11651167 */
    11661168DECLCALLBACK(void) Mouse::i_mouseReportModes(PPDMIMOUSECONNECTOR pInterface, bool fRelative,
    1167                                              bool fAbsolute, bool fMultiTouch)
     1169                                             bool fAbsolute, bool fMTAbsolute, bool fMTRelative)
    11681170{
    11691171    PDRVMAINMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVMAINMOUSE, IConnector);
     
    11761178    else
    11771179        pDrv->u32DevCaps &= ~MOUSE_DEVCAP_ABSOLUTE;
    1178     if (fMultiTouch)
    1179         pDrv->u32DevCaps |= MOUSE_DEVCAP_MULTI_TOUCH;
     1180    if (fMTAbsolute)
     1181        pDrv->u32DevCaps |= MOUSE_DEVCAP_MT_ABSOLUTE;
    11801182    else
    1181         pDrv->u32DevCaps &= ~MOUSE_DEVCAP_MULTI_TOUCH;
     1183        pDrv->u32DevCaps &= ~MOUSE_DEVCAP_MT_ABSOLUTE;
     1184    if (fMTRelative)
     1185        pDrv->u32DevCaps |= MOUSE_DEVCAP_MT_RELATIVE;
     1186    else
     1187        pDrv->u32DevCaps &= ~MOUSE_DEVCAP_MT_RELATIVE;
    11821188
    11831189    pDrv->pMouse->i_sendMouseCapsNotifications();
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette