~ubuntu-branches/ubuntu/precise/virtualbox/precise-updates

« back to all changes in this revision

Viewing changes to src/VBox/Devices/USB/VUSBDevice.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-07-04 13:02:31 UTC
  • mfrom: (3.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110704130231-l843es6wqhx614n7
Tags: 4.0.10-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Add the Modaliases control field manually for maximum backportability.

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
    PFNVUSBRESETDONE    pfnDone;
58
58
    /** User argument to pfnDone. */
59
59
    void               *pvUser;
60
 
    /** The timer used to notify EMT. */
61
 
    PTMTIMER            pTimer;
62
60
} VUSBRESETARGS, *PVUSBRESETARGS;
63
61
 
64
62
 
1167
1165
        {
1168
1166
            PVUSBRESETARGS pArgs = (PVUSBRESETARGS)pDev->pvResetArgs;
1169
1167
            Assert(pArgs->pDev == pDev);
1170
 
            TMR3TimerDestroy(pArgs->pTimer);
1171
 
            pArgs->pTimer = NULL;
1172
1168
            RTMemTmpFree(pArgs);
1173
1169
 
1174
1170
            pDev->hResetThread = NIL_RTTHREAD;
1184
1180
        vusbDevDetach(pDev);
1185
1181
    RTMemFree(pDev->paIfStates);
1186
1182
    pDev->enmState = VUSB_DEVICE_STATE_DESTROYED;
 
1183
    TMR3TimerDestroy(pDev->pResetTimer);
1187
1184
}
1188
1185
 
1189
1186
 
1251
1248
/**
1252
1249
 * Timer callback for doing reset completion.
1253
1250
 *
 
1251
 * @param   pUsbIns     The USB device instance.
 
1252
 * @param   pTimer      The timer instance.
 
1253
 * @param   pvUser      The VUSB device data.
1254
1254
 * @thread EMT
1255
1255
 */
1256
 
static DECLCALLBACK(void) vusbDevResetDoneTimer(void *pvUser)
 
1256
static DECLCALLBACK(void) vusbDevResetDoneTimer(PPDMUSBINS pUsbIns, PTMTIMER pTimer, void *pvUser)
1257
1257
{
1258
 
    PVUSBRESETARGS pArgs = (PVUSBRESETARGS)pvUser;
1259
 
    PVUSBDEV pDev = pArgs->pDev;
1260
 
    Assert(pDev->pvResetArgs == pArgs);
 
1258
    PVUSBDEV        pDev  = (PVUSBDEV)pvUser;
 
1259
    PVUSBRESETARGS  pArgs = (PVUSBRESETARGS)pDev->pvResetArgs;
 
1260
    AssertPtr(pArgs); Assert(pArgs->pDev == pDev); Assert(pDev->pUsbIns == pUsbIns);
1261
1261
 
1262
1262
    /*
1263
1263
     * Release the thread and update the device structure.
1265
1265
    int rc = RTThreadWait(pDev->hResetThread, 2, NULL);
1266
1266
    AssertRC(rc);
1267
1267
    pDev->hResetThread = NIL_RTTHREAD;
1268
 
    pDev->pvResetArgs = NULL;
 
1268
    pDev->pvResetArgs  = NULL;
1269
1269
 
1270
1270
    /*
1271
1271
     * Reset-done processing and cleanup.
1272
1272
     */
1273
1273
    vusbDevResetDone(pArgs->pDev, pArgs->rc, pArgs->pfnDone, pArgs->pvUser);
1274
1274
 
1275
 
    TMR3TimerDestroy(pArgs->pTimer);
1276
1275
    RTMemTmpFree(pArgs);
1277
1276
}
1278
1277
 
1290
1289
static DECLCALLBACK(int) vusbDevResetThread(RTTHREAD Thread, void *pvUser)
1291
1290
{
1292
1291
    PVUSBRESETARGS  pArgs = (PVUSBRESETARGS)pvUser;
 
1292
    PVUSBDEV        pDev  = pArgs->pDev;
1293
1293
    LogFlow(("vusb: reset thread started\n"));
1294
1294
 
1295
1295
    /*
1296
1296
     * Tell EMT that we're in flow and then perform the reset.
1297
1297
     */
1298
 
    uint64_t u64EndTS = TMTimerGet(pArgs->pTimer) + TMTimerFromMilli(pArgs->pTimer, 10);
 
1298
    uint64_t u64EndTS = TMTimerGet(pDev->pResetTimer) + TMTimerFromMilli(pDev->pResetTimer, 10);
1299
1299
    RTThreadUserSignal(Thread);
1300
1300
 
1301
 
    int rc = pArgs->rc = vusbDevResetWorker(pArgs->pDev, pArgs->fResetOnLinux);
 
1301
    int rc = pArgs->rc = vusbDevResetWorker(pDev, pArgs->fResetOnLinux);
1302
1302
 
1303
1303
    /*
1304
1304
     * We use a timer to communicate the result back to EMT.
1305
1305
     * This avoids suspend + poweroff issues, and it should give
1306
1306
     * us more accurate scheduling than making this thread sleep.
1307
1307
     */
1308
 
    int rc2 = TMTimerSet(pArgs->pTimer, u64EndTS);
 
1308
    int rc2 = TMTimerSet(pDev->pResetTimer, u64EndTS);
1309
1309
    AssertReleaseRC(rc2);
1310
1310
 
1311
1311
    LogFlow(("vusb: reset thread exiting, rc=%Rrc\n", rc));
1317
1317
 * Resets a device.
1318
1318
 *
1319
1319
 * Since a device reset shall take at least 10ms from the guest point of view,
1320
 
 * it must be performed asynchronously. We create a thread which performs this
 
1320
 * it must be performed asynchronously.  We create a thread which performs this
1321
1321
 * operation and ensures it will take at least 10ms.
1322
1322
 *
1323
1323
 * At times - like init - a synchronous reset is required, this can be done
1370
1370
        PVUSBRESETARGS pArgs = (PVUSBRESETARGS)RTMemTmpAlloc(sizeof(*pArgs));
1371
1371
        if (pArgs)
1372
1372
        {
1373
 
            pArgs->pTimer = TMR3TimerCreateExternal(pVM, TMCLOCK_VIRTUAL, vusbDevResetDoneTimer, pArgs, "USB Device Reset Timer.");
1374
 
            if (pArgs->pTimer)
 
1373
            pDev->pvResetArgs = pArgs;
 
1374
            pArgs->pDev = pDev;
 
1375
            pArgs->fResetOnLinux = fResetOnLinux;
 
1376
            pArgs->rc = VERR_INTERNAL_ERROR;
 
1377
            pArgs->pfnDone = pfnDone;
 
1378
            pArgs->pvUser = pvUser;
 
1379
            int rc = RTThreadCreate(&pDev->hResetThread, vusbDevResetThread, pArgs, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "USBRESET");
 
1380
            if (RT_SUCCESS(rc))
1375
1381
            {
1376
 
                pDev->pvResetArgs = pArgs;
1377
 
                pArgs->pDev = pDev;
1378
 
                pArgs->fResetOnLinux = fResetOnLinux;
1379
 
                pArgs->rc = VERR_INTERNAL_ERROR;
1380
 
                pArgs->pfnDone = pfnDone;
1381
 
                pArgs->pvUser = pvUser;
1382
 
                int rc = RTThreadCreate(&pDev->hResetThread, vusbDevResetThread, pArgs, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "USBRESET");
1383
 
                if (RT_SUCCESS(rc))
1384
 
                {
1385
 
                    /* give the thread a chance to get started. */
1386
 
                    RTThreadUserWait(pDev->hResetThread, 2);
1387
 
                    return rc;
1388
 
                }
 
1382
                /* give the thread a chance to get started. */
 
1383
                RTThreadUserWait(pDev->hResetThread, 2);
 
1384
                return rc;
 
1385
            }
1389
1386
 
1390
 
                pDev->pvResetArgs = NULL;
1391
 
                pDev->hResetThread = NIL_RTTHREAD;
1392
 
                TMR3TimerDestroy(pArgs->pTimer);
1393
 
            }
 
1387
            pDev->pvResetArgs  = NULL;
 
1388
            pDev->hResetThread = NIL_RTTHREAD;
1394
1389
            RTMemTmpFree(pArgs);
1395
1390
        }
1396
1391
        /* fall back to sync on failure */
1553
1548
    memset(&pDev->aPipes[0], 0, sizeof(pDev->aPipes));
1554
1549
    pDev->hResetThread = NIL_RTTHREAD;
1555
1550
    pDev->pvResetArgs = NULL;
 
1551
    pDev->pResetTimer = NULL;
 
1552
 
 
1553
    /*
 
1554
     * Create the reset timer.
 
1555
     */
 
1556
    int rc = PDMUsbHlpTMTimerCreate(pUsbIns, TMCLOCK_VIRTUAL, vusbDevResetDoneTimer, pDev, 0 /*fFlags*/,
 
1557
                                    "USB Device Reset Timer",  &pDev->pResetTimer);
 
1558
    AssertRCReturn(rc, rc);
1556
1559
 
1557
1560
    /*
1558
1561
     * Get the descriptor cache from the device. (shall cannot fail)