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