diff options
author | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2006-10-22 11:49:23 +0000 |
---|---|---|
committer | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2006-10-22 11:49:23 +0000 |
commit | ac67085436e7ee0148289e564568a7b4cc3d5b27 (patch) | |
tree | 7d5132b6677ee3718cead672dbd3eed012f36a5b /epan/dissectors | |
parent | 7a62c1f5fe5bd225a3956c517bb94ff8b7abe106 (diff) |
add a dissector table for class specific control input/output pdus
implement class specific control commands : reset and getmaxlun for mass storage
now with a better understanding of the problem space for usb and device classes we can start cleaning the code up and make it nice
svn path=/trunk/; revision=19659
Diffstat (limited to 'epan/dissectors')
-rw-r--r-- | epan/dissectors/packet-usb-masstorage.c | 155 | ||||
-rw-r--r-- | epan/dissectors/packet-usb.c | 40 | ||||
-rw-r--r-- | epan/dissectors/packet-usb.h | 15 |
3 files changed, 195 insertions, 15 deletions
diff --git a/epan/dissectors/packet-usb-masstorage.c b/epan/dissectors/packet-usb-masstorage.c index 81669d1dc2..78a31dbffa 100644 --- a/epan/dissectors/packet-usb-masstorage.c +++ b/epan/dissectors/packet-usb-masstorage.c @@ -44,6 +44,11 @@ static int hf_usb_ms_dCBWCBLength = -1; static int hf_usb_ms_dCSWSignature = -1; static int hf_usb_ms_dCSWDataResidue = -1; static int hf_usb_ms_dCSWStatus = -1; +static int hf_usb_ms_request = -1; +static int hf_usb_ms_value = -1; +static int hf_usb_ms_index = -1; +static int hf_usb_ms_length = -1; +static int hf_usb_ms_maxlun = -1; static gint ett_usb_ms = -1; @@ -62,8 +67,124 @@ static const value_string status_vals[] = { {0, NULL} }; + + + +static void +dissect_usb_ms_reset(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info, usb_conv_info_t *usb_conv_info) +{ + if(is_request){ + proto_tree_add_item(tree, hf_usb_ms_value, tvb, offset, 2, FALSE); + offset += 2; + + proto_tree_add_item(tree, hf_usb_ms_index, tvb, offset, 2, FALSE); + offset += 2; + + proto_tree_add_item(tree, hf_usb_ms_length, tvb, offset, 2, FALSE); + offset += 2; + } else { + /* no data in reset response */ + } +} + +static void +dissect_usb_ms_get_max_lun(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info, usb_conv_info_t *usb_conv_info) +{ + if(is_request){ + proto_tree_add_item(tree, hf_usb_ms_value, tvb, offset, 2, FALSE); + offset += 2; + + proto_tree_add_item(tree, hf_usb_ms_index, tvb, offset, 2, FALSE); + offset += 2; + + proto_tree_add_item(tree, hf_usb_ms_length, tvb, offset, 2, FALSE); + offset += 2; + } else { + proto_tree_add_item(tree, hf_usb_ms_maxlun, tvb, offset, 1, FALSE); + offset++; + } +} + + +typedef void (*usb_setup_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info, 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; +#define USB_SETUP_RESET 0xff +#define USB_SETUP_GET_MAX_LUN 0xfe +static const usb_setup_dissector_table_t setup_dissectors[] = { + {USB_SETUP_RESET, dissect_usb_ms_reset}, + {USB_SETUP_GET_MAX_LUN, dissect_usb_ms_get_max_lun}, + {0, NULL} +}; +static const value_string setup_request_names_vals[] = { + {USB_SETUP_RESET, "RESET"}, + {USB_SETUP_GET_MAX_LUN, "GET MAX LUN"}, + {0, NULL} +}; + +/* Dissector for mass storage control . + * Returns TRUE if a class specific dissector was found + * and FALSE othervise. + */ +static gint +dissect_usb_ms_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + gboolean is_request; + usb_conv_info_t *usb_conv_info; + usb_trans_info_t *usb_trans_info; + int offset=0; + usb_setup_dissector dissector; + const usb_setup_dissector_table_t *tmp; + + + is_request=(pinfo->srcport==NO_ENDPOINT); + + usb_conv_info=pinfo->usb_conv_info; + usb_trans_info=usb_conv_info->usb_trans_info; + + + /* See if we can find a class specific dissector for this request */ + dissector=NULL; + for(tmp=setup_dissectors;tmp->dissector;tmp++){ + if(tmp->request==usb_trans_info->request){ + dissector=tmp->dissector; + break; + } + } + /* No we could not find any class specific dissector for this request + * return FALSE and let USB try any of the standard requests. + */ + if(!dissector){ + return FALSE; + } + + + if(check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBMS"); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_clear(pinfo->cinfo, COL_INFO); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", + val_to_str(usb_trans_info->request, setup_request_names_vals, "Unknown type %x"), + is_request?"Request":"Response"); + } + + if(is_request){ + proto_tree_add_item(tree, hf_usb_ms_request, tvb, offset, 1, TRUE); + offset += 1; + } + + dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info); + return TRUE; +} + + +/* dissector for mass storage bulk data */ static void -dissect_usb_ms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) +dissect_usb_ms_bulk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { usb_conv_info_t *usb_conv_info; usb_ms_conv_info_t *usb_ms_conv_info; @@ -287,6 +408,26 @@ proto_register_usb_ms(void) { "Status", "usbms.dCSWStatus", FT_UINT8, BASE_HEX, VALS(status_vals), 0x0, "", HFILL }}, + { &hf_usb_ms_request, + { "bRequest", "usbms.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0, + "", HFILL }}, + + { &hf_usb_ms_value, + { "wValue", "usbms.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0, + "", HFILL }}, + + { &hf_usb_ms_index, + { "wIndex", "usbms.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL }}, + + { &hf_usb_ms_length, + { "wLength", "usbms.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0, + "", HFILL }}, + + { &hf_usb_ms_maxlun, + { "Max LUN", "usbms.setup.maxlun", FT_UINT8, BASE_DEC, NULL, 0x0, + "", HFILL }}, + }; static gint *usb_ms_subtrees[] = { @@ -298,14 +439,18 @@ proto_register_usb_ms(void) proto_register_field_array(proto_usb_ms, hf, array_length(hf)); proto_register_subtree_array(usb_ms_subtrees, array_length(usb_ms_subtrees)); - register_dissector("usbms", dissect_usb_ms, proto_usb_ms); + register_dissector("usbms", dissect_usb_ms_bulk, proto_usb_ms); } void proto_reg_handoff_usb_ms(void) { - dissector_handle_t usb_ms_handle; - usb_ms_handle = create_dissector_handle(dissect_usb_ms, proto_usb_ms); + dissector_handle_t usb_ms_bulk_handle; + dissector_handle_t usb_ms_control_handle; + + usb_ms_bulk_handle = create_dissector_handle(dissect_usb_ms_bulk, proto_usb_ms); + dissector_add("usb.bulk", IF_CLASS_MASSTORAGE, usb_ms_bulk_handle); - dissector_add("usb.bulk", IF_CLASS_MASSTORAGE, usb_ms_handle); + usb_ms_control_handle = new_create_dissector_handle(dissect_usb_ms_control, proto_usb_ms); + dissector_add("usb.control", IF_CLASS_MASSTORAGE, usb_ms_control_handle); } diff --git a/epan/dissectors/packet-usb.c b/epan/dissectors/packet-usb.c index d11eb6beb7..fdc65e69ff 100644 --- a/epan/dissectors/packet-usb.c +++ b/epan/dissectors/packet-usb.c @@ -107,6 +107,7 @@ static gint ett_configuration_bEndpointAddress = -1; static dissector_table_t usb_bulk_dissector_table; +static dissector_table_t usb_control_dissector_table; typedef enum { @@ -975,16 +976,19 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent) PROTO_ITEM_SET_GENERATED(ti); if(is_request){ + tvbuff_t *next_tvb; + /* this is a request */ ti = proto_tree_add_protocol_format(tree, proto_usb, tvb, offset, sizeof(usb_setup_t), "URB setup"); setup_tree = proto_item_add_subtree(ti, usb_setup_hdr); requesttype=tvb_get_guint8(tvb, offset); offset=dissect_usb_setup_bmrequesttype(setup_tree, tvb, offset); - request=tvb_get_guint8(tvb, offset); - proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE); - offset += 1; + /* read the request code and spawn off to a class specific + * dissector if found + */ + request=tvb_get_guint8(tvb, offset); usb_trans_info=se_tree_lookup32(usb_conv_info->transactions, pinfo->fd->num); if(!usb_trans_info){ usb_trans_info=se_alloc(sizeof(usb_trans_info_t)); @@ -994,6 +998,20 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent) usb_trans_info->request=request; se_tree_insert32(usb_conv_info->transactions, pinfo->fd->num, usb_trans_info); } + usb_conv_info->usb_trans_info=usb_trans_info; + pinfo->usb_conv_info=usb_conv_info; + + /* Try to find a class specific dissector */ + next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset)); + if(dissector_try_port(usb_control_dissector_table, usb_conv_info->class, next_tvb, pinfo, tree)){ + return; + } + + /* + * This was a standard request which is managed by this dissector + */ + proto_tree_add_item(setup_tree, hf_usb_request, tvb, offset, 1, TRUE); + offset += 1; if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); @@ -1021,6 +1039,8 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent) offset += 2; } } else { + tvbuff_t *next_tvb; + /* this is a response */ if(pinfo->fd->flags.visited){ usb_trans_info=se_tree_lookup32(usb_conv_info->transactions, pinfo->fd->num); @@ -1032,6 +1052,7 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent) } } if(usb_trans_info){ + usb_conv_info->usb_trans_info=usb_trans_info; dissector=NULL; for(tmp=setup_dissectors;tmp->dissector;tmp++){ if(tmp->request==usb_trans_info->request){ @@ -1039,7 +1060,15 @@ dissect_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent) break; } } - + + /* Try to find a class specific dissector */ + usb_conv_info->usb_trans_info=usb_trans_info; + pinfo->usb_conv_info=usb_conv_info; + next_tvb=tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset)); + if(dissector_try_port(usb_control_dissector_table, usb_conv_info->class, next_tvb, pinfo, tree)){ + return; + } + if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); col_append_fstr(pinfo->cinfo, COL_INFO, "%s Response", @@ -1334,6 +1363,9 @@ proto_register_usb(void) usb_bulk_dissector_table = register_dissector_table("usb.bulk", "USB bulk endpoint", FT_UINT8, BASE_DEC); + usb_control_dissector_table = register_dissector_table("usb.control", + "USB control endpoint", FT_UINT8, BASE_DEC); + } void diff --git a/epan/dissectors/packet-usb.h b/epan/dissectors/packet-usb.h index 972a1fcb95..2c55681d1d 100644 --- a/epan/dissectors/packet-usb.h +++ b/epan/dissectors/packet-usb.h @@ -24,12 +24,7 @@ #ifndef __PACKET_USB_H__ #define __PACKET_USB_H__ -/* there is one such structure for each device/endpoint conversation */ -typedef struct _usb_conv_info_t { - guint16 class; /* class for this conversation */ - emem_tree_t *transactions; - void *masstorage; /* mass storage data */ -} usb_conv_info_t; +typedef struct _usb_conv_info_t usb_conv_info_t; /* there is one such structure for each request/response */ typedef struct _usb_trans_info_t { @@ -54,6 +49,14 @@ typedef struct _usb_trans_info_t { usb_conv_info_t *interface_info; } usb_trans_info_t; +/* there is one such structure for each device/endpoint conversation */ +struct _usb_conv_info_t { + guint16 class; /* class for this conversation */ + emem_tree_t *transactions; + void *masstorage; /* mass storage data */ + usb_trans_info_t *usb_trans_info; /* pointer to the current transaction */ +}; + /* This is the endpoint number user for "no endpoint" or the fake endpoint * for the host side since we need two endpoints to manage conversations |