epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-usb-com.c
blobb7144083a895f0e82c1c4130bef680fbc32f5824
1 /* packet-usb-com.c
2 * Routines for USB Communications and CDC Control dissection
3 * Copyright 2013, Pascal Quantin <pascal@wireshark.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include <epan/follow.h>
17 #include <epan/conversation.h>
18 #include <epan/tfs.h>
19 #include <epan/unit_strings.h>
20 #include "packet-usb.h"
22 static int cdc_data_follow_tap;
23 static int proto_usb;
25 /* protocols and header fields */
26 static int proto_usb_com;
27 static int hf_usb_com_descriptor_subtype;
28 static int hf_usb_com_descriptor_cdc;
29 static int hf_usb_com_descriptor_payload;
30 static int hf_usb_com_control_subclass;
31 static int hf_usb_com_control_request_code;
32 static int hf_usb_com_control_value;
33 static int hf_usb_com_control_index;
34 static int hf_usb_com_control_length;
35 static int hf_usb_com_control_response_code;
36 static int hf_usb_com_control_payload;
37 static int hf_usb_com_get_ntb_params_length;
38 static int hf_usb_com_get_ntb_params_ntb_formats_supported;
39 static int hf_usb_com_get_ntb_params_ntb_formats_supported_16bit;
40 static int hf_usb_com_get_ntb_params_ntb_formats_supported_32bit;
41 static int hf_usb_com_get_ntb_params_ntb_in_max_size;
42 static int hf_usb_com_get_ntb_params_ndp_in_divisor;
43 static int hf_usb_com_get_ntb_params_ndp_in_payload_remainder;
44 static int hf_usb_com_get_ntb_params_ndp_in_alignment;
45 static int hf_usb_com_get_ntb_params_reserved;
46 static int hf_usb_com_get_ntb_params_ntb_out_max_size;
47 static int hf_usb_com_get_ntb_params_ndp_out_divisor;
48 static int hf_usb_com_get_ntb_params_ndp_out_payload_remainder;
49 static int hf_usb_com_get_ntb_params_ndp_out_alignment;
50 static int hf_usb_com_get_ntb_params_ntb_out_max_datagrams;
51 static int hf_usb_com_get_net_address_eui48;
52 static int hf_usb_com_set_net_address_eui48;
53 static int hf_usb_com_get_ntb_format_ntb_format;
54 static int hf_usb_com_set_ntb_format_ntb_format;
55 static int hf_usb_com_get_ntb_input_size_ntb_in_max_size;
56 static int hf_usb_com_get_ntb_input_size_ntb_in_max_datagrams;
57 static int hf_usb_com_get_ntb_input_size_reserved;
58 static int hf_usb_com_set_ntb_input_size_ntb_in_max_size;
59 static int hf_usb_com_set_ntb_input_size_ntb_in_max_datagrams;
60 static int hf_usb_com_set_ntb_input_size_reserved;
61 static int hf_usb_com_get_max_datagram_size_size;
62 static int hf_usb_com_set_max_datagram_size_size;
63 static int hf_usb_com_get_crc_mode_crc_mode;
64 static int hf_usb_com_set_crc_mode_crc_mode;
65 static int hf_usb_com_capabilities;
66 static int hf_usb_com_descriptor_acm_capabilities_reserved;
67 static int hf_usb_com_descriptor_acm_capabilities_network_connection;
68 static int hf_usb_com_descriptor_acm_capabilities_send_break;
69 static int hf_usb_com_descriptor_acm_capabilities_line_and_state;
70 static int hf_usb_com_descriptor_acm_capabilities_comm_features;
71 static int hf_usb_com_descriptor_control_interface;
72 static int hf_usb_com_descriptor_subordinate_interface;
73 static int hf_usb_com_descriptor_cm_capabilities_reserved;
74 static int hf_usb_com_descriptor_cm_capabilities_call_management_over_data_class_interface;
75 static int hf_usb_com_descriptor_cm_capabilities_call_management;
76 static int hf_usb_com_descriptor_cm_data_interface;
77 static int hf_usb_com_descriptor_ecm_mac_address;
78 static int hf_usb_com_descriptor_ecm_eth_stats;
79 static int hf_usb_com_descriptor_ecm_eth_stats_reserved;
80 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_late_collisions;
81 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_times_crs_lost;
82 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_heartbeat_failure;
83 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_underrun;
84 static int hf_usb_com_descriptor_ecm_eth_stats_rcv_overrun;
85 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_max_collisions;
86 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_deferred;
87 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_more_collisions;
88 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_one_collision;
89 static int hf_usb_com_descriptor_ecm_eth_stats_rcv_error_alignment;
90 static int hf_usb_com_descriptor_ecm_eth_stats_transmit_queue_length;
91 static int hf_usb_com_descriptor_ecm_eth_stats_rcv_crc_error;
92 static int hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_rcv;
93 static int hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_rcv;
94 static int hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_rcv;
95 static int hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_rcv;
96 static int hf_usb_com_descriptor_ecm_eth_stats_directed_frames_rcv;
97 static int hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_rcv;
98 static int hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_xmit;
99 static int hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_xmit;
100 static int hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_xmit;
101 static int hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_xmit;
102 static int hf_usb_com_descriptor_ecm_eth_stats_directed_frames_xmit;
103 static int hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_xmit;
104 static int hf_usb_com_descriptor_ecm_eth_stats_rcv_no_buffer;
105 static int hf_usb_com_descriptor_ecm_eth_stats_rcv_error;
106 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_error;
107 static int hf_usb_com_descriptor_ecm_eth_stats_rvc_ok;
108 static int hf_usb_com_descriptor_ecm_eth_stats_xmit_ok;
109 static int hf_usb_com_descriptor_ecm_max_segment_size;
110 static int hf_usb_com_descriptor_ecm_nb_mc_filters;
111 static int hf_usb_com_descriptor_ecm_nb_mc_filters_mc_address_filtering;
112 static int hf_usb_com_descriptor_ecm_nb_mc_filters_nb_filters_supported;
113 static int hf_usb_com_descriptor_ecm_nb_power_filters;
114 static int hf_usb_com_interrupt_request_type;
115 static int hf_usb_com_interrupt_notif_code;
116 static int hf_usb_com_interrupt_value;
117 static int hf_usb_com_interrupt_value_nw_conn;
118 static int hf_usb_com_interrupt_index;
119 static int hf_usb_com_interrupt_length;
120 static int hf_usb_com_interrupt_dl_bitrate;
121 static int hf_usb_com_interrupt_ul_bitrate;
122 static int hf_usb_com_interrupt_payload;
123 static int hf_usb_com_data_stream;
124 static int hf_usb_com_data_in_payload;
125 static int hf_usb_com_data_out_payload;
127 static int ett_usb_com;
128 static int ett_usb_com_capabilities;
129 static int ett_usb_com_bitmap;
130 static int ett_usb_com_descriptor_ecm_eth_stats;
131 static int ett_usb_com_descriptor_ecm_nb_mc_filters;
133 static dissector_handle_t usb_com_descriptor_handle;
134 static dissector_handle_t usb_com_control_handle;
135 static dissector_handle_t usb_com_bulk_handle;
136 static dissector_handle_t usb_com_interrupt_handle;
138 static dissector_handle_t mbim_control_handle;
139 static dissector_handle_t mbim_descriptor_handle;
140 static dissector_handle_t mbim_bulk_handle;
141 static dissector_handle_t eth_withoutfcs_handle;
143 static expert_field ei_unexpected_controlling_iface;
145 static wmem_tree_t* controlling_ifaces;
147 typedef struct _controlling_iface {
148 uint16_t interfaceClass;
149 uint16_t interfaceSubclass;
150 uint16_t interfaceProtocol;
151 } controlling_iface_t;
153 static uint32_t cdc_data_stream_count;
155 typedef struct _cdc_data_conv {
156 uint32_t stream;
157 } cdc_data_conv_t;
159 #define CS_INTERFACE 0x24
160 #define CS_ENDPOINT 0x25
162 static const value_string usb_com_descriptor_type_vals[] = {
163 { CS_INTERFACE, "CS_INTERFACE"},
164 { CS_ENDPOINT, "CS_ENDPOINT"},
165 { 0, NULL}
167 static value_string_ext usb_com_descriptor_type_vals_ext = VALUE_STRING_EXT_INIT(usb_com_descriptor_type_vals);
169 static const value_string usb_com_descriptor_subtype_vals[] = {
170 { 0x00, "Header Functional Descriptor"},
171 { 0x01, "Call Management Functional Descriptor"},
172 { 0x02, "Abstract Control Management Functional Descriptor"},
173 { 0x03, "Direct Line Management Functional Descriptor"},
174 { 0x04, "Telephone Ringer Functional Descriptor"},
175 { 0x05, "Telephone Call and Line State Reporting Capabilities Functional Descriptor"},
176 { 0x06, "Union Functional Descriptor"},
177 { 0x07, "Country Selection Functional Descriptor"},
178 { 0x08, "Telephone Operational Modes Functional Descriptor"},
179 { 0x09, "USB Terminal Functional Descriptor"},
180 { 0x0A, "Network Channel Terminal Descriptor"},
181 { 0x0B, "Protocol Unit Functional Descriptor"},
182 { 0x0C, "Extension Unit Functional Descriptor"},
183 { 0x0D, "Multi-Channel Management Functional Descriptor"},
184 { 0x0E, "CAPI Control Management Functional Descriptor"},
185 { 0x0F, "Ethernet Networking Functional Descriptor"},
186 { 0x10, "ATM Networking Functional Descriptor"},
187 { 0x11, "Wireless Handset Control Model Functional Descriptor"},
188 { 0x12, "Mobile Direct Line Model Functional Descriptor"},
189 { 0x13, "MDLM Detail Functional Descriptor"},
190 { 0x14, "Device Management Model Functional Descriptor"},
191 { 0x15, "OBEX Functional Descriptor"},
192 { 0x16, "Command Set Functional Descriptor"},
193 { 0x17, "Command Set Detail Functional Descriptor"},
194 { 0x18, "Telephone Control Model Functional Descriptor"},
195 { 0x19, "OBEX Service Identifier Functional Descriptor"},
196 { 0x1A, "NCM Functional Descriptor"},
197 { 0x1B, "MBIM Functional Descriptor"},
198 { 0x1C, "MBIM Extended Functional Descriptor"},
199 { 0, NULL}
201 static value_string_ext usb_com_descriptor_subtype_vals_ext = VALUE_STRING_EXT_INIT(usb_com_descriptor_subtype_vals);
203 #define COM_SUBCLASS_RESERVED 0x00
204 #define COM_SUBCLASS_DLCM 0x01
205 #define COM_SUBCLASS_ACM 0x02
206 #define COM_SUBCLASS_TCM 0x03
207 #define COM_SUBCLASS_MCCM 0x04
208 #define COM_SUBCLASS_CCM 0x05
209 #define COM_SUBCLASS_ENCM 0x06
210 #define COM_SUBCLASS_ANCM 0x07
211 #define COM_SUBCLASS_WHCM 0x08
212 #define COM_SUBCLASS_DM 0x09
213 #define COM_SUBCLASS_MDLM 0x0a
214 #define COM_SUBCLASS_OBEX 0x0b
215 #define COM_SUBCLASS_EEM 0x0c
216 #define COM_SUBCLASS_NCM 0x0d
217 #define COM_SUBCLASS_MBIM 0x0e
219 static const value_string usb_com_subclass_vals[] = {
220 {COM_SUBCLASS_RESERVED, "RESERVED"},
221 {COM_SUBCLASS_DLCM, "Direct Line Control Model"},
222 {COM_SUBCLASS_ACM, "Abstract Control Model"},
223 {COM_SUBCLASS_TCM, "Telephone Control Model"},
224 {COM_SUBCLASS_MCCM, "Multi-Channel Control Model"},
225 {COM_SUBCLASS_CCM, "CAPI Control Model"},
226 {COM_SUBCLASS_ENCM, "Ethernet Networking Control Model"},
227 {COM_SUBCLASS_ANCM, "ATM Networking Control Model"},
228 {COM_SUBCLASS_WHCM, "Wireless Handset Control Model"},
229 {COM_SUBCLASS_DM, "Device Management"},
230 {COM_SUBCLASS_MDLM, "Mobile Direct Line Model"},
231 {COM_SUBCLASS_OBEX, "OBEX"},
232 {COM_SUBCLASS_EEM, "Ethernet Emulation Model"},
233 {COM_SUBCLASS_NCM, "Network Control Model"},
234 {COM_SUBCLASS_MBIM, "Mobile Broadband Interface Model"},
235 {0, NULL}
237 value_string_ext ext_usb_com_subclass_vals = VALUE_STRING_EXT_INIT(usb_com_subclass_vals);
239 #define SEND_ENCAPSULATED_COMMAND 0x00
240 #define GET_ENCAPSULATED_RESPONSE 0x01
241 #define SET_COMM_FEATURE 0x02
242 #define GET_COMM_FEATURE 0x03
243 #define CLEAR_COMM_FEATURE 0x04
244 #define RESET_FUNCTION 0x05
245 #define SET_AUX_LINE_STATE 0x10
246 #define SET_HOOK_STATE 0x11
247 #define PULSE_SETUP 0x12
248 #define SEND_PULSE 0x13
249 #define SET_PULSE_TIME 0x14
250 #define RING_AUX_JACK 0x15
251 #define SET_LINE_CODING 0x20
252 #define GET_LINE_CODING 0x21
253 #define SET_CONTROL_LINE_STATE 0x22
254 #define SEND_BREAK 0x23
255 #define SET_RINGER_PARMS 0x30
256 #define GET_RINGER_PARMS 0x31
257 #define SET_OPERATION_PARMS 0x32
258 #define GET_OPERATION_PARMS 0x33
259 #define SET_LINE_PARMS 0x34
260 #define GET_LINE_PARMS 0x35
261 #define DIAL_DIGITS 0x36
262 #define SET_UNIT_PARAMETER 0x37
263 #define GET_UNIT_PARAMETER 0x38
264 #define CLEAR_UNIT_PARAMETER 0x39
265 #define GET_PROFILE 0x3a
266 #define SET_ETHERNET_MULTICAST_FILTERS 0x40
267 #define SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x41
268 #define GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x42
269 #define SET_ETHERNET_PACKET_FILTER 0x43
270 #define GET_ETHERNET_STATISTIC 0x44
271 #define SET_ATM_DATA_FORMAT 0x50
272 #define GET_ATM_DEVICE_STATISTICS 0x51
273 #define SET_ATM_DEFAULT_VC 0x52
274 #define GET_ATM_VC_STATISTICS 0x53
275 #define GET_NTB_PARAMETERS 0x80
276 #define GET_NET_ADDRESS 0x81
277 #define SET_NET_ADDRESS 0x82
278 #define GET_NTB_FORMAT 0x83
279 #define SET_NTB_FORMAT 0x84
280 #define GET_NTB_INPUT_SIZE 0x85
281 #define SET_NTB_INPUT_SIZE 0x86
282 #define GET_MAX_DATAGRAM_SIZE 0x87
283 #define SET_MAX_DATAGRAM_SIZE 0x88
284 #define GET_CRC_MODE 0x89
285 #define SET_CRC_MODE 0x8a
287 static const value_string usb_com_setup_request_vals[] = {
288 {SEND_ENCAPSULATED_COMMAND, "SEND ENCAPSULATED COMMAND"},
289 {GET_ENCAPSULATED_RESPONSE, "GET ENCAPSULATED RESPONSE"},
290 {SET_COMM_FEATURE, "SET COMM FEATURE"},
291 {GET_COMM_FEATURE, "GET COMM FEATURE"},
292 {CLEAR_COMM_FEATURE, "CLEAR COMM FEATURE"},
293 {RESET_FUNCTION, "RESET FUNCTION"},
294 {SET_AUX_LINE_STATE, "SET AUX LINE STATE"},
295 {SET_HOOK_STATE, "SET HOOK STATE"},
296 {PULSE_SETUP, "PULSE SETUP"},
297 {SEND_PULSE, "SEND PULSE"},
298 {SET_PULSE_TIME, "SET PULSE TIME"},
299 {RING_AUX_JACK, "RING AUX JACK"},
300 {SET_LINE_CODING, "SET LINE CODING"},
301 {GET_LINE_CODING, "GET LINE CODING"},
302 {SET_CONTROL_LINE_STATE, "SET CONTROL LINE STATE"},
303 {SEND_BREAK, "SEND BREAK"},
304 {SET_RINGER_PARMS, "SET RINGER PARMS"},
305 {GET_RINGER_PARMS, "GET RINGER PARMS"},
306 {SET_OPERATION_PARMS, "SET OPERATION PARMS"},
307 {GET_OPERATION_PARMS, "GET OPERATION PARMS"},
308 {SET_LINE_PARMS, "SET LINE PARMS"},
309 {GET_LINE_PARMS, "GET LINE PARMS"},
310 {DIAL_DIGITS, "DIAL DIGITS"},
311 {SET_UNIT_PARAMETER, "SET UNIT PARAMETER"},
312 {GET_UNIT_PARAMETER, "GET UNIT PARAMETER"},
313 {CLEAR_UNIT_PARAMETER, "CLEAR UNIT PARAMETER"},
314 {GET_PROFILE, "GET PROFILE"},
315 {SET_ETHERNET_MULTICAST_FILTERS, "SET ETHERNET MULTICAST FILTERS"},
316 {SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER, "SET ETHERNET POWER MANAGEMENT PATTERN FILTER"},
317 {GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER, "GET ETHERNET POWER MANAGEMENT PATTERN FILTER"},
318 {SET_ETHERNET_PACKET_FILTER, "SET ETHERNET PACKET FILTER"},
319 {GET_ETHERNET_STATISTIC, "GET ETHERNET STATISTIC"},
320 {SET_ATM_DATA_FORMAT, "SET ATM DATA FORMAT"},
321 {GET_ATM_DEVICE_STATISTICS, "GET ATM DEVICE STATISTICS"},
322 {SET_ATM_DEFAULT_VC, "SET ATM DEFAULT VC"},
323 {GET_ATM_VC_STATISTICS, "GET ATM VC STATISTICS"},
324 {GET_NTB_PARAMETERS, "GET NTB PARAMETERS"},
325 {GET_NET_ADDRESS, "GET NET ADDRESS"},
326 {SET_NET_ADDRESS, "SET NET ADDRESS"},
327 {GET_NTB_FORMAT, "GET NTB FORMAT"},
328 {SET_NTB_FORMAT, "SET NTB FORMAT"},
329 {GET_NTB_INPUT_SIZE, "GET NTB INPUT SIZE"},
330 {SET_NTB_INPUT_SIZE, "SET NTB INPUT SIZE"},
331 {GET_MAX_DATAGRAM_SIZE, "GET MAX DATAGRAM SIZE"},
332 {SET_MAX_DATAGRAM_SIZE, "SET MAX DATAGRAM SIZE"},
333 {GET_CRC_MODE, "GET CRC MODE"},
334 {SET_CRC_MODE, "SET CRC MODE"},
335 {0, NULL}
337 static value_string_ext usb_com_setup_request_vals_ext = VALUE_STRING_EXT_INIT(usb_com_setup_request_vals);
339 static int * const usb_com_get_ntb_params_ntb_formats_supported_fields[] = {
340 &hf_usb_com_get_ntb_params_ntb_formats_supported_16bit,
341 &hf_usb_com_get_ntb_params_ntb_formats_supported_32bit,
342 NULL
345 static const value_string usb_com_ntb_format_vals[] = {
346 { 0x0000, "NTB-16"},
347 { 0x0001, "NTB-32"},
348 {0, NULL}
351 static const value_string usb_com_crc_mode_vals[] = {
352 { 0x0000, "CRCs shall not be appended"},
353 { 0x0001, "CRCs shall be appended"},
354 {0, NULL}
357 static int * const ecm_eth_stats[] = {
358 &hf_usb_com_descriptor_ecm_eth_stats_reserved,
359 &hf_usb_com_descriptor_ecm_eth_stats_xmit_late_collisions,
360 &hf_usb_com_descriptor_ecm_eth_stats_xmit_times_crs_lost,
361 &hf_usb_com_descriptor_ecm_eth_stats_xmit_heartbeat_failure,
362 &hf_usb_com_descriptor_ecm_eth_stats_xmit_underrun,
363 &hf_usb_com_descriptor_ecm_eth_stats_rcv_overrun,
364 &hf_usb_com_descriptor_ecm_eth_stats_xmit_max_collisions,
365 &hf_usb_com_descriptor_ecm_eth_stats_xmit_deferred,
366 &hf_usb_com_descriptor_ecm_eth_stats_xmit_more_collisions,
367 &hf_usb_com_descriptor_ecm_eth_stats_xmit_one_collision,
368 &hf_usb_com_descriptor_ecm_eth_stats_rcv_error_alignment,
369 &hf_usb_com_descriptor_ecm_eth_stats_transmit_queue_length,
370 &hf_usb_com_descriptor_ecm_eth_stats_rcv_crc_error,
371 &hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_rcv,
372 &hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_rcv,
373 &hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_rcv,
374 &hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_rcv,
375 &hf_usb_com_descriptor_ecm_eth_stats_directed_frames_rcv,
376 &hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_rcv,
377 &hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_xmit,
378 &hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_xmit,
379 &hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_xmit,
380 &hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_xmit,
381 &hf_usb_com_descriptor_ecm_eth_stats_directed_frames_xmit,
382 &hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_xmit,
383 &hf_usb_com_descriptor_ecm_eth_stats_rcv_no_buffer,
384 &hf_usb_com_descriptor_ecm_eth_stats_rcv_error,
385 &hf_usb_com_descriptor_ecm_eth_stats_xmit_error,
386 &hf_usb_com_descriptor_ecm_eth_stats_rvc_ok,
387 &hf_usb_com_descriptor_ecm_eth_stats_xmit_ok,
388 NULL
391 static const true_false_string usb_com_ecm_mc_address_filtering = {
392 "Imperfect",
393 "Perfect"
396 static int * const ecm_nb_mc_filters[] = {
397 &hf_usb_com_descriptor_ecm_nb_mc_filters_mc_address_filtering,
398 &hf_usb_com_descriptor_ecm_nb_mc_filters_nb_filters_supported,
399 NULL
402 #define NETWORK_CONNECTION 0x00
403 #define RESPONSE_AVAILABLE 0x01
404 #define AUX_JACK_HOOK_STATE 0x08
405 #define RING_DETECT 0x09
406 #define SERIAL_STATE 0x20
407 #define CALL_STATE_CHANGE 0x28
408 #define LINE_STATE_CHANGE 0x29
409 #define CONNECTION_SPEED_CHANGE 0x2a
411 static const value_string usb_com_interrupt_notif_code_vals[] = {
412 {NETWORK_CONNECTION, "NETWORK CONNECTION"},
413 {RESPONSE_AVAILABLE, "RESPONSE AVAILABLE"},
414 {AUX_JACK_HOOK_STATE, "AUX JACK HOOK STATE"},
415 {RING_DETECT, "RING DETECT"},
416 {SERIAL_STATE, "SERIAL STATE"},
417 {CALL_STATE_CHANGE, "CALL STATE CHANGE"},
418 {LINE_STATE_CHANGE, "LINE STATE CHANGE"},
419 {CONNECTION_SPEED_CHANGE, "CONNECTION SPEED CHANGE"},
420 {0, NULL}
423 static const value_string usb_com_interrupt_value_nw_conn_vals[] = {
424 {0, "Disconnect"},
425 {1, "Connected"},
426 {0, NULL}
429 void proto_register_usb_com(void);
430 void proto_reg_handoff_usb_com(void);
432 static int
433 dissect_usb_com_descriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
435 urb_info_t *urb = (urb_info_t *)data;
436 int offset = 0;
437 uint8_t type, subtype;
438 proto_tree *subtree;
439 proto_tree *subtree_capabilities;
440 proto_item *subitem_capabilities;
442 if (!urb) {
443 return 0;
446 subtree = proto_tree_add_subtree(tree, tvb, offset, tvb_captured_length(tvb), ett_usb_com, NULL, "COMMUNICATIONS DESCRIPTOR");
448 dissect_usb_descriptor_header(subtree, tvb, offset, &usb_com_descriptor_type_vals_ext);
449 offset += 2;
451 type = tvb_get_uint8(tvb, 1);
452 switch (type) {
453 case CS_INTERFACE:
454 subtype = tvb_get_uint8(tvb, offset);
455 proto_tree_add_uint(subtree, hf_usb_com_descriptor_subtype, tvb, offset, 1, subtype);
456 offset++;
457 switch (subtype) {
458 case 0x00:
459 proto_tree_add_item(subtree, hf_usb_com_descriptor_cdc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
460 offset += 2;
461 break;
462 case 0x01:
463 subitem_capabilities = proto_tree_add_item(subtree, hf_usb_com_capabilities, tvb, 3, 1, ENC_LITTLE_ENDIAN);
464 subtree_capabilities = proto_item_add_subtree(subitem_capabilities, ett_usb_com_capabilities);
466 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_cm_capabilities_reserved, tvb, 3, 1, ENC_LITTLE_ENDIAN);
467 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_cm_capabilities_call_management_over_data_class_interface, tvb, 3, 1, ENC_LITTLE_ENDIAN);
468 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_cm_capabilities_call_management, tvb, 3, 1, ENC_LITTLE_ENDIAN);
470 proto_tree_add_item(subtree, hf_usb_com_descriptor_cm_data_interface, tvb, 4, 1, ENC_LITTLE_ENDIAN);
471 offset = 5;
472 break;
473 case 0x02:
474 subitem_capabilities = proto_tree_add_item(subtree, hf_usb_com_capabilities, tvb, 3, 1, ENC_LITTLE_ENDIAN);
475 subtree_capabilities = proto_item_add_subtree(subitem_capabilities, ett_usb_com_capabilities);
477 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_reserved, tvb, 3, 1, ENC_LITTLE_ENDIAN);
478 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_network_connection, tvb, 3, 1, ENC_LITTLE_ENDIAN);
479 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_send_break, tvb, 3, 1, ENC_LITTLE_ENDIAN);
480 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_line_and_state, tvb, 3, 1, ENC_LITTLE_ENDIAN);
481 proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_comm_features, tvb, 3, 1, ENC_LITTLE_ENDIAN);
482 offset = 4;
483 break;
484 case 0x06: {
485 proto_item *control_item;
486 uint32_t k_bus_id;
487 uint32_t k_device_address;
488 uint32_t k_subordinate_id;
489 uint32_t k_frame_number;
490 wmem_tree_key_t key[] = {
491 { .length = 1, .key = &k_bus_id },
492 { .length = 1, .key = &k_device_address },
493 { .length = 1, .key = &k_subordinate_id },
494 { .length = 1, .key = &k_frame_number },
495 { .length = 0, .key = NULL },
497 controlling_iface_t *master_info = NULL;
498 uint32_t master;
500 k_bus_id = urb->bus_id;
501 k_device_address = urb->device_address;
502 k_frame_number = pinfo->num;
504 control_item = proto_tree_add_item_ret_uint(subtree, hf_usb_com_descriptor_control_interface, tvb, offset, 1, ENC_LITTLE_ENDIAN, &master);
506 if (master != urb->conv->interfaceNum) {
507 expert_add_info(pinfo, control_item, &ei_unexpected_controlling_iface);
508 } else if (!PINFO_FD_VISITED(pinfo)) {
509 master_info = wmem_new(wmem_file_scope(), controlling_iface_t);
510 master_info->interfaceClass = urb->conv->interfaceClass;
511 master_info->interfaceSubclass = urb->conv->interfaceSubclass;
512 master_info->interfaceProtocol = urb->conv->interfaceProtocol;
515 offset += 1;
516 while (tvb_reported_length_remaining(tvb,offset) > 0) {
517 proto_tree_add_item_ret_uint(subtree, hf_usb_com_descriptor_subordinate_interface, tvb, offset, 1, ENC_LITTLE_ENDIAN, &k_subordinate_id);
518 offset += 1;
520 if (master_info) {
521 wmem_tree_insert32_array(controlling_ifaces, key, master_info);
524 break;
526 case 0x0f:
527 proto_tree_add_item(subtree, hf_usb_com_descriptor_ecm_mac_address, tvb, offset, 1, ENC_LITTLE_ENDIAN);
528 offset += 1;
529 proto_tree_add_bitmask_with_flags(subtree, tvb, offset, hf_usb_com_descriptor_ecm_eth_stats,
530 ett_usb_com_descriptor_ecm_eth_stats, ecm_eth_stats,
531 ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
532 offset += 4;
533 proto_tree_add_item(subtree, hf_usb_com_descriptor_ecm_max_segment_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
534 offset += 2;
535 proto_tree_add_bitmask_with_flags(subtree, tvb, offset, hf_usb_com_descriptor_ecm_nb_mc_filters,
536 ett_usb_com_descriptor_ecm_nb_mc_filters, ecm_nb_mc_filters,
537 ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
538 offset += 2;
539 proto_tree_add_item(subtree, hf_usb_com_descriptor_ecm_nb_power_filters, tvb, offset, 1, ENC_LITTLE_ENDIAN);
540 offset += 1;
541 break;
542 case 0x1b:
543 case 0x1c:
544 offset = call_dissector_only(mbim_descriptor_handle, tvb, pinfo, subtree, data);
545 break;
546 default:
547 break;
549 break;
550 case CS_ENDPOINT:
551 default:
552 break;
555 if (tvb_reported_length_remaining(tvb, offset) > 0) {
556 proto_tree_add_item(subtree, hf_usb_com_descriptor_payload, tvb, offset, -1, ENC_NA);
558 return tvb_captured_length(tvb);
561 static int
562 dissect_usb_com_get_ntb_params(tvbuff_t *tvb, proto_tree *tree, int base_offset)
564 int offset = base_offset;
566 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
567 offset += 2;
568 proto_tree_add_bitmask(tree, tvb, offset, hf_usb_com_get_ntb_params_ntb_formats_supported, ett_usb_com_bitmap,
569 usb_com_get_ntb_params_ntb_formats_supported_fields, ENC_LITTLE_ENDIAN);
570 offset += 2;
571 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ntb_in_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
572 offset += 4;
573 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_in_divisor, tvb, offset, 2, ENC_LITTLE_ENDIAN);
574 offset += 2;
575 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_in_payload_remainder, tvb, offset, 2, ENC_LITTLE_ENDIAN);
576 offset += 2;
577 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_in_alignment, tvb, offset, 2, ENC_LITTLE_ENDIAN);
578 offset += 2;
579 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
580 offset += 2;
581 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ntb_out_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
582 offset += 4;
583 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_out_divisor, tvb, offset, 2, ENC_LITTLE_ENDIAN);
584 offset += 2;
585 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_out_payload_remainder, tvb, offset, 2, ENC_LITTLE_ENDIAN);
586 offset += 2;
587 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_out_alignment, tvb, offset, 2, ENC_LITTLE_ENDIAN);
588 offset += 2;
589 proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ntb_out_max_datagrams, tvb, offset, 2, ENC_LITTLE_ENDIAN);
590 offset += 2;
592 return offset;
595 static int
596 dissect_usb_com_ntb_input_size(tvbuff_t *tvb, proto_tree *tree, int base_offset, bool is_set)
598 int offset = base_offset;
600 proto_tree_add_item(tree, is_set ? hf_usb_com_set_ntb_input_size_ntb_in_max_size :
601 hf_usb_com_get_ntb_input_size_ntb_in_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
602 offset += 4;
603 if (tvb_reported_length_remaining(tvb, offset) > 0) {
604 proto_tree_add_item(tree, is_set ? hf_usb_com_set_ntb_input_size_ntb_in_max_datagrams :
605 hf_usb_com_get_ntb_input_size_ntb_in_max_datagrams, tvb, offset, 2, ENC_LITTLE_ENDIAN);
606 offset += 2;
607 proto_tree_add_item(tree, is_set ? hf_usb_com_set_ntb_input_size_reserved :
608 hf_usb_com_get_ntb_input_size_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
609 offset += 2;
612 return offset;
615 static int
616 dissect_usb_com_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
618 urb_info_t *urb = (urb_info_t *)data;
619 usb_trans_info_t *usb_trans_info;
620 proto_tree *subtree;
621 proto_item *ti;
622 int offset = 0;
623 bool is_request;
625 if (tvb_reported_length(tvb) == 0) {
626 return 0;
629 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCOM");
631 ti = proto_tree_add_item(tree, proto_usb_com, tvb, 0, -1, ENC_NA);
632 subtree = proto_item_add_subtree(ti, ett_usb_com);
634 if (urb) {
635 usb_trans_info = urb->usb_trans_info;
637 ti = proto_tree_add_uint(subtree, hf_usb_com_control_subclass, tvb, 0, 0,
638 urb->conv->interfaceSubclass);
639 proto_item_set_generated(ti);
641 is_request = (pinfo->srcport==NO_ENDPOINT);
642 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
643 val_to_str_ext(usb_trans_info->setup.request, &usb_com_setup_request_vals_ext, "Unknown type %x"),
644 is_request ? "Request" : "Response");
646 if (is_request) {
647 proto_tree_add_item(subtree, hf_usb_com_control_request_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
648 offset += 1;
649 proto_tree_add_item(subtree, hf_usb_com_control_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
650 offset += 2;
651 proto_tree_add_item(subtree, hf_usb_com_control_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
652 offset += 2;
653 proto_tree_add_item(subtree, hf_usb_com_control_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
654 offset += 2;
655 } else {
656 ti = proto_tree_add_uint(subtree, hf_usb_com_control_response_code, tvb, 0, 0,
657 usb_trans_info->setup.request);
658 proto_item_set_generated(ti);
661 switch (usb_trans_info->setup.request)
663 case SEND_ENCAPSULATED_COMMAND:
664 if ((urb->conv->interfaceSubclass == COM_SUBCLASS_MBIM) && is_request) {
665 tvbuff_t *mbim_tvb = tvb_new_subset_remaining(tvb, offset);
666 offset += call_dissector_only(mbim_control_handle, mbim_tvb, pinfo, tree, urb);
668 break;
669 case GET_ENCAPSULATED_RESPONSE:
670 if ((urb->conv->interfaceSubclass == COM_SUBCLASS_MBIM) && !is_request) {
671 offset += call_dissector_only(mbim_control_handle, tvb, pinfo, tree, urb);
673 break;
674 case GET_NTB_PARAMETERS:
675 if (!is_request) {
676 offset = dissect_usb_com_get_ntb_params(tvb, subtree, offset);
678 break;
679 case GET_NET_ADDRESS:
680 if (!is_request) {
681 proto_tree_add_item(subtree, hf_usb_com_get_net_address_eui48, tvb, offset, 6, ENC_NA);
682 offset += 6;
684 break;
685 case SET_NET_ADDRESS:
686 if (is_request) {
687 proto_tree_add_item(subtree, hf_usb_com_set_net_address_eui48, tvb, offset, 6, ENC_NA);
688 offset += 6;
690 break;
691 case GET_NTB_FORMAT:
692 if (!is_request) {
693 proto_tree_add_item(subtree, hf_usb_com_get_ntb_format_ntb_format, tvb, offset, 2, ENC_LITTLE_ENDIAN);
694 offset += 2;
696 break;
697 case SET_NTB_FORMAT:
698 if (is_request) {
699 proto_tree_add_item(subtree, hf_usb_com_set_ntb_format_ntb_format, tvb, offset-6, 2, ENC_LITTLE_ENDIAN);
701 break;
702 case GET_NTB_INPUT_SIZE:
703 if (!is_request) {
704 offset = dissect_usb_com_ntb_input_size(tvb, subtree, offset, false);
706 break;
707 case SET_NTB_INPUT_SIZE:
708 if (!is_request) {
709 offset = dissect_usb_com_ntb_input_size(tvb, subtree, offset, true);
711 break;
712 case GET_MAX_DATAGRAM_SIZE:
713 if (!is_request) {
714 proto_tree_add_item(subtree, hf_usb_com_get_max_datagram_size_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
715 offset += 2;
717 break;
718 case SET_MAX_DATAGRAM_SIZE:
719 if (is_request) {
720 proto_tree_add_item(subtree, hf_usb_com_set_max_datagram_size_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
721 offset += 2;
723 break;
724 case GET_CRC_MODE:
725 if (!is_request) {
726 proto_tree_add_item(subtree, hf_usb_com_get_crc_mode_crc_mode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
727 offset += 2;
729 break;
730 case SET_CRC_MODE:
731 if (is_request) {
732 proto_tree_add_item(subtree, hf_usb_com_set_crc_mode_crc_mode, tvb, offset-6, 2, ENC_LITTLE_ENDIAN);
734 break;
735 default:
736 break;
740 if (tvb_reported_length_remaining(tvb, offset) > 0) {
741 proto_tree_add_item(subtree, hf_usb_com_control_payload, tvb, offset, -1, ENC_NA);
743 return tvb_captured_length(tvb);
746 static int
747 dissect_usb_com_bulk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
749 urb_info_t *urb = (urb_info_t *)data;
750 usb_conv_info_t *usb_conv_info;
751 cdc_data_conv_t *cdc_data_info;
752 uint32_t k_bus_id;
753 uint32_t k_device_address;
754 uint32_t k_subordinate_id;
755 wmem_tree_key_t key[] = {
756 { .length = 1, .key = &k_bus_id },
757 { .length = 1, .key = &k_device_address },
758 { .length = 1, .key = &k_subordinate_id },
759 { .length = 0, .key = NULL },
761 wmem_tree_t *wmem_tree;
762 controlling_iface_t *master_iface = NULL;
763 proto_tree *subtree;
764 proto_item *item;
766 if (!urb || !urb->conv) {
767 return 0;
770 usb_conv_info = urb->conv;
772 if ((usb_conv_info->interfaceClass != IF_CLASS_CDC_DATA) || (usb_conv_info->interfaceSubclass != 0)) {
773 /* As per Communications Device Class Revision 1.2 subclass is currently unused for CDC Data and should be zero
774 * If it is not, then we are either dealing with malformed descriptor or a new CDC Revision.
776 return 0;
779 /* Generic handling to allow follow stream functionality regardless if data
780 * is passed to higher layer dissector or not.
782 cdc_data_info = (cdc_data_conv_t *)usb_conv_info->class_data;
783 if (!cdc_data_info) {
784 cdc_data_info = wmem_new(wmem_file_scope(), cdc_data_conv_t);
785 cdc_data_info->stream = cdc_data_stream_count++;
786 usb_conv_info->class_data = cdc_data_info;
787 usb_conv_info->class_data_type = USB_CONV_CDC_DATA;
788 } else if (usb_conv_info->class_data_type != USB_CONV_CDC_DATA) {
789 /* Don't dissect if another USB type is in the conversation */
790 return 0;
793 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCOM");
795 item = proto_tree_add_item(tree, proto_usb_com, tvb, 0, -1, ENC_NA);
796 subtree = proto_item_add_subtree(item, ett_usb_com);
798 item = proto_tree_add_uint(subtree, hf_usb_com_data_stream, tvb, 0, 0, cdc_data_info->stream);
799 proto_item_set_generated(item);
801 if (pinfo->p2p_dir == P2P_DIR_RECV) {
802 proto_tree_add_item(subtree, hf_usb_com_data_in_payload, tvb, 0, -1, ENC_NA);
803 } else {
804 proto_tree_add_item(subtree, hf_usb_com_data_out_payload, tvb, 0, -1, ENC_NA);
807 if (have_tap_listener(cdc_data_follow_tap)) {
808 tap_queue_packet(cdc_data_follow_tap, pinfo, tvb);
811 k_bus_id = urb->bus_id;
812 k_device_address = urb->device_address;
813 k_subordinate_id = usb_conv_info->interfaceNum;
815 wmem_tree = (wmem_tree_t*)wmem_tree_lookup32_array(controlling_ifaces, key);
816 if (wmem_tree) {
817 master_iface = (controlling_iface_t *)wmem_tree_lookup32_le(wmem_tree, pinfo->num);
820 if (master_iface) {
821 if (master_iface->interfaceClass == IF_CLASS_COMMUNICATIONS) {
822 if ((master_iface->interfaceSubclass == COM_SUBCLASS_ENCM) &&
823 (master_iface->interfaceProtocol == 0) &&
824 (usb_conv_info->interfaceProtocol == 0)) {
825 /* Ethernet without FCS */
826 return call_dissector_only(eth_withoutfcs_handle, tvb, pinfo, tree, NULL);
832 switch (usb_conv_info->interfaceProtocol) {
833 case 0x01: /* Network Transfer Block */
834 case 0x02: /* Network Transfer Block (IP + DSS) */
835 return call_dissector_only(mbim_bulk_handle, tvb, pinfo, tree, NULL);
836 default:
837 break;
840 /* Unknown (class, subclass, protocol) tuple. No further dissection. */
841 return tvb_captured_length(tvb);
844 static int
845 dissect_usb_com_interrupt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
847 proto_tree *subtree;
848 proto_item *it;
849 uint32_t notif_code;
850 int offset = 0;
852 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCOM");
854 it = proto_tree_add_item(tree, proto_usb_com, tvb, 0, -1, ENC_NA);
855 subtree = proto_item_add_subtree(it, ett_usb_com);
857 proto_tree_add_item(subtree, hf_usb_com_interrupt_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
858 offset++;
859 proto_tree_add_item_ret_uint(subtree, hf_usb_com_interrupt_notif_code, tvb, offset, 1, ENC_LITTLE_ENDIAN, &notif_code);
860 offset++;
861 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(notif_code, usb_com_interrupt_notif_code_vals, "Unknown type %x"));
862 switch (notif_code) {
863 case NETWORK_CONNECTION:
864 proto_tree_add_item(subtree, hf_usb_com_interrupt_value_nw_conn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
865 offset += 2;
866 proto_tree_add_item(subtree, hf_usb_com_interrupt_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
867 offset += 2;
868 proto_tree_add_item(subtree, hf_usb_com_interrupt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
869 offset += 2;
870 break;
871 case RESPONSE_AVAILABLE:
872 proto_tree_add_item(subtree, hf_usb_com_interrupt_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
873 offset += 2;
874 proto_tree_add_item(subtree, hf_usb_com_interrupt_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
875 offset += 2;
876 proto_tree_add_item(subtree, hf_usb_com_interrupt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
877 offset += 2;
878 break;
879 case CONNECTION_SPEED_CHANGE:
880 proto_tree_add_item(subtree, hf_usb_com_interrupt_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
881 offset += 2;
882 proto_tree_add_item(subtree, hf_usb_com_interrupt_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
883 offset += 2;
884 proto_tree_add_item(subtree, hf_usb_com_interrupt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
885 offset += 2;
886 proto_tree_add_item(subtree, hf_usb_com_interrupt_dl_bitrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
887 offset += 4;
888 proto_tree_add_item(subtree, hf_usb_com_interrupt_ul_bitrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
889 offset += 4;
890 break;
891 default:
892 break;
895 if (tvb_reported_length_remaining(tvb, offset) > 0) {
896 proto_tree_add_item(subtree, hf_usb_com_interrupt_payload, tvb, offset, -1, ENC_NA);
898 return tvb_captured_length(tvb);
901 static cdc_data_conv_t *get_cdc_data_conv(packet_info *pinfo)
903 conversation_t *conversation;
904 usb_conv_info_t *usb_conv_info;
906 if (pinfo->ptype != PT_USB) {
907 return NULL;
910 conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_USB,
911 pinfo->srcport, pinfo->destport, 0);
912 if (!conversation) {
913 return NULL;
916 usb_conv_info = (usb_conv_info_t *)conversation_get_proto_data(conversation, proto_usb);
917 if (!usb_conv_info || (usb_conv_info->class_data_type != USB_CONV_CDC_DATA)) {
918 return NULL;
921 return (cdc_data_conv_t *)usb_conv_info->class_data;
924 static char *cdc_data_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream _U_)
926 cdc_data_conv_t *cdc_data_info;
928 cdc_data_info = get_cdc_data_conv(pinfo);
929 if (cdc_data_info) {
930 *stream = cdc_data_info->stream;
931 return ws_strdup_printf("usbcom.data.stream eq %u", cdc_data_info->stream);
934 return NULL;
937 static char *cdc_data_follow_index_filter(unsigned stream, unsigned sub_stream _U_)
939 return ws_strdup_printf("usbcom.data.stream eq %u", stream);
942 static char *cdc_data_follow_address_filter(address *src_addr _U_, address *dst_addr _U_, int src_port _U_, int dst_port _U_)
944 /* We always just filter stream based on an arbitrarily generated index. */
945 return NULL;
948 static char *cdc_data_port_to_display(wmem_allocator_t *allocator, unsigned port)
950 return wmem_strdup(allocator, port == NO_ENDPOINT ? "host" : "device");
953 static tap_packet_status
954 follow_cdc_data_tap_listener(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
955 const void *data, tap_flags_t flags _U_)
957 follow_record_t *follow_record;
958 follow_info_t *follow_info = (follow_info_t *)tapdata;
959 tvbuff_t *tvb = (tvbuff_t *)data;
960 uint32_t data_length = tvb_captured_length(tvb);
961 bool is_server;
963 if (follow_info->client_port == 0) {
964 /* XXX: Client/Server does not quite match how USB works. Simply assume
965 * that host is "server" but it is important to note that client port
966 * will be set to either IN or OUT endpoint (whichever transmits data
967 * first). Client "receive" is OUT endpoint while client "transmit" is
968 * IN endpoint. The "other end" is always host.
970 if (pinfo->srcport == NO_ENDPOINT) {
971 follow_info->client_port = pinfo->destport;
972 copy_address(&follow_info->client_ip, &pinfo->dst);
973 follow_info->server_port = pinfo->srcport;
974 copy_address(&follow_info->server_ip, &pinfo->src);
975 } else {
976 follow_info->client_port = pinfo->srcport;
977 copy_address(&follow_info->client_ip, &pinfo->src);
978 follow_info->server_port = pinfo->destport;
979 copy_address(&follow_info->server_ip, &pinfo->dst);
983 is_server = pinfo->srcport == NO_ENDPOINT;
985 follow_record = g_new0(follow_record_t, 1);
986 follow_record->is_server = is_server;
987 follow_record->packet_num = pinfo->fd->num;
988 follow_record->abs_ts = pinfo->fd->abs_ts;
989 follow_record->data = g_byte_array_append(g_byte_array_new(),
990 tvb_get_ptr(tvb, 0, data_length),
991 data_length);
993 follow_info->bytes_written[is_server] += follow_record->data->len;
994 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
996 return TAP_PACKET_DONT_REDRAW;
999 static uint32_t get_cdc_data_stream_count(void)
1001 return cdc_data_stream_count;
1004 static void
1005 usb_com_cleanup_data(void)
1007 cdc_data_stream_count = 0;
1010 void
1011 proto_register_usb_com(void)
1013 static hf_register_info hf[] = {
1014 { &hf_usb_com_descriptor_subtype,
1015 { "Descriptor Subtype", "usbcom.descriptor.subtype", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1016 &usb_com_descriptor_subtype_vals_ext, 0, NULL, HFILL }},
1017 { &hf_usb_com_descriptor_cdc,
1018 { "CDC", "usbcom.descriptor.cdc", FT_UINT16, BASE_HEX,
1019 NULL, 0, NULL, HFILL }},
1020 { &hf_usb_com_descriptor_payload,
1021 { "Payload", "usbcom.descriptor.payload", FT_BYTES, BASE_NONE,
1022 NULL, 0, NULL, HFILL }},
1023 { &hf_usb_com_control_subclass,
1024 { "Subclass", "usbcom.control.subclass", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1025 &ext_usb_com_subclass_vals, 0, NULL, HFILL }},
1026 { &hf_usb_com_control_request_code,
1027 { "Request Code", "usbcom.control.request_code", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1028 &usb_com_setup_request_vals_ext, 0, NULL, HFILL }},
1029 { &hf_usb_com_control_value,
1030 { "Value", "usbcom.control.value", FT_UINT16, BASE_DEC,
1031 NULL, 0, NULL, HFILL }},
1032 { &hf_usb_com_control_index,
1033 { "Index", "usbcom.control.index", FT_UINT16, BASE_DEC,
1034 NULL, 0, NULL, HFILL }},
1035 { &hf_usb_com_control_length,
1036 { "Length", "usbcom.control.length", FT_UINT16, BASE_DEC,
1037 NULL, 0, NULL, HFILL }},
1038 { &hf_usb_com_control_response_code,
1039 { "Response Code", "usbcom.control.response_code", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1040 &usb_com_setup_request_vals_ext, 0, NULL, HFILL }},
1041 { &hf_usb_com_get_ntb_params_length,
1042 { "Length", "usbcom.control.get_ntb_params.length", FT_UINT16, BASE_DEC,
1043 NULL, 0, NULL, HFILL }},
1044 { &hf_usb_com_get_ntb_params_ntb_formats_supported,
1045 { "NTB Formats Supported", "usbcom.control.get_ntb_params.ntb_formats_supported", FT_UINT16, BASE_HEX,
1046 NULL, 0, NULL, HFILL }},
1047 { &hf_usb_com_get_ntb_params_ntb_formats_supported_16bit,
1048 { "16-bit NTB", "usbcom.control.get_ntb_params.ntb_formats_supported.16bit", FT_BOOLEAN, 16,
1049 TFS(&tfs_supported_not_supported), 0x0001, NULL, HFILL }},
1050 { &hf_usb_com_get_ntb_params_ntb_formats_supported_32bit,
1051 { "32-bit NTB", "usbcom.control.get_ntb_params.ntb_formats_supported.32bit", FT_BOOLEAN, 16,
1052 TFS(&tfs_supported_not_supported), 0x0002, NULL, HFILL }},
1053 { &hf_usb_com_get_ntb_params_ntb_in_max_size,
1054 { "NTB IN Max Size", "usbcom.control.get_ntb_params.ntb_in_max_size", FT_UINT32, BASE_DEC,
1055 NULL, 0, NULL, HFILL }},
1056 { &hf_usb_com_get_ntb_params_ndp_in_divisor,
1057 { "NDP IN Divisor", "usbcom.control.get_ntb_params.ndp_in_divisor", FT_UINT16, BASE_DEC,
1058 NULL, 0, NULL, HFILL }},
1059 { &hf_usb_com_get_ntb_params_ndp_in_payload_remainder,
1060 { "NDP IN Payload Remainder", "usbcom.control.get_ntb_params.ndp_in_payload_remainder", FT_UINT16, BASE_DEC,
1061 NULL, 0, NULL, HFILL }},
1062 { &hf_usb_com_get_ntb_params_ndp_in_alignment,
1063 { "NDP IN Alignment", "usbcom.control.get_ntb_params.ndp_in_alignment", FT_UINT16, BASE_DEC,
1064 NULL, 0, NULL, HFILL }},
1065 { &hf_usb_com_get_ntb_params_reserved,
1066 { "Reserved", "usbcom.control.get_ntb_params.reserved", FT_UINT16, BASE_HEX,
1067 NULL, 0, NULL, HFILL }},
1068 { &hf_usb_com_get_ntb_params_ntb_out_max_size,
1069 { "NTB OUT Max Size", "usbcom.control.get_ntb_params.ntb_out_max_size", FT_UINT32, BASE_DEC,
1070 NULL, 0, NULL, HFILL }},
1071 { &hf_usb_com_get_ntb_params_ndp_out_divisor,
1072 { "NDP OUT Divisor", "usbcom.control.get_ntb_params.ndp_out_divisor", FT_UINT16, BASE_DEC,
1073 NULL, 0, NULL, HFILL }},
1074 { &hf_usb_com_get_ntb_params_ndp_out_payload_remainder,
1075 { "NDP OUT Payload Remainder", "usbcom.control.get_ntb_params.ndp_out_payload_remainder", FT_UINT16, BASE_DEC,
1076 NULL, 0, NULL, HFILL }},
1077 { &hf_usb_com_get_ntb_params_ndp_out_alignment,
1078 { "NDP OUT Alignment", "usbcom.control.get_ntb_params.ndp_out_alignment", FT_UINT16, BASE_DEC,
1079 NULL, 0, NULL, HFILL }},
1080 { &hf_usb_com_get_ntb_params_ntb_out_max_datagrams,
1081 { "NTB OUT Max Datagrams", "usbcom.control.get_ntb_params.ntb_out_max_datagrams", FT_UINT16, BASE_DEC,
1082 NULL, 0, NULL, HFILL }},
1083 { &hf_usb_com_get_net_address_eui48,
1084 { "EUI-48", "usbcom.control.get_net_address.eui48", FT_ETHER, BASE_NONE,
1085 NULL, 0, NULL, HFILL }},
1086 { &hf_usb_com_set_net_address_eui48,
1087 { "EUI-48", "usbcom.control.set_net_address.eui48", FT_ETHER, BASE_NONE,
1088 NULL, 0, NULL, HFILL }},
1089 { &hf_usb_com_get_ntb_format_ntb_format,
1090 { "NTB Format", "usbcom.control.get_net_address.ntb_format", FT_UINT16, BASE_HEX,
1091 VALS(usb_com_ntb_format_vals), 0, NULL, HFILL }},
1092 { &hf_usb_com_set_ntb_format_ntb_format,
1093 { "NTB Format", "usbcom.control.set_net_address.ntb_format", FT_UINT16, BASE_HEX,
1094 VALS(usb_com_ntb_format_vals), 0, NULL, HFILL }},
1095 { &hf_usb_com_get_ntb_input_size_ntb_in_max_size,
1096 { "NTB IN Max Size", "usbcom.control.get_ntb_input_size.ntb_in_max_size", FT_UINT32, BASE_DEC,
1097 NULL, 0, NULL, HFILL }},
1098 { &hf_usb_com_get_ntb_input_size_ntb_in_max_datagrams,
1099 { "NTB IN Max Datagrams", "usbcom.control.get_ntb_input_size.ntb_in_max_datagrams", FT_UINT16, BASE_DEC,
1100 NULL, 0, NULL, HFILL }},
1101 { &hf_usb_com_get_ntb_input_size_reserved,
1102 { "Reserved", "usbcom.control.get_ntb_input_size.reserved", FT_UINT16, BASE_HEX,
1103 NULL, 0, NULL, HFILL }},
1104 { &hf_usb_com_set_ntb_input_size_ntb_in_max_size,
1105 { "NTB IN Max Size", "usbcom.control.set_ntb_input_size.ntb_in_max_size", FT_UINT32, BASE_DEC,
1106 NULL, 0, NULL, HFILL }},
1107 { &hf_usb_com_set_ntb_input_size_ntb_in_max_datagrams,
1108 { "NTB IN Max Datagrams", "usbcom.control.set_ntb_input_size.ntb_in_max_datagrams", FT_UINT16, BASE_DEC,
1109 NULL, 0, NULL, HFILL }},
1110 { &hf_usb_com_set_ntb_input_size_reserved,
1111 { "Reserved", "usbcom.control.set_ntb_input_size.reserved", FT_UINT16, BASE_HEX,
1112 NULL, 0, NULL, HFILL }},
1113 { &hf_usb_com_get_max_datagram_size_size,
1114 { "Max Datagram Size", "usbcom.control.get_max_datagram_size.size", FT_UINT16, BASE_DEC,
1115 NULL, 0, NULL, HFILL }},
1116 { &hf_usb_com_set_max_datagram_size_size,
1117 { "Max Datagram Size", "usbcom.control.set_max_datagram_size.size", FT_UINT16, BASE_DEC,
1118 NULL, 0, NULL, HFILL }},
1119 { &hf_usb_com_get_crc_mode_crc_mode,
1120 { "CRC Mode", "usbcom.control.get_crc_mode.crc_mode", FT_UINT16, BASE_HEX,
1121 VALS(usb_com_crc_mode_vals), 0, NULL, HFILL }},
1122 { &hf_usb_com_set_crc_mode_crc_mode,
1123 { "CRC Mode", "usbcom.control.set_crc_mode.crc_mode", FT_UINT16, BASE_HEX,
1124 VALS(usb_com_crc_mode_vals), 0, NULL, HFILL }},
1125 { &hf_usb_com_control_payload,
1126 { "Payload", "usbcom.control.payload", FT_BYTES, BASE_NONE,
1127 NULL, 0, NULL, HFILL }},
1128 { &hf_usb_com_capabilities,
1129 { "bmCapabilities", "usbcom.descriptor.capabilities", FT_UINT8, BASE_HEX,
1130 NULL, 0, NULL, HFILL }},
1131 { &hf_usb_com_descriptor_acm_capabilities_reserved,
1132 { "Reserved", "usbcom.descriptor.acm.capabilities.reserved", FT_UINT8, BASE_HEX,
1133 NULL, 0xF0, NULL, HFILL }},
1134 { &hf_usb_com_descriptor_acm_capabilities_network_connection,
1135 { "Network_Connection", "usbcom.descriptor.acm.capabilities.network_connection", FT_BOOLEAN, 8,
1136 TFS(&tfs_supported_not_supported), 0x08, NULL, HFILL }},
1137 { &hf_usb_com_descriptor_acm_capabilities_send_break,
1138 { "Send_Break", "usbcom.descriptor.acm.capabilities.send_break", FT_BOOLEAN, 8,
1139 TFS(&tfs_supported_not_supported), 0x04, NULL, HFILL }},
1140 { &hf_usb_com_descriptor_acm_capabilities_line_and_state,
1141 { "Line Requests and State Notification", "usbcom.descriptor.acm.capabilities.line_and_state", FT_BOOLEAN, 8,
1142 TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
1143 { &hf_usb_com_descriptor_acm_capabilities_comm_features,
1144 { "Comm Features Combinations", "usbcom.descriptor.acm.capabilities.comm_features", FT_BOOLEAN, 8,
1145 TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
1146 { &hf_usb_com_descriptor_control_interface,
1147 { "Control Interface", "usbcom.descriptor.control_interface", FT_UINT8, BASE_HEX,
1148 NULL, 0, NULL, HFILL }},
1149 { &hf_usb_com_descriptor_subordinate_interface,
1150 { "Subordinate Interface", "usbcom.descriptor.subordinate_interface", FT_UINT8, BASE_HEX,
1151 NULL, 0, NULL, HFILL }},
1152 { &hf_usb_com_descriptor_cm_capabilities_reserved,
1153 { "Reserved", "usbcom.descriptor.cm.capabilities.reserved", FT_UINT8, BASE_HEX,
1154 NULL, 0xFC, NULL, HFILL }},
1155 { &hf_usb_com_descriptor_cm_capabilities_call_management_over_data_class_interface,
1156 { "Call Management over Data Class Interface", "usbcom.descriptor.cm.capabilities.call_management_over_data_class_interface", FT_BOOLEAN, 8,
1157 TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
1158 { &hf_usb_com_descriptor_cm_capabilities_call_management,
1159 { "Call Management", "usbcom.descriptor.cm.capabilities.call_management", FT_BOOLEAN, 8,
1160 TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
1161 { &hf_usb_com_descriptor_cm_data_interface,
1162 { "Data Interface", "usbcom.descriptor.cm.data_interface", FT_UINT8, BASE_HEX,
1163 NULL, 0, NULL, HFILL }},
1164 { &hf_usb_com_descriptor_ecm_mac_address,
1165 { "MAC Address", "usbcom.descriptor.ecm.mac_address", FT_UINT8, BASE_HEX,
1166 NULL, 0, NULL, HFILL }},
1167 { &hf_usb_com_descriptor_ecm_eth_stats,
1168 { "Ethernet Statistics", "usbcom.descriptor.ecm.eth_stats", FT_UINT32, BASE_HEX,
1169 NULL, 0, NULL, HFILL }},
1170 { &hf_usb_com_descriptor_ecm_eth_stats_reserved,
1171 { "Reserved", "usbcom.descriptor.ecm.eth_stats.reserved", FT_UINT32, BASE_HEX,
1172 NULL, 0xe0000000, NULL, HFILL }},
1173 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_late_collisions,
1174 { "XMIT Late Collisions", "usbcom.descriptor.ecm.eth_stats.xmit_late_collisions", FT_BOOLEAN, 32,
1175 TFS(&tfs_supported_not_supported), 0x10000000, NULL, HFILL }},
1176 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_times_crs_lost,
1177 { "XMIT TImes CRS Lost", "usbcom.descriptor.ecm.eth_stats.xmit_times_crs_lost", FT_BOOLEAN, 32,
1178 TFS(&tfs_supported_not_supported), 0x08000000, NULL, HFILL }},
1179 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_heartbeat_failure,
1180 { "XMIT Heartbeat Failure", "usbcom.descriptor.ecm.eth_stats.xmit_heartbeat_failure", FT_BOOLEAN, 32,
1181 TFS(&tfs_supported_not_supported), 0x04000000, NULL, HFILL }},
1182 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_underrun,
1183 { "XMIT Underrun", "usbcom.descriptor.ecm.eth_stats.xmit_underrun", FT_BOOLEAN, 32,
1184 TFS(&tfs_supported_not_supported), 0x02000000, NULL, HFILL }},
1185 { &hf_usb_com_descriptor_ecm_eth_stats_rcv_overrun,
1186 { "RCV Overrun", "usbcom.descriptor.ecm.eth_stats.rcv_overrun", FT_BOOLEAN, 32,
1187 TFS(&tfs_supported_not_supported), 0x01000000, NULL, HFILL }},
1188 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_max_collisions,
1189 { "XMIT Max Collisions", "usbcom.descriptor.ecm.eth_stats.xmit_max_collisions", FT_BOOLEAN, 32,
1190 TFS(&tfs_supported_not_supported), 0x00800000, NULL, HFILL }},
1191 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_deferred,
1192 { "XMIT Deferred", "usbcom.descriptor.ecm.eth_stats.xmit_deferred", FT_BOOLEAN, 32,
1193 TFS(&tfs_supported_not_supported), 0x00400000, NULL, HFILL }},
1194 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_more_collisions,
1195 { "XMIT More Collisions", "usbcom.descriptor.ecm.eth_stats.xmit_more_collisions", FT_BOOLEAN, 32,
1196 TFS(&tfs_supported_not_supported), 0x00200000, NULL, HFILL }},
1197 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_one_collision,
1198 { "XMIT One Collision", "usbcom.descriptor.ecm.eth_stats.xmit_one_collision", FT_BOOLEAN, 32,
1199 TFS(&tfs_supported_not_supported), 0x00100000, NULL, HFILL }},
1200 { &hf_usb_com_descriptor_ecm_eth_stats_rcv_error_alignment,
1201 { "RCV Error Alignment", "usbcom.descriptor.ecm.eth_stats.rcv_error_alignment", FT_BOOLEAN, 32,
1202 TFS(&tfs_supported_not_supported), 0x00080000, NULL, HFILL }},
1203 { &hf_usb_com_descriptor_ecm_eth_stats_transmit_queue_length,
1204 { "Transmit Queue Length", "usbcom.descriptor.ecm.eth_stats.transmit_queue_length", FT_BOOLEAN, 32,
1205 TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
1206 { &hf_usb_com_descriptor_ecm_eth_stats_rcv_crc_error,
1207 { "RCV CRC Error", "usbcom.descriptor.ecm.eth_stats.rcv_crc_error", FT_BOOLEAN, 32,
1208 TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
1209 { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_rcv,
1210 { "Broadcast Frames RCV", "usbcom.descriptor.ecm.eth_stats.broadcast_frames_rcv", FT_BOOLEAN, 32,
1211 TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
1212 { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_rcv,
1213 { "Broadcast Bytes RCV", "usbcom.descriptor.ecm.eth_stats.broadcast_bytes_rcv", FT_BOOLEAN, 32,
1214 TFS(&tfs_supported_not_supported), 0x00008000, NULL, HFILL }},
1215 { &hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_rcv,
1216 { "Multicast Frames RCV", "usbcom.descriptor.ecm.eth_stats.multicast_frames_rcv", FT_BOOLEAN, 32,
1217 TFS(&tfs_supported_not_supported), 0x00004000, NULL, HFILL }},
1218 { &hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_rcv,
1219 { "Multicast Bytes RCV", "usbcom.descriptor.ecm.eth_stats.multicast_bytes_rcv", FT_BOOLEAN, 32,
1220 TFS(&tfs_supported_not_supported), 0x00002000, NULL, HFILL }},
1221 { &hf_usb_com_descriptor_ecm_eth_stats_directed_frames_rcv,
1222 { "Directed Frames RCV", "usbcom.descriptor.ecm.eth_stats.directed_frames_rcv", FT_BOOLEAN, 32,
1223 TFS(&tfs_supported_not_supported), 0x00001000, NULL, HFILL }},
1224 { &hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_rcv,
1225 { "Directed Bytes RCV", "usbcom.descriptor.ecm.eth_stats.directed_bytes_rcv", FT_BOOLEAN, 32,
1226 TFS(&tfs_supported_not_supported), 0x00000800, NULL, HFILL }},
1227 { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_xmit,
1228 { "Broadcast Frames XMIT", "usbcom.descriptor.ecm.eth_stats.broadcast_frames_xmit", FT_BOOLEAN, 32,
1229 TFS(&tfs_supported_not_supported), 0x00000400, NULL, HFILL }},
1230 { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_xmit,
1231 { "Broadcast Bytes XMIT", "usbcom.descriptor.ecm.eth_stats.broadcast_bytes_xmit", FT_BOOLEAN, 32,
1232 TFS(&tfs_supported_not_supported), 0x00000200, NULL, HFILL }},
1233 { &hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_xmit,
1234 { "Multicast Frames XMIT", "usbcom.descriptor.ecm.eth_stats.multicast_frames_xmit", FT_BOOLEAN, 32,
1235 TFS(&tfs_supported_not_supported), 0x00000100, NULL, HFILL }},
1236 { &hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_xmit,
1237 { "Multicast Bytes XMIT", "usbcom.descriptor.ecm.eth_stats.multicast_bytes_xmit", FT_BOOLEAN, 32,
1238 TFS(&tfs_supported_not_supported), 0x00000080, NULL, HFILL }},
1239 { &hf_usb_com_descriptor_ecm_eth_stats_directed_frames_xmit,
1240 { "Directed Frames XMIT", "usbcom.descriptor.ecm.eth_stats.directed_frames_xmit", FT_BOOLEAN, 32,
1241 TFS(&tfs_supported_not_supported), 0x00000040, NULL, HFILL }},
1242 { &hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_xmit,
1243 { "Directed Bytes XMIT", "usbcom.descriptor.ecm.eth_stats.directed_bytes_xmit", FT_BOOLEAN, 32,
1244 TFS(&tfs_supported_not_supported), 0x00000020, NULL, HFILL }},
1245 { &hf_usb_com_descriptor_ecm_eth_stats_rcv_no_buffer,
1246 { "RCV No Buffer", "usbcom.descriptor.ecm.eth_stats.rcv_no_buffer", FT_BOOLEAN, 32,
1247 TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
1248 { &hf_usb_com_descriptor_ecm_eth_stats_rcv_error,
1249 { "RCV Error", "usbcom.descriptor.ecm.eth_stats.rcv_error", FT_BOOLEAN, 32,
1250 TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
1251 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_error,
1252 { "XMIT Error", "usbcom.descriptor.ecm.eth_stats.xmit_error", FT_BOOLEAN, 32,
1253 TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
1254 { &hf_usb_com_descriptor_ecm_eth_stats_rvc_ok,
1255 { "RCV OK", "usbcom.descriptor.ecm.eth_stats.rvc_ok", FT_BOOLEAN, 32,
1256 TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
1257 { &hf_usb_com_descriptor_ecm_eth_stats_xmit_ok,
1258 { "XMIT OK", "usbcom.descriptor.ecm.eth_stats.xmit_ok", FT_BOOLEAN, 32,
1259 TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
1260 { &hf_usb_com_descriptor_ecm_max_segment_size,
1261 { "Max Segment Size", "usbcom.descriptor.ecm.max_segment_size", FT_UINT16, BASE_DEC,
1262 NULL, 0, NULL, HFILL }},
1263 { &hf_usb_com_descriptor_ecm_nb_mc_filters,
1264 { "Number MC Filters", "usbcom.descriptor.ecm.nb_mc_filters", FT_UINT16, BASE_HEX,
1265 NULL, 0, NULL, HFILL }},
1266 { &hf_usb_com_descriptor_ecm_nb_mc_filters_mc_address_filtering,
1267 { "Multicast Address Filtering", "usbcom.descriptor.ecm.nb_mc_filters.mc_address_filtering", FT_BOOLEAN, 16,
1268 TFS(&usb_com_ecm_mc_address_filtering), 0x8000, NULL, HFILL }},
1269 { &hf_usb_com_descriptor_ecm_nb_mc_filters_nb_filters_supported,
1270 { "Number of Multicast Address Filters Supported", "usbcom.descriptor.ecm.nb_mc_filters.nb_filters_supported", FT_UINT16, BASE_DEC,
1271 NULL, 0x7fff, NULL, HFILL }},
1272 { &hf_usb_com_descriptor_ecm_nb_power_filters,
1273 { "Number Power Filters", "usbcom.descriptor.ecm.nb_power_filters", FT_UINT8, BASE_DEC,
1274 NULL, 0, NULL, HFILL }},
1275 { &hf_usb_com_interrupt_request_type,
1276 { "Request Type", "usbcom.interrupt.request_type", FT_UINT8, BASE_HEX,
1277 NULL, 0, NULL, HFILL }},
1278 { &hf_usb_com_interrupt_notif_code,
1279 { "Notification Code", "usbcom.interrupt.notification_code", FT_UINT8, BASE_HEX,
1280 VALS(usb_com_interrupt_notif_code_vals), 0, NULL, HFILL }},
1281 { &hf_usb_com_interrupt_value,
1282 { "Value", "usbcom.interrupt.value", FT_UINT16, BASE_HEX,
1283 NULL, 0, NULL, HFILL }},
1284 { &hf_usb_com_interrupt_value_nw_conn,
1285 { "Value", "usbcom.interrupt.value", FT_UINT16, BASE_HEX,
1286 VALS(usb_com_interrupt_value_nw_conn_vals), 0, NULL, HFILL }},
1287 { &hf_usb_com_interrupt_index,
1288 { "Index", "usbcom.interrupt.index", FT_UINT16, BASE_DEC,
1289 NULL, 0, NULL, HFILL }},
1290 { &hf_usb_com_interrupt_length,
1291 { "Length", "usbcom.interrupt.length", FT_UINT16, BASE_DEC,
1292 NULL, 0, NULL, HFILL }},
1293 { &hf_usb_com_interrupt_dl_bitrate,
1294 { "DL Bitrate", "usbcom.interrupt.conn_speed_change.dl_bitrate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING,
1295 UNS(&units_bit_sec), 0, NULL, HFILL }},
1296 { &hf_usb_com_interrupt_ul_bitrate,
1297 { "UL Bitrate", "usbcom.interrupt.conn_speed_change.ul_bitrate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING,
1298 UNS(&units_bit_sec), 0, NULL, HFILL }},
1299 { &hf_usb_com_interrupt_payload,
1300 { "Payload", "usbcom.interrupt.payload", FT_BYTES, BASE_NONE,
1301 NULL, 0, NULL, HFILL }},
1302 { &hf_usb_com_data_stream,
1303 { "Stream index", "usbcom.data.stream", FT_UINT32, BASE_DEC,
1304 NULL, 0, NULL, HFILL }},
1305 { &hf_usb_com_data_in_payload,
1306 { "IN payload", "usbcom.data.in_payload", FT_BYTES, BASE_NONE,
1307 NULL, 0, NULL, HFILL }},
1308 { &hf_usb_com_data_out_payload,
1309 { "OUT payload", "usbcom.data.out_payload", FT_BYTES, BASE_NONE,
1310 NULL, 0, NULL, HFILL }},
1313 static int *usb_com_ett[] = {
1314 &ett_usb_com,
1315 &ett_usb_com_capabilities,
1316 &ett_usb_com_bitmap,
1317 &ett_usb_com_descriptor_ecm_eth_stats,
1318 &ett_usb_com_descriptor_ecm_nb_mc_filters
1321 static ei_register_info ei[] = {
1322 { &ei_unexpected_controlling_iface, { "usbcom.descriptor.control_interface.unexpected_iface", PI_MALFORMED, PI_ERROR, "Unexpected controlling interface index (report to wireshark.org)", EXPFILL }},
1325 expert_module_t* expert_usb_com;
1327 controlling_ifaces = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1329 proto_usb_com = proto_register_protocol("USB Communications and CDC Control", "USBCOM", "usbcom");
1330 proto_register_field_array(proto_usb_com, hf, array_length(hf));
1331 proto_register_subtree_array(usb_com_ett, array_length(usb_com_ett));
1333 usb_com_descriptor_handle = register_dissector("usbcom.descriptor", dissect_usb_com_descriptor, proto_usb_com);
1334 usb_com_control_handle = register_dissector("usbcom.control", dissect_usb_com_control, proto_usb_com);
1335 usb_com_bulk_handle = register_dissector("usbcom.bulk", dissect_usb_com_bulk, proto_usb_com);
1336 usb_com_interrupt_handle = register_dissector("usbcom.interrupt", dissect_usb_com_interrupt, proto_usb_com);
1338 expert_usb_com = expert_register_protocol(proto_usb_com);
1339 expert_register_field_array(expert_usb_com, ei, array_length(ei));
1341 register_cleanup_routine(usb_com_cleanup_data);
1343 cdc_data_follow_tap = register_tap("cdc_data_follow");
1344 register_follow_stream(proto_usb_com, "cdc_data_follow", cdc_data_follow_conv_filter, cdc_data_follow_index_filter,
1345 cdc_data_follow_address_filter, cdc_data_port_to_display, follow_cdc_data_tap_listener,
1346 get_cdc_data_stream_count, NULL);
1349 void
1350 proto_reg_handoff_usb_com(void)
1352 dissector_add_uint("usb.descriptor", IF_CLASS_COMMUNICATIONS, usb_com_descriptor_handle);
1353 dissector_add_uint("usb.control", IF_CLASS_COMMUNICATIONS, usb_com_control_handle);
1354 dissector_add_uint("usb.bulk", IF_CLASS_CDC_DATA, usb_com_bulk_handle);
1355 dissector_add_uint("usb.interrupt", IF_CLASS_COMMUNICATIONS, usb_com_interrupt_handle);
1356 mbim_control_handle = find_dissector_add_dependency("mbim.control", proto_usb_com);
1357 mbim_descriptor_handle = find_dissector_add_dependency("mbim.descriptor", proto_usb_com);
1358 mbim_bulk_handle = find_dissector_add_dependency("mbim.bulk", proto_usb_com);
1359 eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_usb_com);
1361 proto_usb = proto_get_id_by_filter_name("usb");
1365 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1367 * Local variables:
1368 * c-basic-offset: 4
1369 * tab-width: 8
1370 * indent-tabs-mode: nil
1371 * End:
1373 * vi: set shiftwidth=4 tabstop=8 expandtab:
1374 * :indentSize=4:tabSize=8:noTabs=true: