• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 2000-2005 Mustek.
4    Originally maintained by Mustek
5 
6    Copyright (C) 2001-2005 by Henning Meier-Geinitz.
7 
8    This file is part of the SANE package.
9 
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of the
13    License, or (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <https://www.gnu.org/licenses/>.
22 
23    As a special exception, the authors of SANE give permission for
24    additional uses of the libraries contained in this release of SANE.
25 
26    The exception is that, if you link a SANE library with other files
27    to produce an executable, this does not by itself cause the
28    resulting executable to be covered by the GNU General Public
29    License.  Your use of that executable is in no way restricted on
30    account of linking the SANE library code into it.
31 
32    This exception does not, however, invalidate any other reasons why
33    the executable file might be covered by the GNU General Public
34    License.
35 
36    If you submit changes to SANE to the maintainers to be included in
37    a subsequent release, you agree by submitting the changes that
38    those changes may be distributed with this exception intact.
39 
40    If you write modifications of your own for SANE, it is your choice
41    whether to permit this exception to apply to your modifications.
42    If you do not wish that, delete this exception notice.
43 
44    This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro
45    and similar USB2 scanners. */
46 
47 #define BUILD 10
48 
49 #include "../include/sane/config.h"
50 
51 #include <ctype.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <limits.h>
55 #include <signal.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60 #include <math.h>
61 
62 #include <sys/time.h>
63 #include <sys/types.h>
64 #include <sys/wait.h>
65 
66 #include "../include/sane/sane.h"
67 #include "../include/sane/sanei.h"
68 #include "../include/sane/saneopts.h"
69 
70 #define BACKEND_NAME mustek_usb2
71 
72 #include "../include/sane/sanei_backend.h"
73 #include "mustek_usb2_high.c"
74 
75 #include "mustek_usb2.h"
76 
77 static SANE_Int num_devices;
78 static const SANE_Device **devlist = 0;
79 
80 static const SANE_Range u8_range = {
81   0,				/* minimum */
82   255,				/* maximum */
83   0				/* quantization */
84 };
85 static SANE_Range x_range = {
86   SANE_FIX (0.0),		/* minimum */
87   SANE_FIX (8.3 * MM_PER_INCH),	/* maximum */
88   SANE_FIX (0.0)		/* quantization */
89 };
90 
91 static SANE_Range y_range = {
92   SANE_FIX (0.0),		/* minimum */
93   SANE_FIX (11.6 * MM_PER_INCH),	/* maximum */
94   SANE_FIX (0.0)		/* quantization */
95 };
96 
97 static SANE_Range gamma_range = {
98   SANE_FIX (0.01),		/* minimum */
99   SANE_FIX (5.0),		/* maximum */
100   SANE_FIX (0.01)		/* quantization */
101 };
102 static SANE_String_Const mode_list[] = {
103   SANE_I18N ("Color48"),
104   SANE_I18N ("Color24"),
105   SANE_I18N ("Gray16"),
106   SANE_I18N ("Gray8"),
107   SANE_VALUE_SCAN_MODE_LINEART,
108   0
109 };
110 
111 static SANE_String_Const negative_mode_list[] = {
112   SANE_I18N ("Color24"),
113   0
114 };
115 
116 static SANE_String_Const source_list[] = {
117   SANE_I18N ("Reflective"),
118   SANE_I18N ("Positive"),
119   SANE_I18N ("Negative"),
120   0
121 };
122 static Scanner_Model mustek_A2nu2_model = {
123   "mustek-A2nu2",		/* Name */
124   "Mustek",			/* Device vendor string */
125 
126   "BearPaw 2448TA Pro",		/* Device model name */
127   "",				/* Name of the firmware file */
128 
129   {1200, 600, 300, 150, 75, 0},	/* possible resolutions */
130 
131   SANE_FIX (0.0),		/* Start of scan area in mm  (x) */
132   SANE_FIX (0.0),		/* Start of scan area in mm (y) */
133   SANE_FIX (8.3 * MM_PER_INCH),	/* Size of scan area in mm (x) */
134   SANE_FIX (11.6 * MM_PER_INCH),	/* Size of scan area in mm (y) */
135 
136   SANE_FIX (0.0),		/* Start of scan area in TA mode in mm (x) */
137   SANE_FIX (0.0),		/* Start of scan area in TA mode in mm (y) */
138   SANE_FIX (1.46 * MM_PER_INCH),	/* Size of scan area in TA mode in mm (x) */
139   SANE_FIX (6.45 * MM_PER_INCH),	/* Size of scan area in TA mode in mm (y) */
140 
141   0,				/* Order of the CCD/CIS colors 0:RO_RGB 1:RO_BGR */
142   SANE_FIX (2.0),		/* Default gamma value */
143 
144   SANE_FALSE,			/* Is this a CIS scanner? */
145   0				/* Which flags are needed for this scanner? */
146     /* Setup and tested */
147 };
148 
149 
150 /* Forward declarations */
151 
152 static SANE_Bool GetDeviceStatus (void);
153 static SANE_Bool PowerControl (SANE_Bool isLampOn, SANE_Bool isTaLampOn);
154 static SANE_Bool CarriageHome (void);
155 static SANE_Bool SetParameters (LPSETPARAMETERS pSetParameters);
156 static SANE_Bool GetParameters (LPGETPARAMETERS pGetParameters);
157 static SANE_Bool StartScan (void);
158 static SANE_Bool ReadScannedData (LPIMAGEROWS pImageRows);
159 static SANE_Bool StopScan (void);
160 static SANE_Bool IsTAConnected (void);
161 static void AutoLevel (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
162 		unsigned int BytesPerLine);
163 static size_t max_string_size (const SANE_String_Const strings[]);
164 static SANE_Status calc_parameters (Mustek_Scanner * s);
165 #ifdef SANE_UNUSED
166 static SANE_Bool GetGammaInfo (LPGAMMAINFO pGamaInfo);
167 static SANE_Bool GetKeyStatus (SANE_Byte * pKey);
168 static void QBetChange (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
169 		 unsigned int BytesPerLine);
170 static void QBETDetectAutoLevel (void *pDIB, unsigned int ImageWidth, unsigned int ImageHeight);
171 #endif
172 
173 
174 
175 static size_t
max_string_size(const SANE_String_Const strings[])176 max_string_size (const SANE_String_Const strings[])
177 {
178   size_t size, max_size = 0;
179   SANE_Int i;
180 
181   for (i = 0; strings[i]; ++i)
182     {
183       size = strlen (strings[i]) + 1;
184       if (size > max_size)
185 	max_size = size;
186     }
187   return max_size;
188 }
189 
190 static SANE_Status
calc_parameters(Mustek_Scanner * s)191 calc_parameters (Mustek_Scanner * s)
192 {
193   SANE_String val, val_source;
194   val = s->val[OPT_MODE].s;
195   val_source = s->val[OPT_SOURCE].s;
196 
197   s->params.last_frame = SANE_TRUE;
198 
199   if (strcmp (val, "Color48") == 0)	/* Color48 */
200     {
201       s->params.format = SANE_FRAME_RGB;
202       s->params.depth = 16;
203       s->setpara.smScanMode = SM_RGB48;
204       if (s->val[OPT_PREVIEW].w)
205 	{
206 	  DBG (DBG_DET, "calc_parameters : preview set ScanMode SM_RGB24\n");
207 	  s->params.depth = 8;
208 	  s->setpara.smScanMode = SM_RGB24;
209 	}
210     }
211   else if (strcmp (val, "Color24") == 0)	/* Color24 */
212     {
213       s->params.format = SANE_FRAME_RGB;
214       s->params.depth = 8;
215       s->setpara.smScanMode = SM_RGB24;
216     }
217   else if (strcmp (val, "Gray16") == 0)
218     {
219       s->params.format = SANE_FRAME_GRAY;
220       s->params.depth = 16;
221       s->setpara.smScanMode = SM_GRAY16;
222       if (s->val[OPT_PREVIEW].w)
223 	{
224 	  s->params.depth = 8;
225 	  DBG (DBG_DET, "calc_parameters : preview set ScanMode SM_GRAY\n");
226 	  s->setpara.smScanMode = SM_GRAY;
227 	}
228     }
229   else if (strcmp (val, "Gray8") == 0)
230     {
231       s->params.format = SANE_FRAME_GRAY;
232       s->params.depth = 8;
233       s->setpara.smScanMode = SM_GRAY;
234     }
235   else if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)
236     {
237       s->params.format = SANE_FRAME_GRAY;
238       s->params.depth = 1;
239       s->setpara.smScanMode = SM_TEXT;
240     }
241 
242   /*set Scan Source */
243   DBG (DBG_DET, "calc_parameters :scan Source = %s\n", val_source);
244   if (strcmp (val_source, "Reflective") == 0)
245     {
246       s->setpara.ssScanSource = SS_Reflective;
247     }
248   else if (strcmp (val_source, "Positive") == 0)
249     {
250       s->setpara.ssScanSource = SS_Positive;
251     }
252   else if (strcmp (val_source, "Negative") == 0)
253     {
254       s->setpara.ssScanSource = SS_Negative;
255     }
256 
257 
258   s->setpara.fmArea.x1 =
259     (unsigned short) ((SANE_UNFIX (s->val[OPT_TL_X].w) * 300.0) / MM_PER_INCH + 0.5);
260   s->setpara.fmArea.x2 =
261     (unsigned short) ((SANE_UNFIX (s->val[OPT_BR_X].w) * 300.0) / MM_PER_INCH + 0.5);
262   s->setpara.fmArea.y1 =
263     (unsigned short) ((SANE_UNFIX (s->val[OPT_TL_Y].w) * 300.0) / MM_PER_INCH + 0.5);
264   s->setpara.fmArea.y2 =
265     (unsigned short) ((SANE_UNFIX (s->val[OPT_BR_Y].w) * 300.0) / MM_PER_INCH + 0.5);
266 
267   if (s->val[OPT_PREVIEW].w)
268     {
269       s->setpara.fmArea.y1 = s->setpara.fmArea.y1 + PER_ADD_START_LINES;
270       s->setpara.fmArea.x1 += PRE_ADD_START_X;
271     }				/*just for range bug. */
272 
273   s->setpara.pfPixelFlavor = PF_BlackIs0;
274   s->setpara.wLinearThreshold = s->val[OPT_THRESHOLD].w;
275 
276   s->setpara.wTargetDPI = s->val[OPT_RESOLUTION].w;
277   if (s->val[OPT_PREVIEW].w)
278     {
279       s->setpara.wTargetDPI = 75;
280     }
281 
282   s->setpara.pGammaTable = NULL;
283 
284   s->params.pixels_per_line =
285     (SANE_Int) ((s->setpara.fmArea.x2 -
286 		 s->setpara.fmArea.x1) * s->setpara.wTargetDPI / 300.0 + 0.5);
287 
288   switch (s->params.format)
289     {
290     case SANE_FRAME_RGB:
291       if (s->params.depth == 8)
292 	s->params.bytes_per_line = s->params.pixels_per_line * 3;
293       if (s->params.depth == 16)
294 	s->params.bytes_per_line = s->params.pixels_per_line * 6;
295       break;
296     case SANE_FRAME_GRAY:
297       if (s->params.depth == 1)
298 	s->params.bytes_per_line = s->params.pixels_per_line / 8;
299       if (s->params.depth == 8)
300 	s->params.bytes_per_line = s->params.pixels_per_line;
301       if (s->params.depth == 16)
302 	s->params.bytes_per_line = s->params.pixels_per_line * 2;
303       break;
304     default:
305       DBG (DBG_DET, "sane_star:sane params .format = %d\n", s->params.format);
306     }
307 
308   s->params.lines =
309     (SANE_Int) ((s->setpara.fmArea.y2 -
310 		 s->setpara.fmArea.y1) * s->setpara.wTargetDPI / 300 + 0.5);
311 
312   DBG (DBG_FUNC, "calc_parameters: end\n");
313 
314   return SANE_STATUS_GOOD;
315 }
316 
317 static SANE_Status
init_options(Mustek_Scanner * s)318 init_options (Mustek_Scanner * s)
319 {
320   SANE_Int option, count;
321   SANE_Word *dpi_list;		/*Resolution Support */
322 
323   DBG (DBG_FUNC, "init_options: start\n");
324 
325   memset (s->opt, 0, sizeof (s->opt));
326   memset (s->val, 0, sizeof (s->val));
327 
328   for (option = 0; option < NUM_OPTIONS; ++option)
329     {
330       s->opt[option].size = sizeof (SANE_Word);
331       s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
332     }
333   /*  Option num */
334   s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
335   s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
336   s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
337   s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
338   s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
339   s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
340 
341   /* "Mode" group: */
342   s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode");
343   s->opt[OPT_MODE_GROUP].desc = "";
344   s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
345   s->opt[OPT_MODE_GROUP].size = 0;
346   s->opt[OPT_MODE_GROUP].cap = 0;
347   s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
348 
349   /* scan mode */
350   s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
351   s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
352   s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
353   s->opt[OPT_MODE].type = SANE_TYPE_STRING;
354   s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
355   s->opt[OPT_MODE].size = max_string_size (mode_list);
356   s->opt[OPT_MODE].constraint.string_list = mode_list;
357   s->val[OPT_MODE].s = strdup ("Color24");
358 
359   /* Scan Source */
360   s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
361   s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
362   s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
363   s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
364   s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
365   s->opt[OPT_SOURCE].size = max_string_size (source_list);
366   s->opt[OPT_SOURCE].constraint.string_list = source_list;
367   s->val[OPT_SOURCE].s = strdup ("Reflective");
368 
369   if (!IsTAConnected ())
370     {
371       DISABLE (OPT_SOURCE);
372     }
373 
374 
375   /* resolution */
376 
377   for (count = 0; s->model.dpi_values[count] != 0; count++)
378     {
379     }
380   dpi_list = malloc ((count + 1) * sizeof (SANE_Word));
381   if (!dpi_list)
382     return SANE_STATUS_NO_MEM;
383   dpi_list[0] = count;
384 
385   for (count = 0; s->model.dpi_values[count] != 0; count++)
386     dpi_list[count + 1] = s->model.dpi_values[count];
387 
388   s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
389   s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
390 
391 
392   s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
393   s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
394   s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
395   s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
396   s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
397   s->val[OPT_RESOLUTION].w = 300;
398 
399   /* preview */
400   s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
401   s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
402   s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
403   s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
404   s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
405   s->val[OPT_PREVIEW].w = SANE_FALSE;
406 
407   /* "Debug" group: */
408   s->opt[OPT_DEBUG_GROUP].title = SANE_I18N ("Debugging Options");
409   s->opt[OPT_DEBUG_GROUP].desc = "";
410   s->opt[OPT_DEBUG_GROUP].type = SANE_TYPE_GROUP;
411   s->opt[OPT_DEBUG_GROUP].size = 0;
412   s->opt[OPT_DEBUG_GROUP].cap = 0;
413   s->opt[OPT_DEBUG_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
414 
415   /* auto warmup */
416   s->opt[OPT_AUTO_WARMUP].name = "auto-warmup";
417   s->opt[OPT_AUTO_WARMUP].title = SANE_I18N ("Automatic warmup");
418   s->opt[OPT_AUTO_WARMUP].desc =
419     SANE_I18N ("Warm-up until the lamp's brightness is constant "
420 	       "instead of insisting on 40 seconds warm-up time.");
421   s->opt[OPT_AUTO_WARMUP].type = SANE_TYPE_BOOL;
422   s->opt[OPT_AUTO_WARMUP].unit = SANE_UNIT_NONE;
423   s->opt[OPT_AUTO_WARMUP].constraint_type = SANE_CONSTRAINT_NONE;
424   s->val[OPT_AUTO_WARMUP].w = SANE_FALSE;
425   if (s->model.is_cis)
426     DISABLE (OPT_AUTO_WARMUP);
427 
428   /* "Enhancement" group: */
429   s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement");
430   s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
431   s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
432 
433   s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
434   s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
435   s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
436 
437   /* threshold */
438   s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
439   s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
440   s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
441   s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
442   s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
443   s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
444   s->opt[OPT_THRESHOLD].constraint.range = &u8_range;
445   s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
446   s->val[OPT_THRESHOLD].w = DEF_LINEARTTHRESHOLD;
447 
448   /* internal gamma value */
449   s->opt[OPT_GAMMA_VALUE].name = "gamma-value";
450   s->opt[OPT_GAMMA_VALUE].title = SANE_I18N ("Gamma value");
451   s->opt[OPT_GAMMA_VALUE].desc =
452     SANE_I18N ("Sets the gamma value of all channels.");
453   s->opt[OPT_GAMMA_VALUE].type = SANE_TYPE_FIXED;
454   s->opt[OPT_GAMMA_VALUE].unit = SANE_UNIT_NONE;
455   s->opt[OPT_GAMMA_VALUE].constraint_type = SANE_CONSTRAINT_RANGE;
456   s->opt[OPT_GAMMA_VALUE].constraint.range = &gamma_range;
457   s->opt[OPT_GAMMA_VALUE].cap |= SANE_CAP_EMULATED;
458   s->val[OPT_GAMMA_VALUE].w = s->model.default_gamma_value;
459 
460   DISABLE (OPT_GAMMA_VALUE);
461 
462   /* "Geometry" group: */
463   s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry");
464   s->opt[OPT_GEOMETRY_GROUP].desc = "";
465   s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
466   s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
467   s->opt[OPT_GEOMETRY_GROUP].size = 0;
468   s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
469 
470   x_range.max = s->model.x_size;
471   y_range.max = s->model.y_size;
472 
473   /* top-left x */
474   s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
475   s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
476   s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
477   s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
478   s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
479   s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
480   s->opt[OPT_TL_X].constraint.range = &x_range;
481 
482   s->val[OPT_TL_X].w = 0;
483 
484   /* top-left y */
485   s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
486   s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
487   s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
488   s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
489   s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
490   s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
491   s->opt[OPT_TL_Y].constraint.range = &y_range;
492   s->val[OPT_TL_Y].w = 0;
493 
494   /* bottom-right x */
495   s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
496   s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
497   s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
498   s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
499   s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
500   s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
501   s->opt[OPT_BR_X].constraint.range = &x_range;
502   s->val[OPT_BR_X].w = x_range.max;
503 
504   /* bottom-right y */
505   s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
506   s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
507   s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
508   s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
509   s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
510   s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
511   s->opt[OPT_BR_Y].constraint.range = &y_range;
512   s->val[OPT_BR_Y].w = y_range.max;
513 
514   calc_parameters (s);
515 
516   DBG (DBG_FUNC, "init_options: exit\n");
517   return SANE_STATUS_GOOD;
518 }
519 
520 /***************************** Code from spicall.c *****************************/
521 
522 static SANE_Byte * g_lpNegImageData = NULL;
523 static SANE_Bool g_bIsFirstGetNegData = TRUE;
524 static SANE_Bool g_bIsMallocNegData = FALSE;
525 static unsigned int g_dwAlreadyGetNegLines = 0;
526 
527 /**********************************************************************
528 Author: Jack            Date: 2005/05/13
529 Routine Description:
530 	Check the device connect status
531 Parameters:
532 	none
533 Return value:
534 	if the device is connected
535 	return TRUE
536 	else
537 	return FALSE
538 ***********************************************************************/
539 static SANE_Bool
GetDeviceStatus()540 GetDeviceStatus ()
541 {
542   DBG (DBG_FUNC, "GetDeviceStatus: start\n");
543   return MustScanner_GetScannerState ();
544 }
545 
546 /**********************************************************************
547 Author: Jack            Date: 2005/05/13
548 Routine Description:
549 	Turn the lamp on or off
550 Parameters:
551 	isLampOn: turn the lamp on or off
552 	isTALampOn: turn the TA lamp on or off
553 Return value:
554 	if operation success
555 	return TRUE
556 	else
557 	return FALSE
558 ***********************************************************************/
559 static SANE_Bool
PowerControl(SANE_Bool isLampOn,SANE_Bool isTALampOn)560 PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn)
561 {
562   DBG (DBG_FUNC, "PowerControl: start\n");
563   return MustScanner_PowerControl (isLampOn, isTALampOn);
564 }
565 
566 /**********************************************************************
567 Author: Jack            Date: 2005/05/13
568 Routine Description:
569 	Turn the carriage home
570 Parameters:
571 	none
572 Return value:
573 	if the operation success
574 	return TRUE
575 	else
576 	return FALSE
577 ***********************************************************************/
578 static SANE_Bool
CarriageHome()579 CarriageHome ()
580 {
581   DBG (DBG_FUNC, "CarriageHome: start\n");
582   return MustScanner_BackHome ();
583 }
584 
585 #ifdef SANE_UNUSED
586 /**********************************************************************
587 Author: Jack            Date: 2005/05/13
588 Routine Description:
589 	Get gamma input/output bit count
590 Parameters:
591 	pGammaInfo: the gamma information
592 Return value:
593 	if the operation success
594 	return TRUE
595 	else
596 	return FALSE
597 ***********************************************************************/
598 static SANE_Bool
GetGammaInfo(LPGAMMAINFO pGammaInfo)599 GetGammaInfo (LPGAMMAINFO pGammaInfo)
600 {
601   DBG (DBG_FUNC, "GetGammaInfo: start\n");
602 
603   switch (pGammaInfo->smScanMode)
604     {
605     case SM_GRAY:
606       pGammaInfo->wInputGammaBits = 12;
607       pGammaInfo->wOutputGammaBits = 8;
608       break;
609     case SM_RGB24:
610       pGammaInfo->wInputGammaBits = 12;
611       pGammaInfo->wOutputGammaBits = 8;
612       break;
613     case SM_GRAY16:
614       pGammaInfo->wInputGammaBits = 16;
615       pGammaInfo->wOutputGammaBits = 16;
616       break;
617     case SM_RGB48:
618       pGammaInfo->wInputGammaBits = 16;
619       pGammaInfo->wOutputGammaBits = 16;
620       break;
621     default:
622       pGammaInfo->wInputGammaBits = 0;
623       pGammaInfo->wOutputGammaBits = 0;
624       return FALSE;
625     }
626 
627   DBG (DBG_FUNC, "GetGammaInfo: exit\n");
628   return TRUE;
629 }
630 #endif
631 /**********************************************************************
632 Author: Jack            Date: 2005/05/13
633 Routine Description:
634 	set scan parameters
635 Parameters:
636 	pSetParameters: the information of scanning
637 Return value:
638 	if the operation success
639 	return TRUE
640 	else
641 	return FALSE
642 ***********************************************************************/
643 static SANE_Bool
SetParameters(LPSETPARAMETERS pSetParameters)644 SetParameters (LPSETPARAMETERS pSetParameters)
645 {
646   unsigned short X1inTargetDpi;
647   unsigned short Y1inTargetDpi;
648   unsigned short X2inTargetDpi;
649   unsigned short Y2inTargetDpi;
650 
651   DBG (DBG_FUNC, "SetParameters: start\n");
652 
653   /*0. Reset */
654   if (ST_Reflective == g_ScanType)
655     {
656       Reflective_Reset ();
657     }
658   else
659     {
660       Transparent_Reset ();
661     }
662 
663   /*1. Scan mode */
664   switch (pSetParameters->smScanMode)
665     {
666     case SM_TEXT:
667       g_tiTarget.cmColorMode = CM_TEXT;
668       break;
669     case SM_GRAY:
670       g_tiTarget.cmColorMode = CM_GRAY8;
671       break;
672     case SM_GRAY16:
673       g_tiTarget.cmColorMode = CM_GRAY16;
674       break;
675     case SM_RGB24:
676       g_tiTarget.cmColorMode = CM_RGB24;
677       break;
678     case SM_RGB48:
679       g_tiTarget.cmColorMode = CM_RGB48;
680       break;
681     default:
682       return FALSE;
683     }
684 
685   /*2. Scan source */
686   g_ssScanSource = pSetParameters->ssScanSource;
687   g_tiTarget.bScanSource = pSetParameters->ssScanSource;
688 
689 
690   if (SS_Reflective == pSetParameters->ssScanSource)
691     {
692       g_ScanType = ST_Reflective;
693     }
694   else if (SS_Positive == pSetParameters->ssScanSource
695 	   || SS_Negative == pSetParameters->ssScanSource
696 	   || SS_ADF == pSetParameters->ssScanSource)
697     {
698       g_ScanType = ST_Transparent;
699     }
700   else
701     {
702       DBG (DBG_ERR, "SetParameters: ScanSource error\n");
703       return FALSE;
704     }
705 
706   /*3. pixel flavor */
707   if (PF_BlackIs0 == pSetParameters->pfPixelFlavor
708       || PF_WhiteIs0 == pSetParameters->pfPixelFlavor)
709     {
710       g_PixelFlavor = pSetParameters->pfPixelFlavor;
711     }
712   else
713     {
714       DBG (DBG_ERR, "SetParameters: PixelFlavor error\n");
715       return FALSE;
716     }
717 
718   /*4. Scan area */
719   if (pSetParameters->fmArea.x1 >= pSetParameters->fmArea.x2)
720     {
721       DBG (DBG_ERR, "SetParameters: x1 > x2, error\n");
722       return FALSE;
723     }
724   if (pSetParameters->fmArea.y1 >= pSetParameters->fmArea.y2)
725     {
726       DBG (DBG_ERR, "SetParameters: y1 >= y2, error\n");
727       return FALSE;
728     }
729   if (pSetParameters->fmArea.x2 > MAX_SCANNING_WIDTH)	/* Just for A4 size */
730     {
731       DBG (DBG_ERR, "SetParameters: x2 > MAX_SCANNING_WIDTH, error\n");
732       return FALSE;
733     }
734   if (pSetParameters->fmArea.y2 > MAX_SCANNING_HEIGHT)	/* Just for A4 size */
735     {
736       DBG (DBG_ERR, "SetParameters: y2 > MAX_SCANNING_HEIGHT, error\n");
737       return FALSE;
738     }
739 
740   X1inTargetDpi =
741     (unsigned short) ((unsigned int) (pSetParameters->fmArea.x1) *
742 	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
743   Y1inTargetDpi =
744     (unsigned short) ((unsigned int) (pSetParameters->fmArea.y1) *
745 	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
746   X2inTargetDpi =
747     (unsigned short) ((unsigned int) (pSetParameters->fmArea.x2) *
748 	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
749   Y2inTargetDpi =
750     (unsigned short) ((unsigned int) (pSetParameters->fmArea.y2) *
751 	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
752 
753   g_tiTarget.isOptimalSpeed = TRUE;
754   g_tiTarget.wDpi = pSetParameters->wTargetDPI;
755   g_tiTarget.wX = X1inTargetDpi;
756   g_tiTarget.wY = Y1inTargetDpi;
757   g_tiTarget.wWidth = X2inTargetDpi - X1inTargetDpi;
758   g_tiTarget.wHeight = Y2inTargetDpi - Y1inTargetDpi;
759 
760   DBG (DBG_INFO, "SetParameters: g_tiTarget.wDpi=%d\n", g_tiTarget.wDpi);
761   DBG (DBG_INFO, "SetParameters: g_tiTarget.wX=%d\n", g_tiTarget.wX);
762   DBG (DBG_INFO, "SetParameters: g_tiTarget.wY=%d\n", g_tiTarget.wY);
763   DBG (DBG_INFO, "SetParameters: g_tiTarget.wWidth=%d\n", g_tiTarget.wWidth);
764   DBG (DBG_INFO, "SetParameters: g_tiTarget.wHeight=%d\n",
765        g_tiTarget.wHeight);
766 
767   /*5.Prepare */
768   if (FALSE == MustScanner_Prepare (g_tiTarget.bScanSource))
769     {
770       DBG (DBG_ERR, "SetParameters: MustScanner_Prepare fail\n");
771       return FALSE;
772     }
773 
774   /*6. Linear threshold */
775   if (pSetParameters->wLinearThreshold > 256
776       && pSetParameters->smScanMode == SM_TEXT)
777     {
778       DBG (DBG_ERR, "SetParameters: LinearThreshold error\n");
779       return FALSE;
780     }
781   else
782     {
783       g_wLineartThreshold = pSetParameters->wLinearThreshold;
784     }
785 
786   /*7. Gamma table */
787   if (NULL != pSetParameters->pGammaTable)
788     {
789       DBG (DBG_INFO, "SetParameters: IN gamma table not NULL\n");
790       g_pGammaTable = pSetParameters->pGammaTable;
791       g_isSelfGamma = FALSE;
792     }
793   else if (pSetParameters->smScanMode == SM_GRAY
794 	   || pSetParameters->smScanMode == SM_RGB24)
795     {
796       unsigned short i;
797       SANE_Byte byGammaData;
798       double pow_d;
799       double pow_z = (double) 10 / 16.0;
800 
801       g_pGammaTable = (unsigned short *) malloc (sizeof (unsigned short) * 4096 * 3);
802 
803       DBG (DBG_INFO, "SetParameters: gamma table malloc %ld Bytes\n",
804 	   (long int) sizeof (unsigned short) * 4096 * 3);
805       DBG (DBG_INFO, "SetParameters: address of g_pGammaTable=%p\n",
806 	   (void *) g_pGammaTable);
807 
808       if (NULL == g_pGammaTable)
809 	{
810 	  DBG (DBG_ERR, "SetParameters: gamma table malloc fail\n");
811 	  return FALSE;
812 	}
813       g_isSelfGamma = TRUE;
814 
815       for (i = 0; i < 4096; i++)
816 	{
817 	  pow_d = (double) i / (double) 4096;
818 
819 	  byGammaData = (SANE_Byte) (pow (pow_d, pow_z) * 255);
820 
821 	  *(g_pGammaTable + i) = byGammaData;
822 	  *(g_pGammaTable + i + 4096) = byGammaData;
823 	  *(g_pGammaTable + i + 8192) = byGammaData;
824 	}
825     }
826   else if (pSetParameters->smScanMode == SM_GRAY16
827 	   || pSetParameters->smScanMode == SM_RGB48)
828     {
829       unsigned int i, wGammaData;
830       g_pGammaTable = (unsigned short *) malloc (sizeof (unsigned short) * 65536 * 3);
831 
832       if (g_pGammaTable == NULL)
833 	{
834 	  DBG (DBG_ERR, "SetParameters: gamma table malloc fail\n");
835 	  return FALSE;
836 	}
837       g_isSelfGamma = TRUE;
838 
839       for (i = 0; i < 65536; i++)
840 	{
841 	  wGammaData =
842 	    (unsigned short) (pow ((((float) i) / 65536.0), (((float) 10) / 16.0)) *
843 		    65535);
844 
845 	  *(g_pGammaTable + i) = wGammaData;
846 	  *(g_pGammaTable + i + 65536) = wGammaData;
847 	  *(g_pGammaTable + i + 65536 * 2) = wGammaData;
848 	}
849     }
850   else
851     {
852       DBG (DBG_INFO, "SetParameters: set g_pGammaTable to NULL\n");
853       g_pGammaTable = NULL;
854     }
855 
856   DBG (DBG_FUNC, "SetParameters: exit\n");
857   return TRUE;
858 }
859 
860 /**********************************************************************
861 Author: Jack            Date: 2005/05/13
862 Routine Description:
863 	get the optical dpi and scan area
864 Parameters:
865 	pGetParameters: the information of scan
866 Return value:
867 	if the operation is success
868 	return TRUE
869 	else
870 	return FALSE
871 ***********************************************************************/
872 static SANE_Bool
GetParameters(LPGETPARAMETERS pGetParameters)873 GetParameters (LPGETPARAMETERS pGetParameters)
874 {
875   DBG (DBG_FUNC, "GetParameters: start\n");
876   if (ST_Reflective == g_ScanType)
877     {
878       if (FALSE == Reflective_ScanSuggest (&g_tiTarget, &g_ssSuggest))
879 	{
880 	  DBG (DBG_ERR, "GetParameters: Reflective_ScanSuggest error\n");
881 	  return FALSE;
882 	}
883     }
884   else
885     {
886       if (FALSE == Transparent_ScanSuggest (&g_tiTarget, &g_ssSuggest))
887 	{
888 	  DBG (DBG_ERR, "GetParameters: Transparent_ScanSuggest error\n");
889 	  return FALSE;
890 	}
891     }
892 
893   pGetParameters->wSourceXDPI = g_ssSuggest.wXDpi;
894   pGetParameters->wSourceYDPI = g_ssSuggest.wYDpi;
895   pGetParameters->dwLength = (unsigned int) g_ssSuggest.wHeight;
896   pGetParameters->dwLineByteWidth = g_ssSuggest.dwBytesPerRow;
897 
898   DBG (DBG_FUNC, "GetParameters: exit\n");
899 
900   return TRUE;
901 }
902 
903 /**********************************************************************
904 Author: Jack            Date: 2005/05/13
905 
906 Routine Description:
907 	start scan image
908 Parameters:
909 	none
910 Return value:
911 	if operation is success
912 	return TRUE
913 	else
914 	return FALSE
915 ***********************************************************************/
916 static SANE_Bool
StartScan()917 StartScan ()
918 {
919   DBG (DBG_FUNC, "StartScan: start\n");
920   if (ST_Reflective == g_ScanType)
921     {
922       DBG (DBG_INFO, "StartScan: g_ScanType==ST_Reflective\n");
923 
924       return Reflective_SetupScan (g_ssSuggest.cmScanMode,
925 				   g_ssSuggest.wXDpi,
926 				   g_ssSuggest.wYDpi,
927 				   PF_BlackIs0,
928 				   g_ssSuggest.wX,
929 				   g_ssSuggest.wY,
930 				   g_ssSuggest.wWidth, g_ssSuggest.wHeight);
931     }
932   else
933 
934     {
935 
936       DBG (DBG_INFO, "StartScan: g_ScanType==ST_Transparent\n");
937 
938       return Transparent_SetupScan (g_ssSuggest.cmScanMode,
939 				    g_ssSuggest.wXDpi,
940 				    g_ssSuggest.wYDpi,
941 				    PF_BlackIs0,
942 				    g_ssSuggest.wX,
943 				    g_ssSuggest.wY,
944 				    g_ssSuggest.wWidth, g_ssSuggest.wHeight);
945     }
946 }
947 
948 /**********************************************************************
949 Author: Jack             Date: 2005/05/14
950 Routine Description:
951 	Read the scanner data
952 Parameters:
953 
954 	pImageRows: the information of the data
955 Return value:
956 	if the operation is seccuss
957 	return TRUE
958 	else
959 	return FALSE
960 ***********************************************************************/
961 static SANE_Bool
ReadScannedData(LPIMAGEROWS pImageRows)962 ReadScannedData (LPIMAGEROWS pImageRows)
963 {
964   SANE_Bool isRGBInvert;
965   unsigned short Rows = 0;
966   SANE_Byte *lpBlock = (SANE_Byte *) pImageRows->pBuffer;
967   SANE_Byte *lpReturnData = (SANE_Byte *) pImageRows->pBuffer;
968   int i = 0;
969 
970   DBG (DBG_FUNC, "ReadScannedData: start\n");
971 
972   if (pImageRows->roRgbOrder == RO_RGB)
973     isRGBInvert = FALSE;
974   else
975     isRGBInvert = TRUE;
976 
977   Rows = pImageRows->wWantedLineNum;
978 
979   DBG (DBG_INFO, "ReadScannedData: wanted Rows = %d\n", Rows);
980 
981   if (ST_Reflective == g_ScanType)
982     {
983       if (FALSE == Reflective_GetRows (lpBlock, &Rows, isRGBInvert))
984 	return FALSE;
985     }
986   else if (SS_Positive == g_ssScanSource)
987     {
988       if (FALSE == Transparent_GetRows (lpBlock, &Rows, isRGBInvert))
989 	return FALSE;
990     }
991 
992   pImageRows->wXferedLineNum = Rows;
993 
994   if (g_PixelFlavor == PF_WhiteIs0 || g_ScanMode == CM_TEXT)
995     {
996       int TotalSize = Rows * g_ssSuggest.dwBytesPerRow;
997       for (i = 0; i < TotalSize; i++)
998 	{
999 	  *(lpBlock++) ^= 0xff;
1000 	}
1001     }
1002 
1003   if (SS_Negative == g_ssScanSource)
1004     {
1005       DBG (DBG_INFO, "ReadScannedData: deal with the Negative\n");
1006 
1007       if (g_bIsFirstGetNegData)
1008 	{
1009 	  unsigned int TotalImgeSize = g_SWHeight * g_ssSuggest.dwBytesPerRow;
1010 	  g_lpNegImageData = (SANE_Byte *) malloc (TotalImgeSize);
1011 	  if (NULL != g_lpNegImageData)
1012 	    {
1013 	      SANE_Byte * lpTempData = g_lpNegImageData;
1014 	      DBG (DBG_INFO,
1015 		   "ReadScannedData: malloc the negative data is success!\n");
1016 	      g_bIsMallocNegData = TRUE;
1017 	      if (!Transparent_GetRows
1018 		  (g_lpNegImageData, &g_SWHeight, isRGBInvert))
1019 		{
1020 		  return FALSE;
1021 		}
1022 
1023 	      DBG (DBG_INFO, "ReadScannedData: get image data is over!\n");
1024 
1025 	      for (i = 0; i < (int) TotalImgeSize; i++)
1026 		{
1027 		  *(g_lpNegImageData++) ^= 0xff;
1028 		}
1029 	      g_lpNegImageData = lpTempData;
1030 	      AutoLevel (g_lpNegImageData, g_ScanMode, g_SWHeight,
1031 			 g_ssSuggest.dwBytesPerRow);
1032 	      DBG (DBG_INFO, "ReadScannedData: autolevel is ok\n");
1033 	    }
1034 	  g_bIsFirstGetNegData = FALSE;
1035 	}
1036 
1037       if (g_bIsMallocNegData)
1038 	{
1039 	  memcpy (pImageRows->pBuffer,
1040 		  g_lpNegImageData +
1041 		  g_ssSuggest.dwBytesPerRow * g_dwAlreadyGetNegLines,
1042 		  g_ssSuggest.dwBytesPerRow * Rows);
1043 
1044 	  DBG (DBG_INFO, "ReadScannedData: copy the data over!\n");
1045 
1046 	  g_dwAlreadyGetNegLines += Rows;
1047 	  if (g_dwAlreadyGetNegLines >= g_SWHeight)
1048 	    {
1049 	      DBG (DBG_INFO, "ReadScannedData: free the image data!\n");
1050 	      free (g_lpNegImageData);
1051 	      g_lpNegImageData = NULL;
1052 	      g_bIsFirstGetNegData = TRUE;
1053 	      g_dwAlreadyGetNegLines = 0;
1054 	      g_bIsMallocNegData = FALSE;
1055 	    }
1056 	}
1057       else
1058 	{
1059 	  int TotalSize = Rows * g_ssSuggest.dwBytesPerRow;
1060 	  DBG (DBG_INFO,
1061 	       "ReadScannedData: malloc the negative data is fail!\n");
1062 	  if (!Transparent_GetRows (lpReturnData, &Rows, isRGBInvert))
1063 	    {
1064 	      return FALSE;
1065 	    }
1066 
1067 	  for (i = 0; i < TotalSize; i++)
1068 	    {
1069 	      *(lpReturnData++) ^= 0xff;
1070 	    }
1071 	  pImageRows->wXferedLineNum = Rows;
1072 
1073 	  g_dwAlreadyGetNegLines += Rows;
1074 	  if (g_dwAlreadyGetNegLines >= g_SWHeight)
1075 	    {
1076 	      g_bIsFirstGetNegData = TRUE;
1077 	      g_dwAlreadyGetNegLines = 0;
1078 	      g_bIsMallocNegData = FALSE;
1079 	    }
1080 	}
1081 
1082     }
1083 
1084   DBG (DBG_FUNC, "ReadScannedData: leave ReadScannedData\n");
1085 
1086   return TRUE;
1087 }
1088 
1089 /**********************************************************************
1090 Author: Jack             Date: 2005/05/14
1091 Routine Description:
1092 	Stop scan
1093 Parameters:
1094 	none
1095 Return value:
1096 	if operation is success
1097 	return TRUE
1098 	else
1099 	return FALSE
1100 ***********************************************************************/
1101 static SANE_Bool
StopScan()1102 StopScan ()
1103 {
1104   SANE_Bool rt;
1105   int i;
1106 
1107   DBG (DBG_FUNC, "StopScan: start\n");
1108 
1109   /*stop read data and kill thread */
1110   if (ST_Reflective == g_ScanType)
1111     {
1112       rt = Reflective_StopScan ();
1113     }
1114   else
1115     {
1116       rt = Transparent_StopScan ();
1117     }
1118 
1119   /*free gamma table */
1120   if (g_isSelfGamma && g_pGammaTable != NULL)
1121     {
1122       for (i = 0; i < 20; i++)
1123 	{
1124 	  if (!g_isScanning)
1125 	    {
1126 	      free (g_pGammaTable);
1127 	      g_pGammaTable = NULL;
1128 	      break;
1129 	    }
1130 	  else
1131 	    {
1132 	      sleep (1);	/*waiting ReadScannedData return. */
1133 	    }
1134 	}
1135     }
1136 
1137   /*free image buffer */
1138   if (g_lpReadImageHead != NULL)
1139 
1140     {
1141       free (g_lpReadImageHead);
1142       g_lpReadImageHead = NULL;
1143     }
1144 
1145   DBG (DBG_FUNC, "StopScan: exit\n");
1146   return rt;
1147 }
1148 
1149 /**********************************************************************
1150 Author: Jack             Date: 2005/05/14
1151 Routine Description:
1152 	Check the status of TA
1153 Parameters:
1154 	none
1155 Return value:
1156 	if operation is success
1157 	return TRUE
1158 	else
1159 	return FALSE
1160 ***********************************************************************/
1161 static SANE_Bool
IsTAConnected()1162 IsTAConnected ()
1163 {
1164   SANE_Bool hasTA;
1165 
1166   DBG (DBG_FUNC, "StopScan: start\n");
1167 
1168   if (Asic_Open (&g_chip, g_pDeviceFile) != SANE_STATUS_GOOD)
1169     {
1170       return FALSE;
1171     }
1172 
1173   if (Asic_IsTAConnected (&g_chip, &hasTA) != SANE_STATUS_GOOD)
1174     {
1175       Asic_Close (&g_chip);
1176       return FALSE;
1177     }
1178 
1179   Asic_Close (&g_chip);
1180 
1181   DBG (DBG_FUNC, "StopScan: exit\n");
1182   return hasTA;
1183 }
1184 
1185 #ifdef SANE_UNUSED
1186 /**********************************************************************
1187 Author: Jack             Date: 2005/05/14
1188 Routine Description:
1189 	Get the status of the HK
1190 Parameters:
1191 	pKey: the status of key
1192 Return value:
1193 	if the operation is success
1194 	return TRUE
1195 	else
1196 	return FALSE
1197 ***********************************************************************/
1198 static SANE_Bool
GetKeyStatus(SANE_Byte * pKey)1199 GetKeyStatus (SANE_Byte * pKey)
1200 {
1201   SANE_Byte pKeyTemp = 0x00;
1202   SANE_Status status = Asic_CheckFunctionKey (&g_chip, &pKeyTemp);
1203   DBG (DBG_FUNC, "GetKeyStatus: start\n");
1204 
1205   if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
1206     {
1207       DBG (DBG_ERR, "GetKeyStatus: Asic_Open is fail\n");
1208       return FALSE;
1209     }
1210 
1211   if (SANE_STATUS_GOOD != status)
1212     {
1213       DBG (DBG_ERR, "GetKeyStatus: Asic_CheckFunctionKey is fail\n");
1214       return FALSE;
1215     }
1216 
1217   if (0x01 == pKeyTemp)
1218     {
1219       *pKey = 0x01;		/*Scan key pressed */
1220     }
1221 
1222   if (0x02 == pKeyTemp)
1223     {
1224       *pKey = 0x02;		/*Copy key pressed */
1225     }
1226   if (0x04 == pKeyTemp)
1227     {
1228       *pKey = 0x03;		/*Fax key pressed */
1229     }
1230   if (0x08 == pKeyTemp)
1231     {
1232       *pKey = 0x04;		/*Email key pressed */
1233     }
1234   if (0x10 == pKeyTemp)
1235     {
1236       *pKey = 0x05;		/*Panel key pressed */
1237     }
1238 
1239   if (SANE_STATUS_GOOD != Asic_Close (&g_chip))
1240     {
1241       DBG (DBG_ERR, "GetKeyStatus: Asic_Close is fail\n");
1242       return FALSE;
1243     }
1244 
1245   DBG (DBG_FUNC, "GetKeyStatus: exit\n");
1246   return TRUE;
1247 }
1248 #endif
1249 /**********************************************************************
1250 Author: Jack             Date: 2005/05/14
1251 Routine Description:
1252 	Deal with the image with auto level
1253 Parameters:
1254 	lpSource: the data of image
1255 	scanMode: the scan mode
1256 	ScanLines: the rows of image
1257 	BytesPerLine: the bytes of per line
1258 Return value:
1259 	none
1260 ***********************************************************************/
1261 static void
AutoLevel(SANE_Byte * lpSource,SCANMODE scanMode,unsigned short ScanLines,unsigned int BytesPerLine)1262 AutoLevel (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
1263 	   unsigned int BytesPerLine)
1264 {
1265   int ii;
1266   unsigned int i, j;
1267   unsigned int tLines, CountPixels, TotalImgSize;
1268   unsigned short R, G, B, max_R, max_G, max_B, min_R, min_G, min_B;
1269   float fmax_R, fmax_G, fmax_B;
1270   unsigned int sum_R = 0, sum_G = 0, sum_B = 0;
1271   unsigned int hisgram_R[256], hisgram_G[256], hisgram_B[256];
1272 
1273   unsigned int iWidth = BytesPerLine / 3;
1274   unsigned int iHeight = ScanLines;
1275   SANE_Byte *pbmpdata = (SANE_Byte *) lpSource;
1276 
1277   unsigned short imin_threshold[3];
1278   unsigned short imax_threshold[3];
1279 
1280   DBG (DBG_FUNC, "AutoLevel: start\n");
1281 
1282   if (scanMode != CM_RGB24ext)
1283     {
1284       return;
1285     }
1286 
1287   i = j = 0;
1288   tLines = CountPixels = TotalImgSize = 0;
1289 
1290   TotalImgSize = iWidth * iHeight;
1291 
1292 
1293 
1294   for (i = 0; i < 256; i++)
1295     {
1296 
1297       hisgram_R[i] = 0;
1298       hisgram_G[i] = 0;
1299       hisgram_B[i] = 0;
1300     }
1301 
1302 
1303   DBG (DBG_INFO, "AutoLevel: init data is over\n");
1304 
1305   /* Find min , max, mean */
1306   max_R = max_G = max_B = 0;
1307   min_R = min_G = min_B = 255;
1308   tLines = 0;
1309   DBG (DBG_INFO, "AutoLevel: iHeight = %d, iWidth = %d\n", iHeight, iWidth);
1310 
1311   for (j = 0; j < iHeight; j++)
1312     {
1313       tLines = j * iWidth * 3;
1314 
1315 
1316       for (i = 0; i < iWidth; i++)
1317 	{
1318 	  R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1319 	  G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1320 	  B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1321 
1322 	  max_R = _MAX (R, max_R);
1323 	  max_G = _MAX (G, max_G);
1324 	  max_B = _MAX (B, max_B);
1325 
1326 	  min_R = _MIN (R, min_R);
1327 	  min_G = _MIN (G, min_G);
1328 	  min_B = _MIN (B, min_B);
1329 
1330 	  hisgram_R[(SANE_Byte) R]++;
1331 	  hisgram_G[(SANE_Byte) G]++;
1332 	  hisgram_B[(SANE_Byte) B]++;
1333 
1334 	  sum_R += R;
1335 	  sum_G += G;
1336 	  sum_B += B;
1337 
1338 	  *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R;
1339 	  *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G;
1340 	  *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B;
1341 
1342 	  CountPixels++;
1343 	}
1344 
1345     }
1346 
1347   DBG (DBG_INFO, "AutoLevel: Find min , max is over!\n");
1348 
1349 
1350   imin_threshold[0] = 0;
1351   imin_threshold[1] = 0;
1352   imin_threshold[2] = 0;
1353   imax_threshold[0] = 0;
1354   imax_threshold[1] = 0;
1355   imax_threshold[2] = 0;
1356 
1357   for (ii = 0; ii < 256; ii++)
1358     {
1359       if (hisgram_R[ii] > 0)
1360 	if (hisgram_R[ii] >= imin_threshold[0])
1361 	  {
1362 	    min_R = ii;
1363 	    break;
1364 	  }
1365     }
1366 
1367   for (ii = 255; ii >= 0; ii--)
1368     {
1369       if (hisgram_R[ii] > 0)
1370 	if (hisgram_R[ii] >= imax_threshold[0])
1371 	  {
1372 	    max_R = ii;
1373 	    break;
1374 	  }
1375     }
1376 
1377   for (ii = 0; ii < 256; ii++)
1378     {
1379       if (hisgram_G[ii] > 0)
1380 	if (hisgram_G[ii] >= imin_threshold[1])
1381 	  {
1382 	    min_G = ii;
1383 	    break;
1384 	  }
1385     }
1386 
1387   for (ii = 255; ii >= 0; ii--)
1388     {
1389       if (hisgram_G[ii] > 0)
1390 	if (hisgram_G[ii] >= imax_threshold[1])
1391 	  {
1392 	    max_G = ii;
1393 	    break;
1394 	  }
1395     }
1396 
1397   for (ii = 0; ii < 256; ii++)
1398     {
1399       if (hisgram_B[ii] > 0)
1400 	if (hisgram_B[ii] >= imin_threshold[2])
1401 	  {
1402 	    min_B = ii;
1403 	    break;
1404 	  }
1405     }
1406 
1407   for (ii = 255; ii >= 0; ii--)
1408     {
1409       if (hisgram_B[ii] > 0)
1410 	if (hisgram_B[ii] >= imax_threshold[2])
1411 	  {
1412 	    max_B = ii;
1413 	    break;
1414 	  }
1415     }
1416 
1417   DBG (DBG_INFO, "AutoLevel: Set min , max is over!\n");
1418 
1419   /*Autolevel: */
1420   sum_R = max_R - min_R;
1421   sum_G = max_G - min_G;
1422   sum_B = max_B - min_B;
1423 
1424   for (j = 0; j < iHeight; j++)
1425     {
1426       tLines = j * iWidth * 3;
1427       for (i = 0; i < iWidth; i++)
1428 	{
1429 	  R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1430 	  G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1431 	  B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1432 
1433 	   /*R*/ if (sum_R == 0)
1434 	    R = max_R;
1435 	  else if (R < min_R)
1436 	    R = 0;
1437 	  else if (R <= 255)
1438 	    {
1439 	      fmax_R = ((float) ((R - min_R) * 255) / (float) sum_R);
1440 	      R = (unsigned short) fmax_R;
1441 	      fmax_R = (fmax_R - R) * 10;
1442 
1443 	      if (fmax_R >= 5)
1444 		R++;
1445 	    }
1446 	  if (R > 255)
1447 	    R = 255;
1448 
1449 	   /*G*/ if (sum_G == 0)
1450 	    G = max_G;
1451 	  else if (G < min_G)
1452 	    G = 0;
1453 	  else if (G <= 255)
1454 	    {
1455 	      fmax_G = ((float) ((G - min_G) * 255) / (float) sum_G);
1456 	      G = (unsigned short) fmax_G;
1457 	      fmax_G = (fmax_G - G) * 10;
1458 	      if (fmax_G >= 5)
1459 		G++;
1460 
1461 	    }
1462 	  if (G > 255)
1463 	    G = 255;
1464 
1465 	   /*B*/ if (sum_B == 0)
1466 	    B = max_B;
1467 	  else if (B < min_B)
1468 	    B = 0;
1469 	  else if (B <= 255)
1470 	    {
1471 	      fmax_B = ((float) (B - min_B) * 255 / (float) sum_B);
1472 	      B = (unsigned short) fmax_B;
1473 	      fmax_B = (fmax_B - B) * 10;
1474 	      if (fmax_B >= 5)
1475 		B++;
1476 	    }
1477 	  if (B > 255)
1478 	    B = 255;
1479 
1480 	  hisgram_R[(SANE_Byte) R]++;
1481 	  hisgram_G[(SANE_Byte) G]++;
1482 	  hisgram_B[(SANE_Byte) B]++;
1483 
1484 	  *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R;
1485 	  *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G;
1486 	  *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B;
1487 
1488 	}
1489     }
1490 
1491   DBG (DBG_FUNC, "AutoLevel: exit\n");
1492   return;
1493 }
1494 
1495 #ifdef SANE_UNUSED
1496 /**********************************************************************
1497 Author: Jack             Date: 2005/05/14
1498 Routine Description:
1499 	Deal with image with auto level
1500 Parameters:
1501 	pDIB: the data of image
1502 	ImageWidth: the width of image
1503 	ImageHeight: the height of image
1504 Return value:
1505 	none
1506 ***********************************************************************/
1507 static void
QBETDetectAutoLevel(void * pDIB,unsigned int ImageWidth,unsigned int ImageHeight)1508 QBETDetectAutoLevel (void *pDIB, unsigned int ImageWidth, unsigned int ImageHeight)
1509 {
1510   unsigned short *pbmpdata;
1511   float fRPercent = 0.0;
1512   float fGPercent = 0.0;
1513   float fBPercent = 0.0;
1514   float fRSum, fGSum, fBSum;
1515 
1516   int i, j;
1517   unsigned int tLines, CountPixels, TotalImgSize;
1518   unsigned short R, G, B, max_R, max_G, max_B, min_R, min_G, min_B;
1519   unsigned short wIndexR, wIndexG, wIndexB;
1520   float fmax_R, fmax_G, fmax_B;
1521   unsigned int sum_R = 0, sum_G = 0, sum_B = 0;
1522   unsigned int hisgram_R[1024], hisgram_G[1024], hisgram_B[1024];
1523 
1524   if (!pDIB)
1525     {
1526       return;
1527     }
1528 
1529   pbmpdata = (unsigned short *) pDIB;
1530 
1531   CountPixels = 0;
1532   TotalImgSize = ImageWidth * ImageHeight;
1533 
1534 
1535   for (i = 0; i < 1024; i++)
1536     {
1537 
1538       hisgram_R[i] = 0;
1539       hisgram_G[i] = 0;
1540       hisgram_B[i] = 0;
1541     }
1542 
1543 
1544   /*Find min , max, mean */
1545   max_R = max_G = max_B = 0;
1546   min_R = min_G = min_B = 1023;
1547   tLines = 0;
1548 
1549   for (j = 0; j < (int) ImageHeight; j++)
1550     {
1551       tLines = j * ImageWidth * 3;
1552       for (i = 0; i < (int) ImageWidth; i++)
1553 	{
1554 	  R = *(pbmpdata + (tLines + i * 3 + 2));
1555 	  G = *(pbmpdata + (tLines + i * 3 + 1));
1556 	  B = *(pbmpdata + (tLines + i * 3));
1557 
1558 	  max_R = _MAX (R, max_R);
1559 	  max_G = _MAX (G, max_G);
1560 	  max_B = _MAX (B, max_B);
1561 
1562 	  min_R = _MIN (R, min_R);
1563 	  min_G = _MIN (G, min_G);
1564 	  min_B = _MIN (B, min_B);
1565 
1566 	  hisgram_R[R]++;
1567 	  hisgram_G[G]++;
1568 	  hisgram_B[B]++;
1569 
1570 	  sum_R += R;
1571 	  sum_G += G;
1572 	  sum_B += B;
1573 
1574 	  *(pbmpdata + (tLines + i * 3 + 2)) = R;
1575 	  *(pbmpdata + (tLines + i * 3 + 1)) = G;
1576 	  *(pbmpdata + (tLines + i * 3)) = B;
1577 
1578 	  CountPixels++;
1579 	}
1580 
1581     }
1582 
1583 
1584   fRSum = 0.0;
1585   fGSum = 0.0;
1586   fBSum = 0.0;
1587 
1588   wIndexR = 511;
1589   wIndexG = 511;
1590   wIndexB = 511;
1591 
1592   for (i = 0; i < 1024; i++)
1593     {
1594       fRSum += (float) hisgram_R[i];
1595       fRPercent = (fRSum / CountPixels) * 100;
1596       if (fRPercent > 50)
1597 	{
1598 	  wIndexR = i;
1599 	  break;
1600 	}
1601 
1602     }
1603 
1604   for (i = 0; i < 1024; i++)
1605     {
1606       fGSum += (float) hisgram_G[i];
1607       fGPercent = (fGSum / CountPixels) * 100;
1608       if (fGPercent > 50)
1609 	{
1610 	  wIndexG = i;
1611 	  break;
1612 	}
1613     }
1614 
1615   for (i = 0; i < 1024; i++)
1616     {
1617       fBSum += (float) hisgram_B[i];
1618       fBPercent = (fBSum / CountPixels) * 100;
1619       if (fBPercent > 50)
1620 	{
1621 	  wIndexB = i;
1622 	  break;
1623 	}
1624 
1625     }
1626 
1627 
1628   fRSum = 0.0;
1629 
1630   for (i = wIndexR; i >= 0; i--)
1631     {
1632       fRSum += (float) hisgram_R[i];
1633       fRPercent = (fRSum / CountPixels) * 100;
1634       if (fRPercent >= 48)
1635 	{
1636 	  min_R = i;
1637 	  break;
1638 	}
1639 
1640     }
1641 
1642   fRSum = 0.0;
1643   for (i = wIndexR; i < 1024; i++)
1644     {
1645       fRSum += (float) hisgram_R[i];
1646       fRPercent = (fRSum / CountPixels) * 100;
1647       if (fRPercent >= 47)
1648 	{
1649 	  max_R = i;
1650 	  break;
1651 	}
1652 
1653     }
1654 
1655 
1656   fGSum = 0.0;
1657   for (i = wIndexG; i >= 0; i--)
1658     {
1659       fGSum += (float) hisgram_G[i];
1660       fGPercent = (fGSum / CountPixels) * 100;
1661       if (fGPercent >= 48)
1662 	{
1663 	  min_G = i;
1664 	  break;
1665 	}
1666 
1667     }
1668 
1669   fGSum = 0.0;
1670   for (i = wIndexG; i < 1024; i++)
1671     {
1672       fGSum += (float) hisgram_G[i];
1673       fGPercent = (fGSum / CountPixels) * 100;
1674       if (fGPercent >= 47)
1675 	{
1676 	  max_G = i;
1677 	  break;
1678 	}
1679 
1680     }
1681 
1682   fBSum = 0.0;
1683   for (i = wIndexB; i >= 0; i--)
1684     {
1685       fBSum += (float) hisgram_B[i];
1686       fBPercent = (fBSum / CountPixels) * 100;
1687       if (fBPercent >= 46)
1688 	{
1689 	  min_B = i;
1690 	  break;
1691 	}
1692 
1693     }
1694 
1695   fBSum = 0.0;
1696   for (i = wIndexB; i < 1024; i++)
1697     {
1698       fBSum += (float) hisgram_B[i];
1699       fBPercent = (fBSum / CountPixels) * 100;
1700       if (fBPercent >= 47)
1701 	{
1702 	  max_B = i;
1703 	  break;
1704 	}
1705 
1706     }
1707 
1708 
1709   /*Autolevel: */
1710   sum_R = max_R - min_R;
1711   sum_G = max_G - min_G;
1712   sum_B = max_B - min_B;
1713 
1714   for (j = 0; j < (int) ImageHeight; j++)
1715     {
1716       tLines = j * ImageWidth * 3;
1717       for (i = 0; i < (int) ImageWidth; i++)
1718 	{
1719 	  R = *(pbmpdata + (tLines + i * 3 + 2));
1720 	  G = *(pbmpdata + (tLines + i * 3 + 1));
1721 	  B = *(pbmpdata + (tLines + i * 3));
1722 
1723 
1724 	   /*R*/ if (sum_R == 0)
1725 	    R = max_R;
1726 	  else if (R < min_R)
1727 	    {
1728 
1729 	      R = 0;
1730 	    }
1731 	  else if ((R >= min_R) && (R <= 1023))
1732 	    {
1733 	      fmax_R = ((float) ((R - min_R) * 923) / (float) sum_R) + 100;
1734 	      R = (unsigned short) fmax_R;
1735 	      fmax_R = (fmax_R - R) * 10;
1736 	      if (fmax_R >= 5)
1737 		R++;
1738 	    }
1739 	  if (R > 1023)
1740 	    R = 1023;
1741 
1742 	   /*G*/ if (sum_G == 0)
1743 	    G = max_G;
1744 	  else if (G < min_G)
1745 	    {
1746 
1747 	      G = 0;
1748 	    }
1749 	  else if ((G >= min_G) && (G <= 1023))
1750 	    {
1751 	      fmax_G = ((float) ((G - min_G) * 923) / (float) sum_G) + 100;
1752 	      G = (unsigned short) fmax_G;
1753 	      fmax_G = (fmax_G - G) * 10;
1754 	      if (fmax_G >= 5)
1755 		G++;
1756 	    }
1757 	  if (G > 1023)
1758 	    G = 1023;
1759 
1760 	   /*B*/ if (sum_B == 0)
1761 	    B = max_B;
1762 	  else if (B < min_R)
1763 	    {
1764 
1765 	      B = 0;
1766 	    }
1767 	  else if ((B >= min_B) && (R <= 1023))
1768 	    {
1769 	      fmax_B = ((float) (B - min_B) * 923 / (float) sum_B) + 100;
1770 
1771 	      B = (unsigned short) fmax_B;
1772 	      fmax_B = (fmax_B - B) * 10;
1773 	      if (fmax_B >= 5)
1774 		B++;
1775 	    }
1776 	  if (B > 1023)
1777 	    B = 1023;
1778 
1779 	  *(pbmpdata + (tLines + i * 3 + 2)) = R;
1780 	  *(pbmpdata + (tLines + i * 3 + 1)) = G;
1781 	  *(pbmpdata + (tLines + i * 3)) = B;
1782 
1783 	}
1784     }
1785 
1786   return;
1787 }
1788 #endif
1789 
1790 #ifdef SANE_UNUSED
1791 /**********************************************************************
1792 Author: Jack             Date: 2005/05/14
1793 Routine Description:
1794 	Change the image data and deal with auto level
1795 Parameters:
1796 	lpSource: the data of image
1797 	scanMode: the scan mode
1798 	ScanLines: the rows of image
1799 	BytesPerLine: the bytes of per line
1800 Return value:
1801 	none
1802 ***********************************************************************/
1803 static void
QBetChange(SANE_Byte * lpSource,SCANMODE scanMode,unsigned short ScanLines,unsigned int BytesPerLine)1804 QBetChange (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
1805 	    unsigned int BytesPerLine)
1806 {
1807   unsigned short i, j;
1808   unsigned int tLines, TotalImgSize;
1809   unsigned short R1, G1, B1, R, G, B, R2, G2, B2, QBET_RGB = 0, PointF, PointB;
1810   unsigned short *pwRGB;
1811 
1812   int k;
1813 
1814   unsigned int ImageWidth = BytesPerLine / 3;
1815   unsigned int ImageHeight = ScanLines;
1816   SANE_Byte *pbmpdata = (SANE_Byte *) lpSource;
1817 
1818   if (scanMode != CM_RGB24ext)
1819     {
1820       return;
1821     }
1822 
1823 
1824   TotalImgSize = ImageWidth * ImageHeight * 3 * 2;
1825   if ((pwRGB = (unsigned short *) malloc (TotalImgSize)) == NULL)
1826     {
1827       return;
1828     }
1829 
1830 
1831   for (j = 0; j < ImageHeight; j++)
1832     {
1833       tLines = j * ImageWidth * 3;
1834       for (i = 0; i < ImageWidth; i++)
1835 	{
1836 	  if (i == 0)
1837 	    {
1838 	      R1 = R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1839 	      G1 = G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1840 	      B1 = B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1841 	      R2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 2));
1842 	      G2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 1));
1843 	      B2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3));
1844 	    }
1845 	  else if (i == (ImageWidth - 1))
1846 	    {
1847 	      R1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 2));
1848 	      G1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 1));
1849 	      B1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3));
1850 	      R2 = R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1851 	      G2 = G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1852 	      B2 = B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1853 	    }
1854 	  else
1855 	    {
1856 	      R1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 2));
1857 	      G1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 1));
1858 	      B1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3));
1859 
1860 	      R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1861 	      G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1862 	      B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1863 
1864 	      R2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 2));
1865 	      G2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 1));
1866 	      B2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3));
1867 	    }
1868 
1869 	  R1 = R1 & 0x0003;
1870 	  G1 = G1 & 0x0003;
1871 	  B1 = B1 & 0x0003;
1872 
1873 	  R2 = R2 & 0x0003;
1874 	  G2 = G2 & 0x0003;
1875 	  B2 = B2 & 0x0003;
1876 	  for (k = 0; k < 3; k++)
1877 	    {
1878 	      if (k == 0)
1879 		{
1880 		  PointF = R1;
1881 		  PointB = R2;
1882 		}
1883 	      else if (k == 1)
1884 		{
1885 		  PointF = G1;
1886 		  PointB = G2;
1887 		}
1888 	      else if (k == 2)
1889 		{
1890 		  PointF = B1;
1891 		  PointB = B2;
1892 		}
1893 
1894 	      switch (PointF)
1895 		{
1896 		case 0:
1897 		case 1:
1898 		  if (PointB == 0)
1899 		    QBET_RGB = 0xFFFC;
1900 		  else if (PointB == 1)
1901 		    QBET_RGB = 0xFFFC;
1902 		  else if (PointB == 2)
1903 		    QBET_RGB = 0xFFFD;
1904 		  else if (PointB == 3)
1905 		    QBET_RGB = 0xFFFE;
1906 		  break;
1907 		case 2:
1908 		  if (PointB == 0)
1909 		    QBET_RGB = 0xFFFD;
1910 		  else if (PointB == 1)
1911 		    QBET_RGB = 0xFFFD;
1912 		  else if (PointB == 2)
1913 		    QBET_RGB = 0xFFFF;
1914 		  else if (PointB == 3)
1915 		    QBET_RGB = 0xFFFF;
1916 		  break;
1917 		case 3:
1918 		  if (PointB == 0)
1919 		    QBET_RGB = 0xFFFE;
1920 		  else if (PointB == 1)
1921 		    QBET_RGB = 0xFFFE;
1922 		  else if (PointB == 2)
1923 		    QBET_RGB = 0xFFFF;
1924 		  else if (PointB == 3)
1925 		    QBET_RGB = 0xFFFF;
1926 		  break;
1927 		default:
1928 		  break;
1929 		}
1930 
1931 	      if (k == 0)
1932 		{
1933 		  R = R << 2;
1934 		  R = R + 0x0003;
1935 		  R = R & QBET_RGB;
1936 		}
1937 	      else if (k == 1)
1938 		{
1939 		  G = G << 2;
1940 		  G = G + 0x0003;
1941 		  G = G & QBET_RGB;
1942 		}
1943 	      else if (k == 2)
1944 		{
1945 		  B = B << 2;
1946 		  B = B + 0x0003;
1947 		  B = B & QBET_RGB;
1948 		}
1949 
1950 	    }
1951 
1952 	  *(pwRGB + (tLines + i * 3 + 2)) = R;
1953 	  *(pwRGB + (tLines + i * 3 + 1)) = G;
1954 	  *(pwRGB + (tLines + i * 3)) = B;
1955 
1956 	}
1957 
1958     }
1959 
1960 
1961   QBETDetectAutoLevel (pwRGB, ImageWidth, ImageHeight);
1962 
1963 
1964   for (j = 0; j < ImageHeight; j++)
1965     {
1966       tLines = j * ImageWidth * 3;
1967 
1968       for (i = 0; i < ImageWidth; i++)
1969 	{
1970 	  R = *(pwRGB + (tLines + i * 3 + 2));
1971 	  G = *(pwRGB + (tLines + i * 3 + 1));
1972 	  B = *(pwRGB + (tLines + i * 3));
1973 
1974 	  R = R >> 2;
1975 	  G = G >> 2;
1976 
1977 	  B = B >> 2;
1978 	  if (R > 255)
1979 	    R = 255;
1980 	  if (G > 255)
1981 	    G = 255;
1982 	  if (B > 255)
1983 	    B = 255;
1984 
1985 	  *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R;
1986 	  *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G;
1987 	  *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B;
1988 
1989 	}
1990 
1991     }
1992 
1993 
1994   if (pwRGB != NULL)
1995     {
1996       free (pwRGB);
1997     }
1998 
1999   return;
2000 }
2001 #endif
2002 
2003 /****************************** SANE API functions *****************************/
2004 
2005 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)2006 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
2007 {
2008   DBG_INIT ();
2009   DBG (DBG_FUNC, "sane_init: start\n");
2010   DBG (DBG_ERR, "SANE Mustek USB2 backend version %d.%d build %d from %s\n",
2011        SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
2012 
2013   num_devices = 1;		/* HOLD: only one device in this backend */
2014 
2015   if (version_code != NULL)
2016     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
2017 
2018   DBG (DBG_INFO, "sane_init: authorize %s null\n", authorize ? "!=" : "==");
2019 
2020   DBG (DBG_FUNC, "sane_init: exit\n");
2021   return SANE_STATUS_GOOD;
2022 }
2023 
2024 void
sane_exit(void)2025 sane_exit (void)
2026 {
2027   DBG (DBG_FUNC, "sane_exit: start\n");
2028 
2029   if (devlist != NULL)
2030     {
2031       free (devlist);
2032       devlist = NULL;
2033     }
2034 
2035   devlist = NULL;
2036   DBG (DBG_FUNC, "sane_exit: exit\n");
2037 }
2038 
2039 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)2040 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
2041 {
2042   SANE_Int dev_num;
2043   DBG (DBG_FUNC, "sane_get_devices: start: local_only = %s\n",
2044        local_only == SANE_TRUE ? "true" : "false");
2045 
2046   if (devlist != NULL)
2047     {
2048       free (devlist);
2049       devlist = NULL;
2050     }
2051 
2052   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
2053   if (devlist == NULL)
2054     return SANE_STATUS_NO_MEM;
2055 
2056   dev_num = 0;
2057   /* HOLD: This is ugly (only one scanner!) and should go to sane_init */
2058   if (GetDeviceStatus ())
2059     {
2060       SANE_Device *sane_device;
2061 
2062       sane_device = malloc (sizeof (*sane_device));
2063       if (sane_device == NULL)
2064 	return SANE_STATUS_NO_MEM;
2065       sane_device->name = strdup (device_name);
2066       sane_device->vendor = strdup ("Mustek");
2067       sane_device->model = strdup ("BearPaw 2448 TA Pro");
2068       sane_device->type = strdup ("flatbed scanner");
2069       devlist[dev_num++] = sane_device;
2070     }
2071   devlist[dev_num] = 0;
2072   *device_list = devlist;
2073   DBG (DBG_FUNC, "sane_get_devices: exit\n");
2074   return SANE_STATUS_GOOD;
2075 }
2076 
2077 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)2078 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
2079 {
2080   Mustek_Scanner *s;
2081 
2082   DBG (DBG_FUNC, "sane_open: start :devicename = %s\n", devicename);
2083 
2084   if (!MustScanner_Init ())
2085     {
2086       return SANE_STATUS_INVAL;
2087     }
2088   if (!PowerControl (SANE_FALSE, SANE_FALSE))
2089     {
2090       return SANE_STATUS_INVAL;
2091     }
2092   if (!CarriageHome ())
2093     {
2094       return SANE_STATUS_INVAL;
2095     }
2096 
2097   s = malloc (sizeof (*s));
2098   if (s == NULL)
2099     return SANE_STATUS_NO_MEM;
2100   memset (s, 0, sizeof (*s));
2101 
2102   s->gamma_table = NULL;
2103   memcpy (&s->model, &mustek_A2nu2_model, sizeof (Scanner_Model));
2104   s->next = NULL;
2105   s->bIsScanning = SANE_FALSE;
2106   s->bIsReading = SANE_FALSE;
2107 
2108   init_options (s);
2109   *handle = s;
2110 
2111   s->read_rows = 0;
2112   s->scan_buffer_len = 0;
2113 
2114   DBG (DBG_FUNC, "sane_open: exit\n");
2115   return SANE_STATUS_GOOD;
2116 }
2117 
2118 
2119 void
sane_close(SANE_Handle handle)2120 sane_close (SANE_Handle handle)
2121 {
2122   Mustek_Scanner *s = handle;
2123   DBG (DBG_FUNC, "sane_close: start\n");
2124 
2125   PowerControl (SANE_FALSE, SANE_FALSE);
2126 
2127   CarriageHome ();
2128 
2129   if (NULL != g_pDeviceFile)
2130     {
2131       free (g_pDeviceFile);
2132       g_pDeviceFile = NULL;
2133     }
2134 
2135   if (s->Scan_data_buf != NULL)
2136     free (s->Scan_data_buf);
2137 
2138   s->Scan_data_buf = NULL;
2139 
2140   free (handle);
2141 
2142   DBG (DBG_FUNC, "sane_close: exit\n");
2143 }
2144 
2145 
2146 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)2147 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2148 {
2149   Mustek_Scanner *s = handle;
2150 
2151   if ((unsigned) option >= NUM_OPTIONS)
2152     return 0;
2153   DBG (DBG_FUNC, "sane_get_option_descriptor: option = %s (%d)\n",
2154        s->opt[option].name, option);
2155   return s->opt + option;
2156 }
2157 
2158 
2159 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)2160 sane_control_option (SANE_Handle handle, SANE_Int option,
2161 		     SANE_Action action, void *val, SANE_Int * info)
2162 {
2163   Mustek_Scanner *s = handle;
2164   SANE_Status status;
2165   SANE_Word cap;
2166   SANE_Int myinfo = 0;
2167 
2168   DBG (DBG_FUNC,
2169        "sane_control_option: start: action = %s, option = %s (%d)\n",
2170        (action == SANE_ACTION_GET_VALUE) ? "get" : (action ==
2171 						    SANE_ACTION_SET_VALUE) ?
2172        "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown",
2173        s->opt[option].name, option);
2174 
2175 
2176   if (info)
2177     *info = 0;
2178 
2179   if (s->bIsScanning)
2180     {
2181       DBG (DBG_ERR, "sane_control_option: don't call this function while "
2182 	   "scanning\n");
2183       return SANE_STATUS_DEVICE_BUSY;
2184     }
2185   if (option >= NUM_OPTIONS || option < 0)
2186     {
2187       DBG (DBG_ERR,
2188 	   "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n",
2189 	   option);
2190       return SANE_STATUS_INVAL;
2191     }
2192 
2193   cap = s->opt[option].cap;
2194   if (!SANE_OPTION_IS_ACTIVE (cap))
2195     {
2196       DBG (DBG_ERR, "sane_control_option: option %d is inactive\n", option);
2197       return SANE_STATUS_INVAL;
2198     }
2199   if (action == SANE_ACTION_GET_VALUE)
2200     {
2201       switch (option)
2202 	{
2203 	  /* word options: */
2204 	case OPT_NUM_OPTS:
2205 	case OPT_RESOLUTION:
2206 	case OPT_PREVIEW:
2207 	case OPT_AUTO_WARMUP:
2208 	case OPT_GAMMA_VALUE:
2209 	case OPT_THRESHOLD:
2210 	case OPT_TL_X:
2211 	case OPT_TL_Y:
2212 	case OPT_BR_X:
2213 	case OPT_BR_Y:
2214 	  *(SANE_Word *) val = s->val[option].w;
2215 	  break;
2216 	  /* string options: */
2217 	case OPT_MODE:
2218 	  strcpy (val, s->val[option].s);
2219 	  break;
2220 
2221 	case OPT_SOURCE:
2222 	  strcpy (val, s->val[option].s);
2223 	  break;
2224 	default:
2225 	  DBG (DBG_ERR, "sane_control_option: can't get unknown option %d\n",
2226 	       option);
2227 	  ;
2228 	}
2229     }
2230   else if (action == SANE_ACTION_SET_VALUE)
2231     {
2232       if (!SANE_OPTION_IS_SETTABLE (cap))
2233 	{
2234 	  DBG (DBG_ERR, "sane_control_option: option %d is not settable\n",
2235 	       option);
2236 	  return SANE_STATUS_INVAL;
2237 	}
2238 
2239       status = sanei_constrain_value (s->opt + option, val, &myinfo);
2240       if (status != SANE_STATUS_GOOD)
2241 	{
2242 	  DBG (2, "sane_control_option: sanei_constrain_value returned %s\n",
2243 	       sane_strstatus (status));
2244 	  return status;
2245 	}
2246 
2247       switch (option)
2248 	{
2249 	  /* (mostly) side-effect-free word options: */
2250 	case OPT_RESOLUTION:
2251 	case OPT_PREVIEW:
2252 	case OPT_TL_X:
2253 	case OPT_TL_Y:
2254 	case OPT_BR_X:
2255 	case OPT_BR_Y:
2256 	  s->val[option].w = *(SANE_Word *) val;
2257 	  RIE (calc_parameters (s));
2258 	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2259 	  break;
2260 	case OPT_THRESHOLD:
2261 	case OPT_AUTO_WARMUP:
2262 	case OPT_GAMMA_VALUE:
2263 	  s->val[option].w = *(SANE_Word *) val;
2264 	  break;
2265 	  /* side-effect-free word-array options: */
2266 	case OPT_MODE:
2267 	  if (s->val[option].s)
2268 	    free (s->val[option].s);
2269 	  s->val[option].s = strdup (val);
2270 	  if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
2271 	    {
2272 	      ENABLE (OPT_THRESHOLD);
2273 	    }
2274 	  else
2275 	    {
2276 	      DISABLE (OPT_THRESHOLD);
2277 	    }
2278 	  RIE (calc_parameters (s));
2279 	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2280 	  break;
2281 	case OPT_SOURCE:
2282 	  if (strcmp (s->val[option].s, val) != 0)
2283 	    {			/* something changed */
2284 	      if (s->val[option].s)
2285 		free (s->val[option].s);
2286 	      s->val[option].s = strdup (val);
2287 	      if (strcmp (s->val[option].s, "Reflective") == 0)
2288 		{
2289 		  PowerControl (SANE_TRUE, SANE_FALSE);
2290 		  s->opt[OPT_MODE].size = max_string_size (mode_list);
2291 		  s->opt[OPT_MODE].constraint.string_list = mode_list;
2292 		  s->val[OPT_MODE].s = strdup ("Color24");
2293 		  x_range.max = s->model.x_size;
2294 		  y_range.max = s->model.y_size;
2295 		}
2296 	      else if (0 == strcmp (s->val[option].s, "Negative"))
2297 		{
2298 		  PowerControl (SANE_FALSE, SANE_TRUE);
2299 		  s->opt[OPT_MODE].size =
2300 		    max_string_size (negative_mode_list);
2301 		  s->opt[OPT_MODE].constraint.string_list =
2302 		    negative_mode_list;
2303 		  s->val[OPT_MODE].s = strdup ("Color24");
2304 		  x_range.max = s->model.x_size_ta;
2305 		  y_range.max = s->model.y_size_ta;
2306 		}
2307 	      else if (0 == strcmp (s->val[option].s, "Positive"))
2308 		{
2309 		  PowerControl (SANE_FALSE, SANE_TRUE);
2310 		  s->opt[OPT_MODE].size = max_string_size (mode_list);
2311 		  s->opt[OPT_MODE].constraint.string_list = mode_list;
2312 		  s->val[OPT_MODE].s = strdup ("Color24");
2313 		  x_range.max = s->model.x_size_ta;
2314 		  y_range.max = s->model.y_size_ta;
2315 		}
2316 	    }
2317 	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2318 	  break;
2319 	default:
2320 	  DBG (DBG_ERR, "sane_control_option: can't set unknown option %d\n",
2321 	       option);
2322 	}
2323     }
2324   else
2325     {
2326       DBG (DBG_ERR, "sane_control_option: unknown action %d for option %d\n",
2327 	   action, option);
2328       return SANE_STATUS_INVAL;
2329     }
2330   if (info)
2331     *info = myinfo;
2332 
2333   DBG (DBG_FUNC, "sane_control_option: exit\n");
2334   return SANE_STATUS_GOOD;
2335 }
2336 
2337 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)2338 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
2339 {
2340   Mustek_Scanner *s = handle;
2341 
2342   DBG (DBG_FUNC, "sane_get_parameters: start\n");
2343 
2344   DBG (DBG_INFO, "sane_get_parameters :params.format = %d\n",
2345        s->params.format);
2346 
2347   DBG (DBG_INFO, "sane_get_parameters :params.depth = %d\n", s->params.depth);
2348   DBG (DBG_INFO, "sane_get_parameters :params.pixels_per_line = %d\n",
2349        s->params.pixels_per_line);
2350   DBG (DBG_INFO, "sane_get_parameters :params.bytes_per_line = %d\n",
2351        s->params.bytes_per_line);
2352   DBG (DBG_INFO, "sane_get_parameters :params.lines = %d\n", s->params.lines);
2353   if (params != NULL)
2354     *params = s->params;
2355 
2356   DBG (DBG_FUNC, "sane_get_parameters: exit\n");
2357 
2358   return SANE_STATUS_GOOD;
2359 
2360 }
2361 
2362 SANE_Status
sane_start(SANE_Handle handle)2363 sane_start (SANE_Handle handle)
2364 {
2365   int i;
2366   Mustek_Scanner *s = handle;
2367 
2368   DBG (DBG_FUNC, "sane_start: start\n");
2369 
2370   s->scan_buffer_len = 0;
2371 
2372   calc_parameters (s);
2373 
2374   if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w)
2375     {
2376       DBG (DBG_CRIT,
2377 	   "sane_start: top left x >= bottom right x --- exiting\n");
2378       return SANE_STATUS_INVAL;
2379     }
2380   if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w)
2381     {
2382       DBG (DBG_CRIT,
2383 	   "sane_start: top left y >= bottom right y --- exiting\n");
2384       return SANE_STATUS_INVAL;
2385     }
2386 
2387   s->setpara.pGammaTable = NULL;
2388 
2389   DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.x1=%d\n",
2390        s->setpara.fmArea.x1);
2391   DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.x2=%d\n",
2392        s->setpara.fmArea.x2);
2393   DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.y1=%d\n",
2394        s->setpara.fmArea.y1);
2395   DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.y2=%d\n",
2396        s->setpara.fmArea.y2);
2397   DBG (DBG_INFO, "Sane_start:setpara ,setpara.pfPixelFlavor=%d\n",
2398        s->setpara.pfPixelFlavor);
2399   DBG (DBG_INFO, "Sane_start:setpara ,setpara.wLinearThreshold=%d\n",
2400        s->setpara.wLinearThreshold);
2401   DBG (DBG_INFO, "Sane_start:setpara ,setpara.wTargetDPI=%d\n",
2402        s->setpara.wTargetDPI);
2403   DBG (DBG_INFO, "Sane_start:setpara ,setpara.smScanMode=%d\n",
2404        s->setpara.smScanMode);
2405   DBG (DBG_INFO, "Sane_start:setpara ,setpara.ssScanSource =%d\n",
2406        s->setpara.ssScanSource);
2407   DBG (DBG_INFO, "Sane_start:setpara ,setpara.pGammaTable =%p\n",
2408        (void *) s->setpara.pGammaTable);
2409 
2410   SetParameters (&s->setpara);
2411 
2412   GetParameters (&s->getpara);
2413 
2414   switch (s->params.format)
2415     {
2416     case SANE_FRAME_RGB:
2417       if (s->params.depth == 8)
2418 
2419 	s->params.pixels_per_line = s->getpara.dwLineByteWidth / 3;
2420       if (s->params.depth == 16)
2421 	s->params.pixels_per_line = s->getpara.dwLineByteWidth / 6;
2422 
2423 
2424       break;
2425     case SANE_FRAME_GRAY:
2426       if (s->params.depth == 1)
2427 	s->params.pixels_per_line = s->getpara.dwLineByteWidth * 8;
2428       if (s->params.depth == 8)
2429 	s->params.pixels_per_line = s->getpara.dwLineByteWidth;
2430       if (s->params.depth == 16)
2431 	s->params.pixels_per_line = s->getpara.dwLineByteWidth / 2;
2432       break;
2433     default:
2434       DBG (DBG_INFO, "sane_start: sane_params.format = %d\n",
2435 	   s->params.format);
2436     }
2437 
2438   s->params.bytes_per_line = s->getpara.dwLineByteWidth;
2439   s->params.lines = s->getpara.dwLength;
2440 
2441   s->params.last_frame = TRUE;
2442 
2443 
2444   s->read_rows = s->getpara.dwLength;
2445   DBG (DBG_INFO, "sane_start : read_rows = %d\n", s->read_rows);
2446 
2447   /*warmming up */
2448   if (s->val[OPT_AUTO_WARMUP].w)
2449     {
2450       for (i = 30; i > 0; i--)
2451 	{
2452 	  sleep (1);
2453 	  DBG (DBG_ERR, "warming up: %d\n", i);
2454 	}
2455     }
2456   DBG (DBG_INFO, "SCANNING ... \n");
2457 
2458   s->bIsScanning = SANE_TRUE;
2459   if (s->Scan_data_buf != NULL)
2460     free (s->Scan_data_buf);
2461   s->Scan_data_buf = NULL;
2462 
2463   s->Scan_data_buf = malloc (SCAN_BUFFER_SIZE * sizeof (SANE_Byte));
2464   if (s->Scan_data_buf == NULL)
2465     return SANE_STATUS_NO_MEM;
2466 
2467   StartScan ();
2468 
2469   DBG (DBG_FUNC, "sane_start: exit\n");
2470 
2471   return SANE_STATUS_GOOD;
2472 }
2473 
2474 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)2475 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
2476 	   SANE_Int * len)
2477 {
2478 
2479   Mustek_Scanner *s = handle;
2480   static SANE_Byte *tempbuf;
2481   SANE_Int lines_to_read, lines_read;
2482   IMAGEROWS image_row;
2483 
2484   int maxbuffersize = max_len;
2485 
2486   DBG (DBG_FUNC, "sane_read: start: max_len=%d\n", max_len);
2487 
2488   if (s == NULL)
2489     {
2490       DBG (DBG_ERR, "sane_read: handle is null!\n");
2491       return SANE_STATUS_INVAL;
2492     }
2493 
2494   if (buf == NULL)
2495     {
2496       DBG (DBG_ERR, "sane_read: buf is null!\n");
2497       return SANE_STATUS_INVAL;
2498     }
2499 
2500   if (len == NULL)
2501     {
2502       DBG (DBG_ERR, "sane_read: len is null!\n");
2503       return SANE_STATUS_INVAL;
2504     }
2505   *len = 0;
2506   if (!s->bIsScanning)
2507     {
2508       DBG (DBG_WARN, "sane_read: scan was cancelled, is over or has not been "
2509 	   "initiated yet\n");
2510       return SANE_STATUS_CANCELLED;
2511     }
2512   DBG (DBG_DBG, "sane_read: before read data read_row=%d\n", s->read_rows);
2513   if (s->scan_buffer_len == 0)
2514     {
2515       if (s->read_rows > 0)
2516 	{
2517 	  lines_to_read = SCAN_BUFFER_SIZE / s->getpara.dwLineByteWidth;
2518 
2519 	  if (lines_to_read > s->read_rows)
2520 	    lines_to_read = s->read_rows;
2521 
2522 	  tempbuf =
2523 	    (SANE_Byte *) malloc (sizeof (SANE_Byte) * lines_to_read *
2524 			     s->getpara.dwLineByteWidth + 3 * 1024 + 1);
2525 	  memset (tempbuf, 0,
2526 		  sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth +
2527 		  3 * 1024 + 1);
2528 
2529 	  DBG (DBG_INFO, "sane_read: buffer size is %ld\n",
2530 	       (long int) sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth +
2531 	       3 * 1024 + 1);
2532 
2533 	  image_row.roRgbOrder = mustek_A2nu2_model.line_mode_color_order;
2534 	  image_row.wWantedLineNum = lines_to_read;
2535 	  image_row.pBuffer = (SANE_Byte *) tempbuf;
2536 	  s->bIsReading = SANE_TRUE;
2537 
2538 	  if (!ReadScannedData (&image_row))
2539 	    {
2540 	      DBG (DBG_ERR, "sane_read: ReadScannedData error\n");
2541 	      s->bIsReading = SANE_FALSE;
2542 	      return SANE_STATUS_INVAL;
2543 	    }
2544 
2545 	  DBG (DBG_DBG, "sane_read: Finish ReadScanedData\n");
2546 	  s->bIsReading = SANE_FALSE;
2547 	  memset (s->Scan_data_buf, 0, SCAN_BUFFER_SIZE);
2548 	  s->scan_buffer_len =
2549 	    image_row.wXferedLineNum * s->getpara.dwLineByteWidth;
2550 	  DBG (DBG_INFO, "sane_read : s->scan_buffer_len = %ld\n",
2551 	       (long int) s->scan_buffer_len);
2552 
2553 	  memcpy (s->Scan_data_buf, tempbuf, s->scan_buffer_len);
2554 
2555 	  DBG (DBG_DBG, "sane_read :after memcpy\n");
2556 	  free (tempbuf);
2557 	  s->Scan_data_buf_start = s->Scan_data_buf;
2558 	  s->read_rows -= image_row.wXferedLineNum;
2559 
2560 	}
2561       else
2562 	{
2563 	  DBG (DBG_FUNC, "sane_read: scan finished -- exit\n");
2564 	  sane_cancel (handle);
2565 	  return SANE_STATUS_EOF;
2566 	}
2567     }
2568   if (s->scan_buffer_len == 0)
2569     {
2570       DBG (DBG_FUNC, "sane_read: scan finished -- exit\n");
2571       sane_cancel (handle);
2572       return SANE_STATUS_EOF;
2573     }
2574 
2575 
2576 
2577 
2578   lines_read =
2579     (maxbuffersize <
2580      (SANE_Int) s->scan_buffer_len) ? maxbuffersize : (SANE_Int) s->scan_buffer_len;
2581   DBG (DBG_DBG, "sane_read: after %d\n", lines_read);
2582 
2583   *len = (SANE_Int) lines_read;
2584 
2585   DBG (DBG_INFO, "sane_read : get lines_read = %d\n", lines_read);
2586   DBG (DBG_INFO, "sane_read : get *len = %d\n", *len);
2587   memcpy (buf, s->Scan_data_buf_start, lines_read);
2588 
2589   s->scan_buffer_len -= lines_read;
2590   s->Scan_data_buf_start += lines_read;
2591   DBG (DBG_FUNC, "sane_read: exit\n");
2592   return SANE_STATUS_GOOD;
2593 
2594 }
2595 
2596 void
sane_cancel(SANE_Handle handle)2597 sane_cancel (SANE_Handle handle)
2598 {
2599   Mustek_Scanner *s = handle;
2600   int i;
2601   DBG (DBG_FUNC, "sane_cancel: start\n");
2602   if (s->bIsScanning)
2603     {
2604       s->bIsScanning = SANE_FALSE;
2605       if (s->read_rows > 0)
2606 	{
2607 	  DBG (DBG_INFO, "sane_cancel: warning: is scanning\n");
2608 
2609 	}
2610       else
2611 	{
2612 	  DBG (DBG_INFO, "sane_cancel: Scan finished\n");
2613 	}
2614 
2615       StopScan ();
2616 
2617       CarriageHome ();
2618       for (i = 0; i < 20; i++)
2619 	{
2620 	  if (s->bIsReading == SANE_FALSE)
2621 	    {
2622 	      if (s->gamma_table != NULL)
2623 		{
2624 		  free (s->gamma_table);
2625 		  s->gamma_table = NULL;
2626 		  break;
2627 		}
2628 	    }
2629 	  else
2630 	    sleep (1);
2631 	}
2632       if (s->Scan_data_buf != NULL)
2633 	{
2634 	  free (s->Scan_data_buf);
2635 	  s->Scan_data_buf = NULL;
2636 	  s->Scan_data_buf_start = NULL;
2637 	}
2638 
2639       s->read_rows = 0;
2640       s->scan_buffer_len = 0;
2641       memset (&s->setpara, 0, sizeof (s->setpara));
2642       memset (&s->getpara, 0, sizeof (s->getpara));
2643 
2644     }
2645   else
2646     {
2647       DBG (DBG_INFO, "sane_cancel: do nothing\n");
2648     }
2649 
2650 
2651   DBG (DBG_FUNC, "sane_cancel: exit\n");
2652 
2653 }
2654 
2655 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)2656 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2657 {
2658   Mustek_Scanner *s = handle;
2659   DBG (DBG_FUNC, "sane_set_io_mode: handle = %p, non_blocking = %s\n",
2660        handle, non_blocking == SANE_TRUE ? "true" : "false");
2661   if (!s->bIsScanning)
2662     {
2663       DBG (DBG_WARN, "sane_set_io_mode: not scanning\n");
2664       return SANE_STATUS_INVAL;
2665     }
2666   if (non_blocking)
2667     return SANE_STATUS_UNSUPPORTED;
2668   return SANE_STATUS_GOOD;
2669 }
2670 
2671 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)2672 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2673 {
2674   Mustek_Scanner *s = handle;
2675   DBG (DBG_FUNC, "sane_get_select_fd: handle = %p, fd = %p\n", handle,
2676        (void *) fd);
2677   if (!s->bIsScanning)
2678     {
2679       DBG (DBG_WARN, "%s", "sane_get_select_fd: not scanning\n");
2680       return SANE_STATUS_INVAL;
2681     }
2682   return SANE_STATUS_UNSUPPORTED;
2683 }
2684