VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/VUSBSnifferUsbMon.cpp@ 77807

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/* $Id: VUSBSnifferUsbMon.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * Virtual USB Sniffer facility - Linux usbmon ASCII format.
4 */
5
6/*
7 * Copyright (C) 2016-2019 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
38/*********************************************************************************************************************************
39* Structures and Typedefs *
40*********************************************************************************************************************************/
41
42/**
43 * The internal VUSB sniffer state.
44 */
45typedef struct VUSBSNIFFERFMTINT
46{
47 /** Stream handle. */
48 PVUSBSNIFFERSTRM pStrm;
49} VUSBSNIFFERFMTINT;
50
51
52/*********************************************************************************************************************************
53* Static Variables *
54*********************************************************************************************************************************/
55
56/**
57 * Supported file extensions.
58 */
59static const char *s_apszFileExts[] =
60{
61 "mon",
62 "usbmon",
63 NULL
64};
65
66
67/*********************************************************************************************************************************
68* Internal Functions *
69*********************************************************************************************************************************/
70
71
72/** @interface_method_impl{VUSBSNIFFERFMT,pfnInit} */
73static DECLCALLBACK(int) vusbSnifferFmtUsbMonInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
74{
75 pThis->pStrm = pStrm;
76 return VINF_SUCCESS;
77}
78
79
80/** @interface_method_impl{VUSBSNIFFERFMT,pfnDestroy} */
81static DECLCALLBACK(void) vusbSnifferFmtUsbMonDestroy(PVUSBSNIFFERFMTINT pThis)
82{
83 RT_NOREF(pThis);
84}
85
86
87/** @interface_method_impl{VUSBSNIFFERFMT,pfnRecordEvent} */
88static DECLCALLBACK(int) vusbSnifferFmtUsbMonRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
89{
90 char aszLineBuf[512];
91 char chEvtType = 'X';
92 char chDir = 'X';
93 char chEptType = 'X';
94
95 switch (enmEvent)
96 {
97 case VUSBSNIFFEREVENT_SUBMIT:
98 chEvtType = 'S';
99 break;
100 case VUSBSNIFFEREVENT_COMPLETE:
101 chEvtType = 'C';
102 break;
103 case VUSBSNIFFEREVENT_ERROR_SUBMIT:
104 case VUSBSNIFFEREVENT_ERROR_COMPLETE:
105 chEvtType = 'E';
106 break;
107 default:
108 AssertMsgFailed(("Invalid event type %d\n", enmEvent));
109 }
110
111 switch (pUrb->enmType)
112 {
113 case VUSBXFERTYPE_ISOC:
114 chEptType = 'Z';
115 break;
116 case VUSBXFERTYPE_BULK:
117 chEptType = 'B';
118 break;
119 case VUSBXFERTYPE_INTR:
120 chEptType = 'I';
121 break;
122 case VUSBXFERTYPE_CTRL:
123 case VUSBXFERTYPE_MSG:
124 chEptType = 'C';
125 break;
126 default:
127 AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
128 }
129
130 if (pUrb->enmDir == VUSBDIRECTION_IN)
131 chDir = 'i';
132 else if (pUrb->enmDir == VUSBDIRECTION_OUT)
133 chDir = 'o';
134 else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
135 chDir = 'o';
136
137 RT_ZERO(aszLineBuf);
138
139 /* Assemble the static part. */
140 size_t cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%p %llu %c %c%c:%u:%u:%u ",
141 pUrb, RTTimeNanoTS() / RT_NS_1US, chEvtType, chEptType, chDir,
142 0, pUrb->DstAddress, pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00));
143 int rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
144 if (RT_SUCCESS(rc))
145 {
146 /* Log the setup packet for control requests, the status otherwise. */
147 if ( (pUrb->enmType == VUSBXFERTYPE_CTRL || pUrb->enmType == VUSBXFERTYPE_MSG)
148 && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
149 {
150 PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
151
152 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "s %02x %02x %04x %04x %04x ",
153 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
154 pSetup->wIndex, pSetup->wLength);
155 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
156 }
157 else
158 {
159 bool fLogAdditionalStatus = pUrb->enmType == VUSBXFERTYPE_ISOC
160 || pUrb->enmType == VUSBXFERTYPE_INTR;
161
162 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d%s", pUrb->enmStatus,
163 fLogAdditionalStatus ? "" : " ");
164
165 /* There are additional fields to log for isochronous and interrupt URBs. */
166 if (pUrb->enmType == VUSBXFERTYPE_ISOC)
167 {
168 if (enmEvent == VUSBSNIFFEREVENT_COMPLETE)
169 {
170 uint32_t u32ErrorCount = 0;
171
172 for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
173 if ( pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
174 && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
175 u32ErrorCount++;
176
177 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u:%u ",
178 1 /* Interval */, 0 /* Frame number */, u32ErrorCount);
179 }
180 else
181 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u ",
182 1 /* Interval */, 0 /* Frame number */);
183 }
184 else if (pUrb->enmType == VUSBXFERTYPE_INTR)
185 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u ",
186 1 /* Interval */);
187
188 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
189 }
190
191 /* Log the packet descriptors for isochronous URBs. */
192 if ( RT_SUCCESS(rc)
193 && pUrb->enmType == VUSBXFERTYPE_ISOC)
194 {
195 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%u ", pUrb->cIsocPkts);
196 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
197 for (unsigned i = 0; i < pUrb->cIsocPkts && RT_SUCCESS(rc); i++)
198 {
199 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d:%u:%u ",
200 pUrb->aIsocPkts[i].enmStatus, pUrb->aIsocPkts[i].off,
201 pUrb->aIsocPkts[i].cb);
202 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
203 }
204 }
205
206 if (RT_SUCCESS(rc))
207 {
208 /* Print data length */
209 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d n\n", pUrb->cbData);
210 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
211 }
212
213 /** @todo Dump the data */
214 }
215
216 return rc;
217}
218
219/**
220 * VUSB sniffer format writer.
221 */
222const VUSBSNIFFERFMT g_VUsbSnifferFmtUsbMon =
223{
224 /** szName */
225 "USBMON",
226 /** pszDesc */
227 "UsbMon format writer compatible with vusb-analyzer: http://vusb-analyzer.sourceforge.net",
228 /** papszFileExts */
229 &s_apszFileExts[0],
230 /** cbFmt */
231 sizeof(VUSBSNIFFERFMTINT),
232 /** pfnInit */
233 vusbSnifferFmtUsbMonInit,
234 /** pfnDestroy */
235 vusbSnifferFmtUsbMonDestroy,
236 /** pfnRecordEvent */
237 vusbSnifferFmtUsbMonRecordEvent
238};
239
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