/* packet-usb-hid.c
- *
- * $Id$
*
* USB HID dissector
* By Adam Nielsen <a.nielsen@shikadi.net> 2009
#include "config.h"
-#include <glib.h>
+
#include <epan/packet.h>
-#include <string.h>
#include "packet-usb.h"
#include "packet-usb-hid.h"
+#include "packet-btsdp.h"
+
+
+void proto_register_usb_hid(void);
+void proto_reg_handoff_usb_hid(void);
/* protocols and header fields */
static int proto_usb_hid = -1;
static int hf_usb_hid_duration = -1;
static int hf_usb_hid_zero = -1;
-static const true_false_string tfs_mainitem_bit0 = {"Data", "Constant"};
-static const true_false_string tfs_mainitem_bit1 = {"Array", "Variable"};
-static const true_false_string tfs_mainitem_bit2 = {"Absolute", "Relative"};
-static const true_false_string tfs_mainitem_bit3 = {"No wrap", "Wrap"};
-static const true_false_string tfs_mainitem_bit4 = {"Linear", "Nonlinear"};
-static const true_false_string tfs_mainitem_bit5 = {"Preferred state", "No preferred state"};
-static const true_false_string tfs_mainitem_bit6 = {"No null position", "Null state"};
-static const true_false_string tfs_mainitem_bit7 = {"Non-volatile", "Volatile"};
-static const true_false_string tfs_mainitem_bit8 = {"Bit field", "Buffered bytes"};
+static int hf_usb_hid_bcdHID = -1;
+static int hf_usb_hid_bCountryCode = -1;
+static int hf_usb_hid_bNumDescriptors = -1;
+static int hf_usb_hid_bDescriptorIndex = -1;
+static int hf_usb_hid_bDescriptorType = -1;
+static int hf_usb_hid_wInterfaceNumber = -1;
+static int hf_usb_hid_wDescriptorLength = -1;
+
+static int hf_usbhid_boot_report_keyboard_modifier_right_gui = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_right_alt = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_right_shift = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_right_ctrl = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_left_gui = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_left_alt = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_left_shift = -1;
+static int hf_usbhid_boot_report_keyboard_modifier_left_ctrl = -1;
+static int hf_usbhid_boot_report_keyboard_reserved = -1;
+static int hf_usbhid_boot_report_keyboard_keycode_1 = -1;
+static int hf_usbhid_boot_report_keyboard_keycode_2 = -1;
+static int hf_usbhid_boot_report_keyboard_keycode_3 = -1;
+static int hf_usbhid_boot_report_keyboard_keycode_4 = -1;
+static int hf_usbhid_boot_report_keyboard_keycode_5 = -1;
+static int hf_usbhid_boot_report_keyboard_keycode_6 = -1;
+static int hf_usbhid_boot_report_keyboard_leds_constants = -1;
+static int hf_usbhid_boot_report_keyboard_leds_kana = -1;
+static int hf_usbhid_boot_report_keyboard_leds_compose = -1;
+static int hf_usbhid_boot_report_keyboard_leds_scroll_lock = -1;
+static int hf_usbhid_boot_report_keyboard_leds_caps_lock = -1;
+static int hf_usbhid_boot_report_keyboard_leds_num_lock = -1;
+static int hf_usbhid_boot_report_mouse_button_8 = -1;
+static int hf_usbhid_boot_report_mouse_button_7 = -1;
+static int hf_usbhid_boot_report_mouse_button_6 = -1;
+static int hf_usbhid_boot_report_mouse_button_5 = -1;
+static int hf_usbhid_boot_report_mouse_button_4 = -1;
+static int hf_usbhid_boot_report_mouse_button_middle = -1;
+static int hf_usbhid_boot_report_mouse_button_right = -1;
+static int hf_usbhid_boot_report_mouse_button_left = -1;
+static int hf_usbhid_boot_report_mouse_x_displacement = -1;
+static int hf_usbhid_boot_report_mouse_y_displacement = -1;
+static int hf_usbhid_boot_report_mouse_horizontal_scroll_wheel = -1;
+static int hf_usbhid_boot_report_mouse_vertical_scroll_wheel = -1;
+static int hf_usbhid_data = -1;
+
+static const true_false_string tfs_mainitem_bit0 = {"Constant", "Data"};
+static const true_false_string tfs_mainitem_bit1 = {"Variable", "Array"};
+static const true_false_string tfs_mainitem_bit2 = {"Relative", "Absolute"};
+static const true_false_string tfs_mainitem_bit3 = {"Wrap", "No Wrap"};
+static const true_false_string tfs_mainitem_bit4 = {"Non Linear", "Linear"};
+static const true_false_string tfs_mainitem_bit5 = {"No Preferred", "Preferred State"};
+static const true_false_string tfs_mainitem_bit6 = {"Null state", "No Null position"};
+static const true_false_string tfs_mainitem_bit7 = {"Volatile", "Non Volatile"};
+static const true_false_string tfs_mainitem_bit8 = {"Buffered Bytes", "Bit Field"};
struct usb_hid_global_state {
unsigned int usage_page;
};
+
+/* HID class specific descriptor types */
+#define USB_DT_HID 0x21
+#define USB_DT_HID_REPORT 0x22
+static const value_string hid_descriptor_type_vals[] = {
+ {USB_DT_HID, "HID"},
+ {USB_DT_HID_REPORT, "HID Report"},
+ {0,NULL}
+};
+static value_string_ext hid_descriptor_type_vals_ext =
+ VALUE_STRING_EXT_INIT(hid_descriptor_type_vals);
+
+
#define USBHID_SIZE_MASK 0x03
#define USBHID_TYPE_MASK 0x0C
#define USBHID_TAG_MASK 0xF0
{0, 0, NULL}
};
+static const value_string keycode_vals[] = {
+ { 0x00, "<ACTION KEY UP>" },
+ { 0x01, "ErrorRollOver" },
+ { 0x02, "POSTFail" },
+ { 0x03, "ErrorUndefined" },
+
+ { 0x04, "a" },
+ { 0x05, "b" },
+ { 0x06, "c" },
+ { 0x07, "d" },
+ { 0x08, "e" },
+ { 0x09, "f" },
+ { 0x0A, "g" },
+ { 0x0B, "h" },
+ { 0x0C, "i" },
+ { 0x0D, "j" },
+ { 0x0E, "k" },
+ { 0x0F, "l" },
+ { 0x10, "m" },
+ { 0x11, "n" },
+ { 0x12, "o" },
+ { 0x13, "p" },
+ { 0x14, "q" },
+ { 0x15, "r" },
+ { 0x16, "s" },
+ { 0x17, "t" },
+ { 0x18, "u" },
+ { 0x19, "v" },
+ { 0x1A, "w" },
+ { 0x1B, "x" },
+ { 0x1C, "y" },
+ { 0x1D, "z" },
+
+ { 0x1E, "1" },
+ { 0x1F, "2" },
+ { 0x20, "3" },
+ { 0x21, "4" },
+ { 0x22, "5" },
+ { 0x23, "6" },
+ { 0x24, "7" },
+ { 0x25, "8" },
+ { 0x26, "9" },
+ { 0x27, "0" },
+
+ { 0x28, "ENTER" },
+ { 0x29, "Escape" },
+ { 0x2A, "Backspace" },
+ { 0x2B, "Tab" },
+ { 0x2C, "Spacebar" },
+
+ { 0x2D, "-" },
+ { 0x2E, "=" },
+ { 0x2F, "[" },
+ { 0x30, "]" },
+ { 0x31, "\\" },
+ { 0x32, "NonUS #/~" },
+ { 0x33, ";" },
+ { 0x34, "'" },
+ { 0x35, "`" },
+ { 0x36, "," },
+ { 0x37, "." },
+ { 0x38, "/" },
+ { 0x39, "CapsLock" },
+ { 0x3A, "F1" },
+ { 0x3B, "F2" },
+ { 0x3C, "F3" },
+ { 0x3D, "F4" },
+ { 0x3E, "F5" },
+ { 0x3F, "F6" },
+ { 0x40, "F7" },
+ { 0x41, "F8" },
+ { 0x42, "F9" },
+ { 0x43, "F10" },
+ { 0x44, "F11" },
+ { 0x45, "F12" },
+ { 0x46, "PrintScreen" },
+ { 0x47, "ScrollLock" },
+ { 0x48, "Pause" },
+ { 0x49, "Insert" },
+ { 0x4A, "Home" },
+ { 0x4B, "PageUp" },
+ { 0x4C, "DeleteForward" },
+ { 0x4D, "End" },
+ { 0x4E, "PageDown" },
+ { 0x4F, "RightArrow" },
+ { 0x50, "LeftArrow" },
+ { 0x51, "DownArrow" },
+ { 0x52, "UpArrow" },
+ { 0x53, "NumLock" },
+
+ /* Keypad */
+ { 0x54, "Keypad /" },
+ { 0x55, "Keypad *" },
+ { 0x56, "Keypad -" },
+ { 0x57, "Keypad +" },
+ { 0x58, "Keypad ENTER" },
+ { 0x59, "Keypad 1" },
+ { 0x5A, "Keypad 2" },
+ { 0x5B, "Keypad 3" },
+ { 0x5C, "Keypad 4" },
+ { 0x5D, "Keypad 5" },
+ { 0x5E, "Keypad 6" },
+ { 0x5F, "Keypad 7" },
+ { 0x60, "Keypad 8" },
+ { 0x61, "Keypad 9" },
+ { 0x62, "Keypad 0" },
+ { 0x63, "Keypad ." },
+
+ /* non PC AT */
+ { 0x64, "NonUS \\/|" },
+ { 0x65, "Application" },
+ { 0x66, "Power" },
+ { 0x67, "Keypad =" },
+ { 0x68, "F13" },
+ { 0x69, "F14" },
+ { 0x6A, "F15" },
+ { 0x6B, "F16" },
+ { 0x6C, "F17" },
+ { 0x6D, "F18" },
+ { 0x6E, "F19" },
+ { 0x6F, "F20" },
+
+ { 0x70, "F21" },
+ { 0x71, "F22" },
+ { 0x72, "F23" },
+ { 0x73, "F24" },
+ { 0x74, "Execute" },
+ { 0x75, "Help" },
+ { 0x76, "Menu" },
+ { 0x77, "Select" },
+ { 0x78, "Stop" },
+ { 0x79, "Again" },
+ { 0x7A, "Undo" },
+ { 0x7B, "Cut" },
+ { 0x7C, "Copy" },
+ { 0x7D, "Paste" },
+ { 0x7E, "Find" },
+ { 0x7F, "Mute" },
+
+ { 0x80, "VolumeUp" },
+ { 0x81, "VolumeDown" },
+ { 0x82, "Locking CapsLock" },
+ { 0x83, "Locking NumLock" },
+ { 0x84, "Locking ScrollLock" },
+ { 0x85, "Keypad Comma" },
+ { 0x86, "Keypad EqualSign" },
+ { 0x87, "International1" },
+ { 0x88, "International2" },
+ { 0x89, "International3" },
+ { 0x8A, "International4" },
+ { 0x8B, "International5" },
+ { 0x8C, "International6" },
+ { 0x8D, "International7" },
+ { 0x8E, "International8" },
+ { 0x8F, "International9" },
+
+ { 0x90, "LANG1" },
+ { 0x91, "LANG2" },
+ { 0x92, "LANG3" },
+ { 0x93, "LANG4" },
+ { 0x94, "LANG5" },
+ { 0x95, "LANG6" },
+ { 0x96, "LANG7" },
+ { 0x97, "LANG8" },
+ { 0x98, "LANG9" },
+ { 0x99, "AlternateErase" },
+ { 0x9A, "SysReq/Attention" },
+ { 0x9B, "Cancel" },
+ { 0x9C, "Clear" },
+ { 0x9D, "Prior" },
+ { 0x9E, "Return" },
+ { 0x9F, "Separator" },
+
+ { 0xA0, "Out" },
+ { 0xA1, "Oper" },
+ { 0xA2, "Clear/Again" },
+ { 0xA3, "CrSel/Props" },
+ { 0xA4, "ExSel" },
+ /* 0xA5..0xAF - reserved */
+ { 0xB0, "Keypad 00" },
+ { 0xB1, "Keypad 000" },
+ { 0xB2, "ThousandsSeparator" },
+ { 0xB3, "DecimalSeparator" },
+ { 0xB4, "CurrencyUnit" },
+ { 0xB5, "CurrencySubunit" },
+ { 0xB6, "Keypad (" },
+ { 0xB7, "Keypad )" },
+ { 0xB8, "Keypad {" },
+ { 0xB9, "Keypad }" },
+ { 0xBA, "Keypad Tab" },
+ { 0xBB, "Keypad Backspace" },
+ { 0xBC, "Keypad A" },
+ { 0xBD, "Keypad B" },
+ { 0xBE, "Keypad C" },
+ { 0xBF, "Keypad D" },
+
+ { 0xC0, "Keypad E" },
+ { 0xC1, "Keypad F" },
+ { 0xC2, "Keypad XOR" },
+ { 0xC3, "Keypad ^" },
+ { 0xC4, "Keypad %" },
+ { 0xC5, "Keypad <" },
+ { 0xC6, "Keypad >" },
+ { 0xC7, "Keypad &" },
+ { 0xC8, "Keypad &&" },
+ { 0xC9, "Keypad |" },
+ { 0xCA, "Keypad ||" },
+ { 0xCB, "Keypad :" },
+ { 0xCC, "Keypad #" },
+ { 0xCD, "Keypad Space" },
+ { 0xCE, "Keypad @" },
+ { 0xCF, "Keypad !" },
+
+ { 0xD0, "Keypad Memory Store" },
+ { 0xD1, "Keypad Memory Recall" },
+ { 0xD2, "Keypad Memory Clear" },
+ { 0xD3, "Keypad Memory Add" },
+ { 0xD4, "Keypad Memory Subtract" },
+ { 0xD5, "Keypad Memory Multiply" },
+ { 0xD6, "Keypad Memory Divide" },
+ { 0xD7, "Keypad +/-" },
+ { 0xD8, "Keypad Clear" },
+ { 0xD9, "Keypad Clear Entry" },
+ { 0xDA, "Keypad Binary" },
+ { 0xDB, "Keypad Octal" },
+ { 0xDC, "Keypad Decimal" },
+ { 0xDD, "Keypad Hexadecimal" },
+ /* 0xDE..0xDF - reserved, */
+ { 0xE0, "LeftControl" },
+ { 0xE1, "LeftShift" },
+ { 0xE2, "LeftAlt" },
+ { 0xE3, "LeftGUI" },
+ { 0xE4, "RightControl" },
+ { 0xE5, "RightShift" },
+ { 0xE6, "RightAlt" },
+ { 0xE7, "RightGUI" },
+
+ { 0, NULL }
+};
+value_string_ext keycode_vals_ext = VALUE_STRING_EXT_INIT(keycode_vals);
+
/* Dissector for the data in a HID main report. */
static int
dissect_usb_hid_report_mainitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag)
if (bSize > 1) {
proto_tree_add_item(tree, hf_usb_hid_mainitem_bit8, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
} else {
- proto_tree_add_text(tree, tvb, offset, 0, "Bits or bytes: Buffered bytes (default, no second byte present)");
+ proto_tree_add_boolean_format_value(tree, hf_usb_hid_mainitem_bit8, tvb, offset, 0, FALSE, "Buffered bytes (default, no second byte present)");
}
break;
case USBHID_MAINITEM_TAG_COLLECTION:
usage_page = (global->usage_page & 0xFFFFFF00) | tvb_get_guint8(tvb, offset);
else if (bSize == 2)
usage_page = (global->usage_page & 0xFFFF0000) | tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, bSize, "Usage: %s (0x%08x)",
- rval_to_str(usage_page, usb_hid_item_usage_vals, "[Unknown page!]"),
- usage_page);
+ proto_tree_add_uint(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, usage_page);
}
break;
case USBHID_LOCALITEM_TAG_USAGE_MIN:
/* Dissector for individual HID report items. Recursive. */
static int
-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)
+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)
{
- proto_item *item=NULL, *subitem=NULL;
- proto_tree *tree=NULL, *subtree=NULL;
+ proto_item *subitem;
+ proto_tree *tree, *subtree;
int old_offset;
unsigned int tmp;
unsigned int bSize, bType, bTag;
break;
}
- subitem = proto_tree_add_text(parent_tree, tvb, offset, bSize + 1, "%s item (%s)",
+ subtree = proto_tree_add_subtree_format(parent_tree, tvb, offset, bSize + 1,
+ ett_usb_hid_item_header, &subitem, "%s item (%s)",
val_to_str(bType, usb_hid_item_bType_vals, "Unknown/%u"),
val_to_str(bTag, usb_hid_cur_bTag_vals, "Unknown/%u tag")
);
- subtree = proto_item_add_subtree(subitem, ett_usb_hid_item_header);
- item = proto_tree_add_text(subtree, tvb, offset, 1, "Header");
- tree = proto_item_add_subtree(item, ett_usb_hid_item_header);
+ tree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_usb_hid_item_header, NULL, "Header");
proto_tree_add_item(tree, hf_usb_hid_item_bSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_usb_hid_item_bType, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_usb_hid_curitem_bTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
if (bType == USBHID_ITEMTYPE_MAIN) {
if (bTag == USBHID_MAINITEM_TAG_COLLECTION) {
/* Begin collection, nest following elements under us */
- offset = dissect_usb_hid_report_item(pinfo, subtree, tvb, offset, usb_trans_info, usb_conv_info, &cur_global);
+ offset = dissect_usb_hid_report_item(pinfo, subtree, tvb, offset, usb_conv_info, &cur_global);
proto_item_set_len(subitem, offset-old_offset);
} else if (bTag == USBHID_MAINITEM_TAG_ENDCOLLECTION) {
/* End collection, break out to parent tree item */
/* Dissector for HID "GET DESCRIPTOR" subtype. */
int
-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_)
+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)
{
- proto_item *item=NULL;
- proto_tree *tree=NULL;
+ proto_item *item;
+ proto_tree *tree;
int old_offset=offset;
struct usb_hid_global_state initial_global;
+
memset(&initial_global, 0, sizeof(struct usb_hid_global_state));
- if (parent_tree) {
- item = proto_tree_add_protocol_format(parent_tree, proto_usb_hid, tvb, offset,
- -1, "HID Report");
- tree = proto_item_add_subtree(item, ett_usb_hid_report);
- offset = dissect_usb_hid_report_item(pinfo, tree, tvb, offset, usb_trans_info, usb_conv_info, &initial_global);
+ item = proto_tree_add_protocol_format(parent_tree, proto_usb_hid, tvb, offset,
+ -1, "HID Report");
+ tree = proto_item_add_subtree(item, ett_usb_hid_report);
+ offset = dissect_usb_hid_report_item(pinfo, tree, tvb, offset, usb_conv_info, &initial_global);
- proto_item_set_len(item, offset-old_offset);
- }
+ proto_item_set_len(item, offset-old_offset);
return offset;
}
/* Dissector for HID GET_REPORT request. See USBHID 1.11, Chapter 7.2.1 Get_Report Request */
static void
-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_)
+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_)
{
- proto_item *item = NULL;
- proto_tree *subtree = NULL;
+ proto_item *item;
+ proto_tree *subtree;
- if (is_request) {
- item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
+ if (!is_request)
+ return;
- /* Report Type in the high byte, Report ID in the low byte */
- proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
- proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* Report Type in the high byte, Report ID in the low byte */
+ proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
- proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- /*offset += 2;*/
- } else {
- }
+ proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /*offset += 2;*/
}
/* Dissector for HID SET_REPORT request. See USBHID 1.11, Chapter 7.2.2 Set_Report Request */
static void
-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_)
+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_)
{
- proto_item *item = NULL;
- proto_tree *subtree = NULL;
+ proto_item *item;
+ proto_tree *subtree;
- if (is_request) {
- item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
+ if (!is_request)
+ return;
- proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
- proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ proto_tree_add_item(subtree, hf_usb_hid_report_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
- proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- /*offset += 2;*/
- } else {
- }
+ proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /*offset += 2;*/
}
/* Dissector for HID GET_IDLE request. See USBHID 1.11, Chapter 7.2.3 Get_Idle Request */
static void
-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_)
+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_)
{
- proto_item *item = NULL;
- proto_tree *subtree = NULL;
+ proto_item *item;
+ proto_tree *subtree;
- if (is_request) {
- item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
+ if (!is_request)
+ return;
- proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- proto_tree_add_item(subtree, hf_usb_hid_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
- proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ proto_tree_add_item(subtree, hf_usb_hid_zero, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
- proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- /*offset += 2;*/
- } else {
- }
+ proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /*offset += 2;*/
}
/* Dissector for HID SET_IDLE request. See USBHID 1.11, Chapter 7.2.4 Set_Idle Request */
static void
-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_)
+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_)
{
- proto_item *item = NULL;
- proto_tree *subtree = NULL;
+ proto_item *item;
+ proto_tree *subtree;
- if (is_request) {
- item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
+ if (!is_request)
+ return;
- /* Duration in the high byte, Report ID in the low byte */
- proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- proto_tree_add_item(subtree, hf_usb_hid_duration, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ item = proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ subtree = proto_item_add_subtree(item, ett_usb_hid_wValue);
- proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* Duration in the high byte, Report ID in the low byte */
+ proto_tree_add_item(subtree, hf_usb_hid_report_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ proto_tree_add_item(subtree, hf_usb_hid_duration, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
- proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- /*offset += 2;*/
- } else {
- }
+ proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /*offset += 2;*/
}
/* Dissector for HID GET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.5 Get_Protocol Request */
static void
-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_)
+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_)
{
- if (is_request) {
- proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ if (!is_request)
+ return;
- proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- /*offset += 2;*/
- } else {
- }
+ proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /*offset += 2;*/
}
/* Dissector for HID SET_PROTOCOL request. See USBHID 1.11, Chapter 7.2.6 Set_Protocol Request */
static void
-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_)
+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_)
{
- if (is_request) {
- proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ if (!is_request)
+ return;
- proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(tree, hf_usb_hid_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- /*offset += 2;*/
- } else {
- }
+ proto_tree_add_item(tree, hf_usb_hid_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /*offset += 2;*/
}
-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);
+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);
typedef struct _usb_setup_dissector_table_t {
guint8 request;
{ 0, NULL }
};
-/* Dissector for HID class-specific control request as defined in
- * USBHID 1.11, Chapter 7.2.
- * Returns TRUE if a class specific dissector was found
- * and FALSE otherwise.
- */
static gint
-dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+dissect_usb_hid_boot_keyboard_input_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint offset = 0;
+ gboolean shortcut_helper = FALSE;
+ guint modifier;
+ guint keycode;
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_gui, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_alt, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_right_ctrl, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_gui, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_alt, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_modifier_left_ctrl, tvb, offset, 1, ENC_BIG_ENDIAN);
+ modifier = tvb_get_guint8(tvb, offset);
+
+ col_append_str(pinfo->cinfo, COL_INFO, " - ");
+ if (modifier & 0x80) {
+ col_append_str(pinfo->cinfo, COL_INFO, "RIGHT GUI");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x40) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "RIGHT ALT");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x20) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "RIGHT SHIFT");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x10) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "RIGHT CTRL");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x08) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "LEFT GUI");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x04) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "LEFT ALT");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x02) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "LEFT SHIFT");
+ shortcut_helper = TRUE;
+ }
+ if (modifier & 0x01) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "LEFT CTRL");
+ shortcut_helper = TRUE;
+ }
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_1, tvb, offset, 1, ENC_BIG_ENDIAN);
+ keycode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (keycode) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
+ shortcut_helper = TRUE;
+ }
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_2, tvb, offset, 1, ENC_BIG_ENDIAN);
+ keycode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (keycode) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
+ shortcut_helper = TRUE;
+ }
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_3, tvb, offset, 1, ENC_BIG_ENDIAN);
+ keycode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (keycode) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
+ shortcut_helper = TRUE;
+ }
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_4, tvb, offset, 1, ENC_BIG_ENDIAN);
+ keycode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (keycode) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
+ shortcut_helper = TRUE;
+ }
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_5, tvb, offset, 1, ENC_BIG_ENDIAN);
+ keycode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (keycode) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
+ shortcut_helper = TRUE;
+ }
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_keycode_6, tvb, offset, 1, ENC_BIG_ENDIAN);
+ keycode = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (keycode) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(keycode, &keycode_vals_ext, "Unknown"));
+ shortcut_helper = TRUE;
+ }
+
+ if (shortcut_helper == FALSE) {
+ col_append_str(pinfo->cinfo, COL_INFO, "<action key up>");
+ }
+
+ return offset;
+}
+
+static gint
+dissect_usb_hid_boot_keyboard_output_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint offset = 0;
+ gboolean shortcut_helper = FALSE;
+ guint leds;
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_constants, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_kana, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_compose, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_scroll_lock, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_caps_lock, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_keyboard_leds_num_lock, tvb, offset, 1, ENC_BIG_ENDIAN);
+ leds = tvb_get_guint8(tvb, offset);
+
+ col_append_str(pinfo->cinfo, COL_INFO, " - LEDs: ");
+ if (leds & 0x01) {
+ col_append_str(pinfo->cinfo, COL_INFO, "NumLock");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x02) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "CapsLock");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x04) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "ScrollLock");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x08) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Compose");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x10) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Kana");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x20) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Constant1");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x40) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Constant2");
+ shortcut_helper = TRUE;
+ }
+ if (leds & 0x80) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Constant3");
+ /*shortcut_helper = TRUE;*/
+ }
+ if (!leds) {
+ col_append_str(pinfo->cinfo, COL_INFO, "none");
+ }
+
+ offset += 1;
+
+ return offset;
+}
+
+static gint
+dissect_usb_hid_boot_mouse_input_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint offset = 0;
+ gboolean shortcut_helper = FALSE;
+ guint buttons;
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_8, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_7, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_6, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_5, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_4, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_middle, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_right, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_button_left, tvb, offset, 1, ENC_BIG_ENDIAN);
+ buttons = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (buttons) col_append_str(pinfo->cinfo, COL_INFO, " - ");
+ if (buttons & 0x01) {
+ col_append_str(pinfo->cinfo, COL_INFO, "Button LEFT");
+ shortcut_helper = TRUE;
+ }
+ if (buttons & 0x02) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button RIGHT");
+ shortcut_helper = TRUE;
+ }
+ if (buttons & 0x04) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button MIDDLE");
+ }
+ if (buttons & 0x08) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button 4");
+ shortcut_helper = TRUE;
+ }
+ if (buttons & 0x10) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button 5");
+ shortcut_helper = TRUE;
+ }
+ if (buttons & 0x20) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button 6");
+ shortcut_helper = TRUE;
+ }
+ if (buttons & 0x40) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button 7");
+ shortcut_helper = TRUE;
+ }
+ if (buttons & 0x80) {
+ if (shortcut_helper) col_append_str(pinfo->cinfo, COL_INFO, " + ");
+ col_append_str(pinfo->cinfo, COL_INFO, "Button 8");
+ /* Not necessary, this is the last case where it is used
+ * shortcut_helper = TRUE;
+ */
+ }
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_x_displacement, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_y_displacement, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ /* not really in HID Specification */
+ if (tvb_reported_length_remaining(tvb, offset)) {
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_horizontal_scroll_wheel, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ }
+
+ /* not really in HID Specification */
+ if (tvb_reported_length_remaining(tvb, offset)) {
+ proto_tree_add_item(tree, hf_usbhid_boot_report_mouse_vertical_scroll_wheel, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ }
+
+ if (tvb_reported_length_remaining(tvb, offset)) {
+ proto_tree_add_item(tree, hf_usbhid_data, tvb, offset, -1, ENC_NA);
+ offset += tvb_captured_length_remaining(tvb, offset);
+ }
+
+ return offset;
+}
+
+
+/* dissect a "standard" control message that's sent to an interface */
+static gint
+dissect_usb_hid_control_std_intf(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, usb_conv_info_t *usb_conv_info)
+{
+ gint offset = 0;
+ usb_trans_info_t *usb_trans_info;
+ guint8 req;
+
+ usb_trans_info = usb_conv_info->usb_trans_info;
+
+ /* XXX - can we do some plausibility checks here? */
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
+
+ /* we can't use usb_conv_info->is_request since usb_conv_info
+ was replaced with the interface conversation */
+ if (usb_trans_info->request_in == pinfo->num) {
+ /* the tvb that we see here is the setup packet
+ without the request type byte */
+
+ req = tvb_get_guint8(tvb, offset);
+ if (req != USB_SETUP_GET_DESCRIPTOR)
+ return offset;
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "GET DESCRIPTOR Request");
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_usb_hid_bDescriptorIndex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ usb_trans_info->u.get_descriptor.usb_index = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_usb_hid_bDescriptorType, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ usb_trans_info->u.get_descriptor.type = tvb_get_guint8(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ val_to_str_ext(usb_trans_info->u.get_descriptor.type,
+ &hid_descriptor_type_vals_ext, "Unknown type %u"));
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_usb_hid_wInterfaceNumber, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_usb_hid_wDescriptorLength, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ }
+ else {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "GET DESCRIPTOR Response");
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ val_to_str_ext(usb_trans_info->u.get_descriptor.type,
+ &hid_descriptor_type_vals_ext, "Unknown type %u"));
+ if (usb_trans_info->u.get_descriptor.type == USB_DT_HID_REPORT) {
+ offset = dissect_usb_hid_get_report_descriptor(
+ pinfo, tree, tvb, offset, usb_conv_info);
+ }
+ }
+
+ return offset;
+}
+
+/* dissect a class-specific control message that's sent to an interface */
+static gint
+dissect_usb_hid_control_class_intf(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, usb_conv_info_t *usb_conv_info)
{
- gboolean is_request;
- usb_conv_info_t *usb_conv_info;
usb_trans_info_t *usb_trans_info;
+ gboolean is_request;
int offset = 0;
- usb_setup_dissector dissector;
+ usb_setup_dissector dissector = NULL;
const usb_setup_dissector_table_t *tmp;
- is_request = (pinfo->srcport==NO_ENDPOINT);
-
- usb_conv_info = (usb_conv_info_t *)pinfo->usb_conv_info;
usb_trans_info = usb_conv_info->usb_trans_info;
- /* See if we can find a class specific dissector for this request */
- dissector = NULL;
+ is_request = (pinfo->srcport==NO_ENDPOINT);
/* Check valid values for bmRequestType. See Chapter 7.2 in USBHID 1.11 */
- if ((usb_trans_info->setup.requesttype & 0x7F) ==
- ((RQT_SETUP_TYPE_CLASS << 5) | RQT_SETUP_RECIPIENT_INTERFACE)) {
- for (tmp = setup_dissectors; tmp->dissector; tmp++) {
- if (tmp->request == usb_trans_info->setup.request) {
- dissector = tmp->dissector;
- break;
- }
+ for (tmp = setup_dissectors; tmp->dissector; tmp++) {
+ if (tmp->request == usb_trans_info->setup.request) {
+ dissector = tmp->dissector;
+ break;
}
}
/* No, we could not find any class specific dissector for this request
- * return FALSE and let USB try any of the standard requests.
+ * return 0 and let USB try any of the standard requests.
*/
if (!dissector) {
- return FALSE;
+ return 0;
}
col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
offset += 1;
}
- dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
- return TRUE;
+ dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info);
+ return tvb_captured_length(tvb);
}
+/* Dissector for HID class-specific control request as defined in
+ * USBHID 1.11, Chapter 7.2.
+ * returns the number of bytes consumed */
+static gint
+dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ usb_conv_info_t *usb_conv_info;
+ usb_trans_info_t *usb_trans_info;
+ guint8 type, recip;
+
+ usb_conv_info = (usb_conv_info_t *)data;
+ if (!usb_conv_info)
+ return 0;
+ usb_trans_info = usb_conv_info->usb_trans_info;
+ if (!usb_trans_info)
+ return 0;
+
+ type = USB_TYPE(usb_trans_info->setup.requesttype);
+ recip = USB_RECIPIENT(usb_trans_info->setup.requesttype);
+
+ if (recip == RQT_SETUP_RECIPIENT_INTERFACE) {
+ if (type == RQT_SETUP_TYPE_STANDARD) {
+ return dissect_usb_hid_control_std_intf(
+ tvb, pinfo, tree, usb_conv_info);
+ }
+ else if (type == RQT_SETUP_TYPE_CLASS) {
+ return dissect_usb_hid_control_class_intf(
+ tvb, pinfo, tree, usb_conv_info);
+ }
+ }
+
+ return 0;
+}
+/* dissect a descriptor that is specific to the HID class */
static gint
-dissect_usb_hid_descriptors(tvbuff_t *tvb, packet_info *pinfo _U_,
+dissect_usb_hid_class_descriptors(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, void *data _U_)
{
guint8 type;
+ gint offset = 0;
proto_item *ti;
proto_tree *desc_tree;
+ guint8 num_desc;
+ guint i;
type = tvb_get_guint8(tvb, 1);
if (type != USB_DT_HID)
return 0;
- ti = proto_tree_add_text(tree,
- tvb, 0, tvb_reported_length(tvb), "HID DESCRIPTOR");
- desc_tree = proto_item_add_subtree(ti, ett_usb_hid_descriptor);
-
- dissect_usb_descriptor_header(desc_tree, tvb, 0);
+ desc_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_usb_hid_descriptor, &ti, "HID DESCRIPTOR");
+
+ dissect_usb_descriptor_header(desc_tree, tvb, offset,
+ &hid_descriptor_type_vals_ext);
+ offset += 2;
+ proto_tree_add_item(desc_tree, hf_usb_hid_bcdHID,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(desc_tree, hf_usb_hid_bCountryCode,
+ tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ num_desc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(desc_tree, hf_usb_hid_bNumDescriptors,
+ tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ for (i=0;i<num_desc;i++) {
+ proto_tree_add_item(desc_tree, hf_usb_hid_bDescriptorType,
+ tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset++;
+ proto_tree_add_item(desc_tree, hf_usb_hid_wDescriptorLength,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ }
- return tvb_reported_length(tvb);
+ proto_item_set_len(ti, offset);
+ return offset;
}
{ &hf_usb_hid_zero,
{ "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
- NULL, HFILL }}
+ NULL, HFILL }},
+ /* components of the HID descriptor */
+ { &hf_usb_hid_bcdHID,
+ { "bcdHID", "usbhid.descriptor.hid.bcdHID", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_usb_hid_bCountryCode,
+ { "bCountryCode", "usbhid.descriptor.hid.bCountryCode", FT_UINT8,
+ BASE_HEX, VALS(hid_country_code_vals), 0x0, NULL, HFILL }},
+
+ { &hf_usb_hid_bNumDescriptors,
+ { "bNumDescriptors", "usbhid.descriptor.hid.bNumDescriptors", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_usb_hid_bDescriptorIndex,
+ { "bDescriptorIndex", "usbhid.descriptor.hid.bDescriptorIndex", FT_UINT8,
+ BASE_HEX, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_usb_hid_bDescriptorType,
+ { "bDescriptorType", "usbhid.descriptor.hid.bDescriptorType", FT_UINT8,
+ BASE_HEX|BASE_EXT_STRING, &hid_descriptor_type_vals_ext,
+ 0x00, NULL, HFILL }},
+
+ { &hf_usb_hid_wInterfaceNumber,
+ { "wInterfaceNumber", "usbhid.descriptor.hid.wInterfaceNumber", FT_UINT16,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_usb_hid_wDescriptorLength,
+ { "wDescriptorLength", "usbhid.descriptor.hid.wDescriptorLength", FT_UINT16,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_usbhid_boot_report_keyboard_reserved,
+ { "Reserved", "usbhid.boot_report.keyboard.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_keycode_1,
+ { "Keycode 1", "usbhid.boot_report.keyboard.keycode_1",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_keycode_2,
+ { "Keycode 2", "usbhid.boot_report.keyboard.keycode_2",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_keycode_3,
+ { "Keycode 3", "usbhid.boot_report.keyboard.keycode_3",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_keycode_4,
+ { "Keycode 4", "usbhid.boot_report.keyboard.keycode_4",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_keycode_5,
+ { "Keycode 5", "usbhid.boot_report.keyboard.keycode_5",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_keycode_6,
+ { "Keycode 6", "usbhid.boot_report.keyboard.keycode_6",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &keycode_vals_ext, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_right_gui,
+ { "Modifier: RIGHT GUI", "usbhid.boot_report.keyboard.modifier.right_gui",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_right_alt,
+ { "Modifier: RIGHT ALT", "usbhid.boot_report.keyboard.modifier.right_alt",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_right_shift,
+ { "Modifier: RIGHT SHIFT", "usbhid.boot_report.keyboard.modifier.right_shift",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_right_ctrl,
+ { "Modifier: RIGHT CTRL", "usbhid.boot_report.keyboard.modifier.right_ctrl",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_left_gui,
+ { "Modifier: LEFT GUI", "usbhid.boot_report.keyboard.modifier.left_gui",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_left_alt,
+ { "Modifier: LEFT ALT", "usbhid.boot_report.keyboard.modifier.left_alt",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_left_shift,
+ { "Modifier: LEFT SHIFT", "usbhid.boot_report.keyboard.modifier.left_shift",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_modifier_left_ctrl,
+ { "Modifier: LEFT CTRL", "usbhid.boot_report.keyboard.modifier.left_ctrl",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_leds_constants,
+ { "Constants", "usbhid.boot_report.keyboard.leds.constants",
+ FT_UINT8, BASE_HEX, NULL, 0xE0,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_leds_kana,
+ { "KANA", "usbhid.boot_report.keyboard.leds.kana",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_leds_compose,
+ { "COMPOSE", "usbhid.boot_report.keyboard.leds.compose",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_leds_scroll_lock,
+ { "SCROLL LOCK", "usbhid.boot_report.keyboard.leds.scroll_lock",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_leds_caps_lock,
+ { "CAPS LOCK", "usbhid.boot_report.keyboard.leds.caps_lock",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_keyboard_leds_num_lock,
+ { "NUM LOCK", "usbhid.boot_report.keyboard.leds.num_lock",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_8,
+ { "Button 8", "usbhid.boot_report.mouse.button.8",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_7,
+ { "Button 7", "usbhid.boot_report.mouse.button.7",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_6,
+ { "Button 6", "usbhid.boot_report.mouse.button.6",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_5,
+ { "Button 5", "usbhid.boot_report.mouse.button.5",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_4,
+ { "Button 4", "usbhid.boot_report.mouse.button.4",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_middle,
+ { "Button Middle", "usbhid.boot_report.mouse.button.middle",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_right,
+ { "Button Right", "usbhid.boot_report.mouse.button.right",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_button_left,
+ { "Button Left", "usbhid.boot_report.mouse.button.left",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_x_displacement,
+ { "X Displacement", "usbhid.boot_report.mouse.x_displacement",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_y_displacement,
+ { "Y Displacement", "usbhid.boot_report.mouse.y_displacement",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_horizontal_scroll_wheel,
+ { "Horizontal Scroll Wheel", "usbhid.boot_report.mouse.scroll_wheel.horizontal",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_boot_report_mouse_vertical_scroll_wheel,
+ { "Vertical Scroll Wheel", "usbhid.boot_report.mouse.scroll_wheel.vertical",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ NULL, HFILL }
+ },
+ { &hf_usbhid_data,
+ { "Data", "usbhid.data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ NULL, HFILL }
+ },
};
static gint *usb_hid_subtrees[] = {
proto_usb_hid = proto_register_protocol("USB HID", "USBHID", "usbhid");
proto_register_field_array(proto_usb_hid, hf, array_length(hf));
proto_register_subtree_array(usb_hid_subtrees, array_length(usb_hid_subtrees));
+
+ /*usb_hid_boot_keyboard_input_report_handle =*/ register_dissector("usbhid.boot_report.keyboard.input", dissect_usb_hid_boot_keyboard_input_report, proto_usb_hid);
+ /*usb_hid_boot_keyboard_output_report_handle =*/ register_dissector("usbhid.boot_report.keyboard.output", dissect_usb_hid_boot_keyboard_output_report, proto_usb_hid);
+ /*usb_hid_boot_mouse_input_report_handle =*/ register_dissector("usbhid.boot_report.mouse.input", dissect_usb_hid_boot_mouse_input_report, proto_usb_hid);
+
}
void
-proto_reg_handoff_usb_hid(void) {
+proto_reg_handoff_usb_hid(void)
+{
dissector_handle_t usb_hid_control_handle, usb_hid_descr_handle;
- usb_hid_control_handle = new_create_dissector_handle(dissect_usb_hid_control, proto_usb_hid);
+ usb_hid_control_handle = create_dissector_handle(
+ dissect_usb_hid_control, proto_usb_hid);
dissector_add_uint("usb.control", IF_CLASS_HID, usb_hid_control_handle);
- usb_hid_descr_handle = new_create_dissector_handle(dissect_usb_hid_descriptors, proto_usb_hid);
+ dissector_add_for_decode_as("usb.device", usb_hid_control_handle);
+
+ usb_hid_descr_handle = create_dissector_handle(
+ dissect_usb_hid_class_descriptors, proto_usb_hid);
dissector_add_uint("usb.descriptor", IF_CLASS_HID, usb_hid_descr_handle);
}