finished implementing comedi_set_calibration() (untested)
authorFrank Mori Hess <fmhess@speakeasy.net>
Wed, 26 Feb 2003 19:19:57 +0000 (19:19 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Wed, 26 Feb 2003 19:19:57 +0000 (19:19 +0000)
include/comedilib.h
lib/calib.c
lib/version_script

index ff98c7053d0eca4d4a5d882721b1752c330ebe53..f63a2ebf973b2d2c5b3d4bf869409a1d06b61300 100644 (file)
@@ -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
index fd8126ac5c1202e49c5d15e5c5d36f4130784f39..3bdc1c033eb8a95efc9033eea1cb2917b6aca4a0 100644 (file)
 #define _GNU_SOURCE
 
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include <comedilib.h>
 #include <libinternal.h>
 
-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;
 }
index 2f3b360212701692fc4effbde313478ece9a0d8c..beaaaf5abd223e3c196a4f30f0c824deff05c5ab 100644 (file)
@@ -18,3 +18,6 @@ v0.7.19 {
 
 } v0.7.18;
 
+v0.7.20 {
+
+} v0.7.19;