blob: 07f77676591adfe13b7719a7367fed7dd416ad11 [file] [log] [blame]
// Copyright 2022 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 "input_server.h"
namespace input_sample {
// Convert local data structure to a `fuchsia.input.report/InputReport` format.
void SampleInputReport::ToFidlInputReport(
fidl::WireTableBuilder<::fuchsia_input_report::wire::InputReport>& input_report,
fidl::AnyArena& arena) {
std::vector<uint8_t> pressed_buttons;
for (uint8_t i = 0; i < kMouseButtonCount; i++) {
if (buttons & (1 << i)) {
pressed_buttons.push_back(i + 1);
}
}
fidl::VectorView<uint8_t> buttons_vec(arena, pressed_buttons.size());
size_t idx = 0;
for (const auto& button : pressed_buttons) {
buttons_vec[idx++] = button;
}
auto mouse_input_rpt = fuchsia_input_report::wire::MouseInputReport::Builder(arena);
mouse_input_rpt.pressed_buttons(buttons_vec);
mouse_input_rpt.movement_x(rel_x);
mouse_input_rpt.movement_y(rel_y);
input_report.mouse(mouse_input_rpt.Build());
input_report.event_time(event_time.get());
}
// Static
// Handle incoming connection requests from FIDL clients
fidl::ServerBindingRef<fuchsia_input_report::InputDevice> InputSampleServer::BindDeviceClient(
driver::Logger* logger, async_dispatcher_t* dispatcher,
std::weak_ptr<input_report_reader::InputReportReaderManager<SampleInputReport>>
input_report_readers,
fidl::ServerEnd<fuchsia_input_report::InputDevice> request) {
// Bind each connection request to a unique FIDL server instance
auto server_impl = std::make_unique<InputSampleServer>(logger, dispatcher, input_report_readers);
return fidl::BindServer(dispatcher, std::move(request), std::move(server_impl),
std::mem_fn(&InputSampleServer::OnUnbound));
}
// This method is called when a server connection is torn down.
void InputSampleServer::OnUnbound(fidl::UnbindInfo info,
fidl::ServerEnd<fuchsia_input_report::InputDevice> server_end) {
if (info.is_peer_closed()) {
FDF_LOG(DEBUG, "Client disconnected");
} else if (!info.is_user_initiated()) {
FDF_LOG(ERROR, "Client connection unbound: %s", info.status_string());
}
}
// Protocol method for `fuchsia.input.report/InputDevice` to begin serving input reports
void InputSampleServer::GetInputReportsReader(GetInputReportsReaderRequestView request,
GetInputReportsReaderCompleter::Sync& completer) {
auto reader_manager = input_report_readers_.lock();
if (!reader_manager) {
FDF_LOG(ERROR, "Unable to access InputReport reader manager.");
request->reader.Close(ZX_ERR_BAD_STATE);
return;
}
zx_status_t status = reader_manager->CreateReader(dispatcher_, std::move(request->reader));
if (status != ZX_OK) {
FDF_LOG(ERROR, "Could not create input report reader: %d", status);
request->reader.Close(ZX_ERR_BAD_STATE);
}
}
// Protocol method for `fuchsia.input.report/InputDevice` to return the device descriptor
void InputSampleServer::GetDescriptor(GetDescriptorCompleter::Sync& completer) {
fidl::Arena allocator;
auto descriptor = fuchsia_input_report::wire::DeviceDescriptor::Builder(allocator);
fuchsia_input_report::wire::DeviceInfo device_info;
// We pick random VID/PIDs here, but these should be taken from the HID device,
// or defined in fuchsia.input.report/device_ids.fidl
device_info.vendor_id = 0x12345678;
device_info.product_id = 0x87654321;
fidl::VectorView<uint8_t> buttons(allocator, kMouseButtonCount);
buttons[0] = 0x01;
buttons[1] = 0x02;
buttons[2] = 0x03;
constexpr fuchsia_input_report::wire::Axis movement_x{
.range = {.min = -127, .max = 127},
.unit = {.type = fuchsia_input_report::wire::UnitType::kNone, .exponent = 0},
};
constexpr fuchsia_input_report::wire::Axis movement_y{
.range = {.min = -127, .max = 127},
.unit = {.type = fuchsia_input_report::wire::UnitType::kNone, .exponent = 0},
};
auto mouse_in_desc = fuchsia_input_report::wire::MouseInputDescriptor::Builder(allocator);
mouse_in_desc.buttons(buttons);
mouse_in_desc.movement_x(movement_x);
mouse_in_desc.movement_y(movement_y);
auto mouse_descriptor = fuchsia_input_report::wire::MouseDescriptor::Builder(allocator);
mouse_descriptor.input(mouse_in_desc.Build());
descriptor.mouse(mouse_descriptor.Build());
descriptor.device_info(device_info);
completer.Reply(descriptor.Build());
}
} // namespace input_sample