| // 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 "examples/drivers/transport/driver/v2/child-driver.h" |
| |
| #include <lib/driver/component/cpp/driver_export.h> |
| #include <lib/driver/logging/cpp/logger.h> |
| |
| namespace driver_transport { |
| |
| zx::result<> ChildTransportDriver::Start() { |
| auto connect_result = incoming()->Connect<fuchsia_hardware_i2cimpl::Service::Device>(); |
| if (connect_result.is_error()) { |
| fdf::error("Failed to connect fuchsia.hardware.i2cimpl device protocol: {}", connect_result); |
| return connect_result.take_error(); |
| } |
| |
| i2c_impl_client_.Bind(std::move(connect_result.value()), driver_dispatcher()->get()); |
| |
| auto result = QueryInfo(); |
| if (result.is_error()) { |
| return result.take_error(); |
| } |
| |
| std::vector<fuchsia_driver_framework::NodeProperty2> properties = {}; |
| zx::result child_result = AddChild("transport-child", properties, {}); |
| if (child_result.is_error()) { |
| return child_result.take_error(); |
| } |
| |
| controller_.Bind(std::move(child_result.value()), dispatcher()); |
| |
| // Since we set the dispatcher to "ALLOW_SYNC_CALLS" in the driver CML, we |
| // need to seal the option after we finish all our sync calls over driver transport. |
| auto status = |
| fdf_dispatcher_seal(driver_dispatcher()->get(), FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS); |
| if (status != ZX_OK) { |
| fdf::error("Failed to seal ALLOW_SYNC_CALLS: {}", zx::make_result(status)); |
| return zx::error(status); |
| } |
| |
| return zx::ok(); |
| } |
| |
| void ChildTransportDriver::SetBitrate(uint32_t bitrate) { |
| // Since we sealed synchronous calls at the end of the Start() function, all future calls |
| // over the driver transport must be asynchronous. |
| fdf::Arena arena('I2CI'); |
| i2c_impl_client_.buffer(arena)->SetBitrate(bitrate).Then( |
| [bitrate](fdf::WireUnownedResult<fuchsia_hardware_i2cimpl::Device::SetBitrate>& result) { |
| if (!result.ok()) { |
| fdf::error("Failed to set the bitrate: {}", result.error()); |
| } |
| if (result->is_error()) { |
| fdf::error("Bitrate request returned an error: {}", result->error_value()); |
| } |
| fdf::info("Successfully set the bitrate to {}", bitrate); |
| }); |
| } |
| |
| zx::result<> ChildTransportDriver::QueryInfo() { |
| // Query and store the max transfer size. |
| fdf::Arena arena('I2CI'); |
| auto max_transfer_sz_result = i2c_impl_client_.sync().buffer(arena)->GetMaxTransferSize(); |
| if (!max_transfer_sz_result.ok()) { |
| fdf::error("Failed to request max transfer size: {}", max_transfer_sz_result.error()); |
| return zx::error(max_transfer_sz_result.status()); |
| } |
| if (max_transfer_sz_result->is_error()) { |
| fdf::error("GetMaxTransferSize request returned an error: {}", |
| max_transfer_sz_result->error_value()); |
| return max_transfer_sz_result->take_error(); |
| } |
| |
| max_transfer_size_ = max_transfer_sz_result.value()->size; |
| fdf::info("Max transfer size: {}", max_transfer_size_); |
| return zx::ok(); |
| } |
| |
| } // namespace driver_transport |
| |
| FUCHSIA_DRIVER_EXPORT(driver_transport::ChildTransportDriver); |