/* packet-usb.h * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef __PACKET_USB_H__ #define __PACKET_USB_H__ #include #include #include #include #include #include typedef struct _usb_address_t { uint32_t device; uint32_t endpoint; uint16_t bus_id; } usb_address_t; #define USB_ADDR_LEN (sizeof(usb_address_t)) /* Flag used to mark usb_address_t.endpoint as an interface * address instead of the normal endpoint address. */ #define INTERFACE_PORT 0x80000000 typedef struct _usb_conv_info_t usb_conv_info_t; typedef struct _urb_info_t urb_info_t; /* Wireshark specific (i.e. numeric values are arbitrary) enum representing * USB device speed. */ typedef enum { USB_SPEED_UNKNOWN, /* Unknown, skip speed specific processing */ USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, } usb_speed_t; /* header type */ typedef enum { USB_HEADER_LINUX_48_BYTES, USB_HEADER_LINUX_64_BYTES, USB_HEADER_USBPCAP, USB_HEADER_MAUSB, USB_HEADER_USBIP, USB_HEADER_DARWIN, USB_HEADER_PSEUDO_URB, } usb_header_t; #define USB_HEADER_IS_LINUX(type) \ ((type) == USB_HEADER_LINUX_48_BYTES || (type) == USB_HEADER_LINUX_64_BYTES) typedef struct _usb_pseudo_urb_t { bool from_host; uint8_t transfer_type; uint8_t device_address; uint8_t endpoint; uint16_t bus_id; usb_speed_t speed; } usb_pseudo_urb_t; /* there is one such structure for each request/response */ typedef struct _usb_trans_info_t { uint32_t request_in; uint32_t response_in; nstime_t req_time; usb_header_t header_type; /* Valid only for SETUP transactions */ struct _usb_setup { uint8_t requesttype; uint8_t request; uint16_t wValue; uint16_t wIndex; uint16_t wLength; } setup; /* Valid only during GET DESCRIPTOR transactions */ union { struct { uint8_t type; uint8_t usb_index; } get_descriptor; } u; /* used to pass the interface class from the * interface descriptor onto the endpoint * descriptors so that we can create a * conversation with the appropriate class * once we know the endpoint. * Valid only during GET CONFIGURATION response. */ uint8_t interface_endpoint; usb_conv_info_t *interface_info; uint64_t usb_id; } usb_trans_info_t; enum usb_conv_class_data_type { USB_CONV_UNKNOWN = 0, USB_CONV_U3V, USB_CONV_AUDIO, USB_CONV_VIDEO, USB_CONV_MASS_STORAGE_BOT, USB_CONV_MASS_STORAGE_UASP, USB_CONV_CDC_DATA, }; /* Conversation Structure * there is one such structure for each device/endpoint conversation */ struct _usb_conv_info_t { uint8_t descriptor_transfer_type; /* transfer type lifted from the configuration descriptor */ uint16_t max_packet_size; /* max packet size from configuration descriptor */ uint16_t interfaceClass; /* Interface Descriptor - class */ uint16_t interfaceSubclass; /* Interface Descriptor - subclass */ uint16_t interfaceProtocol; /* Interface Descriptor - protocol */ uint8_t interfaceNum; /* Most recent interface number */ uint16_t deviceVendor; /* Device Descriptor - USB Vendor ID */ uint32_t deviceProduct; /* Device Descriptor - USB Product ID - MSBs only for encoding unknown */ uint16_t deviceVersion; /* Device Descriptor - USB device version number BCD */ uint8_t iSerialNumber; /* Device Descriptor - iSerialNumber (0 if no serial number available) */ wmem_tree_t *transactions; void *class_data; /* private class/id decode data */ enum usb_conv_class_data_type class_data_type; wmem_array_t *alt_settings; }; /* URB data lifetime is limited to packet scope */ struct _urb_info_t { uint16_t bus_id; uint16_t device_address; uint8_t endpoint; int direction; uint8_t transfer_type; /* transfer type from URB */ uint32_t device_protocol; bool is_request; bool is_setup; uint8_t setup_requesttype; usb_speed_t speed; usb_trans_info_t *usb_trans_info; /* pointer to the current transaction */ usb_conv_info_t *conv; }; /* This is what a tap will tap */ typedef struct _usb_tap_data_t { uint8_t urb_type; uint8_t transfer_type; urb_info_t *urb; usb_trans_info_t *trans_info; } usb_tap_data_t; /* the value for "no endpoint" that's used usb_addr_t, e.g. for the address of the host */ #define NO_ENDPOINT 0xffffffff /* the 8bit version of NO_ENDPOINT, it's used in usb_conv_info_t 0xff would be an invalid endpoint number (reserved bits are 1) */ #define NO_ENDPOINT8 ((uint8_t)(NO_ENDPOINT& UINT8_MAX)) /* * Values from the Linux USB pseudo-header. */ /* * event_type values */ #define URB_SUBMIT 'S' #define URB_COMPLETE 'C' #define URB_ERROR 'E' /* * URB transfer_type values */ #define URB_ISOCHRONOUS 0x0 #define URB_INTERRUPT 0x1 #define URB_CONTROL 0x2 #define URB_BULK 0x3 #define URB_UNKNOWN 0xFF #define URB_TRANSFER_IN 0x80 /* to host */ /* http://www.usb.org/developers/defined_class */ #define IF_CLASS_DEVICE 0x00 #define IF_CLASS_AUDIO 0x01 #define IF_CLASS_COMMUNICATIONS 0x02 #define IF_CLASS_HID 0x03 #define IF_CLASS_PHYSICAL 0x05 #define IF_CLASS_IMAGE 0x06 #define IF_CLASS_PRINTER 0x07 #define IF_CLASS_MASS_STORAGE 0x08 #define IF_CLASS_HUB 0x09 #define IF_CLASS_CDC_DATA 0x0a #define IF_CLASS_SMART_CARD 0x0b #define IF_CLASS_CONTENT_SECURITY 0x0d #define IF_CLASS_VIDEO 0x0e #define IF_CLASS_PERSONAL_HEALTHCARE 0x0f #define IF_CLASS_AUDIO_VIDEO 0x10 #define IF_CLASS_BILLBOARD 0x11 #define IF_CLASS_USB_C_BRIDGE 0x12 #define IF_CLASS_BULK_DISPLAY_PROTO 0x13 #define IF_CLASS_MCTP_USB_EP 0x14 #define IF_CLASS_I3C 0x3c #define IF_CLASS_DIAGNOSTIC_DEVICE 0xdc #define IF_CLASS_WIRELESS_CONTROLLER 0xe0 #define IF_CLASS_MISCELLANEOUS 0xef #define IF_CLASS_APPLICATION_SPECIFIC 0xfe #define IF_CLASS_VENDOR_SPECIFIC 0xff #define IF_CLASS_UNKNOWN 0xffff #define IF_SUBCLASS_UNKNOWN 0xffff #define IF_PROTOCOL_UNKNOWN 0xffff #define DEV_VENDOR_UNKNOWN 0x0000 /* this id is unassigned */ #define DEV_PRODUCT_UNKNOWN 0xfffffff /* 0x0000 and 0xffff are used values by vendors, so MSBs encode unknown */ #define DEV_VERSION_UNKNOWN 0xffff #define IF_SUBCLASS_MISC_U3V 0x05 #define IF_SUBCLASS_APP_DFU 0x01 #define IF_PROTOCOL_DFU_RUNTIME 0x01 #define IF_PROTOCOL_DFU_MODE 0x02 /* Key to be used with "usb.control", "usb.bulk" and/or "usb.interrupt" * dissector tables when the dissector only applies to specific triple. * Use class code directly if the code is not shared with other specifications. * * MSB (bit 31) is arbitrarily chosen to ensure class registered dissectors * won't clash with protocol key. */ #define USB_PROTOCOL_KEY(class, subclass, protocol) \ (1u << 31 | (class & 0xff) << 16 | (subclass & 0xff) << 8 | (protocol & 0xff)) /* bmRequestType values */ #define USB_DIR_OUT 0 /* to device */ #define USB_DIR_IN 0x80 /* to host */ #define USB_TYPE_MASK (0x03 << 5) #define USB_TYPE(type) (((type) & USB_TYPE_MASK) >> 5) #define RQT_SETUP_TYPE_STANDARD 0 #define RQT_SETUP_TYPE_CLASS 1 #define RQT_SETUP_TYPE_VENDOR 2 #define USB_RECIPIENT_MASK 0x1F #define USB_RECIPIENT(type) ((type) & USB_RECIPIENT_MASK) #define RQT_SETUP_RECIPIENT_DEVICE 0 #define RQT_SETUP_RECIPIENT_INTERFACE 1 #define RQT_SETUP_RECIPIENT_ENDPOINT 2 #define RQT_SETUP_RECIPIENT_OTHER 3 /* Endpoint descriptor bmAttributes */ #define ENDPOINT_TYPE(ep_attrib) ((ep_attrib) & 0x03) #define ENDPOINT_TYPE_CONTROL 0 #define ENDPOINT_TYPE_ISOCHRONOUS 1 #define ENDPOINT_TYPE_BULK 2 #define ENDPOINT_TYPE_INTERRUPT 3 #define ENDPOINT_TYPE_NOT_SET 255 /* wMaxPacketSize */ #define USB_MPS_EP_SIZE(max_packet_size) ((max_packet_size) & 0x07FF) #define USB_MPS_ADDNL(max_packet_size) (((max_packet_size) & 0x1800) >> 11) #define USB_MPS(ep_size, addnl) (((addnl) << 11) | (ep_size)) #define USB_MPS_TPL(max_packet_size) \ ((USB_MPS_ADDNL(max_packet_size) + 1) * USB_MPS_EP_SIZE(max_packet_size)) #define USB_SETUP_GET_STATUS 0 #define USB_SETUP_CLEAR_FEATURE 1 #define USB_SETUP_SET_FEATURE 3 #define USB_SETUP_SET_ADDRESS 5 #define USB_SETUP_GET_DESCRIPTOR 6 #define USB_SETUP_SET_DESCRIPTOR 7 #define USB_SETUP_GET_CONFIGURATION 8 #define USB_SETUP_SET_CONFIGURATION 9 #define USB_SETUP_GET_INTERFACE 10 #define USB_SETUP_SET_INTERFACE 11 #define USB_SETUP_SYNCH_FRAME 12 #define USB_SETUP_SET_SEL 48 #define USB_SETUP_SET_ISOCH_DELAY 49 /* transfer_flags */ #define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ #define URB_ISO_ASAP 0x0002 /* iso-only; use the first unexpired * slot in the schedule */ #define URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */ #define URB_NO_FSBR 0x0020 /* UHCI-specific */ #define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */ #define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt * needed */ #define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */ /* The following flags are used internally by usbcore and HCDs */ #define URB_DIR_IN 0x0200 /* Transfer from device to host */ #define URB_DIR_OUT 0 #define URB_DIR_MASK URB_DIR_IN #define URB_DMA_MAP_SINGLE 0x00010000 /* Non-scatter-gather mapping */ #define URB_DMA_MAP_PAGE 0x00020000 /* HCD-unsupported S-G */ #define URB_DMA_MAP_SG 0x00040000 /* HCD-supported S-G */ #define URB_MAP_LOCAL 0x00080000 /* HCD-local-memory mapping */ #define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */ #define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */ #define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */ #define URB_ALIGNED_TEMP_BUFFER 0x00800000 /* Temp buffer was alloc'd */ /* 9.6.6 */ extern const true_false_string tfs_endpoint_direction; extern value_string_ext usb_class_vals_ext; usb_conv_info_t *get_usb_iface_conv_info(packet_info *pinfo, uint8_t interface_num); usb_conv_info_t *get_existing_usb_ep_conv_info(packet_info *pinfo, uint16_t bus_id, uint16_t device_address, int endpoint); proto_item * dissect_usb_descriptor_header(proto_tree *tree, tvbuff_t *tvb, int offset, value_string_ext *type_val_str); void dissect_usb_endpoint_address(proto_tree *tree, tvbuff_t *tvb, int offset); unsigned int sanitize_usb_max_packet_size(uint8_t ep_type, usb_speed_t speed, unsigned int max_packet_size); int dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, urb_info_t *urb, uint8_t *out_ep_type, usb_speed_t speed); int dissect_usb_unknown_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, urb_info_t *urb _U_); int dissect_urb_transfer_flags(tvbuff_t *tvb, int offset, proto_tree* tree, int hf, int endian); struct mausb_header; void dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, usb_header_t header_type, void *extra_data); void usb_lpm_besl_str(char *buf, uint32_t value); #endif /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */