Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-usb-hub.c
Line
Count
Source
1
/* packet-usb-hub.c
2
 * Routines for USB HUB dissection
3
 * Copyright 2009, Marton Nemeth <nm127@freemail.hu>
4
 *
5
 * USB HUB Specification can be found in the Universal Serial Bus
6
 * Specification 2.0, Chapter 11 Hub Specification.
7
 * http://www.usb.org/developers/docs/usb_20_052709.zip
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include "packet-usb.h"
20
21
void proto_register_usb_hub(void);
22
void proto_reg_handoff_usb_hub(void);
23
24
static dissector_handle_t usb_hub_control_handle;
25
26
/* protocols and header fields */
27
static int proto_usb_hub;
28
29
/* USB 2.0, Chapter 11.24.2 Class-Specific Requests */
30
static int hf_usb_hub_request;
31
static int hf_usb_hub_value;
32
static int hf_usb_hub_index;
33
static int hf_usb_hub_length;
34
35
static int hf_usb_hub_hub_feature_selector;
36
static int hf_usb_hub_port_feature_selector;
37
static int hf_usb_hub_dev_addr;
38
static int hf_usb_hub_ep_num;
39
static int hf_usb_hub_descriptor_type;
40
static int hf_usb_hub_descriptor_index;
41
static int hf_usb_hub_zero;
42
static int hf_usb_hub_tt_flags;
43
static int hf_usb_hub_tt_port;
44
static int hf_usb_hub_tt_state_length;
45
static int hf_usb_hub_port;
46
static int hf_usb_hub_port_selector;
47
static int hf_usb_hub_port_status;
48
static int hf_usb_hub_port_change;
49
static int hf_usb_hub_port_status_connection;
50
static int hf_usb_hub_port_status_enable;
51
static int hf_usb_hub_port_status_suspend;
52
static int hf_usb_hub_port_status_overcurrent;
53
static int hf_usb_hub_port_status_reset;
54
static int hf_usb_hub_port_status_power;
55
static int hf_usb_hub_port_status_low_speed;
56
static int hf_usb_hub_port_status_high_speed;
57
static int hf_usb_hub_port_status_test;
58
static int hf_usb_hub_port_status_indicator;
59
static int hf_usb_hub_port_change_connection;
60
static int hf_usb_hub_port_change_enable;
61
static int hf_usb_hub_port_change_suspend;
62
static int hf_usb_hub_port_change_overcurrent;
63
static int hf_usb_hub_port_change_reset;
64
static int hf_usb_hub_descriptor_length;
65
66
static int ett_usb_hub_wValue;
67
static int ett_usb_hub_wIndex;
68
static int ett_usb_hub_wLength;
69
static int ett_usb_hub_port_status;
70
static int ett_usb_hub_port_change;
71
72
/* Table 11-16. Hub Class Request Codes */
73
#define USB_HUB_REQUEST_GET_STATUS            0
74
#define USB_HUB_REQUEST_CLEAR_FEATURE         1
75
#define USB_HUB_REQUEST_SET_FEATURE           3
76
#define USB_HUB_REQUEST_GET_DESCRIPTOR        6
77
#define USB_HUB_REQUEST_SET_DESCRIPTOR        7
78
#define USB_HUB_REQUEST_CLEAR_TT_BUFFER       8
79
#define USB_HUB_REQUEST_RESET_TT              9
80
#define USB_HUB_REQUEST_GET_TT_STATE         10
81
#define USB_HUB_REQUEST_STOP_TT              11
82
83
static const value_string setup_request_names_vals[] = {
84
  { USB_HUB_REQUEST_GET_STATUS,    "GET_STATUS" },
85
  { USB_HUB_REQUEST_CLEAR_FEATURE,   "CLEAR_FEATURE" },
86
  { USB_HUB_REQUEST_SET_FEATURE,     "SET_FEATURE" },
87
  { USB_HUB_REQUEST_GET_DESCRIPTOR,  "GET_DESCRIPTOR" },
88
  { USB_HUB_REQUEST_SET_DESCRIPTOR,  "SET_DESCRIPTOR" },
89
  { USB_HUB_REQUEST_CLEAR_TT_BUFFER, "CLEAR_TT_BUFFER" },
90
  { USB_HUB_REQUEST_GET_TT_STATE,    "GET_TT_STATE" },
91
  { USB_HUB_REQUEST_STOP_TT,     "STOP_TT" },
92
  { 0, NULL }
93
};
94
95
96
/* Table 11-17 Hub Class Feature Selectors */
97
#define USB_HUB_FEATURE_C_HUB_LOCAL_POWER      0
98
#define USB_HUB_FEATURE_C_HUB_OVER_CURRENT     1
99
100
#define USB_HUB_FEATURE_PORT_CONNECTION        0
101
#define USB_HUB_FEATURE_PORT_ENABLE            1
102
#define USB_HUB_FEATURE_PORT_SUSPEND           2
103
#define USB_HUB_FEATURE_PORT_OVER_CURRENT      3
104
#define USB_HUB_FEATURE_PORT_RESET             4
105
#define USB_HUB_FEATURE_PORT_POWER             8
106
#define USB_HUB_FEATURE_PORT_LOW_SPEED         9
107
#define USB_HUB_FEATURE_C_PORT_CONNECTION     16
108
#define USB_HUB_FEATURE_C_PORT_ENABLE         17
109
#define USB_HUB_FEATURE_C_PORT_SUSPEND        18
110
#define USB_HUB_FEATURE_C_PORT_OVER_CURRENT   19
111
#define USB_HUB_FEATURE_C_PORT_RESET          20
112
#define USB_HUB_FEATURE_PORT_TEST             21
113
#define USB_HUB_FEATURE_PORT_INDICATOR        22
114
/* Table 10-9 Hub Class Feature Selectors (USB3) */
115
#define USB_HUB_FEATURE_PORT_U1_TIMEOUT       23
116
#define USB_HUB_FEATURE_PORT_U2_TIMEOUT       24
117
#define USB_HUB_FEATURE_C_PORT_LINK_STATE     25
118
#define USB_HUB_FEATURE_C_PORT_CONFIG_ERROR   26
119
#define USB_HUB_FEATURE_PORT_REMOTE_WAKE_MASK 27
120
#define USB_HUB_FEATURE_BH_PORT_RESET         28
121
#define USB_HUB_FEATURE_C_BH_PORT_RESET       29
122
#define USB_HUB_FEATURE_FORCE_LINKPM_ACCEPT   30
123
124
static const value_string hub_class_feature_selectors_recipient_hub_vals[] = {
125
  { USB_HUB_FEATURE_C_HUB_LOCAL_POWER,  "C_HUB_LOCAL_POWER" },
126
  { USB_HUB_FEATURE_C_HUB_OVER_CURRENT, "C_HUB_OVER_CURRENT" },
127
  { 0, NULL }
128
};
129
130
static const value_string hub_class_feature_selectors_recipient_port_vals[] = {
131
  { USB_HUB_FEATURE_PORT_CONNECTION,      "PORT_CONNECTION" },
132
  { USB_HUB_FEATURE_PORT_ENABLE,          "PORT_ENABLE" },
133
  { USB_HUB_FEATURE_PORT_SUSPEND,         "PORT_SUSPEND" },
134
  { USB_HUB_FEATURE_PORT_OVER_CURRENT,    "PORT_OVER_CURRENT" },
135
  { USB_HUB_FEATURE_PORT_RESET,           "PORT_RESET" },
136
  { USB_HUB_FEATURE_PORT_POWER,           "PORT_POWER" },
137
  { USB_HUB_FEATURE_PORT_LOW_SPEED,       "PORT_LOW_SPEED" },
138
  { USB_HUB_FEATURE_C_PORT_CONNECTION,    "C_PORT_CONNECTION" },
139
  { USB_HUB_FEATURE_C_PORT_ENABLE,        "C_PORT_ENABLE" },
140
  { USB_HUB_FEATURE_C_PORT_SUSPEND,       "C_PORT_SUSPEND" },
141
  { USB_HUB_FEATURE_C_PORT_OVER_CURRENT,  "C_PORT_OVER_CURRENT" },
142
  { USB_HUB_FEATURE_C_PORT_RESET,         "C_PORT_RESET" },
143
  { USB_HUB_FEATURE_PORT_TEST,            "PORT_TEST" },
144
  { USB_HUB_FEATURE_PORT_INDICATOR,       "PORT_INDICATOR" },
145
  { USB_HUB_FEATURE_PORT_U1_TIMEOUT,      "PORT_U1_TIMEOUT" },
146
  { USB_HUB_FEATURE_PORT_U2_TIMEOUT,      "PORT_U2_TIMEOUT" },
147
  { USB_HUB_FEATURE_C_PORT_LINK_STATE,    "C_PORT_LINK_STATE" },
148
  { USB_HUB_FEATURE_C_PORT_CONFIG_ERROR,  "C_PORT_CONFIG_ERROR" },
149
  { USB_HUB_FEATURE_PORT_REMOTE_WAKE_MASK,"PORT_REMOTE_WAKE_MASK" },
150
  { USB_HUB_FEATURE_BH_PORT_RESET,        "BH_PORT_RESET" },
151
  { USB_HUB_FEATURE_C_BH_PORT_RESET,      "C_BH_PORT_RESET" },
152
  { USB_HUB_FEATURE_FORCE_LINKPM_ACCEPT,  "FORCE_LINKPM_ACCEPT" },
153
  { 0, NULL }
154
};
155
156
static const true_false_string hub_port_status_indicator_meaning = {
157
  "Software-controlled color",
158
  "Default colors"
159
};
160
161
/* Dissector for ClearHubFeature, Chapter 11.24.2.1 Clear Hub Feature */
162
static void
163
dissect_usb_hub_clear_hub_feature(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
164
0
{
165
0
  proto_item *item = NULL;
166
0
  proto_tree *subtree = NULL;
167
0
  const char* feature_name;
168
169
0
  feature_name = val_to_str(pinfo->pool, usb_trans_info->setup.wValue,
170
0
                hub_class_feature_selectors_recipient_hub_vals,
171
0
                "UNKNOWN (0x%x)");
172
0
  col_append_fstr(pinfo->cinfo, COL_INFO, " [Hub: %s]", feature_name);
173
174
0
  if (is_request) {
175
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
176
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
177
0
    proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
178
0
    offset += 2;
179
180
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
181
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
182
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
183
0
    offset += 2;
184
185
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
186
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
187
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
188
    /*offset += 2;*/
189
0
  } else {
190
0
  }
191
0
}
192
193
/* Dissector for ClearPortFeature, Chapter 11.24.2.2 Clear Port Feature */
194
static void
195
dissect_usb_hub_clear_port_feature(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
196
0
{
197
0
  proto_item *item = NULL;
198
0
  proto_tree *subtree = NULL;
199
0
  const char* feature_name;
200
201
0
  feature_name = val_to_str(pinfo->pool, usb_trans_info->setup.wValue,
202
0
                hub_class_feature_selectors_recipient_port_vals,
203
0
                "UNKNOWN (0x%x)");
204
0
  col_append_fstr(pinfo->cinfo, COL_INFO, " [Port %u: %s]", usb_trans_info->setup.wIndex, feature_name);
205
206
0
  if (is_request) {
207
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
208
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
209
0
    proto_tree_add_item(subtree, hf_usb_hub_port_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
210
0
    offset += 2;
211
212
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
213
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
214
0
    proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
215
0
    offset++;
216
0
    proto_tree_add_item(subtree, hf_usb_hub_port_selector, tvb, offset, 1, ENC_LITTLE_ENDIAN);
217
0
    offset++;
218
219
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
220
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
221
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
222
    /*offset += 2;*/
223
0
  } else {
224
0
  }
225
0
}
226
227
/* Dissector for ClearTTBuffer, Chapter 11.24.2.3 Clear TT Buffer */
228
static void
229
dissect_usb_hub_clear_tt_buffer(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
230
0
{
231
0
  proto_item *item = NULL;
232
0
  proto_tree *subtree = NULL;
233
234
0
  if (is_request) {
235
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
236
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
237
0
    proto_tree_add_item(subtree, hf_usb_hub_ep_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
238
0
    offset++;
239
0
    proto_tree_add_item(subtree, hf_usb_hub_dev_addr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
240
0
    offset++;
241
242
0
    proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
243
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
244
0
    proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
245
0
    offset += 2;
246
247
0
    proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
248
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
249
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
250
    /*offset += 2;*/
251
0
  } else {
252
0
  }
253
0
}
254
255
/* Dissector for GetHubDescriptor, Chapter 11.24.2.5 Get Hub Descriptor */
256
static void
257
dissect_usb_hub_get_hub_descriptor(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
258
0
{
259
0
  proto_item *item = NULL;
260
0
  proto_tree *subtree = NULL;
261
262
0
  if (is_request) {
263
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
264
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
265
0
    proto_tree_add_item(subtree, hf_usb_hub_descriptor_index, tvb, offset, 1, ENC_LITTLE_ENDIAN);
266
0
    offset++;
267
0
    proto_tree_add_item(subtree, hf_usb_hub_descriptor_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
268
0
    offset++;
269
270
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
271
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
272
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
273
0
    offset += 2;
274
275
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
276
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
277
0
    proto_tree_add_item(subtree, hf_usb_hub_descriptor_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
278
    /*offset += 2;*/
279
0
  } else {
280
0
  }
281
0
}
282
283
/* Dissector for GetHubStatus, Chapter 11.24.2.6 Get Hub Status */
284
static void
285
dissect_usb_hub_get_hub_status(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
286
0
{
287
0
  proto_item *item = NULL;
288
0
  proto_tree *subtree = NULL;
289
290
0
  col_append_str(pinfo->cinfo, COL_INFO, "    [Hub]");
291
292
0
  if (is_request) {
293
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
294
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
295
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
296
0
    offset += 2;
297
298
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
299
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
300
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
301
0
    offset += 2;
302
303
0
    proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
304
    /* length shall always contain 4 */
305
    /*offset += 2;*/
306
0
  } else {
307
0
  }
308
0
}
309
310
/* Dissector for GetPortStatus, Chapter 11.24.2.7 Get Port Status */
311
static void
312
dissect_usb_hub_get_port_status(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info, urb_info_t *urb _U_)
313
0
{
314
0
  proto_item *item = NULL;
315
0
  proto_tree *subtree = NULL;
316
317
0
  col_append_fstr(pinfo->cinfo, COL_INFO, "    [Port %u]", usb_trans_info->setup.wIndex);
318
319
0
  if (is_request) {
320
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
321
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
322
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
323
0
    offset += 2;
324
325
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
326
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
327
0
    proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
328
0
    offset += 2;
329
330
0
    proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
331
    /* length shall always contain 4 */
332
    /*offset += 2;*/
333
0
  } else {
334
0
    static int * const status_fields[] = {
335
0
      &hf_usb_hub_port_status_connection,
336
0
      &hf_usb_hub_port_status_enable,
337
0
      &hf_usb_hub_port_status_suspend,
338
0
      &hf_usb_hub_port_status_overcurrent,
339
0
      &hf_usb_hub_port_status_reset,
340
0
      &hf_usb_hub_port_status_power,
341
0
      &hf_usb_hub_port_status_low_speed,
342
0
      &hf_usb_hub_port_status_high_speed,
343
0
      &hf_usb_hub_port_status_test,
344
0
      &hf_usb_hub_port_status_indicator,
345
0
      NULL
346
0
    };
347
348
0
    static int * const change_fields[] = {
349
0
      &hf_usb_hub_port_change_connection,
350
0
      &hf_usb_hub_port_change_enable,
351
0
      &hf_usb_hub_port_change_suspend,
352
0
      &hf_usb_hub_port_change_overcurrent,
353
0
      &hf_usb_hub_port_change_reset,
354
0
      NULL
355
0
    };
356
357
0
    proto_tree_add_bitmask(tree, tvb, offset, hf_usb_hub_port_status,
358
0
                           ett_usb_hub_port_status, status_fields, ENC_LITTLE_ENDIAN);
359
0
    offset += 2;
360
0
    proto_tree_add_bitmask(tree, tvb, offset, hf_usb_hub_port_change,
361
0
                           ett_usb_hub_port_change, change_fields, ENC_LITTLE_ENDIAN);
362
    /*offset += 2;*/
363
0
  }
364
0
}
365
366
/* Dissector for GetTTState, Chapter 11.24.2.8 Get_TT_State */
367
static void
368
dissect_usb_hub_get_tt_state(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
369
0
{
370
0
  proto_item *item = NULL;
371
0
  proto_tree *subtree = NULL;
372
373
0
  if (is_request) {
374
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
375
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
376
0
    proto_tree_add_item(subtree, hf_usb_hub_tt_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
377
0
    offset += 2;
378
379
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
380
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
381
0
    proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
382
0
    offset += 2;
383
384
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
385
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
386
0
    proto_tree_add_item(subtree, hf_usb_hub_tt_state_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387
    /*offset += 2;*/
388
0
  } else {
389
0
  }
390
0
}
391
392
/* Dissector for ResetTT, Chapter 11.24.2.9 Reset_TT */
393
static void
394
dissect_usb_hub_reset_tt(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
395
0
{
396
0
  proto_item *item = NULL;
397
0
  proto_tree *subtree = NULL;
398
399
0
  if (is_request) {
400
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
401
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
402
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403
0
    offset += 2;
404
405
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
406
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
407
0
    proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
408
0
    offset += 2;
409
410
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
411
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
412
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
413
    /*offset += 2;*/
414
0
  } else {
415
0
  }
416
0
}
417
418
/* Dissector for SetHubDescriptor, Chapter 11.24.2.10 Set Hub Descriptor */
419
static void
420
dissect_usb_hub_set_hub_descriptor(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
421
0
{
422
0
  proto_item *item = NULL;
423
0
  proto_tree *subtree = NULL;
424
425
0
  if (is_request) {
426
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
427
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
428
0
    proto_tree_add_item(subtree, hf_usb_hub_descriptor_index, tvb, offset, 1, ENC_LITTLE_ENDIAN);
429
0
    offset++;
430
0
    proto_tree_add_item(subtree, hf_usb_hub_descriptor_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
431
0
    offset++;
432
433
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
434
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
435
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
436
0
    offset += 2;
437
438
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
439
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
440
0
    proto_tree_add_item(subtree, hf_usb_hub_descriptor_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
441
    /*offset += 2;*/
442
0
  } else {
443
0
  }
444
0
}
445
446
/* Dissector for StopTT, Chapter 11.24.2.11 Stop TT */
447
static void
448
dissect_usb_hub_stop_tt(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info _U_, urb_info_t *urb _U_)
449
0
{
450
0
  proto_item *item = NULL;
451
0
  proto_tree *subtree = NULL;
452
453
0
  if (is_request) {
454
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
455
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
456
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
457
0
    offset += 2;
458
459
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
460
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
461
0
    proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
462
0
    offset += 2;
463
464
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
465
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
466
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
467
    /*offset += 2;*/
468
0
  } else {
469
0
  }
470
0
}
471
472
/* Dissector for SetHubFeature, Chapter 11.24.2.12 Set Hub Feature */
473
static void
474
dissect_usb_hub_set_hub_feature(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info, urb_info_t *urb _U_)
475
0
{
476
0
  proto_item *item = NULL;
477
0
  proto_tree *subtree = NULL;
478
0
  const char* feature_name;
479
0
  feature_name = val_to_str(pinfo->pool, usb_trans_info->setup.wValue,
480
0
                hub_class_feature_selectors_recipient_hub_vals,
481
0
                "UNKNOWN (0x%x)");
482
0
  col_append_fstr(pinfo->cinfo, COL_INFO, "   [Hub: %s]", feature_name);
483
484
0
  if (is_request) {
485
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
486
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
487
0
    proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
488
0
    offset += 2;
489
490
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
491
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
492
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
493
0
    offset += 2;
494
495
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
496
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
497
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
498
    /*offset += 2;*/
499
0
  } else {
500
0
  }
501
0
}
502
503
/* Dissector for SetPortFeature, Chapter 11.24.2.13 Set Port Feature */
504
static void
505
dissect_usb_hub_set_port_feature(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info, urb_info_t *urb _U_)
506
0
{
507
0
  proto_item *item = NULL;
508
0
  proto_tree *subtree = NULL;
509
0
  const char* feature_name;
510
511
0
  feature_name = val_to_str(pinfo->pool, usb_trans_info->setup.wValue,
512
0
                hub_class_feature_selectors_recipient_port_vals,
513
0
                "UNKNOWN (0x%x)");
514
0
  col_append_fstr(pinfo->cinfo, COL_INFO, "   [Port %u: %s]", usb_trans_info->setup.wIndex,
515
0
          feature_name);
516
517
0
  if (is_request) {
518
0
    item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
519
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
520
0
    proto_tree_add_item(subtree, hf_usb_hub_port_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
521
0
    offset += 2;
522
523
0
    item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
524
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
525
0
    proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
526
0
    offset++;
527
0
    proto_tree_add_item(subtree, hf_usb_hub_port_selector, tvb, offset, 1, ENC_LITTLE_ENDIAN);
528
0
    offset++;
529
530
0
    item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
531
0
    subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
532
0
    proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
533
    /*offset += 2;*/
534
0
  } else {
535
0
  }
536
0
}
537
538
539
typedef void (*usb_setup_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, bool is_request, usb_trans_info_t *usb_trans_info, urb_info_t *urb);
540
541
typedef struct _usb_setup_dissector_table_t {
542
  uint8_t request_type;
543
  uint8_t request;
544
  usb_setup_dissector dissector;
545
} usb_setup_dissector_table_t;
546
547
548
/* USB 2.0, Table 11-15 Hub Class Requests */
549
static const usb_setup_dissector_table_t setup_dissectors[] = {
550
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
551
    USB_HUB_REQUEST_CLEAR_FEATURE,
552
    dissect_usb_hub_clear_hub_feature
553
  },
554
555
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
556
    USB_HUB_REQUEST_CLEAR_FEATURE,
557
    dissect_usb_hub_clear_port_feature
558
  },
559
560
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
561
    USB_HUB_REQUEST_CLEAR_TT_BUFFER,
562
    dissect_usb_hub_clear_tt_buffer
563
  },
564
565
  { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
566
    USB_HUB_REQUEST_GET_DESCRIPTOR,
567
    dissect_usb_hub_get_hub_descriptor
568
  },
569
570
  { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
571
    USB_HUB_REQUEST_GET_STATUS,
572
    dissect_usb_hub_get_hub_status
573
  },
574
575
  { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
576
    USB_HUB_REQUEST_GET_STATUS,
577
    dissect_usb_hub_get_port_status
578
  },
579
580
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
581
    USB_HUB_REQUEST_RESET_TT,
582
    dissect_usb_hub_reset_tt
583
  },
584
585
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
586
    USB_HUB_REQUEST_SET_DESCRIPTOR,
587
    dissect_usb_hub_set_hub_descriptor
588
  },
589
590
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
591
    USB_HUB_REQUEST_SET_FEATURE,
592
    dissect_usb_hub_set_hub_feature
593
  },
594
595
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
596
    USB_HUB_REQUEST_SET_FEATURE,
597
    dissect_usb_hub_set_port_feature
598
  },
599
600
  { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
601
    USB_HUB_REQUEST_GET_TT_STATE,
602
    dissect_usb_hub_get_tt_state
603
  },
604
605
  { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
606
    USB_HUB_REQUEST_STOP_TT,
607
    dissect_usb_hub_stop_tt
608
  },
609
610
  { 0, 0, NULL }
611
};
612
613
/* Dissector for USB HUB class-specific control request as defined in
614
 * USB 2.0, Chapter 11.24.2 Class-specific Requests
615
 * Returns tvb_captured_length(tvb) if a class specific dissector was found
616
 * and 0 otherwise.
617
 */
618
static int
619
dissect_usb_hub_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
620
0
{
621
0
  bool is_request;
622
0
  urb_info_t *urb;
623
0
  usb_trans_info_t *usb_trans_info;
624
0
  int offset = 0;
625
0
  usb_setup_dissector dissector;
626
0
  const usb_setup_dissector_table_t *tmp;
627
628
  /* Reject the packet if data or usb_trans_info are NULL */
629
0
  if (data == NULL || ((urb_info_t *)data)->usb_trans_info == NULL)
630
0
    return 0;
631
0
  urb = (urb_info_t *)data;
632
0
  usb_trans_info = urb->usb_trans_info;
633
634
0
  is_request = (pinfo->srcport==NO_ENDPOINT);
635
636
  /* See if we can find a class specific dissector for this request */
637
0
  dissector = NULL;
638
639
  /* Check valid values for bmRequestType and bRequest */
640
0
  for (tmp = setup_dissectors; tmp->dissector; tmp++) {
641
0
    if (tmp->request_type == usb_trans_info->setup.requesttype &&
642
0
        tmp->request == usb_trans_info->setup.request) {
643
0
      dissector = tmp->dissector;
644
0
      break;
645
0
    }
646
0
  }
647
  /* No, we could not find any class specific dissector for this request
648
   * return 0 and let USB try any of the standard requests.
649
   */
650
0
  if (!dissector) {
651
0
    return 0;
652
0
  }
653
654
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHUB");
655
656
0
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
657
0
  val_to_str(pinfo->pool, usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
658
0
    is_request ? "Request " : "Response");
659
660
0
  if (is_request) {
661
0
    proto_tree_add_item(tree, hf_usb_hub_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
662
0
    offset += 1;
663
0
  }
664
665
0
  dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, urb);
666
0
  return tvb_captured_length(tvb);
667
0
}
668
669
void
670
proto_register_usb_hub(void)
671
14
{
672
14
  static hf_register_info hf[] = {
673
    /* USB HUB specific requests */
674
14
    { &hf_usb_hub_request,
675
14
    { "bRequest", "usbhub.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
676
14
      NULL, HFILL }},
677
678
14
    { &hf_usb_hub_value,
679
14
    { "wValue", "usbhub.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
680
14
      NULL, HFILL }},
681
682
14
    { &hf_usb_hub_index,
683
14
    { "wIndex", "usbhub.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
684
14
      NULL, HFILL }},
685
686
14
    { &hf_usb_hub_length,
687
14
    { "wLength", "usbhub.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
688
14
      NULL, HFILL }},
689
690
14
    { &hf_usb_hub_hub_feature_selector,
691
14
    { "HubFeatureSelector", "usbhub.setup.HubFeatureSelector", FT_UINT16, BASE_DEC,
692
14
      VALS(hub_class_feature_selectors_recipient_hub_vals), 0x0,
693
14
      NULL, HFILL }},
694
695
14
    { &hf_usb_hub_port_feature_selector,
696
14
    { "PortFeatureSelector", "usbhub.setup.PortFeatureSelector", FT_UINT16, BASE_DEC,
697
14
      VALS(hub_class_feature_selectors_recipient_port_vals), 0x0,
698
14
      NULL, HFILL }},
699
700
14
    { &hf_usb_hub_dev_addr,
701
14
    { "Dev_Addr", "usbhub.setup.Dev_Addr", FT_UINT8, BASE_DEC, NULL, 0x0,
702
14
      NULL, HFILL }},
703
704
14
    { &hf_usb_hub_ep_num,
705
14
    { "EP_Num", "usbhub.setup.EP_Num", FT_UINT8, BASE_DEC, NULL, 0x0,
706
14
      NULL, HFILL }},
707
708
14
    { &hf_usb_hub_descriptor_type,
709
14
    { "DescriptorType", "usbhub.setup.DescriptorType", FT_UINT8, BASE_DEC, NULL, 0x0,
710
14
      NULL, HFILL }},
711
712
14
    { &hf_usb_hub_descriptor_index,
713
14
    { "DescriptorIndex", "usbhub.setup.DescriptorIndex", FT_UINT8, BASE_DEC, NULL, 0x0,
714
14
      NULL, HFILL }},
715
716
14
    { &hf_usb_hub_descriptor_length,
717
14
    { "DescriptorLength", "usbhub.setup.DescriptorLength", FT_UINT16, BASE_DEC, NULL, 0x0,
718
14
      NULL, HFILL }},
719
720
14
    { &hf_usb_hub_zero,
721
14
    { "(zero)", "usbhub.setup.zero", FT_UINT16, BASE_DEC, NULL, 0x0,
722
14
      NULL, HFILL }},
723
724
14
    { &hf_usb_hub_tt_flags,
725
14
    { "TT_Flags", "usbhub.setup.TT_Flags", FT_UINT8, BASE_DEC, NULL, 0x0,
726
14
      NULL, HFILL }},
727
728
14
    { &hf_usb_hub_tt_port,
729
14
    { "TT_Port", "usbhub.setup.TT_Port", FT_UINT16, BASE_DEC, NULL, 0x0,
730
14
      NULL, HFILL }},
731
732
14
    { &hf_usb_hub_tt_state_length,
733
14
    { "TT State Length", "usbhub.setup.TT_StateLength", FT_UINT16, BASE_DEC, NULL, 0x0,
734
14
      NULL, HFILL }},
735
736
14
    { &hf_usb_hub_port_selector,
737
14
    { "PortSelector", "usbhub.setup.PortSelector", FT_UINT8, BASE_DEC, NULL, 0x0,
738
14
      NULL, HFILL }},
739
740
14
    { &hf_usb_hub_port,
741
14
    { "Port", "usbhub.setup.Port", FT_UINT16, BASE_DEC, NULL, 0x0,
742
14
      NULL, HFILL }},
743
744
14
    { &hf_usb_hub_port_status,
745
14
    { "Port Status", "usbhub.status.port", FT_UINT16, BASE_HEX, NULL, 0,
746
14
      NULL, HFILL }},
747
748
14
    { &hf_usb_hub_port_change,
749
14
    { "Port Change", "usbhub.change.port", FT_UINT16, BASE_HEX, NULL, 0,
750
14
      NULL, HFILL }},
751
752
14
    { &hf_usb_hub_port_status_connection,
753
14
    { "PORT_CONNECTION", "usbhub.status.port.connection", FT_BOOLEAN, 16, NULL, (1<<0),
754
14
      NULL, HFILL }},
755
756
14
    { &hf_usb_hub_port_status_enable,
757
14
    { "PORT_ENABLE", "usbhub.status.port.enable", FT_BOOLEAN, 16, NULL, (1<<1),
758
14
      NULL, HFILL }},
759
760
14
    { &hf_usb_hub_port_status_suspend,
761
14
    { "PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN, 16, NULL, (1<<2),
762
14
      NULL, HFILL }},
763
764
14
    { &hf_usb_hub_port_status_overcurrent,
765
14
    { "PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN, 16, NULL, (1<<3),
766
14
      NULL, HFILL }},
767
768
14
    { &hf_usb_hub_port_status_reset,
769
14
    { "PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN, 16, NULL, (1<<4),
770
14
      NULL, HFILL }},
771
772
14
    { &hf_usb_hub_port_status_power,
773
14
    { "PORT_POWER", "usbhub.status.port.power", FT_BOOLEAN, 16, NULL, (1<<8),
774
14
      NULL, HFILL }},
775
776
14
    { &hf_usb_hub_port_status_low_speed,
777
14
    { "PORT_LOW_SPEED", "usbhub.status.port.low_speed", FT_BOOLEAN, 16, NULL, (1<<9),
778
14
      NULL, HFILL }},
779
780
14
    { &hf_usb_hub_port_status_high_speed,
781
14
    { "PORT_HIGH_SPEED", "usbhub.status.port.high_speed", FT_BOOLEAN, 16, NULL, (1<<10),
782
14
      NULL, HFILL }},
783
784
14
    { &hf_usb_hub_port_status_test,
785
14
    { "PORT_TEST", "usbhub.status.port.test", FT_BOOLEAN, 16, NULL, (1<<11),
786
14
      NULL, HFILL }},
787
788
14
    { &hf_usb_hub_port_status_indicator,
789
14
    { "PORT_INDICATOR", "usbhub.status.port.indicator", FT_BOOLEAN, 16,
790
14
      TFS(&hub_port_status_indicator_meaning), (1<<12),
791
14
      NULL, HFILL }},
792
793
14
    { &hf_usb_hub_port_change_connection,
794
14
    { "C_PORT_CONNECTION", "usbhub.change.port.connection", FT_BOOLEAN, 16, NULL, (1<<0),
795
14
      NULL, HFILL }},
796
797
14
    { &hf_usb_hub_port_change_enable,
798
14
    { "C_PORT_ENABLE", "usbhub.change.port.enable", FT_BOOLEAN, 16, NULL, (1<<1),
799
14
      NULL, HFILL }},
800
801
14
    { &hf_usb_hub_port_change_suspend,
802
14
    { "C_PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN, 16, NULL, (1<<2),
803
14
      NULL, HFILL }},
804
805
14
    { &hf_usb_hub_port_change_overcurrent,
806
14
    { "C_PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN, 16, NULL, (1<<3),
807
14
      NULL, HFILL }},
808
809
14
    { &hf_usb_hub_port_change_reset,
810
14
    { "C_PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN, 16, NULL, (1<<4),
811
14
      NULL, HFILL }}
812
14
  };
813
814
14
  static int *usb_hub_ett[] = {
815
14
    &ett_usb_hub_wValue,
816
14
    &ett_usb_hub_wIndex,
817
14
    &ett_usb_hub_wLength,
818
14
    &ett_usb_hub_port_status,
819
14
    &ett_usb_hub_port_change
820
14
  };
821
822
14
  proto_usb_hub = proto_register_protocol("USB HUB", "USBHUB", "usbhub");
823
14
  proto_register_field_array(proto_usb_hub, hf, array_length(hf));
824
14
  proto_register_subtree_array(usb_hub_ett, array_length(usb_hub_ett));
825
14
  usb_hub_control_handle = register_dissector("usbhub", dissect_usb_hub_control, proto_usb_hub);
826
14
}
827
828
void
829
proto_reg_handoff_usb_hub(void)
830
14
{
831
14
  dissector_add_uint("usb.control", IF_CLASS_HUB, usb_hub_control_handle);
832
14
  dissector_add_uint("usb.control", IF_CLASS_UNKNOWN, usb_hub_control_handle);
833
14
}
834
835
/*
836
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
837
 *
838
 * Local variables:
839
 * c-basic-offset: 8
840
 * tab-width: 8
841
 * indent-tabs-mode: t
842
 * End:
843
 *
844
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
845
 * :indentSize=8:tabSize=8:noTabs=false:
846
 */