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