Hi,
Currently the usbpcap is fairly terse in that it prints the endpoints,
type of transfer and data size. Below is a diff to start decoding more
data from the packets, currently focusing on control transfers:
- print the control stage
- for the Setup control transfer stage, print additional information
about the request. This diff contains the bits to decode the wValue
for GET_DESCRIPTOR requests, others will follow shortly after making sure
my approach is right.
with this diff the output (for a selection of packets) goes from this:
22:28:09.517113 bus 0 < addr 1: ep1 intr dlen=2
22:28:09.517145 bus 0 > addr 1: ep0 ctrl dlen=8
22:28:09.517146 bus 0 > addr 1: ep0 ctrl dlen=0
22:28:09.517148 bus 0 < addr 1: ep0 ctrl dlen=4
[..]
22:28:10.138325 bus 0 > addr 0: ep0 ctrl dlen=8
to this:
22:28:09.517113 bus 0 < addr 1: ep1 intr dlen=2
22:28:09.517145 bus 0 > addr 1: ep0 ctrl dlen=8 stage=setup
bmRequestType=UT_READ_CLASS_OTHER bRequest=GET_STATUS wValue=0x0000 wIndex=0003
wLength=4
22:28:09.517146 bus 0 > addr 1: ep0 ctrl dlen=0 stage=status
22:28:09.517148 bus 0 < addr 1: ep0 ctrl dlen=4 stage=data
[..]
22:28:10.138325 bus 0 > addr 0: ep0 ctrl dlen=8 stage=setup
bmRequestType=UT_READ_DEVICE bRequest=GET_DESCRIPTOR type=DEVICE index=0x00
wIndex=0000 wLength=8
OK?
Index: print-usbpcap.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-usbpcap.c,v
retrieving revision 1.3
diff -u -p -r1.3 print-usbpcap.c
--- print-usbpcap.c 22 Feb 2020 14:05:08 -0000 1.3
+++ print-usbpcap.c 23 Feb 2020 13:06:55 -0000
@@ -29,6 +29,41 @@
const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"};
+struct usbpcap_control_stage_fields {
+ uint8_t stage;
+ char *name;
+};
+
+static const struct usbpcap_control_stage_fields usb_control_stages[] = {
+ { USBPCAP_CONTROL_STAGE_SETUP, "setup" },
+ { USBPCAP_CONTROL_STAGE_DATA, "data" },
+ { USBPCAP_CONTROL_STAGE_STATUS, "status" },
+};
+
+struct usbpcap_request_code_fields {
+ uByte request;
+ char *name;
+};
+
+static const struct usbpcap_request_code_fields usb_request_codes[] = {
+ { UR_GET_STATUS, "GET_STATUS" },
+ { UR_CLEAR_FEATURE, "CLEAR_FEATURE" },
+ { 0, NULL },
+ { UR_SET_FEATURE, "SET_FEATURE" },
+ { 0, NULL },
+ { UR_SET_ADDRESS, "SET_ADDRESS" },
+ { UR_GET_DESCRIPTOR, "GET_DESCRIPTOR" },
+ { UR_SET_DESCRIPTOR, "SET_DESCRIPTOR" },
+ { UR_GET_CONFIG, "GET_CONFIG" },
+ { UR_SET_CONFIG, "SET_CONFIG" },
+ { UR_GET_INTERFACE, "GET_INTERFACE" },
+ { UR_SET_INTERFACE, "SET_INTERFACE" },
+ { UR_SYNCH_FRAME, "SYNCH_FRAME" },
+};
+
+void usbpcap_print_descriptor(int);
+void usbpcap_print_request_type(uint8_t);
+
void
usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
@@ -65,6 +100,40 @@ usbpcap_if_print(u_char *user, const str
printf(" dlen=%u", letoh32(uph->uph_dlen));
+ if (uph->uph_xfertype == USBPCAP_TRANSFER_CONTROL) {
+ struct usbpcap_ctl_hdr *ctl_hdr = (struct usbpcap_ctl_hdr *)p;
+
+ if (ctl_hdr->uch_stage < nitems(usb_control_stages))
+ printf(" stage=%s",
usb_control_stages[ctl_hdr->uch_stage].name);
+ else
+ printf(" stage=?");
+
+ if (ctl_hdr->uch_stage == USBPCAP_CONTROL_STAGE_SETUP) {
+ /* Setup packets must be 8 bytes in size as per
+ * 9.3 USB Device Requests. */
+ if (letoh32(uph->uph_dlen != 8))
+ goto trunc;
+
+ usb_device_request_t *req =
+ (usb_device_request_t *)(p+sizeof(struct
usbpcap_ctl_hdr));
+
+ usbpcap_print_request_type(req->bmRequestType);
+
+ if (req->bRequest < nitems(usb_request_codes))
+ printf(" bRequest=%s",
usb_request_codes[req->bRequest].name);
+ else
+ printf(" bRequest=?");
+
+ if (req->bRequest == UR_GET_DESCRIPTOR)
+ usbpcap_print_descriptor(UGETW(req->wValue));
+ else
+ printf(" wValue=0x%04x", UGETW(req->wValue));
+
+ printf(" wIndex=%04x", UGETW(req->wIndex));
+ printf(" wLength=%u", UGETW(req->wLength));
+ }
+ }
+
if (xflag)
default_print(p + sizeof(*uph), length - sizeof(*uph));
out:
@@ -72,4 +141,154 @@ out:
return;
trunc:
printf("[|usb]");
+}
+
+void
+usbpcap_print_descriptor(int value) {
+ printf(" type=");
+ switch (value >> 8) {
+ case UDESC_DEVICE:
+ printf("DEVICE");
+ break;
+ case UDESC_CONFIG:
+ printf("CONFIGURATION");
+ break;
+ case UDESC_STRING:
+ printf("STRING");
+ break;
+ case UDESC_INTERFACE:
+ printf("INTERFACE");
+ break;
+ case UDESC_ENDPOINT:
+ printf("ENDPOINT");
+ break;
+ case UDESC_DEVICE_QUALIFIER:
+ printf("DEVICE_QUALIFIER");
+ break;
+ case UDESC_OTHER_SPEED_CONFIGURATION:
+ printf("OTHER_SPEED_CONFIGURATION");
+ break;
+ case UDESC_INTERFACE_POWER:
+ printf("INTERFACE_POWER");
+ break;
+ case UDESC_OTG:
+ printf("OTG");
+ break;
+ case UDESC_DEBUG:
+ printf("DEBUG");
+ break;
+ case UDESC_IFACE_ASSOC:
+ printf("INTERFACE_ASSOCIATION");
+ break;
+ case UDESC_BOS:
+ printf("BOS");
+ break;
+ case UDESC_DEVICE_CAPABILITY:
+ printf("DEVICE_CAPABILITY");
+ break;
+ case UDESC_CS_DEVICE:
+ printf("CS_DEVICE");
+ break;
+ case UDESC_CS_CONFIG:
+ printf("CS_CONFIGURATION");
+ break;
+ case UDESC_CS_STRING:
+ printf("CS_STRING");
+ break;
+ case UDESC_CS_INTERFACE:
+ printf("CS_INTERFACE");
+ break;
+ case UDESC_CS_ENDPOINT:
+ printf("CS_ENDPOINT");
+ break;
+ case UDESC_HUB:
+ printf("HUB");
+ break;
+ case UDESC_SS_HUB:
+ printf("SS_HUB");
+ break;
+ case UDESC_ENDPOINT_SS_COMP:
+ printf("SS_COMPANION");
+ break;
+ default:
+ printf("?");
+ }
+
+ printf(" index=0x%02x", value & 0xff);
+}
+
+void
+usbpcap_print_request_type(uint8_t request_type) {
+ printf(" bmRequestType=");
+
+ switch (request_type) {
+ case UT_READ_DEVICE:
+ printf("UT_READ_DEVICE");
+ break;
+ case UT_READ_INTERFACE:
+ printf("UT_READ_INTERFACE");
+ break;
+ case UT_READ_ENDPOINT:
+ printf("UT_READ_ENDPOINT");
+ break;
+ case UT_WRITE_DEVICE:
+ printf("UT_WRITE_DEVICE");
+ break;
+ case UT_WRITE_INTERFACE:
+ printf("UT_WRITE_INTERFACE");
+ break;
+ case UT_WRITE_ENDPOINT:
+ printf("UT_WRITE_ENDPOINT");
+ break;
+ case UT_READ_CLASS_DEVICE:
+ printf("UT_READ_CLASS_DEVICE");
+ break;
+ case UT_READ_CLASS_INTERFACE:
+ printf("UT_READ_CLASS_INTERFACE");
+ break;
+ case UT_READ_CLASS_OTHER:
+ printf("UT_READ_CLASS_OTHER");
+ break;
+ case UT_READ_CLASS_ENDPOINT:
+ printf("UT_READ_CLASS_ENDPOINT");
+ break;
+ case UT_WRITE_CLASS_DEVICE:
+ printf("UT_WRITE_CLASS_DEVICE");
+ break;
+ case UT_WRITE_CLASS_INTERFACE:
+ printf("UT_WRITE_CLASS_INTERFACE");
+ break;
+ case UT_WRITE_CLASS_OTHER:
+ printf("UT_WRITE_CLASS_OTHER");
+ break;
+ case UT_WRITE_CLASS_ENDPOINT:
+ printf("UT_WRITE_CLASS_ENDPOINT");
+ break;
+ case UT_READ_VENDOR_DEVICE:
+ printf("UT_READ_VENDOR_DEVICE");
+ break;
+ case UT_READ_VENDOR_INTERFACE:
+ printf("UT_READ_VENDOR_INTERFACE");
+ break;
+ case UT_READ_VENDOR_OTHER:
+ printf("UT_READ_VENDOR_OTHER");
+ break;
+ case UT_READ_VENDOR_ENDPOINT:
+ printf("UT_READ_VENDOR_ENDPOINT");
+ break;
+ case UT_WRITE_VENDOR_DEVICE:
+ printf("UT_WRITE_VENDOR_DEVICE");
+ break;
+ case UT_WRITE_VENDOR_INTERFACE:
+ printf("UT_WRITE_VENDOR_INTERFACE");
+ break;
+ case UT_WRITE_VENDOR_OTHER:
+ printf("UT_WRITE_VENDOR_OTHER");
+ break;
+ case UT_WRITE_VENDOR_ENDPOINT:
+ printf("UT_WRITE_VENDOR_ENDPOINT");
+ break;
+ default:
+ printf("?");
+ }
}
--
jasper