Пример #1
0
DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags,
                                  const char *pszCaptureFilename, const char *pszDesc)
{
    int rc = VINF_SUCCESS;
    PVUSBSNIFFERINT pThis = NULL;

    pThis = (PVUSBSNIFFERINT)RTMemAllocZ(sizeof(VUSBSNIFFERINT));
    if (pThis)
    {
        pThis->hFile       = NIL_RTFILE;
        pThis->cbBlockCur  = 0;
        pThis->cbBlockMax  = 0;
        pThis->pbBlockData = NULL;
        pThis->hMtx        = NIL_RTSEMFASTMUTEX;

        rc = RTSemFastMutexCreate(&pThis->hMtx);
        if (RT_SUCCESS(rc))
        {
            rc = RTFileOpen(&pThis->hFile, pszCaptureFilename, RTFILE_O_DENY_NONE | RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_READ);
            if (RT_SUCCESS(rc))
            {
                /* Write header and link type blocks. */
                DumpFileShb Shb;

                Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
                Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
                Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
                Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
                Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
                Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */

                /* Write the blocks. */
                rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
                if (RT_SUCCESS(rc))
                {
                    const char *pszOpt = RTBldCfgTargetDotArch();
                    rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
                }

                if (RT_SUCCESS(rc))
                {
                    char szTmp[512];
                    size_t cbTmp = sizeof(szTmp);

                    RT_ZERO(szTmp);

                    /* Build the OS code. */
                    rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
                    if (RT_SUCCESS(rc))
                    {
                        size_t cb = strlen(szTmp);

                        szTmp[cb] = ' ';
                        rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
                        if (RT_SUCCESS(rc))
                        {
                            cb = strlen(szTmp);
                            szTmp[cb] = ' ';
                            rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
                        }
                    }

                    if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
                        rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
                    else
                        rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
                }

                if (RT_SUCCESS(rc))
                {
                    /** @todo: Add product info. */
                }

                if (RT_SUCCESS(rc))
                    rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
                if (RT_SUCCESS(rc))
                    rc = vusbSnifferBlockCommit(pThis);

                /* Write Interface descriptor block. */
                if (RT_SUCCESS(rc))
                {
                    DumpFileIdb Idb;

                    Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
                    Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
                    Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
                    Idb.u16Reserved             = 0;
                    Idb.u32SnapLen              = UINT32_C(0xffffffff);

                    rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
                    if (RT_SUCCESS(rc))
                    {
                        uint8_t u8TsResolution = 9; /* Nano second resolution. */
                        /* Add timestamp resolution option. */
                        rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
                                                  &u8TsResolution, sizeof(u8TsResolution));
                    }
                    if (RT_SUCCESS(rc))
                        rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
                    if (RT_SUCCESS(rc))
                        rc = vusbSnifferBlockCommit(pThis);
                }

                if (RT_SUCCESS(rc))
                {
                    *phSniffer = pThis;
                    return VINF_SUCCESS;
                }

                RTFileClose(pThis->hFile);
                pThis->hFile = NIL_RTFILE;
                RTFileDelete(pszCaptureFilename);
            }
            RTSemFastMutexDestroy(pThis->hMtx);
            pThis->hMtx = NIL_RTSEMFASTMUTEX;
        }
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}
Пример #2
0
/**
 * 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;
}
Пример #3
0
/** @copydoc VUSBSNIFFERFMT::pfnInit */
static DECLCALLBACK(int) vusbSnifferFmtPcanNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
{
    int rc = VINF_SUCCESS;

    pThis->pStrm       = pStrm;
    pThis->cbBlockCur  = 0;
    pThis->cbBlockMax  = 0;
    pThis->pbBlockData = NULL;

    /* Write header and link type blocks. */
    DumpFileShb Shb;

    Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
    Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
    Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
    Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
    Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */

    /* Write the blocks. */
    rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
    if (RT_SUCCESS(rc))
    {
        const char *pszOpt = RTBldCfgTargetDotArch();
        rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
    }

    if (RT_SUCCESS(rc))
    {
        char szTmp[512];
        size_t cbTmp = sizeof(szTmp);

        RT_ZERO(szTmp);

        /* Build the OS code. */
        rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
        if (RT_SUCCESS(rc))
        {
            size_t cb = strlen(szTmp);

            szTmp[cb] = ' ';
            rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
            if (RT_SUCCESS(rc))
            {
                cb = strlen(szTmp);
                szTmp[cb] = ' ';
                rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
            }
        }

        if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
            rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
        else
            rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
    }

    if (RT_SUCCESS(rc))
    {
        /** @todo: Add product info. */
    }

    if (RT_SUCCESS(rc))
        rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    if (RT_SUCCESS(rc))
        rc = vusbSnifferBlockCommit(pThis);

    /* Write Interface descriptor block. */
    if (RT_SUCCESS(rc))
    {
        DumpFileIdb Idb;

        Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
        Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
        Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
        Idb.u16Reserved             = 0;
        Idb.u32SnapLen              = UINT32_C(0xffffffff);

        rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
        if (RT_SUCCESS(rc))
        {
            uint8_t u8TsResolution = 9; /* Nano second resolution. */
            /* Add timestamp resolution option. */
            rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
                                      &u8TsResolution, sizeof(u8TsResolution));
        }
        if (RT_SUCCESS(rc))
            rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
        if (RT_SUCCESS(rc))
            rc = vusbSnifferBlockCommit(pThis);
    }

    if (   RT_FAILURE(rc)
        && pThis->pbBlockData)
        RTMemFree(pThis->pbBlockData);

    return rc;
}