blob: 793f2636af539b8e41d8528b5d81419cc70ad93c [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 <memory>
#include <string>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include "libmems/common_types.h"
#include "libmems/iio_channel_impl.h"
#include "libmems/iio_device.h"
namespace libmems {
IioChannelImpl::IioChannelImpl(iio_channel* channel,
int device_id,
const char* device_name)
: channel_(channel) {
CHECK(channel_);
log_prefix_ =
base::StringPrintf("Device with id: %d and name: %s, channel: %s. ",
device_id, device_name, GetId());
}
const char* IioChannelImpl::GetId() const {
return iio_channel_get_id(channel_);
}
bool IioChannelImpl::IsEnabled() const {
return iio_channel_is_enabled(channel_);
}
void IioChannelImpl::SetEnabled(bool en) {
if (en)
iio_channel_enable(channel_);
else
iio_channel_disable(channel_);
}
bool IioChannelImpl::SetScanElementsEnabled(bool en) {
if (!iio_channel_is_scan_element(channel_))
return true;
std::string en_attrib_name = base::StringPrintf(
"scan_elements/%s_%s_en", iio_channel_is_output(channel_) ? "out" : "in",
GetId());
int error = iio_channel_attr_write_bool(channel_, en_attrib_name.c_str(), en);
if (error) {
LOG(WARNING) << log_prefix_ << "Could not write to " << en_attrib_name
<< ", error: " << error;
return false;
}
return true;
}
base::Optional<std::string> IioChannelImpl::ReadStringAttribute(
const std::string& name) const {
char data[kReadAttrBufferSize] = {0};
ssize_t len =
iio_channel_attr_read(channel_, name.c_str(), data, sizeof(data));
if (len < 0) {
LOG(WARNING) << log_prefix_ << "Attempting to read string attribute "
<< name << " failed: " << len;
return base::nullopt;
}
return std::string(data, len);
}
base::Optional<int64_t> IioChannelImpl::ReadNumberAttribute(
const std::string& name) const {
long long val = 0; // NOLINT(runtime/int)
int error = iio_channel_attr_read_longlong(channel_, name.c_str(), &val);
if (error) {
LOG(WARNING) << log_prefix_ << "Attempting to read number attribute "
<< name << " failed: " << error;
return base::nullopt;
}
return val;
}
base::Optional<double> IioChannelImpl::ReadDoubleAttribute(
const std::string& name) const {
double val = 0;
int error = iio_channel_attr_read_double(channel_, name.c_str(), &val);
if (error) {
LOG(WARNING) << log_prefix_ << "Attempting to read double attribute "
<< name << " failed: " << error;
return base::nullopt;
}
return val;
}
bool IioChannelImpl::WriteStringAttribute(const std::string& name,
const std::string& value) {
int error = iio_channel_attr_write_raw(
channel_, name.size() > 0 ? name.c_str() : nullptr, value.data(),
value.size());
if (error) {
LOG(WARNING) << log_prefix_ << "Attempting to write string attribute "
<< name << " failed: " << error;
return false;
}
return true;
}
bool IioChannelImpl::WriteNumberAttribute(const std::string& name,
int64_t value) {
int error = iio_channel_attr_write_longlong(channel_, name.c_str(), value);
if (error) {
LOG(WARNING) << log_prefix_ << "Attempting to write number attribute "
<< name << " failed: " << error;
return false;
}
return true;
}
bool IioChannelImpl::WriteDoubleAttribute(const std::string& name,
double value) {
int error = iio_channel_attr_write_double(channel_, name.c_str(), value);
if (error) {
LOG(WARNING) << log_prefix_ << "Attempting to write double attribute "
<< name << " failed: " << error;
return false;
}
return true;
}
base::Optional<int64_t> IioChannelImpl::Convert(const uint8_t* src) const {
const iio_data_format* format = iio_channel_get_data_format(channel_);
if (!format) {
LOG(WARNING) << log_prefix_ << "Cannot find format.";
return base::nullopt;
}
size_t len = format->length;
if (len == 0)
return 0;
int64_t value = 0;
iio_channel_convert(channel_, &value, src);
if (format->is_signed && len < CHAR_BIT * sizeof(int64_t)) {
int64_t mask = 1LL << (len - 1);
if (mask & value) {
// Doing sign extension
value |= (~0LL) << len;
}
}
return value;
}
base::Optional<uint64_t> IioChannelImpl::Length() const {
const iio_data_format* format = iio_channel_get_data_format(channel_);
if (!format) {
LOG(WARNING) << log_prefix_ << "Cannot find format.";
return base::nullopt;
}
return format->length;
}
} // namespace libmems