blob: c94a36d505d5992096b49e09fd909c792d3a41c9 [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_sample.h"
#include <lib/async/cpp/task.h>
#include <lib/driver2/service_client.h>
#include "driver_compat.h"
namespace input_sample {
zx::status<> InputSampleDriver::Start() {
// Connect to the parent device node.
auto parent =
driver::Connect<fuchsia_driver_compat::Service::Device>(*context().incoming(), "default");
if (parent.status_value() != ZX_OK) {
FDF_SLOG(ERROR, "Failed to connect to parent", KV("status", parent.status_string()));
return parent.take_error();
}
// Add the fuchsia.input.report/InputDevice protocol to be served as "/svc/input-sample"
auto result = context().outgoing()->component().AddProtocol<fuchsia_input_report::InputDevice>(
[this](fidl::ServerEnd<fuchsia_input_report::InputDevice> request) {
InputSampleServer::BindDeviceClient(logger_, async_dispatcher(), input_report_readers_,
std::move(request));
},
kName);
if (result.status_value() != ZX_OK) {
return result;
}
auto service_dir = fidl::StringView::FromExternal(std::string("svc/").append(kName));
// Construct a devfs path that matches the device nodes topological path
auto path_result = fidl::WireCall(*parent)->GetTopologicalPath();
if (!path_result.ok()) {
FDF_SLOG(ERROR, "Failed to get topological path", KV("status", path_result.status_string()));
return zx::error(path_result.status());
}
std::string parent_path(path_result->path.data(), path_result->path.size());
auto devfs_path = fidl::StringView::FromExternal(parent_path.append("/").append(kName));
// Export an entry to devfs for fuchsia.input.report as an input device class
auto devfs_dir = input_driver_compat::ExportDevfsEntry(context().incoming().get(), service_dir,
devfs_path, /* INPUT_REPORT */ 26);
if (devfs_dir.is_error()) {
FDF_SLOG(ERROR, "Failed to export service", KV("status", devfs_dir.status_string()));
return devfs_dir.take_error();
}
// Serve the driver's FIDL protocol to clients.
auto status = context().outgoing()->Serve(std::move(devfs_dir.value()));
if (status.is_error()) {
FDF_SLOG(ERROR, "Failed to serve devfs directory", KV("status", status.status_string()));
return status.take_error();
}
// Start sending fake reports
input_report_readers_ =
std::make_shared<input_report_reader::InputReportReaderManager<SampleInputReport>>();
SendFakeReport();
return zx::ok();
}
// Periodically send a new input report with fake data.
void InputSampleDriver::SendFakeReport() {
// Update fake mouse report
report_.event_time = zx::time(zx_clock_get_monotonic());
report_.buttons++;
report_.rel_x++;
report_.rel_y++;
// Send fake mouse report
input_report_readers_->SendReportToAllReaders(report_);
// Run again in 1 second
async::PostDelayedTask(
async_dispatcher(), [this]() mutable { SendFakeReport(); }, zx::sec(1));
}
} // namespace input_sample
FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<input_sample::InputSampleDriver>);