VirtualBox

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

Last change on this file since 102788 was 98103, checked in by vboxsync, 20 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
RevLine 
[53014]1/* $Id: VUSBSnifferUsbMon.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
[59633]3 * Virtual USB Sniffer facility - Linux usbmon ASCII format.
[53014]4 */
5
6/*
[98103]7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
[53014]8 *
[96407]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
[53014]26 */
27
[57358]28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
[53014]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>
[53072]38#include <iprt/time.h>
[53014]39
[59615]40#include "VUSBSnifferInternal.h"
[53014]41
42
[57358]43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46
[62463]47
[57358]48/*********************************************************************************************************************************
49* Structures and Typedefs *
50*********************************************************************************************************************************/
51
[53014]52/**
53 * The internal VUSB sniffer state.
54 */
[59615]55typedef struct VUSBSNIFFERFMTINT
[53014]56{
[59615]57 /** Stream handle. */
58 PVUSBSNIFFERSTRM pStrm;
59} VUSBSNIFFERFMTINT;
[53014]60
[59615]61
62/*********************************************************************************************************************************
63* Static Variables *
64*********************************************************************************************************************************/
65
[53014]66/**
[59615]67 * Supported file extensions.
68 */
69static const char *s_apszFileExts[] =
70{
[59633]71 "mon",
72 "usbmon",
[59615]73 NULL
74};
75
76
77/*********************************************************************************************************************************
78* Internal Functions *
79*********************************************************************************************************************************/
80
[53014]81
[62956]82/** @interface_method_impl{VUSBSNIFFERFMT,pfnInit} */
[59633]83static DECLCALLBACK(int) vusbSnifferFmtUsbMonInit(PVUSBSNIFFERFMTINT pThis, PVUSBSNIFFERSTRM pStrm)
[53014]84{
[59633]85 pThis->pStrm = pStrm;
86 return VINF_SUCCESS;
[53014]87}
88
[59615]89
[62956]90/** @interface_method_impl{VUSBSNIFFERFMT,pfnDestroy} */
[59633]91static DECLCALLBACK(void) vusbSnifferFmtUsbMonDestroy(PVUSBSNIFFERFMTINT pThis)
[53014]92{
[62960]93 RT_NOREF(pThis);
[53014]94}
95
[59615]96
[62956]97/** @interface_method_impl{VUSBSNIFFERFMT,pfnRecordEvent} */
[59633]98static DECLCALLBACK(int) vusbSnifferFmtUsbMonRecordEvent(PVUSBSNIFFERFMTINT pThis, PVUSBURB pUrb, VUSBSNIFFEREVENT enmEvent)
[53014]99{
[59633]100 char aszLineBuf[512];
[59686]101 char chEvtType = 'X';
102 char chDir = 'X';
103 char chEptType = 'X';
[53014]104
105 switch (enmEvent)
106 {
107 case VUSBSNIFFEREVENT_SUBMIT:
[59633]108 chEvtType = 'S';
[53014]109 break;
110 case VUSBSNIFFEREVENT_COMPLETE:
[59633]111 chEvtType = 'C';
[53014]112 break;
113 case VUSBSNIFFEREVENT_ERROR_SUBMIT:
114 case VUSBSNIFFEREVENT_ERROR_COMPLETE:
[59633]115 chEvtType = 'E';
[53014]116 break;
117 default:
118 AssertMsgFailed(("Invalid event type %d\n", enmEvent));
119 }
[53146]120
[53014]121 switch (pUrb->enmType)
122 {
123 case VUSBXFERTYPE_ISOC:
[59633]124 chEptType = 'Z';
[59615]125 break;
[53014]126 case VUSBXFERTYPE_BULK:
[59633]127 chEptType = 'B';
128 break;
[53014]129 case VUSBXFERTYPE_INTR:
[59633]130 chEptType = 'I';
131 break;
[53014]132 case VUSBXFERTYPE_CTRL:
133 case VUSBXFERTYPE_MSG:
[59633]134 chEptType = 'C';
135 break;
[53014]136 default:
137 AssertMsgFailed(("invalid transfer type %d\n", pUrb->enmType));
138 }
139
[53146]140 if (pUrb->enmDir == VUSBDIRECTION_IN)
[59633]141 chDir = 'i';
[53161]142 else if (pUrb->enmDir == VUSBDIRECTION_OUT)
[59633]143 chDir = 'o';
[53168]144 else if (pUrb->enmDir == VUSBDIRECTION_SETUP)
[59633]145 chDir = 'o';
[53060]146
[59633]147 RT_ZERO(aszLineBuf);
[53072]148
[59633]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))
[53014]155 {
[59633]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;
[53014]161
[59633]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;
[53014]171
[59633]172 cch = RTStrPrintf(&aszLineBuf[0], sizeof(aszLineBuf), "%d%s", pUrb->enmStatus,
173 fLogAdditionalStatus ? "" : " ");
[59615]174
[59633]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;
[53014]181
[59633]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++;
[53014]186
[59633]187 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u:%u ",
[59700]188 1 /* Interval */, 0 /* Frame number */, u32ErrorCount);
[59633]189 }
190 else
191 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u:%u ",
[59700]192 1 /* Interval */, 0 /* Frame number */);
[59633]193 }
194 else if (pUrb->enmType == VUSBXFERTYPE_INTR)
195 cch += RTStrPrintf(&aszLineBuf[cch], sizeof(aszLineBuf) - cch, ":%u ",
196 1 /* Interval */);
[53014]197
[59633]198 rc = pThis->pStrm->pfnWrite(pThis->pStrm, &aszLineBuf[0], cch);
199 }
[53060]200
[59633]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
[63562]223 /** @todo Dump the data */
[59633]224 }
225
[53014]226 return rc;
227}
228
[59615]229/**
230 * VUSB sniffer format writer.
231 */
[59633]232const VUSBSNIFFERFMT g_VUsbSnifferFmtUsbMon =
[59615]233{
234 /** szName */
[59633]235 "USBMON",
[59615]236 /** pszDesc */
[59633]237 "UsbMon format writer compatible with vusb-analyzer: http://vusb-analyzer.sourceforge.net",
[59615]238 /** papszFileExts */
239 &s_apszFileExts[0],
240 /** cbFmt */
241 sizeof(VUSBSNIFFERFMTINT),
242 /** pfnInit */
[59633]243 vusbSnifferFmtUsbMonInit,
[59615]244 /** pfnDestroy */
[59633]245 vusbSnifferFmtUsbMonDestroy,
[59615]246 /** pfnRecordEvent */
[59633]247 vusbSnifferFmtUsbMonRecordEvent
[59615]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