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