| // 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>); |