blob: c45badd863f1bc3c705ab2c4256fd4a12f09fc4e [file] [log] [blame]
/**
* @brief Provides helpful file IO wrappers for use with sysfs.
* @details Based on Jonathan Cameron's @e iio_utils.h.
*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include "inv_sysfs_utils.h"
/* General TODO list:
* Select more reasonable string lengths or use fseek and malloc.
*/
/**
* inv_sysfs_write() - Write an integer to a file.
* @filename: Path to file.
* @data: Value to write to file.
* Returns number of bytes written or a negative error code.
*/
int inv_sysfs_write(char *filename, long data)
{
FILE *fp;
int count;
if (!filename)
return -1;
fp = fopen(filename, "w");
if (!fp)
return -errno;
count = fprintf(fp, "%ld", data);
fclose(fp);
return count;
}
/**
* inv_sysfs_read() - Read a string from a file.
* @filename: Path to file.
* @num_bytes: Number of bytes to read.
* @data: Data from file.
* Returns number of bytes written or a negative error code.
*/
int inv_sysfs_read(char *filename, long num_bytes, char *data)
{
FILE *fp;
int count;
if (!filename)
return -1;
fp = fopen(filename, "r");
if (!fp)
return -errno;
count = fread(data, 1, num_bytes, fp);
fclose(fp);
return count;
}
/**
* inv_read_buffer() - Read data from ring buffer.
* @fd: File descriptor for buffer file.
* @data: Data in hardware units.
* @timestamp: Time when data was read from device. Use NULL if unsupported.
* Returns number of bytes written or a negative error code.
*/
int inv_read_buffer(int fd, long *data, long long *timestamp)
{
char str[35];
int count;
count = read(fd, str, sizeof(str));
if (!count)
return count;
if (!timestamp)
count = sscanf(str, "%ld%ld%ld", &data[0], &data[1], &data[2]);
else
count = sscanf(str, "%ld%ld%ld%lld", &data[0], &data[1],
&data[2], timestamp);
if (count < (timestamp?4:3))
return -EAGAIN;
return count;
}
/**
* inv_read_raw() - Read raw data.
* @names: Names of sysfs files.
* @data: Data in hardware units.
* @timestamp: Time when data was read from device. Use NULL if unsupported.
* Returns number of bytes written or a negative error code.
*/
int inv_read_raw(const struct inv_sysfs_names_s *names, long *data,
long long *timestamp)
{
char str[40];
int count;
count = inv_sysfs_read((char*)names->raw_data, sizeof(str), str);
if (count < 0)
return count;
if (!timestamp)
count = sscanf(str, "%ld%ld%ld", &data[0], &data[1], &data[2]);
else
count = sscanf(str, "%ld%ld%ld%lld", &data[0], &data[1],
&data[2], timestamp);
if (count < (timestamp?4:3))
return -EAGAIN;
return count;
}
/**
* inv_read_temperature_raw() - Read temperature.
* @names: Names of sysfs files.
* @data: Data in hardware units.
* @timestamp: Time when data was read from device.
* Returns number of bytes written or a negative error code.
*/
int inv_read_temperature_raw(const struct inv_sysfs_names_s *names, short *data,
long long *timestamp)
{
char str[25];
int count;
count = inv_sysfs_read((char*)names->temperature, sizeof(str), str);
if (count < 0)
return count;
count = sscanf(str, "%hd%lld", &data[0], timestamp);
if (count < 2)
return -EAGAIN;
return count;
}
/**
* inv_read_fifo_rate() - Read fifo rate.
* @names: Names of sysfs files.
* @data: Fifo rate.
* Returns number of bytes written or a negative error code.
*/
int inv_read_fifo_rate(const struct inv_sysfs_names_s *names, short *data)
{
char str[8];
int count;
count = inv_sysfs_read((char*)names->fifo_rate, sizeof(str), str);
if (count < 0)
return count;
count = sscanf(str, "%hd", data);
if (count < 1)
return -EAGAIN;
return count;
}
/**
* inv_read_power_state() - Read power state.
* @names: Names of sysfs files.
* @data: 1 if device is on.
* Returns number of bytes written or a negative error code.
*/
int inv_read_power_state(const struct inv_sysfs_names_s *names, char *data)
{
char str[2];
int count;
count = inv_sysfs_read((char*)names->power_state, sizeof(str), str);
if (count < 0)
return count;
count = sscanf(str, "%hd", (short*)data);
if (count < 1)
return -EAGAIN;
return count;
}
/**
* inv_read_scale() - Read scale.
* @names: Names of sysfs files.
* @data: 1 if device is on.
* Returns number of bytes written or a negative error code.
*/
int inv_read_scale(const struct inv_sysfs_names_s *names, float *data)
{
char str[5];
int count;
count = inv_sysfs_read((char*)names->scale, sizeof(str), str);
if (count < 0)
return count;
count = sscanf(str, "%f", data);
if (count < 1)
return -EAGAIN;
return count;
}
/**
* inv_read_temp_scale() - Read temperature scale.
* @names: Names of sysfs files.
* @data: 1 if device is on.
* Returns number of bytes written or a negative error code.
*/
int inv_read_temp_scale(const struct inv_sysfs_names_s *names, short *data)
{
char str[4];
int count;
count = inv_sysfs_read((char*)names->temp_scale, sizeof(str), str);
if (count < 0)
return count;
count = sscanf(str, "%hd", data);
if (count < 1)
return -EAGAIN;
return count;
}
/**
* inv_read_temp_offset() - Read temperature offset.
* @names: Names of sysfs files.
* @data: 1 if device is on.
* Returns number of bytes written or a negative error code.
*/
int inv_read_temp_offset(const struct inv_sysfs_names_s *names, short *data)
{
char str[4];
int count;
count = inv_sysfs_read((char*)names->temp_offset, sizeof(str), str);
if (count < 0)
return count;
count = sscanf(str, "%hd", data);
if (count < 1)
return -EAGAIN;
return count;
}
/**
* inv_read_q16() - Get data as q16 fixed point.
* @names: Names of sysfs files.
* @data: 1 if device is on.
* @timestamp: Time when data was read from device.
* Returns number of bytes written or a negative error code.
*/
int inv_read_q16(const struct inv_sysfs_names_s *names, long *data,
long long *timestamp)
{
int count;
short raw[3];
float scale;
count = inv_read_raw(names, (long*)raw, timestamp);
count += inv_read_scale(names, &scale);
data[0] = (long)(raw[0] * (65536.f / scale));
data[1] = (long)(raw[1] * (65536.f / scale));
data[2] = (long)(raw[2] * (65536.f / scale));
return count;
}
/**
* inv_read_q16() - Get temperature data as q16 fixed point.
* @names: Names of sysfs files.
* @data: 1 if device is on.
* @timestamp: Time when data was read from device.
* Returns number of bytes read or a negative error code.
*/
int inv_read_temp_q16(const struct inv_sysfs_names_s *names, long *data,
long long *timestamp)
{
int count = 0;
short raw;
static short scale, offset;
static unsigned char first_read = 1;
if (first_read) {
count += inv_read_temp_scale(names, &scale);
count += inv_read_temp_offset(names, &offset);
first_read = 0;
}
count += inv_read_temperature_raw(names, &raw, timestamp);
data[0] = (long)((35 + ((float)(raw - offset) / scale)) * 65536.f);
return count;
}
/**
* inv_write_fifo_rate() - Write fifo rate.
* @names: Names of sysfs files.
* @data: Fifo rate.
* Returns number of bytes written or a negative error code.
*/
int inv_write_fifo_rate(const struct inv_sysfs_names_s *names, short data)
{
return inv_sysfs_write((char*)names->fifo_rate, (long)data);
}
/**
* inv_write_buffer_enable() - Enable/disable buffer in /dev.
* @names: Names of sysfs files.
* @data: Fifo rate.
* Returns number of bytes written or a negative error code.
*/
int inv_write_buffer_enable(const struct inv_sysfs_names_s *names, char data)
{
return inv_sysfs_write((char*)names->enable, (long)data);
}
/**
* inv_write_power_state() - Turn device on/off.
* @names: Names of sysfs files.
* @data: 1 to turn on.
* Returns number of bytes written or a negative error code.
*/
int inv_write_power_state(const struct inv_sysfs_names_s *names, char data)
{
return inv_sysfs_write((char*)names->power_state, (long)data);
}