VirtualBox

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


Ignore:
Timestamp:
Feb 9, 2016 1:08:14 PM (9 years ago)
Author:
vboxsync
Message:

USB/VUSBSniffer: Separate API from format to make it possible to introduce other formats to capture the traffic in (will come next)

Location:
trunk/src/VBox/Devices/USB
Files:
4 edited
1 copied

Legend:

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

    r57442 r59615  
    10521052    if (pszCaptureFilename)
    10531053    {
    1054         rc = VUSBSnifferCreate(&pThis->hSniffer, 0, pszCaptureFilename, NULL);
     1054        rc = VUSBSnifferCreate(&pThis->hSniffer, 0, pszCaptureFilename, NULL, NULL);
    10551055        if (RT_FAILURE(rc))
    10561056            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
  • trunk/src/VBox/Devices/USB/VUSBDevice.cpp

    r58364 r59615  
    16471647        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
    16481648
    1649         vusbDevUrbIoThreadWakeup(pDev);
     1649        /* In case we are called on the I/O thread just process the request. */
     1650        if (   pDev->hUrbIoThread == RTThreadSelf()
     1651            && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
     1652        {
     1653            int rc2 = RTReqQueueProcess(pDev->hReqQueueSync, 0);
     1654            Assert(RT_SUCCESS(rc2) || rc2 == VERR_TIMEOUT);
     1655        }
     1656        else
     1657            vusbDevUrbIoThreadWakeup(pDev);
     1658
    16501659        if (   rc == VERR_TIMEOUT
    16511660            && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
     
    17821791    if (pszCaptureFilename)
    17831792    {
    1784         rc = VUSBSnifferCreate(&pDev->hSniffer, 0, pszCaptureFilename, NULL);
     1793        rc = VUSBSnifferCreate(&pDev->hSniffer, 0, pszCaptureFilename, NULL, NULL);
    17851794        AssertRCReturn(rc, rc);
    17861795    }
  • trunk/src/VBox/Devices/USB/VUSBSniffer.cpp

    r57526 r59615  
    55
    66/*
    7  * Copyright (C) 2014-2015 Oracle Corporation
     7 * Copyright (C) 2014-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2323#include <VBox/log.h>
    2424#include <iprt/file.h>
     25#include <iprt/path.h>
    2526#include <iprt/mem.h>
    26 #include <iprt/buildconfig.h>
    2727#include <iprt/string.h>
    28 #include <iprt/system.h>
    2928#include <iprt/semaphore.h>
    3029#include <iprt/time.h>
    3130
    32 #include "VUSBSniffer.h"
     31#include "VUSBSnifferInternal.h"
    3332
    3433
     
    3635*   Defined Constants And Macros                                                                                                 *
    3736*********************************************************************************************************************************/
    38 
    39 /** DumpFile Section Header Block type. */
    40 #define DUMPFILE_SHB_BLOCK_TYPE       UINT32_C(0x0a0d0d0a)
    41 /** The byte order magic value. */
    42 #define DUMPFILE_SHB_BYTE_ORDER_MAGIC UINT32_C(0x1a2b3c4d)
    43 /** Current major version. */
    44 #define DUMPFILE_SHB_VERSION_MAJOR    UINT16_C(1)
    45 /** Current minor version. */
    46 #define DUMPFILE_SHB_VERSION_MINOR    UINT16_C(0)
    47 
    48 /** Block type for the interface descriptor block. */
    49 #define DUMPFILE_IDB_BLOCK_TYPE       UINT32_C(0x00000001)
    50 /** USB link type. */
    51 #define DUMPFILE_IDB_LINK_TYPE_USB_LINUX        UINT16_C(189)
    52 #define DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED UINT16_C(220)
    53 
    54 /** Block type for an enhanced packet block. */
    55 #define DUMPFILE_EPB_BLOCK_TYPE       UINT32_C(0x00000006)
    56 
    57 /** USB packet event types. */
    58 #define DUMPFILE_USB_EVENT_TYPE_SUBMIT   ('S')
    59 #define DUMPFILE_USB_EVENT_TYPE_COMPLETE ('C')
    60 #define DUMPFILE_USB_EVENT_TYPE_ERROR    ('E')
    61 
    62 #define DUMPFILE_OPTION_CODE_END      UINT16_C(0)
    63 #define DUMPFILE_OPTION_CODE_COMMENT  UINT16_C(1)
    64 
    65 #define DUMPFILE_OPTION_CODE_HARDWARE UINT16_C(2)
    66 #define DUMPFILE_OPTION_CODE_OS       UINT16_C(3)
    67 #define DUMPFILE_OPTION_CODE_USERAPP  UINT16_C(4)
    68 
    69 #define DUMPFILE_IDB_OPTION_TS_RESOLUTION UINT16_C(9)
    70 
    71 
    72 /*********************************************************************************************************************************
    73 *   DumpFile format structures                                                                                                   *
    74 *********************************************************************************************************************************/
    75 
    76 /**
    77  * DumpFile Block header.
    78  */
    79 typedef struct DumpFileBlockHdr
    80 {
    81     /** Block type. */
    82     uint32_t            u32BlockType;
    83     /** Block total length. */
    84     uint32_t            u32BlockTotalLength;
    85 } DumpFileBlockHdr;
    86 /** Pointer to a block header. */
    87 typedef DumpFileBlockHdr *PDumpFileBlockHdr;
    88 
    89 /**
    90  * DumpFile Option header.
    91  */
    92 typedef struct DumpFileOptionHdr
    93 {
    94     /** Option code. */
    95     uint16_t            u16OptionCode;
    96     /** Block total length. */
    97     uint16_t            u16OptionLength;
    98 } DumpFileOptionHdr;
    99 /** Pointer to a option header. */
    100 typedef DumpFileOptionHdr *PDumpFileOptionHdr;
    101 
    102 /**
    103  * DumpFile Section Header Block.
    104  */
    105 typedef struct DumpFileShb
    106 {
    107     /** Block header. */
    108     DumpFileBlockHdr    Hdr;
    109     /** Byte order magic. */
    110     uint32_t            u32ByteOrderMagic;
    111     /** Major version. */
    112     uint16_t            u16VersionMajor;
    113     /** Minor version. */
    114     uint16_t            u16VersionMinor;
    115     /** Section length. */
    116     uint64_t            u64SectionLength;
    117 } DumpFileShb;
    118 /** Pointer to a Section Header Block. */
    119 typedef DumpFileShb *PDumpFileShb;
    120 
    121 /**
    122  * DumpFile Interface description block.
    123  */
    124 typedef struct DumpFileIdb
    125 {
    126     /** Block header. */
    127     DumpFileBlockHdr    Hdr;
    128     /** Link type. */
    129     uint16_t            u16LinkType;
    130     /** Reserved. */
    131     uint16_t            u16Reserved;
    132     /** Maximum number of bytes dumped from each packet. */
    133     uint32_t            u32SnapLen;
    134 } DumpFileIdb;
    135 /** Pointer to an Interface description block. */
    136 typedef DumpFileIdb *PDumpFileIdb;
    137 
    138 /**
    139  * DumpFile Enhanced packet block.
    140  */
    141 typedef struct DumpFileEpb
    142 {
    143     /** Block header. */
    144     DumpFileBlockHdr    Hdr;
    145     /** Interface ID. */
    146     uint32_t            u32InterfaceId;
    147     /** Timestamp (high). */
    148     uint32_t            u32TimestampHigh;
    149     /** Timestamp (low). */
    150     uint32_t            u32TimestampLow;
    151     /** Captured packet length. */
    152     uint32_t            u32CapturedLen;
    153     /** Original packet length. */
    154     uint32_t            u32PacketLen;
    155 } DumpFileEpb;
    156 /** Pointer to an Enhanced packet block. */
    157 typedef DumpFileEpb *PDumpFileEpb;
    158 
    159 /**
    160  * USB setup URB data.
    161  */
    162 typedef struct DumpFileUsbSetup
    163 {
    164     uint8_t    bmRequestType;
    165     uint8_t    bRequest;
    166     uint16_t   wValue;
    167     uint16_t   wIndex;
    168     uint16_t   wLength;
    169 } DumpFileUsbSetup;
    170 typedef DumpFileUsbSetup *PDumpFileUsbSetup;
    171 
    172 /**
    173  * USB Isochronous data.
    174  */
    175 typedef struct DumpFileIsoRec
    176 {
    177     int32_t    i32ErrorCount;
    178     int32_t    i32NumDesc;
    179 } DumpFileIsoRec;
    180 typedef DumpFileIsoRec *PDumpFileIsoRec;
    181 
    182 /**
    183  * USB packet header (Linux mmapped variant).
    184  */
    185 typedef struct DumpFileUsbHeaderLnxMmapped
    186 {
    187     /** Packet Id. */
    188     uint64_t    u64Id;
    189     /** Event type. */
    190     uint8_t     u8EventType;
    191     /** Transfer type. */
    192     uint8_t     u8TransferType;
    193     /** Endpoint number. */
    194     uint8_t     u8EndpointNumber;
    195     /** Device address. */
    196     uint8_t     u8DeviceAddress;
    197     /** Bus id. */
    198     uint16_t    u16BusId;
    199     /** Setup flag != 0 if the URB setup header is not present. */
    200     uint8_t     u8SetupFlag;
    201     /** Data present flag != 0 if the URB data is not present. */
    202     uint8_t     u8DataFlag;
    203     /** Timestamp (second part). */
    204     uint64_t    u64TimestampSec;
    205     /** Timestamp (us part). */
    206     uint32_t    u32TimestampUSec;
    207     /** Status. */
    208     int32_t     i32Status;
    209     /** URB length. */
    210     uint32_t    u32UrbLength;
    211     /** Recorded data length. */
    212     uint32_t    u32DataLength;
    213     /** Union of data for different URB types. */
    214     union
    215     {
    216         DumpFileUsbSetup    UsbSetup;
    217         DumpFileIsoRec      IsoRec;
    218     } u;
    219     int32_t     i32Interval;
    220     int32_t     i32StartFrame;
    221     /** Copy of transfer flags. */
    222     uint32_t    u32XferFlags;
    223     /** Number of isochronous descriptors. */
    224     uint32_t    u32NumDesc;
    225 } DumpFileUsbHeaderLnxMmapped;
    226 /** Pointer to a USB packet header. */
    227 typedef DumpFileUsbHeaderLnxMmapped *PDumpFileUsbHeaderLnxMmapped;
    228 
    229 AssertCompileSize(DumpFileUsbHeaderLnxMmapped, 64);
    230 
    231 /**
    232  * USB packet isochronous descriptor.
    233  */
    234 typedef struct DumpFileUsbIsoDesc
    235 {
    236     int32_t     i32Status;
    237     uint32_t    u32Offset;
    238     uint32_t    u32Len;
    239     uint8_t     au8Padding[4];
    240 } DumpFileUsbIsoDesc;
    241 typedef DumpFileUsbIsoDesc *PDumpFileUsbIsoDesc;
    242 
    24337
    24438/*********************************************************************************************************************************
     
    25347    /** The file handle to dump to. */
    25448    RTFILE            hFile;
    255     /** Current size of the block being written. */
    256     uint32_t          cbBlockCur;
    257     /** Maximum size allocated for the block. */
    258     uint32_t          cbBlockMax;
    259     /** Current block header. */
    260     PDumpFileBlockHdr pBlockHdr;
    261     /** Pointer to the block data which will be written on commit. */
    262     uint8_t          *pbBlockData;
    26349    /** Fast Mutex protecting the state against concurrent access. */
    26450    RTSEMFASTMUTEX    hMtx;
     51    /** File stream. */
     52    VUSBSNIFFERSTRM   Strm;
     53    /** Pointer to the used format. */
     54    PCVUSBSNIFFERFMT  pFmt;
     55    /** Format specific state - variable in size. */
     56    uint8_t           abFmt[1];
    26557} VUSBSNIFFERINT;
    26658/** Pointer to the internal VUSB sniffer state. */
    26759typedef VUSBSNIFFERINT *PVUSBSNIFFERINT;
    26860
    269 /**
    270  * Allocates additional space for the block.
    271  *
    272  * @returns Pointer to the new unused space or NULL if out of memory.
    273  * @param   pThis           The VUSB sniffer instance.
    274  * @param   cbAdditional    The additional memory requested.
    275  */
    276 static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERINT pThis, uint32_t cbAdditional)
    277 {
    278     /* Fast path where we have enough memory allocated. */
    279     if (pThis->cbBlockCur + cbAdditional <= pThis->cbBlockMax)
    280     {
    281         void *pv = pThis->pbBlockData + pThis->cbBlockCur;
    282         pThis->cbBlockCur += cbAdditional;
    283         return pv;
    284     }
    285 
    286     /* Allocate additional memory. */
    287     uint32_t cbNew = pThis->cbBlockCur + cbAdditional;
    288     uint8_t *pbDataNew = (uint8_t *)RTMemRealloc(pThis->pbBlockData, cbNew);
    289     if (pbDataNew)
    290     {
    291         pThis->pbBlockData = pbDataNew;
    292         pThis->pBlockHdr   = (PDumpFileBlockHdr)pbDataNew;
    293 
    294         void *pv = pThis->pbBlockData + pThis->cbBlockCur;
    295         pThis->cbBlockCur = cbNew;
    296         pThis->cbBlockMax = cbNew;
    297         return pv;
     61
     62/*********************************************************************************************************************************
     63*   Static Variables                                                                                                             *
     64*********************************************************************************************************************************/
     65
     66static PCVUSBSNIFFERFMT s_aVUsbSnifferFmts[] =
     67{
     68    &g_VUsbSnifferFmtPcapNg
     69};
     70
     71
     72/*********************************************************************************************************************************
     73*   Internal Functions                                                                                                           *
     74*********************************************************************************************************************************/
     75
     76/** @copydoc VUSBSNIFFERSTRM::pfnWrite. */
     77static DECLCALLBACK(int) vusbSnifferStrmWrite(PVUSBSNIFFERSTRM pStrm, const void *pvBuf, size_t cbBuf)
     78{
     79    PVUSBSNIFFERINT pThis = RT_FROM_MEMBER(pStrm, VUSBSNIFFERINT, Strm);
     80
     81    return RTFileWrite(pThis->hFile, pvBuf, cbBuf, NULL);
     82}
     83
     84/**
     85 * Returns a supporting format writer taken from the given format name.
     86 *
     87 * @returns Pointer to the format structure or NULL if none was found.
     88 * @param   pszFmt    The format to use.
     89 */
     90static PCVUSBSNIFFERFMT vusbSnifferGetFmtFromString(const char *pszFmt)
     91{
     92    for (unsigned i = 0; i < RT_ELEMENTS(s_aVUsbSnifferFmts); i++)
     93    {
     94        if (!RTStrICmp(pszFmt, s_aVUsbSnifferFmts[i]->szName))
     95            return s_aVUsbSnifferFmts[i];
    29896    }
    29997
     
    302100
    303101/**
    304  * Adds new data to the current block.
    305  *
    306  * @returns VBox status code.
    307  * @param   pThis           The VUSB sniffer instance.
    308  * @param   pvData          The data to add.
    309  * @param   cbData          Amount of data to add.
    310  */
    311 static int vusbSnifferBlockAddData(PVUSBSNIFFERINT pThis, const void *pvData, uint32_t cbData)
    312 {
    313     int rc = VINF_SUCCESS;
    314 
    315     Assert(pThis->cbBlockCur);
    316     AssertPtr(pThis->pBlockHdr);
    317 
    318     void *pv = vusbSnifferBlockAllocSpace(pThis, cbData);
    319     if (pv)
    320         memcpy(pv, pvData, cbData);
    321     else
    322         rc = VERR_NO_MEMORY;
    323 
    324     return rc;
    325 }
    326 
    327 /**
    328  * Aligns the current block data to a 32bit boundary.
    329  *
    330  * @returns VBox status code.
    331  * @param   pThis           The VUSB sniffer instance.
    332  */
    333 static int vusbSnifferBlockAlign(PVUSBSNIFFERINT pThis)
    334 {
    335     int rc = VINF_SUCCESS;
    336 
    337     Assert(pThis->cbBlockCur);
    338 
    339     /* Pad to 32bits. */
    340     uint8_t abPad[3] = { 0 };
    341     uint32_t cbPad = RT_ALIGN_32(pThis->cbBlockCur, 4) - pThis->cbBlockCur;
    342 
    343     Assert(cbPad <= 3);
    344     if (cbPad)
    345         rc = vusbSnifferBlockAddData(pThis, abPad, cbPad);
    346 
    347     return rc;
    348 }
    349 
    350 /**
    351  * Commits the current block to the capture file.
    352  *
    353  * @returns VBox status code.
    354  * @param   pThis           The VUSB sniffer instance.
    355  */
    356 static int vusbSnifferBlockCommit(PVUSBSNIFFERINT pThis)
    357 {
    358     int rc = VINF_SUCCESS;
    359 
    360     AssertPtr(pThis->pBlockHdr);
    361 
    362     rc = vusbSnifferBlockAlign(pThis);
    363     if (RT_SUCCESS(rc))
    364     {
    365         /* Update the block total length field. */
    366         uint32_t *pcbTotalLength = (uint32_t *)vusbSnifferBlockAllocSpace(pThis, 4);
    367         if (pcbTotalLength)
     102 * Returns a supporting format writer taken from the file suffix.
     103 *
     104 * @returns Pointer to the format structure or NULL if none was found.
     105 * @param   pFilename    The file name to take the suffix from.
     106 */
     107static PCVUSBSNIFFERFMT vusbSnifferGetFmtFromFilename(const char *pszFilename)
     108{
     109    const char *pszFileExt = RTPathSuffix(pszFilename);
     110    if (!pszFileExt)
     111        return NULL;
     112
     113    pszFileExt++; /* Skip the dot. */
     114
     115    for (unsigned i = 0; i < RT_ELEMENTS(s_aVUsbSnifferFmts); i++)
     116    {
     117        unsigned idxFileExt = 0;
     118
     119        while (s_aVUsbSnifferFmts[i]->papszFileExts[idxFileExt])
    368120        {
    369             *pcbTotalLength = pThis->cbBlockCur;
    370             pThis->pBlockHdr->u32BlockTotalLength = pThis->cbBlockCur;
    371 
    372             /* Write the data. */
    373             rc = RTFileWrite(pThis->hFile, pThis->pbBlockData, pThis->cbBlockCur, NULL);
    374             pThis->cbBlockCur = 0;
    375             pThis->pBlockHdr  = NULL;
     121            if (!RTStrICmp(pszFileExt, s_aVUsbSnifferFmts[i]->papszFileExts[idxFileExt]))
     122                return s_aVUsbSnifferFmts[i];
     123
     124            idxFileExt++;
    376125        }
    377         else
    378             rc = VERR_NO_MEMORY;
    379     }
    380 
    381     return rc;
    382 }
    383 
    384 /**
    385  * Starts a new block for capturing.
    386  *
    387  * @returns VBox status code.
    388  * @param   pThis           The VUSB sniffer instance.
    389  * @param   pBlockHdr       Pointer to the block header for the new block.
    390  * @param   cbData          Amount of data added with this block.
    391  */
    392 static int vusbSnifferBlockNew(PVUSBSNIFFERINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)
    393 {
    394     int rc = VINF_SUCCESS;
    395 
    396     /* Validate we don't get called while another block is active. */
    397     Assert(!pThis->cbBlockCur);
    398     Assert(!pThis->pBlockHdr);
    399     pThis->pBlockHdr = (PDumpFileBlockHdr)vusbSnifferBlockAllocSpace(pThis, cbData);
    400     if (pThis->pBlockHdr)
    401         memcpy(pThis->pBlockHdr, pBlockHdr, cbData);
    402     else
    403         rc = VERR_NO_MEMORY;
    404 
    405     return rc;
    406 }
    407 
    408 /**
    409  * Add a new option to the current block.
    410  *
    411  * @returns VBox status code.
    412  * @param   pThis           The VUSB sniffer instance.
    413  * @param   u16OptionCode   The option code identifying the type of option.
    414  * @param   pvOption        Raw data for the option.
    415  * @param   cbOption        Size of the optiob data.
    416  */
    417 static int vusbSnifferAddOption(PVUSBSNIFFERINT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption)
    418 {
    419     int rc = VINF_SUCCESS;
    420     DumpFileOptionHdr OptHdr;
    421 
    422     OptHdr.u16OptionCode   = u16OptionCode;
    423     OptHdr.u16OptionLength = cbOption;
    424     rc = vusbSnifferBlockAddData(pThis, &OptHdr, sizeof(OptHdr));
    425     if (   RT_SUCCESS(rc)
    426         && u16OptionCode != DUMPFILE_OPTION_CODE_END
    427         && cbOption != 0)
    428     {
    429         rc = vusbSnifferBlockAddData(pThis, pvOption, cbOption);
    430         if (RT_SUCCESS(rc))
    431             rc = vusbSnifferBlockAlign(pThis);
    432     }
    433 
    434     return rc;
    435 }
     126    }
     127
     128    return NULL;
     129}
     130
    436131
    437132DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags,
    438                                   const char *pszCaptureFilename, const char *pszDesc)
     133                                  const char *pszCaptureFilename, const char *pszFmt,
     134                                  const char *pszDesc)
    439135{
    440136    int rc = VINF_SUCCESS;
    441137    PVUSBSNIFFERINT pThis = NULL;
    442 
    443     pThis = (PVUSBSNIFFERINT)RTMemAllocZ(sizeof(VUSBSNIFFERINT));
     138    PCVUSBSNIFFERFMT pFmt = NULL;
     139
     140    if (pszFmt)
     141        pFmt = vusbSnifferGetFmtFromString(pszFmt);
     142    else
     143        pFmt = vusbSnifferGetFmtFromFilename(pszCaptureFilename);
     144
     145    if (!pFmt)
     146        return VERR_NOT_FOUND;
     147
     148    pThis = (PVUSBSNIFFERINT)RTMemAllocZ(RT_OFFSETOF(VUSBSNIFFERINT, abFmt[pFmt->cbFmt]));
    444149    if (pThis)
    445150    {
    446         pThis->hFile       = NIL_RTFILE;
    447         pThis->cbBlockCur  = 0;
    448         pThis->cbBlockMax  = 0;
    449         pThis->pbBlockData = NULL;
    450         pThis->hMtx        = NIL_RTSEMFASTMUTEX;
     151        pThis->hFile         = NIL_RTFILE;
     152        pThis->hMtx          = NIL_RTSEMFASTMUTEX;
     153        pThis->pFmt          = pFmt;
     154        pThis->Strm.pfnWrite = vusbSnifferStrmWrite;
    451155
    452156        rc = RTSemFastMutexCreate(&pThis->hMtx);
     
    456160            if (RT_SUCCESS(rc))
    457161            {
    458                 /* Write header and link type blocks. */
    459                 DumpFileShb Shb;
    460 
    461                 Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
    462                 Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    463                 Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
    464                 Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
    465                 Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
    466                 Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */
    467 
    468                 /* Write the blocks. */
    469                 rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
    470                 if (RT_SUCCESS(rc))
    471                 {
    472                     const char *pszOpt = RTBldCfgTargetDotArch();
    473                     rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
    474                 }
    475 
    476                 if (RT_SUCCESS(rc))
    477                 {
    478                     char szTmp[512];
    479                     size_t cbTmp = sizeof(szTmp);
    480 
    481                     RT_ZERO(szTmp);
    482 
    483                     /* Build the OS code. */
    484                     rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
    485                     if (RT_SUCCESS(rc))
    486                     {
    487                         size_t cb = strlen(szTmp);
    488 
    489                         szTmp[cb] = ' ';
    490                         rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
    491                         if (RT_SUCCESS(rc))
    492                         {
    493                             cb = strlen(szTmp);
    494                             szTmp[cb] = ' ';
    495                             rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
    496                         }
    497                     }
    498 
    499                     if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
    500                         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
    501                     else
    502                         rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
    503                 }
    504 
    505                 if (RT_SUCCESS(rc))
    506                 {
    507                     /** @todo: Add product info. */
    508                 }
    509 
    510                 if (RT_SUCCESS(rc))
    511                     rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    512                 if (RT_SUCCESS(rc))
    513                     rc = vusbSnifferBlockCommit(pThis);
    514 
    515                 /* Write Interface descriptor block. */
    516                 if (RT_SUCCESS(rc))
    517                 {
    518                     DumpFileIdb Idb;
    519 
    520                     Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
    521                     Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    522                     Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
    523                     Idb.u16Reserved             = 0;
    524                     Idb.u32SnapLen              = UINT32_C(0xffffffff);
    525 
    526                     rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
    527                     if (RT_SUCCESS(rc))
    528                     {
    529                         uint8_t u8TsResolution = 9; /* Nano second resolution. */
    530                         /* Add timestamp resolution option. */
    531                         rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
    532                                                   &u8TsResolution, sizeof(u8TsResolution));
    533                     }
    534                     if (RT_SUCCESS(rc))
    535                         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    536                     if (RT_SUCCESS(rc))
    537                         rc = vusbSnifferBlockCommit(pThis);
    538                 }
    539 
     162                rc = pThis->pFmt->pfnInit((PVUSBSNIFFERFMTINT)&pThis->abFmt[0], &pThis->Strm);
    540163                if (RT_SUCCESS(rc))
    541164                {
     
    551174            pThis->hMtx = NIL_RTSEMFASTMUTEX;
    552175        }
    553         if (pThis->pbBlockData)
    554             RTMemFree(pThis->pbBlockData);
     176
    555177        RTMemFree(pThis);
    556178    }
     
    574196    AssertRC(rc);
    575197
     198    pThis->pFmt->pfnDestroy((PVUSBSNIFFERFMTINT)&pThis->abFmt[0]);
     199
    576200    if (pThis->hFile != NIL_RTFILE)
    577201        RTFileClose(pThis->hFile);
    578     if (pThis->pbBlockData)
    579         RTMemFree(pThis->pbBlockData);
    580202
    581203    RTSemFastMutexRelease(pThis->hMtx);
     
    596218    int rc = VINF_SUCCESS;
    597219    PVUSBSNIFFERINT pThis = hSniffer;
    598     DumpFileEpb Epb;
    599     DumpFileUsbHeaderLnxMmapped UsbHdr;
    600     DumpFileUsbSetup UsbSetup;
    601     RTTIMESPEC TimeNow;
    602     uint64_t u64TimestampEvent;
    603     size_t cbUrbLength = 0;
    604     uint32_t cbDataLength = 0;
    605     uint32_t cbCapturedLength = sizeof(UsbHdr);
    606     uint32_t cIsocPkts = 0;
    607     uint8_t *pbData = NULL;
    608 
    609     RTTimeNow(&TimeNow);
    610     u64TimestampEvent = RTTimeSpecGetNano(&TimeNow);
    611 
    612     /* Start with the enhanced packet block. */
    613     Epb.Hdr.u32BlockType        = DUMPFILE_EPB_BLOCK_TYPE;
    614     Epb.Hdr.u32BlockTotalLength = 0;
    615     Epb.u32InterfaceId          = 0;
    616     Epb.u32TimestampHigh        = (u64TimestampEvent >> 32) & UINT32_C(0xffffffff);
    617     Epb.u32TimestampLow         = u64TimestampEvent & UINT32_C(0xffffffff);
    618 
    619     UsbHdr.u64Id = (uint64_t)pUrb; /** @todo: check whether the pointer is a good ID. */
    620     switch (enmEvent)
    621     {
    622         case VUSBSNIFFEREVENT_SUBMIT:
    623             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_SUBMIT;
    624             cbUrbLength = pUrb->cbData;
    625             break;
    626         case VUSBSNIFFEREVENT_COMPLETE:
    627             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_COMPLETE;
    628             cbUrbLength = pUrb->cbData;
    629             break;
    630         case VUSBSNIFFEREVENT_ERROR_SUBMIT:
    631         case VUSBSNIFFEREVENT_ERROR_COMPLETE:
    632             UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_ERROR;
    633             break;
    634         default:
    635             AssertMsgFailed(("Invalid event type %d\n", enmEvent));
    636     }
    637     cbDataLength = cbUrbLength;
    638     pbData = &pUrb->abData[0];
    639 
    640     switch (pUrb->enmType)
    641     {
    642         case VUSBXFERTYPE_ISOC:
    643         {
    644                 int32_t i32ErrorCount = 0;
    645 
    646                 UsbHdr.u8TransferType = 0;
    647                 cIsocPkts = pUrb->cIsocPkts;
    648                 for (unsigned i = 0; i < cIsocPkts; i++)
    649                     if (   pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
    650                         && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
    651                         i32ErrorCount++;
    652 
    653                 UsbHdr.u.IsoRec.i32ErrorCount = i32ErrorCount;
    654                 UsbHdr.u.IsoRec.i32NumDesc    = pUrb->cIsocPkts;
    655                 cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    656                 break;
    657         }
    658         case VUSBXFERTYPE_BULK:
    659                 UsbHdr.u8TransferType = 3;
    660                 break;
    661         case VUSBXFERTYPE_INTR:
    662                 UsbHdr.u8TransferType = 1;
    663                 break;
    664         case VUSBXFERTYPE_CTRL:
    665         case VUSBXFERTYPE_MSG:
    666                 UsbHdr.u8TransferType = 2;
    667                 break;
    668         default:
    669             AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
    670     }
    671 
    672     if (pUrb->enmDir == VUSBDIRECTION_IN)
    673     {
    674         if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
    675             cbDataLength = 0;
    676     }
    677     else if (pUrb->enmDir == VUSBDIRECTION_OUT)
    678     {
    679         if (   enmEvent == VUSBSNIFFEREVENT_COMPLETE
    680             || pUrb->enmType == VUSBXFERTYPE_CTRL
    681             || pUrb->enmType == VUSBXFERTYPE_MSG)
    682             cbDataLength = 0;
    683     }
    684     else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
    685         cbDataLength -= sizeof(VUSBSETUP);
    686 
    687     Epb.u32CapturedLen = cbCapturedLength + cbDataLength;
    688     Epb.u32PacketLen   = cbCapturedLength + cbUrbLength;
    689 
    690     UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00);
    691     UsbHdr.u8DeviceAddress  = pUrb->DstAddress;
    692     UsbHdr.u16BusId         = 0;
    693     UsbHdr.u8DataFlag       = cbDataLength ? 0 : 1;
    694     UsbHdr.u64TimestampSec  = u64TimestampEvent / RT_NS_1SEC_64;
    695     UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC;
    696     UsbHdr.i32Status        = pUrb->enmStatus;
    697     UsbHdr.u32UrbLength     = cbUrbLength;
    698     UsbHdr.u32DataLength    = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    699     UsbHdr.i32Interval      = 0;
    700     UsbHdr.i32StartFrame    = 0;
    701     UsbHdr.u32XferFlags     = 0;
    702     UsbHdr.u32NumDesc       = cIsocPkts;
    703 
    704     if (   (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL)
    705         && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
    706     {
    707         PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
    708 
    709         UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType;
    710         UsbHdr.u.UsbSetup.bRequest      = pSetup->bRequest;
    711         UsbHdr.u.UsbSetup.wValue        = pSetup->wValue;
    712         UsbHdr.u.UsbSetup.wIndex        = pSetup->wIndex;
    713         UsbHdr.u.UsbSetup.wLength       = pSetup->wLength;
    714         UsbHdr.u8SetupFlag              = 0;
    715     }
    716     else
    717         UsbHdr.u8SetupFlag  = '-'; /* Follow usbmon source here. */
    718220
    719221    /* Write the packet to the capture file. */
     
    721223    if (RT_SUCCESS(rc))
    722224    {
    723         rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
    724         if (RT_SUCCESS(rc))
    725             rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
    726 
    727         /* Add Isochronous descriptors now. */
    728         for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
    729         {
    730             DumpFileUsbIsoDesc IsoDesc;
    731             IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
    732             IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
    733             IsoDesc.u32Len    = pUrb->aIsocPkts[i].cb;
    734             rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
    735         }
    736 
    737         /* Record data. */
    738         if (   RT_SUCCESS(rc)
    739             && cbDataLength)
    740             rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
    741 
    742         if (RT_SUCCESS(rc))
    743             rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    744 
    745         if (RT_SUCCESS(rc))
    746             rc = vusbSnifferBlockCommit(pThis);
    747 
     225        rc = pThis->pFmt->pfnRecordEvent((PVUSBSNIFFERFMTINT)&pThis->abFmt[0], pUrb, enmEvent);
    748226        RTSemFastMutexRelease(pThis->hMtx);
    749227    }
  • trunk/src/VBox/Devices/USB/VUSBSniffer.h

    r56292 r59615  
    55
    66/*
    7  * Copyright (C) 2014-2015 Oracle Corporation
     7 * Copyright (C) 2014-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2525RT_C_DECLS_BEGIN
    2626
    27 /** Opauqe VUSB sniffer handle. */
     27/** Opaque VUSB sniffer handle. */
    2828typedef struct VUSBSNIFFERINT *VUSBSNIFFER;
    2929/** Pointer to a VUSB sniffer handle. */
     
    5959 * @param   fFlags                Flags, reserved, must be 0.
    6060 * @param   pszCaptureFilename    The filename to use for capturing the sniffed data.
     61 * @param   pszFmt                The format of the dump, NULL to select one based on the filename
     62 *                                extension.
    6163 * @param   pszDesc               Optional description for the dump.
    6264 */
    6365DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags,
    64                                   const char *pszCaptureFilename, const char *pszDesc);
     66                                  const char *pszCaptureFilename, const char *pszFmt,
     67                                  const char *pszDesc);
    6568
    6669/**
  • trunk/src/VBox/Devices/USB/VUSBSnifferPcapNg.cpp

    r59601 r59615  
    11/* $Id$ */
    22/** @file
    3  * Virtual USB - Sniffer facility.
     3 * Virtual USB Sniffer facility - PCAP-NG format writer.
    44 */
    55
    66/*
    7  * Copyright (C) 2014-2015 Oracle Corporation
     7 * Copyright (C) 2014-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2222#define LOG_GROUP LOG_GROUP_DRV_VUSB
    2323#include <VBox/log.h>
    24 #include <iprt/file.h>
    2524#include <iprt/mem.h>
    2625#include <iprt/buildconfig.h>
    2726#include <iprt/string.h>
    2827#include <iprt/system.h>
    29 #include <iprt/semaphore.h>
    3028#include <iprt/time.h>
    3129
    32 #include "VUSBSniffer.h"
     30#include "VUSBSnifferInternal.h"
    3331
    3432
     
    249247 * The internal VUSB sniffer state.
    250248 */
    251 typedef struct VUSBSNIFFERINT
    252 {
    253     /** The file handle to dump to. */
    254     RTFILE            hFile;
     249typedef struct VUSBSNIFFERFMTINT
     250{
     251    /** Stream handle. */
     252    PVUSBSNIFFERSTRM  pStrm;
    255253    /** Current size of the block being written. */
    256254    uint32_t          cbBlockCur;
     
    261259    /** Pointer to the block data which will be written on commit. */
    262260    uint8_t          *pbBlockData;
    263     /** Fast Mutex protecting the state against concurrent access. */
    264     RTSEMFASTMUTEX    hMtx;
    265 } VUSBSNIFFERINT;
    266 /** Pointer to the internal VUSB sniffer state. */
    267 typedef VUSBSNIFFERINT *PVUSBSNIFFERINT;
     261} VUSBSNIFFERFMTINT;
     262
     263
     264/*********************************************************************************************************************************
     265*   Static Variables                                                                                                             *
     266*********************************************************************************************************************************/
     267
     268/**
     269 * Supported file extensions.
     270 */
     271static const char *s_apszFileExts[] =
     272{
     273    "pcap",
     274    "pcapng",
     275    NULL
     276};
     277
     278
     279/*********************************************************************************************************************************
     280*   Internal Functions                                                                                                           *
     281*********************************************************************************************************************************/
    268282
    269283/**
     
    274288 * @param   cbAdditional    The additional memory requested.
    275289 */
    276 static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERINT pThis, uint32_t cbAdditional)
     290static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERFMTINT pThis, uint32_t cbAdditional)
    277291{
    278292    /* Fast path where we have enough memory allocated. */
     
    309323 * @param   cbData          Amount of data to add.
    310324 */
    311 static int vusbSnifferBlockAddData(PVUSBSNIFFERINT pThis, const void *pvData, uint32_t cbData)
     325static int vusbSnifferBlockAddData(PVUSBSNIFFERFMTINT pThis, const void *pvData, uint32_t cbData)
    312326{
    313327    int rc = VINF_SUCCESS;
     
    331345 * @param   pThis           The VUSB sniffer instance.
    332346 */
    333 static int vusbSnifferBlockAlign(PVUSBSNIFFERINT pThis)
     347static int vusbSnifferBlockAlign(PVUSBSNIFFERFMTINT pThis)
    334348{
    335349    int rc = VINF_SUCCESS;
     
    354368 * @param   pThis           The VUSB sniffer instance.
    355369 */
    356 static int vusbSnifferBlockCommit(PVUSBSNIFFERINT pThis)
     370static int vusbSnifferBlockCommit(PVUSBSNIFFERFMTINT pThis)
    357371{
    358372    int rc = VINF_SUCCESS;
     
    371385
    372386            /* Write the data. */
    373             rc = RTFileWrite(pThis->hFile, pThis->pbBlockData, pThis->cbBlockCur, NULL);
     387            rc = pThis->pStrm->pfnWrite(pThis->pStrm, pThis->pbBlockData, pThis->cbBlockCur);
    374388            pThis->cbBlockCur = 0;
    375389            pThis->pBlockHdr  = NULL;
     
    390404 * @param   cbData          Amount of data added with this block.
    391405 */
    392 static int vusbSnifferBlockNew(PVUSBSNIFFERINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)
     406static int vusbSnifferBlockNew(PVUSBSNIFFERFMTINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)
    393407{
    394408    int rc = VINF_SUCCESS;
     
    415429 * @param   cbOption        Size of the optiob data.
    416430 */
    417 static int vusbSnifferAddOption(PVUSBSNIFFERINT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption)
     431static int vusbSnifferAddOption(PVUSBSNIFFERFMTINT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption)
    418432{
    419433    int rc = VINF_SUCCESS;
     
    435449}
    436450
    437 DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags,
    438                                   const char *pszCaptureFilename, const char *pszDesc)
     451
     452/** @copydoc VUSBSNIFFERFMT::pfnInit */
     453static DECLCALLBACK(int) vusbSnifferFmtPcanNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
    439454{
    440455    int rc = VINF_SUCCESS;
    441     PVUSBSNIFFERINT pThis = NULL;
    442 
    443     pThis = (PVUSBSNIFFERINT)RTMemAllocZ(sizeof(VUSBSNIFFERINT));
    444     if (pThis)
    445     {
    446         pThis->hFile       = NIL_RTFILE;
    447         pThis->cbBlockCur  = 0;
    448         pThis->cbBlockMax  = 0;
    449         pThis->pbBlockData = NULL;
    450         pThis->hMtx        = NIL_RTSEMFASTMUTEX;
    451 
    452         rc = RTSemFastMutexCreate(&pThis->hMtx);
     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);
    453489        if (RT_SUCCESS(rc))
    454490        {
    455             rc = RTFileOpen(&pThis->hFile, pszCaptureFilename, RTFILE_O_DENY_NONE | RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_READ);
     491            size_t cb = strlen(szTmp);
     492
     493            szTmp[cb] = ' ';
     494            rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
    456495            if (RT_SUCCESS(rc))
    457496            {
    458                 /* Write header and link type blocks. */
    459                 DumpFileShb Shb;
    460 
    461                 Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
    462                 Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    463                 Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
    464                 Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
    465                 Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
    466                 Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */
    467 
    468                 /* Write the blocks. */
    469                 rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
    470                 if (RT_SUCCESS(rc))
    471                 {
    472                     const char *pszOpt = RTBldCfgTargetDotArch();
    473                     rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
    474                 }
    475 
    476                 if (RT_SUCCESS(rc))
    477                 {
    478                     char szTmp[512];
    479                     size_t cbTmp = sizeof(szTmp);
    480 
    481                     RT_ZERO(szTmp);
    482 
    483                     /* Build the OS code. */
    484                     rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
    485                     if (RT_SUCCESS(rc))
    486                     {
    487                         size_t cb = strlen(szTmp);
    488 
    489                         szTmp[cb] = ' ';
    490                         rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
    491                         if (RT_SUCCESS(rc))
    492                         {
    493                             cb = strlen(szTmp);
    494                             szTmp[cb] = ' ';
    495                             rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
    496                         }
    497                     }
    498 
    499                     if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
    500                         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
    501                     else
    502                         rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
    503                 }
    504 
    505                 if (RT_SUCCESS(rc))
    506                 {
    507                     /** @todo: Add product info. */
    508                 }
    509 
    510                 if (RT_SUCCESS(rc))
    511                     rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    512                 if (RT_SUCCESS(rc))
    513                     rc = vusbSnifferBlockCommit(pThis);
    514 
    515                 /* Write Interface descriptor block. */
    516                 if (RT_SUCCESS(rc))
    517                 {
    518                     DumpFileIdb Idb;
    519 
    520                     Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
    521                     Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
    522                     Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
    523                     Idb.u16Reserved             = 0;
    524                     Idb.u32SnapLen              = UINT32_C(0xffffffff);
    525 
    526                     rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
    527                     if (RT_SUCCESS(rc))
    528                     {
    529                         uint8_t u8TsResolution = 9; /* Nano second resolution. */
    530                         /* Add timestamp resolution option. */
    531                         rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
    532                                                   &u8TsResolution, sizeof(u8TsResolution));
    533                     }
    534                     if (RT_SUCCESS(rc))
    535                         rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    536                     if (RT_SUCCESS(rc))
    537                         rc = vusbSnifferBlockCommit(pThis);
    538                 }
    539 
    540                 if (RT_SUCCESS(rc))
    541                 {
    542                     *phSniffer = pThis;
    543                     return VINF_SUCCESS;
    544                 }
    545 
    546                 RTFileClose(pThis->hFile);
    547                 pThis->hFile = NIL_RTFILE;
    548                 RTFileDelete(pszCaptureFilename);
     497                cb = strlen(szTmp);
     498                szTmp[cb] = ' ';
     499                rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
    549500            }
    550             RTSemFastMutexDestroy(pThis->hMtx);
    551             pThis->hMtx = NIL_RTSEMFASTMUTEX;
    552501        }
    553         if (pThis->pbBlockData)
    554             RTMemFree(pThis->pbBlockData);
    555         RTMemFree(pThis);
    556     }
    557     else
    558         rc = VERR_NO_MEMORY;
     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);
    559547
    560548    return rc;
    561549}
    562550
    563 /**
    564  * Destroys the given VUSB sniffer instance.
    565  *
    566  * @returns nothing.
    567  * @param   hSniffer              The sniffer instance to destroy.
    568  */
    569 DECLHIDDEN(void) VUSBSnifferDestroy(VUSBSNIFFER hSniffer)
    570 {
    571     PVUSBSNIFFERINT pThis = hSniffer;
    572 
    573     int rc = RTSemFastMutexRequest(pThis->hMtx);
    574     AssertRC(rc);
    575 
    576     if (pThis->hFile != NIL_RTFILE)
    577         RTFileClose(pThis->hFile);
     551
     552/** @copydoc VUSBSNIFFERFMT::pfnDestroy */
     553static DECLCALLBACK(void) vusbSnifferFmtPcanNgDestroy(PVUSBSNIFFERFMTINT pThis)
     554{
    578555    if (pThis->pbBlockData)
    579556        RTMemFree(pThis->pbBlockData);
    580 
    581     RTSemFastMutexRelease(pThis->hMtx);
    582     RTSemFastMutexDestroy(pThis->hMtx);
    583     RTMemFree(pThis);
    584 }
    585 
    586 /**
    587  * Records an VUSB event.
    588  *
    589  * @returns VBox status code.
    590  * @param   hSniffer              The sniffer instance.
    591  * @param   pUrb                  The URB triggering the event.
    592  * @param   enmEvent              The type of event to record.
    593  */
    594 DECLHIDDEN(int) VUSBSnifferRecordEvent(VUSBSNIFFER hSniffer, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
     557}
     558
     559
     560/** @copydoc VUSBSNIFFERFMT::pfnRecordEvent */
     561static DECLCALLBACK(int) vusbSnifferFmtPcanNgRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
    595562{
    596563    int rc = VINF_SUCCESS;
    597     PVUSBSNIFFERINT pThis = hSniffer;
    598564    DumpFileEpb Epb;
    599565    DumpFileUsbHeaderLnxMmapped UsbHdr;
     
    642608        case VUSBXFERTYPE_ISOC:
    643609        {
    644                 int32_t i32ErrorCount = 0;
    645 
    646                 UsbHdr.u8TransferType = 0;
    647                 cIsocPkts = pUrb->cIsocPkts;
    648                 for (unsigned i = 0; i < cIsocPkts; i++)
    649                     if (   pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
    650                         && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
    651                         i32ErrorCount++;
    652 
    653                 UsbHdr.u.IsoRec.i32ErrorCount = i32ErrorCount;
    654                 UsbHdr.u.IsoRec.i32NumDesc    = pUrb->cIsocPkts;
    655                 cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
    656                 break;
     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;
    657623        }
    658624        case VUSBXFERTYPE_BULK:
     
    718684
    719685    /* Write the packet to the capture file. */
    720     rc = RTSemFastMutexRequest(pThis->hMtx);
    721     if (RT_SUCCESS(rc))
    722     {
    723         rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
    724         if (RT_SUCCESS(rc))
    725             rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
    726 
    727         /* Add Isochronous descriptors now. */
    728         for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
    729         {
    730             DumpFileUsbIsoDesc IsoDesc;
    731             IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
    732             IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
    733             IsoDesc.u32Len    = pUrb->aIsocPkts[i].cb;
    734             rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
    735         }
    736 
    737         /* Record data. */
    738         if (   RT_SUCCESS(rc)
    739             && cbDataLength)
    740             rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
    741 
    742         if (RT_SUCCESS(rc))
    743             rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
    744 
    745         if (RT_SUCCESS(rc))
    746             rc = vusbSnifferBlockCommit(pThis);
    747 
    748         RTSemFastMutexRelease(pThis->hMtx);
    749     }
     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);
    750710
    751711    return rc;
    752712}
    753713
     714/**
     715 * VUSB sniffer format writer.
     716 */
     717const VUSBSNIFFERFMT g_VUsbSnifferFmtPcapNg =
     718{
     719    /** szName */
     720    "PCAPNG",
     721    /** pszDesc */
     722    "PCAP-NG format writer compatible with WireShark",
     723    /** papszFileExts */
     724    &s_apszFileExts[0],
     725    /** cbFmt */
     726    sizeof(VUSBSNIFFERFMTINT),
     727    /** pfnInit */
     728    vusbSnifferFmtPcanNgInit,
     729    /** pfnDestroy */
     730    vusbSnifferFmtPcanNgDestroy,
     731    /** pfnRecordEvent */
     732    vusbSnifferFmtPcanNgRecordEvent
     733};
     734
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