Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -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 | #include "mems_setup/configuration.h" |
| 6 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 7 | #include <algorithm> |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 8 | #include <initializer_list> |
Gwendal Grignou | ba911fe | 2019-12-08 17:14:53 -0800 | [diff] [blame] | 9 | #include <string> |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 10 | #include <vector> |
| 11 | |
Qijiang Fan | 713061e | 2021-03-08 15:45:12 +0900 | [diff] [blame] | 12 | #include <base/check.h> |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 13 | #include <base/files/file_enumerator.h> |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 14 | #include <base/files/file_util.h> |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 15 | #include <base/files/file_path.h> |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 16 | #include <base/logging.h> |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 17 | #include <base/process/launch.h> |
| 18 | #include <base/stl_util.h> |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 19 | #include <base/strings/string_number_conversions.h> |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 20 | #include <base/strings/string_split.h> |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 21 | #include <base/strings/stringprintf.h> |
| 22 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 23 | #include <libmems/common_types.h> |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 24 | #include <libmems/iio_channel.h> |
| 25 | #include <libmems/iio_context.h> |
| 26 | #include <libmems/iio_device.h> |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 27 | #include <libmems/iio_device_impl.h> |
| 28 | |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 29 | #include "mems_setup/sensor_location.h" |
| 30 | |
| 31 | namespace mems_setup { |
| 32 | |
| 33 | namespace { |
| 34 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 35 | struct ImuVpdCalibrationEntry { |
| 36 | std::string name; |
| 37 | std::string calib; |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 38 | base::Optional<int> max_value; |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 39 | base::Optional<int> value; |
Enrico Granata | fc7227d | 2019-07-26 13:51:19 -0700 | [diff] [blame] | 40 | bool missing_is_error; |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 41 | }; |
| 42 | |
| 43 | struct LightVpdCalibrationEntry { |
| 44 | std::string vpd_name; |
| 45 | std::string iio_name; |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 46 | }; |
| 47 | |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 48 | struct LightColorCalibrationEntry { |
| 49 | std::string iio_name; |
| 50 | base::Optional<double> value; |
| 51 | }; |
| 52 | |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 53 | #if USE_IIOSERVICE |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 54 | constexpr char kIioServiceGroupName[] = "iioservice"; |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 55 | #else |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 56 | constexpr char kArcSensorGroupName[] = "arc-sensor"; |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 57 | #endif // USE_IIOSERVICE |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 58 | |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 59 | constexpr char kCalibrationBias[] = "bias"; |
Enrico Granata | fc7227d | 2019-07-26 13:51:19 -0700 | [diff] [blame] | 60 | constexpr char kCalibrationScale[] = "scale"; |
Gwendal Grignou | 1a66337 | 2020-01-24 09:36:49 -0800 | [diff] [blame] | 61 | constexpr char kSysfsTriggerPrefix[] = "sysfstrig"; |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 62 | |
Enrico Granata | 7a62234 | 2019-05-21 11:10:59 -0700 | [diff] [blame] | 63 | constexpr int kGyroMaxVpdCalibration = 16384; // 16dps |
Gwendal Grignou | 4bf5ae6 | 2020-01-06 14:16:47 -0800 | [diff] [blame] | 64 | constexpr int kAccelMaxVpdCalibration = 103; // .100g |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 65 | constexpr int kAccelSysfsTriggerId = 0; |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 66 | |
Harvey Yang | 0c0dab5 | 2019-11-18 12:04:30 +0800 | [diff] [blame] | 67 | constexpr int kSysfsTriggerId = -1; |
| 68 | |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 69 | constexpr std::initializer_list<const char*> kAccelAxes = { |
| 70 | "x", |
| 71 | "y", |
| 72 | "z", |
| 73 | }; |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 74 | |
| 75 | constexpr char kTriggerString[] = "trigger"; |
| 76 | |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 77 | #if USE_IIOSERVICE |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 78 | constexpr char kDevString[] = "/dev/"; |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 79 | #endif // USE_IIOSERVICE |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 80 | |
Harvey Yang | 68188d4 | 2021-01-22 10:47:12 +0800 | [diff] [blame] | 81 | constexpr char kFilesToSetReadAndOwnership[][28] = { |
| 82 | "buffer/hwfifo_timeout", "buffer/hwfifo_watermark_max", "buffer/enable", |
| 83 | "buffer/length", "trigger/current_trigger"}; |
Harvey Yang | 2e5587f | 2020-09-29 00:12:35 +0800 | [diff] [blame] | 84 | constexpr char kFilesToSetWriteAndOwnership[][24] = {"sampling_frequency", |
| 85 | "buffer/hwfifo_timeout", |
| 86 | "buffer/hwfifo_flush", |
| 87 | "buffer/enable", |
| 88 | "buffer/length", |
| 89 | "trigger/current_trigger", |
| 90 | "flush", |
| 91 | "frequency"}; |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 92 | |
| 93 | constexpr char kScanElementsString[] = "scan_elements"; |
| 94 | constexpr char kChnEnableFormatString[] = "in_%s_en"; |
| 95 | |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 96 | } // namespace |
| 97 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 98 | // static |
| 99 | const char* Configuration::GetGroupNameForSysfs() { |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 100 | #if USE_IIOSERVICE |
| 101 | return kIioServiceGroupName; |
| 102 | #else |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 103 | return kArcSensorGroupName; |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 104 | #endif // USE_IIOSERVICE |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 105 | } |
| 106 | |
Gwendal Grignou | ba911fe | 2019-12-08 17:14:53 -0800 | [diff] [blame] | 107 | Configuration::Configuration(libmems::IioContext* context, |
| 108 | libmems::IioDevice* sensor, |
Enrico Granata | 51cdb94 | 2019-06-18 16:40:17 -0700 | [diff] [blame] | 109 | Delegate* del) |
Harvey Yang | 7339462 | 2020-02-12 10:57:57 +0800 | [diff] [blame] | 110 | : delegate_(del), sensor_(sensor), context_(context) { |
| 111 | DCHECK(sensor_); |
| 112 | |
| 113 | kind_ = mems_setup::SensorKindFromString( |
| 114 | sensor_->GetName() ? sensor_->GetName() : ""); |
| 115 | } |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 116 | |
| 117 | bool Configuration::Configure() { |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 118 | iioservice_gid_ = delegate_->FindGroupId(GetGroupNameForSysfs()); |
| 119 | if (!iioservice_gid_.has_value()) { |
| 120 | LOG(ERROR) << "iioservice group not found"; |
| 121 | return false; |
| 122 | } |
| 123 | |
| 124 | if (!ConfigureOnKind()) |
| 125 | return false; |
| 126 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 127 | if (!SetupPermissions()) |
| 128 | return false; |
| 129 | |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 130 | #if USE_IIOSERVICE |
| 131 | // If the buffer is enabled, which means mems_setup has already been used on |
| 132 | // this sensor and iioservice is reading the samples from it, skip setting the |
| 133 | // frequency. |
| 134 | if (!sensor_->IsBufferEnabled()) |
| 135 | sensor_->WriteDoubleAttribute(libmems::kSamplingFrequencyAttr, 0.0); |
| 136 | #endif // USE_IIOSERVICE |
| 137 | |
Harvey Yang | 72b89f8 | 2020-12-02 16:23:01 +0800 | [diff] [blame] | 138 | // Ignores the error as it may fail on kernel 4.4. |
| 139 | sensor_->WriteStringAttribute("current_timestamp_clock", "boottime"); |
| 140 | |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 141 | return true; |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 142 | } |
| 143 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 144 | bool Configuration::CopyLightCalibrationFromVpd() { |
| 145 | std::vector<LightVpdCalibrationEntry> calib_attributes = { |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 146 | {"als_cal_intercept", "calibbias"}, |
| 147 | {"als_cal_slope", "calibscale"}, |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 148 | }; |
| 149 | |
| 150 | for (auto& calib_attribute : calib_attributes) { |
| 151 | auto attrib_value = delegate_->ReadVpdValue(calib_attribute.vpd_name); |
| 152 | if (!attrib_value.has_value()) { |
| 153 | LOG(ERROR) << "VPD missing calibration value " |
| 154 | << calib_attribute.vpd_name; |
| 155 | continue; |
| 156 | } |
| 157 | |
| 158 | double value; |
| 159 | if (!base::StringToDouble(attrib_value.value(), &value)) { |
| 160 | LOG(ERROR) << "VPD calibration value " << calib_attribute.vpd_name |
| 161 | << " has invalid value " << attrib_value.value(); |
| 162 | continue; |
| 163 | } |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 164 | auto chn = sensor_->GetChannel("illuminance"); |
| 165 | if (!chn) { |
| 166 | LOG(ERROR) << "No channel illuminance"; |
| 167 | return false; |
| 168 | } |
| 169 | LOG(INFO) << "iio: " << calib_attribute.iio_name; |
| 170 | if (!chn->WriteDoubleAttribute(calib_attribute.iio_name, value)) |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 171 | LOG(ERROR) << "failed to set calibration value " |
| 172 | << calib_attribute.iio_name; |
| 173 | } |
| 174 | |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 175 | /* |
| 176 | * RGB sensors may need per channel calibration. |
| 177 | */ |
| 178 | std::vector<LightColorCalibrationEntry> calib_color_entries = { |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 179 | {"illuminance_red", base::nullopt}, |
| 180 | {"illuminance_green", base::nullopt}, |
| 181 | {"illuminance_blue", base::nullopt}, |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 182 | }; |
| 183 | auto attrib_value = delegate_->ReadVpdValue("als_cal_slope_color"); |
| 184 | |
| 185 | if (attrib_value.has_value()) { |
| 186 | /* |
| 187 | * Split the attributes in 3 doubles. |
| 188 | */ |
Tom Hughes | 09483d1 | 2020-08-27 15:55:08 -0700 | [diff] [blame] | 189 | std::vector<std::string> attrs = |
| 190 | base::SplitString(attrib_value.value(), " ", base::TRIM_WHITESPACE, |
| 191 | base::SPLIT_WANT_NONEMPTY); |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 192 | |
| 193 | if (attrs.size() == 3) { |
| 194 | for (int i = 0; i < 3; i++) { |
| 195 | double value; |
| 196 | if (!base::StringToDouble(attrs[i], &value)) { |
| 197 | LOG(ERROR) << "VPD_entry " << i << " of als_cal_slope_color " |
| 198 | << "is not a float: " << attrs[i]; |
| 199 | break; |
| 200 | } |
| 201 | calib_color_entries[i].value = value; |
| 202 | } |
| 203 | |
| 204 | for (auto& color_entry : calib_color_entries) { |
| 205 | if (!color_entry.value) { |
Tom Hughes | 09483d1 | 2020-08-27 15:55:08 -0700 | [diff] [blame] | 206 | LOG(ERROR) << "No value set for " << color_entry.iio_name; |
| 207 | continue; |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 208 | } |
| 209 | LOG(ERROR) << "writing " << *color_entry.value; |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 210 | auto chn = sensor_->GetChannel(color_entry.iio_name); |
| 211 | if (!chn) { |
| 212 | LOG(ERROR) << "No channel " << color_entry.iio_name; |
| 213 | return false; |
| 214 | } |
| 215 | if (!chn->WriteDoubleAttribute("calibscale", *color_entry.value)) |
| 216 | LOG(WARNING) << "failed to to set calibration value " |
| 217 | << color_entry.iio_name << " to " << *color_entry.value; |
Gwendal Grignou | aee3740 | 2019-12-18 23:51:43 -0800 | [diff] [blame] | 218 | } |
| 219 | } else { |
| 220 | LOG(ERROR) << "VPD_entry als_cal_slope_color is malformed : " |
| 221 | << attrib_value.value(); |
| 222 | } |
| 223 | } |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 224 | return true; |
| 225 | } |
| 226 | |
| 227 | bool Configuration::CopyImuCalibationFromVpd(int max_value) { |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 228 | if (sensor_->IsSingleSensor()) { |
| 229 | auto location = sensor_->ReadStringAttribute("location"); |
| 230 | if (!location || location->empty()) { |
| 231 | LOG(ERROR) << "cannot read a valid sensor location"; |
| 232 | return false; |
| 233 | } |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 234 | return CopyImuCalibationFromVpd(max_value, location->c_str()); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 235 | } else { |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 236 | bool base_config = CopyImuCalibationFromVpd(max_value, kBaseSensorLocation); |
| 237 | bool lid_config = CopyImuCalibationFromVpd(max_value, kLidSensorLocation); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 238 | return base_config && lid_config; |
| 239 | } |
| 240 | } |
| 241 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 242 | bool Configuration::CopyImuCalibationFromVpd(int max_value, |
| 243 | const std::string& location) { |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 244 | const bool is_single_sensor = sensor_->IsSingleSensor(); |
| 245 | std::string kind = SensorKindToString(kind_); |
| 246 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 247 | std::vector<ImuVpdCalibrationEntry> calib_attributes = { |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 248 | {"x", kCalibrationBias, max_value, base::nullopt, true}, |
| 249 | {"y", kCalibrationBias, max_value, base::nullopt, true}, |
| 250 | {"z", kCalibrationBias, max_value, base::nullopt, true}, |
Enrico Granata | fc7227d | 2019-07-26 13:51:19 -0700 | [diff] [blame] | 251 | |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 252 | {"x", kCalibrationScale, base::nullopt, base::nullopt, false}, |
| 253 | {"y", kCalibrationScale, base::nullopt, base::nullopt, false}, |
| 254 | {"z", kCalibrationScale, base::nullopt, base::nullopt, false}, |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 255 | }; |
| 256 | |
| 257 | for (auto& calib_attribute : calib_attributes) { |
| 258 | auto attrib_name = base::StringPrintf( |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 259 | "in_%s_%s_%s_calib%s", kind.c_str(), calib_attribute.name.c_str(), |
| 260 | location.c_str(), calib_attribute.calib.c_str()); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 261 | auto attrib_value = delegate_->ReadVpdValue(attrib_name.c_str()); |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 262 | LOG(INFO) << attrib_name |
| 263 | << " attrib_value: " << attrib_value.value_or("nan"); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 264 | if (!attrib_value.has_value()) { |
Enrico Granata | fc7227d | 2019-07-26 13:51:19 -0700 | [diff] [blame] | 265 | if (calib_attribute.missing_is_error) |
| 266 | LOG(ERROR) << "VPD missing calibration value " << attrib_name; |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 267 | continue; |
| 268 | } |
| 269 | |
| 270 | int value; |
| 271 | if (!base::StringToInt(attrib_value.value(), &value)) { |
| 272 | LOG(ERROR) << "VPD calibration value " << attrib_name |
| 273 | << " has invalid value " << attrib_value.value(); |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 274 | // TODO(crbug/1039454: gwendal): Add uma stats. |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 275 | continue; |
| 276 | } |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 277 | if (calib_attribute.max_value && abs(value) > calib_attribute.max_value) { |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 278 | LOG(ERROR) << "VPD calibration value " << attrib_name |
| 279 | << " has out-of-range value " << attrib_value.value(); |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 280 | // TODO(crbug/1039454: gwendal): Add uma stats. |
| 281 | return false; |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 282 | } else { |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 283 | calib_attribute.value = value; |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 284 | } |
| 285 | } |
| 286 | |
| 287 | for (const auto& calib_attribute : calib_attributes) { |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 288 | if (!calib_attribute.value) |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 289 | continue; |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 290 | auto chn_id = |
| 291 | base::StringPrintf("%s_%s", kind.c_str(), calib_attribute.name.c_str()); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 292 | |
| 293 | if (!is_single_sensor) |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 294 | chn_id = base::StringPrintf("%s_%s", chn_id.c_str(), location.c_str()); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 295 | |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 296 | auto chn = sensor_->GetChannel(chn_id); |
| 297 | if (!chn) { |
| 298 | LOG(ERROR) << "No channel with id " << chn_id; |
| 299 | return false; |
| 300 | } |
| 301 | auto attrib_name = |
| 302 | base::StringPrintf("calib%s", calib_attribute.calib.c_str()); |
| 303 | if (!chn->WriteNumberAttribute(attrib_name, *calib_attribute.value)) { |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 304 | LOG(ERROR) << "failed to set calibration value " << attrib_name; |
Harvey Yang | fc9178f | 2020-03-16 14:26:53 +0800 | [diff] [blame] | 305 | return false; |
| 306 | } |
| 307 | LOG(INFO) << attrib_name << ": " |
| 308 | << chn->ReadNumberAttribute(attrib_name).value_or(-88888); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | LOG(INFO) << "VPD calibration complete"; |
| 312 | return true; |
| 313 | } |
| 314 | |
Gwendal Grignou | 1a66337 | 2020-01-24 09:36:49 -0800 | [diff] [blame] | 315 | bool Configuration::AddSysfsTrigger(int sysfs_trigger_id) { |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 316 | std::string dev_name = |
| 317 | libmems::IioDeviceImpl::GetStringFromId(sensor_->GetId()); |
| 318 | // /sys/bus/iio/devices/iio:deviceX |
Harvey Yang | 9fae371 | 2020-10-29 22:45:03 +0800 | [diff] [blame] | 319 | base::FilePath sys_dev_path = sensor_->GetPath(); |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 320 | |
| 321 | if (!delegate_->Exists(sys_dev_path.Append(kTriggerString))) { |
| 322 | // Uses FIFO and doesn't need a trigger. |
| 323 | return true; |
| 324 | } |
| 325 | |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 326 | // There is a potential cross-process race here, where multiple instances |
| 327 | // of this tool may be trying to access the trigger at once. To solve this, |
| 328 | // first see if the trigger is already there. If not, try to create it, and |
| 329 | // then try to access it again. Only if the latter access fails then |
| 330 | // error out. |
Tom Hughes | 09483d1 | 2020-08-27 15:55:08 -0700 | [diff] [blame] | 331 | auto trigger_name = |
| 332 | base::StringPrintf("%s%d", kSysfsTriggerPrefix, sysfs_trigger_id); |
Gwendal Grignou | 1a66337 | 2020-01-24 09:36:49 -0800 | [diff] [blame] | 333 | auto triggers = context_->GetTriggersByName(trigger_name); |
| 334 | |
| 335 | if (triggers.size() > 1) { |
| 336 | LOG(ERROR) << "Several triggers with the same name " << trigger_name |
| 337 | << " is not expected."; |
| 338 | return false; |
| 339 | } |
| 340 | if (triggers.size() == 0) { |
| 341 | LOG(INFO) << "trigger " << trigger_name << " not found; adding"; |
| 342 | |
| 343 | auto iio_sysfs_trigger = context_->GetTriggerById(kSysfsTriggerId); |
| 344 | if (iio_sysfs_trigger == nullptr) { |
| 345 | LOG(ERROR) << "cannot find iio_trig_sysfs kernel module"; |
| 346 | return false; |
| 347 | } |
| 348 | |
| 349 | if (!iio_sysfs_trigger->WriteNumberAttribute("add_trigger", |
| 350 | sysfs_trigger_id)) { |
| 351 | // It may happen if another instance of mems_setup is running in parallel. |
| 352 | LOG(WARNING) << "cannot instantiate trigger " << trigger_name; |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 353 | } |
| 354 | |
Gwendal Grignou | ba911fe | 2019-12-08 17:14:53 -0800 | [diff] [blame] | 355 | context_->Reload(); |
Gwendal Grignou | 1a66337 | 2020-01-24 09:36:49 -0800 | [diff] [blame] | 356 | triggers = context_->GetTriggersByName(trigger_name); |
| 357 | if (triggers.size() != 1) { |
| 358 | LOG(ERROR) << "Trigger " << trigger_name << " not been created properly"; |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 359 | return false; |
| 360 | } |
| 361 | } |
| 362 | |
Gwendal Grignou | 1a66337 | 2020-01-24 09:36:49 -0800 | [diff] [blame] | 363 | if (!sensor_->SetTrigger(triggers[0])) { |
| 364 | LOG(ERROR) << "cannot set sensor's trigger to " << trigger_name; |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 365 | return false; |
| 366 | } |
| 367 | |
Gwendal Grignou | 1a66337 | 2020-01-24 09:36:49 -0800 | [diff] [blame] | 368 | base::FilePath trigger_now = triggers[0]->GetPath().Append("trigger_now"); |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 369 | |
| 370 | base::Optional<gid_t> chronos_gid = delegate_->FindGroupId("chronos"); |
| 371 | if (!chronos_gid) { |
| 372 | LOG(ERROR) << "chronos group not found"; |
| 373 | return false; |
| 374 | } |
| 375 | |
| 376 | if (!delegate_->SetOwnership(trigger_now, -1, chronos_gid.value())) { |
| 377 | LOG(ERROR) << "cannot configure ownership on the trigger"; |
| 378 | return false; |
| 379 | } |
| 380 | |
| 381 | int permission = delegate_->GetPermissions(trigger_now); |
| 382 | permission |= base::FILE_PERMISSION_WRITE_BY_GROUP; |
| 383 | if (!delegate_->SetPermissions(trigger_now, permission)) { |
| 384 | LOG(ERROR) << "cannot configure permissions on the trigger"; |
| 385 | return false; |
| 386 | } |
| 387 | |
| 388 | LOG(INFO) << "sysfs trigger setup complete"; |
| 389 | return true; |
| 390 | } |
| 391 | |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 392 | bool Configuration::EnableAccelScanElements() { |
| 393 | auto timestamp = sensor_->GetChannel("timestamp"); |
| 394 | if (!timestamp) { |
| 395 | LOG(ERROR) << "cannot find timestamp channel"; |
| 396 | return false; |
| 397 | } |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 398 | if (!timestamp->SetScanElementsEnabled(false)) { |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 399 | LOG(ERROR) << "failed to disable timestamp channel"; |
| 400 | return false; |
| 401 | } |
| 402 | |
| 403 | std::vector<std::string> channels_to_enable; |
| 404 | |
| 405 | if (sensor_->IsSingleSensor()) { |
| 406 | for (const auto& axis : kAccelAxes) { |
| 407 | channels_to_enable.push_back(base::StringPrintf("accel_%s", axis)); |
| 408 | } |
| 409 | } else { |
| 410 | for (const auto& axis : kAccelAxes) { |
| 411 | channels_to_enable.push_back( |
| 412 | base::StringPrintf("accel_%s_%s", axis, kBaseSensorLocation)); |
| 413 | channels_to_enable.push_back( |
| 414 | base::StringPrintf("accel_%s_%s", axis, kLidSensorLocation)); |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | for (const auto& chan_name : channels_to_enable) { |
| 419 | auto channel = sensor_->GetChannel(chan_name); |
| 420 | if (!channel) { |
| 421 | LOG(ERROR) << "cannot find channel " << chan_name; |
| 422 | return false; |
| 423 | } |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 424 | if (!channel->SetScanElementsEnabled(true)) { |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 425 | LOG(ERROR) << "failed to enable channel " << chan_name; |
| 426 | return false; |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | sensor_->EnableBuffer(1); |
| 431 | if (!sensor_->IsBufferEnabled()) { |
| 432 | LOG(ERROR) << "failed to enable buffer"; |
| 433 | return false; |
| 434 | } |
| 435 | |
| 436 | LOG(INFO) << "buffer enabled"; |
| 437 | return true; |
| 438 | } |
| 439 | |
Gwendal Grignou | 7397fe7 | 2019-11-18 10:03:59 -0800 | [diff] [blame] | 440 | bool Configuration::EnableCalibration(bool enable) { |
| 441 | auto calibration = sensor_->GetChannel("calibration"); |
| 442 | if (!calibration) { |
| 443 | LOG(ERROR) << "cannot find calibration channel"; |
| 444 | return false; |
| 445 | } |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 446 | return calibration->SetScanElementsEnabled(enable); |
Gwendal Grignou | 7397fe7 | 2019-11-18 10:03:59 -0800 | [diff] [blame] | 447 | } |
| 448 | |
Enrico Granata | fc2e347 | 2019-07-16 11:23:25 -0700 | [diff] [blame] | 449 | bool Configuration::EnableKeyboardAngle() { |
| 450 | base::FilePath kb_wake_angle; |
| 451 | if (sensor_->IsSingleSensor()) { |
| 452 | kb_wake_angle = base::FilePath("/sys/class/chromeos/cros_ec/kb_wake_angle"); |
| 453 | } else { |
| 454 | kb_wake_angle = sensor_->GetPath().Append("in_angl_offset"); |
| 455 | } |
| 456 | |
| 457 | if (!delegate_->Exists(kb_wake_angle)) { |
| 458 | LOG(INFO) << kb_wake_angle.value() |
| 459 | << " not found; will not enable EC wake angle"; |
| 460 | return true; |
| 461 | } |
| 462 | |
| 463 | base::Optional<gid_t> power_gid = delegate_->FindGroupId("power"); |
| 464 | if (!power_gid) { |
| 465 | LOG(ERROR) << "cannot configure ownership on the wake angle file"; |
| 466 | return false; |
| 467 | } |
| 468 | |
| 469 | delegate_->SetOwnership(kb_wake_angle, -1, power_gid.value()); |
| 470 | int permission = delegate_->GetPermissions(kb_wake_angle); |
| 471 | permission |= base::FILE_PERMISSION_WRITE_BY_GROUP; |
| 472 | delegate_->SetPermissions(kb_wake_angle, permission); |
| 473 | |
| 474 | LOG(INFO) << "keyboard angle enabled"; |
| 475 | return true; |
| 476 | } |
| 477 | |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 478 | bool Configuration::ConfigureOnKind() { |
| 479 | switch (kind_) { |
| 480 | case SensorKind::ACCELEROMETER: |
| 481 | return ConfigAccelerometer(); |
| 482 | case SensorKind::GYROSCOPE: |
| 483 | return ConfigGyro(); |
| 484 | case SensorKind::LIGHT: |
| 485 | return ConfigIlluminance(); |
| 486 | case SensorKind::SYNC: |
| 487 | // No other configs needed. |
| 488 | return true; |
| 489 | case SensorKind::MAGNETOMETER: |
| 490 | // No other configs needed. |
| 491 | return true; |
| 492 | case SensorKind::LID_ANGLE: |
| 493 | // No other configs needed. |
| 494 | return true; |
| 495 | case SensorKind::BAROMETER: |
| 496 | // TODO(chenghaoyang): Setup calibrations for the barometer. |
| 497 | return true; |
| 498 | default: |
| 499 | CHECK(kind_ == SensorKind::OTHERS); |
| 500 | LOG(ERROR) << sensor_->GetName() << " unimplemented"; |
| 501 | return false; |
| 502 | } |
| 503 | } |
| 504 | |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 505 | bool Configuration::ConfigGyro() { |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 506 | CopyImuCalibationFromVpd(kGyroMaxVpdCalibration); |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 507 | |
| 508 | LOG(INFO) << "gyroscope configuration complete"; |
| 509 | return true; |
| 510 | } |
| 511 | |
Enrico Granata | 7a62234 | 2019-05-21 11:10:59 -0700 | [diff] [blame] | 512 | bool Configuration::ConfigAccelerometer() { |
Gwendal Grignou | 4460a0d | 2020-01-06 14:07:00 -0800 | [diff] [blame] | 513 | CopyImuCalibationFromVpd(kAccelMaxVpdCalibration); |
Enrico Granata | 7a62234 | 2019-05-21 11:10:59 -0700 | [diff] [blame] | 514 | |
Enrico Granata | 10e19de | 2019-05-21 14:17:36 -0700 | [diff] [blame] | 515 | if (!AddSysfsTrigger(kAccelSysfsTriggerId)) |
| 516 | return false; |
| 517 | |
Harvey Yang | aa650ed | 2020-09-24 13:03:02 +0800 | [diff] [blame] | 518 | if (!USE_IIOSERVICE && !EnableAccelScanElements()) |
Enrico Granata | 064a25c | 2019-07-15 15:48:03 -0700 | [diff] [blame] | 519 | return false; |
| 520 | |
Enrico Granata | fc2e347 | 2019-07-16 11:23:25 -0700 | [diff] [blame] | 521 | if (!EnableKeyboardAngle()) |
| 522 | return false; |
| 523 | |
Gwendal Grignou | ba911fe | 2019-12-08 17:14:53 -0800 | [diff] [blame] | 524 | /* |
| 525 | * Gather gyroscope. If one of them is on the same plane, set |
| 526 | * accelerometer range to 4g to meet Android 10 CCD Requirements |
| 527 | * (Sectiom 7.1.4, C.1.4). |
| 528 | * If no gyro found, set range to 4g on the lid accel. |
| 529 | */ |
| 530 | int range = 0; |
| 531 | auto location = sensor_->ReadStringAttribute("location"); |
| 532 | if (location && !location->empty()) { |
| 533 | auto gyros = context_->GetDevicesByName("cros-ec-gyro"); |
| 534 | if (gyros.size() != 1 && strcmp(location->c_str(), kLidSensorLocation) == 0) |
| 535 | range = 4; |
| 536 | else if (gyros.size() == 1 && |
| 537 | strcmp(location->c_str(), |
| 538 | gyros[0]->ReadStringAttribute("location")->c_str()) == 0) |
| 539 | range = 4; |
| 540 | else |
| 541 | range = 2; |
| 542 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 543 | if (!sensor_->WriteNumberAttribute(kCalibrationScale, range)) |
| 544 | return false; |
Gwendal Grignou | ba911fe | 2019-12-08 17:14:53 -0800 | [diff] [blame] | 545 | } |
| 546 | |
Enrico Granata | 7a62234 | 2019-05-21 11:10:59 -0700 | [diff] [blame] | 547 | LOG(INFO) << "accelerometer configuration complete"; |
| 548 | return true; |
| 549 | } |
| 550 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 551 | bool Configuration::ConfigIlluminance() { |
Harvey Yang | 06ce00f | 2020-12-01 18:05:23 +0800 | [diff] [blame] | 552 | if (USE_IIOSERVICE && strcmp(sensor_->GetName(), "acpi-als") == 0) { |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 553 | std::string trigger_name = |
| 554 | base::StringPrintf(libmems::kHrtimerNameFormatString, sensor_->GetId()); |
| 555 | if (context_->GetTriggersByName(trigger_name).empty()) { |
Harvey Yang | 06ce00f | 2020-12-01 18:05:23 +0800 | [diff] [blame] | 556 | base::FilePath hrtimer_path("/sys/kernel/config/iio/triggers/hrtimer"); |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 557 | hrtimer_path = hrtimer_path.Append(trigger_name); |
Harvey Yang | 06ce00f | 2020-12-01 18:05:23 +0800 | [diff] [blame] | 558 | |
| 559 | if (!delegate_->Exists(hrtimer_path) && |
| 560 | !delegate_->ProbeKernelModule("iio-trig-hrtimer")) { |
| 561 | LOG(ERROR) << "cannot load iio-trig-hrtimer module"; |
| 562 | return false; |
| 563 | } |
| 564 | |
| 565 | if (!delegate_->CreateDirectory(hrtimer_path)) { |
| 566 | LOG(ERROR) << "cannot mkdir " << hrtimer_path.value() |
| 567 | << " to create the hrtimer device"; |
| 568 | return false; |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | context_->Reload(); |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 573 | auto triggers = context_->GetTriggersByName(trigger_name); |
Harvey Yang | 06ce00f | 2020-12-01 18:05:23 +0800 | [diff] [blame] | 574 | if (triggers.empty()) { |
| 575 | LOG(ERROR) << "cannot find acpi-als's trigger"; |
| 576 | return false; |
| 577 | } |
| 578 | |
Harvey Yang | ee5a26d | 2021-03-23 17:19:27 +0800 | [diff] [blame] | 579 | // Don't set |trigger| as |sensor_|'s trigger, or else the samples start |
| 580 | // flowing. |
Harvey Yang | 06ce00f | 2020-12-01 18:05:23 +0800 | [diff] [blame] | 581 | auto trigger = triggers.front(); |
| 582 | // /sys/bus/iio/devices/triggerX |
| 583 | base::FilePath sys_trg_path = |
| 584 | trigger->GetPath().Append(libmems::kSamplingFrequencyAttr); |
| 585 | SetReadPermissionAndOwnership(sys_trg_path); |
| 586 | SetWritePermissionAndOwnership(sys_trg_path); |
Harvey Yang | 06ce00f | 2020-12-01 18:05:23 +0800 | [diff] [blame] | 587 | } |
| 588 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 589 | if (!CopyLightCalibrationFromVpd()) |
| 590 | return false; |
| 591 | |
Gwendal Grignou | 7397fe7 | 2019-11-18 10:03:59 -0800 | [diff] [blame] | 592 | // Disable calibration: it can fail if the light sensor does not support |
| 593 | // calibration mode. |
| 594 | EnableCalibration(false); |
| 595 | |
Enrico Granata | 651d257 | 2019-07-16 15:17:01 -0700 | [diff] [blame] | 596 | LOG(INFO) << "light configuration complete"; |
| 597 | return true; |
| 598 | } |
| 599 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 600 | bool Configuration::SetupPermissions() { |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 601 | std::vector<base::FilePath> files_to_set_read_own; |
| 602 | std::vector<base::FilePath> files_to_set_write_own; |
| 603 | |
| 604 | std::string dev_name = |
| 605 | libmems::IioDeviceImpl::GetStringFromId(sensor_->GetId()); |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 606 | #if USE_IIOSERVICE |
| 607 | // /dev/iio:deviceX |
| 608 | base::FilePath dev_path = base::FilePath(kDevString).Append(dev_name.c_str()); |
| 609 | if (!delegate_->Exists(dev_path)) { |
| 610 | LOG(ERROR) << "Missing path: " << dev_path.value(); |
| 611 | return false; |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 612 | } |
| 613 | |
Harvey Yang | 1d50fff | 2020-10-27 12:24:38 +0800 | [diff] [blame] | 614 | files_to_set_read_own.push_back(dev_path); |
| 615 | files_to_set_write_own.push_back(dev_path); |
| 616 | #endif // USE_IIOSERVICE |
| 617 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 618 | // /sys/bus/iio/devices/iio:deviceX |
Harvey Yang | 9fae371 | 2020-10-29 22:45:03 +0800 | [diff] [blame] | 619 | base::FilePath sys_dev_path = sensor_->GetPath(); |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 620 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 621 | // Files under /sys/bus/iio/devices/iio:deviceX/. |
| 622 | auto files = EnumerateAllFiles(sys_dev_path); |
| 623 | files_to_set_read_own.insert(files_to_set_read_own.end(), files.begin(), |
| 624 | files.end()); |
| 625 | // Files under /sys/bus/iio/devices/iio:deviceX/scan_elements/. |
| 626 | files = EnumerateAllFiles(sys_dev_path.Append(kScanElementsString)); |
| 627 | files_to_set_read_own.insert(files_to_set_read_own.end(), files.begin(), |
| 628 | files.end()); |
| 629 | |
| 630 | for (auto file : kFilesToSetReadAndOwnership) |
| 631 | files_to_set_read_own.push_back(sys_dev_path.Append(file)); |
| 632 | |
Harvey Yang | 34f464c | 2020-01-08 17:43:46 +0800 | [diff] [blame] | 633 | for (auto file : kFilesToSetWriteAndOwnership) |
| 634 | files_to_set_write_own.push_back(sys_dev_path.Append(file)); |
| 635 | |
| 636 | for (auto channel : sensor_->GetAllChannels()) { |
| 637 | files_to_set_write_own.push_back( |
| 638 | sys_dev_path.Append(kScanElementsString) |
| 639 | .Append( |
| 640 | base::StringPrintf(kChnEnableFormatString, channel->GetId()))); |
| 641 | } |
| 642 | |
| 643 | // Set permissions and ownerships. |
| 644 | bool result = true; |
| 645 | |
| 646 | for (base::FilePath path : files_to_set_read_own) |
| 647 | result &= SetReadPermissionAndOwnership(path); |
| 648 | |
| 649 | for (base::FilePath path : files_to_set_write_own) |
| 650 | result &= SetWritePermissionAndOwnership(path); |
| 651 | |
| 652 | return result; |
| 653 | } |
| 654 | |
| 655 | std::vector<base::FilePath> Configuration::EnumerateAllFiles( |
| 656 | base::FilePath file_path) { |
| 657 | std::vector<base::FilePath> files; |
| 658 | |
| 659 | base::FileEnumerator file_enumerator(file_path, false, |
| 660 | base::FileEnumerator::FILES); |
| 661 | |
| 662 | for (base::FilePath file = file_enumerator.Next(); !file.empty(); |
| 663 | file = file_enumerator.Next()) |
| 664 | files.push_back(file); |
| 665 | |
| 666 | return files; |
| 667 | } |
| 668 | |
| 669 | bool Configuration::SetReadPermissionAndOwnership(base::FilePath file_path) { |
| 670 | DCHECK(iioservice_gid_.has_value()); |
| 671 | |
| 672 | if (!delegate_->Exists(file_path)) |
| 673 | return true; |
| 674 | |
| 675 | bool result = true; |
| 676 | |
| 677 | int permission = delegate_->GetPermissions(file_path); |
| 678 | permission |= base::FILE_PERMISSION_READ_BY_GROUP; |
| 679 | |
| 680 | if (!delegate_->SetPermissions(file_path, permission)) { |
| 681 | LOG(ERROR) << "cannot configure permissions on " << file_path.value(); |
| 682 | result = false; |
| 683 | } |
| 684 | |
| 685 | if (!delegate_->SetOwnership(file_path, -1, iioservice_gid_.value())) { |
| 686 | LOG(ERROR) << "cannot configure ownership on " << file_path.value(); |
| 687 | result = false; |
| 688 | } |
| 689 | |
| 690 | return result; |
| 691 | } |
| 692 | |
| 693 | bool Configuration::SetWritePermissionAndOwnership(base::FilePath file_path) { |
| 694 | DCHECK(iioservice_gid_.has_value()); |
| 695 | |
| 696 | if (!delegate_->Exists(file_path)) |
| 697 | return true; |
| 698 | |
| 699 | bool result = true; |
| 700 | |
| 701 | int permission = delegate_->GetPermissions(file_path); |
| 702 | permission |= base::FILE_PERMISSION_WRITE_BY_GROUP; |
| 703 | |
| 704 | if (!delegate_->SetPermissions(file_path, permission)) { |
| 705 | LOG(ERROR) << "cannot configure permissions on " << file_path.value(); |
| 706 | result = false; |
| 707 | } |
| 708 | |
| 709 | if (!delegate_->SetOwnership(file_path, -1, iioservice_gid_.value())) { |
| 710 | LOG(ERROR) << "cannot configure ownership on " << file_path.value(); |
| 711 | result = false; |
| 712 | } |
| 713 | |
| 714 | return result; |
| 715 | } |
| 716 | |
Enrico Granata | 60b1cbc | 2019-05-20 11:06:46 -0700 | [diff] [blame] | 717 | } // namespace mems_setup |