6 * By Adam Nielsen <a.nielsen@shikadi.net> 2009
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <epan/packet.h>
31 #include "packet-usb.h"
32 #include "packet-usb-hid.h"
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;
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;
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;
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;
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;
92 static int hf_usb_hid_request = -1;
93 static int hf_usb_hid_value = -1;
94 static int hf_usb_hid_index = -1;
95 static int hf_usb_hid_length = -1;
96 static int hf_usb_hid_report_type = -1;
97 static int hf_usb_hid_report_id = -1;
98 static int hf_usb_hid_duration = -1;
99 static int hf_usb_hid_zero = -1;
101 static const true_false_string tfs_mainitem_bit0 = {"Data", "Constant"};
102 static const true_false_string tfs_mainitem_bit1 = {"Array", "Variable"};
103 static const true_false_string tfs_mainitem_bit2 = {"Absolute", "Relative"};
104 static const true_false_string tfs_mainitem_bit3 = {"No wrap", "Wrap"};
105 static const true_false_string tfs_mainitem_bit4 = {"Linear", "Nonlinear"};
106 static const true_false_string tfs_mainitem_bit5 = {"Preferred state", "No preferred state"};
107 static const true_false_string tfs_mainitem_bit6 = {"No null position", "Null state"};
108 static const true_false_string tfs_mainitem_bit7 = {"Non-volatile", "Volatile"};
109 static const true_false_string tfs_mainitem_bit8 = {"Bit field", "Buffered bytes"};
112 struct usb_hid_global_state {
113 unsigned int usage_page;
116 #define USBHID_SIZE_MASK 0x03
117 #define USBHID_TYPE_MASK 0x0C
118 #define USBHID_TAG_MASK 0xF0
120 static const value_string usb_hid_item_bSize_vals[] = {
128 #define USBHID_ITEMTYPE_MAIN 0
129 #define USBHID_ITEMTYPE_GLOBAL 1
130 #define USBHID_ITEMTYPE_LOCAL 2
131 #define USBHID_ITEMTYPE_LONG 3
132 static const value_string usb_hid_item_bType_vals[] = {
133 {USBHID_ITEMTYPE_MAIN, "Main"},
134 {USBHID_ITEMTYPE_GLOBAL, "Global"},
135 {USBHID_ITEMTYPE_LOCAL, "Local"},
136 {USBHID_ITEMTYPE_LONG, "Long item"},
140 #define USBHID_MAINITEM_TAG_INPUT 8
141 #define USBHID_MAINITEM_TAG_OUTPUT 9
142 #define USBHID_MAINITEM_TAG_FEATURE 11
143 #define USBHID_MAINITEM_TAG_COLLECTION 10
144 #define USBHID_MAINITEM_TAG_ENDCOLLECTION 12
145 static const value_string usb_hid_mainitem_bTag_vals[] = {
146 {USBHID_MAINITEM_TAG_INPUT, "Input"},
147 {USBHID_MAINITEM_TAG_OUTPUT, "Output"},
148 {USBHID_MAINITEM_TAG_FEATURE, "Feature"},
149 {USBHID_MAINITEM_TAG_COLLECTION, "Collection"},
150 {USBHID_MAINITEM_TAG_ENDCOLLECTION, "End collection"},
153 #define USBHID_GLOBALITEM_TAG_USAGE_PAGE 0
154 #define USBHID_GLOBALITEM_TAG_LOG_MIN 1
155 #define USBHID_GLOBALITEM_TAG_LOG_MAX 2
156 #define USBHID_GLOBALITEM_TAG_PHY_MIN 3
157 #define USBHID_GLOBALITEM_TAG_PHY_MAX 4
158 #define USBHID_GLOBALITEM_TAG_UNIT_EXP 5
159 #define USBHID_GLOBALITEM_TAG_UNIT 6
160 #define USBHID_GLOBALITEM_TAG_REPORT_SIZE 7
161 #define USBHID_GLOBALITEM_TAG_REPORT_ID 8
162 #define USBHID_GLOBALITEM_TAG_REPORT_COUNT 9
163 #define USBHID_GLOBALITEM_TAG_PUSH 10
164 #define USBHID_GLOBALITEM_TAG_POP 11
165 static const value_string usb_hid_globalitem_bTag_vals[] = {
166 {USBHID_GLOBALITEM_TAG_USAGE_PAGE, "Usage"},
167 {USBHID_GLOBALITEM_TAG_LOG_MIN, "Logical minimum"},
168 {USBHID_GLOBALITEM_TAG_LOG_MAX, "Logical maximum"},
169 {USBHID_GLOBALITEM_TAG_PHY_MIN, "Physical minimum"},
170 {USBHID_GLOBALITEM_TAG_PHY_MAX, "Physical maximum"},
171 {USBHID_GLOBALITEM_TAG_UNIT_EXP, "Unit exponent"},
172 {USBHID_GLOBALITEM_TAG_UNIT, "Units"},
173 {USBHID_GLOBALITEM_TAG_REPORT_SIZE, "Report size"},
174 {USBHID_GLOBALITEM_TAG_REPORT_ID, "Report ID"},
175 {USBHID_GLOBALITEM_TAG_REPORT_COUNT, "Report count"},
176 {USBHID_GLOBALITEM_TAG_PUSH, "Push"},
177 {USBHID_GLOBALITEM_TAG_POP, "Pop"},
184 #define USBHID_LOCALITEM_TAG_USAGE_PAGE 0
185 #define USBHID_LOCALITEM_TAG_USAGE_MIN 1
186 #define USBHID_LOCALITEM_TAG_USAGE_MAX 2
187 #define USBHID_LOCALITEM_TAG_DESIG_INDEX 3
188 #define USBHID_LOCALITEM_TAG_DESIG_MIN 4
189 #define USBHID_LOCALITEM_TAG_DESIG_MAX 5
191 #define USBHID_LOCALITEM_TAG_STRING_INDEX 7
192 #define USBHID_LOCALITEM_TAG_STRING_MIN 8
193 #define USBHID_LOCALITEM_TAG_STRING_MAX 9
194 #define USBHID_LOCALITEM_TAG_DELIMITER 10 /* Also listed as reserved in spec! */
195 static const value_string usb_hid_localitem_bTag_vals[] = {
196 {USBHID_LOCALITEM_TAG_USAGE_PAGE, "Usage"},
197 {USBHID_LOCALITEM_TAG_USAGE_MIN, "Usage minimum"},
198 {USBHID_LOCALITEM_TAG_USAGE_MAX, "Usage maximum"},
199 {USBHID_LOCALITEM_TAG_DESIG_INDEX, "Designator index"},
200 {USBHID_LOCALITEM_TAG_DESIG_MIN, "Designator minimum"},
201 {USBHID_LOCALITEM_TAG_DESIG_MAX, "Designator maximum"},
202 {USBHID_LOCALITEM_TAG_STRING_INDEX, "String index"},
203 {USBHID_LOCALITEM_TAG_STRING_MIN, "String minimum"},
204 {USBHID_LOCALITEM_TAG_STRING_MAX, "String maximum"},
205 {USBHID_LOCALITEM_TAG_DELIMITER, "Delimiter"},
213 static const value_string usb_hid_longitem_bTag_vals[] = {
218 static const range_string usb_hid_mainitem_colltype_vals[] = {
219 {0x00, 0x00, "Physical"},
220 {0x01, 0x01, "Application"},
221 {0x02, 0x02, "Logical"},
222 {0x03, 0x03, "Report"},
223 {0x04, 0x04, "Named array"},
224 {0x05, 0x05, "Usage switch"},
225 {0x06, 0x06, "Usage modifier"},
226 {0x07, 0x7F, "[Reserved]"},
227 {0x80, 0xFF, "[Vendor-defined]"},
231 static const value_string usb_hid_globalitem_unit_exp_vals[] = {
250 static const range_string usb_hid_item_usage_vals[] = {
251 {0x00, 0x00, "Undefined"},
252 {0x01, 0x01, "Generic desktop controls"},
253 {0x02, 0x02, "Simulation controls"},
254 {0x03, 0x03, "VR controls"},
255 {0x04, 0x04, "Sport controls"},
256 {0x05, 0x05, "Game controls"},
257 {0x06, 0x06, "Generic device controls"},
258 {0x07, 0x07, "Keyboard/keypad"},
259 {0x08, 0x08, "LEDs"},
260 {0x09, 0x09, "Button"},
261 {0x0A, 0x0A, "Ordinal"},
262 {0x0B, 0x0B, "Telephony"},
263 {0x0C, 0x0C, "Consumer"},
264 {0x0D, 0x0D, "Digitizer"},
265 {0x0E, 0x0E, "[Reserved]"},
266 {0x0F, 0x0F, "Physical Interface Device (PID) page"},
267 {0x10, 0x10, "Unicode"},
268 {0x11, 0x13, "[Reserved]"},
269 {0x14, 0x14, "Alphanumeric display"},
270 {0x15, 0x3F, "[Reserved]"},
271 {0x40, 0x40, "Medical instruments"},
272 {0x41, 0x7F, "[Reserved]"},
273 {0x80, 0x83, "Monitor page"},
274 {0x84, 0x87, "Power page"},
275 {0x88, 0x8B, "[Reserved]"},
276 {0x8C, 0x8C, "Bar code scanner page"},
277 {0x8D, 0x8D, "Scale page"},
278 {0x8E, 0x8E, "Magnetic Stripe Reading (MSR) devices"},
279 {0x8F, 0x8F, "[Reserved Point of Sale page]"},
280 {0x90, 0x90, "Camera control page"},
281 {0x91, 0x91, "Arcade page"},
282 {0x92, 0xFEFF, "[Reserved]"},
283 {0xFF00, 0xFFFF, "[Vendor-defined]"},
287 /* Dissector for the data in a HID main report. */
289 dissect_usb_hid_report_mainitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag)
292 case USBHID_MAINITEM_TAG_INPUT:
293 case USBHID_MAINITEM_TAG_OUTPUT:
294 case USBHID_MAINITEM_TAG_FEATURE:
295 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit0, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
296 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit1, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
297 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit2, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
298 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit3, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
299 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit4, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
300 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit5, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
301 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit6, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
302 if (bTag == USBHID_MAINITEM_TAG_INPUT) {
303 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7_input, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
305 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
308 proto_tree_add_item(tree, hf_usb_hid_mainitem_bit8, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
310 proto_tree_add_text(tree, tvb, offset, 0, "Bits or bytes: Buffered bytes (default, no second byte present)");
313 case USBHID_MAINITEM_TAG_COLLECTION:
314 proto_tree_add_item(tree, hf_usb_hid_mainitem_colltype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
316 case USBHID_MAINITEM_TAG_ENDCOLLECTION:
320 proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
327 /* Dissector for the data in a HID main report. */
329 dissect_usb_hid_report_globalitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag, struct usb_hid_global_state *global)
332 case USBHID_GLOBALITEM_TAG_USAGE_PAGE:
334 case 1: global->usage_page = tvb_get_guint8(tvb, offset); break;
335 case 2: global->usage_page = tvb_get_letohs(tvb, offset); break;
336 case 3: global->usage_page = tvb_get_letoh24(tvb, offset); break;
337 case 4: global->usage_page = tvb_get_letohl(tvb, offset); break;
338 default: global->usage_page = 0; break;
340 proto_tree_add_item(tree, hf_usb_hid_globalitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
342 case USBHID_GLOBALITEM_TAG_LOG_MIN:
343 proto_tree_add_item(tree, hf_usb_hid_globalitem_log_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
345 case USBHID_GLOBALITEM_TAG_LOG_MAX:
346 proto_tree_add_item(tree, hf_usb_hid_globalitem_log_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
348 case USBHID_GLOBALITEM_TAG_PHY_MIN:
349 proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
351 case USBHID_GLOBALITEM_TAG_PHY_MAX:
352 proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
354 case USBHID_GLOBALITEM_TAG_UNIT_EXP:
355 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_exp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
357 case USBHID_GLOBALITEM_TAG_UNIT:
358 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_sys, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
359 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_len, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
360 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_mass, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
361 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_time, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
362 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_temp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
363 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_current, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
364 proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_brightness, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
366 case USBHID_GLOBALITEM_TAG_REPORT_SIZE:
367 proto_tree_add_item(tree, hf_usb_hid_globalitem_report_size, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
369 case USBHID_GLOBALITEM_TAG_REPORT_ID:
370 proto_tree_add_item(tree, hf_usb_hid_globalitem_report_id, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
372 case USBHID_GLOBALITEM_TAG_REPORT_COUNT:
373 proto_tree_add_item(tree, hf_usb_hid_globalitem_report_count, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
375 case USBHID_GLOBALITEM_TAG_PUSH:
376 proto_tree_add_item(tree, hf_usb_hid_globalitem_push, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
378 case USBHID_GLOBALITEM_TAG_POP:
379 proto_tree_add_item(tree, hf_usb_hid_globalitem_pop, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
382 proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
389 /* Dissector for the data in a HID main report. */
391 dissect_usb_hid_report_localitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag, struct usb_hid_global_state *global)
393 unsigned int usage_page = 0xffffffff; /* in case bSize == 0 */
396 case USBHID_LOCALITEM_TAG_USAGE_PAGE:
399 proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
401 /* Only lower few bits given, need to combine with last global ID */
403 usage_page = (global->usage_page & 0xFFFFFF00) | tvb_get_guint8(tvb, offset);
405 usage_page = (global->usage_page & 0xFFFF0000) | tvb_get_ntohs(tvb, offset);
406 proto_tree_add_text(tree, tvb, offset, bSize, "Usage: %s (0x%08x)",
407 rval_to_str(usage_page, usb_hid_item_usage_vals, "[Unknown page!]"),
411 case USBHID_LOCALITEM_TAG_USAGE_MIN:
412 proto_tree_add_item(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
414 case USBHID_LOCALITEM_TAG_USAGE_MAX:
415 proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
417 case USBHID_LOCALITEM_TAG_DESIG_INDEX:
418 proto_tree_add_item(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
420 case USBHID_LOCALITEM_TAG_DESIG_MIN:
421 proto_tree_add_item(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
423 case USBHID_LOCALITEM_TAG_DESIG_MAX:
424 proto_tree_add_item(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
426 case USBHID_LOCALITEM_TAG_STRING_INDEX:
427 proto_tree_add_item(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
429 case USBHID_LOCALITEM_TAG_STRING_MIN:
430 proto_tree_add_item(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
432 case USBHID_LOCALITEM_TAG_STRING_MAX:
433 proto_tree_add_item(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
435 case USBHID_LOCALITEM_TAG_DELIMITER:
436 proto_tree_add_item(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
439 proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
446 /* Dissector for individual HID report items. Recursive. */
448 dissect_usb_hid_report_item(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_, const struct usb_hid_global_state *global)
450 proto_item *item=NULL, *subitem=NULL;
451 proto_tree *tree=NULL, *subtree=NULL;
454 unsigned int bSize, bType, bTag;
455 const value_string *usb_hid_cur_bTag_vals;
456 int hf_usb_hid_curitem_bTag;
457 struct usb_hid_global_state cur_global;
458 memcpy(&cur_global, global, sizeof(struct usb_hid_global_state));
460 while (tvb_reported_length_remaining(tvb, offset))
464 tmp = tvb_get_guint8(tvb, offset);
465 bSize = tmp & USBHID_SIZE_MASK;
466 if (bSize == 3) bSize++; /* 3 == four bytes */
467 bType = (tmp & USBHID_TYPE_MASK) >> 2;
468 bTag = (tmp & USBHID_TAG_MASK) >> 4;
471 case USBHID_ITEMTYPE_MAIN:
472 hf_usb_hid_curitem_bTag = hf_usb_hid_mainitem_bTag;
473 usb_hid_cur_bTag_vals = usb_hid_mainitem_bTag_vals;
475 case USBHID_ITEMTYPE_GLOBAL:
476 hf_usb_hid_curitem_bTag = hf_usb_hid_globalitem_bTag;
477 usb_hid_cur_bTag_vals = usb_hid_globalitem_bTag_vals;
479 case USBHID_ITEMTYPE_LOCAL:
480 hf_usb_hid_curitem_bTag = hf_usb_hid_localitem_bTag;
481 usb_hid_cur_bTag_vals = usb_hid_localitem_bTag_vals;
483 default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
484 hf_usb_hid_curitem_bTag = hf_usb_hid_longitem_bTag;
485 usb_hid_cur_bTag_vals = usb_hid_longitem_bTag_vals;
489 subitem = proto_tree_add_text(parent_tree, tvb, offset, bSize + 1, "%s item (%s)",
490 val_to_str(bType, usb_hid_item_bType_vals, "Unknown/%u"),
491 val_to_str(bTag, usb_hid_cur_bTag_vals, "Unknown/%u tag")
493 subtree = proto_item_add_subtree(subitem, ett_usb_hid_item_header);
495 item = proto_tree_add_text(subtree, tvb, offset, 1, "Header");
496 tree = proto_item_add_subtree(item, ett_usb_hid_item_header);
497 proto_tree_add_item(tree, hf_usb_hid_item_bSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
498 proto_tree_add_item(tree, hf_usb_hid_item_bType, tvb, offset, 1, ENC_LITTLE_ENDIAN);
499 proto_tree_add_item(tree, hf_usb_hid_curitem_bTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
501 if ((bType == 3) && (bTag == 16)) {
503 bSize = tvb_get_guint8(tvb, offset);
504 proto_tree_add_item(subtree, hf_usb_hid_item_bDataSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
506 proto_tree_add_item(subtree, hf_usb_hid_item_bLongItemTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
508 proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
513 case USBHID_ITEMTYPE_MAIN:
514 offset = dissect_usb_hid_report_mainitem_data(pinfo, subtree, tvb, offset, bSize, bTag);
516 case USBHID_ITEMTYPE_GLOBAL:
517 offset = dissect_usb_hid_report_globalitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
519 case USBHID_ITEMTYPE_LOCAL:
520 offset = dissect_usb_hid_report_localitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
522 default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
523 proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
529 if (bType == USBHID_ITEMTYPE_MAIN) {
530 if (bTag == USBHID_MAINITEM_TAG_COLLECTION) {
531 /* Begin collection, nest following elements under us */
532 offset = dissect_usb_hid_report_item(pinfo, subtree, tvb, offset, usb_trans_info, usb_conv_info, &cur_global);
533 proto_item_set_len(subitem, offset-old_offset);
534 } else if (bTag == USBHID_MAINITEM_TAG_ENDCOLLECTION) {
535 /* End collection, break out to parent tree item */
543 /* Dissector for HID "GET DESCRIPTOR" subtype. */
545 dissect_usb_hid_get_report_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
547 proto_item *item=NULL;
548 proto_tree *tree=NULL;
549 int old_offset=offset;
550 struct usb_hid_global_state initial_global;
551 memset(&initial_global, 0, sizeof(struct usb_hid_global_state));
554 item = proto_tree_add_protocol_format(parent_tree, proto_usb_hid, tvb, offset,
556 tree = proto_item_add_subtree(item, ett_usb_hid_report);
557 offset = dissect_usb_hid_report_item(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info, &initial_global);
559 proto_item_set_len(item, offset-old_offset);
565 /* Dissector for HID GET_REPORT request. See USBHID 1.11, Chapter 7.2.1 Get_Report Request */
567 dissect_usb_hid_get_report(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
569 proto_item *item = NULL;
570 proto_tree *subtree = NULL;
573 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
574 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
576 /* Report Type in the high byte, Report ID in the low byte */
577 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
579 proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
582 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
585 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
591 /* Dissector for HID SET_REPORT request. See USBHID 1.11, Chapter 7.2.2 Set_Report Request */
593 dissect_usb_hid_set_report(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
595 proto_item *item = NULL;
596 proto_tree *subtree = NULL;
599 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
600 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
602 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
604 proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
607 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
610 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
617 /* Dissector for HID GET_IDLE request. See USBHID 1.11, Chapter 7.2.3 Get_Idle Request */
619 dissect_usb_hid_get_idle(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
621 proto_item *item = NULL;
622 proto_tree *subtree = NULL;
625 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
626 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
628 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
630 proto_tree_add_item(subtree, hf_usb_hid_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
633 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
636 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
642 /* Dissector for HID SET_IDLE request. See USBHID 1.11, Chapter 7.2.4 Set_Idle Request */
644 dissect_usb_hid_set_idle(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
646 proto_item *item = NULL;
647 proto_tree *subtree = NULL;
650 item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
651 subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
653 /* Duration in the high byte, Report ID in the low byte */
654 proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
656 proto_tree_add_item(subtree, hf_usb_hid_duration, tvb, offset, 1, ENC_LITTLE_ENDIAN);
659 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
662 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
668 /* Dissector for HID GET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.5 Get_Protocol Request */
670 dissect_usb_hid_get_protocol(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
673 proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
676 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
679 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
685 /* Dissector for HID SET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.6 Set_Protocol Request */
687 dissect_usb_hid_set_protocol(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
690 proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
693 proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
696 proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
703 typedef void (*usb_setup_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info, usb_conv_info_t *usb_conv_info);
705 typedef struct _usb_setup_dissector_table_t {
707 usb_setup_dissector dissector;
708 } usb_setup_dissector_table_t;
711 /* USBHID 1.11, Chapter 7.2 Class-Specific Requests */
712 #define USB_HID_SETUP_GET_REPORT 0x01
713 #define USB_HID_SETUP_GET_IDLE 0x02
714 #define USB_HID_SETUP_GET_PROTOCOL 0x03
715 /* 0x04..0x08: Reserved */
716 #define USB_HID_SETUP_SET_REPORT 0x09
717 #define USB_HID_SETUP_SET_IDLE 0x0A
718 #define USB_HID_SETUP_SET_PROTOCOL 0x0B
720 static const usb_setup_dissector_table_t setup_dissectors[] = {
721 { USB_HID_SETUP_GET_REPORT, dissect_usb_hid_get_report },
722 { USB_HID_SETUP_GET_IDLE, dissect_usb_hid_get_idle },
723 { USB_HID_SETUP_GET_PROTOCOL, dissect_usb_hid_get_protocol },
724 { USB_HID_SETUP_SET_REPORT, dissect_usb_hid_set_report },
725 { USB_HID_SETUP_SET_IDLE, dissect_usb_hid_set_idle },
726 { USB_HID_SETUP_SET_PROTOCOL, dissect_usb_hid_set_protocol },
730 static const value_string setup_request_names_vals[] = {
731 { USB_HID_SETUP_GET_REPORT, "GET_REPORT" },
732 { USB_HID_SETUP_GET_IDLE, "GET_IDLE" },
733 { USB_HID_SETUP_GET_PROTOCOL, "GET_PROTOCOL" },
734 { USB_HID_SETUP_SET_REPORT, "SET_REPORT" },
735 { USB_HID_SETUP_SET_IDLE, "SET_IDLE" },
736 { USB_HID_SETUP_SET_PROTOCOL, "SET_PROTOCOL" },
740 static const value_string usb_hid_report_type_vals[] = {
747 /* Dissector for HID class-specific control request as defined in
748 * USBHID 1.11, Chapter 7.2.
749 * Returns TRUE if a class specific dissector was found
750 * and FALSE otherwise.
753 dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
756 usb_conv_info_t *usb_conv_info;
757 usb_trans_info_t *usb_trans_info;
759 usb_setup_dissector dissector;
760 const usb_setup_dissector_table_t *tmp;
762 is_request = (pinfo->srcport==NO_ENDPOINT);
764 usb_conv_info = pinfo->usb_conv_info;
765 usb_trans_info = usb_conv_info->usb_trans_info;
767 /* See if we can find a class specific dissector for this request */
770 /* Check valid values for bmRequestType. See Chapter 7.2 in USBHID 1.11 */
771 if ((usb_trans_info->setup.requesttype & 0x7F) ==
772 ((RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_INTERFACE)) {
773 for (tmp = setup_dissectors; tmp->dissector; tmp++) {
774 if (tmp->request == usb_trans_info->setup.request) {
775 dissector = tmp->dissector;
780 /* No, we could not find any class specific dissector for this request
781 * return FALSE and let USB try any of the standard requests.
787 col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
789 if (check_col(pinfo->cinfo, COL_INFO)) {
790 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
791 val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
792 is_request ? "Request" : "Response");
796 proto_tree_add_item(tree, hf_usb_hid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
800 dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
805 proto_register_usb_hid(void)
807 static hf_register_info hf[] = {
808 { &hf_usb_hid_item_bSize,
809 { "bSize", "usbhid.item.bSize", FT_UINT8, BASE_DEC,
810 VALS(usb_hid_item_bSize_vals), USBHID_SIZE_MASK, NULL, HFILL }},
812 { &hf_usb_hid_item_bType,
813 { "bType", "usbhid.item.bType", FT_UINT8, BASE_DEC,
814 VALS(usb_hid_item_bType_vals), USBHID_TYPE_MASK, NULL, HFILL }},
816 { &hf_usb_hid_mainitem_bTag,
817 { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
818 VALS(usb_hid_mainitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
820 { &hf_usb_hid_globalitem_bTag,
821 { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
822 VALS(usb_hid_globalitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
824 { &hf_usb_hid_localitem_bTag,
825 { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
826 VALS(usb_hid_localitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
828 { &hf_usb_hid_longitem_bTag,
829 { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
830 VALS(usb_hid_longitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
832 { &hf_usb_hid_item_bDataSize,
833 { "bDataSize", "usbhid.item.bDataSize", FT_UINT8, BASE_DEC,
834 NULL, 0, NULL, HFILL }},
836 { &hf_usb_hid_item_bLongItemTag,
837 { "bTag", "usbhid.item.bLongItemTag", FT_UINT8, BASE_HEX,
838 NULL, 0, NULL, HFILL }},
840 /* Main-report item data */
842 { &hf_usb_hid_mainitem_bit0,
843 { "Data/constant", "usbhid.item.main.readonly", FT_BOOLEAN, 9,
844 TFS(&tfs_mainitem_bit0), 1<<0, NULL, HFILL }},
846 { &hf_usb_hid_mainitem_bit1,
847 { "Data type", "usbhid.item.main.variable", FT_BOOLEAN, 9,
848 TFS(&tfs_mainitem_bit1), 1<<1, NULL, HFILL }},
850 { &hf_usb_hid_mainitem_bit2,
851 { "Coordinates", "usbhid.item.main.relative", FT_BOOLEAN, 9,
852 TFS(&tfs_mainitem_bit2), 1<<2, NULL, HFILL }},
854 { &hf_usb_hid_mainitem_bit3,
855 { "Min/max wraparound", "usbhid.item.main.wrap", FT_BOOLEAN, 9,
856 TFS(&tfs_mainitem_bit3), 1<<3, NULL, HFILL }},
858 { &hf_usb_hid_mainitem_bit4,
859 { "Physical relationship to data", "usbhid.item.main.nonlinear", FT_BOOLEAN, 9,
860 TFS(&tfs_mainitem_bit4), 1<<4, NULL, HFILL }},
862 { &hf_usb_hid_mainitem_bit5,
863 { "Preferred state", "usbhid.item.main.no_preferred_state", FT_BOOLEAN, 9,
864 TFS(&tfs_mainitem_bit5), 1<<5, NULL, HFILL }},
866 { &hf_usb_hid_mainitem_bit6,
867 { "Has null position", "usbhid.item.main.nullstate", FT_BOOLEAN, 9,
868 TFS(&tfs_mainitem_bit6), 1<<6, NULL, HFILL }},
870 { &hf_usb_hid_mainitem_bit7,
871 { "(Non)-volatile", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
872 TFS(&tfs_mainitem_bit7), 1<<7, NULL, HFILL }},
874 { &hf_usb_hid_mainitem_bit7_input,
875 { "[Reserved]", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
876 NULL, 1<<7, NULL, HFILL }},
878 { &hf_usb_hid_mainitem_bit8,
879 { "Bits or bytes", "usbhid.item.main.buffered_bytes", FT_BOOLEAN, 9,
880 TFS(&tfs_mainitem_bit8), 1<<8, NULL, HFILL }},
882 { &hf_usb_hid_mainitem_colltype,
883 { "Collection type", "usbhid.item.main.colltype", FT_UINT8, BASE_HEX,
884 RVALS(usb_hid_mainitem_colltype_vals), 0, NULL, HFILL }},
886 /* Global-report item data */
888 { &hf_usb_hid_globalitem_usage,
889 { "Usage page", "usbhid.item.global.usage", FT_UINT8, BASE_HEX,
890 RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
892 { &hf_usb_hid_globalitem_log_min,
893 { "Logical minimum", "usbhid.item.global.log_min", FT_UINT8, BASE_DEC,
894 NULL, 0, NULL, HFILL }},
896 { &hf_usb_hid_globalitem_log_max,
897 { "Logical maximum", "usbhid.item.global.log_max", FT_UINT8, BASE_DEC,
898 NULL, 0, NULL, HFILL }},
900 { &hf_usb_hid_globalitem_phy_min,
901 { "Physical minimum", "usbhid.item.global.phy_min", FT_UINT8, BASE_DEC,
902 NULL, 0, NULL, HFILL }},
904 { &hf_usb_hid_globalitem_phy_max,
905 { "Physical maximum", "usbhid.item.global.phy_max", FT_UINT8, BASE_DEC,
906 NULL, 0, NULL, HFILL }},
908 { &hf_usb_hid_globalitem_unit_exp,
909 { "Unit exponent", "usbhid.item.global.unit_exp", FT_UINT8, BASE_DEC,
910 NULL, 0, NULL, HFILL }},
912 { &hf_usb_hid_globalitem_unit_sys,
913 { "System", "usbhid.item.global.unit.system", FT_UINT32, BASE_HEX,
914 VALS(usb_hid_globalitem_unit_exp_vals), 0x0000000F, NULL, HFILL }},
916 { &hf_usb_hid_globalitem_unit_len,
917 { "Length", "usbhid.item.global.unit.length", FT_UINT32, BASE_HEX,
918 VALS(usb_hid_globalitem_unit_exp_vals), 0x000000F0, NULL, HFILL }},
920 { &hf_usb_hid_globalitem_unit_mass,
921 { "Mass", "usbhid.item.global.unit.mass", FT_UINT32, BASE_HEX,
922 VALS(usb_hid_globalitem_unit_exp_vals), 0x00000F00, NULL, HFILL }},
924 { &hf_usb_hid_globalitem_unit_time,
925 { "Time", "usbhid.item.global.unit.time", FT_UINT32, BASE_HEX,
926 VALS(usb_hid_globalitem_unit_exp_vals), 0x0000F000, NULL, HFILL }},
928 { &hf_usb_hid_globalitem_unit_temp,
929 { "Temperature", "usbhid.item.global.unit.temperature", FT_UINT32, BASE_HEX,
930 VALS(usb_hid_globalitem_unit_exp_vals), 0x000F0000, NULL, HFILL }},
932 { &hf_usb_hid_globalitem_unit_current,
933 { "Current", "usbhid.item.global.unit.current", FT_UINT32, BASE_HEX,
934 VALS(usb_hid_globalitem_unit_exp_vals), 0x00F00000, NULL, HFILL }},
936 { &hf_usb_hid_globalitem_unit_brightness,
937 { "Luminous intensity", "usbhid.item.global.unit.brightness", FT_UINT32, BASE_HEX,
938 VALS(usb_hid_globalitem_unit_exp_vals), 0x0F000000, NULL, HFILL }},
940 { &hf_usb_hid_globalitem_report_size,
941 { "Report size", "usbhid.item.global.report_size", FT_UINT8, BASE_DEC,
942 NULL, 0, NULL, HFILL }},
944 { &hf_usb_hid_globalitem_report_id,
945 { "Report ID", "usbhid.item.global.report_id", FT_UINT8, BASE_HEX,
946 NULL, 0, NULL, HFILL }},
948 { &hf_usb_hid_globalitem_report_count,
949 { "Report count", "usbhid.item.global.report_count", FT_UINT8, BASE_DEC,
950 NULL, 0, NULL, HFILL }},
952 { &hf_usb_hid_globalitem_push,
953 { "Push", "usbhid.item.global.push", FT_UINT8, BASE_HEX,
954 NULL, 0, NULL, HFILL }},
956 { &hf_usb_hid_globalitem_pop,
957 { "Pop", "usbhid.item.global.pop", FT_UINT8, BASE_HEX,
958 NULL, 0, NULL, HFILL }},
960 /* Local-report item data */
962 { &hf_usb_hid_localitem_usage,
963 { "Usage", "usbhid.item.local.usage", FT_UINT8, BASE_HEX,
964 RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
966 { &hf_usb_hid_localitem_usage_min,
967 { "Usage minimum", "usbhid.item.local.usage_min", FT_UINT8, BASE_HEX,
968 NULL, 0, NULL, HFILL }},
970 { &hf_usb_hid_localitem_usage_max,
971 { "Usage maximum", "usbhid.item.local.usage_max", FT_UINT8, BASE_HEX,
972 NULL, 0, NULL, HFILL }},
974 { &hf_usb_hid_localitem_desig_index,
975 { "Designator index", "usbhid.item.local.desig_index", FT_UINT8, BASE_HEX,
976 NULL, 0, NULL, HFILL }},
978 { &hf_usb_hid_localitem_desig_min,
979 { "Designator minimum", "usbhid.item.local.desig_min", FT_UINT8, BASE_HEX,
980 NULL, 0, NULL, HFILL }},
982 { &hf_usb_hid_localitem_desig_max,
983 { "Designator maximum", "usbhid.item.local.desig_max", FT_UINT8, BASE_HEX,
984 NULL, 0, NULL, HFILL }},
986 { &hf_usb_hid_localitem_string_index,
987 { "String index", "usbhid.item.local.string_index", FT_UINT8, BASE_HEX,
988 NULL, 0, NULL, HFILL }},
990 { &hf_usb_hid_localitem_string_min,
991 { "String minimum", "usbhid.item.local.string_min", FT_UINT8, BASE_HEX,
992 NULL, 0, NULL, HFILL }},
994 { &hf_usb_hid_localitem_string_max,
995 { "String maximum", "usbhid.item.local.string_max", FT_UINT8, BASE_HEX,
996 NULL, 0, NULL, HFILL }},
998 { &hf_usb_hid_localitem_delimiter,
999 { "Delimiter", "usbhid.item.local.delimiter", FT_UINT8, BASE_HEX,
1000 NULL, 0, NULL, HFILL }},
1003 { &hf_usb_hid_item_unk_data,
1004 { "Item data", "usbhid.item.data", FT_BYTES, BASE_NONE,
1005 NULL, 0, NULL, HFILL }},
1007 /* USB HID specific requests */
1008 { &hf_usb_hid_request,
1009 { "bRequest", "usbhid.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
1012 { &hf_usb_hid_value,
1013 { "wValue", "usbhid.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
1016 { &hf_usb_hid_index,
1017 { "wIndex", "usbhid.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
1020 { &hf_usb_hid_length,
1021 { "wLength", "usbhid.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
1024 { &hf_usb_hid_report_type,
1025 { "ReportType", "usbhid.setup.ReportType", FT_UINT8, BASE_DEC,
1026 VALS(usb_hid_report_type_vals), 0x0,
1029 { &hf_usb_hid_report_id,
1030 { "ReportID", "usbhid.setup.ReportID", FT_UINT8, BASE_DEC, NULL, 0x0,
1033 { &hf_usb_hid_duration,
1034 { "Duration", "usbhid.setup.Duration", FT_UINT8, BASE_DEC, NULL, 0x0,
1038 { "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
1043 static gint *usb_hid_subtrees[] = {
1044 &ett_usb_hid_report,
1045 &ett_usb_hid_item_header,
1049 proto_usb_hid = proto_register_protocol("USB HID", "USBHID", "usbhid");
1050 proto_register_field_array(proto_usb_hid, hf, array_length(hf));
1051 proto_register_subtree_array(usb_hid_subtrees, array_length(usb_hid_subtrees));
1055 proto_reg_handoff_usb_hid(void) {
1056 dissector_handle_t usb_hid_control_handle;
1058 usb_hid_control_handle = new_create_dissector_handle(dissect_usb_hid_control, proto_usb_hid);
1059 dissector_add_uint("usb.control", IF_CLASS_HID, usb_hid_control_handle);