VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/VUSBSnifferPcapNg.cpp@ 76474

Last change on this file since 76474 was 76474, checked in by vboxsync, 6 years ago

scm --fix-err-h src/ (bugref:9344)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.2 KB
Line 
1/* $Id: VUSBSnifferPcapNg.cpp 76474 2018-12-25 07:21:57Z vboxsync $ */
2/** @file
3 * Virtual USB Sniffer facility - PCAP-NG format writer.
4 */
5
6/*
7 * Copyright (C) 2014-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DRV_VUSB
23#include <VBox/log.h>
24#include <iprt/buildconfig.h>
25#include <iprt/errcore.h>
26#include <iprt/mem.h>
27#include <iprt/string.h>
28#include <iprt/system.h>
29#include <iprt/time.h>
30
31#include "VUSBSnifferInternal.h"
32
33
34/*********************************************************************************************************************************
35* Defined Constants And Macros *
36*********************************************************************************************************************************/
37
38/** DumpFile Section Header Block type. */
39#define DUMPFILE_SHB_BLOCK_TYPE UINT32_C(0x0a0d0d0a)
40/** The byte order magic value. */
41#define DUMPFILE_SHB_BYTE_ORDER_MAGIC UINT32_C(0x1a2b3c4d)
42/** Current major version. */
43#define DUMPFILE_SHB_VERSION_MAJOR UINT16_C(1)
44/** Current minor version. */
45#define DUMPFILE_SHB_VERSION_MINOR UINT16_C(0)
46
47/** Block type for the interface descriptor block. */
48#define DUMPFILE_IDB_BLOCK_TYPE UINT32_C(0x00000001)
49/** USB link type. */
50#define DUMPFILE_IDB_LINK_TYPE_USB_LINUX UINT16_C(189)
51#define DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED UINT16_C(220)
52
53/** Block type for an enhanced packet block. */
54#define DUMPFILE_EPB_BLOCK_TYPE UINT32_C(0x00000006)
55
56/** USB packet event types. */
57#define DUMPFILE_USB_EVENT_TYPE_SUBMIT ('S')
58#define DUMPFILE_USB_EVENT_TYPE_COMPLETE ('C')
59#define DUMPFILE_USB_EVENT_TYPE_ERROR ('E')
60
61#define DUMPFILE_OPTION_CODE_END UINT16_C(0)
62#define DUMPFILE_OPTION_CODE_COMMENT UINT16_C(1)
63
64#define DUMPFILE_OPTION_CODE_HARDWARE UINT16_C(2)
65#define DUMPFILE_OPTION_CODE_OS UINT16_C(3)
66#define DUMPFILE_OPTION_CODE_USERAPP UINT16_C(4)
67
68#define DUMPFILE_IDB_OPTION_TS_RESOLUTION UINT16_C(9)
69
70
71/*********************************************************************************************************************************
72* DumpFile format structures *
73*********************************************************************************************************************************/
74
75/**
76 * DumpFile Block header.
77 */
78typedef struct DumpFileBlockHdr
79{
80 /** Block type. */
81 uint32_t u32BlockType;
82 /** Block total length. */
83 uint32_t u32BlockTotalLength;
84} DumpFileBlockHdr;
85/** Pointer to a block header. */
86typedef DumpFileBlockHdr *PDumpFileBlockHdr;
87
88/**
89 * DumpFile Option header.
90 */
91typedef struct DumpFileOptionHdr
92{
93 /** Option code. */
94 uint16_t u16OptionCode;
95 /** Block total length. */
96 uint16_t u16OptionLength;
97} DumpFileOptionHdr;
98/** Pointer to a option header. */
99typedef DumpFileOptionHdr *PDumpFileOptionHdr;
100
101/**
102 * DumpFile Section Header Block.
103 */
104typedef struct DumpFileShb
105{
106 /** Block header. */
107 DumpFileBlockHdr Hdr;
108 /** Byte order magic. */
109 uint32_t u32ByteOrderMagic;
110 /** Major version. */
111 uint16_t u16VersionMajor;
112 /** Minor version. */
113 uint16_t u16VersionMinor;
114 /** Section length. */
115 uint64_t u64SectionLength;
116} DumpFileShb;
117/** Pointer to a Section Header Block. */
118typedef DumpFileShb *PDumpFileShb;
119
120/**
121 * DumpFile Interface description block.
122 */
123typedef struct DumpFileIdb
124{
125 /** Block header. */
126 DumpFileBlockHdr Hdr;
127 /** Link type. */
128 uint16_t u16LinkType;
129 /** Reserved. */
130 uint16_t u16Reserved;
131 /** Maximum number of bytes dumped from each packet. */
132 uint32_t u32SnapLen;
133} DumpFileIdb;
134/** Pointer to an Interface description block. */
135typedef DumpFileIdb *PDumpFileIdb;
136
137/**
138 * DumpFile Enhanced packet block.
139 */
140typedef struct DumpFileEpb
141{
142 /** Block header. */
143 DumpFileBlockHdr Hdr;
144 /** Interface ID. */
145 uint32_t u32InterfaceId;
146 /** Timestamp (high). */
147 uint32_t u32TimestampHigh;
148 /** Timestamp (low). */
149 uint32_t u32TimestampLow;
150 /** Captured packet length. */
151 uint32_t u32CapturedLen;
152 /** Original packet length. */
153 uint32_t u32PacketLen;
154} DumpFileEpb;
155/** Pointer to an Enhanced packet block. */
156typedef DumpFileEpb *PDumpFileEpb;
157
158/**
159 * USB setup URB data.
160 */
161typedef struct DumpFileUsbSetup
162{
163 uint8_t bmRequestType;
164 uint8_t bRequest;
165 uint16_t wValue;
166 uint16_t wIndex;
167 uint16_t wLength;
168} DumpFileUsbSetup;
169typedef DumpFileUsbSetup *PDumpFileUsbSetup;
170
171/**
172 * USB Isochronous data.
173 */
174typedef struct DumpFileIsoRec
175{
176 int32_t i32ErrorCount;
177 int32_t i32NumDesc;
178} DumpFileIsoRec;
179typedef DumpFileIsoRec *PDumpFileIsoRec;
180
181/**
182 * USB packet header (Linux mmapped variant).
183 */
184typedef struct DumpFileUsbHeaderLnxMmapped
185{
186 /** Packet Id. */
187 uint64_t u64Id;
188 /** Event type. */
189 uint8_t u8EventType;
190 /** Transfer type. */
191 uint8_t u8TransferType;
192 /** Endpoint number. */
193 uint8_t u8EndpointNumber;
194 /** Device address. */
195 uint8_t u8DeviceAddress;
196 /** Bus id. */
197 uint16_t u16BusId;
198 /** Setup flag != 0 if the URB setup header is not present. */
199 uint8_t u8SetupFlag;
200 /** Data present flag != 0 if the URB data is not present. */
201 uint8_t u8DataFlag;
202 /** Timestamp (second part). */
203 uint64_t u64TimestampSec;
204 /** Timestamp (us part). */
205 uint32_t u32TimestampUSec;
206 /** Status. */
207 int32_t i32Status;
208 /** URB length. */
209 uint32_t u32UrbLength;
210 /** Recorded data length. */
211 uint32_t u32DataLength;
212 /** Union of data for different URB types. */
213 union
214 {
215 DumpFileUsbSetup UsbSetup;
216 DumpFileIsoRec IsoRec;
217 } u;
218 int32_t i32Interval;
219 int32_t i32StartFrame;
220 /** Copy of transfer flags. */
221 uint32_t u32XferFlags;
222 /** Number of isochronous descriptors. */
223 uint32_t u32NumDesc;
224} DumpFileUsbHeaderLnxMmapped;
225/** Pointer to a USB packet header. */
226typedef DumpFileUsbHeaderLnxMmapped *PDumpFileUsbHeaderLnxMmapped;
227
228AssertCompileSize(DumpFileUsbHeaderLnxMmapped, 64);
229
230/**
231 * USB packet isochronous descriptor.
232 */
233typedef struct DumpFileUsbIsoDesc
234{
235 int32_t i32Status;
236 uint32_t u32Offset;
237 uint32_t u32Len;
238 uint8_t au8Padding[4];
239} DumpFileUsbIsoDesc;
240typedef DumpFileUsbIsoDesc *PDumpFileUsbIsoDesc;
241
242
243/*********************************************************************************************************************************
244* Structures and Typedefs *
245*********************************************************************************************************************************/
246
247/**
248 * The internal VUSB sniffer state.
249 */
250typedef struct VUSBSNIFFERFMTINT
251{
252 /** Stream handle. */
253 PVUSBSNIFFERSTRM pStrm;
254 /** Current size of the block being written. */
255 uint32_t cbBlockCur;
256 /** Maximum size allocated for the block. */
257 uint32_t cbBlockMax;
258 /** Current block header. */
259 PDumpFileBlockHdr pBlockHdr;
260 /** Pointer to the block data which will be written on commit. */
261 uint8_t *pbBlockData;
262} VUSBSNIFFERFMTINT;
263
264
265/*********************************************************************************************************************************
266* Static Variables *
267*********************************************************************************************************************************/
268
269/**
270 * Supported file extensions.
271 */
272static const char *s_apszFileExts[] =
273{
274 "pcap",
275 "pcapng",
276 NULL
277};
278
279
280/*********************************************************************************************************************************
281* Internal Functions *
282*********************************************************************************************************************************/
283
284/**
285 * Allocates additional space for the block.
286 *
287 * @returns Pointer to the new unused space or NULL if out of memory.
288 * @param pThis The VUSB sniffer instance.
289 * @param cbAdditional The additional memory requested.
290 */
291static void *vusbSnifferBlockAllocSpace(PVUSBSNIFFERFMTINT pThis, uint32_t cbAdditional)
292{
293 /* Fast path where we have enough memory allocated. */
294 if (pThis->cbBlockCur + cbAdditional <= pThis->cbBlockMax)
295 {
296 void *pv = pThis->pbBlockData + pThis->cbBlockCur;
297 pThis->cbBlockCur += cbAdditional;
298 return pv;
299 }
300
301 /* Allocate additional memory. */
302 uint32_t cbNew = pThis->cbBlockCur + cbAdditional;
303 uint8_t *pbDataNew = (uint8_t *)RTMemRealloc(pThis->pbBlockData, cbNew);
304 if (pbDataNew)
305 {
306 pThis->pbBlockData = pbDataNew;
307 pThis->pBlockHdr = (PDumpFileBlockHdr)pbDataNew;
308
309 void *pv = pThis->pbBlockData + pThis->cbBlockCur;
310 pThis->cbBlockCur = cbNew;
311 pThis->cbBlockMax = cbNew;
312 return pv;
313 }
314
315 return NULL;
316}
317
318/**
319 * Adds new data to the current block.
320 *
321 * @returns VBox status code.
322 * @param pThis The VUSB sniffer instance.
323 * @param pvData The data to add.
324 * @param cbData Amount of data to add.
325 */
326static int vusbSnifferBlockAddData(PVUSBSNIFFERFMTINT pThis, const void *pvData, uint32_t cbData)
327{
328 int rc = VINF_SUCCESS;
329
330 Assert(pThis->cbBlockCur);
331 AssertPtr(pThis->pBlockHdr);
332
333 void *pv = vusbSnifferBlockAllocSpace(pThis, cbData);
334 if (pv)
335 memcpy(pv, pvData, cbData);
336 else
337 rc = VERR_NO_MEMORY;
338
339 return rc;
340}
341
342/**
343 * Aligns the current block data to a 32bit boundary.
344 *
345 * @returns VBox status code.
346 * @param pThis The VUSB sniffer instance.
347 */
348static int vusbSnifferBlockAlign(PVUSBSNIFFERFMTINT pThis)
349{
350 int rc = VINF_SUCCESS;
351
352 Assert(pThis->cbBlockCur);
353
354 /* Pad to 32bits. */
355 uint8_t abPad[3] = { 0 };
356 uint32_t cbPad = RT_ALIGN_32(pThis->cbBlockCur, 4) - pThis->cbBlockCur;
357
358 Assert(cbPad <= 3);
359 if (cbPad)
360 rc = vusbSnifferBlockAddData(pThis, abPad, cbPad);
361
362 return rc;
363}
364
365/**
366 * Commits the current block to the capture file.
367 *
368 * @returns VBox status code.
369 * @param pThis The VUSB sniffer instance.
370 */
371static int vusbSnifferBlockCommit(PVUSBSNIFFERFMTINT pThis)
372{
373 int rc = VINF_SUCCESS;
374
375 AssertPtr(pThis->pBlockHdr);
376
377 rc = vusbSnifferBlockAlign(pThis);
378 if (RT_SUCCESS(rc))
379 {
380 /* Update the block total length field. */
381 uint32_t *pcbTotalLength = (uint32_t *)vusbSnifferBlockAllocSpace(pThis, 4);
382 if (pcbTotalLength)
383 {
384 *pcbTotalLength = pThis->cbBlockCur;
385 pThis->pBlockHdr->u32BlockTotalLength = pThis->cbBlockCur;
386
387 /* Write the data. */
388 rc = pThis->pStrm->pfnWrite(pThis->pStrm, pThis->pbBlockData, pThis->cbBlockCur);
389 pThis->cbBlockCur = 0;
390 pThis->pBlockHdr = NULL;
391 }
392 else
393 rc = VERR_NO_MEMORY;
394 }
395
396 return rc;
397}
398
399/**
400 * Starts a new block for capturing.
401 *
402 * @returns VBox status code.
403 * @param pThis The VUSB sniffer instance.
404 * @param pBlockHdr Pointer to the block header for the new block.
405 * @param cbData Amount of data added with this block.
406 */
407static int vusbSnifferBlockNew(PVUSBSNIFFERFMTINT pThis, PDumpFileBlockHdr pBlockHdr, uint32_t cbData)
408{
409 int rc = VINF_SUCCESS;
410
411 /* Validate we don't get called while another block is active. */
412 Assert(!pThis->cbBlockCur);
413 Assert(!pThis->pBlockHdr);
414 pThis->pBlockHdr = (PDumpFileBlockHdr)vusbSnifferBlockAllocSpace(pThis, cbData);
415 if (pThis->pBlockHdr)
416 memcpy(pThis->pBlockHdr, pBlockHdr, cbData);
417 else
418 rc = VERR_NO_MEMORY;
419
420 return rc;
421}
422
423/**
424 * Add a new option to the current block.
425 *
426 * @returns VBox status code.
427 * @param pThis The VUSB sniffer instance.
428 * @param u16OptionCode The option code identifying the type of option.
429 * @param pvOption Raw data for the option.
430 * @param cbOption Size of the optiob data.
431 */
432static int vusbSnifferAddOption(PVUSBSNIFFERFMTINT pThis, uint16_t u16OptionCode, const void *pvOption, size_t cbOption)
433{
434 AssertStmt((uint16_t)cbOption == cbOption, cbOption = UINT16_MAX);
435 DumpFileOptionHdr OptHdr;
436 OptHdr.u16OptionCode = u16OptionCode;
437 OptHdr.u16OptionLength = (uint16_t)cbOption;
438 int 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, (uint16_t)cbOption);
444 if (RT_SUCCESS(rc))
445 rc = vusbSnifferBlockAlign(pThis);
446 }
447
448 return rc;
449}
450
451
452/** @interface_method_impl{VUSBSNIFFERFMT,pfnInit} */
453static DECLCALLBACK(int) vusbSnifferFmtPcapNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
454{
455 pThis->pStrm = pStrm;
456 pThis->cbBlockCur = 0;
457 pThis->cbBlockMax = 0;
458 pThis->pbBlockData = NULL;
459
460 /* Write header and link type blocks. */
461 DumpFileShb Shb;
462
463 Shb.Hdr.u32BlockType = DUMPFILE_SHB_BLOCK_TYPE;
464 Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
465 Shb.u32ByteOrderMagic = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
466 Shb.u16VersionMajor = DUMPFILE_SHB_VERSION_MAJOR;
467 Shb.u16VersionMinor = DUMPFILE_SHB_VERSION_MINOR;
468 Shb.u64SectionLength = UINT64_C(0xffffffffffffffff); /* -1 */
469
470 /* Write the blocks. */
471 int rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
472 if (RT_SUCCESS(rc))
473 {
474 const char *pszOpt = RTBldCfgTargetDotArch();
475 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
476 }
477
478 if (RT_SUCCESS(rc))
479 {
480 char szTmp[512];
481 size_t cbTmp = sizeof(szTmp);
482
483 RT_ZERO(szTmp);
484
485 /* Build the OS code. */
486 rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
487 if (RT_SUCCESS(rc))
488 {
489 size_t cb = strlen(szTmp);
490
491 szTmp[cb] = ' ';
492 rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
493 if (RT_SUCCESS(rc))
494 {
495 cb = strlen(szTmp);
496 szTmp[cb] = ' ';
497 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
498 }
499 }
500
501 if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
502 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
503 else
504 rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
505 }
506
507 if (RT_SUCCESS(rc))
508 {
509 /** @todo Add product info. */
510 }
511
512 if (RT_SUCCESS(rc))
513 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
514 if (RT_SUCCESS(rc))
515 rc = vusbSnifferBlockCommit(pThis);
516
517 /* Write Interface descriptor block. */
518 if (RT_SUCCESS(rc))
519 {
520 DumpFileIdb Idb;
521
522 Idb.Hdr.u32BlockType = DUMPFILE_IDB_BLOCK_TYPE;
523 Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
524 Idb.u16LinkType = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
525 Idb.u16Reserved = 0;
526 Idb.u32SnapLen = UINT32_C(0xffffffff);
527
528 rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
529 if (RT_SUCCESS(rc))
530 {
531 uint8_t u8TsResolution = 9; /* Nano second resolution. */
532 /* Add timestamp resolution option. */
533 rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
534 &u8TsResolution, sizeof(u8TsResolution));
535 }
536 if (RT_SUCCESS(rc))
537 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
538 if (RT_SUCCESS(rc))
539 rc = vusbSnifferBlockCommit(pThis);
540 }
541
542 if ( RT_FAILURE(rc)
543 && pThis->pbBlockData)
544 RTMemFree(pThis->pbBlockData);
545
546 return rc;
547}
548
549
550/** @interface_method_impl{VUSBSNIFFERFMT,pfnDestroy} */
551static DECLCALLBACK(void) vusbSnifferFmtPcapNgDestroy(PVUSBSNIFFERFMTINT pThis)
552{
553 if (pThis->pbBlockData)
554 RTMemFree(pThis->pbBlockData);
555}
556
557
558/** @interface_method_impl{VUSBSNIFFERFMT,pfnRecordEvent} */
559static DECLCALLBACK(int) vusbSnifferFmtPcapNgRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
560{
561 DumpFileEpb Epb;
562 DumpFileUsbHeaderLnxMmapped UsbHdr;
563 uint32_t cbCapturedLength = sizeof(UsbHdr);
564 uint8_t *pbData = NULL;
565
566 RTTIMESPEC TimeNow;
567 RTTimeNow(&TimeNow);
568 uint64_t u64TimestampEvent = RTTimeSpecGetNano(&TimeNow);
569
570 /* Start with the enhanced packet block. */
571 Epb.Hdr.u32BlockType = DUMPFILE_EPB_BLOCK_TYPE;
572 Epb.Hdr.u32BlockTotalLength = 0;
573 Epb.u32InterfaceId = 0;
574 Epb.u32TimestampHigh = (u64TimestampEvent >> 32) & UINT32_C(0xffffffff);
575 Epb.u32TimestampLow = u64TimestampEvent & UINT32_C(0xffffffff);
576
577 UsbHdr.u64Id = (uintptr_t)pUrb; /** @todo check whether the pointer is a good ID. */
578 uint32_t cbUrbLength;
579 switch (enmEvent)
580 {
581 case VUSBSNIFFEREVENT_SUBMIT:
582 UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_SUBMIT;
583 cbUrbLength = pUrb->cbData;
584 break;
585 case VUSBSNIFFEREVENT_COMPLETE:
586 UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_COMPLETE;
587 cbUrbLength = pUrb->cbData;
588 break;
589 case VUSBSNIFFEREVENT_ERROR_SUBMIT:
590 case VUSBSNIFFEREVENT_ERROR_COMPLETE:
591 UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_ERROR;
592 cbUrbLength = 0;
593 break;
594 default:
595 AssertMsgFailed(("Invalid event type %d\n", enmEvent));
596 cbUrbLength = 0;
597 }
598 uint32_t cbDataLength = cbUrbLength;
599 pbData = &pUrb->abData[0];
600
601 uint32_t cIsocPkts = 0;
602 switch (pUrb->enmType)
603 {
604 case VUSBXFERTYPE_ISOC:
605 {
606 int32_t cErrors = 0;
607
608 UsbHdr.u8TransferType = 0;
609 cIsocPkts = pUrb->cIsocPkts;
610 for (unsigned i = 0; i < cIsocPkts; i++)
611 if ( pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
612 && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
613 cErrors++;
614
615 UsbHdr.u.IsoRec.i32ErrorCount = cErrors;
616 UsbHdr.u.IsoRec.i32NumDesc = pUrb->cIsocPkts;
617 cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
618 break;
619 }
620 case VUSBXFERTYPE_BULK:
621 UsbHdr.u8TransferType = 3;
622 break;
623 case VUSBXFERTYPE_INTR:
624 UsbHdr.u8TransferType = 1;
625 break;
626 case VUSBXFERTYPE_CTRL:
627 case VUSBXFERTYPE_MSG:
628 UsbHdr.u8TransferType = 2;
629 break;
630 default:
631 AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
632 }
633
634 if (pUrb->enmDir == VUSBDIRECTION_IN)
635 {
636 if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
637 cbDataLength = 0;
638 }
639 else if (pUrb->enmDir == VUSBDIRECTION_OUT)
640 {
641 if ( enmEvent == VUSBSNIFFEREVENT_COMPLETE
642 || pUrb->enmType == VUSBXFERTYPE_CTRL
643 || pUrb->enmType == VUSBXFERTYPE_MSG)
644 cbDataLength = 0;
645 }
646 else if ( pUrb->enmDir == VUSBDIRECTION_SETUP
647 && cbDataLength >= sizeof(VUSBSETUP))
648 cbDataLength -= sizeof(VUSBSETUP);
649
650 Epb.u32CapturedLen = cbCapturedLength + cbDataLength;
651 Epb.u32PacketLen = cbCapturedLength + cbUrbLength;
652
653 UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00);
654 UsbHdr.u8DeviceAddress = pUrb->DstAddress;
655 UsbHdr.u16BusId = 0;
656 UsbHdr.u8DataFlag = cbDataLength ? 0 : 1;
657 UsbHdr.u64TimestampSec = u64TimestampEvent / RT_NS_1SEC_64;
658 UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC;
659 UsbHdr.i32Status = pUrb->enmStatus;
660 UsbHdr.u32UrbLength = cbUrbLength;
661 UsbHdr.u32DataLength = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc);
662 UsbHdr.i32Interval = 0;
663 UsbHdr.i32StartFrame = 0;
664 UsbHdr.u32XferFlags = 0;
665 UsbHdr.u32NumDesc = cIsocPkts;
666
667 if ( (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL)
668 && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
669 {
670 PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
671
672 UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType;
673 UsbHdr.u.UsbSetup.bRequest = pSetup->bRequest;
674 UsbHdr.u.UsbSetup.wValue = pSetup->wValue;
675 UsbHdr.u.UsbSetup.wIndex = pSetup->wIndex;
676 UsbHdr.u.UsbSetup.wLength = pSetup->wLength;
677 UsbHdr.u8SetupFlag = 0;
678 }
679 else
680 UsbHdr.u8SetupFlag = '-'; /* Follow usbmon source here. */
681
682 /* Write the packet to the capture file. */
683 int rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
684 if (RT_SUCCESS(rc))
685 rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
686
687 /* Add Isochronous descriptors now. */
688 for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
689 {
690 DumpFileUsbIsoDesc IsoDesc;
691 IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
692 IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
693 IsoDesc.u32Len = pUrb->aIsocPkts[i].cb;
694 rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
695 }
696
697 /* Record data. */
698 if ( RT_SUCCESS(rc)
699 && cbDataLength)
700 rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
701
702 if (RT_SUCCESS(rc))
703 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
704
705 if (RT_SUCCESS(rc))
706 rc = vusbSnifferBlockCommit(pThis);
707
708 return rc;
709}
710
711/**
712 * VUSB sniffer format writer.
713 */
714const VUSBSNIFFERFMT g_VUsbSnifferFmtPcapNg =
715{
716 /** szName */
717 "PCAPNG",
718 /** pszDesc */
719 "PCAP-NG format writer compatible with WireShark",
720 /** papszFileExts */
721 &s_apszFileExts[0],
722 /** cbFmt */
723 sizeof(VUSBSNIFFERFMTINT),
724 /** pfnInit */
725 vusbSnifferFmtPcapNgInit,
726 /** pfnDestroy */
727 vusbSnifferFmtPcapNgDestroy,
728 /** pfnRecordEvent */
729 vusbSnifferFmtPcapNgRecordEvent
730};
731
Note: See TracBrowser for help on using the repository browser.

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