blob: c3bef63ebc736ebd3170aaea2d079b969706a1d0 [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 "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);