dissect_usb_hid_keyboard_page(tvbuff_t *tvb, packet_info _U_ *pinfo,
        proto_tree *tree, hid_field_t *field, int *bit_offset)
{
    gint32 val = 0;
    unsigned int usage_count = wmem_array_get_count(field->usages);
    guint32 usage;
    proto_item *array_ti;
    proto_tree *array_tree = NULL;
    int array_offset = -1;

    if ((field->properties & HID_MAIN_TYPE) == HID_MAIN_ARRAY) {
        array_ti = proto_tree_add_bits_item(tree, hf_usbhid_key_array, tvb, *bit_offset,
                                field->report_size * field->report_count, ENC_NA);
        array_tree = proto_item_add_subtree(array_ti, ett_usb_hid_key_array);
        array_offset = *bit_offset;
        *bit_offset += field->report_size * field->report_count;
    }

    for(unsigned int i = 0; i < field->report_count; i++) {
        switch (field->properties & HID_MAIN_TYPE)
        {
            case HID_MAIN_ARRAY:
                /* the data is the usage (eg. KEY_A + KEY_B) */

                if (hid_unpack_logical(tvb, array_offset, field->report_size, field->logical_min, &val))
                    return -1;

                if (val) /* val == 0 means no key in this array element*/
                    proto_tree_add_boolean_bits_format_value(array_tree, hf_usbhid_key, tvb, array_offset, field->report_size,
                                val, "%s (0x%02x)", val_to_str_ext(val, &keycode_vals_ext, "Unknown"), val);
                array_offset += field->report_size;
                break;

            case HID_MAIN_VARIABLE:
                /* the data is a boolean state for the usage (eg. KEY_SHIFT = 1, KEY_CONTROL = 0) */

                if (hid_unpack_logical(tvb, *bit_offset, field->report_size, field->logical_min, &val))
                    return -1;

                if (i >= usage_count) {
                    proto_tree_add_bits_item(tree, hf_usbhid_padding, tvb, *bit_offset, field->report_size, ENC_NA);
                    *bit_offset += field->report_size;
                    continue;
                }

                usage = *((guint32*) wmem_array_index(field->usages, i));

                proto_tree_add_boolean_bits_format_value(tree, hf_usbhid_key, tvb, *bit_offset, field->report_size, val,
                            "%s (0x%02x) = %s", val_to_str_ext(usage, &keycode_vals_ext, "Unknown"), usage, val ? "DOWN" : "UP");
                *bit_offset += field->report_size;
                break;

            default:
                return -1;
        }
    }

    return 0;
}
dissect_usb_hid_keyboard_page(tvbuff_t *tvb, packet_info _U_ *pinfo,
        proto_tree *tree, hid_field_t *field, int *bit_offset)
{
    gint32 val = 0;
    unsigned int usage_count = wmem_array_get_count(field->usages);
    guint32 usage;
    proto_item *array_ti;
    proto_tree *array_tree = NULL;
    int array_offset = -1;

    if ((field->properties & HID_MAIN_TYPE) == HID_MAIN_ARRAY) {
        array_ti = proto_tree_add_bits_item(tree, hf_usbhid_key_array, tvb, *bit_offset,
                                field->report_size * field->report_count, ENC_NA);
        array_tree = proto_item_add_subtree(array_ti, ett_usb_hid_key_array);
        array_offset = *bit_offset;
        *bit_offset += field->report_size * field->report_count;
    }

    for(unsigned int i = 0; i < field->report_count; i++) {
        switch (field->properties & HID_MAIN_TYPE)
        {
            case HID_MAIN_ARRAY:
                 

                if (hid_unpack_logical(tvb, array_offset, field->report_size, field->logical_min, &val))
                    return -1;

                if (val)  
                    proto_tree_add_boolean_bits_format_value(array_tree, hf_usbhid_key, tvb, array_offset, field->report_size,
                                val, "%s (0x%02x)", val_to_str_ext(val, &keycode_vals_ext, "Unknown"), val);
                array_offset += field->report_size;
                break;

            case HID_MAIN_VARIABLE:
                 

                if (hid_unpack_logical(tvb, *bit_offset, field->report_size, field->logical_min, &val))
                    return -1;

                if (i >= usage_count) {
                    proto_tree_add_bits_item(tree, hf_usbhid_padding, tvb, *bit_offset, field->report_size, ENC_NA);
                    *bit_offset += field->report_size;
                    continue;
                }

                usage = *((guint32*) wmem_array_index(field->usages, i));

                proto_tree_add_boolean_bits_format_value(tree, hf_usbhid_key, tvb, *bit_offset, field->report_size, val,
                            "%s (0x%02x) = %s", val_to_str_ext(usage, &keycode_vals_ext, "Unknown"), usage, val ? "DOWN" : "UP");
                *bit_offset += field->report_size;
                break;

            default:
                return -1;
        }
    }

    return 0;
}