new_create_dissector_handle -> create_dissector_handle for dissector directory.
[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 #include "packet-btsdp.h"
29
30
31 void proto_register_usb_hid(void);
32 void proto_reg_handoff_usb_hid(void);
33
34 /* protocols and header fields */
35 static int proto_usb_hid = -1;
36 static int hf_usb_hid_item_bSize = -1;
37 static int hf_usb_hid_item_bType = -1;
38 static int hf_usb_hid_mainitem_bTag = -1;
39 static int hf_usb_hid_globalitem_bTag = -1;
40 static int hf_usb_hid_localitem_bTag = -1;
41 static int hf_usb_hid_longitem_bTag = -1;
42 static int hf_usb_hid_item_bDataSize = -1;
43 static int hf_usb_hid_item_bLongItemTag = -1;
44 static int hf_usb_hid_item_unk_data = -1;
45
46 static int hf_usb_hid_mainitem_bit0 = -1;
47 static int hf_usb_hid_mainitem_bit1 = -1;
48 static int hf_usb_hid_mainitem_bit2 = -1;
49 static int hf_usb_hid_mainitem_bit3 = -1;
50 static int hf_usb_hid_mainitem_bit4 = -1;
51 static int hf_usb_hid_mainitem_bit5 = -1;
52 static int hf_usb_hid_mainitem_bit6 = -1;
53 static int hf_usb_hid_mainitem_bit7 = -1;
54 static int hf_usb_hid_mainitem_bit7_input = -1;
55 static int hf_usb_hid_mainitem_bit8 = -1;
56 static int hf_usb_hid_mainitem_colltype = -1;
57
58 static int hf_usb_hid_globalitem_usage = -1;
59 static int hf_usb_hid_globalitem_log_min = -1;
60 static int hf_usb_hid_globalitem_log_max = -1;
61 static int hf_usb_hid_globalitem_phy_min = -1;
62 static int hf_usb_hid_globalitem_phy_max = -1;
63 static int hf_usb_hid_globalitem_unit_exp = -1;
64 static int hf_usb_hid_globalitem_unit_sys = -1;
65 static int hf_usb_hid_globalitem_unit_len = -1;
66 static int hf_usb_hid_globalitem_unit_mass = -1;
67 static int hf_usb_hid_globalitem_unit_time = -1;
68 static int hf_usb_hid_globalitem_unit_temp = -1;
69 static int hf_usb_hid_globalitem_unit_current = -1;
70 static int hf_usb_hid_globalitem_unit_brightness = -1;
71 static int hf_usb_hid_globalitem_report_size = -1;
72 static int hf_usb_hid_globalitem_report_id = -1;
73 static int hf_usb_hid_globalitem_report_count = -1;
74 static int hf_usb_hid_globalitem_push = -1;
75 static int hf_usb_hid_globalitem_pop = -1;
76
77 static int hf_usb_hid_localitem_usage = -1;
78 static int hf_usb_hid_localitem_usage_min = -1;
79 /* static int hf_usb_hid_localitem_usage_max = -1; */
80 static int hf_usb_hid_localitem_desig_index = -1;
81 static int hf_usb_hid_localitem_desig_min = -1;
82 static int hf_usb_hid_localitem_desig_max = -1;
83 static int hf_usb_hid_localitem_string_index = -1;
84 static int hf_usb_hid_localitem_string_min = -1;
85 static int hf_usb_hid_localitem_string_max = -1;
86 static int hf_usb_hid_localitem_delimiter = -1;
87
88 static gint ett_usb_hid_report = -1;
89 static gint ett_usb_hid_item_header = -1;
90 static gint ett_usb_hid_wValue = -1;
91 static gint ett_usb_hid_descriptor = -1;
92
93 static int hf_usb_hid_request = -1;
94 static int hf_usb_hid_value = -1;
95 static int hf_usb_hid_index = -1;
96 static int hf_usb_hid_length = -1;
97 static int hf_usb_hid_report_type = -1;
98 static int hf_usb_hid_report_id = -1;
99 static int hf_usb_hid_duration = -1;
100 static int hf_usb_hid_zero = -1;
101
102 static int hf_usb_hid_bcdHID = -1;
103 static int hf_usb_hid_bCountryCode = -1;
104 static int hf_usb_hid_bNumDescriptors = -1;
105 static int hf_usb_hid_bDescriptorIndex = -1;
106 static int hf_usb_hid_bDescriptorType = -1;
107 static int hf_usb_hid_wInterfaceNumber = -1;
108 static int hf_usb_hid_wDescriptorLength = -1;
109
110 static int hf_usbhid_boot_report_keyboard_modifier_right_gui = -1;
111 static int hf_usbhid_boot_report_keyboard_modifier_right_alt = -1;
112 static int hf_usbhid_boot_report_keyboard_modifier_right_shift = -1;
113 static int hf_usbhid_boot_report_keyboard_modifier_right_ctrl = -1;
114 static int hf_usbhid_boot_report_keyboard_modifier_left_gui = -1;
115 static int hf_usbhid_boot_report_keyboard_modifier_left_alt = -1;
116 static int hf_usbhid_boot_report_keyboard_modifier_left_shift = -1;
117 static int hf_usbhid_boot_report_keyboard_modifier_left_ctrl = -1;
118 static int hf_usbhid_boot_report_keyboard_reserved = -1;
119 static int hf_usbhid_boot_report_keyboard_keycode_1 = -1;
120 static int hf_usbhid_boot_report_keyboard_keycode_2 = -1;
121 static int hf_usbhid_boot_report_keyboard_keycode_3 = -1;
122 static int hf_usbhid_boot_report_keyboard_keycode_4 = -1;
123 static int hf_usbhid_boot_report_keyboard_keycode_5 = -1;
124 static int hf_usbhid_boot_report_keyboard_keycode_6 = -1;
125 static int hf_usbhid_boot_report_keyboard_leds_constants = -1;
126 static int hf_usbhid_boot_report_keyboard_leds_kana = -1;
127 static int hf_usbhid_boot_report_keyboard_leds_compose = -1;
128 static int hf_usbhid_boot_report_keyboard_leds_scroll_lock = -1;
129 static int hf_usbhid_boot_report_keyboard_leds_caps_lock = -1;
130 static int hf_usbhid_boot_report_keyboard_leds_num_lock = -1;
131 static int hf_usbhid_boot_report_mouse_button_8 = -1;
132 static int hf_usbhid_boot_report_mouse_button_7 = -1;
133 static int hf_usbhid_boot_report_mouse_button_6 = -1;
134 static int hf_usbhid_boot_report_mouse_button_5 = -1;
135 static int hf_usbhid_boot_report_mouse_button_4 = -1;
136 static int hf_usbhid_boot_report_mouse_button_middle = -1;
137 static int hf_usbhid_boot_report_mouse_button_right = -1;
138 static int hf_usbhid_boot_report_mouse_button_left = -1;
139 static int hf_usbhid_boot_report_mouse_x_displacement = -1;
140 static int hf_usbhid_boot_report_mouse_y_displacement = -1;
141 static int hf_usbhid_boot_report_mouse_horizontal_scroll_wheel = -1;
142 static int hf_usbhid_boot_report_mouse_vertical_scroll_wheel = -1;
143 static int hf_usbhid_data = -1;
144
145 static const true_false_string tfs_mainitem_bit0 = {"Constant", "Data"};
146 static const true_false_string tfs_mainitem_bit1 = {"Variable", "Array"};
147 static const true_false_string tfs_mainitem_bit2 = {"Relative", "Absolute"};
148 static const true_false_string tfs_mainitem_bit3 = {"Wrap", "No Wrap"};
149 static const true_false_string tfs_mainitem_bit4 = {"Non Linear", "Linear"};
150 static const true_false_string tfs_mainitem_bit5 = {"No Preferred", "Preferred State"};
151 static const true_false_string tfs_mainitem_bit6 = {"Null state", "No Null position"};
152 static const true_false_string tfs_mainitem_bit7 = {"Volatile", "Non Volatile"};
153 static const true_false_string tfs_mainitem_bit8 = {"Buffered Bytes", "Bit Field"};
154
155
156 struct usb_hid_global_state {
157     unsigned int usage_page;
158 };
159
160
161 /* HID class specific descriptor types */
162 #define USB_DT_HID        0x21
163 #define USB_DT_HID_REPORT 0x22
164 static const value_string hid_descriptor_type_vals[] = {
165     {USB_DT_HID, "HID"},
166     {USB_DT_HID_REPORT, "HID Report"},
167     {0,NULL}
168 };
169 static value_string_ext hid_descriptor_type_vals_ext =
170                VALUE_STRING_EXT_INIT(hid_descriptor_type_vals);
171
172
173 #define USBHID_SIZE_MASK  0x03
174 #define USBHID_TYPE_MASK  0x0C
175 #define USBHID_TAG_MASK   0xF0
176
177 static const value_string usb_hid_item_bSize_vals[] = {
178     {0, "0 bytes"},
179     {1, "1 byte"},
180     {2, "2 bytes"},
181     {3, "4 bytes"},
182     {0, NULL}
183 };
184
185 #define USBHID_ITEMTYPE_MAIN    0
186 #define USBHID_ITEMTYPE_GLOBAL  1
187 #define USBHID_ITEMTYPE_LOCAL   2
188 #define USBHID_ITEMTYPE_LONG    3
189 static const value_string usb_hid_item_bType_vals[] = {
190     {USBHID_ITEMTYPE_MAIN,   "Main"},
191     {USBHID_ITEMTYPE_GLOBAL, "Global"},
192     {USBHID_ITEMTYPE_LOCAL,  "Local"},
193     {USBHID_ITEMTYPE_LONG,   "Long item"},
194     {0, NULL}
195 };
196
197 #define USBHID_MAINITEM_TAG_INPUT           8
198 #define USBHID_MAINITEM_TAG_OUTPUT          9
199 #define USBHID_MAINITEM_TAG_FEATURE        11
200 #define USBHID_MAINITEM_TAG_COLLECTION     10
201 #define USBHID_MAINITEM_TAG_ENDCOLLECTION  12
202 static const value_string usb_hid_mainitem_bTag_vals[] = {
203     {USBHID_MAINITEM_TAG_INPUT,         "Input"},
204     {USBHID_MAINITEM_TAG_OUTPUT,        "Output"},
205     {USBHID_MAINITEM_TAG_FEATURE,       "Feature"},
206     {USBHID_MAINITEM_TAG_COLLECTION,    "Collection"},
207     {USBHID_MAINITEM_TAG_ENDCOLLECTION, "End collection"},
208     {0, NULL}
209 };
210 #define USBHID_GLOBALITEM_TAG_USAGE_PAGE    0
211 #define USBHID_GLOBALITEM_TAG_LOG_MIN       1
212 #define USBHID_GLOBALITEM_TAG_LOG_MAX       2
213 #define USBHID_GLOBALITEM_TAG_PHY_MIN       3
214 #define USBHID_GLOBALITEM_TAG_PHY_MAX       4
215 #define USBHID_GLOBALITEM_TAG_UNIT_EXP      5
216 #define USBHID_GLOBALITEM_TAG_UNIT          6
217 #define USBHID_GLOBALITEM_TAG_REPORT_SIZE   7
218 #define USBHID_GLOBALITEM_TAG_REPORT_ID     8
219 #define USBHID_GLOBALITEM_TAG_REPORT_COUNT  9
220 #define USBHID_GLOBALITEM_TAG_PUSH         10
221 #define USBHID_GLOBALITEM_TAG_POP          11
222 static const value_string usb_hid_globalitem_bTag_vals[] = {
223     {USBHID_GLOBALITEM_TAG_USAGE_PAGE,   "Usage"},
224     {USBHID_GLOBALITEM_TAG_LOG_MIN,      "Logical minimum"},
225     {USBHID_GLOBALITEM_TAG_LOG_MAX,      "Logical maximum"},
226     {USBHID_GLOBALITEM_TAG_PHY_MIN,      "Physical minimum"},
227     {USBHID_GLOBALITEM_TAG_PHY_MAX,      "Physical maximum"},
228     {USBHID_GLOBALITEM_TAG_UNIT_EXP,     "Unit exponent"},
229     {USBHID_GLOBALITEM_TAG_UNIT,         "Units"},
230     {USBHID_GLOBALITEM_TAG_REPORT_SIZE,  "Report size"},
231     {USBHID_GLOBALITEM_TAG_REPORT_ID,    "Report ID"},
232     {USBHID_GLOBALITEM_TAG_REPORT_COUNT, "Report count"},
233     {USBHID_GLOBALITEM_TAG_PUSH,         "Push"},
234     {USBHID_GLOBALITEM_TAG_POP,          "Pop"},
235     {12, "[Reserved]"},
236     {13, "[Reserved]"},
237     {14, "[Reserved]"},
238     {15, "[Reserved]"},
239     {0, NULL}
240 };
241 #define USBHID_LOCALITEM_TAG_USAGE_PAGE     0
242 #define USBHID_LOCALITEM_TAG_USAGE_MIN      1
243 #define USBHID_LOCALITEM_TAG_USAGE_MAX      2
244 #define USBHID_LOCALITEM_TAG_DESIG_INDEX    3
245 #define USBHID_LOCALITEM_TAG_DESIG_MIN      4
246 #define USBHID_LOCALITEM_TAG_DESIG_MAX      5
247 /* No 6 in spec */
248 #define USBHID_LOCALITEM_TAG_STRING_INDEX   7
249 #define USBHID_LOCALITEM_TAG_STRING_MIN     8
250 #define USBHID_LOCALITEM_TAG_STRING_MAX     9
251 #define USBHID_LOCALITEM_TAG_DELIMITER     10 /* Also listed as reserved in spec! */
252 static const value_string usb_hid_localitem_bTag_vals[] = {
253     {USBHID_LOCALITEM_TAG_USAGE_PAGE,   "Usage"},
254     {USBHID_LOCALITEM_TAG_USAGE_MIN,    "Usage minimum"},
255     {USBHID_LOCALITEM_TAG_USAGE_MAX,    "Usage maximum"},
256     {USBHID_LOCALITEM_TAG_DESIG_INDEX,  "Designator index"},
257     {USBHID_LOCALITEM_TAG_DESIG_MIN,    "Designator minimum"},
258     {USBHID_LOCALITEM_TAG_DESIG_MAX,    "Designator maximum"},
259     {USBHID_LOCALITEM_TAG_STRING_INDEX, "String index"},
260     {USBHID_LOCALITEM_TAG_STRING_MIN,   "String minimum"},
261     {USBHID_LOCALITEM_TAG_STRING_MAX,   "String maximum"},
262     {USBHID_LOCALITEM_TAG_DELIMITER,    "Delimiter"},
263     {11, "[Reserved]"},
264     {12, "[Reserved]"},
265     {13, "[Reserved]"},
266     {14, "[Reserved]"},
267     {15, "[Reserved]"},
268     {0, NULL}
269 };
270 static const value_string usb_hid_longitem_bTag_vals[] = {
271     {15, "Long item"},
272     {0, NULL}
273 };
274
275 static const range_string usb_hid_mainitem_colltype_vals[] = {
276     {0x00, 0x00, "Physical"},
277     {0x01, 0x01, "Application"},
278     {0x02, 0x02, "Logical"},
279     {0x03, 0x03, "Report"},
280     {0x04, 0x04, "Named array"},
281     {0x05, 0x05, "Usage switch"},
282     {0x06, 0x06, "Usage modifier"},
283     {0x07, 0x7F, "[Reserved]"},
284     {0x80, 0xFF, "[Vendor-defined]"},
285     {0, 0, NULL}
286 };
287
288 static const value_string usb_hid_globalitem_unit_exp_vals[] = {
289     {0x0, "n^0"},
290     {0x1, "n^1"},
291     {0x2, "n^2"},
292     {0x3, "n^3"},
293     {0x4, "n^4"},
294     {0x5, "n^5"},
295     {0x6, "n^6"},
296     {0x7, "n^7"},
297     {0x8, "n^-8"},
298     {0x9, "n^-7"},
299     {0xA, "n^-6"},
300     {0xB, "n^-5"},
301     {0xC, "n^-4"},
302     {0xD, "n^-3"},
303     {0xE, "n^-2"},
304     {0xF, "n^-1"},
305     {0, NULL}
306 };
307 static const range_string usb_hid_item_usage_vals[] = {
308     {0x00, 0x00, "Undefined"},
309     {0x01, 0x01, "Generic desktop controls"},
310     {0x02, 0x02, "Simulation controls"},
311     {0x03, 0x03, "VR controls"},
312     {0x04, 0x04, "Sport controls"},
313     {0x05, 0x05, "Game controls"},
314     {0x06, 0x06, "Generic device controls"},
315     {0x07, 0x07, "Keyboard/keypad"},
316     {0x08, 0x08, "LEDs"},
317     {0x09, 0x09, "Button"},
318     {0x0A, 0x0A, "Ordinal"},
319     {0x0B, 0x0B, "Telephony"},
320     {0x0C, 0x0C, "Consumer"},
321     {0x0D, 0x0D, "Digitizer"},
322     {0x0E, 0x0E, "[Reserved]"},
323     {0x0F, 0x0F, "Physical Interface Device (PID) page"},
324     {0x10, 0x10, "Unicode"},
325     {0x11, 0x13, "[Reserved]"},
326     {0x14, 0x14, "Alphanumeric display"},
327     {0x15, 0x3F, "[Reserved]"},
328     {0x40, 0x40, "Medical instruments"},
329     {0x41, 0x7F, "[Reserved]"},
330     {0x80, 0x83, "Monitor page"},
331     {0x84, 0x87, "Power page"},
332     {0x88, 0x8B, "[Reserved]"},
333     {0x8C, 0x8C, "Bar code scanner page"},
334     {0x8D, 0x8D, "Scale page"},
335     {0x8E, 0x8E, "Magnetic Stripe Reading (MSR) devices"},
336     {0x8F, 0x8F, "[Reserved Point of Sale page]"},
337     {0x90, 0x90, "Camera control page"},
338     {0x91, 0x91, "Arcade page"},
339     {0x92, 0xFEFF, "[Reserved]"},
340     {0xFF00, 0xFFFF, "[Vendor-defined]"},
341     {0, 0, NULL}
342 };
343
344 static const value_string keycode_vals[] = {
345     { 0x00,   "<ACTION KEY UP>" },
346     { 0x01,   "ErrorRollOver" },
347     { 0x02,   "POSTFail" },
348     { 0x03,   "ErrorUndefined" },
349
350     { 0x04,   "a" },
351     { 0x05,   "b" },
352     { 0x06,   "c" },
353     { 0x07,   "d" },
354     { 0x08,   "e" },
355     { 0x09,   "f" },
356     { 0x0A,   "g" },
357     { 0x0B,   "h" },
358     { 0x0C,   "i" },
359     { 0x0D,   "j" },
360     { 0x0E,   "k" },
361     { 0x0F,   "l" },
362     { 0x10,   "m" },
363     { 0x11,   "n" },
364     { 0x12,   "o" },
365     { 0x13,   "p" },
366     { 0x14,   "q" },
367     { 0x15,   "r" },
368     { 0x16,   "s" },
369     { 0x17,   "t" },
370     { 0x18,   "u" },
371     { 0x19,   "v" },
372     { 0x1A,   "w" },
373     { 0x1B,   "x" },
374     { 0x1C,   "y" },
375     { 0x1D,   "z" },
376
377     { 0x1E,   "1" },
378     { 0x1F,   "2" },
379     { 0x20,   "3" },
380     { 0x21,   "4" },
381     { 0x22,   "5" },
382     { 0x23,   "6" },
383     { 0x24,   "7" },
384     { 0x25,   "8" },
385     { 0x26,   "9" },
386     { 0x27,   "0" },
387
388     { 0x28,   "ENTER" },
389     { 0x29,   "Escape" },
390     { 0x2A,   "Backspace" },
391     { 0x2B,   "Tab" },
392     { 0x2C,   "Spacebar" },
393
394     { 0x2D,   "-" },
395     { 0x2E,   "=" },
396     { 0x2F,   "[" },
397     { 0x30,   "]" },
398     { 0x31,   "\\" },
399     { 0x32,   "NonUS #/~" },
400     { 0x33,   ";" },
401     { 0x34,   "'" },
402     { 0x35,   "`" },
403     { 0x36,   "," },
404     { 0x37,   "." },
405     { 0x38,   "/" },
406     { 0x39,   "CapsLock" },
407     { 0x3A,   "F1" },
408     { 0x3B,   "F2" },
409     { 0x3C,   "F3" },
410     { 0x3D,   "F4" },
411     { 0x3E,   "F5" },
412     { 0x3F,   "F6" },
413     { 0x40,   "F7" },
414     { 0x41,   "F8" },
415     { 0x42,   "F9" },
416     { 0x43,   "F10" },
417     { 0x44,   "F11" },
418     { 0x45,   "F12" },
419     { 0x46,   "PrintScreen" },
420     { 0x47,   "ScrollLock" },
421     { 0x48,   "Pause" },
422     { 0x49,   "Insert" },
423     { 0x4A,   "Home" },
424     { 0x4B,   "PageUp" },
425     { 0x4C,   "DeleteForward" },
426     { 0x4D,   "End" },
427     { 0x4E,   "PageDown" },
428     { 0x4F,   "RightArrow" },
429     { 0x50,   "LeftArrow" },
430     { 0x51,   "DownArrow" },
431     { 0x52,   "UpArrow" },
432     { 0x53,   "NumLock" },
433
434     /* Keypad */
435     { 0x54,   "Keypad /" },
436     { 0x55,   "Keypad *" },
437     { 0x56,   "Keypad -" },
438     { 0x57,   "Keypad +" },
439     { 0x58,   "Keypad ENTER" },
440     { 0x59,   "Keypad 1" },
441     { 0x5A,   "Keypad 2" },
442     { 0x5B,   "Keypad 3" },
443     { 0x5C,   "Keypad 4" },
444     { 0x5D,   "Keypad 5" },
445     { 0x5E,   "Keypad 6" },
446     { 0x5F,   "Keypad 7" },
447     { 0x60,   "Keypad 8" },
448     { 0x61,   "Keypad 9" },
449     { 0x62,   "Keypad 0" },
450     { 0x63,   "Keypad ." },
451
452     /* non PC AT */
453     { 0x64,   "NonUS \\/|" },
454     { 0x65,   "Application" },
455     { 0x66,   "Power" },
456     { 0x67,   "Keypad =" },
457     { 0x68,   "F13" },
458     { 0x69,   "F14" },
459     { 0x6A,   "F15" },
460     { 0x6B,   "F16" },
461     { 0x6C,   "F17" },
462     { 0x6D,   "F18" },
463     { 0x6E,   "F19" },
464     { 0x6F,   "F20" },
465
466     { 0x70,   "F21" },
467     { 0x71,   "F22" },
468     { 0x72,   "F23" },
469     { 0x73,   "F24" },
470     { 0x74,   "Execute" },
471     { 0x75,   "Help" },
472     { 0x76,   "Menu" },
473     { 0x77,   "Select" },
474     { 0x78,   "Stop" },
475     { 0x79,   "Again" },
476     { 0x7A,   "Undo" },
477     { 0x7B,   "Cut" },
478     { 0x7C,   "Copy" },
479     { 0x7D,   "Paste" },
480     { 0x7E,   "Find" },
481     { 0x7F,   "Mute" },
482
483     { 0x80,   "VolumeUp" },
484     { 0x81,   "VolumeDown" },
485     { 0x82,   "Locking CapsLock" },
486     { 0x83,   "Locking NumLock" },
487     { 0x84,   "Locking ScrollLock" },
488     { 0x85,   "Keypad Comma" },
489     { 0x86,   "Keypad EqualSign" },
490     { 0x87,   "International1" },
491     { 0x88,   "International2" },
492     { 0x89,   "International3" },
493     { 0x8A,   "International4" },
494     { 0x8B,   "International5" },
495     { 0x8C,   "International6" },
496     { 0x8D,   "International7" },
497     { 0x8E,   "International8" },
498     { 0x8F,   "International9" },
499
500     { 0x90,   "LANG1" },
501     { 0x91,   "LANG2" },
502     { 0x92,   "LANG3" },
503     { 0x93,   "LANG4" },
504     { 0x94,   "LANG5" },
505     { 0x95,   "LANG6" },
506     { 0x96,   "LANG7" },
507     { 0x97,   "LANG8" },
508     { 0x98,   "LANG9" },
509     { 0x99,   "AlternateErase" },
510     { 0x9A,   "SysReq/Attention" },
511     { 0x9B,   "Cancel" },
512     { 0x9C,   "Clear" },
513     { 0x9D,   "Prior" },
514     { 0x9E,   "Return" },
515     { 0x9F,   "Separator" },
516
517     { 0xA0,   "Out" },
518     { 0xA1,   "Oper" },
519     { 0xA2,   "Clear/Again" },
520     { 0xA3,   "CrSel/Props" },
521     { 0xA4,   "ExSel" },
522     /* 0xA5..0xAF - reserved */
523     { 0xB0,   "Keypad 00" },
524     { 0xB1,   "Keypad 000" },
525     { 0xB2,   "ThousandsSeparator" },
526     { 0xB3,   "DecimalSeparator" },
527     { 0xB4,   "CurrencyUnit" },
528     { 0xB5,   "CurrencySubunit" },
529     { 0xB6,   "Keypad (" },
530     { 0xB7,   "Keypad )" },
531     { 0xB8,   "Keypad {" },
532     { 0xB9,   "Keypad }" },
533     { 0xBA,   "Keypad Tab" },
534     { 0xBB,   "Keypad Backspace" },
535     { 0xBC,   "Keypad A" },
536     { 0xBD,   "Keypad B" },
537     { 0xBE,   "Keypad C" },
538     { 0xBF,   "Keypad D" },
539
540     { 0xC0,   "Keypad E" },
541     { 0xC1,   "Keypad F" },
542     { 0xC2,   "Keypad XOR" },
543     { 0xC3,   "Keypad ^" },
544     { 0xC4,   "Keypad %" },
545     { 0xC5,   "Keypad <" },
546     { 0xC6,   "Keypad >" },
547     { 0xC7,   "Keypad &" },
548     { 0xC8,   "Keypad &&" },
549     { 0xC9,   "Keypad |" },
550     { 0xCA,   "Keypad ||" },
551     { 0xCB,   "Keypad :" },
552     { 0xCC,   "Keypad #" },
553     { 0xCD,   "Keypad Space" },
554     { 0xCE,   "Keypad @" },
555     { 0xCF,   "Keypad !" },
556
557     { 0xD0,   "Keypad Memory Store" },
558     { 0xD1,   "Keypad Memory Recall" },
559     { 0xD2,   "Keypad Memory Clear" },
560     { 0xD3,   "Keypad Memory Add" },
561     { 0xD4,   "Keypad Memory Subtract" },
562     { 0xD5,   "Keypad Memory Multiply" },
563     { 0xD6,   "Keypad Memory Divide" },
564     { 0xD7,   "Keypad +/-" },
565     { 0xD8,   "Keypad Clear" },
566     { 0xD9,   "Keypad Clear Entry" },
567     { 0xDA,   "Keypad Binary" },
568     { 0xDB,   "Keypad Octal" },
569     { 0xDC,   "Keypad Decimal" },
570     { 0xDD,   "Keypad Hexadecimal" },
571     /* 0xDE..0xDF - reserved,  */
572     { 0xE0,   "LeftControl" },
573     { 0xE1,   "LeftShift" },
574     { 0xE2,   "LeftAlt" },
575     { 0xE3,   "LeftGUI" },
576     { 0xE4,   "RightControl" },
577     { 0xE5,   "RightShift" },
578     { 0xE6,   "RightAlt" },
579     { 0xE7,   "RightGUI" },
580
581     { 0, NULL }
582 };
583 value_string_ext keycode_vals_ext = VALUE_STRING_EXT_INIT(keycode_vals);
584
585 /* Dissector for the data in a HID main report. */
586 static int
587 dissect_usb_hid_report_mainitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag)
588 {
589     switch (bTag) {
590         case USBHID_MAINITEM_TAG_INPUT:
591         case USBHID_MAINITEM_TAG_OUTPUT:
592         case USBHID_MAINITEM_TAG_FEATURE:
593             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit0, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
594             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit1, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
595             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit2, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
596             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit3, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
597             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit4, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
598             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit5, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
599             proto_tree_add_item(tree, hf_usb_hid_mainitem_bit6, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
600             if (bTag == USBHID_MAINITEM_TAG_INPUT) {
601                 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7_input, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
602             } else {
603                 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
604             }
605             if (bSize > 1) {
606                 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit8, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
607             } else {
608                 proto_tree_add_boolean_format_value(tree, hf_usb_hid_mainitem_bit8, tvb, offset, 0, FALSE, "Buffered bytes (default, no second byte present)");
609             }
610             break;
611         case USBHID_MAINITEM_TAG_COLLECTION:
612             proto_tree_add_item(tree, hf_usb_hid_mainitem_colltype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
613             break;
614         case USBHID_MAINITEM_TAG_ENDCOLLECTION:
615             /* No item data */
616             break;
617         default:
618             proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
619             break;
620     }
621     offset += bSize;
622     return offset;
623 }
624
625 /* Dissector for the data in a HID main report. */
626 static int
627 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)
628 {
629     switch (bTag) {
630         case USBHID_GLOBALITEM_TAG_USAGE_PAGE:
631             switch (bSize) {
632                 case 1: global->usage_page = tvb_get_guint8(tvb, offset); break;
633                 case 2: global->usage_page = tvb_get_letohs(tvb, offset); break;
634                 case 3: global->usage_page = tvb_get_letoh24(tvb, offset); break;
635                 case 4: global->usage_page = tvb_get_letohl(tvb, offset); break;
636                 default: global->usage_page = 0; break;
637             }
638             proto_tree_add_item(tree, hf_usb_hid_globalitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
639             break;
640         case USBHID_GLOBALITEM_TAG_LOG_MIN:
641             proto_tree_add_item(tree, hf_usb_hid_globalitem_log_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
642             break;
643         case USBHID_GLOBALITEM_TAG_LOG_MAX:
644             proto_tree_add_item(tree, hf_usb_hid_globalitem_log_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
645             break;
646         case USBHID_GLOBALITEM_TAG_PHY_MIN:
647             proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
648             break;
649         case USBHID_GLOBALITEM_TAG_PHY_MAX:
650             proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
651             break;
652         case USBHID_GLOBALITEM_TAG_UNIT_EXP:
653             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_exp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
654             break;
655         case USBHID_GLOBALITEM_TAG_UNIT:
656             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_sys, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
657             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_len, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
658             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_mass, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
659             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_time, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
660             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_temp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
661             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_current, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
662             proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_brightness, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
663             break;
664         case USBHID_GLOBALITEM_TAG_REPORT_SIZE:
665             proto_tree_add_item(tree, hf_usb_hid_globalitem_report_size, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
666             break;
667         case USBHID_GLOBALITEM_TAG_REPORT_ID:
668             proto_tree_add_item(tree, hf_usb_hid_globalitem_report_id, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
669             break;
670         case USBHID_GLOBALITEM_TAG_REPORT_COUNT:
671             proto_tree_add_item(tree, hf_usb_hid_globalitem_report_count, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
672             break;
673         case USBHID_GLOBALITEM_TAG_PUSH:
674             proto_tree_add_item(tree, hf_usb_hid_globalitem_push, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
675             break;
676         case USBHID_GLOBALITEM_TAG_POP:
677             proto_tree_add_item(tree, hf_usb_hid_globalitem_pop, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
678             break;
679         default:
680             proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
681             break;
682     }
683     offset += bSize;
684     return offset;
685 }
686
687 /* Dissector for the data in a HID main report. */
688 static int
689 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)
690 {
691     unsigned int usage_page = 0xffffffff; /* in case bSize == 0 */
692
693     switch (bTag) {
694         case USBHID_LOCALITEM_TAG_USAGE_PAGE:
695             if (bSize > 2) {
696                 /* Full page ID */
697                 proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
698             } else {
699                 /* Only lower few bits given, need to combine with last global ID */
700                 if (bSize == 1)
701                     usage_page = (global->usage_page & 0xFFFFFF00) | tvb_get_guint8(tvb, offset);
702                 else if (bSize == 2)
703                     usage_page = (global->usage_page & 0xFFFF0000) | tvb_get_ntohs(tvb, offset);
704                 proto_tree_add_uint(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, usage_page);
705             }
706             break;
707         case USBHID_LOCALITEM_TAG_USAGE_MIN:
708             proto_tree_add_item(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
709             break;
710         case USBHID_LOCALITEM_TAG_USAGE_MAX:
711             proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
712             break;
713         case USBHID_LOCALITEM_TAG_DESIG_INDEX:
714             proto_tree_add_item(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
715             break;
716         case USBHID_LOCALITEM_TAG_DESIG_MIN:
717             proto_tree_add_item(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
718             break;
719         case USBHID_LOCALITEM_TAG_DESIG_MAX:
720             proto_tree_add_item(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
721             break;
722         case USBHID_LOCALITEM_TAG_STRING_INDEX:
723             proto_tree_add_item(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
724             break;
725         case USBHID_LOCALITEM_TAG_STRING_MIN:
726             proto_tree_add_item(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
727             break;
728         case USBHID_LOCALITEM_TAG_STRING_MAX:
729             proto_tree_add_item(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
730             break;
731         case USBHID_LOCALITEM_TAG_DELIMITER:
732             proto_tree_add_item(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
733             break;
734         default:
735             proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
736             break;
737     }
738     offset += bSize;
739     return offset;
740 }
741
742 /* Dissector for individual HID report items.  Recursive. */
743 static int
744 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)
745 {
746     proto_item *subitem;
747     proto_tree *tree, *subtree;
748     int old_offset;
749     unsigned int tmp;
750     unsigned int bSize, bType, bTag;
751     const value_string *usb_hid_cur_bTag_vals;
752     int hf_usb_hid_curitem_bTag;
753     struct usb_hid_global_state cur_global;
754     memcpy(&cur_global, global, sizeof(struct usb_hid_global_state));
755
756     while (tvb_reported_length_remaining(tvb, offset) > 0)
757     {
758         old_offset=offset;
759
760         tmp = tvb_get_guint8(tvb, offset);
761         bSize = tmp & USBHID_SIZE_MASK;
762         if (bSize == 3) bSize++; /* 3 == four bytes */
763         bType = (tmp & USBHID_TYPE_MASK) >> 2;
764         bTag = (tmp & USBHID_TAG_MASK) >> 4;
765
766         switch (bType) {
767             case USBHID_ITEMTYPE_MAIN:
768                 hf_usb_hid_curitem_bTag = hf_usb_hid_mainitem_bTag;
769                 usb_hid_cur_bTag_vals = usb_hid_mainitem_bTag_vals;
770                 break;
771             case USBHID_ITEMTYPE_GLOBAL:
772                 hf_usb_hid_curitem_bTag = hf_usb_hid_globalitem_bTag;
773                 usb_hid_cur_bTag_vals = usb_hid_globalitem_bTag_vals;
774                 break;
775             case USBHID_ITEMTYPE_LOCAL:
776                 hf_usb_hid_curitem_bTag = hf_usb_hid_localitem_bTag;
777                 usb_hid_cur_bTag_vals = usb_hid_localitem_bTag_vals;
778                 break;
779             default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
780                 hf_usb_hid_curitem_bTag = hf_usb_hid_longitem_bTag;
781                 usb_hid_cur_bTag_vals = usb_hid_longitem_bTag_vals;
782                 break;
783         }
784
785         subtree = proto_tree_add_subtree_format(parent_tree, tvb, offset, bSize + 1,
786             ett_usb_hid_item_header, &subitem, "%s item (%s)",
787             val_to_str(bType, usb_hid_item_bType_vals, "Unknown/%u"),
788             val_to_str(bTag, usb_hid_cur_bTag_vals, "Unknown/%u tag")
789         );
790
791         tree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_usb_hid_item_header, NULL, "Header");
792         proto_tree_add_item(tree, hf_usb_hid_item_bSize, tvb, offset,   1, ENC_LITTLE_ENDIAN);
793         proto_tree_add_item(tree, hf_usb_hid_item_bType, tvb, offset,   1, ENC_LITTLE_ENDIAN);
794         proto_tree_add_item(tree, hf_usb_hid_curitem_bTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
795         offset++;
796         if ((bType == 3) && (bTag == 16)) {
797             /* Long item */
798             bSize = tvb_get_guint8(tvb, offset);
799             proto_tree_add_item(subtree, hf_usb_hid_item_bDataSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
800             offset++;
801             proto_tree_add_item(subtree, hf_usb_hid_item_bLongItemTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
802             offset++;
803             proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
804             offset += bSize;
805         } else {
806             /* Short item */
807             switch (bType) {
808                 case USBHID_ITEMTYPE_MAIN:
809                     offset = dissect_usb_hid_report_mainitem_data(pinfo, subtree, tvb, offset, bSize, bTag);
810                     break;
811                 case USBHID_ITEMTYPE_GLOBAL:
812                     offset = dissect_usb_hid_report_globalitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
813                     break;
814                 case USBHID_ITEMTYPE_LOCAL:
815                     offset = dissect_usb_hid_report_localitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
816                     break;
817                 default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
818                     proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
819                     offset += bSize;
820                     break;
821             }
822         }
823
824         if (bType == USBHID_ITEMTYPE_MAIN) {
825             if (bTag == USBHID_MAINITEM_TAG_COLLECTION) {
826                 /* Begin collection, nest following elements under us */
827                 offset = dissect_usb_hid_report_item(pinfo, subtree, tvb, offset, usb_conv_info, &cur_global);
828                 proto_item_set_len(subitem, offset-old_offset);
829             } else if (bTag == USBHID_MAINITEM_TAG_ENDCOLLECTION) {
830                 /* End collection, break out to parent tree item */
831                 break;
832             }
833         }
834     }
835     return offset;
836 }
837
838 /* Dissector for HID "GET DESCRIPTOR" subtype. */
839 int
840 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)
841 {
842     proto_item *item;
843     proto_tree *tree;
844     int old_offset=offset;
845     struct usb_hid_global_state initial_global;
846
847     memset(&initial_global, 0, sizeof(struct usb_hid_global_state));
848
849     item = proto_tree_add_protocol_format(parent_tree, proto_usb_hid, tvb, offset,
850                                           -1, "HID Report");
851     tree = proto_item_add_subtree(item, ett_usb_hid_report);
852     offset = dissect_usb_hid_report_item(pinfo, tree, tvb, offset, usb_conv_info, &initial_global);
853
854     proto_item_set_len(item, offset-old_offset);
855
856     return offset;
857 }
858
859 /* Dissector for HID GET_REPORT request. See USBHID 1.11, Chapter 7.2.1 Get_Report Request */
860 static void
861 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_)
862 {
863     proto_item *item;
864     proto_tree *subtree;
865
866     if (!is_request)
867         return;
868
869     item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
870     subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
871
872     /* Report Type in the high byte, Report ID in the low byte */
873     proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
874     offset++;
875     proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
876     offset++;
877
878     proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
879     offset += 2;
880
881     proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
882     /*offset += 2;*/
883 }
884
885 /* Dissector for HID SET_REPORT request. See USBHID 1.11, Chapter 7.2.2 Set_Report Request */
886 static void
887 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_)
888 {
889     proto_item *item;
890     proto_tree *subtree;
891
892     if (!is_request)
893         return;
894
895     item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
896     subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
897
898     proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
899     offset++;
900     proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
901     offset++;
902
903     proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
904     offset += 2;
905
906     proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
907     /*offset += 2;*/
908 }
909
910
911 /* Dissector for HID GET_IDLE request. See USBHID 1.11, Chapter 7.2.3 Get_Idle Request */
912 static void
913 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_)
914 {
915     proto_item *item;
916     proto_tree *subtree;
917
918     if (!is_request)
919         return;
920
921     item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
922     subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
923
924     proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
925     offset++;
926     proto_tree_add_item(subtree, hf_usb_hid_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
927     offset++;
928
929     proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
930     offset += 2;
931
932     proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
933     /*offset += 2;*/
934 }
935
936 /* Dissector for HID SET_IDLE request. See USBHID 1.11, Chapter 7.2.4 Set_Idle Request */
937 static void
938 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_)
939 {
940     proto_item *item;
941     proto_tree *subtree;
942
943     if (!is_request)
944         return;
945
946     item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
947     subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
948
949     /* Duration in the high byte, Report ID in the low byte */
950     proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
951     offset++;
952     proto_tree_add_item(subtree, hf_usb_hid_duration, tvb, offset, 1, ENC_LITTLE_ENDIAN);
953     offset++;
954
955     proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
956     offset += 2;
957
958     proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
959     /*offset += 2;*/
960 }
961
962 /* Dissector for HID GET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.5 Get_Protocol Request */
963 static void
964 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_)
965 {
966     if (!is_request)
967         return;
968
969     proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
970     offset += 2;
971
972     proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
973     offset += 2;
974
975     proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
976     /*offset += 2;*/
977 }
978
979 /* Dissector for HID SET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.6 Set_Protocol Request */
980 static void
981 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_)
982 {
983     if (!is_request)
984         return;
985
986     proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
987     offset += 2;
988
989     proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
990     offset += 2;
991
992     proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
993     /*offset += 2;*/
994 }
995
996
997 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);
998
999 typedef struct _usb_setup_dissector_table_t {
1000     guint8 request;
1001     usb_setup_dissector dissector;
1002 } usb_setup_dissector_table_t;
1003
1004
1005 /* USBHID 1.11, Chapter 7.2 Class-Specific Requests */
1006 #define USB_HID_SETUP_GET_REPORT      0x01
1007 #define USB_HID_SETUP_GET_IDLE        0x02
1008 #define USB_HID_SETUP_GET_PROTOCOL    0x03
1009 /* 0x04..0x08: Reserved */
1010 #define USB_HID_SETUP_SET_REPORT      0x09
1011 #define USB_HID_SETUP_SET_IDLE        0x0A
1012 #define USB_HID_SETUP_SET_PROTOCOL    0x0B
1013
1014 static const usb_setup_dissector_table_t setup_dissectors[] = {
1015     { USB_HID_SETUP_GET_REPORT,   dissect_usb_hid_get_report },
1016     { USB_HID_SETUP_GET_IDLE,     dissect_usb_hid_get_idle },
1017     { USB_HID_SETUP_GET_PROTOCOL, dissect_usb_hid_get_protocol },
1018     { USB_HID_SETUP_SET_REPORT,   dissect_usb_hid_set_report },
1019     { USB_HID_SETUP_SET_IDLE,     dissect_usb_hid_set_idle },
1020     { USB_HID_SETUP_SET_PROTOCOL, dissect_usb_hid_set_protocol },
1021     { 0, NULL }
1022 };
1023
1024 static const value_string setup_request_names_vals[] = {
1025     { USB_HID_SETUP_GET_REPORT,   "GET_REPORT" },
1026     { USB_HID_SETUP_GET_IDLE,     "GET_IDLE" },
1027     { USB_HID_SETUP_GET_PROTOCOL, "GET_PROTOCOL" },
1028     { USB_HID_SETUP_SET_REPORT,   "SET_REPORT" },
1029     { USB_HID_SETUP_SET_IDLE,     "SET_IDLE" },
1030     { USB_HID_SETUP_SET_PROTOCOL, "SET_PROTOCOL" },
1031     { 0, NULL }
1032 };
1033
1034 static const value_string usb_hid_report_type_vals[] = {
1035     { 1, "Input" },
1036     { 2, "Output" },
1037     { 3, "Feature" },
1038     { 0, NULL }
1039 };
1040
1041 static gint
1042 dissect_usb_hid_boot_keyboard_input_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1043 {
1044     gint      offset = 0;
1045     gboolean  shortcut_helper = FALSE;
1046     guint     modifier;
1047     guint     keycode;
1048
1049     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_gui, tvb, offset, 1, ENC_BIG_ENDIAN);
1050     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_alt, tvb, offset, 1, ENC_BIG_ENDIAN);
1051     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
1052     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_ctrl, tvb, offset, 1, ENC_BIG_ENDIAN);
1053     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_gui, tvb, offset, 1, ENC_BIG_ENDIAN);
1054     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_alt, tvb, offset, 1, ENC_BIG_ENDIAN);
1055     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
1056     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_ctrl, tvb, offset, 1, ENC_BIG_ENDIAN);
1057     modifier = tvb_get_guint8(tvb, offset);
1058
1059     col_append_str(pinfo->cinfo, COL_INFO, " - ");
1060     if (modifier & 0x80) {
1061         col_append_str(pinfo->cinfo, COL_INFO, "RIGHT GUI");
1062         shortcut_helper = TRUE;
1063     }
1064     if (modifier & 0x40) {
1065         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1066         col_append_str(pinfo->cinfo, COL_INFO, "RIGHT ALT");
1067         shortcut_helper = TRUE;
1068     }
1069     if (modifier & 0x20) {
1070         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1071         col_append_str(pinfo->cinfo, COL_INFO, "RIGHT SHIFT");
1072         shortcut_helper = TRUE;
1073     }
1074     if (modifier & 0x10) {
1075         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1076         col_append_str(pinfo->cinfo, COL_INFO, "RIGHT CTRL");
1077         shortcut_helper = TRUE;
1078     }
1079     if (modifier & 0x08) {
1080         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1081         col_append_str(pinfo->cinfo, COL_INFO, "LEFT GUI");
1082         shortcut_helper = TRUE;
1083     }
1084     if (modifier & 0x04) {
1085         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1086         col_append_str(pinfo->cinfo, COL_INFO, "LEFT ALT");
1087         shortcut_helper = TRUE;
1088     }
1089     if (modifier & 0x02) {
1090         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1091         col_append_str(pinfo->cinfo, COL_INFO, "LEFT SHIFT");
1092         shortcut_helper = TRUE;
1093     }
1094     if (modifier & 0x01) {
1095         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1096         col_append_str(pinfo->cinfo, COL_INFO, "LEFT CTRL");
1097         shortcut_helper = TRUE;
1098     }
1099     offset += 1;
1100
1101     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1102     offset += 1;
1103
1104     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1105     keycode = tvb_get_guint8(tvb, offset);
1106     offset += 1;
1107
1108     if (keycode) {
1109         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1110         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
1111         shortcut_helper = TRUE;
1112     }
1113
1114     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_2, tvb, offset, 1, ENC_BIG_ENDIAN);
1115     keycode = tvb_get_guint8(tvb, offset);
1116     offset += 1;
1117
1118     if (keycode) {
1119         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1120         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
1121         shortcut_helper = TRUE;
1122     }
1123
1124     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_3, tvb, offset, 1, ENC_BIG_ENDIAN);
1125     keycode = tvb_get_guint8(tvb, offset);
1126     offset += 1;
1127
1128     if (keycode) {
1129         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1130         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
1131         shortcut_helper = TRUE;
1132     }
1133
1134     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_4, tvb, offset, 1, ENC_BIG_ENDIAN);
1135     keycode = tvb_get_guint8(tvb, offset);
1136     offset += 1;
1137
1138     if (keycode) {
1139         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1140         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
1141         shortcut_helper = TRUE;
1142     }
1143
1144     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_5, tvb, offset, 1, ENC_BIG_ENDIAN);
1145     keycode = tvb_get_guint8(tvb, offset);
1146     offset += 1;
1147
1148     if (keycode) {
1149         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1150         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
1151         shortcut_helper = TRUE;
1152     }
1153
1154     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_6, tvb, offset, 1, ENC_BIG_ENDIAN);
1155     keycode = tvb_get_guint8(tvb, offset);
1156     offset += 1;
1157
1158     if (keycode) {
1159         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1160         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
1161         shortcut_helper = TRUE;
1162     }
1163
1164     if (shortcut_helper == FALSE) {
1165         col_append_str(pinfo->cinfo, COL_INFO, "<action key up>");
1166     }
1167
1168     return offset;
1169 }
1170
1171 static gint
1172 dissect_usb_hid_boot_keyboard_output_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1173 {
1174     gint      offset = 0;
1175     gboolean  shortcut_helper = FALSE;
1176     guint     leds;
1177
1178     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_constants, tvb, offset, 1, ENC_BIG_ENDIAN);
1179     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_kana, tvb, offset, 1, ENC_BIG_ENDIAN);
1180     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_compose, tvb, offset, 1, ENC_BIG_ENDIAN);
1181     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_scroll_lock, tvb, offset, 1, ENC_BIG_ENDIAN);
1182     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_caps_lock, tvb, offset, 1, ENC_BIG_ENDIAN);
1183     proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_num_lock, tvb, offset, 1, ENC_BIG_ENDIAN);
1184     leds = tvb_get_guint8(tvb, offset);
1185
1186     col_append_str(pinfo->cinfo, COL_INFO, " - LEDs: ");
1187     if (leds & 0x01) {
1188         col_append_str(pinfo->cinfo, COL_INFO, "NumLock");
1189         shortcut_helper = TRUE;
1190     }
1191     if (leds & 0x02) {
1192         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1193         col_append_str(pinfo->cinfo, COL_INFO, "CapsLock");
1194         shortcut_helper = TRUE;
1195     }
1196     if (leds & 0x04) {
1197         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1198         col_append_str(pinfo->cinfo, COL_INFO, "ScrollLock");
1199         shortcut_helper = TRUE;
1200     }
1201     if (leds & 0x08) {
1202         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1203         col_append_str(pinfo->cinfo, COL_INFO, "Compose");
1204         shortcut_helper = TRUE;
1205     }
1206     if (leds & 0x10) {
1207         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1208         col_append_str(pinfo->cinfo, COL_INFO, "Kana");
1209         shortcut_helper = TRUE;
1210     }
1211     if (leds & 0x20) {
1212         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1213         col_append_str(pinfo->cinfo, COL_INFO, "Constant1");
1214         shortcut_helper = TRUE;
1215     }
1216     if (leds & 0x40) {
1217         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1218         col_append_str(pinfo->cinfo, COL_INFO, "Constant2");
1219         shortcut_helper = TRUE;
1220     }
1221     if (leds & 0x80) {
1222         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
1223         col_append_str(pinfo->cinfo, COL_INFO, "Constant3");
1224         /*shortcut_helper = TRUE;*/
1225     }
1226     if (!leds) {
1227         col_append_str(pinfo->cinfo, COL_INFO, "none");
1228     }
1229
1230     offset += 1;
1231
1232     return offset;
1233 }
1234
1235 static gint
1236 dissect_usb_hid_boot_mouse_input_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1237 {
1238     gint      offset = 0;
1239     gboolean  shortcut_helper = FALSE;
1240     guint     buttons;
1241
1242     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_8, tvb, offset, 1, ENC_BIG_ENDIAN);
1243     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_7, tvb, offset, 1, ENC_BIG_ENDIAN);
1244     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_6, tvb, offset, 1, ENC_BIG_ENDIAN);
1245     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_5, tvb, offset, 1, ENC_BIG_ENDIAN);
1246     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_4, tvb, offset, 1, ENC_BIG_ENDIAN);
1247     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_middle, tvb, offset, 1, ENC_BIG_ENDIAN);
1248     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_right, tvb, offset, 1, ENC_BIG_ENDIAN);
1249     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_left, tvb, offset, 1, ENC_BIG_ENDIAN);
1250     buttons = tvb_get_guint8(tvb, offset);
1251     offset += 1;
1252
1253     if (buttons) col_append_str(pinfo->cinfo, COL_INFO, " - ");
1254     if (buttons & 0x01) {
1255         col_append_str(pinfo->cinfo, COL_INFO, "Button LEFT");
1256         shortcut_helper = TRUE;
1257     }
1258     if (buttons & 0x02) {
1259         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1260         col_append_str(pinfo->cinfo, COL_INFO, "Button RIGHT");
1261         shortcut_helper = TRUE;
1262     }
1263     if (buttons & 0x04) {
1264         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1265         col_append_str(pinfo->cinfo, COL_INFO, "Button MIDDLE");
1266     }
1267     if (buttons & 0x08) {
1268         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1269         col_append_str(pinfo->cinfo, COL_INFO, "Button 4");
1270         shortcut_helper = TRUE;
1271     }
1272     if (buttons & 0x10) {
1273         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1274         col_append_str(pinfo->cinfo, COL_INFO, "Button 5");
1275         shortcut_helper = TRUE;
1276     }
1277     if (buttons & 0x20) {
1278         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1279         col_append_str(pinfo->cinfo, COL_INFO, "Button 6");
1280         shortcut_helper = TRUE;
1281     }
1282     if (buttons & 0x40) {
1283         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1284         col_append_str(pinfo->cinfo, COL_INFO, "Button 7");
1285         shortcut_helper = TRUE;
1286     }
1287     if (buttons & 0x80) {
1288         if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
1289         col_append_str(pinfo->cinfo, COL_INFO, "Button 8");
1290         /* Not necessary, this is the last case where it is used
1291          * shortcut_helper = TRUE;
1292          */
1293     }
1294
1295     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_x_displacement, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1296     offset += 1;
1297
1298     proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_y_displacement, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1299     offset += 1;
1300
1301     /* not really in HID Specification */
1302     if (tvb_reported_length_remaining(tvb, offset)) {
1303         proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_horizontal_scroll_wheel, tvb, offset, 1, ENC_BIG_ENDIAN);
1304         offset += 1;
1305     }
1306
1307     /* not really in HID Specification */
1308     if (tvb_reported_length_remaining(tvb, offset)) {
1309         proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_vertical_scroll_wheel, tvb, offset, 1, ENC_BIG_ENDIAN);
1310         offset += 1;
1311     }
1312
1313     if (tvb_reported_length_remaining(tvb, offset)) {
1314         proto_tree_add_item(tree, hf_usbhid_data, tvb, offset, -1, ENC_NA);
1315         offset += tvb_captured_length_remaining(tvb, offset);
1316     }
1317
1318     return offset;
1319 }
1320
1321
1322 /* dissect a "standard" control message that's sent to an interface */
1323 static gint
1324 dissect_usb_hid_control_std_intf(tvbuff_t *tvb, packet_info *pinfo,
1325         proto_tree *tree, usb_conv_info_t *usb_conv_info)
1326 {
1327     gint              offset = 0;
1328     usb_trans_info_t *usb_trans_info;
1329     guint8            req;
1330
1331     usb_trans_info = usb_conv_info->usb_trans_info;
1332
1333     /* XXX - can we do some plausibility checks here? */
1334
1335     col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
1336
1337     /* we can't use usb_conv_info->is_request since usb_conv_info
1338        was replaced with the interface conversation */
1339     if (usb_trans_info->request_in == pinfo->fd->num) {
1340         /* the tvb that we see here is the setup packet
1341            without the request type byte */
1342
1343         req = tvb_get_guint8(tvb, offset);
1344         if (req != USB_SETUP_GET_DESCRIPTOR)
1345             return offset;
1346         col_clear(pinfo->cinfo, COL_INFO);
1347         col_append_fstr(pinfo->cinfo, COL_INFO, "GET DESCRIPTOR Request");
1348         offset += 1;
1349
1350         proto_tree_add_item(tree, hf_usb_hid_bDescriptorIndex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1351         usb_trans_info->u.get_descriptor.usb_index = tvb_get_guint8(tvb, offset);
1352         offset += 1;
1353
1354         proto_tree_add_item(tree, hf_usb_hid_bDescriptorType, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1355         usb_trans_info->u.get_descriptor.type = tvb_get_guint8(tvb, offset);
1356         col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1357                 val_to_str_ext(usb_trans_info->u.get_descriptor.type,
1358                     &hid_descriptor_type_vals_ext, "Unknown type %u"));
1359         offset += 1;
1360
1361         proto_tree_add_item(tree, hf_usb_hid_wInterfaceNumber, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1362         offset += 2;
1363
1364         proto_tree_add_item(tree, hf_usb_hid_wDescriptorLength, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1365         offset += 2;
1366     }
1367     else {
1368         col_clear(pinfo->cinfo, COL_INFO);
1369         col_append_fstr(pinfo->cinfo, COL_INFO, "GET DESCRIPTOR Response");
1370         col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1371                 val_to_str_ext(usb_trans_info->u.get_descriptor.type,
1372                     &hid_descriptor_type_vals_ext, "Unknown type %u"));
1373         if (usb_trans_info->u.get_descriptor.type == USB_DT_HID_REPORT) {
1374             offset = dissect_usb_hid_get_report_descriptor(
1375                     pinfo, tree, tvb, offset, usb_conv_info);
1376         }
1377     }
1378
1379     return offset;
1380 }
1381
1382 /* dissect a class-specific control message that's sent to an interface */
1383 static gint
1384 dissect_usb_hid_control_class_intf(tvbuff_t *tvb, packet_info *pinfo,
1385         proto_tree *tree, usb_conv_info_t *usb_conv_info)
1386 {
1387     usb_trans_info_t *usb_trans_info;
1388     gboolean is_request;
1389     int offset = 0;
1390     usb_setup_dissector dissector = NULL;
1391     const usb_setup_dissector_table_t *tmp;
1392
1393     usb_trans_info = usb_conv_info->usb_trans_info;
1394
1395     is_request = (pinfo->srcport==NO_ENDPOINT);
1396
1397     /* Check valid values for bmRequestType. See Chapter 7.2 in USBHID 1.11 */
1398     for (tmp = setup_dissectors; tmp->dissector; tmp++) {
1399         if (tmp->request == usb_trans_info->setup.request) {
1400             dissector = tmp->dissector;
1401             break;
1402         }
1403     }
1404     /* No, we could not find any class specific dissector for this request
1405      * return 0 and let USB try any of the standard requests.
1406      */
1407     if (!dissector) {
1408         return 0;
1409     }
1410
1411     col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
1412
1413     col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
1414     val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
1415         is_request ? "Request" : "Response");
1416
1417     if (is_request) {
1418         proto_tree_add_item(tree, hf_usb_hid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1419         offset += 1;
1420     }
1421
1422     dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info);
1423     return tvb_captured_length(tvb);
1424 }
1425
1426 /* Dissector for HID class-specific control request as defined in
1427  * USBHID 1.11, Chapter 7.2.
1428  * returns the number of bytes consumed */
1429 static gint
1430 dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1431 {
1432     usb_conv_info_t *usb_conv_info;
1433     usb_trans_info_t *usb_trans_info;
1434     guint8 type, recip;
1435
1436     usb_conv_info = (usb_conv_info_t *)data;
1437     if (!usb_conv_info)
1438         return 0;
1439     usb_trans_info = usb_conv_info->usb_trans_info;
1440     if (!usb_trans_info)
1441         return 0;
1442
1443     type = USB_TYPE(usb_trans_info->setup.requesttype);
1444     recip = USB_RECIPIENT(usb_trans_info->setup.requesttype);
1445
1446     if (recip == RQT_SETUP_RECIPIENT_INTERFACE) {
1447         if (type == RQT_SETUP_TYPE_STANDARD) {
1448             return dissect_usb_hid_control_std_intf(
1449                     tvb, pinfo, tree, usb_conv_info);
1450         }
1451         else if (type == RQT_SETUP_TYPE_CLASS) {
1452             return dissect_usb_hid_control_class_intf(
1453                     tvb, pinfo, tree, usb_conv_info);
1454         }
1455     }
1456
1457     return 0;
1458 }
1459
1460 /* dissect a descriptor that is specific to the HID class */
1461 static gint
1462 dissect_usb_hid_class_descriptors(tvbuff_t *tvb, packet_info *pinfo _U_,
1463         proto_tree *tree, void *data _U_)
1464 {
1465     guint8      type;
1466     gint        offset = 0;
1467     proto_item *ti;
1468     proto_tree *desc_tree;
1469     guint8      num_desc;
1470     guint       i;
1471
1472     type = tvb_get_guint8(tvb, 1);
1473
1474     /* for now, we only handle the HID descriptor here */
1475     if (type != USB_DT_HID)
1476         return 0;
1477
1478     desc_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_usb_hid_descriptor, &ti, "HID DESCRIPTOR");
1479
1480     dissect_usb_descriptor_header(desc_tree, tvb, offset,
1481             &hid_descriptor_type_vals_ext);
1482     offset += 2;
1483     proto_tree_add_item(desc_tree, hf_usb_hid_bcdHID,
1484             tvb, offset, 2, ENC_LITTLE_ENDIAN);
1485     offset += 2;
1486     proto_tree_add_item(desc_tree, hf_usb_hid_bCountryCode,
1487             tvb, offset, 1, ENC_LITTLE_ENDIAN);
1488     offset++;
1489     num_desc = tvb_get_guint8(tvb, offset);
1490     proto_tree_add_item(desc_tree, hf_usb_hid_bNumDescriptors,
1491             tvb, offset, 1, ENC_LITTLE_ENDIAN);
1492     offset++;
1493     for (i=0;i<num_desc;i++) {
1494         proto_tree_add_item(desc_tree, hf_usb_hid_bDescriptorType,
1495                 tvb, offset, 1, ENC_LITTLE_ENDIAN);
1496         offset++;
1497         proto_tree_add_item(desc_tree, hf_usb_hid_wDescriptorLength,
1498                 tvb, offset, 2, ENC_LITTLE_ENDIAN);
1499         offset += 2;
1500     }
1501
1502     proto_item_set_len(ti, offset);
1503     return offset;
1504 }
1505
1506
1507 void
1508 proto_register_usb_hid(void)
1509 {
1510     static hf_register_info hf[] = {
1511         { &hf_usb_hid_item_bSize,
1512             { "bSize", "usbhid.item.bSize", FT_UINT8, BASE_DEC,
1513                 VALS(usb_hid_item_bSize_vals), USBHID_SIZE_MASK, NULL, HFILL }},
1514
1515         { &hf_usb_hid_item_bType,
1516             { "bType", "usbhid.item.bType", FT_UINT8, BASE_DEC,
1517                 VALS(usb_hid_item_bType_vals), USBHID_TYPE_MASK, NULL, HFILL }},
1518
1519         { &hf_usb_hid_mainitem_bTag,
1520             { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
1521                 VALS(usb_hid_mainitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
1522
1523         { &hf_usb_hid_globalitem_bTag,
1524             { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
1525                 VALS(usb_hid_globalitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
1526
1527         { &hf_usb_hid_localitem_bTag,
1528             { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
1529                 VALS(usb_hid_localitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
1530
1531         { &hf_usb_hid_longitem_bTag,
1532             { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
1533                 VALS(usb_hid_longitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
1534
1535         { &hf_usb_hid_item_bDataSize,
1536             { "bDataSize", "usbhid.item.bDataSize", FT_UINT8, BASE_DEC,
1537                 NULL, 0, NULL, HFILL }},
1538
1539         { &hf_usb_hid_item_bLongItemTag,
1540             { "bTag", "usbhid.item.bLongItemTag", FT_UINT8, BASE_HEX,
1541                 NULL, 0, NULL, HFILL }},
1542
1543         /* Main-report item data */
1544
1545         { &hf_usb_hid_mainitem_bit0,
1546             { "Data/constant", "usbhid.item.main.readonly", FT_BOOLEAN, 9,
1547                 TFS(&tfs_mainitem_bit0), 1<<0, NULL, HFILL }},
1548
1549         { &hf_usb_hid_mainitem_bit1,
1550             { "Data type", "usbhid.item.main.variable", FT_BOOLEAN, 9,
1551                 TFS(&tfs_mainitem_bit1), 1<<1, NULL, HFILL }},
1552
1553         { &hf_usb_hid_mainitem_bit2,
1554             { "Coordinates", "usbhid.item.main.relative", FT_BOOLEAN, 9,
1555                 TFS(&tfs_mainitem_bit2), 1<<2, NULL, HFILL }},
1556
1557         { &hf_usb_hid_mainitem_bit3,
1558             { "Min/max wraparound", "usbhid.item.main.wrap", FT_BOOLEAN, 9,
1559                 TFS(&tfs_mainitem_bit3), 1<<3, NULL, HFILL }},
1560
1561         { &hf_usb_hid_mainitem_bit4,
1562             { "Physical relationship to data", "usbhid.item.main.nonlinear", FT_BOOLEAN, 9,
1563                 TFS(&tfs_mainitem_bit4), 1<<4, NULL, HFILL }},
1564
1565         { &hf_usb_hid_mainitem_bit5,
1566             { "Preferred state", "usbhid.item.main.no_preferred_state", FT_BOOLEAN, 9,
1567                 TFS(&tfs_mainitem_bit5), 1<<5, NULL, HFILL }},
1568
1569         { &hf_usb_hid_mainitem_bit6,
1570             { "Has null position", "usbhid.item.main.nullstate", FT_BOOLEAN, 9,
1571                 TFS(&tfs_mainitem_bit6), 1<<6, NULL, HFILL }},
1572
1573         { &hf_usb_hid_mainitem_bit7,
1574             { "(Non)-volatile", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
1575                 TFS(&tfs_mainitem_bit7), 1<<7, NULL, HFILL }},
1576
1577         { &hf_usb_hid_mainitem_bit7_input,
1578             { "[Reserved]", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
1579                 NULL, 1<<7, NULL, HFILL }},
1580
1581         { &hf_usb_hid_mainitem_bit8,
1582             { "Bits or bytes", "usbhid.item.main.buffered_bytes", FT_BOOLEAN, 9,
1583                 TFS(&tfs_mainitem_bit8), 1<<8, NULL, HFILL }},
1584
1585         { &hf_usb_hid_mainitem_colltype,
1586             { "Collection type", "usbhid.item.main.colltype", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
1587                 RVALS(usb_hid_mainitem_colltype_vals), 0, NULL, HFILL }},
1588
1589         /* Global-report item data */
1590
1591         { &hf_usb_hid_globalitem_usage,
1592             { "Usage page", "usbhid.item.global.usage", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
1593                 RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
1594
1595         { &hf_usb_hid_globalitem_log_min,
1596             { "Logical minimum", "usbhid.item.global.log_min", FT_UINT8, BASE_DEC,
1597                 NULL, 0, NULL, HFILL }},
1598
1599         { &hf_usb_hid_globalitem_log_max,
1600             { "Logical maximum", "usbhid.item.global.log_max", FT_UINT8, BASE_DEC,
1601                 NULL, 0, NULL, HFILL }},
1602
1603         { &hf_usb_hid_globalitem_phy_min,
1604             { "Physical minimum", "usbhid.item.global.phy_min", FT_UINT8, BASE_DEC,
1605                 NULL, 0, NULL, HFILL }},
1606
1607         { &hf_usb_hid_globalitem_phy_max,
1608             { "Physical maximum", "usbhid.item.global.phy_max", FT_UINT8, BASE_DEC,
1609                 NULL, 0, NULL, HFILL }},
1610
1611         { &hf_usb_hid_globalitem_unit_exp,
1612             { "Unit exponent", "usbhid.item.global.unit_exp", FT_UINT8, BASE_DEC,
1613                 NULL, 0, NULL, HFILL }},
1614
1615         { &hf_usb_hid_globalitem_unit_sys,
1616             { "System", "usbhid.item.global.unit.system", FT_UINT32, BASE_HEX,
1617                 VALS(usb_hid_globalitem_unit_exp_vals), 0x0000000F, NULL, HFILL }},
1618
1619         { &hf_usb_hid_globalitem_unit_len,
1620             { "Length", "usbhid.item.global.unit.length", FT_UINT32, BASE_HEX,
1621                 VALS(usb_hid_globalitem_unit_exp_vals), 0x000000F0, NULL, HFILL }},
1622
1623         { &hf_usb_hid_globalitem_unit_mass,
1624             { "Mass", "usbhid.item.global.unit.mass", FT_UINT32, BASE_HEX,
1625                 VALS(usb_hid_globalitem_unit_exp_vals), 0x00000F00, NULL, HFILL }},
1626
1627         { &hf_usb_hid_globalitem_unit_time,
1628             { "Time", "usbhid.item.global.unit.time", FT_UINT32, BASE_HEX,
1629                 VALS(usb_hid_globalitem_unit_exp_vals), 0x0000F000, NULL, HFILL }},
1630
1631         { &hf_usb_hid_globalitem_unit_temp,
1632             { "Temperature", "usbhid.item.global.unit.temperature", FT_UINT32, BASE_HEX,
1633                 VALS(usb_hid_globalitem_unit_exp_vals), 0x000F0000, NULL, HFILL }},
1634
1635         { &hf_usb_hid_globalitem_unit_current,
1636             { "Current", "usbhid.item.global.unit.current", FT_UINT32, BASE_HEX,
1637                 VALS(usb_hid_globalitem_unit_exp_vals), 0x00F00000, NULL, HFILL }},
1638
1639         { &hf_usb_hid_globalitem_unit_brightness,
1640             { "Luminous intensity", "usbhid.item.global.unit.brightness", FT_UINT32, BASE_HEX,
1641                 VALS(usb_hid_globalitem_unit_exp_vals), 0x0F000000, NULL, HFILL }},
1642
1643         { &hf_usb_hid_globalitem_report_size,
1644             { "Report size", "usbhid.item.global.report_size", FT_UINT8, BASE_DEC,
1645                 NULL, 0, NULL, HFILL }},
1646
1647         { &hf_usb_hid_globalitem_report_id,
1648             { "Report ID", "usbhid.item.global.report_id", FT_UINT8, BASE_HEX,
1649                 NULL, 0, NULL, HFILL }},
1650
1651         { &hf_usb_hid_globalitem_report_count,
1652             { "Report count", "usbhid.item.global.report_count", FT_UINT8, BASE_DEC,
1653                 NULL, 0, NULL, HFILL }},
1654
1655         { &hf_usb_hid_globalitem_push,
1656             { "Push", "usbhid.item.global.push", FT_UINT8, BASE_HEX,
1657                 NULL, 0, NULL, HFILL }},
1658
1659         { &hf_usb_hid_globalitem_pop,
1660             { "Pop", "usbhid.item.global.pop", FT_UINT8, BASE_HEX,
1661                 NULL, 0, NULL, HFILL }},
1662
1663         /* Local-report item data */
1664
1665         { &hf_usb_hid_localitem_usage,
1666             { "Usage", "usbhid.item.local.usage", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
1667                 RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
1668
1669         { &hf_usb_hid_localitem_usage_min,
1670             { "Usage minimum", "usbhid.item.local.usage_min", FT_UINT8, BASE_HEX,
1671                 NULL, 0, NULL, HFILL }},
1672
1673 #if 0
1674         { &hf_usb_hid_localitem_usage_max,
1675             { "Usage maximum", "usbhid.item.local.usage_max", FT_UINT8, BASE_HEX,
1676                 NULL, 0, NULL, HFILL }},
1677 #endif
1678
1679         { &hf_usb_hid_localitem_desig_index,
1680             { "Designator index", "usbhid.item.local.desig_index", FT_UINT8, BASE_HEX,
1681                 NULL, 0, NULL, HFILL }},
1682
1683         { &hf_usb_hid_localitem_desig_min,
1684             { "Designator minimum", "usbhid.item.local.desig_min", FT_UINT8, BASE_HEX,
1685                 NULL, 0, NULL, HFILL }},
1686
1687         { &hf_usb_hid_localitem_desig_max,
1688             { "Designator maximum", "usbhid.item.local.desig_max", FT_UINT8, BASE_HEX,
1689                 NULL, 0, NULL, HFILL }},
1690
1691         { &hf_usb_hid_localitem_string_index,
1692             { "String index", "usbhid.item.local.string_index", FT_UINT8, BASE_HEX,
1693                 NULL, 0, NULL, HFILL }},
1694
1695         { &hf_usb_hid_localitem_string_min,
1696             { "String minimum", "usbhid.item.local.string_min", FT_UINT8, BASE_HEX,
1697                 NULL, 0, NULL, HFILL }},
1698
1699         { &hf_usb_hid_localitem_string_max,
1700             { "String maximum", "usbhid.item.local.string_max", FT_UINT8, BASE_HEX,
1701                 NULL, 0, NULL, HFILL }},
1702
1703         { &hf_usb_hid_localitem_delimiter,
1704             { "Delimiter", "usbhid.item.local.delimiter", FT_UINT8, BASE_HEX,
1705                 NULL, 0, NULL, HFILL }},
1706
1707
1708         { &hf_usb_hid_item_unk_data,
1709             { "Item data", "usbhid.item.data", FT_BYTES, BASE_NONE,
1710                 NULL, 0, NULL, HFILL }},
1711
1712         /* USB HID specific requests */
1713         { &hf_usb_hid_request,
1714         { "bRequest", "usbhid.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
1715           NULL, HFILL }},
1716
1717         { &hf_usb_hid_value,
1718         { "wValue", "usbhid.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
1719           NULL, HFILL }},
1720
1721         { &hf_usb_hid_index,
1722         { "wIndex", "usbhid.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
1723           NULL, HFILL }},
1724
1725         { &hf_usb_hid_length,
1726         { "wLength", "usbhid.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1727           NULL, HFILL }},
1728
1729         { &hf_usb_hid_report_type,
1730         { "ReportType", "usbhid.setup.ReportType", FT_UINT8, BASE_DEC,
1731           VALS(usb_hid_report_type_vals), 0x0,
1732           NULL, HFILL }},
1733
1734         { &hf_usb_hid_report_id,
1735         { "ReportID", "usbhid.setup.ReportID", FT_UINT8, BASE_DEC, NULL, 0x0,
1736           NULL, HFILL }},
1737
1738         { &hf_usb_hid_duration,
1739         { "Duration", "usbhid.setup.Duration", FT_UINT8, BASE_DEC, NULL, 0x0,
1740           NULL, HFILL }},
1741
1742         { &hf_usb_hid_zero,
1743         { "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
1744           NULL, HFILL }},
1745
1746         /* components of the HID descriptor */
1747         { &hf_usb_hid_bcdHID,
1748         { "bcdHID", "usbhid.descriptor.hid.bcdHID", FT_UINT16, BASE_HEX, NULL, 0x0,
1749           NULL, HFILL }},
1750
1751         { &hf_usb_hid_bCountryCode,
1752         { "bCountryCode", "usbhid.descriptor.hid.bCountryCode", FT_UINT8,
1753             BASE_HEX, VALS(hid_country_code_vals), 0x0, NULL, HFILL }},
1754
1755         { &hf_usb_hid_bNumDescriptors,
1756         { "bNumDescriptors", "usbhid.descriptor.hid.bNumDescriptors", FT_UINT8,
1757             BASE_DEC, NULL, 0x0, NULL, HFILL }},
1758
1759         { &hf_usb_hid_bDescriptorIndex,
1760         { "bDescriptorIndex", "usbhid.descriptor.hid.bDescriptorIndex", FT_UINT8,
1761             BASE_HEX, NULL, 0x0, NULL, HFILL }},
1762
1763         { &hf_usb_hid_bDescriptorType,
1764         { "bDescriptorType", "usbhid.descriptor.hid.bDescriptorType", FT_UINT8,
1765             BASE_HEX|BASE_EXT_STRING, &hid_descriptor_type_vals_ext,
1766             0x00, NULL, HFILL }},
1767
1768         { &hf_usb_hid_wInterfaceNumber,
1769         { "wInterfaceNumber", "usbhid.descriptor.hid.wInterfaceNumber", FT_UINT16,
1770             BASE_DEC, NULL, 0x0, NULL, HFILL }},
1771
1772         { &hf_usb_hid_wDescriptorLength,
1773         { "wDescriptorLength", "usbhid.descriptor.hid.wDescriptorLength", FT_UINT16,
1774             BASE_DEC, NULL, 0x0, NULL, HFILL }},
1775
1776         { &hf_usbhid_boot_report_keyboard_reserved,
1777             { "Reserved",                        "usbhid.boot_report.keyboard.reserved",
1778             FT_UINT8, BASE_HEX, NULL, 0x00,
1779             NULL, HFILL }
1780         },
1781         { &hf_usbhid_boot_report_keyboard_keycode_1,
1782             { "Keycode 1",                       "usbhid.boot_report.keyboard.keycode_1",
1783             FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
1784             NULL, HFILL }
1785         },
1786         { &hf_usbhid_boot_report_keyboard_keycode_2,
1787             { "Keycode 2",                       "usbhid.boot_report.keyboard.keycode_2",
1788             FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
1789             NULL, HFILL }
1790         },
1791         { &hf_usbhid_boot_report_keyboard_keycode_3,
1792             { "Keycode 3",                       "usbhid.boot_report.keyboard.keycode_3",
1793             FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
1794             NULL, HFILL }
1795         },
1796         { &hf_usbhid_boot_report_keyboard_keycode_4,
1797             { "Keycode 4",                       "usbhid.boot_report.keyboard.keycode_4",
1798             FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
1799             NULL, HFILL }
1800         },
1801         { &hf_usbhid_boot_report_keyboard_keycode_5,
1802             { "Keycode 5",                       "usbhid.boot_report.keyboard.keycode_5",
1803             FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
1804             NULL, HFILL }
1805         },
1806         { &hf_usbhid_boot_report_keyboard_keycode_6,
1807             { "Keycode 6",                       "usbhid.boot_report.keyboard.keycode_6",
1808             FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
1809             NULL, HFILL }
1810         },
1811         { &hf_usbhid_boot_report_keyboard_modifier_right_gui,
1812             { "Modifier: RIGHT GUI",             "usbhid.boot_report.keyboard.modifier.right_gui",
1813             FT_BOOLEAN, 8, NULL, 0x80,
1814             NULL, HFILL }
1815         },
1816         { &hf_usbhid_boot_report_keyboard_modifier_right_alt,
1817             { "Modifier: RIGHT ALT",             "usbhid.boot_report.keyboard.modifier.right_alt",
1818             FT_BOOLEAN, 8, NULL, 0x40,
1819             NULL, HFILL }
1820         },
1821         { &hf_usbhid_boot_report_keyboard_modifier_right_shift,
1822             { "Modifier: RIGHT SHIFT",           "usbhid.boot_report.keyboard.modifier.right_shift",
1823             FT_BOOLEAN, 8, NULL, 0x20,
1824             NULL, HFILL }
1825         },
1826         { &hf_usbhid_boot_report_keyboard_modifier_right_ctrl,
1827             { "Modifier: RIGHT CTRL",            "usbhid.boot_report.keyboard.modifier.right_ctrl",
1828             FT_BOOLEAN, 8, NULL, 0x10,
1829             NULL, HFILL }
1830         },
1831         { &hf_usbhid_boot_report_keyboard_modifier_left_gui,
1832             { "Modifier: LEFT GUI",              "usbhid.boot_report.keyboard.modifier.left_gui",
1833             FT_BOOLEAN, 8, NULL, 0x08,
1834             NULL, HFILL }
1835         },
1836         { &hf_usbhid_boot_report_keyboard_modifier_left_alt,
1837             { "Modifier: LEFT ALT",              "usbhid.boot_report.keyboard.modifier.left_alt",
1838             FT_BOOLEAN, 8, NULL, 0x04,
1839             NULL, HFILL }
1840         },
1841         { &hf_usbhid_boot_report_keyboard_modifier_left_shift,
1842             { "Modifier: LEFT SHIFT",            "usbhid.boot_report.keyboard.modifier.left_shift",
1843             FT_BOOLEAN, 8, NULL, 0x02,
1844             NULL, HFILL }
1845         },
1846         { &hf_usbhid_boot_report_keyboard_modifier_left_ctrl,
1847             { "Modifier: LEFT CTRL",             "usbhid.boot_report.keyboard.modifier.left_ctrl",
1848             FT_BOOLEAN, 8, NULL, 0x01,
1849             NULL, HFILL }
1850         },
1851         { &hf_usbhid_boot_report_keyboard_leds_constants,
1852             { "Constants",                       "usbhid.boot_report.keyboard.leds.constants",
1853             FT_UINT8, BASE_HEX, NULL, 0xE0,
1854             NULL, HFILL }
1855         },
1856         { &hf_usbhid_boot_report_keyboard_leds_kana,
1857             { "KANA",                            "usbhid.boot_report.keyboard.leds.kana",
1858             FT_BOOLEAN, 8, NULL, 0x10,
1859             NULL, HFILL }
1860         },
1861         { &hf_usbhid_boot_report_keyboard_leds_compose,
1862             { "COMPOSE",                         "usbhid.boot_report.keyboard.leds.compose",
1863             FT_BOOLEAN, 8, NULL, 0x08,
1864             NULL, HFILL }
1865         },
1866         { &hf_usbhid_boot_report_keyboard_leds_scroll_lock,
1867             { "SCROLL LOCK",                     "usbhid.boot_report.keyboard.leds.scroll_lock",
1868             FT_BOOLEAN, 8, NULL, 0x04,
1869             NULL, HFILL }
1870         },
1871         { &hf_usbhid_boot_report_keyboard_leds_caps_lock,
1872             { "CAPS LOCK",                       "usbhid.boot_report.keyboard.leds.caps_lock",
1873             FT_BOOLEAN, 8, NULL, 0x02,
1874             NULL, HFILL }
1875         },
1876         { &hf_usbhid_boot_report_keyboard_leds_num_lock,
1877             { "NUM LOCK",                        "usbhid.boot_report.keyboard.leds.num_lock",
1878             FT_BOOLEAN, 8, NULL, 0x01,
1879             NULL, HFILL }
1880         },
1881         { &hf_usbhid_boot_report_mouse_button_8,
1882             { "Button 8",                        "usbhid.boot_report.mouse.button.8",
1883             FT_BOOLEAN, 8, NULL, 0x80,
1884             NULL, HFILL }
1885         },
1886         { &hf_usbhid_boot_report_mouse_button_7,
1887             { "Button 7",                        "usbhid.boot_report.mouse.button.7",
1888             FT_BOOLEAN, 8, NULL, 0x40,
1889             NULL, HFILL }
1890         },
1891         { &hf_usbhid_boot_report_mouse_button_6,
1892             { "Button 6",                        "usbhid.boot_report.mouse.button.6",
1893             FT_BOOLEAN, 8, NULL, 0x20,
1894             NULL, HFILL }
1895         },
1896         { &hf_usbhid_boot_report_mouse_button_5,
1897             { "Button 5",                        "usbhid.boot_report.mouse.button.5",
1898             FT_BOOLEAN, 8, NULL, 0x10,
1899             NULL, HFILL }
1900         },
1901         { &hf_usbhid_boot_report_mouse_button_4,
1902             { "Button 4",                        "usbhid.boot_report.mouse.button.4",
1903             FT_BOOLEAN, 8, NULL, 0x08,
1904             NULL, HFILL }
1905         },
1906         { &hf_usbhid_boot_report_mouse_button_middle,
1907             { "Button Middle",                   "usbhid.boot_report.mouse.button.middle",
1908             FT_BOOLEAN, 8, NULL, 0x04,
1909             NULL, HFILL }
1910         },
1911         { &hf_usbhid_boot_report_mouse_button_right,
1912             { "Button Right",                    "usbhid.boot_report.mouse.button.right",
1913             FT_BOOLEAN, 8, NULL, 0x02,
1914             NULL, HFILL }
1915         },
1916         { &hf_usbhid_boot_report_mouse_button_left,
1917             { "Button Left",                     "usbhid.boot_report.mouse.button.left",
1918             FT_BOOLEAN, 8, NULL, 0x01,
1919             NULL, HFILL }
1920         },
1921         { &hf_usbhid_boot_report_mouse_x_displacement,
1922             { "X Displacement",                  "usbhid.boot_report.mouse.x_displacement",
1923             FT_INT8, BASE_DEC, NULL, 0x00,
1924             NULL, HFILL }
1925         },
1926         { &hf_usbhid_boot_report_mouse_y_displacement,
1927             { "Y Displacement",                  "usbhid.boot_report.mouse.y_displacement",
1928             FT_INT8, BASE_DEC, NULL, 0x00,
1929             NULL, HFILL }
1930         },
1931         { &hf_usbhid_boot_report_mouse_horizontal_scroll_wheel,
1932             { "Horizontal Scroll Wheel",         "usbhid.boot_report.mouse.scroll_wheel.horizontal",
1933             FT_INT8, BASE_DEC, NULL, 0x00,
1934             NULL, HFILL }
1935         },
1936         { &hf_usbhid_boot_report_mouse_vertical_scroll_wheel,
1937             { "Vertical Scroll Wheel",           "usbhid.boot_report.mouse.scroll_wheel.vertical",
1938             FT_INT8, BASE_DEC, NULL, 0x00,
1939             NULL, HFILL }
1940         },
1941         { &hf_usbhid_data,
1942             { "Data",                            "usbhid.data",
1943             FT_NONE, BASE_NONE, NULL, 0x00,
1944             NULL, HFILL }
1945         },
1946     };
1947
1948     static gint *usb_hid_subtrees[] = {
1949         &ett_usb_hid_report,
1950         &ett_usb_hid_item_header,
1951         &ett_usb_hid_wValue,
1952         &ett_usb_hid_descriptor
1953     };
1954
1955     proto_usb_hid = proto_register_protocol("USB HID", "USBHID", "usbhid");
1956     proto_register_field_array(proto_usb_hid, hf, array_length(hf));
1957     proto_register_subtree_array(usb_hid_subtrees, array_length(usb_hid_subtrees));
1958
1959     /*usb_hid_boot_keyboard_input_report_handle  =*/ new_register_dissector("usbhid.boot_report.keyboard.input",  dissect_usb_hid_boot_keyboard_input_report,  proto_usb_hid);
1960     /*usb_hid_boot_keyboard_output_report_handle =*/ new_register_dissector("usbhid.boot_report.keyboard.output", dissect_usb_hid_boot_keyboard_output_report, proto_usb_hid);
1961     /*usb_hid_boot_mouse_input_report_handle     =*/ new_register_dissector("usbhid.boot_report.mouse.input",     dissect_usb_hid_boot_mouse_input_report,     proto_usb_hid);
1962
1963 }
1964
1965 void
1966 proto_reg_handoff_usb_hid(void)
1967 {
1968     dissector_handle_t usb_hid_control_handle, usb_hid_descr_handle;
1969
1970     usb_hid_control_handle = create_dissector_handle(
1971                         dissect_usb_hid_control, proto_usb_hid);
1972     dissector_add_uint("usb.control", IF_CLASS_HID, usb_hid_control_handle);
1973
1974     usb_hid_descr_handle = create_dissector_handle(
1975                         dissect_usb_hid_class_descriptors, proto_usb_hid);
1976     dissector_add_uint("usb.descriptor", IF_CLASS_HID, usb_hid_descr_handle);
1977 }
1978
1979 /*
1980  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1981  *
1982  * Local variables:
1983  * c-basic-offset: 4
1984  * tab-width: 8
1985  * indent-tabs-mode: nil
1986  * End:
1987  *
1988  * vi: set shiftwidth=4 tabstop=8 expandtab:
1989  * :indentSize=4:tabSize=8:noTabs=true:
1990  */