3 functions for setting calibration
5 Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation, version 2.1
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 #include <comedilib.h>
29 #include <libinternal.h>
31 static int extract_ph_string( const char *file_path, const char *hash_ref,
32 const char *element, char *result, unsigned int result_size )
34 char perl_prog[ 1024 ];
38 snprintf( perl_prog, sizeof( perl_prog ),
45 eval \"\\$%s = $hash;\";
48 hash_ref, file_path, hash_ref, element );
50 perl_stdout = popen( perl_prog, "r");
51 if( perl_stdout == NULL )
53 fprintf( stderr, "popen() failed in ph_extract_element()\n" );
57 if( fgets( result, result_size, perl_stdout ) == NULL )
59 fprintf( stderr, "fgets() returned NULL in ph_extract_element()\n" );
63 retval = pclose( perl_stdout );
66 fprintf( stderr, "perl returned error %i\n in ph_extract_element()", retval );
73 static int extract_ph_integer( const char *file_path, const char *hash_ref,
79 retval = extract_ph_string( file_path, hash_ref, element, result, sizeof( result ) );
80 if( retval < 0 ) return retval;
82 return strtol( result, NULL, 0 );
85 static int check_cal_file( comedi_t *dev, const char *file_path )
90 retval = extract_ph_string( file_path, "cal", "$cal->{driver_name}",
91 result, sizeof( result ) );
92 if( retval < 0 ) return retval;
94 if( strcmp( comedi_get_driver_name( dev ), result ) )
96 fprintf( stderr, "driver name does not match calibration file\n" );
100 retval = extract_ph_string( file_path, "cal", "$cal->{board_name}",
101 result, sizeof( result ) );
102 if( retval < 0 ) return retval;
104 if( strcmp( comedi_get_board_name( dev ), result ) )
106 fprintf( stderr, "board name does not match calibration file\n" );
113 static inline int num_calibrations( const char *file_path )
115 return extract_ph_integer( file_path, "cal", "scalar( @{$cal->{calibrations}} )" );
118 static int extract_array_element( const char *file_path, unsigned int cal_index,
119 const char *array_name, unsigned int array_index )
123 snprintf( element, sizeof( element ),
124 "$cal->{ calibrations }[ %i ]->{ %s }[ %i ]", cal_index, array_name, array_index );
125 return extract_ph_integer( file_path, "cal", element );
128 static int extract_array_length( const char *file_path, unsigned int cal_index,
129 const char *array_name )
133 snprintf( element, sizeof( element ),
134 "scalar( @{ $cal->{ calibrations }[ %i ]->{ %s } } )", cal_index, array_name );
135 return extract_ph_integer( file_path, "cal", element );
138 static int extract_subdevice( const char *file_path, unsigned int cal_index )
142 snprintf( element, sizeof( element ),
143 "$cal->{ calibrations }[ %i ]->{ subdevice }", cal_index );
144 return extract_ph_integer( file_path, "cal", element );
147 static int valid_item( const char *file_path, unsigned int cal_index,
148 const char *item_type, unsigned int item )
152 num_items = extract_array_length( file_path, cal_index, item_type );
153 if( num_items < 0 ) return 0;
154 if( num_items == 0 ) return 1;
155 for( i = 0; i < num_items; i++ )
157 if( extract_array_element( file_path, cal_index, item_type, i ) == item )
164 static inline int valid_range( const char *file_path, unsigned int cal_index,
167 return valid_item( file_path, cal_index, "ranges", range );
170 static inline int valid_channel( const char *file_path, unsigned int cal_index,
171 unsigned int channel )
173 return valid_item( file_path, cal_index, "channels", channel );
176 static inline int valid_aref( const char *file_path, unsigned int cal_index,
179 return valid_item( file_path, cal_index, "arefs", aref );
182 static int find_calibration( const char *file_path, unsigned int subdev,
183 unsigned int channel, unsigned int range, unsigned int aref )
187 num_cals = num_calibrations( file_path );
188 if( num_cals < 0 ) return num_cals;
190 for( i = 0; i < num_cals; i++ )
192 if( extract_subdevice( file_path, i ) != subdev ) continue;
193 if( valid_range( file_path, i, range ) == 0 ) continue;
194 if( valid_channel( file_path, i, channel ) == 0 ) continue;
195 if( valid_aref( file_path, i, aref ) == 0 ) continue;
198 if( i == num_cals ) return -1;
203 static int set_calibration( comedi_t *dev, const char *file_path,
204 unsigned int cal_index )
206 int i, retval, num_caldacs;
208 num_caldacs = extract_array_length( file_path, cal_index, "caldacs" );
209 if( num_caldacs < 0 ) return num_caldacs;
211 for( i = 0; i < num_caldacs; i++ )
213 int subdev, channel, value;
216 asprintf( &element, "$cal->{calibrations}[ %i ]->{caldacs}[ %i ]->{subdevice}",
218 subdev = extract_ph_integer( file_path, "cal", element );
222 fprintf( stderr, "failed to extract subdev\n" );
226 asprintf( &element, "$cal->{calibrations}[ %i ]->{caldacs}[ %i ]->{channel}",
228 channel = extract_ph_integer( file_path, "cal", element );
232 fprintf( stderr, "failed to extract channel\n" );
236 asprintf( &element, "$cal->{calibrations}[ %i ]->{caldacs}[ %i ]->{value}",
238 value = extract_ph_integer( file_path, "cal", element );
242 fprintf( stderr, "failed to extract value\n" );
246 retval = comedi_data_write( dev, subdev, channel, 0, 0, value );
247 if( retval < 0 ) return retval;
253 EXPORT_SYMBOL(comedi_set_calibration,0.7.20);
254 int comedi_set_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel,
255 unsigned int range, unsigned int aref, const char *cal_file_path )
257 struct stat file_stats;
258 char file_path[ 1024 ];
264 strncpy( file_path, cal_file_path, sizeof( file_path ) );
267 if( fstat( comedi_fileno( dev ), &file_stats ) < 0 )
269 fprintf( stderr, "failed to get file stats of comedi device file\n" );
273 snprintf( file_path, sizeof( file_path ), "/etc/comedi/calibrations/%s_0x%lx",
274 comedi_get_board_name( dev ),
275 ( unsigned long ) file_stats.st_ino );
278 retval = check_cal_file( dev, file_path );
279 if( retval < 0 ) return retval;
281 cal_index = find_calibration( file_path, subdev, channel, range, aref );
282 if( cal_index < 0 ) return cal_index;
284 retval = set_calibration( dev, file_path, cal_index );
285 if( retval < 0 ) return retval;