Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 1 | // 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 | |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 5 | #ifndef LIBMEMS_IIO_DEVICE_H_ |
| 6 | #define LIBMEMS_IIO_DEVICE_H_ |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 7 | |
| 8 | #include <iio.h> |
| 9 | |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 10 | #include <memory> |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 11 | #include <string> |
Harvey Yang | c0d19d8 | 2019-07-01 12:17:34 +0800 | [diff] [blame] | 12 | #include <vector> |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 13 | |
Harvey Yang | 34c54d5 | 2020-05-20 13:34:20 +0800 | [diff] [blame] | 14 | #include <base/containers/flat_map.h> |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 15 | #include <base/files/file_path.h> |
| 16 | #include <base/macros.h> |
| 17 | #include <base/optional.h> |
Harvey Yang | 98ff1b3 | 2020-10-28 14:45:35 +0800 | [diff] [blame] | 18 | #include <base/time/time.h> |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 19 | |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 20 | #include "libmems/export.h" |
| 21 | |
| 22 | namespace libmems { |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 23 | |
| 24 | class IioContext; |
| 25 | class IioChannel; |
| 26 | |
| 27 | // The IioDevice represents a single IIO device, such as a gyroscope. |
| 28 | // It offers facilities to read and write attributes on the device, as well as |
| 29 | // configure channels, trigger and buffer for a sensor. |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 30 | class LIBMEMS_EXPORT IioDevice { |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 31 | public: |
Harvey Yang | 9f48d81 | 2020-06-30 16:24:30 +0800 | [diff] [blame] | 32 | // first is channel index; second is the channel's value |
| 33 | using IioSample = base::flat_map<int32_t, int64_t>; |
Harvey Yang | 34c54d5 | 2020-05-20 13:34:20 +0800 | [diff] [blame] | 34 | |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 35 | virtual ~IioDevice(); |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 36 | |
| 37 | // Returns the IIO context that contains this device. |
| 38 | virtual IioContext* GetContext() const = 0; |
| 39 | |
| 40 | // Returns the value of the 'name' attribute of this device. |
| 41 | // It is allowed to return an empty string. |
| 42 | virtual const char* GetName() const = 0; |
| 43 | |
Harvey Yang | 9260b66 | 2019-08-12 15:48:03 +0800 | [diff] [blame] | 44 | // Returns the unique IIO identifier of this device/trigger. |
| 45 | // Return id greater or equal to 0 if it's a device. |
| 46 | // Return id be -1 if it's iio_sysfs_trigger, greater or equal to 0 if it's a |
| 47 | // trigger. |
| 48 | virtual int GetId() const = 0; |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 49 | |
| 50 | // This call is used to enable setting UNIX permissions and ownership on the |
| 51 | // attributes of a sensor. It should not be used as a replacement for the |
| 52 | // read/write attribute accessors below. |
| 53 | virtual base::FilePath GetPath() const = 0; |
| 54 | |
| 55 | // Reads the |name| attribute of this device and returns the value |
| 56 | // as a string. It will return base::nullopt if the attribute cannot |
| 57 | // be read. |
| 58 | virtual base::Optional<std::string> ReadStringAttribute( |
| 59 | const std::string& name) const = 0; |
| 60 | |
| 61 | // Reads the |name| attribute of this device and returns the value |
| 62 | // as a signed number. It will return base::nullopt if the attribute |
| 63 | // cannot be read or is not a valid number. |
| 64 | virtual base::Optional<int64_t> ReadNumberAttribute( |
| 65 | const std::string& name) const = 0; |
| 66 | |
Enrico Granata | d2e57f4 | 2019-07-31 10:46:03 -0700 | [diff] [blame] | 67 | // Reads the |name| attribute of this device and returns the value |
| 68 | // as a double precision floating point. It will return base::nullopt |
| 69 | // if the attribute cannot be read or is not a valid number. |
| 70 | virtual base::Optional<double> ReadDoubleAttribute( |
| 71 | const std::string& name) const = 0; |
| 72 | |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 73 | // Writes the string |value| to the attribute |name| of this device. Returns |
| 74 | // false if an error occurs. |
| 75 | virtual bool WriteStringAttribute(const std::string& name, |
| 76 | const std::string& value) = 0; |
| 77 | |
| 78 | // Writes the number |value| to the attribute |name| of this device. Returns |
| 79 | // false if an error occurs. |
Enrico Granata | d2e57f4 | 2019-07-31 10:46:03 -0700 | [diff] [blame] | 80 | virtual bool WriteNumberAttribute(const std::string& name, int64_t value) = 0; |
| 81 | |
| 82 | // Writes the floating point |value| to the attribute |name| of this device. |
| 83 | // Returns false if an error occurs. |
| 84 | virtual bool WriteDoubleAttribute(const std::string& name, double value) = 0; |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 85 | |
| 86 | // Returns true if this device represents a single sensor, vs. a device |
| 87 | // representing all available cros_ec sensors on the system, as defined |
| 88 | // before 3.18 kernel. |
| 89 | bool IsSingleSensor() const; |
| 90 | |
| 91 | // Returns the iio_device object underlying this object, if any is available. |
| 92 | // Returns nullptr if no iio_device exists, e.g. a mock object. |
| 93 | virtual iio_device* GetUnderlyingIioDevice() const = 0; |
| 94 | |
| 95 | // Sets |trigger| as the IIO trigger device for this device. It is expected |
| 96 | // that |trigger| is owned by the same IIO context as this device. |
| 97 | virtual bool SetTrigger(IioDevice* trigger_device) = 0; |
| 98 | |
| 99 | // Returns the IIO trigger device for this device, or nullptr if this device |
| 100 | // has no trigger, or the trigger can't be found. |
| 101 | virtual IioDevice* GetTrigger() = 0; |
| 102 | |
Harvey Yang | b0c3096 | 2019-09-17 15:00:25 +0800 | [diff] [blame] | 103 | // Returns all channels belonging to this device. |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 104 | std::vector<IioChannel*> GetAllChannels(); |
Harvey Yang | b0c3096 | 2019-09-17 15:00:25 +0800 | [diff] [blame] | 105 | |
Harvey Yang | 9f48d81 | 2020-06-30 16:24:30 +0800 | [diff] [blame] | 106 | // Finds the IIO channel |index| as the index in this device and returns it. |
| 107 | // It will return nullptr if no such channel can be found. |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 108 | IioChannel* GetChannel(int32_t index); |
Harvey Yang | 9f48d81 | 2020-06-30 16:24:30 +0800 | [diff] [blame] | 109 | |
Harvey Yang | b0c3096 | 2019-09-17 15:00:25 +0800 | [diff] [blame] | 110 | // Finds the IIO channel |name| as id or name for this device and returns it. |
| 111 | // It will return nullptr if no such channel can be found. |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 112 | IioChannel* GetChannel(const std::string& name); |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 113 | |
Harvey Yang | c0d19d8 | 2019-07-01 12:17:34 +0800 | [diff] [blame] | 114 | // Returns the sample size in this device. |
| 115 | // Returns base::nullopt on failure. |
| 116 | virtual base::Optional<size_t> GetSampleSize() const = 0; |
| 117 | |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 118 | // Enables the IIO buffer on this device and configures it to return |
Harvey Yang | e8b301b | 2020-05-19 14:43:03 +0800 | [diff] [blame] | 119 | // |num| samples on access. This buffer's lifetime can exceed that of the |
| 120 | // IioContext, and that it's caller responsibility to know when to let go of |
| 121 | // the buffer with DisableBuffer if at all. |
| 122 | // It should not be used along with GetBufferFd or ReadEvent. |
| 123 | // Returns false on failure. |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 124 | virtual bool EnableBuffer(size_t num) = 0; |
| 125 | |
| 126 | // Disables the IIO buffer on this device. Returns false on failure. |
| 127 | virtual bool DisableBuffer() = 0; |
| 128 | |
| 129 | // Returns true if the IIO buffer is enabled for this device. |
| 130 | // If it is enabled, it sets |num| to the number of samples. |
| 131 | virtual bool IsBufferEnabled(size_t* num = nullptr) const = 0; |
| 132 | |
Harvey Yang | e8b301b | 2020-05-19 14:43:03 +0800 | [diff] [blame] | 133 | // Creates the IIO buffer if it doesn't exist, and gets the file descriptor to |
| 134 | // poll for events. Returns base::nullopt on failure. |
| 135 | // The buffer's lifetime is managed by the IioDevice, which will be disabled |
| 136 | // when the IioDevice along with the IioContext gets destroyed. It should not |
| 137 | // be used along with EnableBuffer. |
| 138 | virtual base::Optional<int32_t> GetBufferFd() = 0; |
| 139 | |
Harvey Yang | 34c54d5 | 2020-05-20 13:34:20 +0800 | [diff] [blame] | 140 | // Creates the IIO buffer if it doesn't exist, and reads & returns one sample. |
| 141 | // Returns base::nullopt on failure. |
Harvey Yang | e8b301b | 2020-05-19 14:43:03 +0800 | [diff] [blame] | 142 | // The buffer's lifetime is managed by the IioDevice, which will be disabled |
| 143 | // when the IioDevice along with the IioContext gets destroyed. It should not |
| 144 | // be used along with EnableBuffer. |
Harvey Yang | 34c54d5 | 2020-05-20 13:34:20 +0800 | [diff] [blame] | 145 | virtual base::Optional<IioSample> ReadSample() = 0; |
Harvey Yang | c0d19d8 | 2019-07-01 12:17:34 +0800 | [diff] [blame] | 146 | |
Harvey Yang | 98ff1b3 | 2020-10-28 14:45:35 +0800 | [diff] [blame] | 147 | bool GetMinMaxFrequency(double* min_freq, double* max_freq); |
| 148 | |
| 149 | // Gets the period of time to ignore obsolete samples in the kernel. |
| 150 | virtual base::TimeDelta GetPeriodForObsoleteSamplesInMilliseconds() = 0; |
| 151 | |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 152 | protected: |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 153 | struct ChannelData { |
| 154 | std::string chn_id; |
| 155 | std::unique_ptr<IioChannel> chn; |
| 156 | }; |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 157 | |
Harvey Yang | 9260b66 | 2019-08-12 15:48:03 +0800 | [diff] [blame] | 158 | static base::Optional<int> GetIdAfterPrefix(const char* id_str, |
| 159 | const char* prefix); |
| 160 | |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 161 | IioDevice() = default; |
Qijiang Fan | 6bc59e1 | 2020-11-11 02:51:06 +0900 | [diff] [blame^] | 162 | IioDevice(const IioDevice&) = delete; |
| 163 | IioDevice& operator=(const IioDevice&) = delete; |
Gwendal Grignou | a144647 | 2020-06-30 18:00:05 -0700 | [diff] [blame] | 164 | |
Qijiang Fan | 6bc59e1 | 2020-11-11 02:51:06 +0900 | [diff] [blame^] | 165 | std::vector<ChannelData> channels_; |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 166 | }; |
| 167 | |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 168 | } // namespace libmems |
Enrico Granata | 60a818d | 2019-05-09 09:56:09 -0700 | [diff] [blame] | 169 | |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 170 | #endif // LIBMEMS_IIO_DEVICE_H_ |