blob: 4d2f7d0f96292a30348119c9a94413e11f951cf2 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/lib/input_reader/keyboard.h"
#include <stdint.h>
#include <stdio.h>
#include <set>
#include <vector>
#include <hid-parser/parser.h>
#include <hid-parser/report.h>
#include <hid-parser/units.h>
#include <hid-parser/usages.h>
#include <hid/usages.h>
#include "src/lib/fxl/logging.h"
#include "src/ui/lib/input_reader/device.h"
namespace ui_input {
bool Keyboard::ParseReportDescriptor(const hid::ReportDescriptor& report_descriptor,
Descriptor* device_descriptor) {
std::set<uint32_t> key_values;
auto keyboard = fuchsia::ui::input::KeyboardDescriptor::New();
for (size_t i = 0; i < report_descriptor.input_count; i++) {
const hid::ReportField& field = report_descriptor.input_fields[i];
if (field.attr.usage.page == hid::usage::Page::kKeyboardKeypad) {
if (field.flags & hid::FieldTypeFlags::kArray) {
for (uint8_t key = static_cast<uint8_t>(field.attr.logc_mm.min);
key < static_cast<uint8_t>(field.attr.logc_mm.max); key++) {
key_values.insert(key);
}
} else {
key_values.insert(field.attr.usage.usage);
}
key_fields_.push_back(field);
}
}
keyboard->keys = std::vector<uint32_t>(key_values.begin(), key_values.end());
device_descriptor->has_keyboard = true;
device_descriptor->keyboard_descriptor = std::move(keyboard);
return true;
}
bool Keyboard::ParseReport(const uint8_t* data, size_t len,
fuchsia::ui::input::InputReport* report) {
FXL_CHECK(report);
FXL_CHECK(report->keyboard);
report->keyboard->pressed_keys.resize(0);
for (size_t i = 0; i < key_fields_.size(); i++) {
hid::ReportField& field = key_fields_[i];
double val_out_double;
if (!ExtractAsUnitType(data, len, field.attr, &val_out_double)) {
return false;
}
uint32_t val_out = static_cast<uint32_t>(val_out_double);
if (val_out == 0) {
continue;
}
if (field.flags & hid::FieldTypeFlags::kArray) {
if (val_out == HID_USAGE_KEY_ERROR_ROLLOVER) {
FXL_VLOG(2) << "hid: input_report: keyboard rollover error";
return false;
}
report->keyboard->pressed_keys.push_back(val_out);
} else {
report->keyboard->pressed_keys.push_back(field.attr.usage.usage);
}
}
return true;
}
} // namespace ui_input