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