static void sf_ftime_from_timespec(time_t *time, RTTIMESPEC *ts) { int64_t t = RTTimeSpecGetNano(ts); do_div(t, 1000000000); *time = t; }
/* * sf_reg_aops and sf_backing_dev_info are just quick implementations to make * sendfile work. For more information have a look at * * http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp * * and the sample implementation * * http://pserver.samba.org/samba/ftp/cifs-cvs/samplefs.tar.gz */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) static void sf_ftime_from_timespec(time_t *time, RTTIMESPEC *ts) { int64_t t = RTTimeSpecGetNano(ts); do_div(t, 1000000000); *time = t; } static void sf_timespec_from_ftime(RTTIMESPEC *ts, time_t *time) { int64_t t = 1000000000 * *time; RTTimeSpecSetNano(ts, t); } #else /* >= 2.6.0 */ static void sf_ftime_from_timespec(struct timespec *tv, RTTIMESPEC *ts) { int64_t t = RTTimeSpecGetNano(ts); int64_t nsec; nsec = do_div(t, 1000000000); tv->tv_sec = t; tv->tv_nsec = nsec; }
void testFSInfoQuerySetFileATime(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; const int64_t ccAtimeNano = 100000; SHFLFSOBJINFO Info; SHFLHANDLE Handle; int rc; RTTestSub(hTest, "Query and set file atime"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); RT_ZERO(Info); RTTimeSpecSetNano(&testRTFileQueryInfoATime, ccAtimeNano); rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info), &Info); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, testRTFileQueryInfoFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileQueryInfoFile))); RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano, (hTest, "ATime=%llu\n", LLUIFY(RTTimeSpecGetNano(&Info.AccessTime)))); RT_ZERO(Info); RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano); rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE, sizeof(Info), &Info); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&testRTFileSetTimesATime) == ccAtimeNano, (hTest, "ATime=%llu\n", LLUIFY(RTTimeSpecGetNano(&testRTFileSetTimesATime)))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); }
int main() { RTTIMESPEC Now; RTTIMESPEC Ts1; RTTIMESPEC Ts2; RTTIME T1; RTTIME T2; #ifdef RTTIME_INCL_TIMEVAL struct timeval Tv1; struct timeval Tv2; struct timespec Tsp1; struct timespec Tsp2; #endif RTTEST hTest; int rc = RTTestInitAndCreate("tstRTTimeSpec", &hTest); if (rc) return rc; /* * Simple test with current time. */ RTTestSub(hTest, "Current time (UTC)"); CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Simple test with current local time. */ RTTestSub(hTest, "Current time (local)"); CHECK_NZ(RTTimeLocalNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Some simple tests with fixed dates (just checking for smoke). */ RTTestSub(hTest, "Smoke"); TEST_NS(INT64_C(0)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(86400000000000)); CHECK_TIME(&T1, 1970,01,02, 00,00,00, 0, 2, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(-1)); CHECK_TIME(&T1, 1969,12,31, 23,59,59,999999999, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Test the limits. */ RTTestSub(hTest, "Extremes"); TEST_NS(INT64_MAX); TEST_NS(INT64_MIN); TEST_SEC(1095379198); CHECK_TIME(&T1, 2004, 9,16, 23,59,58, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379199); CHECK_TIME(&T1, 2004, 9,16, 23,59,59, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379200); CHECK_TIME(&T1, 2004, 9,17, 00,00,00, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379201); CHECK_TIME(&T1, 2004, 9,17, 00,00,01, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); /* * Test normalization (UTC). */ RTTestSub(hTest, "Normalization (UTC)"); /* simple */ CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); T2 = T1; CHECK_NZ(RTTimeNormalize(&T1)); if (memcmp(&T1, &T2, sizeof(T1))) RTTestIFailed("simple normalization failed\n"); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); CHECK_NZ(RTTimeSpecIsEqual(&Ts1, &Now)); /* a few partial dates. */ memset(&T1, 0, sizeof(T1)); SET_TIME( &T1, 1970,01,01, 00,00,00, 0, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1970,00,00, 00,00,00, 1, 1, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,12,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1968,01,30, 00,19,24, 5, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1968,01,30, 00,19,24, 5, 30, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 1969,01,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,01,31, 00, 9, 2, 7, 31, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,03,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,03,31, 00, 9, 2, 7, 90, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,31, 00,00,00, 9, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,31, 00,00,00, 9, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,30, 00,00,00, 30, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,30, 00,00,00, 30, 364, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 363, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,29, 00,00,00, 30, 363, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 362, 6, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,28, 00,00,00, 30, 362, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,27, 00,00,00, 30, 0, 5, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,27, 00,00,00, 30, 361, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 360, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,26, 00,00,00, 30, 360, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,25, 00,00,00, 12, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,25, 00,00,00, 12, 359, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,24, 00,00,00, 16, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,24, 00,00,00, 16, 358, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* outside the year table range */ SET_TIME( &T1, 1200,01,30, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1200,01,30, 00,00,00, 2, 30, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2555,11,29, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 2, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2555,00,00, 00,00,00, 3, 333, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 3, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* time overflow */ SET_TIME( &T1, 1969,12,30, 255,255,255, UINT32_MAX, 364, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01, 9, 19,19,19,294967295, 9, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* date overflow */ SET_TIME( &T1, 2007,11,36, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,67, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,98, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2006,24,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2003,60,37, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2003,00,00, 02,15,23, 1,1801, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Conversions. */ #define CHECK_NSEC(Ts1, T2) \ do { \ RTTIMESPEC TsTmp; \ RTTESTI_CHECK_MSG( RTTimeSpecGetNano(&(Ts1)) == RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2))), \ ("line %d: %RI64, %RI64\n", __LINE__, \ RTTimeSpecGetNano(&(Ts1)), RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2)))) ); \ } while (0) RTTestSub(hTest, "Conversions, positive"); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetDosSeconds(&Ts2, 0) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetDosSeconds(&Ts2) == 0); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetNtTime(&Ts2, INT64_C(119600064000000000)) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNtTime(&Ts2) == INT64_C(119600064000000000)); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetSeconds(&Ts2, 1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetSeconds(&Ts2) == 1); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMilli(&Ts2, 1000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMilli(&Ts2) == 1000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMicro(&Ts2, 1000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetNano(&Ts2, 1000000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000000); CHECK_NSEC(Ts2, T1); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1970,01,01, 00,00,01, 5000, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = 1; Tv1.tv_usec = 5; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1970,01,01, 00,00,01, 5, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = 1; Tsp1.tv_nsec = 5; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif RTTestSub(hTest, "Conversions, negative"); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1969,12,31, 23,59,58,999995000, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = -2; Tv1.tv_usec = 999995; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetMicro(&Ts2) == -1000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1969,12,31, 23,59,58,999999995, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = -2; Tsp1.tv_nsec = 999999995; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetNano(&Ts2) == -1000000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }
/** * Records an VUSB event. * * @returns VBox status code. * @param hSniffer The sniffer instance. * @param pUrb The URB triggering the event. * @param enmEvent The type of event to record. */ DECLHIDDEN(int) VUSBSnifferRecordEvent(VUSBSNIFFER hSniffer, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent) { int rc = VINF_SUCCESS; PVUSBSNIFFERINT pThis = hSniffer; DumpFileEpb Epb; DumpFileUsbHeaderLnxMmapped UsbHdr; DumpFileUsbSetup UsbSetup; RTTIMESPEC TimeNow; uint64_t u64TimestampEvent; size_t cbUrbLength = 0; uint32_t cbDataLength = 0; uint32_t cbCapturedLength = sizeof(UsbHdr); uint32_t cIsocPkts = 0; uint8_t *pbData = NULL; RTTimeNow(&TimeNow); u64TimestampEvent = RTTimeSpecGetNano(&TimeNow); /* Start with the enhanced packet block. */ Epb.Hdr.u32BlockType = DUMPFILE_EPB_BLOCK_TYPE; Epb.Hdr.u32BlockTotalLength = 0; Epb.u32InterfaceId = 0; Epb.u32TimestampHigh = (u64TimestampEvent >> 32) & UINT32_C(0xffffffff); Epb.u32TimestampLow = u64TimestampEvent & UINT32_C(0xffffffff); UsbHdr.u64Id = (uint64_t)pUrb; /** @todo: check whether the pointer is a good ID. */ switch (enmEvent) { case VUSBSNIFFEREVENT_SUBMIT: UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_SUBMIT; cbUrbLength = pUrb->cbData; break; case VUSBSNIFFEREVENT_COMPLETE: UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_COMPLETE; cbUrbLength = pUrb->cbData; break; case VUSBSNIFFEREVENT_ERROR_SUBMIT: case VUSBSNIFFEREVENT_ERROR_COMPLETE: UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_ERROR; break; default: AssertMsgFailed(("Invalid event type %d\n", enmEvent)); } cbDataLength = cbUrbLength; pbData = &pUrb->abData[0]; switch (pUrb->enmType) { case VUSBXFERTYPE_ISOC: { int32_t i32ErrorCount = 0; UsbHdr.u8TransferType = 0; cIsocPkts = pUrb->cIsocPkts; for (unsigned i = 0; i < cIsocPkts; i++) if ( pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED) i32ErrorCount++; UsbHdr.u.IsoRec.i32ErrorCount = i32ErrorCount; UsbHdr.u.IsoRec.i32NumDesc = pUrb->cIsocPkts; cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc); break; } case VUSBXFERTYPE_BULK: UsbHdr.u8TransferType = 3; break; case VUSBXFERTYPE_INTR: UsbHdr.u8TransferType = 1; break; case VUSBXFERTYPE_CTRL: case VUSBXFERTYPE_MSG: UsbHdr.u8TransferType = 2; break; default: AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType)); } if (pUrb->enmDir == VUSBDIRECTION_IN) { if (enmEvent == VUSBSNIFFEREVENT_SUBMIT) cbDataLength = 0; } else if (pUrb->enmDir == VUSBDIRECTION_OUT) { if ( enmEvent == VUSBSNIFFEREVENT_COMPLETE || pUrb->enmType == VUSBXFERTYPE_CTRL || pUrb->enmType == VUSBXFERTYPE_MSG) cbDataLength = 0; } else if (pUrb->enmDir == VUSBDIRECTION_SETUP) cbDataLength -= sizeof(VUSBSETUP); Epb.u32CapturedLen = cbCapturedLength + cbDataLength; Epb.u32PacketLen = cbCapturedLength + cbUrbLength; UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00); UsbHdr.u8DeviceAddress = pUrb->DstAddress; UsbHdr.u16BusId = 0; UsbHdr.u8DataFlag = cbDataLength ? 0 : 1; UsbHdr.u64TimestampSec = u64TimestampEvent / RT_NS_1SEC_64; UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC; UsbHdr.i32Status = pUrb->enmStatus; UsbHdr.u32UrbLength = cbUrbLength; UsbHdr.u32DataLength = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc); UsbHdr.i32Interval = 0; UsbHdr.i32StartFrame = 0; UsbHdr.u32XferFlags = 0; UsbHdr.u32NumDesc = cIsocPkts; if ( (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL) && enmEvent == VUSBSNIFFEREVENT_SUBMIT) { PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData; UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType; UsbHdr.u.UsbSetup.bRequest = pSetup->bRequest; UsbHdr.u.UsbSetup.wValue = pSetup->wValue; UsbHdr.u.UsbSetup.wIndex = pSetup->wIndex; UsbHdr.u.UsbSetup.wLength = pSetup->wLength; UsbHdr.u8SetupFlag = 0; } else UsbHdr.u8SetupFlag = '-'; /* Follow usbmon source here. */ /* Write the packet to the capture file. */ rc = RTSemFastMutexRequest(pThis->hMtx); if (RT_SUCCESS(rc)) { rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb)); if (RT_SUCCESS(rc)) rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr)); /* Add Isochronous descriptors now. */ for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++) { DumpFileUsbIsoDesc IsoDesc; IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus; IsoDesc.u32Offset = pUrb->aIsocPkts[i].off; IsoDesc.u32Len = pUrb->aIsocPkts[i].cb; rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc)); } /* Record data. */ if ( RT_SUCCESS(rc) && cbDataLength) rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength); if (RT_SUCCESS(rc)) rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0); if (RT_SUCCESS(rc)) rc = vusbSnifferBlockCommit(pThis); RTSemFastMutexRelease(pThis->hMtx); } return rc; }