57
57
PFNVUSBRESETDONE pfnDone;
58
58
/** User argument to pfnDone. */
60
/** The timer used to notify EMT. */
62
60
} VUSBRESETARGS, *PVUSBRESETARGS;
1252
1249
* Timer callback for doing reset completion.
1251
* @param pUsbIns The USB device instance.
1252
* @param pTimer The timer instance.
1253
* @param pvUser The VUSB device data.
1256
static DECLCALLBACK(void) vusbDevResetDoneTimer(void *pvUser)
1256
static DECLCALLBACK(void) vusbDevResetDoneTimer(PPDMUSBINS pUsbIns, PTMTIMER pTimer, void *pvUser)
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);
1263
1263
* Release the thread and update the device structure.
1265
1265
int rc = RTThreadWait(pDev->hResetThread, 2, NULL);
1267
1267
pDev->hResetThread = NIL_RTTHREAD;
1268
pDev->pvResetArgs = NULL;
1268
pDev->pvResetArgs = NULL;
1271
1271
* Reset-done processing and cleanup.
1273
1273
vusbDevResetDone(pArgs->pDev, pArgs->rc, pArgs->pfnDone, pArgs->pvUser);
1275
TMR3TimerDestroy(pArgs->pTimer);
1276
1275
RTMemTmpFree(pArgs);
1290
1289
static DECLCALLBACK(int) vusbDevResetThread(RTTHREAD Thread, void *pvUser)
1292
1291
PVUSBRESETARGS pArgs = (PVUSBRESETARGS)pvUser;
1292
PVUSBDEV pDev = pArgs->pDev;
1293
1293
LogFlow(("vusb: reset thread started\n"));
1296
1296
* Tell EMT that we're in flow and then perform the reset.
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);
1301
int rc = pArgs->rc = vusbDevResetWorker(pArgs->pDev, pArgs->fResetOnLinux);
1301
int rc = pArgs->rc = vusbDevResetWorker(pDev, pArgs->fResetOnLinux);
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.
1308
int rc2 = TMTimerSet(pArgs->pTimer, u64EndTS);
1308
int rc2 = TMTimerSet(pDev->pResetTimer, u64EndTS);
1309
1309
AssertReleaseRC(rc2);
1311
1311
LogFlow(("vusb: reset thread exiting, rc=%Rrc\n", rc));
1317
1317
* Resets a device.
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.
1323
1323
* At times - like init - a synchronous reset is required, this can be done
1370
1370
PVUSBRESETARGS pArgs = (PVUSBRESETARGS)RTMemTmpAlloc(sizeof(*pArgs));
1373
pArgs->pTimer = TMR3TimerCreateExternal(pVM, TMCLOCK_VIRTUAL, vusbDevResetDoneTimer, pArgs, "USB Device Reset Timer.");
1373
pDev->pvResetArgs = pArgs;
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");
1376
pDev->pvResetArgs = pArgs;
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");
1385
/* give the thread a chance to get started. */
1386
RTThreadUserWait(pDev->hResetThread, 2);
1382
/* give the thread a chance to get started. */
1383
RTThreadUserWait(pDev->hResetThread, 2);
1390
pDev->pvResetArgs = NULL;
1391
pDev->hResetThread = NIL_RTTHREAD;
1392
TMR3TimerDestroy(pArgs->pTimer);
1387
pDev->pvResetArgs = NULL;
1388
pDev->hResetThread = NIL_RTTHREAD;
1394
1389
RTMemTmpFree(pArgs);
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;
1554
* Create the reset timer.
1556
int rc = PDMUsbHlpTMTimerCreate(pUsbIns, TMCLOCK_VIRTUAL, vusbDevResetDoneTimer, pDev, 0 /*fFlags*/,
1557
"USB Device Reset Timer", &pDev->pResetTimer);
1558
AssertRCReturn(rc, rc);
1558
1561
* Get the descriptor cache from the device. (shall cannot fail)