#include <dev/usb/usb.h>
#include <dev/usb/usbpcap.h>
#include <pcap.h>
#include "interface.h"
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"};
const char *usbpcap_control_stages[] = {"setup", "data", "status"};
const char *usbpcap_request_codes[] = {
"GET_STATUS", "CLEAR_FEATURE", "?", "SET_FEATURE", "?", "SET_ADDRESS",
"GET_DESCRIPTOR", "SET_DESCRIPTOR", "GET_CONFIG", "SET_CONFIG",
"GET_INTERFACE", "SET_INTERFACE", "SYNCH_FRAME",
};
void usbpcap_print_descriptor(int);
void usbpcap_print_request_type(uByte);
void
usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
const struct usbpcap_pkt_hdr *uph;
u_int16_t hdrlen;
ts_print(&h->ts);
snapend = p + caplen;
uph = (struct usbpcap_pkt_hdr *)p;
TCHECK(uph->uph_hlen);
hdrlen = letoh16(uph->uph_hlen);
if (hdrlen < sizeof(*uph)) {
printf("[usb: invalid header length %u!]", hdrlen);
goto out;
}
TCHECK(uph[0]);
printf("bus %u %c addr %u: ep%u",
letoh16(uph->uph_bus),
((uph->uph_info & USBPCAP_INFO_DIRECTION_IN) ? '<' : '>'),
letoh16(uph->uph_devaddr), UE_GET_ADDR(uph->uph_epaddr));
if (uph->uph_xfertype < nitems(usbpcap_xfer_type))
printf(" %s", usbpcap_xfer_type[uph->uph_xfertype]);
else
printf(" ??");
printf(" dlen=%u", letoh32(uph->uph_dlen));
TCHECK2(uph[0], hdrlen);
if (uph->uph_xfertype == USBPCAP_TRANSFER_CONTROL) {
struct usbpcap_ctl_hdr *ctl_hdr = (struct usbpcap_ctl_hdr *)p;
TCHECK(ctl_hdr->uch_stage);
if (ctl_hdr->uch_stage < nitems(usbpcap_control_stages))
printf(" stage=%s",
usbpcap_control_stages[ctl_hdr->uch_stage]);
else
printf(" stage=?");
if (ctl_hdr->uch_stage == USBPCAP_CONTROL_STAGE_SETUP) {
usb_device_request_t *req;
req = (usb_device_request_t *)
(p + sizeof(struct usbpcap_ctl_hdr));
if (letoh32(uph->uph_dlen != 8)) {
printf("[usb: invalid data length %u!]",
letoh32(uph->uph_dlen));
goto out;
}
TCHECK(req[0]);
usbpcap_print_request_type(req->bmRequestType);
if (req->bRequest < nitems(usbpcap_request_codes))
printf(" bRequest=%s",
usbpcap_request_codes[req->bRequest]);
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) {
if (eflag)
default_print(p, caplen);
else
default_print(p + hdrlen, caplen - hdrlen);
}
out:
putchar('\n');
return;
trunc:
printf("[|usb]\n");
}
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(uByte 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("?");
}
}