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

Reply via email to