blob: afacf271b47b279b7038a708ffb409d41c205cdd [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
Qijiang Fan713061e2021-03-08 15:45:12 +09008#include <base/check.h>
Harvey Yang9260b662019-08-12 15:48:03 +08009#include <base/strings/stringprintf.h>
Enrico Granata60a818d2019-05-09 09:56:09 -070010#include <base/logging.h>
11
Harvey Yang6698c862019-09-16 17:24:38 +080012#include "libmems/common_types.h"
Enrico Granata51cdb942019-06-18 16:40:17 -070013#include "libmems/iio_channel_impl.h"
14#include "libmems/iio_context_impl.h"
15#include "libmems/iio_device_impl.h"
Harvey Yang9260b662019-08-12 15:48:03 +080016#include "libmems/iio_device_trigger_impl.h"
Enrico Granata60a818d2019-05-09 09:56:09 -070017
Enrico Granata51cdb942019-06-18 16:40:17 -070018namespace libmems {
Enrico Granata60a818d2019-05-09 09:56:09 -070019
20IioContextImpl::IioContextImpl() {
21 Reload();
22}
23
24void IioContextImpl::Reload() {
25 // This context will only be destroyed when the entire IioContextImpl goes
26 // out of scope. In practice, there will only be at most two contexts
27 // in existence (i.e. the initial one and the one we create if we need
28 // to initialize the IIO sysfs trigger). This is done in the interest of
29 // not having to invalidate existing iio_device pointers, as their lifetime
30 // is statically bound to the context that created them (and contexts are
31 // themselves static objects that do not update as devices are added
32 // and/or removed at runtime).
33 context_.push_back({iio_create_local_context(), iio_context_destroy});
34 CHECK(GetCurrentContext());
35}
36
37iio_context* IioContextImpl::GetCurrentContext() const {
38 if (context_.empty())
39 return nullptr;
40 return context_.back().get();
41}
42
Harvey Yang6698c862019-09-16 17:24:38 +080043bool IioContextImpl::SetTimeout(uint32_t timeout) {
44 int error = iio_context_set_timeout(GetCurrentContext(), timeout);
45 if (error) {
46 char errMsg[kErrorBufferSize];
47 iio_strerror(-error, errMsg, sizeof(errMsg));
48 LOG(ERROR) << "Unable to set timeout " << timeout << ": " << errMsg;
49
50 return false;
51 }
52
53 return true;
54}
55
Harvey Yang9260b662019-08-12 15:48:03 +080056std::vector<IioDevice*> IioContextImpl::GetDevicesByName(
57 const std::string& name) {
58 return GetByName(name, &devices_);
59}
60
61IioDevice* IioContextImpl::GetDeviceById(int id) {
62 return GetById(id, &devices_);
63}
64
65std::vector<IioDevice*> IioContextImpl::GetAllDevices() {
66 return GetAll(&devices_);
67}
68
69std::vector<IioDevice*> IioContextImpl::GetTriggersByName(
70 const std::string& name) {
71 return GetByName(name, &triggers_);
72}
73
74IioDevice* IioContextImpl::GetTriggerById(int id) {
75 return GetById(id, &triggers_);
76}
77
78std::vector<IioDevice*> IioContextImpl::GetAllTriggers() {
79 return GetAll(&triggers_);
80}
81
82template <typename T>
83IioDevice* IioContextImpl::GetById(
84 int id, std::map<int, std::unique_ptr<T>>* devices_map) {
85 auto it_dev = devices_map->find(id);
86 if (it_dev != devices_map->end())
87 return it_dev->second.get();
88
89 std::string id_str = T::GetStringFromId(id);
90
Enrico Granata60a818d2019-05-09 09:56:09 -070091 iio_device* device =
Harvey Yang9260b662019-08-12 15:48:03 +080092 iio_context_find_device(GetCurrentContext(), id_str.c_str());
93 if (!device)
Enrico Granata60a818d2019-05-09 09:56:09 -070094 return nullptr;
Harvey Yang9260b662019-08-12 15:48:03 +080095
96 devices_map->emplace(id, std::make_unique<T>(this, device));
97
98 return devices_map->at(id).get();
99}
100
101template <typename T>
102std::vector<IioDevice*> IioContextImpl::GetByName(
103 const std::string& name, std::map<int, std::unique_ptr<T>>* devices_map) {
104 std::vector<IioDevice*> devices;
105 iio_context* ctx = GetCurrentContext();
106 uint32_t dev_count = iio_context_get_devices_count(ctx);
107
108 for (uint32_t i = 0; i < dev_count; ++i) {
109 iio_device* dev = iio_context_get_device(ctx, i);
110 if (!dev) {
111 LOG(WARNING) << "Unable to get " << i << "th device";
112 continue;
113 }
114
115 const char* id_str = iio_device_get_id(dev);
116 if (!id_str)
117 continue;
118
119 auto id = T::GetIdFromString(id_str);
120 if (!id.has_value())
121 continue;
122
123 const char* dev_name = iio_device_get_name(dev);
124 if (dev_name && name.compare(dev_name) == 0)
125 devices.push_back(GetById(id.value(), devices_map));
126 }
127
128 return devices;
129}
130
131template <typename T>
132std::vector<IioDevice*> IioContextImpl::GetAll(
133 std::map<int, std::unique_ptr<T>>* devices_map) {
134 std::vector<IioDevice*> devices;
135 iio_context* ctx = GetCurrentContext();
136 uint32_t dev_count = iio_context_get_devices_count(ctx);
137
138 for (uint32_t i = 0; i < dev_count; ++i) {
139 iio_device* dev = iio_context_get_device(ctx, i);
140 if (!dev) {
141 LOG(WARNING) << "Unable to get " << i << "th device";
142 continue;
143 }
144
145 const char* id_str = iio_device_get_id(dev);
146 if (!id_str)
147 continue;
148
149 auto id = T::GetIdFromString(id_str);
150 if (!id.has_value())
151 continue;
152
153 devices.push_back(GetById(id.value(), devices_map));
154 }
155
156 return devices;
Enrico Granata60a818d2019-05-09 09:56:09 -0700157}
158
Enrico Granata51cdb942019-06-18 16:40:17 -0700159} // namespace libmems