| // 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 <lib/hid-parser/parser.h> |
| #include <lib/hid-parser/report.h> |
| #include <lib/hid-parser/units.h> |
| #include <lib/hid-parser/usages.h> |
| #include <stdint.h> |
| #include <zircon/compiler.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::wire::kSensorMaxValues] = {}; |
| 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; |
| } |
| |
| fuchsia_input_report::wire::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::wire::kSensorMaxValues) { |
| return ParseResult::kTooManyItems; |
| } |
| values[num_values] = field.attr; |
| num_values++; |
| } |
| |
| if (num_values == 0) { |
| return ParseResult::kItemNotFound; |
| } |
| |
| // 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::AnyArena& allocator, |
| fuchsia_input_report::wire::DeviceDescriptor& descriptor) { |
| // Find the first SensorInputDescriptor that isn't filled out yet. |
| uint32_t index = 0; |
| for (; index < descriptor.sensor().input().count(); index++) { |
| if (descriptor.sensor().input()[index].IsEmpty()) { |
| break; |
| } |
| } |
| fuchsia_input_report::wire::SensorInputDescriptor& input = descriptor.sensor().input()[index]; |
| input.Allocate(allocator); |
| input.set_report_id(report_id_); |
| |
| // Set the values array. |
| { |
| fidl::VectorView<fuchsia_input_report::wire::SensorAxis> values(allocator, 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]); |
| } |
| input.set_values(allocator, std::move(values)); |
| } |
| |
| return ParseResult::kOk; |
| } |
| |
| ParseResult Sensor::ParseInputReportInternal( |
| const uint8_t* data, size_t len, fidl::AnyArena& allocator, |
| fuchsia_input_report::wire::InputReport& input_report) { |
| fuchsia_input_report::wire::SensorInputReport sensor_report(allocator); |
| |
| fidl::VectorView<int64_t> values(allocator, 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, std::move(values)); |
| |
| input_report.set_sensor(allocator, std::move(sensor_report)); |
| return ParseResult::kOk; |
| } |
| |
| } // namespace hid_input_report |