VirtualBox

Changeset 26682 in vbox for trunk/src/VBox/Devices/Input


Ignore:
Timestamp:
Feb 22, 2010 4:42:55 PM (15 years ago)
Author:
vboxsync
Message:

UsbMouse: Added tablet support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Input/UsbMouse.cpp

    r26495 r26682  
    3232 * @{ */
    3333#define USBHID_STR_ID_MANUFACTURER  1
    34 #define USBHID_STR_ID_PRODUCT       2
     34#define USBHID_STR_ID_PRODUCT_M     2
     35#define USBHID_STR_ID_PRODUCT_T     3
    3536/** @} */
    3637
     
    4445#define VBOX_USB_VENDOR             0x80EE
    4546#define USBHID_PID_MOUSE            0x0020
     47#define USBHID_PID_TABLET           0x0021
    4648/** @} */
    4749
     
    142144    bool                fHaveDoneQueueWaiter;
    143145
     146    /** Is this an absolute pointing device (tablet)? Relative (mouse) otherwise. */
     147    bool                isAbsolute;
     148
    144149    /**
    145150     * Mouse port - LUN#0.
     
    166171
    167172/**
    168  * The USB HID report structure.
     173 * The USB HID report structure for relative device.
    169174 */
    170175typedef struct USBHIDM_REPORT
     
    176181} USBHIDM_REPORT, *PUSBHIDM_REPORT;
    177182
     183/**
     184 * The USB HID report structure for relative device.
     185 */
     186
     187typedef struct USBHIDT_REPORT
     188{
     189    uint16_t    cx;
     190    uint16_t    cy;
     191    int8_t      dz;
     192    uint8_t     btn;
     193} USBHIDT_REPORT, *PUSBHIDT_REPORT;
     194
    178195/*******************************************************************************
    179196*   Global Variables                                                           *
     
    182199{
    183200    { USBHID_STR_ID_MANUFACTURER,   "VirtualBox"    },
    184     { USBHID_STR_ID_PRODUCT,        "USB Mouse"     },
     201    { USBHID_STR_ID_PRODUCT_M,      "USB Mouse"     },
     202    { USBHID_STR_ID_PRODUCT_T,      "USB Tablet"    },
    185203};
    186204
     
    190208};
    191209
    192 static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescs[] =
     210static const VUSBDESCENDPOINTEX g_aUsbHidMEndpointDescs[] =
    193211{
    194212    {
     
    207225};
    208226
    209 /* HID report descriptor. */
    210 static const uint8_t g_UsbHidReportDesc[] =
     227static const VUSBDESCENDPOINTEX g_aUsbHidTEndpointDescs[] =
     228{
     229    {
     230        {
     231            /* .bLength = */            sizeof(VUSBDESCENDPOINT),
     232            /* .bDescriptorType = */    VUSB_DT_ENDPOINT,
     233            /* .bEndpointAddress = */   0x81 /* ep=1, in */,
     234            /* .bmAttributes = */       3 /* interrupt */,
     235            /* .wMaxPacketSize = */     6,
     236            /* .bInterval = */          10,
     237        },
     238        /* .pvMore = */     NULL,
     239        /* .pvClass = */    NULL,
     240        /* .cbClass = */    0
     241    },
     242};
     243
     244/* HID report descriptor (mouse). */
     245static const uint8_t g_UsbHidMReportDesc[] =
    211246{
    212247    /* Usage Page */                0x05, 0x01,     /* Generic Desktop */
     
    239274};
    240275
     276/* HID report descriptor (tablet). */
     277static const uint8_t g_UsbHidTReportDesc[] =
     278{
     279    /* Usage Page */                0x05, 0x01,     /* Generic Desktop */
     280    /* Usage */                     0x09, 0x02,     /* Mouse */
     281    /* Collection */                0xA1, 0x01,     /* Application */
     282    /* Usage */                     0x09, 0x01,     /* Pointer */
     283    /* Collection */                0xA1, 0x00,     /* Physical */
     284    /* Usage Page */                0x05, 0x01,     /* Generic Desktop */
     285    /* Usage */                     0x09, 0x30,     /* X */
     286    /* Usage */                     0x09, 0x31,     /* Y */
     287    /* Logical Minimum */           0x15, 0x00,     /* 0 */
     288    /* Logical Maximum */           0x26, 0xFF,0x7F,/* 0x7fff */
     289    /* Physical Minimum */          0x35, 0x00,     /* 0 */
     290    /* Physical Maximum */          0x46, 0xFF,0x7F,/* 0x7fff */
     291    /* Report Size */               0x75, 0x10,     /* 16 */
     292    /* Report Count */              0x95, 0x02,     /* 2 */
     293    /* Input */                     0x81, 0x02,     /* Data, Value, Absolute, Bit field */
     294    /* Usage Page */                0x05, 0x01,     /* Generic Desktop */
     295    /* Usage */                     0x09, 0x38,     /* Z (wheel) */
     296    /* Logical Minimum */           0x15, 0x81,     /* -127 */
     297    /* Logical Maximum */           0x25, 0x7F,     /* +127 */
     298    /* Report Size */               0x75, 0x08,     /* 8 */
     299    /* Report Count */              0x95, 0x01,     /* 1 */
     300    /* Input */                     0x81, 0x06,     /* Data, Value, Relative, Bit field */
     301    /* Usage Page */                0x05, 0x09,     /* Button */
     302    /* Usage Minimum */             0x19, 0x01,     /* Button 1 */
     303    /* Usage Maximum */             0x29, 0x03,     /* Button 3 */
     304    /* Logical Minimum */           0x15, 0x00,     /* 0 */
     305    /* Logical Maximum */           0x25, 0x01,     /* 1 */
     306    /* Report Count */              0x95, 0x03,     /* 3 */
     307    /* Report Size */               0x75, 0x01,     /* 1 */
     308    /* Input */                     0x81, 0x02,     /* Data, Value, Absolute, Bit field */
     309    /* Report Count */              0x95, 0x01,     /* 1 */
     310    /* Report Size */               0x75, 0x05,     /* 5 (padding bits) */
     311    /* Input */                     0x81, 0x03,     /* Constant, Value, Absolute, Bit field */
     312    /* End Collection */            0xC0,
     313    /* End Collection */            0xC0,
     314};
     315
    241316/* Additional HID class interface descriptor. */
    242 static const uint8_t g_UsbHidIfHidDesc[] =
     317static const uint8_t g_UsbHidMIfHidDesc[] =
    243318{
    244319    /* .bLength = */                0x09,
     
    248323    /* .bNumDescriptors = */        1,
    249324    /* .bDescriptorType = */        0x22,       /* Report */
    250     /* .wDescriptorLength = */      sizeof(g_UsbHidReportDesc), 0x00
    251 };
    252 
    253 static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDesc =
     325    /* .wDescriptorLength = */      sizeof(g_UsbHidMReportDesc), 0x00
     326};
     327
     328/* Additional HID class interface descriptor. */
     329static const uint8_t g_UsbHidTIfHidDesc[] =
     330{
     331    /* .bLength = */                0x09,
     332    /* .bDescriptorType = */        0x21,       /* HID */
     333    /* .bcdHID = */                 0x10, 0x01, /* 1.1 */
     334    /* .bCountryCode = */           0,
     335    /* .bNumDescriptors = */        1,
     336    /* .bDescriptorType = */        0x22,       /* Report */
     337    /* .wDescriptorLength = */      sizeof(g_UsbHidTReportDesc), 0x00
     338};
     339
     340static const VUSBDESCINTERFACEEX g_UsbHidMInterfaceDesc =
    254341{
    255342    {
     
    265352    },
    266353    /* .pvMore = */     NULL,
    267     /* .pvClass = */    &g_UsbHidIfHidDesc,
    268     /* .cbClass = */    sizeof(g_UsbHidIfHidDesc),
    269     &g_aUsbHidEndpointDescs[0]
    270 };
    271 
    272 static const VUSBINTERFACE g_aUsbHidInterfaces[] =
    273 {
    274     { &g_UsbHidInterfaceDesc, /* .cSettings = */ 1 },
    275 };
    276 
    277 static const VUSBDESCCONFIGEX g_UsbHidConfigDesc =
     354    /* .pvClass = */    &g_UsbHidMIfHidDesc,
     355    /* .cbClass = */    sizeof(g_UsbHidMIfHidDesc),
     356    &g_aUsbHidMEndpointDescs[0]
     357};
     358
     359static const VUSBDESCINTERFACEEX g_UsbHidTInterfaceDesc =
     360{
     361    {
     362        /* .bLength = */                sizeof(VUSBDESCINTERFACE),
     363        /* .bDescriptorType = */        VUSB_DT_INTERFACE,
     364        /* .bInterfaceNumber = */       0,
     365        /* .bAlternateSetting = */      0,
     366        /* .bNumEndpoints = */          1,
     367        /* .bInterfaceClass = */        3 /* HID */,
     368        /* .bInterfaceSubClass = */     1 /* Boot Interface */,
     369        /* .bInterfaceProtocol = */     2 /* Mouse */,
     370        /* .iInterface = */             0
     371    },
     372    /* .pvMore = */     NULL,
     373    /* .pvClass = */    &g_UsbHidTIfHidDesc,
     374    /* .cbClass = */    sizeof(g_UsbHidTIfHidDesc),
     375    &g_aUsbHidTEndpointDescs[0]
     376};
     377
     378static const VUSBINTERFACE g_aUsbHidMInterfaces[] =
     379{
     380    { &g_UsbHidMInterfaceDesc, /* .cSettings = */ 1 },
     381};
     382
     383static const VUSBINTERFACE g_aUsbHidTInterfaces[] =
     384{
     385    { &g_UsbHidTInterfaceDesc, /* .cSettings = */ 1 },
     386};
     387
     388static const VUSBDESCCONFIGEX g_UsbHidMConfigDesc =
    278389{
    279390    {
     
    281392        /* .bDescriptorType = */    VUSB_DT_CONFIG,
    282393        /* .wTotalLength = */       0 /* recalculated on read */,
    283         /* .bNumInterfaces = */     RT_ELEMENTS(g_aUsbHidInterfaces),
     394        /* .bNumInterfaces = */     RT_ELEMENTS(g_aUsbHidMInterfaces),
    284395        /* .bConfigurationValue =*/ 1,
    285396        /* .iConfiguration = */     0,
     
    288399    },
    289400    NULL,
    290     &g_aUsbHidInterfaces[0]
    291 };
    292 
    293 static const VUSBDESCDEVICE g_UsbHidDeviceDesc =
    294 {
    295     /* .bLength = */                sizeof(g_UsbHidDeviceDesc),
     401    &g_aUsbHidMInterfaces[0]
     402};
     403
     404static const VUSBDESCCONFIGEX g_UsbHidTConfigDesc =
     405{
     406    {
     407        /* .bLength = */            sizeof(VUSBDESCCONFIG),
     408        /* .bDescriptorType = */    VUSB_DT_CONFIG,
     409        /* .wTotalLength = */       0 /* recalculated on read */,
     410        /* .bNumInterfaces = */     RT_ELEMENTS(g_aUsbHidTInterfaces),
     411        /* .bConfigurationValue =*/ 1,
     412        /* .iConfiguration = */     0,
     413        /* .bmAttributes = */       RT_BIT(7),
     414        /* .MaxPower = */           50 /* 100mA */
     415    },
     416    NULL,
     417    &g_aUsbHidTInterfaces[0]
     418};
     419
     420static const VUSBDESCDEVICE g_UsbHidMDeviceDesc =
     421{
     422    /* .bLength = */                sizeof(g_UsbHidMDeviceDesc),
    296423    /* .bDescriptorType = */        VUSB_DT_DEVICE,
    297424    /* .bcdUsb = */                 0x110,  /* 1.1 */
     
    304431    /* .bcdDevice = */              0x0100, /* 1.0 */
    305432    /* .iManufacturer = */          USBHID_STR_ID_MANUFACTURER,
    306     /* .iProduct = */               USBHID_STR_ID_PRODUCT,
     433    /* .iProduct = */               USBHID_STR_ID_PRODUCT_M,
    307434    /* .iSerialNumber = */          0,
    308435    /* .bNumConfigurations = */     1
    309436};
    310437
    311 static const PDMUSBDESCCACHE g_UsbHidDescCache =
    312 {
    313     /* .pDevice = */                &g_UsbHidDeviceDesc,
    314     /* .paConfigs = */              &g_UsbHidConfigDesc,
     438static const VUSBDESCDEVICE g_UsbHidTDeviceDesc =
     439{
     440    /* .bLength = */                sizeof(g_UsbHidTDeviceDesc),
     441    /* .bDescriptorType = */        VUSB_DT_DEVICE,
     442    /* .bcdUsb = */                 0x110,  /* 1.1 */
     443    /* .bDeviceClass = */           0 /* Class specified in the interface desc. */,
     444    /* .bDeviceSubClass = */        0 /* Subclass specified in the interface desc. */,
     445    /* .bDeviceProtocol = */        0 /* Protocol specified in the interface desc. */,
     446    /* .bMaxPacketSize0 = */        8,
     447    /* .idVendor = */               VBOX_USB_VENDOR,
     448    /* .idProduct = */              USBHID_PID_TABLET,
     449    /* .bcdDevice = */              0x0100, /* 1.0 */
     450    /* .iManufacturer = */          USBHID_STR_ID_MANUFACTURER,
     451    /* .iProduct = */               USBHID_STR_ID_PRODUCT_T,
     452    /* .iSerialNumber = */          0,
     453    /* .bNumConfigurations = */     1
     454};
     455
     456static const PDMUSBDESCCACHE g_UsbHidMDescCache =
     457{
     458    /* .pDevice = */                &g_UsbHidMDeviceDesc,
     459    /* .paConfigs = */              &g_UsbHidMConfigDesc,
     460    /* .paLanguages = */            g_aUsbHidLanguages,
     461    /* .cLanguages = */             RT_ELEMENTS(g_aUsbHidLanguages),
     462    /* .fUseCachedDescriptors = */  true,
     463    /* .fUseCachedStringsDescriptors = */ true
     464};
     465
     466static const PDMUSBDESCCACHE g_UsbHidTDescCache =
     467{
     468    /* .pDevice = */                &g_UsbHidTDeviceDesc,
     469    /* .paConfigs = */              &g_UsbHidTConfigDesc,
    315470    /* .paLanguages = */            g_aUsbHidLanguages,
    316471    /* .cLanguages = */             RT_ELEMENTS(g_aUsbHidLanguages),
     
    542697
    543698/**
    544  * Mouse event handler.
     699 * Relative mouse event handler.
    545700 *
    546701 * @returns VBox status code.
     
    558713//    AssertReleaseRC(rc);
    559714
     715    /* If we aren't in the expected mode, switch. This should only really need to be done once. */
     716//    if (pThis->isAbsolute)
     717//        pThis->Lun0.pDrv->pfnAbsModeChange(pThis->Lun0.pDrv, pThis->isAbsolute);
     718
    560719    /* Accumulate movement - the events from the front end may arrive
    561720     * at a much higher rate than USB can handle.
     
    571730    if (pUrb)
    572731    {
     732        size_t          cbCopy;
    573733        USBHIDM_REPORT  report;
    574         size_t          cbCopy;
    575734
    576735        //@todo: fix/extend
     
    582741        cbCopy = sizeof(report);
    583742        memcpy(&pUrb->abData[0], &report, cbCopy);
    584         usbHidCompleteOk(pThis, pUrb, cbCopy);
    585743
    586744        /* Clear the accumulated movement. */
    587745        pThis->PtrDelta.dX = pThis->PtrDelta.dY = pThis->PtrDelta.dZ = 0;
     746
     747        /* Complete the URB. */
     748        usbHidCompleteOk(pThis, pUrb, cbCopy);
     749//        LogRel(("Rel movement, dX=%d, dY=%d, dZ=%d, btn=%02x, report size %d\n", report.dx, report.dy, report.dz, report.btn, cbCopy));
     750    }
     751
     752//    PDMCritSectLeave(&pThis->CritSect);
     753    return VINF_SUCCESS;
     754}
     755
     756/**
     757 * Absolute mouse event handler.
     758 *
     759 * @returns VBox status code.
     760 * @param   pInterface      Pointer to the mouse port interface (KBDState::Mouse.iPort).
     761 * @param   u32X            The X coordinate.
     762 * @param   u32Y            The Y coordinate.
     763 * @param   i32DeltaZ       The Z delta.
     764 * @param   i32DeltaW       The W delta.
     765 * @param   fButtonStates   The button states.
     766 */
     767static DECLCALLBACK(int) usbHidMousePutEventAbs(PPDMIMOUSEPORT pInterface, uint32_t u32X, uint32_t u32Y, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)
     768{
     769    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
     770//    int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
     771//    AssertReleaseRC(rc);
     772
     773    Assert(pThis->isAbsolute);
     774
     775    /* Accumulate movement - the events from the front end may arrive
     776     * at a much higher rate than USB can handle. Probably not a real issue
     777     * when only the Z axis is relative.
     778     */
     779    pThis->PtrDelta.btn = fButtonStates;
     780    pThis->PtrDelta.dZ -= i32DeltaZ;    /* Inverted! */
     781
     782    /* Check if there's a URB waiting. If so, send a report.
     783     */
     784    PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
     785    if (pUrb)
     786    {
     787        size_t          cbCopy;
     788        USBHIDT_REPORT  report;
     789
     790        report.btn = pThis->PtrDelta.btn;
     791        report.cx  = u32X / 2;
     792        report.cy  = u32Y / 2;
     793        report.dz  = clamp_i8(pThis->PtrDelta.dZ);
     794
     795        cbCopy = sizeof(report);
     796        memcpy(&pUrb->abData[0], &report, cbCopy);
     797
     798        /* Clear the accumulated movement. */
     799        pThis->PtrDelta.dZ = 0;
     800
     801        /* Complete the URB. */
     802        usbHidCompleteOk(pThis, pUrb, cbCopy);
     803//        LogRel(("Abs movement, X=%d, Y=%d, dZ=%d, btn=%02x, report size %d\n", report.cx, report.cy, report.dz, report.btn, cbCopy));
    588804    }
    589805
     
    734950                        {
    735951                            case DT_IF_HID_REPORT:
    736                                 uint32_t    cbCopy;
    737 
     952                                uint32_t        cbCopy;
     953                                uint32_t        cbDesc;
     954                                const uint8_t   *pDesc;
     955
     956                                if (pThis->isAbsolute)
     957                                {
     958                                    cbDesc = sizeof(g_UsbHidTReportDesc);
     959                                    pDesc = (const uint8_t *)&g_UsbHidTReportDesc;
     960                                }
     961                                else
     962                                {
     963                                    cbDesc = sizeof(g_UsbHidMReportDesc);
     964                                    pDesc = (const uint8_t *)&g_UsbHidMReportDesc;
     965                                }
    738966                                /* Returned data is written after the setup message. */
    739967                                cbCopy = pUrb->cbData - sizeof(*pSetup);
    740                                 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbHidReportDesc));
     968                                cbCopy = RT_MIN(cbCopy, cbDesc);
    741969                                Log(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n", pSetup->wValue, pSetup->wIndex, cbCopy));
    742                                 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbHidReportDesc, cbCopy);
     970                                memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
    743971                                return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
    744972                            default:
     
    8711099    pThis->bConfigurationValue = bConfigurationValue;
    8721100
     1101    /*
     1102     * Set received event type to absolute or relative.
     1103     */
     1104    pThis->Lun0.pDrv->pfnAbsModeChange(pThis->Lun0.pDrv, pThis->isAbsolute);
     1105
    8731106    RTCritSectLeave(&pThis->CritSect);
    8741107    return VINF_SUCCESS;
     
    8831116    PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
    8841117    LogFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
    885     return &g_UsbHidDescCache;
     1118    if (pThis->isAbsolute) {
     1119        return &g_UsbHidTDescCache;
     1120    } else {
     1121        return &g_UsbHidMDescCache;
     1122    }
    8861123}
    8871124
     
    9521189     * Validate and read the configuration.
    9531190     */
    954     rc = CFGMR3ValidateConfig(pCfg, "/", "", "", "UsbHid", iInstance);
     1191    rc = CFGMR3ValidateConfig(pCfg, "/", "Absolute", "Config", "UsbHid", iInstance);
    9551192    if (RT_FAILURE(rc))
    9561193        return rc;
    957 
     1194    rc = CFGMR3QueryBoolDef(pCfg, "Absolute", &pThis->isAbsolute, false);
     1195    if (RT_FAILURE(rc))
     1196        return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
     1197   
    9581198    pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
    9591199    pThis->Lun0.IPort.pfnPutEvent       = usbHidMousePutEvent;
     1200    pThis->Lun0.IPort.pfnPutEventAbs    = usbHidMousePutEventAbs;
    9601201
    9611202    /*
     
    9651206    if (RT_FAILURE(rc))
    9661207        return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach mouse driver"));
     1208
     1209    pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIMOUSECONNECTOR);
     1210    if (!pThis->Lun0.pDrv)
     1211        return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query mouse interface"));
    9671212
    9681213    return VINF_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.

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