Home | History | Annotate | Download | only in linux
      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  */
     26 int 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  */
     48 int 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  */
     70 int 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  */
     96 int 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  */
    122 int 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  */
    143 int 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  */
    163 int 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  */
    183 int 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  */
    203 int 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  */
    223 int 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  */
    244 int 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  */
    265 int 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  */
    290 int 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  */
    301 int 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  */
    312 int 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