VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.2 KB
Line 
1/* $Id: VUSBSnifferUsbMon.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Virtual USB Sniffer facility - Linux usbmon ASCII format.
4 */
5
6/*
7 * Copyright (C) 2016-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DRV_VUSB
33#include <VBox/log.h>
34#include <iprt/mem.h>
35#include <iprt/buildconfig.h>
36#include <iprt/string.h>
37#include <iprt/system.h>
38#include <iprt/time.h>
39
40#include "VUSBSnifferInternal.h"
41
42
43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46
47
48/*********************************************************************************************************************************
49* Structures and Typedefs *
50*********************************************************************************************************************************/
51
52/**
53 * The internal VUSB sniffer state.
54 */
55typedef struct VUSBSNIFFERFMTINT
56{
57 /** Stream handle. */
58 PVUSBSNIFFERSTRM pStrm;
59} VUSBSNIFFERFMTINT;
60
61
62/*********************************************************************************************************************************
63* Static Variables *
64*********************************************************************************************************************************/
65
66/**
67 * Supported file extensions.
68 */
69static const char *s_apszFileExts[] =
70{
71 "mon",
72 "usbmon",
73 NULL
74};
75
76
77/*********************************************************************************************************************************
78* Internal Functions *
79*********************************************************************************************************************************/
80
81
82/** @interface_method_impl{VUSBSNIFFERFMT,pfnInit} */
83static DECLCALLBACK(int) vusbSnifferFmtUsbMonInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
84{
85 pThis->pStrm = pStrm;
86 return VINF_SUCCESS;
87}
88
89
90/** @interface_method_impl{VUSBSNIFFERFMT,pfnDestroy} */
91static DECLCALLBACK(void) vusbSnifferFmtUsbMonDestroy(PVUSBSNIFFERFMTINT pThis)
92{
93 RT_NOREF(pThis);
94}
95
96
97/** @interface_method_impl{VUSBSNIFFERFMT,pfnRecordEvent} */
98static DECLCALLBACK(int) vusbSnifferFmtUsbMonRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
99{
100 char aszLineBuf[512];
101 char chEvtType = 'X';
102 char chDir = 'X';
103 char chEptType = 'X';
104
105 switch (enmEvent)
106 {
107 case VUSBSNIFFEREVENT_SUBMIT:
108 chEvtType = 'S';
109 break;
110 case VUSBSNIFFEREVENT_COMPLETE:
111 chEvtType = 'C';
112 break;
113 case VUSBSNIFFEREVENT_ERROR_SUBMIT:
114 case VUSBSNIFFEREVENT_ERROR_COMPLETE:
115 chEvtType = 'E';
116 break;
117 default:
118 AssertMsgFailed(("Invalid event type %d\n", enmEvent));
119 }
120
121 switch (pUrb->enmType)
122 {
123 case VUSBXFERTYPE_ISOC:
124 chEptType = 'Z';
125 break;
126 case VUSBXFERTYPE_BULK:
127 chEptType = 'B';
128 break;
129 case VUSBXFERTYPE_INTR:
130 chEptType = 'I';
131 break;
132 case VUSBXFERTYPE_CTRL:
133 case VUSBXFERTYPE_MSG:
134 chEptType = 'C';
135 break;
136 default:
137 AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
138 }
139
140 if (pUrb->enmDir == VUSBDIRECTION_IN)
141 chDir = 'i';
142 else if (pUrb->enmDir == VUSBDIRECTION_OUT)
143 chDir = 'o';
144 else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
145 chDir = 'o';
146
147 RT_ZERO(aszLineBuf);
148
149 /* Assemble the static part. */
150 size_t cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%p %llu %c %c%c:%u:%u:%u ",
151 pUrb, RTTimeNanoTS() / RT_NS_1US, chEvtType, chEptType, chDir,
152 0, pUrb->DstAddress, pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0x00));
153 int rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
154 if (RT_SUCCESS(rc))
155 {
156 /* Log the setup packet for control requests, the status otherwise. */
157 if ( (pUrb->enmType == VUSBXFERTYPE_CTRL || pUrb->enmType == VUSBXFERTYPE_MSG)
158 && enmEvent == VUSBSNIFFEREVENT_SUBMIT)
159 {
160 PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
161
162 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "s %02x %02x %04x %04x %04x ",
163 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
164 pSetup->wIndex, pSetup->wLength);
165 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
166 }
167 else
168 {
169 bool fLogAdditionalStatus = pUrb->enmType == VUSBXFERTYPE_ISOC
170 || pUrb->enmType == VUSBXFERTYPE_INTR;
171
172 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d%s", pUrb->enmStatus,
173 fLogAdditionalStatus ? "" : " ");
174
175 /* There are additional fields to log for isochronous and interrupt URBs. */
176 if (pUrb->enmType == VUSBXFERTYPE_ISOC)
177 {
178 if (enmEvent == VUSBSNIFFEREVENT_COMPLETE)
179 {
180 uint32_t u32ErrorCount = 0;
181
182 for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
183 if ( pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_OK
184 && pUrb->aIsocPkts[i].enmStatus != VUSBSTATUS_NOT_ACCESSED)
185 u32ErrorCount++;
186
187 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u:%u ",
188 1 /* Interval */, 0 /* Frame number */, u32ErrorCount);
189 }
190 else
191 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u ",
192 1 /* Interval */, 0 /* Frame number */);
193 }
194 else if (pUrb->enmType == VUSBXFERTYPE_INTR)
195 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u ",
196 1 /* Interval */);
197
198 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
199 }
200
201 /* Log the packet descriptors for isochronous URBs. */
202 if ( RT_SUCCESS(rc)
203 && pUrb->enmType == VUSBXFERTYPE_ISOC)
204 {
205 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%u ", pUrb->cIsocPkts);
206 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
207 for (unsigned i = 0; i < pUrb->cIsocPkts && RT_SUCCESS(rc); i++)
208 {
209 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d:%u:%u ",
210 pUrb->aIsocPkts[i].enmStatus, pUrb->aIsocPkts[i].off,
211 pUrb->aIsocPkts[i].cb);
212 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
213 }
214 }
215
216 if (RT_SUCCESS(rc))
217 {
218 /* Print data length */
219 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d n\n", pUrb->cbData);
220 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
221 }
222
223 /** @todo Dump the data */
224 }
225
226 return rc;
227}
228
229/**
230 * VUSB sniffer format writer.
231 */
232const VUSBSNIFFERFMT g_VUsbSnifferFmtUsbMon =
233{
234 /** szName */
235 "USBMON",
236 /** pszDesc */
237 "UsbMon format writer compatible with vusb-analyzer: http://vusb-analyzer.sourceforge.net",
238 /** papszFileExts */
239 &s_apszFileExts[0],
240 /** cbFmt */
241 sizeof(VUSBSNIFFERFMTINT),
242 /** pfnInit */
243 vusbSnifferFmtUsbMonInit,
244 /** pfnDestroy */
245 vusbSnifferFmtUsbMonDestroy,
246 /** pfnRecordEvent */
247 vusbSnifferFmtUsbMonRecordEvent
248};
249
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