USB: Allow registering protocol specific dissectors

Formerly only the class specific dissectors could be registered for
bulk, control and interrupt endpoints. While this is sufficient for
major classes, there are some classes that only use one or two of
possible class/subclass/protocol triple values. Allow registering
specific triples so appropriate dissector can be automatically selected
based on CONFIGURATION DESCRIPTOR data.

Register DFU Run-Time and DFU Mode triples so user no longer needs to
manually set Decode As for USB DFU.
This commit is contained in:
Tomasz Moń 2022-12-06 10:35:09 +01:00
parent 74b1c07f91
commit bad5ae8c42
No known key found for this signature in database
GPG Key ID: 397DFEBE343AD96F
3 changed files with 42 additions and 3 deletions

View File

@ -551,6 +551,9 @@ proto_register_usb_dfu(void)
"Version of protocol supported by this dissector.");
}
#define RUNTIME_KEY USB_PROTOCOL_KEY(IF_CLASS_APPLICATION_SPECIFIC, IF_SUBCLASS_APP_DFU, IF_PROTOCOL_DFU_RUNTIME)
#define DFU_MODE_KEY USB_PROTOCOL_KEY(IF_CLASS_APPLICATION_SPECIFIC, IF_SUBCLASS_APP_DFU, IF_PROTOCOL_DFU_MODE)
void
proto_reg_handoff_usb_dfu(void)
{
@ -559,6 +562,9 @@ proto_reg_handoff_usb_dfu(void)
usf_dfu_descriptor_handle = create_dissector_handle(dissect_usb_dfu_descriptor, proto_usb_dfu);
dissector_add_uint("usb.descriptor", IF_CLASS_APPLICATION_SPECIFIC, usf_dfu_descriptor_handle);
dissector_add_uint("usb.control", RUNTIME_KEY, usb_dfu_handle);
dissector_add_uint("usb.control", DFU_MODE_KEY, usb_dfu_handle);
dissector_add_uint("usb.product", (0x1d50 << 16) | 0x1db5, usb_dfu_handle); /* IDBG in DFU mode */
dissector_add_uint("usb.product", (0x1d50 << 16) | 0x6001, usb_dfu_handle); /* Ubertooth Zero DFU */
dissector_add_uint("usb.product", (0x1d50 << 16) | 0x6003, usb_dfu_handle); /* Ubertooth One DFU */

View File

@ -3671,6 +3671,7 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin
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;
@ -3824,6 +3825,14 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin
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);
@ -3855,6 +3864,15 @@ try_dissect_next_protocol(proto_tree *tree, tvbuff_t *next_tvb, packet_info *pin
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;
@ -6954,13 +6972,13 @@ proto_register_usb(void)
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_UINT8, BASE_DEC);
"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_UINT8, BASE_DEC);
"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_UINT8, BASE_DEC);
"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);

View File

@ -211,6 +211,21 @@ typedef struct _usb_tap_data_t {
#define IF_SUBCLASS_MISC_U3V 0x05
#define IF_SUBCLASS_APP_DFU 0x01
#define IF_PROTOCOL_DFU_RUNTIME 0x01
#define IF_PROTOCOL_DFU_MODE 0x02
/* Key to be used with "usb.control", "usb.bulk" and/or "usb.interrupt"
* dissector tables when the dissector only applies to specific triple.
* Use class code directly if the code is not shared with other specifications.
*
* MSB (bit 31) is arbitrarily chosen to ensure class registered dissectors
* won't clash with protocol key.
*/
#define USB_PROTOCOL_KEY(class, subclass, protocol) \
(1u << 31 | (class & 0xff) << 16 | (subclass & 0xff) << 8 | (protocol & 0xff))
/* bmRequestType values */
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */