Changeset 59615 in vbox for trunk/src/VBox/Devices/USB
- Timestamp:
- Feb 9, 2016 1:08:14 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/USB
- Files:
-
- 4 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/DrvVUSBRootHub.cpp
r57442 r59615 1052 1052 if (pszCaptureFilename) 1053 1053 { 1054 rc = VUSBSnifferCreate(&pThis->hSniffer, 0, pszCaptureFilename, NULL );1054 rc = VUSBSnifferCreate(&pThis->hSniffer, 0, pszCaptureFilename, NULL, NULL); 1055 1055 if (RT_FAILURE(rc)) 1056 1056 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, -
trunk/src/VBox/Devices/USB/VUSBDevice.cpp
r58364 r59615 1647 1647 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT); 1648 1648 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 1650 1659 if ( rc == VERR_TIMEOUT 1651 1660 && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC)) … … 1782 1791 if (pszCaptureFilename) 1783 1792 { 1784 rc = VUSBSnifferCreate(&pDev->hSniffer, 0, pszCaptureFilename, NULL );1793 rc = VUSBSnifferCreate(&pDev->hSniffer, 0, pszCaptureFilename, NULL, NULL); 1785 1794 AssertRCReturn(rc, rc); 1786 1795 } -
trunk/src/VBox/Devices/USB/VUSBSniffer.cpp
r57526 r59615 5 5 6 6 /* 7 * Copyright (C) 2014-201 5Oracle Corporation7 * Copyright (C) 2014-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 23 23 #include <VBox/log.h> 24 24 #include <iprt/file.h> 25 #include <iprt/path.h> 25 26 #include <iprt/mem.h> 26 #include <iprt/buildconfig.h>27 27 #include <iprt/string.h> 28 #include <iprt/system.h>29 28 #include <iprt/semaphore.h> 30 29 #include <iprt/time.h> 31 30 32 #include "VUSBSniffer .h"31 #include "VUSBSnifferInternal.h" 33 32 34 33 … … 36 35 * Defined Constants And Macros * 37 36 *********************************************************************************************************************************/ 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 DumpFileBlockHdr80 {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 DumpFileOptionHdr93 {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 DumpFileShb106 {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 DumpFileIdb125 {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 DumpFileEpb142 {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 DumpFileUsbSetup163 {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 DumpFileIsoRec176 {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 DumpFileUsbHeaderLnxMmapped186 {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 union215 {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 DumpFileUsbIsoDesc235 {236 int32_t i32Status;237 uint32_t u32Offset;238 uint32_t u32Len;239 uint8_t au8Padding[4];240 } DumpFileUsbIsoDesc;241 typedef DumpFileUsbIsoDesc *PDumpFileUsbIsoDesc;242 243 37 244 38 /********************************************************************************************************************************* … … 253 47 /** The file handle to dump to. */ 254 48 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;263 49 /** Fast Mutex protecting the state against concurrent access. */ 264 50 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]; 265 57 } VUSBSNIFFERINT; 266 58 /** Pointer to the internal VUSB sniffer state. */ 267 59 typedef VUSBSNIFFERINT *PVUSBSNIFFERINT; 268 60 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 66 static PCVUSBSNIFFERFMT s_aVUsbSnifferFmts[] = 67 { 68 &g_VUsbSnifferFmtPcapNg 69 }; 70 71 72 /********************************************************************************************************************************* 73 * Internal Functions * 74 *********************************************************************************************************************************/ 75 76 /** @copydoc VUSBSNIFFERSTRM::pfnWrite. */ 77 static 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 */ 90 static 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]; 298 96 } 299 97 … … 302 100 303 101 /** 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 */ 107 static 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]) 368 120 { 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++; 376 125 } 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 436 131 437 132 DECLHIDDEN(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) 439 135 { 440 136 int rc = VINF_SUCCESS; 441 137 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])); 444 149 if (pThis) 445 150 { 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; 451 155 452 156 rc = RTSemFastMutexCreate(&pThis->hMtx); … … 456 160 if (RT_SUCCESS(rc)) 457 161 { 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); 540 163 if (RT_SUCCESS(rc)) 541 164 { … … 551 174 pThis->hMtx = NIL_RTSEMFASTMUTEX; 552 175 } 553 if (pThis->pbBlockData) 554 RTMemFree(pThis->pbBlockData); 176 555 177 RTMemFree(pThis); 556 178 } … … 574 196 AssertRC(rc); 575 197 198 pThis->pFmt->pfnDestroy((PVUSBSNIFFERFMTINT)&pThis->abFmt[0]); 199 576 200 if (pThis->hFile != NIL_RTFILE) 577 201 RTFileClose(pThis->hFile); 578 if (pThis->pbBlockData)579 RTMemFree(pThis->pbBlockData);580 202 581 203 RTSemFastMutexRelease(pThis->hMtx); … … 596 218 int rc = VINF_SUCCESS; 597 219 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_OK650 && 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_COMPLETE680 || pUrb->enmType == VUSBXFERTYPE_CTRL681 || 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 else717 UsbHdr.u8SetupFlag = '-'; /* Follow usbmon source here. */718 220 719 221 /* Write the packet to the capture file. */ … … 721 223 if (RT_SUCCESS(rc)) 722 224 { 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); 748 226 RTSemFastMutexRelease(pThis->hMtx); 749 227 } -
trunk/src/VBox/Devices/USB/VUSBSniffer.h
r56292 r59615 5 5 6 6 /* 7 * Copyright (C) 2014-201 5Oracle Corporation7 * Copyright (C) 2014-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 25 25 RT_C_DECLS_BEGIN 26 26 27 /** Opa uqe VUSB sniffer handle. */27 /** Opaque VUSB sniffer handle. */ 28 28 typedef struct VUSBSNIFFERINT *VUSBSNIFFER; 29 29 /** Pointer to a VUSB sniffer handle. */ … … 59 59 * @param fFlags Flags, reserved, must be 0. 60 60 * @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. 61 63 * @param pszDesc Optional description for the dump. 62 64 */ 63 65 DECLHIDDEN(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); 65 68 66 69 /** -
trunk/src/VBox/Devices/USB/VUSBSnifferPcapNg.cpp
r59601 r59615 1 1 /* $Id$ */ 2 2 /** @file 3 * Virtual USB - Sniffer facility.3 * Virtual USB Sniffer facility - PCAP-NG format writer. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2014-201 5Oracle Corporation7 * Copyright (C) 2014-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 #define LOG_GROUP LOG_GROUP_DRV_VUSB 23 23 #include <VBox/log.h> 24 #include <iprt/file.h>25 24 #include <iprt/mem.h> 26 25 #include <iprt/buildconfig.h> 27 26 #include <iprt/string.h> 28 27 #include <iprt/system.h> 29 #include <iprt/semaphore.h>30 28 #include <iprt/time.h> 31 29 32 #include "VUSBSniffer .h"30 #include "VUSBSnifferInternal.h" 33 31 34 32 … … 249 247 * The internal VUSB sniffer state. 250 248 */ 251 typedef struct VUSBSNIFFER INT252 { 253 /** The file handle to dump to. */254 RTFILE hFile;249 typedef struct VUSBSNIFFERFMTINT 250 { 251 /** Stream handle. */ 252 PVUSBSNIFFERSTRM pStrm; 255 253 /** Current size of the block being written. */ 256 254 uint32_t cbBlockCur; … … 261 259 /** Pointer to the block data which will be written on commit. */ 262 260 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 */ 271 static const char *s_apszFileExts[] = 272 { 273 "pcap", 274 "pcapng", 275 NULL 276 }; 277 278 279 /********************************************************************************************************************************* 280 * Internal Functions * 281 *********************************************************************************************************************************/ 268 282 269 283 /** … … 274 288 * @param cbAdditional The additional memory requested. 275 289 */ 276 static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFER INT pThis, uint32_t cbAdditional)290 static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERFMTINT pThis, uint32_t cbAdditional) 277 291 { 278 292 /* Fast path where we have enough memory allocated. */ … … 309 323 * @param cbData Amount of data to add. 310 324 */ 311 static int vusbSnifferBlockAddData(PVUSBSNIFFER INT pThis, const void *pvData, uint32_t cbData)325 static int vusbSnifferBlockAddData(PVUSBSNIFFERFMTINT pThis, const void *pvData, uint32_t cbData) 312 326 { 313 327 int rc = VINF_SUCCESS; … … 331 345 * @param pThis The VUSB sniffer instance. 332 346 */ 333 static int vusbSnifferBlockAlign(PVUSBSNIFFER INT pThis)347 static int vusbSnifferBlockAlign(PVUSBSNIFFERFMTINT pThis) 334 348 { 335 349 int rc = VINF_SUCCESS; … … 354 368 * @param pThis The VUSB sniffer instance. 355 369 */ 356 static int vusbSnifferBlockCommit(PVUSBSNIFFER INT pThis)370 static int vusbSnifferBlockCommit(PVUSBSNIFFERFMTINT pThis) 357 371 { 358 372 int rc = VINF_SUCCESS; … … 371 385 372 386 /* Write the data. */ 373 rc = RTFileWrite(pThis->hFile, pThis->pbBlockData, pThis->cbBlockCur, NULL);387 rc = pThis->pStrm->pfnWrite(pThis->pStrm, pThis->pbBlockData, pThis->cbBlockCur); 374 388 pThis->cbBlockCur = 0; 375 389 pThis->pBlockHdr = NULL; … … 390 404 * @param cbData Amount of data added with this block. 391 405 */ 392 static int vusbSnifferBlockNew(PVUSBSNIFFER INT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)406 static int vusbSnifferBlockNew(PVUSBSNIFFERFMTINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData) 393 407 { 394 408 int rc = VINF_SUCCESS; … … 415 429 * @param cbOption Size of the optiob data. 416 430 */ 417 static int vusbSnifferAddOption(PVUSBSNIFFER INT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption)431 static int vusbSnifferAddOption(PVUSBSNIFFERFMTINT pThis, uint16_t u16OptionCode, const void *pvOption, uint16_t cbOption) 418 432 { 419 433 int rc = VINF_SUCCESS; … … 435 449 } 436 450 437 DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags, 438 const char *pszCaptureFilename, const char *pszDesc) 451 452 /** @copydoc VUSBSNIFFERFMT::pfnInit */ 453 static DECLCALLBACK(int) vusbSnifferFmtPcanNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm) 439 454 { 440 455 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); 453 489 if (RT_SUCCESS(rc)) 454 490 { 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)); 456 495 if (RT_SUCCESS(rc)) 457 496 { 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)); 549 500 } 550 RTSemFastMutexDestroy(pThis->hMtx);551 pThis->hMtx = NIL_RTSEMFASTMUTEX;552 501 } 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); 559 547 560 548 return rc; 561 549 } 562 550 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 */ 553 static DECLCALLBACK(void) vusbSnifferFmtPcanNgDestroy(PVUSBSNIFFERFMTINT pThis) 554 { 578 555 if (pThis->pbBlockData) 579 556 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 */ 561 static DECLCALLBACK(int) vusbSnifferFmtPcanNgRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent) 595 562 { 596 563 int rc = VINF_SUCCESS; 597 PVUSBSNIFFERINT pThis = hSniffer;598 564 DumpFileEpb Epb; 599 565 DumpFileUsbHeaderLnxMmapped UsbHdr; … … 642 608 case VUSBXFERTYPE_ISOC: 643 609 { 644 645 646 647 648 649 650 651 652 653 654 655 656 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; 657 623 } 658 624 case VUSBXFERTYPE_BULK: … … 718 684 719 685 /* 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); 750 710 751 711 return rc; 752 712 } 753 713 714 /** 715 * VUSB sniffer format writer. 716 */ 717 const 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.