blob: ac1dd462c92de5a221f7fd490913e35648aa7844 [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
17IioChannelImpl::IioChannelImpl(iio_channel* channel) : channel_(channel) {
18 CHECK(channel_);
19}
20
21const char* IioChannelImpl::GetId() const {
22 return iio_channel_get_id(channel_);
23}
24
25bool IioChannelImpl::IsEnabled() const {
26 return iio_channel_is_enabled(channel_);
27}
28
29bool IioChannelImpl::SetEnabled(bool en) {
30 if (en)
31 iio_channel_enable(channel_);
32 else
33 iio_channel_disable(channel_);
34
35 // this tool will not stick around listening to this channel,
36 // all it needs to do is leave the channel enabled for Chrome to use;
37 // so, we directly write to the scan elements instead of setting up
38 // a buffer and keeping it enabled while we run (which wouldn't be long
39 // enough anyway). we do not need to handle the non scan-element case for
40 // the channels we care about.
41 if (!iio_channel_is_scan_element(channel_))
42 return true;
43
44 std::string en_attrib_name = base::StringPrintf(
Harvey Yangf0a0b232020-08-29 10:20:31 +080045 "scan_elements/%s_%s_en", iio_channel_is_output(channel_) ? "out" : "in",
46 GetId());
Harvey Yang9260b662019-08-12 15:48:03 +080047 int error = iio_channel_attr_write_bool(channel_, en_attrib_name.c_str(), en);
48 if (error) {
Enrico Granata60a818d2019-05-09 09:56:09 -070049 LOG(WARNING) << "could not write to " << en_attrib_name
Harvey Yang9260b662019-08-12 15:48:03 +080050 << ", error: " << error;
Enrico Granata60a818d2019-05-09 09:56:09 -070051 return false;
52 }
53
54 return true;
55}
56
Harvey Yang96029cb2019-06-03 17:26:14 +080057base::Optional<std::string> IioChannelImpl::ReadStringAttribute(
58 const std::string& name) const {
Harvey Yang9260b662019-08-12 15:48:03 +080059 char data[kReadAttrBufferSize] = {0};
Harvey Yang96029cb2019-06-03 17:26:14 +080060 ssize_t len =
61 iio_channel_attr_read(channel_, name.c_str(), data, sizeof(data));
62 if (len < 0) {
63 LOG(WARNING) << "Attempting to read attribute " << name
64 << " failed: " << len;
65 return base::nullopt;
66 }
67 return std::string(data, len);
68}
69
70base::Optional<int64_t> IioChannelImpl::ReadNumberAttribute(
71 const std::string& name) const {
72 long long val = 0; // NOLINT(runtime/int)
73 int error = iio_channel_attr_read_longlong(channel_, name.c_str(), &val);
74 if (error) {
75 LOG(WARNING) << "Attempting to read attribute " << name
76 << " failed: " << error;
77 return base::nullopt;
78 }
79 return val;
80}
81
Harvey Yang34c54d52020-05-20 13:34:20 +080082base::Optional<int64_t> IioChannelImpl::Convert(const uint8_t* src) const {
83 const iio_data_format* format = iio_channel_get_data_format(channel_);
84 if (!format) {
85 LOG(WARNING) << "Cannot find format of channel: " << GetId();
86 return base::nullopt;
87 }
88
89 size_t len = format->length;
90 if (len == 0)
91 return 0;
92
Harvey Yang08c058a2020-06-22 18:10:52 +080093 int64_t value = 0;
Harvey Yang34c54d52020-05-20 13:34:20 +080094 iio_channel_convert(channel_, &value, src);
95
96 if (format->is_signed && len < CHAR_BIT * sizeof(int64_t)) {
97 int64_t mask = 1LL << (len - 1);
98
99 if (mask & value) {
100 // Doing sign extension
101 value |= (~0LL) << len;
102 }
103 }
104
105 return value;
106}
107
Harvey Yang9903fc22020-03-16 14:22:53 +0800108base::Optional<double> IioChannelImpl::ReadDoubleAttribute(
109 const std::string& name) const {
110 double val = 0;
111 int error = iio_channel_attr_read_double(channel_, name.c_str(), &val);
112 if (error) {
113 LOG(WARNING) << "Attempting to read attribute " << name
114 << " failed: " << error;
115 return base::nullopt;
116 }
117 return val;
118}
119
120bool IioChannelImpl::WriteStringAttribute(const std::string& name,
121 const std::string& value) {
122 int error = iio_channel_attr_write_raw(
123 channel_, name.size() > 0 ? name.c_str() : nullptr, value.data(),
124 value.size());
125 if (error) {
126 LOG(WARNING) << "Attempting to write attribute " << name
127 << " failed: " << error;
128 return false;
129 }
130 return true;
131}
132
133bool IioChannelImpl::WriteNumberAttribute(const std::string& name,
134 int64_t value) {
135 int error = iio_channel_attr_write_longlong(channel_, name.c_str(), value);
136 if (error) {
137 LOG(WARNING) << "Attempting to write attribute " << name
138 << " failed: " << error;
139 return false;
140 }
141 return true;
142}
143
144bool IioChannelImpl::WriteDoubleAttribute(const std::string& name,
145 double value) {
146 int error = iio_channel_attr_write_double(channel_, name.c_str(), value);
147 if (error) {
148 LOG(WARNING) << "Attempting to write attribute " << name
149 << " failed: " << error;
150 return false;
151 }
152 return true;
153}
154
Harvey Yang34c54d52020-05-20 13:34:20 +0800155base::Optional<uint64_t> IioChannelImpl::Length() const {
156 const iio_data_format* format = iio_channel_get_data_format(channel_);
157 if (!format) {
158 LOG(WARNING) << "Cannot find format of channel: " << GetId();
159 return base::nullopt;
160 }
161
162 return format->length;
163}
164
Enrico Granata51cdb942019-06-18 16:40:17 -0700165} // namespace libmems