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
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" },
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" },
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" },
156 static const true_false_string hub_port_status_indicator_meaning
= {
157 "Software-controlled color",
161 /* Dissector for ClearHubFeature, Chapter 11.24.2.1 Clear Hub Feature */
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
,
172 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Hub: %s]", feature_name
);
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
);
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
);
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
);
193 /* Dissector for ClearPortFeature, Chapter 11.24.2.2 Clear Port Feature */
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
,
204 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Port %u: %s]", usb_trans_info
->setup
.wIndex
, feature_name
);
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
);
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
);
216 proto_tree_add_item(subtree
, hf_usb_hub_port_selector
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
227 /* Dissector for ClearTTBuffer, Chapter 11.24.2.3 Clear TT Buffer */
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
;
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
);
239 proto_tree_add_item(subtree
, hf_usb_hub_dev_addr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
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
);
255 /* Dissector for GetHubDescriptor, Chapter 11.24.2.5 Get Hub Descriptor */
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
;
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
);
267 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
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
);
283 /* Dissector for GetHubStatus, Chapter 11.24.2.6 Get Hub Status */
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]");
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
);
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
);
303 proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
304 /* length shall always contain 4 */
310 /* Dissector for GetPortStatus, Chapter 11.24.2.7 Get Port Status */
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
);
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
);
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
);
330 proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
331 /* length shall always contain 4 */
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
,
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
,
357 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_usb_hub_port_status
,
358 ett_usb_hub_port_status
, status_fields
, ENC_LITTLE_ENDIAN
);
360 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_usb_hub_port_change
,
361 ett_usb_hub_port_change
, change_fields
, ENC_LITTLE_ENDIAN
);
366 /* Dissector for GetTTState, Chapter 11.24.2.8 Get_TT_State */
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
;
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
);
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
);
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
);
392 /* Dissector for ResetTT, Chapter 11.24.2.9 Reset_TT */
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
;
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
);
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
);
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
);
418 /* Dissector for SetHubDescriptor, Chapter 11.24.2.10 Set Hub Descriptor */
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
;
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
);
430 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
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
);
446 /* Dissector for StopTT, Chapter 11.24.2.11 Stop TT */
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
;
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
);
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
);
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
);
472 /* Dissector for SetHubFeature, Chapter 11.24.2.12 Set Hub Feature */
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
,
482 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Hub: %s]", feature_name
);
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
);
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
);
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
);
503 /* Dissector for SetPortFeature, Chapter 11.24.2.13 Set Port Feature */
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
,
514 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Port %u: %s]", usb_trans_info
->setup
.wIndex
,
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
);
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
);
527 proto_tree_add_item(subtree
, hf_usb_hub_port_selector
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
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
);
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
;
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
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
619 dissect_usb_hub_control(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
623 usb_trans_info_t
*usb_trans_info
;
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
)
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 */
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
;
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.
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");
661 proto_tree_add_item(tree
, hf_usb_hub_request
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
665 dissector(pinfo
, tree
, tvb
, offset
, is_request
, usb_trans_info
, urb
);
666 return tvb_captured_length(tvb
);
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,
679 { "wValue", "usbhub.setup.wValue", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
683 { "wIndex", "usbhub.setup.wIndex", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
686 { &hf_usb_hub_length
,
687 { "wLength", "usbhub.setup.wLength", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
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,
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,
700 { &hf_usb_hub_dev_addr
,
701 { "Dev_Addr", "usbhub.setup.Dev_Addr", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
704 { &hf_usb_hub_ep_num
,
705 { "EP_Num", "usbhub.setup.EP_Num", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
708 { &hf_usb_hub_descriptor_type
,
709 { "DescriptorType", "usbhub.setup.DescriptorType", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
712 { &hf_usb_hub_descriptor_index
,
713 { "DescriptorIndex", "usbhub.setup.DescriptorIndex", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
716 { &hf_usb_hub_descriptor_length
,
717 { "DescriptorLength", "usbhub.setup.DescriptorLength", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
721 { "(zero)", "usbhub.setup.zero", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
724 { &hf_usb_hub_tt_flags
,
725 { "TT_Flags", "usbhub.setup.TT_Flags", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
728 { &hf_usb_hub_tt_port
,
729 { "TT_Port", "usbhub.setup.TT_Port", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
732 { &hf_usb_hub_tt_state_length
,
733 { "TT State Length", "usbhub.setup.TT_StateLength", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
736 { &hf_usb_hub_port_selector
,
737 { "PortSelector", "usbhub.setup.PortSelector", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
741 { "Port", "usbhub.setup.Port", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
744 { &hf_usb_hub_port_status
,
745 { "Port Status", "usbhub.status.port", FT_UINT16
, BASE_HEX
, NULL
, 0,
748 { &hf_usb_hub_port_change
,
749 { "Port Change", "usbhub.change.port", FT_UINT16
, BASE_HEX
, NULL
, 0,
752 { &hf_usb_hub_port_status_connection
,
753 { "PORT_CONNECTION", "usbhub.status.port.connection", FT_BOOLEAN
, 16, NULL
, (1<<0),
756 { &hf_usb_hub_port_status_enable
,
757 { "PORT_ENABLE", "usbhub.status.port.enable", FT_BOOLEAN
, 16, NULL
, (1<<1),
760 { &hf_usb_hub_port_status_suspend
,
761 { "PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN
, 16, NULL
, (1<<2),
764 { &hf_usb_hub_port_status_overcurrent
,
765 { "PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN
, 16, NULL
, (1<<3),
768 { &hf_usb_hub_port_status_reset
,
769 { "PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN
, 16, NULL
, (1<<4),
772 { &hf_usb_hub_port_status_power
,
773 { "PORT_POWER", "usbhub.status.port.power", FT_BOOLEAN
, 16, NULL
, (1<<8),
776 { &hf_usb_hub_port_status_low_speed
,
777 { "PORT_LOW_SPEED", "usbhub.status.port.low_speed", FT_BOOLEAN
, 16, NULL
, (1<<9),
780 { &hf_usb_hub_port_status_high_speed
,
781 { "PORT_HIGH_SPEED", "usbhub.status.port.high_speed", FT_BOOLEAN
, 16, NULL
, (1<<10),
784 { &hf_usb_hub_port_status_test
,
785 { "PORT_TEST", "usbhub.status.port.test", FT_BOOLEAN
, 16, NULL
, (1<<11),
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),
793 { &hf_usb_hub_port_change_connection
,
794 { "C_PORT_CONNECTION", "usbhub.change.port.connection", FT_BOOLEAN
, 16, NULL
, (1<<0),
797 { &hf_usb_hub_port_change_enable
,
798 { "C_PORT_ENABLE", "usbhub.change.port.enable", FT_BOOLEAN
, 16, NULL
, (1<<1),
801 { &hf_usb_hub_port_change_suspend
,
802 { "C_PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN
, 16, NULL
, (1<<2),
805 { &hf_usb_hub_port_change_overcurrent
,
806 { "C_PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN
, 16, NULL
, (1<<3),
809 { &hf_usb_hub_port_change_reset
,
810 { "C_PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN
, 16, NULL
, (1<<4),
814 static int *usb_hub_ett
[] = {
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
);
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
841 * indent-tabs-mode: t
844 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
845 * :indentSize=8:tabSize=8:noTabs=false: