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)
{
    guint32 id = 0xffff;
    proto_item *ti = proto_tree_get_parent(tree);
    gchar *str = NULL;
    guint32 val;

    switch (bTag) {
        case USBHID_LOCALITEM_TAG_USAGE:
            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)
                    id = tvb_get_guint8(tvb, offset);
                else if (bSize == 2)
                    id = tvb_get_ntohs(tvb, offset);
                str = get_usage_page_item_string(global->usage_page, id);
                proto_tree_add_uint_format(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, id, "Usage: %s (0x%02x)", str, id);
                proto_item_append_text(ti, " (%s)", str);
            }
            break;
        case USBHID_LOCALITEM_TAG_USAGE_MIN:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_USAGE_MAX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DESIG_INDEX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DESIG_MIN:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DESIG_MAX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_STRING_INDEX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_STRING_MIN:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_STRING_MAX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DELIMITER:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        default:
            proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
            proto_item_append_text(ti, " (Unknown)");
            break;
    }
    offset += bSize;

    g_free(str);

    return offset;
}
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)
{
    guint32 id = 0xffff;
    proto_item *ti = proto_tree_get_parent(tree);
    gchar *str = NULL;
    guint32 val;

    switch (bTag) {
        case USBHID_LOCALITEM_TAG_USAGE:
            if (bSize > 2) {
                 
                proto_tree_add_item(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN);
            } else {
                 
                if (bSize == 1)
                    id = tvb_get_guint8(tvb, offset);
                else if (bSize == 2)
                    id = tvb_get_ntohs(tvb, offset);
                str = get_usage_page_item_string(global->usage_page, id);
                proto_tree_add_uint_format(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, id, "Usage: %s (0x%02x)", str, id);
                proto_item_append_text(ti, " (%s)", str);
            }
            break;
        case USBHID_LOCALITEM_TAG_USAGE_MIN:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_usage_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_USAGE_MAX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_usage, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DESIG_INDEX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_desig_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DESIG_MIN:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_desig_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DESIG_MAX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_desig_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_STRING_INDEX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_string_index, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_STRING_MIN:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_string_min, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_STRING_MAX:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_string_max, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        case USBHID_LOCALITEM_TAG_DELIMITER:
            proto_tree_add_item_ret_uint(tree, hf_usb_hid_localitem_delimiter, tvb, offset, bSize, ENC_LITTLE_ENDIAN, &val);
            proto_item_append_text(ti, " (0x%02x)", val);
            break;
        default:
            proto_tree_add_item(tree, hf_usb_hid_item_unk_data, tvb, offset, bSize, ENC_NA);
            proto_item_append_text(ti, " (Unknown)");
            break;
    }
    offset += bSize;

    g_free(str);

    return offset;
}