Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-usb-com.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-usb-com.c
2
 * Routines for USB Communications and CDC Control dissection
3
 * Copyright 2013, Pascal Quantin <pascal@wireshark.org>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
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"
21
22
static int cdc_data_follow_tap;
23
static int proto_usb;
24
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;
126
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;
132
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;
137
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;
142
143
static expert_field ei_unexpected_controlling_iface;
144
145
static wmem_tree_t* controlling_ifaces;
146
147
typedef struct _controlling_iface {
148
    uint16_t interfaceClass;
149
    uint16_t interfaceSubclass;
150
    uint16_t interfaceProtocol;
151
} controlling_iface_t;
152
153
static uint32_t cdc_data_stream_count;
154
155
typedef struct _cdc_data_conv {
156
    uint32_t stream;
157
} cdc_data_conv_t;
158
159
0
#define CS_INTERFACE 0x24
160
0
#define CS_ENDPOINT  0x25
161
162
static const value_string usb_com_descriptor_type_vals[] = {
163
    { CS_INTERFACE, "CS_INTERFACE"},
164
    { CS_ENDPOINT, "CS_ENDPOINT"},
165
    { 0, NULL}
166
};
167
static value_string_ext usb_com_descriptor_type_vals_ext = VALUE_STRING_EXT_INIT(usb_com_descriptor_type_vals);
168
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}
200
};
201
static value_string_ext usb_com_descriptor_subtype_vals_ext = VALUE_STRING_EXT_INIT(usb_com_descriptor_subtype_vals);
202
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
0
#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
0
#define COM_SUBCLASS_MBIM     0x0e
218
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}
236
};
237
value_string_ext ext_usb_com_subclass_vals = VALUE_STRING_EXT_INIT(usb_com_subclass_vals);
238
239
0
#define SEND_ENCAPSULATED_COMMAND                    0x00
240
0
#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
0
#define GET_NTB_PARAMETERS                           0x80
276
0
#define GET_NET_ADDRESS                              0x81
277
0
#define SET_NET_ADDRESS                              0x82
278
0
#define GET_NTB_FORMAT                               0x83
279
0
#define SET_NTB_FORMAT                               0x84
280
0
#define GET_NTB_INPUT_SIZE                           0x85
281
0
#define SET_NTB_INPUT_SIZE                           0x86
282
0
#define GET_MAX_DATAGRAM_SIZE                        0x87
283
0
#define SET_MAX_DATAGRAM_SIZE                        0x88
284
0
#define GET_CRC_MODE                                 0x89
285
0
#define SET_CRC_MODE                                 0x8a
286
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}
336
};
337
static value_string_ext usb_com_setup_request_vals_ext = VALUE_STRING_EXT_INIT(usb_com_setup_request_vals);
338
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
343
};
344
345
static const value_string usb_com_ntb_format_vals[] = {
346
    { 0x0000, "NTB-16"},
347
    { 0x0001, "NTB-32"},
348
    {0, NULL}
349
};
350
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}
355
};
356
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
389
};
390
391
static const true_false_string usb_com_ecm_mc_address_filtering = {
392
    "Imperfect",
393
    "Perfect"
394
};
395
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
400
};
401
402
0
#define NETWORK_CONNECTION      0x00
403
0
#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
0
#define CONNECTION_SPEED_CHANGE 0x2a
410
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}
421
};
422
423
static const value_string usb_com_interrupt_value_nw_conn_vals[] = {
424
    {0, "Disconnect"},
425
    {1, "Connected"},
426
    {0, NULL}
427
};
428
429
void proto_register_usb_com(void);
430
void proto_reg_handoff_usb_com(void);
431
432
static int
433
dissect_usb_com_descriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
434
0
{
435
0
    urb_info_t *urb = (urb_info_t *)data;
436
0
    int offset = 0;
437
0
    uint8_t type, subtype;
438
0
    proto_tree *subtree;
439
0
    proto_tree *subtree_capabilities;
440
0
    proto_item *subitem_capabilities;
441
442
0
    if (!urb) {
443
0
        return 0;
444
0
    }
445
446
0
    subtree = proto_tree_add_subtree(tree, tvb, offset, tvb_captured_length(tvb), ett_usb_com, NULL, "COMMUNICATIONS DESCRIPTOR");
447
448
0
    dissect_usb_descriptor_header(subtree, tvb, offset, &usb_com_descriptor_type_vals_ext);
449
0
    offset += 2;
450
451
0
    type = tvb_get_uint8(tvb, 1);
452
0
    switch (type) {
453
0
        case CS_INTERFACE:
454
0
            subtype = tvb_get_uint8(tvb, offset);
455
0
            proto_tree_add_uint(subtree, hf_usb_com_descriptor_subtype, tvb, offset, 1, subtype);
456
0
            offset++;
457
0
            switch (subtype) {
458
0
                case 0x00:
459
0
                    proto_tree_add_item(subtree, hf_usb_com_descriptor_cdc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
460
0
                    offset += 2;
461
0
                    break;
462
0
                case 0x01:
463
0
                    subitem_capabilities = proto_tree_add_item(subtree, hf_usb_com_capabilities, tvb, 3, 1, ENC_LITTLE_ENDIAN);
464
0
                    subtree_capabilities = proto_item_add_subtree(subitem_capabilities, ett_usb_com_capabilities);
465
466
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_cm_capabilities_reserved, tvb, 3, 1, ENC_LITTLE_ENDIAN);
467
0
                    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
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_cm_capabilities_call_management, tvb, 3, 1, ENC_LITTLE_ENDIAN);
469
470
0
                    proto_tree_add_item(subtree, hf_usb_com_descriptor_cm_data_interface, tvb, 4, 1, ENC_LITTLE_ENDIAN);
471
0
                    offset = 5;
472
0
                    break;
473
0
                case 0x02:
474
0
                    subitem_capabilities = proto_tree_add_item(subtree, hf_usb_com_capabilities, tvb, 3, 1, ENC_LITTLE_ENDIAN);
475
0
                    subtree_capabilities = proto_item_add_subtree(subitem_capabilities, ett_usb_com_capabilities);
476
477
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_reserved, tvb, 3, 1, ENC_LITTLE_ENDIAN);
478
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_network_connection, tvb, 3, 1, ENC_LITTLE_ENDIAN);
479
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_send_break, tvb, 3, 1, ENC_LITTLE_ENDIAN);
480
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_line_and_state, tvb, 3, 1, ENC_LITTLE_ENDIAN);
481
0
                    proto_tree_add_item(subtree_capabilities, hf_usb_com_descriptor_acm_capabilities_comm_features, tvb, 3, 1, ENC_LITTLE_ENDIAN);
482
0
                    offset = 4;
483
0
                    break;
484
0
                case 0x06: {
485
0
                    proto_item *control_item;
486
0
                    uint32_t k_bus_id;
487
0
                    uint32_t k_device_address;
488
0
                    uint32_t k_subordinate_id;
489
0
                    uint32_t k_frame_number;
490
0
                    wmem_tree_key_t key[] = {
491
0
                        { .length = 1, .key = &k_bus_id },
492
0
                        { .length = 1, .key = &k_device_address },
493
0
                        { .length = 1, .key = &k_subordinate_id },
494
0
                        { .length = 1, .key = &k_frame_number },
495
0
                        { .length = 0, .key = NULL },
496
0
                    };
497
0
                    controlling_iface_t *master_info = NULL;
498
0
                    uint32_t master;
499
500
0
                    k_bus_id = urb->bus_id;
501
0
                    k_device_address = urb->device_address;
502
0
                    k_frame_number = pinfo->num;
503
504
0
                    control_item = proto_tree_add_item_ret_uint(subtree, hf_usb_com_descriptor_control_interface, tvb, offset, 1, ENC_LITTLE_ENDIAN, &master);
505
506
0
                    if (master != urb->conv->interfaceNum) {
507
0
                        expert_add_info(pinfo, control_item, &ei_unexpected_controlling_iface);
508
0
                    } else if (!PINFO_FD_VISITED(pinfo)) {
509
0
                        master_info = wmem_new(wmem_file_scope(), controlling_iface_t);
510
0
                        master_info->interfaceClass = urb->conv->interfaceClass;
511
0
                        master_info->interfaceSubclass = urb->conv->interfaceSubclass;
512
0
                        master_info->interfaceProtocol = urb->conv->interfaceProtocol;
513
0
                    }
514
515
0
                    offset += 1;
516
0
                    while (tvb_reported_length_remaining(tvb,offset) > 0) {
517
0
                        proto_tree_add_item_ret_uint(subtree, hf_usb_com_descriptor_subordinate_interface, tvb, offset, 1, ENC_LITTLE_ENDIAN, &k_subordinate_id);
518
0
                        offset += 1;
519
520
0
                        if (master_info) {
521
0
                            wmem_tree_insert32_array(controlling_ifaces, key, master_info);
522
0
                        }
523
0
                    }
524
0
                    break;
525
0
                }
526
0
                case 0x0f:
527
0
                    proto_tree_add_item(subtree, hf_usb_com_descriptor_ecm_mac_address, tvb, offset, 1, ENC_LITTLE_ENDIAN);
528
0
                    offset += 1;
529
0
                    proto_tree_add_bitmask_with_flags(subtree, tvb, offset, hf_usb_com_descriptor_ecm_eth_stats,
530
0
                                                      ett_usb_com_descriptor_ecm_eth_stats, ecm_eth_stats,
531
0
                                                      ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
532
0
                    offset += 4;
533
0
                    proto_tree_add_item(subtree, hf_usb_com_descriptor_ecm_max_segment_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
534
0
                    offset += 2;
535
0
                    proto_tree_add_bitmask_with_flags(subtree, tvb, offset, hf_usb_com_descriptor_ecm_nb_mc_filters,
536
0
                                                      ett_usb_com_descriptor_ecm_nb_mc_filters, ecm_nb_mc_filters,
537
0
                                                      ENC_LITTLE_ENDIAN, BMT_NO_APPEND);
538
0
                    offset += 2;
539
0
                    proto_tree_add_item(subtree, hf_usb_com_descriptor_ecm_nb_power_filters, tvb, offset, 1, ENC_LITTLE_ENDIAN);
540
0
                    offset += 1;
541
0
                    break;
542
0
                case 0x1b:
543
0
                case 0x1c:
544
0
                    offset = call_dissector_only(mbim_descriptor_handle, tvb, pinfo, subtree, data);
545
0
                    break;
546
0
                default:
547
0
                    break;
548
0
            }
549
0
            break;
550
0
        case CS_ENDPOINT:
551
0
        default:
552
0
            break;
553
0
    }
554
555
0
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
556
0
        proto_tree_add_item(subtree, hf_usb_com_descriptor_payload, tvb, offset, -1, ENC_NA);
557
0
    }
558
0
    return tvb_captured_length(tvb);
559
0
}
560
561
static int
562
dissect_usb_com_get_ntb_params(tvbuff_t *tvb, proto_tree *tree, int base_offset)
563
0
{
564
0
    int offset = base_offset;
565
566
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
567
0
    offset += 2;
568
0
    proto_tree_add_bitmask(tree, tvb, offset, hf_usb_com_get_ntb_params_ntb_formats_supported, ett_usb_com_bitmap,
569
0
                           usb_com_get_ntb_params_ntb_formats_supported_fields, ENC_LITTLE_ENDIAN);
570
0
    offset += 2;
571
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ntb_in_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
572
0
    offset += 4;
573
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_in_divisor, tvb, offset, 2, ENC_LITTLE_ENDIAN);
574
0
    offset += 2;
575
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_in_payload_remainder, tvb, offset, 2, ENC_LITTLE_ENDIAN);
576
0
    offset += 2;
577
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_in_alignment, tvb, offset, 2, ENC_LITTLE_ENDIAN);
578
0
    offset += 2;
579
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
580
0
    offset += 2;
581
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ntb_out_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
582
0
    offset += 4;
583
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_out_divisor, tvb, offset, 2, ENC_LITTLE_ENDIAN);
584
0
    offset += 2;
585
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_out_payload_remainder, tvb, offset, 2, ENC_LITTLE_ENDIAN);
586
0
    offset += 2;
587
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ndp_out_alignment, tvb, offset, 2, ENC_LITTLE_ENDIAN);
588
0
    offset += 2;
589
0
    proto_tree_add_item(tree, hf_usb_com_get_ntb_params_ntb_out_max_datagrams, tvb, offset, 2, ENC_LITTLE_ENDIAN);
590
0
    offset += 2;
591
592
0
    return offset;
593
0
}
594
595
static int
596
dissect_usb_com_ntb_input_size(tvbuff_t *tvb, proto_tree *tree, int base_offset, bool is_set)
597
0
{
598
0
    int offset = base_offset;
599
600
0
    proto_tree_add_item(tree, is_set ? hf_usb_com_set_ntb_input_size_ntb_in_max_size :
601
0
                        hf_usb_com_get_ntb_input_size_ntb_in_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
602
0
    offset += 4;
603
0
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
604
0
        proto_tree_add_item(tree, is_set ? hf_usb_com_set_ntb_input_size_ntb_in_max_datagrams :
605
0
                            hf_usb_com_get_ntb_input_size_ntb_in_max_datagrams, tvb, offset, 2, ENC_LITTLE_ENDIAN);
606
0
        offset += 2;
607
0
        proto_tree_add_item(tree, is_set ? hf_usb_com_set_ntb_input_size_reserved :
608
0
                            hf_usb_com_get_ntb_input_size_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
609
0
        offset += 2;
610
0
    }
611
612
0
    return offset;
613
0
}
614
615
static int
616
dissect_usb_com_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
617
0
{
618
0
    urb_info_t *urb = (urb_info_t *)data;
619
0
    usb_trans_info_t *usb_trans_info;
620
0
    proto_tree *subtree;
621
0
    proto_item *ti;
622
0
    int offset = 0;
623
0
    bool is_request;
624
625
0
    if (tvb_reported_length(tvb) == 0) {
626
0
        return 0;
627
0
    }
628
629
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCOM");
630
631
0
    ti = proto_tree_add_item(tree, proto_usb_com, tvb, 0, -1, ENC_NA);
632
0
    subtree = proto_item_add_subtree(ti, ett_usb_com);
633
634
0
    if (urb) {
635
0
        usb_trans_info = urb->usb_trans_info;
636
637
0
        ti = proto_tree_add_uint(subtree, hf_usb_com_control_subclass, tvb, 0, 0,
638
0
                                 urb->conv->interfaceSubclass);
639
0
        proto_item_set_generated(ti);
640
641
0
        is_request = (pinfo->srcport==NO_ENDPOINT);
642
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
643
0
        val_to_str_ext(usb_trans_info->setup.request, &usb_com_setup_request_vals_ext, "Unknown type %x"),
644
0
            is_request ? "Request" : "Response");
645
646
0
        if (is_request) {
647
0
            proto_tree_add_item(subtree, hf_usb_com_control_request_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
648
0
            offset += 1;
649
0
            proto_tree_add_item(subtree, hf_usb_com_control_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
650
0
            offset += 2;
651
0
            proto_tree_add_item(subtree, hf_usb_com_control_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
652
0
            offset += 2;
653
0
            proto_tree_add_item(subtree, hf_usb_com_control_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
654
0
            offset += 2;
655
0
        } else {
656
0
            ti = proto_tree_add_uint(subtree, hf_usb_com_control_response_code, tvb, 0, 0,
657
0
                                     usb_trans_info->setup.request);
658
0
            proto_item_set_generated(ti);
659
0
        }
660
661
0
        switch (usb_trans_info->setup.request)
662
0
        {
663
0
            case SEND_ENCAPSULATED_COMMAND:
664
0
                if ((urb->conv->interfaceSubclass == COM_SUBCLASS_MBIM) && is_request) {
665
0
                    tvbuff_t *mbim_tvb = tvb_new_subset_remaining(tvb, offset);
666
0
                    offset += call_dissector_only(mbim_control_handle, mbim_tvb, pinfo, tree, urb);
667
0
                }
668
0
                break;
669
0
            case GET_ENCAPSULATED_RESPONSE:
670
0
                if ((urb->conv->interfaceSubclass == COM_SUBCLASS_MBIM) && !is_request) {
671
0
                    offset += call_dissector_only(mbim_control_handle, tvb, pinfo, tree, urb);
672
0
                }
673
0
                break;
674
0
            case GET_NTB_PARAMETERS:
675
0
                if (!is_request) {
676
0
                    offset = dissect_usb_com_get_ntb_params(tvb, subtree, offset);
677
0
                }
678
0
                break;
679
0
            case GET_NET_ADDRESS:
680
0
                if (!is_request) {
681
0
                    proto_tree_add_item(subtree, hf_usb_com_get_net_address_eui48, tvb, offset, 6, ENC_NA);
682
0
                    offset += 6;
683
0
                }
684
0
                break;
685
0
            case SET_NET_ADDRESS:
686
0
                if (is_request) {
687
0
                    proto_tree_add_item(subtree, hf_usb_com_set_net_address_eui48, tvb, offset, 6, ENC_NA);
688
0
                    offset += 6;
689
0
                }
690
0
                break;
691
0
            case GET_NTB_FORMAT:
692
0
                if (!is_request) {
693
0
                    proto_tree_add_item(subtree, hf_usb_com_get_ntb_format_ntb_format, tvb, offset, 2, ENC_LITTLE_ENDIAN);
694
0
                    offset += 2;
695
0
                }
696
0
                break;
697
0
            case SET_NTB_FORMAT:
698
0
                if (is_request) {
699
0
                    proto_tree_add_item(subtree, hf_usb_com_set_ntb_format_ntb_format, tvb, offset-6, 2, ENC_LITTLE_ENDIAN);
700
0
                }
701
0
                break;
702
0
            case GET_NTB_INPUT_SIZE:
703
0
                if (!is_request) {
704
0
                    offset = dissect_usb_com_ntb_input_size(tvb, subtree, offset, false);
705
0
                }
706
0
                break;
707
0
            case SET_NTB_INPUT_SIZE:
708
0
                if (!is_request) {
709
0
                    offset = dissect_usb_com_ntb_input_size(tvb, subtree, offset, true);
710
0
                }
711
0
                break;
712
0
            case GET_MAX_DATAGRAM_SIZE:
713
0
                if (!is_request) {
714
0
                    proto_tree_add_item(subtree, hf_usb_com_get_max_datagram_size_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
715
0
                    offset += 2;
716
0
                }
717
0
                break;
718
0
            case SET_MAX_DATAGRAM_SIZE:
719
0
                if (is_request) {
720
0
                    proto_tree_add_item(subtree, hf_usb_com_set_max_datagram_size_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
721
0
                    offset += 2;
722
0
                }
723
0
                break;
724
0
            case GET_CRC_MODE:
725
0
                if (!is_request) {
726
0
                    proto_tree_add_item(subtree, hf_usb_com_get_crc_mode_crc_mode, tvb, offset, 2, ENC_LITTLE_ENDIAN);
727
0
                    offset += 2;
728
0
                }
729
0
                break;
730
0
            case SET_CRC_MODE:
731
0
                if (is_request) {
732
0
                    proto_tree_add_item(subtree, hf_usb_com_set_crc_mode_crc_mode, tvb, offset-6, 2, ENC_LITTLE_ENDIAN);
733
0
                }
734
0
                break;
735
0
            default:
736
0
                break;
737
0
        }
738
0
    }
739
740
0
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
741
0
        proto_tree_add_item(subtree, hf_usb_com_control_payload, tvb, offset, -1, ENC_NA);
742
0
    }
743
0
    return tvb_captured_length(tvb);
744
0
}
745
746
static int
747
dissect_usb_com_bulk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
748
0
{
749
0
    urb_info_t *urb = (urb_info_t *)data;
750
0
    usb_conv_info_t *usb_conv_info;
751
0
    cdc_data_conv_t *cdc_data_info;
752
0
    uint32_t k_bus_id;
753
0
    uint32_t k_device_address;
754
0
    uint32_t k_subordinate_id;
755
0
    wmem_tree_key_t key[] = {
756
0
        { .length = 1, .key = &k_bus_id },
757
0
        { .length = 1, .key = &k_device_address },
758
0
        { .length = 1, .key = &k_subordinate_id },
759
0
        { .length = 0, .key = NULL },
760
0
    };
761
0
    wmem_tree_t *wmem_tree;
762
0
    controlling_iface_t *master_iface = NULL;
763
0
    proto_tree *subtree;
764
0
    proto_item *item;
765
766
0
    if (!urb || !urb->conv) {
767
0
        return 0;
768
0
    }
769
770
0
    usb_conv_info = urb->conv;
771
772
0
    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.
775
         */
776
0
        return 0;
777
0
    }
778
779
    /* Generic handling to allow follow stream functionality regardless if data
780
     * is passed to higher layer dissector or not.
781
     */
782
0
    cdc_data_info = (cdc_data_conv_t *)usb_conv_info->class_data;
783
0
    if (!cdc_data_info) {
784
0
        cdc_data_info = wmem_new(wmem_file_scope(), cdc_data_conv_t);
785
0
        cdc_data_info->stream = cdc_data_stream_count++;
786
0
        usb_conv_info->class_data = cdc_data_info;
787
0
        usb_conv_info->class_data_type = USB_CONV_CDC_DATA;
788
0
    } 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
0
        return 0;
791
0
    }
792
793
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCOM");
794
795
0
    item = proto_tree_add_item(tree, proto_usb_com, tvb, 0, -1, ENC_NA);
796
0
    subtree = proto_item_add_subtree(item, ett_usb_com);
797
798
0
    item = proto_tree_add_uint(subtree, hf_usb_com_data_stream, tvb, 0, 0, cdc_data_info->stream);
799
0
    proto_item_set_generated(item);
800
801
0
    if (pinfo->p2p_dir == P2P_DIR_RECV) {
802
0
        proto_tree_add_item(subtree, hf_usb_com_data_in_payload, tvb, 0, -1, ENC_NA);
803
0
    } else {
804
0
        proto_tree_add_item(subtree, hf_usb_com_data_out_payload, tvb, 0, -1, ENC_NA);
805
0
    }
806
807
0
    if (have_tap_listener(cdc_data_follow_tap)) {
808
0
        tap_queue_packet(cdc_data_follow_tap, pinfo, tvb);
809
0
    }
810
811
0
    k_bus_id = urb->bus_id;
812
0
    k_device_address = urb->device_address;
813
0
    k_subordinate_id = usb_conv_info->interfaceNum;
814
815
0
    wmem_tree = (wmem_tree_t*)wmem_tree_lookup32_array(controlling_ifaces, key);
816
0
    if (wmem_tree) {
817
0
        master_iface = (controlling_iface_t *)wmem_tree_lookup32_le(wmem_tree, pinfo->num);
818
0
    }
819
820
0
    if (master_iface) {
821
0
        if (master_iface->interfaceClass == IF_CLASS_COMMUNICATIONS) {
822
0
            if ((master_iface->interfaceSubclass == COM_SUBCLASS_ENCM) &&
823
0
                (master_iface->interfaceProtocol == 0) &&
824
0
                (usb_conv_info->interfaceProtocol == 0)) {
825
                /* Ethernet without FCS */
826
0
                return call_dissector_only(eth_withoutfcs_handle, tvb, pinfo, tree, NULL);
827
0
            }
828
0
        }
829
0
    }
830
831
832
0
    switch (usb_conv_info->interfaceProtocol) {
833
0
        case 0x01: /* Network Transfer Block */
834
0
        case 0x02: /* Network Transfer Block (IP + DSS) */
835
0
            return call_dissector_only(mbim_bulk_handle, tvb, pinfo, tree, NULL);
836
0
        default:
837
0
            break;
838
0
    }
839
840
    /* Unknown (class, subclass, protocol) tuple. No further dissection. */
841
0
    return tvb_captured_length(tvb);
842
0
}
843
844
static int
845
dissect_usb_com_interrupt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
846
0
{
847
0
    proto_tree *subtree;
848
0
    proto_item *it;
849
0
    uint32_t notif_code;
850
0
    int offset = 0;
851
852
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBCOM");
853
854
0
    it = proto_tree_add_item(tree, proto_usb_com, tvb, 0, -1, ENC_NA);
855
0
    subtree = proto_item_add_subtree(it, ett_usb_com);
856
857
0
    proto_tree_add_item(subtree, hf_usb_com_interrupt_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
858
0
    offset++;
859
0
    proto_tree_add_item_ret_uint(subtree, hf_usb_com_interrupt_notif_code, tvb, offset, 1, ENC_LITTLE_ENDIAN, &notif_code);
860
0
    offset++;
861
0
    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(notif_code, usb_com_interrupt_notif_code_vals, "Unknown type %x"));
862
0
    switch (notif_code) {
863
0
        case NETWORK_CONNECTION:
864
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_value_nw_conn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
865
0
            offset += 2;
866
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
867
0
            offset += 2;
868
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
869
0
            offset += 2;
870
0
            break;
871
0
        case RESPONSE_AVAILABLE:
872
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
873
0
            offset += 2;
874
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
875
0
            offset += 2;
876
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
877
0
            offset += 2;
878
0
            break;
879
0
        case CONNECTION_SPEED_CHANGE:
880
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
881
0
            offset += 2;
882
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
883
0
            offset += 2;
884
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
885
0
            offset += 2;
886
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_dl_bitrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
887
0
            offset += 4;
888
0
            proto_tree_add_item(subtree, hf_usb_com_interrupt_ul_bitrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
889
0
            offset += 4;
890
0
            break;
891
0
        default:
892
0
            break;
893
0
    }
894
895
0
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
896
0
        proto_tree_add_item(subtree, hf_usb_com_interrupt_payload, tvb, offset, -1, ENC_NA);
897
0
    }
898
0
    return tvb_captured_length(tvb);
899
0
}
900
901
static cdc_data_conv_t *get_cdc_data_conv(packet_info *pinfo)
902
0
{
903
0
    conversation_t *conversation;
904
0
    usb_conv_info_t *usb_conv_info;
905
906
0
    if (pinfo->ptype != PT_USB) {
907
0
        return NULL;
908
0
    }
909
910
0
    conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, CONVERSATION_USB,
911
0
                                     pinfo->srcport, pinfo->destport, 0);
912
0
    if (!conversation) {
913
0
        return NULL;
914
0
    }
915
916
0
    usb_conv_info = (usb_conv_info_t *)conversation_get_proto_data(conversation, proto_usb);
917
0
    if (!usb_conv_info || (usb_conv_info->class_data_type != USB_CONV_CDC_DATA)) {
918
0
        return NULL;
919
0
    }
920
921
0
    return (cdc_data_conv_t *)usb_conv_info->class_data;
922
0
}
923
924
static char *cdc_data_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream _U_)
925
0
{
926
0
    cdc_data_conv_t *cdc_data_info;
927
928
0
    cdc_data_info = get_cdc_data_conv(pinfo);
929
0
    if (cdc_data_info) {
930
0
        *stream = cdc_data_info->stream;
931
0
        return ws_strdup_printf("usbcom.data.stream eq %u", cdc_data_info->stream);
932
0
    }
933
934
0
    return NULL;
935
0
}
936
937
static char *cdc_data_follow_index_filter(unsigned stream, unsigned sub_stream _U_)
938
0
{
939
0
    return ws_strdup_printf("usbcom.data.stream eq %u", stream);
940
0
}
941
942
static char *cdc_data_follow_address_filter(address *src_addr _U_, address *dst_addr _U_, int src_port _U_, int dst_port _U_)
943
0
{
944
    /* We always just filter stream based on an arbitrarily generated index. */
945
0
    return NULL;
946
0
}
947
948
static char *cdc_data_port_to_display(wmem_allocator_t *allocator, unsigned port)
949
0
{
950
0
    return wmem_strdup(allocator, port == NO_ENDPOINT ? "host" : "device");
951
0
}
952
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_)
956
0
{
957
0
    follow_record_t *follow_record;
958
0
    follow_info_t *follow_info = (follow_info_t *)tapdata;
959
0
    tvbuff_t *tvb = (tvbuff_t *)data;
960
0
    uint32_t data_length = tvb_captured_length(tvb);
961
0
    bool is_server;
962
963
0
    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.
969
         */
970
0
        if (pinfo->srcport == NO_ENDPOINT) {
971
0
            follow_info->client_port = pinfo->destport;
972
0
            copy_address(&follow_info->client_ip, &pinfo->dst);
973
0
            follow_info->server_port = pinfo->srcport;
974
0
            copy_address(&follow_info->server_ip, &pinfo->src);
975
0
        } else {
976
0
            follow_info->client_port = pinfo->srcport;
977
0
            copy_address(&follow_info->client_ip, &pinfo->src);
978
0
            follow_info->server_port = pinfo->destport;
979
0
            copy_address(&follow_info->server_ip, &pinfo->dst);
980
0
        }
981
0
    }
982
983
0
    is_server = pinfo->srcport == NO_ENDPOINT;
984
985
0
    follow_record = g_new0(follow_record_t, 1);
986
0
    follow_record->is_server = is_server;
987
0
    follow_record->packet_num = pinfo->fd->num;
988
0
    follow_record->abs_ts = pinfo->fd->abs_ts;
989
0
    follow_record->data = g_byte_array_append(g_byte_array_new(),
990
0
                                              tvb_get_ptr(tvb, 0, data_length),
991
0
                                              data_length);
992
993
0
    follow_info->bytes_written[is_server] += follow_record->data->len;
994
0
    follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
995
996
0
    return TAP_PACKET_DONT_REDRAW;
997
0
}
998
999
static uint32_t get_cdc_data_stream_count(void)
1000
0
{
1001
0
    return cdc_data_stream_count;
1002
0
}
1003
1004
static void
1005
usb_com_cleanup_data(void)
1006
0
{
1007
0
    cdc_data_stream_count = 0;
1008
0
}
1009
1010
void
1011
proto_register_usb_com(void)
1012
14
{
1013
14
    static hf_register_info hf[] = {
1014
14
        { &hf_usb_com_descriptor_subtype,
1015
14
            { "Descriptor Subtype", "usbcom.descriptor.subtype", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1016
14
              &usb_com_descriptor_subtype_vals_ext, 0, NULL, HFILL }},
1017
14
        { &hf_usb_com_descriptor_cdc,
1018
14
            { "CDC", "usbcom.descriptor.cdc", FT_UINT16, BASE_HEX,
1019
14
              NULL, 0, NULL, HFILL }},
1020
14
        { &hf_usb_com_descriptor_payload,
1021
14
            { "Payload", "usbcom.descriptor.payload", FT_BYTES, BASE_NONE,
1022
14
              NULL, 0, NULL, HFILL }},
1023
14
        { &hf_usb_com_control_subclass,
1024
14
            { "Subclass", "usbcom.control.subclass", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1025
14
              &ext_usb_com_subclass_vals, 0, NULL, HFILL }},
1026
14
        { &hf_usb_com_control_request_code,
1027
14
            { "Request Code", "usbcom.control.request_code", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1028
14
              &usb_com_setup_request_vals_ext, 0, NULL, HFILL }},
1029
14
        { &hf_usb_com_control_value,
1030
14
            { "Value", "usbcom.control.value", FT_UINT16, BASE_DEC,
1031
14
              NULL, 0, NULL, HFILL }},
1032
14
        { &hf_usb_com_control_index,
1033
14
            { "Index", "usbcom.control.index", FT_UINT16, BASE_DEC,
1034
14
              NULL, 0, NULL, HFILL }},
1035
14
        { &hf_usb_com_control_length,
1036
14
            { "Length", "usbcom.control.length", FT_UINT16, BASE_DEC,
1037
14
              NULL, 0, NULL, HFILL }},
1038
14
        { &hf_usb_com_control_response_code,
1039
14
            { "Response Code", "usbcom.control.response_code", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
1040
14
              &usb_com_setup_request_vals_ext, 0, NULL, HFILL }},
1041
14
        { &hf_usb_com_get_ntb_params_length,
1042
14
            { "Length", "usbcom.control.get_ntb_params.length", FT_UINT16, BASE_DEC,
1043
14
              NULL, 0, NULL, HFILL }},
1044
14
        { &hf_usb_com_get_ntb_params_ntb_formats_supported,
1045
14
            { "NTB Formats Supported", "usbcom.control.get_ntb_params.ntb_formats_supported", FT_UINT16, BASE_HEX,
1046
14
              NULL, 0, NULL, HFILL }},
1047
14
        { &hf_usb_com_get_ntb_params_ntb_formats_supported_16bit,
1048
14
            { "16-bit NTB", "usbcom.control.get_ntb_params.ntb_formats_supported.16bit", FT_BOOLEAN, 16,
1049
14
              TFS(&tfs_supported_not_supported), 0x0001, NULL, HFILL }},
1050
14
        { &hf_usb_com_get_ntb_params_ntb_formats_supported_32bit,
1051
14
            { "32-bit NTB", "usbcom.control.get_ntb_params.ntb_formats_supported.32bit", FT_BOOLEAN, 16,
1052
14
              TFS(&tfs_supported_not_supported), 0x0002, NULL, HFILL }},
1053
14
        { &hf_usb_com_get_ntb_params_ntb_in_max_size,
1054
14
            { "NTB IN Max Size", "usbcom.control.get_ntb_params.ntb_in_max_size", FT_UINT32, BASE_DEC,
1055
14
              NULL, 0, NULL, HFILL }},
1056
14
        { &hf_usb_com_get_ntb_params_ndp_in_divisor,
1057
14
            { "NDP IN Divisor", "usbcom.control.get_ntb_params.ndp_in_divisor", FT_UINT16, BASE_DEC,
1058
14
              NULL, 0, NULL, HFILL }},
1059
14
        { &hf_usb_com_get_ntb_params_ndp_in_payload_remainder,
1060
14
            { "NDP IN Payload Remainder", "usbcom.control.get_ntb_params.ndp_in_payload_remainder", FT_UINT16, BASE_DEC,
1061
14
              NULL, 0, NULL, HFILL }},
1062
14
        { &hf_usb_com_get_ntb_params_ndp_in_alignment,
1063
14
            { "NDP IN Alignment", "usbcom.control.get_ntb_params.ndp_in_alignment", FT_UINT16, BASE_DEC,
1064
14
              NULL, 0, NULL, HFILL }},
1065
14
        { &hf_usb_com_get_ntb_params_reserved,
1066
14
            { "Reserved", "usbcom.control.get_ntb_params.reserved", FT_UINT16, BASE_HEX,
1067
14
              NULL, 0, NULL, HFILL }},
1068
14
        { &hf_usb_com_get_ntb_params_ntb_out_max_size,
1069
14
            { "NTB OUT Max Size", "usbcom.control.get_ntb_params.ntb_out_max_size", FT_UINT32, BASE_DEC,
1070
14
              NULL, 0, NULL, HFILL }},
1071
14
        { &hf_usb_com_get_ntb_params_ndp_out_divisor,
1072
14
            { "NDP OUT Divisor", "usbcom.control.get_ntb_params.ndp_out_divisor", FT_UINT16, BASE_DEC,
1073
14
              NULL, 0, NULL, HFILL }},
1074
14
        { &hf_usb_com_get_ntb_params_ndp_out_payload_remainder,
1075
14
            { "NDP OUT Payload Remainder", "usbcom.control.get_ntb_params.ndp_out_payload_remainder", FT_UINT16, BASE_DEC,
1076
14
              NULL, 0, NULL, HFILL }},
1077
14
        { &hf_usb_com_get_ntb_params_ndp_out_alignment,
1078
14
            { "NDP OUT Alignment", "usbcom.control.get_ntb_params.ndp_out_alignment", FT_UINT16, BASE_DEC,
1079
14
              NULL, 0, NULL, HFILL }},
1080
14
        { &hf_usb_com_get_ntb_params_ntb_out_max_datagrams,
1081
14
            { "NTB OUT Max Datagrams", "usbcom.control.get_ntb_params.ntb_out_max_datagrams", FT_UINT16, BASE_DEC,
1082
14
              NULL, 0, NULL, HFILL }},
1083
14
        { &hf_usb_com_get_net_address_eui48,
1084
14
            { "EUI-48", "usbcom.control.get_net_address.eui48", FT_ETHER, BASE_NONE,
1085
14
              NULL, 0, NULL, HFILL }},
1086
14
        { &hf_usb_com_set_net_address_eui48,
1087
14
            { "EUI-48", "usbcom.control.set_net_address.eui48", FT_ETHER, BASE_NONE,
1088
14
              NULL, 0, NULL, HFILL }},
1089
14
        { &hf_usb_com_get_ntb_format_ntb_format,
1090
14
            { "NTB Format", "usbcom.control.get_net_address.ntb_format", FT_UINT16, BASE_HEX,
1091
14
              VALS(usb_com_ntb_format_vals), 0, NULL, HFILL }},
1092
14
        { &hf_usb_com_set_ntb_format_ntb_format,
1093
14
            { "NTB Format", "usbcom.control.set_net_address.ntb_format", FT_UINT16, BASE_HEX,
1094
14
              VALS(usb_com_ntb_format_vals), 0, NULL, HFILL }},
1095
14
        { &hf_usb_com_get_ntb_input_size_ntb_in_max_size,
1096
14
            { "NTB IN Max Size", "usbcom.control.get_ntb_input_size.ntb_in_max_size", FT_UINT32, BASE_DEC,
1097
14
              NULL, 0, NULL, HFILL }},
1098
14
        { &hf_usb_com_get_ntb_input_size_ntb_in_max_datagrams,
1099
14
            { "NTB IN Max Datagrams", "usbcom.control.get_ntb_input_size.ntb_in_max_datagrams", FT_UINT16, BASE_DEC,
1100
14
              NULL, 0, NULL, HFILL }},
1101
14
        { &hf_usb_com_get_ntb_input_size_reserved,
1102
14
            { "Reserved", "usbcom.control.get_ntb_input_size.reserved", FT_UINT16, BASE_HEX,
1103
14
              NULL, 0, NULL, HFILL }},
1104
14
        { &hf_usb_com_set_ntb_input_size_ntb_in_max_size,
1105
14
            { "NTB IN Max Size", "usbcom.control.set_ntb_input_size.ntb_in_max_size", FT_UINT32, BASE_DEC,
1106
14
              NULL, 0, NULL, HFILL }},
1107
14
        { &hf_usb_com_set_ntb_input_size_ntb_in_max_datagrams,
1108
14
            { "NTB IN Max Datagrams", "usbcom.control.set_ntb_input_size.ntb_in_max_datagrams", FT_UINT16, BASE_DEC,
1109
14
              NULL, 0, NULL, HFILL }},
1110
14
        { &hf_usb_com_set_ntb_input_size_reserved,
1111
14
            { "Reserved", "usbcom.control.set_ntb_input_size.reserved", FT_UINT16, BASE_HEX,
1112
14
              NULL, 0, NULL, HFILL }},
1113
14
        { &hf_usb_com_get_max_datagram_size_size,
1114
14
            { "Max Datagram Size", "usbcom.control.get_max_datagram_size.size", FT_UINT16, BASE_DEC,
1115
14
              NULL, 0, NULL, HFILL }},
1116
14
        { &hf_usb_com_set_max_datagram_size_size,
1117
14
            { "Max Datagram Size", "usbcom.control.set_max_datagram_size.size", FT_UINT16, BASE_DEC,
1118
14
              NULL, 0, NULL, HFILL }},
1119
14
        { &hf_usb_com_get_crc_mode_crc_mode,
1120
14
            { "CRC Mode", "usbcom.control.get_crc_mode.crc_mode", FT_UINT16, BASE_HEX,
1121
14
              VALS(usb_com_crc_mode_vals), 0, NULL, HFILL }},
1122
14
        { &hf_usb_com_set_crc_mode_crc_mode,
1123
14
            { "CRC Mode", "usbcom.control.set_crc_mode.crc_mode", FT_UINT16, BASE_HEX,
1124
14
              VALS(usb_com_crc_mode_vals), 0, NULL, HFILL }},
1125
14
        { &hf_usb_com_control_payload,
1126
14
            { "Payload", "usbcom.control.payload", FT_BYTES, BASE_NONE,
1127
14
              NULL, 0, NULL, HFILL }},
1128
14
        { &hf_usb_com_capabilities,
1129
14
            { "bmCapabilities", "usbcom.descriptor.capabilities", FT_UINT8, BASE_HEX,
1130
14
              NULL, 0, NULL, HFILL }},
1131
14
        { &hf_usb_com_descriptor_acm_capabilities_reserved,
1132
14
            { "Reserved", "usbcom.descriptor.acm.capabilities.reserved", FT_UINT8, BASE_HEX,
1133
14
              NULL, 0xF0, NULL, HFILL }},
1134
14
        { &hf_usb_com_descriptor_acm_capabilities_network_connection,
1135
14
            { "Network_Connection", "usbcom.descriptor.acm.capabilities.network_connection", FT_BOOLEAN, 8,
1136
14
              TFS(&tfs_supported_not_supported), 0x08, NULL, HFILL }},
1137
14
        { &hf_usb_com_descriptor_acm_capabilities_send_break,
1138
14
            { "Send_Break", "usbcom.descriptor.acm.capabilities.send_break", FT_BOOLEAN, 8,
1139
14
              TFS(&tfs_supported_not_supported), 0x04, NULL, HFILL }},
1140
14
        { &hf_usb_com_descriptor_acm_capabilities_line_and_state,
1141
14
            { "Line Requests and State Notification", "usbcom.descriptor.acm.capabilities.line_and_state", FT_BOOLEAN, 8,
1142
14
              TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
1143
14
        { &hf_usb_com_descriptor_acm_capabilities_comm_features,
1144
14
            { "Comm Features Combinations", "usbcom.descriptor.acm.capabilities.comm_features", FT_BOOLEAN, 8,
1145
14
              TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
1146
14
        { &hf_usb_com_descriptor_control_interface,
1147
14
            { "Control Interface", "usbcom.descriptor.control_interface", FT_UINT8, BASE_HEX,
1148
14
              NULL, 0, NULL, HFILL }},
1149
14
        { &hf_usb_com_descriptor_subordinate_interface,
1150
14
            { "Subordinate Interface", "usbcom.descriptor.subordinate_interface", FT_UINT8, BASE_HEX,
1151
14
              NULL, 0, NULL, HFILL }},
1152
14
        { &hf_usb_com_descriptor_cm_capabilities_reserved,
1153
14
            { "Reserved", "usbcom.descriptor.cm.capabilities.reserved", FT_UINT8, BASE_HEX,
1154
14
              NULL, 0xFC, NULL, HFILL }},
1155
14
        { &hf_usb_com_descriptor_cm_capabilities_call_management_over_data_class_interface,
1156
14
            { "Call Management over Data Class Interface", "usbcom.descriptor.cm.capabilities.call_management_over_data_class_interface", FT_BOOLEAN, 8,
1157
14
              TFS(&tfs_supported_not_supported), 0x02, NULL, HFILL }},
1158
14
        { &hf_usb_com_descriptor_cm_capabilities_call_management,
1159
14
            { "Call Management", "usbcom.descriptor.cm.capabilities.call_management", FT_BOOLEAN, 8,
1160
14
              TFS(&tfs_supported_not_supported), 0x01, NULL, HFILL }},
1161
14
        { &hf_usb_com_descriptor_cm_data_interface,
1162
14
            { "Data Interface", "usbcom.descriptor.cm.data_interface", FT_UINT8, BASE_HEX,
1163
14
              NULL, 0, NULL, HFILL }},
1164
14
        { &hf_usb_com_descriptor_ecm_mac_address,
1165
14
            { "MAC Address", "usbcom.descriptor.ecm.mac_address", FT_UINT8, BASE_HEX,
1166
14
              NULL, 0, NULL, HFILL }},
1167
14
        { &hf_usb_com_descriptor_ecm_eth_stats,
1168
14
            { "Ethernet Statistics", "usbcom.descriptor.ecm.eth_stats", FT_UINT32, BASE_HEX,
1169
14
              NULL, 0, NULL, HFILL }},
1170
14
        { &hf_usb_com_descriptor_ecm_eth_stats_reserved,
1171
14
            { "Reserved", "usbcom.descriptor.ecm.eth_stats.reserved", FT_UINT32, BASE_HEX,
1172
14
              NULL, 0xe0000000, NULL, HFILL }},
1173
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_late_collisions,
1174
14
            { "XMIT Late Collisions", "usbcom.descriptor.ecm.eth_stats.xmit_late_collisions", FT_BOOLEAN, 32,
1175
14
              TFS(&tfs_supported_not_supported), 0x10000000, NULL, HFILL }},
1176
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_times_crs_lost,
1177
14
            { "XMIT TImes CRS Lost", "usbcom.descriptor.ecm.eth_stats.xmit_times_crs_lost", FT_BOOLEAN, 32,
1178
14
              TFS(&tfs_supported_not_supported), 0x08000000, NULL, HFILL }},
1179
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_heartbeat_failure,
1180
14
            { "XMIT Heartbeat Failure", "usbcom.descriptor.ecm.eth_stats.xmit_heartbeat_failure", FT_BOOLEAN, 32,
1181
14
              TFS(&tfs_supported_not_supported), 0x04000000, NULL, HFILL }},
1182
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_underrun,
1183
14
            { "XMIT Underrun", "usbcom.descriptor.ecm.eth_stats.xmit_underrun", FT_BOOLEAN, 32,
1184
14
              TFS(&tfs_supported_not_supported), 0x02000000, NULL, HFILL }},
1185
14
        { &hf_usb_com_descriptor_ecm_eth_stats_rcv_overrun,
1186
14
            { "RCV Overrun", "usbcom.descriptor.ecm.eth_stats.rcv_overrun", FT_BOOLEAN, 32,
1187
14
              TFS(&tfs_supported_not_supported), 0x01000000, NULL, HFILL }},
1188
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_max_collisions,
1189
14
            { "XMIT Max Collisions", "usbcom.descriptor.ecm.eth_stats.xmit_max_collisions", FT_BOOLEAN, 32,
1190
14
              TFS(&tfs_supported_not_supported), 0x00800000, NULL, HFILL }},
1191
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_deferred,
1192
14
            { "XMIT Deferred", "usbcom.descriptor.ecm.eth_stats.xmit_deferred", FT_BOOLEAN, 32,
1193
14
              TFS(&tfs_supported_not_supported), 0x00400000, NULL, HFILL }},
1194
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_more_collisions,
1195
14
            { "XMIT More Collisions", "usbcom.descriptor.ecm.eth_stats.xmit_more_collisions", FT_BOOLEAN, 32,
1196
14
              TFS(&tfs_supported_not_supported), 0x00200000, NULL, HFILL }},
1197
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_one_collision,
1198
14
            { "XMIT One Collision", "usbcom.descriptor.ecm.eth_stats.xmit_one_collision", FT_BOOLEAN, 32,
1199
14
              TFS(&tfs_supported_not_supported), 0x00100000, NULL, HFILL }},
1200
14
        { &hf_usb_com_descriptor_ecm_eth_stats_rcv_error_alignment,
1201
14
            { "RCV Error Alignment", "usbcom.descriptor.ecm.eth_stats.rcv_error_alignment", FT_BOOLEAN, 32,
1202
14
              TFS(&tfs_supported_not_supported), 0x00080000, NULL, HFILL }},
1203
14
        { &hf_usb_com_descriptor_ecm_eth_stats_transmit_queue_length,
1204
14
            { "Transmit Queue Length", "usbcom.descriptor.ecm.eth_stats.transmit_queue_length", FT_BOOLEAN, 32,
1205
14
              TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
1206
14
        { &hf_usb_com_descriptor_ecm_eth_stats_rcv_crc_error,
1207
14
            { "RCV CRC Error", "usbcom.descriptor.ecm.eth_stats.rcv_crc_error", FT_BOOLEAN, 32,
1208
14
              TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
1209
14
        { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_rcv,
1210
14
            { "Broadcast Frames RCV", "usbcom.descriptor.ecm.eth_stats.broadcast_frames_rcv", FT_BOOLEAN, 32,
1211
14
              TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
1212
14
        { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_rcv,
1213
14
            { "Broadcast Bytes RCV", "usbcom.descriptor.ecm.eth_stats.broadcast_bytes_rcv", FT_BOOLEAN, 32,
1214
14
              TFS(&tfs_supported_not_supported), 0x00008000, NULL, HFILL }},
1215
14
        { &hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_rcv,
1216
14
            { "Multicast Frames RCV", "usbcom.descriptor.ecm.eth_stats.multicast_frames_rcv", FT_BOOLEAN, 32,
1217
14
              TFS(&tfs_supported_not_supported), 0x00004000, NULL, HFILL }},
1218
14
        { &hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_rcv,
1219
14
            { "Multicast Bytes RCV", "usbcom.descriptor.ecm.eth_stats.multicast_bytes_rcv", FT_BOOLEAN, 32,
1220
14
              TFS(&tfs_supported_not_supported), 0x00002000, NULL, HFILL }},
1221
14
        { &hf_usb_com_descriptor_ecm_eth_stats_directed_frames_rcv,
1222
14
            { "Directed Frames RCV", "usbcom.descriptor.ecm.eth_stats.directed_frames_rcv", FT_BOOLEAN, 32,
1223
14
              TFS(&tfs_supported_not_supported), 0x00001000, NULL, HFILL }},
1224
14
        { &hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_rcv,
1225
14
            { "Directed Bytes RCV", "usbcom.descriptor.ecm.eth_stats.directed_bytes_rcv", FT_BOOLEAN, 32,
1226
14
              TFS(&tfs_supported_not_supported), 0x00000800, NULL, HFILL }},
1227
14
        { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_frames_xmit,
1228
14
            { "Broadcast Frames XMIT", "usbcom.descriptor.ecm.eth_stats.broadcast_frames_xmit", FT_BOOLEAN, 32,
1229
14
              TFS(&tfs_supported_not_supported), 0x00000400, NULL, HFILL }},
1230
14
        { &hf_usb_com_descriptor_ecm_eth_stats_broadcast_bytes_xmit,
1231
14
            { "Broadcast Bytes XMIT", "usbcom.descriptor.ecm.eth_stats.broadcast_bytes_xmit", FT_BOOLEAN, 32,
1232
14
              TFS(&tfs_supported_not_supported), 0x00000200, NULL, HFILL }},
1233
14
        { &hf_usb_com_descriptor_ecm_eth_stats_multicast_frames_xmit,
1234
14
            { "Multicast Frames XMIT", "usbcom.descriptor.ecm.eth_stats.multicast_frames_xmit", FT_BOOLEAN, 32,
1235
14
              TFS(&tfs_supported_not_supported), 0x00000100, NULL, HFILL }},
1236
14
        { &hf_usb_com_descriptor_ecm_eth_stats_multicast_bytes_xmit,
1237
14
            { "Multicast Bytes XMIT", "usbcom.descriptor.ecm.eth_stats.multicast_bytes_xmit", FT_BOOLEAN, 32,
1238
14
              TFS(&tfs_supported_not_supported), 0x00000080, NULL, HFILL }},
1239
14
        { &hf_usb_com_descriptor_ecm_eth_stats_directed_frames_xmit,
1240
14
            { "Directed Frames XMIT", "usbcom.descriptor.ecm.eth_stats.directed_frames_xmit", FT_BOOLEAN, 32,
1241
14
              TFS(&tfs_supported_not_supported), 0x00000040, NULL, HFILL }},
1242
14
        { &hf_usb_com_descriptor_ecm_eth_stats_directed_bytes_xmit,
1243
14
            { "Directed Bytes XMIT", "usbcom.descriptor.ecm.eth_stats.directed_bytes_xmit", FT_BOOLEAN, 32,
1244
14
              TFS(&tfs_supported_not_supported), 0x00000020, NULL, HFILL }},
1245
14
        { &hf_usb_com_descriptor_ecm_eth_stats_rcv_no_buffer,
1246
14
            { "RCV No Buffer", "usbcom.descriptor.ecm.eth_stats.rcv_no_buffer", FT_BOOLEAN, 32,
1247
14
              TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
1248
14
        { &hf_usb_com_descriptor_ecm_eth_stats_rcv_error,
1249
14
            { "RCV Error", "usbcom.descriptor.ecm.eth_stats.rcv_error", FT_BOOLEAN, 32,
1250
14
              TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
1251
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_error,
1252
14
            { "XMIT Error", "usbcom.descriptor.ecm.eth_stats.xmit_error", FT_BOOLEAN, 32,
1253
14
              TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
1254
14
        { &hf_usb_com_descriptor_ecm_eth_stats_rvc_ok,
1255
14
            { "RCV OK", "usbcom.descriptor.ecm.eth_stats.rvc_ok", FT_BOOLEAN, 32,
1256
14
              TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
1257
14
        { &hf_usb_com_descriptor_ecm_eth_stats_xmit_ok,
1258
14
            { "XMIT OK", "usbcom.descriptor.ecm.eth_stats.xmit_ok", FT_BOOLEAN, 32,
1259
14
              TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
1260
14
        { &hf_usb_com_descriptor_ecm_max_segment_size,
1261
14
            { "Max Segment Size", "usbcom.descriptor.ecm.max_segment_size", FT_UINT16, BASE_DEC,
1262
14
              NULL, 0, NULL, HFILL }},
1263
14
        { &hf_usb_com_descriptor_ecm_nb_mc_filters,
1264
14
            { "Number MC Filters", "usbcom.descriptor.ecm.nb_mc_filters", FT_UINT16, BASE_HEX,
1265
14
              NULL, 0, NULL, HFILL }},
1266
14
        { &hf_usb_com_descriptor_ecm_nb_mc_filters_mc_address_filtering,
1267
14
            { "Multicast Address Filtering", "usbcom.descriptor.ecm.nb_mc_filters.mc_address_filtering", FT_BOOLEAN, 16,
1268
14
              TFS(&usb_com_ecm_mc_address_filtering), 0x8000, NULL, HFILL }},
1269
14
        { &hf_usb_com_descriptor_ecm_nb_mc_filters_nb_filters_supported,
1270
14
            { "Number of Multicast Address Filters Supported", "usbcom.descriptor.ecm.nb_mc_filters.nb_filters_supported", FT_UINT16, BASE_DEC,
1271
14
              NULL, 0x7fff, NULL, HFILL }},
1272
14
        { &hf_usb_com_descriptor_ecm_nb_power_filters,
1273
14
            { "Number Power Filters", "usbcom.descriptor.ecm.nb_power_filters", FT_UINT8, BASE_DEC,
1274
14
              NULL, 0, NULL, HFILL }},
1275
14
        { &hf_usb_com_interrupt_request_type,
1276
14
            { "Request Type", "usbcom.interrupt.request_type", FT_UINT8, BASE_HEX,
1277
14
              NULL, 0, NULL, HFILL }},
1278
14
        { &hf_usb_com_interrupt_notif_code,
1279
14
            { "Notification Code", "usbcom.interrupt.notification_code", FT_UINT8, BASE_HEX,
1280
14
              VALS(usb_com_interrupt_notif_code_vals), 0, NULL, HFILL }},
1281
14
        { &hf_usb_com_interrupt_value,
1282
14
            { "Value", "usbcom.interrupt.value", FT_UINT16, BASE_HEX,
1283
14
              NULL, 0, NULL, HFILL }},
1284
14
        { &hf_usb_com_interrupt_value_nw_conn,
1285
14
            { "Value", "usbcom.interrupt.value", FT_UINT16, BASE_HEX,
1286
14
              VALS(usb_com_interrupt_value_nw_conn_vals), 0, NULL, HFILL }},
1287
14
        { &hf_usb_com_interrupt_index,
1288
14
            { "Index", "usbcom.interrupt.index", FT_UINT16, BASE_DEC,
1289
14
              NULL, 0, NULL, HFILL }},
1290
14
        { &hf_usb_com_interrupt_length,
1291
14
            { "Length", "usbcom.interrupt.length", FT_UINT16, BASE_DEC,
1292
14
              NULL, 0, NULL, HFILL }},
1293
14
        { &hf_usb_com_interrupt_dl_bitrate,
1294
14
            { "DL Bitrate", "usbcom.interrupt.conn_speed_change.dl_bitrate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING,
1295
14
              UNS(&units_bit_sec), 0, NULL, HFILL }},
1296
14
        { &hf_usb_com_interrupt_ul_bitrate,
1297
14
            { "UL Bitrate", "usbcom.interrupt.conn_speed_change.ul_bitrate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING,
1298
14
              UNS(&units_bit_sec), 0, NULL, HFILL }},
1299
14
        { &hf_usb_com_interrupt_payload,
1300
14
            { "Payload", "usbcom.interrupt.payload", FT_BYTES, BASE_NONE,
1301
14
              NULL, 0, NULL, HFILL }},
1302
14
        { &hf_usb_com_data_stream,
1303
14
            { "Stream index", "usbcom.data.stream", FT_UINT32, BASE_DEC,
1304
14
              NULL, 0, NULL, HFILL }},
1305
14
        { &hf_usb_com_data_in_payload,
1306
14
            { "IN payload", "usbcom.data.in_payload", FT_BYTES, BASE_NONE,
1307
14
              NULL, 0, NULL, HFILL }},
1308
14
        { &hf_usb_com_data_out_payload,
1309
14
            { "OUT payload", "usbcom.data.out_payload", FT_BYTES, BASE_NONE,
1310
14
              NULL, 0, NULL, HFILL }},
1311
14
    };
1312
1313
14
    static int *usb_com_ett[] = {
1314
14
        &ett_usb_com,
1315
14
        &ett_usb_com_capabilities,
1316
14
        &ett_usb_com_bitmap,
1317
14
        &ett_usb_com_descriptor_ecm_eth_stats,
1318
14
        &ett_usb_com_descriptor_ecm_nb_mc_filters
1319
14
    };
1320
1321
14
    static ei_register_info ei[] = {
1322
14
        { &ei_unexpected_controlling_iface, { "usbcom.descriptor.control_interface.unexpected_iface", PI_MALFORMED, PI_ERROR, "Unexpected controlling interface index (report to wireshark.org)", EXPFILL }},
1323
14
    };
1324
1325
14
    expert_module_t* expert_usb_com;
1326
1327
14
    controlling_ifaces = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1328
1329
14
    proto_usb_com = proto_register_protocol("USB Communications and CDC Control", "USBCOM", "usbcom");
1330
14
    proto_register_field_array(proto_usb_com, hf, array_length(hf));
1331
14
    proto_register_subtree_array(usb_com_ett, array_length(usb_com_ett));
1332
1333
14
    usb_com_descriptor_handle = register_dissector("usbcom.descriptor", dissect_usb_com_descriptor, proto_usb_com);
1334
14
    usb_com_control_handle = register_dissector("usbcom.control", dissect_usb_com_control, proto_usb_com);
1335
14
    usb_com_bulk_handle = register_dissector("usbcom.bulk", dissect_usb_com_bulk, proto_usb_com);
1336
14
    usb_com_interrupt_handle = register_dissector("usbcom.interrupt", dissect_usb_com_interrupt, proto_usb_com);
1337
1338
14
    expert_usb_com = expert_register_protocol(proto_usb_com);
1339
14
    expert_register_field_array(expert_usb_com, ei, array_length(ei));
1340
1341
14
    register_cleanup_routine(usb_com_cleanup_data);
1342
1343
14
    cdc_data_follow_tap = register_tap("cdc_data_follow");
1344
14
    register_follow_stream(proto_usb_com, "cdc_data_follow", cdc_data_follow_conv_filter, cdc_data_follow_index_filter,
1345
14
                           cdc_data_follow_address_filter, cdc_data_port_to_display, follow_cdc_data_tap_listener,
1346
14
                           get_cdc_data_stream_count, NULL);
1347
14
}
1348
1349
void
1350
proto_reg_handoff_usb_com(void)
1351
14
{
1352
14
    dissector_add_uint("usb.descriptor", IF_CLASS_COMMUNICATIONS, usb_com_descriptor_handle);
1353
14
    dissector_add_uint("usb.control", IF_CLASS_COMMUNICATIONS, usb_com_control_handle);
1354
14
    dissector_add_uint("usb.bulk", IF_CLASS_CDC_DATA, usb_com_bulk_handle);
1355
14
    dissector_add_uint("usb.interrupt", IF_CLASS_COMMUNICATIONS, usb_com_interrupt_handle);
1356
14
    mbim_control_handle = find_dissector_add_dependency("mbim.control", proto_usb_com);
1357
14
    mbim_descriptor_handle = find_dissector_add_dependency("mbim.descriptor", proto_usb_com);
1358
14
    mbim_bulk_handle = find_dissector_add_dependency("mbim.bulk", proto_usb_com);
1359
14
    eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_usb_com);
1360
1361
14
    proto_usb = proto_get_id_by_filter_name("usb");
1362
14
}
1363
1364
/*
1365
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1366
 *
1367
 * Local variables:
1368
 * c-basic-offset: 4
1369
 * tab-width: 8
1370
 * indent-tabs-mode: nil
1371
 * End:
1372
 *
1373
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1374
 * :indentSize=4:tabSize=8:noTabs=true:
1375
 */