blob: 923ca3643dbf3a20b8992b074d846328324ea868 [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 "temperature_server.h"
#include <endian.h>
#include <lib/driver2/structured_logger.h>
#include "constants.h"
namespace i2c_temperature {
// Static
// Handle incoming connection requests from FIDL clients
fidl::ServerBindingRef<fuchsia_examples_i2c_temperature::Device>
I2cTemperatureServer::BindDeviceClient(
async_dispatcher_t* dispatcher, driver::Logger* logger, std::weak_ptr<I2cChannel> i2c_channel,
fidl::ServerEnd<fuchsia_examples_i2c_temperature::Device> request) {
// Bind each connection request to the shared instance.
auto server_impl = std::make_unique<I2cTemperatureServer>(logger, i2c_channel);
return fidl::BindServer(dispatcher, std::move(request), std::move(server_impl),
std::mem_fn(&I2cTemperatureServer::OnUnbound));
}
// This method is called when a server connection is torn down.
void I2cTemperatureServer::OnUnbound(
fidl::UnbindInfo info, fidl::ServerEnd<fuchsia_examples_i2c_temperature::Device> server_end) {
if (info.is_peer_closed()) {
FDF_LOG(DEBUG, "Client disconnected");
} else if (!info.is_user_initiated()) {
FDF_LOG(ERROR, "Client connection unbound: %s", info.status_string());
}
}
// Protocol method in `fuchsia.examples.i2c.temperature` to return the current temperature
void I2cTemperatureServer::ReadTemperature(ReadTemperatureCompleter::Sync& completer) {
auto channel = i2c_channel_.lock();
if (!channel) {
FDF_LOG(ERROR, "Unable to access I2C channel.");
completer.ReplyError(ZX_ERR_BAD_STATE);
return;
}
// Send a command to start the measurement.
auto status = channel->Write16(kStartMeasurementCommand);
if (status.is_error()) {
FDF_SLOG(ERROR, "Failed to send measurement command: ", KV("status", status.status_string()));
completer.ReplyError(status.status_value());
return;
}
// Read the temperature measurement.
auto temp_result = channel->Read16();
if (temp_result.is_error()) {
FDF_SLOG(ERROR, "Failed to read temperature: ", KV("status", temp_result.status_string()));
completer.ReplyError(temp_result.status_value());
return;
}
auto temp_value = static_cast<uint32_t>(temp_result.value());
FDF_SLOG(INFO, "Received temperature: ", KV("value", temp_value));
return completer.ReplySuccess(temp_value);
}
// Protocol method in `fuchsia.examples.i2c.temperature` to reset the temperature sensor
void I2cTemperatureServer::ResetSensor(ResetSensorCompleter::Sync& completer) {
auto channel = i2c_channel_.lock();
if (!channel) {
FDF_LOG(ERROR, "Unable to access I2C channel.");
completer.ReplyError(ZX_ERR_BAD_STATE);
return;
}
// Send the reset command.
auto result = channel->Write16(kSoftResetCommand);
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to send reset command: ", KV("status", result.status_string()));
completer.ReplyError(result.status_value());
return;
}
}
} // namespace i2c_temperature