Home | History | Annotate | Download | only in linux
      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  */
     32 int 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  */
     54 int 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  */
     76 int 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  */
    102 int 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  */
    128 int 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  */
    149 int 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  */
    169 int 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  */
    189 int 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  */
    209 int 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  */
    229 int 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  */
    250 int 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  */
    271 int 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  */
    296 int 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  */
    307 int 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  */
    318 int 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