/* packet-usb.c * * USB basic dissector * By Paolo Abeni * Ronnie Sahlberg 2006 * * http://www.usb.org/developers/docs/usb_20_122909-2.zip * * https://github.com/torvalds/linux/blob/master/Documentation/usb/usbmon.rst * * http://desowin.org/usbpcap/captureformat.html * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "packet-usb.h" #include "packet-mausb.h" #include "packet-usbip.h" #include "packet-netmon.h" /* dissector handles */ static dissector_handle_t linux_usb_handle; static dissector_handle_t linux_usb_mmapped_handle; static dissector_handle_t win32_usb_handle; static dissector_handle_t freebsd_usb_handle; static dissector_handle_t darwin_usb_handle; static dissector_handle_t netmon_usb_port_handle; /* protocols and header fields */ static int proto_usb = -1; static int proto_usbport = -1; /* USB pseudoheader fields, both FreeBSD and Linux */ static int hf_usb_totlen = -1; static int hf_usb_busunit = -1; static int hf_usb_address = -1; static int hf_usb_mode = -1; static int hf_usb_freebsd_urb_type = -1; static int hf_usb_freebsd_transfer_type = -1; static int hf_usb_xferflags = -1; static int hf_usb_xferflags_force_short_xfer = -1; static int hf_usb_xferflags_short_xfer_ok = -1; static int hf_usb_xferflags_short_frames_ok = -1; static int hf_usb_xferflags_pipe_bof = -1; static int hf_usb_xferflags_proxy_buffer = -1; static int hf_usb_xferflags_ext_buffer = -1; static int hf_usb_xferflags_manual_status = -1; static int hf_usb_xferflags_no_pipe_ok = -1; static int hf_usb_xferflags_stall_pipe = -1; static int hf_usb_xferstatus = -1; static int hf_usb_xferstatus_open = -1; static int hf_usb_xferstatus_transferring = -1; static int hf_usb_xferstatus_did_dma_delay = -1; static int hf_usb_xferstatus_did_close = -1; static int hf_usb_xferstatus_draining = -1; static int hf_usb_xferstatus_started = -1; static int hf_usb_xferstatus_bw_reclaimed = -1; static int hf_usb_xferstatus_control_xfr = -1; static int hf_usb_xferstatus_control_hdr = -1; static int hf_usb_xferstatus_control_act = -1; static int hf_usb_xferstatus_control_stall = -1; static int hf_usb_xferstatus_short_frames_ok = -1; static int hf_usb_xferstatus_short_xfer_ok = -1; static int hf_usb_xferstatus_bdma_enable = -1; static int hf_usb_xferstatus_bdma_no_post_sync = -1; static int hf_usb_xferstatus_bdma_setup = -1; static int hf_usb_xferstatus_isochronous_xfr = -1; static int hf_usb_xferstatus_curr_dma_set = -1; static int hf_usb_xferstatus_can_cancel_immed = -1; static int hf_usb_xferstatus_doing_callback = -1; static int hf_usb_error = -1; static int hf_usb_interval = -1; static int hf_usb_nframes = -1; static int hf_usb_packet_size = -1; static int hf_usb_packet_count = -1; static int hf_usb_speed = -1; static int hf_usb_frame_length = -1; static int hf_usb_frame_flags = -1; static int hf_usb_frame_flags_read = -1; static int hf_usb_frame_flags_data_follows = -1; static int hf_usb_frame_data = -1; static int hf_usb_urb_id = -1; static int hf_usb_linux_urb_type = -1; static int hf_usb_linux_transfer_type = -1; static int hf_usb_endpoint_address = -1; static int hf_usb_endpoint_direction = -1; static int hf_usb_endpoint_number = -1; static int hf_usb_device_address = -1; static int hf_usb_bus_id = -1; static int hf_usb_setup_flag = -1; static int hf_usb_data_flag = -1; static int hf_usb_urb_ts_sec = -1; static int hf_usb_urb_ts_usec = -1; static int hf_usb_urb_status = -1; static int hf_usb_urb_len = -1; static int hf_usb_urb_data_len = -1; static int hf_usb_urb_unused_setup_header = -1; static int hf_usb_urb_interval = -1; static int hf_usb_urb_start_frame = -1; static int hf_usb_urb_copy_of_transfer_flags = -1; /* transfer_flags */ static int hf_short_not_ok = -1; static int hf_iso_asap = -1; static int hf_no_transfer_dma_map = -1; static int hf_no_fsbr = -1; static int hf_zero_packet = -1; static int hf_no_interrupt = -1; static int hf_free_buffer = -1; static int hf_dir_in = -1; static int hf_dma_map_single = -1; static int hf_dma_map_page = -1; static int hf_dma_map_sg = -1; static int hf_map_local = -1; static int hf_setup_map_single = -1; static int hf_setup_map_local = -1; static int hf_dma_sg_combined = -1; static int hf_aligned_temp_buffer = -1; static int * const transfer_flags_fields[] = { &hf_short_not_ok, &hf_iso_asap, &hf_no_transfer_dma_map, &hf_no_fsbr, &hf_zero_packet, &hf_no_interrupt, &hf_free_buffer, &hf_dir_in, &hf_dma_map_single, &hf_dma_map_page, &hf_dma_map_sg, &hf_map_local, &hf_setup_map_single, &hf_setup_map_local, &hf_dma_sg_combined, &hf_aligned_temp_buffer, NULL }; /* Win32 USBPcap pseudoheader fields */ static int hf_usb_win32_header_len = -1; static int hf_usb_irp_id = -1; static int hf_usb_usbd_status = -1; static int hf_usb_function = -1; static int hf_usb_info = -1; static int hf_usb_usbpcap_info_reserved = -1; static int hf_usb_usbpcap_info_direction = -1; static int hf_usb_win32_device_address = -1; static int hf_usb_win32_transfer_type = -1; /* hf_usb_bus_id, hf_usb_endpoint_address, hf_usb_endpoint_direction, * hf_usb_endpoint_number are common with * FreeBSD and Linux pseudoheaders */ static int hf_usb_win32_data_len = -1; static int hf_usb_win32_control_stage = -1; static int hf_usb_win32_iso_start_frame = -1; static int hf_usb_win32_iso_num_packets = -1; static int hf_usb_win32_iso_error_count = -1; static int hf_usb_win32_iso_offset = -1; static int hf_usb_win32_iso_length = -1; static int hf_usb_win32_iso_status = -1; static int hf_usb_request = -1; static int hf_usb_request_unknown_class = -1; static int hf_usb_value = -1; static int hf_usb_index = -1; static int hf_usb_length = -1; /* static int hf_usb_data_len = -1; */ static int hf_usb_capdata = -1; static int hf_usb_device_wFeatureSelector = -1; static int hf_usb_interface_wFeatureSelector = -1; static int hf_usb_endpoint_wFeatureSelector = -1; static int hf_usb_wInterface = -1; static int hf_usb_wEndpoint = -1; static int hf_usb_wStatus = -1; static int hf_usb_wFrameNumber = -1; static int hf_usb_iso_error_count = -1; static int hf_usb_iso_numdesc = -1; static int hf_usb_iso_status = -1; static int hf_usb_iso_off = -1; static int hf_usb_iso_len = -1; static int hf_usb_iso_actual_len = -1; static int hf_usb_iso_pad = -1; static int hf_usb_iso_data = -1; static int hf_usb_bmRequestType = -1; static int hf_usb_control_response_generic = -1; static int hf_usb_bmRequestType_direction = -1; static int hf_usb_bmRequestType_type = -1; static int hf_usb_bmRequestType_recipient = -1; static int hf_usb_bDescriptorType = -1; static int hf_usb_get_descriptor_resp_generic = -1; static int hf_usb_descriptor_index = -1; static int hf_usb_language_id = -1; static int hf_usb_bLength = -1; static int hf_usb_bcdUSB = -1; static int hf_usb_bDeviceClass = -1; static int hf_usb_bDeviceSubClass = -1; static int hf_usb_bDeviceProtocol = -1; static int hf_usb_bMaxPacketSize0 = -1; static int hf_usb_idVendor = -1; static int hf_usb_idProduct = -1; static int hf_usb_bcdDevice = -1; static int hf_usb_iManufacturer = -1; static int hf_usb_iProduct = -1; static int hf_usb_iSerialNumber = -1; static int hf_usb_bNumConfigurations = -1; static int hf_usb_wLANGID = -1; static int hf_usb_bString = -1; static int hf_usb_bInterfaceNumber = -1; static int hf_usb_bAlternateSetting = -1; static int hf_usb_bNumEndpoints = -1; static int hf_usb_bInterfaceClass = -1; static int hf_usb_bInterfaceSubClass = -1; static int hf_usb_bInterfaceSubClass_audio = -1; static int hf_usb_bInterfaceSubClass_cdc = -1; static int hf_usb_bInterfaceSubClass_massstorage = -1; static int hf_usb_bInterfaceSubClass_hid = -1; static int hf_usb_bInterfaceSubClass_misc = -1; static int hf_usb_bInterfaceSubClass_app = -1; static int hf_usb_bInterfaceProtocol = -1; static int hf_usb_bInterfaceProtocol_cdc = -1; static int hf_usb_bInterfaceProtocol_massstorage = -1; static int hf_usb_bInterfaceProtocol_cdc_data = -1; static int hf_usb_bInterfaceProtocol_hid_boot = -1; static int hf_usb_bInterfaceProtocol_app_dfu = -1; static int hf_usb_bInterfaceProtocol_app_irda = -1; static int hf_usb_bInterfaceProtocol_app_usb_test_and_measurement = -1; static int hf_usb_iInterface = -1; static int hf_usb_bEndpointAddress = -1; static int hf_usb_bmAttributes = -1; static int hf_usb_bEndpointAttributeTransfer = -1; static int hf_usb_bEndpointAttributeSynchonisation = -1; static int hf_usb_bEndpointAttributeBehaviour = -1; static int hf_usb_wMaxPacketSize = -1; static int hf_usb_wMaxPacketSize_size = -1; static int hf_usb_wMaxPacketSize_slots = -1; static int hf_usb_bInterval = -1; static int hf_usb_bMaxBurst = -1; static int hf_usb_audio_bRefresh = -1; static int hf_usb_audio_bSynchAddress = -1; static int hf_usb_bSSEndpointAttributeBulkMaxStreams = -1; static int hf_usb_bSSEndpointAttributeIsoMult = -1; static int hf_usb_wBytesPerInterval = -1; static int hf_usb_wTotalLength = -1; static int hf_usb_bNumInterfaces = -1; static int hf_usb_bConfigurationValue = -1; static int hf_usb_iConfiguration = -1; static int hf_usb_bMaxPower = -1; static int hf_usb_configuration_bmAttributes = -1; static int hf_usb_configuration_legacy10buspowered = -1; static int hf_usb_configuration_selfpowered = -1; static int hf_usb_configuration_remotewakeup = -1; static int hf_usb_bEndpointAddress_direction = -1; static int hf_usb_bEndpointAddress_number = -1; static int hf_usb_response_in = -1; static int hf_usb_time = -1; static int hf_usb_request_in = -1; static int hf_usb_bFirstInterface = -1; static int hf_usb_bInterfaceCount = -1; static int hf_usb_bFunctionClass = -1; static int hf_usb_bFunctionSubClass = -1; static int hf_usb_bFunctionProtocol = -1; static int hf_usb_iFunction = -1; static int hf_usb_bNumDeviceCaps = -1; static int hf_usb_bDevCapabilityType = -1; static int hf_usb_usb20ext_bmAttributes = -1; static int hf_usb_usb20ext_LPM = -1; static int hf_usb_usb20ext_BESL_HIRD = -1; static int hf_usb_usb20ext_baseline_BESL_valid = -1; static int hf_usb_usb20ext_deep_BESL_valid = -1; static int hf_usb_usb20ext_baseline_BESL = -1; static int hf_usb_usb20ext_deep_BESL = -1; static int hf_usb_bReserved = -1; static int hf_usb_PlatformCapabilityUUID = -1; static int hf_usb_webusb_bcdVersion = -1; static int hf_usb_webusb_bVendorCode = -1; static int hf_usb_webusb_iLandingPage = -1; static int hf_usb_msos20_dwWindowsVersion = -1; static int hf_usb_msos20_wMSOSDescriptorSetTotalLength = -1; static int hf_usb_msos20_bMS_VendorCode = -1; static int hf_usb_msos20_bAltEnumCode = -1; static int hf_usb_data_fragment = -1; static int hf_usb_src = -1; static int hf_usb_dst = -1; static int hf_usb_addr = -1; /* macOS */ static int hf_usb_darwin_bcd_version = -1; static int hf_usb_darwin_header_len = -1; static int hf_usb_darwin_request_type = -1; static int hf_usb_darwin_io_len = -1; static int hf_usb_darwin_io_status = -1; static int hf_usb_darwin_iso_num_packets = -1; static int hf_usb_darwin_io_id = -1; static int hf_usb_darwin_device_location = -1; static int hf_usb_darwin_speed = -1; static int hf_usb_darwin_device_address = -1; static int hf_usb_darwin_endpoint_address = -1; static int hf_usb_darwin_endpoint_type = -1; static int hf_usb_darwin_iso_status = -1; static int hf_usb_darwin_iso_frame_number = -1; static int hf_usb_darwin_iso_timestamp = -1; /* NetMon */ static int hf_usbport_event_id = -1; static int hf_usbport_device_object = -1; static int hf_usbport_pci_bus = -1; static int hf_usbport_pci_device = -1; static int hf_usbport_pci_function = -1; static int hf_usbport_pci_vendor_id = -1; static int hf_usbport_pci_device_id = -1; static int hf_usbport_port_path_depth = -1; static int hf_usbport_port_path0 = -1; static int hf_usbport_port_path1 = -1; static int hf_usbport_port_path2 = -1; static int hf_usbport_port_path3 = -1; static int hf_usbport_port_path4 = -1; static int hf_usbport_port_path5 = -1; static int hf_usbport_device_handle = -1; static int hf_usbport_device_speed = -1; static int hf_usbport_endpoint = -1; static int hf_usbport_pipehandle = -1; static int hf_usbport_endpoint_desc_length = -1; static int hf_usbport_endpoint_desc_type = -1; static int hf_usbport_endpoint_address = -1; static int hf_usbport_bm_attributes = -1; static int hf_usbport_max_packet_size = -1; static int hf_usbport_interval = -1; static int hf_usbport_irp = -1; static int hf_usbport_urb = -1; static int hf_usbport_urb_transfer_data = -1; static int hf_usbport_urb_header_length = -1; static int hf_usbport_urb_header_function = -1; static int hf_usbport_urb_header_status = -1; static int hf_usbport_urb_header_usbddevice_handle = -1; static int hf_usbport_urb_header_usbdflags = -1; static int hf_usbport_urb_configuration_desc = -1; static int hf_usbport_urb_configuration_handle = -1; static int hf_usbport_urb_pipe_handle = -1; static int hf_usbport_urb_xferflags = -1; static int hf_usbport_urb_transfer_buffer_length = -1; static int hf_usbport_urb_transfer_buffer = -1; static int hf_usbport_urb_transfer_buffer_mdl = -1; static int hf_usbport_urb_reserved_mbz = -1; static int hf_usbport_urb_reserved_hcd = -1; static int hf_usbport_urb_reserved = -1; static int hf_usbport_keyword = -1; static int hf_usbport_keyword_diagnostic = -1; static int hf_usbport_keyword_power_diagnostics = -1; static int hf_usbport_keyword_perf_diagnostics = -1; static int hf_usbport_keyword_reserved1 = -1; static gint ett_usb_hdr = -1; static gint ett_usb_setup_hdr = -1; static gint ett_usb_isodesc = -1; static gint ett_usb_win32_iso_packet = -1; static gint ett_usb_endpoint = -1; static gint ett_usb_setup_bmrequesttype = -1; static gint ett_usb_usbpcap_info = -1; static gint ett_descriptor_device = -1; static gint ett_configuration_bmAttributes = -1; static gint ett_configuration_bEndpointAddress = -1; static gint ett_endpoint_bmAttributes = -1; static gint ett_endpoint_wMaxPacketSize = -1; static gint ett_usb_xferflags = -1; static gint ett_usb_xferstatus = -1; static gint ett_usb_frame = -1; static gint ett_usb_frame_flags = -1; static gint ett_usbport = -1; static gint ett_usbport_host_controller = -1; static gint ett_usbport_path = -1; static gint ett_usbport_device = -1; static gint ett_usbport_endpoint = -1; static gint ett_usbport_endpoint_desc = -1; static gint ett_usbport_urb = -1; static gint ett_usbport_keyword = -1; static gint ett_transfer_flags = -1; static gint ett_usb20ext_bmAttributes = -1; static expert_field ei_usb_undecoded = EI_INIT; static expert_field ei_usb_bLength_even = EI_INIT; static expert_field ei_usb_bLength_too_short = EI_INIT; static expert_field ei_usb_desc_length_invalid = EI_INIT; static expert_field ei_usb_invalid_setup = EI_INIT; static expert_field ei_usb_ss_ep_companion_before_ep = EI_INIT; static expert_field ei_usb_usbpcap_unknown_urb = EI_INIT; static expert_field ei_usb_bad_length = EI_INIT; static expert_field ei_usb_invalid_max_packet_size = EI_INIT; static expert_field ei_usb_invalid_max_packet_size0 = EI_INIT; static expert_field ei_usb_invalid_endpoint_type = EI_INIT; static expert_field ei_usb_unexpected_desc_type = EI_INIT; static expert_field ei_usbport_invalid_path_depth = EI_INIT; static int usb_address_type = -1; static int * const usb_endpoint_fields[] = { &hf_usb_endpoint_direction, &hf_usb_endpoint_number, NULL }; static int * const usb_usbpcap_info_fields[] = { &hf_usb_usbpcap_info_reserved, &hf_usb_usbpcap_info_direction, NULL }; static int usb_tap = -1; static gboolean try_heuristics = TRUE; static dissector_table_t usb_bulk_dissector_table; static dissector_table_t usb_control_dissector_table; static dissector_table_t usb_interrupt_dissector_table; static dissector_table_t usb_descriptor_dissector_table; static heur_dissector_list_t heur_bulk_subdissector_list; static heur_dissector_list_t heur_control_subdissector_list; static heur_dissector_list_t heur_interrupt_subdissector_list; static wmem_tree_t *device_to_protocol_table = NULL; static wmem_tree_t *device_to_product_table = NULL; static wmem_tree_t *usbpcap_setup_data = NULL; static dissector_table_t device_to_dissector; static dissector_table_t protocol_to_dissector; static dissector_table_t product_to_dissector; typedef struct _device_product_data_t { guint16 vendor; guint16 product; guint16 device; guint bus_id; guint device_address; } device_product_data_t; typedef struct _device_protocol_data_t { guint32 protocol; guint bus_id; guint device_address; } device_protocol_data_t; typedef struct _usb_alt_setting_t { guint8 altSetting; guint8 interfaceClass; guint8 interfaceSubclass; guint8 interfaceProtocol; guint8 interfaceNum; } usb_alt_setting_t; typedef struct { guint64 usb_id; guint8 setup_data[8]; } usbpcap_setup_data_t; static const value_string usb_speed_vals[] = { {USB_SPEED_UNKNOWN, "Unknown Speed"}, {USB_SPEED_LOW, "Low-Speed"}, {USB_SPEED_FULL, "Full-Speed"}, {USB_SPEED_HIGH, "High-Speed"}, {0, NULL} }; /* http://www.usb.org/developers/docs/USB_LANGIDs.pdf */ static const value_string usb_langid_vals[] = { {0x0000, "no language specified"}, {0x0401, "Arabic (Saudi Arabia)"}, {0x0402, "Bulgarian"}, {0x0403, "Catalan"}, {0x0404, "Chinese (Taiwan)"}, {0x0405, "Czech"}, {0x0406, "Danish"}, {0x0407, "German (Standard)"}, {0x0408, "Greek"}, {0x0409, "English (United States)"}, {0x040a, "Spanish (Traditional Sort)"}, {0x040b, "Finnish"}, {0x040c, "French (Standard)"}, {0x040d, "Hebrew"}, {0x040e, "Hungarian"}, {0x040f, "Icelandic"}, {0x0410, "Italian (Standard)"}, {0x0411, "Japanese"}, {0x0412, "Korean"}, {0x0413, "Dutch (Netherlands)"}, {0x0414, "Norwegian (Bokmal)"}, {0x0415, "Polish"}, {0x0416, "Portuguese (Brazil)"}, {0x0418, "Romanian"}, {0x0419, "Russian"}, {0x041a, "Croatian"}, {0x041b, "Slovak"}, {0x041c, "Albanian"}, {0x041d, "Swedish"}, {0x041e, "Thai"}, {0x041f, "Turkish"}, {0x0420, "Urdu (Pakistan)"}, {0x0421, "Indonesian"}, {0x0422, "Ukrainian"}, {0x0423, "Belarussian"}, {0x0424, "Slovenian"}, {0x0425, "Estonian"}, {0x0426, "Latvian"}, {0x0427, "Lithuanian"}, {0x0429, "Farsi"}, {0x042a, "Vietnamese"}, {0x042b, "Armenian"}, {0x042c, "Azeri (Latin)"}, {0x042d, "Basque"}, {0x042f, "Macedonian"}, {0x0430, "Sutu"}, {0x0436, "Afrikaans"}, {0x0437, "Georgian"}, {0x0438, "Faeroese"}, {0x0439, "Hindi"}, {0x043e, "Malay (Malaysian)"}, {0x043f, "Kazakh"}, {0x0441, "Swahili (Kenya)"}, {0x0443, "Uzbek (Latin)"}, {0x0444, "Tatar (Tatarstan)"}, {0x0445, "Bengali"}, {0x0446, "Punjabi"}, {0x0447, "Gujarati"}, {0x0448, "Oriya"}, {0x0449, "Tamil"}, {0x044a, "Telugu"}, {0x044b, "Kannada"}, {0x044c, "Malayalam"}, {0x044d, "Assamese"}, {0x044e, "Marathi"}, {0x044f, "Sanskrit"}, {0x0455, "Burmese"}, {0x0457, "Konkani"}, {0x0458, "Manipuri"}, {0x0459, "Sindhi"}, {0x04ff, "HID (Usage Data Descriptor)"}, {0x0801, "Arabic (Iraq)"}, {0x0804, "Chinese (PRC)"}, {0x0807, "German (Switzerland)"}, {0x0809, "English (United Kingdom)"}, {0x080a, "Spanish (Mexican)"}, {0x080c, "French (Belgian)"}, {0x0810, "Italian (Switzerland)"}, {0x0812, "Korean (Johab)"}, {0x0813, "Dutch (Belgium)"}, {0x0814, "Norwegian (Nynorsk)"}, {0x0816, "Portuguese (Standard)"}, {0x081a, "Serbian (Latin)"}, {0x081d, "Swedish (Finland)"}, {0x0820, "Urdu (India)"}, {0x0827, "Lithuanian (Classic)"}, {0x082c, "Azeri (Cyrillic)"}, {0x083e, "Malay (Brunei Darussalam)"}, {0x0843, "Uzbek (Cyrillic)"}, {0x0860, "Kashmiri (India)"}, {0x0861, "Nepali (India)"}, {0x0c01, "Arabic (Egypt)"}, {0x0c04, "Chinese (Hong Kong SAR, PRC)"}, {0x0c07, "German (Austria)"}, {0x0c09, "English (Australian)"}, {0x0c0a, "Spanish (Modern Sort)"}, {0x0c0c, "French (Canadian)"}, {0x0c1a, "Serbian (Cyrillic)"}, {0x1001, "Arabic (Libya)"}, {0x1004, "Chinese (Singapore)"}, {0x1007, "German (Luxembourg)"}, {0x1009, "English (Canadian)"}, {0x100a, "Spanish (Guatemala)"}, {0x100c, "French (Switzerland)"}, {0x1401, "Arabic (Algeria)"}, {0x1404, "Chinese (Macau SAR)"}, {0x1407, "German (Liechtenstein)"}, {0x1409, "English (New Zealand)"}, {0x140a, "Spanish (Costa Rica)"}, {0x140c, "French (Luxembourg)"}, {0x1801, "Arabic (Morocco)"}, {0x1809, "English (Ireland)"}, {0x180a, "Spanish (Panama)"}, {0x180c, "French (Monaco)"}, {0x1c01, "Arabic (Tunisia)"}, {0x1c09, "English (South Africa)"}, {0x1c0a, "Spanish (Dominican Republic)"}, {0x2001, "Arabic (Oman)"}, {0x2009, "English (Jamaica)"}, {0x200a, "Spanish (Venezuela)"}, {0x2401, "Arabic (Yemen)"}, {0x2409, "English (Caribbean)"}, {0x240a, "Spanish (Colombia)"}, {0x2801, "Arabic (Syria)"}, {0x2809, "English (Belize)"}, {0x280a, "Spanish (Peru)"}, {0x2c01, "Arabic (Jordan)"}, {0x2c09, "English (Trinidad)"}, {0x2c0a, "Spanish (Argentina)"}, {0x3001, "Arabic (Lebanon)"}, {0x3009, "English (Zimbabwe)"}, {0x300a, "Spanish (Ecuador)"}, {0x3401, "Arabic (Kuwait)"}, {0x3409, "English (Philippines)"}, {0x340a, "Spanish (Chile)"}, {0x3801, "Arabic (U.A.E.)"}, {0x380a, "Spanish (Uruguay)"}, {0x3c01, "Arabic (Bahrain)"}, {0x3c0a, "Spanish (Paraguay)"}, {0x4001, "Arabic (Qatar)"}, {0x400a, "Spanish (Bolivia)"}, {0x440a, "Spanish (El Salvador)"}, {0x480a, "Spanish (Honduras)"}, {0x4c0a, "Spanish (Nicaragua)"}, {0x500a, "Spanish (Puerto Rico)"}, {0xf0ff, "HID (Vendor Defined 1)"}, {0xf4ff, "HID (Vendor Defined 2)"}, {0xf8ff, "HID (Vendor Defined 3)"}, {0xfcff, "HID (Vendor Defined 4)"}, {0, NULL} }; value_string_ext usb_langid_vals_ext = VALUE_STRING_EXT_INIT(usb_langid_vals); static const value_string usb_class_vals[] = { {IF_CLASS_DEVICE, "Device"}, {IF_CLASS_AUDIO, "Audio"}, {IF_CLASS_COMMUNICATIONS, "Communications and CDC Control"}, {IF_CLASS_HID, "HID"}, {IF_CLASS_PHYSICAL, "Physical"}, {IF_CLASS_IMAGE, "Imaging"}, {IF_CLASS_PRINTER, "Printer"}, {IF_CLASS_MASS_STORAGE, "Mass Storage"}, {IF_CLASS_HUB, "Hub"}, {IF_CLASS_CDC_DATA, "CDC-Data"}, {IF_CLASS_SMART_CARD, "Smart Card"}, {IF_CLASS_CONTENT_SECURITY, "Content Security"}, {IF_CLASS_VIDEO, "Video"}, {IF_CLASS_PERSONAL_HEALTHCARE, "Personal Healthcare"}, {IF_CLASS_AUDIO_VIDEO, "Audio/Video Devices"}, {IF_CLASS_DIAGNOSTIC_DEVICE, "Diagnostic Device"}, {IF_CLASS_WIRELESS_CONTROLLER, "Wireless Controller"}, {IF_CLASS_MISCELLANEOUS, "Miscellaneous"}, {IF_CLASS_APPLICATION_SPECIFIC, "Application Specific"}, {IF_CLASS_VENDOR_SPECIFIC, "Vendor Specific"}, {0, NULL} }; value_string_ext usb_class_vals_ext = VALUE_STRING_EXT_INIT(usb_class_vals); /* use usb class, subclass and protocol id together http://www.usb.org/developers/defined_class USB Class Definitions for Communications Devices, Revision 1.2 December 6, 2012 */ static const value_string usb_protocols[] = { {0x000000, "Use class code info from Interface Descriptors"}, {0x060101, "Still Imaging"}, {0x090000, "Full speed Hub"}, {0x090001, "Hi-speed hub with single TT"}, {0x090002, "Hi-speed hub with multiple TTs"}, {0x0D0000, "Content Security"}, {0x100100, "AVControl Interface"}, {0x100200, "AVData Video Streaming Interface"}, {0x100300, "AVData Audio Streaming Interface"}, {0xDC0101, "USB2 Compliance Device"}, {0xE00101, "Bluetooth Programming Interface"}, {0xE00102, "UWB Radio Control Interface"}, {0xE00103, "Remote NDIS"}, {0xE00104, "Bluetooth AMP Controller"}, {0xE00201, "Host Wire Adapter Control/Data interface"}, {0xE00202, "Device Wire Adapter Control/Data interface"}, {0xE00203, "Device Wire Adapter Isochronous interface"}, {0xEF0101, "Active Sync device"}, {0xEF0102, "Palm Sync"}, {0xEF0201, "Interface Association Descriptor"}, {0xEF0202, "Wire Adapter Multifunction Peripheral programming interface"}, {0xEF0301, "Cable Based Association Framework"}, {0xFE0101, "Device Firmware Upgrade"}, {0xFE0200, "IRDA Bridge device"}, {0xFE0300, "USB Test and Measurement Device"}, {0xFE0301, "USB Test and Measurement Device conforming to the USBTMC USB488"}, {0, NULL} }; static value_string_ext usb_protocols_ext = VALUE_STRING_EXT_INIT(usb_protocols); /* BOS Descriptor Device Capability Type Codes https://www.usb.org/bos-descriptor-types */ #define BOS_CAP_WIRELESS_USB 0x01 #define BOS_CAP_USB_20_EXTENSION 0x02 #define BOS_CAP_SUPERSPEED_USB 0x03 #define BOS_CAP_CONTAINER_ID 0x04 #define BOS_CAP_PLATFORM 0x05 #define BOS_CAP_POWER_DELIVERY 0x06 #define BOS_CAP_BATTERY_INFO 0x07 #define BOS_CAP_PD_CONSUMER_PORT 0x08 #define BOS_CAP_PD_PROVIDER_PORT 0x09 #define BOS_CAP_SUPERSPEED_PLUS 0x0A #define BOS_CAP_PRECISION_TIME_MEAS 0x0B #define BOS_CAP_WIRELESS_USB_EXT 0x0C #define BOS_CAP_BILLBOARD 0x0D #define BOS_CAP_AUTHENTICATION 0x0E #define BOS_CAP_BILLBOARD_EX 0x0F #define BOS_CAP_CONFIGURATION_SUMMARY 0x10 #define BOS_CAP_FWSTATUS 0x11 #define BOS_CAP_USB3_GEN_T 0x13 static const value_string usb_capability_vals[] = { {BOS_CAP_WIRELESS_USB, "Wireless USB"}, {BOS_CAP_USB_20_EXTENSION, "USB 2.0 Extension Descriptor"}, {BOS_CAP_SUPERSPEED_USB, "SuperSpeed USB"}, {BOS_CAP_CONTAINER_ID, "Container ID"}, {BOS_CAP_PLATFORM, "Platform"}, {BOS_CAP_POWER_DELIVERY, "Power Delivery Capability"}, {BOS_CAP_BATTERY_INFO, "Battery Info Capability"}, {BOS_CAP_PD_CONSUMER_PORT, "PD Consumer Port Capability"}, {BOS_CAP_PD_PROVIDER_PORT, "PD Provider Port Capability"}, {BOS_CAP_SUPERSPEED_PLUS, "SuperSpeed Plus"}, {BOS_CAP_PRECISION_TIME_MEAS, "Precision Time Measurement"}, {BOS_CAP_WIRELESS_USB_EXT, "Wireless USB Ext"}, {BOS_CAP_BILLBOARD, "Billboard Capability"}, {BOS_CAP_AUTHENTICATION, "Authentication Capability Descriptor"}, {BOS_CAP_BILLBOARD_EX, "Billboard Ex capability"}, {BOS_CAP_CONFIGURATION_SUMMARY, "Configuration Summary"}, {BOS_CAP_FWSTATUS, "Firmware Status"}, {0x12, "TBD (reserved for USB Audio 4.0)"}, {BOS_CAP_USB3_GEN_T, "USB 3 Gen T Capability"}, {0x14, "TBD (reserved for USB PD)"}, {0, NULL} }; static value_string_ext usb_capability_vals_ext = VALUE_STRING_EXT_INIT(usb_capability_vals); /* FreeBSD header */ /* Transfer mode */ #define FREEBSD_MODE_HOST 0 #define FREEBSD_MODE_DEVICE 1 static const value_string usb_freebsd_transfer_mode_vals[] = { {FREEBSD_MODE_HOST, "Host"}, {FREEBSD_MODE_DEVICE, "Device"}, {0, NULL} }; /* Type */ #define FREEBSD_URB_SUBMIT 0 #define FREEBSD_URB_COMPLETE 1 static const value_string usb_freebsd_urb_type_vals[] = { {FREEBSD_URB_SUBMIT, "URB_SUBMIT"}, {FREEBSD_URB_COMPLETE, "URB_COMPLETE"}, {0, NULL} }; /* Transfer type */ #define FREEBSD_URB_CONTROL 0 #define FREEBSD_URB_ISOCHRONOUS 1 #define FREEBSD_URB_BULK 2 #define FREEBSD_URB_INTERRUPT 3 static const value_string usb_freebsd_transfer_type_vals[] = { {FREEBSD_URB_CONTROL, "URB_CONTROL"}, {FREEBSD_URB_ISOCHRONOUS, "URB_ISOCHRONOUS"}, {FREEBSD_URB_BULK, "URB_BULK"}, {FREEBSD_URB_INTERRUPT, "URB_INTERRUPT"}, {0, NULL} }; /* Transfer flags */ #define FREEBSD_FLAG_FORCE_SHORT_XFER 0x00000001 #define FREEBSD_FLAG_SHORT_XFER_OK 0x00000002 #define FREEBSD_FLAG_SHORT_FRAMES_OK 0x00000004 #define FREEBSD_FLAG_PIPE_BOF 0x00000008 #define FREEBSD_FLAG_PROXY_BUFFER 0x00000010 #define FREEBSD_FLAG_EXT_BUFFER 0x00000020 #define FREEBSD_FLAG_MANUAL_STATUS 0x00000040 #define FREEBSD_FLAG_NO_PIPE_OK 0x00000080 #define FREEBSD_FLAG_STALL_PIPE 0x00000100 static int * const usb_xferflags_fields[] = { &hf_usb_xferflags_force_short_xfer, &hf_usb_xferflags_short_xfer_ok, &hf_usb_xferflags_short_frames_ok, &hf_usb_xferflags_pipe_bof, &hf_usb_xferflags_proxy_buffer, &hf_usb_xferflags_ext_buffer, &hf_usb_xferflags_manual_status, &hf_usb_xferflags_no_pipe_ok, &hf_usb_xferflags_stall_pipe, NULL }; /* Transfer status */ #define FREEBSD_STATUS_OPEN 0x00000001 #define FREEBSD_STATUS_TRANSFERRING 0x00000002 #define FREEBSD_STATUS_DID_DMA_DELAY 0x00000004 #define FREEBSD_STATUS_DID_CLOSE 0x00000008 #define FREEBSD_STATUS_DRAINING 0x00000010 #define FREEBSD_STATUS_STARTED 0x00000020 #define FREEBSD_STATUS_BW_RECLAIMED 0x00000040 #define FREEBSD_STATUS_CONTROL_XFR 0x00000080 #define FREEBSD_STATUS_CONTROL_HDR 0x00000100 #define FREEBSD_STATUS_CONTROL_ACT 0x00000200 #define FREEBSD_STATUS_CONTROL_STALL 0x00000400 #define FREEBSD_STATUS_SHORT_FRAMES_OK 0x00000800 #define FREEBSD_STATUS_SHORT_XFER_OK 0x00001000 #define FREEBSD_STATUS_BDMA_ENABLE 0x00002000 #define FREEBSD_STATUS_BDMA_NO_POST_SYNC 0x00004000 #define FREEBSD_STATUS_BDMA_SETUP 0x00008000 #define FREEBSD_STATUS_ISOCHRONOUS_XFR 0x00010000 #define FREEBSD_STATUS_CURR_DMA_SET 0x00020000 #define FREEBSD_STATUS_CAN_CANCEL_IMMED 0x00040000 #define FREEBSD_STATUS_DOING_CALLBACK 0x00080000 static int * const usb_xferstatus_fields[] = { &hf_usb_xferstatus_open, &hf_usb_xferstatus_transferring, &hf_usb_xferstatus_did_dma_delay, &hf_usb_xferstatus_did_close, &hf_usb_xferstatus_draining, &hf_usb_xferstatus_started, &hf_usb_xferstatus_bw_reclaimed, &hf_usb_xferstatus_control_xfr, &hf_usb_xferstatus_control_hdr, &hf_usb_xferstatus_control_act, &hf_usb_xferstatus_control_stall, &hf_usb_xferstatus_short_frames_ok, &hf_usb_xferstatus_short_xfer_ok, &hf_usb_xferstatus_bdma_enable, &hf_usb_xferstatus_bdma_no_post_sync, &hf_usb_xferstatus_bdma_setup, &hf_usb_xferstatus_isochronous_xfr, &hf_usb_xferstatus_curr_dma_set, &hf_usb_xferstatus_can_cancel_immed, &hf_usb_xferstatus_doing_callback, NULL }; /* USB errors */ #define FREEBSD_ERR_NORMAL_COMPLETION 0 #define FREEBSD_ERR_PENDING_REQUESTS 1 #define FREEBSD_ERR_NOT_STARTED 2 #define FREEBSD_ERR_INVAL 3 #define FREEBSD_ERR_NOMEM 4 #define FREEBSD_ERR_CANCELLED 5 #define FREEBSD_ERR_BAD_ADDRESS 6 #define FREEBSD_ERR_BAD_BUFSIZE 7 #define FREEBSD_ERR_BAD_FLAG 8 #define FREEBSD_ERR_NO_CALLBACK 9 #define FREEBSD_ERR_IN_USE 10 #define FREEBSD_ERR_NO_ADDR 11 #define FREEBSD_ERR_NO_PIPE 12 #define FREEBSD_ERR_ZERO_NFRAMES 13 #define FREEBSD_ERR_ZERO_MAXP 14 #define FREEBSD_ERR_SET_ADDR_FAILED 15 #define FREEBSD_ERR_NO_POWER 16 #define FREEBSD_ERR_TOO_DEEP 17 #define FREEBSD_ERR_IOERROR 18 #define FREEBSD_ERR_NOT_CONFIGURED 19 #define FREEBSD_ERR_TIMEOUT 20 #define FREEBSD_ERR_SHORT_XFER 21 #define FREEBSD_ERR_STALLED 22 #define FREEBSD_ERR_INTERRUPTED 23 #define FREEBSD_ERR_DMA_LOAD_FAILED 24 #define FREEBSD_ERR_BAD_CONTEXT 25 #define FREEBSD_ERR_NO_ROOT_HUB 26 #define FREEBSD_ERR_NO_INTR_THREAD 27 #define FREEBSD_ERR_NOT_LOCKED 28 static const value_string usb_freebsd_err_vals[] = { {FREEBSD_ERR_NORMAL_COMPLETION, "Normal completion"}, {FREEBSD_ERR_PENDING_REQUESTS, "Pending requests"}, {FREEBSD_ERR_NOT_STARTED, "Not started"}, {FREEBSD_ERR_INVAL, "Invalid"}, {FREEBSD_ERR_NOMEM, "No memory"}, {FREEBSD_ERR_CANCELLED, "Cancelled"}, {FREEBSD_ERR_BAD_ADDRESS, "Bad address"}, {FREEBSD_ERR_BAD_BUFSIZE, "Bad buffer size"}, {FREEBSD_ERR_BAD_FLAG, "Bad flag"}, {FREEBSD_ERR_NO_CALLBACK, "No callback"}, {FREEBSD_ERR_IN_USE, "In use"}, {FREEBSD_ERR_NO_ADDR, "No address"}, {FREEBSD_ERR_NO_PIPE, "No pipe"}, {FREEBSD_ERR_ZERO_NFRAMES, "Number of frames is zero"}, {FREEBSD_ERR_ZERO_MAXP, "MAXP is zero"}, {FREEBSD_ERR_SET_ADDR_FAILED, "Set address failed"}, {FREEBSD_ERR_NO_POWER, "No power"}, {FREEBSD_ERR_TOO_DEEP, "Too deep"}, {FREEBSD_ERR_IOERROR, "I/O error"}, {FREEBSD_ERR_NOT_CONFIGURED, "Not configured"}, {FREEBSD_ERR_TIMEOUT, "Timeout"}, {FREEBSD_ERR_SHORT_XFER, "Short transfer"}, {FREEBSD_ERR_STALLED, "Stalled"}, {FREEBSD_ERR_INTERRUPTED, "Interrupted"}, {FREEBSD_ERR_DMA_LOAD_FAILED, "DMA load failed"}, {FREEBSD_ERR_BAD_CONTEXT, "Bad context"}, {FREEBSD_ERR_NO_ROOT_HUB, "No root hub"}, {FREEBSD_ERR_NO_INTR_THREAD, "No interrupt thread"}, {FREEBSD_ERR_NOT_LOCKED, "Not locked"}, {0, NULL} }; /* USB speeds */ #define FREEBSD_SPEED_VARIABLE 0 #define FREEBSD_SPEED_LOW 1 #define FREEBSD_SPEED_FULL 2 #define FREEBSD_SPEED_HIGH 3 #define FREEBSD_SPEED_SUPER 4 static const value_string usb_freebsd_speed_vals[] = { {FREEBSD_SPEED_VARIABLE, "Variable"}, {FREEBSD_SPEED_LOW, "Low"}, {FREEBSD_SPEED_FULL, "Full"}, {FREEBSD_SPEED_HIGH, "High"}, {FREEBSD_SPEED_SUPER, "Super"}, {0, NULL} }; /* Frame flags */ #define FREEBSD_FRAMEFLAG_READ 0x00000001 #define FREEBSD_FRAMEFLAG_DATA_FOLLOWS 0x00000002 static int * const usb_frame_flags_fields[] = { &hf_usb_frame_flags_read, &hf_usb_frame_flags_data_follows, NULL }; static const value_string usb_linux_urb_type_vals[] = { {URB_SUBMIT, "URB_SUBMIT"}, {URB_COMPLETE, "URB_COMPLETE"}, {URB_ERROR, "URB_ERROR"}, {0, NULL} }; static const value_string usb_linux_transfer_type_vals[] = { {URB_CONTROL, "URB_CONTROL"}, {URB_ISOCHRONOUS, "URB_ISOCHRONOUS"}, {URB_INTERRUPT, "URB_INTERRUPT"}, {URB_BULK, "URB_BULK"}, {0, NULL} }; static const value_string usb_transfer_type_and_direction_vals[] = { {URB_CONTROL, "URB_CONTROL out"}, {URB_ISOCHRONOUS, "URB_ISOCHRONOUS out"}, {URB_INTERRUPT, "URB_INTERRUPT out"}, {URB_BULK, "URB_BULK out"}, {URB_CONTROL | URB_TRANSFER_IN, "URB_CONTROL in"}, {URB_ISOCHRONOUS | URB_TRANSFER_IN, "URB_ISOCHRONOUS in"}, {URB_INTERRUPT | URB_TRANSFER_IN, "URB_INTERRUPT in"}, {URB_BULK | URB_TRANSFER_IN, "URB_BULK in"}, {0, NULL} }; static const value_string usb_endpoint_direction_vals[] = { {0, "OUT"}, {1, "IN"}, {0, NULL} }; static const range_string usb_setup_flag_rvals[] = { {0, 0, "relevant"}, {1, 255, "not relevant"}, {0, 0, NULL} }; static const range_string usb_data_flag_rvals[] = { {0, 0, "present"}, {1, 255, "not present"}, {0, 0, NULL} }; extern value_string_ext ext_usb_vendors_vals; extern value_string_ext ext_usb_products_vals; extern value_string_ext ext_usb_audio_subclass_vals; extern value_string_ext ext_usb_com_subclass_vals; extern value_string_ext ext_usb_massstorage_subclass_vals; extern value_string_ext linux_negative_errno_vals_ext; /* * Standard descriptor types. * * all class specific descriptor types were removed from this list * a descriptor type is not globally unique * dissectors for the USB classes should provide their own value string * and pass it to dissect_usb_descriptor_header() * */ #define USB_DT_DEVICE 1 #define USB_DT_CONFIG 2 #define USB_DT_STRING 3 #define USB_DT_INTERFACE 4 #define USB_DT_ENDPOINT 5 #define USB_DT_DEVICE_QUALIFIER 6 #define USB_DT_OTHER_SPEED_CONFIG 7 #define USB_DT_INTERFACE_POWER 8 /* these are from a minor usb 2.0 revision (ECN) */ #define USB_DT_OTG 9 #define USB_DT_DEBUG 10 #define USB_DT_INTERFACE_ASSOCIATION 11 /* these are from usb 3.0 specification */ #define USB_DT_BOS 0x0F #define USB_DT_DEVICE_CAPABILITY 0x10 #define USB_DT_SUPERSPEED_EP_COMPANION 0x30 /* these are from usb 3.1 specification */ #define USB_DT_SUPERSPEED_ISO_EP_COMPANION 0x31 /* There are only Standard Descriptor Types, Class-specific types are provided by "usb.descriptor" descriptors table*/ static const value_string std_descriptor_type_vals[] = { {USB_DT_DEVICE, "DEVICE"}, {USB_DT_CONFIG, "CONFIGURATION"}, {USB_DT_STRING, "STRING"}, {USB_DT_INTERFACE, "INTERFACE"}, {USB_DT_ENDPOINT, "ENDPOINT"}, {USB_DT_DEVICE_QUALIFIER, "DEVICE QUALIFIER"}, {USB_DT_OTHER_SPEED_CONFIG, "OTHER SPEED CONFIG"}, {USB_DT_INTERFACE_POWER, "INTERFACE POWER"}, {USB_DT_OTG, "OTG"}, {USB_DT_DEBUG, "DEBUG"}, {USB_DT_INTERFACE_ASSOCIATION, "INTERFACE ASSOCIATION"}, {USB_DT_BOS, "BOS"}, {USB_DT_DEVICE_CAPABILITY, "DEVICE CAPABILITY"}, {USB_DT_SUPERSPEED_EP_COMPANION, "SUPERSPEED USB ENDPOINT COMPANION"}, {USB_DT_SUPERSPEED_ISO_EP_COMPANION, "SUPERSPEED PLUS ISOCHRONOUS ENDPOINT COMPANION"}, {0,NULL} }; static value_string_ext std_descriptor_type_vals_ext = VALUE_STRING_EXT_INIT(std_descriptor_type_vals); /* * Feature selectors. * Per USB 3.1 spec, Table 9-7 */ #define USB_FS_ENDPOINT_HALT 0 #define USB_FS_FUNCTION_SUSPEND 0 /* same as ENDPOINT_HALT */ #define USB_FS_DEVICE_REMOTE_WAKEUP 1 #define USB_FS_TEST_MODE 2 #define USB_FS_B_HNP_ENABLE 3 #define USB_FS_A_HNP_SUPPORT 4 #define USB_FS_A_ALT_HNP_SUPPORT 5 #define USB_FS_WUSB_DEVICE 6 #define USB_FS_U1_ENABLE 48 #define USB_FS_U2_ENABLE 49 #define USB_FS_LTM_ENABLE 50 #define USB_FS_B3_NTF_HOST_REL 51 #define USB_FS_B3_RSP_ENABLE 52 #define USB_FS_LDM_ENABLE 53 static const value_string usb_endpoint_feature_selector_vals[] = { {USB_FS_ENDPOINT_HALT, "ENDPOINT HALT"}, {0, NULL} }; static const value_string usb_interface_feature_selector_vals[] = { {USB_FS_FUNCTION_SUSPEND, "FUNCTION SUSPEND"}, {0, NULL} }; static const value_string usb_device_feature_selector_vals[] = { {USB_FS_DEVICE_REMOTE_WAKEUP, "DEVICE REMOTE WAKEUP"}, {USB_FS_TEST_MODE, "TEST MODE"}, {USB_FS_B_HNP_ENABLE, "B HNP ENABLE"}, {USB_FS_A_HNP_SUPPORT, "A HNP SUPPORT"}, {USB_FS_A_ALT_HNP_SUPPORT, "A ALT HNP SUPPORT"}, {USB_FS_WUSB_DEVICE, "WUSB DEVICE"}, {USB_FS_U1_ENABLE, "U1 ENABLE"}, {USB_FS_U2_ENABLE, "U2 ENABLE"}, {USB_FS_LTM_ENABLE, "LTM ENABLE"}, {USB_FS_B3_NTF_HOST_REL, "B3 NTF HOST REL"}, {USB_FS_B3_RSP_ENABLE, "B3 RSP ENABLE"}, {USB_FS_LDM_ENABLE, "LDM ENABLE"}, {0, NULL} }; /* the transfer type in the endpoint descriptor, i.e. the type of the endpoint (this is not the same as the URB transfer type) */ #define USB_EP_CONTROL 0x00 #define USB_EP_ISOCHRONOUS 0x01 #define USB_EP_BULK 0x02 #define USB_EP_INTERRUPT 0x03 static const value_string usb_bmAttributes_transfer_vals[] = { {USB_EP_CONTROL, "Control-Transfer"}, {USB_EP_ISOCHRONOUS, "Isochronous-Transfer"}, {USB_EP_BULK, "Bulk-Transfer"}, {USB_EP_INTERRUPT, "Interrupt-Transfer"}, {0, NULL} }; static const value_string usb_bmAttributes_sync_vals[] = { {0x00, "No Sync"}, {0x01, "Asynchronous"}, {0x02, "Adaptive"}, {0x03, "Synchronous"}, {0, NULL} }; static const value_string usb_bmAttributes_behaviour_vals[] = { {0x00, "Data-Endpoint"}, {0x01, "Explicit Feedback-Endpoint"}, {0x02, "Implicit Feedback-Data-Endpoint"}, {0x03, "Reserved"}, {0, NULL} }; static const value_string usb_wMaxPacketSize_slots_vals[] = { {0x00, "1"}, {0x01, "2"}, {0x02, "3"}, {0x03, "Reserved"}, {0, NULL} }; /* USBPcap versions up to 1.4.1.0 captures USB control as 2 or 3 packets: * * SETUP with 8 bytes of Setup data * * DATA with optional data (either OUT or IN) * * STATUS without any USB payload, only the pseudoheader * * USBPcap versions 1.5.0.0 and up captures USB control as 2 packets: * * SETUP with 8 bytes of Setup data and optional DATA OUT * * COMPLETE with optional DATA IN * * The SETUP/COMPLETE matches the way control transfers are captured by * usbmon on Linux. */ #define USB_CONTROL_STAGE_SETUP 0x00 #define USB_CONTROL_STAGE_DATA 0x01 #define USB_CONTROL_STAGE_STATUS 0x02 #define USB_CONTROL_STAGE_COMPLETE 0x03 static const value_string usb_control_stage_vals[] = { {USB_CONTROL_STAGE_SETUP, "Setup"}, {USB_CONTROL_STAGE_DATA, "Data"}, {USB_CONTROL_STAGE_STATUS, "Status"}, {USB_CONTROL_STAGE_COMPLETE, "Complete"}, {0, NULL} }; /* Extra URB code to indicate relevant USB IRPs that don't directly * have any matching USB transfer. */ #define USBPCAP_URB_IRP_INFO 0xFE static const value_string win32_usb_transfer_type_vals[] = { {URB_CONTROL, "URB_CONTROL"}, {URB_ISOCHRONOUS, "URB_ISOCHRONOUS"}, {URB_INTERRUPT, "URB_INTERRUPT"}, {URB_BULK, "URB_BULK"}, {USBPCAP_URB_IRP_INFO, "USB IRP Info"}, {0, NULL} }; static const value_string win32_urb_function_vals[] = { {0x0000, "URB_FUNCTION_SELECT_CONFIGURATION"}, {0x0001, "URB_FUNCTION_SELECT_INTERFACE"}, {0x0002, "URB_FUNCTION_ABORT_PIPE"}, {0x0003, "URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL"}, {0x0004, "URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL"}, {0x0005, "URB_FUNCTION_GET_FRAME_LENGTH"}, {0x0006, "URB_FUNCTION_SET_FRAME_LENGTH"}, {0x0007, "URB_FUNCTION_GET_CURRENT_FRAME_NUMBER"}, {0x0008, "URB_FUNCTION_CONTROL_TRANSFER"}, {0x0009, "URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"}, {0x000A, "URB_FUNCTION_ISOCH_TRANSFER"}, {0x000B, "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"}, {0x000C, "URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE"}, {0x000D, "URB_FUNCTION_SET_FEATURE_TO_DEVICE"}, {0x000E, "URB_FUNCTION_SET_FEATURE_TO_INTERFACE"}, {0x000F, "URB_FUNCTION_SET_FEATURE_TO_ENDPOINT"}, {0x0010, "URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE"}, {0x0011, "URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE"}, {0x0012, "URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT"}, {0x0013, "URB_FUNCTION_GET_STATUS_FROM_DEVICE"}, {0x0014, "URB_FUNCTION_GET_STATUS_FROM_INTERFACE"}, {0x0015, "URB_FUNCTION_GET_STATUS_FROM_ENDPOINT"}, {0x0016, "URB_FUNCTION_RESERVED_0X0016"}, {0x0017, "URB_FUNCTION_VENDOR_DEVICE"}, {0x0018, "URB_FUNCTION_VENDOR_INTERFACE"}, {0x0019, "URB_FUNCTION_VENDOR_ENDPOINT"}, {0x001A, "URB_FUNCTION_CLASS_DEVICE"}, {0x001B, "URB_FUNCTION_CLASS_INTERFACE"}, {0x001C, "URB_FUNCTION_CLASS_ENDPOINT"}, {0x001D, "URB_FUNCTION_RESERVE_0X001D"}, {0x001E, "URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL"}, {0x001F, "URB_FUNCTION_CLASS_OTHER"}, {0x0020, "URB_FUNCTION_VENDOR_OTHER"}, {0x0021, "URB_FUNCTION_GET_STATUS_FROM_OTHER"}, {0x0022, "URB_FUNCTION_CLEAR_FEATURE_TO_OTHER"}, {0x0023, "URB_FUNCTION_SET_FEATURE_TO_OTHER"}, {0x0024, "URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT"}, {0x0025, "URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT"}, {0x0026, "URB_FUNCTION_GET_CONFIGURATION"}, {0x0027, "URB_FUNCTION_GET_INTERFACE"}, {0x0028, "URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"}, {0x0029, "URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE"}, {0x002A, "URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR"}, {0x002B, "URB_FUNCTION_RESERVE_0X002B"}, {0x002C, "URB_FUNCTION_RESERVE_0X002C"}, {0x002D, "URB_FUNCTION_RESERVE_0X002D"}, {0x002E, "URB_FUNCTION_RESERVE_0X002E"}, {0x002F, "URB_FUNCTION_RESERVE_0X002F"}, {0x0030, "URB_FUNCTION_SYNC_RESET_PIPE"}, {0x0031, "URB_FUNCTION_SYNC_CLEAR_STALL"}, {0x0032, "URB_FUNCTION_CONTROL_TRANSFER_EX"}, {0x0033, "URB_FUNCTION_RESERVE_0X0033"}, {0x0034, "URB_FUNCTION_RESERVE_0X0034"}, {0, NULL} }; static value_string_ext win32_urb_function_vals_ext = VALUE_STRING_EXT_INIT(win32_urb_function_vals); static const value_string win32_usbd_status_vals[] = { {0x00000000, "USBD_STATUS_SUCCESS"}, {0x40000000, "USBD_STATUS_PENDING"}, {0x80000200, "USBD_STATUS_INVALID_URB_FUNCTION"}, {0x80000300, "USBD_STATUS_INVALID_PARAMETER"}, {0x80000400, "USBD_STATUS_ERROR_BUSY"}, {0x80000600, "USBD_STATUS_INVALID_PIPE_HANDLE"}, {0x80000700, "USBD_STATUS_NO_BANDWIDTH"}, {0x80000800, "USBD_STATUS_INTERNAL_HC_ERROR"}, {0x80000900, "USBD_STATUS_ERROR_SHORT_TRANSFER"}, {0xC0000001, "USBD_STATUS_CRC"}, {0xC0000002, "USBD_STATUS_BTSTUFF"}, {0xC0000003, "USBD_STATUS_DATA_TOGGLE_MISMATCH"}, {0xC0000004, "USBD_STATUS_STALL_PID"}, {0xC0000005, "USBD_STATUS_DEV_NOT_RESPONDING"}, {0xC0000006, "USBD_STATUS_PID_CHECK_FAILURE"}, {0xC0000007, "USBD_STATUS_UNEXPECTED_PID"}, {0xC0000008, "USBD_STATUS_DATA_OVERRUN"}, {0xC0000009, "USBD_STATUS_DATA_UNDERRUN"}, {0xC000000A, "USBD_STATUS_RESERVED1"}, {0xC000000B, "USBD_STATUS_RESERVED2"}, {0xC000000C, "USBD_STATUS_BUFFER_OVERRUN"}, {0xC000000D, "USBD_STATUS_BUFFER_UNDERRUN"}, {0xC000000F, "USBD_STATUS_NOT_ACCESSED"}, {0xC0000010, "USBD_STATUS_FIFO"}, {0xC0000011, "USBD_STATUS_XACT_ERROR"}, {0xC0000012, "USBD_STATUS_BABBLE_DETECTED"}, {0xC0000013, "USBD_STATUS_DATA_BUFFER_ERROR"}, {0xC0000030, "USBD_STATUS_ENDPOINT_HALTED"}, {0xC0000A00, "USBD_STATUS_BAD_START_FRAME"}, {0xC0000B00, "USBD_STATUS_ISOCH_REQUEST_FAILED"}, {0xC0000C00, "USBD_STATUS_FRAME_CONTROL_OWNED"}, {0xC0000D00, "USBD_STATUS_FRAME_CONTROL_NOT_OWNED"}, {0xC0000E00, "USBD_STATUS_NOT_SUPPORTED"}, {0xC0000F00, "USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR"}, {0xC0001000, "USBD_STATUS_INSUFFICIENT_RESOURCES"}, {0xC0002000, "USBD_STATUS_SET_CONFIG_FAILED"}, {0xC0003000, "USBD_STATUS_BUFFER_TOO_SMALL"}, {0xC0004000, "USBD_STATUS_INTERFACE_NOT_FOUND"}, {0xC0005000, "USBD_STATUS_INVALID_PIPE_FLAGS"}, {0xC0006000, "USBD_STATUS_TIMEOUT"}, {0xC0007000, "USBD_STATUS_DEVICE_GONE"}, {0xC0008000, "USBD_STATUS_STATUS_NOT_MAPPED"}, {0xC0009000, "USBD_STATUS_HUB_INTERNAL_ERROR"}, {0xC0010000, "USBD_STATUS_CANCELED"}, {0xC0020000, "USBD_STATUS_ISO_NOT_ACCESSED_BY_HW"}, {0xC0030000, "USBD_STATUS_ISO_TD_ERROR"}, {0xC0040000, "USBD_STATUS_ISO_NA_LATE_USBPORT"}, {0xC0050000, "USBD_STATUS_ISO_NOT_ACCESSED_LATE"}, {0xC0100000, "USBD_STATUS_BAD_DESCRIPTOR"}, {0xC0100001, "USBD_STATUS_BAD_DESCRIPTOR_BLEN"}, {0xC0100002, "USBD_STATUS_BAD_DESCRIPTOR_TYPE"}, {0xC0100003, "USBD_STATUS_BAD_INTERFACE_DESCRIPTOR"}, {0xC0100004, "USBD_STATUS_BAD_ENDPOINT_DESCRIPTOR"}, {0xC0100005, "USBD_STATUS_BAD_INTERFACE_ASSOC_DESCRIPTOR"}, {0xC0100006, "USBD_STATUS_BAD_CONFIG_DESC_LENGTH"}, {0xC0100007, "USBD_STATUS_BAD_NUMBER_OF_INTERFACES"}, {0xC0100008, "USBD_STATUS_BAD_NUMBER_OF_ENDPOINTS"}, {0xC0100009, "USBD_STATUS_BAD_ENDPOINT_ADDRESS"}, {0, NULL} }; static value_string_ext win32_usbd_status_vals_ext = VALUE_STRING_EXT_INIT(win32_usbd_status_vals); static const value_string win32_usb_info_direction_vals[] = { {0, "FDO -> PDO"}, {1, "PDO -> FDO"}, {0, NULL} }; static const value_string usb_cdc_protocol_vals[] = { {0x00, "No class specific protocol required"}, {0x01, "AT Commands: V.250 etc"}, {0x02, "AT Commands defined by PCCA-101"}, {0x03, "AT Commands defined by PCCA-101 & Annex O"}, {0x04, "AT Commands defined by GSM 07.07"}, {0x05, "AT Commands defined by 3GPP 27.007"}, {0x06, "AT Commands defined by TIA for CDMA"}, {0x07, "Ethernet Emulation Model"}, {0xFE, "External Protocol: Commands defined by Command Set Functional Descriptor"}, {0xFF, "Vendor-specific"}, {0, NULL} }; static value_string_ext usb_cdc_protocol_vals_ext = VALUE_STRING_EXT_INIT(usb_cdc_protocol_vals); extern value_string_ext usb_massstorage_protocol_vals_ext; static const value_string usb_cdc_data_protocol_vals[] = { {0x00, "No class specific protocol required"}, {0x01, "Network Transfer Block"}, {0x02, "Network Transfer Block (IP + DSS)"}, {0x30, "Physical interface protocol for ISDN BRI"}, {0x31, "HDLC"}, {0x32, "Transparent"}, {0x50, "Management protocol for Q.921 data link protocol"}, {0x51, "Data link protocol for Q.931"}, {0x52, "TEI-multiplexor for Q.921 data link protocol"}, {0x90, "Data compression procedures"}, {0x91, "Euro-ISDN protocol control"}, {0x92, "V.24 rate adaptation to ISDN"}, {0x93, "CAPI Commands"}, {0xFE, "The protocol(s) are described using a Protocol Unit Functional Descriptors on Communications Class Interface"}, {0xFF, "Vendor-specific"}, {0, NULL} }; static value_string_ext usb_cdc_data_protocol_vals_ext = VALUE_STRING_EXT_INIT(usb_cdc_data_protocol_vals); static const value_string usb_hid_subclass_vals[] = { {0, "No Subclass"}, {1, "Boot Interface"}, {0, NULL} }; static value_string_ext usb_hid_subclass_vals_ext = VALUE_STRING_EXT_INIT(usb_hid_subclass_vals); static const value_string usb_hid_boot_protocol_vals[] = { {0, "None"}, {1, "Keyboard"}, {2, "Mouse"}, {0, NULL} }; static value_string_ext usb_hid_boot_protocol_vals_ext = VALUE_STRING_EXT_INIT(usb_hid_boot_protocol_vals); static const value_string usb_misc_subclass_vals[] = { {0x03, "Cable Based Association Framework"}, {0x04, "RNDIS"}, {IF_SUBCLASS_MISC_U3V, "USB3 Vision"}, {0x06, "Stream Transport Efficient Protocol"}, {0, NULL} }; static value_string_ext usb_misc_subclass_vals_ext = VALUE_STRING_EXT_INIT(usb_misc_subclass_vals); static const value_string usb_app_subclass_vals[] = { {0x01, "Device Firmware Upgrade"}, {0x02, "IRDA Bridge"}, {0x03, "USB Test and Measurement Device"}, {0, NULL} }; static value_string_ext usb_app_subclass_vals_ext = VALUE_STRING_EXT_INIT(usb_app_subclass_vals); static const value_string usb_app_dfu_protocol_vals[] = { {0x01, "Runtime protocol"}, {0x02, "DFU mode protocol"}, {0, NULL} }; static value_string_ext usb_app_dfu_protocol_vals_ext = VALUE_STRING_EXT_INIT(usb_app_dfu_protocol_vals); static const value_string usb_app_irda_protocol_vals[] = { {0x00, "IRDA Bridge device"}, {0, NULL} }; static value_string_ext usb_app_irda_protocol_vals_ext = VALUE_STRING_EXT_INIT(usb_app_irda_protocol_vals); static const value_string usb_app_usb_test_and_measurement_protocol_vals[] = { {0x00, "USB Test and Measurement Device"}, {0x01, "USB Test and Measurement Device conforming to the USBTMC USB488 Subclass Specification"}, {0, NULL} }; static value_string_ext usb_app_usb_test_and_measurement_protocol_vals_ext = VALUE_STRING_EXT_INIT(usb_app_usb_test_and_measurement_protocol_vals); /* macOS */ /* Request Type */ #define DARWIN_IO_SUBMIT 0 #define DARWIN_IO_COMPLETE 1 static const value_string usb_darwin_request_type_vals[] = { {DARWIN_IO_SUBMIT, "SUBMIT"}, {DARWIN_IO_COMPLETE, "COMPLETE"}, {0, NULL} }; /* Transfer type */ static const value_string usb_darwin_endpoint_type_vals[] = { {USB_EP_CONTROL, "Control"}, {USB_EP_ISOCHRONOUS, "Isochronous"}, {USB_EP_BULK, "Bulk"}, {USB_EP_INTERRUPT, "Interrupt"}, {0, NULL} }; /* USB speeds */ #define DARWIN_SPEED_LOW 0 #define DARWIN_SPEED_FULL 1 #define DARWIN_SPEED_HIGH 2 #define DARWIN_SPEED_SUPER 3 #define DARWIN_SPEED_SUPERPLUS 4 static const value_string usb_darwin_speed_vals[] = { {DARWIN_SPEED_LOW, "Low"}, {DARWIN_SPEED_FULL, "Full"}, {DARWIN_SPEED_HIGH, "High"}, {DARWIN_SPEED_SUPER, "Super"}, {DARWIN_SPEED_SUPERPLUS, "Super+"}, {0, NULL} }; static const value_string darwin_usb_status_vals[] = { {0x00000000, "kIOReturnSuccess"}, {0xe00002bc, "kIOReturnError"}, {0xe00002bd, "kIOReturnNoMemory"}, {0xe00002be, "kIOReturnNoResources"}, {0xe00002bf, "kIOReturnIPCError"}, {0xe00002c0, "kIOReturnNoDevice"}, {0xe00002c1, "kIOReturnNotPrivileged"}, {0xe00002c2, "kIOReturnBadArgument"}, {0xe00002c3, "kIOReturnLockedRead"}, {0xe00002c4, "kIOReturnLockedWrite"}, {0xe00002c5, "kIOReturnExclusiveAccess"}, {0xe00002c6, "kIOReturnBadMessageID"}, {0xe00002c7, "kIOReturnUnsupported"}, {0xe00002c8, "kIOReturnVMError"}, {0xe00002c9, "kIOReturnInternalError"}, {0xe00002ca, "kIOReturnIOError"}, {0xe00002cc, "kIOReturnCannotLock"}, {0xe00002cd, "kIOReturnNotOpen"}, {0xe00002ce, "kIOReturnNotReadable"}, {0xe00002cf, "kIOReturnNotWritable"}, {0xe00002d0, "kIOReturnNotAligned"}, {0xe00002d1, "kIOReturnBadMedia"}, {0xe00002d2, "kIOReturnStillOpen"}, {0xe00002d3, "kIOReturnRLDError"}, {0xe00002d4, "kIOReturnDMAError"}, {0xe00002d5, "kIOReturnBusy"}, {0xe00002d6, "kIOReturnTimeout"}, {0xe00002d7, "kIOReturnOffline"}, {0xe00002d8, "kIOReturnNotReady"}, {0xe00002d9, "kIOReturnNotAttached"}, {0xe00002da, "kIOReturnNoChannels"}, {0xe00002db, "kIOReturnNoSpace"}, {0xe00002dd, "kIOReturnPortExists"}, {0xe00002de, "kIOReturnCannotWire"}, {0xe00002df, "kIOReturnNoInterrupt"}, {0xe00002e0, "kIOReturnNoFrames"}, {0xe00002e1, "kIOReturnMessageTooLarge"}, {0xe00002e2, "kIOReturnNotPermitted"}, {0xe00002e3, "kIOReturnNoPower"}, {0xe00002e4, "kIOReturnNoMedia"}, {0xe00002e5, "kIOReturnUnformattedMedia"}, {0xe00002e6, "kIOReturnUnsupportedMode"}, {0xe00002e7, "kIOReturnUnderrun"}, {0xe00002e8, "kIOReturnOverrun"}, {0xe00002e9, "kIOReturnDeviceError"}, {0xe00002ea, "kIOReturnNoCompletion"}, {0xe00002eb, "kIOReturnAborted"}, {0xe00002ec, "kIOReturnNoBandwidth"}, {0xe00002ed, "kIOReturnNotResponding"}, {0xe00002ee, "kIOReturnIsoTooOld"}, {0xe00002ef, "kIOReturnIsoTooNew"}, {0xe00002f0, "kIOReturnNotFound"}, {0, NULL} }; static const guint32 darwin_endpoint_to_linux[] = { URB_CONTROL, URB_ISOCHRONOUS, URB_BULK, URB_INTERRUPT, URB_UNKNOWN }; static value_string_ext usb_darwin_status_vals_ext = VALUE_STRING_EXT_INIT(darwin_usb_status_vals); static const value_string netmon_event_id_vals[] = { {1, "USBPORT_ETW_EVENT_HC_ADD USBPORT_ETW_EVENT_HC_ADD"}, {2, "USBPORT_ETW_EVENT_HC_REMOVAL USBPORT_ETW_EVENT_HC_REMOVAL"}, {3, "USBPORT_ETW_EVENT_HC_INFORMATION USBPORT_ETW_EVENT_HC_INFORMATION"}, {4, "USBPORT_ETW_EVENT_HC_START USBPORT_ETW_EVENT_HC_START"}, {5, "USBPORT_ETW_EVENT_HC_STOP USBPORT_ETW_EVENT_HC_STOP"}, {6, "USBPORT_ETW_EVENT_HC_SUSPEND USBPORT_ETW_EVENT_HC_SUSPEND"}, {7, "USBPORT_ETW_EVENT_HC_RESUME USBPORT_ETW_EVENT_HC_RESUME"}, {8, "USBPORT_ETW_EVENT_HC_ASYNC_SCHEDULE_ENABLE"}, {9, "USBPORT_ETW_EVENT_HC_ASYNC_SCHEDULE_DISABLE"}, {10, "USBPORT_ETW_EVENT_HC_PERIODIC_SCHEDULE_ENABLE"}, {11, "USBPORT_ETW_EVENT_HC_PERIODIC_SCHEDULE_DISABLE"}, {12, "USBPORT_ETW_EVENT_DEVICE_CREATE"}, {13, "USBPORT_ETW_EVENT_DEVICE_INITIALIZE"}, {14, "USBPORT_ETW_EVENT_DEVICE_REMOVAL"}, {15, "USBPORT_ETW_EVENT_DEVICE_INFORMATION"}, {16, "USBPORT_ETW_EVENT_DEVICE_IDLE_STATE_SET"}, {17, "USBPORT_ETW_EVENT_DEVICE_IDLE_STATE_CLEAR"}, {18, "USBPORT_ETW_EVENT_ENDPOINT_OPEN"}, {19, "USBPORT_ETW_EVENT_ENDPOINT_CLOSE USBPORT_ETW_EVENT_ENDPOINT_CLOSE"}, {20, "USBPORT_ETW_EVENT_ENDPOINT_INFORMATION"}, {21, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SELECT_CONFIGURATION"}, {22, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SELECT_INTERFACE"}, {23, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_CURRENT_FRAME_NUMBER"}, {24, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CONTROL_TRANSFER"}, {25, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CONTROL_TRANSFER_EX"}, {26, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"}, {27, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_ISOCH_TRANSFER"}, {28, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"}, {29, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE"}, {30, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT"}, {31, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT"}, {32, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"}, {33, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE"}, {34, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_FEATURE_TO_DEVICE"}, {35, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_FEATURE_TO_INTERFACE"}, {36, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_FEATURE_TO_ENDPOINT"}, {37, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE"}, {38, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE"}, {39, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT"}, {40, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLEAR_FEATURE_TO_OTHER"}, {41, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_FEATURE_TO_OTHER"}, {42, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_STATUS_FROM_DEVICE"}, {43, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_STATUS_FROM_INTERFACE"}, {44, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_STATUS_FROM_ENDPOINT"}, {45, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_STATUS_FROM_OTHER"}, {46, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_VENDOR_DEVICE"}, {47, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_VENDOR_INTERFACE"}, {48, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_VENDOR_ENDPOINT"}, {49, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLASS_DEVICE"}, {50, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLASS_INTERFACE"}, {51, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLASS_ENDPOINT"}, {52, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_CLASS_OTHER"}, {53, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_VENDOR_OTHER"}, {54, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_ABORT_PIPE"}, {55, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL"}, {56, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SYNC_RESET_PIPE"}, {57, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SYNC_CLEAR_STALL"}, {58, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_CONFIGURATION"}, {59, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_INTERFACE"}, {60, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR"}, {61, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL"}, {62, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL"}, {63, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_GET_FRAME_LENGTH"}, {64, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_SET_FRAME_LENGTH"}, {65, "USBPORT_ETW_EVENT_DISPATCH_URB_FUNCTION_RESERVED"}, {66, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_CONTROL_TRANSFER"}, {67, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_CONTROL_TRANSFER_EX"}, {68, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_CONTROL_TRANSFER_DATA"}, {69, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_CONTROL_TRANSFER_EX_DATA"}, {70, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"}, {71, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_DATA"}, {72, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_ISOCH_TRANSFER"}, {73, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_ISOCH_TRANSFER_DATA"}, {74, "USBPORT_ETW_EVENT_INTERNAL_URB_FUNCTION_CONTROL_TRANSFER"}, {75, "USBPORT_ETW_EVENT_COMPLETE_INTERNAL_URB_FUNCTION_CONTROL_TRANSFER"}, {76, "USBPORT_ETW_EVENT_COMPLETE_INTERNAL_URB_FUNCTION_CONTROL_TRANSFER_DATA"}, {77, "USBPORT_ETW_EVENT_COMPLETE_URB_FUNCTION_ABORT_PIPE"}, {78, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_HEADER_LENGTH_WARNING"}, {79, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_FUNCTION"}, {80, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_HEADER_LENGTH"}, {81, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_DEVICE_HANDLE"}, {82, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_FUNCTION_NOT_SUPPORTED"}, {83, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_FUNCTION_RESERVED"}, {84, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_DUE_TO_HC_SUSPEND"}, {85, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_URB_LINK"}, {86, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_PIPE_HANDLE"}, {87, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_ZERO_BW_PIPE_HANDLE"}, {88, "USBPORT_ETW_EVENT_DISPATCH_URB_NOP_ZERO_BW_PIPE_HANDLE_REQUEST"}, {89, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_CONTROL_TRANSFER_ENDPOINT"}, {90, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_CONTROL_TRANSFER_BUFFER_LENGTH"}, {91, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_BULK_OR_INTERRUPT_TRANSFER_ENDPOINT"}, {92, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_BULK_OR_INTERRUPT_TRANSFER_BUFFER_LENGTH"}, {93, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_ISOCHRONOUS_TRANSFER_ENDPOINT"}, {94, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_NULL_TRANSFER_BUFFER_AND_MDL"}, {95, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_NON_NULL_TRANSFER_BUFFER_MDL"}, {96, "USBPORT_ETW_EVENT_DISPATCH_URB_ALLOCATE_MDL_FAILURE"}, {97, "USBPORT_ETW_EVENT_DISPATCH_URB_ALLOCATE_TRANSFER_CONTEXT_FAILURE"}, {98, "USBPORT_ETW_EVENT_DISPATCH_URB_NOP_ROOTHUB_PIPE_HANDLE_REQUEST"}, {99, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_ISOCHRONOUS_ZERO_LENGTH"}, {100, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_ISOCHRONOUS_NUM_PACKETS"}, {101, "USBPORT_ETW_EVENT_DISPATCH_URB_INVALID_ISOCHRONOUS_START_FRAME"}, {102, "USBPORT_ETW_EVENT_IRP_CANCEL"}, {103, "USBPORT_ETW_EVENT_USBUSER_OP_RAW_RESET_PORT_DISPATCH"}, {104, "USBPORT_ETW_EVENT_USBUSER_OP_RAW_RESET_PORT_STATUS1"}, {105, "USBPORT_ETW_EVENT_USBUSER_OP_RAW_RESET_PORT_STATUS2"}, {106, "USBPORT_ETW_EVENT_USBUSER_OP_RAW_RESET_PORT_STATUS3"}, {107, "USBPORT_ETW_EVENT_USBUSER_OP_RAW_RESET_PORT_COMPLETE"}, {108, "USBPORT_ETW_EVENT_USBUSER_OP_SEND_ONE_PACKET_DISPATCH"}, {109, "USBPORT_ETW_EVENT_USBUSER_OP_SEND_ONE_PACKET_DISPATCH_DATA"}, {110, "USBPORT_ETW_EVENT_USBUSER_OP_SEND_ONE_PACKET_TIMEOUT"}, {111, "USBPORT_ETW_EVENT_USBUSER_OP_SEND_ONE_PACKET_COMPLETE"}, {112, "USBPORT_ETW_EVENT_USBUSER_OP_SEND_ONE_PACKET_COMPLETE_DATA"}, {113, "USBPORT_ETW_EVENT_CODE_EXECUTION_TIME"}, {114, "USBPORT_ETW_EVENT_PUT_SGLIST_EXECUTION_TIME"}, {115, "USBPORT_ETW_EVENT_BUILD_SGLIST_EXECUTION_TIME"}, {1024, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_DISPATCH"}, {1025, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_COMPLETE"}, {1026, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_COMPLETE_ERROR_1"}, {1027, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_COMPLETE_ERROR_2"}, {1028, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_COMPLETE_ERROR_3"}, {1029, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_COMPLETE_ERROR_4"}, {1030, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_START_COMPLETE_ERROR_5"}, {1031, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_STOP_DISPATCH"}, {1032, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_STOP_COMPLETE"}, {1033, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_SUSPEND_DISPATCH"}, {1034, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_SUSPEND_COMPLETE"}, {1035, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_DISPATCH"}, {1036, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE"}, {1037, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE_ERROR_1"}, {1038, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE_ERROR_2"}, {1039, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE_ERROR_3"}, {1040, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE_ERROR_4"}, {1041, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE_ERROR_5"}, {1042, "USBPORT_ETW_EVENT_HC_EHCI_MINIPORT_RESUME_COMPLETE_ERROR_6"}, {2048, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_DISPATCH"}, {2049, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_COMPLETE"}, {2050, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_COMPLETE_ERROR_1"}, {2051, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_COMPLETE_ERROR_2"}, {2052, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_COMPLETE_ERROR_3"}, {2053, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_COMPLETE_ERROR_4"}, {2054, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_START_COMPLETE_ERROR_5"}, {2055, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_STOP_DISPATCH"}, {2056, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_STOP_COMPLETE"}, {2057, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_SUSPEND_DISPATCH"}, {2058, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_SUSPEND_COMPLETE"}, {2059, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_DISPATCH"}, {2060, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_COMPLETE"}, {2061, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_COMPLETE_ERROR_1"}, {2062, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_COMPLETE_ERROR_2"}, {2063, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_COMPLETE_ERROR_3"}, {2064, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_COMPLETE_ERROR_4"}, {2065, "USBPORT_ETW_EVENT_HC_OHCI_MINIPORT_RESUME_COMPLETE_ERROR_5"}, {3072, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_START_DISPATCH"}, {3073, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_START_COMPLETE"}, {3074, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_START_COMPLETE_ERROR_1"}, {3075, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_START_COMPLETE_ERROR_2"}, {3076, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_START_COMPLETE_ERROR_3"}, {3077, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_START_COMPLETE_ERROR_4"}, {3078, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_STOP_DISPATCH"}, {3079, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_STOP_COMPLETE"}, {3080, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_SUSPEND_DISPATCH"}, {3081, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_SUSPEND_COMPLETE"}, {3082, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_DISPATCH"}, {3083, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_COMPLETE"}, {3084, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_COMPLETE_ERROR_1"}, {3085, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_COMPLETE_ERROR_2"}, {3086, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_COMPLETE_ERROR_3"}, {3087, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_COMPLETE_ERROR_4"}, {3088, "USBPORT_ETW_EVENT_HC_UHCI_MINIPORT_RESUME_COMPLETE_ERROR_5"}, {3089, "USBPORT_ETW_EVENT_RTPM_TRANSITION"}, {3090, "USBPORT_ETW_EVENT_DISPATCH_WAIT_WAKE"}, {3091, "USBPORT_ETW_EVENT_COMPLETE_WAIT_WAKE"}, {0, NULL} }; static value_string_ext netmon_event_id_vals_ext = VALUE_STRING_EXT_INIT(netmon_event_id_vals); static const value_string netmon_urb_function_vals[] = { {0x0000, "SELECT_CONFIGURATION"}, {0x0001, "SELECT_INTERFACE"}, {0x0002, "ABORT_PIPE"}, {0x0003, "TAKE_FRAME_LENGTH_CONTROL"}, {0x0004, "RELEASE_FRAME_LENGTH_CONTROL"}, {0x0005, "GET_FRAME_LENGTH"}, {0x0006, "SET_FRAME_LENGTH"}, {0x0007, "GET_CURRENT_FRAME_NUMBER"}, {0x0008, "CONTROL_TRANSFER"}, {0x0009, "BULK_OR_INTERRUPT_TRANSFER"}, {0x000A, "ISOCH_TRANSFER"}, {0x000B, "GET_DESCRIPTOR_FROM_DEVICE"}, {0x000C, "SET_DESCRIPTOR_TO_DEVICE"}, {0x000D, "SET_FEATURE_TO_DEVICE"}, {0x000E, "SET_FEATURE_TO_INTERFACE"}, {0x000F, "SET_FEATURE_TO_ENDPOINT"}, {0x0010, "CLEAR_FEATURE_TO_DEVICE"}, {0x0011, "CLEAR_FEATURE_TO_INTERFACE"}, {0x0012, "CLEAR_FEATURE_TO_ENDPOINT"}, {0x0013, "GET_STATUS_FROM_DEVICE"}, {0x0014, "GET_STATUS_FROM_INTERFACE"}, {0x0015, "GET_STATUS_FROM_ENDPOINT"}, {0x0016, "RESERVED"}, {0x0017, "VENDOR_DEVICE"}, {0x0018, "VENDOR_INTERFACE"}, {0x0019, "VENDOR_ENDPOINT"}, {0x001A, "CLASS_DEVICE"}, {0x001B, "CLASS_INTERFACE"}, {0x001C, "CLASS_ENDPOINT"}, {0x001D, "RESERVE_0X001D"}, {0x001E, "SYNC_RESET_PIPE_AND_CLEAR_STALL"}, {0x001F, "CLASS_OTHER"}, {0x0020, "VENDOR_OTHER"}, {0x0021, "GET_STATUS_FROM_OTHER"}, {0x0022, "CLEAR_FEATURE_TO_OTHER"}, {0x0023, "SET_FEATURE_TO_OTHER"}, {0x0024, "GET_DESCRIPTOR_FROM_ENDPOINT"}, {0x0025, "SET_DESCRIPTOR_TO_ENDPOINT"}, {0x0026, "GET_CONFIGURATION"}, {0x0027, "GET_INTERFACE"}, {0x0028, "GET_DESCRIPTOR_FROM_INTERFACE"}, {0x0029, "SET_DESCRIPTOR_TO_INTERFACE"}, {0x002A, "GET_MS_FEATURE_DESCRIPTOR"}, {0x0030, "SYNC_RESET_PIPE"}, {0x0031, "SYNC_CLEAR_STALL"}, {0x0032, "CONTROL_TRANSFER_EX"}, {0x0035, "OPEN_STATIC_STREAMS"}, {0x0036, "CLOSE_STATIC_STREAMS"}, {0x0037, "BULK_OR_INTERRUPT_TRANSFER_USING_CHAINED_MDL"}, {0x0038, "ISOCH_TRANSFER_USING_CHAINED_MDL"}, {0, NULL} }; static value_string_ext netmon_urb_function_vals_ext = VALUE_STRING_EXT_INIT(netmon_urb_function_vals); void proto_register_usb(void); void proto_reg_handoff_usb(void); /* USB address handling */ static int usb_addr_to_str(const address* addr, gchar *buf, int buf_len _U_) { const guint8 *addrp = (const guint8 *)addr->data; if(pletoh32(&addrp[0])==0xffffffff){ (void) g_strlcpy(buf, "host", buf_len); } else { snprintf(buf, buf_len, "%d.%d.%d", pletoh16(&addrp[8]), pletoh32(&addrp[0]), pletoh32(&addrp[4])); } return (int)(strlen(buf)+1); } static int usb_addr_str_len(const address* addr _U_) { return 50; } /* This keys provide information for DecodeBy and other dissector via per packet data: p_get_proto_data()/p_add_proto_data() */ #define USB_BUS_ID 0 #define USB_DEVICE_ADDRESS 1 #define USB_VENDOR_ID 2 #define USB_PRODUCT_ID 3 #define USB_DEVICE_CLASS 4 #define USB_DEVICE_SUBCLASS 5 #define USB_DEVICE_PROTOCOL 6 static void usb_device_prompt(packet_info *pinfo, gchar* result) { snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Bus ID %u \nDevice Address %u\nas ", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_BUS_ID)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_ADDRESS))); } static gpointer usb_device_value(packet_info *pinfo) { guint32 value = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_BUS_ID)) << 16; value |= GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_ADDRESS)); return GUINT_TO_POINTER(value); } static void usb_product_prompt(packet_info *pinfo, gchar* result) { snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Vendor ID 0x%04x \nProduct ID 0x%04x\nas ", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_VENDOR_ID)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_PRODUCT_ID))); } static gpointer usb_product_value(packet_info *pinfo) { guint32 value = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_VENDOR_ID)) << 16; value |= GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_PRODUCT_ID)); return GUINT_TO_POINTER(value); } static void usb_protocol_prompt(packet_info *pinfo, gchar* result) { snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Class ID 0x%04x \nSubclass ID 0x%04x\nProtocol 0x%04x\nas ", GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_CLASS)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_SUBCLASS)), GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_PROTOCOL))); } static gpointer usb_protocol_value(packet_info *pinfo) { guint32 value = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_CLASS)) << 16; value |= GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_SUBCLASS)) << 8; value |= GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_PROTOCOL)); return GUINT_TO_POINTER(value); } static build_valid_func usb_product_da_build_value[1] = {usb_product_value}; static decode_as_value_t usb_product_da_values = {usb_product_prompt, 1, usb_product_da_build_value}; static decode_as_t usb_product_da = { "usb", "usb.product", 1, 0, &usb_product_da_values, NULL, NULL, decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; static build_valid_func usb_device_da_build_value[1] = {usb_device_value}; static decode_as_value_t usb_device_da_values = {usb_device_prompt, 1, usb_device_da_build_value}; static decode_as_t usb_device_da = { "usb", "usb.device", 1, 0, &usb_device_da_values, NULL, NULL, decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; static build_valid_func usb_protocol_da_build_value[1] = {usb_protocol_value}; static decode_as_value_t usb_protocol_da_values = {usb_protocol_prompt, 1, usb_protocol_da_build_value}; static decode_as_t usb_protocol_da = { "usb", "usb.protocol", 1, 0, &usb_protocol_da_values, NULL, NULL, decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; static usb_conv_info_t * get_usb_conv_info(conversation_t *conversation) { usb_conv_info_t *usb_conv_info; /* do we have conversation specific data ? */ usb_conv_info = (usb_conv_info_t *)conversation_get_proto_data(conversation, proto_usb); if (!usb_conv_info) { /* no not yet so create some */ usb_conv_info = wmem_new0(wmem_file_scope(), usb_conv_info_t); usb_conv_info->interfaceClass = IF_CLASS_UNKNOWN; usb_conv_info->interfaceSubclass = IF_SUBCLASS_UNKNOWN; usb_conv_info->interfaceProtocol = IF_PROTOCOL_UNKNOWN; usb_conv_info->deviceVendor = DEV_VENDOR_UNKNOWN; usb_conv_info->deviceProduct = DEV_PRODUCT_UNKNOWN; usb_conv_info->deviceVersion = DEV_VERSION_UNKNOWN; usb_conv_info->alt_settings = wmem_array_new(wmem_file_scope(), sizeof(usb_alt_setting_t)); usb_conv_info->transactions = wmem_tree_new(wmem_file_scope()); usb_conv_info->descriptor_transfer_type = URB_UNKNOWN; usb_conv_info->max_packet_size = 0; conversation_add_proto_data(conversation, proto_usb, usb_conv_info); } return usb_conv_info; } /* usb_conv_info_t contains some components that are valid only for one specific packet clear_usb_conv_tmp_data() clears these components, it should be called before we dissect a new packet */ static void clear_usb_conv_tmp_data(usb_conv_info_t *usb_conv_info) { /* caller must have checked that usb_conv_info!= NULL */ usb_conv_info->direction = P2P_DIR_UNKNOWN; usb_conv_info->transfer_type = URB_UNKNOWN; usb_conv_info->is_request = FALSE; usb_conv_info->is_setup = FALSE; usb_conv_info->setup_requesttype = 0; usb_conv_info->speed = USB_SPEED_UNKNOWN; /* when we parse the configuration, interface and endpoint descriptors, we store the current interface class in endpoint 0's conversation this must be cleared since endpoint 0 does not belong to any interface class we used to clear these info in dissect_usb_configuration_descriptor() this doesn't work when the descriptor parsing throws an exception */ if (usb_conv_info->endpoint==0) { usb_conv_info->interfaceClass = IF_CLASS_UNKNOWN; usb_conv_info->interfaceSubclass = IF_SUBCLASS_UNKNOWN; usb_conv_info->interfaceProtocol = IF_PROTOCOL_UNKNOWN; } } static conversation_t * get_usb_conversation(packet_info *pinfo, address *src_addr, address *dst_addr, guint32 src_endpoint, guint32 dst_endpoint) { conversation_t *conversation; /* * Do we have a conversation for this connection? */ conversation = find_conversation(pinfo->num, src_addr, dst_addr, conversation_pt_to_conversation_type(pinfo->ptype), src_endpoint, dst_endpoint, 0); if (conversation) { return conversation; } /* We don't yet have a conversation, so create one. */ conversation = conversation_new(pinfo->num, src_addr, dst_addr, conversation_pt_to_conversation_type(pinfo->ptype), src_endpoint, dst_endpoint, 0); return conversation; } /* Fetch or create usb_conv_info for a specified interface. */ usb_conv_info_t * get_usb_iface_conv_info(packet_info *pinfo, guint8 interface_num) { conversation_t *conversation; guint32 if_port; if_port = GUINT32_TO_LE(INTERFACE_PORT | interface_num); if (pinfo->srcport == NO_ENDPOINT) { conversation = get_usb_conversation(pinfo, &pinfo->src, &pinfo->dst, pinfo->srcport, if_port); } else { conversation = get_usb_conversation(pinfo, &pinfo->src, &pinfo->dst, if_port, pinfo->destport); } return get_usb_conv_info(conversation); } /* Fetch usb_conv_info for specified endpoint, return NULL if not found */ usb_conv_info_t * get_existing_usb_ep_conv_info(packet_info* pinfo, guint16 bus_id, guint16 device_address, int endpoint) { usb_address_t *src_addr = wmem_new0(pinfo->pool, usb_address_t), *dst_addr = wmem_new0(pinfo->pool, usb_address_t); address src, dst; conversation_t *conversation; usb_conv_info_t *usb_conv_info = NULL; src_addr->bus_id = GUINT16_TO_LE(bus_id); src_addr->device = GUINT16_TO_LE(device_address); src_addr->endpoint = GUINT32_TO_LE(endpoint); dst_addr->bus_id = GUINT16_TO_LE(bus_id); dst_addr->device = 0xffffffff; dst_addr->endpoint = NO_ENDPOINT; set_address(&src, usb_address_type, USB_ADDR_LEN, (char *)src_addr); set_address(&dst, usb_address_type, USB_ADDR_LEN, (char *)dst_addr); conversation = find_conversation(pinfo->num, &src, &dst, conversation_pt_to_conversation_type(PT_USB), src_addr->endpoint, dst_addr->endpoint, 0); if (conversation) { usb_conv_info = (usb_conv_info_t *)conversation_get_proto_data(conversation, proto_usb); } return usb_conv_info; } static const char* usb_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter) { if ((filter == CONV_FT_SRC_ADDRESS) && (conv->src_address.type == usb_address_type)) return "usb.src"; if ((filter == CONV_FT_DST_ADDRESS) && (conv->dst_address.type == usb_address_type)) return "usb.dst"; if ((filter == CONV_FT_ANY_ADDRESS) && (conv->src_address.type == usb_address_type)) return "usb.addr"; return CONV_FILTER_INVALID; } static ct_dissector_info_t usb_ct_dissector_info = {&usb_conv_get_filter_type}; static tap_packet_status usb_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags) { conv_hash_t *hash = (conv_hash_t*) pct; hash->flags = flags; add_conversation_table_data(hash, &pinfo->src, &pinfo->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &usb_ct_dissector_info, CONVERSATION_NONE); return TAP_PACKET_REDRAW; } static const char* usb_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) { if ((filter == CONV_FT_ANY_ADDRESS) && (endpoint->myaddress.type == usb_address_type)) return "usb.addr"; return CONV_FILTER_INVALID; } static const char* usb_col_filter_str(const address* addr _U_, gboolean is_src) { return is_src ? "usb.src" : "usb.dst"; } static et_dissector_info_t usb_endpoint_dissector_info = {&usb_endpoint_get_filter_type}; static tap_packet_status usb_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags) { conv_hash_t *hash = (conv_hash_t*) pit; hash->flags = flags; /* Take two "add" passes per packet, adding for each direction, ensures that all packets are counted properly (even if address is sending to itself) XXX - this could probably be done more efficiently inside endpoint_table */ add_endpoint_table_data(hash, &pinfo->src, 0, TRUE, 1, pinfo->fd->pkt_len, &usb_endpoint_dissector_info, ENDPOINT_NONE); add_endpoint_table_data(hash, &pinfo->dst, 0, FALSE, 1, pinfo->fd->pkt_len, &usb_endpoint_dissector_info, ENDPOINT_NONE); return TAP_PACKET_REDRAW; } /* SETUP dissectors */ /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / CLEAR FEATURE */ /* 9.4.1 */ static int dissect_usb_setup_clear_feature_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { guint8 recip; if (usb_conv_info) { recip = USB_RECIPIENT(usb_conv_info->usb_trans_info->setup.requesttype); /* feature selector, zero/interface/endpoint */ switch (recip) { case RQT_SETUP_RECIPIENT_DEVICE: proto_tree_add_item(tree, hf_usb_device_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_INTERFACE: proto_tree_add_item(tree, hf_usb_interface_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_wInterface, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_ENDPOINT: proto_tree_add_item(tree, hf_usb_endpoint_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_wEndpoint, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_OTHER: default: proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; } } else { /* No conversation information, so recipient type is unknown */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* length */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_clear_feature_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / GET CONFIGURATION */ /* 9.4.2 */ static int dissect_usb_setup_get_configuration_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { proto_tree_add_item(tree, hf_usb_bConfigurationValue, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / GET DESCRIPTOR */ proto_item * dissect_usb_descriptor_header(proto_tree *tree, tvbuff_t *tvb, int offset, value_string_ext *type_val_str) { guint8 desc_type; proto_item *length_item; length_item = proto_tree_add_item(tree, hf_usb_bLength, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; desc_type = tvb_get_guint8(tvb, offset); /* if the caller provided no class specific value string, we're * using the standard descriptor types */ if (!type_val_str) type_val_str = &std_descriptor_type_vals_ext; proto_tree_add_uint_format_value(tree, hf_usb_bDescriptorType, tvb, offset, 1, desc_type, "0x%02x (%s)", desc_type, val_to_str_ext_const(desc_type, type_val_str, "unknown")); return length_item; } static void dissect_max_packet_size0(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info, gboolean other_speed) { proto_item *item; guint32 max_packet_size; unsigned int sanitized_max_packet_size; usb_speed_t speed = usb_conv_info->speed; item = proto_tree_add_item_ret_uint(tree, hf_usb_bMaxPacketSize0, tvb, offset, 1, ENC_LITTLE_ENDIAN, &max_packet_size); if (other_speed) { if (speed == USB_SPEED_FULL) speed = USB_SPEED_HIGH; else if (speed == USB_SPEED_HIGH) speed = USB_SPEED_FULL; } sanitized_max_packet_size = sanitize_usb_max_packet_size(ENDPOINT_TYPE_CONTROL, speed, max_packet_size); if (sanitized_max_packet_size != max_packet_size) { expert_add_info_format(pinfo, item, &ei_usb_invalid_max_packet_size0, "%s endpoint zero max packet size cannot be %u, using %d instead.", try_val_to_str(speed, usb_speed_vals), max_packet_size, sanitized_max_packet_size); } } /* 9.6.2 */ static int dissect_usb_device_qualifier_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { proto_item *item; proto_tree *tree; proto_item *nitem; int old_offset = offset; guint32 protocol; const gchar *description; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "DEVICE QUALIFIER DESCRIPTOR"); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* bcdUSB */ proto_tree_add_item(tree, hf_usb_bcdUSB, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; protocol = tvb_get_ntoh24(tvb, offset); description = val_to_str_ext_const(protocol, &usb_protocols_ext, ""); /* bDeviceClass */ proto_tree_add_item(tree, hf_usb_bDeviceClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bDeviceSubClass */ proto_tree_add_item(tree, hf_usb_bDeviceSubClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bDeviceProtocol */ nitem = proto_tree_add_item(tree, hf_usb_bDeviceProtocol, tvb, offset, 1, ENC_LITTLE_ENDIAN); if (*description) proto_item_append_text(nitem, " (%s)", description); offset += 1; if (!pinfo->fd->visited) { guint k_bus_id; guint k_device_address; guint k_frame_number; wmem_tree_key_t key[4]; device_protocol_data_t *device_protocol_data; k_frame_number = pinfo->num; k_device_address = usb_conv_info->device_address; k_bus_id = usb_conv_info->bus_id; key[0].length = 1; key[0].key = &k_device_address; key[1].length = 1; key[1].key = &k_bus_id; key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; device_protocol_data = wmem_new(wmem_file_scope(), device_protocol_data_t); device_protocol_data->protocol = protocol; device_protocol_data->bus_id = usb_conv_info->bus_id; device_protocol_data->device_address = usb_conv_info->device_address; wmem_tree_insert32_array(device_to_protocol_table, key, device_protocol_data); } /* bMaxPacketSize0 */ dissect_max_packet_size0(pinfo, tree, tvb, offset, usb_conv_info, TRUE); offset += 1; /* bNumConfigurations */ proto_tree_add_item(tree, hf_usb_bNumConfigurations, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* one reserved byte */ offset += 1; proto_item_set_len(item, offset-old_offset); return offset; } /* 9.6.1 */ static int dissect_usb_device_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { proto_item *item; proto_tree *tree; proto_item *nitem; int old_offset = offset; guint32 protocol; const gchar *description; guint32 vendor_id; guint32 product; guint16 product_id; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "DEVICE DESCRIPTOR"); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* bcdUSB */ proto_tree_add_item(tree, hf_usb_bcdUSB, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; protocol = tvb_get_ntoh24(tvb, offset); description = val_to_str_ext_const(protocol, &usb_protocols_ext, ""); /* bDeviceClass */ proto_tree_add_item(tree, hf_usb_bDeviceClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bDeviceSubClass */ proto_tree_add_item(tree, hf_usb_bDeviceSubClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bDeviceProtocol */ nitem = proto_tree_add_item(tree, hf_usb_bDeviceProtocol, tvb, offset, 1, ENC_LITTLE_ENDIAN); if (*description) proto_item_append_text(nitem, " (%s)", description); offset += 1; /* bMaxPacketSize0 */ dissect_max_packet_size0(pinfo, tree, tvb, offset, usb_conv_info, FALSE); offset += 1; /* if request was only for the first 8 bytes */ /* per 5.5.3 of USB2.0 Spec */ if (8 == usb_conv_info->usb_trans_info->setup.wLength) { proto_item_set_len(item, offset-old_offset); return offset; } /* idVendor */ proto_tree_add_item_ret_uint(tree, hf_usb_idVendor, tvb, offset, 2, ENC_LITTLE_ENDIAN, &vendor_id); usb_conv_info->deviceVendor = (guint16)vendor_id; offset += 2; /* idProduct */ product_id = tvb_get_letohs(tvb, offset); usb_conv_info->deviceProduct = product_id; product = (guint16)vendor_id << 16 | product_id; proto_tree_add_uint_format_value(tree, hf_usb_idProduct, tvb, offset, 2, product_id, "%s (0x%04x)", val_to_str_ext_const(product, &ext_usb_products_vals, "Unknown"), product_id); offset += 2; /* bcdDevice */ usb_conv_info->deviceVersion = tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_usb_bcdDevice, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if (!pinfo->fd->visited) { guint k_bus_id; guint k_device_address; guint k_frame_number; wmem_tree_key_t key[4]; device_product_data_t *device_product_data; device_protocol_data_t *device_protocol_data; k_frame_number = pinfo->num; k_device_address = usb_conv_info->device_address; k_bus_id = usb_conv_info->bus_id; key[0].length = 1; key[0].key = &k_device_address; key[1].length = 1; key[1].key = &k_bus_id; key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; device_product_data = wmem_new(wmem_file_scope(), device_product_data_t); device_product_data->vendor = vendor_id; device_product_data->product = product_id; device_product_data->device = usb_conv_info->deviceVersion; device_product_data->bus_id = usb_conv_info->bus_id; device_product_data->device_address = usb_conv_info->device_address; wmem_tree_insert32_array(device_to_product_table, key, device_product_data); device_protocol_data = wmem_new(wmem_file_scope(), device_protocol_data_t); device_protocol_data->protocol = protocol; device_protocol_data->bus_id = usb_conv_info->bus_id; device_protocol_data->device_address = usb_conv_info->device_address; wmem_tree_insert32_array(device_to_protocol_table, key, device_protocol_data); } /* iManufacturer */ proto_tree_add_item(tree, hf_usb_iManufacturer, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* iProduct */ proto_tree_add_item(tree, hf_usb_iProduct, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* iSerialNumber */ usb_conv_info->iSerialNumber = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_usb_iSerialNumber, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bNumConfigurations */ proto_tree_add_item(tree, hf_usb_bNumConfigurations, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_item_set_len(item, offset-old_offset); return offset; } /* 9.6.7 */ static int dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { proto_item *item; proto_tree *tree; int old_offset = offset; guint8 len; proto_item *len_item; usb_trans_info_t *usb_trans_info; usb_trans_info = usb_conv_info->usb_trans_info; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "STRING DESCRIPTOR"); len = tvb_get_guint8(tvb, offset); /* The USB spec says that the languages / the string are UTF16 and not 0-terminated, i.e. the length field must contain an even number */ if (len & 0x1) { /* bLength */ len_item = proto_tree_add_item(tree, hf_usb_bLength, tvb, offset, 1, ENC_LITTLE_ENDIAN); expert_add_info(pinfo, len_item, &ei_usb_bLength_even); /* bDescriptorType */ proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset+1, 1, ENC_LITTLE_ENDIAN); } else len_item = dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* Report an error, and give up, if the length is < 2 */ if (len < 2) { expert_add_info(pinfo, len_item, &ei_usb_bLength_too_short); return offset; } if (!usb_trans_info->u.get_descriptor.usb_index) { /* list of languanges */ while (offset >= old_offset && len > (offset - old_offset)) { /* wLANGID */ proto_tree_add_item(tree, hf_usb_wLANGID, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=2; } } else { /* UTF-16 string */ /* handle case of host requesting only substring */ guint8 len_str = MIN(len-2, usb_trans_info->setup.wLength -2); proto_tree_add_item(tree, hf_usb_bString, tvb, offset, len_str, ENC_UTF_16 | ENC_LITTLE_ENDIAN); offset += len_str; } proto_item_set_len(item, offset-old_offset); return offset; } /* 9.6.5 */ static int dissect_usb_interface_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { proto_item *item; proto_tree *tree; const char *class_str = NULL; int old_offset = offset; guint8 len; guint8 interface_num; guint8 alt_setting; usb_trans_info_t *usb_trans_info; usb_trans_info = usb_conv_info->usb_trans_info; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "INTERFACE DESCRIPTOR"); len = tvb_get_guint8(tvb, offset); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* bInterfaceNumber */ interface_num = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_usb_bInterfaceNumber, tvb, offset, 1, ENC_LITTLE_ENDIAN); usb_conv_info->interfaceNum = interface_num; offset += 1; /* bAlternateSetting */ alt_setting = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_usb_bAlternateSetting, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bNumEndpoints */ proto_tree_add_item(tree, hf_usb_bNumEndpoints, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bInterfaceClass */ proto_tree_add_item(tree, hf_usb_bInterfaceClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); /* save the class so we can access it later in the endpoint descriptor */ usb_conv_info->interfaceClass = tvb_get_guint8(tvb, offset); class_str = val_to_str_ext(usb_conv_info->interfaceClass, &usb_class_vals_ext, "unknown (0x%X)"); proto_item_append_text(item, " (%u.%u): class %s", interface_num, alt_setting, class_str); if (!pinfo->fd->visited) { usb_alt_setting_t alternate_setting; /* Register conversation for this interface in case CONTROL messages are sent to it */ usb_trans_info->interface_info = get_usb_iface_conv_info(pinfo, interface_num); usb_trans_info->interface_info->bus_id = usb_conv_info->bus_id; usb_trans_info->interface_info->device_address = usb_conv_info->device_address; alternate_setting.altSetting = alt_setting; alternate_setting.interfaceClass = tvb_get_guint8(tvb, offset); alternate_setting.interfaceSubclass = tvb_get_guint8(tvb, offset+1); alternate_setting.interfaceProtocol = tvb_get_guint8(tvb, offset+2); alternate_setting.interfaceNum = interface_num; wmem_array_append_one(usb_trans_info->interface_info->alt_settings, alternate_setting); if (alt_setting == 0) { /* By default let's assume alternate setting 0 will be used */ /* in interface conversations, endpoint has no meaning */ usb_trans_info->interface_info->endpoint = NO_ENDPOINT8; usb_trans_info->interface_info->interfaceClass = alternate_setting.interfaceClass; usb_trans_info->interface_info->interfaceSubclass = alternate_setting.interfaceSubclass; usb_trans_info->interface_info->interfaceProtocol = alternate_setting.interfaceProtocol; usb_trans_info->interface_info->interfaceNum = alternate_setting.interfaceNum; usb_trans_info->interface_info->deviceVendor = usb_conv_info->deviceVendor; usb_trans_info->interface_info->deviceProduct = usb_conv_info->deviceProduct; usb_trans_info->interface_info->deviceVersion = usb_conv_info->deviceVersion; } } offset += 1; /* bInterfaceSubClass */ switch (usb_conv_info->interfaceClass) { case IF_CLASS_AUDIO: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass_audio, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_COMMUNICATIONS: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass_cdc, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_MASS_STORAGE: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass_massstorage, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_HID: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass_hid, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_MISCELLANEOUS: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass_misc, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_APPLICATION_SPECIFIC: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass_app, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; default: proto_tree_add_item(tree, hf_usb_bInterfaceSubClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); } /* save the subclass so we can access it later in class-specific descriptors */ usb_conv_info->interfaceSubclass = tvb_get_guint8(tvb, offset); offset += 1; /* bInterfaceProtocol */ switch (usb_conv_info->interfaceClass) { case IF_CLASS_COMMUNICATIONS: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_cdc, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_MASS_STORAGE: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_massstorage, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_CDC_DATA: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_cdc_data, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case IF_CLASS_APPLICATION_SPECIFIC: switch (usb_conv_info->interfaceSubclass) { case 0x01: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_app_dfu, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case 0x02: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_app_irda, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case 0x03: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_app_usb_test_and_measurement, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; default: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol, tvb, offset, 1, ENC_LITTLE_ENDIAN); } break; case IF_CLASS_HID: if (usb_conv_info->interfaceSubclass == 1) { proto_tree_add_item(tree, hf_usb_bInterfaceProtocol_hid_boot, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; } proto_tree_add_item(tree, hf_usb_bInterfaceProtocol, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; default: proto_tree_add_item(tree, hf_usb_bInterfaceProtocol, tvb, offset, 1, ENC_LITTLE_ENDIAN); } usb_conv_info->interfaceProtocol = tvb_get_guint8(tvb, offset); offset += 1; /* iInterface */ proto_tree_add_item(tree, hf_usb_iInterface, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_item_set_len(item, len); if (offset < old_offset+len) { /* skip unknown records */ offset = old_offset + len; } return offset; } /* 9.6.6 */ const true_false_string tfs_endpoint_direction = { "IN Endpoint", "OUT Endpoint" }; void dissect_usb_endpoint_address(proto_tree *tree, tvbuff_t *tvb, int offset) { proto_item *endpoint_item; proto_tree *endpoint_tree; guint8 endpoint; endpoint_item = proto_tree_add_item(tree, hf_usb_bEndpointAddress, tvb, offset, 1, ENC_LITTLE_ENDIAN); endpoint_tree = proto_item_add_subtree(endpoint_item, ett_configuration_bEndpointAddress); endpoint = tvb_get_guint8(tvb, offset)&0x0f; proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(endpoint_item, " %s", (tvb_get_guint8(tvb, offset)&0x80)?"IN":"OUT"); proto_tree_add_item(endpoint_tree, hf_usb_bEndpointAddress_number, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(endpoint_item, " Endpoint:%d", endpoint); } unsigned int sanitize_usb_max_packet_size(guint8 ep_type, usb_speed_t speed, unsigned int max_packet_size) { unsigned int sanitized = max_packet_size; switch (speed) { case USB_SPEED_LOW: switch (ep_type) { case ENDPOINT_TYPE_CONTROL: /* 8 is the only allowed value */ sanitized = 8; break; case ENDPOINT_TYPE_INTERRUPT: if (max_packet_size > 8) sanitized = 8; break; default: /* Not allowed */ break; } break; case USB_SPEED_FULL: switch (ep_type) { case ENDPOINT_TYPE_CONTROL: case ENDPOINT_TYPE_BULK: /* Allowed values are: 8, 16, 32 and 64 */ if (max_packet_size > 32) sanitized = 64; else if (max_packet_size > 16) sanitized = 32; else if (max_packet_size > 8) sanitized = 16; else sanitized = 8; break; case ENDPOINT_TYPE_INTERRUPT: if (max_packet_size > 64) sanitized = 64; break; case ENDPOINT_TYPE_ISOCHRONOUS: if (max_packet_size > 1023) sanitized = 1023; break; default: break; } break; case USB_SPEED_HIGH: switch (ep_type) { case ENDPOINT_TYPE_CONTROL: /* 64 is the only allowed value */ sanitized = 64; break; case ENDPOINT_TYPE_BULK: /* 512 is the only allowed value */ sanitized = 512; break; case ENDPOINT_TYPE_INTERRUPT: case ENDPOINT_TYPE_ISOCHRONOUS: if (max_packet_size > 1024) sanitized = 1024; break; default: break; } break; case USB_SPEED_UNKNOWN: default: break; } return sanitized; } int dissect_usb_endpoint_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info, guint8 *out_ep_type, usb_speed_t speed) { proto_item *item; proto_tree *tree; proto_item *ep_attrib_item; proto_tree *ep_attrib_tree; proto_item *ep_type_item; proto_item *ep_pktsize_item; proto_tree *ep_pktsize_tree; int old_offset = offset; guint8 endpoint; guint8 ep_type; guint8 len; guint32 max_packet_size; unsigned int sanitized_max_packet_size; usb_trans_info_t *usb_trans_info = NULL; conversation_t *conversation = NULL; if (usb_conv_info) usb_trans_info = usb_conv_info->usb_trans_info; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "ENDPOINT DESCRIPTOR"); len = tvb_get_guint8(tvb, offset); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; endpoint = tvb_get_guint8(tvb, offset)&0x0f; dissect_usb_endpoint_address(tree, tvb, offset); offset += 1; /* Together with class from the interface descriptor we know what kind * of class the device at endpoint is. * Make sure a conversation exists for this endpoint and attach a * usb_conv_into_t structure to it. * * All endpoints for the same interface descriptor share the same * usb_conv_info structure. */ if ((!pinfo->fd->visited) && usb_trans_info && usb_trans_info->interface_info) { if (pinfo->destport == NO_ENDPOINT) { address tmp_addr; usb_address_t *usb_addr = wmem_new0(pinfo->pool, usb_address_t); /* packet is sent from a USB device's endpoint 0 to the host * replace endpoint 0 with the endpoint of this descriptor * and find the corresponding conversation */ usb_addr->bus_id = ((const usb_address_t *)(pinfo->src.data))->bus_id; usb_addr->device = ((const usb_address_t *)(pinfo->src.data))->device; usb_addr->endpoint = GUINT32_TO_LE(endpoint); set_address(&tmp_addr, usb_address_type, USB_ADDR_LEN, (char *)usb_addr); conversation = get_usb_conversation(pinfo, &tmp_addr, &pinfo->dst, usb_addr->endpoint, pinfo->destport); } if (conversation) { usb_trans_info->interface_info->endpoint = endpoint; conversation_add_proto_data(conversation, proto_usb, usb_trans_info->interface_info); } } /* bmAttributes */ ep_type = ENDPOINT_TYPE(tvb_get_guint8(tvb, offset)); if (out_ep_type) { *out_ep_type = ep_type; } ep_attrib_item = proto_tree_add_item(tree, hf_usb_bmAttributes, tvb, offset, 1, ENC_LITTLE_ENDIAN); ep_attrib_tree = proto_item_add_subtree(ep_attrib_item, ett_endpoint_bmAttributes); ep_type_item = proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeTransfer, tvb, offset, 1, ENC_LITTLE_ENDIAN); if (ep_type==USB_EP_ISOCHRONOUS) { proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeSynchonisation, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(ep_attrib_tree, hf_usb_bEndpointAttributeBehaviour, tvb, offset, 1, ENC_LITTLE_ENDIAN); } /* At Low-Speed, only control and interrupt transfers are allowed */ if ((speed == USB_SPEED_LOW) && !((ep_type == USB_EP_CONTROL) || (ep_type == USB_EP_INTERRUPT))) { expert_add_info(pinfo, ep_type_item, &ei_usb_invalid_endpoint_type); } offset += 1; /* wMaxPacketSize */ ep_pktsize_item = proto_tree_add_item(tree, hf_usb_wMaxPacketSize, tvb, offset, 2, ENC_LITTLE_ENDIAN); ep_pktsize_tree = proto_item_add_subtree(ep_pktsize_item, ett_endpoint_wMaxPacketSize); if ((ep_type == ENDPOINT_TYPE_INTERRUPT) || (ep_type == ENDPOINT_TYPE_ISOCHRONOUS)) { proto_tree_add_item(ep_pktsize_tree, hf_usb_wMaxPacketSize_slots, tvb, offset, 2, ENC_LITTLE_ENDIAN); } proto_tree_add_item_ret_uint(ep_pktsize_tree, hf_usb_wMaxPacketSize_size, tvb, offset, 2, ENC_LITTLE_ENDIAN, &max_packet_size); sanitized_max_packet_size = sanitize_usb_max_packet_size(ep_type, speed, max_packet_size); if (sanitized_max_packet_size != max_packet_size) { expert_add_info_format(pinfo, ep_pktsize_item, &ei_usb_invalid_max_packet_size, "%s %s endpoint max packet size cannot be %u, using %d instead.", try_val_to_str(speed, usb_speed_vals), try_val_to_str(ep_type, usb_bmAttributes_transfer_vals), max_packet_size, sanitized_max_packet_size); max_packet_size = sanitized_max_packet_size; } offset+=2; if (conversation) { usb_conv_info_t* endpoint_conv_info = get_usb_conv_info(conversation); guint8 transfer_type; switch(ep_type) { case ENDPOINT_TYPE_CONTROL: transfer_type = URB_CONTROL; break; case ENDPOINT_TYPE_ISOCHRONOUS: transfer_type = URB_ISOCHRONOUS; break; case ENDPOINT_TYPE_BULK: transfer_type = URB_BULK; break; case ENDPOINT_TYPE_INTERRUPT: transfer_type = URB_INTERRUPT; break; default: transfer_type = URB_UNKNOWN; break; } endpoint_conv_info->descriptor_transfer_type = transfer_type; endpoint_conv_info->max_packet_size = max_packet_size; } /* bInterval */ proto_tree_add_item(tree, hf_usb_bInterval, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bRefresh and bSynchAddress are present only in the Audio 1.0 * Endpoint Descriptors, so observe the descriptor size */ if (usb_conv_info && (usb_conv_info->interfaceClass == IF_CLASS_AUDIO) && (len >= 9)) { proto_tree_add_item(tree, hf_usb_audio_bRefresh, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_usb_audio_bSynchAddress, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; } proto_item_set_len(item, len); if (offset < old_offset+len) { /* mark unknown records as undecoded */ proto_tree_add_expert(tree, pinfo, &ei_usb_undecoded, tvb, offset, old_offset + len - offset); offset = old_offset + len; } return offset; } static int dissect_usb_endpoint_companion_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_, guint8 ep_type) { proto_item *item; proto_tree *tree; proto_item *ep_attrib_item; proto_tree *ep_attrib_tree; int old_offset = offset; guint8 len; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "SUPERSPEED ENDPOINT COMPANION DESCRIPTOR"); len = tvb_get_guint8(tvb, offset); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* bMaxBurst */ proto_tree_add_item(tree, hf_usb_bMaxBurst, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bmAttributes */ ep_attrib_item = proto_tree_add_item(tree, hf_usb_bmAttributes, tvb, offset, 1, ENC_LITTLE_ENDIAN); switch (ep_type) { case ENDPOINT_TYPE_CONTROL: break; case ENDPOINT_TYPE_ISOCHRONOUS: ep_attrib_tree = proto_item_add_subtree(ep_attrib_item, ett_endpoint_bmAttributes); proto_tree_add_item(ep_attrib_tree, hf_usb_bSSEndpointAttributeIsoMult, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case ENDPOINT_TYPE_BULK: ep_attrib_tree = proto_item_add_subtree(ep_attrib_item, ett_endpoint_bmAttributes); proto_tree_add_item(ep_attrib_tree, hf_usb_bSSEndpointAttributeBulkMaxStreams, tvb, offset, 1, ENC_LITTLE_ENDIAN); break; case ENDPOINT_TYPE_INTERRUPT: break; default: expert_add_info(pinfo, ep_attrib_item, &ei_usb_ss_ep_companion_before_ep); break; } offset += 1; /* wBytesPerInterval */ proto_tree_add_item(tree, hf_usb_wBytesPerInterval, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_item_set_len(item, len); if (offset < old_offset + len) { /* mark unknown records as undecoded */ proto_tree_add_expert(tree, pinfo, &ei_usb_undecoded, tvb, offset, old_offset + len - offset); offset = old_offset + len; } return offset; } /* ECN */ static int dissect_usb_interface_assn_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { proto_item *item; proto_tree *tree; int old_offset = offset; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "INTERFACE ASSOCIATION DESCRIPTOR"); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* bFirstInterface */ proto_tree_add_item(tree, hf_usb_bFirstInterface, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bInterfaceCount */ proto_tree_add_item(tree, hf_usb_bInterfaceCount, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bFunctionClass */ proto_tree_add_item(tree, hf_usb_bFunctionClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bFunctionSubclass */ proto_tree_add_item(tree, hf_usb_bFunctionSubClass, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bFunctionProtocol */ proto_tree_add_item(tree, hf_usb_bFunctionProtocol, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* iFunction */ proto_tree_add_item(tree, hf_usb_iFunction, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_item_set_len(item, offset-old_offset); return offset; } int dissect_usb_unknown_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { proto_item *item; proto_tree *tree; guint8 bLength; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "UNKNOWN DESCRIPTOR"); bLength = tvb_get_guint8(tvb, offset); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += bLength; proto_item_set_len(item, bLength); return offset; } /* 9.6.3 */ static const true_false_string tfs_mustbeone = { "Must be 1 for USB 1.1 and higher", "FIXME: Is this a USB 1.0 device" }; static const true_false_string tfs_selfpowered = { "This device is SELF-POWERED", "This device is powered from the USB bus" }; static const true_false_string tfs_remotewakeup = { "This device supports REMOTE WAKEUP", "This device does NOT support remote wakeup" }; static int dissect_usb_configuration_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info, usb_speed_t speed) { proto_item *item; proto_tree *tree; int old_offset = offset; guint16 len; proto_item *flags_item; proto_tree *flags_tree; guint8 flags; guint8 last_ep_type = ENDPOINT_TYPE_NOT_SET; proto_item *power_item; guint8 power; gboolean truncation_expected; usb_trans_info_t *usb_trans_info; usb_trans_info = usb_conv_info->usb_trans_info; usb_conv_info->interfaceClass = IF_CLASS_UNKNOWN; usb_conv_info->interfaceSubclass = IF_SUBCLASS_UNKNOWN; usb_conv_info->interfaceProtocol = IF_PROTOCOL_UNKNOWN; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "CONFIGURATION DESCRIPTOR"); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* wTotalLength */ proto_tree_add_item(tree, hf_usb_wTotalLength, tvb, offset, 2, ENC_LITTLE_ENDIAN); len = tvb_get_letohs(tvb, offset); offset+=2; /* bNumInterfaces */ proto_tree_add_item(tree, hf_usb_bNumInterfaces, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bConfigurationValue */ proto_tree_add_item(tree, hf_usb_bConfigurationValue, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* iConfiguration */ proto_tree_add_item(tree, hf_usb_iConfiguration, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* bmAttributes */ flags_item = proto_tree_add_item(tree, hf_usb_configuration_bmAttributes, tvb, offset, 1, ENC_LITTLE_ENDIAN); flags_tree = proto_item_add_subtree(flags_item, ett_configuration_bmAttributes); flags = tvb_get_guint8(tvb, offset); proto_tree_add_item(flags_tree, hf_usb_configuration_legacy10buspowered, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(flags_tree, hf_usb_configuration_selfpowered, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(flags_item, " %sSELF-POWERED", (flags&0x40)?"":"NOT "); proto_tree_add_item(flags_tree, hf_usb_configuration_remotewakeup, tvb, offset, 1, ENC_LITTLE_ENDIAN); proto_item_append_text(flags_item, " %sREMOTE-WAKEUP", (flags&0x20)?"":"NO "); offset += 1; /* bMaxPower */ power_item = proto_tree_add_item(tree, hf_usb_bMaxPower, tvb, offset, 1, ENC_LITTLE_ENDIAN); power = tvb_get_guint8(tvb, offset); proto_item_append_text(power_item, " (%dmA)", power*2); offset += 1; /* initialize interface_info to NULL */ usb_trans_info->interface_info = NULL; truncation_expected = (usb_trans_info->setup.wLength < len); /* decode any additional interface and endpoint descriptors */ while(len>(offset-old_offset)) { guint8 next_type; guint8 next_len = 0; gint remaining_tvb, remaining_len; tvbuff_t *next_tvb = NULL; /* Handle truncated descriptors appropriately */ remaining_tvb = tvb_reported_length_remaining(tvb, offset); if (remaining_tvb > 0) { next_len = tvb_get_guint8(tvb, offset); remaining_len = len - (offset - old_offset); if ((next_len < 3) || (next_len > remaining_len)) { proto_tree_add_expert_format(parent_tree, pinfo, &ei_usb_desc_length_invalid, tvb, offset, 1, "Invalid descriptor length: %u", next_len); item = NULL; break; } } if ((remaining_tvb == 0) || (next_len > remaining_tvb)) { if (truncation_expected) break; } next_type = tvb_get_guint8(tvb, offset+1); switch(next_type) { case USB_DT_INTERFACE: offset = dissect_usb_interface_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info); break; case USB_DT_ENDPOINT: offset = dissect_usb_endpoint_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info, &last_ep_type, speed); break; case USB_DT_INTERFACE_ASSOCIATION: offset = dissect_usb_interface_assn_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info); break; case USB_DT_SUPERSPEED_EP_COMPANION: offset = dissect_usb_endpoint_companion_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info, last_ep_type); break; default: next_tvb = tvb_new_subset_length(tvb, offset, next_len); if (dissector_try_uint_new(usb_descriptor_dissector_table, usb_conv_info->interfaceClass, next_tvb, pinfo, parent_tree, TRUE, usb_conv_info)) { offset += next_len; } else { offset = dissect_usb_unknown_descriptor(pinfo, parent_tree, tvb, offset, usb_conv_info); } break; /* was: return offset; */ } } proto_item_set_len(item, offset-old_offset); return offset; } /* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor */ static int dissect_webusb_platform_descriptor(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { proto_tree_add_item(tree, hf_usb_webusb_bcdVersion, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_webusb_bVendorCode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_usb_webusb_iLandingPage, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; return offset; } /* Microsoft OS 2.0 Descriptors Specification */ static int dissect_msos20_platform_descriptor(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { proto_tree_add_item(tree, hf_usb_msos20_dwWindowsVersion, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_usb_msos20_wMSOSDescriptorSetTotalLength, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_msos20_bMS_VendorCode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_usb_msos20_bAltEnumCode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; return offset; } static struct { e_guid_t uuid; const gchar *text; int (*dissect)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info); } bos_platform_uuids[] = { { {0x3408b638, 0x09a9, 0x47a0, {0x8b, 0xfd, 0xa0, 0x76, 0x88, 0x15, 0xb6, 0x65}}, "WebUSB Platform Capability descriptor", dissect_webusb_platform_descriptor }, { {0xd8dd60df, 0x4589, 0x4cc7, {0x9c, 0xd2, 0x65, 0x9d, 0x9e, 0x64, 0x8a, 0x9f}}, "Microsoft OS 2.0 Platform Capability descriptor", dissect_msos20_platform_descriptor }, }; /* USB 3.2 Specification Table 9-13. Format of a Device Capability Descriptor */ static int dissect_usb_device_capability_descriptor(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { guint8 cap_type; const gchar *cap_text; e_guid_t uuid; unsigned int i; proto_tree_add_item(tree, hf_usb_bDevCapabilityType, tvb, offset, 1, ENC_LITTLE_ENDIAN); cap_type = tvb_get_guint8(tvb, offset); offset += 1; cap_text = try_val_to_str_ext(cap_type, &usb_capability_vals_ext); if (cap_type == BOS_CAP_USB_20_EXTENSION) { /* USB 2.0 ECN Errata for Link Power Management */ static int * const usb20ext_fields[] = { &hf_usb_usb20ext_LPM, &hf_usb_usb20ext_BESL_HIRD, &hf_usb_usb20ext_baseline_BESL_valid, &hf_usb_usb20ext_deep_BESL_valid, &hf_usb_usb20ext_baseline_BESL, &hf_usb_usb20ext_deep_BESL, NULL }; proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_usb_usb20ext_bmAttributes, ett_usb20ext_bmAttributes, usb20ext_fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND); offset += 4; } else if (cap_type == BOS_CAP_PLATFORM) { proto_tree_add_item(tree, hf_usb_bReserved, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; tvb_get_letohguid(tvb, offset, &uuid); proto_tree_add_guid(tree, hf_usb_PlatformCapabilityUUID, tvb, offset, 16, &uuid); offset += 16; for (i = 0; i < array_length(bos_platform_uuids); i++) { if (guid_cmp(&bos_platform_uuids[i].uuid, &uuid) == 0) { offset = bos_platform_uuids[i].dissect(pinfo, tree, tvb, offset, usb_conv_info); cap_text = bos_platform_uuids[i].text; break; } } } if (cap_text) { proto_item_append_text(tree, ": %s", cap_text); } return offset; } /* USB 3.2 Specification 9.6.2 Binary Device Object Store (BOS) */ static int dissect_usb_bos_descriptor(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { proto_item *item; proto_tree *tree; int old_offset = offset; guint16 total_len; usb_trans_info_t *usb_trans_info; usb_trans_info = usb_conv_info->usb_trans_info; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &item, "BOS DESCRIPTOR"); dissect_usb_descriptor_header(tree, tvb, offset, NULL); offset += 2; /* wTotalLength */ proto_tree_add_item(tree, hf_usb_wTotalLength, tvb, offset, 2, ENC_LITTLE_ENDIAN); total_len = tvb_get_letohs(tvb, offset); offset += 2; proto_tree_add_item(tree, hf_usb_bNumDeviceCaps, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; if (offset - old_offset >= usb_trans_info->setup.wLength) { /* Do not report the most common case where host finds out about * wTotalLength by requesting just BOS descriptor as Malformed Packet. * TODO: Generic handling of "host requested too few bytes" (which is * perfectly fine, but complicates dissection) because host is allowed * to request any number of bytes. */ return offset; } /* Dissect capabilities */ while (total_len > (offset - old_offset)) { proto_item *desc_item; int prev_offset = offset; guint8 desc_len, desc_type; tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_descriptor_device, &desc_item, "DEVICE CAPABILITY DESCRIPTOR"); item = proto_tree_add_item(tree, hf_usb_bLength, tvb, offset, 1, ENC_LITTLE_ENDIAN); desc_len = tvb_get_guint8(tvb, offset); offset += 1; if (desc_len < 3) { expert_add_info_format(pinfo, item, &ei_usb_bLength_too_short, "Invalid Length (must be 3 or larger)"); break; } item = proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset, 1, ENC_LITTLE_ENDIAN); desc_type = tvb_get_guint8(tvb, offset); offset += 1; if (desc_type == USB_DT_DEVICE_CAPABILITY) { tvbuff_t *desc_tvb = tvb_new_subset_length(tvb, offset, desc_len - 2); offset += dissect_usb_device_capability_descriptor(pinfo, tree, desc_tvb, 0, usb_conv_info); } else { expert_add_info(pinfo, item, &ei_usb_unexpected_desc_type); /* Already reported unexpected type, do not mark rest as undecoded */ offset = prev_offset + desc_len; } if (offset < prev_offset + desc_len) { proto_tree_add_expert(tree, pinfo, &ei_usb_undecoded, tvb, offset, prev_offset + desc_len - offset); offset = prev_offset + desc_len; } proto_item_set_len(item, offset - prev_offset); } proto_item_set_len(item, offset - old_offset); return offset; } /* 9.4.3 */ static int dissect_usb_setup_get_descriptor_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { usb_trans_info_t *usb_trans_info, trans_info; if (usb_conv_info) usb_trans_info = usb_conv_info->usb_trans_info; else usb_trans_info = &trans_info; /* descriptor index */ proto_tree_add_item(tree, hf_usb_descriptor_index, tvb, offset, 1, ENC_LITTLE_ENDIAN); usb_trans_info->u.get_descriptor.usb_index = tvb_get_guint8(tvb, offset); offset += 1; /* descriptor type */ proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset, 1, ENC_LITTLE_ENDIAN); usb_trans_info->u.get_descriptor.type = tvb_get_guint8(tvb, offset); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_ext(usb_trans_info->u.get_descriptor.type, &std_descriptor_type_vals_ext, "Unknown type %u")); /* language id */ proto_tree_add_item(tree, hf_usb_language_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=2; /* length */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { usb_trans_info_t *usb_trans_info; usb_speed_t speed; usb_trans_info = usb_conv_info->usb_trans_info; speed = usb_conv_info->speed; col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str_ext(usb_trans_info->u.get_descriptor.type, &std_descriptor_type_vals_ext, "Unknown type %u")); switch(usb_trans_info->u.get_descriptor.type) { case USB_DT_INTERFACE: case USB_DT_ENDPOINT: /* an interface or an endpoint descriptor can only be accessed as part of a configuration descriptor */ break; case USB_DT_DEVICE: offset = dissect_usb_device_descriptor(pinfo, tree, tvb, offset, usb_conv_info); break; case USB_DT_OTHER_SPEED_CONFIG: /* USB 2.0 Specification: 9.2.6.6 Speed Dependent Descriptors */ if (speed == USB_SPEED_FULL) speed = USB_SPEED_HIGH; else if (speed == USB_SPEED_HIGH) speed = USB_SPEED_FULL; /* fall-through */ case USB_DT_CONFIG: offset = dissect_usb_configuration_descriptor(pinfo, tree, tvb, offset, usb_conv_info, speed); break; case USB_DT_STRING: offset = dissect_usb_string_descriptor(pinfo, tree, tvb, offset, usb_conv_info); break; case USB_DT_DEVICE_QUALIFIER: offset = dissect_usb_device_qualifier_descriptor(pinfo, tree, tvb, offset, usb_conv_info); break; case USB_DT_BOS: offset = dissect_usb_bos_descriptor(pinfo, tree, tvb, offset, usb_conv_info); break; default: /* XXX dissect the descriptor coming back from the device */ { guint len = tvb_reported_length_remaining(tvb, offset); proto_tree_add_bytes_format(tree, hf_usb_get_descriptor_resp_generic, tvb, offset, len, NULL, "GET DESCRIPTOR Response data (unknown descriptor type %u): %s", usb_trans_info->u.get_descriptor.type, tvb_bytes_to_str(pinfo->pool, tvb, offset, len)); offset = offset + len; } break; } return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / GET INTERFACE */ /* 9.4.4 */ static int dissect_usb_setup_get_interface_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* zero */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* interface */ proto_tree_add_item(tree, hf_usb_wInterface, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* length */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_get_interface_response(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* alternate setting */ proto_tree_add_item(tree, hf_usb_bAlternateSetting, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / GET STATUS */ /* 9.4.5 */ static int dissect_usb_setup_get_status_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* zero */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* zero/interface/endpoint */ if (usb_conv_info) { guint8 recip; recip = USB_RECIPIENT(usb_conv_info->usb_trans_info->setup.requesttype); switch (recip) { case RQT_SETUP_RECIPIENT_INTERFACE: proto_tree_add_item(tree, hf_usb_wInterface, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_ENDPOINT: proto_tree_add_item(tree, hf_usb_wEndpoint, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_DEVICE: case RQT_SETUP_RECIPIENT_OTHER: default: proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; } } else { proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* length */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_get_status_response(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* status */ /* XXX - show bits */ proto_tree_add_item(tree, hf_usb_wStatus, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / SET ADDRESS */ /* 9.4.6 */ static int dissect_usb_setup_set_address_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* device address */ proto_tree_add_item(tree, hf_usb_device_address, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* zero */ proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* zero */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_set_address_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / SET CONFIGURATION */ /* 9.4.7 */ static int dissect_usb_setup_set_configuration_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* configuration value */ proto_tree_add_item(tree, hf_usb_bConfigurationValue, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 2; /* zero */ proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* zero */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_set_configuration_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / SET FEATURE */ /* 9.4.9 */ static int dissect_usb_setup_set_feature_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { guint8 recip; if (usb_conv_info) { recip = USB_RECIPIENT(usb_conv_info->usb_trans_info->setup.requesttype); /* feature selector, zero/interface/endpoint */ switch (recip) { case RQT_SETUP_RECIPIENT_DEVICE: proto_tree_add_item(tree, hf_usb_device_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_INTERFACE: proto_tree_add_item(tree, hf_usb_interface_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_wInterface, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_ENDPOINT: proto_tree_add_item(tree, hf_usb_endpoint_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_wEndpoint, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; case RQT_SETUP_RECIPIENT_OTHER: default: proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; } } else { /* No conversation information, so recipient type is unknown */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* zero */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_set_feature_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / SET INTERFACE */ /* 9.4.10 */ static int dissect_usb_setup_set_interface_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { guint8 alt_setting, interface_num; /* alternate setting */ alt_setting = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_usb_bAlternateSetting, tvb, offset, 2, alt_setting); offset += 2; /* interface */ interface_num = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_usb_wInterface, tvb, offset, 2, interface_num); offset += 2; /* zero */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if (!PINFO_FD_VISITED(pinfo)) { guint i, count; usb_conv_info_t *iface_conv_info = get_usb_iface_conv_info(pinfo, interface_num); /* update the conversation info with the selected alternate setting */ count = wmem_array_get_count(iface_conv_info->alt_settings); for (i = 0; i < count; i++) { usb_alt_setting_t *alternate_setting = (usb_alt_setting_t *)wmem_array_index(iface_conv_info->alt_settings, i); if (alternate_setting->altSetting == alt_setting) { iface_conv_info->interfaceClass = alternate_setting->interfaceClass; iface_conv_info->interfaceSubclass = alternate_setting->interfaceSubclass; iface_conv_info->interfaceProtocol = alternate_setting->interfaceProtocol; iface_conv_info->interfaceNum = alternate_setting->interfaceNum; break; } } } return offset; } static int dissect_usb_setup_set_interface_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { return offset; } /* * These dissectors are used to dissect the setup part and the data * for URB_CONTROL_INPUT / SYNCH FRAME */ /* 9.4.11 */ static int dissect_usb_setup_synch_frame_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { /* zero */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* endpoint */ proto_tree_add_item(tree, hf_usb_wEndpoint, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* two */ proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_usb_setup_synch_frame_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_conv_info_t *usb_conv_info _U_) { /* frame number */ proto_tree_add_item(tree, hf_usb_wFrameNumber, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } /* Dissector used for unknown USB setup request/responses */ static int dissect_usb_setup_generic(packet_info *pinfo _U_, proto_tree *tree , tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info _U_) { proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_index, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_usb_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } typedef int (*usb_setup_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info); typedef struct _usb_setup_dissector_table_t { guint8 request; usb_setup_dissector dissector; } usb_setup_dissector_table_t; static const usb_setup_dissector_table_t setup_request_dissectors[] = { {USB_SETUP_GET_STATUS, dissect_usb_setup_get_status_request}, {USB_SETUP_CLEAR_FEATURE, dissect_usb_setup_clear_feature_request}, {USB_SETUP_SET_FEATURE, dissect_usb_setup_set_feature_request}, {USB_SETUP_SET_ADDRESS, dissect_usb_setup_set_address_request}, {USB_SETUP_GET_DESCRIPTOR, dissect_usb_setup_get_descriptor_request}, {USB_SETUP_SET_CONFIGURATION, dissect_usb_setup_set_configuration_request}, {USB_SETUP_GET_INTERFACE, dissect_usb_setup_get_interface_request}, {USB_SETUP_SET_INTERFACE, dissect_usb_setup_set_interface_request}, {USB_SETUP_SYNCH_FRAME, dissect_usb_setup_synch_frame_request}, {0, NULL} }; static const usb_setup_dissector_table_t setup_response_dissectors[] = { {USB_SETUP_GET_STATUS, dissect_usb_setup_get_status_response}, {USB_SETUP_CLEAR_FEATURE, dissect_usb_setup_clear_feature_response}, {USB_SETUP_SET_FEATURE, dissect_usb_setup_set_feature_response}, {USB_SETUP_SET_ADDRESS, dissect_usb_setup_set_address_response}, {USB_SETUP_GET_DESCRIPTOR, dissect_usb_setup_get_descriptor_response}, {USB_SETUP_GET_CONFIGURATION, dissect_usb_setup_get_configuration_response}, {USB_SETUP_SET_CONFIGURATION, dissect_usb_setup_set_configuration_response}, {USB_SETUP_GET_INTERFACE, dissect_usb_setup_get_interface_response}, {USB_SETUP_SET_INTERFACE, dissect_usb_setup_set_interface_response}, {USB_SETUP_SYNCH_FRAME, dissect_usb_setup_synch_frame_response}, {0, NULL} }; static const value_string setup_request_names_vals[] = { {USB_SETUP_GET_STATUS, "GET STATUS"}, {USB_SETUP_CLEAR_FEATURE, "CLEAR FEATURE"}, {USB_SETUP_SET_FEATURE, "SET FEATURE"}, {USB_SETUP_SET_ADDRESS, "SET ADDRESS"}, {USB_SETUP_GET_DESCRIPTOR, "GET DESCRIPTOR"}, {USB_SETUP_SET_DESCRIPTOR, "SET DESCRIPTOR"}, {USB_SETUP_GET_CONFIGURATION, "GET CONFIGURATION"}, {USB_SETUP_SET_CONFIGURATION, "SET CONFIGURATION"}, {USB_SETUP_GET_INTERFACE, "GET INTERFACE"}, {USB_SETUP_SET_INTERFACE, "SET INTERFACE"}, {USB_SETUP_SYNCH_FRAME, "SYNCH FRAME"}, {USB_SETUP_SET_SEL, "SET SEL"}, {USB_SETUP_SET_ISOCH_DELAY, "SET ISOCH DELAY"}, {0, NULL} }; static value_string_ext setup_request_names_vals_ext = VALUE_STRING_EXT_INIT(setup_request_names_vals); static const true_false_string tfs_bmrequesttype_direction = { "Device-to-host", "Host-to-device" }; static const value_string bmrequesttype_type_vals[] = { {RQT_SETUP_TYPE_STANDARD, "Standard"}, {RQT_SETUP_TYPE_CLASS, "Class"}, {RQT_SETUP_TYPE_VENDOR, "Vendor"}, {0, NULL} }; static const value_string bmrequesttype_recipient_vals[] = { {RQT_SETUP_RECIPIENT_DEVICE, "Device" }, {RQT_SETUP_RECIPIENT_INTERFACE, "Interface" }, {RQT_SETUP_RECIPIENT_ENDPOINT, "Endpoint" }, {RQT_SETUP_RECIPIENT_OTHER, "Other" }, {0, NULL } }; /* Dissector used for standard usb setup requests */ static int dissect_usb_standard_setup_request(packet_info *pinfo, proto_tree *tree , tvbuff_t *tvb, usb_conv_info_t *usb_conv_info, usb_trans_info_t *usb_trans_info) { gint offset = 0; const usb_setup_dissector_table_t *tmp; usb_setup_dissector dissector; proto_tree_add_item(tree, hf_usb_request, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request", val_to_str_ext(usb_trans_info->setup.request, &setup_request_names_vals_ext, "Unknown type %x")); dissector = NULL; for(tmp = setup_request_dissectors;tmp->dissector;tmp++) { if (tmp->request == usb_trans_info->setup.request) { dissector = tmp->dissector; break; } } if (!dissector) { dissector = &dissect_usb_setup_generic; } offset = dissector(pinfo, tree, tvb, offset, usb_conv_info); return offset; } /* Dissector used for standard usb setup responses */ static int dissect_usb_standard_setup_response(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_conv_info_t *usb_conv_info) { const usb_setup_dissector_table_t *tmp; usb_setup_dissector dissector; gint length_remaining; col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response", val_to_str_ext(usb_conv_info->usb_trans_info->setup.request, &setup_request_names_vals_ext, "Unknown type %x")); dissector = NULL; for(tmp = setup_response_dissectors;tmp->dissector;tmp++) { if (tmp->request == usb_conv_info->usb_trans_info->setup.request) { dissector = tmp->dissector; break; } } length_remaining = tvb_reported_length_remaining(tvb, offset); if (length_remaining <= 0) return offset; if (dissector) { offset = dissector(pinfo, tree, tvb, offset, usb_conv_info); } else { proto_tree_add_item(tree, hf_usb_control_response_generic, tvb, offset, length_remaining, ENC_NA); offset += length_remaining; } return offset; } static void usb_tap_queue_packet(packet_info *pinfo, guint8 urb_type, usb_conv_info_t *usb_conv_info) { usb_tap_data_t *tap_data; tap_data = wmem_new(pinfo->pool, usb_tap_data_t); tap_data->urb_type = urb_type; tap_data->transfer_type = (guint8)(usb_conv_info->transfer_type); tap_data->conv_info = usb_conv_info; tap_data->trans_info = usb_conv_info->usb_trans_info; tap_queue_packet(usb_tap, pinfo, tap_data); } static gboolean is_usb_standard_setup_request(usb_trans_info_t *usb_trans_info) { guint8 type, recip; type = USB_TYPE(usb_trans_info->setup.requesttype); recip = USB_RECIPIENT(usb_trans_info->setup.requesttype); if (type != RQT_SETUP_TYPE_STANDARD) return FALSE; /* the USB standards defines the GET_DESCRIPTOR request only as a request to a device if it's not aimed at a device, it's a non-standard request that should be handled by a class-specific dissector */ if (usb_trans_info->setup.request == USB_SETUP_GET_DESCRIPTOR && recip != RQT_SETUP_RECIPIENT_DEVICE) { return FALSE; } return TRUE; } static gint try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pinfo, usb_conv_info_t *usb_conv_info, guint8 urb_type, proto_tree *urb_tree, proto_tree *setup_tree) { int ret; wmem_tree_key_t key[4]; guint32 k_frame_number; guint32 k_device_address; guint32 k_bus_id; usb_conv_info_t *old_conv_info = usb_conv_info; usb_trans_info_t *usb_trans_info; heur_dtbl_entry_t *hdtbl_entry; heur_dissector_list_t heur_subdissector_list = NULL; dissector_table_t usb_dissector_table = NULL; proto_item *sub_item; device_product_data_t *device_product_data; device_protocol_data_t *device_protocol_data; guint8 ctrl_recip; /* if we select the next dissector based on a class, this is the (device or interface) class we're using */ guint32 usb_class; guint8 transfer_type; gboolean use_setup_tree = FALSE; if (!usb_conv_info) { /* * Not enough information to choose the next protocol. * XXX - is there something we can still do here? */ if (tvb_reported_length(next_tvb) > 0) call_data_dissector(next_tvb, pinfo, tree); return tvb_captured_length(next_tvb); } /* try dissect by "usb.device" */ ret = dissector_try_uint_new(device_to_dissector, (guint32)(usb_conv_info->bus_id<<16 | usb_conv_info->device_address), next_tvb, pinfo, tree, TRUE, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); k_frame_number = pinfo->num; k_device_address = usb_conv_info->device_address; k_bus_id = usb_conv_info->bus_id; key[0].length = 1; key[0].key = &k_device_address; key[1].length = 1; key[1].key = &k_bus_id; key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; /* try dissect by "usb.protocol" */ device_protocol_data = (device_protocol_data_t *)wmem_tree_lookup32_array_le(device_to_protocol_table, key); if (device_protocol_data && device_protocol_data->bus_id == usb_conv_info->bus_id && device_protocol_data->device_address == usb_conv_info->device_address) { ret = dissector_try_uint_new(protocol_to_dissector, (guint32)device_protocol_data->protocol, next_tvb, pinfo, tree, TRUE, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); } device_product_data = (device_product_data_t *)wmem_tree_lookup32_array_le(device_to_product_table, key); if (device_product_data && device_product_data->bus_id == usb_conv_info->bus_id && device_product_data->device_address == usb_conv_info->device_address) { ret = dissector_try_uint_new(product_to_dissector, (guint32)(device_product_data->vendor<<16 | device_product_data->product), next_tvb, pinfo, tree, TRUE, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); } transfer_type = usb_conv_info->transfer_type; if (transfer_type == URB_UNKNOWN) transfer_type = usb_conv_info->descriptor_transfer_type; switch(transfer_type) { case URB_BULK: heur_subdissector_list = heur_bulk_subdissector_list; usb_dissector_table = usb_bulk_dissector_table; break; case URB_INTERRUPT: heur_subdissector_list = heur_interrupt_subdissector_list; usb_dissector_table = usb_interrupt_dissector_table; break; case URB_CONTROL: usb_trans_info = usb_conv_info->usb_trans_info; if (!usb_trans_info) break; /* for standard control requests and responses, there's no need to query dissector tables */ if (is_usb_standard_setup_request(usb_trans_info)) break; /* When dissecting requests, and Setup Data tree is created, pass it to next dissector instead of parent. */ if (usb_conv_info->is_request && setup_tree) use_setup_tree = TRUE; ctrl_recip = USB_RECIPIENT(usb_trans_info->setup.requesttype); if (ctrl_recip == RQT_SETUP_RECIPIENT_INTERFACE) { guint8 interface_num = usb_trans_info->setup.wIndex & 0xff; heur_subdissector_list = heur_control_subdissector_list; usb_dissector_table = usb_control_dissector_table; usb_conv_info = get_usb_iface_conv_info(pinfo, interface_num); usb_conv_info->usb_trans_info = usb_trans_info; } else if (ctrl_recip == RQT_SETUP_RECIPIENT_ENDPOINT) { address endpoint_addr; gint endpoint; guint32 src_endpoint, dst_endpoint; conversation_t *conversation; heur_subdissector_list = heur_control_subdissector_list; usb_dissector_table = usb_control_dissector_table; endpoint = usb_trans_info->setup.wIndex & 0x0f; if (usb_conv_info->is_request) { usb_address_t *dst_addr = wmem_new0(pinfo->pool, usb_address_t); dst_addr->bus_id = usb_conv_info->bus_id; dst_addr->device = usb_conv_info->device_address; dst_addr->endpoint = dst_endpoint = GUINT32_TO_LE(endpoint); set_address(&endpoint_addr, usb_address_type, USB_ADDR_LEN, (char *)dst_addr); conversation = get_usb_conversation(pinfo, &pinfo->src, &endpoint_addr, pinfo->srcport, dst_endpoint); } else { usb_address_t *src_addr = wmem_new0(pinfo->pool, usb_address_t); src_addr->bus_id = usb_conv_info->bus_id; src_addr->device = usb_conv_info->device_address; src_addr->endpoint = src_endpoint = GUINT32_TO_LE(endpoint); set_address(&endpoint_addr, usb_address_type, USB_ADDR_LEN, (char *)src_addr); conversation = get_usb_conversation(pinfo, &endpoint_addr, &pinfo->dst, src_endpoint, pinfo->destport); } usb_conv_info = get_usb_conv_info(conversation); usb_conv_info->usb_trans_info = usb_trans_info; } else { /* the recipient is "device" or "other" or "reserved" there's no way for us to determine the interfaceClass we set the usb_dissector_table anyhow as some dissectors register for control messages to IF_CLASS_UNKNOWN (this should be fixed) */ heur_subdissector_list = heur_control_subdissector_list; usb_dissector_table = usb_control_dissector_table; } if (old_conv_info != usb_conv_info) { /* Preserve URB specific information */ usb_conv_info->is_setup = old_conv_info->is_setup; usb_conv_info->is_request = old_conv_info->is_request; usb_conv_info->setup_requesttype = old_conv_info->setup_requesttype; usb_conv_info->speed = old_conv_info->speed; } usb_tap_queue_packet(pinfo, urb_type, usb_conv_info); sub_item = proto_tree_add_uint(urb_tree, hf_usb_bInterfaceClass, next_tvb, 0, 0, usb_conv_info->interfaceClass); proto_item_set_generated(sub_item); break; default: break; } if (try_heuristics && heur_subdissector_list) { ret = dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, use_setup_tree ? setup_tree : tree, &hdtbl_entry, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); } if (usb_dissector_table) { /* we prefer the interface class unless it says we should refer to the device class XXX - use the device class if the interface class is unknown */ if (usb_conv_info->interfaceClass == IF_CLASS_DEVICE) { usb_class = (usb_conv_info->device_protocol>>16) & 0xFF; } else { usb_class = usb_conv_info->interfaceClass; } ret = dissector_try_uint_new(usb_dissector_table, usb_class, next_tvb, pinfo, use_setup_tree ? setup_tree : tree, TRUE, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); /* try protocol specific dissector if there is one */ usb_class = USB_PROTOCOL_KEY(usb_conv_info->interfaceClass, usb_conv_info->interfaceSubclass, usb_conv_info->interfaceProtocol); ret = dissector_try_uint_new(usb_dissector_table, usb_class, next_tvb, pinfo, use_setup_tree ? setup_tree : tree, TRUE, usb_conv_info); if (ret) return tvb_captured_length(next_tvb); } return 0; } static int dissect_usb_setup_response(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 urb_type, usb_conv_info_t *usb_conv_info) { proto_tree *parent; tvbuff_t *next_tvb = NULL; gint length_remaining; parent = proto_tree_get_parent_tree(tree); if (usb_conv_info) { if (usb_conv_info->usb_trans_info && is_usb_standard_setup_request(usb_conv_info->usb_trans_info)) { offset = dissect_usb_standard_setup_response(pinfo, parent, tvb, offset, usb_conv_info); } else { next_tvb = tvb_new_subset_remaining(tvb, offset); offset += try_dissect_next_protocol(parent, next_tvb, pinfo, usb_conv_info, urb_type, tree, NULL); length_remaining = tvb_reported_length_remaining(tvb, offset); if (length_remaining > 0) { proto_tree_add_item(parent, hf_usb_control_response_generic, tvb, offset, length_remaining, ENC_NA); offset += length_remaining; } } } else { /* no matching request available */ length_remaining = tvb_reported_length_remaining(tvb, offset); if (length_remaining > 0) { proto_tree_add_item(parent, hf_usb_control_response_generic, tvb, offset, length_remaining, ENC_NA); offset += length_remaining; } } return offset; } static int dissect_usb_bmrequesttype(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *byte) { guint64 val; static int * const bmRequestType_bits[] = { &hf_usb_bmRequestType_direction, &hf_usb_bmRequestType_type, &hf_usb_bmRequestType_recipient, NULL }; proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree, tvb, offset, hf_usb_bmRequestType, ett_usb_setup_bmrequesttype, bmRequestType_bits, ENC_LITTLE_ENDIAN, BMT_NO_APPEND, &val); *byte = (guint8) val; return ++offset; } int dissect_urb_transfer_flags(tvbuff_t *tvb, int offset, proto_tree* tree, int hf, int endian) { proto_tree_add_bitmask(tree, tvb, offset, hf, ett_transfer_flags, transfer_flags_fields, endian); return 4; } static int dissect_linux_usb_pseudo_header_ext(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) { proto_tree_add_item(tree, hf_usb_urb_interval, tvb, offset, 4, ENC_HOST_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_usb_urb_start_frame, tvb, offset, 4, ENC_HOST_ENDIAN); offset += 4; dissect_urb_transfer_flags(tvb, offset, tree, hf_usb_urb_copy_of_transfer_flags, ENC_HOST_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_usb_iso_numdesc, tvb, offset, 4, ENC_HOST_ENDIAN); offset += 4; return offset; } /* Dissector used for usb setup requests */ static int dissect_usb_setup_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 urb_type, usb_conv_info_t *usb_conv_info, usb_header_t header_type, guint64 usb_id) { gint setup_offset; gint req_type; gint ret; proto_tree *parent, *setup_tree; usb_trans_info_t *usb_trans_info, trans_info; tvbuff_t *next_tvb, *data_tvb = NULL; guint8 bm_request_type; /* we should do the NULL check in all non-static functions */ if (usb_conv_info) usb_trans_info = usb_conv_info->usb_trans_info; else usb_trans_info = &trans_info; parent = proto_tree_get_parent_tree(tree); setup_tree = proto_tree_add_subtree(parent, tvb, offset, 8, ett_usb_setup_hdr, NULL, "Setup Data"); req_type = USB_TYPE(tvb_get_guint8(tvb, offset)); usb_trans_info->setup.requesttype = tvb_get_guint8(tvb, offset); if (usb_conv_info) { usb_conv_info->setup_requesttype = tvb_get_guint8(tvb, offset); if (req_type != RQT_SETUP_TYPE_CLASS) usb_tap_queue_packet(pinfo, urb_type, usb_conv_info); } offset = dissect_usb_bmrequesttype(setup_tree, tvb, offset, &bm_request_type); /* as we're going through the data, we build a next_tvb that contains the the setup packet without the request type and request-specific data all subsequent dissection routines work on this tvb */ setup_offset = offset; usb_trans_info->setup.request = tvb_get_guint8(tvb, offset); offset++; usb_trans_info->setup.wValue = tvb_get_letohs(tvb, offset); offset += 2; usb_trans_info->setup.wIndex = tvb_get_letohs(tvb, offset); offset += 2; usb_trans_info->setup.wLength = tvb_get_letohs(tvb, offset); offset += 2; if (header_type == USB_HEADER_LINUX_64_BYTES) { offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); } else if (header_type == USB_HEADER_USBPCAP) { if ((bm_request_type & 0x80) == 0 && usb_trans_info->setup.wLength > 0 && tvb_reported_length_remaining(tvb, offset) == 0) { /* UPBPcap older than 1.5.0.0 packet, save setup data and do not call subdissector */ if (!PINFO_FD_VISITED(pinfo)) { wmem_tree_key_t key[3]; usbpcap_setup_data_t *setup_data = wmem_new(wmem_file_scope(), usbpcap_setup_data_t); setup_data->usb_id = usb_id; tvb_memcpy(tvb, setup_data->setup_data, setup_offset-1, 8); key[0].length = 2; key[0].key = (guint32 *)&usb_id; key[1].length = 1; key[1].key = &pinfo->num; key[2].length = 0; key[2].key = NULL; wmem_tree_insert32_array(usbpcap_setup_data, key, setup_data); } proto_tree_add_item(setup_tree, hf_usb_request_unknown_class, tvb, setup_offset, 1, ENC_LITTLE_ENDIAN); dissect_usb_setup_generic(pinfo, setup_tree, tvb, setup_offset+1, usb_conv_info); return offset; } } if (tvb_captured_length_remaining(tvb, offset) > 0) { next_tvb = tvb_new_composite(); tvb_composite_append(next_tvb, tvb_new_subset_length(tvb, setup_offset, 7)); data_tvb = tvb_new_subset_remaining(tvb, offset); tvb_composite_append(next_tvb, data_tvb); offset += tvb_captured_length(data_tvb); tvb_composite_finalize(next_tvb); next_tvb = tvb_new_child_real_data(tvb, (const guint8 *) tvb_memdup(pinfo->pool, next_tvb, 0, tvb_captured_length(next_tvb)), tvb_captured_length(next_tvb), tvb_captured_length(next_tvb)); add_new_data_source(pinfo, next_tvb, "USB Control"); } else { next_tvb = tvb_new_subset_length(tvb, setup_offset, 7); } /* at this point, offset contains the number of bytes that we dissected */ if (is_usb_standard_setup_request(usb_trans_info)) { /* there's no point in checking the return value as there's no fallback for standard setup requests */ dissect_usb_standard_setup_request(pinfo, setup_tree, next_tvb, usb_conv_info, usb_trans_info); } else { /* no standard request - pass it on to class-specific dissectors */ ret = try_dissect_next_protocol( parent, next_tvb, pinfo, usb_conv_info, urb_type, tree, setup_tree); if (ret <= 0) { /* no class-specific dissector could handle it, dissect it as generic setup request */ proto_tree_add_item(setup_tree, hf_usb_request_unknown_class, next_tvb, 0, 1, ENC_LITTLE_ENDIAN); dissect_usb_setup_generic(pinfo, setup_tree, next_tvb, 1, usb_conv_info); } /* at this point, non-standard request has been dissectored */ } if (data_tvb) proto_tree_add_item(setup_tree, hf_usb_data_fragment, data_tvb, 0, -1, ENC_NA); return offset; } /* dissect the linux-specific USB pseudo header and fill the conversation struct return the number of dissected bytes */ static gint dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, usb_conv_info_t *usb_conv_info, guint64 *urb_id) { guint8 transfer_type; guint8 endpoint_byte; guint8 transfer_type_and_direction; guint8 urb_type; guint32 flag; guint32 bus_id; *urb_id = tvb_get_guint64(tvb, 0, ENC_HOST_ENDIAN); proto_tree_add_uint64(tree, hf_usb_urb_id, tvb, 0, 8, *urb_id); /* show the urb type of this URB as string and as a character */ urb_type = tvb_get_guint8(tvb, 8); usb_conv_info->is_request = (urb_type==URB_SUBMIT); proto_tree_add_uint(tree, hf_usb_linux_urb_type, tvb, 8, 1, urb_type); proto_tree_add_item(tree, hf_usb_linux_transfer_type, tvb, 9, 1, ENC_LITTLE_ENDIAN); transfer_type = tvb_get_guint8(tvb, 9); usb_conv_info->transfer_type = transfer_type; endpoint_byte = tvb_get_guint8(tvb, 10); /* direction bit | endpoint */ usb_conv_info->endpoint = endpoint_byte & 0x7F; if (endpoint_byte & URB_TRANSFER_IN) usb_conv_info->direction = P2P_DIR_RECV; else usb_conv_info->direction = P2P_DIR_SENT; transfer_type_and_direction = (transfer_type & 0x7F) | (endpoint_byte & 0x80); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(transfer_type_and_direction, usb_transfer_type_and_direction_vals, "Unknown type %x")); proto_tree_add_bitmask(tree, tvb, 10, hf_usb_endpoint_address, ett_usb_endpoint, usb_endpoint_fields, ENC_NA); proto_tree_add_item(tree, hf_usb_device_address, tvb, 11, 1, ENC_LITTLE_ENDIAN); usb_conv_info->device_address = (guint16)tvb_get_guint8(tvb, 11); proto_tree_add_item_ret_uint(tree, hf_usb_bus_id, tvb, 12, 2, ENC_HOST_ENDIAN, &bus_id); usb_conv_info->bus_id = (guint16) bus_id; /* Right after the pseudo header we always have * sizeof(struct usb_device_setup_hdr) bytes. The content of these * bytes only have meaning in case setup_flag == 0. */ proto_tree_add_item_ret_uint(tree, hf_usb_setup_flag, tvb, 14, 1, ENC_NA, &flag); if (flag == 0) { usb_conv_info->is_setup = TRUE; if (usb_conv_info->transfer_type!=URB_CONTROL) proto_tree_add_expert(tree, pinfo, &ei_usb_invalid_setup, tvb, 14, 1); } else { usb_conv_info->is_setup = FALSE; } proto_tree_add_item(tree, hf_usb_data_flag, tvb, 15, 1, ENC_NA); proto_tree_add_item(tree, hf_usb_urb_ts_sec, tvb, 16, 8, ENC_HOST_ENDIAN); proto_tree_add_item(tree, hf_usb_urb_ts_usec, tvb, 24, 4, ENC_HOST_ENDIAN); proto_tree_add_item(tree, hf_usb_urb_status, tvb, 28, 4, ENC_HOST_ENDIAN); proto_tree_add_item(tree, hf_usb_urb_len, tvb, 32, 4, ENC_HOST_ENDIAN); proto_tree_add_item(tree, hf_usb_urb_data_len, tvb, 36, 4, ENC_HOST_ENDIAN); return 40; } /* dissect the usbpcap_buffer_packet_header and fill the conversation struct this function does not handle the transfer-specific headers return the number of bytes processed */ static gint dissect_usbpcap_buffer_packet_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, usb_conv_info_t *usb_conv_info, guint32 *win32_data_len, guint64 *irp_id) { proto_item *item; guint32 function_code; guint8 transfer_type; guint8 endpoint_byte; guint8 transfer_type_and_direction; guint8 tmp_val8; proto_tree_add_item(tree, hf_usb_win32_header_len, tvb, 0, 2, ENC_LITTLE_ENDIAN); *irp_id = tvb_get_guint64(tvb, 2, ENC_LITTLE_ENDIAN); proto_tree_add_uint64(tree, hf_usb_irp_id, tvb, 2, 8, *irp_id); proto_tree_add_item(tree, hf_usb_usbd_status, tvb, 10, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item_ret_uint(tree, hf_usb_function, tvb, 14, 2, ENC_LITTLE_ENDIAN, &function_code); proto_tree_add_bitmask(tree, tvb, 16, hf_usb_info, ett_usb_usbpcap_info, usb_usbpcap_info_fields, ENC_LITTLE_ENDIAN); tmp_val8 = tvb_get_guint8(tvb, 16); /* TODO: Handle errors */ if (tmp_val8 & 0x01) { usb_conv_info->is_request = FALSE; } else { usb_conv_info->is_request = TRUE; } proto_tree_add_item(tree, hf_usb_bus_id, tvb, 17, 2, ENC_LITTLE_ENDIAN); usb_conv_info->bus_id = tvb_get_letohs(tvb, 17); proto_tree_add_item(tree, hf_usb_win32_device_address, tvb, 19, 2, ENC_LITTLE_ENDIAN); usb_conv_info->device_address = tvb_get_letohs(tvb, 19); endpoint_byte = tvb_get_guint8(tvb, 21); usb_conv_info->direction = endpoint_byte&URB_TRANSFER_IN ? P2P_DIR_RECV : P2P_DIR_SENT; usb_conv_info->endpoint = endpoint_byte&0x7F; proto_tree_add_bitmask(tree, tvb, 21, hf_usb_endpoint_address, ett_usb_endpoint, usb_endpoint_fields, ENC_LITTLE_ENDIAN); transfer_type = tvb_get_guint8(tvb, 22); usb_conv_info->transfer_type = transfer_type; item = proto_tree_add_item(tree, hf_usb_win32_transfer_type, tvb, 22, 1, ENC_LITTLE_ENDIAN); if (transfer_type == URB_UNKNOWN) { expert_add_info(pinfo, item, &ei_usb_usbpcap_unknown_urb); } /* Workaround bug in captures created with USBPcap earlier than 1.3.0.0 */ if ((endpoint_byte == 0x00) && (transfer_type == URB_CONTROL) && (tvb_get_guint8(tvb, 27) == USB_CONTROL_STAGE_DATA)) { usb_conv_info->is_request = TRUE; } if (transfer_type != USBPCAP_URB_IRP_INFO) { transfer_type_and_direction = (transfer_type & 0x7F) | (endpoint_byte & 0x80); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(transfer_type_and_direction, usb_transfer_type_and_direction_vals, "Unknown type %x")); } else { col_append_str(pinfo->cinfo, COL_INFO, val_to_str_ext(function_code, &win32_urb_function_vals_ext, "Unknown function %x")); } *win32_data_len = tvb_get_letohl(tvb, 23); proto_tree_add_item(tree, hf_usb_win32_data_len, tvb, 23, 4, ENC_LITTLE_ENDIAN); /* by default, we assume it's no setup packet the correct values will be set when we parse the control header */ usb_conv_info->is_setup = FALSE; usb_conv_info->setup_requesttype = 0; /* we don't handle the transfer-specific headers here */ return 27; } static gint dissect_darwin_buffer_packet_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, usb_conv_info_t *usb_conv_info, guint64 *id) { guint8 transfer_type; guint8 request_type; guint8 endpoint_byte; guint8 transfer_type_and_direction; guint8 header_length; proto_tree_add_item(tree, hf_usb_darwin_bcd_version, tvb, 0, 2, ENC_LITTLE_ENDIAN); header_length = tvb_get_guint8(tvb, 2); proto_tree_add_item(tree, hf_usb_darwin_header_len, tvb, 2, 1, ENC_LITTLE_ENDIAN); request_type = tvb_get_guint8(tvb, 3); usb_conv_info->is_request = (request_type == DARWIN_IO_SUBMIT); proto_tree_add_uint(tree, hf_usb_darwin_request_type, tvb, 3, 1, request_type); proto_tree_add_item(tree, hf_usb_darwin_io_len, tvb, 4, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_darwin_io_status, tvb, 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_darwin_iso_num_packets, tvb, 12, 4, ENC_LITTLE_ENDIAN); *id = tvb_get_guint64(tvb, 16, ENC_LITTLE_ENDIAN); proto_tree_add_uint64(tree, hf_usb_darwin_io_id, tvb, 16, 8, *id); proto_tree_add_item(tree, hf_usb_darwin_device_location, tvb, 24, 4, ENC_LITTLE_ENDIAN); usb_conv_info->bus_id = tvb_get_letohl(tvb, 24) >> 24; proto_tree_add_item(tree, hf_usb_darwin_speed, tvb, 28, 1, ENC_LITTLE_ENDIAN); usb_conv_info->device_address = (guint16)tvb_get_guint8(tvb, 29); proto_tree_add_uint(tree, hf_usb_darwin_device_address, tvb, 29, 1, usb_conv_info->device_address); endpoint_byte = tvb_get_guint8(tvb, 30); /* direction bit | endpoint */ usb_conv_info->endpoint = endpoint_byte & 0x7F; if (endpoint_byte & URB_TRANSFER_IN) { usb_conv_info->direction = P2P_DIR_RECV; } else { usb_conv_info->direction = P2P_DIR_SENT; } proto_tree_add_uint(tree, hf_usb_darwin_endpoint_address, tvb, 30, 1, endpoint_byte); proto_tree_add_bitmask(tree, tvb, 30, hf_usb_endpoint_number, ett_usb_endpoint, usb_endpoint_fields, ENC_LITTLE_ENDIAN); transfer_type = MIN(tvb_get_guint8(tvb, 31), G_N_ELEMENTS(darwin_endpoint_to_linux) - 1); usb_conv_info->transfer_type = darwin_endpoint_to_linux[transfer_type]; proto_tree_add_uint(tree, hf_usb_darwin_endpoint_type, tvb, 31, 1, transfer_type); transfer_type_and_direction = (darwin_endpoint_to_linux[transfer_type] & 0x7F) | (endpoint_byte & 0x80); col_append_str(pinfo->cinfo, COL_INFO, val_to_str(transfer_type_and_direction, usb_transfer_type_and_direction_vals, "Unknown type %x")); col_append_str(pinfo->cinfo, COL_INFO, usb_conv_info->is_request == TRUE ? " (submitted)" : " (completed)"); usb_conv_info->is_setup = FALSE; if ((usb_conv_info->is_request == TRUE) && (usb_conv_info->transfer_type == URB_CONTROL)) { usb_conv_info->is_setup = TRUE; } usb_conv_info->setup_requesttype = 0; /* we don't handle the transfer-specific headers here */ return header_length; } /* Set the usb_address_t fields based on the direction of the urb */ static void usb_set_addr(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, guint16 bus_id, guint16 device_address, int endpoint, gboolean req) { proto_item *sub_item; usb_address_t *src_addr = wmem_new0(pinfo->pool, usb_address_t), *dst_addr = wmem_new0(pinfo->pool, usb_address_t); guint8 *str_src_addr; guint8 *str_dst_addr; if (req) { /* request */ src_addr->device = 0xffffffff; src_addr->endpoint = NO_ENDPOINT; dst_addr->device = GUINT16_TO_LE(device_address); dst_addr->endpoint = GUINT32_TO_LE(endpoint); } else { /* response */ src_addr->device = GUINT16_TO_LE(device_address); src_addr->endpoint = GUINT32_TO_LE(endpoint); dst_addr->device = 0xffffffff; dst_addr->endpoint = NO_ENDPOINT; } src_addr->bus_id = GUINT16_TO_LE(bus_id); dst_addr->bus_id = GUINT16_TO_LE(bus_id); set_address(&pinfo->net_src, usb_address_type, USB_ADDR_LEN, (char *)src_addr); copy_address_shallow(&pinfo->src, &pinfo->net_src); set_address(&pinfo->net_dst, usb_address_type, USB_ADDR_LEN, (char *)dst_addr); copy_address_shallow(&pinfo->dst, &pinfo->net_dst); pinfo->ptype = PT_USB; pinfo->srcport = src_addr->endpoint; pinfo->destport = dst_addr->endpoint; /* sent/received is from the perspective of the USB host */ pinfo->p2p_dir = req ? P2P_DIR_SENT : P2P_DIR_RECV; str_src_addr = address_to_str(pinfo->pool, &pinfo->src); str_dst_addr = address_to_str(pinfo->pool, &pinfo->dst); sub_item = proto_tree_add_string(tree, hf_usb_src, tvb, 0, 0, str_src_addr); proto_item_set_generated(sub_item); sub_item = proto_tree_add_string(tree, hf_usb_addr, tvb, 0, 0, str_src_addr); proto_item_set_hidden(sub_item); sub_item = proto_tree_add_string(tree, hf_usb_dst, tvb, 0, 0, str_dst_addr); proto_item_set_generated(sub_item); sub_item = proto_tree_add_string(tree, hf_usb_addr, tvb, 0, 0, str_dst_addr); proto_item_set_hidden(sub_item); } /* Gets the transfer info for a given packet * Generates transfer info if none exists yet * Also adds request/response info to the tree for the given packet */ static usb_trans_info_t *usb_get_trans_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, usb_header_t header_type, usb_conv_info_t *usb_conv_info, guint64 usb_id) { usb_trans_info_t *usb_trans_info; proto_item *ti; nstime_t t, deltat; wmem_tree_key_t key[3]; /* request/response matching so we can keep track of transaction specific * data. */ key[0].length = 2; key[0].key = (guint32 *)&usb_id; key[1].length = 1; key[1].key = &pinfo->num; key[2].length = 0; key[2].key = NULL; if (usb_conv_info->is_request) { /* this is a request */ usb_trans_info = (usb_trans_info_t *)wmem_tree_lookup32_array(usb_conv_info->transactions, key); if (!usb_trans_info) { usb_trans_info = wmem_new0(wmem_file_scope(), usb_trans_info_t); usb_trans_info->request_in = pinfo->num; usb_trans_info->req_time = pinfo->abs_ts; usb_trans_info->header_type = header_type; usb_trans_info->usb_id = usb_id; wmem_tree_insert32_array(usb_conv_info->transactions, key, usb_trans_info); } if (usb_trans_info->response_in) { ti = proto_tree_add_uint(tree, hf_usb_response_in, tvb, 0, 0, usb_trans_info->response_in); proto_item_set_generated(ti); } } else { /* this is a response */ if (pinfo->fd->visited) { usb_trans_info = (usb_trans_info_t *)wmem_tree_lookup32_array(usb_conv_info->transactions, key); } else { usb_trans_info = (usb_trans_info_t *)wmem_tree_lookup32_array_le(usb_conv_info->transactions, key); if (usb_trans_info) { if (usb_trans_info->usb_id == usb_id) { if (usb_trans_info->response_in == 0) { /* USBPcap generates 2 frames for response; store the first one */ usb_trans_info->response_in = pinfo->num; } wmem_tree_insert32_array(usb_conv_info->transactions, key, usb_trans_info); } else { usb_trans_info = NULL; } } } if (usb_trans_info && usb_trans_info->request_in) { ti = proto_tree_add_uint(tree, hf_usb_request_in, tvb, 0, 0, usb_trans_info->request_in); proto_item_set_generated(ti); t = pinfo->abs_ts; nstime_delta(&deltat, &t, &usb_trans_info->req_time); ti = proto_tree_add_time(tree, hf_usb_time, tvb, 0, 0, &deltat); proto_item_set_generated(ti); } } return usb_trans_info; } /* dissect a group of isochronous packets inside an usb packet in usbpcap format */ #define MAX_ISO_PACKETS 100000 // Arbitrary static gint dissect_usbpcap_iso_packets(packet_info *pinfo _U_, proto_tree *urb_tree, guint8 urb_type, tvbuff_t *tvb, gint offset, guint32 win32_data_len, usb_conv_info_t *usb_conv_info) { guint32 i; guint32 num_packets; int data_start_offset; proto_item *num_packets_ti, *urb_tree_ti; proto_tree_add_item(urb_tree, hf_usb_win32_iso_start_frame, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; num_packets = tvb_get_letohl(tvb, offset); num_packets_ti = proto_tree_add_item(urb_tree, hf_usb_win32_iso_num_packets, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(urb_tree, hf_usb_win32_iso_error_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (num_packets > MAX_ISO_PACKETS) { expert_add_info_format(pinfo, num_packets_ti, &ei_usb_bad_length, "Too many isochronous transfer packets (%u)", num_packets); return tvb_captured_length(tvb); } data_start_offset = offset + 12 * num_packets; urb_tree_ti = proto_tree_get_parent(urb_tree); proto_item_set_len(urb_tree_ti, data_start_offset); for (i = 0; i < num_packets; i++) { guint32 this_offset; guint32 next_offset; guint32 iso_len; proto_item *iso_packet_ti, *ti; proto_tree *iso_packet_tree; iso_packet_ti = proto_tree_add_protocol_format( proto_tree_get_root(urb_tree), proto_usb, tvb, offset, 12, "USB isochronous packet"); iso_packet_tree = proto_item_add_subtree(iso_packet_ti, ett_usb_win32_iso_packet); this_offset = tvb_get_letohl(tvb, offset); if (num_packets - i == 1) { /* this is the last packet */ next_offset = win32_data_len; } else { /* there is next packet */ next_offset = tvb_get_letohl(tvb, offset + 12); } if (next_offset > this_offset) { iso_len = next_offset - this_offset; } else { iso_len = 0; } /* If this packet does not contain isochrounous data, do not try to display it */ if (!((usb_conv_info->is_request && usb_conv_info->direction==P2P_DIR_SENT) || (!usb_conv_info->is_request && usb_conv_info->direction==P2P_DIR_RECV))) { iso_len = 0; } proto_tree_add_item(iso_packet_tree, hf_usb_win32_iso_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; ti = proto_tree_add_item(iso_packet_tree, hf_usb_win32_iso_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (usb_conv_info->direction==P2P_DIR_SENT) { /* Isochronous OUT transfer */ proto_item_append_text(ti, " (not used)"); } else { /* Isochronous IN transfer. * Length field is being set by host controller. */ if (usb_conv_info->is_request) { /* Length was not yet set */ proto_item_append_text(ti, " (irrelevant)"); } else { /* Length was set and (should be) valid */ proto_item_append_text(ti, " (relevant)"); iso_len = tvb_get_letohl(tvb, offset); } } offset += 4; ti = proto_tree_add_item(iso_packet_tree, hf_usb_win32_iso_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (urb_type == URB_SUBMIT) { proto_item_append_text(ti, " (irrelevant)"); } else { proto_item_append_text(ti, " (relevant)"); } offset += 4; if (iso_len && data_start_offset + this_offset + iso_len <= tvb_captured_length(tvb)) { proto_tree_add_item(iso_packet_tree, hf_usb_iso_data, tvb, (gint)(data_start_offset + this_offset), (gint)iso_len, ENC_NA); proto_tree_set_appendix(iso_packet_tree, tvb, (gint)(data_start_offset + this_offset), (gint)iso_len); } } if ((usb_conv_info->is_request && usb_conv_info->direction==P2P_DIR_SENT) || (!usb_conv_info->is_request && usb_conv_info->direction==P2P_DIR_RECV)) { /* We have dissected all the isochronous data */ offset += win32_data_len; } return offset; } static gint dissect_linux_usb_iso_transfer(packet_info *pinfo _U_, proto_tree *urb_tree, usb_header_t header_type, tvbuff_t *tvb, gint offset, usb_conv_info_t *usb_conv_info) { guint32 iso_numdesc = 0; proto_item *tii; guint32 i; guint data_base; guint32 iso_status; guint32 iso_off = 0; guint32 iso_len = 0; tii = proto_tree_add_uint(urb_tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->interfaceClass); proto_item_set_generated(tii); /* All fields which belong to Linux usbmon headers are in host-endian * byte order. The fields coming from the USB communication are in little * endian format (see usb_20.pdf, chapter 8.1 Byte/Bit ordering). * * When a capture file is transferred to a host with different endianness * than packet was captured then the necessary swapping happens in * wiretap/pcap-common.c, pcap_byteswap_linux_usb_pseudoheader(). */ /* iso urbs on linux can't possibly contain a setup packet see mon_bin_event() in the linux kernel */ proto_tree_add_item(urb_tree, hf_usb_iso_error_count, tvb, offset, 4, ENC_HOST_ENDIAN); offset += 4; proto_tree_add_item_ret_uint(urb_tree, hf_usb_iso_numdesc, tvb, offset, 4, ENC_HOST_ENDIAN, &iso_numdesc); offset += 4; if (header_type == USB_HEADER_LINUX_64_BYTES) { offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, urb_tree); } data_base = offset + iso_numdesc*16; for (i = 0; ip2p_dir==P2P_DIR_SENT || !iso_status) && iso_len && data_base + iso_off + iso_len <= tvb_captured_length(tvb)) { proto_tree_add_item(iso_desc_tree, hf_usb_iso_data, tvb, data_base + iso_off, iso_len, ENC_NA); proto_tree_set_appendix(iso_desc_tree, tvb, (gint)(data_base+iso_off), (gint)iso_len); } proto_tree_add_item(iso_desc_tree, hf_usb_iso_pad, tvb, offset, 4, ENC_HOST_ENDIAN); offset += 4; } /* we jump to the end of the last iso data chunk this assumes that the iso data starts immediately after the iso descriptors we have to use the offsets from the last iso descriptor, we can't keep track of the offset ourselves as there may be gaps between data packets in the transfer buffer */ return data_base+iso_off+iso_len; } static gint dissect_usbip_iso_transfer(packet_info *pinfo _U_, proto_tree *urb_tree, tvbuff_t *tvb, gint offset, guint32 iso_numdesc, guint32 desc_offset, usb_conv_info_t *usb_conv_info) { proto_item *tii; guint32 i; guint data_base; guint32 iso_off = 0; guint32 iso_len = 0; tii = proto_tree_add_uint(urb_tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->interfaceClass); proto_item_set_generated(tii); /* All fields which belong to usbip are in big-endian byte order. * unlike the linux kernel, the usb isoc descriptor is appended at * the end of the isoc data. We have to reassemble the pdus and jump * to the end (actual_length) and the remaining data is the isoc * descriptor. */ data_base = offset; for (i = 0; i 0) proto_item_append_text(iso_desc_ti, " (%u bytes)", iso_len); /* Show the ISO data if we captured them and either the status is OK or the packet is sent from host to device. The Linux kernel sets the status field in outgoing isochronous URBs to -EXDEV and fills the data part with valid data. */ if ((pinfo->p2p_dir==P2P_DIR_SENT || !iso_status) && iso_len && data_base + iso_off + iso_len <= tvb_reported_length(tvb)) { proto_tree_add_item(iso_desc_tree, hf_usb_iso_data, tvb, (guint) data_base + iso_off, iso_len, ENC_NA); proto_tree_set_appendix(iso_desc_tree, tvb, (guint) data_base + iso_off, (gint)iso_len); } } return desc_offset; } static gint dissect_darwin_usb_iso_transfer(packet_info *pinfo _U_, proto_tree *tree, usb_header_t header_type _U_, guint8 urb_type _U_, tvbuff_t *tvb, gint32 offset, usb_conv_info_t *usb_conv_info) { guint32 frame_length; guint32 frame_header_length; guint32 status; guint32 iso_tree_start; guint32 i; guint32 iso_numdesc; guint32 len; proto_item *tii; len = (gint32)tvb_captured_length(tvb); len -= offset; tii = proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, offset, 0, usb_conv_info->interfaceClass); proto_item_set_generated(tii); status = tvb_get_guint32(tvb, 8, ENC_LITTLE_ENDIAN); iso_numdesc = tvb_get_guint32(tvb, 12, ENC_LITTLE_ENDIAN); iso_tree_start = offset; for (i = 0; (i < iso_numdesc) && (len > 8 /* header len + frame len */); i++) { proto_item *iso_desc_ti; proto_tree *iso_desc_tree; /* Fetch ISO descriptor fields stored in little-endian byte order. */ frame_header_length = tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN); frame_length = tvb_get_guint32(tvb, offset + 4, ENC_LITTLE_ENDIAN); if ((len < frame_header_length) || (frame_header_length < 20)) { break; } iso_desc_ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, 20, "Frame %u", i); iso_desc_tree = proto_item_add_subtree(iso_desc_ti, ett_usb_isodesc); proto_tree_add_item(iso_desc_tree, hf_usb_darwin_iso_frame_number, tvb, offset + 12, 8, ENC_LITTLE_ENDIAN); proto_tree_add_item(iso_desc_tree, hf_usb_iso_len, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN); if (usb_conv_info->is_request == FALSE) { proto_tree_add_item(iso_desc_tree, hf_usb_darwin_iso_timestamp, tvb, offset + 20, 8, ENC_LITTLE_ENDIAN); proto_tree_add_item_ret_uint(iso_desc_tree, hf_usb_darwin_iso_status, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN, &status); proto_item_append_text(iso_desc_ti, " [%s]", val_to_str_ext(status, &usb_darwin_status_vals_ext, "Error %d")); /* Data */ if (frame_length > len) { frame_length = len; } proto_tree_add_item(iso_desc_tree, hf_usb_iso_data, tvb, offset + frame_header_length, frame_length, ENC_NA); proto_tree_set_appendix(iso_desc_tree, tvb, (gint)iso_tree_start, (gint)(offset - iso_tree_start)); len -= frame_length; offset += frame_length; } /* Padding to align the next header */ offset += frame_header_length; offset = WS_ROUNDUP_4(offset); iso_tree_start = offset; len -= frame_header_length; } return offset; } static gint dissect_usb_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, proto_tree *tree, usb_conv_info_t *usb_conv_info, guint8 urb_type, gint offset, guint16 device_address) { wmem_tree_key_t key[4]; guint32 k_frame_number; guint32 k_device_address; guint32 k_bus_id; device_product_data_t *device_product_data = NULL; device_protocol_data_t *device_protocol_data = NULL; tvbuff_t *next_tvb = NULL; k_frame_number = pinfo->num; k_device_address = device_address; k_bus_id = usb_conv_info->bus_id; key[0].length = 1; key[0].key = &k_device_address; key[1].length = 1; key[1].key = &k_bus_id; key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; device_product_data = (device_product_data_t *) wmem_tree_lookup32_array_le(device_to_product_table, key); if (device_product_data && device_product_data->bus_id == usb_conv_info->bus_id && device_product_data->device_address == device_address) { p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_VENDOR_ID, GUINT_TO_POINTER((guint)device_product_data->vendor)); p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_PRODUCT_ID, GUINT_TO_POINTER((guint)device_product_data->product)); usb_conv_info->deviceVendor = device_product_data->vendor; usb_conv_info->deviceProduct = device_product_data->product; usb_conv_info->deviceVersion = device_product_data->device; } device_protocol_data = (device_protocol_data_t *) wmem_tree_lookup32_array_le(device_to_protocol_table, key); if (device_protocol_data && device_protocol_data->bus_id == usb_conv_info->bus_id && device_protocol_data->device_address == device_address) { p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_CLASS, GUINT_TO_POINTER(device_protocol_data->protocol >> 16)); p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_SUBCLASS, GUINT_TO_POINTER((device_protocol_data->protocol >> 8) & 0xFF)); p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_PROTOCOL, GUINT_TO_POINTER(device_protocol_data->protocol & 0xFF)); usb_conv_info->device_protocol = device_protocol_data->protocol; } p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_BUS_ID, GUINT_TO_POINTER((guint)usb_conv_info->bus_id)); p_add_proto_data(pinfo->pool, pinfo, proto_usb, USB_DEVICE_ADDRESS, GUINT_TO_POINTER((guint)device_address)); if (tvb_captured_length_remaining(tvb, offset) > 0) { next_tvb = tvb_new_subset_remaining(tvb, offset); offset += try_dissect_next_protocol(parent, next_tvb, pinfo, usb_conv_info, urb_type, tree, NULL); } if (tvb_captured_length_remaining(tvb, offset) > 0) { /* There is still leftover capture data to add (padding?) */ proto_tree_add_item(parent, hf_usb_capdata, tvb, offset, -1, ENC_NA); } return offset; } static int dissect_freebsd_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, void *data _U_) { int offset = 0; proto_item *ti; proto_tree *tree = NULL, *frame_tree = NULL; guint32 nframes; guint32 i; col_set_str(pinfo->cinfo, COL_PROTOCOL, "USB"); /* add usb hdr*/ if (parent) { ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, 128, "USB URB"); tree = proto_item_add_subtree(ti, ett_usb_hdr); } proto_tree_add_item(tree, hf_usb_totlen, tvb, 0, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_busunit, tvb, 4, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_address, tvb, 8, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_mode, tvb, 9, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_freebsd_urb_type, tvb, 10, 1, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_freebsd_transfer_type, tvb, 11, 1, ENC_LITTLE_ENDIAN); proto_tree_add_bitmask(tree, tvb, 12, hf_usb_xferflags, ett_usb_xferflags, usb_xferflags_fields, ENC_LITTLE_ENDIAN); proto_tree_add_bitmask(tree, tvb, 16, hf_usb_xferstatus, ett_usb_xferstatus, usb_xferstatus_fields, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_error, tvb, 20, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_interval, tvb, 24, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item_ret_uint(tree, hf_usb_nframes, tvb, 28, 4, ENC_LITTLE_ENDIAN, &nframes); proto_tree_add_item(tree, hf_usb_packet_size, tvb, 32, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_usb_packet_count, tvb, 36, 4, ENC_LITTLE_ENDIAN); proto_tree_add_bitmask(tree, tvb, 40, hf_usb_endpoint_address, ett_usb_endpoint, usb_endpoint_fields, ENC_NA); proto_tree_add_item(tree, hf_usb_speed, tvb, 44, 1, ENC_LITTLE_ENDIAN); offset += 128; for (i = 0; i < nframes; i++) { guint32 framelen; guint64 frameflags; frame_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_usb_frame, &ti, "Frame %u", i); proto_tree_add_item_ret_uint(frame_tree, hf_usb_frame_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &framelen); offset += 4; proto_tree_add_bitmask_ret_uint64(frame_tree, tvb, offset, hf_usb_frame_flags, ett_usb_frame_flags, usb_frame_flags_fields, ENC_LITTLE_ENDIAN, &frameflags); offset += 4; if (frameflags & FREEBSD_FRAMEFLAG_DATA_FOLLOWS) { /* * XXX - ultimately, we should dissect this data. */ proto_tree_add_item(frame_tree, hf_usb_frame_data, tvb, offset, framelen, ENC_NA); offset += WS_ROUNDUP_4(framelen); } proto_item_set_end(ti, tvb, offset); } return tvb_captured_length(tvb); } static int netmon_HostController2(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 flags) { proto_tree *host_tree; host_tree = proto_tree_add_subtree(tree, tvb, offset, (flags & EVENT_HEADER_FLAG_64_BIT_HEADER) ? 20 : 16, ett_usbport_host_controller, NULL, "HostController"); netmon_etl_field(host_tree, tvb, &offset, hf_usbport_device_object, flags); proto_tree_add_item(host_tree, hf_usbport_pci_bus, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(host_tree, hf_usbport_pci_device, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(host_tree, hf_usbport_pci_function, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(host_tree, hf_usbport_pci_vendor_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(host_tree, hf_usbport_pci_device_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int netmon_UsbPortPath(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo) { proto_item *path_item, *depth_item; proto_tree *path_tree; guint32 path_depth, path0, path1, path2, path3, path4, path5; path_tree = proto_tree_add_subtree(tree, tvb, offset, 28, ett_usbport_path, &path_item, "PortPath: "); depth_item = proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path_depth); offset += 4; proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path0, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path0); offset += 4; proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path1, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path1); offset += 4; proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path2, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path2); offset += 4; proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path3, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path3); offset += 4; proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path4, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path4); offset += 4; proto_tree_add_item_ret_uint(path_tree, hf_usbport_port_path5, tvb, offset, 4, ENC_LITTLE_ENDIAN, &path5); offset += 4; if (path_depth == 0) { proto_item_append_text(path_item, "-"); } if (path_depth > 0) { proto_item_append_text(path_item, "%d", path0); } if (path_depth > 1) { proto_item_append_text(path_item, ",%d", path1); } if (path_depth > 2) { proto_item_append_text(path_item, ",%d", path2); } if (path_depth > 3) { proto_item_append_text(path_item, ",%d", path3); } if (path_depth > 4) { proto_item_append_text(path_item, ",%d", path4); } if (path_depth > 5) { proto_item_append_text(path_item, ",%d", path5); } if (path_depth > 6) { expert_add_info(pinfo, depth_item, &ei_usbport_invalid_path_depth); } return offset; } static int netmon_fid_USBPORT_Device(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 flags, packet_info *pinfo) { proto_item *device_item; proto_tree *device_tree; device_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_usbport_device, &device_item, "Device"); netmon_etl_field(device_tree, tvb, &offset, hf_usbport_device_handle, flags); proto_tree_add_item(device_tree, hf_usb_idVendor, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(device_tree, hf_usb_idProduct, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; offset = netmon_UsbPortPath(device_tree, tvb, offset, pinfo); proto_tree_add_item(device_tree, hf_usbport_device_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(device_tree, hf_usb_device_address, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; return offset; } static int netmon_fid_USBPORT_Endpoint(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 flags) { proto_tree *endpoint_tree; endpoint_tree = proto_tree_add_subtree(tree, tvb, offset, (flags & EVENT_HEADER_FLAG_64_BIT_HEADER) ? 24 : 12, ett_usbport_endpoint, NULL, "Endpoint"); netmon_etl_field(endpoint_tree, tvb, &offset, hf_usbport_endpoint, flags); netmon_etl_field(endpoint_tree, tvb, &offset, hf_usbport_pipehandle, flags); netmon_etl_field(endpoint_tree, tvb, &offset, hf_usbport_device_handle, flags); return offset; } static int netmon_fid_USBPORT_Endpoint_Descriptor(proto_tree *tree, tvbuff_t *tvb, int offset) { proto_tree *endpoint_desc_tree; endpoint_desc_tree = proto_tree_add_subtree(tree, tvb, offset, 7, ett_usbport_endpoint_desc, NULL, "Endpoint Descriptor"); proto_tree_add_item(endpoint_desc_tree, hf_usbport_endpoint_desc_length, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(endpoint_desc_tree, hf_usbport_endpoint_desc_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(endpoint_desc_tree, hf_usbport_endpoint_address, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(endpoint_desc_tree, hf_usbport_bm_attributes, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(endpoint_desc_tree, hf_usbport_max_packet_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(endpoint_desc_tree, hf_usbport_interval, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; return offset; } static int netmon_URB(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 flags) { proto_item *urb_item; proto_tree *urb_tree; guint32 func; int i, start_offset = offset; urb_tree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_usbport_urb, &urb_item, "URB"); proto_tree_add_item(urb_tree, hf_usbport_urb_header_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item_ret_uint(urb_tree, hf_usbport_urb_header_function, tvb, offset, 2, ENC_LITTLE_ENDIAN, &func); proto_item_append_text(urb_item, ": %s", val_to_str_ext_const(func, &netmon_urb_function_vals_ext, "Unknown")); offset += 2; proto_tree_add_item(urb_tree, hf_usbport_urb_header_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_header_usbddevice_handle, flags); netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_header_usbdflags, flags); switch (func) { case 0x0000: netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_configuration_desc, flags); netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_configuration_handle, flags); break; case 0x0008: //URB_FUNCTION_CONTROL_TRANSFER case 0x0009: //URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER case 0x000A: //URB_FUNCTION_ISOCH_TRANSFER case 0x000B: //URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE case 0x000C: //URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE case 0x000D: //URB_FUNCTION_SET_FEATURE_TO_DEVICE case 0x000E: //URB_FUNCTION_SET_FEATURE_TO_INTERFACE case 0x000F: //URB_FUNCTION_SET_FEATURE_TO_ENDPOINT case 0x0010: //URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE case 0x0011: //URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE case 0x0012: //URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT case 0x0013: //URB_FUNCTION_GET_STATUS_FROM_DEVICE case 0x0014: //URB_FUNCTION_GET_STATUS_FROM_INTERFACE case 0x0015: //URB_FUNCTION_GET_STATUS_FROM_ENDPOINT case 0x0017: //URB_FUNCTION_VENDOR_DEVICE case 0x0018: //URB_FUNCTION_VENDOR_INTERFACE case 0x0019: //URB_FUNCTION_VENDOR_ENDPOINT case 0x001A: //URB_FUNCTION_CLASS_DEVICE case 0x001B: //URB_FUNCTION_CLASS_INTERFACE case 0x001C: //URB_FUNCTION_CLASS_ENDPOINT case 0x001F: //URB_FUNCTION_CLASS_OTHER case 0x0020: //URB_FUNCTION_VENDOR_OTHER case 0x0021: //URB_FUNCTION_GET_STATUS_FROM_OTHER case 0x0022: //URB_FUNCTION_CLEAR_FEATURE_TO_OTHER case 0x0023: //URB_FUNCTION_SET_FEATURE_TO_OTHER case 0x0024: //URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT case 0x0025: //URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT case 0x0026: //URB_FUNCTION_GET_CONFIGURATION case 0x0027: //URB_FUNCTION_GET_INTERFACE case 0x0028: //URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE case 0x0029: //URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE case 0x002A: //URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR case 0x0032: //URB_FUNCTION_CONTROL_TRANSFER_EX case 0x0037: //URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_USING_CHAINED_MDL case 0x0038: //URB_FUNCTION_ISOCH_TRANSFER_USING_CHAINED_MDL netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_pipe_handle, flags); proto_tree_add_bitmask(urb_tree, tvb, offset, hf_usbport_urb_xferflags, ett_usb_xferflags, usb_xferflags_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(urb_tree, hf_usbport_urb_transfer_buffer_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_transfer_buffer, flags); netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_transfer_buffer_mdl, flags); netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_reserved_mbz, flags); for (i = 0; i < 8; i++) { netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_reserved_hcd, flags); } break; case 0x0002: //URB_FUNCTION_ABORT_PIPE case 0x001E: //URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL case 0x0030: //URB_FUNCTION_SYNC_RESET_PIPE case 0x0031: //URB_FUNCTION_SYNC_CLEAR_STALL case 0x0036: //URB_FUNCTION_CLOSE_STATIC_STREAMS netmon_etl_field(urb_tree, tvb, &offset, hf_usbport_urb_pipe_handle, flags); proto_tree_add_item(urb_tree, hf_usbport_urb_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; break; } proto_item_set_len(urb_item, offset-start_offset); return offset; } #define USBPORT_KEYWORD_DIAGNOSTIC G_GUINT64_CONSTANT(0x0000000000000001) #define USBPORT_KEYWORD_POWER_DIAGNOSTICS G_GUINT64_CONSTANT(0x0000000000000002) #define USBPORT_KEYWORD_PERF_DIAGNOSTICS G_GUINT64_CONSTANT(0x0000000000000004) #define USBPORT_KEYWORD_RESERVED1 G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFF8) static int dissect_netmon_usb_port(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, void* data) { proto_item *ti, *generated; proto_tree *usb_port_tree; int offset = 0; struct netmon_provider_id_data *provider_id_data = (struct netmon_provider_id_data*)data; static int * const keyword_fields[] = { &hf_usbport_keyword_diagnostic, &hf_usbport_keyword_power_diagnostics, &hf_usbport_keyword_perf_diagnostics, &hf_usbport_keyword_reserved1, NULL }; DISSECTOR_ASSERT(provider_id_data != NULL); col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBPort"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(parent, proto_usbport, tvb, 0, -1, ENC_NA); usb_port_tree = proto_item_add_subtree(ti, ett_usbport); generated = proto_tree_add_uint(usb_port_tree, hf_usbport_event_id, tvb, 0, 0, provider_id_data->event_id); proto_item_set_generated(generated); generated = proto_tree_add_bitmask_value(usb_port_tree, tvb, 0, hf_usbport_keyword, ett_usbport_keyword, keyword_fields, provider_id_data->keyword); proto_item_set_generated(generated); switch (provider_id_data->event_id) { case 71: offset = netmon_HostController2(usb_port_tree, tvb, offset, provider_id_data->event_flags); offset = netmon_fid_USBPORT_Device(usb_port_tree, tvb, offset, provider_id_data->event_flags, pinfo); offset = netmon_fid_USBPORT_Endpoint(usb_port_tree, tvb, offset, provider_id_data->event_flags); offset = netmon_fid_USBPORT_Endpoint_Descriptor(usb_port_tree, tvb, offset); netmon_etl_field(usb_port_tree, tvb, &offset, hf_usbport_irp, provider_id_data->event_flags); netmon_etl_field(usb_port_tree, tvb, &offset, hf_usbport_urb, provider_id_data->event_flags); offset = netmon_URB(usb_port_tree, tvb, offset, provider_id_data->event_flags); proto_tree_add_item(usb_port_tree, hf_usbport_urb_transfer_data, tvb, offset, 2, ENC_LITTLE_ENDIAN); break; } return tvb_captured_length(tvb); } void dissect_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, usb_header_t header_type, void *extra_data) { gint offset = 0; int endpoint; guint8 urb_type; guint32 win32_data_len = 0; guint32 iso_numdesc = 0; guint32 desc_offset = 0; guint32 location = 0; proto_item *urb_tree_ti; proto_tree *tree; proto_item *item; usb_conv_info_t *usb_conv_info; conversation_t *conversation; guint16 device_address; guint16 bus_id; guint8 usbpcap_control_stage = 0; guint64 usb_id; struct mausb_header *ma_header = NULL; struct usbip_header *ip_header = NULL; usb_pseudo_urb_t *pseudo_urb = NULL; /* the goal is to get the conversation struct as early as possible and store all status values in this struct at first, we read the fields required to create/identify the right conversation struct */ switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: urb_type = tvb_get_guint8(tvb, 8); endpoint = tvb_get_guint8(tvb, 10) & 0x7F; device_address = (guint16)tvb_get_guint8(tvb, 11); bus_id = tvb_get_letohs(tvb, 12); break; case USB_HEADER_USBPCAP: urb_type = tvb_get_guint8(tvb, 16) & 0x01 ? URB_COMPLETE : URB_SUBMIT; device_address = tvb_get_letohs(tvb, 19); endpoint = tvb_get_guint8(tvb, 21); if ((endpoint == 0x00) && (tvb_get_guint8(tvb, 22) == URB_CONTROL) && (tvb_get_guint8(tvb, 27) == USB_CONTROL_STAGE_DATA)) { /* USBPcap before 1.3.0.0 DATA OUT packet (the info at offset 16 is wrong) */ urb_type = URB_SUBMIT; } endpoint &= 0x7F; /* Clear the direction flag */ bus_id = tvb_get_letohs(tvb, 17); break; case USB_HEADER_MAUSB: ma_header = (struct mausb_header *) extra_data; urb_type = mausb_is_from_host(ma_header) ? URB_SUBMIT : URB_COMPLETE; device_address = mausb_ep_handle_dev_addr(ma_header->handle); endpoint = mausb_ep_handle_ep_num(ma_header->handle); bus_id = mausb_ep_handle_bus_num(ma_header->handle); break; case USB_HEADER_USBIP: ip_header = (struct usbip_header *) extra_data; urb_type = tvb_get_ntohl(tvb, 0) == 1 ? URB_SUBMIT : URB_COMPLETE; device_address = ip_header->devid; bus_id = ip_header->busid; endpoint = ip_header->ep; break; case USB_HEADER_DARWIN: urb_type = tvb_get_guint8(tvb, 3) ? URB_COMPLETE : URB_SUBMIT; endpoint = tvb_get_guint8(tvb, 30) & 0x7F; device_address = (guint16)tvb_get_guint8(tvb, 29); location = tvb_get_letohl(tvb, 24); bus_id = location >> 24; break; case USB_HEADER_PSEUDO_URB: pseudo_urb = (usb_pseudo_urb_t *) extra_data; urb_type = pseudo_urb->from_host ? URB_SUBMIT : URB_COMPLETE; device_address = pseudo_urb->device_address; endpoint = pseudo_urb->endpoint; bus_id = pseudo_urb->bus_id; break; default: return; /* invalid USB pseudo header */ } col_set_str(pinfo->cinfo, COL_PROTOCOL, "USB"); urb_tree_ti = proto_tree_add_protocol_format(parent, proto_usb, tvb, 0, -1, "USB URB"); tree = proto_item_add_subtree(urb_tree_ti, ett_usb_hdr); usb_set_addr(tree, tvb, pinfo, bus_id, device_address, endpoint, (urb_type == URB_SUBMIT)); conversation = get_usb_conversation(pinfo, &pinfo->src, &pinfo->dst, pinfo->srcport, pinfo->destport); usb_conv_info = get_usb_conv_info(conversation); clear_usb_conv_tmp_data(usb_conv_info); switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: proto_item_set_len(urb_tree_ti, (header_type == USB_HEADER_LINUX_64_BYTES) ? 64 : 48); offset = dissect_linux_usb_pseudo_header(tvb, pinfo, tree, usb_conv_info, &usb_id); break; case USB_HEADER_USBPCAP: offset = dissect_usbpcap_buffer_packet_header(tvb, pinfo, tree, usb_conv_info, &win32_data_len, &usb_id); /* the length that we're setting here might have to be corrected if there's a transfer-specific pseudo-header following */ proto_item_set_len(urb_tree_ti, offset); break; case USB_HEADER_MAUSB: /* MA USB header gets dissected earlier, just set conversation variables */ offset = MAUSB_DPH_LENGTH; mausb_set_usb_conv_info(usb_conv_info, ma_header); usb_id = 0; break; case USB_HEADER_USBIP: iso_numdesc = tvb_get_ntohl(tvb, 0x20); usb_conv_info->transfer_type = endpoint == 0 ? URB_CONTROL : (iso_numdesc != 0xffffffff ? URB_ISOCHRONOUS : URB_UNKNOWN); usb_conv_info->direction = ip_header->dir == USBIP_DIR_OUT ? P2P_DIR_SENT : P2P_DIR_RECV; usb_conv_info->is_setup = endpoint == 0 ? (tvb_get_ntoh64(tvb, 0x28) != G_GUINT64_CONSTANT(0)) : FALSE; usb_conv_info->is_request = (urb_type==URB_SUBMIT); offset = usb_conv_info->is_setup ? USBIP_HEADER_WITH_SETUP_LEN : USBIP_HEADER_LEN; /* The ISOC descriptor is located at the end of the isoc frame behind the isoc data. */ if ((usb_conv_info->is_request && usb_conv_info->direction == USBIP_DIR_OUT) || (!usb_conv_info->is_request && usb_conv_info->direction == USBIP_DIR_IN)) { desc_offset += tvb_get_ntohl(tvb, 0x18); } desc_offset += offset; usb_id = 0; break; case USB_HEADER_DARWIN: offset = dissect_darwin_buffer_packet_header(tvb, pinfo, tree, usb_conv_info, &usb_id); proto_item_set_len(urb_tree_ti, offset); break; case USB_HEADER_PSEUDO_URB: usb_conv_info->transfer_type = pseudo_urb->transfer_type; usb_conv_info->direction = pseudo_urb->from_host ? P2P_DIR_SENT : P2P_DIR_RECV; usb_conv_info->is_setup = pseudo_urb->from_host && (pseudo_urb->transfer_type == URB_CONTROL); usb_conv_info->is_request = pseudo_urb->from_host; usb_conv_info->speed = pseudo_urb->speed; usb_id = 0; break; default: usb_id = 0; break; } usb_conv_info->usb_trans_info = usb_get_trans_info(tvb, pinfo, tree, header_type, usb_conv_info, usb_id); if (usb_conv_info->transfer_type != URB_CONTROL) { usb_tap_queue_packet(pinfo, urb_type, usb_conv_info); } switch(usb_conv_info->transfer_type) { case URB_BULK: case URB_INTERRUPT: item = proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, 0, 0, usb_conv_info->interfaceClass); proto_item_set_generated(item); switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: /* bulk and interrupt transfers never contain a setup packet */ proto_tree_add_item(tree, hf_usb_urb_unused_setup_header, tvb, offset, 8, ENC_NA); offset += 8; if (header_type == USB_HEADER_LINUX_64_BYTES) { offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); } break; case USB_HEADER_USBPCAP: break; case USB_HEADER_MAUSB: break; case USB_HEADER_USBIP: break; case USB_HEADER_DARWIN: break; case USB_HEADER_PSEUDO_URB: break; } break; case URB_CONTROL: if (header_type == USB_HEADER_USBPCAP) { proto_tree_add_item(tree, hf_usb_win32_control_stage, tvb, offset, 1, ENC_LITTLE_ENDIAN); usbpcap_control_stage = tvb_get_guint8(tvb, offset); offset++; proto_item_set_len(urb_tree_ti, offset); if (usbpcap_control_stage == USB_CONTROL_STAGE_SETUP) { usb_conv_info->is_setup = TRUE; } else if (usbpcap_control_stage == USB_CONTROL_STAGE_DATA && urb_type == URB_SUBMIT) { /* USBPcap before 1.5.0.0 */ wmem_tree_key_t key[3]; key[0].length = 2; key[0].key = (guint32 *)&usb_id; key[1].length = 1; key[1].key = &pinfo->num; key[2].length = 0; key[2].key = NULL; usbpcap_setup_data_t *setup_data = (usbpcap_setup_data_t *)wmem_tree_lookup32_array_le(usbpcap_setup_data, key); if (setup_data && setup_data->usb_id == usb_id) { tvbuff_t *reassembled_tvb = tvb_new_composite(); tvb_composite_append(reassembled_tvb, tvb_new_child_real_data(tvb, setup_data->setup_data, 8, 8)); tvb_composite_append(reassembled_tvb, tvb_new_subset_remaining(tvb, offset)); tvb_composite_finalize(reassembled_tvb); add_new_data_source(pinfo, reassembled_tvb, "USBPcap reassembled setup"); usb_conv_info->is_setup = TRUE; tvb = reassembled_tvb; offset = 0; } } } if (usb_conv_info->is_request) { if (usb_conv_info->is_setup) { offset = dissect_usb_setup_request(pinfo, tree, tvb, offset, urb_type, usb_conv_info, header_type, usb_id); } else { switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: proto_tree_add_item(tree, hf_usb_urb_unused_setup_header, tvb, offset, 8, ENC_NA); offset += 8; if (header_type == USB_HEADER_LINUX_64_BYTES) { offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); } break; case USB_HEADER_USBPCAP: break; case USB_HEADER_MAUSB: break; case USB_HEADER_USBIP: break; case USB_HEADER_DARWIN: break; case USB_HEADER_PSEUDO_URB: break; } } } else { /* this is a response */ switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: /* Skip setup header - it's never applicable for responses */ proto_tree_add_item(tree, hf_usb_urb_unused_setup_header, tvb, offset, 8, ENC_NA); offset += 8; if (header_type == USB_HEADER_LINUX_64_BYTES) { offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); } break; case USB_HEADER_USBPCAP: /* Check if this is status stage */ if ((usb_conv_info->usb_trans_info) && (usbpcap_control_stage == USB_CONTROL_STAGE_STATUS)) { const gchar *description; if (USB_TYPE(usb_conv_info->usb_trans_info->setup.requesttype) == RQT_SETUP_TYPE_STANDARD) { description = val_to_str_ext(usb_conv_info->usb_trans_info->setup.request, &setup_request_names_vals_ext, "Unknown type %x") ; } else { description = "URB_CONTROL"; } col_add_fstr(pinfo->cinfo, COL_INFO, "%s status", description); /* There is no data to dissect */ return; } break; case USB_HEADER_MAUSB: break; case USB_HEADER_USBIP: break; case USB_HEADER_DARWIN: break; case USB_HEADER_PSEUDO_URB: break; } offset = dissect_usb_setup_response(pinfo, tree, tvb, offset, urb_type, usb_conv_info); } break; case URB_ISOCHRONOUS: switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: offset = dissect_linux_usb_iso_transfer(pinfo, tree, header_type, tvb, offset, usb_conv_info); break; case USB_HEADER_USBPCAP: offset = dissect_usbpcap_iso_packets(pinfo, tree, urb_type, tvb, offset, win32_data_len, usb_conv_info); break; case USB_HEADER_MAUSB: break; case USB_HEADER_USBIP: offset = dissect_usbip_iso_transfer(pinfo, tree, tvb, offset, iso_numdesc, desc_offset, usb_conv_info); break; case USB_HEADER_DARWIN: offset = dissect_darwin_usb_iso_transfer(pinfo, tree, header_type, urb_type, tvb, offset, usb_conv_info); break; case USB_HEADER_PSEUDO_URB: break; } break; default: /* unknown transfer type */ switch (header_type) { case USB_HEADER_LINUX_48_BYTES: case USB_HEADER_LINUX_64_BYTES: proto_tree_add_item(tree, hf_usb_urb_unused_setup_header, tvb, offset, 8, ENC_NA); offset += 8; if (header_type == USB_HEADER_LINUX_64_BYTES) { offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); } break; case USB_HEADER_USBPCAP: break; case USB_HEADER_MAUSB: break; case USB_HEADER_USBIP: break; case USB_HEADER_DARWIN: break; case USB_HEADER_PSEUDO_URB: break; } break; } dissect_usb_payload(tvb, pinfo, parent, tree, usb_conv_info, urb_type, offset, device_address); } static int dissect_linux_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, void* data _U_) { dissect_usb_common(tvb, pinfo, parent, USB_HEADER_LINUX_48_BYTES, NULL); return tvb_captured_length(tvb); } static int dissect_linux_usb_mmapped(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, void* data _U_) { dissect_usb_common(tvb, pinfo, parent, USB_HEADER_LINUX_64_BYTES, NULL); return tvb_captured_length(tvb); } static int dissect_win32_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, void* data _U_) { dissect_usb_common(tvb, pinfo, parent, USB_HEADER_USBPCAP, NULL); return tvb_captured_length(tvb); } static int dissect_darwin_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, void* data _U_) { dissect_usb_common(tvb, pinfo, parent, USB_HEADER_DARWIN, NULL); return tvb_captured_length(tvb); } void proto_register_usb(void) { module_t *usb_module; static hf_register_info hf[] = { /* USB packet pseudoheader members */ { &hf_usb_totlen, { "Total length", "usb.totlen", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_busunit, { "Host controller unit number", "usb.busunit", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_address, { "USB device index", "usb.address", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_mode, { "Mode of transfer", "usb.transfer_mode", FT_UINT8, BASE_DEC, VALS(usb_freebsd_transfer_mode_vals), 0x0, NULL, HFILL }}, { &hf_usb_freebsd_urb_type, { "URB type", "usb.freebsd_type", FT_UINT8, BASE_DEC, VALS(usb_freebsd_urb_type_vals), 0x0, NULL, HFILL }}, { &hf_usb_freebsd_transfer_type, { "URB transfer type", "usb.freebsd_transfer_type", FT_UINT8, BASE_HEX, VALS(usb_freebsd_transfer_type_vals), 0x0, NULL, HFILL }}, { &hf_usb_xferflags, { "Transfer flags", "usb.xferflags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_xferflags_force_short_xfer, { "Force short transfer", "usb.xferflags.force_short_xfer", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_FORCE_SHORT_XFER, NULL, HFILL }}, { &hf_usb_xferflags_short_xfer_ok, { "Short transfer OK", "usb.xferflags.short_xfer_ok", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_SHORT_XFER_OK, NULL, HFILL }}, { &hf_usb_xferflags_short_frames_ok, { "Short frames OK", "usb.xferflags.short_frames_ok", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_SHORT_FRAMES_OK, NULL, HFILL }}, { &hf_usb_xferflags_pipe_bof, { "Pipe BOF", "usb.xferflags.pipe_bof", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_PIPE_BOF, NULL, HFILL }}, { &hf_usb_xferflags_proxy_buffer, { "Proxy buffer", "usb.xferflags.proxy_buffer", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_PROXY_BUFFER, NULL, HFILL }}, { &hf_usb_xferflags_ext_buffer, { "External buffer", "usb.xferflags.ext_buffer", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_EXT_BUFFER, NULL, HFILL }}, { &hf_usb_xferflags_manual_status, { "Manual status", "usb.xferflags.manual_status", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_MANUAL_STATUS, NULL, HFILL }}, { &hf_usb_xferflags_no_pipe_ok, { "No pipe OK", "usb.xferflags.no_pipe_ok", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_NO_PIPE_OK, NULL, HFILL }}, { &hf_usb_xferflags_stall_pipe, { "Stall pipe", "usb.xferflags.stall_pipe", FT_BOOLEAN, 32, NULL, FREEBSD_FLAG_STALL_PIPE, NULL, HFILL }}, { &hf_usb_xferstatus, { "Transfer status", "usb.xferstatus", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_xferstatus_open, { "Pipe has been opened", "usb.xferstatus.open", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_OPEN, NULL, HFILL }}, { &hf_usb_xferstatus_transferring, { "Transfer in progress", "usb.xferstatus.transferring", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_TRANSFERRING, NULL, HFILL }}, { &hf_usb_xferstatus_did_dma_delay, { "Waited for hardware DMA", "usb.xferstatus.did_dma_delay", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_DID_DMA_DELAY, NULL, HFILL }}, { &hf_usb_xferstatus_did_close, { "Transfer closed", "usb.xferstatus.did_close", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_DID_CLOSE, NULL, HFILL }}, { &hf_usb_xferstatus_draining, { "Draining transfer", "usb.xferstatus.draining", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_DRAINING, NULL, HFILL }}, { &hf_usb_xferstatus_started, { "Transfer started", "usb.xferstatus.started", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_STARTED, "Whether the transfer is started or stopped", HFILL }}, { &hf_usb_xferstatus_bw_reclaimed, { "Bandwidth reclaimed", "usb.xferstatus.bw_reclaimed", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_BW_RECLAIMED, NULL, HFILL }}, { &hf_usb_xferstatus_control_xfr, { "Control transfer", "usb.xferstatus.control_xfr", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_CONTROL_XFR, NULL, HFILL }}, { &hf_usb_xferstatus_control_hdr, { "Control header being sent", "usb.xferstatus.control_hdr", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_CONTROL_HDR, NULL, HFILL }}, { &hf_usb_xferstatus_control_act, { "Control transfer active", "usb.xferstatus.control_act", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_CONTROL_ACT, NULL, HFILL }}, { &hf_usb_xferstatus_control_stall, { "Control transfer should be stalled", "usb.xferstatus.control_stall", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_CONTROL_STALL, NULL, HFILL }}, { &hf_usb_xferstatus_short_frames_ok, { "Short frames OK", "usb.xferstatus.short_frames_ok", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_SHORT_FRAMES_OK, NULL, HFILL }}, { &hf_usb_xferstatus_short_xfer_ok, { "Short transfer OK", "usb.xferstatus.short_xfer_ok", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_SHORT_XFER_OK, NULL, HFILL }}, { &hf_usb_xferstatus_bdma_enable, { "BUS-DMA enabled", "usb.xferstatus.bdma_enable", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_BDMA_ENABLE, NULL, HFILL }}, { &hf_usb_xferstatus_bdma_no_post_sync, { "BUS-DMA post sync op not done", "usb.xferstatus.bdma_no_post_sync", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_BDMA_NO_POST_SYNC, NULL, HFILL }}, { &hf_usb_xferstatus_bdma_setup, { "BUS-DMA set up", "usb.xferstatus.bdma_setup", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_BDMA_SETUP, NULL, HFILL }}, { &hf_usb_xferstatus_isochronous_xfr, { "Isochronous transfer", "usb.xferstatus.isochronous_xfr", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_ISOCHRONOUS_XFR, NULL, HFILL }}, { &hf_usb_xferstatus_curr_dma_set, { "Current DMA set", "usb.xferstatus.curr_dma_set", FT_UINT32, BASE_DEC, NULL, FREEBSD_STATUS_CURR_DMA_SET, NULL, HFILL }}, { &hf_usb_xferstatus_can_cancel_immed, { "Transfer can be cancelled immediately", "usb.xferstatus.can_cancel_immed", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_CAN_CANCEL_IMMED, NULL, HFILL }}, { &hf_usb_xferstatus_doing_callback, { "Executing the callback", "usb.xferstatus.doing_callback", FT_BOOLEAN, 32, NULL, FREEBSD_STATUS_DOING_CALLBACK, NULL, HFILL }}, { &hf_usb_error, { "Error", "usb.error", FT_UINT32, BASE_DEC, VALS(usb_freebsd_err_vals), 0x0, NULL, HFILL }}, { &hf_usb_interval, { "Interval", "usb.interval", FT_UINT32, BASE_DEC, NULL, 0x0, "Interval (ms)", HFILL }}, { &hf_usb_nframes, { "Number of following frames", "usb.nframes", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_packet_size, { "Packet size used", "usb.packet_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_packet_count, { "Packet count used", "usb.packet_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_speed, { "Speed", "usb.speed", FT_UINT8, BASE_DEC, VALS(usb_freebsd_speed_vals), 0x0, NULL, HFILL }}, { &hf_usb_frame_length, { "Frame length", "usb.frame.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_frame_flags, { "Frame flags", "usb.frame.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_frame_flags_read, { "Data direction is read", "usb.frame.read", FT_BOOLEAN, 32, NULL, FREEBSD_FRAMEFLAG_READ, NULL, HFILL }}, { &hf_usb_frame_flags_data_follows, { "Frame contains data", "usb.frame.data_follows", FT_BOOLEAN, 32, NULL, FREEBSD_FRAMEFLAG_DATA_FOLLOWS, NULL, HFILL }}, { &hf_usb_frame_data, { "Frame data", "usb.frame.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_urb_id, { "URB id", "usb.urb_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_linux_urb_type, { "URB type", "usb.urb_type", FT_CHAR, BASE_HEX, VALS(usb_linux_urb_type_vals), 0x0, NULL, HFILL }}, { &hf_usb_linux_transfer_type, { "URB transfer type", "usb.transfer_type", FT_UINT8, BASE_HEX, VALS(usb_linux_transfer_type_vals), 0x0, NULL, HFILL }}, { &hf_usb_endpoint_address, { "Endpoint", "usb.endpoint_address", FT_UINT8, BASE_HEX, NULL, 0x0, "USB endpoint address", HFILL }}, { &hf_usb_endpoint_direction, { "Direction", "usb.endpoint_address.direction", FT_UINT8, BASE_DEC, VALS(usb_endpoint_direction_vals), 0x80, "USB endpoint direction", HFILL }}, { &hf_usb_endpoint_number, { "Endpoint number", "usb.endpoint_address.number", FT_UINT8, BASE_DEC, NULL, 0x0F, "USB endpoint number", HFILL }}, { &hf_usb_device_address, { "Device", "usb.device_address", FT_UINT32, BASE_DEC, NULL, 0x0, "USB device address", HFILL }}, { &hf_usb_bus_id, { "URB bus id", "usb.bus_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_setup_flag, { "Device setup request", "usb.setup_flag", FT_CHAR, BASE_HEX|BASE_RANGE_STRING, RVALS(usb_setup_flag_rvals), 0x0, "USB device setup request is relevant (0) or not", HFILL }}, { &hf_usb_data_flag, { "Data", "usb.data_flag", FT_CHAR, BASE_HEX|BASE_RANGE_STRING, RVALS(usb_data_flag_rvals), 0x0, "USB data is present (0) or not", HFILL }}, { &hf_usb_urb_ts_sec, { "URB sec", "usb.urb_ts_sec", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_urb_ts_usec, { "URB usec", "usb.urb_ts_usec", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_urb_status, { "URB status", "usb.urb_status", FT_INT32, BASE_DEC|BASE_EXT_STRING, &linux_negative_errno_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_urb_len, { "URB length [bytes]", "usb.urb_len", FT_UINT32, BASE_DEC, NULL, 0x0, "URB length in bytes", HFILL }}, { &hf_usb_urb_data_len, { "Data length [bytes]", "usb.data_len", FT_UINT32, BASE_DEC, NULL, 0x0, "URB data length in bytes", HFILL }}, { &hf_usb_urb_unused_setup_header, { "Unused Setup Header", "usb.unused_setup_header", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_urb_interval, { "Interval", "usb.interval", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_urb_start_frame, { "Start frame", "usb.start_frame", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_urb_copy_of_transfer_flags, { "Copy of Transfer Flags", "usb.copy_of_transfer_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_short_not_ok, { "Short not OK", "usb.transfer_flags.short_not_ok", FT_BOOLEAN, 32, NULL, URB_SHORT_NOT_OK, NULL, HFILL }}, { &hf_iso_asap, { "ISO ASAP", "usb.transfer_flags.iso_asap", FT_BOOLEAN, 32, NULL, URB_ISO_ASAP, NULL, HFILL }}, { &hf_no_transfer_dma_map, { "No transfer DMA map", "usb.transfer_flags.no_transfer_dma_map", FT_BOOLEAN, 32, NULL, URB_NO_TRANSFER_DMA_MAP, NULL, HFILL }}, { &hf_no_fsbr, { "No FSBR", "usb.transfer_flags.no_fsbr", FT_BOOLEAN, 32, NULL, URB_NO_FSBR, NULL, HFILL }}, { &hf_zero_packet, { "Zero Packet", "usb.transfer_flags.zero_packet", FT_BOOLEAN, 32, NULL, URB_ZERO_PACKET, NULL, HFILL }}, { &hf_no_interrupt, { "No Interrupt", "usb.transfer_flags.no_interrupt", FT_BOOLEAN, 32, NULL, URB_NO_INTERRUPT, NULL, HFILL }}, { &hf_free_buffer, { "Free Buffer", "usb.transfer_flags.free_buffer", FT_BOOLEAN, 32, NULL, URB_FREE_BUFFER, NULL, HFILL }}, { &hf_dir_in, { "Dir IN", "usb.transfer_flags.dir_in", FT_BOOLEAN, 32, NULL, URB_DIR_IN, NULL, HFILL }}, { &hf_dma_map_single, { "DMA Map Single", "usb.transfer_flags.dma_map_single", FT_BOOLEAN, 32, NULL, URB_DMA_MAP_SINGLE, NULL, HFILL }}, { &hf_dma_map_page, { "DMA Map Page", "usb.transfer_flags.dma_map_page", FT_BOOLEAN, 32, NULL, URB_DMA_MAP_PAGE, NULL, HFILL }}, { &hf_dma_map_sg, { "DMA Map SG", "usb.transfer_flags.dma_map_sg", FT_BOOLEAN, 32, NULL, URB_DMA_MAP_SG, NULL, HFILL }}, { &hf_map_local, { "Map Local", "usb.transfer_flags.map_local", FT_BOOLEAN, 32, NULL, URB_MAP_LOCAL, NULL, HFILL }}, { &hf_setup_map_single, { "Setup Map Single", "usb.transfer_flags.setup_map_single", FT_BOOLEAN, 32, NULL, URB_SETUP_MAP_SINGLE, NULL, HFILL }}, { &hf_setup_map_local, { "Setup Map Local", "usb.transfer_flags.setup_map_local", FT_BOOLEAN, 32, NULL, URB_SETUP_MAP_LOCAL, NULL, HFILL }}, { &hf_dma_sg_combined, { "DMA S-G Combined", "usb.transfer_flags.dma_sg_combined", FT_BOOLEAN, 32, NULL, URB_DMA_SG_COMBINED, NULL, HFILL }}, { &hf_aligned_temp_buffer, { "Aligned Temp Buffer", "usb.transfer_flags.aligned_temp_buffer", FT_BOOLEAN, 32, NULL, URB_ALIGNED_TEMP_BUFFER, NULL, HFILL }}, /* Win32 USBPcap pseudoheader */ { &hf_usb_win32_header_len, { "USBPcap pseudoheader length", "usb.usbpcap_header_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_irp_id, { "IRP ID", "usb.irp_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_usbd_status, { "IRP USBD_STATUS", "usb.usbd_status", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &win32_usbd_status_vals_ext, 0x0, "USB request status value", HFILL }}, { &hf_usb_function, { "URB Function", "usb.function", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &win32_urb_function_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_info, { "IRP information", "usb.irp_info", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_usbpcap_info_reserved, { "Reserved", "usb.irp_info.reserved", FT_UINT8, BASE_HEX, NULL, 0xFE, NULL, HFILL }}, { &hf_usb_usbpcap_info_direction, { "Direction", "usb.irp_info.direction", FT_UINT8, BASE_HEX, VALS(win32_usb_info_direction_vals), 0x01, NULL, HFILL }}, { &hf_usb_win32_device_address, { "Device address", "usb.device_address", FT_UINT16, BASE_DEC, NULL, 0x0, "Windows USB device address", HFILL }}, { &hf_usb_win32_transfer_type, { "URB transfer type", "usb.transfer_type", FT_UINT8, BASE_HEX, VALS(win32_usb_transfer_type_vals), 0x0, NULL, HFILL } }, { &hf_usb_win32_data_len, { "Packet Data Length", "usb.data_len", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_control_stage, { "Control transfer stage", "usb.control_stage", FT_UINT8, BASE_DEC, VALS(usb_control_stage_vals), 0x0, NULL, HFILL }}, { &hf_usb_win32_iso_start_frame, { "Isochronous transfer start frame", "usb.win32.iso_frame", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_iso_num_packets, { "Isochronous transfer number of packets", "usb.win32.iso_num_packets", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_iso_error_count, { "Isochronous transfer error count", "usb.win32.iso_error_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_iso_offset, { "ISO Data offset", "usb.win32.iso_offset", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_iso_length, { "ISO Data length", "usb.win32.iso_data_len", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_win32_iso_status, { "ISO USBD status", "usb.win32.iso_status", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &win32_usbd_status_vals_ext, 0x0, NULL, HFILL }}, /* macOS usbdump pseudoheader */ { &hf_usb_darwin_bcd_version, { "Darwin header bcdVersion", "usb.darwin.bcdVersion", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_header_len, { "Darwin header length", "usb.darwin.header_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_request_type, { "Request type", "usb.darwin.request_type", FT_UINT8, BASE_DEC, VALS(usb_darwin_request_type_vals), 0x0, NULL, HFILL }}, { &hf_usb_darwin_io_len, { "I/O length [bytes]", "usb.darwin.io_len", FT_UINT32, BASE_DEC, NULL, 0x0, "Request length in bytes", HFILL }}, { &hf_usb_darwin_io_status, { "Request status", "usb.darwin.io_status", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &usb_darwin_status_vals_ext, 0x0, "USB request status", HFILL }}, { &hf_usb_darwin_iso_num_packets, { "Isochronous transfer number of frames", "usb.darwin.io_frame_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_io_id, { "I/O ID", "usb.darwin.io_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_device_location, { "Device location ID", "usb.darwin.location_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_speed, { "Device speed", "usb.darwin_device_speed", FT_UINT8, BASE_DEC, VALS(usb_darwin_speed_vals), 0x0, NULL, HFILL }}, { &hf_usb_darwin_device_address, { "USB device index", "usb.darwin.device_address", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_endpoint_address, { "Endpoint address", "usb.darwin.endpoint_address", FT_UINT8, BASE_HEX, NULL, 0x0, "Endpoint address and direction", HFILL }}, { &hf_usb_darwin_endpoint_type, { "Endpoint transfer type", "usb.darwin.endpoint_type", FT_UINT8, BASE_DEC, VALS(usb_darwin_endpoint_type_vals), 0x0, NULL, HFILL }}, { &hf_usb_darwin_iso_status, { "Frame status", "usb.darwin.iso.status", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &usb_darwin_status_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_darwin_iso_timestamp, { "Frame timestamp", "usb.darwin.iso.timestamp", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_darwin_iso_frame_number, { "Frame number", "usb.darwin.iso.frame_number", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bmRequestType, { "bmRequestType", "usb.bmRequestType", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, /* Only used when response type cannot be determined */ { &hf_usb_control_response_generic, { "CONTROL response data", "usb.control.Response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_request, { "bRequest", "usb.setup.bRequest", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &setup_request_names_vals_ext, 0x0, NULL, HFILL }}, /* Same as hf_usb_request but no descriptive text */ { &hf_usb_request_unknown_class, { "bRequest", "usb.setup.bRequest", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_value, { "wValue", "usb.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_index, { "wIndex", "usb.setup.wIndex", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_length, { "wLength", "usb.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_device_wFeatureSelector, { "wFeatureSelector", "usb.setup.wFeatureSelector", FT_UINT16, BASE_DEC, VALS(usb_device_feature_selector_vals), 0x0, NULL, HFILL }}, { &hf_usb_interface_wFeatureSelector, { "wFeatureSelector", "usb.setup.wFeatureSelector", FT_UINT16, BASE_DEC, VALS(usb_interface_feature_selector_vals), 0x0, NULL, HFILL }}, { &hf_usb_endpoint_wFeatureSelector, { "wFeatureSelector", "usb.setup.wFeatureSelector", FT_UINT16, BASE_DEC, VALS(usb_endpoint_feature_selector_vals), 0x0, NULL, HFILL }}, { &hf_usb_wInterface, { "wInterface", "usb.setup.wInterface", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_wEndpoint, { "wEndpoint", "usb.setup.wEndpoint", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_wStatus, { "wStatus", "usb.setup.wStatus", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_wFrameNumber, { "wFrameNumber", "usb.setup.wFrameNumber", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, /* --------------------------------- */ { &hf_usb_iso_error_count, /* host endian byte order */ { "ISO error count", "usb.iso.error_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iso_numdesc, { "Number of ISO descriptors", "usb.iso.numdesc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, /* fields of struct mon_bin_isodesc from linux/drivers/usb/mon/mon_bin.c */ { &hf_usb_iso_status, { "Status", "usb.iso.iso_status", FT_INT32, BASE_DEC|BASE_EXT_STRING, &linux_negative_errno_vals_ext, 0x0, "ISO descriptor status", HFILL }}, { &hf_usb_iso_off, { "Offset [bytes]", "usb.iso.iso_off", FT_UINT32, BASE_DEC, NULL, 0x0, "ISO data offset in bytes starting from the end of the last ISO descriptor", HFILL }}, { &hf_usb_iso_len, { "Length [bytes]", "usb.iso.iso_len", FT_UINT32, BASE_DEC, NULL, 0x0, "ISO data length in bytes", HFILL }}, { &hf_usb_iso_actual_len, { "Actual Length [bytes]", "usb.iso.iso_actual_len", FT_UINT32, BASE_DEC, NULL, 0x0, "ISO data actual length in bytes", HFILL }}, { &hf_usb_iso_pad, /* host endian byte order */ { "Padding", "usb.iso.pad", FT_UINT32, BASE_HEX, NULL, 0x0, "Padding field of ISO descriptor structure", HFILL }}, { &hf_usb_iso_data, {"ISO Data", "usb.iso.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, /* --------------------------------- */ #if 0 { &hf_usb_data_len, {"Application Data Length", "usb.data.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, #endif { &hf_usb_capdata, {"Leftover Capture Data", "usb.capdata", FT_BYTES, BASE_NONE, NULL, 0x0, "Padding added by the USB capture system", HFILL }}, { &hf_usb_bmRequestType_direction, { "Direction", "usb.bmRequestType.direction", FT_BOOLEAN, 8, TFS(&tfs_bmrequesttype_direction), USB_DIR_IN, NULL, HFILL }}, { &hf_usb_bmRequestType_type, { "Type", "usb.bmRequestType.type", FT_UINT8, BASE_HEX, VALS(bmrequesttype_type_vals), USB_TYPE_MASK, NULL, HFILL }}, { &hf_usb_bmRequestType_recipient, { "Recipient", "usb.bmRequestType.recipient", FT_UINT8, BASE_HEX, VALS(bmrequesttype_recipient_vals), 0x1f, NULL, HFILL }}, { &hf_usb_bDescriptorType, { "bDescriptorType", "usb.bDescriptorType", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &std_descriptor_type_vals_ext, 0x0, NULL, HFILL }}, /* Only used when descriptor type cannot be determined */ { &hf_usb_get_descriptor_resp_generic, { "GET DESCRIPTOR Response data", "usb.getDescriptor.Response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_descriptor_index, { "Descriptor Index", "usb.DescriptorIndex", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_language_id, { "Language Id", "usb.LanguageId", FT_UINT16, BASE_HEX|BASE_EXT_STRING,&usb_langid_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bLength, { "bLength", "usb.bLength", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bcdUSB, { "bcdUSB", "usb.bcdUSB", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bDeviceClass, { "bDeviceClass", "usb.bDeviceClass", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &usb_class_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bDeviceSubClass, { "bDeviceSubClass", "usb.bDeviceSubClass", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bDeviceProtocol, { "bDeviceProtocol", "usb.bDeviceProtocol", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bMaxPacketSize0, { "bMaxPacketSize0", "usb.bMaxPacketSize0", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_idVendor, { "idVendor", "usb.idVendor", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ext_usb_vendors_vals, 0x0, NULL, HFILL }}, { &hf_usb_idProduct, { "idProduct", "usb.idProduct", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bcdDevice, { "bcdDevice", "usb.bcdDevice", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iManufacturer, { "iManufacturer", "usb.iManufacturer", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iProduct, { "iProduct", "usb.iProduct", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iSerialNumber, { "iSerialNumber", "usb.iSerialNumber", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bNumConfigurations, { "bNumConfigurations", "usb.bNumConfigurations", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_wLANGID, { "wLANGID", "usb.wLANGID", FT_UINT16, BASE_HEX|BASE_EXT_STRING,&usb_langid_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bString, { "bString", "usb.bString", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceNumber, { "bInterfaceNumber", "usb.bInterfaceNumber", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bAlternateSetting, { "bAlternateSetting", "usb.bAlternateSetting", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bNumEndpoints, { "bNumEndpoints", "usb.bNumEndpoints", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceClass, { "bInterfaceClass", "usb.bInterfaceClass", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &usb_class_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass, { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass_audio, { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ext_usb_audio_subclass_vals, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass_cdc, { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ext_usb_com_subclass_vals, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass_massstorage , { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ext_usb_massstorage_subclass_vals, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass_hid, { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_hid_subclass_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass_misc, { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_misc_subclass_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceSubClass_app, { "bInterfaceSubClass", "usb.bInterfaceSubClass", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_app_subclass_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_cdc, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_cdc_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_massstorage, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_massstorage_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_cdc_data, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_cdc_data_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_hid_boot, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_hid_boot_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_app_dfu, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_app_dfu_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_app_irda, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_app_irda_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceProtocol_app_usb_test_and_measurement, { "bInterfaceProtocol", "usb.bInterfaceProtocol", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &usb_app_usb_test_and_measurement_protocol_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_iInterface, { "iInterface", "usb.iInterface", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bEndpointAddress, { "bEndpointAddress", "usb.bEndpointAddress", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_configuration_bmAttributes, { "Configuration bmAttributes", "usb.configuration.bmAttributes", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bmAttributes, { "bmAttributes", "usb.bmAttributes", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bEndpointAttributeTransfer, { "Transfertype", "usb.bmAttributes.transfer", FT_UINT8, BASE_HEX, VALS(usb_bmAttributes_transfer_vals), 0x03, NULL, HFILL }}, { &hf_usb_bEndpointAttributeSynchonisation, { "Synchronisationtype", "usb.bmAttributes.sync", FT_UINT8, BASE_HEX, VALS(usb_bmAttributes_sync_vals), 0x0c, NULL, HFILL }}, { &hf_usb_bEndpointAttributeBehaviour, { "Behaviourtype", "usb.bmAttributes.behaviour", FT_UINT8, BASE_HEX, VALS(usb_bmAttributes_behaviour_vals), 0x30, NULL, HFILL }}, { &hf_usb_wMaxPacketSize, { "wMaxPacketSize", "usb.wMaxPacketSize", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_wMaxPacketSize_size, { "Maximum Packet Size", "usb.wMaxPacketSize.size", FT_UINT16, BASE_DEC, NULL, 0x03FF, NULL, HFILL }}, { &hf_usb_wMaxPacketSize_slots, { "Transactions per microframe", "usb.wMaxPacketSize.slots", FT_UINT16, BASE_DEC, VALS(usb_wMaxPacketSize_slots_vals), (3<<11), NULL, HFILL }}, { &hf_usb_bInterval, { "bInterval", "usb.bInterval", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bMaxBurst, { "bMaxBurst", "usb.bMaxBurst", FT_UINT8, BASE_DEC, NULL, 0x0, "Valid values are from 0 to 15. For control endpoints this value shall be 0.", HFILL }}, { &hf_usb_audio_bRefresh, { "bRefresh", "usb.audio.bRefresh", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, { &hf_usb_audio_bSynchAddress, { "bSynchAddress", "usb.audio.bSynchAddress", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, { &hf_usb_bSSEndpointAttributeBulkMaxStreams, { "MaxStreams", "usb.bmAttributes.MaxStreams", FT_UINT8, BASE_DEC, NULL, 0x0F, "Number of streams = 2 to the power MaxStreams", HFILL }}, { &hf_usb_bSSEndpointAttributeIsoMult, { "Mult", "usb.bmAttributes.Mult", FT_UINT8, BASE_DEC, NULL, 0x03, "Maximum number of packets = bMaxBurst * (Mult + 1)", HFILL } }, { &hf_usb_wBytesPerInterval, { "wBytesPerInterval", "usb.wBytesPerInterval", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usb_wTotalLength, { "wTotalLength", "usb.wTotalLength", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bNumInterfaces, { "bNumInterfaces", "usb.bNumInterfaces", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bConfigurationValue, { "bConfigurationValue", "usb.bConfigurationValue", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iConfiguration, { "iConfiguration", "usb.iConfiguration", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bMaxPower, { "bMaxPower", "usb.bMaxPower", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_configuration_legacy10buspowered, { "Must be 1", "usb.configuration.legacy10buspowered", FT_BOOLEAN, 8, TFS(&tfs_mustbeone), 0x80, "Legacy USB 1.0 bus powered", HFILL }}, { &hf_usb_configuration_selfpowered, { "Self-Powered", "usb.configuration.selfpowered", FT_BOOLEAN, 8, TFS(&tfs_selfpowered), 0x40, NULL, HFILL }}, { &hf_usb_configuration_remotewakeup, { "Remote Wakeup", "usb.configuration.remotewakeup", FT_BOOLEAN, 8, TFS(&tfs_remotewakeup), 0x20, NULL, HFILL }}, { &hf_usb_bEndpointAddress_number, { "Endpoint Number", "usb.bEndpointAddress.number", FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }}, { &hf_usb_bEndpointAddress_direction, { "Direction", "usb.bEndpointAddress.direction", FT_BOOLEAN, 8, TFS(&tfs_endpoint_direction), 0x80, NULL, HFILL }}, { &hf_usb_request_in, { "Request in", "usb.request_in", FT_FRAMENUM, BASE_NONE, NULL, 0, "The request to this packet is in this packet", HFILL }}, { &hf_usb_time, { "Time from request", "usb.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "Time between Request and Response for USB cmds", HFILL }}, { &hf_usb_response_in, { "Response in", "usb.response_in", FT_FRAMENUM, BASE_NONE, NULL, 0, "The response to this packet is in this packet", HFILL }}, { &hf_usb_bFirstInterface, { "bFirstInterface", "usb.bFirstInterface", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bInterfaceCount, { "bInterfaceCount", "usb.bInterfaceCount", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bFunctionClass, { "bFunctionClass", "usb.bFunctionClass", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &usb_class_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_bFunctionSubClass, { "bFunctionSubClass", "usb.bFunctionSubClass", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bFunctionProtocol, { "bFunctionProtocol", "usb.bFunctionProtocol", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_iFunction, { "iFunction", "usb.iFunction", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bNumDeviceCaps, { "bNumDeviceCaps", "usb.bNumDeviceCaps", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_bDevCapabilityType, { "bDevCapabilityType", "usb.bDevCapabilityType", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &usb_capability_vals_ext, 0x0, NULL, HFILL }}, { &hf_usb_usb20ext_bmAttributes, { "bmAttributes", "usb.usb20ext.bmAttributes", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_usb20ext_LPM, { "LPM", "usb.usb20ext.bmAttributes.LPM", FT_BOOLEAN, 32, NULL, 0x00000002, NULL, HFILL }}, { &hf_usb_usb20ext_BESL_HIRD, { "BESL & Alternate HIRD", "usb.usb20ext.bmAttributes.BESL", FT_BOOLEAN, 32, NULL, 0x00000004, NULL, HFILL }}, { &hf_usb_usb20ext_baseline_BESL_valid, { "Baseline BESL valid", "usb.usb20ext.bmAttributes.baseline_BESL_valid", FT_BOOLEAN, 32, NULL, 0x00000008, NULL, HFILL }}, { &hf_usb_usb20ext_deep_BESL_valid, { "Deep BESL valid", "usb.usb20ext.bmAttributes.deep_BESL_valid", FT_BOOLEAN, 32, NULL, 0x00000010, NULL, HFILL }}, { &hf_usb_usb20ext_baseline_BESL, { "Recommended Baseline BESL", "usb.usb20ext.bmAttributes.baseline_BESL", FT_UINT32, BASE_CUSTOM, CF_FUNC(usb_lpm_besl_str), 0x00000F00, NULL, HFILL }}, { &hf_usb_usb20ext_deep_BESL, { "Recommended Deep BESL", "usb.usb20ext.bmAttributes.deep_BESL", FT_UINT32, BASE_CUSTOM, CF_FUNC(usb_lpm_besl_str), 0x0000F000, NULL, HFILL }}, { &hf_usb_bReserved, { "bReserved", "usb.bReserved", FT_UINT8, BASE_DEC, NULL, 0x0, "This field is reserved and shall be set to zero", HFILL }}, { &hf_usb_PlatformCapabilityUUID, { "PlatformCapabilityUUID", "usb.PlatformCapabilityUUID", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_webusb_bcdVersion, { "bcdVersion", "usb.webusb.bcdVersion", FT_UINT16, BASE_HEX, NULL, 0x0, "WebUSB descriptor version", HFILL }}, { &hf_usb_webusb_bVendorCode, { "bVendorCode", "usb.webusb.bVendorCode", FT_UINT8, BASE_DEC, NULL, 0x0, "bRequest value for WebUSB", HFILL }}, { &hf_usb_webusb_iLandingPage, { "iLandingPage", "usb.webusb.iLandingPage", FT_UINT8, BASE_DEC, NULL, 0x0, "URL for landing page", HFILL }}, { &hf_usb_msos20_dwWindowsVersion, { "dwWindowsVersion", "usb.msos20.dwWindowsVersion", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_usb_msos20_wMSOSDescriptorSetTotalLength, { "wMSOSDescriptorSetTotalLength", "usb.msos20.wMSOSDescriptorSetTotalLength", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_msos20_bMS_VendorCode, { "bMS_VendorCode", "usb.msos20.bMS_VendorCode", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_msos20_bAltEnumCode, { "bAltEnumCode", "usb.msos20.bAltEnumCode", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_usb_data_fragment, { "Data Fragment", "usb.data_fragment", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_usb_src, { "Source", "usb.src", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_usb_dst, { "Destination", "usb.dst", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_usb_addr, { "Source or Destination", "usb.addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } } }; static hf_register_info hf_usbport[] = { { &hf_usbport_event_id, { "Event ID", "usbport.event_id", FT_UINT32, BASE_DEC_HEX|BASE_EXT_STRING, &netmon_event_id_vals_ext, 0x0, NULL, HFILL } }, { &hf_usbport_device_object, { "Device Object", "usbport.device_object", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_pci_bus, { "PCI Bus", "usbport.pci_bus", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_pci_device, { "PCI Bus", "usbport.pci_device", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_pci_function, { "PCI Function", "usbport.pci_function", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_pci_vendor_id, { "PCI Vendor ID", "usbport.pci_vendor_id", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_pci_device_id, { "PCI Device ID", "usbport.pci_device_id", FT_UINT16, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path_depth, { "Path Depth", "usbport.port_path_depth", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path0, { "Path0", "usbport.port_path0", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path1, { "Path1", "usbport.port_path1", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path2, { "Path2", "usbport.port_path2", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path3, { "Path3", "usbport.port_path3", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path4, { "Path4", "usbport.port_path4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_port_path5, { "Path5", "usbport.port_path5", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_device_handle, { "Device Handle", "usbport.device_handle", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_device_speed, { "Device Speed", "usbport.device_speed", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_endpoint, { "Endpoint", "usbport.endpoint", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_pipehandle, { "Pipe Handle", "usbport.pipehandle", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_endpoint_desc_length, { "Length", "usbport.endpoint_desc_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_endpoint_desc_type, { "Description Type", "usbport.endpoint_desc_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_endpoint_address, { "Endpoint Address", "usbport.endpoint_address", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_bm_attributes, { "bmAttributes", "usbport.bm_attributes", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_max_packet_size, { "Max Packet Size", "usbport.max_packet_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_interval, { "Interval", "usbport.interval", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_irp, { "IRP", "usbport.irp", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb, { "URB", "usbport.urb", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_transfer_data, { "URB Transfer data", "usbport.urb_transfer_data", FT_UINT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_header_length, { "URB Header Length", "usbport.urb_header_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_header_function, { "URB Header Function", "usbport.urb_header_function", FT_UINT16, BASE_DEC|BASE_EXT_STRING, &netmon_urb_function_vals_ext, 0x0, NULL, HFILL } }, { &hf_usbport_urb_header_status, { "URB Header Status", "usbport.urb_header_status", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_header_usbddevice_handle, { "URB Header Device Handle", "usbport.urb_header_usbddevice_handle", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_header_usbdflags, { "URB Header Flags", "usbport.urb_header_usbdflags", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_configuration_desc, { "URB Configuration Description", "usbport.urb_configuration_desc", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_configuration_handle, { "URB Configuration Handle", "usbport.urb_configuration_handle", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_pipe_handle, { "URB Pipe Handle", "usbport.urb_pipe_handle", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_xferflags, { "URB Transfer Flags", "usbport.urb_xferflags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_transfer_buffer_length, { "URB Transfer Buffer Length", "usbport.urb_transfer_buffer_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_transfer_buffer, { "URB Transfer Buffer", "usbport.urb_transfer_buffer", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_transfer_buffer_mdl, { "URB Transfer Buffer MDL", "usbport.urb_transfer_buffer_mdl", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_reserved_mbz, { "URB Reserved MBZ", "usbport.urb_reserved_mbz", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_reserved_hcd, { "URB Reserved HCD", "usbport.urb_reserved_hcd", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_urb_reserved, { "URB Reserved", "usbport.urb_reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_keyword, { "Keyword", "usbport.keyword", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_usbport_keyword_diagnostic, { "USBPORT_ETW_KEYWORD_DIAGNOSTIC", "usbport.keyword.diagnostic", FT_BOOLEAN, 64, NULL, USBPORT_KEYWORD_DIAGNOSTIC, NULL, HFILL } }, { &hf_usbport_keyword_power_diagnostics, { "USBPORT_ETW_KEYWORD_POWER_DIAGNOSTICS", "usbport.keyword.power_diagnostics", FT_BOOLEAN, 64, NULL, USBPORT_KEYWORD_POWER_DIAGNOSTICS, NULL, HFILL } }, { &hf_usbport_keyword_perf_diagnostics, { "USBPORT_ETW_KEYWORD_PERF_DIAGNOSTICS", "usbport.keyword.perf_diagnostics", FT_BOOLEAN, 64, NULL, USBPORT_KEYWORD_PERF_DIAGNOSTICS, NULL, HFILL } }, { &hf_usbport_keyword_reserved1, { "Reserved1", "usbport.keyword.reserved1", FT_UINT64, BASE_HEX, NULL, USBPORT_KEYWORD_RESERVED1, NULL, HFILL } }, }; static gint *usb_subtrees[] = { &ett_usb_hdr, &ett_usb_setup_hdr, &ett_usb_isodesc, &ett_usb_win32_iso_packet, &ett_usb_endpoint, &ett_usb_xferflags, &ett_usb_xferstatus, &ett_usb_frame, &ett_usb_frame_flags, &ett_usb_setup_bmrequesttype, &ett_usb_usbpcap_info, &ett_descriptor_device, &ett_configuration_bmAttributes, &ett_configuration_bEndpointAddress, &ett_endpoint_bmAttributes, &ett_endpoint_wMaxPacketSize, &ett_transfer_flags, &ett_usb20ext_bmAttributes, }; static gint *usbport_subtrees[] = { &ett_usbport, &ett_usbport_host_controller, &ett_usbport_path, &ett_usbport_device, &ett_usbport_endpoint, &ett_usbport_endpoint_desc, &ett_usbport_urb, &ett_usbport_keyword, }; static ei_register_info ei[] = { { &ei_usb_undecoded, { "usb.undecoded", PI_UNDECODED, PI_WARN, "Not dissected yet (report to wireshark.org)", EXPFILL }}, { &ei_usb_bLength_even, { "usb.bLength.even", PI_PROTOCOL, PI_WARN, "Invalid STRING DESCRIPTOR Length (must be even)", EXPFILL }}, { &ei_usb_bLength_too_short, { "usb.bLength.too_short", PI_MALFORMED, PI_ERROR, "Invalid STRING DESCRIPTOR Length (must be 2 or larger)", EXPFILL }}, { &ei_usb_desc_length_invalid, { "usb.desc_length.invalid", PI_MALFORMED, PI_ERROR, "Invalid descriptor length", EXPFILL }}, { &ei_usb_invalid_setup, { "usb.setup.invalid", PI_MALFORMED, PI_ERROR, "Only control URBs may contain a setup packet", EXPFILL }}, { &ei_usb_ss_ep_companion_before_ep, { "usb.bmAttributes.invalid_order", PI_MALFORMED, PI_ERROR, "SuperSpeed Endpoint Companion must come after Endpoint Descriptor", EXPFILL }}, { &ei_usb_usbpcap_unknown_urb, { "usb.usbpcap.unknown_urb", PI_MALFORMED, PI_ERROR, "USBPcap did not recognize URB Function code (report to desowin.org/USBPcap)", EXPFILL }}, { &ei_usb_bad_length, { "usb.bad_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }}, { &ei_usb_invalid_max_packet_size, { "usb.wMaxPacketSize.invalid", PI_PROTOCOL, PI_WARN, "Invalid Max Packet Size", EXPFILL }}, { &ei_usb_invalid_max_packet_size0, { "usb.bMaxPacketSize0.invalid", PI_PROTOCOL, PI_WARN, "Invalid Max Packet Size", EXPFILL }}, { &ei_usb_invalid_endpoint_type, { "usb.bmAttributes.transfer.invalid", PI_PROTOCOL, PI_WARN, "Transfer type not allowed at Low-Speed", EXPFILL }}, { &ei_usb_unexpected_desc_type, { "usb.bDescriptorType.unexpected", PI_MALFORMED, PI_ERROR, "Unexpected descriptor type", EXPFILL }}, }; static ei_register_info ei_usbport[] = { { &ei_usbport_invalid_path_depth, { "usbport.path_depth.invalid", PI_PROTOCOL, PI_WARN, "Invalid path depth", EXPFILL }}, }; expert_module_t *expert_usb, *expert_usbport; proto_usb = proto_register_protocol("USB", "USB", "usb"); proto_usbport = proto_register_protocol("USBPort", "USBPort", "usbport"); proto_register_field_array(proto_usb, hf, array_length(hf)); proto_register_field_array(proto_usbport, hf_usbport, array_length(hf_usbport)); proto_register_subtree_array(usb_subtrees, array_length(usb_subtrees)); proto_register_subtree_array(usbport_subtrees, array_length(usbport_subtrees)); expert_usb = expert_register_protocol(proto_usb); expert_register_field_array(expert_usb, ei, array_length(ei)); expert_usbport = expert_register_protocol(proto_usbport); expert_register_field_array(expert_usbport, ei_usbport, array_length(ei_usbport)); device_to_product_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); device_to_protocol_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); usbpcap_setup_data = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); device_to_dissector = register_dissector_table("usb.device", "USB device", proto_usb, FT_UINT32, BASE_HEX); protocol_to_dissector = register_dissector_table("usb.protocol", "USB protocol", proto_usb, FT_UINT32, BASE_HEX); product_to_dissector = register_dissector_table("usb.product", "USB product", proto_usb, FT_UINT32, BASE_HEX); usb_bulk_dissector_table = register_dissector_table("usb.bulk", "USB bulk endpoint", proto_usb, FT_UINT32, BASE_HEX); heur_bulk_subdissector_list = register_heur_dissector_list("usb.bulk", proto_usb); usb_control_dissector_table = register_dissector_table("usb.control", "USB control endpoint", proto_usb, FT_UINT32, BASE_HEX); heur_control_subdissector_list = register_heur_dissector_list("usb.control", proto_usb); usb_interrupt_dissector_table = register_dissector_table("usb.interrupt", "USB interrupt endpoint", proto_usb, FT_UINT32, BASE_HEX); heur_interrupt_subdissector_list = register_heur_dissector_list("usb.interrupt", proto_usb); usb_descriptor_dissector_table = register_dissector_table("usb.descriptor", "USB descriptor", proto_usb, FT_UINT8, BASE_DEC); usb_module = prefs_register_protocol(proto_usb, NULL); prefs_register_bool_preference(usb_module, "try_heuristics", "Try heuristic sub-dissectors", "Try to decode a packet using a heuristic sub-dissector before " "attempting to dissect the packet using the \"usb.bulk\", \"usb.interrupt\" or " "\"usb.control\" dissector tables.", &try_heuristics); usb_tap = register_tap("usb"); register_decode_as(&usb_protocol_da); register_decode_as(&usb_product_da); register_decode_as(&usb_device_da); linux_usb_handle = register_dissector("usb_linux", dissect_linux_usb, proto_usb); linux_usb_mmapped_handle = register_dissector("usb_linux_mmapped", dissect_linux_usb_mmapped, proto_usb); win32_usb_handle = register_dissector("usb_win32", dissect_win32_usb, proto_usb); freebsd_usb_handle = register_dissector("usb_freebsd", dissect_freebsd_usb, proto_usb); darwin_usb_handle = register_dissector("usb_darwin", dissect_darwin_usb, proto_usb); netmon_usb_port_handle = register_dissector("usb_netmon", dissect_netmon_usb_port, proto_usbport); usb_address_type = address_type_dissector_register("AT_USB", "USB Address", usb_addr_to_str, usb_addr_str_len, NULL, usb_col_filter_str, NULL, NULL, NULL); register_conversation_table(proto_usb, TRUE, usb_conversation_packet, usb_endpoint_packet); } void proto_reg_handoff_usb(void) { static guid_key usb_port_key = {{ 0xc88a4ef5, 0xd048, 0x4013, { 0x94, 0x08, 0xe0, 0x4b, 0x7d, 0xb2, 0x81, 0x4a }}, 0 }; dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_LINUX, linux_usb_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_LINUX_MMAPPED, linux_usb_mmapped_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USBPCAP, win32_usb_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_FREEBSD, freebsd_usb_handle); dissector_add_uint("wtap_encap", WTAP_ENCAP_USB_DARWIN, darwin_usb_handle); dissector_add_guid( "netmon.provider_id", &usb_port_key, netmon_usb_port_handle); } /* * 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: */