VirtualBox

Changeset 43605 in vbox


Ignore:
Timestamp:
Oct 10, 2012 5:54:15 PM (12 years ago)
Author:
vboxsync
Message:

UsbMouse: If event could not be sent to guest due to lack of available URB, send it as soon as an URB shows up.

File:
1 edited

Legend:

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

    r43561 r43605  
    147147     *  is set. */
    148148    RTSEMEVENT          hEvtDoneQueue;
     149
    149150    /** Someone is waiting on the done queue. */
    150151    bool                fHaveDoneQueueWaiter;
    151 
     152    /** If device has pending changes. */
     153    bool                fHasPendingChanges;   
    152154    /** Is this an absolute pointing device (tablet)? Relative (mouse) otherwise. */
    153155    bool                isAbsolute;
    154 
    155156    /** Tablet coordinate shift factor for old and broken operating systems. */
    156157    uint8_t             u8CoordShift;
     
    201202    uint16_t    cy;
    202203} USBHIDT_REPORT, *PUSBHIDT_REPORT;
     204
     205/**
     206 * The combined USB HID report union for relative and absolute device.
     207 */
     208typedef union USBHIDTM_REPORT
     209{
     210    USBHIDT_REPORT      t;
     211    USBHIDM_REPORT      m;
     212} USBHIDTM_REPORT, *PUSBHIDTM_REPORT;
    203213
    204214/*******************************************************************************
     
    669679     */
    670680    pThis->enmState = USBHIDREQSTATE_READY;
     681    pThis->fHasPendingChanges = false;
    671682
    672683    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
     
    691702}
    692703
     704static int8_t clamp_i8(int32_t val)
     705{
     706    if (val > 127) {
     707        val = 127;
     708    } else if (val < -127) {
     709        val = -127;
     710    }
     711    return val;
     712}
     713
     714/**
     715 * Create a USB HID report report based on the currently accumulated data.
     716 */
     717static size_t usbHidFillReport(PUSBHIDTM_REPORT pReport, PUSBHIDM_ACCUM pAccumulated, bool isAbsolute)
     718{
     719    size_t          cbCopy;
     720
     721    if (isAbsolute)
     722    {
     723        pReport->t.btn = pAccumulated->btn;
     724        pReport->t.cx  = pAccumulated->dX;
     725        pReport->t.cy  = pAccumulated->dY;
     726        pReport->t.dz  = clamp_i8(pAccumulated->dZ);
     727
     728        cbCopy = sizeof(pReport->t);
     729//        LogRel(("Abs movement, X=%d, Y=%d, dZ=%d, btn=%02x, report size %d\n", pReport->t.cx, pReport->t.cy, pReport->t.dz, pReport->t.btn, cbCopy));
     730    }
     731    else
     732    {
     733        pReport->m.btn = pAccumulated->btn;
     734        pReport->m.dx  = clamp_i8(pAccumulated->dX);
     735        pReport->m.dy  = clamp_i8(pAccumulated->dY);
     736        pReport->m.dz  = clamp_i8(pAccumulated->dZ);
     737   
     738        cbCopy = sizeof(pReport->m);
     739//        LogRel(("Rel movement, dX=%d, dY=%d, dZ=%d, btn=%02x, report size %d\n", pReport->m.dx, pReport->m.dy, pReport->m.dz, pReport->m.btn, cbCopy));
     740    }
     741
     742    /* Clear the accumulated movement. */
     743    RT_ZERO(*pAccumulated);
     744
     745    return cbCopy;
     746}
     747
     748/**
     749 * Sends a state report to the host if there is a pending URB.
     750 */
     751static int usbHidSendReport(PUSBHID pThis)
     752{
     753    PVUSBURB    pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
     754
     755    if (pUrb)
     756    {
     757        PUSBHIDTM_REPORT    pReport = (PUSBHIDTM_REPORT)&pUrb->abData[0];
     758        size_t              cbCopy;
     759
     760        cbCopy = usbHidFillReport(pReport, &pThis->PtrDelta, pThis->isAbsolute);
     761        pThis->fHasPendingChanges = false;
     762        return usbHidCompleteOk(pThis, pUrb, cbCopy);
     763    }
     764    else
     765    {
     766        Log2(("No available URB for USB mouse\n"));
     767        pThis->fHasPendingChanges = true;
     768    }
     769    return VINF_EOF;
     770}
    693771
    694772/**
     
    701779    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThis->Lun0.IPort);
    702780    return NULL;
    703 }
    704 
    705 static int8_t clamp_i8(int32_t val)
    706 {
    707     if (val > 127) {
    708         val = 127;
    709     } else if (val < -127) {
    710         val = -127;
    711     }
    712     return val;
    713781}
    714782
     
    727795{
    728796    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
    729 //    int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
    730 //    AssertReleaseRC(rc);
    731 
    732     /* If we aren't in the expected mode, switch. This should only really need to be done once. */
    733 //    if (pThis->isAbsolute)
    734 //        pThis->Lun0.pDrv->pfnAbsModeChange(pThis->Lun0.pDrv, pThis->isAbsolute);
     797    RTCritSectEnter(&pThis->CritSect);
    735798
    736799    /* Accumulate movement - the events from the front end may arrive
     
    742805    pThis->PtrDelta.dZ -= i32DeltaZ;    /* Inverted! */
    743806
    744     /* Check if there's a URB waiting. If so, send a report.
    745      */
    746     PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
    747     if (pUrb)
    748     {
    749         size_t          cbCopy;
    750         USBHIDM_REPORT  report;
    751 
    752         //@todo: fix/extend
    753         report.btn = pThis->PtrDelta.btn;
    754         report.dx  = clamp_i8(pThis->PtrDelta.dX);
    755         report.dy  = clamp_i8(pThis->PtrDelta.dY);
    756         report.dz  = clamp_i8(pThis->PtrDelta.dZ);
    757 
    758         cbCopy = sizeof(report);
    759         memcpy(&pUrb->abData[0], &report, cbCopy);
    760 
    761         /* Clear the accumulated movement. */
    762         pThis->PtrDelta.dX = pThis->PtrDelta.dY = pThis->PtrDelta.dZ = 0;
    763 
    764         /* Complete the URB. */
    765         usbHidCompleteOk(pThis, pUrb, cbCopy);
    766 //        LogRel(("Rel movement, dX=%d, dY=%d, dZ=%d, btn=%02x, report size %d\n", report.dx, report.dy, report.dz, report.btn, cbCopy));
    767     }
    768 
    769 //    PDMCritSectLeave(&pThis->CritSect);
     807    /* Send a report if possible. */
     808    usbHidSendReport(pThis);
     809
     810    RTCritSectLeave(&pThis->CritSect);
    770811    return VINF_SUCCESS;
    771812}
     
    785826{
    786827    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
    787 //    int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
    788 //    AssertReleaseRC(rc);
     828    RTCritSectEnter(&pThis->CritSect);
    789829
    790830    Assert(pThis->isAbsolute);
     
    792832    /* Accumulate movement - the events from the front end may arrive
    793833     * at a much higher rate than USB can handle. Probably not a real issue
    794      * when only the Z axis is relative.
     834     * when only the Z axis is relative (X/Y movement isn't technically
     835     * accumulated and only the last value is used).
    795836     */
    796837    pThis->PtrDelta.btn = fButtonStates;
     838    pThis->PtrDelta.dX  = u32X >> pThis->u8CoordShift;
     839    pThis->PtrDelta.dY  = u32Y >> pThis->u8CoordShift;
    797840    pThis->PtrDelta.dZ -= i32DeltaZ;    /* Inverted! */
    798841
    799     /* Check if there's a URB waiting. If so, send a report.
    800      */
    801     PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
    802     if (pUrb)
    803     {
    804         size_t          cbCopy;
    805         USBHIDT_REPORT  report;
    806 
    807         report.btn = pThis->PtrDelta.btn;
    808         report.cx  = u32X >> pThis->u8CoordShift;
    809         report.cy  = u32Y >> pThis->u8CoordShift;
    810         report.dz  = clamp_i8(pThis->PtrDelta.dZ);
    811 
    812         cbCopy = sizeof(report);
    813         memcpy(&pUrb->abData[0], &report, cbCopy);
    814 
    815         /* Clear the accumulated movement. */
    816         pThis->PtrDelta.dZ = 0;
    817 
    818         /* Complete the URB. */
    819         usbHidCompleteOk(pThis, pUrb, cbCopy);
    820 //        LogRel(("Abs movement, X=%d, Y=%d, dZ=%d, btn=%02x, report size %d\n", report.cx, report.cy, report.dz, report.btn, cbCopy));
    821     }
    822 
    823 //    PDMCritSectLeave(&pThis->CritSect);
     842    /* Send a report if possible. */
     843    usbHidSendReport(pThis);
     844
     845    RTCritSectLeave(&pThis->CritSect);
    824846    return VINF_SUCCESS;
    825847}
     
    919941        case USBHIDREQSTATE_READY:
    920942            usbHidQueueAddTail(&pThis->ToHostQueue, pUrb);
     943            /* If a report is pending, send it right away. */
     944            if (pThis->fHasPendingChanges)
     945                usbHidSendReport(pThis);
    921946            LogFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n", pUrb, pUrb->pszDesc));
    922947            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