/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbcalfile.c * @brief Functions for saving/restoring calibration settings * * Copyright (C) 2001-2004 Gerhard Jaeger * * History: * - 0.46 - first version * - 0.47 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ typedef struct { u_long red_light_on; u_long red_light_off; u_long green_light_on; u_long green_light_off; u_long blue_light_on; u_long blue_light_off; u_long green_pwm_duty; } LightCtrl, *pLightCtrl; typedef struct { u_short version; u_short red_gain; u_short green_gain; u_short blue_gain; u_short red_offs; u_short green_offs; u_short blue_offs; LightCtrl light; } CalData, *pCalData; #define _PT_CF_VERSION 0x0001 /** function to read a text file and returns the string which starts which * 'id' string. * no duplicate entries where detected, always the first occurance will be * red. * @param fp - file pointer of file to read * @param id - what to search for * @param res - where to store the result upon success * @return SANE_TRUE on success, SANE_FALSE on any error */ static SANE_Bool usb_ReadSpecLine( FILE *fp, char *id, char* res ) { char tmp[1024]; char *ptr; /* rewind file pointer */ if( 0 != fseek( fp, 0L, SEEK_SET)) { DBG( _DBG_ERROR, "fseek: %s\n", strerror(errno)); return SANE_FALSE; } /* roam through the file and examine each line... */ while( !feof( fp )) { if( NULL != fgets( tmp, 1024, fp )) { if( 0 == strncmp( tmp, id, strlen(id))) { ptr = &tmp[strlen(id)]; if( '\0' == *ptr ) break; strcpy( res, ptr ); res[strlen(res)-1] = '\0'; return SANE_TRUE; } } } return SANE_FALSE; } /** */ static char *usb_ReadOtherLines( FILE *fp, char *except ) { char tmp[1024]; char *ptr, *ptr_base; int len; if( 0 != fseek( fp, 0L, SEEK_END)) return NULL; len = ftell(fp); /* rewind file pointer */ if( 0 != fseek( fp, 0L, SEEK_SET)) return NULL; if( len == 0 ) return NULL; ptr = (char*)malloc(len); if( NULL == ptr ) return NULL; ptr_base = ptr; *ptr = '\0'; /* roam through the file and examine each line... */ while( !feof( fp )) { if( NULL != fgets( tmp, 1024, fp )) { if( 0 == strncmp( tmp, "version=", 8 )) continue; if( 0 != strncmp( tmp, except, strlen(except))) { if( strlen( tmp ) > 0 ) { strcpy( ptr, tmp ); ptr += strlen(tmp); *ptr = '\0'; } } } } return ptr_base; } /** */ static void usb_RestoreCalData( pCalData cal ) { a_bRegs[0x3b] = (u_char)cal->red_gain; a_bRegs[0x3c] = (u_char)cal->green_gain; a_bRegs[0x3d] = (u_char)cal->blue_gain; a_bRegs[0x38] = (u_char)cal->red_offs; a_bRegs[0x39] = (u_char)cal->green_offs; a_bRegs[0x3a] = (u_char)cal->blue_offs; a_bRegs[0x2a] = _HIBYTE((u_short)cal->light.green_pwm_duty); a_bRegs[0x2b] = _LOBYTE((u_short)cal->light.green_pwm_duty); a_bRegs[0x2c] = _HIBYTE((u_short)cal->light.red_light_on); a_bRegs[0x2d] = _LOBYTE((u_short)cal->light.red_light_on); a_bRegs[0x2e] = _HIBYTE((u_short)cal->light.red_light_off); a_bRegs[0x2f] = _LOBYTE((u_short)cal->light.red_light_off); a_bRegs[0x30] = _HIBYTE((u_short)cal->light.green_light_on); a_bRegs[0x31] = _LOBYTE((u_short)cal->light.green_light_on); a_bRegs[0x32] = _HIBYTE((u_short)cal->light.green_light_off); a_bRegs[0x33] = _LOBYTE((u_short)cal->light.green_light_off); a_bRegs[0x34] = _HIBYTE((u_short)cal->light.blue_light_on); a_bRegs[0x35] = _LOBYTE((u_short)cal->light.blue_light_on); a_bRegs[0x36] = _HIBYTE((u_short)cal->light.blue_light_off); a_bRegs[0x37] = _LOBYTE((u_short)cal->light.blue_light_off); } /** */ static void usb_CreatePrefix( pPlustek_Device dev, char *pfx ) { char bd[5]; pScanDef scanning = &dev->scanning; pScanParam param = &scanning->sParam; switch( scanning->sParam.bSource ) { case SOURCE_Transparency: strcpy( pfx, "tpa-" ); break; case SOURCE_Negative: strcpy( pfx, "neg-" ); break; case SOURCE_ADF: strcpy( pfx, "adf-" ); break; default: pfx[0] = '\0'; break; } sprintf( bd, "%u=", param->bBitDepth ); if( param->bDataType == SCANDATATYPE_Color ) strcat( pfx, "color" ); else strcat( pfx, "gray" ); strcat( pfx, bd ); } /** function to read and set the calibration data from external file */ static SANE_Bool usb_ReadAndSetCalData( pPlustek_Device dev ) { char pfx[20]; char tmp[1024]; u_short version; int res; FILE *fp; CalData cal; SANE_Bool ret; DBG( _DBG_INFO, "usb_ReadAndSetCalData()\n" ); if( NULL == dev->calFile ) { DBG( _DBG_ERROR, "- No calibration filename set!\n" ); return SANE_FALSE; } DBG( _DBG_INFO, "- Reading calibration data from file\n"); DBG( _DBG_INFO, " %s\n", dev->calFile ); fp = fopen( dev->calFile, "r" ); if( NULL == fp ) { DBG( _DBG_ERROR, "File %s not found\n", dev->calFile ); return SANE_FALSE; } /* check version */ if( !usb_ReadSpecLine( fp, "version=", tmp )) { DBG( _DBG_ERROR, "Could not find version info!\n" ); fclose( fp ); return SANE_FALSE; } DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp ); if( 1 != sscanf( tmp, "0x%04hx", &version )) { DBG( _DBG_ERROR, "Could not decode version info!\n" ); fclose( fp ); return SANE_FALSE; } if( version != _PT_CF_VERSION ) { DBG( _DBG_ERROR, "Versions do not match!\n" ); fclose( fp ); return SANE_FALSE; } usb_CreatePrefix( dev, pfx ); ret = SANE_FALSE; if( usb_ReadSpecLine( fp, pfx, tmp )) { DBG( _DBG_INFO, "- Calibration data: %s\n", tmp ); res = sscanf( tmp, "%hu,%hu,%hu,%hu,%hu,%hu," "%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", &cal.red_gain, &cal.red_offs, &cal.green_gain, &cal.green_offs, &cal.blue_gain, &cal.blue_offs, &cal.light.red_light_on, &cal.light.red_light_off, &cal.light.green_light_on, &cal.light.green_light_off, &cal.light.blue_light_on, &cal.light.blue_light_off, &cal.light.green_pwm_duty ); if( 13 == res ) { usb_RestoreCalData( &cal ); ret = SANE_TRUE; } } fclose( fp ); DBG( _DBG_INFO, "usb_ReadAndSetCalData() done -> %u\n", ret ); return ret; } /** */ static void usb_PrepCalData( pCalData cal ) { memset( cal, 0, sizeof(CalData)); cal->version = _PT_CF_VERSION; cal->red_gain = (u_short)a_bRegs[0x3b]; cal->green_gain = (u_short)a_bRegs[0x3c]; cal->blue_gain = (u_short)a_bRegs[0x3d]; cal->red_offs = (u_short)a_bRegs[0x38]; cal->green_offs = (u_short)a_bRegs[0x39]; cal->blue_offs = (u_short)a_bRegs[0x3a]; cal->light.green_pwm_duty = a_bRegs[0x2a] * 256 + a_bRegs[0x2b]; cal->light.red_light_on = a_bRegs[0x2c] * 256 + a_bRegs[0x2d]; cal->light.red_light_off = a_bRegs[0x2e] * 256 + a_bRegs[0x2f]; cal->light.green_light_on = a_bRegs[0x30] * 256 + a_bRegs[0x31]; cal->light.green_light_off = a_bRegs[0x32] * 256 + a_bRegs[0x33]; cal->light.blue_light_on = a_bRegs[0x34] * 256 + a_bRegs[0x35]; cal->light.blue_light_off = a_bRegs[0x36] * 256 + a_bRegs[0x37]; } /** function to save/update the calibration data */ static void usb_SaveCalData( pPlustek_Device dev ) { char pfx[20]; char tmp[1024]; char set_tmp[1024]; char *other_tmp; u_short version; FILE *fp; CalData cal; pScanDef scanning = &dev->scanning; DBG( _DBG_INFO, "usb_SaveCalData()\n" ); /* no new data, so skip this step too */ if( SANE_TRUE == scanning->skipCoarseCalib ) { DBG( _DBG_INFO, "- No calibration data to save!\n" ); return; } if( NULL == dev->calFile ) { DBG( _DBG_ERROR, "- No calibration filename set!\n" ); return; } DBG( _DBG_INFO, "- Saving calibration data to file\n" ); DBG( _DBG_INFO, " %s\n", dev->calFile ); usb_PrepCalData ( &cal ); usb_CreatePrefix( dev, pfx ); sprintf( set_tmp, "%s%u,%u,%u,%u,%u,%u," "%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", pfx, cal.red_gain, cal.red_offs, cal.green_gain, cal.green_offs, cal.blue_gain, cal.blue_offs, cal.light.red_light_on, cal.light.red_light_off, cal.light.green_light_on, cal.light.green_light_off, cal.light.blue_light_on, cal.light.blue_light_off, cal.light.green_pwm_duty ); /* read complete old file if compatible... */ other_tmp = NULL; fp = fopen( dev->calFile, "r+" ); if( NULL != fp ) { if( usb_ReadSpecLine( fp, "version=", tmp )) { DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp ); if( 1 == sscanf( tmp, "0x%04hx", &version )) { if( version == cal.version ) { DBG( _DBG_INFO, "- Versions do match\n" ); /* read the rest... */ other_tmp = usb_ReadOtherLines( fp, pfx ); } else { DBG( _DBG_INFO2, "- Versions do not match (0x%04x)\n", version ); } } else { DBG( _DBG_INFO2, "- cannot decode version\n" ); } } else { DBG( _DBG_INFO2, "- Version not found\n" ); } fclose( fp ); } fp = fopen( dev->calFile, "w+" ); if( NULL == fp ) { DBG( _DBG_ERROR, "- Cannot create file %s\n", dev->calFile ); DBG( _DBG_ERROR, "- -> %s\n", strerror(errno)); if( other_tmp ) free( other_tmp ); return; } /* rewrite the file again... */ fprintf( fp, "version=0x%04X\n", cal.version ); if( strlen( set_tmp )) fprintf( fp, "%s", set_tmp ); if( other_tmp ) { fprintf( fp, "%s", other_tmp ); free( other_tmp ); } fclose( fp ); DBG( _DBG_INFO, "usb_SaveCalData() done.\n" ); } /* END PLUSTEK-USBCALFILE.C .................................................*/