| // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "libmems/iio_device.h" |
| |
| #include <stdlib.h> |
| |
| #include <base/strings/string_number_conversions.h> |
| #include <base/strings/string_split.h> |
| |
| #include "libmems/common_types.h" |
| #include "libmems/iio_channel.h" |
| |
| namespace libmems { |
| |
| IioDevice::~IioDevice() = default; |
| |
| bool IioDevice::IsSingleSensor() const { |
| return ReadStringAttribute("location").has_value(); |
| } |
| |
| // static |
| base::Optional<int> IioDevice::GetIdAfterPrefix(const char* id_str, |
| const char* prefix) { |
| size_t id_len = strlen(id_str); |
| size_t prefix_len = strlen(prefix); |
| if (id_len <= prefix_len || strncmp(id_str, prefix, prefix_len) != 0) { |
| return base::nullopt; |
| } |
| |
| int value = 0; |
| bool success = base::StringToInt(std::string(id_str + prefix_len), &value); |
| if (success) |
| return value; |
| |
| return base::nullopt; |
| } |
| |
| std::vector<IioChannel*> IioDevice::GetAllChannels() { |
| std::vector<IioChannel*> channels; |
| for (const auto& channel_data : channels_) |
| channels.push_back(channel_data.chn.get()); |
| |
| return channels; |
| } |
| |
| void IioDevice::EnableAllChannels() { |
| for (IioChannel* chn : GetAllChannels()) { |
| if (!chn->SetEnabledAndCheck(true)) |
| LOG(ERROR) << "Failed to enable channel: " << chn->GetId(); |
| } |
| } |
| |
| IioChannel* IioDevice::GetChannel(int32_t index) { |
| if (index < 0 || index >= channels_.size()) |
| return nullptr; |
| |
| return channels_[index].chn.get(); |
| } |
| |
| IioChannel* IioDevice::GetChannel(const std::string& name) { |
| for (size_t i = 0; i < channels_.size(); ++i) { |
| if (channels_[i].chn_id == name) |
| return channels_[i].chn.get(); |
| } |
| |
| return nullptr; |
| } |
| |
| bool IioDevice::GetMinMaxFrequency(double* min_freq, double* max_freq) { |
| auto available_opt = ReadStringAttribute(kSamplingFrequencyAvailable); |
| if (!available_opt.has_value()) { |
| LOG(ERROR) << "Failed to read attribute: " << kSamplingFrequencyAvailable; |
| return false; |
| } |
| |
| std::string sampling_frequency_available = available_opt.value(); |
| // Remove trailing '\0' for parsing |
| auto pos = available_opt->find_first_of('\0'); |
| if (pos != std::string::npos) |
| sampling_frequency_available = available_opt->substr(0, pos); |
| |
| std::vector<std::string> sampling_frequencies = |
| base::SplitString(sampling_frequency_available, " ", |
| base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| |
| switch (sampling_frequencies.size()) { |
| case 0: |
| LOG(ERROR) << "Invalid format of " << kSamplingFrequencyAvailable << ": " |
| << sampling_frequency_available; |
| return false; |
| |
| case 1: |
| if (!base::StringToDouble(sampling_frequencies.front(), min_freq) || |
| *min_freq < 0.0 || *min_freq < kFrequencyEpsilon) { |
| LOG(ERROR) << "Failed to parse min max sampling_frequency: " |
| << sampling_frequency_available; |
| return false; |
| } |
| |
| *max_freq = *min_freq; |
| return true; |
| |
| default: |
| if (!base::StringToDouble(sampling_frequencies.back(), max_freq) || |
| *max_freq < kFrequencyEpsilon) { |
| LOG(ERROR) << "Failed to parse max sampling_frequency: " |
| << sampling_frequency_available; |
| return false; |
| } |
| |
| if (!base::StringToDouble(sampling_frequencies.front(), min_freq) || |
| *min_freq < 0.0) { |
| LOG(ERROR) << "Failed to parse the first sampling_frequency: " |
| << sampling_frequency_available; |
| return false; |
| } |
| |
| if (*min_freq == 0.0) { |
| if (!base::StringToDouble(sampling_frequencies[1], min_freq) || |
| *min_freq < 0.0 || *max_freq < *min_freq) { |
| LOG(ERROR) << "Failed to parse min sampling_frequency: " |
| << sampling_frequency_available; |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| } |
| |
| } // namespace libmems |