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