From e36d2e5b3a8592dd4d9afbf5237c237f58914813 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Wed, 26 Feb 2003 19:19:57 +0000 Subject: [PATCH] finished implementing comedi_set_calibration() (untested) --- include/comedilib.h | 6 +- lib/calib.c | 181 +++++++++++++++++++++++++++++++++++++------- lib/version_script | 3 + 3 files changed, 160 insertions(+), 30 deletions(-) diff --git a/include/comedilib.h b/include/comedilib.h index ff98c70..f63a2eb 100644 --- a/include/comedilib.h +++ b/include/comedilib.h @@ -50,7 +50,7 @@ typedef struct comedi_sv_struct{ /* range policy */ int range; int aref; - + /* number of measurements to average (for ai) */ int n; @@ -153,7 +153,7 @@ int comedi_sv_update(comedi_sv_t *it); int comedi_sv_measure(comedi_sv_t *it,double *data); /* streaming I/O (commands) */ - + int comedi_get_cmd_src_mask(comedi_t *dev,unsigned int subdevice, comedi_cmd *cmd); int comedi_get_cmd_generic_timed(comedi_t *dev,unsigned int subdevice, @@ -193,6 +193,8 @@ int comedi_get_rangetype(comedi_t *it,unsigned int subdevice, compatibility. In practice, this is a holding place for the next library ABI version change. */ +int comedi_set_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel, + unsigned int range, unsigned int aref, const char *cal_file_path); #endif diff --git a/lib/calib.c b/lib/calib.c index fd8126a..3bdc1c0 100644 --- a/lib/calib.c +++ b/lib/calib.c @@ -23,27 +23,29 @@ #define _GNU_SOURCE #include +#include +#include #include #include -static int ph_extract_element( const char *file_path, const char *element, - char *result, unsigned int result_size ) +static int extract_ph_element( const char *file_path, const char *hash_ref, + const char *element, char *result, unsigned int result_size ) { char perl_prog[ 1024 ]; FILE *perl_stdout; int retval; snprintf( perl_prog, sizeof( perl_prog ), - "perl -e '" - "use strict;" - "use warnings;" - "my $hash;" - "my $cal;" - "$hash = `cat %s`;" - "eval \"\\$cal = $hash;\";" - "print $cal->%s;" - "'", - file_path, element ); + "perl -e ' + use strict; + use warnings; + my $hash; + my $%s; + $hash = `cat %s`; + eval \"\\$%s = $hash;\"; + print %s; + '", + hash_ref, file_path, hash_ref, element ); perl_stdout = popen( perl_prog, "r"); if( perl_stdout == NULL ) @@ -68,37 +70,160 @@ static int ph_extract_element( const char *file_path, const char *element, return 0; } -//EXPORT_SYMBOL(comedi_set_calibration,0.7.20); -int comedi_set_calibration( comedi_t *dev, const char *cal_file_path, - unsigned int subdev, unsigned int channel, unsigned int range, unsigned int aref ) +static int check_cal_file( comedi_t *dev, const char *file_path ) +{ + char result[ 100 ]; + int retval; + + retval = extract_ph_element( file_path, "cal", "cal->{driver_name}", + result, sizeof( result ) ); + if( retval < 0 ) return retval; + + if( strcmp( comedi_get_driver_name( dev ), result ) ) + { + fprintf( stderr, "driver name does not match calibration file\n" ); + return -1; + } + + retval = extract_ph_element( file_path, "cal", "cal->{board_name}", + result, sizeof( result ) ); + if( retval < 0 ) return retval; + + if( strcmp( comedi_get_board_name( dev ), result ) ) + { + fprintf( stderr, "board name does not match calibration file\n" ); + return -1; + } + + return 0; +} + +static int num_calibrations( const char *file_path ) +{ + int retval; + char result[ 100 ]; + + retval = extract_ph_element( file_path, "cal", "scalar( @{$cal->{calibrations}} )", + result, sizeof( result ) ); + if( retval < 0 ) return retval; + + return strtol( result, NULL, 0 ); +} + +static int extract_array_element( const char *file_path, unsigned int cal_index, + const char *array_name, unsigned int array_index ) +{ + char element[ 100 ]; + char result[ 100 ]; + int retval; + + snprintf( element, sizeof( element ), + "cal->{ calibrations }[ %i ]->{ %s }[ %i ]", cal_index, array_name, array_index ); + retval = extract_ph_element( file_path, "cal", element, result, sizeof( result ) ); + if( retval < 0 ) return retval; + + return strtol( result, NULL, 0 ); +} + +static int extract_array_length( const char *file_path, unsigned int cal_index, + const char *array_name ) +{ + char result[ 100 ]; + char element[ 100 ]; + int retval; + + snprintf( element, sizeof( element ), + "scalar( @{ cal->{ calibrations }[ %i ]->{ %s } } )", cal_index, array_name ); + retval = extract_ph_element( file_path, "cal", element, result, sizeof( result ) ); + if( retval < 0 ) return 0; + + return strtol( result, NULL, 0 ); +} + +static int valid_item( const char *file_path, unsigned int cal_index, + const char *item_type, unsigned int item ) +{ + int num_items, i; + + num_items = extract_array_length( file_path, cal_index, item_type ); + if( num_items < 0 ) return 0; + if( num_items == 0 ) return 1; + for( i = 0; i < num_items; i++ ) + { + if( extract_array_element( file_path, cal_index, item_type, i ) == item ) + return 1; + } + + return 0; +} + +static inline int valid_range( const char *file_path, unsigned int cal_index, + unsigned int range ) +{ + return valid_item( file_path, cal_index, "ranges", range ); +} + +static inline int valid_channel( const char *file_path, unsigned int cal_index, + unsigned int channel ) +{ + return valid_item( file_path, cal_index, "channels", channel ); +} + +static inline int valid_aref( const char *file_path, unsigned int cal_index, + unsigned int aref ) +{ + return valid_item( file_path, cal_index, "arefs", aref ); +} + +static int find_calibration( const char *file_path, unsigned int channel, + unsigned int range, unsigned int aref ) +{ + int num_cals, i; + + num_cals = num_calibrations( file_path ); + if( num_cals < 0 ) return num_cals; + + for( i = 0; i < num_cals; i++ ) + { + if( valid_range( file_path, i, range ) == 0 ) continue; + if( valid_channel( file_path, i, channel ) == 0 ) continue; + if( valid_aref( file_path, i, aref ) == 0 ) continue; + break; + } + if( i == num_cals ) return -1; + + return i; +} + +EXPORT_SYMBOL(comedi_set_calibration,0.7.20); +int comedi_set_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel, + unsigned int range, unsigned int aref, const char *cal_file_path ) { struct stat file_stats; - FILE *cal_file; + char file_path[ 1024 ]; + int retval; + int cal_index; if( cal_file_path ) - cal_file = fopen( cal_file_path, "r" ); - else { - char *file_path; - + strncpy( file_path, cal_file_path, sizeof( file_path ) ); + }else + { if( fstat( comedi_fileno( dev ), &file_stats ) < 0 ) { fprintf( stderr, "failed to get file stats of comedi device file\n" ); return -1; } - asprintf( &file_path, "/etc/comedi/calibrations/%s_0x%lx", + snprintf( file_path, sizeof( file_path ), "/etc/comedi/calibrations/%s_0x%lx", comedi_get_board_name( dev ), ( unsigned long ) file_stats.st_ino ); - cal_file = fopen( file_path, "r" ); - free( file_path ); } - if( cal_file == NULL ) - { - fprintf( stderr, "failed to open calibration file\n" ); - return -1; - } + retval = check_cal_file( dev, file_path ); + if( retval < 0 ) return retval; + + cal_index = find_calibration( file_path, channel, range, aref ); return 0; } diff --git a/lib/version_script b/lib/version_script index 2f3b360..beaaaf5 100644 --- a/lib/version_script +++ b/lib/version_script @@ -18,3 +18,6 @@ v0.7.19 { } v0.7.18; +v0.7.20 { + +} v0.7.19; -- 2.26.2