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