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