2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2009-08-18 21:06:32 +04:00
/* IIO - useful set of util functionality
*
* Copyright ( c ) 2008 Jonathan Cameron
*/
2010-05-04 17:43:13 +04:00
# include <string.h>
# include <stdlib.h>
2010-10-08 15:14:14 +04:00
# include <stdio.h>
# include <stdint.h>
2011-10-26 20:27:44 +04:00
# include <dirent.h>
2012-06-26 01:12:17 +04:00
# include <errno.h>
2015-02-26 11:49:24 +03:00
# include <ctype.h>
# include "iio_utils.h"
2009-08-18 21:06:32 +04:00
2010-05-04 17:43:13 +04:00
const char * iio_dir = " /sys/bus/iio/devices/ " ;
2015-03-27 14:53:00 +03:00
static char * const iio_direction [ ] = {
" in " ,
" out " ,
} ;
2010-10-08 15:14:14 +04:00
/**
* iioutils_break_up_name ( ) - extract generic name from full channel name
* @ full_name : the full channel name
* @ generic_name : the output generic channel name
2015-05-31 15:40:16 +03:00
*
* Returns 0 on success , or a negative error code if string extraction failed .
2010-10-08 15:14:14 +04:00
* */
2015-06-10 22:51:20 +03:00
int iioutils_break_up_name ( const char * full_name , char * * generic_name )
2010-10-08 15:14:14 +04:00
{
char * current ;
char * w , * r ;
2015-03-27 14:53:00 +03:00
char * working , * prefix = " " ;
2015-05-31 15:40:02 +03:00
int i , ret ;
2015-03-27 14:53:00 +03:00
2015-07-13 16:20:11 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( iio_direction ) ; i + + )
2015-03-27 14:53:00 +03:00
if ( ! strncmp ( full_name , iio_direction [ i ] ,
strlen ( iio_direction [ i ] ) ) ) {
prefix = iio_direction [ i ] ;
break ;
}
2014-10-04 00:35:54 +04:00
2015-03-27 14:53:00 +03:00
current = strdup ( full_name + strlen ( prefix ) + 1 ) ;
2015-05-31 15:40:02 +03:00
if ( ! current )
return - ENOMEM ;
2010-10-08 15:14:14 +04:00
working = strtok ( current , " _ \0 " ) ;
2015-05-31 15:40:14 +03:00
if ( ! working ) {
free ( current ) ;
return - EINVAL ;
}
2015-03-27 14:53:00 +03:00
2010-10-08 15:14:14 +04:00
w = working ;
r = working ;
2011-03-08 10:55:48 +03:00
while ( * r ! = ' \0 ' ) {
2010-10-08 15:14:14 +04:00
if ( ! isdigit ( * r ) ) {
* w = * r ;
w + + ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
r + + ;
}
* w = ' \0 ' ;
2015-05-31 15:40:02 +03:00
ret = asprintf ( generic_name , " %s_%s " , prefix , working ) ;
2010-10-08 15:14:14 +04:00
free ( current ) ;
2015-05-31 15:40:02 +03:00
return ( ret = = - 1 ) ? - ENOMEM : 0 ;
2010-10-08 15:14:14 +04:00
}
/**
* iioutils_get_type ( ) - find and process _type attribute data
* @ is_signed : output whether channel is signed
* @ bytes : output how many bytes the channel storage occupies
2015-05-31 15:40:16 +03:00
* @ bits_used : output number of valid bits of data
* @ shift : output amount of bits to shift right data before applying bit mask
2010-10-08 15:14:14 +04:00
* @ mask : output a bit mask for the raw data
2015-05-31 15:40:16 +03:00
* @ be : output if data in big endian
* @ device_dir : the IIO device directory
2010-10-08 15:14:14 +04:00
* @ name : the channel name
* @ generic_name : the channel type name
2015-05-31 15:40:16 +03:00
*
* Returns a value > = 0 on success , otherwise a negative error code .
2010-10-08 15:14:14 +04:00
* */
2015-06-10 22:51:20 +03:00
int iioutils_get_type ( unsigned * is_signed , unsigned * bytes , unsigned * bits_used ,
unsigned * shift , uint64_t * mask , unsigned * be ,
const char * device_dir , const char * name ,
const char * generic_name )
2010-10-08 15:14:14 +04:00
{
FILE * sysfsfp ;
int ret ;
DIR * dp ;
char * scan_el_dir , * builtname , * builtname_generic , * filename = 0 ;
2011-12-04 23:10:59 +04:00
char signchar , endianchar ;
2011-02-24 18:34:54 +03:00
unsigned padint ;
2010-10-08 15:14:14 +04:00
const struct dirent * ent ;
ret = asprintf ( & scan_el_dir , FORMAT_SCAN_ELEMENTS_DIR , device_dir ) ;
2015-05-31 15:40:17 +03:00
if ( ret < 0 )
return - ENOMEM ;
2010-10-08 15:14:14 +04:00
ret = asprintf ( & builtname , FORMAT_TYPE_FILE , name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
goto error_free_scan_el_dir ;
}
ret = asprintf ( & builtname_generic , FORMAT_TYPE_FILE , generic_name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
goto error_free_builtname ;
}
dp = opendir ( scan_el_dir ) ;
2015-07-13 16:15:56 +03:00
if ( ! dp ) {
2010-10-08 15:14:14 +04:00
ret = - errno ;
goto error_free_builtname_generic ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = - ENOENT ;
2015-07-13 16:15:56 +03:00
while ( ent = readdir ( dp ) , ent )
2010-10-08 15:14:14 +04:00
if ( ( strcmp ( builtname , ent - > d_name ) = = 0 ) | |
( strcmp ( builtname_generic , ent - > d_name ) = = 0 ) ) {
ret = asprintf ( & filename ,
" %s/%s " , scan_el_dir , ent - > d_name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
goto error_closedir ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
sysfsfp = fopen ( filename , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-10-08 15:14:14 +04:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " failed to open %s \n " ,
filename ) ;
2010-10-08 15:14:14 +04:00
goto error_free_filename ;
}
2011-12-04 23:10:58 +04:00
ret = fscanf ( sysfsfp ,
" %ce:%c%u/%u>>%u " ,
& endianchar ,
& signchar ,
bits_used ,
& padint , shift ) ;
if ( ret < 0 ) {
2012-06-26 01:13:24 +04:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr ,
" failed to pass scan type description \n " ) ;
2012-06-26 01:13:24 +04:00
goto error_close_sysfsfp ;
2015-05-31 15:39:59 +03:00
} else if ( ret ! = 5 ) {
ret = - EIO ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr ,
" scan type description didn't match \n " ) ;
2015-05-31 15:39:59 +03:00
goto error_close_sysfsfp ;
2011-12-04 23:10:58 +04:00
}
2015-06-10 22:51:20 +03:00
2011-12-04 23:10:59 +04:00
* be = ( endianchar = = ' b ' ) ;
2010-10-08 15:14:14 +04:00
* bytes = padint / 8 ;
2011-02-24 18:34:54 +03:00
if ( * bits_used = = 64 )
2019-06-27 10:20:45 +03:00
* mask = ~ ( 0ULL ) ;
2010-10-08 15:14:14 +04:00
else
2019-06-27 10:20:45 +03:00
* mask = ( 1ULL < < * bits_used ) - 1ULL ;
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:19 +03:00
* is_signed = ( signchar = = ' s ' ) ;
2015-05-31 15:40:14 +03:00
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Failed to close %s \n " ,
filename ) ;
2015-05-31 15:40:14 +03:00
goto error_free_filename ;
}
2015-05-31 15:40:20 +03:00
sysfsfp = 0 ;
2011-12-04 23:10:58 +04:00
free ( filename ) ;
filename = 0 ;
2016-08-23 01:19:37 +03:00
/*
* Avoid having a more generic entry overwriting
* the settings .
*/
if ( strcmp ( builtname , ent - > d_name ) = = 0 )
break ;
2010-10-08 15:14:14 +04:00
}
2015-06-10 22:51:20 +03:00
2012-06-26 01:13:24 +04:00
error_close_sysfsfp :
if ( sysfsfp )
2015-05-31 15:40:14 +03:00
if ( fclose ( sysfsfp ) )
perror ( " iioutils_get_type(): Failed to close file " ) ;
2010-10-08 15:14:14 +04:00
error_free_filename :
if ( filename )
free ( filename ) ;
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
error_closedir :
2015-05-31 15:40:14 +03:00
if ( closedir ( dp ) = = - 1 )
perror ( " iioutils_get_type(): Failed to close directory " ) ;
2010-10-08 15:14:14 +04:00
error_free_builtname_generic :
free ( builtname_generic ) ;
error_free_builtname :
free ( builtname ) ;
error_free_scan_el_dir :
free ( scan_el_dir ) ;
2015-05-31 15:40:17 +03:00
2010-10-08 15:14:14 +04:00
return ret ;
}
2015-05-31 15:40:16 +03:00
/**
* iioutils_get_param_float ( ) - read a float value from a channel parameter
* @ output : output the float value
* @ param_name : the parameter name to read
* @ device_dir : the IIO device directory in sysfs
* @ name : the channel name
* @ generic_name : the channel type name
*
* Returns a value > = 0 on success , otherwise a negative error code .
* */
2015-06-10 22:51:20 +03:00
int iioutils_get_param_float ( float * output , const char * param_name ,
const char * device_dir , const char * name ,
const char * generic_name )
2010-10-08 15:14:14 +04:00
{
FILE * sysfsfp ;
int ret ;
DIR * dp ;
char * builtname , * builtname_generic ;
char * filename = NULL ;
const struct dirent * ent ;
ret = asprintf ( & builtname , " %s_%s " , name , param_name ) ;
2015-05-31 15:40:17 +03:00
if ( ret < 0 )
return - ENOMEM ;
2010-10-08 15:14:14 +04:00
ret = asprintf ( & builtname_generic ,
" %s_%s " , generic_name , param_name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
goto error_free_builtname ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
dp = opendir ( device_dir ) ;
2015-07-13 16:15:56 +03:00
if ( ! dp ) {
2010-10-08 15:14:14 +04:00
ret = - errno ;
goto error_free_builtname_generic ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = - ENOENT ;
2015-07-13 16:15:56 +03:00
while ( ent = readdir ( dp ) , ent )
2010-10-08 15:14:14 +04:00
if ( ( strcmp ( builtname , ent - > d_name ) = = 0 ) | |
( strcmp ( builtname_generic , ent - > d_name ) = = 0 ) ) {
ret = asprintf ( & filename ,
" %s/%s " , device_dir , ent - > d_name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
goto error_closedir ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
sysfsfp = fopen ( filename , " r " ) ;
if ( ! sysfsfp ) {
ret = - errno ;
goto error_free_filename ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
errno = 0 ;
if ( fscanf ( sysfsfp , " %f " , output ) ! = 1 )
ret = errno ? - errno : - ENODATA ;
2010-10-08 15:14:14 +04:00
break ;
}
error_free_filename :
if ( filename )
free ( filename ) ;
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
error_closedir :
2015-05-31 15:40:14 +03:00
if ( closedir ( dp ) = = - 1 )
perror ( " iioutils_get_param_float(): Failed to close directory " ) ;
2010-10-08 15:14:14 +04:00
error_free_builtname_generic :
free ( builtname_generic ) ;
error_free_builtname :
free ( builtname ) ;
2015-05-31 15:40:17 +03:00
2010-10-08 15:14:14 +04:00
return ret ;
}
2011-03-08 10:55:48 +03:00
/**
2015-05-31 15:40:16 +03:00
* bsort_channel_array_by_index ( ) - sort the array in index order
* @ ci_array : the iio_channel_info array to be sorted
* @ cnt : the amount of array elements
2011-03-08 10:55:48 +03:00
* */
2015-07-24 18:23:29 +03:00
void bsort_channel_array_by_index ( struct iio_channel_info * ci_array , int cnt )
2011-03-08 10:55:48 +03:00
{
struct iio_channel_info temp ;
int x , y ;
for ( x = 0 ; x < cnt ; x + + )
for ( y = 0 ; y < ( cnt - 1 ) ; y + + )
2015-07-24 18:23:29 +03:00
if ( ci_array [ y ] . index > ci_array [ y + 1 ] . index ) {
temp = ci_array [ y + 1 ] ;
ci_array [ y + 1 ] = ci_array [ y ] ;
ci_array [ y ] = temp ;
2011-03-08 10:55:48 +03:00
}
}
2010-10-08 15:14:14 +04:00
/**
* build_channel_array ( ) - function to figure out what channels are present
* @ device_dir : the IIO device directory in sysfs
2015-05-31 15:40:16 +03:00
* @ ci_array : output the resulting array of iio_channel_info
* @ counter : output the amount of array elements
*
* Returns 0 on success , otherwise a negative error code .
2010-10-08 15:14:14 +04:00
* */
2015-02-26 11:49:24 +03:00
int build_channel_array ( const char * device_dir ,
2015-06-10 22:51:20 +03:00
struct iio_channel_info * * ci_array , int * counter )
2010-10-08 15:14:14 +04:00
{
DIR * dp ;
FILE * sysfsfp ;
2015-05-31 15:40:21 +03:00
int count = 0 , i ;
2010-10-08 15:14:14 +04:00
struct iio_channel_info * current ;
int ret ;
const struct dirent * ent ;
char * scan_el_dir ;
char * filename ;
* counter = 0 ;
ret = asprintf ( & scan_el_dir , FORMAT_SCAN_ELEMENTS_DIR , device_dir ) ;
2015-05-31 15:40:17 +03:00
if ( ret < 0 )
return - ENOMEM ;
2010-10-08 15:14:14 +04:00
dp = opendir ( scan_el_dir ) ;
2015-07-13 16:15:56 +03:00
if ( ! dp ) {
2010-10-08 15:14:14 +04:00
ret = - errno ;
goto error_free_name ;
}
2015-06-10 22:51:20 +03:00
2015-07-13 16:15:56 +03:00
while ( ent = readdir ( dp ) , ent )
2010-10-08 15:14:14 +04:00
if ( strcmp ( ent - > d_name + strlen ( ent - > d_name ) - strlen ( " _en " ) ,
" _en " ) = = 0 ) {
ret = asprintf ( & filename ,
" %s/%s " , scan_el_dir , ent - > d_name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
goto error_close_dir ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
sysfsfp = fopen ( filename , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-10-08 15:14:14 +04:00
ret = - errno ;
free ( filename ) ;
goto error_close_dir ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
errno = 0 ;
if ( fscanf ( sysfsfp , " %i " , & ret ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " build_channel_array(): Failed to close file " ) ;
free ( filename ) ;
goto error_close_dir ;
}
2010-10-08 15:14:14 +04:00
if ( ret = = 1 )
( * counter ) + + ;
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
free ( filename ) ;
goto error_close_dir ;
}
2010-10-08 15:14:14 +04:00
free ( filename ) ;
}
2015-06-10 22:51:20 +03:00
2011-03-08 10:55:48 +03:00
* ci_array = malloc ( sizeof ( * * ci_array ) * ( * counter ) ) ;
2015-07-13 16:15:56 +03:00
if ( ! * ci_array ) {
2010-10-08 15:14:14 +04:00
ret = - ENOMEM ;
goto error_close_dir ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
seekdir ( dp , 0 ) ;
2015-07-13 16:15:56 +03:00
while ( ent = readdir ( dp ) , ent ) {
2010-10-08 15:14:14 +04:00
if ( strcmp ( ent - > d_name + strlen ( ent - > d_name ) - strlen ( " _en " ) ,
" _en " ) = = 0 ) {
2014-01-01 19:38:52 +04:00
int current_enabled = 0 ;
2014-10-04 00:35:54 +04:00
2010-10-08 15:14:14 +04:00
current = & ( * ci_array ) [ count + + ] ;
ret = asprintf ( & filename ,
" %s/%s " , scan_el_dir , ent - > d_name ) ;
if ( ret < 0 ) {
ret = - ENOMEM ;
/* decrement count to avoid freeing name */
count - - ;
goto error_cleanup_array ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
sysfsfp = fopen ( filename , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-10-08 15:14:14 +04:00
ret = - errno ;
2015-05-31 15:39:48 +03:00
free ( filename ) ;
2015-05-31 15:39:45 +03:00
count - - ;
2010-10-08 15:14:14 +04:00
goto error_cleanup_array ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
errno = 0 ;
if ( fscanf ( sysfsfp , " %i " , & current_enabled ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
free ( filename ) ;
count - - ;
goto error_cleanup_array ;
}
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
free ( filename ) ;
count - - ;
goto error_cleanup_array ;
}
2011-03-08 10:55:48 +03:00
2014-01-01 19:38:52 +04:00
if ( ! current_enabled ) {
2011-03-08 10:55:48 +03:00
free ( filename ) ;
count - - ;
continue ;
}
2010-10-08 15:14:14 +04:00
current - > scale = 1.0 ;
current - > offset = 0 ;
current - > name = strndup ( ent - > d_name ,
strlen ( ent - > d_name ) -
strlen ( " _en " ) ) ;
2015-07-13 16:15:56 +03:00
if ( ! current - > name ) {
2010-10-08 15:14:14 +04:00
free ( filename ) ;
ret = - ENOMEM ;
2015-05-31 15:39:45 +03:00
count - - ;
2010-10-08 15:14:14 +04:00
goto error_cleanup_array ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
/* Get the generic and specific name elements */
ret = iioutils_break_up_name ( current - > name ,
& current - > generic_name ) ;
if ( ret ) {
free ( filename ) ;
2015-05-31 15:39:45 +03:00
free ( current - > name ) ;
count - - ;
2010-10-08 15:14:14 +04:00
goto error_cleanup_array ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
ret = asprintf ( & filename ,
" %s/%s_index " ,
scan_el_dir ,
current - > name ) ;
if ( ret < 0 ) {
free ( filename ) ;
ret = - ENOMEM ;
goto error_cleanup_array ;
}
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
sysfsfp = fopen ( filename , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2015-05-31 15:40:14 +03:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " failed to open %s \n " ,
filename ) ;
2015-05-31 15:40:14 +03:00
free ( filename ) ;
goto error_cleanup_array ;
}
errno = 0 ;
if ( fscanf ( sysfsfp , " %u " , & current - > index ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " build_channel_array(): Failed to close file " ) ;
free ( filename ) ;
goto error_cleanup_array ;
}
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
free ( filename ) ;
goto error_cleanup_array ;
}
2010-10-08 15:14:14 +04:00
free ( filename ) ;
/* Find the scale */
ret = iioutils_get_param_float ( & current - > scale ,
" scale " ,
device_dir ,
current - > name ,
current - > generic_name ) ;
2015-07-23 05:53:47 +03:00
if ( ( ret < 0 ) & & ( ret ! = - ENOENT ) )
2010-10-08 15:14:14 +04:00
goto error_cleanup_array ;
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
ret = iioutils_get_param_float ( & current - > offset ,
" offset " ,
device_dir ,
current - > name ,
current - > generic_name ) ;
2015-07-23 05:53:47 +03:00
if ( ( ret < 0 ) & & ( ret ! = - ENOENT ) )
2010-10-08 15:14:14 +04:00
goto error_cleanup_array ;
2015-06-10 22:51:20 +03:00
2010-10-08 15:14:14 +04:00
ret = iioutils_get_type ( & current - > is_signed ,
& current - > bytes ,
& current - > bits_used ,
2011-05-18 17:41:19 +04:00
& current - > shift ,
2010-10-08 15:14:14 +04:00
& current - > mask ,
2011-12-04 23:10:59 +04:00
& current - > be ,
2010-10-08 15:14:14 +04:00
device_dir ,
current - > name ,
current - > generic_name ) ;
2015-05-31 15:40:14 +03:00
if ( ret < 0 )
goto error_cleanup_array ;
2010-10-08 15:14:14 +04:00
}
}
2011-03-08 10:55:48 +03:00
2015-05-31 15:40:14 +03:00
if ( closedir ( dp ) = = - 1 ) {
ret = - errno ;
goto error_cleanup_array ;
}
2015-05-31 15:39:43 +03:00
free ( scan_el_dir ) ;
2011-03-08 10:55:48 +03:00
/* reorder so that the array is in index order */
2015-07-24 18:23:29 +03:00
bsort_channel_array_by_index ( * ci_array , * counter ) ;
2010-10-08 15:14:14 +04:00
return 0 ;
error_cleanup_array :
2015-05-31 15:39:44 +03:00
for ( i = count - 1 ; i > = 0 ; i - - ) {
2010-10-08 15:14:14 +04:00
free ( ( * ci_array ) [ i ] . name ) ;
2015-05-31 15:39:44 +03:00
free ( ( * ci_array ) [ i ] . generic_name ) ;
}
2010-10-08 15:14:14 +04:00
free ( * ci_array ) ;
2015-07-24 18:23:28 +03:00
* ci_array = NULL ;
* counter = 0 ;
2010-10-08 15:14:14 +04:00
error_close_dir :
2015-05-31 15:40:14 +03:00
if ( dp )
if ( closedir ( dp ) = = - 1 )
perror ( " build_channel_array(): Failed to close dir " ) ;
2010-10-08 15:14:14 +04:00
error_free_name :
free ( scan_el_dir ) ;
2015-05-31 15:40:17 +03:00
2010-10-08 15:14:14 +04:00
return ret ;
}
2015-07-28 04:46:13 +03:00
static int calc_digits ( int num )
2015-05-31 15:40:00 +03:00
{
int count = 0 ;
while ( num ! = 0 ) {
num / = 10 ;
count + + ;
}
return count ;
}
2010-05-04 17:43:13 +04:00
/**
* find_type_by_name ( ) - function to match top level types by name
* @ name : top level type instance name
2015-05-31 15:40:16 +03:00
* @ type : the type of top level instance being searched
2010-05-04 17:43:13 +04:00
*
2015-05-31 15:40:16 +03:00
* Returns the device number of a matched IIO device on success , otherwise a
* negative error code .
2010-05-04 17:43:13 +04:00
* Typical types this is used for are device and trigger .
* */
2015-02-26 11:49:24 +03:00
int find_type_by_name ( const char * name , const char * type )
2009-08-18 21:06:32 +04:00
{
const struct dirent * ent ;
2015-05-31 15:40:00 +03:00
int number , numstrlen , ret ;
2009-08-18 21:06:32 +04:00
2015-06-10 22:51:21 +03:00
FILE * namefp ;
2009-08-18 21:06:32 +04:00
DIR * dp ;
2010-05-04 17:43:13 +04:00
char thisname [ IIO_MAX_NAME_LENGTH ] ;
char * filename ;
2009-08-18 21:06:32 +04:00
dp = opendir ( iio_dir ) ;
2015-07-13 16:15:56 +03:00
if ( ! dp ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " No industrialio devices available \n " ) ;
2010-05-04 17:43:13 +04:00
return - ENODEV ;
2009-08-18 21:06:32 +04:00
}
2010-05-04 17:43:13 +04:00
2015-07-13 16:15:56 +03:00
while ( ent = readdir ( dp ) , ent ) {
2009-08-18 21:06:32 +04:00
if ( strcmp ( ent - > d_name , " . " ) ! = 0 & &
2015-06-10 22:51:20 +03:00
strcmp ( ent - > d_name , " .. " ) ! = 0 & &
strlen ( ent - > d_name ) > strlen ( type ) & &
strncmp ( ent - > d_name , type , strlen ( type ) ) = = 0 ) {
2015-05-31 15:40:00 +03:00
errno = 0 ;
ret = sscanf ( ent - > d_name + strlen ( type ) , " %d " , & number ) ;
if ( ret < 0 ) {
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr ,
" failed to read element number \n " ) ;
2015-05-31 15:40:00 +03:00
goto error_close_dir ;
} else if ( ret ! = 1 ) {
ret = - EIO ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr ,
" failed to match element number \n " ) ;
2015-05-31 15:40:00 +03:00
goto error_close_dir ;
}
numstrlen = calc_digits ( number ) ;
2010-05-04 17:43:13 +04:00
/* verify the next character is not a colon */
if ( strncmp ( ent - > d_name + strlen ( type ) + numstrlen ,
2015-06-10 22:51:20 +03:00
" : " , 1 ) ! = 0 ) {
filename = malloc ( strlen ( iio_dir ) + strlen ( type )
+ numstrlen + 6 ) ;
2015-07-13 16:15:56 +03:00
if ( ! filename ) {
2015-05-31 15:40:14 +03:00
ret = - ENOMEM ;
goto error_close_dir ;
}
ret = sprintf ( filename , " %s%s%d/name " , iio_dir ,
type , number ) ;
if ( ret < 0 ) {
free ( filename ) ;
goto error_close_dir ;
2012-06-26 01:13:25 +04:00
}
2015-05-31 15:40:14 +03:00
2015-06-10 22:51:21 +03:00
namefp = fopen ( filename , " r " ) ;
if ( ! namefp ) {
2012-06-26 01:13:25 +04:00
free ( filename ) ;
2010-05-04 17:43:13 +04:00
continue ;
2012-06-26 01:13:25 +04:00
}
2015-06-10 22:51:20 +03:00
2010-05-04 17:43:13 +04:00
free ( filename ) ;
2015-05-31 15:40:14 +03:00
errno = 0 ;
2015-06-10 22:51:21 +03:00
if ( fscanf ( namefp , " %s " , thisname ) ! = 1 ) {
2015-05-31 15:40:14 +03:00
ret = errno ? - errno : - ENODATA ;
goto error_close_dir ;
}
2015-06-10 22:51:21 +03:00
if ( fclose ( namefp ) ) {
2015-05-31 15:40:14 +03:00
ret = - errno ;
goto error_close_dir ;
}
2012-06-26 01:13:25 +04:00
if ( strcmp ( name , thisname ) = = 0 ) {
2015-05-31 15:40:14 +03:00
if ( closedir ( dp ) = = - 1 )
return - errno ;
2015-06-10 22:51:20 +03:00
2012-06-26 01:13:25 +04:00
return number ;
}
2009-08-18 21:06:32 +04:00
}
}
}
2015-05-31 15:40:14 +03:00
if ( closedir ( dp ) = = - 1 )
return - errno ;
2010-05-04 17:43:13 +04:00
return - ENODEV ;
2015-05-31 15:40:00 +03:00
error_close_dir :
if ( closedir ( dp ) = = - 1 )
perror ( " find_type_by_name(): Failed to close directory " ) ;
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:00 +03:00
return ret ;
2009-08-18 21:06:32 +04:00
}
2015-05-31 15:40:36 +03:00
static int _write_sysfs_int ( const char * filename , const char * basedir , int val ,
int verify )
2009-08-18 21:06:32 +04:00
{
2013-10-07 16:42:00 +04:00
int ret = 0 ;
2010-05-04 17:43:13 +04:00
FILE * sysfsfp ;
int test ;
char * temp = malloc ( strlen ( basedir ) + strlen ( filename ) + 2 ) ;
2014-10-04 00:35:54 +04:00
2015-07-13 16:15:56 +03:00
if ( ! temp )
2010-05-04 17:43:13 +04:00
return - ENOMEM ;
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = sprintf ( temp , " %s/%s " , basedir , filename ) ;
if ( ret < 0 )
goto error_free ;
2009-08-18 21:06:32 +04:00
sysfsfp = fopen ( temp , " w " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-05-04 17:43:13 +04:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " failed to open %s \n " , temp ) ;
2010-05-04 17:43:13 +04:00
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = fprintf ( sysfsfp , " %d " , val ) ;
if ( ret < 0 ) {
if ( fclose ( sysfsfp ) )
perror ( " _write_sysfs_int(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
goto error_free ;
}
2010-05-04 17:43:13 +04:00
if ( verify ) {
sysfsfp = fopen ( temp , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-05-04 17:43:13 +04:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " failed to open %s \n " , temp ) ;
2010-05-04 17:43:13 +04:00
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
if ( fscanf ( sysfsfp , " %d " , & test ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " _write_sysfs_int(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
goto error_free ;
}
2010-05-04 17:43:13 +04:00
if ( test ! = val ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr ,
" Possible failure in int write %d to %s/%s \n " ,
val , basedir , filename ) ;
2010-05-04 17:43:13 +04:00
ret = - 1 ;
}
}
2015-06-10 22:51:20 +03:00
2010-05-04 17:43:13 +04:00
error_free :
free ( temp ) ;
return ret ;
}
2015-05-31 15:40:16 +03:00
/**
* write_sysfs_int ( ) - write an integer value to a sysfs file
* @ filename : name of the file to write to
* @ basedir : the sysfs directory in which the file is to be found
* @ val : integer value to write to file
*
* Returns a value > = 0 on success , otherwise a negative error code .
* */
2015-05-31 15:40:36 +03:00
int write_sysfs_int ( const char * filename , const char * basedir , int val )
2010-05-04 17:43:13 +04:00
{
return _write_sysfs_int ( filename , basedir , val , 0 ) ;
2009-08-18 21:06:32 +04:00
}
2015-05-31 15:40:16 +03:00
/**
* write_sysfs_int_and_verify ( ) - write an integer value to a sysfs file
* and verify
* @ filename : name of the file to write to
* @ basedir : the sysfs directory in which the file is to be found
* @ val : integer value to write to file
*
* Returns a value > = 0 on success , otherwise a negative error code .
* */
2015-05-31 15:40:36 +03:00
int write_sysfs_int_and_verify ( const char * filename , const char * basedir ,
int val )
2010-05-04 17:43:13 +04:00
{
return _write_sysfs_int ( filename , basedir , val , 1 ) ;
}
2015-05-31 15:40:36 +03:00
static int _write_sysfs_string ( const char * filename , const char * basedir ,
const char * val , int verify )
2010-05-04 17:43:04 +04:00
{
2010-10-08 15:14:14 +04:00
int ret = 0 ;
2010-05-04 17:43:04 +04:00
FILE * sysfsfp ;
2010-05-04 17:43:13 +04:00
char * temp = malloc ( strlen ( basedir ) + strlen ( filename ) + 2 ) ;
2014-10-04 00:35:54 +04:00
2015-07-13 16:15:56 +03:00
if ( ! temp ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Memory allocation failed \n " ) ;
2010-05-04 17:43:13 +04:00
return - ENOMEM ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = sprintf ( temp , " %s/%s " , basedir , filename ) ;
if ( ret < 0 )
goto error_free ;
2010-05-04 17:43:04 +04:00
sysfsfp = fopen ( temp , " w " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-05-04 17:43:13 +04:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Could not open %s \n " , temp ) ;
2010-05-04 17:43:13 +04:00
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = fprintf ( sysfsfp , " %s " , val ) ;
if ( ret < 0 ) {
if ( fclose ( sysfsfp ) )
perror ( " _write_sysfs_string(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
goto error_free ;
}
2010-05-04 17:43:13 +04:00
if ( verify ) {
sysfsfp = fopen ( temp , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-05-04 17:43:13 +04:00
ret = - errno ;
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Could not open file to verify \n " ) ;
2010-05-04 17:43:13 +04:00
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
if ( fscanf ( sysfsfp , " %s " , temp ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " _write_sysfs_string(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) ) {
ret = - errno ;
goto error_free ;
}
2010-05-04 17:43:13 +04:00
if ( strcmp ( temp , val ) ! = 0 ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr ,
" Possible failure in string write of %s "
" Should be %s written to %s/%s \n " , temp , val ,
basedir , filename ) ;
2010-05-04 17:43:13 +04:00
ret = - 1 ;
}
2010-05-04 17:43:04 +04:00
}
2015-06-10 22:51:20 +03:00
2010-05-04 17:43:13 +04:00
error_free :
free ( temp ) ;
2010-05-04 17:43:04 +04:00
2010-05-04 17:43:13 +04:00
return ret ;
2010-05-04 17:43:04 +04:00
}
2010-10-08 15:14:14 +04:00
2009-08-18 21:06:32 +04:00
/**
* write_sysfs_string_and_verify ( ) - string write , readback and verify
* @ filename : name of file to write to
* @ basedir : the sysfs directory in which the file is to be found
* @ val : the string to write
2015-05-31 15:40:16 +03:00
*
* Returns a value > = 0 on success , otherwise a negative error code .
2009-08-18 21:06:32 +04:00
* */
2015-05-31 15:40:36 +03:00
int write_sysfs_string_and_verify ( const char * filename , const char * basedir ,
const char * val )
2009-08-18 21:06:32 +04:00
{
2010-05-04 17:43:13 +04:00
return _write_sysfs_string ( filename , basedir , val , 1 ) ;
}
2009-08-18 21:06:32 +04:00
2015-05-31 15:40:16 +03:00
/**
* write_sysfs_string ( ) - write string to a sysfs file
* @ filename : name of file to write to
* @ basedir : the sysfs directory in which the file is to be found
* @ val : the string to write
*
* Returns a value > = 0 on success , otherwise a negative error code .
* */
2015-05-31 15:40:36 +03:00
int write_sysfs_string ( const char * filename , const char * basedir ,
const char * val )
2010-05-04 17:43:13 +04:00
{
return _write_sysfs_string ( filename , basedir , val , 0 ) ;
2009-08-18 21:06:32 +04:00
}
2015-05-31 15:40:16 +03:00
/**
* read_sysfs_posint ( ) - read an integer value from file
* @ filename : name of file to read from
* @ basedir : the sysfs directory in which the file is to be found
*
* Returns the read integer value > = 0 on success , otherwise a negative error
* code .
* */
2015-05-31 15:40:36 +03:00
int read_sysfs_posint ( const char * filename , const char * basedir )
2009-08-18 21:06:32 +04:00
{
int ret ;
FILE * sysfsfp ;
2010-05-04 17:43:13 +04:00
char * temp = malloc ( strlen ( basedir ) + strlen ( filename ) + 2 ) ;
2014-10-04 00:35:54 +04:00
2015-07-13 16:15:56 +03:00
if ( ! temp ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Memory allocation failed " ) ;
2010-05-04 17:43:13 +04:00
return - ENOMEM ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = sprintf ( temp , " %s/%s " , basedir , filename ) ;
if ( ret < 0 )
goto error_free ;
2009-08-18 21:06:32 +04:00
sysfsfp = fopen ( temp , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-05-04 17:43:13 +04:00
ret = - errno ;
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
errno = 0 ;
if ( fscanf ( sysfsfp , " %d \n " , & ret ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " read_sysfs_posint(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) )
ret = - errno ;
2010-05-04 17:43:13 +04:00
error_free :
free ( temp ) ;
2015-06-10 22:51:20 +03:00
2010-05-04 17:43:13 +04:00
return ret ;
}
2015-05-31 15:40:16 +03:00
/**
* read_sysfs_float ( ) - read a float value from file
* @ filename : name of file to read from
* @ basedir : the sysfs directory in which the file is to be found
* @ val : output the read float value
*
* Returns a value > = 0 on success , otherwise a negative error code .
* */
2015-05-31 15:40:36 +03:00
int read_sysfs_float ( const char * filename , const char * basedir , float * val )
2010-05-04 17:43:13 +04:00
{
2014-12-06 09:00:00 +03:00
int ret = 0 ;
2010-05-04 17:43:13 +04:00
FILE * sysfsfp ;
char * temp = malloc ( strlen ( basedir ) + strlen ( filename ) + 2 ) ;
2014-10-04 00:35:54 +04:00
2015-07-13 16:15:56 +03:00
if ( ! temp ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Memory allocation failed " ) ;
2010-05-04 17:43:13 +04:00
return - ENOMEM ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = sprintf ( temp , " %s/%s " , basedir , filename ) ;
if ( ret < 0 )
goto error_free ;
2010-05-04 17:43:13 +04:00
sysfsfp = fopen ( temp , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2010-05-04 17:43:13 +04:00
ret = - errno ;
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
errno = 0 ;
if ( fscanf ( sysfsfp , " %f \n " , val ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " read_sysfs_float(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) )
ret = - errno ;
2010-05-04 17:43:13 +04:00
error_free :
free ( temp ) ;
2015-06-10 22:51:20 +03:00
2009-08-18 21:06:32 +04:00
return ret ;
}
2014-05-02 16:23:00 +04:00
2015-05-31 15:40:16 +03:00
/**
* read_sysfs_string ( ) - read a string from file
* @ filename : name of file to read from
* @ basedir : the sysfs directory in which the file is to be found
* @ str : output the read string
*
* Returns a value > = 0 on success , otherwise a negative error code .
* */
2014-12-06 09:00:00 +03:00
int read_sysfs_string ( const char * filename , const char * basedir , char * str )
2014-05-02 16:23:00 +04:00
{
2014-12-06 09:00:00 +03:00
int ret = 0 ;
2014-05-02 16:23:00 +04:00
FILE * sysfsfp ;
char * temp = malloc ( strlen ( basedir ) + strlen ( filename ) + 2 ) ;
2014-10-04 00:35:54 +04:00
2015-07-13 16:15:56 +03:00
if ( ! temp ) {
2015-07-17 18:43:42 +03:00
fprintf ( stderr , " Memory allocation failed " ) ;
2014-05-02 16:23:00 +04:00
return - ENOMEM ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
ret = sprintf ( temp , " %s/%s " , basedir , filename ) ;
if ( ret < 0 )
goto error_free ;
2014-05-02 16:23:00 +04:00
sysfsfp = fopen ( temp , " r " ) ;
2015-07-13 16:15:56 +03:00
if ( ! sysfsfp ) {
2014-05-02 16:23:00 +04:00
ret = - errno ;
goto error_free ;
}
2015-06-10 22:51:20 +03:00
2015-05-31 15:40:14 +03:00
errno = 0 ;
if ( fscanf ( sysfsfp , " %s \n " , str ) ! = 1 ) {
ret = errno ? - errno : - ENODATA ;
if ( fclose ( sysfsfp ) )
perror ( " read_sysfs_string(): Failed to close dir " ) ;
goto error_free ;
}
if ( fclose ( sysfsfp ) )
ret = - errno ;
2014-05-02 16:23:00 +04:00
error_free :
free ( temp ) ;
2015-06-10 22:51:20 +03:00
2014-05-02 16:23:00 +04:00
return ret ;
}