third_party/virtualbox/src/VBox/Devices/USB/VUSBUrb.cpp
/**
 * Does URB completion on roothub level.
 *
 * @param   pUrb    The URB to complete.
 */
Does URB completion on roothub level.
@param   pUrb    The URB to complete.
Does URB completion on roothub level . @param pUrb The URB to complete .
void vusbUrbCompletionRh(PVUSBURB pUrb)
{
    LogFlow(("%s: vusbUrbCompletionRh: type=%s status=%s\n",
             pUrb->pszDesc, vusbUrbTypeName(pUrb->enmType), vusbUrbStatusName(pUrb->enmStatus)));
    AssertMsg(   pUrb->enmState == VUSBURBSTATE_REAPED
              || pUrb->enmState == VUSBURBSTATE_CANCELLED, ("%d\n", pUrb->enmState));
    if (   pUrb->pVUsb->pDev
        && pUrb->pVUsb->pDev->hSniffer)
    {
        int rc = VUSBSnifferRecordEvent(pUrb->pVUsb->pDev->hSniffer, pUrb,
                                          pUrb->enmStatus == VUSBSTATUS_OK
                                        ? VUSBSNIFFEREVENT_COMPLETE
                                        : VUSBSNIFFEREVENT_ERROR_COMPLETE);
        if (RT_FAILURE(rc))
            LogRel(("VUSB: Capturing URB completion event failed with %Rrc\n", rc));
    }
    PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->pVUsb->pDev);
    AssertPtrReturnVoid(pRh);
    if (pRh->hSniffer != VUSBSNIFFER_NIL)
    {
        int rc = VUSBSnifferRecordEvent(pRh->hSniffer, pUrb,
                                          pUrb->enmStatus == VUSBSTATUS_OK
                                        ? VUSBSNIFFEREVENT_COMPLETE
                                        : VUSBSNIFFEREVENT_ERROR_COMPLETE);
        if (RT_FAILURE(rc))
            LogRel(("VUSB: Capturing URB completion event on the root hub failed with %Rrc\n", rc));
    }
#ifdef VBOX_WITH_STATISTICS
    if (pUrb->enmType != VUSBXFERTYPE_MSG)
    {
        Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));
        if (    pUrb->enmStatus == VUSBSTATUS_OK
            ||  pUrb->enmStatus == VUSBSTATUS_DATA_UNDERRUN
            ||  pUrb->enmStatus == VUSBSTATUS_DATA_OVERRUN)
        {
            if (pUrb->enmType == VUSBXFERTYPE_ISOC)
            {
                for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
                {
                    const unsigned cb = pUrb->aIsocPkts[i].cb;
                    if (cb)
                    {
                        STAM_COUNTER_ADD(&pRh->Total.StatActBytes, cb);
                        STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActBytes, cb);
                        STAM_COUNTER_ADD(&pRh->aStatIsocDetails[i].Bytes, cb);
                        if (pUrb->enmDir == VUSBDIRECTION_IN)
                        {
                            STAM_COUNTER_ADD(&pRh->Total.StatActReadBytes, cb);
                            STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActReadBytes, cb);
                        }
                        else
                        {
                            STAM_COUNTER_ADD(&pRh->Total.StatActWriteBytes, cb);
                            STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActWriteBytes, cb);
                        }
                        STAM_COUNTER_INC(&pRh->StatIsocActPkts);
                        STAM_COUNTER_INC(&pRh->StatIsocActReadPkts);
                    }
                    STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Pkts);
                    switch (pUrb->aIsocPkts[i].enmStatus)
                    {
                        case VUSBSTATUS_OK:
                            if (cb)                     STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Ok);
                            else                        STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Ok0); break;
                        case VUSBSTATUS_DATA_UNDERRUN:
                            if (cb)                     STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataUnderrun);
                            else                        STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataUnderrun0); break;
                        case VUSBSTATUS_DATA_OVERRUN:   STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataOverrun); break;
                        case VUSBSTATUS_NOT_ACCESSED:   STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].NotAccessed); break;
                        default:                        STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Misc); break;
                    }
                }
            }
            else
            {
                STAM_COUNTER_ADD(&pRh->Total.StatActBytes, pUrb->cbData);
                STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActBytes, pUrb->cbData);
                if (pUrb->enmDir == VUSBDIRECTION_IN)
                {
                    STAM_COUNTER_ADD(&pRh->Total.StatActReadBytes, pUrb->cbData);
                    STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActReadBytes, pUrb->cbData);
                }
                else
                {
                    STAM_COUNTER_ADD(&pRh->Total.StatActWriteBytes, pUrb->cbData);
                    STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActWriteBytes, pUrb->cbData);
                }
            }
        }
        else
        {
            STAM_COUNTER_INC(&pRh->Total.StatUrbsFailed);
            STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsFailed);
        }
    }
#endif 
    switch (pUrb->enmType)
    {
        case VUSBXFERTYPE_MSG:
            vusbMsgCompletion(pUrb);
            return;
        case VUSBXFERTYPE_ISOC:
            break;
#if 1   
        default:
#endif
        case VUSBXFERTYPE_BULK:
            if (pUrb->enmStatus != VUSBSTATUS_OK)
                vusbUrbErrorRh(pUrb);
            break;
    }
#ifdef LOG_ENABLED
    vusbUrbTrace(pUrb, "vusbUrbCompletionRh", true);
#endif
    pRh->pIRhPort->pfnXferCompletion(pRh->pIRhPort, pUrb);
    if (pUrb->enmState == VUSBURBSTATE_REAPED)
    {
        LogFlow(("%s: vusbUrbCompletionRh: Freeing URB\n", pUrb->pszDesc));
        pUrb->pVUsb->pfnFree(pUrb);
    }
    vusbRhR3ProcessFrame(pRh, true );
}
void vusbUrbCompletionRh ( PVUSBURB pUrb ) { LogFlow ( ( " \n " , pUrb -> pszDesc , vusbUrbTypeName ( pUrb -> enmType ) , vusbUrbStatusName ( pUrb -> enmStatus ) ) ) ; AssertMsg ( pUrb -> enmState == VUSBURBSTATE_REAPED || pUrb -> enmState == VUSBURBSTATE_CANCELLED , ( " \n " , pUrb -> enmState ) ) ; if ( pUrb -> pVUsb -> pDev && pUrb -> pVUsb -> pDev -> hSniffer ) { int rc = VUSBSnifferRecordEvent ( pUrb -> pVUsb -> pDev -> hSniffer , pUrb , pUrb -> enmStatus == VUSBSTATUS_OK ? VUSBSNIFFEREVENT_COMPLETE : VUSBSNIFFEREVENT_ERROR_COMPLETE ) ; if ( RT_FAILURE ( rc ) ) LogRel ( ( " \n " , rc ) ) ; } PVUSBROOTHUB pRh = vusbDevGetRh ( pUrb -> pVUsb -> pDev ) ; AssertPtrReturnVoid ( pRh ) ; if ( pRh -> hSniffer != VUSBSNIFFER_NIL ) { int rc = VUSBSnifferRecordEvent ( pRh -> hSniffer , pUrb , pUrb -> enmStatus == VUSBSTATUS_OK ? VUSBSNIFFEREVENT_COMPLETE : VUSBSNIFFEREVENT_ERROR_COMPLETE ) ; if ( RT_FAILURE ( rc ) ) LogRel ( ( " \n " , rc ) ) ; } #ifdef VBOX_WITH_STATISTICS if ( pUrb -> enmType != VUSBXFERTYPE_MSG ) { Assert ( pUrb -> enmType >= 0 && pUrb -> enmType < ( int ) RT_ELEMENTS ( pRh -> aTypes ) ) ; if ( pUrb -> enmStatus == VUSBSTATUS_OK || pUrb -> enmStatus == VUSBSTATUS_DATA_UNDERRUN || pUrb -> enmStatus == VUSBSTATUS_DATA_OVERRUN ) { if ( pUrb -> enmType == VUSBXFERTYPE_ISOC ) { for ( unsigned i = 0 ; i < pUrb -> cIsocPkts ; i ++ ) { const unsigned cb = pUrb -> aIsocPkts [ i ] . cb ; if ( cb ) { STAM_COUNTER_ADD ( & pRh -> Total . StatActBytes , cb ) ; STAM_COUNTER_ADD ( & pRh -> aTypes [ VUSBXFERTYPE_ISOC ] . StatActBytes , cb ) ; STAM_COUNTER_ADD ( & pRh -> aStatIsocDetails [ i ] . Bytes , cb ) ; if ( pUrb -> enmDir == VUSBDIRECTION_IN ) { STAM_COUNTER_ADD ( & pRh -> Total . StatActReadBytes , cb ) ; STAM_COUNTER_ADD ( & pRh -> aTypes [ VUSBXFERTYPE_ISOC ] . StatActReadBytes , cb ) ; } else { STAM_COUNTER_ADD ( & pRh -> Total . StatActWriteBytes , cb ) ; STAM_COUNTER_ADD ( & pRh -> aTypes [ VUSBXFERTYPE_ISOC ] . StatActWriteBytes , cb ) ; } STAM_COUNTER_INC ( & pRh -> StatIsocActPkts ) ; STAM_COUNTER_INC ( & pRh -> StatIsocActReadPkts ) ; } STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . Pkts ) ; switch ( pUrb -> aIsocPkts [ i ] . enmStatus ) { case VUSBSTATUS_OK : if ( cb ) STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . Ok ) ; else STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . Ok0 ) ; break ; case VUSBSTATUS_DATA_UNDERRUN : if ( cb ) STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . DataUnderrun ) ; else STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . DataUnderrun0 ) ; break ; case VUSBSTATUS_DATA_OVERRUN : STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . DataOverrun ) ; break ; case VUSBSTATUS_NOT_ACCESSED : STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . NotAccessed ) ; break ; default : STAM_COUNTER_INC ( & pRh -> aStatIsocDetails [ i ] . Misc ) ; break ; } } } else { STAM_COUNTER_ADD ( & pRh -> Total . StatActBytes , pUrb -> cbData ) ; STAM_COUNTER_ADD ( & pRh -> aTypes [ pUrb -> enmType ] . StatActBytes , pUrb -> cbData ) ; if ( pUrb -> enmDir == VUSBDIRECTION_IN ) { STAM_COUNTER_ADD ( & pRh -> Total . StatActReadBytes , pUrb -> cbData ) ; STAM_COUNTER_ADD ( & pRh -> aTypes [ pUrb -> enmType ] . StatActReadBytes , pUrb -> cbData ) ; } else { STAM_COUNTER_ADD ( & pRh -> Total . StatActWriteBytes , pUrb -> cbData ) ; STAM_COUNTER_ADD ( & pRh -> aTypes [ pUrb -> enmType ] . StatActWriteBytes , pUrb -> cbData ) ; } } } else { STAM_COUNTER_INC ( & pRh -> Total . StatUrbsFailed ) ; STAM_COUNTER_INC ( & pRh -> aTypes [ pUrb -> enmType ] . StatUrbsFailed ) ; } } #endif switch ( pUrb -> enmType ) { case VUSBXFERTYPE_MSG : vusbMsgCompletion ( pUrb ) ; return ; case VUSBXFERTYPE_ISOC : break ; #if 1 default : #endif case VUSBXFERTYPE_BULK : if ( pUrb -> enmStatus != VUSBSTATUS_OK ) vusbUrbErrorRh ( pUrb ) ; break ; } #ifdef LOG_ENABLED vusbUrbTrace ( pUrb , " " , true ) ; #endif pRh -> pIRhPort -> pfnXferCompletion ( pRh -> pIRhPort , pUrb ) ; if ( pUrb -> enmState == VUSBURBSTATE_REAPED ) { LogFlow ( ( " \n " , pUrb -> pszDesc ) ) ; pUrb -> pVUsb -> pfnFree ( pUrb ) ; } vusbRhR3ProcessFrame ( pRh , true ) ; }
Does URB completion on roothub level.
Does URB completion on roothub level .
/* If there is a sniffer on the roothub record the completed URB there too. */ /*
     * Total and per-type submit statistics.
     */ /* (Note. this also counts the cancelled packets) */ /* VBOX_WITH_STATISTICS */ /*
     * Msg transfers are special virtual transfers associated with
     * vusb, not the roothub
     */ /* Don't bother with error callback for isochronous URBs. */ /** @todo r=bird: OHCI say ''If the Transfer Descriptor is being
         * retired because of an error, the Host Controller must update
         * the Halt bit of the Endpoint Descriptor.''
         *
         * So, I'll subject all transfertypes to the same halt stuff now. It could
         * just happen to fix the logitech disconnect trap in win2k.
         */ /* fCallback */