diff options
author | Anders Broman <anders.broman@ericsson.com> | 2012-11-30 12:33:37 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2012-11-30 12:33:37 +0000 |
commit | 962aaf121f08f094455ac0d3b3f607cea13dcc6c (patch) | |
tree | a2d5098c292b61a4eb65429cab80780f55c7d4f0 /epan/dissectors/packet-usb.c | |
parent | 1a79540fdc4d3a4291c485c637c6a6ca52c55349 (diff) |
From Michal Labedzki:
PATCH] USB: Add support for vendor_id/product_id,
bus_id/device_address and class/subclass/protocol tables
USB subdissectors can be decoded by class/subclass/protocol. If fail try vendor_id/product_id.
bus_id/device_address is intented to use by DecodeBy, so user can decode specified device as need.
Part of:
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5032
svn path=/trunk/; revision=46306
Diffstat (limited to 'epan/dissectors/packet-usb.c')
-rw-r--r-- | epan/dissectors/packet-usb.c | 252 |
1 files changed, 210 insertions, 42 deletions
diff --git a/epan/dissectors/packet-usb.c b/epan/dissectors/packet-usb.c index edf2e01ea8..447d9eb744 100644 --- a/epan/dissectors/packet-usb.c +++ b/epan/dissectors/packet-usb.c @@ -38,6 +38,8 @@ #include <epan/conversation.h> #include <epan/expert.h> #include <epan/prefs.h> +#include <epan/reassemble.h> + #include "packet-usb.h" #include "packet-usb-hid.h" @@ -169,6 +171,27 @@ 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 emem_tree_t *device_to_protocol_table = NULL; +static emem_tree_t *device_to_product_table = 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; + 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; + + /* http://www.usb.org/developers/docs/USB_LANGIDs.pdf */ static const value_string usb_langid_vals[] = { {0x0000, "no language specified"}, @@ -857,7 +880,8 @@ static int dissect_usb_setup_clear_feature_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* feature selector */ proto_tree_add_item(tree, hf_usb_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -879,7 +903,8 @@ static int dissect_usb_setup_clear_feature_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { return offset; } @@ -896,7 +921,8 @@ static int dissect_usb_setup_get_configuration_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { proto_tree_add_item(tree, hf_usb_bConfigurationValue, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; @@ -927,7 +953,8 @@ static int dissect_usb_device_qualifier_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id, guint device_address) { proto_item *item = NULL; proto_tree *tree = NULL; @@ -965,6 +992,33 @@ dissect_usb_device_qualifier_descriptor(packet_info *pinfo _U_, proto_tree *pare proto_item_append_text(nitem, " (%s)", description); offset += 1; + if (!pinfo->fd->flags.visited) { + guint k_bus_id; + guint k_device_address; + guint k_frame_number; + emem_tree_key_t key[4]; + device_protocol_data_t *device_protocol_data; + + k_frame_number = pinfo->fd->num; + k_device_address = device_address; + k_bus_id = 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 = se_alloc(sizeof(device_protocol_data_t)); + device_protocol_data->protocol = protocol; + device_protocol_data->bus_id = bus_id; + device_protocol_data->device_address = device_address; + se_tree_insert32_array(device_to_protocol_table, key, device_protocol_data); + } + /* bMaxPacketSize0 */ proto_tree_add_item(tree, hf_usb_bMaxPacketSize0, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; @@ -988,7 +1042,8 @@ static int dissect_usb_device_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id, guint device_address) { proto_item *item = NULL; proto_tree *tree = NULL; @@ -1010,7 +1065,7 @@ dissect_usb_device_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, /* bcdUSB */ proto_tree_add_item(tree, hf_usb_bcdUSB, tvb, offset, 2, ENC_LITTLE_ENDIAN); - offset+=2; + offset += 2; protocol = tvb_get_ntoh24(tvb, offset); description = val_to_str_const(protocol, usb_protocols, ""); @@ -1047,9 +1102,45 @@ dissect_usb_device_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, product_id); offset += 2; + if (!pinfo->fd->flags.visited) { + guint k_bus_id; + guint k_device_address; + guint k_frame_number; + emem_tree_key_t key[4]; + device_product_data_t *device_product_data; + device_protocol_data_t *device_protocol_data; + + k_frame_number = pinfo->fd->num; + k_device_address = device_address; + k_bus_id = 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 = se_alloc(sizeof(device_product_data_t)); + device_product_data->vendor = vendor_id; + device_product_data->product = product_id; + device_product_data->bus_id = bus_id; + device_product_data->device_address = device_address; + se_tree_insert32_array(device_to_product_table, key, device_product_data); + + device_protocol_data = se_alloc(sizeof(device_protocol_data_t)); + device_protocol_data->protocol = protocol; + device_protocol_data->bus_id = bus_id; + device_protocol_data->device_address = device_address; + + se_tree_insert32_array(device_to_protocol_table, key, device_protocol_data); + } + /* bcdDevice */ proto_tree_add_item(tree, hf_usb_bcdDevice, tvb, offset, 2, ENC_LITTLE_ENDIAN); - offset+=2; + offset += 2; /* iManufacturer */ proto_tree_add_item(tree, hf_usb_iManufacturer, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1587,7 +1678,8 @@ static int dissect_usb_setup_get_descriptor_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* descriptor index */ proto_tree_add_item(tree, hf_usb_descriptor_index, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1618,7 +1710,8 @@ static int dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info, - usb_conv_info_t *usb_conv_info) + usb_conv_info_t *usb_conv_info, + guint bus_id, guint device_address) { if (check_col(pinfo->cinfo, COL_INFO)) { @@ -1627,7 +1720,7 @@ dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, } switch(usb_trans_info->u.get_descriptor.type) { case USB_DT_DEVICE: - offset = dissect_usb_device_descriptor(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info); + offset = dissect_usb_device_descriptor(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info, bus_id, device_address); break; case USB_DT_CONFIG: offset = dissect_usb_configuration_descriptor(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info); @@ -1642,7 +1735,7 @@ dissect_usb_setup_get_descriptor_response(packet_info *pinfo, proto_tree *tree, offset = dissect_usb_endpoint_descriptor(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info); break; case USB_DT_DEVICE_QUALIFIER: - offset = dissect_usb_device_qualifier_descriptor(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info); + offset = dissect_usb_device_qualifier_descriptor(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info, bus_id, device_address); break; case USB_DT_RPIPE: if (usb_conv_info->interfaceClass == IF_CLASS_HID) { @@ -1672,7 +1765,8 @@ static int dissect_usb_setup_get_interface_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* zero */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -1693,7 +1787,8 @@ static int dissect_usb_setup_get_interface_response(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* alternate setting */ proto_tree_add_item(tree, hf_usb_bAlternateSetting, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1714,7 +1809,8 @@ static int dissect_usb_setup_get_status_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* zero */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -1736,7 +1832,8 @@ static int dissect_usb_setup_get_status_response(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* status */ /* XXX - show bits */ @@ -1758,7 +1855,8 @@ static int dissect_usb_setup_set_address_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* device address */ proto_tree_add_item(tree, hf_usb_device_address, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -1779,7 +1877,8 @@ static int dissect_usb_setup_set_address_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { return offset; } @@ -1796,7 +1895,8 @@ static int dissect_usb_setup_set_configuration_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* configuration value */ proto_tree_add_item(tree, hf_usb_bConfigurationValue, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1817,7 +1917,8 @@ static int dissect_usb_setup_set_configuration_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { return offset; } @@ -1834,7 +1935,8 @@ static int dissect_usb_setup_set_feature_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* feature selector */ proto_tree_add_item(tree, hf_usb_wFeatureSelector, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -1856,7 +1958,8 @@ static int dissect_usb_setup_set_feature_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { return offset; } @@ -1873,7 +1976,8 @@ static int dissect_usb_setup_set_interface_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* alternate setting */ proto_tree_add_item(tree, hf_usb_bAlternateSetting, tvb, offset, 1, ENC_LITTLE_ENDIAN); @@ -1894,7 +1998,8 @@ static int dissect_usb_setup_set_interface_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { return offset; } @@ -1911,7 +2016,8 @@ static int dissect_usb_setup_synch_frame_request(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* zero */ proto_tree_add_item(tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -1933,7 +2039,8 @@ static int dissect_usb_setup_synch_frame_response(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset, usb_trans_info_t *usb_trans_info _U_, - usb_conv_info_t *usb_conv_info _U_) + usb_conv_info_t *usb_conv_info _U_, + guint bus_id _U_, guint device_address _U_) { /* frame number */ proto_tree_add_item(tree, hf_usb_wFrameNumber, tvb, offset, 2, ENC_LITTLE_ENDIAN); @@ -1946,7 +2053,8 @@ dissect_usb_setup_synch_frame_response(packet_info *pinfo _U_, proto_tree *tree typedef int (*usb_setup_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info, - usb_conv_info_t *usb_conv_info); + usb_conv_info_t *usb_conv_info, + guint bus_id, guint device_address); typedef struct _usb_setup_dissector_table_t { guint8 request; @@ -2058,7 +2166,8 @@ dissect_usb_bmrequesttype(proto_tree *parent_tree, tvbuff_t *tvb, int offset, in * the reason for the tvb_memcpy() and proto_tree_add_uint[64]() * pairs below. */ static void -dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + guint *bus_id, guint *device_address) { guint8 transfer_type; guint8 endpoint_number; @@ -2089,9 +2198,11 @@ dissect_linux_usb_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t proto_tree_add_bitmask(tree, tvb, 10, hf_usb_endpoint_number, ett_usb_endpoint, usb_endpoint_fields, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_usb_device_address, tvb, 11, 1, ENC_BIG_ENDIAN); + *device_address = tvb_get_guint8(tvb, 11); tvb_memcpy(tvb, (guint8 *)&val16, 12, 2); proto_tree_add_uint(tree, hf_usb_bus_id, tvb, 12, 2, val16); + *bus_id = tvb_get_letohs(tvb, 12); /* Right after the pseudo header we always have * sizeof(struct usb_device_setup_hdr) bytes. The content of these @@ -2172,6 +2283,11 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, usb_trans_info_t *usb_trans_info = NULL; conversation_t *conversation; usb_tap_data_t *tap_data; + guint bus_id = 0; + guint device_address = 0; + usb_data_t *usb_data; + void *pd_save; + tvbuff_t *next_tvb = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "USB"); @@ -2183,7 +2299,7 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, tree = proto_item_add_subtree(ti, usb_hdr); } - dissect_linux_usb_pseudo_header(tvb, pinfo, tree); + dissect_linux_usb_pseudo_header(tvb, pinfo, tree, &bus_id, &device_address); is_request = (tvb_get_guint8(tvb, 8) == URB_SUBMIT) ? TRUE : FALSE; type = tvb_get_guint8(tvb, 9); endpoint = tvb_get_guint8(tvb, 10) & (~URB_TRANSFER_IN); @@ -2191,6 +2307,18 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, setup_flag = tvb_get_guint8(tvb, 14); offset += 40; /* skip first part of the pseudo-header */ + usb_data = se_alloc(sizeof(usb_data_t)); + usb_data->endpoint = endpoint; + + if (tvb_get_guint8(tvb, 10) & URB_TRANSFER_IN) { + usb_data->direction = P2P_DIR_RECV; + } else { + usb_data->direction = P2P_DIR_SENT; + } + + pd_save = pinfo->private_data; + pinfo->private_data = usb_data; + /* Set up addresses and ports. */ if (is_request) { src_addr.device = 0xffffffff; @@ -2296,8 +2424,6 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); if (tvb_reported_length_remaining(tvb, offset)) { - tvbuff_t *next_tvb; - pinfo->usb_conv_info = usb_conv_info; next_tvb = tvb_new_subset_remaining(tvb, offset); if (try_heuristics && dissector_try_heuristic(heur_bulk_subdissector_list, next_tvb, pinfo, parent, NULL)) { @@ -2327,8 +2453,6 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); if (tvb_reported_length_remaining(tvb, offset)) { - tvbuff_t *next_tvb; - pinfo->usb_conv_info = usb_conv_info; next_tvb = tvb_new_subset_remaining(tvb, offset); if (try_heuristics && dissector_try_heuristic(heur_interrupt_subdissector_list, next_tvb, pinfo, parent, NULL)) { @@ -2350,8 +2474,6 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, if (is_request) { if (setup_flag == 0) { - tvbuff_t *next_tvb; - /* this is a request */ /* Dissect the setup header - it's applicable */ @@ -2397,7 +2519,8 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, } if (dissector) { - offset = dissector(pinfo, setup_tree, tvb, offset, usb_trans_info, usb_conv_info); + offset = dissector(pinfo, setup_tree, tvb, offset, usb_trans_info, + usb_conv_info, bus_id, device_address); } else { proto_tree_add_item(setup_tree, hf_usb_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; @@ -2479,8 +2602,6 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, offset = dissect_linux_usb_pseudo_header_ext(tvb, offset, pinfo, tree); if (tvb_reported_length_remaining(tvb, offset) != 0) { - tvbuff_t *next_tvb; - next_tvb = tvb_new_subset_remaining(tvb, offset); if (try_heuristics && dissector_try_heuristic(heur_control_subdissector_list, next_tvb, pinfo, parent, NULL)) { return; @@ -2490,8 +2611,6 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, } } } else { - tvbuff_t *next_tvb; - /* this is a response */ /* Skip setup header - it's never applicable for responses */ @@ -2524,7 +2643,6 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, tap_data->conv_info = usb_conv_info; tap_data->trans_info = usb_trans_info; tap_queue_packet(usb_tap, pinfo, tap_data); - ti = proto_tree_add_uint(tree, hf_usb_bInterfaceClass, tvb, 0, 0, usb_conv_info->interfaceClass); PROTO_ITEM_SET_GENERATED(ti); @@ -2568,7 +2686,8 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, } if (dissector) { - offset = dissector(pinfo, parent, tvb, offset, usb_conv_info->usb_trans_info, usb_conv_info); + offset = dissector(pinfo, parent, tvb, offset, usb_conv_info->usb_trans_info, + usb_conv_info, bus_id, device_address); } else { if (tvb_reported_length_remaining(tvb, offset) != 0) { proto_tree_add_text(parent, tvb, offset, -1, "CONTROL response data"); @@ -2752,10 +2871,53 @@ dissect_linux_usb_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent, break; } + next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_length_remaining(tvb, offset)); + + if (!dissector_try_uint(device_to_dissector, (guint32) (bus_id << 8 | device_address), next_tvb, pinfo, parent)) { + emem_tree_key_t key[4]; + guint32 k_frame_number; + guint32 k_device_address; + guint32 k_bus_id; + device_protocol_data_t *device_protocol_data; + + k_frame_number = pinfo->fd->num; + k_device_address = device_address; + k_bus_id = 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 = se_tree_lookup32_array_le(device_to_protocol_table, key); + if (device_protocol_data && device_protocol_data->bus_id == bus_id && + device_protocol_data->device_address == device_address && + dissector_try_uint(protocol_to_dissector, (guint32) device_protocol_data->protocol, next_tvb, pinfo, parent)) { + offset += tvb_length_remaining(tvb, offset); + } else { + device_product_data_t *device_product_data; + + device_product_data = se_tree_lookup32_array_le(device_to_product_table, key); + if (device_product_data && device_product_data->bus_id == bus_id && + device_product_data->device_address == device_address && + dissector_try_uint(product_to_dissector, (guint32) (device_product_data->vendor << 16 | device_product_data->product), next_tvb, pinfo, parent)) { + offset += tvb_length_remaining(tvb, offset); + } + } + } else { + offset += tvb_length_remaining(tvb, offset); + } + if (tvb_reported_length_remaining(tvb, offset) != 0) { /* There is leftover capture data to add (padding?) */ proto_tree_add_item(parent, hf_usb_capdata, tvb, offset, -1, ENC_NA); } + + pinfo->private_data = pd_save; } static void @@ -3246,6 +3408,11 @@ proto_register_usb(void) &ett_endpoint_wMaxPacketSize }; + device_to_product_table = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "usb device_address, bus_id and frame number to vendor_product"); + device_to_protocol_table = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "usb device_address, bus_id and frame number to class_subclass_protocol"); + device_to_dissector = register_dissector_table("usb.device", "USB device", FT_UINT32, BASE_HEX); + protocol_to_dissector = register_dissector_table("usb.protocol", "USB protocol", FT_UINT32, BASE_HEX); + product_to_dissector = register_dissector_table("usb.product", "USB product", FT_UINT32, BASE_HEX); proto_usb = proto_register_protocol("USB", "USB", "usb"); proto_register_field_array(proto_usb, hf, array_length(hf)); @@ -3277,7 +3444,8 @@ proto_register_usb(void) void proto_reg_handoff_usb(void) { - dissector_handle_t linux_usb_handle, linux_usb_mmapped_handle; + dissector_handle_t linux_usb_handle; + dissector_handle_t linux_usb_mmapped_handle; linux_usb_handle = create_dissector_handle(dissect_linux_usb, proto_usb); linux_usb_mmapped_handle = create_dissector_handle(dissect_linux_usb_mmapped, |