blob: d14de137ed718d2cc47711881826d82105616cda [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/hid-input-report/fidl.h"
#include <stdio.h>
#include <variant>
#include <hid-parser/usages.h>
#include "src/ui/lib/key_util/key_util.h"
namespace hid_input_report {
namespace llcpp_report = ::llcpp::fuchsia::input::report;
namespace {
llcpp_report::Unit HidUnitToLlcppUnit(hid::unit::UnitType unit) {
switch (unit) {
case hid::unit::UnitType::None:
return llcpp_report::Unit::NONE;
case hid::unit::UnitType::Other:
return llcpp_report::Unit::OTHER;
case hid::unit::UnitType::Distance:
return llcpp_report::Unit::DISTANCE;
case hid::unit::UnitType::Weight:
return llcpp_report::Unit::WEIGHT;
case hid::unit::UnitType::Rotation:
return llcpp_report::Unit::ROTATION;
case hid::unit::UnitType::AngularVelocity:
return llcpp_report::Unit::ANGULAR_VELOCITY;
case hid::unit::UnitType::LinearVelocity:
return llcpp_report::Unit::LINEAR_VELOCITY;
case hid::unit::UnitType::Acceleration:
return llcpp_report::Unit::ACCELERATION;
case hid::unit::UnitType::MagneticFlux:
return llcpp_report::Unit::MAGNETIC_FLUX;
case hid::unit::UnitType::Light:
return llcpp_report::Unit::LUMINOUS_FLUX;
case hid::unit::UnitType::Pressure:
return llcpp_report::Unit::PRESSURE;
case hid::unit::UnitType::Lux:
return llcpp_report::Unit::LUX;
default:
return llcpp_report::Unit::OTHER;
}
}
zx_status_t HidSensorUsageToLlcppSensorType(hid::usage::Sensor usage,
llcpp_report::SensorType* type) {
switch (usage) {
case hid::usage::Sensor::kAccelerationAxisX:
*type = llcpp_report::SensorType::ACCELEROMETER_X;
break;
case hid::usage::Sensor::kAccelerationAxisY:
*type = llcpp_report::SensorType::ACCELEROMETER_Y;
break;
case hid::usage::Sensor::kAccelerationAxisZ:
*type = llcpp_report::SensorType::ACCELEROMETER_Z;
break;
case hid::usage::Sensor::kMagneticFluxAxisX:
*type = llcpp_report::SensorType::MAGNETOMETER_X;
break;
case hid::usage::Sensor::kMagneticFluxAxisY:
*type = llcpp_report::SensorType::MAGNETOMETER_Y;
break;
case hid::usage::Sensor::kMagneticFluxAxisZ:
*type = llcpp_report::SensorType::MAGNETOMETER_Z;
break;
case hid::usage::Sensor::kAngularVelocityX:
*type = llcpp_report::SensorType::GYROSCOPE_X;
break;
case hid::usage::Sensor::kAngularVelocityY:
*type = llcpp_report::SensorType::GYROSCOPE_Y;
break;
case hid::usage::Sensor::kAngularVelocityZ:
*type = llcpp_report::SensorType::GYROSCOPE_Z;
break;
case hid::usage::Sensor::kLightIlluminance:
*type = llcpp_report::SensorType::LIGHT_ILLUMINANCE;
break;
case hid::usage::Sensor::kLightRedLight:
*type = llcpp_report::SensorType::LIGHT_RED;
break;
case hid::usage::Sensor::kLightBlueLight:
*type = llcpp_report::SensorType::LIGHT_BLUE;
break;
case hid::usage::Sensor::kLightGreenLight:
*type = llcpp_report::SensorType::LIGHT_GREEN;
break;
default:
return ZX_ERR_NOT_SUPPORTED;
}
return ZX_OK;
}
llcpp_report::Axis HidAxisToLlcppAxis(Axis axis) {
llcpp_report::Axis new_axis = {};
new_axis.range.min = axis.range.min;
new_axis.range.max = axis.range.max;
new_axis.unit = HidUnitToLlcppUnit(axis.unit);
return new_axis;
}
} // namespace
zx_status_t SetMouseDescriptor(const MouseDescriptor& hid_mouse_desc, FidlDescriptor* descriptor) {
FidlMouseDescriptor& mouse_desc = descriptor->mouse_descriptor;
auto& mouse_builder = mouse_desc.mouse_builder;
mouse_builder = llcpp_report::MouseDescriptor::Build();
if (hid_mouse_desc.movement_x.enabled) {
mouse_desc.movement_x = HidAxisToLlcppAxis(hid_mouse_desc.movement_x);
mouse_builder.set_movement_x(&mouse_desc.movement_x);
}
if (hid_mouse_desc.movement_y.enabled) {
mouse_desc.movement_y = HidAxisToLlcppAxis(hid_mouse_desc.movement_y);
mouse_builder.set_movement_y(&mouse_desc.movement_y);
}
for (size_t i = 0; i < hid_mouse_desc.num_buttons; i++) {
mouse_desc.buttons[i] = hid_mouse_desc.button_ids[i];
}
mouse_desc.buttons_view =
fidl::VectorView<uint8_t>(mouse_desc.buttons, hid_mouse_desc.num_buttons);
mouse_builder.set_buttons(&mouse_desc.buttons_view);
descriptor->mouse_descriptor.mouse_descriptor = mouse_builder.view();
descriptor->descriptor_builder.set_mouse(&descriptor->mouse_descriptor.mouse_descriptor);
return ZX_OK;
}
zx_status_t SetMouseReport(const MouseReport& hid_mouse_report, FidlReport* report) {
FidlMouseReport& mouse_report = std::get<FidlMouseReport>(report->report);
auto& mouse_builder = mouse_report.mouse_builder;
mouse_builder = llcpp_report::MouseReport::Build();
mouse_report.report_data = hid_mouse_report;
MouseReport& report_data = mouse_report.report_data;
if (hid_mouse_report.has_movement_x) {
mouse_builder.set_movement_x(&report_data.movement_x);
}
if (hid_mouse_report.has_movement_y) {
mouse_builder.set_movement_y(&report_data.movement_y);
}
mouse_report.buttons_view =
fidl::VectorView<uint8_t>(report_data.buttons_pressed, report_data.num_buttons_pressed);
mouse_builder.set_pressed_buttons(&mouse_report.buttons_view);
mouse_report.mouse_report = mouse_builder.view();
report->report_builder.set_mouse(&mouse_report.mouse_report);
return ZX_OK;
}
zx_status_t SetSensorDescriptor(const SensorDescriptor& hid_sensor_desc,
FidlDescriptor* descriptor) {
FidlSensorDescriptor& sensor_desc = descriptor->sensor_descriptor;
auto& sensor_builder = sensor_desc.sensor_builder;
size_t fidl_value_index = 0;
for (size_t i = 0; i < hid_sensor_desc.num_values; i++) {
zx_status_t status = HidSensorUsageToLlcppSensorType(
hid_sensor_desc.values[i].type, &sensor_desc.values[fidl_value_index].type);
if (status != ZX_OK) {
continue;
}
sensor_desc.values[fidl_value_index].axis = HidAxisToLlcppAxis(hid_sensor_desc.values[i].axis);
fidl_value_index++;
}
sensor_desc.values_view =
fidl::VectorView<llcpp_report::SensorAxis>(sensor_desc.values.data(), fidl_value_index);
sensor_builder.set_values(&sensor_desc.values_view);
descriptor->sensor_descriptor.sensor_descriptor = sensor_builder.view();
descriptor->descriptor_builder.set_sensor(&descriptor->sensor_descriptor.sensor_descriptor);
return ZX_OK;
}
zx_status_t SetSensorReport(const SensorReport& hid_sensor_report, FidlReport* report) {
FidlSensorReport& sensor_report = std::get<FidlSensorReport>(report->report);
auto& sensor_builder = sensor_report.sensor_builder;
sensor_builder = llcpp_report::SensorReport::Build();
sensor_report.report_data = hid_sensor_report;
sensor_report.values_view = fidl::VectorView<int64_t>(sensor_report.report_data.values,
sensor_report.report_data.num_values);
sensor_builder.set_values(&sensor_report.values_view);
sensor_report.sensor_report = sensor_builder.view();
report->report_builder.set_sensor(&sensor_report.sensor_report);
return ZX_OK;
}
zx_status_t SetTouchDescriptor(const TouchDescriptor& hid_touch_desc, FidlDescriptor* descriptor) {
FidlTouchDescriptor& touch_desc = descriptor->touch_descriptor;
auto& touch_builder = touch_desc.touch_builder;
for (size_t i = 0; i < hid_touch_desc.num_contacts; i++) {
FidlContactDescriptor& contact = touch_desc.contacts[i];
if (hid_touch_desc.contacts[i].position_x.enabled) {
contact.position_x = HidAxisToLlcppAxis(hid_touch_desc.contacts[i].position_x);
contact.contact_builder.set_position_x(&touch_desc.contacts[i].position_x);
}
if (hid_touch_desc.contacts[i].position_y.enabled) {
contact.position_y = HidAxisToLlcppAxis(hid_touch_desc.contacts[i].position_y);
contact.contact_builder.set_position_y(&touch_desc.contacts[i].position_y);
}
if (hid_touch_desc.contacts[i].pressure.enabled) {
contact.pressure = HidAxisToLlcppAxis(hid_touch_desc.contacts[i].pressure);
contact.contact_builder.set_pressure(&touch_desc.contacts[i].pressure);
}
if (hid_touch_desc.contacts[i].contact_width.enabled) {
contact.contact_width = HidAxisToLlcppAxis(hid_touch_desc.contacts[i].contact_width);
contact.contact_builder.set_contact_width(&touch_desc.contacts[i].contact_width);
}
if (hid_touch_desc.contacts[i].contact_height.enabled) {
contact.contact_height = HidAxisToLlcppAxis(hid_touch_desc.contacts[i].contact_height);
contact.contact_builder.set_contact_height(&touch_desc.contacts[i].contact_height);
}
touch_desc.contacts_built[i] = contact.contact_builder.view();
}
touch_desc.contacts_view = fidl::VectorView<llcpp_report::ContactDescriptor>(
touch_desc.contacts_built.data(), hid_touch_desc.num_contacts);
touch_builder.set_contacts(&touch_desc.contacts_view);
touch_desc.max_contacts = hid_touch_desc.max_contacts;
touch_builder.set_max_contacts(&touch_desc.max_contacts);
touch_desc.touch_type = hid_touch_desc.touch_type;
touch_builder.set_touch_type(&touch_desc.touch_type);
descriptor->touch_descriptor.touch_descriptor = touch_builder.view();
descriptor->descriptor_builder.set_touch(&descriptor->touch_descriptor.touch_descriptor);
return ZX_OK;
}
zx_status_t SetTouchReport(const TouchReport& hid_touch_report, FidlReport* report) {
FidlTouchReport& touch_report = std::get<FidlTouchReport>(report->report);
auto& touch_builder = touch_report.touch_builder;
touch_report.report_data = hid_touch_report;
TouchReport& report_data = touch_report.report_data;
for (size_t i = 0; i < report_data.num_contacts; i++) {
llcpp_report::ContactReport::Builder& fidl_contact = touch_report.contacts[i].contact;
fidl_contact = llcpp_report::ContactReport::Build();
ContactReport& contact = report_data.contacts[i];
if (contact.has_contact_id) {
fidl_contact.set_contact_id(&contact.contact_id);
}
if (contact.has_position_x) {
fidl_contact.set_position_x(&contact.position_x);
}
if (contact.has_position_y) {
fidl_contact.set_position_y(&contact.position_y);
}
if (contact.has_pressure) {
fidl_contact.set_pressure(&contact.pressure);
}
if (contact.has_contact_width) {
fidl_contact.set_contact_width(&contact.contact_width);
}
if (contact.has_contact_height) {
fidl_contact.set_contact_height(&contact.contact_height);
}
touch_report.contacts_built[i] = fidl_contact.view();
}
touch_report.contacts_view = fidl::VectorView<llcpp_report::ContactReport>(
touch_report.contacts_built.data(), hid_touch_report.num_contacts);
touch_builder.set_contacts(&touch_report.contacts_view);
touch_report.touch_report = touch_builder.view();
report->report_builder.set_touch(&touch_report.touch_report);
return ZX_OK;
}
zx_status_t SetKeyboardDescriptor(const KeyboardDescriptor& hid_keyboard_desc,
FidlDescriptor* descriptor) {
FidlKeyboardDescriptor& keyboard_desc = descriptor->keyboard_descriptor;
size_t fidl_key_index = 0;
for (size_t i = 0; i < hid_keyboard_desc.num_keys; i++) {
std::optional<fuchsia::ui::input2::Key> key = key_util::hid_key_to_fuchsia_key(
hid::USAGE(hid::usage::Page::kKeyboardKeypad, hid_keyboard_desc.keys[i]));
if (key) {
// Cast the key enum from HLCPP to LLCPP. We are guaranteed that this will be equivalent.
keyboard_desc.keys_data[fidl_key_index++] =
static_cast<llcpp::fuchsia::ui::input2::Key>(*key);
}
}
keyboard_desc.keys_view = fidl::VectorView<llcpp::fuchsia::ui::input2::Key>(
keyboard_desc.keys_data.data(), fidl_key_index);
keyboard_desc.keyboard_builder.set_keys(&keyboard_desc.keys_view);
keyboard_desc.keyboard_descriptor = keyboard_desc.keyboard_builder.view();
descriptor->descriptor_builder.set_keyboard(&keyboard_desc.keyboard_descriptor);
return ZX_OK;
}
zx_status_t SetKeyboardReport(const KeyboardReport& hid_keyboard_report, FidlReport* report) {
FidlKeyboardReport& keyboard_report = std::get<FidlKeyboardReport>(report->report);
size_t fidl_key_index = 0;
for (size_t i = 0; i < hid_keyboard_report.num_pressed_keys; i++) {
std::optional<fuchsia::ui::input2::Key> key = key_util::hid_key_to_fuchsia_key(
hid::USAGE(hid::usage::Page::kKeyboardKeypad, hid_keyboard_report.pressed_keys[i]));
if (key) {
// Cast the key enum from HLCPP to LLCPP. We are guaranteed that this will be equivalent.
keyboard_report.pressed_keys_data[fidl_key_index++] =
static_cast<llcpp::fuchsia::ui::input2::Key>(*key);
}
}
keyboard_report.pressed_keys_view = fidl::VectorView<llcpp::fuchsia::ui::input2::Key>(
keyboard_report.pressed_keys_data.data(), fidl_key_index);
keyboard_report.keyboard_builder.set_pressed_keys(&keyboard_report.pressed_keys_view);
keyboard_report.keyboard_report = keyboard_report.keyboard_builder.view();
report->report_builder.set_keyboard(&keyboard_report.keyboard_report);
return ZX_OK;
}
zx_status_t SetFidlDescriptor(const hid_input_report::ReportDescriptor& hid_desc,
FidlDescriptor* descriptor) {
if (std::holds_alternative<MouseDescriptor>(hid_desc.descriptor)) {
return SetMouseDescriptor(std::get<MouseDescriptor>(hid_desc.descriptor), descriptor);
}
if (std::holds_alternative<SensorDescriptor>(hid_desc.descriptor)) {
return SetSensorDescriptor(std::get<SensorDescriptor>(hid_desc.descriptor), descriptor);
}
if (std::holds_alternative<TouchDescriptor>(hid_desc.descriptor)) {
return SetTouchDescriptor(std::get<TouchDescriptor>(hid_desc.descriptor), descriptor);
}
if (std::holds_alternative<KeyboardDescriptor>(hid_desc.descriptor)) {
return SetKeyboardDescriptor(std::get<KeyboardDescriptor>(hid_desc.descriptor), descriptor);
}
return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t SetFidlReport(const hid_input_report::Report& hid_report, FidlReport* report) {
if (std::holds_alternative<MouseReport>(hid_report.report)) {
report->report = FidlMouseReport();
return SetMouseReport(std::get<MouseReport>(hid_report.report), report);
}
if (std::holds_alternative<SensorReport>(hid_report.report)) {
report->report = FidlSensorReport();
return SetSensorReport(std::get<SensorReport>(hid_report.report), report);
}
if (std::holds_alternative<TouchReport>(hid_report.report)) {
report->report = FidlTouchReport();
return SetTouchReport(std::get<TouchReport>(hid_report.report), report);
}
if (std::holds_alternative<KeyboardReport>(hid_report.report)) {
report->report = FidlKeyboardReport();
return SetKeyboardReport(std::get<KeyboardReport>(hid_report.report), report);
}
return ZX_ERR_NOT_SUPPORTED;
}
} // namespace hid_input_report