VirtualBox

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

Last change on this file since 62370 was 59615, checked in by vboxsync, 9 years ago

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

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.1 KB
Line 
1/* $Id: VUSBSnifferPcapNg.cpp 59615 2016-02-09 13:08:14Z vboxsync $ */
2/** @file
3 * Virtual USB Sniffer facility - PCAP-NG format writer.
4 */
5
6/*
7 * Copyright (C) 2014-2016 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/mem.h>
25#include <iprt/buildconfig.h>
26#include <iprt/string.h>
27#include <iprt/system.h>
28#include <iprt/time.h>
29
30#include "VUSBSnifferInternal.h"
31
32
33/*********************************************************************************************************************************
34* Defined Constants And Macros *
35*********************************************************************************************************************************/
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 */
77typedef struct DumpFileBlockHdr
78{
79 /** Block type. */
80 uint32_t u32BlockType;
81 /** Block total length. */
82 uint32_t u32BlockTotalLength;
83} DumpFileBlockHdr;
84/** Pointer to a block header. */
85typedef DumpFileBlockHdr *PDumpFileBlockHdr;
86
87/**
88 * DumpFile Option header.
89 */
90typedef struct DumpFileOptionHdr
91{
92 /** Option code. */
93 uint16_t u16OptionCode;
94 /** Block total length. */
95 uint16_t u16OptionLength;
96} DumpFileOptionHdr;
97/** Pointer to a option header. */
98typedef DumpFileOptionHdr *PDumpFileOptionHdr;
99
100/**
101 * DumpFile Section Header Block.
102 */
103typedef struct DumpFileShb
104{
105 /** Block header. */
106 DumpFileBlockHdr Hdr;
107 /** Byte order magic. */
108 uint32_t u32ByteOrderMagic;
109 /** Major version. */
110 uint16_t u16VersionMajor;
111 /** Minor version. */
112 uint16_t u16VersionMinor;
113 /** Section length. */
114 uint64_t u64SectionLength;
115} DumpFileShb;
116/** Pointer to a Section Header Block. */
117typedef DumpFileShb *PDumpFileShb;
118
119/**
120 * DumpFile Interface description block.
121 */
122typedef struct DumpFileIdb
123{
124 /** Block header. */
125 DumpFileBlockHdr Hdr;
126 /** Link type. */
127 uint16_t u16LinkType;
128 /** Reserved. */
129 uint16_t u16Reserved;
130 /** Maximum number of bytes dumped from each packet. */
131 uint32_t u32SnapLen;
132} DumpFileIdb;
133/** Pointer to an Interface description block. */
134typedef DumpFileIdb *PDumpFileIdb;
135
136/**
137 * DumpFile Enhanced packet block.
138 */
139typedef struct DumpFileEpb
140{
141 /** Block header. */
142 DumpFileBlockHdr Hdr;
143 /** Interface ID. */
144 uint32_t u32InterfaceId;
145 /** Timestamp (high). */
146 uint32_t u32TimestampHigh;
147 /** Timestamp (low). */
148 uint32_t u32TimestampLow;
149 /** Captured packet length. */
150 uint32_t u32CapturedLen;
151 /** Original packet length. */
152 uint32_t u32PacketLen;
153} DumpFileEpb;
154/** Pointer to an Enhanced packet block. */
155typedef DumpFileEpb *PDumpFileEpb;
156
157/**
158 * USB setup URB data.
159 */
160typedef struct DumpFileUsbSetup
161{
162 uint8_t bmRequestType;
163 uint8_t bRequest;
164 uint16_t wValue;
165 uint16_t wIndex;
166 uint16_t wLength;
167} DumpFileUsbSetup;
168typedef DumpFileUsbSetup *PDumpFileUsbSetup;
169
170/**
171 * USB Isochronous data.
172 */
173typedef struct DumpFileIsoRec
174{
175 int32_t i32ErrorCount;
176 int32_t i32NumDesc;
177} DumpFileIsoRec;
178typedef DumpFileIsoRec *PDumpFileIsoRec;
179
180/**
181 * USB packet header (Linux mmapped variant).
182 */
183typedef struct DumpFileUsbHeaderLnxMmapped
184{
185 /** Packet Id. */
186 uint64_t u64Id;
187 /** Event type. */
188 uint8_t u8EventType;
189 /** Transfer type. */
190 uint8_t u8TransferType;
191 /** Endpoint number. */
192 uint8_t u8EndpointNumber;
193 /** Device address. */
194 uint8_t u8DeviceAddress;
195 /** Bus id. */
196 uint16_t u16BusId;
197 /** Setup flag != 0 if the URB setup header is not present. */
198 uint8_t u8SetupFlag;
199 /** Data present flag != 0 if the URB data is not present. */
200 uint8_t u8DataFlag;
201 /** Timestamp (second part). */
202 uint64_t u64TimestampSec;
203 /** Timestamp (us part). */
204 uint32_t u32TimestampUSec;
205 /** Status. */
206 int32_t i32Status;
207 /** URB length. */
208 uint32_t u32UrbLength;
209 /** Recorded data length. */
210 uint32_t u32DataLength;
211 /** Union of data for different URB types. */
212 union
213 {
214 DumpFileUsbSetup UsbSetup;
215 DumpFileIsoRec IsoRec;
216 } u;
217 int32_t i32Interval;
218 int32_t i32StartFrame;
219 /** Copy of transfer flags. */
220 uint32_t u32XferFlags;
221 /** Number of isochronous descriptors. */
222 uint32_t u32NumDesc;
223} DumpFileUsbHeaderLnxMmapped;
224/** Pointer to a USB packet header. */
225typedef DumpFileUsbHeaderLnxMmapped *PDumpFileUsbHeaderLnxMmapped;
226
227AssertCompileSize(DumpFileUsbHeaderLnxMmapped, 64);
228
229/**
230 * USB packet isochronous descriptor.
231 */
232typedef struct DumpFileUsbIsoDesc
233{
234 int32_t i32Status;
235 uint32_t u32Offset;
236 uint32_t u32Len;
237 uint8_t au8Padding[4];
238} DumpFileUsbIsoDesc;
239typedef DumpFileUsbIsoDesc *PDumpFileUsbIsoDesc;
240
241
242/*********************************************************************************************************************************
243* Structures and Typedefs *
244*********************************************************************************************************************************/
245
246/**
247 * The internal VUSB sniffer state.
248 */
249typedef struct VUSBSNIFFERFMTINT
250{
251 /** Stream handle. */
252 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} VUSBSNIFFERFMTINT;
262
263
264/*********************************************************************************************************************************
265* Static Variables *
266*********************************************************************************************************************************/
267
268/**
269 * Supported file extensions.
270 */
271static const char *s_apszFileExts[] =
272{
273 "pcap",
274 "pcapng",
275 NULL
276};
277
278
279/*********************************************************************************************************************************
280* Internal Functions *
281*********************************************************************************************************************************/
282
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 */
290static 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;
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 */
325static 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;
339}
340
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 */
347static 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 */
370static 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 */
406static 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 */
431static 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 */
453static DECLCALLBACK(int) vusbSnifferFmtPcanNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
454{
455 int rc = VINF_SUCCESS;
456
457 pThis->pStrm = pStrm;
458 pThis->cbBlockCur = 0;
459 pThis->cbBlockMax = 0;
460 pThis->pbBlockData = NULL;
461
462 /* Write header and link type blocks. */
463 DumpFileShb Shb;
464
465 Shb.Hdr.u32BlockType = DUMPFILE_SHB_BLOCK_TYPE;
466 Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
467 Shb.u32ByteOrderMagic = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
468 Shb.u16VersionMajor = DUMPFILE_SHB_VERSION_MAJOR;
469 Shb.u16VersionMinor = DUMPFILE_SHB_VERSION_MINOR;
470 Shb.u64SectionLength = UINT64_C(0xffffffffffffffff); /* -1 */
471
472 /* Write the blocks. */
473 rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
474 if (RT_SUCCESS(rc))
475 {
476 const char *pszOpt = RTBldCfgTargetDotArch();
477 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
478 }
479
480 if (RT_SUCCESS(rc))
481 {
482 char szTmp[512];
483 size_t cbTmp = sizeof(szTmp);
484
485 RT_ZERO(szTmp);
486
487 /* Build the OS code. */
488 rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
489 if (RT_SUCCESS(rc))
490 {
491 size_t cb = strlen(szTmp);
492
493 szTmp[cb] = ' ';
494 rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
495 if (RT_SUCCESS(rc))
496 {
497 cb = strlen(szTmp);
498 szTmp[cb] = ' ';
499 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
500 }
501 }
502
503 if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
504 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
505 else
506 rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
507 }
508
509 if (RT_SUCCESS(rc))
510 {
511 /** @todo: Add product info. */
512 }
513
514 if (RT_SUCCESS(rc))
515 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
516 if (RT_SUCCESS(rc))
517 rc = vusbSnifferBlockCommit(pThis);
518
519 /* Write Interface descriptor block. */
520 if (RT_SUCCESS(rc))
521 {
522 DumpFileIdb Idb;
523
524 Idb.Hdr.u32BlockType = DUMPFILE_IDB_BLOCK_TYPE;
525 Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
526 Idb.u16LinkType = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
527 Idb.u16Reserved = 0;
528 Idb.u32SnapLen = UINT32_C(0xffffffff);
529
530 rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
531 if (RT_SUCCESS(rc))
532 {
533 uint8_t u8TsResolution = 9; /* Nano second resolution. */
534 /* Add timestamp resolution option. */
535 rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
536 &u8TsResolution, sizeof(u8TsResolution));
537 }
538 if (RT_SUCCESS(rc))
539 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
540 if (RT_SUCCESS(rc))
541 rc = vusbSnifferBlockCommit(pThis);
542 }
543
544 if ( RT_FAILURE(rc)
545 && pThis->pbBlockData)
546 RTMemFree(pThis->pbBlockData);
547
548 return rc;
549}
550
551
552/** @copydoc VUSBSNIFFERFMT::pfnDestroy */
553static DECLCALLBACK(void) vusbSnifferFmtPcanNgDestroy(PVUSBSNIFFERFMTINT pThis)
554{
555 if (pThis->pbBlockData)
556 RTMemFree(pThis->pbBlockData);
557}
558
559
560/** @copydoc VUSBSNIFFERFMT::pfnRecordEvent */
561static 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. */
586 switch (enmEvent)
587 {
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));
602 }
603 cbDataLength = cbUrbLength;
604 pbData = &pUrb->abData[0];
605
606 switch (pUrb->enmType)
607 {
608 case VUSBXFERTYPE_ISOC:
609 {
610 int32_t i32ErrorCount = 0;
611
612 UsbHdr.u8TransferType = 0;
613 cIsocPkts = pUrb->cIsocPkts;
614 for (unsigned i = 0; i < cIsocPkts; i++)
615 if ( pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
616 && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
617 i32ErrorCount++;
618
619 UsbHdr.u.IsoRec.i32ErrorCount = i32ErrorCount;
620 UsbHdr.u.IsoRec.i32NumDesc = pUrb->cIsocPkts;
621 cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
622 break;
623 }
624 case VUSBXFERTYPE_BULK:
625 UsbHdr.u8TransferType = 3;
626 break;
627 case VUSBXFERTYPE_INTR:
628 UsbHdr.u8TransferType = 1;
629 break;
630 case VUSBXFERTYPE_CTRL:
631 case VUSBXFERTYPE_MSG:
632 UsbHdr.u8TransferType = 2;
633 break;
634 default:
635 AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
636 }
637
638 if (pUrb->enmDir == VUSBDIRECTION_IN)
639 {
640 if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
641 cbDataLength = 0;
642 }
643 else if (pUrb->enmDir == VUSBDIRECTION_OUT)
644 {
645 if ( enmEvent == VUSBSNIFFEREVENT_COMPLETE
646 || pUrb->enmType == VUSBXFERTYPE_CTRL
647 || pUrb->enmType == VUSBXFERTYPE_MSG)
648 cbDataLength = 0;
649 }
650 else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
651 cbDataLength -= sizeof(VUSBSETUP);
652
653 Epb.u32CapturedLen = cbCapturedLength + cbDataLength;
654 Epb.u32PacketLen = cbCapturedLength + cbUrbLength;
655
656 UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00);
657 UsbHdr.u8DeviceAddress = pUrb->DstAddress;
658 UsbHdr.u16BusId = 0;
659 UsbHdr.u8DataFlag = cbDataLength ? 0 : 1;
660 UsbHdr.u64TimestampSec = u64TimestampEvent / RT_NS_1SEC_64;
661 UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC;
662 UsbHdr.i32Status = pUrb->enmStatus;
663 UsbHdr.u32UrbLength = cbUrbLength;
664 UsbHdr.u32DataLength = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc);
665 UsbHdr.i32Interval = 0;
666 UsbHdr.i32StartFrame = 0;
667 UsbHdr.u32XferFlags = 0;
668 UsbHdr.u32NumDesc = cIsocPkts;
669
670 if ( (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL)
671 && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
672 {
673 PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
674
675 UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType;
676 UsbHdr.u.UsbSetup.bRequest = pSetup->bRequest;
677 UsbHdr.u.UsbSetup.wValue = pSetup->wValue;
678 UsbHdr.u.UsbSetup.wIndex = pSetup->wIndex;
679 UsbHdr.u.UsbSetup.wLength = pSetup->wLength;
680 UsbHdr.u8SetupFlag = 0;
681 }
682 else
683 UsbHdr.u8SetupFlag = '-'; /* Follow usbmon source here. */
684
685 /* Write the packet to the capture file. */
686 rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
687 if (RT_SUCCESS(rc))
688 rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
689
690 /* Add Isochronous descriptors now. */
691 for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
692 {
693 DumpFileUsbIsoDesc IsoDesc;
694 IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
695 IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
696 IsoDesc.u32Len = pUrb->aIsocPkts[i].cb;
697 rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
698 }
699
700 /* Record data. */
701 if ( RT_SUCCESS(rc)
702 && cbDataLength)
703 rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
704
705 if (RT_SUCCESS(rc))
706 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
707
708 if (RT_SUCCESS(rc))
709 rc = vusbSnifferBlockCommit(pThis);
710
711 return rc;
712}
713
714/**
715 * VUSB sniffer format writer.
716 */
717const VUSBSNIFFERFMT g_VUsbSnifferFmtPcapNg =
718{
719 /** szName */
720 "PCAPNG",
721 /** pszDesc */
722 "PCAP-NG format writer compatible with WireShark",
723 /** papszFileExts */
724 &s_apszFileExts[0],
725 /** cbFmt */
726 sizeof(VUSBSNIFFERFMTINT),
727 /** pfnInit */
728 vusbSnifferFmtPcanNgInit,
729 /** pfnDestroy */
730 vusbSnifferFmtPcanNgDestroy,
731 /** pfnRecordEvent */
732 vusbSnifferFmtPcanNgRecordEvent
733};
734
Note: See 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