blob: 4865032212530dd57f30acac8a3d3f6e53b3379f [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 "i2c_temperature.h"
#include <fidl/fuchsia.examples.i2c.temperature/cpp/wire.h>
#include <lib/driver2/service_client.h>
#include "constants.h"
#include "temperature_server.h"
namespace i2c_temperature {
zx::result<> I2cTemperatureDriver::Start() {
// Connect to the I2C bus controller.
auto channel_result = SetupI2cChannel();
if (channel_result.is_error()) {
return channel_result.take_error();
}
// Serve the fuchsia.examples.i2c.temperature/Device protocol to clients through the
// fuchsia.examples.i2c.temperature/Service wrapper.
driver::ServiceInstanceHandler handler;
fuchsia_examples_i2c_temperature::Service::Handler service(&handler);
auto result = service.add_device(
[this](fidl::ServerEnd<fuchsia_examples_i2c_temperature::Device> request) -> void {
I2cTemperatureServer::BindDeviceClient(dispatcher(), &logger(), i2c_channel_,
std::move(request));
});
ZX_ASSERT(result.is_ok());
result = context().outgoing()->AddService<fuchsia_examples_i2c_temperature::Service>(
std::move(handler));
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add service", KV("status", result.status_string()));
return result.take_error();
}
// Reset the sensor.
auto write_result = i2c_channel_->Write16(kSoftResetCommand);
if (write_result.is_error()) {
FDF_SLOG(ERROR, "Failed to send reset command: ", KV("status", write_result.status_string()));
return write_result.take_error();
}
// Read the initial temperature value.
auto read_result = i2c_channel_->Read16();
if (read_result.is_error()) {
FDF_SLOG(ERROR, "Failed to read temperature: ", KV("status", read_result.status_string()));
return read_result.take_error();
}
uint32_t temperature = read_result.value();
FDF_SLOG(INFO, "I2C temperature: ", KV("temperature", temperature));
return zx::ok();
}
// Connect to the `fuchsia.hardware.i2c/Device` protocol offered by the parent device node.
zx::result<> I2cTemperatureDriver::SetupI2cChannel() {
auto client_endpoint =
driver::Connect<fuchsia_hardware_i2c::Service::Device>(*context().incoming(), "default");
if (client_endpoint.status_value() != ZX_OK) {
FDF_SLOG(ERROR, "Failed to setup I2cChannel", KV("status", client_endpoint.status_string()));
return client_endpoint.take_error();
}
auto i2c_client = fidl::WireClient(std::move(*client_endpoint), dispatcher());
i2c_channel_ = std::make_shared<I2cChannel>(std::move(i2c_client));
return zx::ok();
}
} // namespace i2c_temperature
FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<i2c_temperature::I2cTemperatureDriver>);