2 * Routines for USB HUB dissection
3 * Copyright 2009, Marton Nemeth <nm127@freemail.hu>
7 * USB HUB Specification can be found in the Universal Serial Bus
8 * Specification 2.0, Chapter 11 Hub Specification.
9 * http://www.usb.org/developers/docs/usb_20_052709.zip
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/packet.h>
34 #include "packet-usb.h"
36 /* protocols and header fields */
37 static int proto_usb_hub
= -1;
39 /* USB 2.0, Chapter 11.24.2 Class-Specific Requests */
40 static int hf_usb_hub_request
= -1;
41 static int hf_usb_hub_value
= -1;
42 static int hf_usb_hub_index
= -1;
43 static int hf_usb_hub_length
= -1;
45 static int hf_usb_hub_hub_feature_selector
= -1;
46 static int hf_usb_hub_port_feature_selector
= -1;
47 static int hf_usb_hub_dev_addr
= -1;
48 static int hf_usb_hub_ep_num
= -1;
49 static int hf_usb_hub_descriptor_type
= -1;
50 static int hf_usb_hub_descriptor_index
= -1;
51 static int hf_usb_hub_zero
= -1;
52 static int hf_usb_hub_tt_flags
= -1;
53 static int hf_usb_hub_tt_port
= -1;
54 static int hf_usb_hub_tt_state_length
= -1;
55 static int hf_usb_hub_port
= -1;
56 static int hf_usb_hub_port_selector
= -1;
57 static int hf_usb_hub_port_status
= -1;
58 static int hf_usb_hub_port_change
= -1;
59 static int hf_usb_hub_port_status_connection
= -1;
60 static int hf_usb_hub_port_status_enable
= -1;
61 static int hf_usb_hub_port_status_suspend
= -1;
62 static int hf_usb_hub_port_status_overcurrent
= -1;
63 static int hf_usb_hub_port_status_reset
= -1;
64 static int hf_usb_hub_port_status_power
= -1;
65 static int hf_usb_hub_port_status_low_speed
= -1;
66 static int hf_usb_hub_port_status_high_speed
= -1;
67 static int hf_usb_hub_port_status_test
= -1;
68 static int hf_usb_hub_port_status_indicator
= -1;
69 static int hf_usb_hub_port_change_connection
= -1;
70 static int hf_usb_hub_port_change_enable
= -1;
71 static int hf_usb_hub_port_change_suspend
= -1;
72 static int hf_usb_hub_port_change_overcurrent
= -1;
73 static int hf_usb_hub_port_change_reset
= -1;
74 static int hf_usb_hub_descriptor_length
= -1;
76 static gint ett_usb_hub_wValue
= -1;
77 static gint ett_usb_hub_wIndex
= -1;
78 static gint ett_usb_hub_wLength
= -1;
79 static gint ett_usb_hub_port_status
= -1;
80 static gint ett_usb_hub_port_change
= -1;
82 /* Table 11-16. Hub Class Request Codes */
83 #define USB_HUB_REQUEST_GET_STATUS 0
84 #define USB_HUB_REQUEST_CLEAR_FEATURE 1
85 #define USB_HUB_REQUEST_SET_FEATURE 3
86 #define USB_HUB_REQUEST_GET_DESCRIPTOR 6
87 #define USB_HUB_REQUEST_SET_DESCRIPTOR 7
88 #define USB_HUB_REQUEST_CLEAR_TT_BUFFER 8
89 #define USB_HUB_REQUEST_RESET_TT 9
90 #define USB_HUB_REQUEST_GET_TT_STATE 10
91 #define USB_HUB_REQUEST_STOP_TT 11
93 static const value_string setup_request_names_vals
[] = {
94 { USB_HUB_REQUEST_GET_STATUS
, "GET_STATUS" },
95 { USB_HUB_REQUEST_CLEAR_FEATURE
, "CLEAR_FEATURE" },
96 { USB_HUB_REQUEST_SET_FEATURE
, "SET_FEATURE" },
97 { USB_HUB_REQUEST_GET_DESCRIPTOR
, "GET_DESCRIPTOR" },
98 { USB_HUB_REQUEST_SET_DESCRIPTOR
, "SET_DESCRIPTOR" },
99 { USB_HUB_REQUEST_CLEAR_TT_BUFFER
, "CLEAR_TT_BUFFER" },
100 { USB_HUB_REQUEST_GET_TT_STATE
, "GET_TT_STATE" },
101 { USB_HUB_REQUEST_STOP_TT
, "STOP_TT" },
106 /* Table 11-17 Hub Class Feature Selectors */
107 #define USB_HUB_FEATURE_C_HUB_LOCAL_POWER 0
108 #define USB_HUB_FEATURE_C_HUB_OVER_CURRENT 1
110 #define USB_HUB_FEATURE_PORT_CONNECTION 0
111 #define USB_HUB_FEATURE_PORT_ENABLE 1
112 #define USB_HUB_FEATURE_PORT_SUSPEND 2
113 #define USB_HUB_FEATURE_PORT_OVER_CURRENT 3
114 #define USB_HUB_FEATURE_PORT_RESET 4
115 #define USB_HUB_FEATURE_PORT_POWER 8
116 #define USB_HUB_FEATURE_PORT_LOW_SPEED 9
117 #define USB_HUB_FEATURE_C_PORT_CONNECTION 16
118 #define USB_HUB_FEATURE_C_PORT_ENABLE 17
119 #define USB_HUB_FEATURE_C_PORT_SUSPEND 18
120 #define USB_HUB_FEATURE_C_PORT_OVER_CURRENT 19
121 #define USB_HUB_FEATURE_C_PORT_RESET 20
122 #define USB_HUB_FEATURE_PORT_TEST 21
123 #define USB_HUB_FEATURE_PORT_INDICATOR 22
125 static const value_string hub_class_feature_selectors_recipient_hub_vals
[] = {
126 { USB_HUB_FEATURE_C_HUB_LOCAL_POWER
, "C_HUB_LOCAL_POWER" },
127 { USB_HUB_FEATURE_C_HUB_OVER_CURRENT
, "C_HUB_OVER_CURRENT" },
131 static const value_string hub_class_feature_selectors_recipient_port_vals
[] = {
132 { USB_HUB_FEATURE_PORT_CONNECTION
, "PORT_CONNECTION" },
133 { USB_HUB_FEATURE_PORT_ENABLE
, "PORT_ENABLE" },
134 { USB_HUB_FEATURE_PORT_SUSPEND
, "PORT_SUSPEND" },
135 { USB_HUB_FEATURE_PORT_OVER_CURRENT
, "PORT_OVER_CURRENT" },
136 { USB_HUB_FEATURE_PORT_RESET
, "PORT_RESET" },
137 { USB_HUB_FEATURE_PORT_POWER
, "PORT_POWER" },
138 { USB_HUB_FEATURE_PORT_LOW_SPEED
, "PORT_LOW_SPEED" },
139 { USB_HUB_FEATURE_C_PORT_CONNECTION
, "C_PORT_CONNECTION" },
140 { USB_HUB_FEATURE_C_PORT_ENABLE
, "C_PORT_ENABLE" },
141 { USB_HUB_FEATURE_C_PORT_SUSPEND
, "C_PORT_SUSPEND" },
142 { USB_HUB_FEATURE_C_PORT_OVER_CURRENT
, "C_PORT_OVER_CURRENT" },
143 { USB_HUB_FEATURE_C_PORT_RESET
, "C_PORT_RESET" },
144 { USB_HUB_FEATURE_PORT_TEST
, "PORT_TEST" },
145 { USB_HUB_FEATURE_PORT_INDICATOR
, "PORT_INDICATOR" },
149 static const true_false_string hub_port_status_indicator_meaning
= {
150 "Software-controlled color",
154 /* Dissector for ClearHubFeature, Chapter 11.24.2.1 Clear Hub Feature */
156 dissect_usb_hub_clear_hub_feature(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
158 proto_item
*item
= NULL
;
159 proto_tree
*subtree
= NULL
;
160 const gchar
* feature_name
;
162 feature_name
= val_to_str(usb_trans_info
->setup
.wValue
,
163 hub_class_feature_selectors_recipient_hub_vals
,
165 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Hub: %s]", feature_name
);
168 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
169 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
170 proto_tree_add_item(subtree
, hf_usb_hub_hub_feature_selector
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
173 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
174 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
175 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
178 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
179 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
180 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
186 /* Dissector for ClearPortFeature, Chapter 11.24.2.2 Clear Port Feature */
188 dissect_usb_hub_clear_port_feature(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
190 proto_item
*item
= NULL
;
191 proto_tree
*subtree
= NULL
;
192 const gchar
* feature_name
;
194 feature_name
= val_to_str(usb_trans_info
->setup
.wValue
,
195 hub_class_feature_selectors_recipient_port_vals
,
197 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Port %u: %s]", usb_trans_info
->setup
.wIndex
, feature_name
);
200 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
201 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
202 proto_tree_add_item(subtree
, hf_usb_hub_port_feature_selector
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
205 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
206 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
207 proto_tree_add_item(subtree
, hf_usb_hub_port
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
209 proto_tree_add_item(subtree
, hf_usb_hub_port_selector
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
212 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
213 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
214 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
220 /* Dissector for ClearTTBuffer, Chapter 11.24.2.3 Clear TT Buffer */
222 dissect_usb_hub_clear_tt_buffer(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
224 proto_item
*item
= NULL
;
225 proto_tree
*subtree
= NULL
;
228 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
229 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
230 proto_tree_add_item(subtree
, hf_usb_hub_ep_num
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
232 proto_tree_add_item(subtree
, hf_usb_hub_dev_addr
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
235 proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
236 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
237 proto_tree_add_item(subtree
, hf_usb_hub_tt_port
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
240 proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
241 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
242 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
248 /* Dissector for GetHubDescriptor, Chapter 11.24.2.5 Get Hub Descriptor */
250 dissect_usb_hub_get_hub_descriptor(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
252 proto_item
*item
= NULL
;
253 proto_tree
*subtree
= NULL
;
256 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
257 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
258 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_index
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
260 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
263 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
264 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
265 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
268 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
269 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
270 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
276 /* Dissector for GetHubStatus, Chapter 11.24.2.6 Get Hub Status */
278 dissect_usb_hub_get_hub_status(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
280 proto_item
*item
= NULL
;
281 proto_tree
*subtree
= NULL
;
283 col_append_str(pinfo
->cinfo
, COL_INFO
, " [Hub]");
286 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
287 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
288 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
291 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
292 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
293 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
296 proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
297 /* length shall always contain 4 */
303 /* Dissector for GetPortStatus, Chapter 11.24.2.7 Get Port Status */
305 dissect_usb_hub_get_port_status(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info
, usb_conv_info_t
*usb_conv_info _U_
)
307 proto_item
*item
= NULL
;
308 proto_tree
*subtree
= NULL
;
310 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Port %u]", usb_trans_info
->setup
.wIndex
);
313 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
314 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
315 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
318 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
319 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
320 proto_tree_add_item(subtree
, hf_usb_hub_port
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
323 proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
324 /* length shall always contain 4 */
327 static const int *status_fields
[] = {
328 &hf_usb_hub_port_status_connection
,
329 &hf_usb_hub_port_status_enable
,
330 &hf_usb_hub_port_status_suspend
,
331 &hf_usb_hub_port_status_overcurrent
,
332 &hf_usb_hub_port_status_reset
,
333 &hf_usb_hub_port_status_power
,
334 &hf_usb_hub_port_status_low_speed
,
335 &hf_usb_hub_port_status_high_speed
,
336 &hf_usb_hub_port_status_test
,
337 &hf_usb_hub_port_status_indicator
,
341 static const int *change_fields
[] = {
342 &hf_usb_hub_port_change_connection
,
343 &hf_usb_hub_port_change_enable
,
344 &hf_usb_hub_port_change_suspend
,
345 &hf_usb_hub_port_change_overcurrent
,
346 &hf_usb_hub_port_change_reset
,
350 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_usb_hub_port_status
,
351 ett_usb_hub_port_status
, status_fields
, ENC_LITTLE_ENDIAN
);
353 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_usb_hub_port_change
,
354 ett_usb_hub_port_change
, change_fields
, ENC_LITTLE_ENDIAN
);
359 /* Dissector for GetTTState, Chapter 11.24.2.8 Get_TT_State */
361 dissect_usb_hub_get_tt_state(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
363 proto_item
*item
= NULL
;
364 proto_tree
*subtree
= NULL
;
367 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
368 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
369 proto_tree_add_item(subtree
, hf_usb_hub_tt_flags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
372 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
373 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
374 proto_tree_add_item(subtree
, hf_usb_hub_tt_port
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
377 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
378 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
379 proto_tree_add_item(subtree
, hf_usb_hub_tt_state_length
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
385 /* Dissector for ResetTT, Chapter 11.24.2.9 Reset_TT */
387 dissect_usb_hub_reset_tt(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
389 proto_item
*item
= NULL
;
390 proto_tree
*subtree
= NULL
;
393 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
394 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
395 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
398 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
399 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
400 proto_tree_add_item(subtree
, hf_usb_hub_tt_port
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
403 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
404 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
405 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
411 /* Dissector for SetHubDescriptor, Chapter 11.24.2.10 Set Hub Descriptor */
413 dissect_usb_hub_set_hub_descriptor(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
415 proto_item
*item
= NULL
;
416 proto_tree
*subtree
= NULL
;
419 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
420 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
421 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_index
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
423 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
426 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
427 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
428 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
431 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
432 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
433 proto_tree_add_item(subtree
, hf_usb_hub_descriptor_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
439 /* Dissector for StopTT, Chapter 11.24.2.11 Stop TT */
441 dissect_usb_hub_stop_tt(packet_info
*pinfo _U_
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info _U_
, usb_conv_info_t
*usb_conv_info _U_
)
443 proto_item
*item
= NULL
;
444 proto_tree
*subtree
= NULL
;
447 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
448 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
449 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
452 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
453 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
454 proto_tree_add_item(subtree
, hf_usb_hub_tt_port
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
457 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
458 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
459 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
465 /* Dissector for SetHubFeature, Chapter 11.24.2.12 Set Hub Feature */
467 dissect_usb_hub_set_hub_feature(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info
, usb_conv_info_t
*usb_conv_info _U_
)
469 proto_item
*item
= NULL
;
470 proto_tree
*subtree
= NULL
;
471 const gchar
* feature_name
;
472 feature_name
= val_to_str(usb_trans_info
->setup
.wValue
,
473 hub_class_feature_selectors_recipient_hub_vals
,
475 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Hub: %s]", feature_name
);
478 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
479 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
480 proto_tree_add_item(subtree
, hf_usb_hub_hub_feature_selector
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
483 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
484 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wIndex
);
485 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
488 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
489 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
490 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
496 /* Dissector for SetPortFeature, Chapter 11.24.2.13 Set Port Feature */
498 dissect_usb_hub_set_port_feature(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info
, usb_conv_info_t
*usb_conv_info _U_
)
500 proto_item
*item
= NULL
;
501 proto_tree
*subtree
= NULL
;
502 const gchar
* feature_name
;
504 feature_name
= val_to_str(usb_trans_info
->setup
.wValue
,
505 hub_class_feature_selectors_recipient_port_vals
,
507 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [Port %u: %s]", usb_trans_info
->setup
.wIndex
,
511 item
= proto_tree_add_item(tree
, hf_usb_hub_value
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
512 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
513 proto_tree_add_item(subtree
, hf_usb_hub_port_feature_selector
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
516 item
= proto_tree_add_item(tree
, hf_usb_hub_index
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
517 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wValue
);
518 proto_tree_add_item(subtree
, hf_usb_hub_port
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
520 proto_tree_add_item(subtree
, hf_usb_hub_port_selector
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
523 item
= proto_tree_add_item(tree
, hf_usb_hub_length
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
524 subtree
= proto_item_add_subtree(item
, ett_usb_hub_wLength
);
525 proto_tree_add_item(subtree
, hf_usb_hub_zero
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
532 typedef void (*usb_setup_dissector
)(packet_info
*pinfo
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, gboolean is_request
, usb_trans_info_t
*usb_trans_info
, usb_conv_info_t
*usb_conv_info
);
534 typedef struct _usb_setup_dissector_table_t
{
537 usb_setup_dissector dissector
;
538 } usb_setup_dissector_table_t
;
541 /* USB 2.0, Table 11-15 Hub Class Requests */
542 static const usb_setup_dissector_table_t setup_dissectors
[] = {
543 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_DEVICE
,
544 USB_HUB_REQUEST_CLEAR_FEATURE
,
545 dissect_usb_hub_clear_hub_feature
548 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
549 USB_HUB_REQUEST_CLEAR_FEATURE
,
550 dissect_usb_hub_clear_port_feature
553 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
554 USB_HUB_REQUEST_CLEAR_TT_BUFFER
,
555 dissect_usb_hub_clear_tt_buffer
558 { USB_DIR_IN
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_DEVICE
,
559 USB_HUB_REQUEST_GET_DESCRIPTOR
,
560 dissect_usb_hub_get_hub_descriptor
563 { USB_DIR_IN
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_DEVICE
,
564 USB_HUB_REQUEST_GET_STATUS
,
565 dissect_usb_hub_get_hub_status
568 { USB_DIR_IN
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
569 USB_HUB_REQUEST_GET_STATUS
,
570 dissect_usb_hub_get_port_status
573 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
574 USB_HUB_REQUEST_RESET_TT
,
575 dissect_usb_hub_reset_tt
578 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_DEVICE
,
579 USB_HUB_REQUEST_SET_DESCRIPTOR
,
580 dissect_usb_hub_set_hub_descriptor
583 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_DEVICE
,
584 USB_HUB_REQUEST_SET_FEATURE
,
585 dissect_usb_hub_set_hub_feature
588 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
589 USB_HUB_REQUEST_SET_FEATURE
,
590 dissect_usb_hub_set_port_feature
593 { USB_DIR_IN
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
594 USB_HUB_REQUEST_GET_TT_STATE
,
595 dissect_usb_hub_get_tt_state
598 { USB_DIR_OUT
| (RQT_SETUP_TYPE_CLASS
<< 5) | RQT_SETUP_RECIPIENT_OTHER
,
599 USB_HUB_REQUEST_STOP_TT
,
600 dissect_usb_hub_stop_tt
606 /* Dissector for USB HUB class-specific control request as defined in
607 * USB 2.0, Chapter 11.24.2 Class-specific Requests
608 * Returns TRUE if a class specific dissector was found
609 * and FALSE otherwise.
612 dissect_usb_hub_control(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
615 usb_conv_info_t
*usb_conv_info
= (usb_conv_info_t
*)data
;
616 usb_trans_info_t
*usb_trans_info
= usb_conv_info
->usb_trans_info
;
618 usb_setup_dissector dissector
;
619 const usb_setup_dissector_table_t
*tmp
;
621 is_request
= (pinfo
->srcport
==NO_ENDPOINT
);
623 /* See if we can find a class specific dissector for this request */
626 /* Check valid values for bmRequestType and bRequest */
627 for (tmp
= setup_dissectors
; tmp
->dissector
; tmp
++) {
628 if (tmp
->request_type
== usb_trans_info
->setup
.requesttype
&&
629 tmp
->request
== usb_trans_info
->setup
.request
) {
630 dissector
= tmp
->dissector
;
634 /* No, we could not find any class specific dissector for this request
635 * return FALSE and let USB try any of the standard requests.
641 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "USBHUB");
643 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s %s",
644 val_to_str(usb_trans_info
->setup
.request
, setup_request_names_vals
, "Unknown type %x"),
645 is_request
? "Request " : "Response");
648 proto_tree_add_item(tree
, hf_usb_hub_request
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
652 dissector(pinfo
, tree
, tvb
, offset
, is_request
, usb_trans_info
, usb_conv_info
);
657 proto_register_usb_hub(void)
659 static hf_register_info hf
[] = {
660 /* USB HUB specific requests */
661 { &hf_usb_hub_request
,
662 { "bRequest", "usbhub.setup.bRequest", FT_UINT8
, BASE_HEX
, VALS(setup_request_names_vals
), 0x0,
666 { "wValue", "usbhub.setup.wValue", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
670 { "wIndex", "usbhub.setup.wIndex", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
673 { &hf_usb_hub_length
,
674 { "wLength", "usbhub.setup.wLength", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
677 { &hf_usb_hub_hub_feature_selector
,
678 { "HubFeatureSelector", "usbhub.setup.HubFeatureSelector", FT_UINT16
, BASE_DEC
,
679 VALS(hub_class_feature_selectors_recipient_hub_vals
), 0x0,
682 { &hf_usb_hub_port_feature_selector
,
683 { "PortFeatureSelector", "usbhub.setup.PortFeatureSelector", FT_UINT16
, BASE_DEC
,
684 VALS(hub_class_feature_selectors_recipient_port_vals
), 0x0,
687 { &hf_usb_hub_dev_addr
,
688 { "Dev_Addr", "usbhub.setup.Dev_Addr", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
691 { &hf_usb_hub_ep_num
,
692 { "EP_Num", "usbhub.setup.EP_Num", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
695 { &hf_usb_hub_descriptor_type
,
696 { "DescriptorType", "usbhub.setup.DescriptorType", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
699 { &hf_usb_hub_descriptor_index
,
700 { "DescriptorIndex", "usbhub.setup.DescriptorIndex", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
703 { &hf_usb_hub_descriptor_length
,
704 { "DescriptorLength", "usbhub.setup.DescriptorLength", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
708 { "(zero)", "usbhub.setup.zero", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
711 { &hf_usb_hub_tt_flags
,
712 { "TT_Flags", "usbhub.setup.TT_Flags", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
715 { &hf_usb_hub_tt_port
,
716 { "TT_Port", "usbhub.setup.TT_Port", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
719 { &hf_usb_hub_tt_state_length
,
720 { "TT State Length", "usbhub.setup.TT_StateLength", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
723 { &hf_usb_hub_port_selector
,
724 { "PortSelector", "usbhub.setup.PortSelector", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
728 { "Port", "usbhub.setup.Port", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
731 { &hf_usb_hub_port_status
,
732 { "Port Status", "usbhub.status.port", FT_UINT16
, BASE_HEX
, NULL
, 0,
735 { &hf_usb_hub_port_change
,
736 { "Port Change", "usbhub.change.port", FT_UINT16
, BASE_HEX
, NULL
, 0,
739 { &hf_usb_hub_port_status_connection
,
740 { "PORT_CONNECTION", "usbhub.status.port.connection", FT_BOOLEAN
, 16, NULL
, (1<<0),
743 { &hf_usb_hub_port_status_enable
,
744 { "PORT_ENABLE", "usbhub.status.port.enable", FT_BOOLEAN
, 16, NULL
, (1<<1),
747 { &hf_usb_hub_port_status_suspend
,
748 { "PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN
, 16, NULL
, (1<<2),
751 { &hf_usb_hub_port_status_overcurrent
,
752 { "PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN
, 16, NULL
, (1<<3),
755 { &hf_usb_hub_port_status_reset
,
756 { "PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN
, 16, NULL
, (1<<4),
759 { &hf_usb_hub_port_status_power
,
760 { "PORT_POWER", "usbhub.status.port.power", FT_BOOLEAN
, 16, NULL
, (1<<8),
763 { &hf_usb_hub_port_status_low_speed
,
764 { "PORT_LOW_SPEED", "usbhub.status.port.low_speed", FT_BOOLEAN
, 16, NULL
, (1<<9),
767 { &hf_usb_hub_port_status_high_speed
,
768 { "PORT_HIGH_SPEED", "usbhub.status.port.high_speed", FT_BOOLEAN
, 16, NULL
, (1<<10),
771 { &hf_usb_hub_port_status_test
,
772 { "PORT_TEST", "usbhub.status.port.test", FT_BOOLEAN
, 16, NULL
, (1<<11),
775 { &hf_usb_hub_port_status_indicator
,
776 { "PORT_INDICATOR", "usbhub.status.port.indicator", FT_BOOLEAN
, 16,
777 TFS(&hub_port_status_indicator_meaning
), (1<<12),
780 { &hf_usb_hub_port_change_connection
,
781 { "C_PORT_CONNECTION", "usbhub.change.port.connection", FT_BOOLEAN
, 16, NULL
, (1<<0),
784 { &hf_usb_hub_port_change_enable
,
785 { "C_PORT_ENABLE", "usbhub.change.port.enable", FT_BOOLEAN
, 16, NULL
, (1<<1),
788 { &hf_usb_hub_port_change_suspend
,
789 { "C_PORT_SUSPEND", "usbhub.status.port.suspend", FT_BOOLEAN
, 16, NULL
, (1<<2),
792 { &hf_usb_hub_port_change_overcurrent
,
793 { "C_PORT_OVER_CURRENT", "usbhub.status.port.overcurrent", FT_BOOLEAN
, 16, NULL
, (1<<3),
796 { &hf_usb_hub_port_change_reset
,
797 { "C_PORT_RESET", "usbhub.status.port.reset", FT_BOOLEAN
, 16, NULL
, (1<<4),
801 static gint
*usb_hub_subtrees
[] = {
804 &ett_usb_hub_wLength
,
805 &ett_usb_hub_port_status
,
806 &ett_usb_hub_port_change
809 proto_usb_hub
= proto_register_protocol("USB HUB", "USBHUB", "usbhub");
810 proto_register_field_array(proto_usb_hub
, hf
, array_length(hf
));
811 proto_register_subtree_array(usb_hub_subtrees
, array_length(usb_hub_subtrees
));
815 proto_reg_handoff_usb_hub(void) {
816 dissector_handle_t usb_hub_control_handle
;
818 usb_hub_control_handle
= new_create_dissector_handle(dissect_usb_hub_control
, proto_usb_hub
);
819 dissector_add_uint("usb.control", IF_CLASS_HUB
, usb_hub_control_handle
);
820 dissector_add_uint("usb.control", IF_CLASS_UNKNOWN
, usb_hub_control_handle
);