1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   Copyright (C) 2000-2005 Mustek.
4141cc406Sopenharmony_ci   Originally maintained by Mustek
5141cc406Sopenharmony_ci
6141cc406Sopenharmony_ci   Copyright (C) 2001-2005 by Henning Meier-Geinitz.
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci   This file is part of the SANE package.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
11141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
12141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
13141cc406Sopenharmony_ci   License, or (at your option) any later version.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
16141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
17141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18141cc406Sopenharmony_ci   General Public License for more details.
19141cc406Sopenharmony_ci
20141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
21141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
22141cc406Sopenharmony_ci
23141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
24141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
25141cc406Sopenharmony_ci
26141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
27141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
28141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
30141cc406Sopenharmony_ci   account of linking the SANE library code into it.
31141cc406Sopenharmony_ci
32141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
33141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
34141cc406Sopenharmony_ci   License.
35141cc406Sopenharmony_ci
36141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
37141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
38141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
41141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
42141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci   This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro
45141cc406Sopenharmony_ci   and similar USB2 scanners. */
46141cc406Sopenharmony_ci
47141cc406Sopenharmony_ci#define BUILD 10
48141cc406Sopenharmony_ci
49141cc406Sopenharmony_ci#include "../include/sane/config.h"
50141cc406Sopenharmony_ci
51141cc406Sopenharmony_ci#include <ctype.h>
52141cc406Sopenharmony_ci#include <errno.h>
53141cc406Sopenharmony_ci#include <fcntl.h>
54141cc406Sopenharmony_ci#include <limits.h>
55141cc406Sopenharmony_ci#include <signal.h>
56141cc406Sopenharmony_ci#include <stdio.h>
57141cc406Sopenharmony_ci#include <stdlib.h>
58141cc406Sopenharmony_ci#include <string.h>
59141cc406Sopenharmony_ci#include <unistd.h>
60141cc406Sopenharmony_ci#include <math.h>
61141cc406Sopenharmony_ci
62141cc406Sopenharmony_ci#include <sys/time.h>
63141cc406Sopenharmony_ci#include <sys/types.h>
64141cc406Sopenharmony_ci#include <sys/wait.h>
65141cc406Sopenharmony_ci
66141cc406Sopenharmony_ci#include "../include/sane/sane.h"
67141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
68141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci#define BACKEND_NAME mustek_usb2
71141cc406Sopenharmony_ci
72141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
73141cc406Sopenharmony_ci#include "mustek_usb2_high.c"
74141cc406Sopenharmony_ci
75141cc406Sopenharmony_ci#include "mustek_usb2.h"
76141cc406Sopenharmony_ci
77141cc406Sopenharmony_cistatic SANE_Int num_devices;
78141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0;
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_cistatic const SANE_Range u8_range = {
81141cc406Sopenharmony_ci  0,				/* minimum */
82141cc406Sopenharmony_ci  255,				/* maximum */
83141cc406Sopenharmony_ci  0				/* quantization */
84141cc406Sopenharmony_ci};
85141cc406Sopenharmony_cistatic SANE_Range x_range = {
86141cc406Sopenharmony_ci  SANE_FIX (0.0),		/* minimum */
87141cc406Sopenharmony_ci  SANE_FIX (8.3 * MM_PER_INCH),	/* maximum */
88141cc406Sopenharmony_ci  SANE_FIX (0.0)		/* quantization */
89141cc406Sopenharmony_ci};
90141cc406Sopenharmony_ci
91141cc406Sopenharmony_cistatic SANE_Range y_range = {
92141cc406Sopenharmony_ci  SANE_FIX (0.0),		/* minimum */
93141cc406Sopenharmony_ci  SANE_FIX (11.6 * MM_PER_INCH),	/* maximum */
94141cc406Sopenharmony_ci  SANE_FIX (0.0)		/* quantization */
95141cc406Sopenharmony_ci};
96141cc406Sopenharmony_ci
97141cc406Sopenharmony_cistatic SANE_Range gamma_range = {
98141cc406Sopenharmony_ci  SANE_FIX (0.01),		/* minimum */
99141cc406Sopenharmony_ci  SANE_FIX (5.0),		/* maximum */
100141cc406Sopenharmony_ci  SANE_FIX (0.01)		/* quantization */
101141cc406Sopenharmony_ci};
102141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = {
103141cc406Sopenharmony_ci  SANE_I18N ("Color48"),
104141cc406Sopenharmony_ci  SANE_I18N ("Color24"),
105141cc406Sopenharmony_ci  SANE_I18N ("Gray16"),
106141cc406Sopenharmony_ci  SANE_I18N ("Gray8"),
107141cc406Sopenharmony_ci  SANE_VALUE_SCAN_MODE_LINEART,
108141cc406Sopenharmony_ci  0
109141cc406Sopenharmony_ci};
110141cc406Sopenharmony_ci
111141cc406Sopenharmony_cistatic SANE_String_Const negative_mode_list[] = {
112141cc406Sopenharmony_ci  SANE_I18N ("Color24"),
113141cc406Sopenharmony_ci  0
114141cc406Sopenharmony_ci};
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_cistatic SANE_String_Const source_list[] = {
117141cc406Sopenharmony_ci  SANE_I18N ("Reflective"),
118141cc406Sopenharmony_ci  SANE_I18N ("Positive"),
119141cc406Sopenharmony_ci  SANE_I18N ("Negative"),
120141cc406Sopenharmony_ci  0
121141cc406Sopenharmony_ci};
122141cc406Sopenharmony_cistatic Scanner_Model mustek_A2nu2_model = {
123141cc406Sopenharmony_ci  "mustek-A2nu2",		/* Name */
124141cc406Sopenharmony_ci  "Mustek",			/* Device vendor string */
125141cc406Sopenharmony_ci
126141cc406Sopenharmony_ci  "BearPaw 2448TA Pro",		/* Device model name */
127141cc406Sopenharmony_ci  "",				/* Name of the firmware file */
128141cc406Sopenharmony_ci
129141cc406Sopenharmony_ci  {1200, 600, 300, 150, 75, 0},	/* possible resolutions */
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci  SANE_FIX (0.0),		/* Start of scan area in mm  (x) */
132141cc406Sopenharmony_ci  SANE_FIX (0.0),		/* Start of scan area in mm (y) */
133141cc406Sopenharmony_ci  SANE_FIX (8.3 * MM_PER_INCH),	/* Size of scan area in mm (x) */
134141cc406Sopenharmony_ci  SANE_FIX (11.6 * MM_PER_INCH),	/* Size of scan area in mm (y) */
135141cc406Sopenharmony_ci
136141cc406Sopenharmony_ci  SANE_FIX (0.0),		/* Start of scan area in TA mode in mm (x) */
137141cc406Sopenharmony_ci  SANE_FIX (0.0),		/* Start of scan area in TA mode in mm (y) */
138141cc406Sopenharmony_ci  SANE_FIX (1.46 * MM_PER_INCH),	/* Size of scan area in TA mode in mm (x) */
139141cc406Sopenharmony_ci  SANE_FIX (6.45 * MM_PER_INCH),	/* Size of scan area in TA mode in mm (y) */
140141cc406Sopenharmony_ci
141141cc406Sopenharmony_ci  0,				/* Order of the CCD/CIS colors 0:RO_RGB 1:RO_BGR */
142141cc406Sopenharmony_ci  SANE_FIX (2.0),		/* Default gamma value */
143141cc406Sopenharmony_ci
144141cc406Sopenharmony_ci  SANE_FALSE,			/* Is this a CIS scanner? */
145141cc406Sopenharmony_ci  0				/* Which flags are needed for this scanner? */
146141cc406Sopenharmony_ci    /* Setup and tested */
147141cc406Sopenharmony_ci};
148141cc406Sopenharmony_ci
149141cc406Sopenharmony_ci
150141cc406Sopenharmony_ci/* Forward declarations */
151141cc406Sopenharmony_ci
152141cc406Sopenharmony_cistatic SANE_Bool GetDeviceStatus (void);
153141cc406Sopenharmony_cistatic SANE_Bool PowerControl (SANE_Bool isLampOn, SANE_Bool isTaLampOn);
154141cc406Sopenharmony_cistatic SANE_Bool CarriageHome (void);
155141cc406Sopenharmony_cistatic SANE_Bool SetParameters (LPSETPARAMETERS pSetParameters);
156141cc406Sopenharmony_cistatic SANE_Bool GetParameters (LPGETPARAMETERS pGetParameters);
157141cc406Sopenharmony_cistatic SANE_Bool StartScan (void);
158141cc406Sopenharmony_cistatic SANE_Bool ReadScannedData (LPIMAGEROWS pImageRows);
159141cc406Sopenharmony_cistatic SANE_Bool StopScan (void);
160141cc406Sopenharmony_cistatic SANE_Bool IsTAConnected (void);
161141cc406Sopenharmony_cistatic void AutoLevel (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
162141cc406Sopenharmony_ci		unsigned int BytesPerLine);
163141cc406Sopenharmony_cistatic size_t max_string_size (const SANE_String_Const strings[]);
164141cc406Sopenharmony_cistatic SANE_Status calc_parameters (Mustek_Scanner * s);
165141cc406Sopenharmony_ci#ifdef SANE_UNUSED
166141cc406Sopenharmony_cistatic SANE_Bool GetGammaInfo (LPGAMMAINFO pGamaInfo);
167141cc406Sopenharmony_cistatic SANE_Bool GetKeyStatus (SANE_Byte * pKey);
168141cc406Sopenharmony_cistatic void QBetChange (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
169141cc406Sopenharmony_ci		 unsigned int BytesPerLine);
170141cc406Sopenharmony_cistatic void QBETDetectAutoLevel (void *pDIB, unsigned int ImageWidth, unsigned int ImageHeight);
171141cc406Sopenharmony_ci#endif
172141cc406Sopenharmony_ci
173141cc406Sopenharmony_ci
174141cc406Sopenharmony_ci
175141cc406Sopenharmony_cistatic size_t
176141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[])
177141cc406Sopenharmony_ci{
178141cc406Sopenharmony_ci  size_t size, max_size = 0;
179141cc406Sopenharmony_ci  SANE_Int i;
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci  for (i = 0; strings[i]; ++i)
182141cc406Sopenharmony_ci    {
183141cc406Sopenharmony_ci      size = strlen (strings[i]) + 1;
184141cc406Sopenharmony_ci      if (size > max_size)
185141cc406Sopenharmony_ci	max_size = size;
186141cc406Sopenharmony_ci    }
187141cc406Sopenharmony_ci  return max_size;
188141cc406Sopenharmony_ci}
189141cc406Sopenharmony_ci
190141cc406Sopenharmony_cistatic SANE_Status
191141cc406Sopenharmony_cicalc_parameters (Mustek_Scanner * s)
192141cc406Sopenharmony_ci{
193141cc406Sopenharmony_ci  SANE_String val, val_source;
194141cc406Sopenharmony_ci  val = s->val[OPT_MODE].s;
195141cc406Sopenharmony_ci  val_source = s->val[OPT_SOURCE].s;
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_ci  s->params.last_frame = SANE_TRUE;
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_ci  if (strcmp (val, "Color48") == 0)	/* Color48 */
200141cc406Sopenharmony_ci    {
201141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_RGB;
202141cc406Sopenharmony_ci      s->params.depth = 16;
203141cc406Sopenharmony_ci      s->setpara.smScanMode = SM_RGB48;
204141cc406Sopenharmony_ci      if (s->val[OPT_PREVIEW].w)
205141cc406Sopenharmony_ci	{
206141cc406Sopenharmony_ci	  DBG (DBG_DET, "calc_parameters : preview set ScanMode SM_RGB24\n");
207141cc406Sopenharmony_ci	  s->params.depth = 8;
208141cc406Sopenharmony_ci	  s->setpara.smScanMode = SM_RGB24;
209141cc406Sopenharmony_ci	}
210141cc406Sopenharmony_ci    }
211141cc406Sopenharmony_ci  else if (strcmp (val, "Color24") == 0)	/* Color24 */
212141cc406Sopenharmony_ci    {
213141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_RGB;
214141cc406Sopenharmony_ci      s->params.depth = 8;
215141cc406Sopenharmony_ci      s->setpara.smScanMode = SM_RGB24;
216141cc406Sopenharmony_ci    }
217141cc406Sopenharmony_ci  else if (strcmp (val, "Gray16") == 0)
218141cc406Sopenharmony_ci    {
219141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
220141cc406Sopenharmony_ci      s->params.depth = 16;
221141cc406Sopenharmony_ci      s->setpara.smScanMode = SM_GRAY16;
222141cc406Sopenharmony_ci      if (s->val[OPT_PREVIEW].w)
223141cc406Sopenharmony_ci	{
224141cc406Sopenharmony_ci	  s->params.depth = 8;
225141cc406Sopenharmony_ci	  DBG (DBG_DET, "calc_parameters : preview set ScanMode SM_GRAY\n");
226141cc406Sopenharmony_ci	  s->setpara.smScanMode = SM_GRAY;
227141cc406Sopenharmony_ci	}
228141cc406Sopenharmony_ci    }
229141cc406Sopenharmony_ci  else if (strcmp (val, "Gray8") == 0)
230141cc406Sopenharmony_ci    {
231141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
232141cc406Sopenharmony_ci      s->params.depth = 8;
233141cc406Sopenharmony_ci      s->setpara.smScanMode = SM_GRAY;
234141cc406Sopenharmony_ci    }
235141cc406Sopenharmony_ci  else if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)
236141cc406Sopenharmony_ci    {
237141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
238141cc406Sopenharmony_ci      s->params.depth = 1;
239141cc406Sopenharmony_ci      s->setpara.smScanMode = SM_TEXT;
240141cc406Sopenharmony_ci    }
241141cc406Sopenharmony_ci
242141cc406Sopenharmony_ci  /*set Scan Source */
243141cc406Sopenharmony_ci  DBG (DBG_DET, "calc_parameters :scan Source = %s\n", val_source);
244141cc406Sopenharmony_ci  if (strcmp (val_source, "Reflective") == 0)
245141cc406Sopenharmony_ci    {
246141cc406Sopenharmony_ci      s->setpara.ssScanSource = SS_Reflective;
247141cc406Sopenharmony_ci    }
248141cc406Sopenharmony_ci  else if (strcmp (val_source, "Positive") == 0)
249141cc406Sopenharmony_ci    {
250141cc406Sopenharmony_ci      s->setpara.ssScanSource = SS_Positive;
251141cc406Sopenharmony_ci    }
252141cc406Sopenharmony_ci  else if (strcmp (val_source, "Negative") == 0)
253141cc406Sopenharmony_ci    {
254141cc406Sopenharmony_ci      s->setpara.ssScanSource = SS_Negative;
255141cc406Sopenharmony_ci    }
256141cc406Sopenharmony_ci
257141cc406Sopenharmony_ci
258141cc406Sopenharmony_ci  s->setpara.fmArea.x1 =
259141cc406Sopenharmony_ci    (unsigned short) ((SANE_UNFIX (s->val[OPT_TL_X].w) * 300.0) / MM_PER_INCH + 0.5);
260141cc406Sopenharmony_ci  s->setpara.fmArea.x2 =
261141cc406Sopenharmony_ci    (unsigned short) ((SANE_UNFIX (s->val[OPT_BR_X].w) * 300.0) / MM_PER_INCH + 0.5);
262141cc406Sopenharmony_ci  s->setpara.fmArea.y1 =
263141cc406Sopenharmony_ci    (unsigned short) ((SANE_UNFIX (s->val[OPT_TL_Y].w) * 300.0) / MM_PER_INCH + 0.5);
264141cc406Sopenharmony_ci  s->setpara.fmArea.y2 =
265141cc406Sopenharmony_ci    (unsigned short) ((SANE_UNFIX (s->val[OPT_BR_Y].w) * 300.0) / MM_PER_INCH + 0.5);
266141cc406Sopenharmony_ci
267141cc406Sopenharmony_ci  if (s->val[OPT_PREVIEW].w)
268141cc406Sopenharmony_ci    {
269141cc406Sopenharmony_ci      s->setpara.fmArea.y1 = s->setpara.fmArea.y1 + PER_ADD_START_LINES;
270141cc406Sopenharmony_ci      s->setpara.fmArea.x1 += PRE_ADD_START_X;
271141cc406Sopenharmony_ci    }				/*just for range bug. */
272141cc406Sopenharmony_ci
273141cc406Sopenharmony_ci  s->setpara.pfPixelFlavor = PF_BlackIs0;
274141cc406Sopenharmony_ci  s->setpara.wLinearThreshold = s->val[OPT_THRESHOLD].w;
275141cc406Sopenharmony_ci
276141cc406Sopenharmony_ci  s->setpara.wTargetDPI = s->val[OPT_RESOLUTION].w;
277141cc406Sopenharmony_ci  if (s->val[OPT_PREVIEW].w)
278141cc406Sopenharmony_ci    {
279141cc406Sopenharmony_ci      s->setpara.wTargetDPI = 75;
280141cc406Sopenharmony_ci    }
281141cc406Sopenharmony_ci
282141cc406Sopenharmony_ci  s->setpara.pGammaTable = NULL;
283141cc406Sopenharmony_ci
284141cc406Sopenharmony_ci  s->params.pixels_per_line =
285141cc406Sopenharmony_ci    (SANE_Int) ((s->setpara.fmArea.x2 -
286141cc406Sopenharmony_ci		 s->setpara.fmArea.x1) * s->setpara.wTargetDPI / 300.0 + 0.5);
287141cc406Sopenharmony_ci
288141cc406Sopenharmony_ci  switch (s->params.format)
289141cc406Sopenharmony_ci    {
290141cc406Sopenharmony_ci    case SANE_FRAME_RGB:
291141cc406Sopenharmony_ci      if (s->params.depth == 8)
292141cc406Sopenharmony_ci	s->params.bytes_per_line = s->params.pixels_per_line * 3;
293141cc406Sopenharmony_ci      if (s->params.depth == 16)
294141cc406Sopenharmony_ci	s->params.bytes_per_line = s->params.pixels_per_line * 6;
295141cc406Sopenharmony_ci      break;
296141cc406Sopenharmony_ci    case SANE_FRAME_GRAY:
297141cc406Sopenharmony_ci      if (s->params.depth == 1)
298141cc406Sopenharmony_ci	s->params.bytes_per_line = s->params.pixels_per_line / 8;
299141cc406Sopenharmony_ci      if (s->params.depth == 8)
300141cc406Sopenharmony_ci	s->params.bytes_per_line = s->params.pixels_per_line;
301141cc406Sopenharmony_ci      if (s->params.depth == 16)
302141cc406Sopenharmony_ci	s->params.bytes_per_line = s->params.pixels_per_line * 2;
303141cc406Sopenharmony_ci      break;
304141cc406Sopenharmony_ci    default:
305141cc406Sopenharmony_ci      DBG (DBG_DET, "sane_star:sane params .format = %d\n", s->params.format);
306141cc406Sopenharmony_ci    }
307141cc406Sopenharmony_ci
308141cc406Sopenharmony_ci  s->params.lines =
309141cc406Sopenharmony_ci    (SANE_Int) ((s->setpara.fmArea.y2 -
310141cc406Sopenharmony_ci		 s->setpara.fmArea.y1) * s->setpara.wTargetDPI / 300 + 0.5);
311141cc406Sopenharmony_ci
312141cc406Sopenharmony_ci  DBG (DBG_FUNC, "calc_parameters: end\n");
313141cc406Sopenharmony_ci
314141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
315141cc406Sopenharmony_ci}
316141cc406Sopenharmony_ci
317141cc406Sopenharmony_cistatic SANE_Status
318141cc406Sopenharmony_ciinit_options (Mustek_Scanner * s)
319141cc406Sopenharmony_ci{
320141cc406Sopenharmony_ci  SANE_Int option, count;
321141cc406Sopenharmony_ci  SANE_Word *dpi_list;		/*Resolution Support */
322141cc406Sopenharmony_ci
323141cc406Sopenharmony_ci  DBG (DBG_FUNC, "init_options: start\n");
324141cc406Sopenharmony_ci
325141cc406Sopenharmony_ci  memset (s->opt, 0, sizeof (s->opt));
326141cc406Sopenharmony_ci  memset (s->val, 0, sizeof (s->val));
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci  for (option = 0; option < NUM_OPTIONS; ++option)
329141cc406Sopenharmony_ci    {
330141cc406Sopenharmony_ci      s->opt[option].size = sizeof (SANE_Word);
331141cc406Sopenharmony_ci      s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
332141cc406Sopenharmony_ci    }
333141cc406Sopenharmony_ci  /*  Option num */
334141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
335141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
336141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
337141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
338141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
339141cc406Sopenharmony_ci  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
340141cc406Sopenharmony_ci
341141cc406Sopenharmony_ci  /* "Mode" group: */
342141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode");
343141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].desc = "";
344141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
345141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].size = 0;
346141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].cap = 0;
347141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
348141cc406Sopenharmony_ci
349141cc406Sopenharmony_ci  /* scan mode */
350141cc406Sopenharmony_ci  s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
351141cc406Sopenharmony_ci  s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
352141cc406Sopenharmony_ci  s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
353141cc406Sopenharmony_ci  s->opt[OPT_MODE].type = SANE_TYPE_STRING;
354141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
355141cc406Sopenharmony_ci  s->opt[OPT_MODE].size = max_string_size (mode_list);
356141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint.string_list = mode_list;
357141cc406Sopenharmony_ci  s->val[OPT_MODE].s = strdup ("Color24");
358141cc406Sopenharmony_ci
359141cc406Sopenharmony_ci  /* Scan Source */
360141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
361141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
362141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
363141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
364141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
365141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].size = max_string_size (source_list);
366141cc406Sopenharmony_ci  s->opt[OPT_SOURCE].constraint.string_list = source_list;
367141cc406Sopenharmony_ci  s->val[OPT_SOURCE].s = strdup ("Reflective");
368141cc406Sopenharmony_ci
369141cc406Sopenharmony_ci  if (!IsTAConnected ())
370141cc406Sopenharmony_ci    {
371141cc406Sopenharmony_ci      DISABLE (OPT_SOURCE);
372141cc406Sopenharmony_ci    }
373141cc406Sopenharmony_ci
374141cc406Sopenharmony_ci
375141cc406Sopenharmony_ci  /* resolution */
376141cc406Sopenharmony_ci
377141cc406Sopenharmony_ci  for (count = 0; s->model.dpi_values[count] != 0; count++)
378141cc406Sopenharmony_ci    {
379141cc406Sopenharmony_ci    }
380141cc406Sopenharmony_ci  dpi_list = malloc ((count + 1) * sizeof (SANE_Word));
381141cc406Sopenharmony_ci  if (!dpi_list)
382141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
383141cc406Sopenharmony_ci  dpi_list[0] = count;
384141cc406Sopenharmony_ci
385141cc406Sopenharmony_ci  for (count = 0; s->model.dpi_values[count] != 0; count++)
386141cc406Sopenharmony_ci    dpi_list[count + 1] = s->model.dpi_values[count];
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
389141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
390141cc406Sopenharmony_ci
391141cc406Sopenharmony_ci
392141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
393141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
394141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
395141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
396141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
397141cc406Sopenharmony_ci  s->val[OPT_RESOLUTION].w = 300;
398141cc406Sopenharmony_ci
399141cc406Sopenharmony_ci  /* preview */
400141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
401141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
402141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
403141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
404141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
405141cc406Sopenharmony_ci  s->val[OPT_PREVIEW].w = SANE_FALSE;
406141cc406Sopenharmony_ci
407141cc406Sopenharmony_ci  /* "Debug" group: */
408141cc406Sopenharmony_ci  s->opt[OPT_DEBUG_GROUP].title = SANE_I18N ("Debugging Options");
409141cc406Sopenharmony_ci  s->opt[OPT_DEBUG_GROUP].desc = "";
410141cc406Sopenharmony_ci  s->opt[OPT_DEBUG_GROUP].type = SANE_TYPE_GROUP;
411141cc406Sopenharmony_ci  s->opt[OPT_DEBUG_GROUP].size = 0;
412141cc406Sopenharmony_ci  s->opt[OPT_DEBUG_GROUP].cap = 0;
413141cc406Sopenharmony_ci  s->opt[OPT_DEBUG_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
414141cc406Sopenharmony_ci
415141cc406Sopenharmony_ci  /* auto warmup */
416141cc406Sopenharmony_ci  s->opt[OPT_AUTO_WARMUP].name = "auto-warmup";
417141cc406Sopenharmony_ci  s->opt[OPT_AUTO_WARMUP].title = SANE_I18N ("Automatic warmup");
418141cc406Sopenharmony_ci  s->opt[OPT_AUTO_WARMUP].desc =
419141cc406Sopenharmony_ci    SANE_I18N ("Warm-up until the lamp's brightness is constant "
420141cc406Sopenharmony_ci	       "instead of insisting on 40 seconds warm-up time.");
421141cc406Sopenharmony_ci  s->opt[OPT_AUTO_WARMUP].type = SANE_TYPE_BOOL;
422141cc406Sopenharmony_ci  s->opt[OPT_AUTO_WARMUP].unit = SANE_UNIT_NONE;
423141cc406Sopenharmony_ci  s->opt[OPT_AUTO_WARMUP].constraint_type = SANE_CONSTRAINT_NONE;
424141cc406Sopenharmony_ci  s->val[OPT_AUTO_WARMUP].w = SANE_FALSE;
425141cc406Sopenharmony_ci  if (s->model.is_cis)
426141cc406Sopenharmony_ci    DISABLE (OPT_AUTO_WARMUP);
427141cc406Sopenharmony_ci
428141cc406Sopenharmony_ci  /* "Enhancement" group: */
429141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement");
430141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
431141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
432141cc406Sopenharmony_ci
433141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
434141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
435141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
436141cc406Sopenharmony_ci
437141cc406Sopenharmony_ci  /* threshold */
438141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
439141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
440141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
441141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
442141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
443141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
444141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].constraint.range = &u8_range;
445141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
446141cc406Sopenharmony_ci  s->val[OPT_THRESHOLD].w = DEF_LINEARTTHRESHOLD;
447141cc406Sopenharmony_ci
448141cc406Sopenharmony_ci  /* internal gamma value */
449141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].name = "gamma-value";
450141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].title = SANE_I18N ("Gamma value");
451141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].desc =
452141cc406Sopenharmony_ci    SANE_I18N ("Sets the gamma value of all channels.");
453141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].type = SANE_TYPE_FIXED;
454141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].unit = SANE_UNIT_NONE;
455141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].constraint_type = SANE_CONSTRAINT_RANGE;
456141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].constraint.range = &gamma_range;
457141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VALUE].cap |= SANE_CAP_EMULATED;
458141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VALUE].w = s->model.default_gamma_value;
459141cc406Sopenharmony_ci
460141cc406Sopenharmony_ci  DISABLE (OPT_GAMMA_VALUE);
461141cc406Sopenharmony_ci
462141cc406Sopenharmony_ci  /* "Geometry" group: */
463141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry");
464141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].desc = "";
465141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
466141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
467141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].size = 0;
468141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_ci  x_range.max = s->model.x_size;
471141cc406Sopenharmony_ci  y_range.max = s->model.y_size;
472141cc406Sopenharmony_ci
473141cc406Sopenharmony_ci  /* top-left x */
474141cc406Sopenharmony_ci  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
475141cc406Sopenharmony_ci  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
476141cc406Sopenharmony_ci  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
477141cc406Sopenharmony_ci  s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
478141cc406Sopenharmony_ci  s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
479141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
480141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint.range = &x_range;
481141cc406Sopenharmony_ci
482141cc406Sopenharmony_ci  s->val[OPT_TL_X].w = 0;
483141cc406Sopenharmony_ci
484141cc406Sopenharmony_ci  /* top-left y */
485141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
486141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
487141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
488141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
489141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
490141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
491141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint.range = &y_range;
492141cc406Sopenharmony_ci  s->val[OPT_TL_Y].w = 0;
493141cc406Sopenharmony_ci
494141cc406Sopenharmony_ci  /* bottom-right x */
495141cc406Sopenharmony_ci  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
496141cc406Sopenharmony_ci  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
497141cc406Sopenharmony_ci  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
498141cc406Sopenharmony_ci  s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
499141cc406Sopenharmony_ci  s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
500141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
501141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint.range = &x_range;
502141cc406Sopenharmony_ci  s->val[OPT_BR_X].w = x_range.max;
503141cc406Sopenharmony_ci
504141cc406Sopenharmony_ci  /* bottom-right y */
505141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
506141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
507141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
508141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
509141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
510141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
511141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint.range = &y_range;
512141cc406Sopenharmony_ci  s->val[OPT_BR_Y].w = y_range.max;
513141cc406Sopenharmony_ci
514141cc406Sopenharmony_ci  calc_parameters (s);
515141cc406Sopenharmony_ci
516141cc406Sopenharmony_ci  DBG (DBG_FUNC, "init_options: exit\n");
517141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
518141cc406Sopenharmony_ci}
519141cc406Sopenharmony_ci
520141cc406Sopenharmony_ci/***************************** Code from spicall.c *****************************/
521141cc406Sopenharmony_ci
522141cc406Sopenharmony_cistatic SANE_Byte * g_lpNegImageData = NULL;
523141cc406Sopenharmony_cistatic SANE_Bool g_bIsFirstGetNegData = TRUE;
524141cc406Sopenharmony_cistatic SANE_Bool g_bIsMallocNegData = FALSE;
525141cc406Sopenharmony_cistatic unsigned int g_dwAlreadyGetNegLines = 0;
526141cc406Sopenharmony_ci
527141cc406Sopenharmony_ci/**********************************************************************
528141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
529141cc406Sopenharmony_ciRoutine Description:
530141cc406Sopenharmony_ci	Check the device connect status
531141cc406Sopenharmony_ciParameters:
532141cc406Sopenharmony_ci	none
533141cc406Sopenharmony_ciReturn value:
534141cc406Sopenharmony_ci	if the device is connected
535141cc406Sopenharmony_ci	return TRUE
536141cc406Sopenharmony_ci	else
537141cc406Sopenharmony_ci	return FALSE
538141cc406Sopenharmony_ci***********************************************************************/
539141cc406Sopenharmony_cistatic SANE_Bool
540141cc406Sopenharmony_ciGetDeviceStatus ()
541141cc406Sopenharmony_ci{
542141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetDeviceStatus: start\n");
543141cc406Sopenharmony_ci  return MustScanner_GetScannerState ();
544141cc406Sopenharmony_ci}
545141cc406Sopenharmony_ci
546141cc406Sopenharmony_ci/**********************************************************************
547141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
548141cc406Sopenharmony_ciRoutine Description:
549141cc406Sopenharmony_ci	Turn the lamp on or off
550141cc406Sopenharmony_ciParameters:
551141cc406Sopenharmony_ci	isLampOn: turn the lamp on or off
552141cc406Sopenharmony_ci	isTALampOn: turn the TA lamp on or off
553141cc406Sopenharmony_ciReturn value:
554141cc406Sopenharmony_ci	if operation success
555141cc406Sopenharmony_ci	return TRUE
556141cc406Sopenharmony_ci	else
557141cc406Sopenharmony_ci	return FALSE
558141cc406Sopenharmony_ci***********************************************************************/
559141cc406Sopenharmony_cistatic SANE_Bool
560141cc406Sopenharmony_ciPowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn)
561141cc406Sopenharmony_ci{
562141cc406Sopenharmony_ci  DBG (DBG_FUNC, "PowerControl: start\n");
563141cc406Sopenharmony_ci  return MustScanner_PowerControl (isLampOn, isTALampOn);
564141cc406Sopenharmony_ci}
565141cc406Sopenharmony_ci
566141cc406Sopenharmony_ci/**********************************************************************
567141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
568141cc406Sopenharmony_ciRoutine Description:
569141cc406Sopenharmony_ci	Turn the carriage home
570141cc406Sopenharmony_ciParameters:
571141cc406Sopenharmony_ci	none
572141cc406Sopenharmony_ciReturn value:
573141cc406Sopenharmony_ci	if the operation success
574141cc406Sopenharmony_ci	return TRUE
575141cc406Sopenharmony_ci	else
576141cc406Sopenharmony_ci	return FALSE
577141cc406Sopenharmony_ci***********************************************************************/
578141cc406Sopenharmony_cistatic SANE_Bool
579141cc406Sopenharmony_ciCarriageHome ()
580141cc406Sopenharmony_ci{
581141cc406Sopenharmony_ci  DBG (DBG_FUNC, "CarriageHome: start\n");
582141cc406Sopenharmony_ci  return MustScanner_BackHome ();
583141cc406Sopenharmony_ci}
584141cc406Sopenharmony_ci
585141cc406Sopenharmony_ci#ifdef SANE_UNUSED
586141cc406Sopenharmony_ci/**********************************************************************
587141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
588141cc406Sopenharmony_ciRoutine Description:
589141cc406Sopenharmony_ci	Get gamma input/output bit count
590141cc406Sopenharmony_ciParameters:
591141cc406Sopenharmony_ci	pGammaInfo: the gamma information
592141cc406Sopenharmony_ciReturn value:
593141cc406Sopenharmony_ci	if the operation success
594141cc406Sopenharmony_ci	return TRUE
595141cc406Sopenharmony_ci	else
596141cc406Sopenharmony_ci	return FALSE
597141cc406Sopenharmony_ci***********************************************************************/
598141cc406Sopenharmony_cistatic SANE_Bool
599141cc406Sopenharmony_ciGetGammaInfo (LPGAMMAINFO pGammaInfo)
600141cc406Sopenharmony_ci{
601141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetGammaInfo: start\n");
602141cc406Sopenharmony_ci
603141cc406Sopenharmony_ci  switch (pGammaInfo->smScanMode)
604141cc406Sopenharmony_ci    {
605141cc406Sopenharmony_ci    case SM_GRAY:
606141cc406Sopenharmony_ci      pGammaInfo->wInputGammaBits = 12;
607141cc406Sopenharmony_ci      pGammaInfo->wOutputGammaBits = 8;
608141cc406Sopenharmony_ci      break;
609141cc406Sopenharmony_ci    case SM_RGB24:
610141cc406Sopenharmony_ci      pGammaInfo->wInputGammaBits = 12;
611141cc406Sopenharmony_ci      pGammaInfo->wOutputGammaBits = 8;
612141cc406Sopenharmony_ci      break;
613141cc406Sopenharmony_ci    case SM_GRAY16:
614141cc406Sopenharmony_ci      pGammaInfo->wInputGammaBits = 16;
615141cc406Sopenharmony_ci      pGammaInfo->wOutputGammaBits = 16;
616141cc406Sopenharmony_ci      break;
617141cc406Sopenharmony_ci    case SM_RGB48:
618141cc406Sopenharmony_ci      pGammaInfo->wInputGammaBits = 16;
619141cc406Sopenharmony_ci      pGammaInfo->wOutputGammaBits = 16;
620141cc406Sopenharmony_ci      break;
621141cc406Sopenharmony_ci    default:
622141cc406Sopenharmony_ci      pGammaInfo->wInputGammaBits = 0;
623141cc406Sopenharmony_ci      pGammaInfo->wOutputGammaBits = 0;
624141cc406Sopenharmony_ci      return FALSE;
625141cc406Sopenharmony_ci    }
626141cc406Sopenharmony_ci
627141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetGammaInfo: exit\n");
628141cc406Sopenharmony_ci  return TRUE;
629141cc406Sopenharmony_ci}
630141cc406Sopenharmony_ci#endif
631141cc406Sopenharmony_ci/**********************************************************************
632141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
633141cc406Sopenharmony_ciRoutine Description:
634141cc406Sopenharmony_ci	set scan parameters
635141cc406Sopenharmony_ciParameters:
636141cc406Sopenharmony_ci	pSetParameters: the information of scanning
637141cc406Sopenharmony_ciReturn value:
638141cc406Sopenharmony_ci	if the operation success
639141cc406Sopenharmony_ci	return TRUE
640141cc406Sopenharmony_ci	else
641141cc406Sopenharmony_ci	return FALSE
642141cc406Sopenharmony_ci***********************************************************************/
643141cc406Sopenharmony_cistatic SANE_Bool
644141cc406Sopenharmony_ciSetParameters (LPSETPARAMETERS pSetParameters)
645141cc406Sopenharmony_ci{
646141cc406Sopenharmony_ci  unsigned short X1inTargetDpi;
647141cc406Sopenharmony_ci  unsigned short Y1inTargetDpi;
648141cc406Sopenharmony_ci  unsigned short X2inTargetDpi;
649141cc406Sopenharmony_ci  unsigned short Y2inTargetDpi;
650141cc406Sopenharmony_ci
651141cc406Sopenharmony_ci  DBG (DBG_FUNC, "SetParameters: start\n");
652141cc406Sopenharmony_ci
653141cc406Sopenharmony_ci  /*0. Reset */
654141cc406Sopenharmony_ci  if (ST_Reflective == g_ScanType)
655141cc406Sopenharmony_ci    {
656141cc406Sopenharmony_ci      Reflective_Reset ();
657141cc406Sopenharmony_ci    }
658141cc406Sopenharmony_ci  else
659141cc406Sopenharmony_ci    {
660141cc406Sopenharmony_ci      Transparent_Reset ();
661141cc406Sopenharmony_ci    }
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  /*1. Scan mode */
664141cc406Sopenharmony_ci  switch (pSetParameters->smScanMode)
665141cc406Sopenharmony_ci    {
666141cc406Sopenharmony_ci    case SM_TEXT:
667141cc406Sopenharmony_ci      g_tiTarget.cmColorMode = CM_TEXT;
668141cc406Sopenharmony_ci      break;
669141cc406Sopenharmony_ci    case SM_GRAY:
670141cc406Sopenharmony_ci      g_tiTarget.cmColorMode = CM_GRAY8;
671141cc406Sopenharmony_ci      break;
672141cc406Sopenharmony_ci    case SM_GRAY16:
673141cc406Sopenharmony_ci      g_tiTarget.cmColorMode = CM_GRAY16;
674141cc406Sopenharmony_ci      break;
675141cc406Sopenharmony_ci    case SM_RGB24:
676141cc406Sopenharmony_ci      g_tiTarget.cmColorMode = CM_RGB24;
677141cc406Sopenharmony_ci      break;
678141cc406Sopenharmony_ci    case SM_RGB48:
679141cc406Sopenharmony_ci      g_tiTarget.cmColorMode = CM_RGB48;
680141cc406Sopenharmony_ci      break;
681141cc406Sopenharmony_ci    default:
682141cc406Sopenharmony_ci      return FALSE;
683141cc406Sopenharmony_ci    }
684141cc406Sopenharmony_ci
685141cc406Sopenharmony_ci  /*2. Scan source */
686141cc406Sopenharmony_ci  g_ssScanSource = pSetParameters->ssScanSource;
687141cc406Sopenharmony_ci  g_tiTarget.bScanSource = pSetParameters->ssScanSource;
688141cc406Sopenharmony_ci
689141cc406Sopenharmony_ci
690141cc406Sopenharmony_ci  if (SS_Reflective == pSetParameters->ssScanSource)
691141cc406Sopenharmony_ci    {
692141cc406Sopenharmony_ci      g_ScanType = ST_Reflective;
693141cc406Sopenharmony_ci    }
694141cc406Sopenharmony_ci  else if (SS_Positive == pSetParameters->ssScanSource
695141cc406Sopenharmony_ci	   || SS_Negative == pSetParameters->ssScanSource
696141cc406Sopenharmony_ci	   || SS_ADF == pSetParameters->ssScanSource)
697141cc406Sopenharmony_ci    {
698141cc406Sopenharmony_ci      g_ScanType = ST_Transparent;
699141cc406Sopenharmony_ci    }
700141cc406Sopenharmony_ci  else
701141cc406Sopenharmony_ci    {
702141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: ScanSource error\n");
703141cc406Sopenharmony_ci      return FALSE;
704141cc406Sopenharmony_ci    }
705141cc406Sopenharmony_ci
706141cc406Sopenharmony_ci  /*3. pixel flavor */
707141cc406Sopenharmony_ci  if (PF_BlackIs0 == pSetParameters->pfPixelFlavor
708141cc406Sopenharmony_ci      || PF_WhiteIs0 == pSetParameters->pfPixelFlavor)
709141cc406Sopenharmony_ci    {
710141cc406Sopenharmony_ci      g_PixelFlavor = pSetParameters->pfPixelFlavor;
711141cc406Sopenharmony_ci    }
712141cc406Sopenharmony_ci  else
713141cc406Sopenharmony_ci    {
714141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: PixelFlavor error\n");
715141cc406Sopenharmony_ci      return FALSE;
716141cc406Sopenharmony_ci    }
717141cc406Sopenharmony_ci
718141cc406Sopenharmony_ci  /*4. Scan area */
719141cc406Sopenharmony_ci  if (pSetParameters->fmArea.x1 >= pSetParameters->fmArea.x2)
720141cc406Sopenharmony_ci    {
721141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: x1 > x2, error\n");
722141cc406Sopenharmony_ci      return FALSE;
723141cc406Sopenharmony_ci    }
724141cc406Sopenharmony_ci  if (pSetParameters->fmArea.y1 >= pSetParameters->fmArea.y2)
725141cc406Sopenharmony_ci    {
726141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: y1 >= y2, error\n");
727141cc406Sopenharmony_ci      return FALSE;
728141cc406Sopenharmony_ci    }
729141cc406Sopenharmony_ci  if (pSetParameters->fmArea.x2 > MAX_SCANNING_WIDTH)	/* Just for A4 size */
730141cc406Sopenharmony_ci    {
731141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: x2 > MAX_SCANNING_WIDTH, error\n");
732141cc406Sopenharmony_ci      return FALSE;
733141cc406Sopenharmony_ci    }
734141cc406Sopenharmony_ci  if (pSetParameters->fmArea.y2 > MAX_SCANNING_HEIGHT)	/* Just for A4 size */
735141cc406Sopenharmony_ci    {
736141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: y2 > MAX_SCANNING_HEIGHT, error\n");
737141cc406Sopenharmony_ci      return FALSE;
738141cc406Sopenharmony_ci    }
739141cc406Sopenharmony_ci
740141cc406Sopenharmony_ci  X1inTargetDpi =
741141cc406Sopenharmony_ci    (unsigned short) ((unsigned int) (pSetParameters->fmArea.x1) *
742141cc406Sopenharmony_ci	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
743141cc406Sopenharmony_ci  Y1inTargetDpi =
744141cc406Sopenharmony_ci    (unsigned short) ((unsigned int) (pSetParameters->fmArea.y1) *
745141cc406Sopenharmony_ci	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
746141cc406Sopenharmony_ci  X2inTargetDpi =
747141cc406Sopenharmony_ci    (unsigned short) ((unsigned int) (pSetParameters->fmArea.x2) *
748141cc406Sopenharmony_ci	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
749141cc406Sopenharmony_ci  Y2inTargetDpi =
750141cc406Sopenharmony_ci    (unsigned short) ((unsigned int) (pSetParameters->fmArea.y2) *
751141cc406Sopenharmony_ci	    (unsigned int) (pSetParameters->wTargetDPI) / 300L);
752141cc406Sopenharmony_ci
753141cc406Sopenharmony_ci  g_tiTarget.isOptimalSpeed = TRUE;
754141cc406Sopenharmony_ci  g_tiTarget.wDpi = pSetParameters->wTargetDPI;
755141cc406Sopenharmony_ci  g_tiTarget.wX = X1inTargetDpi;
756141cc406Sopenharmony_ci  g_tiTarget.wY = Y1inTargetDpi;
757141cc406Sopenharmony_ci  g_tiTarget.wWidth = X2inTargetDpi - X1inTargetDpi;
758141cc406Sopenharmony_ci  g_tiTarget.wHeight = Y2inTargetDpi - Y1inTargetDpi;
759141cc406Sopenharmony_ci
760141cc406Sopenharmony_ci  DBG (DBG_INFO, "SetParameters: g_tiTarget.wDpi=%d\n", g_tiTarget.wDpi);
761141cc406Sopenharmony_ci  DBG (DBG_INFO, "SetParameters: g_tiTarget.wX=%d\n", g_tiTarget.wX);
762141cc406Sopenharmony_ci  DBG (DBG_INFO, "SetParameters: g_tiTarget.wY=%d\n", g_tiTarget.wY);
763141cc406Sopenharmony_ci  DBG (DBG_INFO, "SetParameters: g_tiTarget.wWidth=%d\n", g_tiTarget.wWidth);
764141cc406Sopenharmony_ci  DBG (DBG_INFO, "SetParameters: g_tiTarget.wHeight=%d\n",
765141cc406Sopenharmony_ci       g_tiTarget.wHeight);
766141cc406Sopenharmony_ci
767141cc406Sopenharmony_ci  /*5.Prepare */
768141cc406Sopenharmony_ci  if (FALSE == MustScanner_Prepare (g_tiTarget.bScanSource))
769141cc406Sopenharmony_ci    {
770141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: MustScanner_Prepare fail\n");
771141cc406Sopenharmony_ci      return FALSE;
772141cc406Sopenharmony_ci    }
773141cc406Sopenharmony_ci
774141cc406Sopenharmony_ci  /*6. Linear threshold */
775141cc406Sopenharmony_ci  if (pSetParameters->wLinearThreshold > 256
776141cc406Sopenharmony_ci      && pSetParameters->smScanMode == SM_TEXT)
777141cc406Sopenharmony_ci    {
778141cc406Sopenharmony_ci      DBG (DBG_ERR, "SetParameters: LinearThreshold error\n");
779141cc406Sopenharmony_ci      return FALSE;
780141cc406Sopenharmony_ci    }
781141cc406Sopenharmony_ci  else
782141cc406Sopenharmony_ci    {
783141cc406Sopenharmony_ci      g_wLineartThreshold = pSetParameters->wLinearThreshold;
784141cc406Sopenharmony_ci    }
785141cc406Sopenharmony_ci
786141cc406Sopenharmony_ci  /*7. Gamma table */
787141cc406Sopenharmony_ci  if (NULL != pSetParameters->pGammaTable)
788141cc406Sopenharmony_ci    {
789141cc406Sopenharmony_ci      DBG (DBG_INFO, "SetParameters: IN gamma table not NULL\n");
790141cc406Sopenharmony_ci      g_pGammaTable = pSetParameters->pGammaTable;
791141cc406Sopenharmony_ci      g_isSelfGamma = FALSE;
792141cc406Sopenharmony_ci    }
793141cc406Sopenharmony_ci  else if (pSetParameters->smScanMode == SM_GRAY
794141cc406Sopenharmony_ci	   || pSetParameters->smScanMode == SM_RGB24)
795141cc406Sopenharmony_ci    {
796141cc406Sopenharmony_ci      unsigned short i;
797141cc406Sopenharmony_ci      SANE_Byte byGammaData;
798141cc406Sopenharmony_ci      double pow_d;
799141cc406Sopenharmony_ci      double pow_z = (double) 10 / 16.0;
800141cc406Sopenharmony_ci
801141cc406Sopenharmony_ci      g_pGammaTable = (unsigned short *) malloc (sizeof (unsigned short) * 4096 * 3);
802141cc406Sopenharmony_ci
803141cc406Sopenharmony_ci      DBG (DBG_INFO, "SetParameters: gamma table malloc %ld Bytes\n",
804141cc406Sopenharmony_ci	   (long int) sizeof (unsigned short) * 4096 * 3);
805141cc406Sopenharmony_ci      DBG (DBG_INFO, "SetParameters: address of g_pGammaTable=%p\n",
806141cc406Sopenharmony_ci	   (void *) g_pGammaTable);
807141cc406Sopenharmony_ci
808141cc406Sopenharmony_ci      if (NULL == g_pGammaTable)
809141cc406Sopenharmony_ci	{
810141cc406Sopenharmony_ci	  DBG (DBG_ERR, "SetParameters: gamma table malloc fail\n");
811141cc406Sopenharmony_ci	  return FALSE;
812141cc406Sopenharmony_ci	}
813141cc406Sopenharmony_ci      g_isSelfGamma = TRUE;
814141cc406Sopenharmony_ci
815141cc406Sopenharmony_ci      for (i = 0; i < 4096; i++)
816141cc406Sopenharmony_ci	{
817141cc406Sopenharmony_ci	  pow_d = (double) i / (double) 4096;
818141cc406Sopenharmony_ci
819141cc406Sopenharmony_ci	  byGammaData = (SANE_Byte) (pow (pow_d, pow_z) * 255);
820141cc406Sopenharmony_ci
821141cc406Sopenharmony_ci	  *(g_pGammaTable + i) = byGammaData;
822141cc406Sopenharmony_ci	  *(g_pGammaTable + i + 4096) = byGammaData;
823141cc406Sopenharmony_ci	  *(g_pGammaTable + i + 8192) = byGammaData;
824141cc406Sopenharmony_ci	}
825141cc406Sopenharmony_ci    }
826141cc406Sopenharmony_ci  else if (pSetParameters->smScanMode == SM_GRAY16
827141cc406Sopenharmony_ci	   || pSetParameters->smScanMode == SM_RGB48)
828141cc406Sopenharmony_ci    {
829141cc406Sopenharmony_ci      unsigned int i, wGammaData;
830141cc406Sopenharmony_ci      g_pGammaTable = (unsigned short *) malloc (sizeof (unsigned short) * 65536 * 3);
831141cc406Sopenharmony_ci
832141cc406Sopenharmony_ci      if (g_pGammaTable == NULL)
833141cc406Sopenharmony_ci	{
834141cc406Sopenharmony_ci	  DBG (DBG_ERR, "SetParameters: gamma table malloc fail\n");
835141cc406Sopenharmony_ci	  return FALSE;
836141cc406Sopenharmony_ci	}
837141cc406Sopenharmony_ci      g_isSelfGamma = TRUE;
838141cc406Sopenharmony_ci
839141cc406Sopenharmony_ci      for (i = 0; i < 65536; i++)
840141cc406Sopenharmony_ci	{
841141cc406Sopenharmony_ci	  wGammaData =
842141cc406Sopenharmony_ci	    (unsigned short) (pow ((((float) i) / 65536.0), (((float) 10) / 16.0)) *
843141cc406Sopenharmony_ci		    65535);
844141cc406Sopenharmony_ci
845141cc406Sopenharmony_ci	  *(g_pGammaTable + i) = wGammaData;
846141cc406Sopenharmony_ci	  *(g_pGammaTable + i + 65536) = wGammaData;
847141cc406Sopenharmony_ci	  *(g_pGammaTable + i + 65536 * 2) = wGammaData;
848141cc406Sopenharmony_ci	}
849141cc406Sopenharmony_ci    }
850141cc406Sopenharmony_ci  else
851141cc406Sopenharmony_ci    {
852141cc406Sopenharmony_ci      DBG (DBG_INFO, "SetParameters: set g_pGammaTable to NULL\n");
853141cc406Sopenharmony_ci      g_pGammaTable = NULL;
854141cc406Sopenharmony_ci    }
855141cc406Sopenharmony_ci
856141cc406Sopenharmony_ci  DBG (DBG_FUNC, "SetParameters: exit\n");
857141cc406Sopenharmony_ci  return TRUE;
858141cc406Sopenharmony_ci}
859141cc406Sopenharmony_ci
860141cc406Sopenharmony_ci/**********************************************************************
861141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
862141cc406Sopenharmony_ciRoutine Description:
863141cc406Sopenharmony_ci	get the optical dpi and scan area
864141cc406Sopenharmony_ciParameters:
865141cc406Sopenharmony_ci	pGetParameters: the information of scan
866141cc406Sopenharmony_ciReturn value:
867141cc406Sopenharmony_ci	if the operation is success
868141cc406Sopenharmony_ci	return TRUE
869141cc406Sopenharmony_ci	else
870141cc406Sopenharmony_ci	return FALSE
871141cc406Sopenharmony_ci***********************************************************************/
872141cc406Sopenharmony_cistatic SANE_Bool
873141cc406Sopenharmony_ciGetParameters (LPGETPARAMETERS pGetParameters)
874141cc406Sopenharmony_ci{
875141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetParameters: start\n");
876141cc406Sopenharmony_ci  if (ST_Reflective == g_ScanType)
877141cc406Sopenharmony_ci    {
878141cc406Sopenharmony_ci      if (FALSE == Reflective_ScanSuggest (&g_tiTarget, &g_ssSuggest))
879141cc406Sopenharmony_ci	{
880141cc406Sopenharmony_ci	  DBG (DBG_ERR, "GetParameters: Reflective_ScanSuggest error\n");
881141cc406Sopenharmony_ci	  return FALSE;
882141cc406Sopenharmony_ci	}
883141cc406Sopenharmony_ci    }
884141cc406Sopenharmony_ci  else
885141cc406Sopenharmony_ci    {
886141cc406Sopenharmony_ci      if (FALSE == Transparent_ScanSuggest (&g_tiTarget, &g_ssSuggest))
887141cc406Sopenharmony_ci	{
888141cc406Sopenharmony_ci	  DBG (DBG_ERR, "GetParameters: Transparent_ScanSuggest error\n");
889141cc406Sopenharmony_ci	  return FALSE;
890141cc406Sopenharmony_ci	}
891141cc406Sopenharmony_ci    }
892141cc406Sopenharmony_ci
893141cc406Sopenharmony_ci  pGetParameters->wSourceXDPI = g_ssSuggest.wXDpi;
894141cc406Sopenharmony_ci  pGetParameters->wSourceYDPI = g_ssSuggest.wYDpi;
895141cc406Sopenharmony_ci  pGetParameters->dwLength = (unsigned int) g_ssSuggest.wHeight;
896141cc406Sopenharmony_ci  pGetParameters->dwLineByteWidth = g_ssSuggest.dwBytesPerRow;
897141cc406Sopenharmony_ci
898141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetParameters: exit\n");
899141cc406Sopenharmony_ci
900141cc406Sopenharmony_ci  return TRUE;
901141cc406Sopenharmony_ci}
902141cc406Sopenharmony_ci
903141cc406Sopenharmony_ci/**********************************************************************
904141cc406Sopenharmony_ciAuthor: Jack            Date: 2005/05/13
905141cc406Sopenharmony_ci
906141cc406Sopenharmony_ciRoutine Description:
907141cc406Sopenharmony_ci	start scan image
908141cc406Sopenharmony_ciParameters:
909141cc406Sopenharmony_ci	none
910141cc406Sopenharmony_ciReturn value:
911141cc406Sopenharmony_ci	if operation is success
912141cc406Sopenharmony_ci	return TRUE
913141cc406Sopenharmony_ci	else
914141cc406Sopenharmony_ci	return FALSE
915141cc406Sopenharmony_ci***********************************************************************/
916141cc406Sopenharmony_cistatic SANE_Bool
917141cc406Sopenharmony_ciStartScan ()
918141cc406Sopenharmony_ci{
919141cc406Sopenharmony_ci  DBG (DBG_FUNC, "StartScan: start\n");
920141cc406Sopenharmony_ci  if (ST_Reflective == g_ScanType)
921141cc406Sopenharmony_ci    {
922141cc406Sopenharmony_ci      DBG (DBG_INFO, "StartScan: g_ScanType==ST_Reflective\n");
923141cc406Sopenharmony_ci
924141cc406Sopenharmony_ci      return Reflective_SetupScan (g_ssSuggest.cmScanMode,
925141cc406Sopenharmony_ci				   g_ssSuggest.wXDpi,
926141cc406Sopenharmony_ci				   g_ssSuggest.wYDpi,
927141cc406Sopenharmony_ci				   PF_BlackIs0,
928141cc406Sopenharmony_ci				   g_ssSuggest.wX,
929141cc406Sopenharmony_ci				   g_ssSuggest.wY,
930141cc406Sopenharmony_ci				   g_ssSuggest.wWidth, g_ssSuggest.wHeight);
931141cc406Sopenharmony_ci    }
932141cc406Sopenharmony_ci  else
933141cc406Sopenharmony_ci
934141cc406Sopenharmony_ci    {
935141cc406Sopenharmony_ci
936141cc406Sopenharmony_ci      DBG (DBG_INFO, "StartScan: g_ScanType==ST_Transparent\n");
937141cc406Sopenharmony_ci
938141cc406Sopenharmony_ci      return Transparent_SetupScan (g_ssSuggest.cmScanMode,
939141cc406Sopenharmony_ci				    g_ssSuggest.wXDpi,
940141cc406Sopenharmony_ci				    g_ssSuggest.wYDpi,
941141cc406Sopenharmony_ci				    PF_BlackIs0,
942141cc406Sopenharmony_ci				    g_ssSuggest.wX,
943141cc406Sopenharmony_ci				    g_ssSuggest.wY,
944141cc406Sopenharmony_ci				    g_ssSuggest.wWidth, g_ssSuggest.wHeight);
945141cc406Sopenharmony_ci    }
946141cc406Sopenharmony_ci}
947141cc406Sopenharmony_ci
948141cc406Sopenharmony_ci/**********************************************************************
949141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
950141cc406Sopenharmony_ciRoutine Description:
951141cc406Sopenharmony_ci	Read the scanner data
952141cc406Sopenharmony_ciParameters:
953141cc406Sopenharmony_ci
954141cc406Sopenharmony_ci	pImageRows: the information of the data
955141cc406Sopenharmony_ciReturn value:
956141cc406Sopenharmony_ci	if the operation is seccuss
957141cc406Sopenharmony_ci	return TRUE
958141cc406Sopenharmony_ci	else
959141cc406Sopenharmony_ci	return FALSE
960141cc406Sopenharmony_ci***********************************************************************/
961141cc406Sopenharmony_cistatic SANE_Bool
962141cc406Sopenharmony_ciReadScannedData (LPIMAGEROWS pImageRows)
963141cc406Sopenharmony_ci{
964141cc406Sopenharmony_ci  SANE_Bool isRGBInvert;
965141cc406Sopenharmony_ci  unsigned short Rows = 0;
966141cc406Sopenharmony_ci  SANE_Byte *lpBlock = (SANE_Byte *) pImageRows->pBuffer;
967141cc406Sopenharmony_ci  SANE_Byte *lpReturnData = (SANE_Byte *) pImageRows->pBuffer;
968141cc406Sopenharmony_ci  int i = 0;
969141cc406Sopenharmony_ci
970141cc406Sopenharmony_ci  DBG (DBG_FUNC, "ReadScannedData: start\n");
971141cc406Sopenharmony_ci
972141cc406Sopenharmony_ci  if (pImageRows->roRgbOrder == RO_RGB)
973141cc406Sopenharmony_ci    isRGBInvert = FALSE;
974141cc406Sopenharmony_ci  else
975141cc406Sopenharmony_ci    isRGBInvert = TRUE;
976141cc406Sopenharmony_ci
977141cc406Sopenharmony_ci  Rows = pImageRows->wWantedLineNum;
978141cc406Sopenharmony_ci
979141cc406Sopenharmony_ci  DBG (DBG_INFO, "ReadScannedData: wanted Rows = %d\n", Rows);
980141cc406Sopenharmony_ci
981141cc406Sopenharmony_ci  if (ST_Reflective == g_ScanType)
982141cc406Sopenharmony_ci    {
983141cc406Sopenharmony_ci      if (FALSE == Reflective_GetRows (lpBlock, &Rows, isRGBInvert))
984141cc406Sopenharmony_ci	return FALSE;
985141cc406Sopenharmony_ci    }
986141cc406Sopenharmony_ci  else if (SS_Positive == g_ssScanSource)
987141cc406Sopenharmony_ci    {
988141cc406Sopenharmony_ci      if (FALSE == Transparent_GetRows (lpBlock, &Rows, isRGBInvert))
989141cc406Sopenharmony_ci	return FALSE;
990141cc406Sopenharmony_ci    }
991141cc406Sopenharmony_ci
992141cc406Sopenharmony_ci  pImageRows->wXferedLineNum = Rows;
993141cc406Sopenharmony_ci
994141cc406Sopenharmony_ci  if (g_PixelFlavor == PF_WhiteIs0 || g_ScanMode == CM_TEXT)
995141cc406Sopenharmony_ci    {
996141cc406Sopenharmony_ci      int TotalSize = Rows * g_ssSuggest.dwBytesPerRow;
997141cc406Sopenharmony_ci      for (i = 0; i < TotalSize; i++)
998141cc406Sopenharmony_ci	{
999141cc406Sopenharmony_ci	  *(lpBlock++) ^= 0xff;
1000141cc406Sopenharmony_ci	}
1001141cc406Sopenharmony_ci    }
1002141cc406Sopenharmony_ci
1003141cc406Sopenharmony_ci  if (SS_Negative == g_ssScanSource)
1004141cc406Sopenharmony_ci    {
1005141cc406Sopenharmony_ci      DBG (DBG_INFO, "ReadScannedData: deal with the Negative\n");
1006141cc406Sopenharmony_ci
1007141cc406Sopenharmony_ci      if (g_bIsFirstGetNegData)
1008141cc406Sopenharmony_ci	{
1009141cc406Sopenharmony_ci	  unsigned int TotalImgeSize = g_SWHeight * g_ssSuggest.dwBytesPerRow;
1010141cc406Sopenharmony_ci	  g_lpNegImageData = (SANE_Byte *) malloc (TotalImgeSize);
1011141cc406Sopenharmony_ci	  if (NULL != g_lpNegImageData)
1012141cc406Sopenharmony_ci	    {
1013141cc406Sopenharmony_ci	      SANE_Byte * lpTempData = g_lpNegImageData;
1014141cc406Sopenharmony_ci	      DBG (DBG_INFO,
1015141cc406Sopenharmony_ci		   "ReadScannedData: malloc the negative data is success!\n");
1016141cc406Sopenharmony_ci	      g_bIsMallocNegData = TRUE;
1017141cc406Sopenharmony_ci	      if (!Transparent_GetRows
1018141cc406Sopenharmony_ci		  (g_lpNegImageData, &g_SWHeight, isRGBInvert))
1019141cc406Sopenharmony_ci		{
1020141cc406Sopenharmony_ci		  return FALSE;
1021141cc406Sopenharmony_ci		}
1022141cc406Sopenharmony_ci
1023141cc406Sopenharmony_ci	      DBG (DBG_INFO, "ReadScannedData: get image data is over!\n");
1024141cc406Sopenharmony_ci
1025141cc406Sopenharmony_ci	      for (i = 0; i < (int) TotalImgeSize; i++)
1026141cc406Sopenharmony_ci		{
1027141cc406Sopenharmony_ci		  *(g_lpNegImageData++) ^= 0xff;
1028141cc406Sopenharmony_ci		}
1029141cc406Sopenharmony_ci	      g_lpNegImageData = lpTempData;
1030141cc406Sopenharmony_ci	      AutoLevel (g_lpNegImageData, g_ScanMode, g_SWHeight,
1031141cc406Sopenharmony_ci			 g_ssSuggest.dwBytesPerRow);
1032141cc406Sopenharmony_ci	      DBG (DBG_INFO, "ReadScannedData: autolevel is ok\n");
1033141cc406Sopenharmony_ci	    }
1034141cc406Sopenharmony_ci	  g_bIsFirstGetNegData = FALSE;
1035141cc406Sopenharmony_ci	}
1036141cc406Sopenharmony_ci
1037141cc406Sopenharmony_ci      if (g_bIsMallocNegData)
1038141cc406Sopenharmony_ci	{
1039141cc406Sopenharmony_ci	  memcpy (pImageRows->pBuffer,
1040141cc406Sopenharmony_ci		  g_lpNegImageData +
1041141cc406Sopenharmony_ci		  g_ssSuggest.dwBytesPerRow * g_dwAlreadyGetNegLines,
1042141cc406Sopenharmony_ci		  g_ssSuggest.dwBytesPerRow * Rows);
1043141cc406Sopenharmony_ci
1044141cc406Sopenharmony_ci	  DBG (DBG_INFO, "ReadScannedData: copy the data over!\n");
1045141cc406Sopenharmony_ci
1046141cc406Sopenharmony_ci	  g_dwAlreadyGetNegLines += Rows;
1047141cc406Sopenharmony_ci	  if (g_dwAlreadyGetNegLines >= g_SWHeight)
1048141cc406Sopenharmony_ci	    {
1049141cc406Sopenharmony_ci	      DBG (DBG_INFO, "ReadScannedData: free the image data!\n");
1050141cc406Sopenharmony_ci	      free (g_lpNegImageData);
1051141cc406Sopenharmony_ci	      g_lpNegImageData = NULL;
1052141cc406Sopenharmony_ci	      g_bIsFirstGetNegData = TRUE;
1053141cc406Sopenharmony_ci	      g_dwAlreadyGetNegLines = 0;
1054141cc406Sopenharmony_ci	      g_bIsMallocNegData = FALSE;
1055141cc406Sopenharmony_ci	    }
1056141cc406Sopenharmony_ci	}
1057141cc406Sopenharmony_ci      else
1058141cc406Sopenharmony_ci	{
1059141cc406Sopenharmony_ci	  int TotalSize = Rows * g_ssSuggest.dwBytesPerRow;
1060141cc406Sopenharmony_ci	  DBG (DBG_INFO,
1061141cc406Sopenharmony_ci	       "ReadScannedData: malloc the negative data is fail!\n");
1062141cc406Sopenharmony_ci	  if (!Transparent_GetRows (lpReturnData, &Rows, isRGBInvert))
1063141cc406Sopenharmony_ci	    {
1064141cc406Sopenharmony_ci	      return FALSE;
1065141cc406Sopenharmony_ci	    }
1066141cc406Sopenharmony_ci
1067141cc406Sopenharmony_ci	  for (i = 0; i < TotalSize; i++)
1068141cc406Sopenharmony_ci	    {
1069141cc406Sopenharmony_ci	      *(lpReturnData++) ^= 0xff;
1070141cc406Sopenharmony_ci	    }
1071141cc406Sopenharmony_ci	  pImageRows->wXferedLineNum = Rows;
1072141cc406Sopenharmony_ci
1073141cc406Sopenharmony_ci	  g_dwAlreadyGetNegLines += Rows;
1074141cc406Sopenharmony_ci	  if (g_dwAlreadyGetNegLines >= g_SWHeight)
1075141cc406Sopenharmony_ci	    {
1076141cc406Sopenharmony_ci	      g_bIsFirstGetNegData = TRUE;
1077141cc406Sopenharmony_ci	      g_dwAlreadyGetNegLines = 0;
1078141cc406Sopenharmony_ci	      g_bIsMallocNegData = FALSE;
1079141cc406Sopenharmony_ci	    }
1080141cc406Sopenharmony_ci	}
1081141cc406Sopenharmony_ci
1082141cc406Sopenharmony_ci    }
1083141cc406Sopenharmony_ci
1084141cc406Sopenharmony_ci  DBG (DBG_FUNC, "ReadScannedData: leave ReadScannedData\n");
1085141cc406Sopenharmony_ci
1086141cc406Sopenharmony_ci  return TRUE;
1087141cc406Sopenharmony_ci}
1088141cc406Sopenharmony_ci
1089141cc406Sopenharmony_ci/**********************************************************************
1090141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
1091141cc406Sopenharmony_ciRoutine Description:
1092141cc406Sopenharmony_ci	Stop scan
1093141cc406Sopenharmony_ciParameters:
1094141cc406Sopenharmony_ci	none
1095141cc406Sopenharmony_ciReturn value:
1096141cc406Sopenharmony_ci	if operation is success
1097141cc406Sopenharmony_ci	return TRUE
1098141cc406Sopenharmony_ci	else
1099141cc406Sopenharmony_ci	return FALSE
1100141cc406Sopenharmony_ci***********************************************************************/
1101141cc406Sopenharmony_cistatic SANE_Bool
1102141cc406Sopenharmony_ciStopScan ()
1103141cc406Sopenharmony_ci{
1104141cc406Sopenharmony_ci  SANE_Bool rt;
1105141cc406Sopenharmony_ci  int i;
1106141cc406Sopenharmony_ci
1107141cc406Sopenharmony_ci  DBG (DBG_FUNC, "StopScan: start\n");
1108141cc406Sopenharmony_ci
1109141cc406Sopenharmony_ci  /*stop read data and kill thread */
1110141cc406Sopenharmony_ci  if (ST_Reflective == g_ScanType)
1111141cc406Sopenharmony_ci    {
1112141cc406Sopenharmony_ci      rt = Reflective_StopScan ();
1113141cc406Sopenharmony_ci    }
1114141cc406Sopenharmony_ci  else
1115141cc406Sopenharmony_ci    {
1116141cc406Sopenharmony_ci      rt = Transparent_StopScan ();
1117141cc406Sopenharmony_ci    }
1118141cc406Sopenharmony_ci
1119141cc406Sopenharmony_ci  /*free gamma table */
1120141cc406Sopenharmony_ci  if (g_isSelfGamma && g_pGammaTable != NULL)
1121141cc406Sopenharmony_ci    {
1122141cc406Sopenharmony_ci      for (i = 0; i < 20; i++)
1123141cc406Sopenharmony_ci	{
1124141cc406Sopenharmony_ci	  if (!g_isScanning)
1125141cc406Sopenharmony_ci	    {
1126141cc406Sopenharmony_ci	      free (g_pGammaTable);
1127141cc406Sopenharmony_ci	      g_pGammaTable = NULL;
1128141cc406Sopenharmony_ci	      break;
1129141cc406Sopenharmony_ci	    }
1130141cc406Sopenharmony_ci	  else
1131141cc406Sopenharmony_ci	    {
1132141cc406Sopenharmony_ci	      sleep (1);	/*waiting ReadScannedData return. */
1133141cc406Sopenharmony_ci	    }
1134141cc406Sopenharmony_ci	}
1135141cc406Sopenharmony_ci    }
1136141cc406Sopenharmony_ci
1137141cc406Sopenharmony_ci  /*free image buffer */
1138141cc406Sopenharmony_ci  if (g_lpReadImageHead != NULL)
1139141cc406Sopenharmony_ci
1140141cc406Sopenharmony_ci    {
1141141cc406Sopenharmony_ci      free (g_lpReadImageHead);
1142141cc406Sopenharmony_ci      g_lpReadImageHead = NULL;
1143141cc406Sopenharmony_ci    }
1144141cc406Sopenharmony_ci
1145141cc406Sopenharmony_ci  DBG (DBG_FUNC, "StopScan: exit\n");
1146141cc406Sopenharmony_ci  return rt;
1147141cc406Sopenharmony_ci}
1148141cc406Sopenharmony_ci
1149141cc406Sopenharmony_ci/**********************************************************************
1150141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
1151141cc406Sopenharmony_ciRoutine Description:
1152141cc406Sopenharmony_ci	Check the status of TA
1153141cc406Sopenharmony_ciParameters:
1154141cc406Sopenharmony_ci	none
1155141cc406Sopenharmony_ciReturn value:
1156141cc406Sopenharmony_ci	if operation is success
1157141cc406Sopenharmony_ci	return TRUE
1158141cc406Sopenharmony_ci	else
1159141cc406Sopenharmony_ci	return FALSE
1160141cc406Sopenharmony_ci***********************************************************************/
1161141cc406Sopenharmony_cistatic SANE_Bool
1162141cc406Sopenharmony_ciIsTAConnected ()
1163141cc406Sopenharmony_ci{
1164141cc406Sopenharmony_ci  SANE_Bool hasTA;
1165141cc406Sopenharmony_ci
1166141cc406Sopenharmony_ci  DBG (DBG_FUNC, "StopScan: start\n");
1167141cc406Sopenharmony_ci
1168141cc406Sopenharmony_ci  if (Asic_Open (&g_chip, g_pDeviceFile) != SANE_STATUS_GOOD)
1169141cc406Sopenharmony_ci    {
1170141cc406Sopenharmony_ci      return FALSE;
1171141cc406Sopenharmony_ci    }
1172141cc406Sopenharmony_ci
1173141cc406Sopenharmony_ci  if (Asic_IsTAConnected (&g_chip, &hasTA) != SANE_STATUS_GOOD)
1174141cc406Sopenharmony_ci    {
1175141cc406Sopenharmony_ci      Asic_Close (&g_chip);
1176141cc406Sopenharmony_ci      return FALSE;
1177141cc406Sopenharmony_ci    }
1178141cc406Sopenharmony_ci
1179141cc406Sopenharmony_ci  Asic_Close (&g_chip);
1180141cc406Sopenharmony_ci
1181141cc406Sopenharmony_ci  DBG (DBG_FUNC, "StopScan: exit\n");
1182141cc406Sopenharmony_ci  return hasTA;
1183141cc406Sopenharmony_ci}
1184141cc406Sopenharmony_ci
1185141cc406Sopenharmony_ci#ifdef SANE_UNUSED
1186141cc406Sopenharmony_ci/**********************************************************************
1187141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
1188141cc406Sopenharmony_ciRoutine Description:
1189141cc406Sopenharmony_ci	Get the status of the HK
1190141cc406Sopenharmony_ciParameters:
1191141cc406Sopenharmony_ci	pKey: the status of key
1192141cc406Sopenharmony_ciReturn value:
1193141cc406Sopenharmony_ci	if the operation is success
1194141cc406Sopenharmony_ci	return TRUE
1195141cc406Sopenharmony_ci	else
1196141cc406Sopenharmony_ci	return FALSE
1197141cc406Sopenharmony_ci***********************************************************************/
1198141cc406Sopenharmony_cistatic SANE_Bool
1199141cc406Sopenharmony_ciGetKeyStatus (SANE_Byte * pKey)
1200141cc406Sopenharmony_ci{
1201141cc406Sopenharmony_ci  SANE_Byte pKeyTemp = 0x00;
1202141cc406Sopenharmony_ci  SANE_Status status = Asic_CheckFunctionKey (&g_chip, &pKeyTemp);
1203141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetKeyStatus: start\n");
1204141cc406Sopenharmony_ci
1205141cc406Sopenharmony_ci  if (SANE_STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
1206141cc406Sopenharmony_ci    {
1207141cc406Sopenharmony_ci      DBG (DBG_ERR, "GetKeyStatus: Asic_Open is fail\n");
1208141cc406Sopenharmony_ci      return FALSE;
1209141cc406Sopenharmony_ci    }
1210141cc406Sopenharmony_ci
1211141cc406Sopenharmony_ci  if (SANE_STATUS_GOOD != status)
1212141cc406Sopenharmony_ci    {
1213141cc406Sopenharmony_ci      DBG (DBG_ERR, "GetKeyStatus: Asic_CheckFunctionKey is fail\n");
1214141cc406Sopenharmony_ci      return FALSE;
1215141cc406Sopenharmony_ci    }
1216141cc406Sopenharmony_ci
1217141cc406Sopenharmony_ci  if (0x01 == pKeyTemp)
1218141cc406Sopenharmony_ci    {
1219141cc406Sopenharmony_ci      *pKey = 0x01;		/*Scan key pressed */
1220141cc406Sopenharmony_ci    }
1221141cc406Sopenharmony_ci
1222141cc406Sopenharmony_ci  if (0x02 == pKeyTemp)
1223141cc406Sopenharmony_ci    {
1224141cc406Sopenharmony_ci      *pKey = 0x02;		/*Copy key pressed */
1225141cc406Sopenharmony_ci    }
1226141cc406Sopenharmony_ci  if (0x04 == pKeyTemp)
1227141cc406Sopenharmony_ci    {
1228141cc406Sopenharmony_ci      *pKey = 0x03;		/*Fax key pressed */
1229141cc406Sopenharmony_ci    }
1230141cc406Sopenharmony_ci  if (0x08 == pKeyTemp)
1231141cc406Sopenharmony_ci    {
1232141cc406Sopenharmony_ci      *pKey = 0x04;		/*Email key pressed */
1233141cc406Sopenharmony_ci    }
1234141cc406Sopenharmony_ci  if (0x10 == pKeyTemp)
1235141cc406Sopenharmony_ci    {
1236141cc406Sopenharmony_ci      *pKey = 0x05;		/*Panel key pressed */
1237141cc406Sopenharmony_ci    }
1238141cc406Sopenharmony_ci
1239141cc406Sopenharmony_ci  if (SANE_STATUS_GOOD != Asic_Close (&g_chip))
1240141cc406Sopenharmony_ci    {
1241141cc406Sopenharmony_ci      DBG (DBG_ERR, "GetKeyStatus: Asic_Close is fail\n");
1242141cc406Sopenharmony_ci      return FALSE;
1243141cc406Sopenharmony_ci    }
1244141cc406Sopenharmony_ci
1245141cc406Sopenharmony_ci  DBG (DBG_FUNC, "GetKeyStatus: exit\n");
1246141cc406Sopenharmony_ci  return TRUE;
1247141cc406Sopenharmony_ci}
1248141cc406Sopenharmony_ci#endif
1249141cc406Sopenharmony_ci/**********************************************************************
1250141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
1251141cc406Sopenharmony_ciRoutine Description:
1252141cc406Sopenharmony_ci	Deal with the image with auto level
1253141cc406Sopenharmony_ciParameters:
1254141cc406Sopenharmony_ci	lpSource: the data of image
1255141cc406Sopenharmony_ci	scanMode: the scan mode
1256141cc406Sopenharmony_ci	ScanLines: the rows of image
1257141cc406Sopenharmony_ci	BytesPerLine: the bytes of per line
1258141cc406Sopenharmony_ciReturn value:
1259141cc406Sopenharmony_ci	none
1260141cc406Sopenharmony_ci***********************************************************************/
1261141cc406Sopenharmony_cistatic void
1262141cc406Sopenharmony_ciAutoLevel (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
1263141cc406Sopenharmony_ci	   unsigned int BytesPerLine)
1264141cc406Sopenharmony_ci{
1265141cc406Sopenharmony_ci  int ii;
1266141cc406Sopenharmony_ci  unsigned int i, j;
1267141cc406Sopenharmony_ci  unsigned int tLines, CountPixels, TotalImgSize;
1268141cc406Sopenharmony_ci  unsigned short R, G, B, max_R, max_G, max_B, min_R, min_G, min_B;
1269141cc406Sopenharmony_ci  float fmax_R, fmax_G, fmax_B;
1270141cc406Sopenharmony_ci  unsigned int sum_R = 0, sum_G = 0, sum_B = 0;
1271141cc406Sopenharmony_ci  unsigned int hisgram_R[256], hisgram_G[256], hisgram_B[256];
1272141cc406Sopenharmony_ci
1273141cc406Sopenharmony_ci  unsigned int iWidth = BytesPerLine / 3;
1274141cc406Sopenharmony_ci  unsigned int iHeight = ScanLines;
1275141cc406Sopenharmony_ci  SANE_Byte *pbmpdata = (SANE_Byte *) lpSource;
1276141cc406Sopenharmony_ci
1277141cc406Sopenharmony_ci  unsigned short imin_threshold[3];
1278141cc406Sopenharmony_ci  unsigned short imax_threshold[3];
1279141cc406Sopenharmony_ci
1280141cc406Sopenharmony_ci  DBG (DBG_FUNC, "AutoLevel: start\n");
1281141cc406Sopenharmony_ci
1282141cc406Sopenharmony_ci  if (scanMode != CM_RGB24ext)
1283141cc406Sopenharmony_ci    {
1284141cc406Sopenharmony_ci      return;
1285141cc406Sopenharmony_ci    }
1286141cc406Sopenharmony_ci
1287141cc406Sopenharmony_ci  i = j = 0;
1288141cc406Sopenharmony_ci  tLines = CountPixels = TotalImgSize = 0;
1289141cc406Sopenharmony_ci
1290141cc406Sopenharmony_ci  TotalImgSize = iWidth * iHeight;
1291141cc406Sopenharmony_ci
1292141cc406Sopenharmony_ci
1293141cc406Sopenharmony_ci
1294141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
1295141cc406Sopenharmony_ci    {
1296141cc406Sopenharmony_ci
1297141cc406Sopenharmony_ci      hisgram_R[i] = 0;
1298141cc406Sopenharmony_ci      hisgram_G[i] = 0;
1299141cc406Sopenharmony_ci      hisgram_B[i] = 0;
1300141cc406Sopenharmony_ci    }
1301141cc406Sopenharmony_ci
1302141cc406Sopenharmony_ci
1303141cc406Sopenharmony_ci  DBG (DBG_INFO, "AutoLevel: init data is over\n");
1304141cc406Sopenharmony_ci
1305141cc406Sopenharmony_ci  /* Find min , max, mean */
1306141cc406Sopenharmony_ci  max_R = max_G = max_B = 0;
1307141cc406Sopenharmony_ci  min_R = min_G = min_B = 255;
1308141cc406Sopenharmony_ci  tLines = 0;
1309141cc406Sopenharmony_ci  DBG (DBG_INFO, "AutoLevel: iHeight = %d, iWidth = %d\n", iHeight, iWidth);
1310141cc406Sopenharmony_ci
1311141cc406Sopenharmony_ci  for (j = 0; j < iHeight; j++)
1312141cc406Sopenharmony_ci    {
1313141cc406Sopenharmony_ci      tLines = j * iWidth * 3;
1314141cc406Sopenharmony_ci
1315141cc406Sopenharmony_ci
1316141cc406Sopenharmony_ci      for (i = 0; i < iWidth; i++)
1317141cc406Sopenharmony_ci	{
1318141cc406Sopenharmony_ci	  R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1319141cc406Sopenharmony_ci	  G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1320141cc406Sopenharmony_ci	  B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1321141cc406Sopenharmony_ci
1322141cc406Sopenharmony_ci	  max_R = _MAX (R, max_R);
1323141cc406Sopenharmony_ci	  max_G = _MAX (G, max_G);
1324141cc406Sopenharmony_ci	  max_B = _MAX (B, max_B);
1325141cc406Sopenharmony_ci
1326141cc406Sopenharmony_ci	  min_R = _MIN (R, min_R);
1327141cc406Sopenharmony_ci	  min_G = _MIN (G, min_G);
1328141cc406Sopenharmony_ci	  min_B = _MIN (B, min_B);
1329141cc406Sopenharmony_ci
1330141cc406Sopenharmony_ci	  hisgram_R[(SANE_Byte) R]++;
1331141cc406Sopenharmony_ci	  hisgram_G[(SANE_Byte) G]++;
1332141cc406Sopenharmony_ci	  hisgram_B[(SANE_Byte) B]++;
1333141cc406Sopenharmony_ci
1334141cc406Sopenharmony_ci	  sum_R += R;
1335141cc406Sopenharmony_ci	  sum_G += G;
1336141cc406Sopenharmony_ci	  sum_B += B;
1337141cc406Sopenharmony_ci
1338141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R;
1339141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G;
1340141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B;
1341141cc406Sopenharmony_ci
1342141cc406Sopenharmony_ci	  CountPixels++;
1343141cc406Sopenharmony_ci	}
1344141cc406Sopenharmony_ci
1345141cc406Sopenharmony_ci    }
1346141cc406Sopenharmony_ci
1347141cc406Sopenharmony_ci  DBG (DBG_INFO, "AutoLevel: Find min , max is over!\n");
1348141cc406Sopenharmony_ci
1349141cc406Sopenharmony_ci
1350141cc406Sopenharmony_ci  imin_threshold[0] = 0;
1351141cc406Sopenharmony_ci  imin_threshold[1] = 0;
1352141cc406Sopenharmony_ci  imin_threshold[2] = 0;
1353141cc406Sopenharmony_ci  imax_threshold[0] = 0;
1354141cc406Sopenharmony_ci  imax_threshold[1] = 0;
1355141cc406Sopenharmony_ci  imax_threshold[2] = 0;
1356141cc406Sopenharmony_ci
1357141cc406Sopenharmony_ci  for (ii = 0; ii < 256; ii++)
1358141cc406Sopenharmony_ci    {
1359141cc406Sopenharmony_ci      if (hisgram_R[ii] > 0)
1360141cc406Sopenharmony_ci	if (hisgram_R[ii] >= imin_threshold[0])
1361141cc406Sopenharmony_ci	  {
1362141cc406Sopenharmony_ci	    min_R = ii;
1363141cc406Sopenharmony_ci	    break;
1364141cc406Sopenharmony_ci	  }
1365141cc406Sopenharmony_ci    }
1366141cc406Sopenharmony_ci
1367141cc406Sopenharmony_ci  for (ii = 255; ii >= 0; ii--)
1368141cc406Sopenharmony_ci    {
1369141cc406Sopenharmony_ci      if (hisgram_R[ii] > 0)
1370141cc406Sopenharmony_ci	if (hisgram_R[ii] >= imax_threshold[0])
1371141cc406Sopenharmony_ci	  {
1372141cc406Sopenharmony_ci	    max_R = ii;
1373141cc406Sopenharmony_ci	    break;
1374141cc406Sopenharmony_ci	  }
1375141cc406Sopenharmony_ci    }
1376141cc406Sopenharmony_ci
1377141cc406Sopenharmony_ci  for (ii = 0; ii < 256; ii++)
1378141cc406Sopenharmony_ci    {
1379141cc406Sopenharmony_ci      if (hisgram_G[ii] > 0)
1380141cc406Sopenharmony_ci	if (hisgram_G[ii] >= imin_threshold[1])
1381141cc406Sopenharmony_ci	  {
1382141cc406Sopenharmony_ci	    min_G = ii;
1383141cc406Sopenharmony_ci	    break;
1384141cc406Sopenharmony_ci	  }
1385141cc406Sopenharmony_ci    }
1386141cc406Sopenharmony_ci
1387141cc406Sopenharmony_ci  for (ii = 255; ii >= 0; ii--)
1388141cc406Sopenharmony_ci    {
1389141cc406Sopenharmony_ci      if (hisgram_G[ii] > 0)
1390141cc406Sopenharmony_ci	if (hisgram_G[ii] >= imax_threshold[1])
1391141cc406Sopenharmony_ci	  {
1392141cc406Sopenharmony_ci	    max_G = ii;
1393141cc406Sopenharmony_ci	    break;
1394141cc406Sopenharmony_ci	  }
1395141cc406Sopenharmony_ci    }
1396141cc406Sopenharmony_ci
1397141cc406Sopenharmony_ci  for (ii = 0; ii < 256; ii++)
1398141cc406Sopenharmony_ci    {
1399141cc406Sopenharmony_ci      if (hisgram_B[ii] > 0)
1400141cc406Sopenharmony_ci	if (hisgram_B[ii] >= imin_threshold[2])
1401141cc406Sopenharmony_ci	  {
1402141cc406Sopenharmony_ci	    min_B = ii;
1403141cc406Sopenharmony_ci	    break;
1404141cc406Sopenharmony_ci	  }
1405141cc406Sopenharmony_ci    }
1406141cc406Sopenharmony_ci
1407141cc406Sopenharmony_ci  for (ii = 255; ii >= 0; ii--)
1408141cc406Sopenharmony_ci    {
1409141cc406Sopenharmony_ci      if (hisgram_B[ii] > 0)
1410141cc406Sopenharmony_ci	if (hisgram_B[ii] >= imax_threshold[2])
1411141cc406Sopenharmony_ci	  {
1412141cc406Sopenharmony_ci	    max_B = ii;
1413141cc406Sopenharmony_ci	    break;
1414141cc406Sopenharmony_ci	  }
1415141cc406Sopenharmony_ci    }
1416141cc406Sopenharmony_ci
1417141cc406Sopenharmony_ci  DBG (DBG_INFO, "AutoLevel: Set min , max is over!\n");
1418141cc406Sopenharmony_ci
1419141cc406Sopenharmony_ci  /*Autolevel: */
1420141cc406Sopenharmony_ci  sum_R = max_R - min_R;
1421141cc406Sopenharmony_ci  sum_G = max_G - min_G;
1422141cc406Sopenharmony_ci  sum_B = max_B - min_B;
1423141cc406Sopenharmony_ci
1424141cc406Sopenharmony_ci  for (j = 0; j < iHeight; j++)
1425141cc406Sopenharmony_ci    {
1426141cc406Sopenharmony_ci      tLines = j * iWidth * 3;
1427141cc406Sopenharmony_ci      for (i = 0; i < iWidth; i++)
1428141cc406Sopenharmony_ci	{
1429141cc406Sopenharmony_ci	  R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1430141cc406Sopenharmony_ci	  G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1431141cc406Sopenharmony_ci	  B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1432141cc406Sopenharmony_ci
1433141cc406Sopenharmony_ci	   /*R*/ if (sum_R == 0)
1434141cc406Sopenharmony_ci	    R = max_R;
1435141cc406Sopenharmony_ci	  else if (R < min_R)
1436141cc406Sopenharmony_ci	    R = 0;
1437141cc406Sopenharmony_ci	  else if (R <= 255)
1438141cc406Sopenharmony_ci	    {
1439141cc406Sopenharmony_ci	      fmax_R = ((float) ((R - min_R) * 255) / (float) sum_R);
1440141cc406Sopenharmony_ci	      R = (unsigned short) fmax_R;
1441141cc406Sopenharmony_ci	      fmax_R = (fmax_R - R) * 10;
1442141cc406Sopenharmony_ci
1443141cc406Sopenharmony_ci	      if (fmax_R >= 5)
1444141cc406Sopenharmony_ci		R++;
1445141cc406Sopenharmony_ci	    }
1446141cc406Sopenharmony_ci	  if (R > 255)
1447141cc406Sopenharmony_ci	    R = 255;
1448141cc406Sopenharmony_ci
1449141cc406Sopenharmony_ci	   /*G*/ if (sum_G == 0)
1450141cc406Sopenharmony_ci	    G = max_G;
1451141cc406Sopenharmony_ci	  else if (G < min_G)
1452141cc406Sopenharmony_ci	    G = 0;
1453141cc406Sopenharmony_ci	  else if (G <= 255)
1454141cc406Sopenharmony_ci	    {
1455141cc406Sopenharmony_ci	      fmax_G = ((float) ((G - min_G) * 255) / (float) sum_G);
1456141cc406Sopenharmony_ci	      G = (unsigned short) fmax_G;
1457141cc406Sopenharmony_ci	      fmax_G = (fmax_G - G) * 10;
1458141cc406Sopenharmony_ci	      if (fmax_G >= 5)
1459141cc406Sopenharmony_ci		G++;
1460141cc406Sopenharmony_ci
1461141cc406Sopenharmony_ci	    }
1462141cc406Sopenharmony_ci	  if (G > 255)
1463141cc406Sopenharmony_ci	    G = 255;
1464141cc406Sopenharmony_ci
1465141cc406Sopenharmony_ci	   /*B*/ if (sum_B == 0)
1466141cc406Sopenharmony_ci	    B = max_B;
1467141cc406Sopenharmony_ci	  else if (B < min_B)
1468141cc406Sopenharmony_ci	    B = 0;
1469141cc406Sopenharmony_ci	  else if (B <= 255)
1470141cc406Sopenharmony_ci	    {
1471141cc406Sopenharmony_ci	      fmax_B = ((float) (B - min_B) * 255 / (float) sum_B);
1472141cc406Sopenharmony_ci	      B = (unsigned short) fmax_B;
1473141cc406Sopenharmony_ci	      fmax_B = (fmax_B - B) * 10;
1474141cc406Sopenharmony_ci	      if (fmax_B >= 5)
1475141cc406Sopenharmony_ci		B++;
1476141cc406Sopenharmony_ci	    }
1477141cc406Sopenharmony_ci	  if (B > 255)
1478141cc406Sopenharmony_ci	    B = 255;
1479141cc406Sopenharmony_ci
1480141cc406Sopenharmony_ci	  hisgram_R[(SANE_Byte) R]++;
1481141cc406Sopenharmony_ci	  hisgram_G[(SANE_Byte) G]++;
1482141cc406Sopenharmony_ci	  hisgram_B[(SANE_Byte) B]++;
1483141cc406Sopenharmony_ci
1484141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R;
1485141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G;
1486141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B;
1487141cc406Sopenharmony_ci
1488141cc406Sopenharmony_ci	}
1489141cc406Sopenharmony_ci    }
1490141cc406Sopenharmony_ci
1491141cc406Sopenharmony_ci  DBG (DBG_FUNC, "AutoLevel: exit\n");
1492141cc406Sopenharmony_ci  return;
1493141cc406Sopenharmony_ci}
1494141cc406Sopenharmony_ci
1495141cc406Sopenharmony_ci#ifdef SANE_UNUSED
1496141cc406Sopenharmony_ci/**********************************************************************
1497141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
1498141cc406Sopenharmony_ciRoutine Description:
1499141cc406Sopenharmony_ci	Deal with image with auto level
1500141cc406Sopenharmony_ciParameters:
1501141cc406Sopenharmony_ci	pDIB: the data of image
1502141cc406Sopenharmony_ci	ImageWidth: the width of image
1503141cc406Sopenharmony_ci	ImageHeight: the height of image
1504141cc406Sopenharmony_ciReturn value:
1505141cc406Sopenharmony_ci	none
1506141cc406Sopenharmony_ci***********************************************************************/
1507141cc406Sopenharmony_cistatic void
1508141cc406Sopenharmony_ciQBETDetectAutoLevel (void *pDIB, unsigned int ImageWidth, unsigned int ImageHeight)
1509141cc406Sopenharmony_ci{
1510141cc406Sopenharmony_ci  unsigned short *pbmpdata;
1511141cc406Sopenharmony_ci  float fRPercent = 0.0;
1512141cc406Sopenharmony_ci  float fGPercent = 0.0;
1513141cc406Sopenharmony_ci  float fBPercent = 0.0;
1514141cc406Sopenharmony_ci  float fRSum, fGSum, fBSum;
1515141cc406Sopenharmony_ci
1516141cc406Sopenharmony_ci  int i, j;
1517141cc406Sopenharmony_ci  unsigned int tLines, CountPixels, TotalImgSize;
1518141cc406Sopenharmony_ci  unsigned short R, G, B, max_R, max_G, max_B, min_R, min_G, min_B;
1519141cc406Sopenharmony_ci  unsigned short wIndexR, wIndexG, wIndexB;
1520141cc406Sopenharmony_ci  float fmax_R, fmax_G, fmax_B;
1521141cc406Sopenharmony_ci  unsigned int sum_R = 0, sum_G = 0, sum_B = 0;
1522141cc406Sopenharmony_ci  unsigned int hisgram_R[1024], hisgram_G[1024], hisgram_B[1024];
1523141cc406Sopenharmony_ci
1524141cc406Sopenharmony_ci  if (!pDIB)
1525141cc406Sopenharmony_ci    {
1526141cc406Sopenharmony_ci      return;
1527141cc406Sopenharmony_ci    }
1528141cc406Sopenharmony_ci
1529141cc406Sopenharmony_ci  pbmpdata = (unsigned short *) pDIB;
1530141cc406Sopenharmony_ci
1531141cc406Sopenharmony_ci  CountPixels = 0;
1532141cc406Sopenharmony_ci  TotalImgSize = ImageWidth * ImageHeight;
1533141cc406Sopenharmony_ci
1534141cc406Sopenharmony_ci
1535141cc406Sopenharmony_ci  for (i = 0; i < 1024; i++)
1536141cc406Sopenharmony_ci    {
1537141cc406Sopenharmony_ci
1538141cc406Sopenharmony_ci      hisgram_R[i] = 0;
1539141cc406Sopenharmony_ci      hisgram_G[i] = 0;
1540141cc406Sopenharmony_ci      hisgram_B[i] = 0;
1541141cc406Sopenharmony_ci    }
1542141cc406Sopenharmony_ci
1543141cc406Sopenharmony_ci
1544141cc406Sopenharmony_ci  /*Find min , max, mean */
1545141cc406Sopenharmony_ci  max_R = max_G = max_B = 0;
1546141cc406Sopenharmony_ci  min_R = min_G = min_B = 1023;
1547141cc406Sopenharmony_ci  tLines = 0;
1548141cc406Sopenharmony_ci
1549141cc406Sopenharmony_ci  for (j = 0; j < (int) ImageHeight; j++)
1550141cc406Sopenharmony_ci    {
1551141cc406Sopenharmony_ci      tLines = j * ImageWidth * 3;
1552141cc406Sopenharmony_ci      for (i = 0; i < (int) ImageWidth; i++)
1553141cc406Sopenharmony_ci	{
1554141cc406Sopenharmony_ci	  R = *(pbmpdata + (tLines + i * 3 + 2));
1555141cc406Sopenharmony_ci	  G = *(pbmpdata + (tLines + i * 3 + 1));
1556141cc406Sopenharmony_ci	  B = *(pbmpdata + (tLines + i * 3));
1557141cc406Sopenharmony_ci
1558141cc406Sopenharmony_ci	  max_R = _MAX (R, max_R);
1559141cc406Sopenharmony_ci	  max_G = _MAX (G, max_G);
1560141cc406Sopenharmony_ci	  max_B = _MAX (B, max_B);
1561141cc406Sopenharmony_ci
1562141cc406Sopenharmony_ci	  min_R = _MIN (R, min_R);
1563141cc406Sopenharmony_ci	  min_G = _MIN (G, min_G);
1564141cc406Sopenharmony_ci	  min_B = _MIN (B, min_B);
1565141cc406Sopenharmony_ci
1566141cc406Sopenharmony_ci	  hisgram_R[R]++;
1567141cc406Sopenharmony_ci	  hisgram_G[G]++;
1568141cc406Sopenharmony_ci	  hisgram_B[B]++;
1569141cc406Sopenharmony_ci
1570141cc406Sopenharmony_ci	  sum_R += R;
1571141cc406Sopenharmony_ci	  sum_G += G;
1572141cc406Sopenharmony_ci	  sum_B += B;
1573141cc406Sopenharmony_ci
1574141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 2)) = R;
1575141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 1)) = G;
1576141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3)) = B;
1577141cc406Sopenharmony_ci
1578141cc406Sopenharmony_ci	  CountPixels++;
1579141cc406Sopenharmony_ci	}
1580141cc406Sopenharmony_ci
1581141cc406Sopenharmony_ci    }
1582141cc406Sopenharmony_ci
1583141cc406Sopenharmony_ci
1584141cc406Sopenharmony_ci  fRSum = 0.0;
1585141cc406Sopenharmony_ci  fGSum = 0.0;
1586141cc406Sopenharmony_ci  fBSum = 0.0;
1587141cc406Sopenharmony_ci
1588141cc406Sopenharmony_ci  wIndexR = 511;
1589141cc406Sopenharmony_ci  wIndexG = 511;
1590141cc406Sopenharmony_ci  wIndexB = 511;
1591141cc406Sopenharmony_ci
1592141cc406Sopenharmony_ci  for (i = 0; i < 1024; i++)
1593141cc406Sopenharmony_ci    {
1594141cc406Sopenharmony_ci      fRSum += (float) hisgram_R[i];
1595141cc406Sopenharmony_ci      fRPercent = (fRSum / CountPixels) * 100;
1596141cc406Sopenharmony_ci      if (fRPercent > 50)
1597141cc406Sopenharmony_ci	{
1598141cc406Sopenharmony_ci	  wIndexR = i;
1599141cc406Sopenharmony_ci	  break;
1600141cc406Sopenharmony_ci	}
1601141cc406Sopenharmony_ci
1602141cc406Sopenharmony_ci    }
1603141cc406Sopenharmony_ci
1604141cc406Sopenharmony_ci  for (i = 0; i < 1024; i++)
1605141cc406Sopenharmony_ci    {
1606141cc406Sopenharmony_ci      fGSum += (float) hisgram_G[i];
1607141cc406Sopenharmony_ci      fGPercent = (fGSum / CountPixels) * 100;
1608141cc406Sopenharmony_ci      if (fGPercent > 50)
1609141cc406Sopenharmony_ci	{
1610141cc406Sopenharmony_ci	  wIndexG = i;
1611141cc406Sopenharmony_ci	  break;
1612141cc406Sopenharmony_ci	}
1613141cc406Sopenharmony_ci    }
1614141cc406Sopenharmony_ci
1615141cc406Sopenharmony_ci  for (i = 0; i < 1024; i++)
1616141cc406Sopenharmony_ci    {
1617141cc406Sopenharmony_ci      fBSum += (float) hisgram_B[i];
1618141cc406Sopenharmony_ci      fBPercent = (fBSum / CountPixels) * 100;
1619141cc406Sopenharmony_ci      if (fBPercent > 50)
1620141cc406Sopenharmony_ci	{
1621141cc406Sopenharmony_ci	  wIndexB = i;
1622141cc406Sopenharmony_ci	  break;
1623141cc406Sopenharmony_ci	}
1624141cc406Sopenharmony_ci
1625141cc406Sopenharmony_ci    }
1626141cc406Sopenharmony_ci
1627141cc406Sopenharmony_ci
1628141cc406Sopenharmony_ci  fRSum = 0.0;
1629141cc406Sopenharmony_ci
1630141cc406Sopenharmony_ci  for (i = wIndexR; i >= 0; i--)
1631141cc406Sopenharmony_ci    {
1632141cc406Sopenharmony_ci      fRSum += (float) hisgram_R[i];
1633141cc406Sopenharmony_ci      fRPercent = (fRSum / CountPixels) * 100;
1634141cc406Sopenharmony_ci      if (fRPercent >= 48)
1635141cc406Sopenharmony_ci	{
1636141cc406Sopenharmony_ci	  min_R = i;
1637141cc406Sopenharmony_ci	  break;
1638141cc406Sopenharmony_ci	}
1639141cc406Sopenharmony_ci
1640141cc406Sopenharmony_ci    }
1641141cc406Sopenharmony_ci
1642141cc406Sopenharmony_ci  fRSum = 0.0;
1643141cc406Sopenharmony_ci  for (i = wIndexR; i < 1024; i++)
1644141cc406Sopenharmony_ci    {
1645141cc406Sopenharmony_ci      fRSum += (float) hisgram_R[i];
1646141cc406Sopenharmony_ci      fRPercent = (fRSum / CountPixels) * 100;
1647141cc406Sopenharmony_ci      if (fRPercent >= 47)
1648141cc406Sopenharmony_ci	{
1649141cc406Sopenharmony_ci	  max_R = i;
1650141cc406Sopenharmony_ci	  break;
1651141cc406Sopenharmony_ci	}
1652141cc406Sopenharmony_ci
1653141cc406Sopenharmony_ci    }
1654141cc406Sopenharmony_ci
1655141cc406Sopenharmony_ci
1656141cc406Sopenharmony_ci  fGSum = 0.0;
1657141cc406Sopenharmony_ci  for (i = wIndexG; i >= 0; i--)
1658141cc406Sopenharmony_ci    {
1659141cc406Sopenharmony_ci      fGSum += (float) hisgram_G[i];
1660141cc406Sopenharmony_ci      fGPercent = (fGSum / CountPixels) * 100;
1661141cc406Sopenharmony_ci      if (fGPercent >= 48)
1662141cc406Sopenharmony_ci	{
1663141cc406Sopenharmony_ci	  min_G = i;
1664141cc406Sopenharmony_ci	  break;
1665141cc406Sopenharmony_ci	}
1666141cc406Sopenharmony_ci
1667141cc406Sopenharmony_ci    }
1668141cc406Sopenharmony_ci
1669141cc406Sopenharmony_ci  fGSum = 0.0;
1670141cc406Sopenharmony_ci  for (i = wIndexG; i < 1024; i++)
1671141cc406Sopenharmony_ci    {
1672141cc406Sopenharmony_ci      fGSum += (float) hisgram_G[i];
1673141cc406Sopenharmony_ci      fGPercent = (fGSum / CountPixels) * 100;
1674141cc406Sopenharmony_ci      if (fGPercent >= 47)
1675141cc406Sopenharmony_ci	{
1676141cc406Sopenharmony_ci	  max_G = i;
1677141cc406Sopenharmony_ci	  break;
1678141cc406Sopenharmony_ci	}
1679141cc406Sopenharmony_ci
1680141cc406Sopenharmony_ci    }
1681141cc406Sopenharmony_ci
1682141cc406Sopenharmony_ci  fBSum = 0.0;
1683141cc406Sopenharmony_ci  for (i = wIndexB; i >= 0; i--)
1684141cc406Sopenharmony_ci    {
1685141cc406Sopenharmony_ci      fBSum += (float) hisgram_B[i];
1686141cc406Sopenharmony_ci      fBPercent = (fBSum / CountPixels) * 100;
1687141cc406Sopenharmony_ci      if (fBPercent >= 46)
1688141cc406Sopenharmony_ci	{
1689141cc406Sopenharmony_ci	  min_B = i;
1690141cc406Sopenharmony_ci	  break;
1691141cc406Sopenharmony_ci	}
1692141cc406Sopenharmony_ci
1693141cc406Sopenharmony_ci    }
1694141cc406Sopenharmony_ci
1695141cc406Sopenharmony_ci  fBSum = 0.0;
1696141cc406Sopenharmony_ci  for (i = wIndexB; i < 1024; i++)
1697141cc406Sopenharmony_ci    {
1698141cc406Sopenharmony_ci      fBSum += (float) hisgram_B[i];
1699141cc406Sopenharmony_ci      fBPercent = (fBSum / CountPixels) * 100;
1700141cc406Sopenharmony_ci      if (fBPercent >= 47)
1701141cc406Sopenharmony_ci	{
1702141cc406Sopenharmony_ci	  max_B = i;
1703141cc406Sopenharmony_ci	  break;
1704141cc406Sopenharmony_ci	}
1705141cc406Sopenharmony_ci
1706141cc406Sopenharmony_ci    }
1707141cc406Sopenharmony_ci
1708141cc406Sopenharmony_ci
1709141cc406Sopenharmony_ci  /*Autolevel: */
1710141cc406Sopenharmony_ci  sum_R = max_R - min_R;
1711141cc406Sopenharmony_ci  sum_G = max_G - min_G;
1712141cc406Sopenharmony_ci  sum_B = max_B - min_B;
1713141cc406Sopenharmony_ci
1714141cc406Sopenharmony_ci  for (j = 0; j < (int) ImageHeight; j++)
1715141cc406Sopenharmony_ci    {
1716141cc406Sopenharmony_ci      tLines = j * ImageWidth * 3;
1717141cc406Sopenharmony_ci      for (i = 0; i < (int) ImageWidth; i++)
1718141cc406Sopenharmony_ci	{
1719141cc406Sopenharmony_ci	  R = *(pbmpdata + (tLines + i * 3 + 2));
1720141cc406Sopenharmony_ci	  G = *(pbmpdata + (tLines + i * 3 + 1));
1721141cc406Sopenharmony_ci	  B = *(pbmpdata + (tLines + i * 3));
1722141cc406Sopenharmony_ci
1723141cc406Sopenharmony_ci
1724141cc406Sopenharmony_ci	   /*R*/ if (sum_R == 0)
1725141cc406Sopenharmony_ci	    R = max_R;
1726141cc406Sopenharmony_ci	  else if (R < min_R)
1727141cc406Sopenharmony_ci	    {
1728141cc406Sopenharmony_ci
1729141cc406Sopenharmony_ci	      R = 0;
1730141cc406Sopenharmony_ci	    }
1731141cc406Sopenharmony_ci	  else if ((R >= min_R) && (R <= 1023))
1732141cc406Sopenharmony_ci	    {
1733141cc406Sopenharmony_ci	      fmax_R = ((float) ((R - min_R) * 923) / (float) sum_R) + 100;
1734141cc406Sopenharmony_ci	      R = (unsigned short) fmax_R;
1735141cc406Sopenharmony_ci	      fmax_R = (fmax_R - R) * 10;
1736141cc406Sopenharmony_ci	      if (fmax_R >= 5)
1737141cc406Sopenharmony_ci		R++;
1738141cc406Sopenharmony_ci	    }
1739141cc406Sopenharmony_ci	  if (R > 1023)
1740141cc406Sopenharmony_ci	    R = 1023;
1741141cc406Sopenharmony_ci
1742141cc406Sopenharmony_ci	   /*G*/ if (sum_G == 0)
1743141cc406Sopenharmony_ci	    G = max_G;
1744141cc406Sopenharmony_ci	  else if (G < min_G)
1745141cc406Sopenharmony_ci	    {
1746141cc406Sopenharmony_ci
1747141cc406Sopenharmony_ci	      G = 0;
1748141cc406Sopenharmony_ci	    }
1749141cc406Sopenharmony_ci	  else if ((G >= min_G) && (G <= 1023))
1750141cc406Sopenharmony_ci	    {
1751141cc406Sopenharmony_ci	      fmax_G = ((float) ((G - min_G) * 923) / (float) sum_G) + 100;
1752141cc406Sopenharmony_ci	      G = (unsigned short) fmax_G;
1753141cc406Sopenharmony_ci	      fmax_G = (fmax_G - G) * 10;
1754141cc406Sopenharmony_ci	      if (fmax_G >= 5)
1755141cc406Sopenharmony_ci		G++;
1756141cc406Sopenharmony_ci	    }
1757141cc406Sopenharmony_ci	  if (G > 1023)
1758141cc406Sopenharmony_ci	    G = 1023;
1759141cc406Sopenharmony_ci
1760141cc406Sopenharmony_ci	   /*B*/ if (sum_B == 0)
1761141cc406Sopenharmony_ci	    B = max_B;
1762141cc406Sopenharmony_ci	  else if (B < min_R)
1763141cc406Sopenharmony_ci	    {
1764141cc406Sopenharmony_ci
1765141cc406Sopenharmony_ci	      B = 0;
1766141cc406Sopenharmony_ci	    }
1767141cc406Sopenharmony_ci	  else if ((B >= min_B) && (R <= 1023))
1768141cc406Sopenharmony_ci	    {
1769141cc406Sopenharmony_ci	      fmax_B = ((float) (B - min_B) * 923 / (float) sum_B) + 100;
1770141cc406Sopenharmony_ci
1771141cc406Sopenharmony_ci	      B = (unsigned short) fmax_B;
1772141cc406Sopenharmony_ci	      fmax_B = (fmax_B - B) * 10;
1773141cc406Sopenharmony_ci	      if (fmax_B >= 5)
1774141cc406Sopenharmony_ci		B++;
1775141cc406Sopenharmony_ci	    }
1776141cc406Sopenharmony_ci	  if (B > 1023)
1777141cc406Sopenharmony_ci	    B = 1023;
1778141cc406Sopenharmony_ci
1779141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 2)) = R;
1780141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 1)) = G;
1781141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3)) = B;
1782141cc406Sopenharmony_ci
1783141cc406Sopenharmony_ci	}
1784141cc406Sopenharmony_ci    }
1785141cc406Sopenharmony_ci
1786141cc406Sopenharmony_ci  return;
1787141cc406Sopenharmony_ci}
1788141cc406Sopenharmony_ci#endif
1789141cc406Sopenharmony_ci
1790141cc406Sopenharmony_ci#ifdef SANE_UNUSED
1791141cc406Sopenharmony_ci/**********************************************************************
1792141cc406Sopenharmony_ciAuthor: Jack             Date: 2005/05/14
1793141cc406Sopenharmony_ciRoutine Description:
1794141cc406Sopenharmony_ci	Change the image data and deal with auto level
1795141cc406Sopenharmony_ciParameters:
1796141cc406Sopenharmony_ci	lpSource: the data of image
1797141cc406Sopenharmony_ci	scanMode: the scan mode
1798141cc406Sopenharmony_ci	ScanLines: the rows of image
1799141cc406Sopenharmony_ci	BytesPerLine: the bytes of per line
1800141cc406Sopenharmony_ciReturn value:
1801141cc406Sopenharmony_ci	none
1802141cc406Sopenharmony_ci***********************************************************************/
1803141cc406Sopenharmony_cistatic void
1804141cc406Sopenharmony_ciQBetChange (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines,
1805141cc406Sopenharmony_ci	    unsigned int BytesPerLine)
1806141cc406Sopenharmony_ci{
1807141cc406Sopenharmony_ci  unsigned short i, j;
1808141cc406Sopenharmony_ci  unsigned int tLines, TotalImgSize;
1809141cc406Sopenharmony_ci  unsigned short R1, G1, B1, R, G, B, R2, G2, B2, QBET_RGB = 0, PointF, PointB;
1810141cc406Sopenharmony_ci  unsigned short *pwRGB;
1811141cc406Sopenharmony_ci
1812141cc406Sopenharmony_ci  int k;
1813141cc406Sopenharmony_ci
1814141cc406Sopenharmony_ci  unsigned int ImageWidth = BytesPerLine / 3;
1815141cc406Sopenharmony_ci  unsigned int ImageHeight = ScanLines;
1816141cc406Sopenharmony_ci  SANE_Byte *pbmpdata = (SANE_Byte *) lpSource;
1817141cc406Sopenharmony_ci
1818141cc406Sopenharmony_ci  if (scanMode != CM_RGB24ext)
1819141cc406Sopenharmony_ci    {
1820141cc406Sopenharmony_ci      return;
1821141cc406Sopenharmony_ci    }
1822141cc406Sopenharmony_ci
1823141cc406Sopenharmony_ci
1824141cc406Sopenharmony_ci  TotalImgSize = ImageWidth * ImageHeight * 3 * 2;
1825141cc406Sopenharmony_ci  if ((pwRGB = (unsigned short *) malloc (TotalImgSize)) == NULL)
1826141cc406Sopenharmony_ci    {
1827141cc406Sopenharmony_ci      return;
1828141cc406Sopenharmony_ci    }
1829141cc406Sopenharmony_ci
1830141cc406Sopenharmony_ci
1831141cc406Sopenharmony_ci  for (j = 0; j < ImageHeight; j++)
1832141cc406Sopenharmony_ci    {
1833141cc406Sopenharmony_ci      tLines = j * ImageWidth * 3;
1834141cc406Sopenharmony_ci      for (i = 0; i < ImageWidth; i++)
1835141cc406Sopenharmony_ci	{
1836141cc406Sopenharmony_ci	  if (i == 0)
1837141cc406Sopenharmony_ci	    {
1838141cc406Sopenharmony_ci	      R1 = R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1839141cc406Sopenharmony_ci	      G1 = G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1840141cc406Sopenharmony_ci	      B1 = B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1841141cc406Sopenharmony_ci	      R2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 2));
1842141cc406Sopenharmony_ci	      G2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 1));
1843141cc406Sopenharmony_ci	      B2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3));
1844141cc406Sopenharmony_ci	    }
1845141cc406Sopenharmony_ci	  else if (i == (ImageWidth - 1))
1846141cc406Sopenharmony_ci	    {
1847141cc406Sopenharmony_ci	      R1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 2));
1848141cc406Sopenharmony_ci	      G1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 1));
1849141cc406Sopenharmony_ci	      B1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3));
1850141cc406Sopenharmony_ci	      R2 = R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1851141cc406Sopenharmony_ci	      G2 = G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1852141cc406Sopenharmony_ci	      B2 = B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1853141cc406Sopenharmony_ci	    }
1854141cc406Sopenharmony_ci	  else
1855141cc406Sopenharmony_ci	    {
1856141cc406Sopenharmony_ci	      R1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 2));
1857141cc406Sopenharmony_ci	      G1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 1));
1858141cc406Sopenharmony_ci	      B1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3));
1859141cc406Sopenharmony_ci
1860141cc406Sopenharmony_ci	      R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2));
1861141cc406Sopenharmony_ci	      G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1));
1862141cc406Sopenharmony_ci	      B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3));
1863141cc406Sopenharmony_ci
1864141cc406Sopenharmony_ci	      R2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 2));
1865141cc406Sopenharmony_ci	      G2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 1));
1866141cc406Sopenharmony_ci	      B2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3));
1867141cc406Sopenharmony_ci	    }
1868141cc406Sopenharmony_ci
1869141cc406Sopenharmony_ci	  R1 = R1 & 0x0003;
1870141cc406Sopenharmony_ci	  G1 = G1 & 0x0003;
1871141cc406Sopenharmony_ci	  B1 = B1 & 0x0003;
1872141cc406Sopenharmony_ci
1873141cc406Sopenharmony_ci	  R2 = R2 & 0x0003;
1874141cc406Sopenharmony_ci	  G2 = G2 & 0x0003;
1875141cc406Sopenharmony_ci	  B2 = B2 & 0x0003;
1876141cc406Sopenharmony_ci	  for (k = 0; k < 3; k++)
1877141cc406Sopenharmony_ci	    {
1878141cc406Sopenharmony_ci	      if (k == 0)
1879141cc406Sopenharmony_ci		{
1880141cc406Sopenharmony_ci		  PointF = R1;
1881141cc406Sopenharmony_ci		  PointB = R2;
1882141cc406Sopenharmony_ci		}
1883141cc406Sopenharmony_ci	      else if (k == 1)
1884141cc406Sopenharmony_ci		{
1885141cc406Sopenharmony_ci		  PointF = G1;
1886141cc406Sopenharmony_ci		  PointB = G2;
1887141cc406Sopenharmony_ci		}
1888141cc406Sopenharmony_ci	      else if (k == 2)
1889141cc406Sopenharmony_ci		{
1890141cc406Sopenharmony_ci		  PointF = B1;
1891141cc406Sopenharmony_ci		  PointB = B2;
1892141cc406Sopenharmony_ci		}
1893141cc406Sopenharmony_ci
1894141cc406Sopenharmony_ci	      switch (PointF)
1895141cc406Sopenharmony_ci		{
1896141cc406Sopenharmony_ci		case 0:
1897141cc406Sopenharmony_ci		case 1:
1898141cc406Sopenharmony_ci		  if (PointB == 0)
1899141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFC;
1900141cc406Sopenharmony_ci		  else if (PointB == 1)
1901141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFC;
1902141cc406Sopenharmony_ci		  else if (PointB == 2)
1903141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFD;
1904141cc406Sopenharmony_ci		  else if (PointB == 3)
1905141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFE;
1906141cc406Sopenharmony_ci		  break;
1907141cc406Sopenharmony_ci		case 2:
1908141cc406Sopenharmony_ci		  if (PointB == 0)
1909141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFD;
1910141cc406Sopenharmony_ci		  else if (PointB == 1)
1911141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFD;
1912141cc406Sopenharmony_ci		  else if (PointB == 2)
1913141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFF;
1914141cc406Sopenharmony_ci		  else if (PointB == 3)
1915141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFF;
1916141cc406Sopenharmony_ci		  break;
1917141cc406Sopenharmony_ci		case 3:
1918141cc406Sopenharmony_ci		  if (PointB == 0)
1919141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFE;
1920141cc406Sopenharmony_ci		  else if (PointB == 1)
1921141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFE;
1922141cc406Sopenharmony_ci		  else if (PointB == 2)
1923141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFF;
1924141cc406Sopenharmony_ci		  else if (PointB == 3)
1925141cc406Sopenharmony_ci		    QBET_RGB = 0xFFFF;
1926141cc406Sopenharmony_ci		  break;
1927141cc406Sopenharmony_ci		default:
1928141cc406Sopenharmony_ci		  break;
1929141cc406Sopenharmony_ci		}
1930141cc406Sopenharmony_ci
1931141cc406Sopenharmony_ci	      if (k == 0)
1932141cc406Sopenharmony_ci		{
1933141cc406Sopenharmony_ci		  R = R << 2;
1934141cc406Sopenharmony_ci		  R = R + 0x0003;
1935141cc406Sopenharmony_ci		  R = R & QBET_RGB;
1936141cc406Sopenharmony_ci		}
1937141cc406Sopenharmony_ci	      else if (k == 1)
1938141cc406Sopenharmony_ci		{
1939141cc406Sopenharmony_ci		  G = G << 2;
1940141cc406Sopenharmony_ci		  G = G + 0x0003;
1941141cc406Sopenharmony_ci		  G = G & QBET_RGB;
1942141cc406Sopenharmony_ci		}
1943141cc406Sopenharmony_ci	      else if (k == 2)
1944141cc406Sopenharmony_ci		{
1945141cc406Sopenharmony_ci		  B = B << 2;
1946141cc406Sopenharmony_ci		  B = B + 0x0003;
1947141cc406Sopenharmony_ci		  B = B & QBET_RGB;
1948141cc406Sopenharmony_ci		}
1949141cc406Sopenharmony_ci
1950141cc406Sopenharmony_ci	    }
1951141cc406Sopenharmony_ci
1952141cc406Sopenharmony_ci	  *(pwRGB + (tLines + i * 3 + 2)) = R;
1953141cc406Sopenharmony_ci	  *(pwRGB + (tLines + i * 3 + 1)) = G;
1954141cc406Sopenharmony_ci	  *(pwRGB + (tLines + i * 3)) = B;
1955141cc406Sopenharmony_ci
1956141cc406Sopenharmony_ci	}
1957141cc406Sopenharmony_ci
1958141cc406Sopenharmony_ci    }
1959141cc406Sopenharmony_ci
1960141cc406Sopenharmony_ci
1961141cc406Sopenharmony_ci  QBETDetectAutoLevel (pwRGB, ImageWidth, ImageHeight);
1962141cc406Sopenharmony_ci
1963141cc406Sopenharmony_ci
1964141cc406Sopenharmony_ci  for (j = 0; j < ImageHeight; j++)
1965141cc406Sopenharmony_ci    {
1966141cc406Sopenharmony_ci      tLines = j * ImageWidth * 3;
1967141cc406Sopenharmony_ci
1968141cc406Sopenharmony_ci      for (i = 0; i < ImageWidth; i++)
1969141cc406Sopenharmony_ci	{
1970141cc406Sopenharmony_ci	  R = *(pwRGB + (tLines + i * 3 + 2));
1971141cc406Sopenharmony_ci	  G = *(pwRGB + (tLines + i * 3 + 1));
1972141cc406Sopenharmony_ci	  B = *(pwRGB + (tLines + i * 3));
1973141cc406Sopenharmony_ci
1974141cc406Sopenharmony_ci	  R = R >> 2;
1975141cc406Sopenharmony_ci	  G = G >> 2;
1976141cc406Sopenharmony_ci
1977141cc406Sopenharmony_ci	  B = B >> 2;
1978141cc406Sopenharmony_ci	  if (R > 255)
1979141cc406Sopenharmony_ci	    R = 255;
1980141cc406Sopenharmony_ci	  if (G > 255)
1981141cc406Sopenharmony_ci	    G = 255;
1982141cc406Sopenharmony_ci	  if (B > 255)
1983141cc406Sopenharmony_ci	    B = 255;
1984141cc406Sopenharmony_ci
1985141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R;
1986141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G;
1987141cc406Sopenharmony_ci	  *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B;
1988141cc406Sopenharmony_ci
1989141cc406Sopenharmony_ci	}
1990141cc406Sopenharmony_ci
1991141cc406Sopenharmony_ci    }
1992141cc406Sopenharmony_ci
1993141cc406Sopenharmony_ci
1994141cc406Sopenharmony_ci  if (pwRGB != NULL)
1995141cc406Sopenharmony_ci    {
1996141cc406Sopenharmony_ci      free (pwRGB);
1997141cc406Sopenharmony_ci    }
1998141cc406Sopenharmony_ci
1999141cc406Sopenharmony_ci  return;
2000141cc406Sopenharmony_ci}
2001141cc406Sopenharmony_ci#endif
2002141cc406Sopenharmony_ci
2003141cc406Sopenharmony_ci/****************************** SANE API functions *****************************/
2004141cc406Sopenharmony_ci
2005141cc406Sopenharmony_ciSANE_Status
2006141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
2007141cc406Sopenharmony_ci{
2008141cc406Sopenharmony_ci  DBG_INIT ();
2009141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_init: start\n");
2010141cc406Sopenharmony_ci  DBG (DBG_ERR, "SANE Mustek USB2 backend version %d.%d build %d from %s\n",
2011141cc406Sopenharmony_ci       SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
2012141cc406Sopenharmony_ci
2013141cc406Sopenharmony_ci  num_devices = 1;		/* HOLD: only one device in this backend */
2014141cc406Sopenharmony_ci
2015141cc406Sopenharmony_ci  if (version_code != NULL)
2016141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
2017141cc406Sopenharmony_ci
2018141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_init: authorize %s null\n", authorize ? "!=" : "==");
2019141cc406Sopenharmony_ci
2020141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_init: exit\n");
2021141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2022141cc406Sopenharmony_ci}
2023141cc406Sopenharmony_ci
2024141cc406Sopenharmony_civoid
2025141cc406Sopenharmony_cisane_exit (void)
2026141cc406Sopenharmony_ci{
2027141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_exit: start\n");
2028141cc406Sopenharmony_ci
2029141cc406Sopenharmony_ci  if (devlist != NULL)
2030141cc406Sopenharmony_ci    {
2031141cc406Sopenharmony_ci      free (devlist);
2032141cc406Sopenharmony_ci      devlist = NULL;
2033141cc406Sopenharmony_ci    }
2034141cc406Sopenharmony_ci
2035141cc406Sopenharmony_ci  devlist = NULL;
2036141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_exit: exit\n");
2037141cc406Sopenharmony_ci}
2038141cc406Sopenharmony_ci
2039141cc406Sopenharmony_ciSANE_Status
2040141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
2041141cc406Sopenharmony_ci{
2042141cc406Sopenharmony_ci  SANE_Int dev_num;
2043141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_get_devices: start: local_only = %s\n",
2044141cc406Sopenharmony_ci       local_only == SANE_TRUE ? "true" : "false");
2045141cc406Sopenharmony_ci
2046141cc406Sopenharmony_ci  if (devlist != NULL)
2047141cc406Sopenharmony_ci    {
2048141cc406Sopenharmony_ci      free (devlist);
2049141cc406Sopenharmony_ci      devlist = NULL;
2050141cc406Sopenharmony_ci    }
2051141cc406Sopenharmony_ci
2052141cc406Sopenharmony_ci  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
2053141cc406Sopenharmony_ci  if (devlist == NULL)
2054141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
2055141cc406Sopenharmony_ci
2056141cc406Sopenharmony_ci  dev_num = 0;
2057141cc406Sopenharmony_ci  /* HOLD: This is ugly (only one scanner!) and should go to sane_init */
2058141cc406Sopenharmony_ci  if (GetDeviceStatus ())
2059141cc406Sopenharmony_ci    {
2060141cc406Sopenharmony_ci      SANE_Device *sane_device;
2061141cc406Sopenharmony_ci
2062141cc406Sopenharmony_ci      sane_device = malloc (sizeof (*sane_device));
2063141cc406Sopenharmony_ci      if (sane_device == NULL)
2064141cc406Sopenharmony_ci	return SANE_STATUS_NO_MEM;
2065141cc406Sopenharmony_ci      sane_device->name = strdup (device_name);
2066141cc406Sopenharmony_ci      sane_device->vendor = strdup ("Mustek");
2067141cc406Sopenharmony_ci      sane_device->model = strdup ("BearPaw 2448 TA Pro");
2068141cc406Sopenharmony_ci      sane_device->type = strdup ("flatbed scanner");
2069141cc406Sopenharmony_ci      devlist[dev_num++] = sane_device;
2070141cc406Sopenharmony_ci    }
2071141cc406Sopenharmony_ci  devlist[dev_num] = 0;
2072141cc406Sopenharmony_ci  *device_list = devlist;
2073141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_get_devices: exit\n");
2074141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2075141cc406Sopenharmony_ci}
2076141cc406Sopenharmony_ci
2077141cc406Sopenharmony_ciSANE_Status
2078141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle)
2079141cc406Sopenharmony_ci{
2080141cc406Sopenharmony_ci  Mustek_Scanner *s;
2081141cc406Sopenharmony_ci
2082141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_open: start :devicename = %s\n", devicename);
2083141cc406Sopenharmony_ci
2084141cc406Sopenharmony_ci  if (!MustScanner_Init ())
2085141cc406Sopenharmony_ci    {
2086141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2087141cc406Sopenharmony_ci    }
2088141cc406Sopenharmony_ci  if (!PowerControl (SANE_FALSE, SANE_FALSE))
2089141cc406Sopenharmony_ci    {
2090141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2091141cc406Sopenharmony_ci    }
2092141cc406Sopenharmony_ci  if (!CarriageHome ())
2093141cc406Sopenharmony_ci    {
2094141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2095141cc406Sopenharmony_ci    }
2096141cc406Sopenharmony_ci
2097141cc406Sopenharmony_ci  s = malloc (sizeof (*s));
2098141cc406Sopenharmony_ci  if (s == NULL)
2099141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
2100141cc406Sopenharmony_ci  memset (s, 0, sizeof (*s));
2101141cc406Sopenharmony_ci
2102141cc406Sopenharmony_ci  s->gamma_table = NULL;
2103141cc406Sopenharmony_ci  memcpy (&s->model, &mustek_A2nu2_model, sizeof (Scanner_Model));
2104141cc406Sopenharmony_ci  s->next = NULL;
2105141cc406Sopenharmony_ci  s->bIsScanning = SANE_FALSE;
2106141cc406Sopenharmony_ci  s->bIsReading = SANE_FALSE;
2107141cc406Sopenharmony_ci
2108141cc406Sopenharmony_ci  init_options (s);
2109141cc406Sopenharmony_ci  *handle = s;
2110141cc406Sopenharmony_ci
2111141cc406Sopenharmony_ci  s->read_rows = 0;
2112141cc406Sopenharmony_ci  s->scan_buffer_len = 0;
2113141cc406Sopenharmony_ci
2114141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_open: exit\n");
2115141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2116141cc406Sopenharmony_ci}
2117141cc406Sopenharmony_ci
2118141cc406Sopenharmony_ci
2119141cc406Sopenharmony_civoid
2120141cc406Sopenharmony_cisane_close (SANE_Handle handle)
2121141cc406Sopenharmony_ci{
2122141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2123141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_close: start\n");
2124141cc406Sopenharmony_ci
2125141cc406Sopenharmony_ci  PowerControl (SANE_FALSE, SANE_FALSE);
2126141cc406Sopenharmony_ci
2127141cc406Sopenharmony_ci  CarriageHome ();
2128141cc406Sopenharmony_ci
2129141cc406Sopenharmony_ci  if (NULL != g_pDeviceFile)
2130141cc406Sopenharmony_ci    {
2131141cc406Sopenharmony_ci      free (g_pDeviceFile);
2132141cc406Sopenharmony_ci      g_pDeviceFile = NULL;
2133141cc406Sopenharmony_ci    }
2134141cc406Sopenharmony_ci
2135141cc406Sopenharmony_ci  if (s->Scan_data_buf != NULL)
2136141cc406Sopenharmony_ci    free (s->Scan_data_buf);
2137141cc406Sopenharmony_ci
2138141cc406Sopenharmony_ci  s->Scan_data_buf = NULL;
2139141cc406Sopenharmony_ci
2140141cc406Sopenharmony_ci  free (handle);
2141141cc406Sopenharmony_ci
2142141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_close: exit\n");
2143141cc406Sopenharmony_ci}
2144141cc406Sopenharmony_ci
2145141cc406Sopenharmony_ci
2146141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
2147141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2148141cc406Sopenharmony_ci{
2149141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2150141cc406Sopenharmony_ci
2151141cc406Sopenharmony_ci  if ((unsigned) option >= NUM_OPTIONS)
2152141cc406Sopenharmony_ci    return 0;
2153141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_get_option_descriptor: option = %s (%d)\n",
2154141cc406Sopenharmony_ci       s->opt[option].name, option);
2155141cc406Sopenharmony_ci  return s->opt + option;
2156141cc406Sopenharmony_ci}
2157141cc406Sopenharmony_ci
2158141cc406Sopenharmony_ci
2159141cc406Sopenharmony_ciSANE_Status
2160141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
2161141cc406Sopenharmony_ci		     SANE_Action action, void *val, SANE_Int * info)
2162141cc406Sopenharmony_ci{
2163141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2164141cc406Sopenharmony_ci  SANE_Status status;
2165141cc406Sopenharmony_ci  SANE_Word cap;
2166141cc406Sopenharmony_ci  SANE_Int myinfo = 0;
2167141cc406Sopenharmony_ci
2168141cc406Sopenharmony_ci  DBG (DBG_FUNC,
2169141cc406Sopenharmony_ci       "sane_control_option: start: action = %s, option = %s (%d)\n",
2170141cc406Sopenharmony_ci       (action == SANE_ACTION_GET_VALUE) ? "get" : (action ==
2171141cc406Sopenharmony_ci						    SANE_ACTION_SET_VALUE) ?
2172141cc406Sopenharmony_ci       "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown",
2173141cc406Sopenharmony_ci       s->opt[option].name, option);
2174141cc406Sopenharmony_ci
2175141cc406Sopenharmony_ci
2176141cc406Sopenharmony_ci  if (info)
2177141cc406Sopenharmony_ci    *info = 0;
2178141cc406Sopenharmony_ci
2179141cc406Sopenharmony_ci  if (s->bIsScanning)
2180141cc406Sopenharmony_ci    {
2181141cc406Sopenharmony_ci      DBG (DBG_ERR, "sane_control_option: don't call this function while "
2182141cc406Sopenharmony_ci	   "scanning\n");
2183141cc406Sopenharmony_ci      return SANE_STATUS_DEVICE_BUSY;
2184141cc406Sopenharmony_ci    }
2185141cc406Sopenharmony_ci  if (option >= NUM_OPTIONS || option < 0)
2186141cc406Sopenharmony_ci    {
2187141cc406Sopenharmony_ci      DBG (DBG_ERR,
2188141cc406Sopenharmony_ci	   "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n",
2189141cc406Sopenharmony_ci	   option);
2190141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2191141cc406Sopenharmony_ci    }
2192141cc406Sopenharmony_ci
2193141cc406Sopenharmony_ci  cap = s->opt[option].cap;
2194141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (cap))
2195141cc406Sopenharmony_ci    {
2196141cc406Sopenharmony_ci      DBG (DBG_ERR, "sane_control_option: option %d is inactive\n", option);
2197141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2198141cc406Sopenharmony_ci    }
2199141cc406Sopenharmony_ci  if (action == SANE_ACTION_GET_VALUE)
2200141cc406Sopenharmony_ci    {
2201141cc406Sopenharmony_ci      switch (option)
2202141cc406Sopenharmony_ci	{
2203141cc406Sopenharmony_ci	  /* word options: */
2204141cc406Sopenharmony_ci	case OPT_NUM_OPTS:
2205141cc406Sopenharmony_ci	case OPT_RESOLUTION:
2206141cc406Sopenharmony_ci	case OPT_PREVIEW:
2207141cc406Sopenharmony_ci	case OPT_AUTO_WARMUP:
2208141cc406Sopenharmony_ci	case OPT_GAMMA_VALUE:
2209141cc406Sopenharmony_ci	case OPT_THRESHOLD:
2210141cc406Sopenharmony_ci	case OPT_TL_X:
2211141cc406Sopenharmony_ci	case OPT_TL_Y:
2212141cc406Sopenharmony_ci	case OPT_BR_X:
2213141cc406Sopenharmony_ci	case OPT_BR_Y:
2214141cc406Sopenharmony_ci	  *(SANE_Word *) val = s->val[option].w;
2215141cc406Sopenharmony_ci	  break;
2216141cc406Sopenharmony_ci	  /* string options: */
2217141cc406Sopenharmony_ci	case OPT_MODE:
2218141cc406Sopenharmony_ci	  strcpy (val, s->val[option].s);
2219141cc406Sopenharmony_ci	  break;
2220141cc406Sopenharmony_ci
2221141cc406Sopenharmony_ci	case OPT_SOURCE:
2222141cc406Sopenharmony_ci	  strcpy (val, s->val[option].s);
2223141cc406Sopenharmony_ci	  break;
2224141cc406Sopenharmony_ci	default:
2225141cc406Sopenharmony_ci	  DBG (DBG_ERR, "sane_control_option: can't get unknown option %d\n",
2226141cc406Sopenharmony_ci	       option);
2227141cc406Sopenharmony_ci	  ;
2228141cc406Sopenharmony_ci	}
2229141cc406Sopenharmony_ci    }
2230141cc406Sopenharmony_ci  else if (action == SANE_ACTION_SET_VALUE)
2231141cc406Sopenharmony_ci    {
2232141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (cap))
2233141cc406Sopenharmony_ci	{
2234141cc406Sopenharmony_ci	  DBG (DBG_ERR, "sane_control_option: option %d is not settable\n",
2235141cc406Sopenharmony_ci	       option);
2236141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2237141cc406Sopenharmony_ci	}
2238141cc406Sopenharmony_ci
2239141cc406Sopenharmony_ci      status = sanei_constrain_value (s->opt + option, val, &myinfo);
2240141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2241141cc406Sopenharmony_ci	{
2242141cc406Sopenharmony_ci	  DBG (2, "sane_control_option: sanei_constrain_value returned %s\n",
2243141cc406Sopenharmony_ci	       sane_strstatus (status));
2244141cc406Sopenharmony_ci	  return status;
2245141cc406Sopenharmony_ci	}
2246141cc406Sopenharmony_ci
2247141cc406Sopenharmony_ci      switch (option)
2248141cc406Sopenharmony_ci	{
2249141cc406Sopenharmony_ci	  /* (mostly) side-effect-free word options: */
2250141cc406Sopenharmony_ci	case OPT_RESOLUTION:
2251141cc406Sopenharmony_ci	case OPT_PREVIEW:
2252141cc406Sopenharmony_ci	case OPT_TL_X:
2253141cc406Sopenharmony_ci	case OPT_TL_Y:
2254141cc406Sopenharmony_ci	case OPT_BR_X:
2255141cc406Sopenharmony_ci	case OPT_BR_Y:
2256141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Word *) val;
2257141cc406Sopenharmony_ci	  RIE (calc_parameters (s));
2258141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2259141cc406Sopenharmony_ci	  break;
2260141cc406Sopenharmony_ci	case OPT_THRESHOLD:
2261141cc406Sopenharmony_ci	case OPT_AUTO_WARMUP:
2262141cc406Sopenharmony_ci	case OPT_GAMMA_VALUE:
2263141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Word *) val;
2264141cc406Sopenharmony_ci	  break;
2265141cc406Sopenharmony_ci	  /* side-effect-free word-array options: */
2266141cc406Sopenharmony_ci	case OPT_MODE:
2267141cc406Sopenharmony_ci	  if (s->val[option].s)
2268141cc406Sopenharmony_ci	    free (s->val[option].s);
2269141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2270141cc406Sopenharmony_ci	  if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
2271141cc406Sopenharmony_ci	    {
2272141cc406Sopenharmony_ci	      ENABLE (OPT_THRESHOLD);
2273141cc406Sopenharmony_ci	    }
2274141cc406Sopenharmony_ci	  else
2275141cc406Sopenharmony_ci	    {
2276141cc406Sopenharmony_ci	      DISABLE (OPT_THRESHOLD);
2277141cc406Sopenharmony_ci	    }
2278141cc406Sopenharmony_ci	  RIE (calc_parameters (s));
2279141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2280141cc406Sopenharmony_ci	  break;
2281141cc406Sopenharmony_ci	case OPT_SOURCE:
2282141cc406Sopenharmony_ci	  if (strcmp (s->val[option].s, val) != 0)
2283141cc406Sopenharmony_ci	    {			/* something changed */
2284141cc406Sopenharmony_ci	      if (s->val[option].s)
2285141cc406Sopenharmony_ci		free (s->val[option].s);
2286141cc406Sopenharmony_ci	      s->val[option].s = strdup (val);
2287141cc406Sopenharmony_ci	      if (strcmp (s->val[option].s, "Reflective") == 0)
2288141cc406Sopenharmony_ci		{
2289141cc406Sopenharmony_ci		  PowerControl (SANE_TRUE, SANE_FALSE);
2290141cc406Sopenharmony_ci		  s->opt[OPT_MODE].size = max_string_size (mode_list);
2291141cc406Sopenharmony_ci		  s->opt[OPT_MODE].constraint.string_list = mode_list;
2292141cc406Sopenharmony_ci		  s->val[OPT_MODE].s = strdup ("Color24");
2293141cc406Sopenharmony_ci		  x_range.max = s->model.x_size;
2294141cc406Sopenharmony_ci		  y_range.max = s->model.y_size;
2295141cc406Sopenharmony_ci		}
2296141cc406Sopenharmony_ci	      else if (0 == strcmp (s->val[option].s, "Negative"))
2297141cc406Sopenharmony_ci		{
2298141cc406Sopenharmony_ci		  PowerControl (SANE_FALSE, SANE_TRUE);
2299141cc406Sopenharmony_ci		  s->opt[OPT_MODE].size =
2300141cc406Sopenharmony_ci		    max_string_size (negative_mode_list);
2301141cc406Sopenharmony_ci		  s->opt[OPT_MODE].constraint.string_list =
2302141cc406Sopenharmony_ci		    negative_mode_list;
2303141cc406Sopenharmony_ci		  s->val[OPT_MODE].s = strdup ("Color24");
2304141cc406Sopenharmony_ci		  x_range.max = s->model.x_size_ta;
2305141cc406Sopenharmony_ci		  y_range.max = s->model.y_size_ta;
2306141cc406Sopenharmony_ci		}
2307141cc406Sopenharmony_ci	      else if (0 == strcmp (s->val[option].s, "Positive"))
2308141cc406Sopenharmony_ci		{
2309141cc406Sopenharmony_ci		  PowerControl (SANE_FALSE, SANE_TRUE);
2310141cc406Sopenharmony_ci		  s->opt[OPT_MODE].size = max_string_size (mode_list);
2311141cc406Sopenharmony_ci		  s->opt[OPT_MODE].constraint.string_list = mode_list;
2312141cc406Sopenharmony_ci		  s->val[OPT_MODE].s = strdup ("Color24");
2313141cc406Sopenharmony_ci		  x_range.max = s->model.x_size_ta;
2314141cc406Sopenharmony_ci		  y_range.max = s->model.y_size_ta;
2315141cc406Sopenharmony_ci		}
2316141cc406Sopenharmony_ci	    }
2317141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2318141cc406Sopenharmony_ci	  break;
2319141cc406Sopenharmony_ci	default:
2320141cc406Sopenharmony_ci	  DBG (DBG_ERR, "sane_control_option: can't set unknown option %d\n",
2321141cc406Sopenharmony_ci	       option);
2322141cc406Sopenharmony_ci	}
2323141cc406Sopenharmony_ci    }
2324141cc406Sopenharmony_ci  else
2325141cc406Sopenharmony_ci    {
2326141cc406Sopenharmony_ci      DBG (DBG_ERR, "sane_control_option: unknown action %d for option %d\n",
2327141cc406Sopenharmony_ci	   action, option);
2328141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2329141cc406Sopenharmony_ci    }
2330141cc406Sopenharmony_ci  if (info)
2331141cc406Sopenharmony_ci    *info = myinfo;
2332141cc406Sopenharmony_ci
2333141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_control_option: exit\n");
2334141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2335141cc406Sopenharmony_ci}
2336141cc406Sopenharmony_ci
2337141cc406Sopenharmony_ciSANE_Status
2338141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
2339141cc406Sopenharmony_ci{
2340141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2341141cc406Sopenharmony_ci
2342141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_get_parameters: start\n");
2343141cc406Sopenharmony_ci
2344141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_get_parameters :params.format = %d\n",
2345141cc406Sopenharmony_ci       s->params.format);
2346141cc406Sopenharmony_ci
2347141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_get_parameters :params.depth = %d\n", s->params.depth);
2348141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_get_parameters :params.pixels_per_line = %d\n",
2349141cc406Sopenharmony_ci       s->params.pixels_per_line);
2350141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_get_parameters :params.bytes_per_line = %d\n",
2351141cc406Sopenharmony_ci       s->params.bytes_per_line);
2352141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_get_parameters :params.lines = %d\n", s->params.lines);
2353141cc406Sopenharmony_ci  if (params != NULL)
2354141cc406Sopenharmony_ci    *params = s->params;
2355141cc406Sopenharmony_ci
2356141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_get_parameters: exit\n");
2357141cc406Sopenharmony_ci
2358141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2359141cc406Sopenharmony_ci
2360141cc406Sopenharmony_ci}
2361141cc406Sopenharmony_ci
2362141cc406Sopenharmony_ciSANE_Status
2363141cc406Sopenharmony_cisane_start (SANE_Handle handle)
2364141cc406Sopenharmony_ci{
2365141cc406Sopenharmony_ci  int i;
2366141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2367141cc406Sopenharmony_ci
2368141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_start: start\n");
2369141cc406Sopenharmony_ci
2370141cc406Sopenharmony_ci  s->scan_buffer_len = 0;
2371141cc406Sopenharmony_ci
2372141cc406Sopenharmony_ci  calc_parameters (s);
2373141cc406Sopenharmony_ci
2374141cc406Sopenharmony_ci  if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w)
2375141cc406Sopenharmony_ci    {
2376141cc406Sopenharmony_ci      DBG (DBG_CRIT,
2377141cc406Sopenharmony_ci	   "sane_start: top left x >= bottom right x --- exiting\n");
2378141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2379141cc406Sopenharmony_ci    }
2380141cc406Sopenharmony_ci  if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w)
2381141cc406Sopenharmony_ci    {
2382141cc406Sopenharmony_ci      DBG (DBG_CRIT,
2383141cc406Sopenharmony_ci	   "sane_start: top left y >= bottom right y --- exiting\n");
2384141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2385141cc406Sopenharmony_ci    }
2386141cc406Sopenharmony_ci
2387141cc406Sopenharmony_ci  s->setpara.pGammaTable = NULL;
2388141cc406Sopenharmony_ci
2389141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.x1=%d\n",
2390141cc406Sopenharmony_ci       s->setpara.fmArea.x1);
2391141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.x2=%d\n",
2392141cc406Sopenharmony_ci       s->setpara.fmArea.x2);
2393141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.y1=%d\n",
2394141cc406Sopenharmony_ci       s->setpara.fmArea.y1);
2395141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.y2=%d\n",
2396141cc406Sopenharmony_ci       s->setpara.fmArea.y2);
2397141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.pfPixelFlavor=%d\n",
2398141cc406Sopenharmony_ci       s->setpara.pfPixelFlavor);
2399141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.wLinearThreshold=%d\n",
2400141cc406Sopenharmony_ci       s->setpara.wLinearThreshold);
2401141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.wTargetDPI=%d\n",
2402141cc406Sopenharmony_ci       s->setpara.wTargetDPI);
2403141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.smScanMode=%d\n",
2404141cc406Sopenharmony_ci       s->setpara.smScanMode);
2405141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.ssScanSource =%d\n",
2406141cc406Sopenharmony_ci       s->setpara.ssScanSource);
2407141cc406Sopenharmony_ci  DBG (DBG_INFO, "Sane_start:setpara ,setpara.pGammaTable =%p\n",
2408141cc406Sopenharmony_ci       (void *) s->setpara.pGammaTable);
2409141cc406Sopenharmony_ci
2410141cc406Sopenharmony_ci  SetParameters (&s->setpara);
2411141cc406Sopenharmony_ci
2412141cc406Sopenharmony_ci  GetParameters (&s->getpara);
2413141cc406Sopenharmony_ci
2414141cc406Sopenharmony_ci  switch (s->params.format)
2415141cc406Sopenharmony_ci    {
2416141cc406Sopenharmony_ci    case SANE_FRAME_RGB:
2417141cc406Sopenharmony_ci      if (s->params.depth == 8)
2418141cc406Sopenharmony_ci
2419141cc406Sopenharmony_ci	s->params.pixels_per_line = s->getpara.dwLineByteWidth / 3;
2420141cc406Sopenharmony_ci      if (s->params.depth == 16)
2421141cc406Sopenharmony_ci	s->params.pixels_per_line = s->getpara.dwLineByteWidth / 6;
2422141cc406Sopenharmony_ci
2423141cc406Sopenharmony_ci
2424141cc406Sopenharmony_ci      break;
2425141cc406Sopenharmony_ci    case SANE_FRAME_GRAY:
2426141cc406Sopenharmony_ci      if (s->params.depth == 1)
2427141cc406Sopenharmony_ci	s->params.pixels_per_line = s->getpara.dwLineByteWidth * 8;
2428141cc406Sopenharmony_ci      if (s->params.depth == 8)
2429141cc406Sopenharmony_ci	s->params.pixels_per_line = s->getpara.dwLineByteWidth;
2430141cc406Sopenharmony_ci      if (s->params.depth == 16)
2431141cc406Sopenharmony_ci	s->params.pixels_per_line = s->getpara.dwLineByteWidth / 2;
2432141cc406Sopenharmony_ci      break;
2433141cc406Sopenharmony_ci    default:
2434141cc406Sopenharmony_ci      DBG (DBG_INFO, "sane_start: sane_params.format = %d\n",
2435141cc406Sopenharmony_ci	   s->params.format);
2436141cc406Sopenharmony_ci    }
2437141cc406Sopenharmony_ci
2438141cc406Sopenharmony_ci  s->params.bytes_per_line = s->getpara.dwLineByteWidth;
2439141cc406Sopenharmony_ci  s->params.lines = s->getpara.dwLength;
2440141cc406Sopenharmony_ci
2441141cc406Sopenharmony_ci  s->params.last_frame = TRUE;
2442141cc406Sopenharmony_ci
2443141cc406Sopenharmony_ci
2444141cc406Sopenharmony_ci  s->read_rows = s->getpara.dwLength;
2445141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_start : read_rows = %d\n", s->read_rows);
2446141cc406Sopenharmony_ci
2447141cc406Sopenharmony_ci  /*warmming up */
2448141cc406Sopenharmony_ci  if (s->val[OPT_AUTO_WARMUP].w)
2449141cc406Sopenharmony_ci    {
2450141cc406Sopenharmony_ci      for (i = 30; i > 0; i--)
2451141cc406Sopenharmony_ci	{
2452141cc406Sopenharmony_ci	  sleep (1);
2453141cc406Sopenharmony_ci	  DBG (DBG_ERR, "warming up: %d\n", i);
2454141cc406Sopenharmony_ci	}
2455141cc406Sopenharmony_ci    }
2456141cc406Sopenharmony_ci  DBG (DBG_INFO, "SCANNING ... \n");
2457141cc406Sopenharmony_ci
2458141cc406Sopenharmony_ci  s->bIsScanning = SANE_TRUE;
2459141cc406Sopenharmony_ci  if (s->Scan_data_buf != NULL)
2460141cc406Sopenharmony_ci    free (s->Scan_data_buf);
2461141cc406Sopenharmony_ci  s->Scan_data_buf = NULL;
2462141cc406Sopenharmony_ci
2463141cc406Sopenharmony_ci  s->Scan_data_buf = malloc (SCAN_BUFFER_SIZE * sizeof (SANE_Byte));
2464141cc406Sopenharmony_ci  if (s->Scan_data_buf == NULL)
2465141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
2466141cc406Sopenharmony_ci
2467141cc406Sopenharmony_ci  StartScan ();
2468141cc406Sopenharmony_ci
2469141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_start: exit\n");
2470141cc406Sopenharmony_ci
2471141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2472141cc406Sopenharmony_ci}
2473141cc406Sopenharmony_ci
2474141cc406Sopenharmony_ciSANE_Status
2475141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
2476141cc406Sopenharmony_ci	   SANE_Int * len)
2477141cc406Sopenharmony_ci{
2478141cc406Sopenharmony_ci
2479141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2480141cc406Sopenharmony_ci  static SANE_Byte *tempbuf;
2481141cc406Sopenharmony_ci  SANE_Int lines_to_read, lines_read;
2482141cc406Sopenharmony_ci  IMAGEROWS image_row;
2483141cc406Sopenharmony_ci
2484141cc406Sopenharmony_ci  int maxbuffersize = max_len;
2485141cc406Sopenharmony_ci
2486141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_read: start: max_len=%d\n", max_len);
2487141cc406Sopenharmony_ci
2488141cc406Sopenharmony_ci  if (s == NULL)
2489141cc406Sopenharmony_ci    {
2490141cc406Sopenharmony_ci      DBG (DBG_ERR, "sane_read: handle is null!\n");
2491141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2492141cc406Sopenharmony_ci    }
2493141cc406Sopenharmony_ci
2494141cc406Sopenharmony_ci  if (buf == NULL)
2495141cc406Sopenharmony_ci    {
2496141cc406Sopenharmony_ci      DBG (DBG_ERR, "sane_read: buf is null!\n");
2497141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2498141cc406Sopenharmony_ci    }
2499141cc406Sopenharmony_ci
2500141cc406Sopenharmony_ci  if (len == NULL)
2501141cc406Sopenharmony_ci    {
2502141cc406Sopenharmony_ci      DBG (DBG_ERR, "sane_read: len is null!\n");
2503141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2504141cc406Sopenharmony_ci    }
2505141cc406Sopenharmony_ci  *len = 0;
2506141cc406Sopenharmony_ci  if (!s->bIsScanning)
2507141cc406Sopenharmony_ci    {
2508141cc406Sopenharmony_ci      DBG (DBG_WARN, "sane_read: scan was cancelled, is over or has not been "
2509141cc406Sopenharmony_ci	   "initiated yet\n");
2510141cc406Sopenharmony_ci      return SANE_STATUS_CANCELLED;
2511141cc406Sopenharmony_ci    }
2512141cc406Sopenharmony_ci  DBG (DBG_DBG, "sane_read: before read data read_row=%d\n", s->read_rows);
2513141cc406Sopenharmony_ci  if (s->scan_buffer_len == 0)
2514141cc406Sopenharmony_ci    {
2515141cc406Sopenharmony_ci      if (s->read_rows > 0)
2516141cc406Sopenharmony_ci	{
2517141cc406Sopenharmony_ci	  lines_to_read = SCAN_BUFFER_SIZE / s->getpara.dwLineByteWidth;
2518141cc406Sopenharmony_ci
2519141cc406Sopenharmony_ci	  if (lines_to_read > s->read_rows)
2520141cc406Sopenharmony_ci	    lines_to_read = s->read_rows;
2521141cc406Sopenharmony_ci
2522141cc406Sopenharmony_ci	  tempbuf =
2523141cc406Sopenharmony_ci	    (SANE_Byte *) malloc (sizeof (SANE_Byte) * lines_to_read *
2524141cc406Sopenharmony_ci			     s->getpara.dwLineByteWidth + 3 * 1024 + 1);
2525141cc406Sopenharmony_ci	  memset (tempbuf, 0,
2526141cc406Sopenharmony_ci		  sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth +
2527141cc406Sopenharmony_ci		  3 * 1024 + 1);
2528141cc406Sopenharmony_ci
2529141cc406Sopenharmony_ci	  DBG (DBG_INFO, "sane_read: buffer size is %ld\n",
2530141cc406Sopenharmony_ci	       (long int) sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth +
2531141cc406Sopenharmony_ci	       3 * 1024 + 1);
2532141cc406Sopenharmony_ci
2533141cc406Sopenharmony_ci	  image_row.roRgbOrder = mustek_A2nu2_model.line_mode_color_order;
2534141cc406Sopenharmony_ci	  image_row.wWantedLineNum = lines_to_read;
2535141cc406Sopenharmony_ci	  image_row.pBuffer = (SANE_Byte *) tempbuf;
2536141cc406Sopenharmony_ci	  s->bIsReading = SANE_TRUE;
2537141cc406Sopenharmony_ci
2538141cc406Sopenharmony_ci	  if (!ReadScannedData (&image_row))
2539141cc406Sopenharmony_ci	    {
2540141cc406Sopenharmony_ci	      DBG (DBG_ERR, "sane_read: ReadScannedData error\n");
2541141cc406Sopenharmony_ci	      s->bIsReading = SANE_FALSE;
2542141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
2543141cc406Sopenharmony_ci	    }
2544141cc406Sopenharmony_ci
2545141cc406Sopenharmony_ci	  DBG (DBG_DBG, "sane_read: Finish ReadScanedData\n");
2546141cc406Sopenharmony_ci	  s->bIsReading = SANE_FALSE;
2547141cc406Sopenharmony_ci	  memset (s->Scan_data_buf, 0, SCAN_BUFFER_SIZE);
2548141cc406Sopenharmony_ci	  s->scan_buffer_len =
2549141cc406Sopenharmony_ci	    image_row.wXferedLineNum * s->getpara.dwLineByteWidth;
2550141cc406Sopenharmony_ci	  DBG (DBG_INFO, "sane_read : s->scan_buffer_len = %ld\n",
2551141cc406Sopenharmony_ci	       (long int) s->scan_buffer_len);
2552141cc406Sopenharmony_ci
2553141cc406Sopenharmony_ci	  memcpy (s->Scan_data_buf, tempbuf, s->scan_buffer_len);
2554141cc406Sopenharmony_ci
2555141cc406Sopenharmony_ci	  DBG (DBG_DBG, "sane_read :after memcpy\n");
2556141cc406Sopenharmony_ci	  free (tempbuf);
2557141cc406Sopenharmony_ci	  s->Scan_data_buf_start = s->Scan_data_buf;
2558141cc406Sopenharmony_ci	  s->read_rows -= image_row.wXferedLineNum;
2559141cc406Sopenharmony_ci
2560141cc406Sopenharmony_ci	}
2561141cc406Sopenharmony_ci      else
2562141cc406Sopenharmony_ci	{
2563141cc406Sopenharmony_ci	  DBG (DBG_FUNC, "sane_read: scan finished -- exit\n");
2564141cc406Sopenharmony_ci	  sane_cancel (handle);
2565141cc406Sopenharmony_ci	  return SANE_STATUS_EOF;
2566141cc406Sopenharmony_ci	}
2567141cc406Sopenharmony_ci    }
2568141cc406Sopenharmony_ci  if (s->scan_buffer_len == 0)
2569141cc406Sopenharmony_ci    {
2570141cc406Sopenharmony_ci      DBG (DBG_FUNC, "sane_read: scan finished -- exit\n");
2571141cc406Sopenharmony_ci      sane_cancel (handle);
2572141cc406Sopenharmony_ci      return SANE_STATUS_EOF;
2573141cc406Sopenharmony_ci    }
2574141cc406Sopenharmony_ci
2575141cc406Sopenharmony_ci
2576141cc406Sopenharmony_ci
2577141cc406Sopenharmony_ci
2578141cc406Sopenharmony_ci  lines_read =
2579141cc406Sopenharmony_ci    (maxbuffersize <
2580141cc406Sopenharmony_ci     (SANE_Int) s->scan_buffer_len) ? maxbuffersize : (SANE_Int) s->scan_buffer_len;
2581141cc406Sopenharmony_ci  DBG (DBG_DBG, "sane_read: after %d\n", lines_read);
2582141cc406Sopenharmony_ci
2583141cc406Sopenharmony_ci  *len = (SANE_Int) lines_read;
2584141cc406Sopenharmony_ci
2585141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_read : get lines_read = %d\n", lines_read);
2586141cc406Sopenharmony_ci  DBG (DBG_INFO, "sane_read : get *len = %d\n", *len);
2587141cc406Sopenharmony_ci  memcpy (buf, s->Scan_data_buf_start, lines_read);
2588141cc406Sopenharmony_ci
2589141cc406Sopenharmony_ci  s->scan_buffer_len -= lines_read;
2590141cc406Sopenharmony_ci  s->Scan_data_buf_start += lines_read;
2591141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_read: exit\n");
2592141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2593141cc406Sopenharmony_ci
2594141cc406Sopenharmony_ci}
2595141cc406Sopenharmony_ci
2596141cc406Sopenharmony_civoid
2597141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
2598141cc406Sopenharmony_ci{
2599141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2600141cc406Sopenharmony_ci  int i;
2601141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_cancel: start\n");
2602141cc406Sopenharmony_ci  if (s->bIsScanning)
2603141cc406Sopenharmony_ci    {
2604141cc406Sopenharmony_ci      s->bIsScanning = SANE_FALSE;
2605141cc406Sopenharmony_ci      if (s->read_rows > 0)
2606141cc406Sopenharmony_ci	{
2607141cc406Sopenharmony_ci	  DBG (DBG_INFO, "sane_cancel: warning: is scanning\n");
2608141cc406Sopenharmony_ci
2609141cc406Sopenharmony_ci	}
2610141cc406Sopenharmony_ci      else
2611141cc406Sopenharmony_ci	{
2612141cc406Sopenharmony_ci	  DBG (DBG_INFO, "sane_cancel: Scan finished\n");
2613141cc406Sopenharmony_ci	}
2614141cc406Sopenharmony_ci
2615141cc406Sopenharmony_ci      StopScan ();
2616141cc406Sopenharmony_ci
2617141cc406Sopenharmony_ci      CarriageHome ();
2618141cc406Sopenharmony_ci      for (i = 0; i < 20; i++)
2619141cc406Sopenharmony_ci	{
2620141cc406Sopenharmony_ci	  if (s->bIsReading == SANE_FALSE)
2621141cc406Sopenharmony_ci	    {
2622141cc406Sopenharmony_ci	      if (s->gamma_table != NULL)
2623141cc406Sopenharmony_ci		{
2624141cc406Sopenharmony_ci		  free (s->gamma_table);
2625141cc406Sopenharmony_ci		  s->gamma_table = NULL;
2626141cc406Sopenharmony_ci		  break;
2627141cc406Sopenharmony_ci		}
2628141cc406Sopenharmony_ci	    }
2629141cc406Sopenharmony_ci	  else
2630141cc406Sopenharmony_ci	    sleep (1);
2631141cc406Sopenharmony_ci	}
2632141cc406Sopenharmony_ci      if (s->Scan_data_buf != NULL)
2633141cc406Sopenharmony_ci	{
2634141cc406Sopenharmony_ci	  free (s->Scan_data_buf);
2635141cc406Sopenharmony_ci	  s->Scan_data_buf = NULL;
2636141cc406Sopenharmony_ci	  s->Scan_data_buf_start = NULL;
2637141cc406Sopenharmony_ci	}
2638141cc406Sopenharmony_ci
2639141cc406Sopenharmony_ci      s->read_rows = 0;
2640141cc406Sopenharmony_ci      s->scan_buffer_len = 0;
2641141cc406Sopenharmony_ci      memset (&s->setpara, 0, sizeof (s->setpara));
2642141cc406Sopenharmony_ci      memset (&s->getpara, 0, sizeof (s->getpara));
2643141cc406Sopenharmony_ci
2644141cc406Sopenharmony_ci    }
2645141cc406Sopenharmony_ci  else
2646141cc406Sopenharmony_ci    {
2647141cc406Sopenharmony_ci      DBG (DBG_INFO, "sane_cancel: do nothing\n");
2648141cc406Sopenharmony_ci    }
2649141cc406Sopenharmony_ci
2650141cc406Sopenharmony_ci
2651141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_cancel: exit\n");
2652141cc406Sopenharmony_ci
2653141cc406Sopenharmony_ci}
2654141cc406Sopenharmony_ci
2655141cc406Sopenharmony_ciSANE_Status
2656141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2657141cc406Sopenharmony_ci{
2658141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2659141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_set_io_mode: handle = %p, non_blocking = %s\n",
2660141cc406Sopenharmony_ci       handle, non_blocking == SANE_TRUE ? "true" : "false");
2661141cc406Sopenharmony_ci  if (!s->bIsScanning)
2662141cc406Sopenharmony_ci    {
2663141cc406Sopenharmony_ci      DBG (DBG_WARN, "sane_set_io_mode: not scanning\n");
2664141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2665141cc406Sopenharmony_ci    }
2666141cc406Sopenharmony_ci  if (non_blocking)
2667141cc406Sopenharmony_ci    return SANE_STATUS_UNSUPPORTED;
2668141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2669141cc406Sopenharmony_ci}
2670141cc406Sopenharmony_ci
2671141cc406Sopenharmony_ciSANE_Status
2672141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2673141cc406Sopenharmony_ci{
2674141cc406Sopenharmony_ci  Mustek_Scanner *s = handle;
2675141cc406Sopenharmony_ci  DBG (DBG_FUNC, "sane_get_select_fd: handle = %p, fd = %p\n", handle,
2676141cc406Sopenharmony_ci       (void *) fd);
2677141cc406Sopenharmony_ci  if (!s->bIsScanning)
2678141cc406Sopenharmony_ci    {
2679141cc406Sopenharmony_ci      DBG (DBG_WARN, "%s", "sane_get_select_fd: not scanning\n");
2680141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2681141cc406Sopenharmony_ci    }
2682141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
2683141cc406Sopenharmony_ci}
2684