4 * By Adam Nielsen <a.nielsen@shikadi.net> 2009
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.
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.
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.
25 #include <epan/packet.h>
26 #include "packet-usb.h"
27 #include "packet-usb-hid.h"
29 void proto_register_usb_hid(void);
30 void proto_reg_handoff_usb_hid(void);
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;
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;
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;
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;
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;
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;
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;
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"};
117 struct usb_hid_global_state {
118 unsigned int usage_page;
122 /* HID class specific descriptor types */
123 #define USB_DT_HID 33
124 static const value_string hid_descriptor_type_vals[] = {
128 static value_string_ext hid_descriptor_type_vals_ext =
129 VALUE_STRING_EXT_INIT(hid_descriptor_type_vals);
132 #define USBHID_SIZE_MASK 0x03
133 #define USBHID_TYPE_MASK 0x0C
134 #define USBHID_TAG_MASK 0xF0
136 static const value_string usb_hid_item_bSize_vals[] = {
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"},
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"},
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"},
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
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"},
229 static const value_string usb_hid_longitem_bTag_vals[] = {
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]"},
247 static const value_string usb_hid_globalitem_unit_exp_vals[] = {
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]"},
303 /* Dissector for the data in a HID main report. */
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)
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);
321 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
324 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit8, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
326 proto_tree_add_boolean_format_value(tree, hf_usb_hid_mainitem_bit8, tvb, offset, 0, FALSE, "Buffered bytes (default, no second byte present)");
329 case USBHID_MAINITEM_TAG_COLLECTION:
330 proto_tree_add_item(tree, hf_usb_hid_mainitem_colltype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
332 case USBHID_MAINITEM_TAG_ENDCOLLECTION:
336 proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
343 /* Dissector for the data in a HID main report. */
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)
348 case USBHID_GLOBALITEM_TAG_USAGE_PAGE:
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;
356 proto_tree_add_item(tree, hf_usb_hid_globalitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
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);
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);
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);
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);
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);
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);
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);
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);
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);
391 case USBHID_GLOBALITEM_TAG_PUSH:
392 proto_tree_add_item(tree, hf_usb_hid_globalitem_push, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
394 case USBHID_GLOBALITEM_TAG_POP:
395 proto_tree_add_item(tree, hf_usb_hid_globalitem_pop, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
398 proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
405 /* Dissector for the data in a HID main report. */
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)
409 unsigned int usage_page = 0xffffffff; /* in case bSize == 0 */
412 case USBHID_LOCALITEM_TAG_USAGE_PAGE:
415 proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
417 /* Only lower few bits given, need to combine with last global ID */
419 usage_page = (global->usage_page & 0xFFFFFF00) | tvb_get_guint8(tvb, offset);
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);
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);
428 case USBHID_LOCALITEM_TAG_USAGE_MAX:
429 proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
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);
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);
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);
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);
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);
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);
449 case USBHID_LOCALITEM_TAG_DELIMITER:
450 proto_tree_add_item(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
453 proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
460 /* Dissector for individual HID report items. Recursive. */
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)
464 proto_item *subitem=NULL;
465 proto_tree *tree=NULL, *subtree=NULL;
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));
474 while (tvb_reported_length_remaining(tvb, offset) > 0)
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;
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;
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;
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;
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;
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")
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);
514 if ((bType == 3) && (bTag == 16)) {
516 bSize = tvb_get_guint8(tvb, offset);
517 proto_tree_add_item(subtree, hf_usb_hid_item_bDataSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
519 proto_tree_add_item(subtree, hf_usb_hid_item_bLongItemTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
521 proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
526 case USBHID_ITEMTYPE_MAIN:
527 offset = dissect_usb_hid_report_mainitem_data(pinfo, subtree, tvb, offset, bSize, bTag);
529 case USBHID_ITEMTYPE_GLOBAL:
530 offset = dissect_usb_hid_report_globalitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
532 case USBHID_ITEMTYPE_LOCAL:
533 offset = dissect_usb_hid_report_localitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
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);
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 */
556 /* Dissector for HID "GET DESCRIPTOR" subtype. */
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)
560 proto_item *item=NULL;
561 proto_tree *tree=NULL;
562 int old_offset=offset;
563 struct usb_hid_global_state initial_global;
565 memset(&initial_global, 0, sizeof(struct usb_hid_global_state));
568 item = proto_tree_add_protocol_format(parent_tree, proto_usb_hid, tvb, offset,
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);
573 proto_item_set_len(item, offset-old_offset);
579 /* Dissector for HID GET_REPORT request. See USBHID 1.11, Chapter 7.2.1 Get_Report Request */
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_)
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);
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);
595 proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
598 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
601 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
605 /* Dissector for HID SET_REPORT request. See USBHID 1.11, Chapter 7.2.2 Set_Report Request */
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_)
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);
618 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
620 proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
623 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
626 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
631 /* Dissector for HID GET_IDLE request. See USBHID 1.11, Chapter 7.2.3 Get_Idle Request */
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_)
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);
644 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
646 proto_tree_add_item(subtree, hf_usb_hid_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
649 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
652 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
656 /* Dissector for HID SET_IDLE request. See USBHID 1.11, Chapter 7.2.4 Set_Idle Request */
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_)
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);
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);
672 proto_tree_add_item(subtree, hf_usb_hid_duration, tvb, offset, 1, ENC_LITTLE_ENDIAN);
675 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
678 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
682 /* Dissector for HID GET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.5 Get_Protocol Request */
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_)
689 proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
692 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
695 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
699 /* Dissector for HID SET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.6 Set_Protocol Request */
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_)
706 proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
709 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
712 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
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);
719 typedef struct _usb_setup_dissector_table_t {
721 usb_setup_dissector dissector;
722 } usb_setup_dissector_table_t;
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
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 },
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" },
754 static const value_string usb_hid_report_type_vals[] = {
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
767 dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
770 usb_conv_info_t *usb_conv_info;
771 usb_trans_info_t *usb_trans_info;
773 usb_setup_dissector dissector;
774 const usb_setup_dissector_table_t *tmp;
776 usb_conv_info = (usb_conv_info_t *)data;
779 usb_trans_info = usb_conv_info->usb_trans_info;
783 is_request = (pinfo->srcport==NO_ENDPOINT);
785 /* See if we can find a class specific dissector for this request */
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;
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.
805 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
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");
812 proto_tree_add_item(tree, hf_usb_hid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
816 dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info);
817 return tvb_captured_length(tvb);
820 /* dissect a descriptor that is specific to the HID class */
822 dissect_usb_hid_class_descriptors(tvbuff_t *tvb, packet_info *pinfo _U_,
823 proto_tree *tree, void *data _U_)
828 proto_tree *desc_tree;
832 type = tvb_get_guint8(tvb, 1);
834 /* for now, we only handle the HID descriptor here */
835 if (type != USB_DT_HID)
838 desc_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_usb_hid_descriptor, &ti, "HID DESCRIPTOR");
840 dissect_usb_descriptor_header(desc_tree, tvb, offset,
841 &hid_descriptor_type_vals_ext);
843 proto_tree_add_item(desc_tree, hf_usb_hid_bcdHID,
844 tvb, offset, 2, ENC_LITTLE_ENDIAN);
846 proto_tree_add_item(desc_tree, hf_usb_hid_bCountryCode,
847 tvb, offset, 1, ENC_LITTLE_ENDIAN);
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);
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);
857 proto_tree_add_item(desc_tree, hf_usb_hid_wDescriptorLength,
858 tvb, offset, 2, ENC_LITTLE_ENDIAN);
862 proto_item_set_len(ti, offset);
868 proto_register_usb_hid(void)
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 }},
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 }},
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 }},
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 }},
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 }},
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 }},
895 { &hf_usb_hid_item_bDataSize,
896 { "bDataSize", "usbhid.item.bDataSize", FT_UINT8, BASE_DEC,
897 NULL, 0, NULL, HFILL }},
899 { &hf_usb_hid_item_bLongItemTag,
900 { "bTag", "usbhid.item.bLongItemTag", FT_UINT8, BASE_HEX,
901 NULL, 0, NULL, HFILL }},
903 /* Main-report item data */
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 }},
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 }},
913 { &hf_usb_hid_mainitem_bit2,
914 { "Coordinates", "usbhid.item.main.relative", FT_BOOLEAN, 9,
915 TFS(&tfs_mainitem_bit2), 1<<2, NULL, HFILL }},
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 }},
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 }},
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 }},
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 }},
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 }},
937 { &hf_usb_hid_mainitem_bit7_input,
938 { "[Reserved]", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
939 NULL, 1<<7, NULL, HFILL }},
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 }},
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 }},
949 /* Global-report item data */
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 }},
955 { &hf_usb_hid_globalitem_log_min,
956 { "Logical minimum", "usbhid.item.global.log_min", FT_UINT8, BASE_DEC,
957 NULL, 0, NULL, HFILL }},
959 { &hf_usb_hid_globalitem_log_max,
960 { "Logical maximum", "usbhid.item.global.log_max", FT_UINT8, BASE_DEC,
961 NULL, 0, NULL, HFILL }},
963 { &hf_usb_hid_globalitem_phy_min,
964 { "Physical minimum", "usbhid.item.global.phy_min", FT_UINT8, BASE_DEC,
965 NULL, 0, NULL, HFILL }},
967 { &hf_usb_hid_globalitem_phy_max,
968 { "Physical maximum", "usbhid.item.global.phy_max", FT_UINT8, BASE_DEC,
969 NULL, 0, NULL, HFILL }},
971 { &hf_usb_hid_globalitem_unit_exp,
972 { "Unit exponent", "usbhid.item.global.unit_exp", FT_UINT8, BASE_DEC,
973 NULL, 0, NULL, HFILL }},
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 }},
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 }},
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 }},
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 }},
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 }},
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 }},
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 }},
1003 { &hf_usb_hid_globalitem_report_size,
1004 { "Report size", "usbhid.item.global.report_size", FT_UINT8, BASE_DEC,
1005 NULL, 0, NULL, HFILL }},
1007 { &hf_usb_hid_globalitem_report_id,
1008 { "Report ID", "usbhid.item.global.report_id", FT_UINT8, BASE_HEX,
1009 NULL, 0, NULL, HFILL }},
1011 { &hf_usb_hid_globalitem_report_count,
1012 { "Report count", "usbhid.item.global.report_count", FT_UINT8, BASE_DEC,
1013 NULL, 0, NULL, HFILL }},
1015 { &hf_usb_hid_globalitem_push,
1016 { "Push", "usbhid.item.global.push", FT_UINT8, BASE_HEX,
1017 NULL, 0, NULL, HFILL }},
1019 { &hf_usb_hid_globalitem_pop,
1020 { "Pop", "usbhid.item.global.pop", FT_UINT8, BASE_HEX,
1021 NULL, 0, NULL, HFILL }},
1023 /* Local-report item data */
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 }},
1029 { &hf_usb_hid_localitem_usage_min,
1030 { "Usage minimum", "usbhid.item.local.usage_min", FT_UINT8, BASE_HEX,
1031 NULL, 0, NULL, HFILL }},
1034 { &hf_usb_hid_localitem_usage_max,
1035 { "Usage maximum", "usbhid.item.local.usage_max", FT_UINT8, BASE_HEX,
1036 NULL, 0, NULL, HFILL }},
1039 { &hf_usb_hid_localitem_desig_index,
1040 { "Designator index", "usbhid.item.local.desig_index", FT_UINT8, BASE_HEX,
1041 NULL, 0, NULL, HFILL }},
1043 { &hf_usb_hid_localitem_desig_min,
1044 { "Designator minimum", "usbhid.item.local.desig_min", FT_UINT8, BASE_HEX,
1045 NULL, 0, NULL, HFILL }},
1047 { &hf_usb_hid_localitem_desig_max,
1048 { "Designator maximum", "usbhid.item.local.desig_max", FT_UINT8, BASE_HEX,
1049 NULL, 0, NULL, HFILL }},
1051 { &hf_usb_hid_localitem_string_index,
1052 { "String index", "usbhid.item.local.string_index", FT_UINT8, BASE_HEX,
1053 NULL, 0, NULL, HFILL }},
1055 { &hf_usb_hid_localitem_string_min,
1056 { "String minimum", "usbhid.item.local.string_min", FT_UINT8, BASE_HEX,
1057 NULL, 0, NULL, HFILL }},
1059 { &hf_usb_hid_localitem_string_max,
1060 { "String maximum", "usbhid.item.local.string_max", FT_UINT8, BASE_HEX,
1061 NULL, 0, NULL, HFILL }},
1063 { &hf_usb_hid_localitem_delimiter,
1064 { "Delimiter", "usbhid.item.local.delimiter", FT_UINT8, BASE_HEX,
1065 NULL, 0, NULL, HFILL }},
1068 { &hf_usb_hid_item_unk_data,
1069 { "Item data", "usbhid.item.data", FT_BYTES, BASE_NONE,
1070 NULL, 0, NULL, HFILL }},
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,
1077 { &hf_usb_hid_value,
1078 { "wValue", "usbhid.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
1081 { &hf_usb_hid_index,
1082 { "wIndex", "usbhid.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
1085 { &hf_usb_hid_length,
1086 { "wLength", "usbhid.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1089 { &hf_usb_hid_report_type,
1090 { "ReportType", "usbhid.setup.ReportType", FT_UINT8, BASE_DEC,
1091 VALS(usb_hid_report_type_vals), 0x0,
1094 { &hf_usb_hid_report_id,
1095 { "ReportID", "usbhid.setup.ReportID", FT_UINT8, BASE_DEC, NULL, 0x0,
1098 { &hf_usb_hid_duration,
1099 { "Duration", "usbhid.setup.Duration", FT_UINT8, BASE_DEC, NULL, 0x0,
1103 { "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
1106 /* components of the HID descriptor */
1107 { &hf_usb_hid_bcdHID,
1108 { "bcdHID", "usbhid.descriptor.hid.bcdHID", FT_UINT16, BASE_HEX, NULL, 0x0,
1111 { &hf_usb_hid_bCountryCode,
1112 { "bCountryCode", "usbhid.descriptor.hid.bCountryCode", FT_UINT8,
1113 BASE_HEX, NULL, 0x0, NULL, HFILL }},
1115 { &hf_usb_hid_bNumDescriptors,
1116 { "bNumDescriptors", "usbhid.descriptor.hid.bNumDescriptors", FT_UINT8,
1117 BASE_DEC, NULL, 0x0, NULL, HFILL }},
1119 { &hf_usb_hid_bDescriptorType,
1120 { "bDescriptorType", "usbhid.descriptor.hid.bDescriptorType", FT_UINT8,
1121 BASE_HEX, NULL, 0x0, NULL, HFILL }},
1123 { &hf_usb_hid_wDescriptorLength,
1124 { "wDescriptorLength", "usbhid.descriptor.hid.wDescriptorLength", FT_UINT16,
1125 BASE_DEC, NULL, 0x0, NULL, HFILL }}
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
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));
1141 proto_reg_handoff_usb_hid(void)
1143 dissector_handle_t usb_hid_control_handle, usb_hid_descr_handle;
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);
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);
1154 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1159 * indent-tabs-mode: nil
1162 * vi: set shiftwidth=4 tabstop=8 expandtab:
1163 * :indentSize=4:tabSize=8:noTabs=true: