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