Add format_text_wmem.
[metze/wireshark/wip.git] / epan / dissectors / packet-usb-hid.c
index 82c62ccacfa9398b5d0939618935b2eb04ddb4d3..046f43b1e4bbfbc4e22c0ee732935945805bae9c 100644 (file)
@@ -1,6 +1,4 @@
 /* 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;
@@ -86,6 +88,7 @@ static int hf_usb_hid_localitem_delimiter = -1;
 static gint ett_usb_hid_report = -1;
 static gint ett_usb_hid_item_header = -1;
 static gint ett_usb_hid_wValue = -1;
+static gint ett_usb_hid_descriptor = -1;
 
 static int hf_usb_hid_request = -1;
 static int hf_usb_hid_value = -1;
@@ -96,31 +99,87 @@ static int hf_usb_hid_report_id = -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;
+    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
 
 static const value_string usb_hid_item_bSize_vals[] = {
-       {0, "0 bytes"},
-       {1, "1 byte"},
-       {2, "2 bytes"},
-       {3, "4 bytes"},
-       {0, NULL}
+    {0, "0 bytes"},
+    {1, "1 byte"},
+    {2, "2 bytes"},
+    {3, "4 bytes"},
+    {0, NULL}
 };
 
 #define USBHID_ITEMTYPE_MAIN    0
@@ -128,11 +187,11 @@ static const value_string usb_hid_item_bSize_vals[] = {
 #define USBHID_ITEMTYPE_LOCAL   2
 #define USBHID_ITEMTYPE_LONG    3
 static const value_string usb_hid_item_bType_vals[] = {
-       {USBHID_ITEMTYPE_MAIN,   "Main"},
-       {USBHID_ITEMTYPE_GLOBAL, "Global"},
-       {USBHID_ITEMTYPE_LOCAL,  "Local"},
-       {USBHID_ITEMTYPE_LONG,   "Long item"},
-       {0, NULL}
+    {USBHID_ITEMTYPE_MAIN,   "Main"},
+    {USBHID_ITEMTYPE_GLOBAL, "Global"},
+    {USBHID_ITEMTYPE_LOCAL,  "Local"},
+    {USBHID_ITEMTYPE_LONG,   "Long item"},
+    {0, NULL}
 };
 
 #define USBHID_MAINITEM_TAG_INPUT           8
@@ -141,12 +200,12 @@ static const value_string usb_hid_item_bType_vals[] = {
 #define USBHID_MAINITEM_TAG_COLLECTION     10
 #define USBHID_MAINITEM_TAG_ENDCOLLECTION  12
 static const value_string usb_hid_mainitem_bTag_vals[] = {
-       {USBHID_MAINITEM_TAG_INPUT,         "Input"},
-       {USBHID_MAINITEM_TAG_OUTPUT,        "Output"},
-       {USBHID_MAINITEM_TAG_FEATURE,       "Feature"},
-       {USBHID_MAINITEM_TAG_COLLECTION,    "Collection"},
-       {USBHID_MAINITEM_TAG_ENDCOLLECTION, "End collection"},
-       {0, NULL}
+    {USBHID_MAINITEM_TAG_INPUT,         "Input"},
+    {USBHID_MAINITEM_TAG_OUTPUT,        "Output"},
+    {USBHID_MAINITEM_TAG_FEATURE,       "Feature"},
+    {USBHID_MAINITEM_TAG_COLLECTION,    "Collection"},
+    {USBHID_MAINITEM_TAG_ENDCOLLECTION, "End collection"},
+    {0, NULL}
 };
 #define USBHID_GLOBALITEM_TAG_USAGE_PAGE    0
 #define USBHID_GLOBALITEM_TAG_LOG_MIN       1
@@ -161,23 +220,23 @@ static const value_string usb_hid_mainitem_bTag_vals[] = {
 #define USBHID_GLOBALITEM_TAG_PUSH         10
 #define USBHID_GLOBALITEM_TAG_POP          11
 static const value_string usb_hid_globalitem_bTag_vals[] = {
-       {USBHID_GLOBALITEM_TAG_USAGE_PAGE,   "Usage"},
-       {USBHID_GLOBALITEM_TAG_LOG_MIN,      "Logical minimum"},
-       {USBHID_GLOBALITEM_TAG_LOG_MAX,      "Logical maximum"},
-       {USBHID_GLOBALITEM_TAG_PHY_MIN,      "Physical minimum"},
-       {USBHID_GLOBALITEM_TAG_PHY_MAX,      "Physical maximum"},
-       {USBHID_GLOBALITEM_TAG_UNIT_EXP,     "Unit exponent"},
-       {USBHID_GLOBALITEM_TAG_UNIT,         "Units"},
-       {USBHID_GLOBALITEM_TAG_REPORT_SIZE,  "Report size"},
-       {USBHID_GLOBALITEM_TAG_REPORT_ID,    "Report ID"},
-       {USBHID_GLOBALITEM_TAG_REPORT_COUNT, "Report count"},
-       {USBHID_GLOBALITEM_TAG_PUSH,         "Push"},
-       {USBHID_GLOBALITEM_TAG_POP,          "Pop"},
-       {12, "[Reserved]"},
-       {13, "[Reserved]"},
-       {14, "[Reserved]"},
-       {15, "[Reserved]"},
-       {0, NULL}
+    {USBHID_GLOBALITEM_TAG_USAGE_PAGE,   "Usage"},
+    {USBHID_GLOBALITEM_TAG_LOG_MIN,      "Logical minimum"},
+    {USBHID_GLOBALITEM_TAG_LOG_MAX,      "Logical maximum"},
+    {USBHID_GLOBALITEM_TAG_PHY_MIN,      "Physical minimum"},
+    {USBHID_GLOBALITEM_TAG_PHY_MAX,      "Physical maximum"},
+    {USBHID_GLOBALITEM_TAG_UNIT_EXP,     "Unit exponent"},
+    {USBHID_GLOBALITEM_TAG_UNIT,         "Units"},
+    {USBHID_GLOBALITEM_TAG_REPORT_SIZE,  "Report size"},
+    {USBHID_GLOBALITEM_TAG_REPORT_ID,    "Report ID"},
+    {USBHID_GLOBALITEM_TAG_REPORT_COUNT, "Report count"},
+    {USBHID_GLOBALITEM_TAG_PUSH,         "Push"},
+    {USBHID_GLOBALITEM_TAG_POP,          "Pop"},
+    {12, "[Reserved]"},
+    {13, "[Reserved]"},
+    {14, "[Reserved]"},
+    {15, "[Reserved]"},
+    {0, NULL}
 };
 #define USBHID_LOCALITEM_TAG_USAGE_PAGE     0
 #define USBHID_LOCALITEM_TAG_USAGE_MIN      1
@@ -191,518 +250,755 @@ static const value_string usb_hid_globalitem_bTag_vals[] = {
 #define USBHID_LOCALITEM_TAG_STRING_MAX     9
 #define USBHID_LOCALITEM_TAG_DELIMITER     10 /* Also listed as reserved in spec! */
 static const value_string usb_hid_localitem_bTag_vals[] = {
-       {USBHID_LOCALITEM_TAG_USAGE_PAGE,   "Usage"},
-       {USBHID_LOCALITEM_TAG_USAGE_MIN,    "Usage minimum"},
-       {USBHID_LOCALITEM_TAG_USAGE_MAX,    "Usage maximum"},
-       {USBHID_LOCALITEM_TAG_DESIG_INDEX,  "Designator index"},
-       {USBHID_LOCALITEM_TAG_DESIG_MIN,    "Designator minimum"},
-       {USBHID_LOCALITEM_TAG_DESIG_MAX,    "Designator maximum"},
-       {USBHID_LOCALITEM_TAG_STRING_INDEX, "String index"},
-       {USBHID_LOCALITEM_TAG_STRING_MIN,   "String minimum"},
-       {USBHID_LOCALITEM_TAG_STRING_MAX,   "String maximum"},
-       {USBHID_LOCALITEM_TAG_DELIMITER,    "Delimiter"},
-       {11, "[Reserved]"},
-       {12, "[Reserved]"},
-       {13, "[Reserved]"},
-       {14, "[Reserved]"},
-       {15, "[Reserved]"},
-       {0, NULL}
+    {USBHID_LOCALITEM_TAG_USAGE_PAGE,   "Usage"},
+    {USBHID_LOCALITEM_TAG_USAGE_MIN,    "Usage minimum"},
+    {USBHID_LOCALITEM_TAG_USAGE_MAX,    "Usage maximum"},
+    {USBHID_LOCALITEM_TAG_DESIG_INDEX,  "Designator index"},
+    {USBHID_LOCALITEM_TAG_DESIG_MIN,    "Designator minimum"},
+    {USBHID_LOCALITEM_TAG_DESIG_MAX,    "Designator maximum"},
+    {USBHID_LOCALITEM_TAG_STRING_INDEX, "String index"},
+    {USBHID_LOCALITEM_TAG_STRING_MIN,   "String minimum"},
+    {USBHID_LOCALITEM_TAG_STRING_MAX,   "String maximum"},
+    {USBHID_LOCALITEM_TAG_DELIMITER,    "Delimiter"},
+    {11, "[Reserved]"},
+    {12, "[Reserved]"},
+    {13, "[Reserved]"},
+    {14, "[Reserved]"},
+    {15, "[Reserved]"},
+    {0, NULL}
 };
 static const value_string usb_hid_longitem_bTag_vals[] = {
-       {15, "Long item"},
-       {0, NULL}
+    {15, "Long item"},
+    {0, NULL}
 };
 
 static const range_string usb_hid_mainitem_colltype_vals[] = {
-       {0x00, 0x00, "Physical"},
-       {0x01, 0x01, "Application"},
-       {0x02, 0x02, "Logical"},
-       {0x03, 0x03, "Report"},
-       {0x04, 0x04, "Named array"},
-       {0x05, 0x05, "Usage switch"},
-       {0x06, 0x06, "Usage modifier"},
-       {0x07, 0x7F, "[Reserved]"},
-       {0x80, 0xFF, "[Vendor-defined]"},
-       {0, 0, NULL}
+    {0x00, 0x00, "Physical"},
+    {0x01, 0x01, "Application"},
+    {0x02, 0x02, "Logical"},
+    {0x03, 0x03, "Report"},
+    {0x04, 0x04, "Named array"},
+    {0x05, 0x05, "Usage switch"},
+    {0x06, 0x06, "Usage modifier"},
+    {0x07, 0x7F, "[Reserved]"},
+    {0x80, 0xFF, "[Vendor-defined]"},
+    {0, 0, NULL}
 };
 
 static const value_string usb_hid_globalitem_unit_exp_vals[] = {
-       {0x0, "n^0"},
-       {0x1, "n^1"},
-       {0x2, "n^2"},
-       {0x3, "n^3"},
-       {0x4, "n^4"},
-       {0x5, "n^5"},
-       {0x6, "n^6"},
-       {0x7, "n^7"},
-       {0x8, "n^-8"},
-       {0x9, "n^-7"},
-       {0xA, "n^-6"},
-       {0xB, "n^-5"},
-       {0xC, "n^-4"},
-       {0xD, "n^-3"},
-       {0xE, "n^-2"},
-       {0xF, "n^-1"},
-       {0, NULL}
+    {0x0, "n^0"},
+    {0x1, "n^1"},
+    {0x2, "n^2"},
+    {0x3, "n^3"},
+    {0x4, "n^4"},
+    {0x5, "n^5"},
+    {0x6, "n^6"},
+    {0x7, "n^7"},
+    {0x8, "n^-8"},
+    {0x9, "n^-7"},
+    {0xA, "n^-6"},
+    {0xB, "n^-5"},
+    {0xC, "n^-4"},
+    {0xD, "n^-3"},
+    {0xE, "n^-2"},
+    {0xF, "n^-1"},
+    {0, NULL}
 };
 static const range_string usb_hid_item_usage_vals[] = {
-       {0x00, 0x00, "Undefined"},
-       {0x01, 0x01, "Generic desktop controls"},
-       {0x02, 0x02, "Simulation controls"},
-       {0x03, 0x03, "VR controls"},
-       {0x04, 0x04, "Sport controls"},
-       {0x05, 0x05, "Game controls"},
-       {0x06, 0x06, "Generic device controls"},
-       {0x07, 0x07, "Keyboard/keypad"},
-       {0x08, 0x08, "LEDs"},
-       {0x09, 0x09, "Button"},
-       {0x0A, 0x0A, "Ordinal"},
-       {0x0B, 0x0B, "Telephony"},
-       {0x0C, 0x0C, "Consumer"},
-       {0x0D, 0x0D, "Digitizer"},
-       {0x0E, 0x0E, "[Reserved]"},
-       {0x0F, 0x0F, "Physical Interface Device (PID) page"},
-       {0x10, 0x10, "Unicode"},
-       {0x11, 0x13, "[Reserved]"},
-       {0x14, 0x14, "Alphanumeric display"},
-       {0x15, 0x3F, "[Reserved]"},
-       {0x40, 0x40, "Medical instruments"},
-       {0x41, 0x7F, "[Reserved]"},
-       {0x80, 0x83, "Monitor page"},
-       {0x84, 0x87, "Power page"},
-       {0x88, 0x8B, "[Reserved]"},
-       {0x8C, 0x8C, "Bar code scanner page"},
-       {0x8D, 0x8D, "Scale page"},
-       {0x8E, 0x8E, "Magnetic Stripe Reading (MSR) devices"},
-       {0x8F, 0x8F, "[Reserved Point of Sale page]"},
-       {0x90, 0x90, "Camera control page"},
-       {0x91, 0x91, "Arcade page"},
-       {0x92, 0xFEFF, "[Reserved]"},
-       {0xFF00, 0xFFFF, "[Vendor-defined]"},
-       {0, 0, NULL}
+    {0x00, 0x00, "Undefined"},
+    {0x01, 0x01, "Generic desktop controls"},
+    {0x02, 0x02, "Simulation controls"},
+    {0x03, 0x03, "VR controls"},
+    {0x04, 0x04, "Sport controls"},
+    {0x05, 0x05, "Game controls"},
+    {0x06, 0x06, "Generic device controls"},
+    {0x07, 0x07, "Keyboard/keypad"},
+    {0x08, 0x08, "LEDs"},
+    {0x09, 0x09, "Button"},
+    {0x0A, 0x0A, "Ordinal"},
+    {0x0B, 0x0B, "Telephony"},
+    {0x0C, 0x0C, "Consumer"},
+    {0x0D, 0x0D, "Digitizer"},
+    {0x0E, 0x0E, "[Reserved]"},
+    {0x0F, 0x0F, "Physical Interface Device (PID) page"},
+    {0x10, 0x10, "Unicode"},
+    {0x11, 0x13, "[Reserved]"},
+    {0x14, 0x14, "Alphanumeric display"},
+    {0x15, 0x3F, "[Reserved]"},
+    {0x40, 0x40, "Medical instruments"},
+    {0x41, 0x7F, "[Reserved]"},
+    {0x80, 0x83, "Monitor page"},
+    {0x84, 0x87, "Power page"},
+    {0x88, 0x8B, "[Reserved]"},
+    {0x8C, 0x8C, "Bar code scanner page"},
+    {0x8D, 0x8D, "Scale page"},
+    {0x8E, 0x8E, "Magnetic Stripe Reading (MSR) devices"},
+    {0x8F, 0x8F, "[Reserved Point of Sale page]"},
+    {0x90, 0x90, "Camera control page"},
+    {0x91, 0x91, "Arcade page"},
+    {0x92, 0xFEFF, "[Reserved]"},
+    {0xFF00, 0xFFFF, "[Vendor-defined]"},
+    {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)
 {
-       switch (bTag) {
-               case USBHID_MAINITEM_TAG_INPUT:
-               case USBHID_MAINITEM_TAG_OUTPUT:
-               case USBHID_MAINITEM_TAG_FEATURE:
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit0, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit1, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit2, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit3, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit4, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit5, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_bit6, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       if (bTag == USBHID_MAINITEM_TAG_INPUT) {
-                               proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7_input, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       } else {
-                               proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       }
-                       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)");
-                       }
-                       break;
-               case USBHID_MAINITEM_TAG_COLLECTION:
-                       proto_tree_add_item(tree, hf_usb_hid_mainitem_colltype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_MAINITEM_TAG_ENDCOLLECTION:
-                       /* No item data */
-                       break;
-               default:
-                       proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
-                       break;
-       }
-       offset += bSize;
-       return offset;
+    switch (bTag) {
+        case USBHID_MAINITEM_TAG_INPUT:
+        case USBHID_MAINITEM_TAG_OUTPUT:
+        case USBHID_MAINITEM_TAG_FEATURE:
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit0, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit1, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit2, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit3, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit4, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit5, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_bit6, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            if (bTag == USBHID_MAINITEM_TAG_INPUT) {
+                proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7_input, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            } else {
+                proto_tree_add_item(tree, hf_usb_hid_mainitem_bit7, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            }
+            if (bSize > 1) {
+                proto_tree_add_item(tree, hf_usb_hid_mainitem_bit8, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            } else {
+                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:
+            proto_tree_add_item(tree, hf_usb_hid_mainitem_colltype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_MAINITEM_TAG_ENDCOLLECTION:
+            /* No item data */
+            break;
+        default:
+            proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
+            break;
+    }
+    offset += bSize;
+    return offset;
 }
 
 /* Dissector for the data in a HID main report. */
 static int
 dissect_usb_hid_report_globalitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag, struct usb_hid_global_state *global)
 {
-       switch (bTag) {
-               case USBHID_GLOBALITEM_TAG_USAGE_PAGE:
-                       switch (bSize) {
-                               case 1: global->usage_page = tvb_get_guint8(tvb, offset); break;
-                               case 2: global->usage_page = tvb_get_letohs(tvb, offset); break;
-                               case 3: global->usage_page = tvb_get_letoh24(tvb, offset); break;
-                               case 4: global->usage_page = tvb_get_letohl(tvb, offset); break;
-                               default: global->usage_page = 0; break;
-                       }
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_LOG_MIN:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_log_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_LOG_MAX:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_log_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_PHY_MIN:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_PHY_MAX:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_UNIT_EXP:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_exp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_UNIT:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_sys, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_len, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_mass, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_time, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_temp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_current, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_brightness, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_REPORT_SIZE:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_report_size, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_REPORT_ID:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_report_id, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_REPORT_COUNT:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_report_count, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_PUSH:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_push, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_GLOBALITEM_TAG_POP:
-                       proto_tree_add_item(tree, hf_usb_hid_globalitem_pop, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               default:
-                       proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
-                       break;
-       }
-       offset += bSize;
-       return offset;
+    switch (bTag) {
+        case USBHID_GLOBALITEM_TAG_USAGE_PAGE:
+            switch (bSize) {
+                case 1: global->usage_page = tvb_get_guint8(tvb, offset); break;
+                case 2: global->usage_page = tvb_get_letohs(tvb, offset); break;
+                case 3: global->usage_page = tvb_get_letoh24(tvb, offset); break;
+                case 4: global->usage_page = tvb_get_letohl(tvb, offset); break;
+                default: global->usage_page = 0; break;
+            }
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_LOG_MIN:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_log_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_LOG_MAX:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_log_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_PHY_MIN:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_PHY_MAX:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_phy_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_UNIT_EXP:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_exp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_UNIT:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_sys, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_len, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_mass, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_time, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_temp, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_current, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_unit_brightness, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_REPORT_SIZE:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_report_size, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_REPORT_ID:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_report_id, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_REPORT_COUNT:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_report_count, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_PUSH:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_push, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_GLOBALITEM_TAG_POP:
+            proto_tree_add_item(tree, hf_usb_hid_globalitem_pop, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        default:
+            proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
+            break;
+    }
+    offset += bSize;
+    return offset;
 }
 
 /* Dissector for the data in a HID main report. */
 static int
 dissect_usb_hid_report_localitem_data(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, unsigned int bSize, unsigned int bTag, struct usb_hid_global_state *global)
 {
-       unsigned int usage_page = 0xffffffff; /* in case bSize == 0 */
-
-       switch (bTag) {
-               case USBHID_LOCALITEM_TAG_USAGE_PAGE:
-                       if (bSize > 2) {
-                               /* Full page ID */
-                               proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       } else {
-                               /* Only lower few bits given, need to combine with last global ID */
-                               if (bSize == 1)
-                                       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);
-                       }
-                       break;
-               case USBHID_LOCALITEM_TAG_USAGE_MIN:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_USAGE_MAX:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_DESIG_INDEX:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_DESIG_MIN:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_DESIG_MAX:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_STRING_INDEX:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_STRING_MIN:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_STRING_MAX:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               case USBHID_LOCALITEM_TAG_DELIMITER:
-                       proto_tree_add_item(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
-                       break;
-               default:
-                       proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
-                       break;
-       }
-       offset += bSize;
-       return offset;
+    unsigned int usage_page = 0xffffffff; /* in case bSize == 0 */
+
+    switch (bTag) {
+        case USBHID_LOCALITEM_TAG_USAGE_PAGE:
+            if (bSize > 2) {
+                /* Full page ID */
+                proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            } else {
+                /* Only lower few bits given, need to combine with last global ID */
+                if (bSize == 1)
+                    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_uint(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, usage_page);
+            }
+            break;
+        case USBHID_LOCALITEM_TAG_USAGE_MIN:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_USAGE_MAX:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_DESIG_INDEX:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_DESIG_MIN:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_DESIG_MAX:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_STRING_INDEX:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_STRING_MIN:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_STRING_MAX:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        case USBHID_LOCALITEM_TAG_DELIMITER:
+            proto_tree_add_item(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
+            break;
+        default:
+            proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
+            break;
+    }
+    offset += bSize;
+    return offset;
 }
 
 /* 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;
-       int old_offset;
-       unsigned int tmp;
-       unsigned int bSize, bType, bTag;
-       const value_string *usb_hid_cur_bTag_vals;
-       int hf_usb_hid_curitem_bTag;
-       struct usb_hid_global_state cur_global;
-       memcpy(&cur_global, global, sizeof(struct usb_hid_global_state));
-
-       while (tvb_reported_length_remaining(tvb, offset))
-       {
-               old_offset=offset;
-
-               tmp = tvb_get_guint8(tvb, offset);
-               bSize = tmp & USBHID_SIZE_MASK;
-               if (bSize == 3) bSize++; /* 3 == four bytes */
-               bType = (tmp & USBHID_TYPE_MASK) >> 2;
-               bTag = (tmp & USBHID_TAG_MASK) >> 4;
-
-               switch (bType) {
-                       case USBHID_ITEMTYPE_MAIN:
-                               hf_usb_hid_curitem_bTag = hf_usb_hid_mainitem_bTag;
-                               usb_hid_cur_bTag_vals = usb_hid_mainitem_bTag_vals;
-                               break;
-                       case USBHID_ITEMTYPE_GLOBAL:
-                               hf_usb_hid_curitem_bTag = hf_usb_hid_globalitem_bTag;
-                               usb_hid_cur_bTag_vals = usb_hid_globalitem_bTag_vals;
-                               break;
-                       case USBHID_ITEMTYPE_LOCAL:
-                               hf_usb_hid_curitem_bTag = hf_usb_hid_localitem_bTag;
-                               usb_hid_cur_bTag_vals = usb_hid_localitem_bTag_vals;
-                               break;
-                       default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
-                               hf_usb_hid_curitem_bTag = hf_usb_hid_longitem_bTag;
-                               usb_hid_cur_bTag_vals = usb_hid_longitem_bTag_vals;
-                               break;
-               }
-
-               subitem = proto_tree_add_text(parent_tree, tvb, offset, bSize + 1, "%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);
-               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);
-               offset++;
-               if ((bType == 3) && (bTag == 16)) {
-                       /* Long item */
-                       bSize = tvb_get_guint8(tvb, offset);
-                       proto_tree_add_item(subtree, hf_usb_hid_item_bDataSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-                       offset++;
-                       proto_tree_add_item(subtree, hf_usb_hid_item_bLongItemTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-                       offset++;
-                       proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
-                       offset += bSize;
-               } else {
-                       /* Short item */
-                       switch (bType) {
-                               case USBHID_ITEMTYPE_MAIN:
-                                       offset = dissect_usb_hid_report_mainitem_data(pinfo, subtree, tvb, offset, bSize, bTag);
-                                       break;
-                               case USBHID_ITEMTYPE_GLOBAL:
-                                       offset = dissect_usb_hid_report_globalitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
-                                       break;
-                               case USBHID_ITEMTYPE_LOCAL:
-                                       offset = dissect_usb_hid_report_localitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
-                                       break;
-                               default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
-                                       proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
-                                       offset += bSize;
-                                       break;
-                       }
-               }
-
-               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);
-                               proto_item_set_len(subitem, offset-old_offset);
-                       } else if (bTag == USBHID_MAINITEM_TAG_ENDCOLLECTION) {
-                               /* End collection, break out to parent tree item */
-                               break;
-                       }
-               }
-       }
-       return offset;
+    proto_item *subitem;
+    proto_tree *tree, *subtree;
+    int old_offset;
+    unsigned int tmp;
+    unsigned int bSize, bType, bTag;
+    const value_string *usb_hid_cur_bTag_vals;
+    int hf_usb_hid_curitem_bTag;
+    struct usb_hid_global_state cur_global;
+    memcpy(&cur_global, global, sizeof(struct usb_hid_global_state));
+
+    while (tvb_reported_length_remaining(tvb, offset) > 0)
+    {
+        old_offset=offset;
+
+        tmp = tvb_get_guint8(tvb, offset);
+        bSize = tmp & USBHID_SIZE_MASK;
+        if (bSize == 3) bSize++; /* 3 == four bytes */
+        bType = (tmp & USBHID_TYPE_MASK) >> 2;
+        bTag = (tmp & USBHID_TAG_MASK) >> 4;
+
+        switch (bType) {
+            case USBHID_ITEMTYPE_MAIN:
+                hf_usb_hid_curitem_bTag = hf_usb_hid_mainitem_bTag;
+                usb_hid_cur_bTag_vals = usb_hid_mainitem_bTag_vals;
+                break;
+            case USBHID_ITEMTYPE_GLOBAL:
+                hf_usb_hid_curitem_bTag = hf_usb_hid_globalitem_bTag;
+                usb_hid_cur_bTag_vals = usb_hid_globalitem_bTag_vals;
+                break;
+            case USBHID_ITEMTYPE_LOCAL:
+                hf_usb_hid_curitem_bTag = hf_usb_hid_localitem_bTag;
+                usb_hid_cur_bTag_vals = usb_hid_localitem_bTag_vals;
+                break;
+            default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
+                hf_usb_hid_curitem_bTag = hf_usb_hid_longitem_bTag;
+                usb_hid_cur_bTag_vals = usb_hid_longitem_bTag_vals;
+                break;
+        }
+
+        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")
+        );
+
+        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);
+        offset++;
+        if ((bType == 3) && (bTag == 16)) {
+            /* Long item */
+            bSize = tvb_get_guint8(tvb, offset);
+            proto_tree_add_item(subtree, hf_usb_hid_item_bDataSize, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+            offset++;
+            proto_tree_add_item(subtree, hf_usb_hid_item_bLongItemTag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+            offset++;
+            proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
+            offset += bSize;
+        } else {
+            /* Short item */
+            switch (bType) {
+                case USBHID_ITEMTYPE_MAIN:
+                    offset = dissect_usb_hid_report_mainitem_data(pinfo, subtree, tvb, offset, bSize, bTag);
+                    break;
+                case USBHID_ITEMTYPE_GLOBAL:
+                    offset = dissect_usb_hid_report_globalitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
+                    break;
+                case USBHID_ITEMTYPE_LOCAL:
+                    offset = dissect_usb_hid_report_localitem_data(pinfo, subtree, tvb, offset, bSize, bTag, &cur_global);
+                    break;
+                default: /* Only USBHID_ITEMTYPE_LONG, but keep compiler happy */
+                    proto_tree_add_item(subtree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
+                    offset += bSize;
+                    break;
+            }
+        }
+
+        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_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 */
+                break;
+            }
+        }
+    }
+    return offset;
 }
 
 /* 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;
-       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);
-
-               proto_item_set_len(item, offset-old_offset);
-       }
-
-       return offset;
+    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));
+
+    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);
+
+    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;
-
-       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);
-
-               /* 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_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;*/
-       } else {
-       }
+    proto_item *item;
+    proto_tree *subtree;
+
+    if (!is_request)
+        return;
+
+    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);
+
+    /* 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_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)
+        return;
 
-       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);
+    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(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(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_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
-               offset += 2;
+    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;*/
-       } else {
-       }
+    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;
-
-       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);
-
-               /* 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_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;*/
-       } else {
-       }
+    proto_item *item;
+    proto_tree *subtree;
+
+    if (!is_request)
+        return;
+
+    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);
+
+    /* 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_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_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    offset += 2;
 
-               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_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;*/
-       } else {
-       }
+    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;
-       usb_setup_dissector dissector;
+    guint8 request;
+    usb_setup_dissector dissector;
 } usb_setup_dissector_table_t;
 
 
@@ -716,345 +1012,981 @@ typedef struct _usb_setup_dissector_table_t {
 #define USB_HID_SETUP_SET_PROTOCOL    0x0B
 
 static const usb_setup_dissector_table_t setup_dissectors[] = {
-       { USB_HID_SETUP_GET_REPORT,   dissect_usb_hid_get_report },
-       { USB_HID_SETUP_GET_IDLE,     dissect_usb_hid_get_idle },
-       { USB_HID_SETUP_GET_PROTOCOL, dissect_usb_hid_get_protocol },
-       { USB_HID_SETUP_SET_REPORT,   dissect_usb_hid_set_report },
-       { USB_HID_SETUP_SET_IDLE,     dissect_usb_hid_set_idle },
-       { USB_HID_SETUP_SET_PROTOCOL, dissect_usb_hid_set_protocol },
-       { 0, NULL }
+    { USB_HID_SETUP_GET_REPORT,   dissect_usb_hid_get_report },
+    { USB_HID_SETUP_GET_IDLE,     dissect_usb_hid_get_idle },
+    { USB_HID_SETUP_GET_PROTOCOL, dissect_usb_hid_get_protocol },
+    { USB_HID_SETUP_SET_REPORT,   dissect_usb_hid_set_report },
+    { USB_HID_SETUP_SET_IDLE,     dissect_usb_hid_set_idle },
+    { USB_HID_SETUP_SET_PROTOCOL, dissect_usb_hid_set_protocol },
+    { 0, NULL }
 };
 
 static const value_string setup_request_names_vals[] = {
-       { USB_HID_SETUP_GET_REPORT,   "GET_REPORT" },
-       { USB_HID_SETUP_GET_IDLE,     "GET_IDLE" },
-       { USB_HID_SETUP_GET_PROTOCOL, "GET_PROTOCOL" },
-       { USB_HID_SETUP_SET_REPORT,   "SET_REPORT" },
-       { USB_HID_SETUP_SET_IDLE,     "SET_IDLE" },
-       { USB_HID_SETUP_SET_PROTOCOL, "SET_PROTOCOL" },
-       { 0, NULL }
+    { USB_HID_SETUP_GET_REPORT,   "GET_REPORT" },
+    { USB_HID_SETUP_GET_IDLE,     "GET_IDLE" },
+    { USB_HID_SETUP_GET_PROTOCOL, "GET_PROTOCOL" },
+    { USB_HID_SETUP_SET_REPORT,   "SET_REPORT" },
+    { USB_HID_SETUP_SET_IDLE,     "SET_IDLE" },
+    { USB_HID_SETUP_SET_PROTOCOL, "SET_PROTOCOL" },
+    { 0, NULL }
 };
 
 static const value_string usb_hid_report_type_vals[] = {
-       { 1, "Input" },
-       { 2, "Output" },
-       { 3, "Feature" },
-       { 0, NULL }
+    { 1, "Input" },
+    { 2, "Output" },
+    { 3, "Feature" },
+    { 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_)
 {
-       gboolean is_request;
-       usb_conv_info_t *usb_conv_info;
-       usb_trans_info_t *usb_trans_info;
-       int offset = 0;
-       usb_setup_dissector dissector;
-       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;
-
-       /* 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;
-                       }
-               }
-       }
-       /* No, we could not find any class specific dissector for this request
-        * return FALSE and let USB try any of the standard requests.
-        */
-       if (!dissector) {
-               return FALSE;
-       }
-
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
-
-       if (check_col(pinfo->cinfo, COL_INFO)) {
-               col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
-               val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
-                       is_request ? "Request" : "Response");
-       }
-
-       if (is_request) {
-               proto_tree_add_item(tree, hf_usb_hid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
-               offset += 1;
-       }
-
-       dissector(pinfo, tree, tvb, offset, is_request, usb_trans_info, usb_conv_info);
-       return TRUE;
+    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;
 }
 
-void
-proto_register_usb_hid(void)
+static gint
+dissect_usb_hid_boot_keyboard_output_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
-       static hf_register_info hf[] = {
-               { &hf_usb_hid_item_bSize,
-                       { "bSize", "usbhid.item.bSize", FT_UINT8, BASE_DEC,
-                               VALS(usb_hid_item_bSize_vals), USBHID_SIZE_MASK, NULL, HFILL }},
-
-               { &hf_usb_hid_item_bType,
-                       { "bType", "usbhid.item.bType", FT_UINT8, BASE_DEC,
-                               VALS(usb_hid_item_bType_vals), USBHID_TYPE_MASK, NULL, HFILL }},
-
-               { &hf_usb_hid_mainitem_bTag,
-                       { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
-                               VALS(usb_hid_mainitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
-
-               { &hf_usb_hid_globalitem_bTag,
-                       { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
-                               VALS(usb_hid_globalitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
-
-               { &hf_usb_hid_localitem_bTag,
-                       { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
-                               VALS(usb_hid_localitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
-
-               { &hf_usb_hid_longitem_bTag,
-                       { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
-                               VALS(usb_hid_longitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
-
-               { &hf_usb_hid_item_bDataSize,
-                       { "bDataSize", "usbhid.item.bDataSize", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+    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;
+}
 
-               { &hf_usb_hid_item_bLongItemTag,
-                       { "bTag", "usbhid.item.bLongItemTag", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+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;
+}
 
-               /* Main-report item data */
 
-               { &hf_usb_hid_mainitem_bit0,
-                       { "Data/constant", "usbhid.item.main.readonly", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit0), 1<<0, NULL, HFILL }},
+/* 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;
+}
 
-               { &hf_usb_hid_mainitem_bit1,
-                       { "Data type", "usbhid.item.main.variable", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit1), 1<<1, NULL, HFILL }},
+/* 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 = NULL;
+    const usb_setup_dissector_table_t *tmp;
+
+    usb_trans_info = usb_conv_info->usb_trans_info;
+
+    is_request = (pinfo->srcport==NO_ENDPOINT);
+
+    /* Check valid values for bmRequestType. See Chapter 7.2 in USBHID 1.11 */
+    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 0 and let USB try any of the standard requests.
+     */
+    if (!dissector) {
+        return 0;
+    }
+
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "USBHID");
+
+    col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+    val_to_str(usb_trans_info->setup.request, setup_request_names_vals, "Unknown type %x"),
+        is_request ? "Request" : "Response");
+
+    if (is_request) {
+        proto_tree_add_item(tree, hf_usb_hid_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        offset += 1;
+    }
+
+    dissector(pinfo, tree, tvb, offset, is_request, usb_conv_info);
+    return tvb_captured_length(tvb);
+}
 
-               { &hf_usb_hid_mainitem_bit2,
-                       { "Coordinates", "usbhid.item.main.relative", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit2), 1<<2, NULL, HFILL }},
+/* 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;
+}
 
-               { &hf_usb_hid_mainitem_bit3,
-                       { "Min/max wraparound", "usbhid.item.main.wrap", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit3), 1<<3, NULL, HFILL }},
+/* dissect a descriptor that is specific to the HID class */
+static gint
+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);
+
+    /* for now, we only handle the HID descriptor here */
+    if (type != USB_DT_HID)
+        return 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;
+    }
+
+    proto_item_set_len(ti, offset);
+    return offset;
+}
 
-               { &hf_usb_hid_mainitem_bit4,
-                       { "Physical relationship to data", "usbhid.item.main.nonlinear", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit4), 1<<4, NULL, HFILL }},
 
-               { &hf_usb_hid_mainitem_bit5,
-                       { "Preferred state", "usbhid.item.main.no_preferred_state", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit5), 1<<5, NULL, HFILL }},
+void
+proto_register_usb_hid(void)
+{
+    static hf_register_info hf[] = {
+        { &hf_usb_hid_item_bSize,
+            { "bSize", "usbhid.item.bSize", FT_UINT8, BASE_DEC,
+                VALS(usb_hid_item_bSize_vals), USBHID_SIZE_MASK, NULL, HFILL }},
 
-               { &hf_usb_hid_mainitem_bit6,
-                       { "Has null position", "usbhid.item.main.nullstate", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit6), 1<<6, NULL, HFILL }},
+        { &hf_usb_hid_item_bType,
+            { "bType", "usbhid.item.bType", FT_UINT8, BASE_DEC,
+                VALS(usb_hid_item_bType_vals), USBHID_TYPE_MASK, NULL, HFILL }},
 
-               { &hf_usb_hid_mainitem_bit7,
-                       { "(Non)-volatile", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit7), 1<<7, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bTag,
+            { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
+                VALS(usb_hid_mainitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
 
-               { &hf_usb_hid_mainitem_bit7_input,
-                       { "[Reserved]", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
-                               NULL, 1<<7, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_bTag,
+            { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
+                VALS(usb_hid_globalitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
 
-               { &hf_usb_hid_mainitem_bit8,
-                       { "Bits or bytes", "usbhid.item.main.buffered_bytes", FT_BOOLEAN, 9,
-                               TFS(&tfs_mainitem_bit8), 1<<8, NULL, HFILL }},
+        { &hf_usb_hid_localitem_bTag,
+            { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
+                VALS(usb_hid_localitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
 
-               { &hf_usb_hid_mainitem_colltype,
-                       { "Collection type", "usbhid.item.main.colltype", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
-                               RVALS(usb_hid_mainitem_colltype_vals), 0, NULL, HFILL }},
+        { &hf_usb_hid_longitem_bTag,
+            { "bTag", "usbhid.item.bTag", FT_UINT8, BASE_HEX,
+                VALS(usb_hid_longitem_bTag_vals), USBHID_TAG_MASK, NULL, HFILL }},
 
-               /* Global-report item data */
+        { &hf_usb_hid_item_bDataSize,
+            { "bDataSize", "usbhid.item.bDataSize", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_usage,
-                       { "Usage page", "usbhid.item.global.usage", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
-                               RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
+        { &hf_usb_hid_item_bLongItemTag,
+            { "bTag", "usbhid.item.bLongItemTag", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_log_min,
-                       { "Logical minimum", "usbhid.item.global.log_min", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        /* Main-report item data */
 
-               { &hf_usb_hid_globalitem_log_max,
-                       { "Logical maximum", "usbhid.item.global.log_max", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit0,
+            { "Data/constant", "usbhid.item.main.readonly", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit0), 1<<0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_phy_min,
-                       { "Physical minimum", "usbhid.item.global.phy_min", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit1,
+            { "Data type", "usbhid.item.main.variable", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit1), 1<<1, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_phy_max,
-                       { "Physical maximum", "usbhid.item.global.phy_max", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit2,
+            { "Coordinates", "usbhid.item.main.relative", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit2), 1<<2, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_exp,
-                       { "Unit exponent", "usbhid.item.global.unit_exp", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit3,
+            { "Min/max wraparound", "usbhid.item.main.wrap", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit3), 1<<3, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_sys,
-                       { "System", "usbhid.item.global.unit.system", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x0000000F, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit4,
+            { "Physical relationship to data", "usbhid.item.main.nonlinear", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit4), 1<<4, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_len,
-                       { "Length", "usbhid.item.global.unit.length", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x000000F0, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit5,
+            { "Preferred state", "usbhid.item.main.no_preferred_state", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit5), 1<<5, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_mass,
-                       { "Mass", "usbhid.item.global.unit.mass", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x00000F00, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit6,
+            { "Has null position", "usbhid.item.main.nullstate", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit6), 1<<6, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_time,
-                       { "Time", "usbhid.item.global.unit.time", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x0000F000, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit7,
+            { "(Non)-volatile", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit7), 1<<7, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_temp,
-                       { "Temperature", "usbhid.item.global.unit.temperature", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x000F0000, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit7_input,
+            { "[Reserved]", "usbhid.item.main.volatile", FT_BOOLEAN, 9,
+                NULL, 1<<7, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_current,
-                       { "Current", "usbhid.item.global.unit.current", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x00F00000, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_bit8,
+            { "Bits or bytes", "usbhid.item.main.buffered_bytes", FT_BOOLEAN, 9,
+                TFS(&tfs_mainitem_bit8), 1<<8, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_unit_brightness,
-                       { "Luminous intensity", "usbhid.item.global.unit.brightness", FT_UINT32, BASE_HEX,
-                               VALS(usb_hid_globalitem_unit_exp_vals), 0x0F000000, NULL, HFILL }},
+        { &hf_usb_hid_mainitem_colltype,
+            { "Collection type", "usbhid.item.main.colltype", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
+                RVALS(usb_hid_mainitem_colltype_vals), 0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_report_size,
-                       { "Report size", "usbhid.item.global.report_size", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        /* Global-report item data */
 
-               { &hf_usb_hid_globalitem_report_id,
-                       { "Report ID", "usbhid.item.global.report_id", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_usage,
+            { "Usage page", "usbhid.item.global.usage", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
+                RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_report_count,
-                       { "Report count", "usbhid.item.global.report_count", FT_UINT8, BASE_DEC,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_log_min,
+            { "Logical minimum", "usbhid.item.global.log_min", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_push,
-                       { "Push", "usbhid.item.global.push", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_log_max,
+            { "Logical maximum", "usbhid.item.global.log_max", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_globalitem_pop,
-                       { "Pop", "usbhid.item.global.pop", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_phy_min,
+            { "Physical minimum", "usbhid.item.global.phy_min", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               /* Local-report item data */
+        { &hf_usb_hid_globalitem_phy_max,
+            { "Physical maximum", "usbhid.item.global.phy_max", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_usage,
-                       { "Usage", "usbhid.item.local.usage", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
-                               RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_exp,
+            { "Unit exponent", "usbhid.item.global.unit_exp", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_usage_min,
-                       { "Usage minimum", "usbhid.item.local.usage_min", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_sys,
+            { "System", "usbhid.item.global.unit.system", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x0000000F, NULL, HFILL }},
 
-#if 0
-               { &hf_usb_hid_localitem_usage_max,
-                       { "Usage maximum", "usbhid.item.local.usage_max", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
-#endif
+        { &hf_usb_hid_globalitem_unit_len,
+            { "Length", "usbhid.item.global.unit.length", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x000000F0, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_desig_index,
-                       { "Designator index", "usbhid.item.local.desig_index", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_mass,
+            { "Mass", "usbhid.item.global.unit.mass", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x00000F00, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_desig_min,
-                       { "Designator minimum", "usbhid.item.local.desig_min", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_time,
+            { "Time", "usbhid.item.global.unit.time", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x0000F000, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_desig_max,
-                       { "Designator maximum", "usbhid.item.local.desig_max", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_temp,
+            { "Temperature", "usbhid.item.global.unit.temperature", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x000F0000, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_string_index,
-                       { "String index", "usbhid.item.local.string_index", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_current,
+            { "Current", "usbhid.item.global.unit.current", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x00F00000, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_string_min,
-                       { "String minimum", "usbhid.item.local.string_min", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_unit_brightness,
+            { "Luminous intensity", "usbhid.item.global.unit.brightness", FT_UINT32, BASE_HEX,
+                VALS(usb_hid_globalitem_unit_exp_vals), 0x0F000000, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_string_max,
-                       { "String maximum", "usbhid.item.local.string_max", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_report_size,
+            { "Report size", "usbhid.item.global.report_size", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_localitem_delimiter,
-                       { "Delimiter", "usbhid.item.local.delimiter", FT_UINT8, BASE_HEX,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_report_id,
+            { "Report ID", "usbhid.item.global.report_id", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
 
+        { &hf_usb_hid_globalitem_report_count,
+            { "Report count", "usbhid.item.global.report_count", FT_UINT8, BASE_DEC,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_item_unk_data,
-                       { "Item data", "usbhid.item.data", FT_BYTES, BASE_NONE,
-                               NULL, 0, NULL, HFILL }},
+        { &hf_usb_hid_globalitem_push,
+            { "Push", "usbhid.item.global.push", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
 
-               /* USB HID specific requests */
-               { &hf_usb_hid_request,
-               { "bRequest", "usbhid.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
-                 NULL, HFILL }},
+        { &hf_usb_hid_globalitem_pop,
+            { "Pop", "usbhid.item.global.pop", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_value,
-               { "wValue", "usbhid.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
-                 NULL, HFILL }},
+        /* Local-report item data */
 
-               { &hf_usb_hid_index,
-               { "wIndex", "usbhid.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
-                 NULL, HFILL }},
+        { &hf_usb_hid_localitem_usage,
+            { "Usage", "usbhid.item.local.usage", FT_UINT8, BASE_RANGE_STRING|BASE_HEX,
+                RVALS(usb_hid_item_usage_vals), 0, NULL, HFILL }},
 
-               { &hf_usb_hid_length,
-               { "wLength", "usbhid.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
-                 NULL, HFILL }},
+        { &hf_usb_hid_localitem_usage_min,
+            { "Usage minimum", "usbhid.item.local.usage_min", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
 
-               { &hf_usb_hid_report_type,
-               { "ReportType", "usbhid.setup.ReportType", FT_UINT8, BASE_DEC,
-                 VALS(usb_hid_report_type_vals), 0x0,
-                 NULL, HFILL }},
+#if 0
+        { &hf_usb_hid_localitem_usage_max,
+            { "Usage maximum", "usbhid.item.local.usage_max", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+#endif
 
-               { &hf_usb_hid_report_id,
-               { "ReportID", "usbhid.setup.ReportID", FT_UINT8, BASE_DEC, NULL, 0x0,
-                 NULL, HFILL }},
+        { &hf_usb_hid_localitem_desig_index,
+            { "Designator index", "usbhid.item.local.desig_index", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+        { &hf_usb_hid_localitem_desig_min,
+            { "Designator minimum", "usbhid.item.local.desig_min", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+        { &hf_usb_hid_localitem_desig_max,
+            { "Designator maximum", "usbhid.item.local.desig_max", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+        { &hf_usb_hid_localitem_string_index,
+            { "String index", "usbhid.item.local.string_index", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+        { &hf_usb_hid_localitem_string_min,
+            { "String minimum", "usbhid.item.local.string_min", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+        { &hf_usb_hid_localitem_string_max,
+            { "String maximum", "usbhid.item.local.string_max", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+        { &hf_usb_hid_localitem_delimiter,
+            { "Delimiter", "usbhid.item.local.delimiter", FT_UINT8, BASE_HEX,
+                NULL, 0, NULL, HFILL }},
+
+
+        { &hf_usb_hid_item_unk_data,
+            { "Item data", "usbhid.item.data", FT_BYTES, BASE_NONE,
+                NULL, 0, NULL, HFILL }},
+
+        /* USB HID specific requests */
+        { &hf_usb_hid_request,
+        { "bRequest", "usbhid.setup.bRequest", FT_UINT8, BASE_HEX, VALS(setup_request_names_vals), 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_value,
+        { "wValue", "usbhid.setup.wValue", FT_UINT16, BASE_HEX, NULL, 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_index,
+        { "wIndex", "usbhid.setup.wIndex", FT_UINT16, BASE_DEC, NULL, 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_length,
+        { "wLength", "usbhid.setup.wLength", FT_UINT16, BASE_DEC, NULL, 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_report_type,
+        { "ReportType", "usbhid.setup.ReportType", FT_UINT8, BASE_DEC,
+          VALS(usb_hid_report_type_vals), 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_report_id,
+        { "ReportID", "usbhid.setup.ReportID", FT_UINT8, BASE_DEC, NULL, 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_duration,
+        { "Duration", "usbhid.setup.Duration", FT_UINT8, BASE_DEC, NULL, 0x0,
+          NULL, HFILL }},
+
+        { &hf_usb_hid_zero,
+        { "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
+          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[] = {
+        &ett_usb_hid_report,
+        &ett_usb_hid_item_header,
+        &ett_usb_hid_wValue,
+        &ett_usb_hid_descriptor
+    };
+
+    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);
 
-               { &hf_usb_hid_duration,
-               { "Duration", "usbhid.setup.Duration", FT_UINT8, BASE_DEC, NULL, 0x0,
-                 NULL, HFILL }},
+}
 
-               { &hf_usb_hid_zero,
-               { "(zero)", "usbhid.setup.zero", FT_UINT8, BASE_DEC, NULL, 0x0,
-                 NULL, HFILL }}
+void
+proto_reg_handoff_usb_hid(void)
+{
+    dissector_handle_t usb_hid_control_handle, usb_hid_descr_handle;
 
-       };
+    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);
 
-       static gint *usb_hid_subtrees[] = {
-               &ett_usb_hid_report,
-               &ett_usb_hid_item_header,
-               &ett_usb_hid_wValue
-       };
+    dissector_add_for_decode_as("usb.device", usb_hid_control_handle);
 
-       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_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);
 }
 
-void
-proto_reg_handoff_usb_hid(void) {
-       dissector_handle_t usb_hid_control_handle;
-
-       usb_hid_control_handle = new_create_dissector_handle(dissect_usb_hid_control, proto_usb_hid);
-       dissector_add_uint("usb.control", IF_CLASS_HID, usb_hid_control_handle);
-}
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */