wireshark usb traces explanations
Solution 1
A USB URB is like an IP packet and a USB endpoint is like an IP port. USB endpoints 0x00-0x7F are on the host, and the endpoints 0x80-0xFF are on the device (I think). Therefore, the endpoint encodes the direction of the transfer. lsusb
will show you what endpoints and which transfer types a device supports.
I'll use "packets" in quotes to mean the unit of activity that wireshark captures. These aren't literally what is being send on the wire. For example, the "packets" will have timestamps for when transfers were initiated, even though this isn't transmitted over the USB bus.
I think the most confusing aspect of sniffing the USB protocol is that you see two Wireshark "packets" for each USB URB. When the host initiates some transfer, that is a URB_SUBMIT
(Wireshark display filter usb.urb_type == URB_SUBMIT
) . When the transfer completes, that is a URB_COMPLETE
(Wireshark display filter usb.urb_type == URB_COMPLETE
)
From what I can tell, when there is a transfer from host to device, the SUBMIT
"packet" contains the actual USB data transmitted. When there is a transfer from device to host (initiated by the host, as always), the COMPLETE
"packet" contains the actual USB data transmitted.
From the point of view of analyzing a protocol, all other "packets" are a distraction OR a URB error. To filter out the distractions, I use the following display filter
!(usb.urb_type == URB_SUBMIT && usb.endpoint_address.direction == IN) && !(usb.urb_type == URB_COMPLETE && usb.endpoint_address.direction == OUT)
I believe the USB protocol does involve some handshaking and ACKs and retransmissions, but this is all handled by the host controller, and the OS is not involved. I don't think, for example, the OS keeps track of the acknowledgements or retransmissions.
By the way, I am using the following command to analyze a protocol. In addition to doing the filtering above, it only displays the endpoint number (in decimal) and the USB data. This is on a GNU/Linux machine using the usbmon1 device to sniff, and assuming that the USB device I want to monitor is on bus 1 and has address 11.
tshark -i usbmon1 -Y "usb.device_address == 11 && !(usb.urb_type == URB_SUBMIT && usb.endpoint_address.direction == IN) && !(usb.urb_type == URB_COMPLETE && usb.endpoint_address.direction == OUT)" -Tfields -e usb.endpoint_address -e usb.capdata
EDIT: the field endpoint_address
was previously endpoint_number
Solution 2
WireShark USB logs are done at the OS level. With Linux its based on the data that usbmon generates which is based on Linux's internal URB structure described here. So, looking at kernel and WireShark comments and docs provides the best insight into what it is.
What I've found from the kernel docs is that the packets are usbmon structs followed by the data sent and received. This is the struct (copied from here):
struct usbmon_packet {
u64 id; /* 0: URB ID - from submission to callback */
unsigned char type; /* 8: Same as text; extensible. */
unsigned char xfer_type; /* ISO (0), Intr, Control, Bulk (3) */
unsigned char epnum; /* Endpoint number and transfer direction */
unsigned char devnum; /* Device address */
u16 busnum; /* 12: Bus number */
char flag_setup; /* 14: Same as text */
char flag_data; /* 15: Same as text; Binary zero is OK. */
s64 ts_sec; /* 16: gettimeofday */
s32 ts_usec; /* 24: gettimeofday */
int status; /* 28: */
unsigned int length; /* 32: Length of data (submitted or actual) */
unsigned int len_cap; /* 36: Delivered length */
union { /* 40: */
unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
struct iso_rec { /* Only for ISO */
int error_count;
int numdesc;
} iso;
} s;
int interval; /* 48: Only for Interrupt and ISO */
int start_frame; /* 52: For ISO */
unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */
unsigned int ndesc; /* 60: Actual number of ISO descriptors */
};
Related videos on Youtube
user415772
Updated on September 18, 2022Comments
-
user415772 over 1 year
I am trying to reverse engineer an usb (HID) device and cannot really figure out how what I see on wireshark (usbmon + wireshark on linux, or windows) relates to the usb protocol?. I have looked at the usb protocol from www.usb.org.
What does wireshark show?
1)One line per packet? (token, data, handshake)
2)One line per transaction? (token + [data] + handshake) (my guess)
3)One line per control transfer?
The direction of the transaction is very strange as well (to/from fields). At least,it does not match my expectations :-) ... And the data part of the enumeration, hid report etc... seems sometimes to be displayed with the setup data (8 bytes) and sometime not... I don't really know what URB is... there is no mention of that in the usb protocol as far as I could see... It looks to me that wireshark/usbmon trace at a higher stack level and tries to deduce what would be on the wire from that...
An example of what I can see is given below, what to we see here?.
a)I could not even find bmtype=0x20 (of the setup, frame No=599)in the specs.
b)Because I have a HID device, I assumed this could be a report/feature config (the enumeration is passed at this stage). So I could agree with the direction (host->device). but where is the data? Or there no data phase here? What is frame 600 then?
c)what is frame 600? the data?
d)what is frame 601? a status ACK?... but then the data and ACK have the same source?
No. Time Source Destination Protocol Length Info 599 67.996889 host 2.0 USB 36 URB_CONTROL out Frame 599: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) USB URB USBPcap pseudoheader length: 28 IRP ID: 0xfffffa800a1e2610 IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000) URB Function: URB_FUNCTION_CLASS_DEVICE (0x001a) IRP information: 0x00, Direction: FDO -> PDO URB bus id: 1 Device address: 2 Endpoint: 0x00, Direction: OUT URB transfer type: URB_CONTROL (0x02) Packet Data Length: 8 Control transfer stage: Setup (0) [Response in: 601] [bInterfaceClass: Unknown (0xffff)] URB setup bmRequestType: 0x20 0... .... = Direction: Host-to-device .01. .... = Type: Class (0x01) ...0 0000 = Recipient: Device (0x00) bRequest: 0 wValue: 0x0000 wIndex: 0 wLength: 16 0000 1c 00 10 26 1e 0a 80 fa ff ff 00 00 00 00 1a 00 ...&............ 0010 00 01 00 02 00 00 02 08 00 00 00 00 20 00 00 00 ............ ... 0020 00 00 10 00 .... No. Time Source Destination Protocol Length Info 600 67.997889 2.0 host USB 44 URB_CONTROL out Frame 600: 44 bytes on wire (352 bits), 44 bytes captured (352 bits) USB URB USBPcap pseudoheader length: 28 IRP ID: 0xfffffa800a1e2610 IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000) URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008) IRP information: 0x01, Direction: PDO -> FDO URB bus id: 1 Device address: 2 Endpoint: 0x00, Direction: OUT URB transfer type: URB_CONTROL (0x02) Packet Data Length: 16 Control transfer stage: Data (1) [Request in: 599] [Time from request: 0.001000000 seconds] [bInterfaceClass: Unknown (0xffff)] CONTROL response data 0000 1c 00 10 26 1e 0a 80 fa ff ff 00 00 00 00 08 00 ...&............ 0010 01 01 00 02 00 00 02 10 00 00 00 01 05 04 0d 56 ...............V 0020 fb 82 c0 1d 10 18 cc 02 00 00 00 01 ............ No. Time Source Destination Protocol Length Info 601 67.997889 2.0 host USB 28 GET STATUS Status Frame 601: 28 bytes on wire (224 bits), 28 bytes captured (224 bits) USB URB USBPcap pseudoheader length: 28 IRP ID: 0xfffffa800a1e2610 IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000) URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008) IRP information: 0x01, Direction: PDO -> FDO URB bus id: 1 Device address: 2 Endpoint: 0x00, Direction: OUT URB transfer type: URB_CONTROL (0x02) Packet Data Length: 0 Control transfer stage: Status (2) [Request in: 599] [Time from request: 0.001000000 seconds] 0000 1c 00 10 26 1e 0a 80 fa ff ff 00 00 00 00 08 00 ...&............ 0010 01 01 00 02 00 00 02 00 00 00 00 02 ............
Obviously I am missing something. A general explanation on how the wireshark display relates to the protocol and, (based on it), the meaning of the above trace is welcomed!
I originaly posted this on Stack Overflow, but was told it was not directly a programming question. Hope it fits better here.
-
user415772 about 9 yearsThanks for your answer, Gus. Actually this does not answer all my questions, but you gave the best (as unique) answer!. Would you mind commenting the capture I have included as example (taking from a HID device). What is it we see? what fields in the trace tells what? Thanks again!
-
Khalid about 3 yearsHas this changed recently? I'm looking at my HID devices in Wireshark and there are zero
URB_SUBMIT
andURB_COMPLETE
entries - onlyURB_INTERRUPT
. -
Gus about 3 years@Dai as tannewt clarified in their answer, this USB activity is captured based on the OS's implementation of USB. When I wrote my answer, I did not realize this might vary across different OSs. What operating system are you running? In any case, I might have based my information on a device that was not an HID, and so the transfer type might be different due to that. After reading wiki.osdev.org/USB_Human_Interface_Devices , I wonder if you'll see a different transfer type if you hit any keys that modify the keyboard lights, like Num, Caps, or Scroll Lock. Please report back!
-
Khalid about 3 years@Gus Windows 10 2004 - I was looking at the data my Logitech mouse sends to my computer. I didn't see any other types of entries besides
URB_INTERRUPT
on both my mouse and keyboard, regardless of what keyboard/mouse button I pressed. -
rlittles about 2 yearsCan i ask a tangentially-related question regarding how the Wireshark USB capture is displayed in relation to writing a driver? I did a USB capture between a device and an application, and the capture looked roughly like this: * URB_INTERRUPT out from host to target * URB_INTERRUPT out from target to host * URB_INTERRUPT out from host to target * URB_INTERRUPT out from target to host If I'm writing a driver for this device, do I need to have 4 calls to
libusb_interrupt_transfer
, or only 2 -- the ones from host to target?