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