1 /*.............................................................................
2 * Project : SANE library for Plustek flatbed scanners.
3 *.............................................................................
4 */
5
6 /** @file plustek-usbcalfile.c
7 * @brief Functions for saving/restoring calibration settings
8 *
9 * Copyright (C) 2001-2007 Gerhard Jaeger <gerhard@gjaeger.de>
10 *
11 * History:
12 * - 0.46 - first version
13 * - 0.47 - no changes
14 * - 0.48 - no changes
15 * - 0.49 - a_bRegs is now part of the device structure
16 * - 0.50 - cleanup
17 * - 0.51 - added functions for saving, reading and restoring
18 * fine calibration data
19 * - 0.52 - no changes
20 * .
21 * <hr>
22 * This file is part of the SANE package.
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License as
26 * published by the Free Software Foundation; either version 2 of the
27 * License, or (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful, but
30 * WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 * General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program. If not, see <https://www.gnu.org/licenses/>.
36 *
37 * As a special exception, the authors of SANE give permission for
38 * additional uses of the libraries contained in this release of SANE.
39 *
40 * The exception is that, if you link a SANE library with other files
41 * to produce an executable, this does not by itself cause the
42 * resulting executable to be covered by the GNU General Public
43 * License. Your use of that executable is in no way restricted on
44 * account of linking the SANE library code into it.
45 *
46 * This exception does not, however, invalidate any other reasons why
47 * the executable file might be covered by the GNU General Public
48 * License.
49 *
50 * If you submit changes to SANE to the maintainers to be included in
51 * a subsequent release, you agree by submitting the changes that
52 * those changes may be distributed with this exception intact.
53 *
54 * If you write modifications of your own for SANE, it is your choice
55 * whether to permit this exception to apply to your modifications.
56 * If you do not wish that, delete this exception notice.
57 * <hr>
58 */
59
60 typedef struct {
61 u_long red_light_on;
62 u_long red_light_off;
63 u_long green_light_on;
64 u_long green_light_off;
65 u_long blue_light_on;
66 u_long blue_light_off;
67 u_long green_pwm_duty;
68
69 } LightCtrl;
70
71 typedef struct {
72 u_short version;
73
74 u_short red_gain;
75 u_short green_gain;
76 u_short blue_gain;
77
78 u_short red_offs;
79 u_short green_offs;
80 u_short blue_offs;
81
82 LightCtrl light;
83
84 } CalData;
85
86 /* our shading buffers */
87 static u_short a_wWhiteShading[_SHADING_BUF] = {0};
88 static u_short a_wDarkShading[_SHADING_BUF] = {0};
89
90 /* the version the calibration files */
91 #define _PT_CF_VERSION 0x0002
92
93 /** function to read a text file and returns the string which starts which
94 * 'id' string.
95 * no duplicate entries where detected, always the first occurrence will be
96 * red.
97 * @param fp - file pointer of file to read
98 * @param id - what to search for
99 * @param res - where to store the result upon success
100 * @return SANE_TRUE on success, SANE_FALSE on any error
101 */
102 static SANE_Bool
usb_ReadSpecLine(FILE * fp,char * id,char * res)103 usb_ReadSpecLine( FILE *fp, char *id, char* res )
104 {
105 char tmp[1024];
106 char *ptr;
107
108 /* rewind file pointer */
109 if( 0 != fseek( fp, 0L, SEEK_SET)) {
110 DBG( _DBG_ERROR, "fseek: %s\n", strerror(errno));
111 return SANE_FALSE;
112 }
113
114 /* roam through the file and examine each line... */
115 while( !feof( fp )) {
116
117 memset( tmp, 0, sizeof(tmp));
118 if( NULL != fgets( tmp, 1024, fp )) {
119
120 if( 0 == strncmp( tmp, id, strlen(id))) {
121
122 ptr = &tmp[strlen(id)];
123 if( '\0' == *ptr )
124 break;
125
126 strcpy( res, ptr );
127 res[strlen(res)-1] = '\0';
128 return SANE_TRUE;
129 }
130 }
131 }
132 return SANE_FALSE;
133 }
134
135 /** function to read data from a file and excluding certain stuff like
136 * the version lines
137 * @param fp - file pointer of file to read
138 * @param except - what to exclude
139 * @return Pointer to the allocated memory for the data, NULL on any error.
140 */
141 static char*
usb_ReadOtherLines(FILE * fp,char * except)142 usb_ReadOtherLines( FILE *fp, char *except )
143 {
144 char tmp[1024];
145 char *ptr, *ptr_base;
146 int ignore;
147 int len;
148
149 if( 0 != fseek( fp, 0L, SEEK_END))
150 return NULL;
151
152 len = ftell(fp);
153
154 /* rewind file pointer */
155 if( 0 != fseek( fp, 0L, SEEK_SET))
156 return NULL;
157
158 if( len == 0 )
159 return NULL;
160
161 ptr = (char*)malloc(len);
162 if( NULL == ptr )
163 return NULL;
164
165 ptr_base = ptr;
166 *ptr = '\0';
167 ignore = 0;
168
169 /* roam through the file and examine each line... */
170 while( !feof( fp )) {
171
172 if( NULL != fgets( tmp, 1024, fp )) {
173
174 /* we ignore the version line... */
175 if( 0 == strncmp( tmp, "version=", 8 ))
176 continue;
177
178 if( !ignore ) {
179 if(0 != strncmp(tmp, except, strlen(except))) {
180
181 if( strlen( tmp ) > 0 ) {
182 strcpy( ptr, tmp );
183 ptr += strlen(tmp);
184 *ptr = '\0';
185 }
186 } else {
187 ignore = 1;
188 }
189 }
190
191 /* newline in tmp string resets ignore flag */
192 if( strrchr(tmp, '\n')) {
193 ignore = 0;
194 }
195 }
196 }
197 return ptr_base;
198 }
199
200 /**
201 */
202 static SANE_Bool
usb_ReadSamples(FILE * fp,char * which,u_long * dim,u_short * buffer)203 usb_ReadSamples( FILE *fp, char *which, u_long *dim, u_short *buffer )
204 {
205 char *p, *next, *rb;
206 char tmp[1024+30];
207 int ignore, diml, c;
208 u_long val;
209
210 /* rewind file pointer */
211 if( 0 != fseek( fp, 0L, SEEK_SET))
212 return SANE_FALSE;
213
214 ignore = 0;
215 diml = 0;
216 c = 0;
217 rb = tmp;
218 *dim = 0;
219
220 /* roam through the file and examine each line... */
221 while( !feof( fp )) {
222
223 if( NULL != fgets( rb, 1024, fp )) {
224
225 /* we ignore the version line... */
226 if( 0 == strncmp( tmp, "version=", 8 ))
227 continue;
228
229 p = tmp;
230 if( !ignore && diml == 0) {
231 if(0 == strncmp(tmp, which, strlen(which))) {
232
233 /* get dimension */
234 diml = strtol(&tmp[strlen(which)], NULL, 10);
235 p = strchr( &tmp[strlen(which)], ':' );
236 p++;
237 } else {
238 ignore = 1;
239 }
240 }
241
242 /* parse the values... */
243 if( !ignore ) {
244
245 rb = tmp;
246 while( *p ) {
247 val = strtoul( p, &next, 10 );
248
249 /* check for error condition */
250 if( val == 0 ) {
251 if( p == next ) {
252 if( c+1 == diml ) {
253 *dim = diml;
254 return SANE_TRUE;
255 }
256 break;
257 }
258 }
259
260 buffer[c] = (u_short)val;
261
262 /* more values? */
263 if( *next == ',') {
264 p = next+1;
265 c++;
266 } else {
267 p = next;
268 }
269 /* reached the end? */
270 if( *next == '\0' ) {
271
272 /* we probably have only parsed a part of a value
273 * so we copy that back to the input buffer and
274 * parse it the next time...
275 */
276 if( c < diml ) {
277 sprintf( tmp, "%u", buffer[c] );
278 rb = &tmp[strlen(tmp)];
279 }
280 }
281 }
282 }
283
284 /* newline in tmp string resets ignore flag */
285 if( strrchr(tmp, '\n')) {
286 ignore = 0;
287 }
288 }
289 }
290 return SANE_FALSE;
291 }
292
293 /**
294 */
295 static void
usb_RestoreCalData(Plustek_Device * dev,CalData * cal)296 usb_RestoreCalData( Plustek_Device *dev, CalData *cal )
297 {
298 HWDef *hw = &dev->usbDev.HwSetting;
299 u_char *regs = dev->usbDev.a_bRegs;
300
301 regs[0x3b] = (u_char)cal->red_gain;
302 regs[0x3c] = (u_char)cal->green_gain;
303 regs[0x3d] = (u_char)cal->blue_gain;
304 regs[0x38] = (u_char)cal->red_offs;
305 regs[0x39] = (u_char)cal->green_offs;
306 regs[0x3a] = (u_char)cal->blue_offs;
307
308 regs[0x2a] = _HIBYTE((u_short)cal->light.green_pwm_duty);
309 regs[0x2b] = _LOBYTE((u_short)cal->light.green_pwm_duty);
310
311 regs[0x2c] = _HIBYTE((u_short)cal->light.red_light_on);
312 regs[0x2d] = _LOBYTE((u_short)cal->light.red_light_on);
313 regs[0x2e] = _HIBYTE((u_short)cal->light.red_light_off);
314 regs[0x2f] = _LOBYTE((u_short)cal->light.red_light_off);
315
316 regs[0x30] = _HIBYTE((u_short)cal->light.green_light_on);
317 regs[0x31] = _LOBYTE((u_short)cal->light.green_light_on);
318 regs[0x32] = _HIBYTE((u_short)cal->light.green_light_off);
319 regs[0x33] = _LOBYTE((u_short)cal->light.green_light_off);
320
321 regs[0x34] = _HIBYTE((u_short)cal->light.blue_light_on);
322 regs[0x35] = _LOBYTE((u_short)cal->light.blue_light_on);
323 regs[0x36] = _HIBYTE((u_short)cal->light.blue_light_off);
324 regs[0x37] = _LOBYTE((u_short)cal->light.blue_light_off);
325
326 hw->red_lamp_on = (u_short)cal->light.red_light_on;
327 hw->red_lamp_off = (u_short)cal->light.red_light_off;
328 hw->green_lamp_on = (u_short)cal->light.green_light_on;
329 hw->green_lamp_off = (u_short)cal->light.green_light_off;
330 hw->blue_lamp_on = (u_short)cal->light.blue_light_on;
331 hw->blue_lamp_off = (u_short)cal->light.blue_light_off;
332 }
333
334 /**
335 */
336 static void
usb_CreatePrefix(Plustek_Device * dev,char * pfx,SANE_Bool add_bitdepth)337 usb_CreatePrefix( Plustek_Device *dev, char *pfx, SANE_Bool add_bitdepth )
338 {
339 char bd[5];
340 ScanDef *scanning = &dev->scanning;
341 ScanParam *param = &scanning->sParam;
342
343 switch( scanning->sParam.bSource ) {
344
345 case SOURCE_Transparency: strcpy( pfx, "tpa-" ); break;
346 case SOURCE_Negative: strcpy( pfx, "neg-" ); break;
347 case SOURCE_ADF: strcpy( pfx, "adf-" ); break;
348 default: pfx[0] = '\0'; break;
349 }
350
351 sprintf( bd, "%u=", param->bBitDepth );
352 if( param->bDataType == SCANDATATYPE_Color )
353 strcat( pfx, "color" );
354 else
355 strcat( pfx, "gray" );
356
357 if( add_bitdepth )
358 strcat( pfx, bd );
359 }
360
361 /** function to read and set the calibration data from external file
362 */
363 static SANE_Bool
usb_ReadAndSetCalData(Plustek_Device * dev)364 usb_ReadAndSetCalData( Plustek_Device *dev )
365 {
366 char pfx[20];
367 char tmp[1024];
368 u_short version;
369 int res;
370 FILE *fp;
371 CalData cal;
372 SANE_Bool ret;
373
374 DBG( _DBG_INFO, "usb_ReadAndSetCalData()\n" );
375
376 if( usb_InCalibrationMode(dev)) {
377 DBG( _DBG_INFO, "- we are in calibration mode!\n" );
378 return SANE_FALSE;
379 }
380
381 if( NULL == dev->calFile ) {
382 DBG( _DBG_ERROR, "- No calibration filename set!\n" );
383 return SANE_FALSE;
384 }
385
386 sprintf( tmp, "%s-coarse.cal", dev->calFile );
387 DBG( _DBG_INFO, "- Reading coarse calibration data from file\n");
388 DBG( _DBG_INFO, " %s\n", tmp );
389
390 fp = fopen( tmp, "r" );
391 if( NULL == fp ) {
392 DBG( _DBG_ERROR, "File %s not found\n", tmp );
393 return SANE_FALSE;
394 }
395
396 /* check version */
397 if( !usb_ReadSpecLine( fp, "version=", tmp )) {
398 DBG( _DBG_ERROR, "Could not find version info!\n" );
399 fclose( fp );
400 return SANE_FALSE;
401 }
402
403 DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp );
404 if( 1 != sscanf( tmp, "0x%04hx", &version )) {
405 DBG( _DBG_ERROR, "Could not decode version info!\n" );
406 fclose( fp );
407 return SANE_FALSE;
408 }
409
410 if( version != _PT_CF_VERSION ) {
411 DBG( _DBG_ERROR, "Versions do not match!\n" );
412 fclose( fp );
413 return SANE_FALSE;
414 }
415
416 usb_CreatePrefix( dev, pfx, SANE_TRUE );
417
418 ret = SANE_FALSE;
419 if( usb_ReadSpecLine( fp, pfx, tmp )) {
420 DBG( _DBG_INFO, "- Calibration data: %s\n", tmp );
421
422 res = sscanf( tmp, "%hu,%hu,%hu,%hu,%hu,%hu,"
423 "%lu,%lu,%lu,%lu,%lu,%lu,%lu\n",
424 &cal.red_gain, &cal.red_offs,
425 &cal.green_gain, &cal.green_offs,
426 &cal.blue_gain, &cal.blue_offs,
427 &cal.light.red_light_on, &cal.light.red_light_off,
428 &cal.light.green_light_on, &cal.light.green_light_off,
429 &cal.light.blue_light_on, &cal.light.blue_light_off,
430 &cal.light.green_pwm_duty );
431
432 if( 13 == res ) {
433 usb_RestoreCalData( dev, &cal );
434 ret = SANE_TRUE;
435 } else {
436 DBG( _DBG_ERROR, "Error reading coarse-calibration data, only "
437 "%d elements available!\n", res );
438 }
439 } else {
440 DBG( _DBG_ERROR, "Error reading coarse-calibration data for "
441 "PFX: >%s<!\n", pfx );
442 }
443
444 fclose( fp );
445 DBG( _DBG_INFO, "usb_ReadAndSetCalData() done -> %u\n", ret );
446
447 return ret;
448 }
449
450 /**
451 */
452 static void
usb_PrepCalData(Plustek_Device * dev,CalData * cal)453 usb_PrepCalData( Plustek_Device *dev, CalData *cal )
454 {
455 u_char *regs = dev->usbDev.a_bRegs;
456
457 memset( cal, 0, sizeof(CalData));
458 cal->version = _PT_CF_VERSION;
459
460 cal->red_gain = (u_short)regs[0x3b];
461 cal->green_gain = (u_short)regs[0x3c];
462 cal->blue_gain = (u_short)regs[0x3d];
463 cal->red_offs = (u_short)regs[0x38];
464 cal->green_offs = (u_short)regs[0x39];
465 cal->blue_offs = (u_short)regs[0x3a];
466
467 cal->light.green_pwm_duty = regs[0x2a] * 256 + regs[0x2b];
468
469 cal->light.red_light_on = regs[0x2c] * 256 + regs[0x2d];
470 cal->light.red_light_off = regs[0x2e] * 256 + regs[0x2f];
471 cal->light.green_light_on = regs[0x30] * 256 + regs[0x31];
472 cal->light.green_light_off = regs[0x32] * 256 + regs[0x33];
473 cal->light.blue_light_on = regs[0x34] * 256 + regs[0x35];
474 cal->light.blue_light_off = regs[0x36] * 256 + regs[0x37];
475 }
476
477 /** function to save/update the calibration data
478 */
479 static void
usb_SaveCalData(Plustek_Device * dev)480 usb_SaveCalData( Plustek_Device *dev )
481 {
482 char pfx[20];
483 char fn[1024];
484 char tmp[1024];
485 char set_tmp[1024];
486 char *other_tmp;
487 u_short version;
488 FILE *fp;
489 CalData cal;
490 ScanDef *scanning = &dev->scanning;
491
492 DBG( _DBG_INFO, "usb_SaveCalData()\n" );
493
494 /* no new data, so skip this step too */
495 if( SANE_TRUE == scanning->skipCoarseCalib ) {
496 DBG( _DBG_INFO, "- No calibration data to save!\n" );
497 return;
498 }
499
500 if( NULL == dev->calFile ) {
501 DBG( _DBG_ERROR, "- No calibration filename set!\n" );
502 return;
503 }
504
505 sprintf( fn, "%s-coarse.cal", dev->calFile );
506 DBG( _DBG_INFO, "- Saving coarse calibration data to file\n" );
507 DBG( _DBG_INFO, " %s\n", fn );
508
509 usb_PrepCalData ( dev, &cal );
510 usb_CreatePrefix( dev, pfx, SANE_TRUE );
511 DBG( _DBG_INFO2, "- PFX: >%s<\n", pfx );
512
513 sprintf( set_tmp, "%s%u,%u,%u,%u,%u,%u,"
514 "%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", pfx,
515 cal.red_gain, cal.red_offs,
516 cal.green_gain, cal.green_offs,
517 cal.blue_gain, cal.blue_offs,
518 cal.light.red_light_on, cal.light.red_light_off,
519 cal.light.green_light_on, cal.light.green_light_off,
520 cal.light.blue_light_on, cal.light.blue_light_off,
521 cal.light.green_pwm_duty );
522
523 /* read complete old file if compatible... */
524 other_tmp = NULL;
525 fp = fopen( fn, "r+" );
526 if( NULL != fp ) {
527
528 if( usb_ReadSpecLine( fp, "version=", tmp )) {
529 DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp );
530
531 if( 1 == sscanf( tmp, "0x%04hx", &version )) {
532
533 if( version == cal.version ) {
534
535 DBG( _DBG_INFO, "- Versions do match\n" );
536
537 /* read the rest... */
538 other_tmp = usb_ReadOtherLines( fp, pfx );
539 } else {
540 DBG( _DBG_INFO2, "- Versions do not match (0x%04x)\n", version );
541 }
542 } else {
543 DBG( _DBG_INFO2, "- cannot decode version\n" );
544 }
545 } else {
546 DBG( _DBG_INFO2, "- Version not found\n" );
547 }
548 fclose( fp );
549 }
550 fp = fopen( fn, "w+" );
551 if( NULL == fp ) {
552 DBG( _DBG_ERROR, "- Cannot create file %s\n", fn );
553 DBG( _DBG_ERROR, "- -> %s\n", strerror(errno));
554 if( other_tmp )
555 free( other_tmp );
556 return;
557 }
558
559 /* rewrite the file again... */
560 fprintf( fp, "version=0x%04X\n", cal.version );
561 if( strlen( set_tmp ))
562 fprintf( fp, "%s", set_tmp );
563
564 if( other_tmp ) {
565 fprintf( fp, "%s", other_tmp );
566 free( other_tmp );
567 }
568 fclose( fp );
569 DBG( _DBG_INFO, "usb_SaveCalData() done.\n" );
570 }
571
572 /**
573 */
574 static void
usb_SaveFineCalData(Plustek_Device * dev,int dpi,u_short * dark,u_short * white,u_long vals)575 usb_SaveFineCalData( Plustek_Device *dev, int dpi,
576 u_short *dark, u_short *white, u_long vals )
577 {
578 char pfx[30];
579 char fn[1024];
580 char tmp[1024];
581 char *other_tmp;
582 u_short version;
583 u_long i;
584 FILE *fp;
585
586 if( NULL == dev->calFile ) {
587 DBG( _DBG_ERROR, "- No calibration filename set!\n" );
588 return;
589 }
590
591 sprintf( fn, "%s-fine.cal", dev->calFile );
592 DBG( _DBG_INFO, "- Saving fine calibration data to file\n" );
593 DBG( _DBG_INFO, " %s\n", fn );
594
595 usb_CreatePrefix( dev, pfx, SANE_FALSE );
596 sprintf( tmp, "%s:%u", pfx, dpi );
597 strcpy( pfx, tmp );
598 DBG( _DBG_INFO2, "- PFX: >%s<\n", pfx );
599
600 /* read complete old file if compatible... */
601 other_tmp = NULL;
602 fp = fopen( fn, "r+" );
603 if( NULL != fp ) {
604
605 if( usb_ReadSpecLine( fp, "version=", tmp )) {
606 DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp );
607
608 if( 1 == sscanf( tmp, "0x%04hx", &version )) {
609
610 if( version == _PT_CF_VERSION ) {
611 DBG( _DBG_INFO, "- Versions do match\n" );
612
613 /* read the rest... */
614 other_tmp = usb_ReadOtherLines( fp, pfx );
615 } else {
616 DBG( _DBG_INFO2, "- Versions do not match (0x%04x)\n", version );
617 }
618 } else {
619 DBG( _DBG_INFO2, "- cannot decode version\n" );
620 }
621 } else {
622 DBG( _DBG_INFO2, "- Version not found\n" );
623 }
624 fclose( fp );
625 }
626
627 fp = fopen( fn, "w+" );
628 if( NULL == fp ) {
629 DBG( _DBG_ERROR, "- Cannot create file %s\n", fn );
630 return;
631 }
632
633 /* rewrite the file again... */
634 fprintf( fp, "version=0x%04X\n", _PT_CF_VERSION );
635
636 if( other_tmp ) {
637 fprintf( fp, "%s", other_tmp );
638 free( other_tmp );
639 }
640
641 fprintf( fp, "%s:dark:dim=%lu:", pfx, vals );
642 for( i=0; i<vals-1; i++ )
643 fprintf( fp, "%u,", dark[i]);
644 fprintf( fp, "%u\n", dark[vals-1]);
645
646 fprintf( fp, "%s:white:dim=%lu:", pfx, vals );
647 for( i=0; i<vals-1; i++ )
648 fprintf( fp, "%u,", white[i]);
649 fprintf( fp, "%u\n", white[vals-1]);
650
651 fclose( fp );
652 }
653
654 /** function to read and set the calibration data from external file
655 */
656 static SANE_Bool
usb_ReadFineCalData(Plustek_Device * dev,int dpi,u_long * dim_d,u_short * dark,u_long * dim_w,u_short * white)657 usb_ReadFineCalData( Plustek_Device *dev, int dpi,
658 u_long *dim_d, u_short *dark,
659 u_long *dim_w, u_short *white )
660 {
661 char pfx[30];
662 char tmp[1024];
663 u_short version;
664 FILE *fp;
665
666 DBG( _DBG_INFO, "usb_ReadFineCalData()\n" );
667 if( usb_InCalibrationMode(dev)) {
668 DBG( _DBG_INFO, "- we are in calibration mode!\n" );
669 return SANE_FALSE;
670 }
671
672 if( NULL == dev->calFile ) {
673 DBG( _DBG_ERROR, "- No calibration filename set!\n" );
674 return SANE_FALSE;
675 }
676
677 sprintf( tmp, "%s-fine.cal", dev->calFile );
678 DBG( _DBG_INFO, "- Reading fine calibration data from file\n");
679 DBG( _DBG_INFO, " %s\n", tmp );
680
681 *dim_d = *dim_w = 0;
682
683 fp = fopen( tmp, "r" );
684 if( NULL == fp ) {
685 DBG( _DBG_ERROR, "File %s not found\n", tmp );
686 return SANE_FALSE;
687 }
688
689 /* check version */
690 if( !usb_ReadSpecLine( fp, "version=", tmp )) {
691 DBG( _DBG_ERROR, "Could not find version info!\n" );
692 fclose( fp );
693 return SANE_FALSE;
694 }
695
696 DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp );
697 if( 1 != sscanf( tmp, "0x%04hx", &version )) {
698 DBG( _DBG_ERROR, "Could not decode version info!\n" );
699 fclose( fp );
700 return SANE_FALSE;
701 }
702
703 if( version != _PT_CF_VERSION ) {
704 DBG( _DBG_ERROR, "Versions do not match!\n" );
705 fclose( fp );
706 return SANE_FALSE;
707 }
708
709 usb_CreatePrefix( dev, pfx, SANE_FALSE );
710
711 sprintf( tmp, "%s:%u:%s:dim=", pfx, dpi, "dark" );
712 if( !usb_ReadSamples( fp, tmp, dim_d, dark )) {
713 DBG( _DBG_ERROR, "Error reading dark-calibration data!\n" );
714 fclose( fp );
715 return SANE_FALSE;
716 }
717
718 sprintf( tmp, "%s:%u:%s:dim=", pfx, dpi, "white" );
719 if( !usb_ReadSamples( fp, tmp, dim_w, white )) {
720 DBG( _DBG_ERROR, "Error reading white-calibration data!\n" );
721 fclose( fp );
722 return SANE_FALSE;
723 }
724
725 fclose( fp );
726 return SANE_TRUE;
727 }
728
729 /**
730 */
731 static void
usb_get_shading_part(u_short * buf,u_long offs,u_long src_len,int dst_len)732 usb_get_shading_part(u_short *buf, u_long offs, u_long src_len, int dst_len)
733 {
734 u_short *p_src, *p_dst;
735 int i, j;
736
737 if (src_len == 0 || dst_len == 0)
738 return;
739
740 p_dst = buf;
741 for (i=0; i<3; i++) {
742
743 p_src = buf + src_len * i + offs;
744
745 for (j=0; j<dst_len; j++) {
746
747 *(p_dst++) = *(p_src++);
748 }
749 }
750 }
751
752 /** function to read the fine calibration results from file
753 * and to set the correct part of the calibration buffers for
754 * storing in the device
755 * @param dev - the almigthy device structure
756 * @returns SANE_FALSE when the reading fails or SANE_TRUE on success
757 */
758 static SANE_Bool
usb_FineShadingFromFile(Plustek_Device * dev)759 usb_FineShadingFromFile( Plustek_Device *dev )
760 {
761 ScanDef *scan = &dev->scanning;
762 ScanParam *sp = &scan->sParam;
763 u_short xdpi;
764 u_long dim_w, dim_d, offs;
765
766 xdpi = usb_SetAsicDpiX( dev, sp->UserDpi.x );
767
768 if( !usb_ReadFineCalData( dev, xdpi, &dim_d, a_wDarkShading,
769 &dim_w, a_wWhiteShading)) {
770 return SANE_FALSE;
771 }
772
773 /* now we need to get the correct part of the line... */
774 dim_d /= 3;
775 dim_w /= 3;
776
777 offs = ((u_long)sp->Origin.x * xdpi) / 300;
778
779 usb_GetPhyPixels( dev, sp );
780
781 DBG( _DBG_INFO2, "FINE Calibration from file:\n" );
782 DBG( _DBG_INFO2, "XDPI = %u\n", xdpi );
783 DBG( _DBG_INFO2, "Dim = %lu\n", dim_d );
784 DBG( _DBG_INFO2, "Pixels = %lu\n", sp->Size.dwPixels );
785 DBG( _DBG_INFO2, "PhyPixels = %lu\n", sp->Size.dwPhyPixels );
786 DBG( _DBG_INFO2, "Origin.X = %u\n", sp->Origin.x );
787 DBG( _DBG_INFO2, "Offset = %lu\n", offs );
788
789 usb_get_shading_part(a_wDarkShading, offs, dim_d, sp->Size.dwPhyPixels);
790 usb_get_shading_part(a_wWhiteShading, offs, dim_w, sp->Size.dwPhyPixels);
791
792 return SANE_TRUE;
793 }
794
795 /** function to save the fine calibration results and to set the correct part
796 * of the calibration buffers for storing in the device
797 * @param dev - the almigthy device structure
798 * @param tmp_sp - intermediate scan parameter
799 */
800 static void
usb_SaveCalSetShading(Plustek_Device * dev,ScanParam * tmp_sp)801 usb_SaveCalSetShading( Plustek_Device *dev, ScanParam *tmp_sp )
802 {
803 ScanParam *sp = &dev->scanning.sParam;
804 u_short xdpi;
805 u_long offs;
806
807 if( !dev->adj.cacheCalData )
808 return;
809
810 /* save the values */
811 xdpi = usb_SetAsicDpiX( dev, tmp_sp->UserDpi.x );
812
813 usb_SaveFineCalData( dev, xdpi, a_wDarkShading,
814 a_wWhiteShading, tmp_sp->Size.dwPixels*3 );
815
816 /* now we need to get the correct part of the line... */
817 xdpi = usb_SetAsicDpiX( dev, sp->UserDpi.x );
818 offs = ((u_long)sp->Origin.x * xdpi) / 300;
819 usb_GetPhyPixels( dev, sp );
820
821 DBG( _DBG_INFO2, "FINE Calibration area after saving:\n" );
822 DBG( _DBG_INFO2, "XDPI = %u\n", xdpi );
823 DBG( _DBG_INFO2, "Dim = %lu\n", tmp_sp->Size.dwPixels );
824 DBG( _DBG_INFO2, "Pixels = %lu\n", sp->Size.dwPixels );
825 DBG( _DBG_INFO2, "PhyPixels = %lu\n", sp->Size.dwPhyPixels );
826 DBG( _DBG_INFO2, "Origin.X = %u\n", sp->Origin.x );
827 DBG( _DBG_INFO2, "Offset = %lu\n", offs );
828
829 if (!usb_InCalibrationMode(dev)) {
830
831 usb_get_shading_part( a_wDarkShading, offs,
832 tmp_sp->Size.dwPixels, sp->Size.dwPhyPixels );
833 usb_get_shading_part( a_wWhiteShading, offs,
834 tmp_sp->Size.dwPixels, sp->Size.dwPhyPixels );
835
836 memcpy( tmp_sp, sp, sizeof(ScanParam));
837 tmp_sp->bBitDepth = 16;
838
839 usb_GetPhyPixels( dev, tmp_sp );
840 }
841 }
842
843 /* END PLUSTEK-USBCALFILE.C .................................................*/
844