Add format_text_wmem.
[metze/wireshark/wip.git] / epan / dissectors / packet-usb-hid.c
index 725b16b1be112257cebcd0dce4456e6673eb73c7..046f43b1e4bbfbc4e22c0ee732935945805bae9c 100644 (file)
@@ -25,6 +25,8 @@
 #include <epan/packet.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);
@@ -100,9 +102,46 @@ static int hf_usb_hid_zero = -1;
 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"};
@@ -120,9 +159,11 @@ struct usb_hid_global_state {
 
 
 /* HID class specific descriptor types */
-#define USB_DT_HID 33
+#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 =
@@ -300,6 +341,247 @@ static const range_string usb_hid_item_usage_vals[] = {
     {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)
@@ -459,10 +741,10 @@ dissect_usb_hid_report_localitem_data(packet_info *pinfo _U_, proto_tree *tree,
 
 /* 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 *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;
@@ -501,7 +783,7 @@ dissect_usb_hid_report_item(packet_info *pinfo _U_, proto_tree *parent_tree, tvb
         }
 
         subtree = proto_tree_add_subtree_format(parent_tree, tvb, offset, bSize + 1,
-            ett_usb_hid_item_header, NULL, "%s item (%s)",
+            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")
         );
@@ -542,7 +824,7 @@ dissect_usb_hid_report_item(packet_info *pinfo _U_, proto_tree *parent_tree, tvb
         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 */
@@ -557,167 +839,162 @@ dissect_usb_hid_report_item(packet_info *pinfo _U_, proto_tree *parent_tree, tvb
 int
 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;
-    usb_trans_info_t *usb_trans_info;
-
-    usb_trans_info = usb_conv_info->usb_trans_info;
 
     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;
@@ -761,40 +1038,367 @@ static const value_string usb_hid_report_type_vals[] = {
     { 0, NULL }
 };
 
-/* Dissector for HID class-specific control request as defined in
- * USBHID 1.11, Chapter 7.2.
- * Returns tvb_length(tvb) if a class specific dissector was found
- * and 0 otherwise.
- */
 static gint
-dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_usb_hid_boot_keyboard_input_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
-    gboolean is_request;
-    usb_conv_info_t *usb_conv_info;
+    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)
+{
+    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;
 
-    /* Reject the packet if data or usb_trans_info are NULL */
-    if (data == NULL || ((usb_conv_info_t *)data)->usb_trans_info == NULL)
-        return 0;
-    usb_conv_info = (usb_conv_info_t *)data;
     usb_trans_info = usb_conv_info->usb_trans_info;
 
     is_request = (pinfo->srcport==NO_ENDPOINT);
 
-    /* See if we can find a class specific dissector for this request */
-    dissector = NULL;
-
     /* 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
@@ -815,8 +1419,42 @@ dissect_usb_hid_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
         offset += 1;
     }
 
-    dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
-    return tvb_length(tvb);
+    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 */
@@ -1112,19 +1750,199 @@ proto_register_usb_hid(void)
 
         { &hf_usb_hid_bCountryCode,
         { "bCountryCode", "usbhid.descriptor.hid.bCountryCode", FT_UINT8,
-            BASE_HEX, NULL, 0x0, NULL, HFILL }},
+            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, NULL, 0x0, NULL, HFILL }},
+            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 }}
+            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[] = {
@@ -1137,6 +1955,11 @@ proto_register_usb_hid(void)
     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
@@ -1144,10 +1967,13 @@ 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(
+    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);
 }