VirtualBox

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

Last change on this file since 75142 was 65895, checked in by vboxsync, 8 years ago

USB/VUSBSnifferPcapNg: Adjust data length only if there if it is big enough + typo fixes

  • 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 65895 2017-02-28 10:41:05Z 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/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, size_t cbOption)
432{
433 AssertStmt((uint16_t)cbOption == cbOption, cbOption = UINT16_MAX);
434 DumpFileOptionHdr OptHdr;
435 OptHdr.u16OptionCode = u16OptionCode;
436 OptHdr.u16OptionLength = (uint16_t)cbOption;
437 int rc = vusbSnifferBlockAddData(pThis, &OptHdr, sizeof(OptHdr));
438 if ( RT_SUCCESS(rc)
439 && u16OptionCode != DUMPFILE_OPTION_CODE_END
440 && cbOption != 0)
441 {
442 rc = vusbSnifferBlockAddData(pThis, pvOption, (uint16_t)cbOption);
443 if (RT_SUCCESS(rc))
444 rc = vusbSnifferBlockAlign(pThis);
445 }
446
447 return rc;
448}
449
450
451/** @interface_method_impl{VUSBSNIFFERFMT,pfnInit} */
452static DECLCALLBACK(int) vusbSnifferFmtPcapNgInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
453{
454 pThis->pStrm = pStrm;
455 pThis->cbBlockCur = 0;
456 pThis->cbBlockMax = 0;
457 pThis->pbBlockData = NULL;
458
459 /* Write header and link type blocks. */
460 DumpFileShb Shb;
461
462 Shb.Hdr.u32BlockType = DUMPFILE_SHB_BLOCK_TYPE;
463 Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
464 Shb.u32ByteOrderMagic = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
465 Shb.u16VersionMajor = DUMPFILE_SHB_VERSION_MAJOR;
466 Shb.u16VersionMinor = DUMPFILE_SHB_VERSION_MINOR;
467 Shb.u64SectionLength = UINT64_C(0xffffffffffffffff); /* -1 */
468
469 /* Write the blocks. */
470 int rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
471 if (RT_SUCCESS(rc))
472 {
473 const char *pszOpt = RTBldCfgTargetDotArch();
474 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
475 }
476
477 if (RT_SUCCESS(rc))
478 {
479 char szTmp[512];
480 size_t cbTmp = sizeof(szTmp);
481
482 RT_ZERO(szTmp);
483
484 /* Build the OS code. */
485 rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
486 if (RT_SUCCESS(rc))
487 {
488 size_t cb = strlen(szTmp);
489
490 szTmp[cb] = ' ';
491 rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
492 if (RT_SUCCESS(rc))
493 {
494 cb = strlen(szTmp);
495 szTmp[cb] = ' ';
496 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
497 }
498 }
499
500 if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
501 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
502 else
503 rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
504 }
505
506 if (RT_SUCCESS(rc))
507 {
508 /** @todo Add product info. */
509 }
510
511 if (RT_SUCCESS(rc))
512 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
513 if (RT_SUCCESS(rc))
514 rc = vusbSnifferBlockCommit(pThis);
515
516 /* Write Interface descriptor block. */
517 if (RT_SUCCESS(rc))
518 {
519 DumpFileIdb Idb;
520
521 Idb.Hdr.u32BlockType = DUMPFILE_IDB_BLOCK_TYPE;
522 Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
523 Idb.u16LinkType = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
524 Idb.u16Reserved = 0;
525 Idb.u32SnapLen = UINT32_C(0xffffffff);
526
527 rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
528 if (RT_SUCCESS(rc))
529 {
530 uint8_t u8TsResolution = 9; /* Nano second resolution. */
531 /* Add timestamp resolution option. */
532 rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
533 &u8TsResolution, sizeof(u8TsResolution));
534 }
535 if (RT_SUCCESS(rc))
536 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
537 if (RT_SUCCESS(rc))
538 rc = vusbSnifferBlockCommit(pThis);
539 }
540
541 if ( RT_FAILURE(rc)
542 && pThis->pbBlockData)
543 RTMemFree(pThis->pbBlockData);
544
545 return rc;
546}
547
548
549/** @interface_method_impl{VUSBSNIFFERFMT,pfnDestroy} */
550static DECLCALLBACK(void) vusbSnifferFmtPcapNgDestroy(PVUSBSNIFFERFMTINT pThis)
551{
552 if (pThis->pbBlockData)
553 RTMemFree(pThis->pbBlockData);
554}
555
556
557/** @interface_method_impl{VUSBSNIFFERFMT,pfnRecordEvent} */
558static DECLCALLBACK(int) vusbSnifferFmtPcapNgRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
559{
560 DumpFileEpb Epb;
561 DumpFileUsbHeaderLnxMmapped UsbHdr;
562 uint32_t cbCapturedLength = sizeof(UsbHdr);
563 uint8_t *pbData = NULL;
564
565 RTTIMESPEC TimeNow;
566 RTTimeNow(&TimeNow);
567 uint64_t u64TimestampEvent = RTTimeSpecGetNano(&TimeNow);
568
569 /* Start with the enhanced packet block. */
570 Epb.Hdr.u32BlockType = DUMPFILE_EPB_BLOCK_TYPE;
571 Epb.Hdr.u32BlockTotalLength = 0;
572 Epb.u32InterfaceId = 0;
573 Epb.u32TimestampHigh = (u64TimestampEvent >> 32) & UINT32_C(0xffffffff);
574 Epb.u32TimestampLow = u64TimestampEvent & UINT32_C(0xffffffff);
575
576 UsbHdr.u64Id = (uintptr_t)pUrb; /** @todo check whether the pointer is a good ID. */
577 uint32_t cbUrbLength;
578 switch (enmEvent)
579 {
580 case VUSBSNIFFEREVENT_SUBMIT:
581 UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_SUBMIT;
582 cbUrbLength = pUrb->cbData;
583 break;
584 case VUSBSNIFFEREVENT_COMPLETE:
585 UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_COMPLETE;
586 cbUrbLength = pUrb->cbData;
587 break;
588 case VUSBSNIFFEREVENT_ERROR_SUBMIT:
589 case VUSBSNIFFEREVENT_ERROR_COMPLETE:
590 UsbHdr.u8EventType = DUMPFILE_USB_EVENT_TYPE_ERROR;
591 cbUrbLength = 0;
592 break;
593 default:
594 AssertMsgFailed(("Invalid event type %d\n", enmEvent));
595 cbUrbLength = 0;
596 }
597 uint32_t cbDataLength = cbUrbLength;
598 pbData = &pUrb->abData[0];
599
600 uint32_t cIsocPkts = 0;
601 switch (pUrb->enmType)
602 {
603 case VUSBXFERTYPE_ISOC:
604 {
605 int32_t cErrors = 0;
606
607 UsbHdr.u8TransferType = 0;
608 cIsocPkts = pUrb->cIsocPkts;
609 for (unsigned i = 0; i < cIsocPkts; i++)
610 if ( pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
611 && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
612 cErrors++;
613
614 UsbHdr.u.IsoRec.i32ErrorCount = cErrors;
615 UsbHdr.u.IsoRec.i32NumDesc = pUrb->cIsocPkts;
616 cbCapturedLength += cIsocPkts * sizeof(DumpFileUsbIsoDesc);
617 break;
618 }
619 case VUSBXFERTYPE_BULK:
620 UsbHdr.u8TransferType = 3;
621 break;
622 case VUSBXFERTYPE_INTR:
623 UsbHdr.u8TransferType = 1;
624 break;
625 case VUSBXFERTYPE_CTRL:
626 case VUSBXFERTYPE_MSG:
627 UsbHdr.u8TransferType = 2;
628 break;
629 default:
630 AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
631 }
632
633 if (pUrb->enmDir == VUSBDIRECTION_IN)
634 {
635 if (enmEvent == VUSBSNIFFEREVENT_SUBMIT)
636 cbDataLength = 0;
637 }
638 else if (pUrb->enmDir == VUSBDIRECTION_OUT)
639 {
640 if ( enmEvent == VUSBSNIFFEREVENT_COMPLETE
641 || pUrb->enmType == VUSBXFERTYPE_CTRL
642 || pUrb->enmType == VUSBXFERTYPE_MSG)
643 cbDataLength = 0;
644 }
645 else if ( pUrb->enmDir == VUSBDIRECTION_SETUP
646 && cbDataLength >= sizeof(VUSBSETUP))
647 cbDataLength -= sizeof(VUSBSETUP);
648
649 Epb.u32CapturedLen = cbCapturedLength + cbDataLength;
650 Epb.u32PacketLen = cbCapturedLength + cbUrbLength;
651
652 UsbHdr.u8EndpointNumber = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00);
653 UsbHdr.u8DeviceAddress = pUrb->DstAddress;
654 UsbHdr.u16BusId = 0;
655 UsbHdr.u8DataFlag = cbDataLength ? 0 : 1;
656 UsbHdr.u64TimestampSec = u64TimestampEvent / RT_NS_1SEC_64;
657 UsbHdr.u32TimestampUSec = u64TimestampEvent / RT_NS_1US_64 - UsbHdr.u64TimestampSec * RT_US_1SEC;
658 UsbHdr.i32Status = pUrb->enmStatus;
659 UsbHdr.u32UrbLength = cbUrbLength;
660 UsbHdr.u32DataLength = cbDataLength + cIsocPkts * sizeof(DumpFileUsbIsoDesc);
661 UsbHdr.i32Interval = 0;
662 UsbHdr.i32StartFrame = 0;
663 UsbHdr.u32XferFlags = 0;
664 UsbHdr.u32NumDesc = cIsocPkts;
665
666 if ( (pUrb->enmType == VUSBXFERTYPE_MSG || pUrb->enmType == VUSBXFERTYPE_CTRL)
667 && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
668 {
669 PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
670
671 UsbHdr.u.UsbSetup.bmRequestType = pSetup->bmRequestType;
672 UsbHdr.u.UsbSetup.bRequest = pSetup->bRequest;
673 UsbHdr.u.UsbSetup.wValue = pSetup->wValue;
674 UsbHdr.u.UsbSetup.wIndex = pSetup->wIndex;
675 UsbHdr.u.UsbSetup.wLength = pSetup->wLength;
676 UsbHdr.u8SetupFlag = 0;
677 }
678 else
679 UsbHdr.u8SetupFlag = '-'; /* Follow usbmon source here. */
680
681 /* Write the packet to the capture file. */
682 int rc = vusbSnifferBlockNew(pThis, &Epb.Hdr, sizeof(Epb));
683 if (RT_SUCCESS(rc))
684 rc = vusbSnifferBlockAddData(pThis, &UsbHdr, sizeof(UsbHdr));
685
686 /* Add Isochronous descriptors now. */
687 for (unsigned i = 0; i < cIsocPkts && RT_SUCCESS(rc); i++)
688 {
689 DumpFileUsbIsoDesc IsoDesc;
690 IsoDesc.i32Status = pUrb->aIsocPkts[i].enmStatus;
691 IsoDesc.u32Offset = pUrb->aIsocPkts[i].off;
692 IsoDesc.u32Len = pUrb->aIsocPkts[i].cb;
693 rc = vusbSnifferBlockAddData(pThis, &IsoDesc, sizeof(IsoDesc));
694 }
695
696 /* Record data. */
697 if ( RT_SUCCESS(rc)
698 && cbDataLength)
699 rc = vusbSnifferBlockAddData(pThis, pbData, cbDataLength);
700
701 if (RT_SUCCESS(rc))
702 rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
703
704 if (RT_SUCCESS(rc))
705 rc = vusbSnifferBlockCommit(pThis);
706
707 return rc;
708}
709
710/**
711 * VUSB sniffer format writer.
712 */
713const VUSBSNIFFERFMT g_VUsbSnifferFmtPcapNg =
714{
715 /** szName */
716 "PCAPNG",
717 /** pszDesc */
718 "PCAP-NG format writer compatible with WireShark",
719 /** papszFileExts */
720 &s_apszFileExts[0],
721 /** cbFmt */
722 sizeof(VUSBSNIFFERFMTINT),
723 /** pfnInit */
724 vusbSnifferFmtPcapNgInit,
725 /** pfnDestroy */
726 vusbSnifferFmtPcapNgDestroy,
727 /** pfnRecordEvent */
728 vusbSnifferFmtPcapNgRecordEvent
729};
730
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