Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-usb-hub.c
blob78644d00170e9a7032c3294c080b563638118660
1 /* packet-usb-hub.c
2 * Routines for USB HUB dissection
3 * Copyright 2009, Marton Nemeth <nm127@freemail.hu>
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
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "config.h"
18 #include <epan/packet.h>
19 #include "packet-usb.h"
21 void proto_register_usb_hub(void);
22 void proto_reg_handoff_usb_hub(void);
24 static dissector_handle_t usb_hub_control_handle;
26 /* protocols and header fields */
27 static int proto_usb_hub;
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;
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;
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;
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
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 }
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
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
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 }
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 }
156 static const true_false_string hub_port_status_indicator_meaning = {
157 "Software-controlled color",
158 "Default colors"
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_)
165 proto_item *item = NULL;
166 proto_tree *subtree = NULL;
167 const char* feature_name;
169 feature_name = val_to_str(usb_trans_info->setup.wValue,
170 hub_class_feature_selectors_recipient_hub_vals,
171 "UNKNOWN (0x%x)");
172 col_append_fstr(pinfo->cinfo, COL_INFO, " [Hub: %s]", feature_name);
174 if (is_request) {
175 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
176 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
177 proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
178 offset += 2;
180 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
181 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
182 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
183 offset += 2;
185 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
186 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
187 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
188 /*offset += 2;*/
189 } else {
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_)
197 proto_item *item = NULL;
198 proto_tree *subtree = NULL;
199 const char* feature_name;
201 feature_name = val_to_str(usb_trans_info->setup.wValue,
202 hub_class_feature_selectors_recipient_port_vals,
203 "UNKNOWN (0x%x)");
204 col_append_fstr(pinfo->cinfo, COL_INFO, " [Port %u: %s]", usb_trans_info->setup.wIndex, feature_name);
206 if (is_request) {
207 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
208 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
209 proto_tree_add_item(subtree, hf_usb_hub_port_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
210 offset += 2;
212 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
213 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
214 proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
215 offset++;
216 proto_tree_add_item(subtree, hf_usb_hub_port_selector, tvb, offset, 1, ENC_LITTLE_ENDIAN);
217 offset++;
219 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
220 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
221 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
222 /*offset += 2;*/
223 } else {
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_)
231 proto_item *item = NULL;
232 proto_tree *subtree = NULL;
234 if (is_request) {
235 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
236 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
237 proto_tree_add_item(subtree, hf_usb_hub_ep_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
238 offset++;
239 proto_tree_add_item(subtree, hf_usb_hub_dev_addr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
240 offset++;
242 proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
243 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
244 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
245 offset += 2;
247 proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
248 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
249 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
250 /*offset += 2;*/
251 } else {
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_)
259 proto_item *item = NULL;
260 proto_tree *subtree = NULL;
262 if (is_request) {
263 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
264 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
265 proto_tree_add_item(subtree, hf_usb_hub_descriptor_index, tvb, offset, 1, ENC_LITTLE_ENDIAN);
266 offset++;
267 proto_tree_add_item(subtree, hf_usb_hub_descriptor_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
268 offset++;
270 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
271 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
272 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
273 offset += 2;
275 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
276 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
277 proto_tree_add_item(subtree, hf_usb_hub_descriptor_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
278 /*offset += 2;*/
279 } else {
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_)
287 proto_item *item = NULL;
288 proto_tree *subtree = NULL;
290 col_append_str(pinfo->cinfo, COL_INFO, " [Hub]");
292 if (is_request) {
293 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
294 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
295 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
296 offset += 2;
298 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
299 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
300 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
301 offset += 2;
303 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 } else {
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_)
314 proto_item *item = NULL;
315 proto_tree *subtree = NULL;
317 col_append_fstr(pinfo->cinfo, COL_INFO, " [Port %u]", usb_trans_info->setup.wIndex);
319 if (is_request) {
320 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
321 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
322 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
323 offset += 2;
325 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
326 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
327 proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
328 offset += 2;
330 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 } else {
334 static int * const status_fields[] = {
335 &hf_usb_hub_port_status_connection,
336 &hf_usb_hub_port_status_enable,
337 &hf_usb_hub_port_status_suspend,
338 &hf_usb_hub_port_status_overcurrent,
339 &hf_usb_hub_port_status_reset,
340 &hf_usb_hub_port_status_power,
341 &hf_usb_hub_port_status_low_speed,
342 &hf_usb_hub_port_status_high_speed,
343 &hf_usb_hub_port_status_test,
344 &hf_usb_hub_port_status_indicator,
345 NULL
348 static int * const change_fields[] = {
349 &hf_usb_hub_port_change_connection,
350 &hf_usb_hub_port_change_enable,
351 &hf_usb_hub_port_change_suspend,
352 &hf_usb_hub_port_change_overcurrent,
353 &hf_usb_hub_port_change_reset,
354 NULL
357 proto_tree_add_bitmask(tree, tvb, offset, hf_usb_hub_port_status,
358 ett_usb_hub_port_status, status_fields, ENC_LITTLE_ENDIAN);
359 offset += 2;
360 proto_tree_add_bitmask(tree, tvb, offset, hf_usb_hub_port_change,
361 ett_usb_hub_port_change, change_fields, ENC_LITTLE_ENDIAN);
362 /*offset += 2;*/
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_)
370 proto_item *item = NULL;
371 proto_tree *subtree = NULL;
373 if (is_request) {
374 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
375 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
376 proto_tree_add_item(subtree, hf_usb_hub_tt_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
377 offset += 2;
379 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
380 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
381 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
382 offset += 2;
384 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
385 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
386 proto_tree_add_item(subtree, hf_usb_hub_tt_state_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387 /*offset += 2;*/
388 } else {
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_)
396 proto_item *item = NULL;
397 proto_tree *subtree = NULL;
399 if (is_request) {
400 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
401 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
402 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403 offset += 2;
405 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
406 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
407 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
408 offset += 2;
410 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
411 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
412 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
413 /*offset += 2;*/
414 } else {
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_)
422 proto_item *item = NULL;
423 proto_tree *subtree = NULL;
425 if (is_request) {
426 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
427 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
428 proto_tree_add_item(subtree, hf_usb_hub_descriptor_index, tvb, offset, 1, ENC_LITTLE_ENDIAN);
429 offset++;
430 proto_tree_add_item(subtree, hf_usb_hub_descriptor_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
431 offset++;
433 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
434 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
435 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
436 offset += 2;
438 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
439 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
440 proto_tree_add_item(subtree, hf_usb_hub_descriptor_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
441 /*offset += 2;*/
442 } else {
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_)
450 proto_item *item = NULL;
451 proto_tree *subtree = NULL;
453 if (is_request) {
454 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
455 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
456 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
457 offset += 2;
459 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
460 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
461 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
462 offset += 2;
464 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
465 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
466 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
467 /*offset += 2;*/
468 } else {
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_)
476 proto_item *item = NULL;
477 proto_tree *subtree = NULL;
478 const char* feature_name;
479 feature_name = val_to_str(usb_trans_info->setup.wValue,
480 hub_class_feature_selectors_recipient_hub_vals,
481 "UNKNOWN (0x%x)");
482 col_append_fstr(pinfo->cinfo, COL_INFO, " [Hub: %s]", feature_name);
484 if (is_request) {
485 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
486 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
487 proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
488 offset += 2;
490 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
491 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
492 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
493 offset += 2;
495 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
496 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
497 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
498 /*offset += 2;*/
499 } else {
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_)
507 proto_item *item = NULL;
508 proto_tree *subtree = NULL;
509 const char* feature_name;
511 feature_name = val_to_str(usb_trans_info->setup.wValue,
512 hub_class_feature_selectors_recipient_port_vals,
513 "UNKNOWN (0x%x)");
514 col_append_fstr(pinfo->cinfo, COL_INFO, " [Port %u: %s]", usb_trans_info->setup.wIndex,
515 feature_name);
517 if (is_request) {
518 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
519 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
520 proto_tree_add_item(subtree, hf_usb_hub_port_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
521 offset += 2;
523 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
524 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
525 proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
526 offset++;
527 proto_tree_add_item(subtree, hf_usb_hub_port_selector, tvb, offset, 1, ENC_LITTLE_ENDIAN);
528 offset++;
530 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
531 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
532 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
533 /*offset += 2;*/
534 } else {
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);
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;
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
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
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
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
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
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
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
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
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
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
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
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
610 { 0, 0, NULL }
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.
618 static int
619 dissect_usb_hub_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
621 bool is_request;
622 urb_info_t *urb;
623 usb_trans_info_t *usb_trans_info;
624 int offset = 0;
625 usb_setup_dissector dissector;
626 const usb_setup_dissector_table_t *tmp;
628 /* Reject the packet if data or usb_trans_info are NULL */
629 if (data == NULL || ((urb_info_t *)data)->usb_trans_info == NULL)
630 return 0;
631 urb = (urb_info_t *)data;
632 usb_trans_info = urb->usb_trans_info;
634 is_request = (pinfo->srcport==NO_ENDPOINT);
636 /* See if we can find a class specific dissector for this request */
637 dissector = NULL;
639 /* Check valid values for bmRequestType and bRequest */
640 for (tmp = setup_dissectors; tmp->dissector; tmp++) {
641 if (tmp->request_type == usb_trans_info->setup.requesttype &&
642 tmp->request == usb_trans_info->setup.request) {
643 dissector = tmp->dissector;
644 break;
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.
650 if (!dissector) {
651 return 0;
654 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHUB");
656 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
657 val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
658 is_request ? "Request " : "Response");
660 if (is_request) {
661 proto_tree_add_item(tree, hf_usb_hub_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
662 offset += 1;
665 dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, urb);
666 return tvb_captured_length(tvb);
669 void
670 proto_register_usb_hub(void)
672 static hf_register_info hf[] = {
673 /* USB HUB specific requests */
674 { &hf_usb_hub_request,
675 { "bRequest", "usbhub.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
676 NULL, HFILL }},
678 { &hf_usb_hub_value,
679 { "wValue", "usbhub.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
680 NULL, HFILL }},
682 { &hf_usb_hub_index,
683 { "wIndex", "usbhub.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
684 NULL, HFILL }},
686 { &hf_usb_hub_length,
687 { "wLength", "usbhub.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
688 NULL, HFILL }},
690 { &hf_usb_hub_hub_feature_selector,
691 { "HubFeatureSelector", "usbhub.setup.HubFeatureSelector", FT_UINT16, BASE_DEC,
692 VALS(hub_class_feature_selectors_recipient_hub_vals), 0x0,
693 NULL, HFILL }},
695 { &hf_usb_hub_port_feature_selector,
696 { "PortFeatureSelector", "usbhub.setup.PortFeatureSelector", FT_UINT16, BASE_DEC,
697 VALS(hub_class_feature_selectors_recipient_port_vals), 0x0,
698 NULL, HFILL }},
700 { &hf_usb_hub_dev_addr,
701 { "Dev_Addr", "usbhub.setup.Dev_Addr", FT_UINT8, BASE_DEC, NULL, 0x0,
702 NULL, HFILL }},
704 { &hf_usb_hub_ep_num,
705 { "EP_Num", "usbhub.setup.EP_Num", FT_UINT8, BASE_DEC, NULL, 0x0,
706 NULL, HFILL }},
708 { &hf_usb_hub_descriptor_type,
709 { "DescriptorType", "usbhub.setup.DescriptorType", FT_UINT8, BASE_DEC, NULL, 0x0,
710 NULL, HFILL }},
712 { &hf_usb_hub_descriptor_index,
713 { "DescriptorIndex", "usbhub.setup.DescriptorIndex", FT_UINT8, BASE_DEC, NULL, 0x0,
714 NULL, HFILL }},
716 { &hf_usb_hub_descriptor_length,
717 { "DescriptorLength", "usbhub.setup.DescriptorLength", FT_UINT16, BASE_DEC, NULL, 0x0,
718 NULL, HFILL }},
720 { &hf_usb_hub_zero,
721 { "(zero)", "usbhub.setup.zero", FT_UINT16, BASE_DEC, NULL, 0x0,
722 NULL, HFILL }},
724 { &hf_usb_hub_tt_flags,
725 { "TT_Flags", "usbhub.setup.TT_Flags", FT_UINT8, BASE_DEC, NULL, 0x0,
726 NULL, HFILL }},
728 { &hf_usb_hub_tt_port,
729 { "TT_Port", "usbhub.setup.TT_Port", FT_UINT16, BASE_DEC, NULL, 0x0,
730 NULL, HFILL }},
732 { &hf_usb_hub_tt_state_length,
733 { "TT State Length", "usbhub.setup.TT_StateLength", FT_UINT16, BASE_DEC, NULL, 0x0,
734 NULL, HFILL }},
736 { &hf_usb_hub_port_selector,
737 { "PortSelector", "usbhub.setup.PortSelector", FT_UINT8, BASE_DEC, NULL, 0x0,
738 NULL, HFILL }},
740 { &hf_usb_hub_port,
741 { "Port", "usbhub.setup.Port", FT_UINT16, BASE_DEC, NULL, 0x0,
742 NULL, HFILL }},
744 { &hf_usb_hub_port_status,
745 { "Port Status", "usbhub.status.port", FT_UINT16, BASE_HEX, NULL, 0,
746 NULL, HFILL }},
748 { &hf_usb_hub_port_change,
749 { "Port Change", "usbhub.change.port", FT_UINT16, BASE_HEX, NULL, 0,
750 NULL, HFILL }},
752 { &hf_usb_hub_port_status_connection,
753 { "PORT_CONNECTION", "usbhub.status.port.connection", FT_BOOLEAN, 16, NULL, (1<<0),
754 NULL, HFILL }},
756 { &hf_usb_hub_port_status_enable,
757 { "PORT_ENABLE", "usbhub.status.port.enable", FT_BOOLEAN, 16, NULL, (1<<1),
758 NULL, HFILL }},
760 { &hf_usb_hub_port_status_suspend,
761 { "PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN, 16, NULL, (1<<2),
762 NULL, HFILL }},
764 { &hf_usb_hub_port_status_overcurrent,
765 { "PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN, 16, NULL, (1<<3),
766 NULL, HFILL }},
768 { &hf_usb_hub_port_status_reset,
769 { "PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN, 16, NULL, (1<<4),
770 NULL, HFILL }},
772 { &hf_usb_hub_port_status_power,
773 { "PORT_POWER", "usbhub.status.port.power", FT_BOOLEAN, 16, NULL, (1<<8),
774 NULL, HFILL }},
776 { &hf_usb_hub_port_status_low_speed,
777 { "PORT_LOW_SPEED", "usbhub.status.port.low_speed", FT_BOOLEAN, 16, NULL, (1<<9),
778 NULL, HFILL }},
780 { &hf_usb_hub_port_status_high_speed,
781 { "PORT_HIGH_SPEED", "usbhub.status.port.high_speed", FT_BOOLEAN, 16, NULL, (1<<10),
782 NULL, HFILL }},
784 { &hf_usb_hub_port_status_test,
785 { "PORT_TEST", "usbhub.status.port.test", FT_BOOLEAN, 16, NULL, (1<<11),
786 NULL, HFILL }},
788 { &hf_usb_hub_port_status_indicator,
789 { "PORT_INDICATOR", "usbhub.status.port.indicator", FT_BOOLEAN, 16,
790 TFS(&hub_port_status_indicator_meaning), (1<<12),
791 NULL, HFILL }},
793 { &hf_usb_hub_port_change_connection,
794 { "C_PORT_CONNECTION", "usbhub.change.port.connection", FT_BOOLEAN, 16, NULL, (1<<0),
795 NULL, HFILL }},
797 { &hf_usb_hub_port_change_enable,
798 { "C_PORT_ENABLE", "usbhub.change.port.enable", FT_BOOLEAN, 16, NULL, (1<<1),
799 NULL, HFILL }},
801 { &hf_usb_hub_port_change_suspend,
802 { "C_PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN, 16, NULL, (1<<2),
803 NULL, HFILL }},
805 { &hf_usb_hub_port_change_overcurrent,
806 { "C_PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN, 16, NULL, (1<<3),
807 NULL, HFILL }},
809 { &hf_usb_hub_port_change_reset,
810 { "C_PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN, 16, NULL, (1<<4),
811 NULL, HFILL }}
814 static int *usb_hub_ett[] = {
815 &ett_usb_hub_wValue,
816 &ett_usb_hub_wIndex,
817 &ett_usb_hub_wLength,
818 &ett_usb_hub_port_status,
819 &ett_usb_hub_port_change
822 proto_usb_hub = proto_register_protocol("USB HUB", "USBHUB", "usbhub");
823 proto_register_field_array(proto_usb_hub, hf, array_length(hf));
824 proto_register_subtree_array(usb_hub_ett, array_length(usb_hub_ett));
825 usb_hub_control_handle = register_dissector("usbhub", dissect_usb_hub_control, proto_usb_hub);
828 void
829 proto_reg_handoff_usb_hub(void)
831 dissector_add_uint("usb.control", IF_CLASS_HUB, usb_hub_control_handle);
832 dissector_add_uint("usb.control", IF_CLASS_UNKNOWN, usb_hub_control_handle);
836 * Editor modelines - https://www.wireshark.org/tools/modelines.html
838 * Local variables:
839 * c-basic-offset: 8
840 * tab-width: 8
841 * indent-tabs-mode: t
842 * End:
844 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
845 * :indentSize=8:tabSize=8:noTabs=false: