1/* 2 $License: 3 Copyright (C) 2014 InvenSense Corporation, All Rights Reserved. 4 $ 5 */ 6 7/** 8 * @brief Provides helpful file IO wrappers for use with sysfs. 9 * @details Based on Jonathan Cameron's @e iio_utils.h. 10 */ 11 12#include <string.h> 13#include <stdlib.h> 14#include <ctype.h> 15#include <stdio.h> 16#include <stdint.h> 17#include <dirent.h> 18#include <errno.h> 19#include <unistd.h> 20#include "inv_sysfs_utils.h" 21 22/* General TODO list: 23 * Select more reasonable string lengths or use fseek and malloc. 24 */ 25 26/** 27 * inv_sysfs_write() - Write an integer to a file. 28 * @filename: Path to file. 29 * @data: Value to write to file. 30 * Returns number of bytes written or a negative error code. 31 */ 32int inv_sysfs_write(char *filename, long data) 33{ 34 FILE *fp; 35 int count; 36 37 if (!filename) 38 return -1; 39 fp = fopen(filename, "w"); 40 if (!fp) 41 return -errno; 42 count = fprintf(fp, "%ld", data); 43 fclose(fp); 44 return count; 45} 46 47/** 48 * inv_sysfs_read() - Read a string from a file. 49 * @filename: Path to file. 50 * @num_bytes: Number of bytes to read. 51 * @data: Data from file. 52 * Returns number of bytes written or a negative error code. 53 */ 54int inv_sysfs_read(char *filename, long num_bytes, char *data) 55{ 56 FILE *fp; 57 int count; 58 59 if (!filename) 60 return -1; 61 fp = fopen(filename, "r"); 62 if (!fp) 63 return -errno; 64 count = fread(data, 1, num_bytes, fp); 65 fclose(fp); 66 return count; 67} 68 69/** 70 * inv_read_buffer() - Read data from ring buffer. 71 * @fd: File descriptor for buffer file. 72 * @data: Data in hardware units. 73 * @timestamp: Time when data was read from device. Use NULL if unsupported. 74 * Returns number of bytes written or a negative error code. 75 */ 76int inv_read_buffer(int fd, long *data, long long *timestamp) 77{ 78 char str[35]; 79 int count; 80 81 count = read(fd, str, sizeof(str)); 82 if (!count) 83 return count; 84 if (!timestamp) 85 count = sscanf(str, "%ld%ld%ld", &data[0], &data[1], &data[2]); 86 else 87 count = sscanf(str, "%ld%ld%ld%lld", &data[0], &data[1], 88 &data[2], timestamp); 89 90 if (count < (timestamp?4:3)) 91 return -EAGAIN; 92 return count; 93} 94 95/** 96 * inv_read_raw() - Read raw data. 97 * @names: Names of sysfs files. 98 * @data: Data in hardware units. 99 * @timestamp: Time when data was read from device. Use NULL if unsupported. 100 * Returns number of bytes written or a negative error code. 101 */ 102int inv_read_raw(const struct inv_sysfs_names_s *names, long *data, 103 long long *timestamp) 104{ 105 char str[40]; 106 int count; 107 108 count = inv_sysfs_read((char*)names->raw_data, sizeof(str), str); 109 if (count < 0) 110 return count; 111 if (!timestamp) 112 count = sscanf(str, "%ld%ld%ld", &data[0], &data[1], &data[2]); 113 else 114 count = sscanf(str, "%ld%ld%ld%lld", &data[0], &data[1], 115 &data[2], timestamp); 116 if (count < (timestamp?4:3)) 117 return -EAGAIN; 118 return count; 119} 120 121/** 122 * inv_read_temperature_raw() - Read temperature. 123 * @names: Names of sysfs files. 124 * @data: Data in hardware units. 125 * @timestamp: Time when data was read from device. 126 * Returns number of bytes written or a negative error code. 127 */ 128int inv_read_temperature_raw(const struct inv_sysfs_names_s *names, short *data, 129 long long *timestamp) 130{ 131 char str[25]; 132 int count; 133 134 count = inv_sysfs_read((char*)names->temperature, sizeof(str), str); 135 if (count < 0) 136 return count; 137 count = sscanf(str, "%hd%lld", &data[0], timestamp); 138 if (count < 2) 139 return -EAGAIN; 140 return count; 141} 142 143/** 144 * inv_read_fifo_rate() - Read fifo rate. 145 * @names: Names of sysfs files. 146 * @data: Fifo rate. 147 * Returns number of bytes written or a negative error code. 148 */ 149int inv_read_fifo_rate(const struct inv_sysfs_names_s *names, short *data) 150{ 151 char str[8]; 152 int count; 153 154 count = inv_sysfs_read((char*)names->fifo_rate, sizeof(str), str); 155 if (count < 0) 156 return count; 157 count = sscanf(str, "%hd", data); 158 if (count < 1) 159 return -EAGAIN; 160 return count; 161} 162 163/** 164 * inv_read_power_state() - Read power state. 165 * @names: Names of sysfs files. 166 * @data: 1 if device is on. 167 * Returns number of bytes written or a negative error code. 168 */ 169int inv_read_power_state(const struct inv_sysfs_names_s *names, char *data) 170{ 171 char str[2]; 172 int count; 173 174 count = inv_sysfs_read((char*)names->power_state, sizeof(str), str); 175 if (count < 0) 176 return count; 177 count = sscanf(str, "%hd", (short*)data); 178 if (count < 1) 179 return -EAGAIN; 180 return count; 181} 182 183/** 184 * inv_read_scale() - Read scale. 185 * @names: Names of sysfs files. 186 * @data: 1 if device is on. 187 * Returns number of bytes written or a negative error code. 188 */ 189int inv_read_scale(const struct inv_sysfs_names_s *names, float *data) 190{ 191 char str[5]; 192 int count; 193 194 count = inv_sysfs_read((char*)names->scale, sizeof(str), str); 195 if (count < 0) 196 return count; 197 count = sscanf(str, "%f", data); 198 if (count < 1) 199 return -EAGAIN; 200 return count; 201} 202 203/** 204 * inv_read_temp_scale() - Read temperature scale. 205 * @names: Names of sysfs files. 206 * @data: 1 if device is on. 207 * Returns number of bytes written or a negative error code. 208 */ 209int inv_read_temp_scale(const struct inv_sysfs_names_s *names, short *data) 210{ 211 char str[4]; 212 int count; 213 214 count = inv_sysfs_read((char*)names->temp_scale, sizeof(str), str); 215 if (count < 0) 216 return count; 217 count = sscanf(str, "%hd", data); 218 if (count < 1) 219 return -EAGAIN; 220 return count; 221} 222 223/** 224 * inv_read_temp_offset() - Read temperature offset. 225 * @names: Names of sysfs files. 226 * @data: 1 if device is on. 227 * Returns number of bytes written or a negative error code. 228 */ 229int inv_read_temp_offset(const struct inv_sysfs_names_s *names, short *data) 230{ 231 char str[4]; 232 int count; 233 234 count = inv_sysfs_read((char*)names->temp_offset, sizeof(str), str); 235 if (count < 0) 236 return count; 237 count = sscanf(str, "%hd", data); 238 if (count < 1) 239 return -EAGAIN; 240 return count; 241} 242 243/** 244 * inv_read_q16() - Get data as q16 fixed point. 245 * @names: Names of sysfs files. 246 * @data: 1 if device is on. 247 * @timestamp: Time when data was read from device. 248 * Returns number of bytes written or a negative error code. 249 */ 250int inv_read_q16(const struct inv_sysfs_names_s *names, long *data, 251 long long *timestamp) 252{ 253 int count; 254 short raw[3]; 255 float scale; 256 count = inv_read_raw(names, (long*)raw, timestamp); 257 count += inv_read_scale(names, &scale); 258 data[0] = (long)(raw[0] * (65536.f / scale)); 259 data[1] = (long)(raw[1] * (65536.f / scale)); 260 data[2] = (long)(raw[2] * (65536.f / scale)); 261 return count; 262} 263 264/** 265 * inv_read_q16() - Get temperature data as q16 fixed point. 266 * @names: Names of sysfs files. 267 * @data: 1 if device is on. 268 * @timestamp: Time when data was read from device. 269 * Returns number of bytes read or a negative error code. 270 */ 271int inv_read_temp_q16(const struct inv_sysfs_names_s *names, long *data, 272 long long *timestamp) 273{ 274 int count = 0; 275 short raw; 276 static short scale, offset; 277 static unsigned char first_read = 1; 278 279 if (first_read) { 280 count += inv_read_temp_scale(names, &scale); 281 count += inv_read_temp_offset(names, &offset); 282 first_read = 0; 283 } 284 count += inv_read_temperature_raw(names, &raw, timestamp); 285 data[0] = (long)((35 + ((float)(raw - offset) / scale)) * 65536.f); 286 287 return count; 288} 289 290/** 291 * inv_write_fifo_rate() - Write fifo rate. 292 * @names: Names of sysfs files. 293 * @data: Fifo rate. 294 * Returns number of bytes written or a negative error code. 295 */ 296int inv_write_fifo_rate(const struct inv_sysfs_names_s *names, short data) 297{ 298 return inv_sysfs_write((char*)names->fifo_rate, (long)data); 299} 300 301/** 302 * inv_write_buffer_enable() - Enable/disable buffer in /dev. 303 * @names: Names of sysfs files. 304 * @data: Fifo rate. 305 * Returns number of bytes written or a negative error code. 306 */ 307int inv_write_buffer_enable(const struct inv_sysfs_names_s *names, char data) 308{ 309 return inv_sysfs_write((char*)names->enable, (long)data); 310} 311 312/** 313 * inv_write_power_state() - Turn device on/off. 314 * @names: Names of sysfs files. 315 * @data: 1 to turn on. 316 * Returns number of bytes written or a negative error code. 317 */ 318int inv_write_power_state(const struct inv_sysfs_names_s *names, char data) 319{ 320 return inv_sysfs_write((char*)names->power_state, (long)data); 321} 322 323 324 325