From Steve Magnani:
[metze/wireshark/wip.git] / epan / dissectors / packet-usb-hid.c
1 /* packet-usb-hid.c
2  *
3  * $Id$
4  *
5  * USB HID dissector
6  * By Adam Nielsen <a.nielsen@shikadi.net> 2009
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <glib.h>
29 #include <epan/packet.h>
30 #include <string.h>
31 #include "packet-usb.h"
32 #include "packet-usb-hid.h"
33
34 /* protocols and header fields */
35 static int proto_usb_hid = -1;
36 static int hf_usb_hid_item_bSize = -1;
37 static int hf_usb_hid_item_bType = -1;
38 static int hf_usb_hid_mainitem_bTag = -1;
39 static int hf_usb_hid_globalitem_bTag = -1;
40 static int hf_usb_hid_localitem_bTag = -1;
41 static int hf_usb_hid_longitem_bTag = -1;
42 static int hf_usb_hid_item_bDataSize = -1;
43 static int hf_usb_hid_item_bLongItemTag = -1;
44 static int hf_usb_hid_item_unk_data = -1;
45
46 static int hf_usb_hid_mainitem_bit0 = -1;
47 static int hf_usb_hid_mainitem_bit1 = -1;
48 static int hf_usb_hid_mainitem_bit2 = -1;
49 static int hf_usb_hid_mainitem_bit3 = -1;
50 static int hf_usb_hid_mainitem_bit4 = -1;
51 static int hf_usb_hid_mainitem_bit5 = -1;
52 static int hf_usb_hid_mainitem_bit6 = -1;
53 static int hf_usb_hid_mainitem_bit7 = -1;
54 static int hf_usb_hid_mainitem_bit7_input = -1;
55 static int hf_usb_hid_mainitem_bit8 = -1;
56 static int hf_usb_hid_mainitem_colltype = -1;
57
58 static int hf_usb_hid_globalitem_usage = -1;
59 static int hf_usb_hid_globalitem_log_min = -1;
60 static int hf_usb_hid_globalitem_log_max = -1;
61 static int hf_usb_hid_globalitem_phy_min = -1;
62 static int hf_usb_hid_globalitem_phy_max = -1;
63 static int hf_usb_hid_globalitem_unit_exp = -1;
64 static int hf_usb_hid_globalitem_unit_sys = -1;
65 static int hf_usb_hid_globalitem_unit_len = -1;
66 static int hf_usb_hid_globalitem_unit_mass = -1;
67 static int hf_usb_hid_globalitem_unit_time = -1;
68 static int hf_usb_hid_globalitem_unit_temp = -1;
69 static int hf_usb_hid_globalitem_unit_current = -1;
70 static int hf_usb_hid_globalitem_unit_brightness = -1;
71 static int hf_usb_hid_globalitem_report_size = -1;
72 static int hf_usb_hid_globalitem_report_id = -1;
73 static int hf_usb_hid_globalitem_report_count = -1;
74 static int hf_usb_hid_globalitem_push = -1;
75 static int hf_usb_hid_globalitem_pop = -1;
76
77 static int hf_usb_hid_localitem_usage = -1;
78 static int hf_usb_hid_localitem_usage_min = -1;
79 static int hf_usb_hid_localitem_usage_max = -1;
80 static int hf_usb_hid_localitem_desig_index = -1;
81 static int hf_usb_hid_localitem_desig_min = -1;
82 static int hf_usb_hid_localitem_desig_max = -1;
83 static int hf_usb_hid_localitem_string_index = -1;
84 static int hf_usb_hid_localitem_string_min = -1;
85 static int hf_usb_hid_localitem_string_max = -1;
86 static int hf_usb_hid_localitem_delimiter = -1;
87
88 static gint ett_usb_hid_report = -1;
89 static gint ett_usb_hid_item_header = -1;
90 static gint ett_usb_hid_wValue = -1;
91
92 static int hf_usb_hid_request = -1;
93 static int hf_usb_hid_value = -1;
94 static int hf_usb_hid_index = -1;
95 static int hf_usb_hid_length = -1;
96 static int hf_usb_hid_report_type = -1;
97 static int hf_usb_hid_report_id = -1;
98 static int hf_usb_hid_duration = -1;
99 static int hf_usb_hid_zero = -1;
100
101 static const true_false_string tfs_mainitem_bit0 = {"Data", "Constant"};
102 static const true_false_string tfs_mainitem_bit1 = {"Array", "Variable"};
103 static const true_false_string tfs_mainitem_bit2 = {"Absolute", "Relative"};
104 static const true_false_string tfs_mainitem_bit3 = {"No wrap", "Wrap"};
105 static const true_false_string tfs_mainitem_bit4 = {"Linear", "Nonlinear"};
106 static const true_false_string tfs_mainitem_bit5 = {"Preferred state", "No preferred state"};
107 static const true_false_string tfs_mainitem_bit6 = {"No null position", "Null state"};
108 static const true_false_string tfs_mainitem_bit7 = {"Non-volatile", "Volatile"};
109 static const true_false_string tfs_mainitem_bit8 = {"Bit field", "Buffered bytes"};
110
111
112 struct usb_hid_global_state {
113         unsigned int usage_page;
114 };
115
116 #define USBHID_SIZE_MASK  0x03
117 #define USBHID_TYPE_MASK  0x0C
118 #define USBHID_TAG_MASK   0xF0
119
120 static const value_string usb_hid_item_bSize_vals[] = {
121         {0, "0 bytes"},
122         {1, "1 byte"},
123         {2, "2 bytes"},
124         {3, "4 bytes"},
125         {0, NULL}
126 };
127
128 #define USBHID_ITEMTYPE_MAIN    0
129 #define USBHID_ITEMTYPE_GLOBAL  1
130 #define USBHID_ITEMTYPE_LOCAL   2
131 #define USBHID_ITEMTYPE_LONG    3
132 static const value_string usb_hid_item_bType_vals[] = {
133         {USBHID_ITEMTYPE_MAIN,   "Main"},
134         {USBHID_ITEMTYPE_GLOBAL, "Global"},
135         {USBHID_ITEMTYPE_LOCAL,  "Local"},
136         {USBHID_ITEMTYPE_LONG,   "Long item"},
137         {0, NULL}
138 };
139
140 #define USBHID_MAINITEM_TAG_INPUT           8
141 #define USBHID_MAINITEM_TAG_OUTPUT          9
142 #define USBHID_MAINITEM_TAG_FEATURE        11
143 #define USBHID_MAINITEM_TAG_COLLECTION     10
144 #define USBHID_MAINITEM_TAG_ENDCOLLECTION  12
145 static const value_string usb_hid_mainitem_bTag_vals[] = {
146         {USBHID_MAINITEM_TAG_INPUT,         "Input"},
147         {USBHID_MAINITEM_TAG_OUTPUT,        "Output"},
148         {USBHID_MAINITEM_TAG_FEATURE,       "Feature"},
149         {USBHID_MAINITEM_TAG_COLLECTION,    "Collection"},
150         {USBHID_MAINITEM_TAG_ENDCOLLECTION, "End collection"},
151         {0, NULL}
152 };
153 #define USBHID_GLOBALITEM_TAG_USAGE_PAGE    0
154 #define USBHID_GLOBALITEM_TAG_LOG_MIN       1
155 #define USBHID_GLOBALITEM_TAG_LOG_MAX       2
156 #define USBHID_GLOBALITEM_TAG_PHY_MIN       3
157 #define USBHID_GLOBALITEM_TAG_PHY_MAX       4
158 #define USBHID_GLOBALITEM_TAG_UNIT_EXP      5
159 #define USBHID_GLOBALITEM_TAG_UNIT          6
160 #define USBHID_GLOBALITEM_TAG_REPORT_SIZE   7
161 #define USBHID_GLOBALITEM_TAG_REPORT_ID     8
162 #define USBHID_GLOBALITEM_TAG_REPORT_COUNT  9
163 #define USBHID_GLOBALITEM_TAG_PUSH         10
164 #define USBHID_GLOBALITEM_TAG_POP          11
165 static const value_string usb_hid_globalitem_bTag_vals[] = {
166         {USBHID_GLOBALITEM_TAG_USAGE_PAGE,   "Usage"},
167         {USBHID_GLOBALITEM_TAG_LOG_MIN,      "Logical minimum"},
168         {USBHID_GLOBALITEM_TAG_LOG_MAX,      "Logical maximum"},
169         {USBHID_GLOBALITEM_TAG_PHY_MIN,      "Physical minimum"},
170         {USBHID_GLOBALITEM_TAG_PHY_MAX,      "Physical maximum"},
171         {USBHID_GLOBALITEM_TAG_UNIT_EXP,     "Unit exponent"},
172         {USBHID_GLOBALITEM_TAG_UNIT,         "Units"},
173         {USBHID_GLOBALITEM_TAG_REPORT_SIZE,  "Report size"},
174         {USBHID_GLOBALITEM_TAG_REPORT_ID,    "Report ID"},
175         {USBHID_GLOBALITEM_TAG_REPORT_COUNT, "Report count"},
176         {USBHID_GLOBALITEM_TAG_PUSH,         "Push"},
177         {USBHID_GLOBALITEM_TAG_POP,          "Pop"},
178         {12, "[Reserved]"},
179         {13, "[Reserved]"},
180         {14, "[Reserved]"},
181         {15, "[Reserved]"},
182         {0, NULL}
183 };
184 #define USBHID_LOCALITEM_TAG_USAGE_PAGE     0
185 #define USBHID_LOCALITEM_TAG_USAGE_MIN      1
186 #define USBHID_LOCALITEM_TAG_USAGE_MAX      2
187 #define USBHID_LOCALITEM_TAG_DESIG_INDEX    3
188 #define USBHID_LOCALITEM_TAG_DESIG_MIN      4
189 #define USBHID_LOCALITEM_TAG_DESIG_MAX      5
190 /* No 6 in spec */
191 #define USBHID_LOCALITEM_TAG_STRING_INDEX   7
192 #define USBHID_LOCALITEM_TAG_STRING_MIN     8
193 #define USBHID_LOCALITEM_TAG_STRING_MAX     9
194 #define USBHID_LOCALITEM_TAG_DELIMITER     10 /* Also listed as reserved in spec! */
195 static const value_string usb_hid_localitem_bTag_vals[] = {
196         {USBHID_LOCALITEM_TAG_USAGE_PAGE,   "Usage"},
197         {USBHID_LOCALITEM_TAG_USAGE_MIN,    "Usage minimum"},
198         {USBHID_LOCALITEM_TAG_USAGE_MAX,    "Usage maximum"},
199         {USBHID_LOCALITEM_TAG_DESIG_INDEX,  "Designator index"},
200         {USBHID_LOCALITEM_TAG_DESIG_MIN,    "Designator minimum"},
201         {USBHID_LOCALITEM_TAG_DESIG_MAX,    "Designator maximum"},
202         {USBHID_LOCALITEM_TAG_STRING_INDEX, "String index"},
203         {USBHID_LOCALITEM_TAG_STRING_MIN,   "String minimum"},
204         {USBHID_LOCALITEM_TAG_STRING_MAX,   "String maximum"},
205         {USBHID_LOCALITEM_TAG_DELIMITER,    "Delimiter"},
206         {11, "[Reserved]"},
207         {12, "[Reserved]"},
208         {13, "[Reserved]"},
209         {14, "[Reserved]"},
210         {15, "[Reserved]"},
211         {0, NULL}
212 };
213 static const value_string usb_hid_longitem_bTag_vals[] = {
214         {15, "Long item"},
215         {0, NULL}
216 };
217
218 static const range_string usb_hid_mainitem_colltype_vals[] = {
219         {0x00, 0x00, "Physical"},
220         {0x01, 0x01, "Application"},
221         {0x02, 0x02, "Logical"},
222         {0x03, 0x03, "Report"},
223         {0x04, 0x04, "Named array"},
224         {0x05, 0x05, "Usage switch"},
225         {0x06, 0x06, "Usage modifier"},
226         {0x07, 0x7F, "[Reserved]"},
227         {0x80, 0xFF, "[Vendor-defined]"},
228         {0, 0, NULL}
229 };
230
231 static const value_string usb_hid_globalitem_unit_exp_vals[] = {
232         {0x0, "n^0"},
233         {0x1, "n^1"},
234         {0x2, "n^2"},
235         {0x3, "n^3"},
236         {0x4, "n^4"},
237         {0x5, "n^5"},
238         {0x6, "n^6"},
239         {0x7, "n^7"},
240         {0x8, "n^-8"},
241         {0x9, "n^-7"},
242         {0xA, "n^-6"},
243         {0xB, "n^-5"},
244         {0xC, "n^-4"},
245         {0xD, "n^-3"},
246         {0xE, "n^-2"},
247         {0xF, "n^-1"},
248         {0, NULL}
249 };
250 static const range_string usb_hid_item_usage_vals[] = {
251         {0x00, 0x00, "Undefined"},
252         {0x01, 0x01, "Generic desktop controls"},
253         {0x02, 0x02, "Simulation controls"},
254         {0x03, 0x03, "VR controls"},
255         {0x04, 0x04, "Sport controls"},
256         {0x05, 0x05, "Game controls"},
257         {0x06, 0x06, "Generic device controls"},
258         {0x07, 0x07, "Keyboard/keypad"},
259         {0x08, 0x08, "LEDs"},
260         {0x09, 0x09, "Button"},
261         {0x0A, 0x0A, "Ordinal"},
262         {0x0B, 0x0B, "Telephony"},
263         {0x0C, 0x0C, "Consumer"},
264         {0x0D, 0x0D, "Digitizer"},
265         {0x0E, 0x0E, "[Reserved]"},
266         {0x0F, 0x0F, "Physical Interface Device (PID) page"},
267         {0x10, 0x10, "Unicode"},
268         {0x11, 0x13, "[Reserved]"},
269         {0x14, 0x14, "Alphanumeric display"},
270         {0x15, 0x3F, "[Reserved]"},
271         {0x40, 0x40, "Medical instruments"},
272         {0x41, 0x7F, "[Reserved]"},
273         {0x80, 0x83, "Monitor page"},
274         {0x84, 0x87, "Power page"},
275         {0x88, 0x8B, "[Reserved]"},
276         {0x8C, 0x8C, "Bar code scanner page"},
277         {0x8D, 0x8D, "Scale page"},
278         {0x8E, 0x8E, "Magnetic Stripe Reading (MSR) devices"},
279         {0x8F, 0x8F, "[Reserved Point of Sale page]"},
280         {0x90, 0x90, "Camera control page"},
281         {0x91, 0x91, "Arcade page"},
282         {0x92, 0xFEFF, "[Reserved]"},
283         {0xFF00, 0xFFFF, "[Vendor-defined]"},
284         {0, 0, NULL}
285 };
286
287 /* Dissector for the data in a HID main report. */
288 static int
289 dissect_usb_hid_report_mainitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag)
290 {
291         switch (bTag) {
292                 case USBHID_MAINITEM_TAG_INPUT:
293                 case USBHID_MAINITEM_TAG_OUTPUT:
294                 case USBHID_MAINITEM_TAG_FEATURE:
295                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit0, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
296                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit1, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
297                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit2, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
298                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit3, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
299                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit4, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
300                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit5, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
301                         proto_tree_add_item(tree, hf_usb_hid_mainitem_bit6, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
302                         if (bTag == USBHID_MAINITEM_TAG_INPUT) {
303                                 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7_input, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
304                         } else {
305                                 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
306                         }
307                         if (bSize > 1) {
308                                 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit8, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
309                         } else {
310                                 proto_tree_add_text(tree, tvb, offset, 0, "Bits or bytes: Buffered bytes (default, no second byte present)");
311                         }
312                         break;
313                 case USBHID_MAINITEM_TAG_COLLECTION:
314                         proto_tree_add_item(tree, hf_usb_hid_mainitem_colltype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
315                         break;
316                 case USBHID_MAINITEM_TAG_ENDCOLLECTION:
317                         /* No item data */
318                         break;
319                 default:
320                         proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
321                         break;
322         }
323         offset += bSize;
324         return offset;
325 }
326
327 /* Dissector for the data in a HID main report. */
328 static int
329 dissect_usb_hid_report_globalitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag, struct usb_hid_global_state *global)
330 {
331         switch (bTag) {
332                 case USBHID_GLOBALITEM_TAG_USAGE_PAGE:
333                         switch (bSize) {
334                                 case 1: global->usage_page = tvb_get_guint8(tvb, offset); break;
335                                 case 2: global->usage_page = tvb_get_letohs(tvb, offset); break;
336                                 case 3: global->usage_page = tvb_get_letoh24(tvb, offset); break;
337                                 case 4: global->usage_page = tvb_get_letohl(tvb, offset); break;
338                                 default: global->usage_page = 0; break;
339                         }
340                         proto_tree_add_item(tree, hf_usb_hid_globalitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
341                         break;
342                 case USBHID_GLOBALITEM_TAG_LOG_MIN:
343                         proto_tree_add_item(tree, hf_usb_hid_globalitem_log_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
344                         break;
345                 case USBHID_GLOBALITEM_TAG_LOG_MAX:
346                         proto_tree_add_item(tree, hf_usb_hid_globalitem_log_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
347                         break;
348                 case USBHID_GLOBALITEM_TAG_PHY_MIN:
349                         proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
350                         break;
351                 case USBHID_GLOBALITEM_TAG_PHY_MAX:
352                         proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
353                         break;
354                 case USBHID_GLOBALITEM_TAG_UNIT_EXP:
355                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_exp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
356                         break;
357                 case USBHID_GLOBALITEM_TAG_UNIT:
358                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_sys, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
359                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_len, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
360                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_mass, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
361                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_time, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
362                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_temp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
363                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_current, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
364                         proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_brightness, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
365                         break;
366                 case USBHID_GLOBALITEM_TAG_REPORT_SIZE:
367                         proto_tree_add_item(tree, hf_usb_hid_globalitem_report_size, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
368                         break;
369                 case USBHID_GLOBALITEM_TAG_REPORT_ID:
370                         proto_tree_add_item(tree, hf_usb_hid_globalitem_report_id, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
371                         break;
372                 case USBHID_GLOBALITEM_TAG_REPORT_COUNT:
373                         proto_tree_add_item(tree, hf_usb_hid_globalitem_report_count, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
374                         break;
375                 case USBHID_GLOBALITEM_TAG_PUSH:
376                         proto_tree_add_item(tree, hf_usb_hid_globalitem_push, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
377                         break;
378                 case USBHID_GLOBALITEM_TAG_POP:
379                         proto_tree_add_item(tree, hf_usb_hid_globalitem_pop, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
380                         break;
381                 default:
382                         proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
383                         break;
384         }
385         offset += bSize;
386         return offset;
387 }
388
389 /* Dissector for the data in a HID main report. */
390 static int
391 dissect_usb_hid_report_localitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag, struct usb_hid_global_state *global)
392 {
393         unsigned int usage_page = 0xffffffff; /* in case bSize == 0 */
394
395         switch (bTag) {
396                 case USBHID_LOCALITEM_TAG_USAGE_PAGE:
397                         if (bSize > 2) {
398                                 /* Full page ID */
399                                 proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
400                         } else {
401                                 /* Only lower few bits given, need to combine with last global ID */
402                                 if (bSize == 1)
403                                         usage_page = (global->usage_page & 0xFFFFFF00) | tvb_get_guint8(tvb, offset);
404                                 else if (bSize == 2)
405                                         usage_page = (global->usage_page & 0xFFFF0000) | tvb_get_ntohs(tvb, offset);
406                                 proto_tree_add_text(tree, tvb, offset, bSize, "Usage: %s (0x%08x)",
407                                         rval_to_str(usage_page, usb_hid_item_usage_vals, "[Unknown page!]"),
408                                         usage_page);
409                         }
410                         break;
411                 case USBHID_LOCALITEM_TAG_USAGE_MIN:
412                         proto_tree_add_item(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
413                         break;
414                 case USBHID_LOCALITEM_TAG_USAGE_MAX:
415                         proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
416                         break;
417                 case USBHID_LOCALITEM_TAG_DESIG_INDEX:
418                         proto_tree_add_item(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
419                         break;
420                 case USBHID_LOCALITEM_TAG_DESIG_MIN:
421                         proto_tree_add_item(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
422                         break;
423                 case USBHID_LOCALITEM_TAG_DESIG_MAX:
424                         proto_tree_add_item(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
425                         break;
426                 case USBHID_LOCALITEM_TAG_STRING_INDEX:
427                         proto_tree_add_item(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
428                         break;
429                 case USBHID_LOCALITEM_TAG_STRING_MIN:
430                         proto_tree_add_item(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
431                         break;
432                 case USBHID_LOCALITEM_TAG_STRING_MAX:
433                         proto_tree_add_item(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
434                         break;
435                 case USBHID_LOCALITEM_TAG_DELIMITER:
436                         proto_tree_add_item(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
437                         break;
438                 default:
439                         proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
440                         break;
441         }
442         offset += bSize;
443         return offset;
444 }
445
446 /* Dissector for individual HID report items.  Recursive. */
447 static int
448 dissect_usb_hid_report_item(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_, const struct usb_hid_global_state *global)
449 {
450         proto_item *item=NULL, *subitem=NULL;
451         proto_tree *tree=NULL, *subtree=NULL;
452         int old_offset;
453         unsigned int tmp;
454         unsigned int bSize, bType, bTag;
455         const value_string *usb_hid_cur_bTag_vals;
456         int hf_usb_hid_curitem_bTag;
457         struct usb_hid_global_state cur_global;
458         memcpy(&cur_global, global, sizeof(struct usb_hid_global_state));
459
460         while (tvb_reported_length_remaining(tvb, offset))
461         {
462                 old_offset=offset;
463
464                 tmp = tvb_get_guint8(tvb, offset);
465                 bSize = tmp & USBHID_SIZE_MASK;
466                 if (bSize == 3) bSize++; /* 3 == four bytes */
467                 bType = (tmp & USBHID_TYPE_MASK) >> 2;
468                 bTag = (tmp & USBHID_TAG_MASK) >> 4;
469
470                 switch (bType) {
471                         case USBHID_ITEMTYPE_MAIN:
472                                 hf_usb_hid_curitem_bTag = hf_usb_hid_mainitem_bTag;
473                                 usb_hid_cur_bTag_vals = usb_hid_mainitem_bTag_vals;
474                                 break;
475                         case USBHID_ITEMTYPE_GLOBAL:
476                                 hf_usb_hid_curitem_bTag = hf_usb_hid_globalitem_bTag;
477                                 usb_hid_cur_bTag_vals = usb_hid_globalitem_bTag_vals;
478                                 break;
479                         case USBHID_ITEMTYPE_LOCAL:
480                                 hf_usb_hid_curitem_bTag = hf_usb_hid_localitem_bTag;
481                                 usb_hid_cur_bTag_vals = usb_hid_localitem_bTag_vals;
482                                 break;
483                         default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
484                                 hf_usb_hid_curitem_bTag = hf_usb_hid_longitem_bTag;
485                                 usb_hid_cur_bTag_vals = usb_hid_longitem_bTag_vals;
486                                 break;
487                 }
488
489                 subitem = proto_tree_add_text(parent_tree, tvb, offset, bSize + 1, "%s item (%s)",
490                         val_to_str(bType, usb_hid_item_bType_vals, "Unknown/%u"),
491                         val_to_str(bTag, usb_hid_cur_bTag_vals, "Unknown/%u tag")
492                 );
493                 subtree = proto_item_add_subtree(subitem, ett_usb_hid_item_header);
494
495                 item = proto_tree_add_text(subtree, tvb, offset, 1, "Header");
496                 tree = proto_item_add_subtree(item, ett_usb_hid_item_header);
497                 proto_tree_add_item(tree, hf_usb_hid_item_bSize, tvb, offset,   1, ENC_LITTLE_ENDIAN);
498                 proto_tree_add_item(tree, hf_usb_hid_item_bType, tvb, offset,   1, ENC_LITTLE_ENDIAN);
499                 proto_tree_add_item(tree, hf_usb_hid_curitem_bTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
500                 offset++;
501                 if ((bType == 3) && (bTag == 16)) {
502                         /* Long item */
503                         bSize = tvb_get_guint8(tvb, offset);
504                         proto_tree_add_item(subtree, hf_usb_hid_item_bDataSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
505                         offset++;
506                         proto_tree_add_item(subtree, hf_usb_hid_item_bLongItemTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
507                         offset++;
508                         proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
509                         offset += bSize;
510                 } else {
511                         /* Short item */
512                         switch (bType) {
513                                 case USBHID_ITEMTYPE_MAIN:
514                                         offset = dissect_usb_hid_report_mainitem_data(pinfo, subtree, tvb, offset, bSize, bTag);
515                                         break;
516                                 case USBHID_ITEMTYPE_GLOBAL:
517                                         offset = dissect_usb_hid_report_globalitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
518                                         break;
519                                 case USBHID_ITEMTYPE_LOCAL:
520                                         offset = dissect_usb_hid_report_localitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
521                                         break;
522                                 default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
523                                         proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
524                                         offset += bSize;
525                                         break;
526                         }
527                 }
528
529                 if (bType == USBHID_ITEMTYPE_MAIN) {
530                         if (bTag == USBHID_MAINITEM_TAG_COLLECTION) {
531                                 /* Begin collection, nest following elements under us */
532                                 offset = dissect_usb_hid_report_item(pinfo, subtree, tvb, offset, usb_trans_info, usb_conv_info, &cur_global);
533                                 proto_item_set_len(subitem, offset-old_offset);
534                         } else if (bTag == USBHID_MAINITEM_TAG_ENDCOLLECTION) {
535                                 /* End collection, break out to parent tree item */
536                                 break;
537                         }
538                 }
539         }
540         return offset;
541 }
542
543 /* Dissector for HID "GET DESCRIPTOR" subtype. */
544 int
545 dissect_usb_hid_get_report_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
546 {
547         proto_item *item=NULL;
548         proto_tree *tree=NULL;
549         int old_offset=offset;
550         struct usb_hid_global_state initial_global;
551         memset(&initial_global, 0, sizeof(struct usb_hid_global_state));
552
553         if (parent_tree) {
554                 item = proto_tree_add_protocol_format(parent_tree, proto_usb_hid, tvb, offset,
555                                                       -1, "HID Report");
556                 tree = proto_item_add_subtree(item, ett_usb_hid_report);
557                 offset = dissect_usb_hid_report_item(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info, &initial_global);
558
559                 proto_item_set_len(item, offset-old_offset);
560         }
561
562         return offset;
563 }
564
565 /* Dissector for HID GET_REPORT request. See USBHID 1.11, Chapter 7.2.1 Get_Report Request */
566 static void
567 dissect_usb_hid_get_report(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_)
568 {
569         proto_item *item = NULL;
570         proto_tree *subtree = NULL;
571
572         if (is_request) {
573                 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
574                 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
575
576                 /* Report Type in the high byte, Report ID in the low byte */
577                 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
578                 offset++;
579                 proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
580                 offset++;
581
582                 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
583                 offset += 2;
584
585                 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
586                 offset += 2;
587         } else {
588         }
589 }
590
591 /* Dissector for HID SET_REPORT request. See USBHID 1.11, Chapter 7.2.2 Set_Report Request */
592 static void
593 dissect_usb_hid_set_report(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_)
594 {
595         proto_item *item = NULL;
596         proto_tree *subtree = NULL;
597
598         if (is_request) {
599                 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
600                 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
601
602                 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
603                 offset++;
604                 proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
605                 offset++;
606
607                 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
608                 offset += 2;
609
610                 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
611                 offset += 2;
612         } else {
613         }
614 }
615
616
617 /* Dissector for HID GET_IDLE request. See USBHID 1.11, Chapter 7.2.3 Get_Idle Request */
618 static void
619 dissect_usb_hid_get_idle(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_)
620 {
621         proto_item *item = NULL;
622         proto_tree *subtree = NULL;
623
624         if (is_request) {
625                 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
626                 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
627
628                 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
629                 offset++;
630                 proto_tree_add_item(subtree, hf_usb_hid_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
631                 offset++;
632
633                 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
634                 offset += 2;
635
636                 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
637                 offset += 2;
638         } else {
639         }
640 }
641
642 /* Dissector for HID SET_IDLE request. See USBHID 1.11, Chapter 7.2.4 Set_Idle Request */
643 static void
644 dissect_usb_hid_set_idle(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_)
645 {
646         proto_item *item = NULL;
647         proto_tree *subtree = NULL;
648
649         if (is_request) {
650                 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
651                 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
652
653                 /* Duration in the high byte, Report ID in the low byte */
654                 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
655                 offset++;
656                 proto_tree_add_item(subtree, hf_usb_hid_duration, tvb, offset, 1, ENC_LITTLE_ENDIAN);
657                 offset++;
658
659                 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
660                 offset += 2;
661
662                 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
663                 offset += 2;
664         } else {
665         }
666 }
667
668 /* Dissector for HID GET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.5 Get_Protocol Request */
669 static void
670 dissect_usb_hid_get_protocol(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_)
671 {
672         if (is_request) {
673                 proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
674                 offset += 2;
675
676                 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
677                 offset += 2;
678
679                 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
680                 offset += 2;
681         } else {
682         }
683 }
684
685 /* Dissector for HID SET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.6 Set_Protocol Request */
686 static void
687 dissect_usb_hid_set_protocol(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_)
688 {
689         if (is_request) {
690                 proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
691                 offset += 2;
692
693                 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
694                 offset += 2;
695
696                 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
697                 offset += 2;
698         } else {
699         }
700 }
701
702
703 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);
704
705 typedef struct _usb_setup_dissector_table_t {
706         guint8 request;
707         usb_setup_dissector dissector;
708 } usb_setup_dissector_table_t;
709
710
711 /* USBHID 1.11, Chapter 7.2 Class-Specific Requests */
712 #define USB_HID_SETUP_GET_REPORT      0x01
713 #define USB_HID_SETUP_GET_IDLE        0x02
714 #define USB_HID_SETUP_GET_PROTOCOL    0x03
715 /* 0x04..0x08: Reserved */
716 #define USB_HID_SETUP_SET_REPORT      0x09
717 #define USB_HID_SETUP_SET_IDLE        0x0A
718 #define USB_HID_SETUP_SET_PROTOCOL    0x0B
719
720 static const usb_setup_dissector_table_t setup_dissectors[] = {
721         { USB_HID_SETUP_GET_REPORT,   dissect_usb_hid_get_report },
722         { USB_HID_SETUP_GET_IDLE,     dissect_usb_hid_get_idle },
723         { USB_HID_SETUP_GET_PROTOCOL, dissect_usb_hid_get_protocol },
724         { USB_HID_SETUP_SET_REPORT,   dissect_usb_hid_set_report },
725         { USB_HID_SETUP_SET_IDLE,     dissect_usb_hid_set_idle },
726         { USB_HID_SETUP_SET_PROTOCOL, dissect_usb_hid_set_protocol },
727         { 0, NULL }
728 };
729
730 static const value_string setup_request_names_vals[] = {
731         { USB_HID_SETUP_GET_REPORT,   "GET_REPORT" },
732         { USB_HID_SETUP_GET_IDLE,     "GET_IDLE" },
733         { USB_HID_SETUP_GET_PROTOCOL, "GET_PROTOCOL" },
734         { USB_HID_SETUP_SET_REPORT,   "SET_REPORT" },
735         { USB_HID_SETUP_SET_IDLE,     "SET_IDLE" },
736         { USB_HID_SETUP_SET_PROTOCOL, "SET_PROTOCOL" },
737         { 0, NULL }
738 };
739
740 static const value_string usb_hid_report_type_vals[] = {
741         { 1, "Input" },
742         { 2, "Output" },
743         { 3, "Feature" },
744         { 0, NULL }
745 };
746
747 /* Dissector for HID class-specific control request as defined in
748  * USBHID 1.11, Chapter 7.2.
749  * Returns TRUE if a class specific dissector was found
750  * and FALSE otherwise.
751  */
752 static gint
753 dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
754 {
755         gboolean is_request;
756         usb_conv_info_t *usb_conv_info;
757         usb_trans_info_t *usb_trans_info;
758         int offset = 0;
759         usb_setup_dissector dissector;
760         const usb_setup_dissector_table_t *tmp;
761
762         is_request = (pinfo->srcport==NO_ENDPOINT);
763
764         usb_conv_info = pinfo->usb_conv_info;
765         usb_trans_info = usb_conv_info->usb_trans_info;
766
767         /* See if we can find a class specific dissector for this request */
768         dissector = NULL;
769
770         /* Check valid values for bmRequestType. See Chapter 7.2 in USBHID 1.11 */
771         if ((usb_trans_info->setup.requesttype & 0x7F) ==
772             ((RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_INTERFACE)) {
773                 for (tmp = setup_dissectors; tmp->dissector; tmp++) {
774                         if (tmp->request == usb_trans_info->setup.request) {
775                                 dissector = tmp->dissector;
776                                 break;
777                         }
778                 }
779         }
780         /* No, we could not find any class specific dissector for this request
781          * return FALSE and let USB try any of the standard requests.
782          */
783         if (!dissector) {
784                 return FALSE;
785         }
786
787         col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
788
789         if (check_col(pinfo->cinfo, COL_INFO)) {
790                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
791                 val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
792                         is_request ? "Request" : "Response");
793         }
794
795         if (is_request) {
796                 proto_tree_add_item(tree, hf_usb_hid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
797                 offset += 1;
798         }
799
800         dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
801         return TRUE;
802 }
803
804 void
805 proto_register_usb_hid(void)
806 {
807         static hf_register_info hf[] = {
808                 { &hf_usb_hid_item_bSize,
809                         { "bSize", "usbhid.item.bSize", FT_UINT8, BASE_DEC,
810                                 VALS(usb_hid_item_bSize_vals), USBHID_SIZE_MASK, NULL, HFILL }},
811
812                 { &hf_usb_hid_item_bType,
813                         { "bType", "usbhid.item.bType", FT_UINT8, BASE_DEC,
814                                 VALS(usb_hid_item_bType_vals), USBHID_TYPE_MASK, NULL, HFILL }},
815
816                 { &hf_usb_hid_mainitem_bTag,
817                         { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
818                                 VALS(usb_hid_mainitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
819
820                 { &hf_usb_hid_globalitem_bTag,
821                         { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
822                                 VALS(usb_hid_globalitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
823
824                 { &hf_usb_hid_localitem_bTag,
825                         { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
826                                 VALS(usb_hid_localitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
827
828                 { &hf_usb_hid_longitem_bTag,
829                         { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
830                                 VALS(usb_hid_longitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
831
832                 { &hf_usb_hid_item_bDataSize,
833                         { "bDataSize", "usbhid.item.bDataSize", FT_UINT8, BASE_DEC,
834                                 NULL, 0, NULL, HFILL }},
835
836                 { &hf_usb_hid_item_bLongItemTag,
837                         { "bTag", "usbhid.item.bLongItemTag", FT_UINT8, BASE_HEX,
838                                 NULL, 0, NULL, HFILL }},
839
840                 /* Main-report item data */
841
842                 { &hf_usb_hid_mainitem_bit0,
843                         { "Data/constant", "usbhid.item.main.readonly", FT_BOOLEAN, 9,
844                                 TFS(&tfs_mainitem_bit0), 1<<0, NULL, HFILL }},
845
846                 { &hf_usb_hid_mainitem_bit1,
847                         { "Data type", "usbhid.item.main.variable", FT_BOOLEAN, 9,
848                                 TFS(&tfs_mainitem_bit1), 1<<1, NULL, HFILL }},
849
850                 { &hf_usb_hid_mainitem_bit2,
851                         { "Coordinates", "usbhid.item.main.relative", FT_BOOLEAN, 9,
852                                 TFS(&tfs_mainitem_bit2), 1<<2, NULL, HFILL }},
853
854                 { &hf_usb_hid_mainitem_bit3,
855                         { "Min/max wraparound", "usbhid.item.main.wrap", FT_BOOLEAN, 9,
856                                 TFS(&tfs_mainitem_bit3), 1<<3, NULL, HFILL }},
857
858                 { &hf_usb_hid_mainitem_bit4,
859                         { "Physical relationship to data", "usbhid.item.main.nonlinear", FT_BOOLEAN, 9,
860                                 TFS(&tfs_mainitem_bit4), 1<<4, NULL, HFILL }},
861
862                 { &hf_usb_hid_mainitem_bit5,
863                         { "Preferred state", "usbhid.item.main.no_preferred_state", FT_BOOLEAN, 9,
864                                 TFS(&tfs_mainitem_bit5), 1<<5, NULL, HFILL }},
865
866                 { &hf_usb_hid_mainitem_bit6,
867                         { "Has null position", "usbhid.item.main.nullstate", FT_BOOLEAN, 9,
868                                 TFS(&tfs_mainitem_bit6), 1<<6, NULL, HFILL }},
869
870                 { &hf_usb_hid_mainitem_bit7,
871                         { "(Non)-volatile", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
872                                 TFS(&tfs_mainitem_bit7), 1<<7, NULL, HFILL }},
873
874                 { &hf_usb_hid_mainitem_bit7_input,
875                         { "[Reserved]", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
876                                 NULL, 1<<7, NULL, HFILL }},
877
878                 { &hf_usb_hid_mainitem_bit8,
879                         { "Bits or bytes", "usbhid.item.main.buffered_bytes", FT_BOOLEAN, 9,
880                                 TFS(&tfs_mainitem_bit8), 1<<8, NULL, HFILL }},
881
882                 { &hf_usb_hid_mainitem_colltype,
883                         { "Collection type", "usbhid.item.main.colltype", FT_UINT8, BASE_HEX,
884                                 RVALS(usb_hid_mainitem_colltype_vals), 0, NULL, HFILL }},
885
886                 /* Global-report item data */
887
888                 { &hf_usb_hid_globalitem_usage,
889                         { "Usage page", "usbhid.item.global.usage", FT_UINT8, BASE_HEX,
890                                 RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
891
892                 { &hf_usb_hid_globalitem_log_min,
893                         { "Logical minimum", "usbhid.item.global.log_min", FT_UINT8, BASE_DEC,
894                                 NULL, 0, NULL, HFILL }},
895
896                 { &hf_usb_hid_globalitem_log_max,
897                         { "Logical maximum", "usbhid.item.global.log_max", FT_UINT8, BASE_DEC,
898                                 NULL, 0, NULL, HFILL }},
899
900                 { &hf_usb_hid_globalitem_phy_min,
901                         { "Physical minimum", "usbhid.item.global.phy_min", FT_UINT8, BASE_DEC,
902                                 NULL, 0, NULL, HFILL }},
903
904                 { &hf_usb_hid_globalitem_phy_max,
905                         { "Physical maximum", "usbhid.item.global.phy_max", FT_UINT8, BASE_DEC,
906                                 NULL, 0, NULL, HFILL }},
907
908                 { &hf_usb_hid_globalitem_unit_exp,
909                         { "Unit exponent", "usbhid.item.global.unit_exp", FT_UINT8, BASE_DEC,
910                                 NULL, 0, NULL, HFILL }},
911
912                 { &hf_usb_hid_globalitem_unit_sys,
913                         { "System", "usbhid.item.global.unit.system", FT_UINT32, BASE_HEX,
914                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x0000000F, NULL, HFILL }},
915
916                 { &hf_usb_hid_globalitem_unit_len,
917                         { "Length", "usbhid.item.global.unit.length", FT_UINT32, BASE_HEX,
918                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x000000F0, NULL, HFILL }},
919
920                 { &hf_usb_hid_globalitem_unit_mass,
921                         { "Mass", "usbhid.item.global.unit.mass", FT_UINT32, BASE_HEX,
922                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x00000F00, NULL, HFILL }},
923
924                 { &hf_usb_hid_globalitem_unit_time,
925                         { "Time", "usbhid.item.global.unit.time", FT_UINT32, BASE_HEX,
926                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x0000F000, NULL, HFILL }},
927
928                 { &hf_usb_hid_globalitem_unit_temp,
929                         { "Temperature", "usbhid.item.global.unit.temperature", FT_UINT32, BASE_HEX,
930                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x000F0000, NULL, HFILL }},
931
932                 { &hf_usb_hid_globalitem_unit_current,
933                         { "Current", "usbhid.item.global.unit.current", FT_UINT32, BASE_HEX,
934                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x00F00000, NULL, HFILL }},
935
936                 { &hf_usb_hid_globalitem_unit_brightness,
937                         { "Luminous intensity", "usbhid.item.global.unit.brightness", FT_UINT32, BASE_HEX,
938                                 VALS(usb_hid_globalitem_unit_exp_vals), 0x0F000000, NULL, HFILL }},
939
940                 { &hf_usb_hid_globalitem_report_size,
941                         { "Report size", "usbhid.item.global.report_size", FT_UINT8, BASE_DEC,
942                                 NULL, 0, NULL, HFILL }},
943
944                 { &hf_usb_hid_globalitem_report_id,
945                         { "Report ID", "usbhid.item.global.report_id", FT_UINT8, BASE_HEX,
946                                 NULL, 0, NULL, HFILL }},
947
948                 { &hf_usb_hid_globalitem_report_count,
949                         { "Report count", "usbhid.item.global.report_count", FT_UINT8, BASE_DEC,
950                                 NULL, 0, NULL, HFILL }},
951
952                 { &hf_usb_hid_globalitem_push,
953                         { "Push", "usbhid.item.global.push", FT_UINT8, BASE_HEX,
954                                 NULL, 0, NULL, HFILL }},
955
956                 { &hf_usb_hid_globalitem_pop,
957                         { "Pop", "usbhid.item.global.pop", FT_UINT8, BASE_HEX,
958                                 NULL, 0, NULL, HFILL }},
959
960                 /* Local-report item data */
961
962                 { &hf_usb_hid_localitem_usage,
963                         { "Usage", "usbhid.item.local.usage", FT_UINT8, BASE_HEX,
964                                 RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
965
966                 { &hf_usb_hid_localitem_usage_min,
967                         { "Usage minimum", "usbhid.item.local.usage_min", FT_UINT8, BASE_HEX,
968                                 NULL, 0, NULL, HFILL }},
969
970                 { &hf_usb_hid_localitem_usage_max,
971                         { "Usage maximum", "usbhid.item.local.usage_max", FT_UINT8, BASE_HEX,
972                                 NULL, 0, NULL, HFILL }},
973
974                 { &hf_usb_hid_localitem_desig_index,
975                         { "Designator index", "usbhid.item.local.desig_index", FT_UINT8, BASE_HEX,
976                                 NULL, 0, NULL, HFILL }},
977
978                 { &hf_usb_hid_localitem_desig_min,
979                         { "Designator minimum", "usbhid.item.local.desig_min", FT_UINT8, BASE_HEX,
980                                 NULL, 0, NULL, HFILL }},
981
982                 { &hf_usb_hid_localitem_desig_max,
983                         { "Designator maximum", "usbhid.item.local.desig_max", FT_UINT8, BASE_HEX,
984                                 NULL, 0, NULL, HFILL }},
985
986                 { &hf_usb_hid_localitem_string_index,
987                         { "String index", "usbhid.item.local.string_index", FT_UINT8, BASE_HEX,
988                                 NULL, 0, NULL, HFILL }},
989
990                 { &hf_usb_hid_localitem_string_min,
991                         { "String minimum", "usbhid.item.local.string_min", FT_UINT8, BASE_HEX,
992                                 NULL, 0, NULL, HFILL }},
993
994                 { &hf_usb_hid_localitem_string_max,
995                         { "String maximum", "usbhid.item.local.string_max", FT_UINT8, BASE_HEX,
996                                 NULL, 0, NULL, HFILL }},
997
998                 { &hf_usb_hid_localitem_delimiter,
999                         { "Delimiter", "usbhid.item.local.delimiter", FT_UINT8, BASE_HEX,
1000                                 NULL, 0, NULL, HFILL }},
1001
1002
1003                 { &hf_usb_hid_item_unk_data,
1004                         { "Item data", "usbhid.item.data", FT_BYTES, BASE_NONE,
1005                                 NULL, 0, NULL, HFILL }},
1006
1007                 /* USB HID specific requests */
1008                 { &hf_usb_hid_request,
1009                 { "bRequest", "usbhid.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
1010                   NULL, HFILL }},
1011
1012                 { &hf_usb_hid_value,
1013                 { "wValue", "usbhid.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
1014                   NULL, HFILL }},
1015
1016                 { &hf_usb_hid_index,
1017                 { "wIndex", "usbhid.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
1018                   NULL, HFILL }},
1019
1020                 { &hf_usb_hid_length,
1021                 { "wLength", "usbhid.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1022                   NULL, HFILL }},
1023
1024                 { &hf_usb_hid_report_type,
1025                 { "ReportType", "usbhid.setup.ReportType", FT_UINT8, BASE_DEC,
1026                   VALS(usb_hid_report_type_vals), 0x0,
1027                   NULL, HFILL }},
1028
1029                 { &hf_usb_hid_report_id,
1030                 { "ReportID", "usbhid.setup.ReportID", FT_UINT8, BASE_DEC, NULL, 0x0,
1031                   NULL, HFILL }},
1032
1033                 { &hf_usb_hid_duration,
1034                 { "Duration", "usbhid.setup.Duration", FT_UINT8, BASE_DEC, NULL, 0x0,
1035                   NULL, HFILL }},
1036
1037                 { &hf_usb_hid_zero,
1038                 { "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
1039                   NULL, HFILL }}
1040
1041         };
1042
1043         static gint *usb_hid_subtrees[] = {
1044                 &ett_usb_hid_report,
1045                 &ett_usb_hid_item_header,
1046                 &ett_usb_hid_wValue
1047         };
1048
1049         proto_usb_hid = proto_register_protocol("USB HID", "USBHID", "usbhid");
1050         proto_register_field_array(proto_usb_hid, hf, array_length(hf));
1051         proto_register_subtree_array(usb_hid_subtrees, array_length(usb_hid_subtrees));
1052 }
1053
1054 void
1055 proto_reg_handoff_usb_hid(void) {
1056         dissector_handle_t usb_hid_control_handle;
1057
1058         usb_hid_control_handle = new_create_dissector_handle(dissect_usb_hid_control, proto_usb_hid);
1059         dissector_add_uint("usb.control", IF_CLASS_HID, usb_hid_control_handle);
1060 }