blob: 0c75bb5da88466277fb3df07745401797c6836c0 [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/input/lib/hid-input-report/sensor.h"
#include <stdint.h>
#include <zircon/compiler.h>
#include <hid-parser/parser.h>
#include <hid-parser/report.h>
#include <hid-parser/units.h>
#include <hid-parser/usages.h>
#include "src/ui/input/lib/hid-input-report/axis.h"
#include "src/ui/input/lib/hid-input-report/device.h"
namespace hid_input_report {
ParseResult Sensor::ParseReportDescriptor(const hid::ReportDescriptor& hid_report_descriptor) {
hid::Attributes values[fuchsia_input_report::SENSOR_MAX_VALUES] = {};
size_t num_values = 0;
for (size_t i = 0; i < hid_report_descriptor.input_count; i++) {
const hid::ReportField& field = hid_report_descriptor.input_fields[i];
if (field.attr.usage.page != static_cast<uint32_t>(hid::usage::Page::kSensor)) {
continue;
}
llcpp::fuchsia::input::report::SensorType type;
zx_status_t status = HidSensorUsageToLlcppSensorType(
static_cast<hid::usage::Sensor>(field.attr.usage.usage), &type);
if (status != ZX_OK) {
continue;
}
if (num_values == fuchsia_input_report::SENSOR_MAX_VALUES) {
return ParseResult::kTooManyItems;
}
values[num_values] = field.attr;
num_values++;
}
// No error, write to class members.
num_values_ = num_values;
for (size_t i = 0; i < num_values; i++) {
values_[i] = values[i];
}
report_size_ = hid_report_descriptor.input_byte_sz;
report_id_ = hid_report_descriptor.report_id;
return ParseResult::kOk;
}
ParseResult Sensor::CreateDescriptor(fidl::Allocator* allocator,
fuchsia_input_report::DeviceDescriptor::Builder* descriptor) {
auto input = fuchsia_input_report::SensorInputDescriptor::Builder(
allocator->make<fuchsia_input_report::SensorInputDescriptor::Frame>());
// Set the values array.
{
auto values = allocator->make<fuchsia_input_report::SensorAxis[]>(num_values_);
for (size_t i = 0; i < num_values_; i++) {
if (HidSensorUsageToLlcppSensorType(static_cast<hid::usage::Sensor>(values_[i].usage.usage),
&values[i].type) != ZX_OK) {
return ParseResult::kItemNotFound;
}
values[i].axis = LlcppAxisFromAttribute(values_[i]);
}
auto values_view = allocator->make<fidl::VectorView<fuchsia_input_report::SensorAxis>>(
std::move(values), num_values_);
input.set_values(std::move(values_view));
}
auto sensor = fuchsia_input_report::SensorDescriptor::Builder(
allocator->make<fuchsia_input_report::SensorDescriptor::Frame>());
sensor.set_input(allocator->make<fuchsia_input_report::SensorInputDescriptor>(input.build()));
descriptor->set_sensor(allocator->make<fuchsia_input_report::SensorDescriptor>(sensor.build()));
return ParseResult::kOk;
}
ParseResult Sensor::ParseInputReport(const uint8_t* data, size_t len, fidl::Allocator* allocator,
fuchsia_input_report::InputReport::Builder* report) {
auto sensor_report = fuchsia_input_report::SensorInputReport::Builder(
allocator->make<fuchsia_input_report::SensorInputReport::Frame>());
auto values = allocator->make<int64_t[]>(num_values_);
for (size_t i = 0; i < num_values_; i++) {
double value_out;
if (hid::ExtractAsUnitType(data, len, values_[i], &value_out)) {
values[i] = static_cast<int64_t>(value_out);
}
}
sensor_report.set_values(
allocator->make<fidl::VectorView<int64_t>>(std::move(values), num_values_));
report->set_sensor(
allocator->make<fuchsia_input_report::SensorInputReport>(sensor_report.build()));
return ParseResult::kOk;
}
} // namespace hid_input_report