VirtualBox

Changeset 59633 in vbox for trunk/src/VBox/Devices/USB


Ignore:
Timestamp:
Feb 10, 2016 3:39:58 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
105476
Message:

USB/Sniffer: Add format writers for Linux usbmon ASCII output and VMware debug logs so analyzing logs with vusb-analyzer is possible

Location:
trunk/src/VBox/Devices/USB
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/USB/VUSBSniffer.cpp

    r59615 r59633  
    6666static PCVUSBSNIFFERFMT s_aVUsbSnifferFmts[] =
    6767{
    68     &g_VUsbSnifferFmtPcapNg
     68    &g_VUsbSnifferFmtPcapNg,
     69    &g_VUsbSnifferFmtUsbMon,
     70    &g_VUsbSnifferFmtVmx,
    6971};
    7072
  • trunk/src/VBox/Devices/USB/VUSBSnifferInternal.h

    r59616 r59633  
    100100/** VMware VMX log format writer. */
    101101extern const VUSBSNIFFERFMT g_VUsbSnifferFmtVmx;
     102/** Linux UsbMon log format writer. */
     103extern const VUSBSNIFFERFMT g_VUsbSnifferFmtUsbMon;
    102104
    103105RT_C_DECLS_END
  • trunk/src/VBox/Devices/USB/VUSBSnifferUsbMon.cpp

    r59615 r59633  
    11/* $Id$ */
    22/** @file
    3  * Virtual USB Sniffer facility - PCAP-NG format writer.
     3 * Virtual USB Sniffer facility - Linux usbmon ASCII format.
    44 */
    55
    66/*
    7  * Copyright (C) 2014-2016 Oracle Corporation
     7 * Copyright (C) 2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3535*********************************************************************************************************************************/
    3636
    37 /** DumpFile Section Header Block type. */
    38 #define DUMPFILE_SHB_BLOCK_TYPE       UINT32_C(0x0a0d0d0a)
    39 /** The byte order magic value. */
    40 #define DUMPFILE_SHB_BYTE_ORDER_MAGIC UINT32_C(0x1a2b3c4d)
    41 /** Current major version. */
    42 #define DUMPFILE_SHB_VERSION_MAJOR    UINT16_C(1)
    43 /** Current minor version. */
    44 #define DUMPFILE_SHB_VERSION_MINOR    UINT16_C(0)
    45 
    46 /** Block type for the interface descriptor block. */
    47 #define DUMPFILE_IDB_BLOCK_TYPE       UINT32_C(0x00000001)
    48 /** USB link type. */
    49 #define DUMPFILE_IDB_LINK_TYPE_USB_LINUX        UINT16_C(189)
    50 #define DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED UINT16_C(220)
    51 
    52 /** Block type for an enhanced packet block. */
    53 #define DUMPFILE_EPB_BLOCK_TYPE       UINT32_C(0x00000006)
    54 
    55 /** USB packet event types. */
    56 #define DUMPFILE_USB_EVENT_TYPE_SUBMIT   ('S')
    57 #define DUMPFILE_USB_EVENT_TYPE_COMPLETE ('C')
    58 #define DUMPFILE_USB_EVENT_TYPE_ERROR    ('E')
    59 
    60 #define DUMPFILE_OPTION_CODE_END      UINT16_C(0)
    61 #define DUMPFILE_OPTION_CODE_COMMENT  UINT16_C(1)
    62 
    63 #define DUMPFILE_OPTION_CODE_HARDWARE UINT16_C(2)
    64 #define DUMPFILE_OPTION_CODE_OS       UINT16_C(3)
    65 #define DUMPFILE_OPTION_CODE_USERAPP  UINT16_C(4)
    66 
    67 #define DUMPFILE_IDB_OPTION_TS_RESOLUTION UINT16_C(9)
    68 
    69 
    70 /*********************************************************************************************************************************
    71 *   DumpFile format structures                                                                                                   *
    72 *********************************************************************************************************************************/
    73 
    74 /**
    75  * DumpFile Block header.
    76  */
    77 typedef struct DumpFileBlockHdr
    78 {
    79     /** Block type. */
    80     uint32_t            u32BlockType;
    81     /** Block total length. */
    82     uint32_t            u32BlockTotalLength;
    83 } DumpFileBlockHdr;
    84 /** Pointer to a block header. */
    85 typedef DumpFileBlockHdr *PDumpFileBlockHdr;
    86 
    87 /**
    88  * DumpFile Option header.
    89  */
    90 typedef struct DumpFileOptionHdr
    91 {
    92     /** Option code. */
    93     uint16_t            u16OptionCode;
    94     /** Block total length. */
    95     uint16_t            u16OptionLength;
    96 } DumpFileOptionHdr;
    97 /** Pointer to a option header. */
    98 typedef DumpFileOptionHdr *PDumpFileOptionHdr;
    99 
    100 /**
    101  * DumpFile Section Header Block.
    102  */
    103 typedef struct DumpFileShb
    104 {
    105     /** Block header. */
    106     DumpFileBlockHdr    Hdr;
    107     /** Byte order magic. */
    108     uint32_t            u32ByteOrderMagic;
    109     /** Major version. */
    110     uint16_t            u16VersionMajor;
    111     /** Minor version. */
    112     uint16_t            u16VersionMinor;
    113     /** Section length. */
    114     uint64_t            u64SectionLength;
    115 } DumpFileShb;
    116 /** Pointer to a Section Header Block. */
    117 typedef DumpFileShb *PDumpFileShb;
    118 
    119 /**
    120  * DumpFile Interface description block.
    121  */
    122 typedef struct DumpFileIdb
    123 {
    124     /** Block header. */
    125     DumpFileBlockHdr    Hdr;
    126     /** Link type. */
    127     uint16_t            u16LinkType;
    128     /** Reserved. */
    129     uint16_t            u16Reserved;
    130     /** Maximum number of bytes dumped from each packet. */
    131     uint32_t            u32SnapLen;
    132 } DumpFileIdb;
    133 /** Pointer to an Interface description block. */
    134 typedef DumpFileIdb *PDumpFileIdb;
    135 
    136 /**
    137  * DumpFile Enhanced packet block.
    138  */
    139 typedef struct DumpFileEpb
    140 {
    141     /** Block header. */
    142     DumpFileBlockHdr    Hdr;
    143     /** Interface ID. */
    144     uint32_t            u32InterfaceId;
    145     /** Timestamp (high). */
    146     uint32_t            u32TimestampHigh;
    147     /** Timestamp (low). */
    148     uint32_t            u32TimestampLow;
    149     /** Captured packet length. */
    150     uint32_t            u32CapturedLen;
    151     /** Original packet length. */
    152     uint32_t            u32PacketLen;
    153 } DumpFileEpb;
    154 /** Pointer to an Enhanced packet block. */
    155 typedef DumpFileEpb *PDumpFileEpb;
    156 
    157 /**
    158  * USB setup URB data.
    159  */
    160 typedef struct DumpFileUsbSetup
    161 {
    162     uint8_t    bmRequestType;
    163     uint8_t    bRequest;
    164     uint16_t   wValue;
    165     uint16_t   wIndex;
    166     uint16_t   wLength;
    167 } DumpFileUsbSetup;
    168 typedef DumpFileUsbSetup *PDumpFileUsbSetup;
    169 
    170 /**
    171  * USB Isochronous data.
    172  */
    173 typedef struct DumpFileIsoRec
    174 {
    175     int32_t    i32ErrorCount;
    176     int32_t    i32NumDesc;
    177 } DumpFileIsoRec;
    178 typedef DumpFileIsoRec *PDumpFileIsoRec;
    179 
    180 /**
    181  * USB packet header (Linux mmapped variant).
    182  */
    183 typedef struct DumpFileUsbHeaderLnxMmapped
    184 {
    185     /** Packet Id. */
    186     uint64_t    u64Id;
    187     /** Event type. */
    188     uint8_t     u8EventType;
    189     /** Transfer type. */
    190     uint8_t     u8TransferType;
    191     /** Endpoint number. */
    192     uint8_t     u8EndpointNumber;
    193     /** Device address. */
    194     uint8_t     u8DeviceAddress;
    195     /** Bus id. */
    196     uint16_t    u16BusId;
    197     /** Setup flag != 0 if the URB setup header is not present. */
    198     uint8_t     u8SetupFlag;
    199     /** Data present flag != 0 if the URB data is not present. */
    200     uint8_t     u8DataFlag;
    201     /** Timestamp (second part). */
    202     uint64_t    u64TimestampSec;
    203     /** Timestamp (us part). */
    204     uint32_t    u32TimestampUSec;
    205     /** Status. */
    206     int32_t     i32Status;
    207     /** URB length. */
    208     uint32_t    u32UrbLength;
    209     /** Recorded data length. */
    210     uint32_t    u32DataLength;
    211     /** Union of data for different URB types. */
    212     union
    213     {
    214         DumpFileUsbSetup    UsbSetup;
    215         DumpFileIsoRec      IsoRec;
    216     } u;
    217     int32_t     i32Interval;
    218     int32_t     i32StartFrame;
    219     /** Copy of transfer flags. */
    220     uint32_t    u32XferFlags;
    221     /** Number of isochronous descriptors. */
    222     uint32_t    u32NumDesc;
    223 } DumpFileUsbHeaderLnxMmapped;
    224 /** Pointer to a USB packet header. */
    225 typedef DumpFileUsbHeaderLnxMmapped *PDumpFileUsbHeaderLnxMmapped;
    226 
    227 AssertCompileSize(DumpFileUsbHeaderLnxMmapped, 64);
    228 
    229 /**
    230  * USB packet isochronous descriptor.
    231  */
    232 typedef struct DumpFileUsbIsoDesc
    233 {
    234     int32_t     i32Status;
    235     uint32_t    u32Offset;
    236     uint32_t    u32Len;
    237     uint8_t     au8Padding[4];
    238 } DumpFileUsbIsoDesc;
    239 typedef DumpFileUsbIsoDesc *PDumpFileUsbIsoDesc;
    240 
    241 
    24237/*********************************************************************************************************************************
    24338*   Structures and Typedefs                                                                                                      *
     
    25146    /** Stream handle. */
    25247    PVUSBSNIFFERSTRM  pStrm;
    253     /** Current size of the block being written. */
    254     uint32_t          cbBlockCur;
    255     /** Maximum size allocated for the block. */
    256     uint32_t          cbBlockMax;
    257     /** Current block header. */
    258     PDumpFileBlockHdr pBlockHdr;
    259     /** Pointer to the block data which will be written on commit. */
    260     uint8_t          *pbBlockData;
    26148} VUSBSNIFFERFMTINT;
    26249
     
    27158static const char *s_apszFileExts[] =
    27259{
    273     "pcap",
    274     "pcapng",
     60    "mon",
     61    "usbmon",
    27562    NULL
    27663};
     
    28168*********************************************************************************************************************************/
    28269
    283 /**
    284  * Allocates additional space for the block.
    285  *
    286  * @returns Pointer to the new unused space or NULL if out of memory.
    287  * @param   pThis           The VUSB sniffer instance.
    288  * @param   cbAdditional    The additional memory requested.
    289  */
    290 static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERFMTINT pThis, uint32_t cbAdditional)
    291 {
    292     /* Fast path where we have enough memory allocated. */
    293     if (pThis->cbBlockCur + cbAdditional <= pThis->cbBlockMax)
    294     {
    295         void *pv = pThis->pbBlockData + pThis->cbBlockCur;
    296         pThis->cbBlockCur += cbAdditional;
    297         return pv;
    298     }
    299 
    300     /* Allocate additional memory. */
    301     uint32_t cbNew = pThis->cbBlockCur + cbAdditional;
    302     uint8_t *pbDataNew = (uint8_t *)RTMemRealloc(pThis->pbBlockData, cbNew);
    303     if (pbDataNew)
    304     {
    305         pThis->pbBlockData = pbDataNew;
    306         pThis->pBlockHdr   = (PDumpFileBlockHdr)pbDataNew;
    307 
    308         void *pv = pThis->pbBlockData + pThis->cbBlockCur;
    309         pThis->cbBlockCur = cbNew;
    310         pThis->cbBlockMax = cbNew;
    311         return pv;
    312     }
    313 
    314     return NULL;
     70
     71/** @copydoc VUSBSNIFFERFMT::pfnInit */
     72static DECLCALLBACK(int) vusbSnifferFmtUsbMonInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
     73{
     74    pThis->pStrm = pStrm;
     75    return VINF_SUCCESS;
    31576}
    31677
    317 /**
    318  * Adds new data to the current block.
    319  *
    320  * @returns VBox status code.
    321  * @param   pThis           The VUSB sniffer instance.
    322  * @param   pvData          The data to add.
    323  * @param   cbData          Amount of data to add.
    324  */
    325 static int vusbSnifferBlockAddData(PVUSBSNIFFERFMTINT pThis, const void *pvData, uint32_t cbData)
    326 {
    327     int rc = VINF_SUCCESS;
    328 
    329     Assert(pThis->cbBlockCur);
    330     AssertPtr(pThis->pBlockHdr);
    331 
    332     void *pv = vusbSnifferBlockAllocSpace(pThis, cbData);
    333     if (pv)
    334         memcpy(pv, pvData, cbData);
    335     else
    336         rc = VERR_NO_MEMORY;
    337 
    338     return rc;
     78
     79/** @copydoc VUSBSNIFFERFMT::pfnDestroy */
     80static DECLCALLBACK(void) vusbSnifferFmtUsbMonDestroy(PVUSBSNIFFERFMTINT pThis)
     81{
     82
    33983}
    34084
    341 /**
    342  * Aligns the current block data to a 32bit boundary.
    343  *
    344  * @returns VBox status code.
    345  * @param   pThis           The VUSB sniffer instance.
    346  */
    347 static int vusbSnifferBlockAlign(PVUSBSNIFFERFMTINT pThis)
    348 {
    349     int rc = VINF_SUCCESS;
    350 
    351     Assert(pThis->cbBlockCur);
    352 
    353     /* Pad to 32bits. */
    354     uint8_t abPad[3] = { 0 };
    355     uint32_t cbPad = RT_ALIGN_32(pThis->cbBlockCur, 4) - pThis->cbBlockCur;
    356 
    357     Assert(cbPad <= 3);
    358     if (cbPad)
    359         rc = vusbSnifferBlockAddData(pThis, abPad, cbPad);
    360 
    361     return rc;
    362 }
    363 
    364 /**
    365  * Commits the current block to the capture file.
    366  *
    367  * @returns VBox status code.
    368  * @param   pThis           The VUSB sniffer instance.
    369  */
    370 static int vusbSnifferBlockCommit(PVUSBSNIFFERFMTINT pThis)
    371 {
    372     int rc = VINF_SUCCESS;
    373 
    374     AssertPtr(pThis->pBlockHdr);
    375 
    376     rc = vusbSnifferBlockAlign(pThis);
    377     if (RT_SUCCESS(rc))
    378     {
    379         /* Update the block total length field. */
    380         uint32_t *pcbTotalLength = (uint32_t *)vusbSnifferBlockAllocSpace(pThis, 4);
    381         if (pcbTotalLength)
    382         {
    383             *pcbTotalLength = pThis->cbBlockCur;
    384             pThis->pBlockHdr->u32BlockTotalLength = pThis->cbBlockCur;
    385 
    386             /* Write the data. */
    387             rc = pThis->pStrm->pfnWrite(pThis->pStrm, pThis->pbBlockData, pThis->cbBlockCur);
    388             pThis->cbBlockCur = 0;
    389             pThis->pBlockHdr  = NULL;
    390         }
    391         else
    392             rc = VERR_NO_MEMORY;
    393     }
    394 
    395     return rc;
    396 }
    397 
    398 /**
    399  * Starts a new block for capturing.
    400  *
    401  * @returns VBox status code.
    402  * @param   pThis           The VUSB sniffer instance.
    403  * @param   pBlockHdr       Pointer to the block header for the new block.
    404  * @param   cbData          Amount of data added with this block.
    405  */
    406 static int vusbSnifferBlockNew(PVUSBSNIFFERFMTINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)
    407 {
    408     int rc = VINF_SUCCESS;
    409 
    410     /* Validate we don't get called while another block is active. */
    411     Assert(!pThis->cbBlockCur);
    412     Assert(!pThis->pBlockHdr);
    413     pThis->pBlockHdr = (PDumpFileBlockHdr)vusbSnifferBlockAllocSpace(pThis, cbData);
    414     if (pThis->pBlockHdr)
    415         memcpy(pThis->pBlockHdr, pBlockHdr, cbData);
    416     else
    417         rc = VERR_NO_MEMORY;
    418 
    419     return rc;
    420 }
    421 
    422 /**
    423  * Add a new option to the current block.
    424  *
    425  * @returns VBox status code.
    426  * @param   pThis           The VUSB sniffer instance.
    427  * @param   u16OptionCode   The option code identifying the type of option.
    428  * @param   pvOption        Raw data for the option.
    429  * @param   cbOption        Size of the optiob data.
    430  */
    431 static int vusbSnifferAddOption(PVUSBSNIFFERFMTINT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption)
    432 {
    433     int rc = VINF_SUCCESS;
    434     DumpFileOptionHdr OptHdr;
    435 
    436     OptHdr.u16OptionCode   = u16OptionCode;
    437     OptHdr.u16OptionLength = cbOption;
    438     rc = vusbSnifferBlockAddData(pThis, &OptHdr, sizeof(OptHdr));
    439     if (   RT_SUCCESS(rc)
    440         && u16OptionCode != DUMPFILE_OPTION_CODE_END
    441         && cbOption != 0)
    442     {
    443         rc = vusbSnifferBlockAddData(pThis, pvOption, cbOption);
    444         if (RT_SUCCESS(rc))
    445             rc = vusbSnifferBlockAlign(pThis);
    446     }
    447 
    448     return rc;
    449 }
    450 
    451 
    452 /** @copydoc VUSBSNIFFERFMT::pfnInit */
    453 static DECLCALLBACK(int) vusbSnifferFmtPcanNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
    454 {
    455     int rc = VINF_SUCCESS;
    456 
    457     pThis->pStrm       = pStrm;
    458     pThis->cbBlockCur  = 0;
    459     pThis->cbBlockMax  = 0;
    460     pThis->pbBlockData = NULL;
    461 
    462     /* Write header and link type blocks. */
    463     DumpFileShb Shb;
    464 
    465     Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
    466     Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    467     Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
    468     Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
    469     Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
    470     Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */
    471 
    472     /* Write the blocks. */
    473     rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
    474     if (RT_SUCCESS(rc))
    475     {
    476         const char *pszOpt = RTBldCfgTargetDotArch();
    477         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
    478     }
    479 
    480     if (RT_SUCCESS(rc))
    481     {
    482         char szTmp[512];
    483         size_t cbTmp = sizeof(szTmp);
    484 
    485         RT_ZERO(szTmp);
    486 
    487         /* Build the OS code. */
    488         rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
    489         if (RT_SUCCESS(rc))
    490         {
    491             size_t cb = strlen(szTmp);
    492 
    493             szTmp[cb] = ' ';
    494             rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
    495             if (RT_SUCCESS(rc))
    496             {
    497                 cb = strlen(szTmp);
    498                 szTmp[cb] = ' ';
    499                 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
    500             }
    501         }
    502 
    503         if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
    504             rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
    505         else
    506             rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
    507     }
    508 
    509     if (RT_SUCCESS(rc))
    510     {
    511         /** @todo: Add product info. */
    512     }
    513 
    514     if (RT_SUCCESS(rc))
    515         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    516     if (RT_SUCCESS(rc))
    517         rc = vusbSnifferBlockCommit(pThis);
    518 
    519     /* Write Interface descriptor block. */
    520     if (RT_SUCCESS(rc))
    521     {
    522         DumpFileIdb Idb;
    523 
    524         Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
    525         Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    526         Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
    527         Idb.u16Reserved             = 0;
    528         Idb.u32SnapLen              = UINT32_C(0xffffffff);
    529 
    530         rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
    531         if (RT_SUCCESS(rc))
    532         {
    533             uint8_t u8TsResolution = 9; /* Nano second resolution. */
    534             /* Add timestamp resolution option. */
    535             rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
    536                                       &u8TsResolution, sizeof(u8TsResolution));
    537         }
    538         if (RT_SUCCESS(rc))
    539             rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    540         if (RT_SUCCESS(rc))
    541             rc = vusbSnifferBlockCommit(pThis);
    542     }
    543 
    544     if (   RT_FAILURE(rc)
    545         && pThis->pbBlockData)
    546         RTMemFree(pThis->pbBlockData);
    547 
    548     return rc;
    549 }
    550 
    551 
    552 /** @copydoc VUSBSNIFFERFMT::pfnDestroy */
    553 static DECLCALLBACK(void) vusbSnifferFmtPcanNgDestroy(PVUSBSNIFFERFMTINT pThis)
    554 {
    555     if (pThis->pbBlockData)
    556         RTMemFree(pThis->pbBlockData);
    557 }
    558 
    55985
    56086/** @copydoc VUSBSNIFFERFMT::pfnRecordEvent */
    561 static DECLCALLBACK(int) vusbSnifferFmtPcanNgRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
    562 {
    563     int rc = VINF_SUCCESS;
    564     DumpFileEpb Epb;
    565     DumpFileUsbHeaderLnxMmapped UsbHdr;
    566     DumpFileUsbSetup UsbSetup;
    567     RTTIMESPEC TimeNow;
    568     uint64_t u64TimestampEvent;
    569     size_t cbUrbLength = 0;
    570     uint32_t cbDataLength = 0;
    571     uint32_t cbCapturedLength = sizeof(UsbHdr);
    572     uint32_t cIsocPkts = 0;
    573     uint8_t *pbData = NULL;
    574 
    575     RTTimeNow(&TimeNow);
    576     u64TimestampEvent = RTTimeSpecGetNano(&TimeNow);
    577 
    578     /* Start with the enhanced packet block. */
    579     Epb.Hdr.u32BlockType        = DUMPFILE_EPB_BLOCK_TYPE;
    580     Epb.Hdr.u32BlockTotalLength = 0;
    581     Epb.u32InterfaceId          = 0;
    582     Epb.u32TimestampHigh        = (u64TimestampEvent >> 32) & UINT32_C(0xffffffff);
    583     Epb.u32TimestampLow         = u64TimestampEvent & UINT32_C(0xffffffff);
    584 
    585     UsbHdr.u64Id = (uint64_t)pUrb; /** @todo: check whether the pointer is a good ID. */
     87static DECLCALLBACK(int) vusbSnifferFmtUsbMonRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
     88{
     89    char aszLineBuf[512];
     90    char chEvtType;
     91    char chDir;
     92    char chEptType;
     93
    58694    switch (enmEvent)
    58795    {
    58896        case VUSBSNIFFEREVENT_SUBMIT:
    589             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_SUBMIT;
    590             cbUrbLength = pUrb->cbData;
     97            chEvtType = 'S';
    59198            break;
    59299        case VUSBSNIFFEREVENT_COMPLETE:
    593             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_COMPLETE;
    594             cbUrbLength = pUrb->cbData;
     100            chEvtType = 'C';
    595101            break;
    596102        case VUSBSNIFFEREVENT_ERROR_SUBMIT:
    597103        case VUSBSNIFFEREVENT_ERROR_COMPLETE:
    598             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_ERROR;
     104            chEvtType = 'E';
    599105            break;
    600106        default:
    601107            AssertMsgFailed(("Invalid event type %d\n", enmEvent));
    602108    }
    603     cbDataLength = cbUrbLength;
    604     pbData = &pUrb->abData[0];
    605109
    606110    switch (pUrb->enmType)
    607111    {
    608112        case VUSBXFERTYPE_ISOC:
    609         {
    610             int32_t i32ErrorCount = 0;
    611 
    612             UsbHdr.u8TransferType = 0;
    613             cIsocPkts = pUrb->cIsocPkts;
    614             for (unsigned i = 0; i < cIsocPkts; i++)
    615                 if (   pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
    616                     && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
    617                     i32ErrorCount++;
    618 
    619             UsbHdr.u.IsoRec.i32ErrorCount = i32ErrorCount;
    620             UsbHdr.u.IsoRec.i32NumDesc    = pUrb->cIsocPkts;
    621             cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    622             break;
    623         }
     113            chEptType = 'Z';
     114            break;
    624115        case VUSBXFERTYPE_BULK:
    625                 UsbHdr.u8TransferType = 3;
    626                 break;
     116            chEptType = 'B';
     117            break;
    627118        case VUSBXFERTYPE_INTR:
    628                 UsbHdr.u8TransferType = 1;
    629                 break;
     119            chEptType = 'I';
     120            break;
    630121        case VUSBXFERTYPE_CTRL:
    631122        case VUSBXFERTYPE_MSG:
    632                 UsbHdr.u8TransferType = 2;
    633                 break;
     123            chEptType = 'C';
     124            break;
    634125        default:
    635126            AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
     
    637128
    638129    if (pUrb->enmDir == VUSBDIRECTION_IN)
     130        chDir = 'i';
     131    else if (pUrb->enmDir == VUSBDIRECTION_OUT)
     132        chDir = 'o';
     133    else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
     134        chDir = 'o';
     135
     136    RT_ZERO(aszLineBuf);
     137
     138    /* Assemble the static part. */
     139    size_t cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%p %llu %c %c%c:%u:%u:%u ",
     140                             pUrb, RTTimeNanoTS() / RT_NS_1US, chEvtType, chEptType, chDir,
     141                             0, pUrb->DstAddress, pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00));
     142    int rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     143    if (RT_SUCCESS(rc))
    639144    {
    640         if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
    641             cbDataLength = 0;
     145        /* Log the setup packet for control requests, the status otherwise. */
     146        if (   (pUrb->enmType == VUSBXFERTYPE_CTRL || pUrb->enmType == VUSBXFERTYPE_MSG)
     147            && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
     148        {
     149            PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
     150
     151            cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "s %02x %02x %04x %04x %04x ",
     152                              pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
     153                              pSetup->wIndex, pSetup->wLength);
     154            rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     155        }
     156        else
     157        {
     158            bool fLogAdditionalStatus =    pUrb->enmType == VUSBXFERTYPE_ISOC
     159                                        || pUrb->enmType == VUSBXFERTYPE_INTR;
     160
     161            cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d%s", pUrb->enmStatus,
     162                              fLogAdditionalStatus ? "" : " ");
     163
     164            /* There are additional fields to log for isochronous and interrupt URBs. */
     165            if (pUrb->enmType == VUSBXFERTYPE_ISOC)
     166            {
     167                if (enmEvent == VUSBSNIFFEREVENT_COMPLETE)
     168                {
     169                    uint32_t u32ErrorCount = 0;
     170
     171                    for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
     172                        if (   pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
     173                            && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
     174                            u32ErrorCount++;
     175
     176                    cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u:%u ",
     177                                       1 /* Interval */, pUrb->Hci.u32FrameNo, u32ErrorCount);
     178                }
     179                else
     180                    cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u ",
     181                                       1 /* Interval */, pUrb->Hci.u32FrameNo);
     182            }
     183            else if (pUrb->enmType == VUSBXFERTYPE_INTR)
     184                cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u ",
     185                                   1 /* Interval */);
     186
     187            rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     188        }
     189
     190        /* Log the packet descriptors for isochronous URBs. */
     191        if (   RT_SUCCESS(rc)
     192            && pUrb->enmType == VUSBXFERTYPE_ISOC)
     193        {
     194            cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%u ", pUrb->cIsocPkts);
     195            rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     196            for (unsigned i = 0; i < pUrb->cIsocPkts && RT_SUCCESS(rc); i++)
     197            {
     198                cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d:%u:%u ",
     199                                  pUrb->aIsocPkts[i].enmStatus, pUrb->aIsocPkts[i].off,
     200                                  pUrb->aIsocPkts[i].cb);
     201                rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     202            }
     203        }
     204
     205        if (RT_SUCCESS(rc))
     206        {
     207            /* Print data length */
     208            cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d n\n", pUrb->cbData);
     209            rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     210        }
     211
     212        /** @todo: Dump the data */
    642213    }
    643     else if (pUrb->enmDir == VUSBDIRECTION_OUT)
    644     {
    645         if (   enmEvent == VUSBSNIFFEREVENT_COMPLETE
    646             || pUrb->enmType == VUSBXFERTYPE_CTRL
    647             || pUrb->enmType == VUSBXFERTYPE_MSG)
    648             cbDataLength = 0;
    649     }
    650     else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
    651         cbDataLength -= sizeof(VUSBSETUP);
    652 
    653     Epb.u32CapturedLen = cbCapturedLength + cbDataLength;
    654     Epb.u32PacketLen   = cbCapturedLength + cbUrbLength;
    655 
    656     UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00);
    657     UsbHdr.u8DeviceAddress  = pUrb->DstAddress;
    658     UsbHdr.u16BusId         = 0;
    659     UsbHdr.u8DataFlag       = cbDataLength ? 0 : 1;
    660     UsbHdr.u64TimestampSec  = u64TimestampEvent / RT_NS_1SEC_64;
    661     UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC;
    662     UsbHdr.i32Status        = pUrb->enmStatus;
    663     UsbHdr.u32UrbLength     = cbUrbLength;
    664     UsbHdr.u32DataLength    = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    665     UsbHdr.i32Interval      = 0;
    666     UsbHdr.i32StartFrame    = 0;
    667     UsbHdr.u32XferFlags     = 0;
    668     UsbHdr.u32NumDesc       = cIsocPkts;
    669 
    670     if (   (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL)
    671         && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
    672     {
    673         PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
    674 
    675         UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType;
    676         UsbHdr.u.UsbSetup.bRequest      = pSetup->bRequest;
    677         UsbHdr.u.UsbSetup.wValue        = pSetup->wValue;
    678         UsbHdr.u.UsbSetup.wIndex        = pSetup->wIndex;
    679         UsbHdr.u.UsbSetup.wLength       = pSetup->wLength;
    680         UsbHdr.u8SetupFlag              = 0;
    681     }
    682     else
    683         UsbHdr.u8SetupFlag  = '-'; /* Follow usbmon source here. */
    684 
    685     /* Write the packet to the capture file. */
    686     rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
    687     if (RT_SUCCESS(rc))
    688         rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
    689 
    690     /* Add Isochronous descriptors now. */
    691     for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
    692     {
    693         DumpFileUsbIsoDesc IsoDesc;
    694         IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
    695         IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
    696         IsoDesc.u32Len    = pUrb->aIsocPkts[i].cb;
    697         rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
    698     }
    699 
    700     /* Record data. */
    701     if (   RT_SUCCESS(rc)
    702         && cbDataLength)
    703         rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
    704 
    705     if (RT_SUCCESS(rc))
    706         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    707 
    708     if (RT_SUCCESS(rc))
    709         rc = vusbSnifferBlockCommit(pThis);
    710214
    711215    return rc;
     
    715219 * VUSB sniffer format writer.
    716220 */
    717 const VUSBSNIFFERFMT g_VUsbSnifferFmtPcapNg =
     221const VUSBSNIFFERFMT g_VUsbSnifferFmtUsbMon =
    718222{
    719223    /** szName */
    720     "PCAPNG",
     224    "USBMON",
    721225    /** pszDesc */
    722     "PCAP-NG format writer compatible with WireShark",
     226    "UsbMon format writer compatible with vusb-analyzer: http://vusb-analyzer.sourceforge.net",
    723227    /** papszFileExts */
    724228    &s_apszFileExts[0],
     
    726230    sizeof(VUSBSNIFFERFMTINT),
    727231    /** pfnInit */
    728     vusbSnifferFmtPcanNgInit,
     232    vusbSnifferFmtUsbMonInit,
    729233    /** pfnDestroy */
    730     vusbSnifferFmtPcanNgDestroy,
     234    vusbSnifferFmtUsbMonDestroy,
    731235    /** pfnRecordEvent */
    732     vusbSnifferFmtPcanNgRecordEvent
     236    vusbSnifferFmtUsbMonRecordEvent
    733237};
    734238
  • trunk/src/VBox/Devices/USB/VUSBSnifferVmx.cpp

    r59615 r59633  
    11/* $Id$ */
    22/** @file
    3  * Virtual USB Sniffer facility - PCAP-NG format writer.
     3 * Virtual USB Sniffer facility - VMX USBIO format.
    44 */
    55
    66/*
    7  * Copyright (C) 2014-2016 Oracle Corporation
     7 * Copyright (C) 2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3535*********************************************************************************************************************************/
    3636
    37 /** DumpFile Section Header Block type. */
    38 #define DUMPFILE_SHB_BLOCK_TYPE       UINT32_C(0x0a0d0d0a)
    39 /** The byte order magic value. */
    40 #define DUMPFILE_SHB_BYTE_ORDER_MAGIC UINT32_C(0x1a2b3c4d)
    41 /** Current major version. */
    42 #define DUMPFILE_SHB_VERSION_MAJOR    UINT16_C(1)
    43 /** Current minor version. */
    44 #define DUMPFILE_SHB_VERSION_MINOR    UINT16_C(0)
    45 
    46 /** Block type for the interface descriptor block. */
    47 #define DUMPFILE_IDB_BLOCK_TYPE       UINT32_C(0x00000001)
    48 /** USB link type. */
    49 #define DUMPFILE_IDB_LINK_TYPE_USB_LINUX        UINT16_C(189)
    50 #define DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED UINT16_C(220)
    51 
    52 /** Block type for an enhanced packet block. */
    53 #define DUMPFILE_EPB_BLOCK_TYPE       UINT32_C(0x00000006)
    54 
    55 /** USB packet event types. */
    56 #define DUMPFILE_USB_EVENT_TYPE_SUBMIT   ('S')
    57 #define DUMPFILE_USB_EVENT_TYPE_COMPLETE ('C')
    58 #define DUMPFILE_USB_EVENT_TYPE_ERROR    ('E')
    59 
    60 #define DUMPFILE_OPTION_CODE_END      UINT16_C(0)
    61 #define DUMPFILE_OPTION_CODE_COMMENT  UINT16_C(1)
    62 
    63 #define DUMPFILE_OPTION_CODE_HARDWARE UINT16_C(2)
    64 #define DUMPFILE_OPTION_CODE_OS       UINT16_C(3)
    65 #define DUMPFILE_OPTION_CODE_USERAPP  UINT16_C(4)
    66 
    67 #define DUMPFILE_IDB_OPTION_TS_RESOLUTION UINT16_C(9)
    68 
    69 
    70 /*********************************************************************************************************************************
    71 *   DumpFile format structures                                                                                                   *
    72 *********************************************************************************************************************************/
    73 
    74 /**
    75  * DumpFile Block header.
    76  */
    77 typedef struct DumpFileBlockHdr
    78 {
    79     /** Block type. */
    80     uint32_t            u32BlockType;
    81     /** Block total length. */
    82     uint32_t            u32BlockTotalLength;
    83 } DumpFileBlockHdr;
    84 /** Pointer to a block header. */
    85 typedef DumpFileBlockHdr *PDumpFileBlockHdr;
    86 
    87 /**
    88  * DumpFile Option header.
    89  */
    90 typedef struct DumpFileOptionHdr
    91 {
    92     /** Option code. */
    93     uint16_t            u16OptionCode;
    94     /** Block total length. */
    95     uint16_t            u16OptionLength;
    96 } DumpFileOptionHdr;
    97 /** Pointer to a option header. */
    98 typedef DumpFileOptionHdr *PDumpFileOptionHdr;
    99 
    100 /**
    101  * DumpFile Section Header Block.
    102  */
    103 typedef struct DumpFileShb
    104 {
    105     /** Block header. */
    106     DumpFileBlockHdr    Hdr;
    107     /** Byte order magic. */
    108     uint32_t            u32ByteOrderMagic;
    109     /** Major version. */
    110     uint16_t            u16VersionMajor;
    111     /** Minor version. */
    112     uint16_t            u16VersionMinor;
    113     /** Section length. */
    114     uint64_t            u64SectionLength;
    115 } DumpFileShb;
    116 /** Pointer to a Section Header Block. */
    117 typedef DumpFileShb *PDumpFileShb;
    118 
    119 /**
    120  * DumpFile Interface description block.
    121  */
    122 typedef struct DumpFileIdb
    123 {
    124     /** Block header. */
    125     DumpFileBlockHdr    Hdr;
    126     /** Link type. */
    127     uint16_t            u16LinkType;
    128     /** Reserved. */
    129     uint16_t            u16Reserved;
    130     /** Maximum number of bytes dumped from each packet. */
    131     uint32_t            u32SnapLen;
    132 } DumpFileIdb;
    133 /** Pointer to an Interface description block. */
    134 typedef DumpFileIdb *PDumpFileIdb;
    135 
    136 /**
    137  * DumpFile Enhanced packet block.
    138  */
    139 typedef struct DumpFileEpb
    140 {
    141     /** Block header. */
    142     DumpFileBlockHdr    Hdr;
    143     /** Interface ID. */
    144     uint32_t            u32InterfaceId;
    145     /** Timestamp (high). */
    146     uint32_t            u32TimestampHigh;
    147     /** Timestamp (low). */
    148     uint32_t            u32TimestampLow;
    149     /** Captured packet length. */
    150     uint32_t            u32CapturedLen;
    151     /** Original packet length. */
    152     uint32_t            u32PacketLen;
    153 } DumpFileEpb;
    154 /** Pointer to an Enhanced packet block. */
    155 typedef DumpFileEpb *PDumpFileEpb;
    156 
    157 /**
    158  * USB setup URB data.
    159  */
    160 typedef struct DumpFileUsbSetup
    161 {
    162     uint8_t    bmRequestType;
    163     uint8_t    bRequest;
    164     uint16_t   wValue;
    165     uint16_t   wIndex;
    166     uint16_t   wLength;
    167 } DumpFileUsbSetup;
    168 typedef DumpFileUsbSetup *PDumpFileUsbSetup;
    169 
    170 /**
    171  * USB Isochronous data.
    172  */
    173 typedef struct DumpFileIsoRec
    174 {
    175     int32_t    i32ErrorCount;
    176     int32_t    i32NumDesc;
    177 } DumpFileIsoRec;
    178 typedef DumpFileIsoRec *PDumpFileIsoRec;
    179 
    180 /**
    181  * USB packet header (Linux mmapped variant).
    182  */
    183 typedef struct DumpFileUsbHeaderLnxMmapped
    184 {
    185     /** Packet Id. */
    186     uint64_t    u64Id;
    187     /** Event type. */
    188     uint8_t     u8EventType;
    189     /** Transfer type. */
    190     uint8_t     u8TransferType;
    191     /** Endpoint number. */
    192     uint8_t     u8EndpointNumber;
    193     /** Device address. */
    194     uint8_t     u8DeviceAddress;
    195     /** Bus id. */
    196     uint16_t    u16BusId;
    197     /** Setup flag != 0 if the URB setup header is not present. */
    198     uint8_t     u8SetupFlag;
    199     /** Data present flag != 0 if the URB data is not present. */
    200     uint8_t     u8DataFlag;
    201     /** Timestamp (second part). */
    202     uint64_t    u64TimestampSec;
    203     /** Timestamp (us part). */
    204     uint32_t    u32TimestampUSec;
    205     /** Status. */
    206     int32_t     i32Status;
    207     /** URB length. */
    208     uint32_t    u32UrbLength;
    209     /** Recorded data length. */
    210     uint32_t    u32DataLength;
    211     /** Union of data for different URB types. */
    212     union
    213     {
    214         DumpFileUsbSetup    UsbSetup;
    215         DumpFileIsoRec      IsoRec;
    216     } u;
    217     int32_t     i32Interval;
    218     int32_t     i32StartFrame;
    219     /** Copy of transfer flags. */
    220     uint32_t    u32XferFlags;
    221     /** Number of isochronous descriptors. */
    222     uint32_t    u32NumDesc;
    223 } DumpFileUsbHeaderLnxMmapped;
    224 /** Pointer to a USB packet header. */
    225 typedef DumpFileUsbHeaderLnxMmapped *PDumpFileUsbHeaderLnxMmapped;
    226 
    227 AssertCompileSize(DumpFileUsbHeaderLnxMmapped, 64);
    228 
    229 /**
    230  * USB packet isochronous descriptor.
    231  */
    232 typedef struct DumpFileUsbIsoDesc
    233 {
    234     int32_t     i32Status;
    235     uint32_t    u32Offset;
    236     uint32_t    u32Len;
    237     uint8_t     au8Padding[4];
    238 } DumpFileUsbIsoDesc;
    239 typedef DumpFileUsbIsoDesc *PDumpFileUsbIsoDesc;
    240 
    241 
    24237/*********************************************************************************************************************************
    24338*   Structures and Typedefs                                                                                                      *
     
    25146    /** Stream handle. */
    25247    PVUSBSNIFFERSTRM  pStrm;
    253     /** Current size of the block being written. */
    254     uint32_t          cbBlockCur;
    255     /** Maximum size allocated for the block. */
    256     uint32_t          cbBlockMax;
    257     /** Current block header. */
    258     PDumpFileBlockHdr pBlockHdr;
    259     /** Pointer to the block data which will be written on commit. */
    260     uint8_t          *pbBlockData;
    26148} VUSBSNIFFERFMTINT;
    26249
     
    27158static const char *s_apszFileExts[] =
    27259{
    273     "pcap",
    274     "pcapng",
     60    "vmx",
     61    "vmware",
     62    "usbio",
    27563    NULL
    27664};
    27765
     66
     67/**
     68 * Month strings.
     69 */
     70static const char *s_apszMonths[] =
     71{
     72    "Jan",
     73    "Feb",
     74    "Mar",
     75    "Apr",
     76    "May",
     77    "Jun",
     78    "Jul",
     79    "Aug",
     80    "Sep",
     81    "Oct",
     82    "Nov",
     83    "Dec"
     84};
    27885
    27986/*********************************************************************************************************************************
     
    28188*********************************************************************************************************************************/
    28289
    283 /**
    284  * Allocates additional space for the block.
    285  *
    286  * @returns Pointer to the new unused space or NULL if out of memory.
    287  * @param   pThis           The VUSB sniffer instance.
    288  * @param   cbAdditional    The additional memory requested.
    289  */
    290 static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERFMTINT pThis, uint32_t cbAdditional)
    291 {
    292     /* Fast path where we have enough memory allocated. */
    293     if (pThis->cbBlockCur + cbAdditional <= pThis->cbBlockMax)
    294     {
    295         void *pv = pThis->pbBlockData + pThis->cbBlockCur;
    296         pThis->cbBlockCur += cbAdditional;
    297         return pv;
    298     }
    29990
    300     /* Allocate additional memory. */
    301     uint32_t cbNew = pThis->cbBlockCur + cbAdditional;
    302     uint8_t *pbDataNew = (uint8_t *)RTMemRealloc(pThis->pbBlockData, cbNew);
    303     if (pbDataNew)
    304     {
    305         pThis->pbBlockData = pbDataNew;
    306         pThis->pBlockHdr   = (PDumpFileBlockHdr)pbDataNew;
    307 
    308         void *pv = pThis->pbBlockData + pThis->cbBlockCur;
    309         pThis->cbBlockCur = cbNew;
    310         pThis->cbBlockMax = cbNew;
    311         return pv;
    312     }
    313 
    314     return NULL;
    315 }
    316 
    317 /**
    318  * Adds new data to the current block.
    319  *
    320  * @returns VBox status code.
    321  * @param   pThis           The VUSB sniffer instance.
    322  * @param   pvData          The data to add.
    323  * @param   cbData          Amount of data to add.
    324  */
    325 static int vusbSnifferBlockAddData(PVUSBSNIFFERFMTINT pThis, const void *pvData, uint32_t cbData)
     91static int vusbSnifferFmtVmxLogData(PVUSBSNIFFERFMTINT pThis, PRTTIME pTime, uint8_t *pbBuf, size_t cbBuf)
    32692{
    32793    int rc = VINF_SUCCESS;
     94    char aszLineBuf[256];
     95    uint16_t off = 0;
    32896
    329     Assert(pThis->cbBlockCur);
    330     AssertPtr(pThis->pBlockHdr);
    331 
    332     void *pv = vusbSnifferBlockAllocSpace(pThis, cbData);
    333     if (pv)
    334         memcpy(pv, pvData, cbData);
    335     else
    336         rc = VERR_NO_MEMORY;
     97    do
     98    {
     99        size_t cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf),
     100                                 "%s %02u %02u:%02u:%02u.%3.*u: vmx| USBIO:  %03x: %16.*Rhxs\n",
     101                                 s_apszMonths[pTime->u8Month - 1], pTime->u8MonthDay, pTime->u8Hour, pTime->u8Minute, pTime->u8Second, 3, pTime->u32Nanosecond,
     102                                 off, RT_MIN(cbBuf - off, 16), pbBuf);
     103        rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     104        off   += RT_MIN(cbBuf, 16);
     105        pbBuf += RT_MIN(cbBuf, 16);
     106    } while (RT_SUCCESS(rc) && off < cbBuf);
    337107
    338108    return rc;
    339109}
    340110
    341 /**
    342  * Aligns the current block data to a 32bit boundary.
    343  *
    344  * @returns VBox status code.
    345  * @param   pThis           The VUSB sniffer instance.
    346  */
    347 static int vusbSnifferBlockAlign(PVUSBSNIFFERFMTINT pThis)
     111/** @copydoc VUSBSNIFFERFMT::pfnInit */
     112static DECLCALLBACK(int) vusbSnifferFmtVmxInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
    348113{
    349     int rc = VINF_SUCCESS;
    350 
    351     Assert(pThis->cbBlockCur);
    352 
    353     /* Pad to 32bits. */
    354     uint8_t abPad[3] = { 0 };
    355     uint32_t cbPad = RT_ALIGN_32(pThis->cbBlockCur, 4) - pThis->cbBlockCur;
    356 
    357     Assert(cbPad <= 3);
    358     if (cbPad)
    359         rc = vusbSnifferBlockAddData(pThis, abPad, cbPad);
    360 
    361     return rc;
    362 }
    363 
    364 /**
    365  * Commits the current block to the capture file.
    366  *
    367  * @returns VBox status code.
    368  * @param   pThis           The VUSB sniffer instance.
    369  */
    370 static int vusbSnifferBlockCommit(PVUSBSNIFFERFMTINT pThis)
    371 {
    372     int rc = VINF_SUCCESS;
    373 
    374     AssertPtr(pThis->pBlockHdr);
    375 
    376     rc = vusbSnifferBlockAlign(pThis);
    377     if (RT_SUCCESS(rc))
    378     {
    379         /* Update the block total length field. */
    380         uint32_t *pcbTotalLength = (uint32_t *)vusbSnifferBlockAllocSpace(pThis, 4);
    381         if (pcbTotalLength)
    382         {
    383             *pcbTotalLength = pThis->cbBlockCur;
    384             pThis->pBlockHdr->u32BlockTotalLength = pThis->cbBlockCur;
    385 
    386             /* Write the data. */
    387             rc = pThis->pStrm->pfnWrite(pThis->pStrm, pThis->pbBlockData, pThis->cbBlockCur);
    388             pThis->cbBlockCur = 0;
    389             pThis->pBlockHdr  = NULL;
    390         }
    391         else
    392             rc = VERR_NO_MEMORY;
    393     }
    394 
    395     return rc;
    396 }
    397 
    398 /**
    399  * Starts a new block for capturing.
    400  *
    401  * @returns VBox status code.
    402  * @param   pThis           The VUSB sniffer instance.
    403  * @param   pBlockHdr       Pointer to the block header for the new block.
    404  * @param   cbData          Amount of data added with this block.
    405  */
    406 static int vusbSnifferBlockNew(PVUSBSNIFFERFMTINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)
    407 {
    408     int rc = VINF_SUCCESS;
    409 
    410     /* Validate we don't get called while another block is active. */
    411     Assert(!pThis->cbBlockCur);
    412     Assert(!pThis->pBlockHdr);
    413     pThis->pBlockHdr = (PDumpFileBlockHdr)vusbSnifferBlockAllocSpace(pThis, cbData);
    414     if (pThis->pBlockHdr)
    415         memcpy(pThis->pBlockHdr, pBlockHdr, cbData);
    416     else
    417         rc = VERR_NO_MEMORY;
    418 
    419     return rc;
    420 }
    421 
    422 /**
    423  * Add a new option to the current block.
    424  *
    425  * @returns VBox status code.
    426  * @param   pThis           The VUSB sniffer instance.
    427  * @param   u16OptionCode   The option code identifying the type of option.
    428  * @param   pvOption        Raw data for the option.
    429  * @param   cbOption        Size of the optiob data.
    430  */
    431 static int vusbSnifferAddOption(PVUSBSNIFFERFMTINT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption)
    432 {
    433     int rc = VINF_SUCCESS;
    434     DumpFileOptionHdr OptHdr;
    435 
    436     OptHdr.u16OptionCode   = u16OptionCode;
    437     OptHdr.u16OptionLength = cbOption;
    438     rc = vusbSnifferBlockAddData(pThis, &OptHdr, sizeof(OptHdr));
    439     if (   RT_SUCCESS(rc)
    440         && u16OptionCode != DUMPFILE_OPTION_CODE_END
    441         && cbOption != 0)
    442     {
    443         rc = vusbSnifferBlockAddData(pThis, pvOption, cbOption);
    444         if (RT_SUCCESS(rc))
    445             rc = vusbSnifferBlockAlign(pThis);
    446     }
    447 
    448     return rc;
    449 }
    450 
    451 
    452 /** @copydoc VUSBSNIFFERFMT::pfnInit */
    453 static DECLCALLBACK(int) vusbSnifferFmtPcanNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
    454 {
    455     int rc = VINF_SUCCESS;
    456 
    457     pThis->pStrm       = pStrm;
    458     pThis->cbBlockCur  = 0;
    459     pThis->cbBlockMax  = 0;
    460     pThis->pbBlockData = NULL;
    461 
    462     /* Write header and link type blocks. */
    463     DumpFileShb Shb;
    464 
    465     Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
    466     Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    467     Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
    468     Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
    469     Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
    470     Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */
    471 
    472     /* Write the blocks. */
    473     rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
    474     if (RT_SUCCESS(rc))
    475     {
    476         const char *pszOpt = RTBldCfgTargetDotArch();
    477         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
    478     }
    479 
    480     if (RT_SUCCESS(rc))
    481     {
    482         char szTmp[512];
    483         size_t cbTmp = sizeof(szTmp);
    484 
    485         RT_ZERO(szTmp);
    486 
    487         /* Build the OS code. */
    488         rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
    489         if (RT_SUCCESS(rc))
    490         {
    491             size_t cb = strlen(szTmp);
    492 
    493             szTmp[cb] = ' ';
    494             rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
    495             if (RT_SUCCESS(rc))
    496             {
    497                 cb = strlen(szTmp);
    498                 szTmp[cb] = ' ';
    499                 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
    500             }
    501         }
    502 
    503         if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
    504             rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
    505         else
    506             rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
    507     }
    508 
    509     if (RT_SUCCESS(rc))
    510     {
    511         /** @todo: Add product info. */
    512     }
    513 
    514     if (RT_SUCCESS(rc))
    515         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    516     if (RT_SUCCESS(rc))
    517         rc = vusbSnifferBlockCommit(pThis);
    518 
    519     /* Write Interface descriptor block. */
    520     if (RT_SUCCESS(rc))
    521     {
    522         DumpFileIdb Idb;
    523 
    524         Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
    525         Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    526         Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
    527         Idb.u16Reserved             = 0;
    528         Idb.u32SnapLen              = UINT32_C(0xffffffff);
    529 
    530         rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
    531         if (RT_SUCCESS(rc))
    532         {
    533             uint8_t u8TsResolution = 9; /* Nano second resolution. */
    534             /* Add timestamp resolution option. */
    535             rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
    536                                       &u8TsResolution, sizeof(u8TsResolution));
    537         }
    538         if (RT_SUCCESS(rc))
    539             rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    540         if (RT_SUCCESS(rc))
    541             rc = vusbSnifferBlockCommit(pThis);
    542     }
    543 
    544     if (   RT_FAILURE(rc)
    545         && pThis->pbBlockData)
    546         RTMemFree(pThis->pbBlockData);
    547 
    548     return rc;
     114    pThis->pStrm = pStrm;
     115    return VINF_SUCCESS;
    549116}
    550117
    551118
    552119/** @copydoc VUSBSNIFFERFMT::pfnDestroy */
    553 static DECLCALLBACK(void) vusbSnifferFmtPcanNgDestroy(PVUSBSNIFFERFMTINT pThis)
     120static DECLCALLBACK(void) vusbSnifferFmtVmxDestroy(PVUSBSNIFFERFMTINT pThis)
    554121{
    555     if (pThis->pbBlockData)
    556         RTMemFree(pThis->pbBlockData);
     122    NOREF(pThis);
    557123}
    558124
    559125
    560126/** @copydoc VUSBSNIFFERFMT::pfnRecordEvent */
    561 static DECLCALLBACK(int) vusbSnifferFmtPcanNgRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
     127static DECLCALLBACK(int) vusbSnifferFmtVmxRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
    562128{
    563     int rc = VINF_SUCCESS;
    564     DumpFileEpb Epb;
    565     DumpFileUsbHeaderLnxMmapped UsbHdr;
    566     DumpFileUsbSetup UsbSetup;
    567129    RTTIMESPEC TimeNow;
    568     uint64_t u64TimestampEvent;
    569     size_t cbUrbLength = 0;
    570     uint32_t cbDataLength = 0;
    571     uint32_t cbCapturedLength = sizeof(UsbHdr);
    572     uint32_t cIsocPkts = 0;
    573     uint8_t *pbData = NULL;
     130    RTTIME Time;
     131    char aszLineBuf[256];
     132    const char *pszEvt = enmEvent == VUSBSNIFFEREVENT_SUBMIT ? "Down" : "Up";
     133    uint8_t cIsocPkts = pUrb->enmType == VUSBXFERTYPE_ISOC ? pUrb->cIsocPkts : 0;
     134
     135    if (pUrb->enmType == VUSBXFERTYPE_MSG)
     136        return VINF_SUCCESS;
     137
     138    RT_ZERO(aszLineBuf);
    574139
    575140    RTTimeNow(&TimeNow);
    576     u64TimestampEvent = RTTimeSpecGetNano(&TimeNow);
     141    RTTimeExplode(&Time, &TimeNow);
    577142
    578     /* Start with the enhanced packet block. */
    579     Epb.Hdr.u32BlockType        = DUMPFILE_EPB_BLOCK_TYPE;
    580     Epb.Hdr.u32BlockTotalLength = 0;
    581     Epb.u32InterfaceId          = 0;
    582     Epb.u32TimestampHigh        = (u64TimestampEvent >> 32) & UINT32_C(0xffffffff);
    583     Epb.u32TimestampLow         = u64TimestampEvent & UINT32_C(0xffffffff);
    584 
    585     UsbHdr.u64Id = (uint64_t)pUrb; /** @todo: check whether the pointer is a good ID. */
    586     switch (enmEvent)
     143    size_t cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf),
     144                             "%s %02u %02u:%02u:%02u.%3.*u: vmx| USBIO: %s dev=%u endpt=%x datalen=%u numPackets=%u status=%u 0\n",
     145                             s_apszMonths[Time.u8Month - 1], Time.u8MonthDay, Time.u8Hour, Time.u8Minute, Time.u8Second, 3, Time.u32Nanosecond,
     146                             pszEvt, pUrb->DstAddress, pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00),
     147                             pUrb->cbData, cIsocPkts, pUrb->enmStatus);
     148    int rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
     149    if (RT_SUCCESS(rc))
    587150    {
    588         case VUSBSNIFFEREVENT_SUBMIT:
    589             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_SUBMIT;
    590             cbUrbLength = pUrb->cbData;
    591             break;
    592         case VUSBSNIFFEREVENT_COMPLETE:
    593             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_COMPLETE;
    594             cbUrbLength = pUrb->cbData;
    595             break;
    596         case VUSBSNIFFEREVENT_ERROR_SUBMIT:
    597         case VUSBSNIFFEREVENT_ERROR_COMPLETE:
    598             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_ERROR;
    599             break;
    600         default:
    601             AssertMsgFailed(("Invalid event type %d\n", enmEvent));
     151        /* Log the data in the appropriate stage. */
     152        if (   pUrb->enmType == VUSBXFERTYPE_CTRL
     153            || pUrb->enmType == VUSBXFERTYPE_MSG)
     154        {
     155            if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
     156                rc = vusbSnifferFmtVmxLogData(pThis, &Time, &pUrb->abData[0], sizeof(VUSBSETUP));
     157            else if (enmEvent == VUSBSNIFFEREVENT_COMPLETE)
     158            {
     159                rc = vusbSnifferFmtVmxLogData(pThis, &Time, &pUrb->abData[0], sizeof(VUSBSETUP));
     160                if (   RT_SUCCESS(rc)
     161                    && pUrb->cbData > sizeof(VUSBSETUP))
     162                    rc = vusbSnifferFmtVmxLogData(pThis, &Time, &pUrb->abData[sizeof(VUSBSETUP)], pUrb->cbData - sizeof(VUSBSETUP));
     163            }
     164        }
     165        else
     166        {
     167            if (   enmEvent == VUSBSNIFFEREVENT_SUBMIT
     168                && pUrb->enmDir == VUSBDIRECTION_OUT)
     169                rc = vusbSnifferFmtVmxLogData(pThis, &Time, &pUrb->abData[0], pUrb->cbData);
     170            else if (   enmEvent == VUSBSNIFFEREVENT_COMPLETE
     171                     && pUrb->enmDir == VUSBDIRECTION_IN)
     172                rc = vusbSnifferFmtVmxLogData(pThis, &Time, &pUrb->abData[0], pUrb->cbData);
     173        }
    602174    }
    603     cbDataLength = cbUrbLength;
    604     pbData = &pUrb->abData[0];
    605 
    606     switch (pUrb->enmType)
    607     {
    608         case VUSBXFERTYPE_ISOC:
    609         {
    610             int32_t i32ErrorCount = 0;
    611 
    612             UsbHdr.u8TransferType = 0;
    613             cIsocPkts = pUrb->cIsocPkts;
    614             for (unsigned i = 0; i < cIsocPkts; i++)
    615                 if (   pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
    616                     && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
    617                     i32ErrorCount++;
    618 
    619             UsbHdr.u.IsoRec.i32ErrorCount = i32ErrorCount;
    620             UsbHdr.u.IsoRec.i32NumDesc    = pUrb->cIsocPkts;
    621             cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    622             break;
    623         }
    624         case VUSBXFERTYPE_BULK:
    625                 UsbHdr.u8TransferType = 3;
    626                 break;
    627         case VUSBXFERTYPE_INTR:
    628                 UsbHdr.u8TransferType = 1;
    629                 break;
    630         case VUSBXFERTYPE_CTRL:
    631         case VUSBXFERTYPE_MSG:
    632                 UsbHdr.u8TransferType = 2;
    633                 break;
    634         default:
    635             AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
    636     }
    637 
    638     if (pUrb->enmDir == VUSBDIRECTION_IN)
    639     {
    640         if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
    641             cbDataLength = 0;
    642     }
    643     else if (pUrb->enmDir == VUSBDIRECTION_OUT)
    644     {
    645         if (   enmEvent == VUSBSNIFFEREVENT_COMPLETE
    646             || pUrb->enmType == VUSBXFERTYPE_CTRL
    647             || pUrb->enmType == VUSBXFERTYPE_MSG)
    648             cbDataLength = 0;
    649     }
    650     else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
    651         cbDataLength -= sizeof(VUSBSETUP);
    652 
    653     Epb.u32CapturedLen = cbCapturedLength + cbDataLength;
    654     Epb.u32PacketLen   = cbCapturedLength + cbUrbLength;
    655 
    656     UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00);
    657     UsbHdr.u8DeviceAddress  = pUrb->DstAddress;
    658     UsbHdr.u16BusId         = 0;
    659     UsbHdr.u8DataFlag       = cbDataLength ? 0 : 1;
    660     UsbHdr.u64TimestampSec  = u64TimestampEvent / RT_NS_1SEC_64;
    661     UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC;
    662     UsbHdr.i32Status        = pUrb->enmStatus;
    663     UsbHdr.u32UrbLength     = cbUrbLength;
    664     UsbHdr.u32DataLength    = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    665     UsbHdr.i32Interval      = 0;
    666     UsbHdr.i32StartFrame    = 0;
    667     UsbHdr.u32XferFlags     = 0;
    668     UsbHdr.u32NumDesc       = cIsocPkts;
    669 
    670     if (   (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL)
    671         && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
    672     {
    673         PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
    674 
    675         UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType;
    676         UsbHdr.u.UsbSetup.bRequest      = pSetup->bRequest;
    677         UsbHdr.u.UsbSetup.wValue        = pSetup->wValue;
    678         UsbHdr.u.UsbSetup.wIndex        = pSetup->wIndex;
    679         UsbHdr.u.UsbSetup.wLength       = pSetup->wLength;
    680         UsbHdr.u8SetupFlag              = 0;
    681     }
    682     else
    683         UsbHdr.u8SetupFlag  = '-'; /* Follow usbmon source here. */
    684 
    685     /* Write the packet to the capture file. */
    686     rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
    687     if (RT_SUCCESS(rc))
    688         rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
    689 
    690     /* Add Isochronous descriptors now. */
    691     for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
    692     {
    693         DumpFileUsbIsoDesc IsoDesc;
    694         IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
    695         IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
    696         IsoDesc.u32Len    = pUrb->aIsocPkts[i].cb;
    697         rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
    698     }
    699 
    700     /* Record data. */
    701     if (   RT_SUCCESS(rc)
    702         && cbDataLength)
    703         rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
    704 
    705     if (RT_SUCCESS(rc))
    706         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    707 
    708     if (RT_SUCCESS(rc))
    709         rc = vusbSnifferBlockCommit(pThis);
    710175
    711176    return rc;
     
    715180 * VUSB sniffer format writer.
    716181 */
    717 const VUSBSNIFFERFMT g_VUsbSnifferFmtPcapNg =
     182const VUSBSNIFFERFMT g_VUsbSnifferFmtVmx =
    718183{
    719184    /** szName */
    720     "PCAPNG",
     185    "VMX",
    721186    /** pszDesc */
    722     "PCAP-NG format writer compatible with WireShark",
     187    "VMX log format writer supported by vusb-analyzer: http://vusb-analyzer.sourceforge.net",
    723188    /** papszFileExts */
    724189    &s_apszFileExts[0],
     
    726191    sizeof(VUSBSNIFFERFMTINT),
    727192    /** pfnInit */
    728     vusbSnifferFmtPcanNgInit,
     193    vusbSnifferFmtVmxInit,
    729194    /** pfnDestroy */
    730     vusbSnifferFmtPcanNgDestroy,
     195    vusbSnifferFmtVmxDestroy,
    731196    /** pfnRecordEvent */
    732     vusbSnifferFmtPcanNgRecordEvent
     197    vusbSnifferFmtVmxRecordEvent
    733198};
    734199
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette