blob: 106966d947db59581ed06daebc9ddcea029b86aa [file] [log] [blame]
Enrico Granata60a818d2019-05-09 09:56:09 -07001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
6#include <string>
7
8#include <base/logging.h>
9#include <base/strings/stringprintf.h>
10
Harvey Yang9260b662019-08-12 15:48:03 +080011#include "libmems/common_types.h"
Enrico Granata51cdb942019-06-18 16:40:17 -070012#include "libmems/iio_channel_impl.h"
13#include "libmems/iio_device.h"
Enrico Granata60a818d2019-05-09 09:56:09 -070014
Enrico Granata51cdb942019-06-18 16:40:17 -070015namespace libmems {
Enrico Granata60a818d2019-05-09 09:56:09 -070016
Harvey Yang705e40f2020-11-19 15:42:44 +080017IioChannelImpl::IioChannelImpl(iio_channel* channel,
18 int device_id,
19 const char* device_name)
20 : channel_(channel) {
Enrico Granata60a818d2019-05-09 09:56:09 -070021 CHECK(channel_);
Harvey Yang705e40f2020-11-19 15:42:44 +080022
23 log_prefix_ =
24 base::StringPrintf("Device with id: %d and name: %s, channel: %s. ",
25 device_id, device_name, GetId());
Enrico Granata60a818d2019-05-09 09:56:09 -070026}
27
28const char* IioChannelImpl::GetId() const {
29 return iio_channel_get_id(channel_);
30}
31
32bool IioChannelImpl::IsEnabled() const {
33 return iio_channel_is_enabled(channel_);
34}
35
Harvey Yang2c08cf72020-09-24 12:36:23 +080036void IioChannelImpl::SetEnabled(bool en) {
Enrico Granata60a818d2019-05-09 09:56:09 -070037 if (en)
38 iio_channel_enable(channel_);
39 else
40 iio_channel_disable(channel_);
Harvey Yang2c08cf72020-09-24 12:36:23 +080041}
Enrico Granata60a818d2019-05-09 09:56:09 -070042
Harvey Yang2c08cf72020-09-24 12:36:23 +080043bool IioChannelImpl::SetScanElementsEnabled(bool en) {
Enrico Granata60a818d2019-05-09 09:56:09 -070044 if (!iio_channel_is_scan_element(channel_))
45 return true;
46
47 std::string en_attrib_name = base::StringPrintf(
Harvey Yangf0a0b232020-08-29 10:20:31 +080048 "scan_elements/%s_%s_en", iio_channel_is_output(channel_) ? "out" : "in",
49 GetId());
Harvey Yang9260b662019-08-12 15:48:03 +080050 int error = iio_channel_attr_write_bool(channel_, en_attrib_name.c_str(), en);
51 if (error) {
Harvey Yang705e40f2020-11-19 15:42:44 +080052 LOG(WARNING) << log_prefix_ << "Could not write to " << en_attrib_name
Harvey Yang9260b662019-08-12 15:48:03 +080053 << ", error: " << error;
Enrico Granata60a818d2019-05-09 09:56:09 -070054 return false;
55 }
56
57 return true;
58}
59
Harvey Yang96029cb2019-06-03 17:26:14 +080060base::Optional<std::string> IioChannelImpl::ReadStringAttribute(
61 const std::string& name) const {
Harvey Yang9260b662019-08-12 15:48:03 +080062 char data[kReadAttrBufferSize] = {0};
Harvey Yang96029cb2019-06-03 17:26:14 +080063 ssize_t len =
64 iio_channel_attr_read(channel_, name.c_str(), data, sizeof(data));
65 if (len < 0) {
Harvey Yang705e40f2020-11-19 15:42:44 +080066 LOG(WARNING) << log_prefix_ << "Attempting to read attribute " << name
Harvey Yang96029cb2019-06-03 17:26:14 +080067 << " failed: " << len;
68 return base::nullopt;
69 }
70 return std::string(data, len);
71}
72
73base::Optional<int64_t> IioChannelImpl::ReadNumberAttribute(
74 const std::string& name) const {
75 long long val = 0; // NOLINT(runtime/int)
76 int error = iio_channel_attr_read_longlong(channel_, name.c_str(), &val);
77 if (error) {
Harvey Yang705e40f2020-11-19 15:42:44 +080078 LOG(WARNING) << log_prefix_ << "Attempting to read attribute " << name
Harvey Yang96029cb2019-06-03 17:26:14 +080079 << " failed: " << error;
80 return base::nullopt;
81 }
82 return val;
83}
84
Harvey Yang705e40f2020-11-19 15:42:44 +080085base::Optional<double> IioChannelImpl::ReadDoubleAttribute(
86 const std::string& name) const {
87 double val = 0;
88 int error = iio_channel_attr_read_double(channel_, name.c_str(), &val);
89 if (error) {
90 LOG(WARNING) << log_prefix_ << "Attempting to read attribute " << name
91 << " failed: " << error;
92 return base::nullopt;
93 }
94 return val;
95}
96
97bool IioChannelImpl::WriteStringAttribute(const std::string& name,
98 const std::string& value) {
99 int error = iio_channel_attr_write_raw(
100 channel_, name.size() > 0 ? name.c_str() : nullptr, value.data(),
101 value.size());
102 if (error) {
103 LOG(WARNING) << log_prefix_ << "Attempting to write attribute " << name
104 << " failed: " << error;
105 return false;
106 }
107 return true;
108}
109
110bool IioChannelImpl::WriteNumberAttribute(const std::string& name,
111 int64_t value) {
112 int error = iio_channel_attr_write_longlong(channel_, name.c_str(), value);
113 if (error) {
114 LOG(WARNING) << log_prefix_ << "Attempting to write attribute " << name
115 << " failed: " << error;
116 return false;
117 }
118 return true;
119}
120
121bool IioChannelImpl::WriteDoubleAttribute(const std::string& name,
122 double value) {
123 int error = iio_channel_attr_write_double(channel_, name.c_str(), value);
124 if (error) {
125 LOG(WARNING) << log_prefix_ << "Attempting to write attribute " << name
126 << " failed: " << error;
127 return false;
128 }
129 return true;
130}
131
Harvey Yang34c54d52020-05-20 13:34:20 +0800132base::Optional<int64_t> IioChannelImpl::Convert(const uint8_t* src) const {
133 const iio_data_format* format = iio_channel_get_data_format(channel_);
134 if (!format) {
Harvey Yang705e40f2020-11-19 15:42:44 +0800135 LOG(WARNING) << log_prefix_ << "Cannot find format.";
Harvey Yang34c54d52020-05-20 13:34:20 +0800136 return base::nullopt;
137 }
138
139 size_t len = format->length;
140 if (len == 0)
141 return 0;
142
Harvey Yang08c058a2020-06-22 18:10:52 +0800143 int64_t value = 0;
Harvey Yang34c54d52020-05-20 13:34:20 +0800144 iio_channel_convert(channel_, &value, src);
145
146 if (format->is_signed && len < CHAR_BIT * sizeof(int64_t)) {
147 int64_t mask = 1LL << (len - 1);
148
149 if (mask & value) {
150 // Doing sign extension
151 value |= (~0LL) << len;
152 }
153 }
154
155 return value;
156}
157
158base::Optional<uint64_t> IioChannelImpl::Length() const {
159 const iio_data_format* format = iio_channel_get_data_format(channel_);
160 if (!format) {
Harvey Yang705e40f2020-11-19 15:42:44 +0800161 LOG(WARNING) << log_prefix_ << "Cannot find format.";
Harvey Yang34c54d52020-05-20 13:34:20 +0800162 return base::nullopt;
163 }
164
165 return format->length;
166}
167
Enrico Granata51cdb942019-06-18 16:40:17 -0700168} // namespace libmems