4 * Copyright (c) 2021 Gerd Hoffmann <kraxel@redhat.com>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
13 #define PCAP_MAGIC 0xa1b2c3d4
17 /* https://wiki.wireshark.org/Development/LibpcapFileFormat */
20 uint32_t magic_number
; /* magic number */
21 uint16_t version_major
; /* major version number */
22 uint16_t version_minor
; /* minor version number */
23 int32_t thiszone
; /* GMT to local correction */
24 uint32_t sigfigs
; /* accuracy of timestamps */
25 uint32_t snaplen
; /* max length of captured packets, in octets */
26 uint32_t network
; /* data link type */
30 uint32_t ts_sec
; /* timestamp seconds */
31 uint32_t ts_usec
; /* timestamp microseconds */
32 uint32_t incl_len
; /* number of octets of packet saved in file */
33 uint32_t orig_len
; /* actual length of packet */
36 /* https://www.tcpdump.org/linktypes.html */
37 /* linux: Documentation/usb/usbmon.rst */
38 /* linux: drivers/usb/mon/mon_bin.c */
40 #define LINKTYPE_USB_LINUX 189 /* first 48 bytes only */
41 #define LINKTYPE_USB_LINUX_MMAPPED 220 /* full 64 byte header */
43 struct usbmon_packet
{
44 uint64_t id
; /* 0: URB ID - from submission to callback */
45 unsigned char type
; /* 8: Same as text; extensible. */
46 unsigned char xfer_type
; /* ISO (0), Intr, Control, Bulk (3) */
47 unsigned char epnum
; /* Endpoint number and transfer direction */
48 unsigned char devnum
; /* Device address */
49 uint16_t busnum
; /* 12: Bus number */
50 char flag_setup
; /* 14: Same as text */
51 char flag_data
; /* 15: Same as text; Binary zero is OK. */
52 int64_t ts_sec
; /* 16: gettimeofday */
53 int32_t ts_usec
; /* 24: gettimeofday */
54 int32_t status
; /* 28: */
55 unsigned int length
; /* 32: Length of data (submitted or actual) */
56 unsigned int len_cap
; /* 36: Delivered length */
58 unsigned char setup
[8]; /* Only for Control S-type */
59 struct iso_rec
{ /* Only for ISO */
64 int32_t interval
; /* 48: Only for Interrupt and ISO */
65 int32_t start_frame
; /* 52: For ISO */
66 uint32_t xfer_flags
; /* 56: copy of URB's transfer_flags */
67 uint32_t ndesc
; /* 60: Actual number of ISO descriptors */
68 }; /* 64 total length */
70 /* ------------------------------------------------------------------------ */
75 static int usbmon_status(USBPacket
*p
)
81 return -19; /* -ENODEV */
83 return -121; /* -EREMOTEIO */
87 static unsigned int usbmon_epnum(USBPacket
*p
)
92 epnum
|= (p
->pid
== USB_TOKEN_IN
) ? 0x80 : 0;
96 static unsigned char usbmon_xfer_type
[] = {
97 [USB_ENDPOINT_XFER_CONTROL
] = 2,
98 [USB_ENDPOINT_XFER_ISOC
] = 0,
99 [USB_ENDPOINT_XFER_BULK
] = 3,
100 [USB_ENDPOINT_XFER_INT
] = 1,
103 static void do_usb_pcap_header(FILE *fp
, struct usbmon_packet
*packet
)
105 struct pcaprec_hdr header
;
108 gettimeofday(&tv
, NULL
);
109 packet
->ts_sec
= tv
.tv_sec
;
110 packet
->ts_usec
= tv
.tv_usec
;
112 header
.ts_sec
= packet
->ts_sec
;
113 header
.ts_usec
= packet
->ts_usec
;
114 header
.incl_len
= packet
->len_cap
;
115 header
.orig_len
= packet
->length
+ sizeof(*packet
);
116 fwrite(&header
, sizeof(header
), 1, fp
);
117 fwrite(packet
, sizeof(*packet
), 1, fp
);
120 static void do_usb_pcap_ctrl(FILE *fp
, USBPacket
*p
, bool setup
)
122 USBDevice
*dev
= p
->ep
->dev
;
123 bool in
= dev
->setup_buf
[0] & USB_DIR_IN
;
124 struct usbmon_packet packet
= {
126 .type
= setup
? 'S' : 'C',
127 .xfer_type
= usbmon_xfer_type
[USB_ENDPOINT_XFER_CONTROL
],
128 .epnum
= in
? 0x80 : 0,
130 .flag_setup
= setup
? 0 : '-',
132 .length
= dev
->setup_len
,
134 int data_len
= dev
->setup_len
;
136 if (data_len
> CTRL_LEN
) {
140 memcpy(packet
.s
.setup
, dev
->setup_buf
, 8);
142 packet
.status
= usbmon_status(p
);
146 packet
.flag_data
= '<';
151 packet
.flag_data
= '>';
156 packet
.len_cap
= data_len
+ sizeof(packet
);
157 do_usb_pcap_header(fp
, &packet
);
159 fwrite(dev
->data_buf
, data_len
, 1, fp
);
165 static void do_usb_pcap_data(FILE *fp
, USBPacket
*p
, bool setup
)
167 struct usbmon_packet packet
= {
169 .type
= setup
? 'S' : 'C',
170 .xfer_type
= usbmon_xfer_type
[p
->ep
->type
],
171 .epnum
= usbmon_epnum(p
),
172 .devnum
= p
->ep
->dev
->addr
,
175 .length
= p
->iov
.size
,
177 int data_len
= p
->iov
.size
;
179 if (p
->ep
->nr
== 0) {
180 /* ignore control pipe packets */
184 if (data_len
> DATA_LEN
) {
188 packet
.status
= usbmon_status(p
);
189 if (packet
.length
> p
->actual_length
) {
190 packet
.length
= p
->actual_length
;
192 if (data_len
> p
->actual_length
) {
193 data_len
= p
->actual_length
;
197 if (p
->pid
== USB_TOKEN_IN
&& setup
) {
198 packet
.flag_data
= '<';
202 if (p
->pid
== USB_TOKEN_OUT
&& !setup
) {
203 packet
.flag_data
= '>';
208 packet
.len_cap
= data_len
+ sizeof(packet
);
209 do_usb_pcap_header(fp
, &packet
);
211 void *buf
= g_malloc(data_len
);
212 iov_to_buf(p
->iov
.iov
, p
->iov
.niov
, 0, buf
, data_len
);
213 fwrite(buf
, data_len
, 1, fp
);
220 void usb_pcap_init(FILE *fp
)
222 struct pcap_hdr header
= {
223 .magic_number
= PCAP_MAGIC
,
226 .snaplen
= MAX(CTRL_LEN
, DATA_LEN
) + sizeof(struct usbmon_packet
),
227 .network
= LINKTYPE_USB_LINUX_MMAPPED
,
230 fwrite(&header
, sizeof(header
), 1, fp
);
233 void usb_pcap_ctrl(USBPacket
*p
, bool setup
)
235 FILE *fp
= p
->ep
->dev
->pcap
;
241 do_usb_pcap_ctrl(fp
, p
, setup
);
244 void usb_pcap_data(USBPacket
*p
, bool setup
)
246 FILE *fp
= p
->ep
->dev
->pcap
;
252 do_usb_pcap_data(fp
, p
, setup
);