1 /* HP Scanjet 3900 series - SANE Backend controller
2    Copyright (C) 2005-2009 Jonathan Bravo Lopez <jkdsoft@gmail.com>
3 
4    This file is part of the SANE package.
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    as published by the Free Software Foundation; either version 2
9    of the License, or (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <https://www.gnu.org/licenses/>.
18 
19    As a special exception, the authors of SANE give permission for
20    additional uses of the libraries contained in this release of SANE.
21 
22    The exception is that, if you link a SANE library with other files
23    to produce an executable, this does not by itself cause the
24    resulting executable to be covered by the GNU General Public
25    License.  Your use of that executable is in no way restricted on
26    account of linking the SANE library code into it.
27 
28    This exception does not, however, invalidate any other reasons why
29    the executable file might be covered by the GNU General Public
30    License.
31 
32    If you submit changes to SANE to the maintainers to be included in
33    a subsequent release, you agree by submitting the changes that
34    those changes may be distributed with this exception intact.
35 
36    If you write modifications of your own for SANE, it is your choice
37    whether to permit this exception to apply to your modifications.
38    If you do not wish that, delete this exception notice.
39 */
40 
41 /* Backend Code for SANE*/
42 #define HP3900_CONFIG_FILE "hp3900.conf"
43 #define GAMMA_DEFAULT 1.0
44 
45 #include "../include/sane/config.h"
46 #include "../include/sane/sane.h"
47 #include "../include/sane/sanei.h"
48 #include "../include/sane/sanei_backend.h"
49 #include "../include/sane/sanei_config.h"
50 #include "../include/sane/saneopts.h"
51 #include "../include/sane/sanei_usb.h"
52 #include "../include/sane/sanei_debug.h"
53 
54 #include "hp3900_rts8822.c"
55 
56 struct st_convert
57 {
58   SANE_Int colormode;
59   SANE_Int depth;
60   SANE_Int threshold;
61   SANE_Int negative;
62   SANE_Int real_depth;
63 };
64 
65 /* options enumerator */
66 typedef enum
67 {
68   opt_begin = 0,
69 
70   grp_geometry,
71   opt_tlx, opt_tly, opt_brx, opt_bry,
72   opt_resolution,
73 
74   /* gamma tables */
75   opt_gamma_red,
76   opt_gamma_green,
77   opt_gamma_blue,
78 
79   opt_scantype,
80   opt_colormode,
81   opt_depth,
82   opt_threshold,
83 
84   /* debugging options */
85   grp_debug,
86   opt_model,
87   opt_negative,
88   opt_nogamma,
89   opt_nowshading,
90   opt_realdepth,
91   opt_emulategray,
92   opt_nowarmup,
93   opt_dbgimages,
94   opt_reset,
95 
96   /* device information */
97   grp_info,
98   opt_chipname,
99   opt_chipid,
100   opt_scancount,
101   opt_infoupdate,
102 
103   /* supported buttons. RTS8822 supports up to 6 buttons */
104   grp_sensors,
105   opt_button_0,
106   opt_button_1,
107   opt_button_2,
108   opt_button_3,
109   opt_button_4,
110   opt_button_5,
111 
112   opt_count
113 } EOptionIndex;
114 
115 /* linked list of SANE_Device structures */
116 typedef struct TDevListEntry
117 {
118   struct TDevListEntry *pNext;
119   SANE_Device dev;
120   char *devname;
121 } TDevListEntry;
122 
123 typedef struct
124 {
125   char *pszVendor;
126   char *pszName;
127 } TScannerModel;
128 
129 typedef union
130 {
131   SANE_Word w;
132   SANE_Word *wa;		/* word array */
133   SANE_String s;
134 } TOptionValue;
135 
136 typedef struct
137 {
138   SANE_Int model;
139   SANE_Option_Descriptor aOptions[opt_count];
140   TOptionValue aValues[opt_count];
141   struct params ScanParams;
142 
143   /* lists */
144   SANE_String_Const *list_colormodes;
145   SANE_Int *list_depths;
146   SANE_String_Const *list_models;
147   SANE_Int *list_resolutions;
148   SANE_String_Const *list_sources;
149 
150   SANE_Word *aGammaTable[3];	/* a 16-to-16 bit color lookup table */
151   SANE_Range rng_gamma;
152 
153   /* reading image */
154   SANE_Byte *image;
155   SANE_Byte *rest;
156   SANE_Int rest_amount;
157   SANE_Int mylin;
158 
159   /* conversion settings */
160   struct st_convert cnv;
161 
162   /* ranges */
163   SANE_Range rng_threshold;
164   SANE_Range rng_horizontal;
165   SANE_Range rng_vertical;
166 
167   SANE_Int scan_count;
168   SANE_Int fScanning;		/* TRUE if actively scanning */
169 } TScanner;
170 
171 /* functions to manage backend's options */
172 static void options_init (TScanner * scanner);
173 static void options_free (TScanner * scanner);
174 
175 /* devices listing */
176 static SANE_Int _ReportDevice (TScannerModel * pModel,
177 			       const char *pszDeviceName);
178 static SANE_Status attach_one_device (SANE_String_Const devname);
179 
180 /* capabilities */
181 static SANE_Status bknd_colormodes (TScanner * scanner, SANE_Int model);
182 static void bknd_constrains (TScanner * scanner, SANE_Int source,
183 			     SANE_Int type);
184 static SANE_Status bknd_depths (TScanner * scanner, SANE_Int model);
185 static SANE_Status bknd_info (TScanner * scanner);
186 static SANE_Status bknd_models (TScanner * scanner);
187 static SANE_Status bknd_resolutions (TScanner * scanner, SANE_Int model);
188 static SANE_Status bknd_sources (TScanner * scanner, SANE_Int model);
189 
190 /* conversions */
191 static void Color_Negative (SANE_Byte * buffer, SANE_Int size,
192 			    SANE_Int depth);
193 static void Color_to_Gray (SANE_Byte * buffer, SANE_Int size, SANE_Int depth);
194 static void Gray_to_Lineart (SANE_Byte * buffer, SANE_Int size,
195 			     SANE_Int threshold);
196 static void Depth_16_to_8 (SANE_Byte * from_buffer, SANE_Int size,
197 			   SANE_Byte * to_buffer);
198 
199 /* gamma functions */
200 static void gamma_apply (TScanner * s, SANE_Byte * buffer, SANE_Int size,
201 			 SANE_Int depth);
202 static SANE_Int gamma_create (TScanner * s, double gamma);
203 static void gamma_free (TScanner * s);
204 
205 static SANE_Int Get_Colormode (SANE_String colormode);
206 static SANE_Int Get_Model (SANE_String model);
207 static SANE_Int Get_Source (SANE_String source);
208 static SANE_Int GetUSB_device_model (SANE_String_Const name);
209 static size_t max_string_size (const SANE_String_Const strings[]);
210 
211 static SANE_Status get_button_status (TScanner * s);
212 
213 /* reading buffers */
214 static SANE_Status img_buffers_alloc (TScanner * scanner, SANE_Int size);
215 static SANE_Status img_buffers_free (TScanner * scanner);
216 
217 static SANE_Status option_get (TScanner * scanner, SANE_Int optid,
218 			       void *result);
219 static SANE_Status option_set (TScanner * scanner, SANE_Int optid,
220 			       void *value, SANE_Int * pInfo);
221 
222 static void Set_Coordinates (SANE_Int scantype, SANE_Int resolution,
223 			     struct st_coords *coords);
224 static SANE_Int set_ScannerModel (SANE_Int proposed, SANE_Int product,
225 				  SANE_Int vendor);
226 static void Silent_Compile (void);
227 static SANE_Status Translate_coords (struct st_coords *coords);
228 
229 /* SANE functions */
230 void sane_cancel (SANE_Handle h);
231 void sane_close (SANE_Handle h);
232 SANE_Status sane_control_option (SANE_Handle h, SANE_Int n,
233 				 SANE_Action Action, void *pVal,
234 				 SANE_Int * pInfo);
235 void sane_exit (void);
236 SANE_Status sane_get_devices (const SANE_Device *** device_list,
237 			      SANE_Bool local_only);
238 const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h,
239 							  SANE_Int n);
240 SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p);
241 SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd);
242 SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize);
243 SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h);
244 SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen,
245 		       SANE_Int * len);
246 SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking);
247 SANE_Status sane_start (SANE_Handle h);
248 
249 /* variables */
250 static struct st_device *device = NULL;
251 static TDevListEntry *_pFirstSaneDev = 0;
252 static SANE_Int iNumSaneDev = 0;
253 static const SANE_Device **_pSaneDevList = 0;
254 
255 /* Own functions */
256 
257 static SANE_Status
bknd_resolutions(TScanner * scanner,SANE_Int model)258 bknd_resolutions (TScanner * scanner, SANE_Int model)
259 {
260   SANE_Status rst = SANE_STATUS_INVAL;
261 
262   DBG (DBG_FNC, "> bknd_resolutions(*scanner, model=%i)\n", model);
263 
264   if (scanner != NULL)
265     {
266       SANE_Int *res = NULL;
267 
268       switch (model)
269 	{
270 	case BQ5550:
271 	case UA4900:
272 	  {
273 	    SANE_Int myres[] = { 8, 50, 75, 100, 150, 200, 300, 600, 1200 };
274 
275 	    res = (SANE_Int *) malloc (sizeof (myres));
276 	    if (res != NULL)
277 	      memcpy (res, &myres, sizeof (myres));
278 	  }
279 	  break;
280 
281 	case HPG2710:
282 	case HP3800:
283 	  {
284 	    /* 1200 and 2400 dpi are disabled until problems are solved */
285 	    SANE_Int myres[] = { 7, 50, 75, 100, 150, 200, 300, 600 };
286 
287 	    res = (SANE_Int *) malloc (sizeof (myres));
288 	    if (res != NULL)
289 	      memcpy (res, &myres, sizeof (myres));
290 	  }
291 	  break;
292 
293 	case HP4370:
294 	case HPG3010:
295 	case HPG3110:
296 	  {
297 	    SANE_Int myres[] =
298 	      { 10, 50, 75, 100, 150, 200, 300, 600, 1200, 2400, 4800 };
299 
300 	    res = (SANE_Int *) malloc (sizeof (myres));
301 	    if (res != NULL)
302 	      memcpy (res, &myres, sizeof (myres));
303 	  }
304 	  break;
305 
306 	default:		/* HP3970 & HP4070 & UA4900 */
307 	  {
308 	    SANE_Int myres[] =
309 	      { 9, 50, 75, 100, 150, 200, 300, 600, 1200, 2400 };
310 
311 	    res = (SANE_Int *) malloc (sizeof (myres));
312 	    if (res != NULL)
313 	      memcpy (res, &myres, sizeof (myres));
314 	  }
315 	  break;
316 	}
317 
318       if (res != NULL)
319 	{
320 	  if (scanner->list_resolutions != NULL)
321 	    free (scanner->list_resolutions);
322 
323 	  scanner->list_resolutions = res;
324 	  rst = SANE_STATUS_GOOD;
325 	}
326     }
327 
328   return rst;
329 }
330 
331 static SANE_Status
bknd_models(TScanner * scanner)332 bknd_models (TScanner * scanner)
333 {
334   SANE_Status rst = SANE_STATUS_INVAL;
335 
336   DBG (DBG_FNC, "> bknd_models:\n");
337 
338   if (scanner != NULL)
339     {
340       SANE_String_Const *model = NULL;
341 
342       /* at this moment all devices use the same list */
343       SANE_String_Const mymodel[] =
344 	{ "HP3800", "HP3970", "HP4070", "HP4370", "UA4900", "HPG3010",
345 "BQ5550", "HPG2710", "HPG3110", 0 };
346 
347       /* allocate space to save list */
348       model = (SANE_String_Const *) malloc (sizeof (mymodel));
349       if (model != NULL)
350 	memcpy (model, &mymodel, sizeof (mymodel));
351 
352       if (model != NULL)
353 	{
354 	  /* free previous list */
355 	  if (scanner->list_models != NULL)
356 	    free (scanner->list_models);
357 
358 	  /* set new list */
359 	  scanner->list_models = model;
360 	  rst = SANE_STATUS_GOOD;
361 	}
362     }
363 
364   return rst;
365 }
366 
367 static SANE_Status
bknd_colormodes(TScanner * scanner,SANE_Int model)368 bknd_colormodes (TScanner * scanner, SANE_Int model)
369 {
370   SANE_Status rst = SANE_STATUS_INVAL;
371 
372   DBG (DBG_FNC, "> bknd_colormodes(*scanner, model=%i)\n", model);
373 
374   if (scanner != NULL)
375     {
376       SANE_String_Const *colormode = NULL;
377 
378       /* at this moment all devices use the same list */
379       SANE_String_Const mycolormode[] =
380 	{ SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, 0 };
381 
382       /* silence gcc */
383       model = model;
384 
385       colormode = (SANE_String_Const *) malloc (sizeof (mycolormode));
386       if (colormode != NULL)
387 	memcpy (colormode, &mycolormode, sizeof (mycolormode));
388 
389       if (colormode != NULL)
390 	{
391 	  if (scanner->list_colormodes != NULL)
392 	    free (scanner->list_colormodes);
393 
394 	  scanner->list_colormodes = colormode;
395 	  rst = SANE_STATUS_GOOD;
396 	}
397     }
398 
399   return rst;
400 }
401 
402 static SANE_Status
bknd_sources(TScanner * scanner,SANE_Int model)403 bknd_sources (TScanner * scanner, SANE_Int model)
404 {
405   SANE_Status rst = SANE_STATUS_INVAL;
406 
407   DBG (DBG_FNC, "> bknd_sources(*scanner, model=%i)\n", model);
408 
409   if (scanner != NULL)
410     {
411       SANE_String_Const *source = NULL;
412 
413       switch (model)
414 	{
415 	case UA4900:
416 	  {
417 	    SANE_String_Const mysource[] = { SANE_I18N ("Flatbed"), 0 };
418 	    source = (SANE_String_Const *) malloc (sizeof (mysource));
419 	    if (source != NULL)
420 	      memcpy (source, &mysource, sizeof (mysource));
421 	  }
422 	  break;
423 	default:		/* hp3970, hp4070, hp4370 and others */
424 	  {
425 	    SANE_String_Const mysource[] =
426 	      { SANE_I18N ("Flatbed"), SANE_I18N ("Slide"),
427 SANE_I18N ("Negative"), 0 };
428 	    source = (SANE_String_Const *) malloc (sizeof (mysource));
429 	    if (source != NULL)
430 	      memcpy (source, &mysource, sizeof (mysource));
431 	  }
432 	  break;
433 	}
434 
435       if (source != NULL)
436 	{
437 	  if (scanner->list_sources != NULL)
438 	    free (scanner->list_sources);
439 
440 	  scanner->list_sources = source;
441 	  rst = SANE_STATUS_GOOD;
442 	}
443     }
444 
445   return rst;
446 }
447 
448 static SANE_Status
bknd_depths(TScanner * scanner,SANE_Int model)449 bknd_depths (TScanner * scanner, SANE_Int model)
450 {
451   SANE_Status rst = SANE_STATUS_INVAL;
452 
453   DBG (DBG_FNC, "> bknd_depths(*scanner, model=%i\n", model);
454 
455   if (scanner != NULL)
456     {
457       SANE_Int *depth = NULL;
458 
459       /* at this moment all devices use the same list */
460       SANE_Int mydepth[] = { 2, 8, 16 };	/*{3, 8, 12, 16}; */
461 
462       /* silence gcc */
463       model = model;
464 
465       depth = (SANE_Int *) malloc (sizeof (mydepth));
466       if (depth != NULL)
467 	memcpy (depth, &mydepth, sizeof (mydepth));
468 
469       if (depth != NULL)
470 	{
471 	  if (scanner->list_depths != NULL)
472 	    free (scanner->list_depths);
473 
474 	  scanner->list_depths = depth;
475 	  rst = SANE_STATUS_GOOD;
476 	}
477     }
478 
479   return rst;
480 }
481 
482 static SANE_Status
bknd_info(TScanner * scanner)483 bknd_info (TScanner * scanner)
484 {
485   SANE_Status rst = SANE_STATUS_INVAL;
486 
487   DBG (DBG_FNC, "> bknd_info(*scanner)");
488 
489   if (scanner != NULL)
490     {
491       char data[256];
492 
493       /* update chipset name */
494       Chipset_Name (device, data, 255);
495       if (scanner->aValues[opt_chipname].s != NULL)
496 	{
497 	  free (scanner->aValues[opt_chipname].s);
498 	  scanner->aValues[opt_chipname].s = NULL;
499 	}
500 
501       scanner->aValues[opt_chipname].s = strdup (data);
502       scanner->aOptions[opt_chipname].size = strlen (data) + 1;
503 
504       /* update chipset id */
505       scanner->aValues[opt_chipid].w = Chipset_ID (device);
506 
507       /* update scans counter */
508       scanner->aValues[opt_scancount].w = RTS_ScanCounter_Get (device);
509 
510       rst = SANE_STATUS_GOOD;
511     }
512 
513   return rst;
514 }
515 
516 static SANE_Int
GetUSB_device_model(SANE_String_Const name)517 GetUSB_device_model (SANE_String_Const name)
518 {
519   SANE_Int usbid, model;
520 
521   /* default model is unknown */
522   model = -1;
523 
524   /* open usb device */
525   if (sanei_usb_open (name, &usbid) == SANE_STATUS_GOOD)
526     {
527       SANE_Int vendor, product;
528 
529       if (sanei_usb_get_vendor_product (usbid, &vendor, &product) ==
530 	  SANE_STATUS_GOOD)
531 	model = Device_get (product, vendor);
532 
533       sanei_usb_close (usbid);
534     }
535 
536   return model;
537 }
538 
539 static void
Silent_Compile(void)540 Silent_Compile (void)
541 {
542   /*
543      There are some functions in hp3900_rts8822.c that aren't used yet.
544      To avoid compilation warnings we will use them here
545    */
546 
547   SANE_Byte a = 1;
548 
549   if (a == 0)
550     {
551       Buttons_Status (device);
552       Calib_WriteTable (device, NULL, 0, 0);
553       Gamma_GetTables (device, NULL);
554     }
555 }
556 
557 static void
bknd_constrains(TScanner * scanner,SANE_Int source,SANE_Int type)558 bknd_constrains (TScanner * scanner, SANE_Int source, SANE_Int type)
559 {
560   struct st_coords *coords = Constrains_Get (device, source);
561 
562   if ((coords != NULL) && (scanner != NULL))
563     {
564       switch (type)
565 	{
566 	case 1:		/* Y */
567 	  scanner->rng_vertical.max = coords->height;
568 	  break;
569 	default:		/* X */
570 	  scanner->rng_horizontal.max = coords->width;
571 	  break;
572 	}
573     }
574 }
575 
576 static SANE_Status
img_buffers_free(TScanner * scanner)577 img_buffers_free (TScanner * scanner)
578 {
579   if (scanner != NULL)
580     {
581       if (scanner->image != NULL)
582 	{
583 	  free (scanner->image);
584 	  scanner->image = NULL;
585 	}
586 
587       if (scanner->rest != NULL)
588 	{
589 	  free (scanner->rest);
590 	  scanner->rest = NULL;
591 	}
592 
593       scanner->rest_amount = 0;
594     }
595 
596   return SANE_STATUS_GOOD;
597 }
598 
599 static SANE_Status
img_buffers_alloc(TScanner * scanner,SANE_Int size)600 img_buffers_alloc (TScanner * scanner, SANE_Int size)
601 {
602   SANE_Status rst;
603 
604   /* default result at this point */
605   rst = SANE_STATUS_INVAL;
606 
607   if (scanner != NULL)
608     {
609       /* default result at this point */
610       rst = SANE_STATUS_NO_MEM;
611 
612       /* free previous allocs */
613       img_buffers_free (scanner);
614 
615       scanner->image = (SANE_Byte *) malloc (size * sizeof (SANE_Byte));
616       if (scanner->image != NULL)
617 	{
618 	  scanner->rest = (SANE_Byte *) malloc (size * sizeof (SANE_Byte));
619 	  if (scanner->rest != NULL)
620 	    rst = SANE_STATUS_GOOD;	/* ok !! */
621 	}
622 
623       if (rst != SANE_STATUS_GOOD)
624 	img_buffers_free (scanner);
625     }
626 
627   return rst;
628 }
629 
630 static SANE_Int
set_ScannerModel(SANE_Int proposed,SANE_Int product,SANE_Int vendor)631 set_ScannerModel (SANE_Int proposed, SANE_Int product, SANE_Int vendor)
632 {
633   /* This function will set the device behaviour */
634 
635   SANE_Int current = Device_get (product, vendor);
636   char *sdevname[10] =
637     { "Unknown", "HP3970", "HP4070", "HP4370", "UA4900", "HP3800", "HPG3010",
638 "BQ5550", "HPG2710", "HPG3110" };
639 
640   DBG (DBG_FNC,
641        "> set_ScannerModel(proposed=%i, product=%04x, vendor=%04x)\n",
642        proposed, product, vendor);
643 
644   if (proposed < 0)
645     {
646       if ((current < 0) || (current >= DEVSCOUNT))
647 	{
648 	  DBG (DBG_VRB, " -> Unknown device. Defaulting to HP3970...\n");
649 	  RTS_Debug->dev_model = HP3970;
650 	}
651       else
652 	{
653 	  RTS_Debug->dev_model = current;
654 	  DBG (DBG_VRB, " -> Device model is %s\n", sdevname[current + 1]);
655 	}
656     }
657   else
658     {
659       if (proposed < DEVSCOUNT)
660 	{
661 	  RTS_Debug->dev_model = proposed;
662 	  DBG (DBG_VRB, " -> Device %s ,  treating as %s ...\n",
663 	       sdevname[current + 1], sdevname[proposed + 1]);
664 	}
665       else
666 	{
667 	  if ((current >= 0) && (current < DEVSCOUNT))
668 	    {
669 	      RTS_Debug->dev_model = current;
670 	      DBG (DBG_VRB,
671 		   " -> Device not supported. Defaulting to %s ...\n",
672 		   sdevname[current + 1]);
673 	    }
674 	  else
675 	    {
676 	      RTS_Debug->dev_model = HP3970;
677 	      DBG (DBG_VRB,
678 		   "-> Device not supported. Defaulting to HP3970...\n");
679 	    }
680 	}
681     }
682 
683   return OK;
684 }
685 
686 static void
Set_Coordinates(SANE_Int scantype,SANE_Int resolution,struct st_coords * coords)687 Set_Coordinates (SANE_Int scantype, SANE_Int resolution,
688 		 struct st_coords *coords)
689 {
690   struct st_coords *limits = Constrains_Get (device, scantype);
691 
692   DBG (DBG_FNC, "> Set_Coordinates(res=%i, *coords):\n", resolution);
693 
694   if (coords->left == -1)
695     coords->left = 0;
696 
697   if (coords->width == -1)
698     coords->width = limits->width;
699 
700   if (coords->top == -1)
701     coords->top = 0;
702 
703   if (coords->height == -1)
704     coords->height = limits->height;
705 
706   DBG (DBG_FNC, " -> Coords [MM] : xy(%i, %i) wh(%i, %i)\n", coords->left,
707        coords->top, coords->width, coords->height);
708 
709   coords->left = MM_TO_PIXEL (coords->left, resolution);
710   coords->width = MM_TO_PIXEL (coords->width, resolution);
711   coords->top = MM_TO_PIXEL (coords->top, resolution);
712   coords->height = MM_TO_PIXEL (coords->height, resolution);
713 
714   DBG (DBG_FNC, " -> Coords [px] : xy(%i, %i) wh(%i, %i)\n", coords->left,
715        coords->top, coords->width, coords->height);
716 
717   Constrains_Check (device, resolution, scantype, coords);
718 
719   DBG (DBG_FNC, " -> Coords [check]: xy(%i, %i) wh(%i, %i)\n", coords->left,
720        coords->top, coords->width, coords->height);
721 }
722 
723 static void
Color_Negative(SANE_Byte * buffer,SANE_Int size,SANE_Int depth)724 Color_Negative (SANE_Byte * buffer, SANE_Int size, SANE_Int depth)
725 {
726   if (buffer != NULL)
727     {
728       SANE_Int a;
729       SANE_Int max_value = (1 << depth) - 1;
730 
731       if (depth > 8)
732 	{
733 	  USHORT *sColor = (void *) buffer;
734 	  for (a = 0; a < size / 2; a++)
735 	    {
736 	      *sColor = max_value - *sColor;
737 	      sColor++;
738 	    }
739 	}
740       else
741 	{
742 	  for (a = 0; a < size; a++)
743 	    *(buffer + a) = max_value - *(buffer + a);
744 	}
745     }
746 }
747 
748 static SANE_Status
get_button_status(TScanner * s)749 get_button_status (TScanner * s)
750 {
751   if (s != NULL)
752     {
753       SANE_Int a, b, status, btn;
754 
755       b = 1;
756       status = Buttons_Released (device) & 63;
757       for (a = 0; a < 6; a++)
758 	{
759 	  if ((status & b) != 0)
760 	    {
761 	      btn = Buttons_Order (device, b);
762 	      if (btn != -1)
763 		s->aValues[opt_button_0 + btn].w = SANE_TRUE;
764 	    }
765 
766 	  b <<= 1;
767 	}
768     }
769 
770   return SANE_STATUS_GOOD;
771 }
772 
773 static void
Depth_16_to_8(SANE_Byte * from_buffer,SANE_Int size,SANE_Byte * to_buffer)774 Depth_16_to_8 (SANE_Byte * from_buffer, SANE_Int size, SANE_Byte * to_buffer)
775 {
776   if ((from_buffer != NULL) && (to_buffer != NULL))
777     {
778       SANE_Int a, b;
779 
780       a = 1;
781       b = 0;
782 
783       while (a < size)
784 	{
785 	  *(to_buffer + b) = *(from_buffer + a);
786 	  a += 2;
787 	  b++;
788 	}
789     }
790 }
791 
792 static void
Gray_to_Lineart(SANE_Byte * buffer,SANE_Int size,SANE_Int threshold)793 Gray_to_Lineart (SANE_Byte * buffer, SANE_Int size, SANE_Int threshold)
794 {
795   /* code provided by tobias leutwein */
796 
797   if (buffer != NULL)
798     {
799       SANE_Byte toBufferByte;
800       SANE_Int fromBufferPos_i = 0;
801       SANE_Int toBufferPos_i = 0;
802       SANE_Int bitPos_i;
803 
804       while (fromBufferPos_i < size)
805 	{
806 	  toBufferByte = 0;
807 
808 	  for (bitPos_i = 7; bitPos_i != (-1); bitPos_i--)
809 	    {
810 	      if ((fromBufferPos_i < size)
811 		  && (buffer[fromBufferPos_i] < threshold))
812 		toBufferByte |= (1u << bitPos_i);
813 
814 	      fromBufferPos_i++;
815 	    }
816 
817 	  buffer[toBufferPos_i] = toBufferByte;
818 	  toBufferPos_i++;
819 	}
820     }
821 }
822 
823 static void
Color_to_Gray(SANE_Byte * buffer,SANE_Int size,SANE_Int depth)824 Color_to_Gray (SANE_Byte * buffer, SANE_Int size, SANE_Int depth)
825 {
826   /* converts 3 color channel into 1 gray channel of specified bit depth */
827 
828   if (buffer != NULL)
829     {
830       SANE_Int c, chn, chn_size;
831       SANE_Byte *ptr_src = NULL;
832       SANE_Byte *ptr_dst = NULL;
833       float data, chn_data;
834       float coef[3] = { 0.299, 0.587, 0.114 };	/* coefficients per channel */
835 
836       chn_size = (depth > 8) ? 2 : 1;
837       ptr_src = (void *) buffer;
838       ptr_dst = (void *) buffer;
839 
840       for (c = 0; c < size / (3 * chn_size); c++)
841 	{
842 	  data = 0.;
843 
844 	  /* get, apply coeffs and sum channels */
845 	  for (chn = 0; chn < 3; chn++)
846 	    {
847 	      chn_data = data_lsb_get (ptr_src + (chn * chn_size), chn_size);
848 	      data += (chn_data * coef[chn]);
849 	    }
850 
851 	  /* save result */
852 	  data_lsb_set (ptr_dst, (SANE_Int) data, chn_size);
853 
854 	  ptr_src += 3 * chn_size;	/* next triplet */
855 	  ptr_dst += chn_size;
856 	}
857     }
858 }
859 
860 static void
gamma_free(TScanner * s)861 gamma_free (TScanner * s)
862 {
863   DBG (DBG_FNC, "> gamma_free()\n");
864 
865   if (s != NULL)
866     {
867       /* Destroy gamma tables */
868       SANE_Int a;
869 
870       for (a = CL_RED; a <= CL_BLUE; a++)
871 	{
872 	  if (s->aGammaTable[a] != NULL)
873 	    {
874 	      free (s->aGammaTable[a]);
875 	      s->aGammaTable[a] = NULL;
876 	    }
877 	}
878     }
879 }
880 
881 static SANE_Int
gamma_create(TScanner * s,double gamma)882 gamma_create (TScanner * s, double gamma)
883 {
884   SANE_Int rst = ERROR;		/* by default */
885 
886   DBG (DBG_FNC, "> gamma_create(*s)\n");
887 
888   if (s != NULL)
889     {
890       SANE_Int a;
891       double value, c;
892 
893       /* default result */
894       rst = OK;
895 
896       /* destroy previous gamma tables */
897       gamma_free (s);
898 
899       /* check gamma value */
900       if (gamma < 0)
901 	gamma = GAMMA_DEFAULT;
902 
903       /* allocate space for 16 bit gamma tables */
904       for (a = CL_RED; a <= CL_BLUE; a++)
905 	{
906 	  s->aGammaTable[a] = malloc (65536 * sizeof (SANE_Word));
907 	  if (s->aGammaTable[a] == NULL)
908 	    {
909 	      rst = ERROR;
910 	      break;
911 	    }
912 	}
913 
914       if (rst == OK)
915 	{
916 	  /* fill tables */
917 	  for (a = 0; a < 65536; a++)
918 	    {
919 	      value = (a / (65536. - 1));
920 	      value = pow (value, (1. / gamma));
921 	      value = value * (65536. - 1);
922 
923 	      c = (SANE_Int) value;
924 	      if (c > (65536. - 1))
925 		c = (65536. - 1);
926 	      else if (c < 0)
927 		c = 0;
928 
929 	      s->aGammaTable[CL_RED][a] = c;
930 	      s->aGammaTable[CL_GREEN][a] = c;
931 	      s->aGammaTable[CL_BLUE][a] = c;
932 	    }
933 	}
934       else
935 	gamma_free (s);
936     }
937 
938   return rst;
939 }
940 
941 static void
gamma_apply(TScanner * s,SANE_Byte * buffer,SANE_Int size,SANE_Int depth)942 gamma_apply (TScanner * s, SANE_Byte * buffer, SANE_Int size, SANE_Int depth)
943 {
944   if ((s != NULL) && (buffer != NULL))
945     {
946       SANE_Int c;
947       SANE_Int dot_size = 3 * ((depth > 8) ? 2 : 1);
948       SANE_Byte *pColor = buffer;
949       USHORT *sColor = (void *) buffer;
950 
951       if ((s->aGammaTable[CL_RED] != NULL)
952 	  && (s->aGammaTable[CL_GREEN] != NULL)
953 	  && (s->aGammaTable[CL_BLUE] != NULL))
954 	{
955 	  for (c = 0; c < size / dot_size; c++)
956 	    {
957 	      if (depth > 8)
958 		{
959 		  *sColor = s->aGammaTable[CL_RED][*sColor];
960 		  *(sColor + 1) = s->aGammaTable[CL_GREEN][*(sColor + 1)];
961 		  *(sColor + 2) = s->aGammaTable[CL_BLUE][*(sColor + 2)];
962 		  sColor += 3;
963 		}
964 	      else
965 		{
966 		  /* 8 bits gamma */
967 		  *pColor =
968 		    (s->aGammaTable[CL_RED][*pColor * 256] >> 8) & 0xff;
969 		  *(pColor + 1) =
970 		    (s->
971 		     aGammaTable[CL_GREEN][*(pColor + 1) * 256] >> 8) & 0xff;
972 		  *(pColor + 2) =
973 		    (s->
974 		     aGammaTable[CL_BLUE][*(pColor + 2) * 256] >> 8) & 0xff;
975 		  pColor += 3;
976 		}
977 	    }
978 	}
979     }
980 }
981 
982 static SANE_Int
Get_Model(SANE_String model)983 Get_Model (SANE_String model)
984 {
985   SANE_Int rst;
986 
987   if (strcmp (model, "HP3800") == 0)
988     rst = HP3800;
989   else if (strcmp (model, "HPG2710") == 0)
990     rst = HPG2710;
991   else if (strcmp (model, "HP3970") == 0)
992     rst = HP3970;
993   else if (strcmp (model, "HP4070") == 0)
994     rst = HP4070;
995   else if (strcmp (model, "HP4370") == 0)
996     rst = HP4370;
997   else if (strcmp (model, "HPG3010") == 0)
998     rst = HPG3010;
999   else if (strcmp (model, "HPG3110") == 0)
1000     rst = HPG3110;
1001   else if (strcmp (model, "UA4900") == 0)
1002     rst = UA4900;
1003   else if (strcmp (model, "BQ5550") == 0)
1004     rst = BQ5550;
1005   else
1006     rst = HP3970;		/* default */
1007 
1008   return rst;
1009 }
1010 
1011 static SANE_Int
Get_Source(SANE_String source)1012 Get_Source (SANE_String source)
1013 {
1014   SANE_Int rst;
1015 
1016   if (strcmp (source, SANE_I18N ("Flatbed")) == 0)
1017     rst = ST_NORMAL;
1018   else if (strcmp (source, SANE_I18N ("Slide")) == 0)
1019     rst = ST_TA;
1020   else if (strcmp (source, SANE_I18N ("Negative")) == 0)
1021     rst = ST_NEG;
1022   else
1023     rst = ST_NORMAL;		/* default */
1024 
1025   return rst;
1026 }
1027 
1028 static SANE_Int
Get_Colormode(SANE_String colormode)1029 Get_Colormode (SANE_String colormode)
1030 {
1031   SANE_Int rst;
1032 
1033   if (strcmp (colormode, SANE_VALUE_SCAN_MODE_COLOR) == 0)
1034     rst = CM_COLOR;
1035   else if (strcmp (colormode, SANE_VALUE_SCAN_MODE_GRAY) == 0)
1036     rst = CM_GRAY;
1037   else if (strcmp (colormode, SANE_VALUE_SCAN_MODE_LINEART) == 0)
1038     rst = CM_LINEART;
1039   else
1040     rst = CM_COLOR;		/* default */
1041 
1042   return rst;
1043 }
1044 
1045 static SANE_Status
Translate_coords(struct st_coords * coords)1046 Translate_coords (struct st_coords *coords)
1047 {
1048   SANE_Int data;
1049 
1050   DBG (DBG_FNC, "> Translate_coords(*coords)\n");
1051 
1052   if ((coords->left < 0) || (coords->top < 0) ||
1053       (coords->width < 0) || (coords->height < 0))
1054     return SANE_STATUS_INVAL;
1055 
1056   if (coords->width < coords->left)
1057     {
1058       data = coords->left;
1059       coords->left = coords->width;
1060       coords->width = data;
1061     }
1062 
1063   if (coords->height < coords->top)
1064     {
1065       data = coords->top;
1066       coords->top = coords->height;
1067       coords->height = data;
1068     }
1069 
1070   coords->width -= coords->left;
1071   coords->height -= coords->top;
1072 
1073   if (coords->width == 0)
1074     coords->width++;
1075 
1076   if (coords->height == 0)
1077     coords->height++;
1078 
1079   return SANE_STATUS_GOOD;
1080 }
1081 
1082 static size_t
max_string_size(const SANE_String_Const strings[])1083 max_string_size (const SANE_String_Const strings[])
1084 {
1085   size_t size, max_size = 0;
1086   SANE_Int i;
1087 
1088   DBG (DBG_FNC, "> max_string_size:\n");
1089 
1090   for (i = 0; strings[i]; ++i)
1091     {
1092       size = strlen (strings[i]) + 1;
1093       if (size > max_size)
1094 	max_size = size;
1095     }
1096 
1097   return max_size;
1098 }
1099 
1100 static void
options_free(TScanner * scanner)1101 options_free (TScanner * scanner)
1102 {
1103   /* frees all information contained in controls */
1104 
1105   DBG (DBG_FNC, "> options_free\n");
1106 
1107   if (scanner != NULL)
1108     {
1109       SANE_Int i;
1110       SANE_Option_Descriptor *pDesc;
1111       TOptionValue *pVal;
1112 
1113       /* free gamma tables */
1114       gamma_free (scanner);
1115 
1116       /* free lists */
1117       if (scanner->list_resolutions != NULL)
1118 	free (scanner->list_resolutions);
1119 
1120       if (scanner->list_depths != NULL)
1121 	free (scanner->list_depths);
1122 
1123       if (scanner->list_sources != NULL)
1124 	free (scanner->list_sources);
1125 
1126       if (scanner->list_colormodes != NULL)
1127 	free (scanner->list_colormodes);
1128 
1129       if (scanner->list_models != NULL)
1130 	free (scanner->list_models);
1131 
1132       /* free values in certain controls */
1133       for (i = opt_begin; i < opt_count; i++)
1134 	{
1135 	  pDesc = &scanner->aOptions[i];
1136 	  pVal = &scanner->aValues[i];
1137 
1138 	  if (pDesc->type == SANE_TYPE_STRING)
1139 	    {
1140 	      if (pVal->s != NULL)
1141 		free (pVal->s);
1142 	    }
1143 	}
1144     }
1145 }
1146 
1147 static void
options_init(TScanner * scanner)1148 options_init (TScanner * scanner)
1149 {
1150   /* initializes all controls */
1151 
1152   DBG (DBG_FNC, "> options_init\n");
1153 
1154   if (scanner != NULL)
1155     {
1156       SANE_Int i;
1157       SANE_Option_Descriptor *pDesc;
1158       TOptionValue *pVal;
1159 
1160       /* set gamma */
1161       gamma_create (scanner, 1.0);
1162 
1163       /* color conversion */
1164       scanner->cnv.colormode = -1;
1165       scanner->cnv.negative = FALSE;
1166       scanner->cnv.threshold = 40;
1167       scanner->cnv.real_depth = FALSE;
1168       scanner->cnv.depth = -1;
1169 
1170       /* setting threshold */
1171       scanner->rng_threshold.min = 0;
1172       scanner->rng_threshold.max = 255;
1173       scanner->rng_threshold.quant = 0;
1174 
1175       /* setting gamma range (16 bits depth) */
1176       scanner->rng_gamma.min = 0;
1177       scanner->rng_gamma.max = 65535;
1178       scanner->rng_gamma.quant = 0;
1179 
1180       /* setting default horizontal constraint in millimeters */
1181       scanner->rng_horizontal.min = 0;
1182       scanner->rng_horizontal.max = 220;
1183       scanner->rng_horizontal.quant = 1;
1184 
1185       /* setting default vertical constraint in millimeters */
1186       scanner->rng_vertical.min = 0;
1187       scanner->rng_vertical.max = 300;
1188       scanner->rng_vertical.quant = 1;
1189 
1190       /* allocate option lists */
1191       bknd_info (scanner);
1192       bknd_colormodes (scanner, RTS_Debug->dev_model);
1193       bknd_depths (scanner, RTS_Debug->dev_model);
1194       bknd_models (scanner);
1195       bknd_resolutions (scanner, RTS_Debug->dev_model);
1196       bknd_sources (scanner, RTS_Debug->dev_model);
1197 
1198       /* By default preview scan */
1199       scanner->ScanParams.scantype = ST_NORMAL;
1200       scanner->ScanParams.colormode = CM_COLOR;
1201       scanner->ScanParams.resolution_x = 75;
1202       scanner->ScanParams.resolution_y = 75;
1203       scanner->ScanParams.coords.left = 0;
1204       scanner->ScanParams.coords.top = 0;
1205       scanner->ScanParams.coords.width = 220;
1206       scanner->ScanParams.coords.height = 300;
1207       scanner->ScanParams.depth = 8;
1208       scanner->ScanParams.channel = 0;
1209 
1210       for (i = opt_begin; i < opt_count; i++)
1211 	{
1212 	  pDesc = &scanner->aOptions[i];
1213 	  pVal = &scanner->aValues[i];
1214 
1215 	  /* defaults */
1216 	  pDesc->name = "";
1217 	  pDesc->title = "";
1218 	  pDesc->desc = "";
1219 	  pDesc->type = SANE_TYPE_INT;
1220 	  pDesc->unit = SANE_UNIT_NONE;
1221 	  pDesc->size = sizeof (SANE_Word);
1222 	  pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1223 	  pDesc->cap = 0;
1224 
1225 	  switch (i)
1226 	    {
1227 	    case opt_begin:
1228 	      pDesc->title = SANE_TITLE_NUM_OPTIONS;
1229 	      pDesc->desc = SANE_DESC_NUM_OPTIONS;
1230 	      pDesc->cap = SANE_CAP_SOFT_DETECT;
1231 	      pVal->w = (SANE_Word) opt_count;
1232 	      break;
1233 
1234 	    case grp_geometry:
1235 	      pDesc->name = SANE_NAME_GEOMETRY;
1236 	      pDesc->title = SANE_TITLE_GEOMETRY;
1237 	      pDesc->desc = SANE_DESC_GEOMETRY;
1238 	      pDesc->type = SANE_TYPE_GROUP;
1239 	      pDesc->unit = SANE_UNIT_NONE;
1240 	      pDesc->size = 0;
1241 	      pDesc->cap = 0;
1242 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1243 	      pDesc->constraint.range = 0;
1244 	      pVal->w = 0;
1245 	      break;
1246 
1247 	    case opt_tlx:
1248 	      pDesc->name = SANE_NAME_SCAN_TL_X;
1249 	      pDesc->title = SANE_TITLE_SCAN_TL_X;
1250 	      pDesc->desc = SANE_DESC_SCAN_TL_X;
1251 	      pDesc->unit = SANE_UNIT_MM;
1252 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1253 	      pDesc->constraint.range = &scanner->rng_horizontal;
1254 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1255 	      pVal->w = 0;
1256 	      break;
1257 
1258 	    case opt_tly:
1259 	      pDesc->name = SANE_NAME_SCAN_TL_Y;
1260 	      pDesc->title = SANE_TITLE_SCAN_TL_Y;
1261 	      pDesc->desc = SANE_DESC_SCAN_TL_Y;
1262 	      pDesc->unit = SANE_UNIT_MM;
1263 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1264 	      pDesc->constraint.range = &scanner->rng_vertical;
1265 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1266 	      pVal->w = 0;
1267 	      break;
1268 
1269 	    case opt_brx:
1270 	      pDesc->name = SANE_NAME_SCAN_BR_X;
1271 	      pDesc->title = SANE_TITLE_SCAN_BR_X;
1272 	      pDesc->desc = SANE_DESC_SCAN_BR_X;
1273 	      pDesc->unit = SANE_UNIT_MM;
1274 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1275 	      pDesc->constraint.range = &scanner->rng_horizontal;
1276 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1277 	      pVal->w = scanner->rng_horizontal.max;
1278 	      break;
1279 
1280 	    case opt_bry:
1281 	      pDesc->name = SANE_NAME_SCAN_BR_Y;
1282 	      pDesc->title = SANE_TITLE_SCAN_BR_Y;
1283 	      pDesc->desc = SANE_DESC_SCAN_BR_Y;
1284 	      pDesc->unit = SANE_UNIT_MM;
1285 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1286 	      pDesc->constraint.range = &scanner->rng_vertical;
1287 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1288 	      pVal->w = scanner->rng_vertical.max;
1289 	      break;
1290 
1291 	    case opt_resolution:
1292 	      pDesc->name = SANE_NAME_SCAN_RESOLUTION;
1293 	      pDesc->title = SANE_TITLE_SCAN_RESOLUTION;
1294 	      pDesc->desc = SANE_DESC_SCAN_RESOLUTION;
1295 	      pDesc->unit = SANE_UNIT_DPI;
1296 	      pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST;
1297 	      pDesc->constraint.word_list = scanner->list_resolutions;
1298 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1299 	      pVal->w = scanner->list_resolutions[1];
1300 	      break;
1301 
1302 	    case opt_gamma_red:
1303 	      pDesc->name = SANE_NAME_GAMMA_VECTOR_R;
1304 	      pDesc->title = SANE_TITLE_GAMMA_VECTOR_R;
1305 	      pDesc->desc = SANE_DESC_GAMMA_VECTOR_R;
1306 	      pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word);
1307 	      pDesc->unit = SANE_UNIT_NONE;
1308 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1309 	      pDesc->constraint.range = &scanner->rng_gamma;
1310 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1311 	      pVal->wa = scanner->aGammaTable[CL_RED];
1312 	      break;
1313 
1314 	    case opt_gamma_green:
1315 	      pDesc->name = SANE_NAME_GAMMA_VECTOR_G;
1316 	      pDesc->title = SANE_TITLE_GAMMA_VECTOR_G;
1317 	      pDesc->desc = SANE_DESC_GAMMA_VECTOR_G;
1318 	      pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word);
1319 	      pDesc->unit = SANE_UNIT_NONE;
1320 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1321 	      pDesc->constraint.range = &scanner->rng_gamma;
1322 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1323 	      pVal->wa = scanner->aGammaTable[CL_GREEN];
1324 	      break;
1325 
1326 	    case opt_gamma_blue:
1327 	      pDesc->name = SANE_NAME_GAMMA_VECTOR_B;
1328 	      pDesc->title = SANE_TITLE_GAMMA_VECTOR_B;
1329 	      pDesc->desc = SANE_DESC_GAMMA_VECTOR_B;
1330 	      pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word);
1331 	      pDesc->unit = SANE_UNIT_NONE;
1332 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1333 	      pDesc->constraint.range = &scanner->rng_gamma;
1334 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1335 	      pVal->wa = scanner->aGammaTable[CL_BLUE];
1336 	      break;
1337 
1338 	    case opt_scantype:
1339 	      pDesc->name = SANE_NAME_SCAN_SOURCE;
1340 	      pDesc->title = SANE_TITLE_SCAN_SOURCE;
1341 	      pDesc->desc = SANE_DESC_SCAN_SOURCE;
1342 	      pDesc->type = SANE_TYPE_STRING;
1343 	      pDesc->size = max_string_size (scanner->list_sources);
1344 	      pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1345 	      pDesc->constraint.string_list = scanner->list_sources;
1346 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1347 	      pVal->s = strdup (scanner->list_sources[0]);
1348 	      break;
1349 
1350 	    case opt_colormode:
1351 	      pDesc->name = SANE_NAME_SCAN_MODE;
1352 	      pDesc->title = SANE_TITLE_SCAN_MODE;
1353 	      pDesc->desc = SANE_DESC_SCAN_MODE;
1354 	      pDesc->type = SANE_TYPE_STRING;
1355 	      pDesc->size = max_string_size (scanner->list_colormodes);
1356 	      pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1357 	      pDesc->constraint.string_list = scanner->list_colormodes;
1358 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1359 	      pVal->s = strdup (scanner->list_colormodes[0]);
1360 	      break;
1361 
1362 	    case opt_depth:
1363 	      pDesc->name = SANE_NAME_BIT_DEPTH;
1364 	      pDesc->title = SANE_TITLE_BIT_DEPTH;
1365 	      pDesc->desc = SANE_DESC_BIT_DEPTH;
1366 	      pDesc->type = SANE_TYPE_INT;
1367 	      pDesc->unit = SANE_UNIT_BIT;
1368 	      pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST;
1369 	      pDesc->constraint.word_list = scanner->list_depths;
1370 	      pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1371 	      pVal->w = scanner->list_depths[1];
1372 	      break;
1373 
1374 	    case opt_threshold:
1375 	      pDesc->name = SANE_NAME_THRESHOLD;
1376 	      pDesc->title = SANE_TITLE_THRESHOLD;
1377 	      pDesc->desc = SANE_DESC_THRESHOLD;
1378 	      pDesc->type = SANE_TYPE_INT;
1379 	      pDesc->unit = SANE_UNIT_NONE;
1380 	      pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
1381 	      pDesc->constraint.range = &scanner->rng_threshold;
1382 	      pDesc->cap |=
1383 		SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT |
1384 		SANE_CAP_INACTIVE;
1385 	      pVal->w = 0x80;
1386 	      break;
1387 
1388 	      /* debugging options */
1389 	    case grp_debug:
1390 	      pDesc->name = "grp_debug";
1391 	      pDesc->title = SANE_I18N ("Debugging Options");
1392 	      pDesc->desc = "";
1393 	      pDesc->type = SANE_TYPE_GROUP;
1394 	      pDesc->unit = SANE_UNIT_NONE;
1395 	      pDesc->size = 0;
1396 	      pDesc->cap = SANE_CAP_ADVANCED;
1397 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1398 	      pDesc->constraint.range = 0;
1399 	      pVal->w = 0;
1400 	      break;
1401 
1402 	    case opt_model:
1403 	      pDesc->name = "opt_model";
1404 	      pDesc->title = SANE_I18N ("Scanner model");
1405 	      pDesc->desc =
1406 		SANE_I18N
1407 		("Allows one to test device behavior with other supported models");
1408 	      pDesc->type = SANE_TYPE_STRING;
1409 	      pDesc->size = max_string_size (scanner->list_models);
1410 	      pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1411 	      pDesc->constraint.string_list = scanner->list_models;
1412 	      pDesc->cap =
1413 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT |
1414 		SANE_CAP_SOFT_DETECT;
1415 	      pVal->s = strdup (scanner->list_models[0]);
1416 	      break;
1417 
1418 	    case opt_negative:
1419 	      pDesc->name = "opt_negative";
1420 	      pDesc->title = SANE_I18N ("Negative");
1421 	      pDesc->desc = SANE_I18N ("Image colors will be inverted");
1422 	      pDesc->type = SANE_TYPE_BOOL;
1423 	      pDesc->unit = SANE_UNIT_NONE;
1424 	      pDesc->size = sizeof (SANE_Word);
1425 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1426 	      pDesc->constraint.range = 0;
1427 	      pDesc->cap =
1428 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1429 		SANE_CAP_SOFT_SELECT;
1430 	      pVal->w = SANE_FALSE;
1431 	      break;
1432 
1433 	    case opt_nogamma:
1434 	      pDesc->name = "opt_nogamma";
1435 	      pDesc->title = SANE_I18N ("Disable gamma correction");
1436 	      pDesc->desc = SANE_I18N ("Gamma correction will be disabled");
1437 	      pDesc->type = SANE_TYPE_BOOL;
1438 	      pDesc->unit = SANE_UNIT_NONE;
1439 	      pDesc->size = sizeof (SANE_Word);
1440 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1441 	      pDesc->constraint.range = 0;
1442 	      pDesc->cap =
1443 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1444 		SANE_CAP_SOFT_SELECT;
1445 	      pVal->w = SANE_FALSE;
1446 	      break;
1447 
1448 	    case opt_nowshading:
1449 	      pDesc->name = "opt_nowshading";
1450 	      pDesc->title = SANE_I18N ("Disable white shading correction");
1451 	      pDesc->desc =
1452 		SANE_I18N ("White shading correction will be disabled");
1453 	      pDesc->type = SANE_TYPE_BOOL;
1454 	      pDesc->unit = SANE_UNIT_NONE;
1455 	      pDesc->size = sizeof (SANE_Word);
1456 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1457 	      pDesc->constraint.range = 0;
1458 	      pDesc->cap =
1459 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1460 		SANE_CAP_SOFT_SELECT;
1461 	      pVal->w = SANE_FALSE;
1462 	      break;
1463 
1464 	    case opt_nowarmup:
1465 	      pDesc->name = "opt_nowarmup";
1466 	      pDesc->title = SANE_I18N ("Skip warmup process");
1467 	      pDesc->desc = SANE_I18N ("Warmup process will be disabled");
1468 	      pDesc->type = SANE_TYPE_BOOL;
1469 	      pDesc->unit = SANE_UNIT_NONE;
1470 	      pDesc->size = sizeof (SANE_Word);
1471 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1472 	      pDesc->constraint.range = 0;
1473 	      pDesc->cap =
1474 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1475 		SANE_CAP_SOFT_SELECT;
1476 	      pVal->w = SANE_FALSE;
1477 	      break;
1478 
1479 	    case opt_realdepth:
1480 	      pDesc->name = "opt_realdepth";
1481 	      pDesc->title = SANE_I18N ("Force real depth");
1482 	      pDesc->desc =
1483 		SANE_I18N
1484 		("If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.");
1485 	      pDesc->type = SANE_TYPE_BOOL;
1486 	      pDesc->unit = SANE_UNIT_NONE;
1487 	      pDesc->size = sizeof (SANE_Word);
1488 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1489 	      pDesc->constraint.range = 0;
1490 	      pDesc->cap =
1491 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1492 		SANE_CAP_SOFT_SELECT;
1493 	      pVal->w = SANE_FALSE;
1494 	      break;
1495 
1496 	    case opt_emulategray:
1497 	      pDesc->name = "opt_emulategray";
1498 	      pDesc->title = SANE_I18N ("Emulate Grayscale");
1499 	      pDesc->desc =
1500 		SANE_I18N
1501 		("If enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.");
1502 	      pDesc->type = SANE_TYPE_BOOL;
1503 	      pDesc->unit = SANE_UNIT_NONE;
1504 	      pDesc->size = sizeof (SANE_Word);
1505 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1506 	      pDesc->constraint.range = 0;
1507 	      pDesc->cap =
1508 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1509 		SANE_CAP_SOFT_SELECT;
1510 	      pVal->w = SANE_FALSE;
1511 	      break;
1512 
1513 	    case opt_dbgimages:
1514 	      pDesc->name = "opt_dbgimages";
1515 	      pDesc->title = SANE_I18N ("Save debugging images");
1516 	      pDesc->desc =
1517 		SANE_I18N
1518 		("If enabled, some images involved in scanner processing are saved to analyze them.");
1519 	      pDesc->type = SANE_TYPE_BOOL;
1520 	      pDesc->unit = SANE_UNIT_NONE;
1521 	      pDesc->size = sizeof (SANE_Word);
1522 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1523 	      pDesc->constraint.range = 0;
1524 	      pDesc->cap =
1525 		SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT |
1526 		SANE_CAP_SOFT_SELECT;
1527 	      pVal->w = SANE_FALSE;
1528 	      break;
1529 
1530 	    case opt_reset:
1531 	      pDesc->name = "opt_reset";
1532 	      pDesc->title = SANE_I18N ("Reset chipset");
1533 	      pDesc->desc = SANE_I18N ("Resets chipset data");
1534 	      pDesc->type = SANE_TYPE_BUTTON;
1535 	      pDesc->unit = SANE_UNIT_NONE;
1536 	      pDesc->size = 0;
1537 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1538 	      pDesc->constraint.string_list = 0;
1539 	      pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT;
1540 	      pVal->w = 0;
1541 	      break;
1542 
1543 	      /* device information */
1544 	    case grp_info:
1545 	      pDesc->name = "grp_info";
1546 	      pDesc->title = SANE_I18N ("Information");
1547 	      pDesc->desc = "";
1548 	      pDesc->type = SANE_TYPE_GROUP;
1549 	      pDesc->unit = SANE_UNIT_NONE;
1550 	      pDesc->size = 0;
1551 	      pDesc->cap = 0;
1552 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1553 	      pDesc->constraint.range = 0;
1554 	      pVal->w = 0;
1555 	      break;
1556 
1557 	    case opt_chipname:
1558 	      pDesc->name = "opt_chipname";
1559 	      pDesc->title = SANE_I18N ("Chipset name");
1560 	      pDesc->desc = SANE_I18N ("Shows chipset name used in device.");
1561 	      pDesc->type = SANE_TYPE_STRING;
1562 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1563 	      pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT;
1564 	      pVal->s = strdup (SANE_I18N ("Unknown"));
1565 	      pDesc->size = strlen(pVal->s) + 1;
1566 	      break;
1567 
1568 	    case opt_chipid:
1569 	      pDesc->name = "opt_chipid";
1570 	      pDesc->title = SANE_I18N ("Chipset ID");
1571 	      pDesc->desc = SANE_I18N ("Shows the chipset ID");
1572 	      pDesc->type = SANE_TYPE_INT;
1573 	      pDesc->unit = SANE_UNIT_NONE;
1574 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1575 	      pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT;
1576 	      pVal->w = -1;
1577 	      break;
1578 
1579 	    case opt_scancount:
1580 	      pDesc->name = "opt_scancount";
1581 	      pDesc->title = SANE_I18N ("Scan counter");
1582 	      pDesc->desc =
1583 		SANE_I18N ("Shows the number of scans made by scanner");
1584 	      pDesc->type = SANE_TYPE_INT;
1585 	      pDesc->unit = SANE_UNIT_NONE;
1586 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1587 	      pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT;
1588 	      pVal->w = -1;
1589 	      break;
1590 
1591 	    case opt_infoupdate:
1592 	      pDesc->name = "opt_infoupdate";
1593 	      pDesc->title = SANE_I18N ("Update information");
1594 	      pDesc->desc = SANE_I18N ("Updates information about device");
1595 	      pDesc->type = SANE_TYPE_BUTTON;
1596 	      pDesc->unit = SANE_UNIT_NONE;
1597 	      pDesc->size = 0;
1598 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1599 	      pDesc->constraint.string_list = 0;
1600 	      pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT;
1601 	      pVal->w = 0;
1602 	      break;
1603 
1604 	      /* buttons support */
1605 	    case grp_sensors:
1606 	      pDesc->name = SANE_NAME_SENSORS;
1607 	      pDesc->title = SANE_TITLE_SENSORS;
1608 	      pDesc->desc = SANE_DESC_SENSORS;
1609 	      pDesc->type = SANE_TYPE_GROUP;
1610 	      pDesc->unit = SANE_UNIT_NONE;
1611 	      pDesc->size = 0;
1612 	      pDesc->cap = 0;
1613 	      pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1614 	      pDesc->constraint.range = 0;
1615 	      pVal->w = 0;
1616 	      break;
1617 
1618 	    case opt_button_0:
1619 	    case opt_button_1:
1620 	    case opt_button_2:
1621 	    case opt_button_3:
1622 	    case opt_button_4:
1623 	    case opt_button_5:
1624 	      {
1625 		char name[12];
1626 		char title[128];
1627 
1628 		sprintf (name, "button %d", i - opt_button_0);
1629 		sprintf (title, "Scanner button %d", i - opt_button_0);
1630 		pDesc->name = strdup (name);
1631 		pDesc->title = strdup (title);
1632 		pDesc->desc =
1633 		  SANE_I18N
1634 		  ("This option reflects a front panel scanner button");
1635 		pDesc->type = SANE_TYPE_BOOL;
1636 		pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
1637 
1638 		if (i - opt_button_0 >= Buttons_Count (device))
1639 		  pDesc->cap |= SANE_CAP_INACTIVE;
1640 
1641 		pDesc->unit = SANE_UNIT_NONE;
1642 		pDesc->size = sizeof (SANE_Word);
1643 		pDesc->constraint_type = SANE_CONSTRAINT_NONE;
1644 		pVal->w = SANE_FALSE;
1645 	      }
1646 	      break;
1647 	    }
1648 	}
1649     }
1650 }
1651 
1652 static SANE_Int
_ReportDevice(TScannerModel * pModel,const char * pszDeviceName)1653 _ReportDevice (TScannerModel * pModel, const char *pszDeviceName)
1654 {
1655   SANE_Int rst = ERROR;
1656   TDevListEntry *pNew, *pDev;
1657 
1658   DBG (DBG_FNC, "> _ReportDevice:\n");
1659 
1660   pNew = malloc (sizeof (TDevListEntry));
1661   if (pNew != NULL)
1662     {
1663       rst = OK;
1664 
1665       /* add new element to the end of the list */
1666       if (_pFirstSaneDev != NULL)
1667 	{
1668 	  /* Add at the end of existing list */
1669 	  for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext);
1670 
1671 	  pDev->pNext = pNew;
1672 	}
1673       else
1674 	_pFirstSaneDev = pNew;
1675 
1676       /* fill in new element */
1677       pNew->pNext = NULL;
1678       pNew->devname = (char *) strdup (pszDeviceName);
1679       pNew->dev.name = pNew->devname;
1680       pNew->dev.vendor = pModel->pszVendor;
1681       pNew->dev.model = pModel->pszName;
1682       pNew->dev.type = SANE_I18N ("flatbed scanner");
1683 
1684       iNumSaneDev++;
1685     }
1686 
1687   return rst;
1688 }
1689 
1690 static SANE_Status
attach_one_device(SANE_String_Const devname)1691 attach_one_device (SANE_String_Const devname)
1692 {
1693   static TScannerModel sModel;
1694 
1695   DBG (DBG_FNC, "> attach_one_device(devname=%s)\n", devname);
1696 
1697   switch (GetUSB_device_model (devname))
1698     {
1699     case HP3800:
1700       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1701       sModel.pszName = (char *) strdup ("Scanjet 3800");
1702       break;
1703     case HPG2710:
1704       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1705       sModel.pszName = (char *) strdup ("Scanjet G2710");
1706       break;
1707     case HP3970:
1708       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1709       sModel.pszName = (char *) strdup ("Scanjet 3970");
1710       break;
1711     case HP4070:
1712       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1713       sModel.pszName = (char *) strdup ("Scanjet 4070 Photosmart");
1714       break;
1715     case HP4370:
1716       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1717       sModel.pszName = (char *) strdup ("Scanjet 4370");
1718       break;
1719     case HPG3010:
1720       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1721       sModel.pszName = (char *) strdup ("Scanjet G3010");
1722       break;
1723     case HPG3110:
1724       sModel.pszVendor = (char *) strdup ("Hewlett-Packard");
1725       sModel.pszName = (char *) strdup ("Scanjet G3110");
1726       break;
1727     case UA4900:
1728       sModel.pszVendor = (char *) strdup ("UMAX");
1729       sModel.pszName = (char *) strdup ("Astra 4900");
1730       break;
1731     case BQ5550:
1732       sModel.pszVendor = (char *) strdup ("BenQ");
1733       sModel.pszName = (char *) strdup ("5550");
1734       break;
1735     default:
1736       sModel.pszVendor = (char *) strdup ("Unknown");
1737       sModel.pszName = (char *) strdup ("RTS8822 chipset based");
1738       break;
1739     }
1740 
1741   _ReportDevice (&sModel, devname);
1742 
1743   return SANE_STATUS_GOOD;
1744 }
1745 
1746 /* Sane default functions */
1747 
1748 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)1749 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
1750 {
1751   FILE *conf_fp;		/* Config file stream  */
1752   SANE_Char line[PATH_MAX];
1753   SANE_Char *str = NULL;
1754   SANE_String_Const proper_str;
1755   SANE_Int nline = 0;
1756 
1757   /* Initialize debug */
1758   DBG_INIT ();
1759 
1760   DBG (DBG_FNC, "> sane_init\n");
1761 
1762   /* silence gcc */
1763   authorize = authorize;
1764 
1765   /* Initialize usb */
1766   sanei_usb_init ();
1767 
1768   /* Parse config file */
1769   conf_fp = sanei_config_open (HP3900_CONFIG_FILE);
1770   if (conf_fp)
1771     {
1772       while (sanei_config_read (line, sizeof (line), conf_fp))
1773 	{
1774 	  nline++;
1775 	  if (str)
1776 	    free (str);
1777 
1778 	  proper_str = sanei_config_get_string (line, &str);
1779 
1780 	  /* Discards white lines and comments */
1781 	  if ((str != NULL) && (proper_str != line) && (str[0] != '#'))
1782 	    {
1783 	      /* If line's not blank or a comment, then it's the device
1784 	       * filename or a usb directive. */
1785 	      sanei_usb_attach_matching_devices (line, attach_one_device);
1786 	    }
1787 	}
1788       fclose (conf_fp);
1789     }
1790   else
1791     {
1792       /* default */
1793       DBG (DBG_VRB, "- %s not found. Looking for hardcoded usb ids ...\n",
1794 	   HP3900_CONFIG_FILE);
1795 
1796       sanei_usb_attach_matching_devices ("usb 0x03f0 0x2605", attach_one_device);	/* HP3800  */
1797       sanei_usb_attach_matching_devices ("usb 0x03f0 0x2805", attach_one_device);	/* HPG2710 */
1798       sanei_usb_attach_matching_devices ("usb 0x03f0 0x2305", attach_one_device);	/* HP3970  */
1799       sanei_usb_attach_matching_devices ("usb 0x03f0 0x2405", attach_one_device);	/* HP4070  */
1800       sanei_usb_attach_matching_devices ("usb 0x03f0 0x4105", attach_one_device);	/* HP4370  */
1801       sanei_usb_attach_matching_devices ("usb 0x03f0 0x4205", attach_one_device);	/* HPG3010 */
1802       sanei_usb_attach_matching_devices ("usb 0x03f0 0x4305", attach_one_device);	/* HPG3110 */
1803       sanei_usb_attach_matching_devices ("usb 0x06dc 0x0020", attach_one_device);	/* UA4900  */
1804       sanei_usb_attach_matching_devices ("usb 0x04a5 0x2211", attach_one_device);	/* BQ5550  */
1805     }
1806 
1807   /* Return backend version */
1808   if (version_code != NULL)
1809     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0);
1810 
1811   return SANE_STATUS_GOOD;
1812 }
1813 
1814 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)1815 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1816 {
1817   SANE_Status rst = SANE_STATUS_GOOD;
1818 
1819   local_only = local_only;
1820 
1821   if (_pSaneDevList)
1822     free (_pSaneDevList);
1823 
1824   _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1));
1825   if (_pSaneDevList != NULL)
1826     {
1827       TDevListEntry *pDev;
1828       SANE_Int i = 0;
1829 
1830       for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext)
1831 	_pSaneDevList[i++] = &pDev->dev;
1832 
1833       _pSaneDevList[i++] = 0;	/* last entry is 0 */
1834       *device_list = _pSaneDevList;
1835     }
1836   else
1837     rst = SANE_STATUS_NO_MEM;
1838 
1839   DBG (DBG_FNC, "> sane_get_devices: %i\n", rst);
1840 
1841   return rst;
1842 }
1843 
1844 SANE_Status
sane_open(SANE_String_Const name,SANE_Handle * h)1845 sane_open (SANE_String_Const name, SANE_Handle * h)
1846 {
1847   TScanner *s;
1848   SANE_Status rst;
1849 
1850   /* check the name */
1851   if (strlen (name) == 0)
1852     /* default to first available device */
1853     name = _pFirstSaneDev->dev.name;
1854 
1855   /* allocate space for RTS environment */
1856   device = RTS_Alloc ();
1857   if (device != NULL)
1858     {
1859       /* Open device */
1860       rst = sanei_usb_open (name, &device->usb_handle);
1861       if (rst == SANE_STATUS_GOOD)
1862 	{
1863 	  /* Allocating memory for device */
1864 	  s = malloc (sizeof (TScanner));
1865 	  if (s != NULL)
1866 	    {
1867 	      memset (s, 0, sizeof (TScanner));
1868 
1869 	      /* Initializing RTS */
1870 	      if (Init_Vars () == OK)
1871 		{
1872 		  SANE_Int vendor, product;
1873 
1874 		  /* Setting device model */
1875 		  if (sanei_usb_get_vendor_product
1876 		      (device->usb_handle, &vendor,
1877 		       &product) == SANE_STATUS_GOOD)
1878 		    s->model = Device_get (product, vendor);
1879 		  else
1880 		    s->model = HP3970;
1881 
1882 		  set_ScannerModel (s->model, product, vendor);
1883 
1884 		  /* Initialize device */
1885 		  if (RTS_Scanner_Init (device) == OK)
1886 		    {
1887 		      /* silencing unused functions */
1888 		      Silent_Compile ();
1889 
1890 		      /* initialize backend options */
1891 		      options_init (s);
1892 		      *h = s;
1893 
1894 		      /* everything went ok */
1895 		      rst = SANE_STATUS_GOOD;
1896 		    }
1897 		  else
1898 		    {
1899 		      free ((void *) s);
1900 		      rst = SANE_STATUS_INVAL;
1901 		    }
1902 		}
1903 	      else
1904 		rst = SANE_STATUS_NO_MEM;
1905 	    }
1906 	  else
1907 	    rst = SANE_STATUS_NO_MEM;
1908 	}
1909     }
1910   else
1911     rst = SANE_STATUS_NO_MEM;
1912 
1913   DBG (DBG_FNC, "> sane_open(name=%s): %i\n", name, rst);
1914 
1915   return rst;
1916 }
1917 
1918 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle h,SANE_Int n)1919 sane_get_option_descriptor (SANE_Handle h, SANE_Int n)
1920 {
1921   SANE_Option_Descriptor *rst = NULL;
1922 
1923   if ((n >= opt_begin) && (n < opt_count))
1924     {
1925       TScanner *s = (TScanner *) h;
1926       rst = &s->aOptions[n];
1927     }
1928 
1929   DBG (DBG_FNC, "> SANE_Option_Descriptor(handle, n=%i): %i\n", n,
1930        (rst == NULL) ? -1 : 0);
1931 
1932   return rst;
1933 }
1934 
1935 static SANE_Status
option_get(TScanner * scanner,SANE_Int optid,void * result)1936 option_get (TScanner * scanner, SANE_Int optid, void *result)
1937 {
1938   /* This function returns value contained in selected option */
1939 
1940   DBG (DBG_FNC, "> option_get(optid=%i)\n", optid);
1941 
1942   if ((scanner != NULL) && (result != NULL))
1943     {
1944       switch (optid)
1945 	{
1946 	  /* SANE_Word */
1947 	case opt_begin:	/* null */
1948 	case opt_reset:	/* null */
1949 	case opt_negative:
1950 	case opt_nogamma:
1951 	case opt_nowshading:
1952 	case opt_emulategray:
1953 	case opt_dbgimages:
1954 	case opt_nowarmup:
1955 	case opt_realdepth:
1956 	case opt_depth:
1957 	case opt_resolution:
1958 	case opt_threshold:
1959 	case opt_brx:
1960 	case opt_tlx:
1961 	case opt_bry:
1962 	case opt_tly:
1963 	  *(SANE_Word *) result = scanner->aValues[optid].w;
1964 	  break;
1965 
1966 	  /* SANE_Int */
1967 	case opt_chipid:
1968 	case opt_scancount:
1969 	  *(SANE_Int *) result = scanner->aValues[optid].w;
1970 	  break;
1971 
1972 	  /* SANE_Word array */
1973 	case opt_gamma_red:
1974 	case opt_gamma_green:
1975 	case opt_gamma_blue:
1976 	  memcpy (result, scanner->aValues[optid].wa,
1977 		  scanner->aOptions[optid].size);
1978 	  break;
1979 
1980 	  /* String */
1981 	case opt_colormode:
1982 	case opt_scantype:
1983 	case opt_model:
1984 	case opt_chipname:
1985 	  strncpy (result, scanner->aValues[optid].s, scanner->aOptions[optid].size);
1986 	  ((char*)result)[scanner->aOptions[optid].size-1] = '\0';
1987 
1988 	  break;
1989 
1990 	  /* scanner buttons */
1991 	case opt_button_0:
1992 	  get_button_status (scanner);
1993           // fall through
1994 	case opt_button_1:
1995 	case opt_button_2:
1996 	case opt_button_3:
1997 	case opt_button_4:
1998 	case opt_button_5:
1999 	  /* copy the button state */
2000 	  *(SANE_Word *) result = scanner->aValues[optid].w;
2001 	  /* clear the button state */
2002 	  scanner->aValues[optid].w = SANE_FALSE;
2003 	  break;
2004 	}
2005     }
2006 
2007   return SANE_STATUS_GOOD;
2008 }
2009 
2010 static SANE_Status
option_set(TScanner * scanner,SANE_Int optid,void * value,SANE_Int * pInfo)2011 option_set (TScanner * scanner, SANE_Int optid, void *value, SANE_Int * pInfo)
2012 {
2013   SANE_Status rst;
2014 
2015   DBG (DBG_FNC, "> option_set(optid=%i)\n", optid);
2016 
2017   rst = SANE_STATUS_INVAL;
2018 
2019   if (scanner != NULL)
2020     {
2021       if (scanner->fScanning == FALSE)
2022 	{
2023 	  SANE_Int info = 0;
2024 
2025 	  rst = SANE_STATUS_GOOD;
2026 
2027 	  switch (optid)
2028 	    {
2029 	    case opt_brx:
2030 	    case opt_tlx:
2031 	    case opt_bry:
2032 	    case opt_tly:
2033 	    case opt_depth:
2034 	    case opt_nogamma:
2035 	    case opt_nowshading:
2036 	    case opt_nowarmup:
2037 	    case opt_negative:
2038 	    case opt_emulategray:
2039 	    case opt_dbgimages:
2040 	    case opt_threshold:
2041 	    case opt_resolution:
2042 	      info |= SANE_INFO_RELOAD_PARAMS;
2043 	      scanner->aValues[optid].w = *(SANE_Word *) value;
2044 	      break;
2045 
2046 	    case opt_gamma_red:
2047 	    case opt_gamma_green:
2048 	    case opt_gamma_blue:
2049 	      memcpy (scanner->aValues[optid].wa, value,
2050 		      scanner->aOptions[optid].size);
2051 	      break;
2052 
2053 	    case opt_scantype:
2054 	      if (strcmp (scanner->aValues[optid].s, value) != 0)
2055 		{
2056 		  struct st_coords *coords;
2057 		  SANE_Int source;
2058 
2059 		  if (scanner->aValues[optid].s)
2060 		    free (scanner->aValues[optid].s);
2061 
2062 		  scanner->aValues[optid].s = strdup (value);
2063 
2064 		  source = Get_Source (scanner->aValues[opt_scantype].s);
2065 		  coords = Constrains_Get (device, source);
2066 		  if (coords != NULL)
2067 		    {
2068 		      bknd_constrains (scanner, source, 0);
2069 		      bknd_constrains (scanner, source, 1);
2070 		      scanner->aValues[opt_tlx].w = 0;
2071 		      scanner->aValues[opt_tly].w = 0;
2072 		      scanner->aValues[opt_brx].w = coords->width;
2073 		      scanner->aValues[opt_bry].w = coords->height;
2074 		    }
2075 
2076 		  info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2077 		}
2078 	      break;
2079 
2080 	    case opt_colormode:
2081 	      if (strcmp (scanner->aValues[optid].s, value) != 0)
2082 		{
2083 		  if (scanner->aValues[optid].s)
2084 		    free (scanner->aValues[optid].s);
2085 		  scanner->aValues[optid].s = strdup (value);
2086 		  if (Get_Colormode (scanner->aValues[optid].s) == CM_LINEART)
2087 		    scanner->aOptions[opt_threshold].cap &=
2088 		      ~SANE_CAP_INACTIVE;
2089 		  else
2090 		    scanner->aOptions[opt_threshold].cap |= SANE_CAP_INACTIVE;
2091 		  info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2092 		}
2093 	      break;
2094 
2095 	    case opt_model:
2096 	      if (strcmp (scanner->aValues[optid].s, value) != 0)
2097 		{
2098 		  SANE_Int model;
2099 
2100 		  if (scanner->aValues[optid].s)
2101 		    free (scanner->aValues[optid].s);
2102 		  scanner->aValues[optid].s = strdup (value);
2103 
2104 		  model = Get_Model (scanner->aValues[optid].s);
2105 		  if (model != RTS_Debug->dev_model)
2106 		    {
2107 		      SANE_Int source;
2108 		      struct st_coords *coords;
2109 
2110 		      /* free configuration of last model */
2111 		      Free_Config (device);
2112 
2113 		      /* set new model */
2114 		      RTS_Debug->dev_model = model;
2115 
2116 		      /* and load configuration of current model */
2117 		      Load_Config (device);
2118 
2119 		      /* update options according to selected device */
2120 		      bknd_info (scanner);
2121 		      bknd_colormodes (scanner, model);
2122 		      bknd_depths (scanner, model);
2123 		      bknd_resolutions (scanner, model);
2124 		      bknd_sources (scanner, model);
2125 
2126 		      /* updating lists */
2127 		      scanner->aOptions[opt_colormode].size =
2128 			max_string_size (scanner->list_colormodes);
2129 		      scanner->aOptions[opt_colormode].constraint.
2130 			string_list = scanner->list_colormodes;
2131 		      scanner->aOptions[opt_depth].constraint.word_list =
2132 			scanner->list_depths;
2133 		      scanner->aOptions[opt_resolution].constraint.word_list =
2134 			scanner->list_resolutions;
2135 		      scanner->aOptions[opt_scantype].size =
2136 			max_string_size (scanner->list_sources);
2137 		      scanner->aOptions[opt_scantype].constraint.string_list =
2138 			scanner->list_sources;
2139 
2140 		      /* default values */
2141 		      if (scanner->aValues[opt_colormode].s != NULL)
2142 			free (scanner->aValues[opt_colormode].s);
2143 
2144 		      if (scanner->aValues[opt_scantype].s != NULL)
2145 			free (scanner->aValues[opt_scantype].s);
2146 
2147 		      scanner->aValues[opt_colormode].s =
2148 			strdup (scanner->list_colormodes[0]);
2149 		      scanner->aValues[opt_scantype].s =
2150 			strdup (scanner->list_sources[0]);
2151 		      scanner->aValues[opt_resolution].w =
2152 			scanner->list_resolutions[1];
2153 		      scanner->aValues[opt_depth].w = scanner->list_depths[1];
2154 
2155 		      source = Get_Source (scanner->aValues[opt_scantype].s);
2156 		      coords = Constrains_Get (device, source);
2157 		      if (coords != NULL)
2158 			{
2159 			  bknd_constrains (scanner, source, 0);
2160 			  bknd_constrains (scanner, source, 1);
2161 			  scanner->aValues[opt_tlx].w = 0;
2162 			  scanner->aValues[opt_tly].w = 0;
2163 			  scanner->aValues[opt_brx].w = coords->width;
2164 			  scanner->aValues[opt_bry].w = coords->height;
2165 			}
2166 		    }
2167 
2168 		  info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2169 		}
2170 	      break;
2171 
2172 	    case opt_reset:
2173 	      Chipset_Reset (device);
2174 	      break;
2175 
2176 	    case opt_realdepth:
2177 	      scanner->aValues[optid].w =
2178 		(scanner->cnv.real_depth == TRUE) ? SANE_TRUE : SANE_FALSE;
2179 	      break;
2180 
2181 	    case opt_infoupdate:
2182 	      if (bknd_info (scanner) == SANE_STATUS_GOOD)
2183 		info |= SANE_INFO_RELOAD_OPTIONS;
2184 	      break;
2185 
2186 	    default:
2187 	      rst = SANE_STATUS_INVAL;
2188 	      break;
2189 	    }
2190 
2191 	  if (pInfo != NULL)
2192 	    *pInfo = info;
2193 	}
2194     }
2195 
2196   return rst;
2197 }
2198 
2199 SANE_Status
sane_control_option(SANE_Handle h,SANE_Int n,SANE_Action Action,void * pVal,SANE_Int * pInfo)2200 sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
2201 		     void *pVal, SANE_Int * pInfo)
2202 {
2203   TScanner *scanner;
2204   SANE_Status rst;
2205 
2206   DBG (DBG_FNC, "> sane_control_option\n");
2207 
2208   scanner = (TScanner *) h;
2209 
2210   switch (Action)
2211     {
2212     case SANE_ACTION_GET_VALUE:
2213       rst = option_get (scanner, n, pVal);
2214       break;
2215 
2216     case SANE_ACTION_SET_VALUE:
2217       rst = option_set (scanner, n, pVal, pInfo);
2218       break;
2219 
2220     case SANE_ACTION_SET_AUTO:
2221       rst = SANE_STATUS_UNSUPPORTED;
2222       break;
2223 
2224     default:
2225       rst = SANE_STATUS_INVAL;
2226       break;
2227     }
2228 
2229   return rst;
2230 }
2231 
2232 SANE_Status
sane_get_parameters(SANE_Handle h,SANE_Parameters * p)2233 sane_get_parameters (SANE_Handle h, SANE_Parameters * p)
2234 {
2235   SANE_Status rst = SANE_STATUS_INVAL;
2236   TScanner *s = (TScanner *) h;
2237 
2238   DBG (DBG_FNC, "+ sane_get_parameters:");
2239 
2240   if (s != NULL)
2241     {
2242       struct st_coords coords;
2243       SANE_Int res, source, depth, colormode, frameformat, bpl;
2244 
2245       /* first do some checks */
2246 
2247       /* colormode */
2248       colormode = Get_Colormode (s->aValues[opt_colormode].s);
2249 
2250       /* frameformat */
2251       frameformat =
2252 	(colormode == CM_COLOR) ? SANE_FRAME_RGB : SANE_FRAME_GRAY;
2253 
2254       /* depth */
2255       depth = (colormode == CM_LINEART) ? 1 : s->aValues[opt_depth].w;
2256 
2257       /* scan type */
2258       source = Get_Source (s->aValues[opt_scantype].s);
2259 
2260       /* resolution */
2261       res = s->aValues[opt_resolution].w;
2262 
2263       /* image coordinates in millimeters */
2264       coords.left = s->aValues[opt_tlx].w;
2265       coords.top = s->aValues[opt_tly].w;
2266       coords.width = s->aValues[opt_brx].w;
2267       coords.height = s->aValues[opt_bry].w;
2268 
2269       /* validate coords */
2270       if (Translate_coords (&coords) == SANE_STATUS_GOOD)
2271 	{
2272 	  Set_Coordinates (source, res, &coords);
2273 
2274 	  if (colormode != CM_LINEART)
2275 	    {
2276 	      bpl = coords.width * ((depth > 8) ? 2 : 1);
2277 	      if (colormode == CM_COLOR)
2278 		bpl *= 3;	/* three channels */
2279 	    }
2280 	  else
2281 	    bpl = (coords.width + 7) / 8;
2282 
2283 	  /* return the data */
2284 	  p->format = frameformat;
2285 	  p->last_frame = SANE_TRUE;
2286 	  p->depth = depth;
2287 	  p->lines = coords.height;
2288 	  p->pixels_per_line = coords.width;
2289 	  p->bytes_per_line = bpl;
2290 
2291 	  DBG (DBG_FNC, " -> Depth : %i\n", depth);
2292 	  DBG (DBG_FNC, " -> Height: %i\n", coords.height);
2293 	  DBG (DBG_FNC, " -> Width : %i\n", coords.width);
2294 	  DBG (DBG_FNC, " -> BPL   : %i\n", bpl);
2295 
2296 	  rst = SANE_STATUS_GOOD;
2297 	}
2298     }
2299 
2300   DBG (DBG_FNC, "- sane_get_parameters: %i\n", rst);
2301 
2302   return rst;
2303 }
2304 
2305 SANE_Status
sane_start(SANE_Handle h)2306 sane_start (SANE_Handle h)
2307 {
2308   SANE_Status rst = SANE_STATUS_INVAL;
2309   TScanner *s;
2310 
2311   DBG (DBG_FNC, "+ sane_start\n");
2312 
2313   s = (TScanner *) h;
2314   if (s != NULL)
2315     {
2316       struct st_coords coords;
2317       SANE_Int res, source, colormode, depth, channel;
2318 
2319       /* first do some checks */
2320       /* Get Scan type */
2321       source = Get_Source (s->aValues[opt_scantype].s);
2322 
2323       /* Check if scanner supports slides and negatives in case selected source is tma */
2324       if (!((source != ST_NORMAL) && (RTS_isTmaAttached (device) == FALSE)))
2325 	{
2326 	  /* Get depth */
2327 	  depth = s->aValues[opt_depth].w;
2328 
2329 	  /* Get color mode */
2330 	  colormode = Get_Colormode (s->aValues[opt_colormode].s);
2331 
2332 	  /* Emulating certain color modes */
2333 	  if (colormode == CM_LINEART)
2334 	    {
2335 	      /* emulate lineart */
2336 	      s->cnv.colormode = CM_LINEART;
2337 	      colormode = CM_GRAY;
2338 	      depth = 8;
2339 	    }
2340 	  else if ((colormode == CM_GRAY)
2341 		   && (s->aValues[opt_emulategray].w == SANE_TRUE))
2342 	    {
2343 	      /* emulate grayscale */
2344 	      s->cnv.colormode = CM_GRAY;
2345 	      colormode = CM_COLOR;
2346 	    }
2347 	  else
2348 	    s->cnv.colormode = -1;
2349 
2350 	  /* setting channel for colormodes different than CM_COLOR */
2351 	  channel = (colormode != CM_COLOR) ? 1 : 0;
2352 
2353 	  /* negative colors */
2354 	  s->cnv.negative =
2355 	    (s->aValues[opt_negative].w == SANE_TRUE) ? TRUE : FALSE;
2356 
2357 	  /* Get threshold */
2358 	  s->cnv.threshold = s->aValues[opt_threshold].w;
2359 
2360 	  /* Get resolution */
2361 	  res = s->aValues[opt_resolution].w;
2362 
2363 	  /* set depth emulation */
2364 	  if (s->cnv.colormode == CM_LINEART)
2365 	    s->cnv.real_depth = TRUE;
2366 	  else
2367 	    s->cnv.real_depth =
2368 	      (s->aValues[opt_realdepth].w == SANE_TRUE) ? TRUE : FALSE;
2369 
2370 	  /* use gamma? */
2371 	  RTS_Debug->EnableGamma =
2372 	    (s->aValues[opt_nogamma].w == SANE_TRUE) ? FALSE : TRUE;
2373 
2374 	  /* disable white shading correction? */
2375 	  RTS_Debug->wshading =
2376 	    (s->aValues[opt_nowshading].w == SANE_TRUE) ? FALSE : TRUE;
2377 
2378 	  /* skip warmup process? */
2379 	  RTS_Debug->warmup =
2380 	    (s->aValues[opt_nowarmup].w == SANE_TRUE) ? FALSE : TRUE;
2381 
2382 	  /* save debugging images? */
2383 	  RTS_Debug->SaveCalibFile =
2384 	    (s->aValues[opt_dbgimages].w == SANE_TRUE) ? TRUE : FALSE;
2385 
2386 	  /* Get image coordinates in millimeters */
2387 	  coords.left = s->aValues[opt_tlx].w;
2388 	  coords.top = s->aValues[opt_tly].w;
2389 	  coords.width = s->aValues[opt_brx].w;
2390 	  coords.height = s->aValues[opt_bry].w;
2391 
2392 	  /* Validate coords */
2393 	  if (Translate_coords (&coords) == SANE_STATUS_GOOD)
2394 	    {
2395 
2396 	      /* Stop previusly started scan */
2397 	      RTS_Scanner_StopScan (device, TRUE);
2398 
2399 	      s->ScanParams.scantype = source;
2400 	      s->ScanParams.colormode = colormode;
2401 	      s->ScanParams.resolution_x = res;
2402 	      s->ScanParams.resolution_y = res;
2403 	      s->ScanParams.channel = channel;
2404 
2405 	      memcpy (&s->ScanParams.coords, &coords,
2406 		      sizeof (struct st_coords));
2407 	      Set_Coordinates (source, res, &s->ScanParams.coords);
2408 
2409 	      /* emulating depth? */
2410 	      if ((s->cnv.real_depth == FALSE) && (depth < 16)
2411 		  && (RTS_Debug->EnableGamma == TRUE))
2412 		{
2413 		  /* In order to improve image quality, we will scan at 16bits if
2414 		     we are using gamma correction */
2415 		  s->cnv.depth = depth;
2416 		  s->ScanParams.depth = 16;
2417 		}
2418 	      else
2419 		{
2420 		  s->ScanParams.depth = depth;
2421 		  s->cnv.depth = -1;
2422 		}
2423 
2424 	      /* set scanning parameters */
2425 	      if (RTS_Scanner_SetParams (device, &s->ScanParams) == OK)
2426 		{
2427 		  /* Start scanning process */
2428 		  if (RTS_Scanner_StartScan (device) == OK)
2429 		    {
2430 		      /* Allocate buffer to read one line */
2431 		      s->mylin = 0;
2432 		      rst = img_buffers_alloc (s, bytesperline);
2433 		    }
2434 		}
2435 	    }
2436 	}
2437       else
2438 	rst = SANE_STATUS_COVER_OPEN;
2439     }
2440 
2441   DBG (DBG_FNC, "- sane_start: %i\n", rst);
2442 
2443   return rst;
2444 }
2445 
2446 SANE_Status
sane_read(SANE_Handle h,SANE_Byte * buf,SANE_Int maxlen,SANE_Int * len)2447 sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
2448 {
2449   SANE_Status rst = SANE_STATUS_GOOD;
2450   TScanner *s = (TScanner *) h;
2451 
2452   DBG (DBG_FNC, "+ sane_read\n");
2453 
2454   if ((s != NULL) && (buf != NULL) && (len != NULL))
2455     {
2456       /* nothing has been read at the moment */
2457       *len = 0;
2458 
2459       /* if we read all the lines return EOF */
2460       if ((s->mylin == s->ScanParams.coords.height)
2461 	  || (device->status->cancel == TRUE))
2462 	{
2463 	  rst =
2464 	    (device->status->cancel ==
2465 	     TRUE) ? SANE_STATUS_CANCELLED : SANE_STATUS_EOF;
2466 
2467 	  RTS_Scanner_StopScan (device, FALSE);
2468 	  img_buffers_free (s);
2469 	}
2470       else
2471 	{
2472 	  SANE_Int emul_len, emul_maxlen;
2473 	  SANE_Int thwidth, transferred, bufflength;
2474 	  SANE_Byte *buffer, *pbuffer;
2475 
2476 	  emul_len = 0;
2477 	  if (s->cnv.depth != -1)
2478 	    emul_maxlen = maxlen * (s->ScanParams.depth / s->cnv.depth);
2479 	  else
2480 	    emul_maxlen = maxlen;
2481 
2482 	  /* if grayscale emulation is enabled check that retrieved data is multiple of three */
2483 	  if (s->cnv.colormode == CM_GRAY)
2484 	    {
2485 	      SANE_Int chn_size, rest;
2486 
2487 	      chn_size = (s->ScanParams.depth > 8) ? 2 : 1;
2488 	      rest = emul_maxlen % (3 * chn_size);
2489 
2490 	      if (rest != 0)
2491 		emul_maxlen -= rest;
2492 	    }
2493 
2494 	  /* this is important to keep lines alignment in lineart mode */
2495 	  if (s->cnv.colormode == CM_LINEART)
2496 	    emul_maxlen = s->ScanParams.coords.width;
2497 
2498 	  /* if we are emulating depth, we scan at 16bit when frontend waits
2499 	     for 8bit data. Next buffer will be used to retrieve data from
2500 	     scanner prior to convert to 8 bits depth */
2501 	  buffer = (SANE_Byte *) malloc (emul_maxlen * sizeof (SANE_Byte));
2502 
2503 	  if (buffer != NULL)
2504 	    {
2505 	      pbuffer = buffer;
2506 
2507 	      /* get bytes per line */
2508 	      if (s->ScanParams.colormode != CM_LINEART)
2509 		{
2510 		  thwidth =
2511 		    s->ScanParams.coords.width *
2512 		    ((s->ScanParams.depth > 8) ? 2 : 1);
2513 
2514 		  if (s->ScanParams.colormode == CM_COLOR)
2515 		    thwidth *= 3;	/* three channels */
2516 		}
2517 	      else
2518 		thwidth = (s->ScanParams.coords.width + 7) / 8;
2519 
2520 	      /* read as many lines the buffer may contain and while there are lines to be read */
2521 	      while ((emul_len < emul_maxlen)
2522 		     && (s->mylin < s->ScanParams.coords.height))
2523 		{
2524 		  /* Is there any data waiting for being passed ? */
2525 		  if (s->rest_amount != 0)
2526 		    {
2527 		      /* copy to buffer as many bytes as we can */
2528 		      bufflength =
2529 			min (emul_maxlen - emul_len, s->rest_amount);
2530 		      memcpy (pbuffer, s->rest, bufflength);
2531 		      emul_len += bufflength;
2532 		      pbuffer += bufflength;
2533 		      s->rest_amount -= bufflength;
2534 		      if (s->rest_amount == 0)
2535 			s->mylin++;
2536 		    }
2537 		  else
2538 		    {
2539 		      /* read from scanner up to one line */
2540 		      if (Read_Image
2541 			  (device, bytesperline, s->image,
2542 			   &transferred) != OK)
2543 			{
2544 			  /* error, exit function */
2545 			  rst = SANE_STATUS_EOF;
2546 			  break;
2547 			}
2548 
2549 		      /* is there any data? */
2550 		      if (transferred != 0)
2551 			{
2552 			  /* copy to buffer as many bytes as we can */
2553 			  bufflength = min (emul_maxlen - emul_len, thwidth);
2554 
2555 			  memcpy (pbuffer, s->image, bufflength);
2556 			  emul_len += bufflength;
2557 			  pbuffer += bufflength;
2558 
2559 			  /* the rest will be copied to s->rest buffer */
2560 			  if (bufflength < thwidth)
2561 			    {
2562 			      s->rest_amount = thwidth - bufflength;
2563 			      memcpy (s->rest, s->image + bufflength,
2564 				      s->rest_amount);
2565 			    }
2566 			  else
2567 			    s->mylin++;
2568 			}
2569 		      else
2570 			break;
2571 		    }
2572 		}		/* while */
2573 
2574 	      /* process buffer before sending to frontend */
2575 	      if ((emul_len > 0) && (rst != SANE_STATUS_EOF))
2576 		{
2577 		  /* at this point ...
2578 		     buffer  : contains retrieved image
2579 		     emul_len: contains size in bytes of retrieved image
2580 
2581 		     after this code ...
2582 		     buf : will contain postprocessed image
2583 		     len : will contain size in bytes of postprocessed image */
2584 
2585 		  /* apply gamma if necessary */
2586 		  if (RTS_Debug->EnableGamma == TRUE)
2587 		    gamma_apply (s, buffer, emul_len, s->ScanParams.depth);
2588 
2589 		  /* if we are scanning negatives, let's invert colors */
2590 		  if (s->ScanParams.scantype == ST_NEG)
2591 		    {
2592 		      if (s->cnv.negative == FALSE)
2593 			Color_Negative (buffer, emul_len,
2594 					s->ScanParams.depth);
2595 		    }
2596 		  else if (s->cnv.negative != FALSE)
2597 		    Color_Negative (buffer, emul_len, s->ScanParams.depth);
2598 
2599 		  /* emulating grayscale ? */
2600 		  if (s->cnv.colormode == CM_GRAY)
2601 		    {
2602 		      Color_to_Gray (buffer, emul_len, s->ScanParams.depth);
2603 		      emul_len /= 3;
2604 		    }
2605 
2606 		  /* emulating depth */
2607 		  if (s->cnv.depth != -1)
2608 		    {
2609 		      switch (s->cnv.depth)
2610 			{
2611 			  /* case 1: treated separately as lineart */
2612 			  /*case 12: in the future */
2613 			case 8:
2614 			  Depth_16_to_8 (buffer, emul_len, buffer);
2615 			  emul_len /= 2;
2616 			  break;
2617 			}
2618 		    }
2619 
2620 		  /* lineart mode ? */
2621 		  if (s->cnv.colormode == CM_LINEART)
2622 		    {
2623 		      /* I didn't see any scanner supporting lineart mode.
2624 		         Windows drivers scan in grayscale and then convert image to lineart
2625 		         so let's perform conversion */
2626 		      SANE_Int rest = emul_len % 8;
2627 
2628 		      Gray_to_Lineart (buffer, emul_len, s->cnv.threshold);
2629 		      emul_len /= 8;
2630 		      if (rest > 0)
2631 			emul_len++;
2632 		    }
2633 
2634 		  /* copy postprocessed image */
2635 		  *len = emul_len;
2636 		  memcpy (buf, buffer, *len);
2637 		}
2638 
2639 	      free (buffer);
2640 	    }
2641 	}
2642     }
2643   else
2644     rst = SANE_STATUS_EOF;
2645 
2646   DBG (DBG_FNC, "- sane_read: %s\n", sane_strstatus (rst));
2647 
2648   return rst;
2649 }
2650 
2651 void
sane_cancel(SANE_Handle h)2652 sane_cancel (SANE_Handle h)
2653 {
2654   DBG (DBG_FNC, "> sane_cancel\n");
2655 
2656   /* silence gcc */
2657   h = h;
2658 
2659   device->status->cancel = TRUE;
2660 }
2661 
2662 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)2663 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2664 {
2665   DBG (DBG_FNC, "> sane_set_io_mode\n");
2666 
2667   /* silence gcc */
2668   handle = handle;
2669   non_blocking = non_blocking;
2670 
2671   return SANE_STATUS_UNSUPPORTED;
2672 }
2673 
2674 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)2675 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2676 {
2677   DBG (DBG_FNC, "> sane_get_select_fd\n");
2678 
2679   /* silence gcc */
2680   handle = handle;
2681   fd = fd;
2682 
2683   return SANE_STATUS_UNSUPPORTED;
2684 }
2685 
2686 void
sane_close(SANE_Handle h)2687 sane_close (SANE_Handle h)
2688 {
2689   TScanner *scanner = (TScanner *) h;
2690 
2691   DBG (DBG_FNC, "- sane_close...\n");
2692 
2693   /* stop previous scans */
2694   RTS_Scanner_StopScan (device, TRUE);
2695 
2696   /* close usb */
2697   sanei_usb_close (device->usb_handle);
2698 
2699   /* free scanner internal variables */
2700   RTS_Scanner_End (device);
2701 
2702   /* free RTS environment */
2703   RTS_Free (device);
2704 
2705   /* free backend variables */
2706   if (scanner != NULL)
2707     {
2708       options_free (scanner);
2709 
2710       img_buffers_free (scanner);
2711     }
2712 }
2713 
2714 void
sane_exit(void)2715 sane_exit (void)
2716 {
2717   /* free device list memory */
2718   if (_pSaneDevList)
2719     {
2720       TDevListEntry *pDev, *pNext;
2721 
2722       for (pDev = _pFirstSaneDev; pDev; pDev = pNext)
2723 	{
2724 	  pNext = pDev->pNext;
2725 	  /* pDev->dev.name is the same pointer that pDev->devname */
2726 	  free (pDev->devname);
2727 	  free (pDev);
2728 	}
2729 
2730       _pFirstSaneDev = NULL;
2731       free (_pSaneDevList);
2732       _pSaneDevList = NULL;
2733     }
2734 }
2735