#include <string.h> and/or #include <stdio.h> not needed.
[obnox/wireshark/wip.git] / epan / dissectors / packet-usb-hub.c
1 /* packet-usb-hub.c
2  * Routines for USB HUB dissection
3  * Copyright 2009, Marton Nemeth <nm127@freemail.hu>
4  *
5  * $Id$
6  *
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
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
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.
19  *
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.
24  *
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.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include "packet-usb.h"
37
38 /* protocols and header fields */
39 static int proto_usb_hub = -1;
40
41 /* USB 2.0, Chapter 11.24.2 Class-Specific Requests */
42 static int hf_usb_hub_request = -1;
43 static int hf_usb_hub_value = -1;
44 static int hf_usb_hub_index = -1;
45 static int hf_usb_hub_length = -1;
46
47 static int hf_usb_hub_hub_feature_selector = -1;
48 static int hf_usb_hub_port_feature_selector = -1;
49 static int hf_usb_hub_dev_addr = -1;
50 static int hf_usb_hub_ep_num = -1;
51 static int hf_usb_hub_descriptor_type = -1;
52 static int hf_usb_hub_descriptor_index = -1;
53 static int hf_usb_hub_zero = -1;
54 static int hf_usb_hub_tt_flags = -1;
55 static int hf_usb_hub_tt_port = -1;
56 static int hf_usb_hub_tt_state_length = -1;
57 static int hf_usb_hub_port = -1;
58 static int hf_usb_hub_port_selector = -1;
59 static int hf_usb_hub_descriptor_length = -1;
60
61 static gint ett_usb_hub_wValue = -1;
62 static gint ett_usb_hub_wIndex = -1;
63 static gint ett_usb_hub_wLength = -1;
64
65 /* Table 11-16. Hub Class Request Codes */
66 #define USB_HUB_REQUEST_GET_STATUS           0
67 #define USB_HUB_REQUEST_CLEAR_FEATURE        1
68 #define USB_HUB_REQUEST_SET_FEATURE          3
69 #define USB_HUB_REQUEST_GET_DESCRIPTOR       6
70 #define USB_HUB_REQUEST_SET_DESCRIPTOR       7
71 #define USB_HUB_REQUEST_CLEAR_TT_BUFFER      8
72 #define USB_HUB_REQUEST_RESET_TT             9
73 #define USB_HUB_REQUEST_GET_TT_STATE         10
74 #define USB_HUB_REQUEST_STOP_TT              11
75
76 static const value_string setup_request_names_vals[] = {
77         { USB_HUB_REQUEST_GET_STATUS, "GET_STATUS" },
78         { USB_HUB_REQUEST_CLEAR_FEATURE, "CLEAR_FEATURE" },
79         { USB_HUB_REQUEST_SET_FEATURE, "SET_FEATURE" },
80         { USB_HUB_REQUEST_GET_DESCRIPTOR, "GET_DESCRIPTOR" },
81         { USB_HUB_REQUEST_SET_DESCRIPTOR, "SET_DESCRIPTOR" },
82         { USB_HUB_REQUEST_CLEAR_TT_BUFFER, "CLEAR_TT_BUFFER" },
83         { USB_HUB_REQUEST_GET_TT_STATE, "GET_TT_STATE" },
84         { USB_HUB_REQUEST_STOP_TT, "STOP_TT" },
85         { 0, NULL }
86 };
87
88
89 /* Table 11-17 Hub Class Feature Selectors */
90 #define USB_HUB_FEATURE_C_HUB_LOCAL_POWER     0
91 #define USB_HUB_FEATURE_C_HUB_OVER_CURRENT    1
92
93 #define USB_HUB_FEATURE_PORT_CONNECTION       0
94 #define USB_HUB_FEATURE_PORT_ENABLE           1
95 #define USB_HUB_FEATURE_PORT_SUSPEND          2
96 #define USB_HUB_FEATURE_PORT_OVER_CURRENT     3
97 #define USB_HUB_FEATURE_PORT_RESET            4
98 #define USB_HUB_FEATURE_PORT_POWER            8
99 #define USB_HUB_FEATURE_PORT_LOW_SPEED        9
100 #define USB_HUB_FEATURE_C_PORT_CONNECTION     16
101 #define USB_HUB_FEATURE_C_PORT_ENABLE         17
102 #define USB_HUB_FEATURE_C_PORT_SUSPEND        18
103 #define USB_HUB_FEATURE_C_PORT_OVER_CURRENT   19
104 #define USB_HUB_FEATURE_C_PORT_RESET          20
105 #define USB_HUB_FEATURE_PORT_TEST             21
106 #define USB_HUB_FEATURE_PORT_INDICATOR        22
107
108 static const value_string hub_class_feature_selectors_recipient_hub_vals[] = {
109         { USB_HUB_FEATURE_C_HUB_LOCAL_POWER, "C_HUB_LOCAL_POWER" },
110         { USB_HUB_FEATURE_C_HUB_OVER_CURRENT, "C_HUB_OVER_CURRENT" },
111         { 0, NULL }
112 };
113
114 static const value_string hub_class_feature_selectors_recipient_port_vals[] = {
115         { USB_HUB_FEATURE_PORT_CONNECTION, "PORT_CONNECTION" },
116         { USB_HUB_FEATURE_PORT_ENABLE, "PORT_ENABLE" },
117         { USB_HUB_FEATURE_PORT_SUSPEND, "PORT_SUSPEND" },
118         { USB_HUB_FEATURE_PORT_OVER_CURRENT, "PORT_OVER_CURRENT" },
119         { USB_HUB_FEATURE_PORT_RESET, "PORT_RESET" },
120         { USB_HUB_FEATURE_PORT_POWER, "PORT_POWER" },
121         { USB_HUB_FEATURE_PORT_LOW_SPEED, "PORT_LOW_SPEED" },
122         { USB_HUB_FEATURE_C_PORT_CONNECTION, "C_PORT_CONNECTION" },
123         { USB_HUB_FEATURE_C_PORT_ENABLE, "C_PORT_ENABLE" },
124         { USB_HUB_FEATURE_C_PORT_SUSPEND, "C_PORT_SUSPEND" },
125         { USB_HUB_FEATURE_C_PORT_OVER_CURRENT, "C_PORT_OVER_CURRENT" },
126         { USB_HUB_FEATURE_C_PORT_RESET, "C_PORT_RESET" },
127         { USB_HUB_FEATURE_PORT_TEST, "PORT_TEST" },
128         { USB_HUB_FEATURE_PORT_INDICATOR, "PORT_INDICATOR" },
129         { 0, NULL }
130 };
131
132
133 /* Dissector for ClearHubFeature, Chapter 11.24.2.1 Clear Hub Feature */
134 static void
135 dissect_usb_hub_clear_hub_feature(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_)
136 {
137         proto_item *item = NULL;
138         proto_tree *subtree = NULL;
139
140         if (is_request) {
141                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
142                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
143                 proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, TRUE);
144                 offset += 2;
145
146                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
147                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
148                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
149                 offset += 2;
150
151                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
152                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
153                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
154                 offset += 2;
155         } else {
156         }
157 }
158
159 /* Dissector for ClearPortFeature, Chapter 11.24.2.2 Clear Port Feature */
160 static void
161 dissect_usb_hub_clear_port_feature(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_)
162 {
163         proto_item *item = NULL;
164         proto_tree *subtree = NULL;
165
166         if (is_request) {
167                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
168                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
169                 proto_tree_add_item(subtree, hf_usb_hub_port_feature_selector, tvb, offset, 2, TRUE);
170                 offset += 2;
171
172                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
173                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
174                 proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 1, TRUE);
175                 offset++;
176                 proto_tree_add_item(subtree, hf_usb_hub_port_selector, tvb, offset, 1, TRUE);
177                 offset++;
178
179                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
180                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
181                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
182                 offset += 2;
183         } else {
184         }
185 }
186
187 /* Dissector for ClearTTBuffer, Chapter 11.24.2.3 Clear TT Buffer */
188 static void
189 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_)
190 {
191         proto_item *item = NULL;
192         proto_tree *subtree = NULL;
193
194         if (is_request) {
195                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
196                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
197                 proto_tree_add_item(subtree, hf_usb_hub_ep_num, tvb, offset, 1, TRUE);
198                 offset++;
199                 proto_tree_add_item(subtree, hf_usb_hub_dev_addr, tvb, offset, 1, TRUE);
200                 offset++;
201
202                 proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
203                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
204                 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 2, TRUE);
205                 offset += 2;
206
207                 proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
208                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
209                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
210                 offset += 2;
211         } else {
212         }
213 }
214
215 /* Dissector for GetHubDescriptor, Chapter 11.24.2.5 Get Hub Descriptor */
216 static void
217 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_)
218 {
219         proto_item *item = NULL;
220         proto_tree *subtree = NULL;
221
222         if (is_request) {
223                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
224                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
225                 proto_tree_add_item(subtree, hf_usb_hub_descriptor_index, tvb, offset, 1, TRUE);
226                 offset++;
227                 proto_tree_add_item(subtree, hf_usb_hub_descriptor_type, tvb, offset, 1, TRUE);
228                 offset++;
229
230                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
231                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
232                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
233                 offset += 2;
234
235                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
236                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
237                 proto_tree_add_item(subtree, hf_usb_hub_descriptor_length, tvb, offset, 2, TRUE);
238                 offset += 2;
239         } else {
240         }
241 }
242
243 /* Dissector for GetHubStatus, Chapter 11.24.2.6 Get Hub Status */
244 static void
245 dissect_usb_hub_get_hub_status(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_)
246 {
247         proto_item *item = NULL;
248         proto_tree *subtree = NULL;
249
250         if (is_request) {
251                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
252                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
253                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
254                 offset += 2;
255
256                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
257                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
258                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
259                 offset += 2;
260
261                 proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
262                 /* length shall always contain 4 */
263                 offset += 2;
264         } else {
265         }
266 }
267
268 /* Dissector for GetPortStatus, Chapter 11.24.2.7 Get Port Status */
269 static void
270 dissect_usb_hub_get_port_status(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_)
271 {
272         proto_item *item = NULL;
273         proto_tree *subtree = NULL;
274
275         if (is_request) {
276                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
277                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
278                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
279                 offset += 2;
280
281                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
282                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
283                 proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 2, TRUE);
284                 offset += 2;
285
286                 proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
287                 /* length shall always contain 4 */
288                 offset += 2;
289         } else {
290         }
291 }
292
293 /* Dissector for GetTTState, Chapter 11.24.2.8 Get_TT_State */
294 static void
295 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_)
296 {
297         proto_item *item = NULL;
298         proto_tree *subtree = NULL;
299
300         if (is_request) {
301                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
302                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
303                 proto_tree_add_item(subtree, hf_usb_hub_tt_flags, tvb, offset, 1, TRUE);
304                 offset += 2;
305
306                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
307                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
308                 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 1, TRUE);
309                 offset += 2;
310
311                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
312                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
313                 proto_tree_add_item(subtree, hf_usb_hub_tt_state_length, tvb, offset, 1, TRUE);
314                 offset += 2;
315         } else {
316         }
317 }
318
319 /* Dissector for ResetTT, Chapter 11.24.2.9 Reset_TT */
320 static void
321 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_)
322 {
323         proto_item *item = NULL;
324         proto_tree *subtree = NULL;
325
326         if (is_request) {
327                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
328                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
329                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, TRUE);
330                 offset += 2;
331
332                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
333                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
334                 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 1, TRUE);
335                 offset += 2;
336
337                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
338                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
339                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, TRUE);
340                 offset += 2;
341         } else {
342         }
343 }
344
345 /* Dissector for SetHubDescriptor, Chapter 11.24.2.10 Set Hub Descriptor */
346 static void
347 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_)
348 {
349         proto_item *item = NULL;
350         proto_tree *subtree = NULL;
351
352         if (is_request) {
353                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
354                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
355                 proto_tree_add_item(subtree, hf_usb_hub_descriptor_index, tvb, offset, 1, TRUE);
356                 offset++;
357                 proto_tree_add_item(subtree, hf_usb_hub_descriptor_type, tvb, offset, 1, TRUE);
358                 offset++;
359
360                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
361                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
362                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
363                 offset += 2;
364
365                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
366                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
367                 proto_tree_add_item(subtree, hf_usb_hub_descriptor_length, tvb, offset, 2, TRUE);
368                 offset += 2;
369         } else {
370         }
371 }
372
373 /* Dissector for StopTT, Chapter 11.24.2.11 Stop TT */
374 static void
375 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_)
376 {
377         proto_item *item = NULL;
378         proto_tree *subtree = NULL;
379
380         if (is_request) {
381                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
382                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
383                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 1, TRUE);
384                 offset += 2;
385
386                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
387                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
388                 proto_tree_add_item(subtree, hf_usb_hub_tt_port, tvb, offset, 2, TRUE);
389                 offset += 2;
390
391                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
392                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
393                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
394                 offset += 2;
395         } else {
396         }
397 }
398
399 /* Dissector for SetHubFeature, Chapter 11.24.2.12 Set Hub Feature */
400 static void
401 dissect_usb_hub_set_hub_feature(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_)
402 {
403         proto_item *item = NULL;
404         proto_tree *subtree = NULL;
405
406         if (is_request) {
407                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
408                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
409                 proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, TRUE);
410                 offset += 2;
411
412                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
413                 subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
414                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
415                 offset += 2;
416
417                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
418                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
419                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
420                 offset += 2;
421         } else {
422         }
423 }
424
425 /* Dissector for SetPortFeature, Chapter 11.24.2.13 Set Port Feature */
426 static void
427 dissect_usb_hub_set_port_feature(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_)
428 {
429         proto_item *item = NULL;
430         proto_tree *subtree = NULL;
431
432         if (is_request) {
433                 item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, TRUE);
434                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
435                 proto_tree_add_item(subtree, hf_usb_hub_port_feature_selector, tvb, offset, 2, TRUE);
436                 offset += 2;
437
438                 item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, TRUE);
439                 subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
440                 proto_tree_add_item(subtree, hf_usb_hub_port, tvb, offset, 1, TRUE);
441                 offset++;
442                 proto_tree_add_item(subtree, hf_usb_hub_port_selector, tvb, offset, 1, TRUE);
443                 offset++;
444
445                 item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, TRUE);
446                 subtree = proto_item_add_subtree(item, ett_usb_hub_wLength);
447                 proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, TRUE);
448                 offset += 2;
449         } else {
450         }
451 }
452
453
454 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);
455
456 typedef struct _usb_setup_dissector_table_t {
457         guint8 request_type;
458         guint8 request;
459         usb_setup_dissector dissector;
460 } usb_setup_dissector_table_t;
461
462
463 /* USB 2.0, Table 11-15 Hub Class Requests */
464 static const usb_setup_dissector_table_t setup_dissectors[] = {
465         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
466           USB_HUB_REQUEST_CLEAR_FEATURE,
467           dissect_usb_hub_clear_hub_feature
468         },
469
470         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
471           USB_HUB_REQUEST_CLEAR_FEATURE,
472           dissect_usb_hub_clear_port_feature
473         },
474
475         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
476           USB_HUB_REQUEST_CLEAR_TT_BUFFER,
477           dissect_usb_hub_clear_tt_buffer
478         },
479
480         { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
481           USB_HUB_REQUEST_GET_DESCRIPTOR,
482           dissect_usb_hub_get_hub_descriptor
483         },
484
485         { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
486           USB_HUB_REQUEST_GET_STATUS,
487           dissect_usb_hub_get_hub_status
488         },
489
490         { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
491           USB_HUB_REQUEST_GET_STATUS,
492           dissect_usb_hub_get_port_status
493         },
494
495         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
496           USB_HUB_REQUEST_RESET_TT,
497           dissect_usb_hub_reset_tt
498         },
499
500         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
501           USB_HUB_REQUEST_SET_DESCRIPTOR,
502           dissect_usb_hub_set_hub_descriptor
503         },
504
505         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_DEVICE,
506           USB_HUB_REQUEST_SET_FEATURE,
507           dissect_usb_hub_set_hub_feature
508         },
509
510         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
511           USB_HUB_REQUEST_SET_FEATURE,
512           dissect_usb_hub_set_port_feature
513         },
514
515         { USB_DIR_IN | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
516           USB_HUB_REQUEST_GET_TT_STATE,
517           dissect_usb_hub_get_tt_state
518         },
519
520         { USB_DIR_OUT | (RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_OTHER,
521           USB_HUB_REQUEST_STOP_TT,
522           dissect_usb_hub_stop_tt
523         },
524
525         { 0, 0, NULL }
526 };
527
528 /* Dissector for USB HUB class-specific control request as defined in
529  * USB 2.0, Chapter 11.24.2 Class-specific Requests
530  * Returns TRUE if a class specific dissector was found
531  * and FALSE otherwise.
532  */
533 static gint
534 dissect_usb_hub_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
535 {
536         gboolean is_request;
537         usb_conv_info_t *usb_conv_info;
538         usb_trans_info_t *usb_trans_info;
539         int offset = 0;
540         usb_setup_dissector dissector;
541         const usb_setup_dissector_table_t *tmp;
542
543         is_request = (pinfo->srcport==NO_ENDPOINT);
544
545         usb_conv_info = pinfo->usb_conv_info;
546         usb_trans_info = usb_conv_info->usb_trans_info;
547
548         /* See if we can find a class specific dissector for this request */
549         dissector = NULL;
550
551         /* Check valid values for bmRequestType and bRequest */
552         for (tmp = setup_dissectors; tmp->dissector; tmp++) {
553                 if (tmp->request_type == usb_trans_info->requesttype &&
554                     tmp->request == usb_trans_info->request) {
555                         dissector = tmp->dissector;
556                         break;
557                 }
558         }
559         /* No, we could not find any class specific dissector for this request
560          * return FALSE and let USB try any of the standard requests.
561          */
562         if (!dissector) {
563                 return FALSE;
564         }
565
566         col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHUB");
567
568         if (check_col(pinfo->cinfo, COL_INFO)) {
569                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
570                 val_to_str(usb_trans_info->request, setup_request_names_vals, "Unknown type %x"),
571                         is_request ? "Request" : "Response");
572         }
573
574         if (is_request) {
575                 proto_tree_add_item(tree, hf_usb_hub_request, tvb, offset, 1, TRUE);
576                 offset += 1;
577         }
578
579         dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
580         return TRUE;
581 }
582
583 void
584 proto_register_usb_hub(void)
585 {
586         static hf_register_info hf[] = {
587                 /* USB HUB specific requests */
588                 { &hf_usb_hub_request,
589                 { "bRequest", "usbhub.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
590                   NULL, HFILL }},
591
592                 { &hf_usb_hub_value,
593                 { "wValue", "usbhub.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
594                   NULL, HFILL }},
595
596                 { &hf_usb_hub_index,
597                 { "wIndex", "usbhub.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
598                   NULL, HFILL }},
599
600                 { &hf_usb_hub_length,
601                 { "wLength", "usbhub.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
602                   NULL, HFILL }},
603
604                 { &hf_usb_hub_hub_feature_selector,
605                 { "HubFeatureSelector", "usbhub.setup.HubFeatureSelector", FT_UINT16, BASE_DEC,
606                   VALS(hub_class_feature_selectors_recipient_hub_vals), 0x0,
607                   NULL, HFILL }},
608
609                 { &hf_usb_hub_port_feature_selector,
610                 { "PortFeatureSelector", "usbhub.setup.PortFeatureSelector", FT_UINT16, BASE_DEC,
611                   VALS(hub_class_feature_selectors_recipient_port_vals), 0x0,
612                   NULL, HFILL }},
613
614                 { &hf_usb_hub_dev_addr,
615                 { "Dev_Addr", "usbhub.setup.Dev_Addr", FT_UINT8, BASE_DEC, NULL, 0x0,
616                   NULL, HFILL }},
617
618                 { &hf_usb_hub_ep_num,
619                 { "EP_Num", "usbhub.setup.EP_Num", FT_UINT8, BASE_DEC, NULL, 0x0,
620                   NULL, HFILL }},
621
622                 { &hf_usb_hub_descriptor_type,
623                 { "DescriptorType", "usbhub.setup.DescriptorType", FT_UINT8, BASE_DEC, NULL, 0x0,
624                   NULL, HFILL }},
625
626                 { &hf_usb_hub_descriptor_index,
627                 { "DescriptorIndex", "usbhub.setup.DescriptorIndex", FT_UINT8, BASE_DEC, NULL, 0x0,
628                   NULL, HFILL }},
629
630                 { &hf_usb_hub_descriptor_length,
631                 { "DescriptorLength", "usbhub.setup.DescriptorLength", FT_UINT8, BASE_DEC, NULL, 0x0,
632                   NULL, HFILL }},
633
634                 { &hf_usb_hub_zero,
635                 { "(zero)", "usbhub.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
636                   NULL, HFILL }},
637
638                 { &hf_usb_hub_tt_flags,
639                 { "TT_Flags", "usbhub.setup.TT_Flags", FT_UINT8, BASE_DEC, NULL, 0x0,
640                   NULL, HFILL }},
641
642                 { &hf_usb_hub_tt_port,
643                 { "TT_Port", "usbhub.setup.TT_Port", FT_UINT16, BASE_DEC, NULL, 0x0,
644                   NULL, HFILL }},
645
646                 { &hf_usb_hub_tt_state_length,
647                 { "TT State Length", "usbhub.setup.TT_StateLength", FT_UINT16, BASE_DEC, NULL, 0x0,
648                   NULL, HFILL }},
649
650                 { &hf_usb_hub_port_selector,
651                 { "PortSelector", "usbhub.setup.PortSelector", FT_UINT8, BASE_DEC, NULL, 0x0,
652                   NULL, HFILL }},
653
654                 { &hf_usb_hub_port,
655                 { "Port", "usbhub.setup.Port", FT_UINT8, BASE_DEC, NULL, 0x0,
656                   NULL, HFILL }}
657
658         };
659
660         static gint *usb_hub_subtrees[] = {
661                 &ett_usb_hub_wValue,
662                 &ett_usb_hub_wIndex,
663                 &ett_usb_hub_wLength
664         };
665
666         proto_usb_hub = proto_register_protocol("USB HUB", "USBHUB", "usbhub");
667         proto_register_field_array(proto_usb_hub, hf, array_length(hf));
668         proto_register_subtree_array(usb_hub_subtrees, array_length(usb_hub_subtrees));
669 }
670
671 void
672 proto_reg_handoff_usb_hub(void) {
673         dissector_handle_t usb_hub_control_handle;
674
675         usb_hub_control_handle = new_create_dissector_handle(dissect_usb_hub_control, proto_usb_hub);
676         dissector_add("usb.control", IF_CLASS_HUB, usb_hub_control_handle);
677         dissector_add("usb.control", IF_CLASS_UNKNOWN, usb_hub_control_handle);
678 }