1 /* ------------------------------------------------------------------------- */
2 /* sane - Scanner Access Now Easy.
3 coolscan.c , version 0.4.4
4
5 This file is part of the SANE package.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20 As a special exception, the authors of SANE give permission for
21 additional uses of the libraries contained in this release of SANE.
22
23 The exception is that, if you link a SANE library with other files
24 to produce an executable, this does not by itself cause the
25 resulting executable to be covered by the GNU General Public
26 License. Your use of that executable is in no way restricted on
27 account of linking the SANE library code into it.
28
29 This exception does not, however, invalidate any other reasons why
30 the executable file might be covered by the GNU General Public
31 License.
32
33 If you submit changes to SANE to the maintainers to be included in
34 a subsequent release, you agree by submitting the changes that
35 those changes may be distributed with this exception intact.
36
37 If you write modifications of your own for SANE, it is your choice
38 whether to permit this exception to apply to your modifications.
39 If you do not wish that, delete this exception notice.
40
41 This file implements a SANE backend for COOLSCAN flatbed scanners. */
42
43 /* ------------------------------------------------------------------------- */
44
45
46 /* SANE-FLOW-DIAGRAMM
47
48 - sane_init() : initialize backend, attach scanners
49 . - sane_get_devices() : query list of scanner-devices
50 . - sane_open() : open a particular scanner-device
51 . . - sane_set_io_mode : set blocking-mode
52 . . - sane_get_select_fd : get scanner-fd
53 . . - sane_get_option_descriptor() : get option information
54 . . - sane_control_option() : change option values
55 . .
56 . . - sane_start() : start image acquisition
57 . . - sane_get_parameters() : returns actual scan-parameters
58 . . - sane_read() : read image-data (from pipe)
59 . .
60 . . - sane_cancel() : cancel operation
61 . - sane_close() : close opened scanner-device
62 - sane_exit() : terminate use of backend
63 */
64
65 #ifdef _AIX
66 # include "lalloca.h" /* MUST come first for AIX! */
67 #endif
68
69 #include "../include/sane/config.h"
70 #include "lalloca.h"
71
72 #include <errno.h>
73 #include <math.h>
74 #include <fcntl.h>
75 #include <limits.h>
76 #include <signal.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80
81 #include <sys/types.h>
82 #include <unistd.h>
83
84 #include "../include/sane/sane.h"
85 #include "../include/sane/sanei.h"
86 #include "../include/sane/saneopts.h"
87 #include "../include/sane/sanei_scsi.h"
88 #include "../include/sane/sanei_debug.h"
89 #include "../include/sane/sanei_thread.h"
90
91 #include "../include/sane/sanei_config.h"
92 #define COOLSCAN_CONFIG_FILE "coolscan.conf"
93 #include "../include/sane/sanei_backend.h"
94
95 #include "coolscan.h"
96 #include "coolscan-scsidef.h"
97
98
99 #ifndef PATH_MAX
100 #define PATH_MAX 1024
101 #endif
102
103 /* ------------------------------------------------------------------------- */
104 static const SANE_Int resolution_list[] =
105 {
106 25,
107 2700, 1350, 900, 675, 540, 450, 385, 337, 300, 270, 245, 225, 207,
108 192, 180, 168, 158, 150, 142, 135, 128, 122, 117, 112, 108
109 };
110
111
112 #define coolscan_do_scsi_open(dev, fd, handler) sanei_scsi_open(dev, fd, handler)
113 #define coolscan_do_scsi_close(fd) sanei_scsi_close(fd)
114
115 #define COOLSCAN_MAX_RETRY 25
116
117
118 static SANE_Status sense_handler (int scsi_fd, unsigned char * result, void *arg);
119 static int coolscan_check_values (Coolscan_t * s);
120 static int get_internal_info (Coolscan_t *);
121 static void coolscan_get_inquiry_values (Coolscan_t *);
122 static void hexdump (int level, char *comment, unsigned char *p, int l);
123 static int swap_res (Coolscan_t * s);
124 /* --------------------------- COOLSCAN_DO_SCSI_CMD ----------------------- */
125 static int
do_scsi_cmd(int fd,unsigned char * cmd,int cmd_len,unsigned char * out,size_t out_len)126 do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len)
127 {
128 int ret;
129 size_t ol = out_len;
130
131 hexdump (20, "", cmd, cmd_len);
132
133 ret = sanei_scsi_cmd (fd, cmd, cmd_len, out, &ol);
134 if ((out_len != 0) && (out_len != ol))
135 {
136 DBG (1, "sanei_scsi_cmd: asked %lu bytes, got %lu\n",
137 (u_long) out_len, (u_long) ol);
138 }
139 if (ret)
140 {
141 DBG (1, "sanei_scsi_cmd: returning 0x%08x\n", ret);
142 }
143 DBG (10, "sanei_scsi_cmd: returning %lu bytes:\n", (u_long) ol);
144 if (out != NULL && out_len != 0)
145 hexdump (15, "", out, (out_len > 0x60) ? 0x60 : out_len);
146
147 return ret;
148 }
149
150
151 static int
request_sense_parse(unsigned char * sensed_data)152 request_sense_parse (unsigned char *sensed_data)
153 {
154 int ret, sense, asc, ascq;
155 sense = get_RS_sense_key (sensed_data);
156 asc = get_RS_ASC (sensed_data);
157 ascq = get_RS_ASCQ (sensed_data);
158
159 ret = SANE_STATUS_IO_ERROR;
160
161 switch (sense)
162 {
163 case 0x0:
164 DBG (5, "\t%d/%d/%d: Scanner ready\n", sense, asc, ascq);
165 return SANE_STATUS_GOOD;
166
167 case 0x1:
168 if ((0x37 == asc) && (0x00 == ascq)) {
169 DBG (1, "\t%d/%d/%d: Rounded Parameter\n", sense, asc, ascq);
170 ret = SANE_STATUS_GOOD;
171 }
172 else if ((0x61 == asc) && (0x02 == ascq))
173 DBG (1, "\t%d/%d/%d: Out Of Focus\n", sense, asc, ascq);
174 else
175 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
176 break;
177
178 case 0x2:
179 if ((0x4 == asc) && (0x1 == ascq)) {
180 DBG (10, "\t%d/%d/%d: Logical unit is in process of becoming ready\n",
181 sense, asc, ascq);
182 ret = SANE_STATUS_DEVICE_BUSY;
183 }
184 else if ((0x3A == asc) && (0x00 == ascq))
185 {
186 DBG (1, "\t%d/%d/%d: No Diapo inserted\n", sense, asc, ascq);
187 ret = SANE_STATUS_GOOD;
188 }
189 else if ((0x60 == asc) && (0x00 == ascq))
190 DBG (1, "\t%d/%d/%d: Lamp Failure\n", sense, asc, ascq);
191 else
192 {
193 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
194 ret = SANE_STATUS_GOOD;
195 }
196 break;
197
198 case 0x3:
199 if ((0x3b == asc) && (0xe == ascq))
200 DBG (1, "\t%d/%d/%d: Medium source element empty\n", sense, asc, ascq);
201 else if ((0x53 == asc) && (0x00 == ascq))
202 DBG (1, "\t%d/%d/%d: Media Load of Eject Failed\n", sense, asc, ascq);
203 else
204 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
205 break;
206
207 case 0x4:
208 if ((0x15 == asc) && (0x1 == ascq))
209 DBG (1, "\t%d/%d/%d: Mechanical Positioning Error\n", sense, asc, ascq);
210 else
211 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
212 break;
213
214 case 0x5:
215 if ((0x00 == asc) && (0x5 == ascq))
216 DBG (1, "\t%d/%d/%d: End-Of-Data Detected\n", sense, asc, ascq);
217 else if ((0x1a == asc) && (0x00 == ascq))
218 DBG (1, "\t%d/%d/%d: Parameter List Length Error\n", sense, asc, ascq);
219 else if ((0x20 == asc) && (0x00 == ascq))
220 DBG (1, "\t%d/%d/%d: Invalid Command Operation Code\n", sense, asc, ascq);
221 else if ((0x24 == asc) && (0x00 == ascq))
222 DBG (1, "\t%d/%d/%d: Invalid Field In CDB\n", sense, asc, ascq);
223 else if ((0x25 == asc) && (0x00 == ascq))
224 DBG (1, "\t%d/%d/%d: Logical Unit Not Supported\n", sense, asc, ascq);
225 else if ((0x26 == asc) && (0x00 == ascq))
226 DBG (1, "\t%d/%d/%d: Invalid Field in Parameter List\n", sense, asc, ascq);
227 else if ((0x2c == asc) && (0x00 == ascq))
228 DBG (1, "\t%d/%d/%d: Command Sequence Error\n", sense, asc, ascq);
229 else if ((0x39 == asc) && (0x00 == ascq))
230 DBG (1, "\t%d/%d/%d: Saving Parameters Not Supported\n", sense, asc, ascq);
231 else if ((0x3d == asc) && (0x00 == ascq))
232 DBG (1, "\t%d/%d/%d: Invalid Bits In Identify Message\n", sense, asc, ascq);
233 else
234 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
235 break;
236
237 case 0x6:
238 if ((0x29 == asc) && (0x0 == ascq))
239 DBG (1, "\t%d/%d/%d: Power On, Reset, or Bus Device Reset Occurred\n", sense, asc, ascq);
240 else if ((0x2a == asc) && (0x1 == ascq))
241 DBG (1, "\t%d/%d/%d: Mode Parameters Changed\n", sense, asc, ascq);
242 else
243 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
244 break;
245
246 case 0xb:
247 if ((0x43 == asc) && (0x0 == ascq))
248 DBG (1, "\t%d/%d/%d: Message Error\n", sense, asc, ascq);
249 else if ((0x47 == asc) && (0x0 == ascq))
250 DBG (1, "\t%d/%d/%d: SCSI Parity Error\n", sense, asc, ascq);
251 else if ((0x48 == asc) && (0x0 == ascq))
252 DBG (1, "\t%d/%d/%d: Initiator Detected Error Message Received\n", sense, asc, ascq);
253 else if ((0x49 == asc) && (0x0 == ascq))
254 DBG (1, "\t%d/%d/%d: Invalid Message Error\n", sense, asc, ascq);
255 else if ((0x4e == asc) && (0x0 == ascq))
256 DBG (1, "\t%d/%d/%d: Overlapped Commands Attempted\n", sense, asc, ascq);
257 else
258 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
259 break;
260
261 default:
262 DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq);
263 break;
264 } /* switch */
265 return ret;
266 }
267
268 /*
269 * wait_scanner should spin until TEST_UNIT_READY returns 0 (GOOD)
270 * returns 0 on success,
271 * returns -1 on error.
272 */
273 static int
wait_scanner(Coolscan_t * s)274 wait_scanner (Coolscan_t * s)
275 {
276 int ret = -1;
277 int cnt = 0;
278 DBG (10, "wait_scanner: Testing if scanner is ready\n");
279
280 while (ret != 0)
281 {
282 ret = do_scsi_cmd (s->sfd, test_unit_ready.cmd,
283 test_unit_ready.size, 0, 0);
284
285 if (ret == SANE_STATUS_DEVICE_BUSY)
286 {
287 usleep (500000); /* wait 0.5 seconds */
288 if (cnt++ > 40)
289 { /* 20 sec. max (prescan takes up to 15 sec. */
290 DBG (1, "wait_scanner: scanner does NOT get ready\n");
291 return -1;
292 }
293 }
294 else if (ret == SANE_STATUS_GOOD)
295 {
296 DBG (10, "wait_scanner: scanner is ready\n");
297 return ret;
298 }
299 else
300 {
301 DBG (1, "wait_scanner: test unit ready failed (%s)\n",
302 sane_strstatus (ret));
303 }
304 }
305 return 0;
306 }
307
308 /* ------------------------- COOLSCAN GRAB SCANNER ----------------------------- */
309
310
311 /* coolscan_grab_scanner should go through the following command sequence:
312 * TEST UNIT READY
313 * CHECK CONDITION \
314 * REQUEST SENSE > These should be handled automagically by
315 * UNIT ATTENTION / the kernel if they happen (powerup/reset)
316 * TEST UNIT READY
317 * GOOD
318 * RESERVE UNIT
319 * GOOD
320 *
321 * It is then responsible for installing appropriate signal handlers
322 * to call emergency_give_scanner() if user aborts.
323 */
324
325 static int
coolscan_grab_scanner(Coolscan_t * s)326 coolscan_grab_scanner (Coolscan_t * s)
327 {
328 int ret;
329
330 DBG (10, "grabbing scanner\n");
331
332 wait_scanner (s); /* wait for scanner ready, if not print
333 sense and return 1 */
334 ret = do_scsi_cmd (s->sfd, reserve_unit.cmd, reserve_unit.size, NULL, 0);
335 if (ret)
336 return ret;
337
338 DBG (10, "scanner reserved\n");
339 return 0;
340 }
341
342 /*
343 * Convert a size in ilu to the units expected by the scanner
344 */
345
346 static int
resDivToVal(int res_div)347 resDivToVal (int res_div)
348 {
349 if (res_div < 1 || res_div > resolution_list[0])
350 {
351 DBG (1, "Invalid resolution divisor %d \n", res_div);
352 return 2700;
353 }
354 else
355 {
356 return resolution_list[res_div];
357 }
358 }
359
360 static int
resValToDiv(int res_val)361 resValToDiv (int res_val)
362 {
363 int res_div;
364 int max_res = resolution_list[0];
365 for (res_div = 1; res_div <= max_res; res_div++)
366 {
367 if (resolution_list[res_div] == res_val)
368 break;
369 }
370 if (res_div > max_res)
371 {
372 DBG (1, "Invalid resolution value\n");
373 return 1;
374 }
375 else
376 {
377 return res_div;
378 }
379 }
380 /*
381 * use mode select to force a measurement divisor of 2700
382 */
383 static unsigned char mode_select[] =
384 {
385 MODE_SELECT, 0x10, 0, 0, 20, 0,
386 0, 0, 0, 8,
387 0, 0, 0, 0, 0, 0, 0, 1,
388 3, 6, 0, 0, 0xA, 0x8C, 0, 0};
389
390 static int
select_MUD(Coolscan_t * s)391 select_MUD (Coolscan_t * s)
392 {
393 return do_scsi_cmd (s->sfd, mode_select, 26, NULL, 0);
394 }
395
396 static int
coolscan_autofocus_LS30(Coolscan_t * s)397 coolscan_autofocus_LS30 (Coolscan_t * s)
398 {
399 int x, y;
400
401 wait_scanner(s);
402 memcpy(s->buffer, autofocusLS30.cmd, autofocusLS30.size);
403 memcpy(s->buffer+ autofocusLS30.size, autofocuspos, 9);
404
405 x = s->xmaxpix - (s->brx + s->tlx) / 2;
406 y = (s->bry + s->tly) / 2;
407
408 DBG (10, "Attempting AutoFocus at x=%d, y=%d\n", x, y);
409
410 do_scsi_cmd (s->sfd, s->buffer,
411 autofocusLS30.size + 9, NULL, 0);
412 /* Trashes when used in combination with scsi-driver AM53C974.o */
413 do_scsi_cmd (s->sfd, command_c1.cmd,
414 command_c1.size, NULL, 0);
415
416 DBG (10, "\tWaiting end of Autofocus\n");
417 wait_scanner (s);
418 DBG (10, "AutoFocused.\n");
419 return 0;
420 }
421
422 static int
coolscan_autofocus(Coolscan_t * s)423 coolscan_autofocus (Coolscan_t * s)
424 {
425 int x, y;
426
427 if(s->LS>=2)
428 { return coolscan_autofocus_LS30(s);
429 }
430
431 wait_scanner(s);
432 memcpy(s->buffer, autofocus.cmd, autofocus.size);
433
434 x = s->xmaxpix - (s->brx + s->tlx) / 2;
435 y = (s->bry + s->tly) / 2;
436
437 DBG (10, "Attempting AutoFocus at x=%d, y=%d\n", x, y);
438
439 set_AF_XPoint (s->buffer, x);
440 set_AF_YPoint (s->buffer, y);
441
442 set_AF_transferlength (s->buffer, 0); /* should be 8 !*/
443 do_scsi_cmd (s->sfd, s->buffer,
444 autofocus.size + AF_Point_length, NULL, 0);
445
446 sleep(5); /* autofocus takes a minimum of 5 sec. */
447
448 DBG (10, "\tWaiting end of Autofocus\n");
449 wait_scanner (s);
450 DBG (10, "AutoFocused.\n");
451 return 0;
452 }
453
454 /*
455 static int
456 coolscan_abort_scan (Coolscan_t * s)
457 {
458 int ret;
459
460 DBG (5, "Aborting scan...\n");
461 ret = do_scsi_cmd (s->sfd, sabort.cmd, sabort.size, NULL, 0);
462 if (ret)
463 DBG (5, "Scan Aborted\n");
464 else
465 DBG (5, "Not scanning\n");
466 return 0;
467 }
468 */
469 static int
coolscan_mode_sense(Coolscan_t * s)470 coolscan_mode_sense (Coolscan_t * s)
471 {
472 int ret, len;
473
474 DBG (10, "Mode Sense...\n");
475 len = 12;
476 set_MS_DBD (mode_sense.cmd, 1);
477 set_MS_len (mode_sense.cmd, len);
478 ret = do_scsi_cmd (s->sfd, mode_sense.cmd, mode_sense.size,
479 s->buffer, len);
480
481 if (ret == 0)
482 {
483 s->MUD = get_MS_MUD (s->buffer);
484 DBG (10, "\tMode Sensed (MUD is %d)\n", s->MUD);
485 }
486 return ret;
487 }
488
489 static int
coolscan_object_discharge(Coolscan_t * s)490 coolscan_object_discharge (Coolscan_t * s)
491 {
492 int ret;
493
494 DBG (10, "Trying to discharge object...\n");
495
496 memcpy (s->buffer, object_position.cmd, object_position.size);
497 set_OP_autofeed (s->buffer, OP_Discharge);
498 ret = do_scsi_cmd (s->sfd, s->buffer,
499 object_position.size, NULL, 0);
500 wait_scanner (s);
501 DBG (10, "Object discharged.\n");
502 return ret;
503 }
504
505 static int
coolscan_object_feed(Coolscan_t * s)506 coolscan_object_feed (Coolscan_t * s)
507 {
508 int ret;
509 DBG (10, "Trying to feed object...\n");
510 if (!s->asf)
511 {
512 DBG (10, "\tAutofeeder not present.\n");
513 return 0;
514 }
515 memcpy (s->buffer, object_position.cmd, object_position.size);
516 set_OP_autofeed (s->buffer, OP_Feed);
517 ret = do_scsi_cmd (s->sfd, s->buffer,
518 object_position.size, NULL, 0);
519 wait_scanner (s);
520 DBG (10, "Object fed.\n");
521 return ret;
522 }
523
524 /* coolscan_give_scanner should go through the following sequence:
525 * OBJECT POSITION DISCHARGE
526 * GOOD
527 * RELEASE UNIT
528 * GOOD
529 */
530 static int
coolscan_give_scanner(Coolscan_t * s)531 coolscan_give_scanner (Coolscan_t * s)
532 {
533 DBG (10, "trying to release scanner ...\n");
534 coolscan_object_discharge (s);
535 wait_scanner (s);
536 do_scsi_cmd (s->sfd, release_unit.cmd, release_unit.size, NULL, 0);
537 DBG (10, "scanner released\n");
538 return 0;
539 }
540
541
542 static int
coolscan_set_window_param_LS20(Coolscan_t * s,int prescan)543 coolscan_set_window_param_LS20 (Coolscan_t * s, int prescan)
544 {
545 unsigned char buffer_r[max_WDB_size];
546 int ret;
547
548 wait_scanner (s);
549 memset (buffer_r, '\0', max_WDB_size); /* clear buffer */
550 memcpy (buffer_r, window_descriptor_block.cmd,
551 window_descriptor_block.size); /* copy preset data */
552
553 set_WD_wid (buffer_r, WD_wid_all); /* window identifier */
554 set_WD_auto (buffer_r, s->set_auto); /* 0 or 1: don't know what it is */
555
556 set_WD_negative (buffer_r, s->negative); /* Negative/positive slide */
557
558 if (prescan)
559 {
560 set_WD_scanmode (buffer_r, WD_Prescan);
561 }
562 else
563 {
564 set_WD_scanmode (buffer_r, WD_Scan);
565
566 /* geometry */
567 set_WD_Xres (buffer_r, resDivToVal (s->x_nres)); /* x resolution in dpi */
568 set_WD_Yres (buffer_r, resDivToVal (s->y_nres)); /* y resolution in dpi */
569
570 /* the coolscan uses the upper right corner as the origin of coordinates */
571 /* xmax and ymax are given in 1200 dpi */
572 set_WD_ULX (buffer_r, (s->xmaxpix - s->brx));
573 set_WD_ULY (buffer_r, s->tly); /* upper_edge y */
574 set_WD_width (buffer_r, (s->brx - s->tlx + 1));
575 set_WD_length (buffer_r, (s->bry - s->tly + 1));
576
577 /* BTC */
578 if (s->brightness == 128)
579 {
580 set_WD_brightness (buffer_r, 0);
581 }
582 else
583 {
584 set_WD_brightness (buffer_r, s->brightness); /* brightness */
585 }
586
587 if (s->contrast == 128)
588 {
589 set_WD_contrast (buffer_r, 0);
590 }
591 else
592 {
593 set_WD_contrast (buffer_r, s->contrast); /* contrast */
594 }
595
596 /* scanmode */
597 if (s->colormode == GREYSCALE)
598 set_WD_composition (buffer_r, WD_comp_grey); /* GRAY composition */
599 else
600 set_WD_composition (buffer_r, WD_comp_rgb_full); /* RGB composition */
601
602 set_WD_dropoutcolor (buffer_r, s->dropoutcolor); /* Which color to scan with when grayscale scan */
603 set_WD_transfermode (buffer_r, WD_LineSequence);
604 set_WD_gammaselection (buffer_r, s->gammaselection); /* monitor/linear */
605
606 set_WD_shading (buffer_r, WD_Shading_ON); /* default for non-manufacturing */
607
608 if (1 == s->LS)
609 { /* Analog gamma reserved on LS-1000 */
610 set_WD_analog_gamma_R (buffer_r, 0);
611 set_WD_analog_gamma_G (buffer_r, 0);
612 set_WD_analog_gamma_R (buffer_r, 0);
613 }
614 else
615 {
616 /* Quote spec: "It is recommended that analog gamma bits 5, 4 and 3 be
617 * set to 1 (OFF) when the object type of byte 48 is positive and the
618 * gamma specification of byte 51 is linear, and to 0 (ON) in all
619 * other cases." */
620 /*
621 int foo;
622 if ((buffer_r[48] == WD_Positive) && (buffer_r[51] == WD_Linear))
623 foo = WD_Analog_Gamma_OFF;
624 else
625 foo = WD_Analog_Gamma_ON;
626 set_WD_analog_gamma_R (buffer_r, foo);
627 set_WD_analog_gamma_G (buffer_r, foo);
628 set_WD_analog_gamma_B (buffer_r, foo);
629 */
630 set_WD_analog_gamma_R (buffer_r, s->analog_gamma_r);
631 set_WD_analog_gamma_G (buffer_r, s->analog_gamma_g);
632 set_WD_analog_gamma_B (buffer_r, s->analog_gamma_b);
633 if (s->gamma_bind)
634 {
635 set_WD_LUT_R (buffer_r, 1);
636 set_WD_LUT_G (buffer_r, 1);
637 set_WD_LUT_B (buffer_r, 1);
638 }
639 else
640 {
641 set_WD_LUT_R (buffer_r, 1);
642 set_WD_LUT_G (buffer_r, 2);
643 set_WD_LUT_B (buffer_r, 3);
644 }
645 }
646 set_WD_averaging (buffer_r, s->averaging);
647
648 set_WD_brightness_R (buffer_r, s->brightness_R);
649 set_WD_brightness_G (buffer_r, s->brightness_G);
650 set_WD_brightness_B (buffer_r, s->brightness_B);
651
652 set_WD_contrast_R (buffer_r, s->contrast_R);
653 set_WD_contrast_G (buffer_r, s->contrast_G);
654 set_WD_contrast_B (buffer_r, s->contrast_B);
655
656 set_WD_exposure_R (buffer_r, s->exposure_R);
657 set_WD_exposure_G (buffer_r, s->exposure_G);
658 set_WD_exposure_B (buffer_r, s->exposure_B);
659 set_WD_shift_R (buffer_r, s->shift_R);
660 set_WD_shift_G (buffer_r, s->shift_G);
661 set_WD_shift_B (buffer_r, s->shift_B);
662
663
664 /* FIXME: LUT-[RGB] */
665 /* FIXME: stop on/off */
666 }
667
668 DBG (10, "\tx_nres=%d, y_nres=%d, upper left-x=%d, upper left-y=%d\n",
669 s->x_nres, s->y_nres, s->tlx, s->tly);
670 DBG (10, "\twindow width=%d, MUD=%d, brx=%d\n",
671 s->brx - s->tlx, s->MUD, s->brx);
672 DBG (10, "\tcolormode=%d, bits per pixel=%d\n",
673 s->colormode, s->bits_per_color);
674 DBG (10, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n",
675 s->negative, s->dropoutcolor, s->preview, s->transfermode,
676 s->gammaselection);
677
678 /* prepare SCSI-BUFFER */
679 memcpy (s->buffer, set_window.cmd, set_window.size); /* SET-WINDOW cmd */
680 memcpy ((s->buffer + set_window.size), /* add WPDB */
681 window_parameter_data_block.cmd,
682 window_parameter_data_block.size);
683 set_WPDB_wdblen ((s->buffer + set_window.size), used_WDB_size); /* set WD_len */
684 memcpy (s->buffer + set_window.size + window_parameter_data_block.size,
685 buffer_r, window_descriptor_block.size);
686
687 hexdump (15, "Window set", buffer_r, s->wdb_len);
688
689 set_SW_xferlen (s->buffer, (window_parameter_data_block.size +
690 window_descriptor_block.size));
691
692 ret = do_scsi_cmd (s->sfd, s->buffer, set_window.size +
693 window_parameter_data_block.size +
694 window_descriptor_block.size,
695 NULL, 0);
696 DBG (10, "window set.\n");
697 return ret;
698 }
699
700 static int
coolscan_set_window_param_LS30(Coolscan_t * s,int wid,int prescan)701 coolscan_set_window_param_LS30 (Coolscan_t * s, int wid, int prescan)
702 {
703 unsigned char buffer_r[max_WDB_size];
704 int ret;
705
706 wait_scanner (s);
707 memset (buffer_r, '\0', max_WDB_size); /* clear buffer */
708 memcpy (buffer_r, window_descriptor_block_LS30.cmd,
709 window_descriptor_block_LS30.size); /* copy preset data */
710
711 set_WD_wid (buffer_r, wid); /* window identifier */
712 set_WD_auto (buffer_r, s->set_auto); /* 0 or 1: don't know what it is */
713
714 /* geometry */
715 set_WD_Xres (buffer_r, resDivToVal (s->x_nres)); /* x resolution in dpi */
716 set_WD_Yres (buffer_r, resDivToVal (s->y_nres)); /* y resolution in dpi */
717
718 if (prescan)
719 {
720 set_WD_scanmode_LS30 (buffer_r, WD_Prescan);
721 set_WD_Xres (buffer_r, resDivToVal (1)); /* x res. in dpi */
722 set_WD_Yres (buffer_r, resDivToVal (1)); /* y res. in dpi */
723 buffer_r[0x29]=0x81;
724 buffer_r[0x2a]=0x04;
725 buffer_r[0x2b]=0x02;
726 buffer_r[0x2c]=0x01;
727 buffer_r[0x2d]=0xff;
728 buffer_r[0x30]=0x00;
729 buffer_r[0x31]=0x00;
730 buffer_r[0x32]=0x00;
731 buffer_r[0x33]=0x00;
732 set_WD_width (buffer_r,(2592));
733 set_WD_length (buffer_r,(3894));
734 }
735 else
736 {
737 set_WD_scanmode_LS30 (buffer_r, WD_Scan);
738
739 /* the coolscan LS-30 uses the upper left corner
740 as the origin of coordinates */
741 /* xmax and ymax are given in 1200 dpi */
742 set_WD_ULX (buffer_r, s->tlx);
743 set_WD_ULY (buffer_r, s->tly); /* upper_edge y */
744 set_WD_width (buffer_r, (s->brx - s->tlx+1));
745 set_WD_length (buffer_r, (s->bry - s->tly+1));
746
747 /* BTC */
748 if (s->brightness == 128)
749 {
750 buffer_r[0x32]=0x00;
751 }
752 else
753 {
754 buffer_r[0x32]=s->brightness; /* brightness */
755 }
756
757 if (s->contrast == 128)
758 {
759 buffer_r[0x33]=0x00;
760 }
761 else
762 {
763 buffer_r[0x33]=s->contrast; /* contrast */
764 }
765
766 /* scanmode */
767 if (s->colormode == GREYSCALE)
768 set_WD_composition (buffer_r, WD_comp_grey); /* GRAY composition */
769 else
770 set_WD_composition (buffer_r, WD_comp_rgb_full); /* RGB composition */
771
772 set_WD_composition (buffer_r, WD_comp_rgb_full); /* always RGB composition */
773
774 /* Bits per pixel */
775 set_WD_bitsperpixel(buffer_r, s->bits_per_color);
776
777 buffer_r[0x29]=0x81;
778 buffer_r[0x2a]=0x01;
779 buffer_r[0x2b]=0x02;
780 buffer_r[0x2c]=0x01;
781 buffer_r[0x2d]=0xff;
782 buffer_r[0x30]=0x00;
783
784 }
785 set_WD_negative_LS30(buffer_r, s->negative); /* Negative/positive slide */
786
787 switch(wid)
788 { case 1: set_gain_LS30(buffer_r,(s->exposure_R*s->pretv_r)/50);
789 break;
790 case 2: set_gain_LS30(buffer_r,(s->exposure_G*s->pretv_g)/50);
791 break;
792 case 3: set_gain_LS30(buffer_r,(s->exposure_B*s->pretv_b)/50);
793 break;
794 }
795
796 DBG (10, "\texpo_r=%d, expo_g=%d, expob=%d\n",
797 s->exposure_R, s->exposure_G, s->exposure_B);
798 DBG (10, "\tpre_r=%d, pre_g=%d, preb=%d\n",
799 s->pretv_r, s->pretv_g, s->pretv_b);
800 DBG (10, "\tx_nres=%d, y_nres=%d, upper left-x=%d, upper left-y=%d\n",
801 s->x_nres, s->y_nres, s->tlx, s->tly);
802 DBG (10, "\twindow width=%d, MUD=%d, brx=%d\n",
803 s->brx - s->tlx, s->MUD, s->brx);
804 DBG (10, "\tcolormode=%d, bits per pixel=%d\n",
805 s->colormode, s->bits_per_color);
806 DBG (10, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n",
807 s->negative, s->dropoutcolor, s->preview, s->transfermode,
808 s->gammaselection);
809
810 /* prepare SCSI-BUFFER */
811 memcpy (s->buffer, set_window.cmd, set_window.size); /* SET-WINDOW cmd */
812 memcpy ((s->buffer + set_window.size), /* add WPDB */
813 window_parameter_data_block.cmd,
814 window_parameter_data_block.size);
815 set_WPDB_wdblen ((s->buffer + set_window.size), used_WDB_size_LS30); /* set WD_len */
816 memcpy (s->buffer + set_window.size + window_parameter_data_block.size,
817 buffer_r, window_descriptor_block_LS30.size);
818
819 hexdump (15, "Window set", buffer_r, s->wdb_len);
820
821 set_SW_xferlen (s->buffer, (window_parameter_data_block.size +
822 window_descriptor_block_LS30.size));
823
824 ret = do_scsi_cmd (s->sfd, s->buffer, set_window.size +
825 window_parameter_data_block.size +
826 window_descriptor_block_LS30.size,
827 NULL, 0);
828 DBG (10, "window set.\n");
829 return ret;
830 }
831
832 static int
coolscan_set_window_param(Coolscan_t * s,int prescan)833 coolscan_set_window_param (Coolscan_t * s, int prescan)
834 {
835 int ret;
836 ret=0;
837 DBG (10, "set_window_param\n");
838
839 if(s->LS<2) /* distinguish between old and new scanners */
840 { ret=coolscan_set_window_param_LS20 (s,prescan);
841 }
842 else
843 { do_scsi_cmd (s->sfd,commande1.cmd,commande1.size,s->buffer,0x0d);
844 wait_scanner (s);
845 wait_scanner (s);
846 coolscan_set_window_param_LS30(s,1,prescan);
847 ret=coolscan_set_window_param_LS30(s,2,prescan);
848 ret=coolscan_set_window_param_LS30(s,3,prescan);
849 if(s->colormode&0x08)
850 { ret=coolscan_set_window_param_LS30(s,9,prescan);
851 }
852 }
853 return ret;
854 }
855
856
857 /*
858 * The only purpose of get_window is debugging. None of the return parameters
859 * is currently used.
860 */
861 static int
coolscan_get_window_param_LS30(Coolscan_t * s,int wid,int prescanok)862 coolscan_get_window_param_LS30 (Coolscan_t * s, int wid,int prescanok)
863 {
864 int translen;
865 unsigned char *buf;
866
867 DBG (10, "GET_WINDOW_PARAM\n");
868 /* wait_scanner (s); */
869
870 translen = window_parameter_data_block.size + window_descriptor_block_LS30.size;
871
872 /* prepare SCSI-BUFFER */
873 memset (s->buffer, '\0', max_WDB_size); /* clear buffer */
874
875 set_SW_xferlen (get_window.cmd, translen); /* Transfer length */
876 get_window.cmd[5]= wid; /* window identifier */
877
878 hexdump (15, "Get window cmd", get_window.cmd, get_window.size);
879 do_scsi_cmd (s->sfd, get_window.cmd, get_window.size,
880 s->buffer, translen);
881
882 buf = s->buffer + window_parameter_data_block.size;
883 hexdump (10, "Window get", buf, 117);
884
885 s->brightness = buf[0x32]; /* brightness */
886 s->contrast = buf[0x33]; /* contrast */
887 DBG (10, "\tbrightness=%d, contrast=%d\n", s->brightness, s->contrast);
888
889 /* Useful? */
890 s->bits_per_color = get_WD_bitsperpixel (buf); /* bits/pixel (8) */
891
892 DBG (10, "\tcolormode=%d, bits per pixel=%d\n",
893 s->colormode, s->bits_per_color);
894
895 if(prescanok)
896 { switch(wid)
897 { case 1: s->pretv_r = get_gain_LS30(buf);
898 break;
899 case 2: s->pretv_g = get_gain_LS30(buf);
900 break;
901 case 3: s->pretv_b = get_gain_LS30(buf);
902 break;
903 }
904 }
905
906 /* Should this one be set at all, here? */
907 s->transfermode = get_WD_transfermode (buf);
908
909 s->gammaselection = get_WD_gammaselection (buf); /* monitor/linear */
910 DBG (10, "\tpre_r=%d, pre_g=%d, preb=%d\n",
911 s->pretv_r, s->pretv_g, s->pretv_b);
912
913 DBG (5, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n",
914 s->negative, s->dropoutcolor, s->preview, s->transfermode,
915 s->gammaselection);
916
917 DBG (10, "get_window_param - return\n");
918 return 0;
919 }
920
921 /*
922 * The only purpose of get_window is debugging. None of the return parameters
923 * is currently used.
924 */
925 static int
coolscan_get_window_param_LS20(Coolscan_t * s)926 coolscan_get_window_param_LS20 (Coolscan_t * s)
927 {
928 int translen;
929 unsigned char *buf;
930
931 DBG (10, "GET_WINDOW_PARAM\n");
932 wait_scanner (s);
933
934 translen = window_parameter_data_block.size + window_descriptor_block.size;
935
936 /* prepare SCSI-BUFFER */
937 memset (s->buffer, '\0', max_WDB_size); /* clear buffer */
938
939 set_SW_xferlen (get_window.cmd, translen); /* Transfer length */
940
941 hexdump (15, "Get window cmd", get_window.cmd, get_window.size);
942 do_scsi_cmd (s->sfd, get_window.cmd, get_window.size,
943 s->buffer, translen);
944
945 buf = s->buffer + window_parameter_data_block.size;
946 hexdump (10, "Window get", buf, 117);
947
948 /* BTC */
949 s->brightness = get_WD_brightness (buf); /* brightness */
950 s->contrast = get_WD_contrast (buf); /* contrast */
951 DBG (10, "\tbrightness=%d, contrast=%d\n", s->brightness, s->contrast);
952
953 if (WD_comp_gray == get_WD_composition (buf))
954 s->colormode = GREYSCALE;
955 else
956 s->colormode = RGB;
957
958 /* Useful? */
959 s->bits_per_color = get_WD_bitsperpixel (buf); /* bits/pixel (8) */
960
961 DBG (10, "\tcolormode=%d, bits per pixel=%d\n",
962 s->colormode, s->bits_per_color);
963
964
965 s->dropoutcolor = get_WD_dropoutcolor (buf); /* Which color to scan with when grayscale scan */
966
967 /* Should this one be set at all, here? */
968 s->transfermode = get_WD_transfermode (buf);
969
970 s->gammaselection = get_WD_gammaselection (buf); /* monitor/linear */
971
972 DBG (5, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n",
973 s->negative, s->dropoutcolor, s->preview, s->transfermode,
974 s->gammaselection);
975
976 /* Should this one be set at all? */
977 s->shading = get_WD_shading (buf);
978 s->averaging = get_WD_averaging (buf);
979 DBG (10, "get_window_param - return\n");
980 return 0;
981 }
982
983 /*
984 * The only purpose of get_window is debugging. None of the return parameters
985 * is currently used.
986 */
987 static int
coolscan_get_window_param(Coolscan_t * s,int prescanok)988 coolscan_get_window_param (Coolscan_t * s, int prescanok)
989 {
990 int ret;
991 DBG (10, "get_window_param\n");
992
993 ret=0;
994 if(s->LS<2) /* distinguish between old and new scanners */
995 { ret=coolscan_get_window_param_LS20 (s);
996 }
997 else
998 {
999 ret=coolscan_get_window_param_LS30(s,1,prescanok);
1000 ret=coolscan_get_window_param_LS30(s,2,prescanok);
1001 ret=coolscan_get_window_param_LS30(s,3,prescanok);
1002 if(s->colormode&0x08)
1003 { ret=coolscan_get_window_param_LS30(s,9,prescanok);
1004 }
1005 }
1006 return ret;
1007 }
1008
1009 static int
coolscan_start_scanLS30(Coolscan_t * s)1010 coolscan_start_scanLS30 (Coolscan_t * s)
1011 { int channels;
1012 DBG (10, "starting scan\n");
1013
1014 channels=1;
1015 memcpy (s->buffer, scan.cmd, scan.size);
1016 switch(s->colormode)
1017 { case RGB:
1018 case GREYSCALE:
1019 channels=s->buffer[4]=0x03; /* window 1 */
1020 s->buffer[6]=0x01; /* window 1 */
1021 s->buffer[7]=0x02; /* window 2 */
1022 s->buffer[8]=0x03; /* window 3 */
1023
1024 break;
1025 case RGBI:
1026 channels=s->buffer[4]=0x04; /* window 1 */
1027 s->buffer[6]=0x01; /* window 1 */
1028 s->buffer[7]=0x02; /* window 2 */
1029 s->buffer[8]=0x03; /* window 3 */
1030 s->buffer[9]=0x09; /* window 3 */
1031 break;
1032 case IRED:
1033 channels=s->buffer[4]=0x01; /* window 1 */
1034 s->buffer[8]=0x09; /* window 3 */
1035 break;
1036 }
1037
1038 return do_scsi_cmd (s->sfd, s->buffer, scan.size+channels, NULL, 0);
1039 }
1040
1041 static int
coolscan_start_scan(Coolscan_t * s)1042 coolscan_start_scan (Coolscan_t * s)
1043 {
1044 DBG (10, "starting scan\n");
1045 if(s->LS>=2)
1046 { return coolscan_start_scanLS30(s);
1047 }
1048 return do_scsi_cmd (s->sfd, scan.cmd, scan.size, NULL, 0);
1049 }
1050
1051
1052 static int
prescan(Coolscan_t * s)1053 prescan (Coolscan_t * s)
1054 {
1055 int ret;
1056
1057 DBG (10, "Starting prescan...\n");
1058 if(s->LS<2)
1059 { coolscan_set_window_param (s, 1);
1060 }
1061 else
1062 {
1063 do_scsi_cmd (s->sfd,commande1.cmd,commande1.size,s->buffer,0x0d);
1064 wait_scanner (s);
1065 wait_scanner (s);
1066 coolscan_set_window_param_LS30 (s,1,1);
1067 coolscan_set_window_param_LS30 (s,2,1);
1068 coolscan_set_window_param_LS30 (s,3,1);
1069
1070 }
1071 ret = coolscan_start_scan(s);
1072
1073 sleep(8); /* prescan takes a minimum of 10 sec. */
1074 wait_scanner (s);
1075 DBG (10, "Prescan done\n");
1076 return ret;
1077 }
1078
1079 static SANE_Status
do_prescan_now(Coolscan_t * scanner)1080 do_prescan_now (Coolscan_t * scanner)
1081 {
1082
1083 DBG (10, "do_prescan_now \n");
1084 if (scanner->scanning == SANE_TRUE)
1085 return SANE_STATUS_DEVICE_BUSY;
1086
1087 if (scanner->sfd < 0)
1088 { /* first call */
1089 if (sanei_scsi_open (scanner->sane.name,
1090 &(scanner->sfd),
1091 sense_handler, 0) != SANE_STATUS_GOOD)
1092 {
1093 DBG (1, "do_prescan_now: open of %s failed:\n",
1094 scanner->sane.name);
1095 return SANE_STATUS_INVAL;
1096 }
1097 }
1098 scanner->scanning = SANE_TRUE;
1099
1100
1101 if (coolscan_check_values (scanner) != 0)
1102 { /* Verify values */
1103 DBG (1, "ERROR: invalid scan-values\n");
1104 scanner->scanning = SANE_FALSE;
1105 coolscan_give_scanner (scanner);
1106 sanei_scsi_close (scanner->sfd);
1107 scanner->sfd = -1;
1108 return SANE_STATUS_INVAL;
1109 }
1110
1111 if (coolscan_grab_scanner (scanner))
1112 {
1113 sanei_scsi_close (scanner->sfd);
1114 scanner->sfd = -1;
1115 DBG (5, "WARNING: unable to reserve scanner: device busy\n");
1116 scanner->scanning = SANE_FALSE;
1117 return SANE_STATUS_DEVICE_BUSY;
1118 }
1119
1120 prescan (scanner);
1121 if(scanner->LS<2)
1122 { get_internal_info(scanner);
1123 }
1124 coolscan_get_window_param (scanner,1);
1125 scanner->scanning = SANE_FALSE;
1126 coolscan_give_scanner (scanner);
1127 return SANE_STATUS_GOOD;
1128 }
1129
1130
1131 static int
send_one_LUT(Coolscan_t * s,SANE_Word * LUT,int reg)1132 send_one_LUT (Coolscan_t * s, SANE_Word * LUT, int reg)
1133 {
1134 int i;
1135 short lutval;
1136 short bytesperval;
1137 unsigned char *gamma, *gamma_p;
1138 unsigned short *gamma_s;
1139
1140 DBG (10, "send LUT\n");
1141
1142 if(s->LS<2)
1143 { set_S_datatype_code (send.cmd, R_user_reg_gamma);
1144 bytesperval=1;
1145 }
1146 else
1147 {
1148 send.cmd[0x02]=3;
1149 send.cmd[0x05]=1;
1150 bytesperval=2;
1151 }
1152
1153 set_S_xfer_length (send.cmd, s->lutlength*bytesperval);
1154 set_S_datatype_qual_upper (send.cmd, reg);
1155
1156 gamma = alloca (send.size + s->lutlength*2);
1157 memcpy (gamma, send.cmd, send.size);
1158 if(s->LS<2)
1159 { gamma_p = &gamma[send.size];
1160 for (i = 0; i < s->lutlength; i++)
1161 {
1162 if (LUT[i] > 255)
1163 LUT[i] = 255; /* broken gtk */
1164 *gamma_p++ = (unsigned char) LUT[i];
1165 }
1166 }
1167 else if(s->LS==2)
1168 { gamma_s = (unsigned short*)( &gamma[send.size]);
1169 for (i = 0; i < s->lutlength; i++)
1170 {
1171 if(s->negative)
1172 {
1173 lutval=(unsigned short)(LUT[(s->lutlength-i)]);
1174 }
1175 else
1176 {
1177 lutval=(unsigned short)(LUT[i]);
1178 }
1179 if (LUT[i] >= s->max_lut_val)
1180 LUT[i] = s->max_lut_val-1; /* broken gtk */
1181 if(s->low_byte_first) /* if on little endian machine: */
1182 {
1183 lutval=((lutval&0x00ff)<<8)+((lutval&0xff00)>>8); /* inverse byteorder */
1184 }
1185 *gamma_s++ = lutval;
1186 }
1187 }
1188 else if(s->LS==3)
1189 { gamma_s = (unsigned short*)( &gamma[send.size]);
1190 for (i = 0; i < s->lutlength; i++)
1191 {
1192 if(s->negative)
1193 {
1194 lutval=(unsigned short)(LUT[s->lutlength-i]);
1195 }
1196 else
1197 {
1198 lutval=(unsigned short)(LUT[i]);
1199 }
1200 if (LUT[i] >= s->max_lut_val)
1201 LUT[i] = s->max_lut_val-1; /* broken gtk */
1202 if(s->low_byte_first) /* if on little endian machine: */
1203 { lutval=((lutval&0x00ff)<<8)+((lutval&0xff00)>>8); /* inverse byteorder */
1204 }
1205 *gamma_s++ = lutval;
1206 }
1207 }
1208 return do_scsi_cmd (s->sfd, gamma, send.size + s->lutlength*bytesperval, NULL, 0);
1209 }
1210
1211
1212 static int
send_LUT(Coolscan_t * s)1213 send_LUT (Coolscan_t * s)
1214 {
1215 wait_scanner (s);
1216 if (s->gamma_bind)
1217 {
1218 send_one_LUT (s, s->gamma, S_DQ_Reg1);
1219 if(s->LS>=2)
1220 { send_one_LUT (s, s->gamma, S_DQ_Reg2);
1221 send_one_LUT (s, s->gamma, S_DQ_Reg3);
1222 if(s->colormode&0x08)
1223 { send_one_LUT (s, s->gamma, S_DQ_Reg9);
1224 }
1225
1226 }
1227 }
1228 else
1229 {
1230 send_one_LUT (s, s->gamma_r, S_DQ_Reg1);
1231 send_one_LUT (s, s->gamma_g, S_DQ_Reg2);
1232 send_one_LUT (s, s->gamma_b, S_DQ_Reg3);
1233 if(s->colormode&0x08)
1234 { send_one_LUT (s, s->gamma_r, S_DQ_Reg9);
1235 }
1236 }
1237 return 0;
1238 }
1239
1240
1241 static int
coolscan_read_data_block(Coolscan_t * s,unsigned int datatype,unsigned int length)1242 coolscan_read_data_block (Coolscan_t * s, unsigned int datatype, unsigned int length)
1243 {
1244 int r;
1245
1246 DBG (10, "read_data_block (type= %x length = %d)\n",datatype,length);
1247 /*wait_scanner(s); */
1248
1249 set_R_datatype_code (sread.cmd, datatype);
1250 sread.cmd[4]=00;
1251 sread.cmd[5]=00;
1252 set_R_xfer_length (sread.cmd, length);
1253
1254 r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, s->buffer, length);
1255 return ((r != 0) ? -1 : (int) length);
1256 }
1257
1258
1259 static void
coolscan_do_inquiry(Coolscan_t * s)1260 coolscan_do_inquiry (Coolscan_t * s)
1261 {
1262 int size;
1263
1264 DBG (10, "do_inquiry\n");
1265 memset (s->buffer, '\0', 256); /* clear buffer */
1266 size = 36; /* Hardcoded, and as specified by Nikon */
1267 /* then get inquiry with actual size */
1268 set_inquiry_return_size (inquiry.cmd, size);
1269 do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, s->buffer, size);
1270 }
1271
1272 static int
coolscan_identify_scanner(Coolscan_t * s)1273 coolscan_identify_scanner (Coolscan_t * s)
1274 {
1275 unsigned char vendor[9];
1276 unsigned char product[0x11];
1277 unsigned char version[5];
1278 unsigned char *pp;
1279 int i;
1280
1281 vendor[8] = product[0x10] = version[4] = 0;
1282 DBG (10, "identify_scanner\n");
1283 coolscan_do_inquiry (s); /* get inquiry */
1284 if (get_inquiry_periph_devtype (s->buffer) != IN_periph_devtype_scanner)
1285 {
1286 DBG (5, "identify_scanner: not a scanner\n");
1287 return 1;
1288 } /* no, continue searching */
1289
1290 coolscan_get_inquiry_values (s);
1291
1292 get_inquiry_vendor ((char *)s->buffer, (char *)vendor);
1293 get_inquiry_product ((char *)s->buffer, (char *)product);
1294 get_inquiry_version ((char *)s->buffer, (char *)version);
1295
1296 if (strncmp ("Nikon ", (char *)vendor, 8))
1297 {
1298 DBG (5, "identify_scanner: \"%s\" isn't a Nikon product\n", vendor);
1299 return 1;
1300 } /* Not a Nikon product */
1301
1302 pp = &vendor[8];
1303 vendor[8] = ' ';
1304 while (*pp == ' ')
1305 {
1306 *pp-- = '\0';
1307 }
1308
1309 pp = &product[0x10];
1310 product[0x10] = ' ';
1311 while (*(pp - 1) == ' ')
1312 {
1313 *pp-- = '\0';
1314 } /* leave one blank at the end! */
1315
1316 pp = &version[4];
1317 version[4] = ' ';
1318 while (*pp == ' ')
1319 {
1320 *pp-- = '\0';
1321 }
1322
1323 DBG (10, "Found Nikon scanner %sversion %s on device %s\n",
1324 product, version, s->devicename);
1325
1326 /* look for scanners that do not give all inquiry-informations */
1327 /* and if possible use driver-known inquiry-data */
1328 if (get_inquiry_additional_length (s->buffer) >= 0x1f)
1329 {
1330 /* Now identify full supported scanners */
1331 for (i = 0; i < known_scanners; i++)
1332 {
1333 if (!strncmp ((char *)product, scanner_str[i], strlen (scanner_str[i])))
1334 {
1335 s->LS = i;
1336 return 0;
1337 }
1338 }
1339 if (s->cont)
1340 return 0;
1341 else
1342 return 1;
1343 }
1344 else
1345 return 1;
1346 }
1347
1348 static int
pixels_per_line(Coolscan_t * s)1349 pixels_per_line (Coolscan_t * s)
1350 {
1351 int pic_dot;
1352 if(s->LS<2)
1353 { pic_dot = (s->brx - s->tlx + s->x_nres) / s->x_nres;
1354 }
1355 else
1356 { pic_dot = (s->brx - s->tlx + 1) / s->x_nres;
1357 }
1358 DBG (10, "pic_dot=%d\n", pic_dot);
1359 return pic_dot;
1360 }
1361
1362 static int
lines_per_scan(Coolscan_t * s)1363 lines_per_scan (Coolscan_t * s)
1364 {
1365 int pic_line;
1366 if(s->LS<2)
1367 { pic_line = (s->bry - s->tly + s->y_nres) / s->y_nres;
1368 }
1369 else
1370 { pic_line = (( s->bry - s->tly + 1.0 ) / s->y_nres);
1371 }
1372 DBG (10, "pic_line=%d\n", pic_line);
1373 return pic_line;
1374 }
1375
1376 static int
scan_bytes_per_line(Coolscan_t * s)1377 scan_bytes_per_line (Coolscan_t * s)
1378 { int bpl;
1379 switch(s->colormode)
1380 { case RGB:
1381 case GREYSCALE:
1382 bpl=pixels_per_line (s) * 3;
1383 if(s->bits_per_color>8) bpl=bpl*2;
1384 return bpl;
1385 break;
1386 case RGBI:
1387 case IRED:
1388 bpl=pixels_per_line (s) * 4;
1389 if(s->bits_per_color>8) bpl=bpl*2;
1390 return bpl;
1391 break;
1392 }
1393 return 0;
1394 }
1395
1396 static int
write_bytes_per_line(Coolscan_t * s)1397 write_bytes_per_line (Coolscan_t * s)
1398 { int bpl;
1399 switch(s->colormode)
1400 { case RGB:
1401 bpl=pixels_per_line (s) * 3;
1402 if(s->bits_per_color>8) bpl=bpl*2;
1403 return bpl;
1404 break;
1405 case RGBI:
1406 bpl=pixels_per_line (s) * 4;
1407 if(s->bits_per_color>8) bpl=bpl*2;
1408 return bpl;
1409 break;
1410 case IRED:
1411 case GREYSCALE:
1412 bpl= pixels_per_line (s) ;
1413 if(s->bits_per_color>8) bpl=bpl*2;
1414 return bpl;
1415 break;
1416 }
1417 return 0;
1418 }
1419
1420
1421 static void
coolscan_trim_rowbufsize(Coolscan_t * s)1422 coolscan_trim_rowbufsize (Coolscan_t * s)
1423 {
1424 unsigned int row_len;
1425 row_len = scan_bytes_per_line (s);
1426 s->row_bufsize = (s->row_bufsize < row_len) ? s->row_bufsize
1427 : s->row_bufsize - (s->row_bufsize % row_len);
1428 DBG (10, "trim_bufsize to %d\n", s->row_bufsize);
1429 }
1430
1431 static int
coolscan_check_values(Coolscan_t * s)1432 coolscan_check_values (Coolscan_t * s)
1433 {
1434 DBG (10, "check_values\n");
1435 /* -------------------------- asf --------------------------------- */
1436 if (s->asf != 0)
1437 {
1438 if (s->autofeeder == 0)
1439 {
1440 DBG (1, "ERROR: ASF-MODE NOT SUPPORTED BY SCANNER, ABORTING\n");
1441 return (1);
1442 }
1443 }
1444
1445 return (0);
1446 }
1447
1448 /* test_little_endian */
1449
1450 static SANE_Bool
coolscan_test_little_endian(void)1451 coolscan_test_little_endian(void)
1452 {
1453 SANE_Int testvalue = 255;
1454 unsigned char *firstbyte = (unsigned char *) &testvalue;
1455
1456 if (*firstbyte == 255)
1457 { return SANE_TRUE;
1458 }
1459 return SANE_FALSE;
1460 }
1461
1462 static int
get_inquiery_part_LS30(Coolscan_t * s,unsigned char part)1463 get_inquiery_part_LS30 (Coolscan_t * s, unsigned char part)
1464 {
1465 int size;
1466
1467 /* Get length of response */
1468 inquiry.cmd[1]=0x01;
1469 inquiry.cmd[2]=part;
1470 size=4;
1471 set_inquiry_return_size (inquiry.cmd, size);
1472 do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size,
1473 s->buffer, size);
1474 size=get_inquiry_length(s->buffer);
1475 size+=4;
1476 /* then get inquiry with actual size */
1477 set_inquiry_return_size (inquiry.cmd, size);
1478 do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size,
1479 s->buffer, size);
1480 return size;
1481 }
1482
1483 static int
coolscan_read_var_data_block(Coolscan_t * s,int datatype)1484 coolscan_read_var_data_block (Coolscan_t * s,int datatype)
1485 {
1486 int r;
1487 int size;
1488
1489 DBG (10, "read_data_block (type= %x)\n",datatype);
1490 /*wait_scanner(s); */
1491
1492 sread.cmd[2]=datatype;
1493 sread.cmd[4]=00;
1494 sread.cmd[5]=03;
1495 size=6;
1496 set_R_xfer_length (sread.cmd, size);
1497 r = do_scsi_cmd (s->sfd, sread.cmd, sread.size,
1498 s->buffer, size);
1499 size=s->buffer[5];
1500 set_R_xfer_length (sread.cmd, size);
1501 r = do_scsi_cmd (s->sfd, sread.cmd, sread.size,
1502 s->buffer, size);
1503 return ((r != 0) ? -1 : size);
1504 }
1505
1506 static int
get_inquiery_LS30(Coolscan_t * s)1507 get_inquiery_LS30 (Coolscan_t * s)
1508 {
1509 unsigned char part;
1510 unsigned char parts[5];
1511 int i;
1512
1513 /* Get vector of inquiery parts */
1514 get_inquiery_part_LS30(s, (unsigned char) 0);
1515 /* Get the parts of inquiery */
1516 for(i=0;i<5;i++)
1517 { parts[i]=((unsigned char *)s->buffer)[4+11+i];
1518 }
1519 for(i=0;i<5;i++)
1520 { part=parts[i];
1521 get_inquiery_part_LS30 (s, part);
1522 switch(part)
1523 { case 0x0c1:/* max size and resolution */
1524 s->adbits = 8;
1525 s->outputbits = 8;
1526 s->maxres = getnbyte(s->buffer+0x12,2)-1;
1527 s->xmaxpix = getnbyte(s->buffer+0x53,2)-1;
1528 s->ymaxpix = getnbyte(s->buffer+0x3c,2)-1;
1529 break;
1530 case 0x0d1:
1531 break;
1532 case 0x0e1:
1533 break;
1534 case 0x0f0:
1535 break;
1536 case 0x0f8:
1537 break;
1538 }
1539 }
1540
1541 /* get windows */
1542 coolscan_get_window_param_LS30 (s,0,0);
1543 s->xmax = get_WD_width(s->buffer);
1544 s->ymax = get_WD_length(s->buffer);
1545 coolscan_get_window_param_LS30 (s,1,0);
1546 coolscan_get_window_param_LS30 (s,2,0);
1547 coolscan_get_window_param_LS30 (s,3,0);
1548 coolscan_get_window_param_LS30 (s,4,0);
1549 coolscan_get_window_param_LS30 (s,9,0);
1550
1551 s->analoggamma = 0;
1552 return 1;
1553 }
1554
1555 static int
get_feeder_type_LS30(Coolscan_t * s)1556 get_feeder_type_LS30 (Coolscan_t * s)
1557 {
1558 int size;
1559 unsigned char *ptr;
1560 int ima;
1561
1562 /* find out about Film-strip-feeder or Mount-Feeder */
1563 size=get_inquiery_part_LS30(s, (unsigned char) 1);
1564 if(strncmp((char *)s->buffer+5,"Strip",5)==0)
1565 { s->feeder=STRIP_FEEDER;
1566 s->autofeeder = 1;
1567 }
1568 if(strncmp((char *)s->buffer+5,"Mount",5)==0)
1569 { s->feeder=MOUNT_FEEDER;
1570 }
1571 /* find out about Film-strip-feeder positions*/
1572 if(s->feeder==STRIP_FEEDER)
1573 { size=coolscan_read_var_data_block (s,(int)0x88);
1574 if(size>=4)
1575 { s->numima=s->buffer[3];
1576 if(s->numima>6) s->numima=6; /* limit to 6 images for now */
1577 if(s->numima>(size-4)/16) s->numima=(size-4)/16;
1578 ptr=s->buffer+4;
1579 for(ima=0;ima<s->numima;ima++)
1580 { s->ipos[ima].start=getnbyte(ptr,4);
1581 s->ipos[ima].offset=getnbyte(ptr+4,4);
1582 s->ipos[ima].end=getnbyte(ptr+8,4);
1583 s->ipos[ima].height=getnbyte(ptr+12,4);
1584 ptr+=16;
1585 }
1586 }
1587 s->posima=0;
1588 }
1589 return 1;
1590 }
1591
1592
1593 static int
get_internal_info_LS20(Coolscan_t * s)1594 get_internal_info_LS20 (Coolscan_t * s)
1595 {
1596 int ret;
1597
1598 DBG (10, "get_internal_info\n");
1599 wait_scanner (s);
1600 memset (s->buffer, '\0', DI_length); /* clear buffer */
1601
1602 set_R_datatype_code (sread.cmd, R_device_internal_info);
1603 set_R_datatype_qual_upper (sread.cmd, R_DQ_none);
1604 set_R_xfer_length (sread.cmd, DI_length);
1605 /* then get inquiry with actual size */
1606 ret = do_scsi_cmd (s->sfd, sread.cmd, sread.size,
1607 s->buffer, DI_length);
1608
1609 s->adbits = get_DI_ADbits (s->buffer);
1610 s->outputbits = get_DI_Outputbits (s->buffer);
1611 s->maxres = get_DI_MaxResolution (s->buffer);
1612 s->xmax = get_DI_Xmax (s->buffer);
1613 s->ymax = get_DI_Ymax (s->buffer);
1614 s->xmaxpix = get_DI_Xmaxpixel (s->buffer);
1615 s->ymaxpix = get_DI_Ymaxpixel (s->buffer);
1616 s->ycurrent = get_DI_currentY (s->buffer);
1617 s->currentfocus = get_DI_currentFocus (s->buffer);
1618 s->currentscanpitch = get_DI_currentscanpitch (s->buffer);
1619 s->autofeeder = get_DI_autofeeder (s->buffer);
1620 s->analoggamma = get_DI_analoggamma (s->buffer);
1621 s->derr[0] = get_DI_deviceerror0 (s->buffer);
1622 s->derr[1] = get_DI_deviceerror1 (s->buffer);
1623 s->derr[2] = get_DI_deviceerror2 (s->buffer);
1624 s->derr[3] = get_DI_deviceerror3 (s->buffer);
1625 s->derr[4] = get_DI_deviceerror4 (s->buffer);
1626 s->derr[5] = get_DI_deviceerror5 (s->buffer);
1627 s->derr[6] = get_DI_deviceerror6 (s->buffer);
1628 s->derr[7] = get_DI_deviceerror7 (s->buffer);
1629 s->wbetr_r = get_DI_WBETR_R (s->buffer);
1630 s->webtr_g = get_DI_WBETR_G (s->buffer);
1631 s->webtr_b = get_DI_WBETR_B (s->buffer);
1632 s->pretv_r = get_DI_PRETV_R (s->buffer);
1633 s->pretv_g = get_DI_PRETV_G (s->buffer);
1634 s->pretv_r = get_DI_PRETV_R (s->buffer);
1635 s->cetv_r = get_DI_CETV_R (s->buffer);
1636 s->cetv_g = get_DI_CETV_G (s->buffer);
1637 s->cetv_b = get_DI_CETV_B (s->buffer);
1638 s->ietu_r = get_DI_IETU_R (s->buffer);
1639 s->ietu_g = get_DI_IETU_G (s->buffer);
1640 s->ietu_b = get_DI_IETU_B (s->buffer);
1641 s->limitcondition = get_DI_limitcondition (s->buffer);
1642 s->offsetdata_r = get_DI_offsetdata_R (s->buffer);
1643 s->offsetdata_g = get_DI_offsetdata_G (s->buffer);
1644 s->offsetdata_b = get_DI_offsetdata_B (s->buffer);
1645 get_DI_poweron_errors (s->buffer, s->power_on_errors);
1646
1647 DBG (10,
1648 "\tadbits=%d\toutputbits=%d\tmaxres=%d\txmax=%d\tymax=%d\n"
1649 "\txmaxpix=%d\tymaxpix=%d\tycurrent=%d\tcurrentfocus=%d\n"
1650 "\tautofeeder=%s\tanaloggamma=%s\tcurrentscanpitch=%d\n",
1651 s->adbits, s->outputbits, s->maxres, s->xmax, s->ymax,
1652 s->xmaxpix, s->ymaxpix, s->ycurrent, s->currentfocus,
1653 s->autofeeder ? "Yes" : "No", s->analoggamma ? "Yes" : "No",
1654 s->currentscanpitch);
1655 DBG (10,
1656 "\tWhite balance exposure time var [RGB]=\t%d %d %d\n"
1657 "\tPrescan result exposure time var [RGB]=\t%d %d %d\n"
1658 "\tCurrent exposure time var.[RGB]=\t%d %d %d\n"
1659 "\tInternal exposure time unit[RGB]=\t%d %d %d\n",
1660 s->wbetr_r, s->webtr_g, s->webtr_b, s->pretv_r, s->pretv_g,
1661 s->pretv_r, s->cetv_r, s->cetv_g, s->cetv_b, s->ietu_r,
1662 s->ietu_g, s->ietu_b);
1663 DBG (10,
1664 "\toffsetdata_[rgb]=\t0x%x 0x%x 0x%x\n"
1665 "\tlimitcondition=0x%x\n"
1666 "\tdevice error code = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n"
1667 "\tpower-on errors = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1668 s->offsetdata_r, s->offsetdata_g, s->offsetdata_b,
1669 s->limitcondition,
1670 s->derr[0], s->derr[1], s->derr[2], s->derr[3], s->derr[4],
1671 s->derr[5], s->derr[6], s->derr[7],
1672 s->power_on_errors[0], s->power_on_errors[1],
1673 s->power_on_errors[2], s->power_on_errors[3],
1674 s->power_on_errors[4], s->power_on_errors[5],
1675 s->power_on_errors[6], s->power_on_errors[7]);
1676
1677 return ret;
1678 }
1679
1680 static int
get_internal_info(Coolscan_t * s)1681 get_internal_info (Coolscan_t * s)
1682 {
1683 int ret;
1684
1685 DBG (10, "get_internal_info\n");
1686
1687 if(s->LS<2) /* distinguish between old and new scanners */
1688 { ret=get_internal_info_LS20 (s);
1689 }
1690 else
1691 { ret=get_inquiery_LS30 (s);
1692 }
1693 return ret;
1694 }
1695
1696 static void
coolscan_get_inquiry_values(Coolscan_t * s)1697 coolscan_get_inquiry_values (Coolscan_t * s)
1698 {
1699 unsigned char *inquiry_block;
1700
1701 DBG (10, "get_inquiry_values\n");
1702
1703 inquiry_block = (unsigned char *) s->buffer;
1704 s->inquiry_len = 36;
1705
1706 get_inquiry_vendor ((char *)inquiry_block, (char *)s->vendor);
1707 s->vendor[8] = '\0';
1708 get_inquiry_product ((char *)inquiry_block, (char *)s->product);
1709 s->product[16] = '\0';
1710 get_inquiry_version ((char *)inquiry_block, (char *)s->version);
1711 s->version[4] = '\0';
1712
1713 if (s->inquiry_len < 36)
1714 {
1715 DBG (1, "WARNING: inquiry return block is unexpected short (%d instead of 36).\n", s->inquiry_len);
1716 }
1717 s->inquiry_wdb_len = 117;
1718 return;
1719 }
1720
1721 static void
coolscan_initialize_values(Coolscan_t * s)1722 coolscan_initialize_values (Coolscan_t * s)
1723 {
1724 int i;
1725 DBG (10, "initialize_values\n");
1726 /* Initialize us structure */
1727 if(s->LS<2) /* LS-20 or LS-10000 */
1728 { select_MUD (s); /* must be before mode_sense - not for LS-30*/
1729 coolscan_mode_sense (s); /* Obtain MUD (Measurement Unit Divisor) */
1730 get_internal_info (s); /* MUST be called first. */
1731 s->wdb_len = 117;
1732 }
1733 if(s->LS>=2) /* LS-30 */
1734 {
1735 get_inquiery_LS30(s); /* Info about scanner*/
1736 select_MUD (s); /* must be before mode_sense */
1737 get_feeder_type_LS30(s);
1738 s->wdb_len = 117;
1739 }
1740
1741 s->cont = 0; /* do not continue if scanner is unknown */
1742 s->verbose = 2; /* 1=verbose,2=very verbose */
1743
1744
1745 s->x_nres = s->y_nres = 2; /* 2 => 1350 dpi */
1746 s->x_p_nres = s->y_p_nres = 9; /* 9 => 300 dpi */
1747 s->tlx = 0;
1748 s->tly = 0;
1749 s->brx = s->xmaxpix; /* 2700 / 1200; */
1750 s->bry = s->ymaxpix; /* 2700 / 1200; */
1751
1752
1753 s->set_auto = 0; /* Always 0 on Nikon LS-{100|2}0 */
1754 s->preview = 0; /* 1 for preview */
1755 s->colormode = RGB; /* GREYSCALE or RGB */
1756 s->colormode_p = RGB; /* GREYSCALE or RGB for preview*/
1757 s->asf = 0; /* 1 if asf shall be used */
1758 s->gammaselection = WD_Linear;
1759
1760 s->brightness = 128;
1761 s->brightness_R = 128;
1762 s->brightness_G = 128;
1763 s->brightness_B = 128;
1764 s->contrast = 128;
1765 s->contrast_R = 128;
1766 s->contrast_G = 128;
1767 s->contrast_B = 128;
1768
1769 s->exposure_R = 50;
1770 s->exposure_G = 50;
1771 s->exposure_B = 50;
1772
1773 s->pretv_r=40000;
1774 s->pretv_g=40000;
1775 s->pretv_b=40000;
1776
1777 s->shift_R = 128;
1778 s->shift_G = 128;
1779 s->shift_B = 128;
1780
1781 s->ired_red=60;
1782 s->ired_green=1;
1783 s->ired_blue=1;
1784
1785 s->prescan = 1;
1786 s->bits_per_color = 8;
1787 s->rgb_control = 0;
1788 s->gamma_bind = 1;
1789 switch(s->LS)
1790 { case 0:s->lutlength=2048;
1791 s->max_lut_val=256;
1792 break;
1793 case 1:s->lutlength=512;
1794 s->max_lut_val=512;
1795 break;
1796 case 2:s->lutlength=1024;
1797 s->max_lut_val=1024;
1798 break;
1799 case 3:s->lutlength=4096;
1800 s->max_lut_val=4096;
1801 break;
1802 }
1803 for (i = 0; i < s->lutlength; i++)
1804 {
1805 s->gamma[i] =((short)((((double)i)/s->lutlength)*s->max_lut_val));
1806 s->gamma_r[i] = s->gamma[i];
1807 s->gamma_g[i] = s->gamma[i];
1808 s->gamma_b[i] = s->gamma[i];
1809 }
1810
1811 if (coolscan_test_little_endian() == SANE_TRUE)
1812 {
1813 s->low_byte_first = 1; /* in 2 byte mode send lowbyte first */
1814 DBG(10,"backend runs on little endian machine\n");
1815 }
1816 else
1817 {
1818 s->low_byte_first = 0; /* in 2 byte mode send highbyte first */
1819 DBG(10,"backend runs on big endian machine\n");
1820 }
1821 }
1822
1823 static void
hexdump(int level,char * comment,unsigned char * p,int l)1824 hexdump (int level, char *comment, unsigned char *p, int l)
1825 {
1826 int i;
1827 char line[128];
1828 char *ptr;
1829
1830 DBG (level, "%s\n", comment);
1831 ptr = line;
1832 for (i = 0; i < l; i++, p++)
1833 {
1834 if ((i % 16) == 0)
1835 {
1836 if (ptr != line)
1837 {
1838 *ptr = '\0';
1839 DBG (level, "%s\n", line);
1840 ptr = line;
1841 }
1842 sprintf (ptr, "%3.3d:", i);
1843 ptr += 4;
1844 }
1845 sprintf (ptr, " %2.2x", *p);
1846 ptr += 3;
1847 }
1848 *ptr = '\0';
1849 DBG (level, "%s\n", line);
1850 }
1851
1852
1853 static SANE_Status
sense_handler(int scsi_fd,unsigned char * result,void * arg)1854 sense_handler (int scsi_fd, unsigned char * result, void *arg)
1855 {
1856 (void) scsi_fd;
1857 (void) arg;
1858
1859 if (result[0] != 0x70)
1860 {
1861 return SANE_STATUS_IO_ERROR; /* we only know about this one */
1862 }
1863 return request_sense_parse(result);
1864
1865 }
1866
1867
1868 /* ------------------------------------------------------------------------- */
1869
1870
1871 /* ilu per mm */
1872
1873 #define length_quant SANE_UNFIX(SANE_FIX(MM_PER_INCH / 2700.0))
1874 #define mmToIlu(mm) ((mm) / length_quant)
1875 #define iluToMm(ilu) ((ilu) * length_quant)
1876
1877 #define P_200_TO_255(per) SANE_UNFIX((per + 100) * 255/200 )
1878 #define P_100_TO_255(per) SANE_UNFIX(per * 255/100 )
1879
1880 static const char negativeStr[] = "Negative";
1881 static const char positiveStr[] = "Positive";
1882 static SANE_String_Const type_list[] =
1883 {
1884 positiveStr,
1885 negativeStr,
1886 0
1887 };
1888
1889 static const char colorStr[] = SANE_VALUE_SCAN_MODE_COLOR;
1890 static const char grayStr[] = SANE_VALUE_SCAN_MODE_GRAY;
1891 static const char rgbiStr[] = "RGBI";
1892 static const char iredStr[] = "Infrared";
1893
1894 static SANE_String_Const scan_mode_list_LS20[] =
1895 {
1896 colorStr,
1897 grayStr,
1898 NULL
1899 };
1900
1901 static SANE_String_Const scan_mode_list_LS30[] =
1902 {
1903 colorStr,
1904 grayStr,
1905 #ifdef HAS_IRED
1906 rgbiStr,
1907 #endif /* HAS_IRED */
1908 NULL
1909 };
1910
1911 static SANE_Int bit_depth_list[9];
1912
1913 static const char neverStr[] = "never";
1914 static const char previewStr[] = "before preview";
1915 static const char scanStr[] = "before scan";
1916 static const char preandscanStr[] = "before preview and scan";
1917 static SANE_String_Const autofocus_mode_list[] =
1918 {
1919 neverStr,
1920 previewStr,
1921 scanStr,
1922 preandscanStr,
1923 NULL
1924 };
1925
1926 static SANE_String_Const source_list[4] =
1927 {NULL, NULL, NULL, NULL};
1928
1929 static const SANE_Range gamma_range_8 =
1930 {
1931 0, /* minimum */
1932 255, /* maximum */
1933 1 /* quantization */
1934 };
1935
1936
1937 static const SANE_Range gamma_range_9 =
1938 {
1939 0, /* minimum */
1940 511, /* maximum */
1941 1 /* quantization */
1942 };
1943
1944 static const SANE_Range gamma_range_10 =
1945 {
1946 0, /* minimum */
1947 1023, /* maximum */
1948 1 /* quantization */
1949 };
1950
1951 static const SANE_Range gamma_range_12 =
1952 {
1953 0, /* minimum */
1954 4096, /* maximum */
1955 1 /* quantization */
1956 };
1957
1958 static const SANE_Range brightness_range =
1959 {
1960 -5,
1961 +5,
1962 1
1963 };
1964
1965 static const SANE_Range contrast_range =
1966 {
1967 -5,
1968 +5,
1969 0
1970 };
1971
1972 static const SANE_Range exposure_range =
1973 {
1974 24,
1975 400,
1976 2
1977 };
1978
1979 static const SANE_Range shift_range =
1980 {
1981 -15,
1982 +15,
1983 0
1984 };
1985
1986 static const SANE_Device **devlist = 0;
1987 static int num_devices;
1988 static Coolscan_t *first_dev;
1989
1990
1991 static size_t
max_string_size(const SANE_String_Const strings[])1992 max_string_size (const SANE_String_Const strings[])
1993 {
1994 size_t size, max_size = 0;
1995 int i;
1996
1997 for (i = 0; strings[i]; ++i)
1998 {
1999 size = strlen (strings[i]) + 1;
2000 if (size > max_size)
2001 max_size = size;
2002 }
2003 return max_size;
2004 }
2005
2006 static SANE_Status
do_eof(Coolscan_t * scanner)2007 do_eof (Coolscan_t * scanner)
2008 {
2009 DBG (10, "do_eof\n");
2010
2011 if (scanner->pipe >= 0)
2012 {
2013 close (scanner->pipe);
2014 scanner->pipe = -1;
2015 }
2016 return SANE_STATUS_EOF;
2017 }
2018
2019 static SANE_Status
do_cancel(Coolscan_t * scanner)2020 do_cancel (Coolscan_t * scanner)
2021 {
2022 DBG (10, "do_cancel\n");
2023 swap_res (scanner);
2024 scanner->scanning = SANE_FALSE;
2025
2026 do_eof (scanner); /* close pipe and reposition scanner */
2027
2028 if (sanei_thread_is_valid (scanner->reader_pid))
2029 {
2030 int exit_status;
2031
2032 DBG (10, "do_cancel: kill reader_process\n");
2033
2034 /* ensure child knows it's time to stop: */
2035 sanei_thread_kill (scanner->reader_pid);
2036 while (sanei_thread_waitpid(scanner->reader_pid, &exit_status) !=
2037 scanner->reader_pid );
2038 sanei_thread_invalidate (scanner->reader_pid);
2039 }
2040
2041 if (scanner->sfd >= 0)
2042 {
2043 coolscan_give_scanner (scanner);
2044 DBG (10, "do_cancel: close filedescriptor\n");
2045 sanei_scsi_close (scanner->sfd);
2046 scanner->sfd = -1;
2047 }
2048
2049 return SANE_STATUS_CANCELLED;
2050 }
2051
2052 static SANE_Status
attach_scanner(const char * devicename,Coolscan_t ** devp)2053 attach_scanner (const char *devicename, Coolscan_t ** devp)
2054 {
2055 Coolscan_t *dev;
2056 int sfd;
2057
2058 DBG (10, "attach_scanner: %s\n", devicename);
2059
2060 for (dev = first_dev; dev; dev = dev->next)
2061 {
2062 if (strcmp (dev->sane.name, devicename) == 0)
2063 {
2064 if (devp)
2065 {
2066 *devp = dev;
2067 }
2068 DBG (5, "attach_scanner: scanner already attached (is ok)!\n");
2069 return SANE_STATUS_GOOD;
2070 }
2071 }
2072
2073 DBG (10, "attach_scanner: opening %s\n", devicename);
2074 if (sanei_scsi_open (devicename, &sfd, sense_handler, 0) != 0)
2075 {
2076 DBG (1, "attach_scanner: open failed\n");
2077 return SANE_STATUS_INVAL;
2078 }
2079
2080 if (NULL == (dev = malloc (sizeof (*dev))))
2081 return SANE_STATUS_NO_MEM;
2082
2083
2084 dev->row_bufsize = (sanei_scsi_max_request_size < (64 * 1024)) ?
2085 sanei_scsi_max_request_size : 64 * 1024;
2086
2087 if ((dev->buffer = malloc (dev->row_bufsize)) == NULL)
2088 /* if ((dev->buffer = malloc (sanei_scsi_max_request_size)) == NULL)*/
2089 return SANE_STATUS_NO_MEM;
2090
2091 if ((dev->obuffer = malloc (dev->row_bufsize)) == NULL)
2092 return SANE_STATUS_NO_MEM;
2093
2094 dev->devicename = strdup (devicename);
2095 dev->sfd = sfd;
2096
2097 /* Nikon manual: Step 1 */
2098 if (coolscan_identify_scanner (dev) != 0)
2099 {
2100 DBG (1, "attach_scanner: scanner-identification failed\n");
2101 sanei_scsi_close (dev->sfd);
2102 free (dev->buffer);
2103 free (dev);
2104 return SANE_STATUS_INVAL;
2105 }
2106
2107 /* Get MUD (via mode_sense), internal info (via get_internal_info), and
2108 * initialize values */
2109 coolscan_initialize_values (dev);
2110
2111 /* Why? */
2112 sanei_scsi_close (dev->sfd);
2113 dev->sfd = -1;
2114
2115 dev->sane.name = dev->devicename;
2116 dev->sane.vendor = dev->vendor;
2117 dev->sane.model = dev->product;
2118 dev->sane.type = "slide scanner";
2119
2120 dev->x_range.min = SANE_FIX (0);
2121 dev->x_range.quant = SANE_FIX (length_quant);
2122 dev->x_range.max = SANE_FIX ((double) ((dev->xmaxpix) * length_quant));
2123
2124 dev->y_range.min = SANE_FIX (0.0);
2125 dev->y_range.quant = SANE_FIX (length_quant);
2126 dev->y_range.max = SANE_FIX ((double) ((dev->ymaxpix) * length_quant));
2127
2128 /* ...and this?? */
2129 dev->dpi_range.min = SANE_FIX (108);
2130 dev->dpi_range.quant = SANE_FIX (0);
2131 dev->dpi_range.max = SANE_FIX (dev->maxres);
2132 DBG (10, "attach: dev->dpi_range.max = %f\n",
2133 SANE_UNFIX (dev->dpi_range.max));
2134
2135 ++num_devices;
2136 dev->next = first_dev;
2137 first_dev = dev;
2138
2139 if (devp)
2140 {
2141 *devp = dev;
2142 }
2143
2144 DBG (10, "attach_scanner done\n");
2145
2146 return SANE_STATUS_GOOD;
2147 }
2148
2149 static SANE_Status
attach_one(const char * devName)2150 attach_one (const char *devName)
2151 {
2152 return attach_scanner(devName, 0);
2153 }
2154
2155 static void
sigterm_handler(int signal)2156 sigterm_handler (int signal)
2157 {
2158 (void) signal;
2159 sanei_scsi_req_flush_all (); /* flush SCSI queue */
2160 _exit (SANE_STATUS_GOOD);
2161 }
2162
2163
2164 typedef struct Color_correct_s
2165 { int sum; /* number of pixels summed so far */
2166 double sumr; /* sum of red pixel values*/
2167 double sumi; /* sum of infrared pixel values*/
2168 double sumri; /* sum of red*ired pixel values*/
2169 double sumii; /* sum of ired*ired pixel values*/
2170 double sumrr; /* sum of ired*ired pixel values*/
2171 int mr; /* factor between red and ired values (*256) */
2172 int br; /* offset of ired values */
2173 } ColorCorrect;
2174
2175 /* ---------------------------------------------------------------
2176
2177 function: RGBIfix
2178
2179 task: Correct the infrared channel
2180
2181 import: unsigned char * rgbimat - RGBI - matrix from scanner
2182 int size - number of pixels to correct
2183 int *lutr - lookup table for red correction
2184 int *lutg - lookup table for red correction
2185 int *lutb - lookup table for red correction
2186 int *lutr - lookup table for red correction
2187
2188 export: unsigned char * orgbimat - RGBI - corrected matrix
2189
2190 written by: Andreas RICK 19.6.1999
2191
2192 ----------------------------------------------------------------*/
2193
Calc_fix_LUT(Coolscan_t * s)2194 static int Calc_fix_LUT(Coolscan_t * s)
2195 { int uselutr,uselutg,uselutb,useluti;
2196 /* static int irmulr= -34*25; */
2197 int irmulr= -64*25;
2198 int irmulg= -1*25;
2199 int irmulb= -0*25;
2200 int irmuli= 256*25;
2201 int div;
2202 int i;
2203
2204 irmulr=s->ired_red*(25);
2205 irmulg=s->ired_green*(25);
2206 irmulb=s->ired_blue*(25);
2207 irmuli=25*256;
2208
2209 if(s->LS==2) /* TODO: right conversion factors for 10 and 12 bit */
2210 { div=4;
2211 }
2212 else if(s->LS==3)
2213 { div=16;
2214 }
2215 else
2216 { return 0;
2217 }
2218
2219 memset(s->lutr, 0,256*4);
2220 memset(s->lutg, 0,256*4);
2221 memset(s->lutb, 0,256*4);
2222 memset(s->luti, 0,256*4);
2223
2224 for(i=0;i<s->lutlength;i++)
2225 { if(s->gamma_bind)
2226 { uselutr=uselutg=uselutb=useluti=s->gamma[i]/div;
2227 }
2228 else
2229 { uselutr=s->gamma_r[i]/div;
2230 uselutg=s->gamma_g[i]/div;
2231 uselutb=s->gamma_b[i]/div;
2232 useluti=s->gamma_r[i]/div;
2233 }
2234 s->lutr[uselutr]=(int)(irmulr*pow((double)i,(double)0.333333));
2235 s->lutg[uselutg]=(int)(irmulg*pow((double)i,(double)0.333333));
2236 s->lutb[uselutb]=(int)(irmulb*pow((double)i,(double)0.333333));
2237 s->luti[useluti]=(int)(irmuli*pow((double)i,(double)0.333333));
2238 if(uselutr<255)
2239 { if(s->lutr[uselutr+1]==0) s->lutr[uselutr+1]=s->lutr[uselutr];
2240 }
2241 if(uselutg<255)
2242 { if(s->lutg[uselutg+1]==0) s->lutg[uselutg+1]=s->lutg[uselutg];
2243 }
2244 if(uselutb<255)
2245 { if(s->lutb[uselutb+1]==0) s->lutb[uselutb+1]=s->lutb[uselutb];
2246 }
2247 if(useluti<255)
2248 { if(s->luti[useluti+1]==0) s->luti[useluti+1]=s->luti[useluti];
2249 }
2250 }
2251 /* DEBUG
2252 for(i=0;i<255;i++)
2253 { fprintf(stderr,"%d %d %d %d\n"
2254 ,s->lutr[i],s->lutg[i],s->lutb[i],s->luti[i]);
2255 }
2256 */
2257 return 1;
2258 }
2259
2260
2261
2262 /* ---------------------------------------------------------------
2263
2264 function: RGBIfix
2265
2266 task: Correct the infrared channel
2267
2268 import: unsigned char * rgbimat - RGBI - matrix from scanner
2269 int size - number of pixels to correct
2270 int *lutr - lookup table for red correction
2271 int *lutg - lookup table for red correction
2272 int *lutb - lookup table for red correction
2273 int *lutr - lookup table for red correction
2274
2275 export: unsigned char * orgbimat - RGBI - corrected matrix
2276
2277 written by: Andreas RICK 19.6.1999
2278
2279 ----------------------------------------------------------------*/
2280
RGBIfix(Coolscan_t * scanner,unsigned char * rgbimat,unsigned char * orgbimat,int size,int * lutr,int * lutg,int * lutb,int * luti)2281 static int RGBIfix(Coolscan_t * scanner,
2282 unsigned char* rgbimat,
2283 unsigned char* orgbimat,
2284 int size,
2285 int *lutr,
2286 int *lutg,
2287 int *lutb,
2288 int *luti)
2289
2290 {
2291 unsigned char *pr,*pg,*pb,*pi;
2292 unsigned char *opr,*opg,*opb,*opi;
2293
2294 int r,g,b,i;
2295 int ii;
2296 int x;
2297 for(x=0;x<size;x++)
2298 {
2299 pr=rgbimat+x*4;
2300 pg=pr+1;
2301 pb=pg+1;
2302 pi=pb+1;
2303 opr=orgbimat+x*4;
2304 opg=opr+1;
2305 opb=opg+1;
2306 opi=opb+1;
2307 r=lutr[(*pr)];
2308 g=lutg[(*pg)];
2309 b=lutb[(*pb)];
2310 i=luti[(*pi)];
2311 ii= i-r-g-b;
2312 (*opr)=(*pr);
2313 (*opg)=(*pg);
2314 (*opb)=(*pb);
2315 if(ii<0)ii=0;
2316 if(ii>255*256)ii=255*256;
2317 if(scanner->negative)
2318 {
2319 (*opi)=(unsigned char)(255-(ii>>8));
2320 }
2321 else
2322 {
2323 (*opi)=(unsigned char)(ii>>8);
2324 }
2325 }
2326 return 1;
2327 }
2328
2329 /* ---------------------------------------------------------------
2330
2331 function: RGBIfix16
2332
2333 task: Correct the infrared channel for 16 bit images
2334 (doesn't do anything for now)
2335
2336 import: unsigned char * rgbimat - RGBI - matrix from scanner
2337 int size - number of pixels to correct
2338 int *lutr - lookup table for red correction
2339 int *lutg - lookup table for red correction
2340 int *lutb - lookup table for red correction
2341 int *lutr - lookup table for red correction
2342
2343 export: unsigned char * orgbimat - RGBI - corrected matrix
2344
2345 written by: Andreas RICK 19.6.1999
2346
2347 ----------------------------------------------------------------*/
2348
RGBIfix16(Coolscan_t * scanner,unsigned short * rgbimat,unsigned short * orgbimat,int size,int * lutr,int * lutg,int * lutb,int * luti)2349 static int RGBIfix16(Coolscan_t * scanner,
2350 unsigned short* rgbimat,
2351 unsigned short* orgbimat,
2352 int size,
2353 int *lutr,
2354 int *lutg,
2355 int *lutb,
2356 int *luti)
2357
2358 {
2359 unsigned short *pr,*pg,*pb,*pi;
2360 unsigned short *opr,*opg,*opb,*opi;
2361 int x;
2362
2363 (void) scanner; (void) lutr; (void) lutg; (void) lutb; (void) luti;
2364
2365 for(x=0;x<size;x++)
2366 {
2367 pr=rgbimat+x*4;
2368 pg=pr+1;
2369 pb=pg+1;
2370 pi=pb+1;
2371 opr=orgbimat+x*4;
2372 opg=opr+1;
2373 opb=opg+1;
2374 opi=opb+1;
2375 (*opr)=(((*pr)&0x00ff)<<8)+(((*pr)&0xff00)>>8);
2376 (*opg)=(((*pg)&0x00ff)<<8)+(((*pg)&0xff00)>>8);
2377 (*opb)=(((*pb)&0x00ff)<<8)+(((*pb)&0xff00)>>8);
2378 (*opi)=(((*pi)&0x00ff)<<8)+(((*pi)&0xff00)>>8);
2379 }
2380 return 1;
2381 }
2382
2383
2384 /* ---------------------------------------------------------------
2385
2386 function: rgb2g
2387
2388 task: Convert RGB data to grey
2389
2390 import: unsigned char * rgbimat - RGB - matrix from scanner
2391 int size - size of input data (num pixel)
2392
2393 export: unsigned char * gomat - Grey matrix
2394
2395 written by: Andreas RICK 13.7.1999
2396
2397 ----------------------------------------------------------------*/
2398 #define RtoG ((int)(0.27*256))
2399 #define GtoG ((int)(0.54*256))
2400 #define BtoG ((int)(0.19*256))
2401
rgb2g(unsigned char * rgbimat,unsigned char * gomat,int size)2402 static int rgb2g(unsigned char* rgbimat,unsigned char* gomat,
2403 int size)
2404
2405 { unsigned char *pr,*pg,*pb;
2406 unsigned char *opg;
2407
2408 int g;
2409 int x;
2410 for(x=0;x<size;x++)
2411 {
2412 pr=rgbimat+x*3;
2413 pg=pr+1;
2414 pb=pg+1;
2415 opg=gomat+x;
2416 g= RtoG*(*pr) + GtoG*(*pg) + BtoG*(*pb);
2417 (*opg)=(unsigned char)(g>>8);
2418 }
2419 return 1;
2420 }
2421
2422
2423 /* ---------------------------------------------------------------
2424
2425 function: RGBIfix1
2426
2427 task: Correct the infrared channel.
2428 The input image data is the output of scanning
2429 with LUT. To calculate the original values
2430 the lutr and luti is applied.
2431 The infrared values is corrected by:
2432
2433 Ir=mr*lutr(r)+luti(i)
2434
2435 import: unsigned char * rgbimat - RGBI - matrix from scanner
2436 int size - number of pixels to correct
2437 ColorCorrect *cc,
2438 int *lutr - lookup table for red correction
2439 int *luti - lookup table for ired correction
2440
2441 export: unsigned char * orgbimat - RGBI - corrected matrix
2442
2443 written by: Andreas RICK 3.7.1999
2444
2445 ----------------------------------------------------------------*/
2446 #if 0
2447 static int RGBIfix1(unsigned char* rgbimat,unsigned char* orgbimat,
2448 int size,
2449 int *lutr,
2450 int *lutg,
2451 int *lutb,
2452 int *luti)
2453
2454 { unsigned char *pr,*pg,*pb,*pi;
2455 unsigned char *opr,*opg,*opb,*opi;
2456 ColorCorrect cc;
2457 int r,i;
2458 static int thresi=100;
2459 int ii;
2460 int x;
2461
2462 (void) lutg; (void) lutb;
2463
2464 /* calculate regression between r and ir */
2465 cc.sum=0;
2466 cc.sumr=cc.sumii=cc.sumrr=cc.sumi=cc.sumri=0.0;
2467 for(x=0;x<size;x++)
2468 { pr=rgbimat+x*4;
2469 pi=pr+3;
2470 r=lutr[(*pr)];
2471 i=luti[(*pi)];
2472 /* r=(*pr);
2473 i=(*pi); */
2474 if((*pi)>thresi)
2475 { cc.sum++;
2476 cc.sumr+=r;
2477 cc.sumii+=(i*i);
2478 cc.sumrr+=(r*r);
2479 cc.sumi+=i;
2480 cc.sumri+=(i*r);
2481 }
2482 }
2483 if((cc.sumii!=0)&&(cc.sum!=0))
2484 { double dn,dz,dm;
2485 dz=(cc.sumri-cc.sumr*cc.sumi/cc.sum);
2486 dn=(cc.sumrr-cc.sumr*cc.sumr/cc.sum);
2487 DBG (2, "Reg:dz:%e dn:%e\n",dz,dn);
2488 if(dn!=0)
2489 { dm=(dz/dn);
2490 cc.mr=(int)(dm*1024);
2491 }
2492 else
2493 { cc.mr=0;
2494 dm=0;
2495 }
2496 cc.br=(int)((cc.sumi-dm*cc.sumr)/cc.sum);
2497 }
2498 else
2499 { cc.mr=0;
2500 }
2501 DBG (2, "Regression: size:%d I=%d/1024*R b:%d s:%d sr:%e si:%e sii:%e sri:%e srr:%e\n",
2502 size,cc.mr,cc.br,cc.sum,cc.sumr,cc.sumi,cc.sumii,cc.sumri,cc.sumrr);
2503 for(x=0;x<size;x++)
2504 {
2505
2506 pr=rgbimat+x*4;
2507 pg=pr+1;
2508 pb=pg+1;
2509 pi=pb+1;
2510 opr=orgbimat+x*4;
2511 opg=opr+1;
2512 opb=opg+1;
2513 opi=opb+1;
2514 r=lutr[(*pr)];
2515 i=luti[(*pi)];
2516 /* r=(*pr);
2517 i=(*pi); */
2518 ii= ((i-((r*cc.mr)>>10)-cc.br)>>2) +128;
2519 (*opr)=(*pr);
2520 (*opg)=(*pg);
2521 (*opb)=(*pb);
2522 if(ii<0) ii=0;
2523 if(ii>255) ii=255;
2524 (*opi)=(unsigned char)(ii);
2525 }
2526 return 1;
2527 }
2528
2529 #endif
2530 /* This function is executed as a child process. */
2531 static int
reader_process(void * data)2532 reader_process (void *data )
2533 {
2534 int status;
2535 unsigned int i;
2536 unsigned char h;
2537 unsigned int data_left;
2538 unsigned int data_to_read;
2539 unsigned int data_to_write;
2540 FILE *fp;
2541 sigset_t sigterm_set, ignore_set;
2542 struct SIGACTION act;
2543 unsigned int bpl, linesPerBuf, lineOffset;
2544 unsigned char r_data, g_data, b_data;
2545 unsigned int j, line;
2546 Coolscan_t * scanner = (Coolscan_t*)data;
2547
2548 if (sanei_thread_is_forked ())
2549 {
2550 DBG (10, "reader_process started (forked)\n");
2551 close (scanner->pipe);
2552 scanner->pipe = -1;
2553
2554 sigfillset ( &ignore_set );
2555 sigdelset ( &ignore_set, SIGTERM );
2556 #if defined (__APPLE__) && defined (__MACH__)
2557 sigdelset ( &ignore_set, SIGUSR2 );
2558 #endif
2559 sigprocmask( SIG_SETMASK, &ignore_set, 0 );
2560
2561 memset (&act, 0, sizeof (act));
2562 sigaction (SIGTERM, &act, 0);
2563 }
2564 else
2565 {
2566 DBG (10, "reader_process started (as thread)\n");
2567 }
2568
2569 sigemptyset (&sigterm_set);
2570 sigaddset (&sigterm_set, SIGTERM);
2571
2572 fp = fdopen ( scanner->reader_fds, "w");
2573 if (!fp)
2574 {
2575 DBG (1, "reader_process: couldn't open pipe!\n");
2576 return 1;
2577 }
2578
2579 DBG (10, "reader_process: starting to READ data\n");
2580
2581 data_left = scan_bytes_per_line (scanner) *
2582 lines_per_scan (scanner);
2583
2584 /*scanner->row_bufsize = sanei_scsi_max_request_size;*/
2585 coolscan_trim_rowbufsize (scanner); /* trim bufsize */
2586
2587 DBG (10, "reader_process: reading %u bytes in blocks of %u bytes\n",
2588 data_left, scanner->row_bufsize);
2589
2590 memset (&act, 0, sizeof (act));
2591 act.sa_handler = sigterm_handler;
2592 sigaction (SIGTERM, &act, 0);
2593 /* wait_scanner(scanner); */
2594 do
2595 {
2596 data_to_read = (data_left < scanner->row_bufsize) ?
2597 data_left : scanner->row_bufsize;
2598
2599 data_to_write=data_to_read;
2600
2601 status = coolscan_read_data_block (scanner
2602 ,R_datatype_imagedata,data_to_read);
2603 if (status == 0)
2604 {
2605 continue;
2606 }
2607 if (status == -1)
2608 {
2609 DBG (1, "reader_process: unable to get image data from scanner!\n");
2610 fclose (fp);
2611 return (-1);
2612 }
2613
2614 if (scanner->LS == 1) { /* mirror image for LS-1000 */
2615 bpl = scan_bytes_per_line(scanner);
2616 linesPerBuf = data_to_read / bpl;
2617
2618 for (line = 0, lineOffset = 0; line < linesPerBuf;
2619 line++, lineOffset += bpl ) {
2620
2621 if (scanner->colormode == RGB) {
2622 for (j = 0; j < bpl/2 ; j += 3) {
2623 r_data=scanner->buffer[lineOffset + j];
2624 g_data=scanner->buffer[lineOffset + j + 1];
2625 b_data=scanner->buffer[lineOffset + j + 2];
2626
2627 scanner->buffer[lineOffset + j] =
2628 scanner->buffer[lineOffset + bpl -1 - j - 2 ];
2629 scanner->buffer[lineOffset + j + 1] =
2630 scanner->buffer[lineOffset + bpl -1 - j - 1 ];
2631 scanner->buffer[lineOffset + j + 2] =
2632 scanner->buffer[lineOffset + bpl -1 - j ];
2633
2634 scanner->buffer[lineOffset + bpl -1 - j - 2 ] = r_data;
2635 scanner->buffer[lineOffset + bpl -1 - j - 1] = g_data;
2636 scanner->buffer[lineOffset + bpl -1 - j] = b_data;
2637 }
2638 }
2639 else {
2640 for (j = 0; j < bpl/2; j++) {
2641 r_data=scanner->buffer[lineOffset + j];
2642 scanner->buffer[lineOffset + j] =
2643 scanner->buffer[lineOffset + bpl - 1 - j];
2644 scanner->buffer[lineOffset + bpl - 1 - j] = r_data;
2645 }
2646 }
2647 }
2648 }
2649 if(scanner->colormode==RGBI)
2650 { /* Correct Infrared Channel */
2651 if(scanner->bits_per_color>8)
2652 {
2653 RGBIfix16(scanner, (unsigned short * ) scanner->buffer,
2654 (unsigned short * )scanner->obuffer,
2655 data_to_read/8,scanner->lutr,
2656 scanner->lutg,scanner->lutb,scanner->luti);
2657 }
2658 else
2659 {
2660 RGBIfix(scanner,scanner->buffer,scanner->obuffer,
2661 data_to_read/4,scanner->lutr,
2662 scanner->lutg,scanner->lutb,scanner->luti);
2663 }
2664 }
2665 else if((scanner->colormode==GREYSCALE)&&(scanner->LS>=2))
2666 { /* Convert to Grey */
2667 data_to_write/=3;
2668 rgb2g(scanner->buffer,scanner->obuffer,data_to_write);
2669 }
2670 else
2671 { /* or just copy */
2672 memcpy (scanner->obuffer, scanner->buffer,data_to_read);
2673 }
2674 if((!scanner->low_byte_first)&&(scanner->bits_per_color>8))
2675 { for(i=0;i<data_to_write;i++) /* inverse byteorder */
2676 { h=scanner->obuffer[i];
2677 scanner->obuffer[i]=scanner->obuffer[i+1];
2678 i++;
2679 scanner->obuffer[i]=h;
2680 }
2681 }
2682 fwrite (scanner->obuffer, 1, data_to_write, fp);
2683 fflush (fp);
2684 data_left -= data_to_read;
2685 DBG (10, "reader_process: buffer of %d bytes read; %d bytes to go\n",
2686 data_to_read, data_left);
2687 }
2688 while (data_left);
2689
2690 fclose (fp);
2691
2692 DBG (10, "reader_process: finished reading data\n");
2693
2694 return 0;
2695 }
2696
2697 static SANE_Status
init_options(Coolscan_t * scanner)2698 init_options (Coolscan_t * scanner)
2699 {
2700 int i;
2701 int bit_depths;
2702
2703 DBG (10, "init_options\n");
2704
2705 memset (scanner->opt, 0, sizeof (scanner->opt));
2706
2707 for (i = 0; i < NUM_OPTIONS; ++i)
2708 {
2709 scanner->opt[i].size = sizeof (SANE_Word);
2710 scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2711 }
2712
2713 scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
2714 scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
2715 scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
2716 scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
2717
2718 /* "Mode" group: */
2719 scanner->opt[OPT_MODE_GROUP].title = "Scan Mode";
2720 scanner->opt[OPT_MODE_GROUP].desc = "";
2721 scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
2722 scanner->opt[OPT_MODE_GROUP].cap = 0;
2723 scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2724
2725 /* scan mode */
2726 scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
2727 scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
2728 scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
2729 scanner->opt[OPT_MODE].type = SANE_TYPE_STRING;
2730 if(scanner->LS<2)
2731 { scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list_LS20);
2732 scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2733 scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list_LS20;
2734 }
2735 else
2736 { scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list_LS30);
2737 scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2738 scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list_LS30;
2739 }
2740
2741 /* source */
2742 source_list[0] = "Slide";
2743 source_list[1] = "Automatic Slide Feeder";
2744 source_list[2] = NULL;
2745 if (!scanner->autofeeder)
2746 {
2747 scanner->opt[OPT_SOURCE].cap = SANE_CAP_INACTIVE;
2748 }
2749
2750 scanner->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
2751 scanner->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
2752 scanner->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
2753 scanner->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
2754 scanner->opt[OPT_SOURCE].size = max_string_size (source_list);
2755 scanner->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2756 scanner->opt[OPT_SOURCE].constraint.string_list = source_list;
2757
2758 /* negative */
2759 scanner->opt[OPT_TYPE].name = "type";
2760 scanner->opt[OPT_TYPE].title = "Film type";
2761 scanner->opt[OPT_TYPE].desc =
2762 "Select the film type (positive (slide) or negative)";
2763 scanner->opt[OPT_TYPE].type = SANE_TYPE_STRING;
2764 scanner->opt[OPT_TYPE].size = max_string_size (type_list);
2765 scanner->opt[OPT_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2766 scanner->opt[OPT_TYPE].constraint.string_list = type_list;
2767
2768 scanner->opt[OPT_PRESCAN].name = "prescan";
2769 scanner->opt[OPT_PRESCAN].title = "Prescan";
2770 scanner->opt[OPT_PRESCAN].desc =
2771 "Perform a prescan during preview";
2772 scanner->opt[OPT_PRESCAN].type = SANE_TYPE_BOOL;
2773 scanner->opt[OPT_PRESCAN].unit = SANE_UNIT_NONE;
2774
2775 scanner->opt[OPT_PRESCAN_NOW].name = "prescan now";
2776 scanner->opt[OPT_PRESCAN_NOW].title = "Prescan now";
2777 scanner->opt[OPT_PRESCAN_NOW].desc =
2778 "Perform a prescan now";
2779 scanner->opt[OPT_PRESCAN_NOW].type = SANE_TYPE_BUTTON;
2780 scanner->opt[OPT_PRESCAN_NOW].unit = SANE_UNIT_NONE;
2781 scanner->opt[OPT_PRESCAN_NOW].size = 0;
2782 scanner->opt[OPT_PRESCAN_NOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2783 scanner->opt[OPT_PRESCAN_NOW].constraint_type = SANE_CONSTRAINT_NONE;
2784 scanner->opt[OPT_PRESCAN_NOW].constraint.string_list = 0;
2785
2786 /* bit depth */
2787
2788 bit_depths=0;
2789 bit_depth_list[++bit_depths] = 8;
2790 if (scanner->LS==2)
2791 {
2792 bit_depth_list[++bit_depths] = 10;
2793 }
2794 if (scanner->LS==3)
2795 {
2796 bit_depth_list[++bit_depths] = 12;
2797 }
2798
2799 bit_depth_list[0] = bit_depths;
2800
2801 scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
2802 scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
2803 scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
2804 scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
2805 scanner->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT;
2806 scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2807 scanner->opt[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list;
2808
2809 /* resolution */
2810 scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
2811 scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
2812 scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2813 scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
2814 scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
2815 scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2816 scanner->opt[OPT_RESOLUTION].constraint.word_list = resolution_list;
2817
2818 scanner->opt[OPT_PREVIEW_RESOLUTION].name = "preview-resolution";
2819 scanner->opt[OPT_PREVIEW_RESOLUTION].title = "Preview resolution";
2820 scanner->opt[OPT_PREVIEW_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2821 scanner->opt[OPT_PREVIEW_RESOLUTION].type = SANE_TYPE_INT;
2822 scanner->opt[OPT_PREVIEW_RESOLUTION].unit = SANE_UNIT_DPI;
2823 scanner->opt[OPT_PREVIEW_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2824 scanner->opt[OPT_PREVIEW_RESOLUTION].constraint.word_list = resolution_list;
2825
2826 /* "Geometry" group: */
2827 scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
2828 scanner->opt[OPT_GEOMETRY_GROUP].desc = "";
2829 scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2830 scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
2831 scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2832
2833 /* top-left x */
2834 scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2835 scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2836 scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2837 scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2838 scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2839 scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2840 scanner->opt[OPT_TL_X].constraint.range = &(scanner->x_range);
2841
2842 /* top-left y */
2843 scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2844 scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2845 scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2846 scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2847 scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2848 scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2849 scanner->opt[OPT_TL_Y].constraint.range = &(scanner->y_range);
2850
2851 /* bottom-right x */
2852 scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2853 scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2854 scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2855 scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2856 scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2857 scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2858 scanner->opt[OPT_BR_X].constraint.range = &(scanner->x_range);
2859
2860 /* bottom-right y */
2861 scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2862 scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2863 scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2864 scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2865 scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2866 scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2867 scanner->opt[OPT_BR_Y].constraint.range = &(scanner->y_range);
2868
2869
2870 /* ------------------------------ */
2871
2872 /* "Enhancement" group: */
2873 scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
2874 scanner->opt[OPT_ENHANCEMENT_GROUP].desc = "";
2875 scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
2876 scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
2877 scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2878
2879
2880 scanner->opt[OPT_GAMMA_BIND].name = "gamma-bind";
2881 scanner->opt[OPT_GAMMA_BIND].title = "Gamma bind";
2882 scanner->opt[OPT_GAMMA_BIND].desc =
2883 "Use same gamma correction for all colours";
2884 scanner->opt[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL;
2885 scanner->opt[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE;
2886
2887
2888 scanner->opt[OPT_ANALOG_GAMMA].name = "analog_gamma";
2889 scanner->opt[OPT_ANALOG_GAMMA].title = "Analog Gamma";
2890 scanner->opt[OPT_ANALOG_GAMMA].desc = "Analog Gamma";
2891 scanner->opt[OPT_ANALOG_GAMMA].type = SANE_TYPE_BOOL;
2892 scanner->opt[OPT_ANALOG_GAMMA].unit = SANE_UNIT_NONE;
2893 if (!scanner->analoggamma)
2894 {
2895 scanner->opt[OPT_ANALOG_GAMMA].cap = SANE_CAP_INACTIVE;
2896 }
2897
2898 scanner->opt[OPT_AVERAGING].name = "averaging";
2899 scanner->opt[OPT_AVERAGING].title = "Averaging";
2900 scanner->opt[OPT_AVERAGING].desc = "Averaging";
2901 scanner->opt[OPT_AVERAGING].type = SANE_TYPE_BOOL;
2902 scanner->opt[OPT_AVERAGING].unit = SANE_UNIT_NONE;
2903
2904
2905 scanner->opt[OPT_RGB_CONTROL].name = "rgb-control";
2906 scanner->opt[OPT_RGB_CONTROL].title = "RGB control";
2907 scanner->opt[OPT_RGB_CONTROL].desc =
2908 "toggles brightness/contrast control over individual colours";
2909 scanner->opt[OPT_RGB_CONTROL].type = SANE_TYPE_BOOL;
2910 scanner->opt[OPT_RGB_CONTROL].unit = SANE_UNIT_NONE;
2911 if(scanner->LS>=2)
2912 { scanner->opt[OPT_RGB_CONTROL].cap |= SANE_CAP_INACTIVE;
2913 }
2914
2915
2916
2917 /* brightness */
2918 scanner->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
2919 scanner->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
2920 scanner->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2921 scanner->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
2922 scanner->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
2923 scanner->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2924 scanner->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range;
2925 if(scanner->LS>=2)
2926 { scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2927 }
2928
2929
2930 scanner->opt[OPT_R_BRIGHTNESS].name = "red-brightness";
2931 scanner->opt[OPT_R_BRIGHTNESS].title = "Red brightness";
2932 scanner->opt[OPT_R_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2933 scanner->opt[OPT_R_BRIGHTNESS].type = SANE_TYPE_INT;
2934 scanner->opt[OPT_R_BRIGHTNESS].unit = SANE_UNIT_NONE;
2935 scanner->opt[OPT_R_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2936 scanner->opt[OPT_R_BRIGHTNESS].constraint.range = &brightness_range;
2937 scanner->opt[OPT_R_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2938
2939 scanner->opt[OPT_G_BRIGHTNESS].name = "green-brightness";
2940 scanner->opt[OPT_G_BRIGHTNESS].title = "Green brightness";
2941 scanner->opt[OPT_G_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2942 scanner->opt[OPT_G_BRIGHTNESS].type = SANE_TYPE_INT;
2943 scanner->opt[OPT_G_BRIGHTNESS].unit = SANE_UNIT_NONE;
2944 scanner->opt[OPT_G_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2945 scanner->opt[OPT_G_BRIGHTNESS].constraint.range = &brightness_range;
2946 scanner->opt[OPT_G_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2947
2948 scanner->opt[OPT_B_BRIGHTNESS].name = "blue-brightness";
2949 scanner->opt[OPT_B_BRIGHTNESS].title = "Blue brightness";
2950 scanner->opt[OPT_B_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2951 scanner->opt[OPT_B_BRIGHTNESS].type = SANE_TYPE_INT;
2952 scanner->opt[OPT_B_BRIGHTNESS].unit = SANE_UNIT_NONE;
2953 scanner->opt[OPT_B_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2954 scanner->opt[OPT_B_BRIGHTNESS].constraint.range = &brightness_range;
2955 scanner->opt[OPT_B_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2956
2957 /* contrast */
2958 scanner->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
2959 scanner->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
2960 scanner->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
2961 scanner->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
2962 scanner->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
2963 scanner->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2964 scanner->opt[OPT_CONTRAST].constraint.range = &contrast_range;
2965 if(scanner->LS>=2)
2966 { scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
2967 }
2968
2969
2970 scanner->opt[OPT_R_CONTRAST].name = "red-contrast";
2971 scanner->opt[OPT_R_CONTRAST].title = "Red contrast";
2972 scanner->opt[OPT_R_CONTRAST].desc = SANE_DESC_CONTRAST;
2973 scanner->opt[OPT_R_CONTRAST].type = SANE_TYPE_INT;
2974 scanner->opt[OPT_R_CONTRAST].unit = SANE_UNIT_NONE;
2975 scanner->opt[OPT_R_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2976 scanner->opt[OPT_R_CONTRAST].constraint.range = &contrast_range;
2977 scanner->opt[OPT_R_CONTRAST].cap |= SANE_CAP_INACTIVE;
2978
2979 scanner->opt[OPT_G_CONTRAST].name = "green-contrast";
2980 scanner->opt[OPT_G_CONTRAST].title = "Green contrast";
2981 scanner->opt[OPT_G_CONTRAST].desc = SANE_DESC_CONTRAST;
2982 scanner->opt[OPT_G_CONTRAST].type = SANE_TYPE_INT;
2983 scanner->opt[OPT_G_CONTRAST].unit = SANE_UNIT_NONE;
2984 scanner->opt[OPT_G_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2985 scanner->opt[OPT_G_CONTRAST].constraint.range = &contrast_range;
2986 scanner->opt[OPT_G_CONTRAST].cap |= SANE_CAP_INACTIVE;
2987
2988 scanner->opt[OPT_B_CONTRAST].name = "blue-contrast";
2989 scanner->opt[OPT_B_CONTRAST].title = "Blue contrast";
2990 scanner->opt[OPT_B_CONTRAST].desc = SANE_DESC_CONTRAST;
2991 scanner->opt[OPT_B_CONTRAST].type = SANE_TYPE_INT;
2992 scanner->opt[OPT_B_CONTRAST].unit = SANE_UNIT_NONE;
2993 scanner->opt[OPT_B_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2994 scanner->opt[OPT_B_CONTRAST].constraint.range = &contrast_range;
2995 scanner->opt[OPT_B_CONTRAST].cap |= SANE_CAP_INACTIVE;
2996
2997 scanner->opt[OPT_EXPOSURE].name = "exposure";
2998 scanner->opt[OPT_EXPOSURE].title = "Exposure";
2999 scanner->opt[OPT_EXPOSURE].desc = "";
3000 scanner->opt[OPT_EXPOSURE].type = SANE_TYPE_INT;
3001 scanner->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3002 scanner->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT;
3003 scanner->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
3004 scanner->opt[OPT_EXPOSURE].constraint.range = &exposure_range;
3005
3006 scanner->opt[OPT_R_EXPOSURE].name = "red-exposure";
3007 scanner->opt[OPT_R_EXPOSURE].title = "Red exposure";
3008 scanner->opt[OPT_R_EXPOSURE].desc = "";
3009 scanner->opt[OPT_R_EXPOSURE].type = SANE_TYPE_INT;
3010 scanner->opt[OPT_R_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3011 scanner->opt[OPT_R_EXPOSURE].unit = SANE_UNIT_PERCENT;
3012 scanner->opt[OPT_R_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
3013 scanner->opt[OPT_R_EXPOSURE].constraint.range = &exposure_range;
3014
3015 scanner->opt[OPT_G_EXPOSURE].name = "green-exposure";
3016 scanner->opt[OPT_G_EXPOSURE].title = "Green exposure";
3017 scanner->opt[OPT_G_EXPOSURE].desc = "";
3018 scanner->opt[OPT_G_EXPOSURE].type = SANE_TYPE_INT;
3019 scanner->opt[OPT_G_EXPOSURE].unit = SANE_UNIT_PERCENT;
3020 scanner->opt[OPT_G_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
3021 scanner->opt[OPT_G_EXPOSURE].constraint.range = &exposure_range;
3022 scanner->opt[OPT_G_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3023
3024 scanner->opt[OPT_B_EXPOSURE].name = "blue-exposure";
3025 scanner->opt[OPT_B_EXPOSURE].title = "Blue exposre";
3026 scanner->opt[OPT_B_EXPOSURE].desc = "";
3027 scanner->opt[OPT_B_EXPOSURE].type = SANE_TYPE_INT;
3028 scanner->opt[OPT_B_EXPOSURE].unit = SANE_UNIT_PERCENT;
3029 scanner->opt[OPT_B_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
3030 scanner->opt[OPT_B_EXPOSURE].constraint.range = &exposure_range;
3031 scanner->opt[OPT_B_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3032 if(scanner->LS>=2)
3033 { scanner->opt[OPT_R_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3034 scanner->opt[OPT_G_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3035 scanner->opt[OPT_B_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3036 scanner->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3037 }
3038
3039 scanner->opt[OPT_R_SHIFT].name = "red-shift";
3040 scanner->opt[OPT_R_SHIFT].title = "Red shift";
3041 scanner->opt[OPT_R_SHIFT].desc = "";
3042 scanner->opt[OPT_R_SHIFT].type = SANE_TYPE_INT;
3043 scanner->opt[OPT_R_SHIFT].unit = SANE_UNIT_NONE;
3044 scanner->opt[OPT_R_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE;
3045 scanner->opt[OPT_R_SHIFT].constraint.range = &shift_range;
3046 if(scanner->LS>=2)
3047 { scanner->opt[OPT_R_SHIFT].cap |= SANE_CAP_INACTIVE;
3048 }
3049
3050
3051 scanner->opt[OPT_G_SHIFT].name = "green-shift";
3052 scanner->opt[OPT_G_SHIFT].title = "Green shift";
3053 scanner->opt[OPT_G_SHIFT].desc = "";
3054 scanner->opt[OPT_G_SHIFT].type = SANE_TYPE_INT;
3055 scanner->opt[OPT_G_SHIFT].unit = SANE_UNIT_NONE;
3056 scanner->opt[OPT_G_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE;
3057 scanner->opt[OPT_G_SHIFT].constraint.range = &shift_range;
3058 if(scanner->LS>=2)
3059 { scanner->opt[OPT_G_SHIFT].cap |= SANE_CAP_INACTIVE;
3060 }
3061
3062
3063 scanner->opt[OPT_B_SHIFT].name = "blue-shift";
3064 scanner->opt[OPT_B_SHIFT].title = "Blue shift";
3065 scanner->opt[OPT_B_SHIFT].desc = "";
3066 scanner->opt[OPT_B_SHIFT].type = SANE_TYPE_INT;
3067 scanner->opt[OPT_B_SHIFT].unit = SANE_UNIT_NONE;
3068 scanner->opt[OPT_B_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE;
3069 scanner->opt[OPT_B_SHIFT].constraint.range = &shift_range;
3070 if(scanner->LS>=2)
3071 { scanner->opt[OPT_B_SHIFT].cap |= SANE_CAP_INACTIVE;
3072 }
3073
3074 /* R+G+B gamma vector */
3075 scanner->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
3076 scanner->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
3077 scanner->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
3078 scanner->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
3079 if (scanner->LS == 1)
3080 {
3081 scanner->opt[OPT_GAMMA_VECTOR].cap = SANE_CAP_INACTIVE;
3082 }
3083 scanner->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
3084 switch(scanner->LS)
3085 { case 0:
3086 scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_8;
3087 scanner->lutlength=2048;
3088 break;
3089 case 1:
3090 scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_9;
3091 scanner->lutlength=512;
3092 break;
3093 case 2:
3094 scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_10;
3095 scanner->lutlength=1024;
3096 break;
3097 case 3:
3098 scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_12;
3099 scanner->lutlength=4096;
3100 break;
3101 }
3102 scanner->opt[OPT_GAMMA_VECTOR].size = scanner->lutlength * sizeof (SANE_Word);
3103 scanner->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
3104
3105 /* red gamma vector */
3106 scanner->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
3107 scanner->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
3108 scanner->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
3109 scanner->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
3110 scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
3111 scanner->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
3112 switch(scanner->LS)
3113 { case 0:
3114 scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_8;
3115 scanner->lutlength=2048;
3116 break;
3117 case 1:
3118 scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_9;
3119 scanner->lutlength=512;
3120 break;
3121 case 2:
3122 scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_10;
3123 scanner->lutlength=1024;
3124 break;
3125 case 3:
3126 scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_12;
3127 scanner->lutlength=4096;
3128 break;
3129 }
3130 scanner->opt[OPT_GAMMA_VECTOR_R].size = scanner->lutlength * sizeof (SANE_Word);
3131 scanner->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
3132
3133 /* green gamma vector */
3134 scanner->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
3135 scanner->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
3136 scanner->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
3137 scanner->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
3138 scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
3139 scanner->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
3140 switch(scanner->LS)
3141 { case 0:
3142 scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_8;
3143 scanner->lutlength=2048;
3144 break;
3145 case 1:
3146 scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_9;
3147 scanner->lutlength=512;
3148 break;
3149 case 2:
3150 scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_10;
3151 scanner->lutlength=1024;
3152 break;
3153 case 3:
3154 scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_12;
3155 scanner->lutlength=4096;
3156 break;
3157 }
3158 scanner->opt[OPT_GAMMA_VECTOR_G].size = scanner->lutlength * sizeof (SANE_Word);
3159 scanner->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
3160
3161 /* blue gamma vector */
3162 scanner->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
3163 scanner->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
3164 scanner->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
3165 scanner->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
3166 scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
3167 scanner->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
3168 switch(scanner->LS)
3169 { case 0:
3170 scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_8;
3171 scanner->lutlength=2048;
3172 break;
3173 case 1:
3174 scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_9;
3175 scanner->lutlength=512;
3176 break;
3177 case 2:
3178 scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_10;
3179 scanner->lutlength=1024;
3180 break;
3181 case 3:
3182 scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_12;
3183 scanner->lutlength=4096;
3184 break;
3185 }
3186 scanner->opt[OPT_GAMMA_VECTOR_B].size = scanner->lutlength * sizeof (SANE_Word);
3187 scanner->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
3188
3189
3190 /* ------------------------------ */
3191
3192 /* "Advanced" group: */
3193 scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced";
3194 scanner->opt[OPT_ADVANCED_GROUP].desc = "";
3195 scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
3196 scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
3197 scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
3198
3199 /* preview */
3200 scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
3201 scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
3202 scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
3203 scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
3204
3205 /* Autofocus */
3206 scanner->opt[OPT_AUTOFOCUS].name = "Autofocus";
3207 scanner->opt[OPT_AUTOFOCUS].title ="Autofocus";
3208 scanner->opt[OPT_AUTOFOCUS].desc = "When to do autofocussing";
3209 scanner->opt[OPT_AUTOFOCUS].type = SANE_TYPE_STRING;
3210 scanner->opt[OPT_AUTOFOCUS].size = max_string_size (autofocus_mode_list);
3211 scanner->opt[OPT_AUTOFOCUS].constraint_type = SANE_CONSTRAINT_STRING_LIST;
3212 scanner->opt[OPT_AUTOFOCUS].constraint.string_list = autofocus_mode_list;
3213
3214 scanner->opt[OPT_IRED_RED].name = "IRED cor. red";
3215 scanner->opt[OPT_IRED_RED].title ="IRED cor. red";
3216 scanner->opt[OPT_IRED_RED].desc = "Correction of infrared from red";
3217 scanner->opt[OPT_IRED_RED].type = SANE_TYPE_INT;
3218 scanner->opt[OPT_IRED_RED].unit = SANE_UNIT_NONE;
3219 scanner->opt[OPT_IRED_RED].constraint_type = SANE_CONSTRAINT_RANGE;
3220 scanner->opt[OPT_IRED_RED].constraint.range = &gamma_range_8;
3221 scanner->opt[OPT_IRED_RED].cap |= SANE_CAP_ADVANCED;
3222 if(scanner->LS<2)
3223 { scanner->opt[OPT_IRED_RED].cap |= SANE_CAP_INACTIVE;
3224 }
3225
3226
3227
3228 /* scanner->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; */
3229 return SANE_STATUS_GOOD;
3230 }
3231
3232
3233 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)3234 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
3235 {
3236 char dev_name[PATH_MAX];
3237 size_t len;
3238 FILE *fp;
3239
3240 (void) authorize;
3241
3242 DBG_INIT ();
3243 sanei_thread_init ();
3244
3245 DBG (10, "sane_init\n");
3246 if (version_code)
3247 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
3248
3249 fp = sanei_config_open (COOLSCAN_CONFIG_FILE);
3250 if (!fp)
3251 {
3252 attach_scanner ("/dev/scanner", 0); /* no config-file: /dev/scanner */
3253 return SANE_STATUS_GOOD;
3254 }
3255
3256 while (sanei_config_read (dev_name, sizeof (dev_name), fp))
3257 {
3258 if (dev_name[0] == '#')
3259 continue; /* ignore line comments */
3260 len = strlen (dev_name);
3261
3262 if (!len)
3263 continue; /* ignore empty lines */
3264
3265 sanei_config_attach_matching_devices (dev_name, attach_one);
3266 /*attach_scanner (dev_name, 0);*/
3267 }
3268 fclose (fp);
3269 return SANE_STATUS_GOOD;
3270 }
3271
3272 void
sane_exit(void)3273 sane_exit (void)
3274 {
3275 Coolscan_t *dev, *next;
3276
3277 DBG (10, "sane_exit\n");
3278
3279 for (dev = first_dev; dev; dev = next)
3280 {
3281 next = dev->next;
3282 free (dev->devicename);
3283 free (dev->buffer);
3284 free (dev->obuffer);
3285 free (dev);
3286 }
3287
3288 if (devlist)
3289 free (devlist);
3290 }
3291
3292 /* ----------------------------- SANE GET DEVICES -------------------------- */
3293 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)3294 sane_get_devices (const SANE_Device *** device_list,
3295 SANE_Bool local_only)
3296 {
3297 Coolscan_t *dev;
3298 int i;
3299
3300 (void) local_only;
3301
3302 DBG (10, "sane_get_devices\n");
3303
3304 if (devlist)
3305 free (devlist);
3306
3307 devlist = calloc (num_devices + 1, sizeof (devlist[0]));
3308 if (!devlist)
3309 return SANE_STATUS_NO_MEM;
3310
3311 i = 0;
3312
3313 for (dev = first_dev; i < num_devices; dev = dev->next)
3314 devlist[i++] = &dev->sane;
3315
3316 devlist[i++] = 0;
3317
3318 *device_list = devlist;
3319
3320 return SANE_STATUS_GOOD;
3321 }
3322
3323 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)3324 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
3325 {
3326 Coolscan_t *dev;
3327 SANE_Status status;
3328
3329 DBG (10, "sane_open\n");
3330
3331 if (devicename[0])
3332 { /* search for devicename */
3333 for (dev = first_dev; dev; dev = dev->next)
3334 {
3335 if (strcmp (dev->sane.name, devicename) == 0)
3336 {
3337 break;
3338 }
3339 }
3340
3341 if (!dev)
3342 {
3343 status = attach_scanner (devicename, &dev);
3344 if (status != SANE_STATUS_GOOD)
3345 {
3346 return status;
3347 }
3348 }
3349 }
3350 else
3351 {
3352 dev = first_dev; /* empty devicname -> use first device */
3353 }
3354
3355 if (!dev)
3356 return SANE_STATUS_INVAL;
3357
3358 dev->sfd = -1;
3359 dev->pipe = -1;
3360 dev->scanning = SANE_FALSE;
3361
3362 init_options (dev);
3363 *handle = dev;
3364 return SANE_STATUS_GOOD;
3365 }
3366
3367 void
sane_close(SANE_Handle handle)3368 sane_close (SANE_Handle handle)
3369 {
3370 DBG (10, "sane_close\n");
3371 if (((Coolscan_t *) handle)->scanning)
3372 do_cancel (handle);
3373 }
3374
3375 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)3376 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
3377 {
3378 Coolscan_t *scanner = handle;
3379
3380 DBG (10, "sane_get_option_descriptor %d\n", option);
3381
3382 if ((unsigned) option >= NUM_OPTIONS)
3383 return 0;
3384 return &scanner->opt[option];
3385 }
3386
3387 /*
3388 static void
3389 worddump(char *comment, SANE_Word * p, int l)
3390 {
3391 int i;
3392 char line[128];
3393 char *ptr;
3394
3395 DBG (5, "%s\n", comment);
3396 ptr = line;
3397 for (i = 0; i < l; i++, p++)
3398 {
3399 if ((i % 8) == 0)
3400 {
3401 if (ptr != line)
3402 {
3403 *ptr = '\0';
3404 DBG (5, "%s\n", line);
3405 ptr = line;
3406 }
3407 sprintf (ptr, "%3.3d:", i);
3408 ptr += 4;
3409 }
3410 sprintf (ptr, " %4.4d", *p);
3411 ptr += 5;
3412 }
3413 *ptr = '\0';
3414 DBG (5, "%s\n", line);
3415 }
3416 */
3417 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)3418 sane_control_option (SANE_Handle handle, SANE_Int option,
3419 SANE_Action action, void *val,
3420 SANE_Int * info)
3421 {
3422 Coolscan_t *scanner = handle;
3423 SANE_Status status;
3424 SANE_Word cap;
3425
3426 if (info)
3427 *info = 0;
3428
3429 if (scanner->scanning)
3430 return SANE_STATUS_DEVICE_BUSY;
3431
3432 if (option >= NUM_OPTIONS)
3433 return SANE_STATUS_INVAL;
3434
3435 cap = scanner->opt[option].cap;
3436
3437
3438 if (action == SANE_ACTION_GET_VALUE)
3439 {
3440 DBG (10, "sane_control_option %d, get value\n", option);
3441 switch (option)
3442 {
3443 /* word options: */
3444 case OPT_TL_X:
3445 *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tlx));
3446 return SANE_STATUS_GOOD;
3447
3448 case OPT_TL_Y:
3449 *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tly));
3450 return SANE_STATUS_GOOD;
3451
3452 case OPT_BR_X:
3453 *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->brx));
3454 return SANE_STATUS_GOOD;
3455
3456 case OPT_BR_Y:
3457 *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->bry));
3458 return SANE_STATUS_GOOD;
3459
3460 case OPT_PREVIEW:
3461 *(SANE_Word *) val = scanner->preview;
3462 return SANE_STATUS_GOOD;
3463
3464 case OPT_AUTOFOCUS:
3465 switch(scanner->autofocus)
3466 { case AF_NEVER: strcpy (val,neverStr);
3467 break;
3468 case AF_PREVIEW:strcpy (val,previewStr);
3469 break;
3470 case AF_SCAN:if(scanner->LS>=2) strcpy (val,scanStr);
3471 break;
3472 case AF_PREANDSCAN:if(scanner->LS>=2) strcpy (val,preandscanStr);
3473 break;
3474 }
3475 return SANE_STATUS_GOOD;
3476
3477 case OPT_NUM_OPTS:
3478 *(SANE_Word *) val = NUM_OPTIONS;
3479 return SANE_STATUS_GOOD;
3480
3481 case OPT_RESOLUTION:
3482 *(SANE_Word *) val = resDivToVal (scanner->x_nres);
3483 return SANE_STATUS_GOOD;
3484
3485 case OPT_PREVIEW_RESOLUTION:
3486 *(SANE_Word *) val = resDivToVal (scanner->x_p_nres);
3487 return SANE_STATUS_GOOD;
3488
3489 case OPT_BIT_DEPTH:
3490 *(SANE_Word *) val = scanner->bits_per_color;
3491 return SANE_STATUS_GOOD;
3492
3493 case OPT_CONTRAST:
3494 *(SANE_Word *) val = scanner->contrast - 128;
3495 return SANE_STATUS_GOOD;
3496
3497 case OPT_R_CONTRAST:
3498 *(SANE_Word *) val = scanner->contrast_R - 128;
3499 return SANE_STATUS_GOOD;
3500
3501 case OPT_G_CONTRAST:
3502 *(SANE_Word *) val = scanner->contrast_G - 128;
3503 return SANE_STATUS_GOOD;
3504
3505 case OPT_B_CONTRAST:
3506 *(SANE_Word *) val = scanner->contrast_B - 128;
3507 return SANE_STATUS_GOOD;
3508
3509 case OPT_BRIGHTNESS:
3510 *(SANE_Word *) val = scanner->brightness - 128;
3511 return SANE_STATUS_GOOD;
3512
3513 case OPT_R_BRIGHTNESS:
3514 *(SANE_Word *) val = scanner->brightness_R - 128;
3515 return SANE_STATUS_GOOD;
3516
3517 case OPT_G_BRIGHTNESS:
3518 *(SANE_Word *) val = scanner->brightness_G - 128;
3519 return SANE_STATUS_GOOD;
3520
3521 case OPT_B_BRIGHTNESS:
3522 *(SANE_Word *) val = scanner->brightness_B - 128;
3523 return SANE_STATUS_GOOD;
3524
3525 case OPT_EXPOSURE:
3526 *(SANE_Word *) val = scanner->exposure_R * 2;
3527 return SANE_STATUS_GOOD;
3528
3529 case OPT_R_EXPOSURE:
3530 *(SANE_Word *) val = scanner->exposure_R * 2;
3531 return SANE_STATUS_GOOD;
3532
3533 case OPT_G_EXPOSURE:
3534 *(SANE_Word *) val = scanner->exposure_G * 2;
3535 return SANE_STATUS_GOOD;
3536
3537 case OPT_B_EXPOSURE:
3538 *(SANE_Word *) val = scanner->exposure_B * 2;
3539 return SANE_STATUS_GOOD;
3540
3541 case OPT_R_SHIFT:
3542 *(SANE_Word *) val = scanner->shift_R - 128;
3543 return SANE_STATUS_GOOD;
3544
3545 case OPT_G_SHIFT:
3546 *(SANE_Word *) val = scanner->shift_G - 128;
3547 return SANE_STATUS_GOOD;
3548
3549 case OPT_B_SHIFT:
3550 *(SANE_Word *) val = scanner->shift_B - 128;
3551 return SANE_STATUS_GOOD;
3552
3553
3554 case OPT_IRED_RED:
3555 *(SANE_Word *) val = scanner->ired_red;
3556 return SANE_STATUS_GOOD;
3557
3558 /* string options: */
3559 case OPT_TYPE:
3560 strcpy (val, ((scanner->negative) ? negativeStr : positiveStr));
3561 return SANE_STATUS_GOOD;
3562
3563 case OPT_MODE:
3564 switch(scanner->colormode)
3565 { case RGB: strcpy (val,colorStr);
3566 break;
3567 case GREYSCALE:strcpy (val,grayStr);
3568 break;
3569 case RGBI:if(scanner->LS>=2) strcpy (val,rgbiStr);
3570 else strcpy (val,colorStr);
3571 break;
3572 case IRED:if(scanner->LS>=2) strcpy (val,iredStr);
3573 else strcpy (val,grayStr);
3574 break;
3575 }
3576 if (info)
3577 {
3578 *info |= SANE_INFO_RELOAD_PARAMS;
3579 }
3580
3581 return SANE_STATUS_GOOD;
3582
3583 case OPT_PRESCAN:
3584 *(SANE_Word *) val = (scanner->prescan) ? SANE_TRUE : SANE_FALSE;
3585 return SANE_STATUS_GOOD;
3586
3587 case OPT_PRESCAN_NOW:
3588 return SANE_STATUS_GOOD;
3589
3590 case OPT_RGB_CONTROL:
3591 *(SANE_Word *) val = (scanner->rgb_control) ? SANE_TRUE : SANE_FALSE;
3592 return SANE_STATUS_GOOD;
3593
3594 case OPT_GAMMA_BIND:
3595 *(SANE_Word *) val = (scanner->gamma_bind) ? SANE_TRUE : SANE_FALSE;
3596 return SANE_STATUS_GOOD;
3597
3598 case OPT_ANALOG_GAMMA:
3599 *(SANE_Word *) val =
3600 (scanner->analog_gamma_r) ? SANE_TRUE : SANE_FALSE;
3601 return SANE_STATUS_GOOD;
3602
3603 case OPT_AVERAGING:
3604 *(SANE_Word *) val = (scanner->averaging) ? SANE_TRUE : SANE_FALSE;
3605 return SANE_STATUS_GOOD;
3606
3607 case OPT_GAMMA_VECTOR:
3608 memcpy (val, scanner->gamma, scanner->opt[option].size);
3609 return SANE_STATUS_GOOD;
3610 case OPT_GAMMA_VECTOR_R:
3611 memcpy (val, scanner->gamma_r, scanner->opt[option].size);
3612 return SANE_STATUS_GOOD;
3613 case OPT_GAMMA_VECTOR_G:
3614 memcpy (val, scanner->gamma_g, scanner->opt[option].size);
3615 return SANE_STATUS_GOOD;
3616 case OPT_GAMMA_VECTOR_B:
3617 memcpy (val, scanner->gamma_b, scanner->opt[option].size);
3618 return SANE_STATUS_GOOD;
3619
3620 case OPT_SOURCE:
3621 if (strcmp (val, "Automatic Slide Feeder") == 0)
3622 {
3623 /* Feed/Discharge/update filename/etc */
3624 }
3625 else
3626 {
3627 /* Reset above */
3628 }
3629 if (info)
3630 {
3631 *info |= SANE_INFO_RELOAD_PARAMS;
3632 }
3633 }
3634
3635 }
3636 else if (action == SANE_ACTION_SET_VALUE)
3637 {
3638 DBG (10, "sane_control_option %d, set value\n", option);
3639
3640 if (!SANE_OPTION_IS_ACTIVE (cap))
3641 return SANE_STATUS_INVAL;
3642
3643 if (!SANE_OPTION_IS_SETTABLE (cap))
3644 return SANE_STATUS_INVAL;
3645
3646 status = sanei_constrain_value (scanner->opt + option, val, info);
3647 if (status != SANE_STATUS_GOOD)
3648 return status;
3649
3650 switch (option)
3651 {
3652 case OPT_GAMMA_BIND:
3653 scanner->gamma_bind = (*(SANE_Word *) val == SANE_TRUE);
3654 if (scanner->LS != 1)
3655 {
3656 if (scanner->gamma_bind)
3657 {
3658 scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
3659 scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
3660 scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
3661 scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
3662
3663 }
3664 else
3665 {
3666 scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
3667 scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
3668 scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
3669 scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
3670
3671 }
3672 }
3673 if (info)
3674 {
3675 *info |= SANE_INFO_RELOAD_OPTIONS;
3676 }
3677 return SANE_STATUS_GOOD;
3678
3679 case OPT_ANALOG_GAMMA:
3680 scanner->analog_gamma_r = scanner->analog_gamma_g =
3681 scanner->analog_gamma_b = (*(SANE_Word *) val == SANE_TRUE);
3682 return SANE_STATUS_GOOD;
3683
3684 case OPT_AVERAGING:
3685 scanner->averaging = (*(SANE_Word *) val == SANE_TRUE);
3686 return SANE_STATUS_GOOD;
3687
3688 case OPT_PRESCAN:
3689 scanner->prescan = (*(SANE_Word *) val == SANE_TRUE);
3690 return SANE_STATUS_GOOD;
3691
3692 case OPT_PRESCAN_NOW:
3693 do_prescan_now(scanner);
3694 return SANE_STATUS_GOOD;
3695
3696 case OPT_BIT_DEPTH:
3697 scanner->bits_per_color=(*(SANE_Word *)val);
3698 if (info)
3699 *info |= SANE_INFO_RELOAD_PARAMS;
3700 return SANE_STATUS_GOOD;
3701
3702
3703 case OPT_RGB_CONTROL:
3704 scanner->rgb_control = (*(SANE_Word *) val == SANE_TRUE);
3705 if (scanner->rgb_control)
3706 {
3707 scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
3708 scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
3709 scanner->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3710
3711 scanner->opt[OPT_R_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
3712 scanner->opt[OPT_G_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
3713 scanner->opt[OPT_B_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
3714
3715 scanner->opt[OPT_R_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
3716 scanner->opt[OPT_G_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
3717 scanner->opt[OPT_B_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
3718
3719 scanner->opt[OPT_R_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3720 scanner->opt[OPT_G_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3721 scanner->opt[OPT_B_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3722
3723 scanner->contrast_R = 128;
3724 scanner->contrast_G = 128;
3725 scanner->contrast_B = 128;
3726 scanner->brightness_R = 128;
3727 scanner->brightness_G = 128;
3728 scanner->brightness_B = 128;
3729 scanner->exposure_R = 50;
3730 scanner->exposure_G = 50;
3731 scanner->exposure_B = 50;
3732 }
3733 else
3734 {
3735 scanner->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
3736 scanner->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
3737 scanner->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
3738
3739 scanner->contrast = 128;
3740 scanner->brightness = 128;
3741 scanner->exposure_R = 50;
3742 scanner->exposure_G = 50;
3743 scanner->exposure_B = 50;
3744
3745 scanner->opt[OPT_R_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
3746 scanner->opt[OPT_G_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
3747 scanner->opt[OPT_B_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
3748
3749 scanner->opt[OPT_R_CONTRAST].cap |= SANE_CAP_INACTIVE;
3750 scanner->opt[OPT_G_CONTRAST].cap |= SANE_CAP_INACTIVE;
3751 scanner->opt[OPT_B_CONTRAST].cap |= SANE_CAP_INACTIVE;
3752
3753 scanner->opt[OPT_R_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3754 scanner->opt[OPT_G_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3755 scanner->opt[OPT_B_EXPOSURE].cap |= SANE_CAP_INACTIVE;
3756 }
3757 if (info)
3758 {
3759 *info |= SANE_INFO_RELOAD_OPTIONS;
3760 }
3761 return SANE_STATUS_GOOD;
3762
3763 case OPT_RESOLUTION:
3764 scanner->y_nres = scanner->x_nres =
3765 resValToDiv (*(SANE_Word *) val);
3766
3767 if (info)
3768 *info |= SANE_INFO_RELOAD_PARAMS;
3769 return SANE_STATUS_GOOD;
3770
3771 case OPT_PREVIEW_RESOLUTION:
3772 scanner->y_p_nres = scanner->x_p_nres =
3773 resValToDiv (*(SANE_Word *) val);
3774
3775 if (info)
3776 *info |= SANE_INFO_RELOAD_PARAMS;
3777 return SANE_STATUS_GOOD;
3778
3779 case OPT_TL_X:
3780 scanner->tlx = mmToIlu (SANE_UNFIX (*(SANE_Word *) val));
3781 if (info)
3782 *info |= SANE_INFO_RELOAD_PARAMS;
3783
3784 return SANE_STATUS_GOOD;
3785
3786 case OPT_TL_Y:
3787 scanner->tly = mmToIlu (SANE_UNFIX (*(SANE_Word *) val));
3788 if (info)
3789 *info |= SANE_INFO_RELOAD_PARAMS;
3790 return SANE_STATUS_GOOD;
3791
3792 case OPT_BR_X:
3793 scanner->brx = mmToIlu (SANE_UNFIX (*(SANE_Word *) val));
3794 if (info)
3795 *info |= SANE_INFO_RELOAD_PARAMS;
3796 return SANE_STATUS_GOOD;
3797
3798 case OPT_BR_Y:
3799 scanner->bry = mmToIlu (SANE_UNFIX (*(SANE_Word *) val));
3800 if (info)
3801 *info |= SANE_INFO_RELOAD_PARAMS;
3802 return SANE_STATUS_GOOD;
3803
3804 case OPT_NUM_OPTS:
3805 return SANE_STATUS_GOOD;
3806
3807 case OPT_PREVIEW:
3808 scanner->preview = *(SANE_Word *) val;
3809 return SANE_STATUS_GOOD;
3810
3811 case OPT_AUTOFOCUS:
3812 if(strcmp(val,neverStr)==0)
3813 { scanner->autofocus=AF_NEVER;
3814 }
3815 if(strcmp(val,previewStr)==0)
3816 { scanner->autofocus=AF_PREVIEW;
3817 }
3818 if(strcmp(val,scanStr)==0)
3819 { scanner->autofocus=AF_SCAN;
3820 }
3821 if(strcmp(val,preandscanStr)==0)
3822 { scanner->autofocus=AF_PREANDSCAN;;
3823 }
3824 return SANE_STATUS_GOOD;
3825
3826 case OPT_CONTRAST:
3827 scanner->contrast = *(SANE_Word *) val + 128;
3828 return SANE_STATUS_GOOD;
3829 case OPT_R_CONTRAST:
3830 scanner->contrast_R = *(SANE_Word *) val + 128;
3831 return SANE_STATUS_GOOD;
3832 case OPT_G_CONTRAST:
3833 scanner->contrast_G = *(SANE_Word *) val + 128;
3834 return SANE_STATUS_GOOD;
3835 case OPT_B_CONTRAST:
3836 scanner->contrast_B = *(SANE_Word *) val + 128;
3837 return SANE_STATUS_GOOD;
3838
3839 case OPT_BRIGHTNESS:
3840 scanner->brightness = *(SANE_Word *) val + 128;
3841 return SANE_STATUS_GOOD;
3842 case OPT_R_BRIGHTNESS:
3843 scanner->brightness_R = *(SANE_Word *) val + 128;
3844 return SANE_STATUS_GOOD;
3845 case OPT_G_BRIGHTNESS:
3846 scanner->brightness_G = *(SANE_Word *) val + 128;
3847 return SANE_STATUS_GOOD;
3848 case OPT_B_BRIGHTNESS:
3849 scanner->brightness_B = *(SANE_Word *) val + 128;
3850 return SANE_STATUS_GOOD;
3851
3852 case OPT_EXPOSURE:
3853 scanner->exposure_R = *(SANE_Word *) val / 2;
3854 scanner->exposure_G = *(SANE_Word *) val / 2;
3855 scanner->exposure_B = *(SANE_Word *) val / 2;
3856 return SANE_STATUS_GOOD;
3857 case OPT_R_EXPOSURE:
3858 scanner->exposure_R = *(SANE_Word *) val / 2;
3859 return SANE_STATUS_GOOD;
3860 case OPT_G_EXPOSURE:
3861 scanner->exposure_G = *(SANE_Word *) val / 2;
3862 return SANE_STATUS_GOOD;
3863 case OPT_B_EXPOSURE:
3864 scanner->exposure_B = *(SANE_Word *) val / 2;
3865 return SANE_STATUS_GOOD;
3866
3867 case OPT_R_SHIFT:
3868 scanner->shift_R = *(SANE_Word *) val + 128;
3869 return SANE_STATUS_GOOD;
3870 case OPT_G_SHIFT:
3871 scanner->shift_G = *(SANE_Word *) val + 128;
3872 return SANE_STATUS_GOOD;
3873 case OPT_B_SHIFT:
3874 scanner->shift_B = *(SANE_Word *) val + 128;
3875 return SANE_STATUS_GOOD;
3876
3877 case OPT_IRED_RED:
3878 scanner->ired_red= *(SANE_Word *) val;
3879 return SANE_STATUS_GOOD;
3880
3881 case OPT_SOURCE:
3882 scanner->asf = (strcmp (val, "Automatic...") == 0);
3883 return SANE_STATUS_GOOD;
3884
3885 case OPT_TYPE:
3886 scanner->negative = (strcmp (val, negativeStr) == 0);
3887 if (info)
3888 {
3889 *info |= SANE_INFO_RELOAD_PARAMS;
3890 }
3891 return SANE_STATUS_GOOD;
3892 case OPT_MODE:
3893 if(strcmp(val,colorStr)==0)
3894 { scanner->colormode=RGB;
3895 scanner->colormode_p=RGB;
3896 }
3897 if(strcmp(val,grayStr)==0)
3898 { scanner->colormode=GREYSCALE;
3899 scanner->colormode_p=GREYSCALE;
3900 }
3901 if(strcmp(val,rgbiStr)==0)
3902 { scanner->colormode=RGBI;
3903 scanner->colormode_p=RGB;
3904 }
3905 if(strcmp(val,iredStr)==0)
3906 { scanner->colormode=IRED;
3907 scanner->colormode_p=GREYSCALE;
3908 }
3909 if (info)
3910 {
3911 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
3912 }
3913 return SANE_STATUS_GOOD;
3914
3915 case OPT_GAMMA_VECTOR:
3916 memcpy (scanner->gamma, val, scanner->opt[option].size);
3917 if(scanner->LS>2) Calc_fix_LUT(scanner);
3918 return SANE_STATUS_GOOD;
3919
3920 case OPT_GAMMA_VECTOR_R:
3921 memcpy (scanner->gamma_r, val, scanner->opt[option].size);
3922 if(scanner->LS>2) Calc_fix_LUT(scanner);
3923 return SANE_STATUS_GOOD;
3924
3925 case OPT_GAMMA_VECTOR_G:
3926 memcpy (scanner->gamma_g, val, scanner->opt[option].size);
3927 if(scanner->LS>2) Calc_fix_LUT(scanner);
3928 return SANE_STATUS_GOOD;
3929
3930 case OPT_GAMMA_VECTOR_B:
3931 memcpy (scanner->gamma_b, val, scanner->opt[option].size);
3932 if(scanner->LS>2) Calc_fix_LUT(scanner);
3933 return SANE_STATUS_GOOD;
3934
3935 } /* switch */
3936 } /* else */
3937 return SANE_STATUS_INVAL;
3938 }
3939
3940 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)3941 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
3942 {
3943 Coolscan_t *scanner = handle;
3944
3945 DBG (10, "sane_get_parameters");
3946 switch(scanner->colormode)
3947 { case RGB:
3948 params->format = SANE_FRAME_RGB;
3949 break;
3950 #ifdef HAS_IRED
3951 case RGBI:
3952 params->format = SANE_FRAME_RGBA;
3953 break;
3954 #endif /* HAS_RGBI */
3955 case GREYSCALE:
3956 params->format = SANE_FRAME_GRAY;
3957 break;
3958 }
3959
3960 params->depth = scanner->bits_per_color>8?16:8;
3961 params->pixels_per_line = pixels_per_line (scanner);
3962 params->lines = lines_per_scan (scanner);
3963 params->bytes_per_line = write_bytes_per_line (scanner);
3964 params->last_frame = 1;
3965 return SANE_STATUS_GOOD;
3966 }
3967 static int
swap_res(Coolscan_t * s)3968 swap_res (Coolscan_t * s)
3969 {
3970 if (s->preview)
3971 {
3972 /* swap preview/scan resolutions */
3973 int xres, yres, cmode;
3974 xres = s->x_nres;
3975 yres = s->y_nres;
3976 s->x_nres = s->x_p_nres;
3977 s->y_nres = s->y_p_nres;
3978
3979 s->x_p_nres = xres;
3980 s->y_p_nres = yres;
3981 cmode=s->colormode;
3982 s->colormode=s->colormode_p;
3983 s->colormode_p=cmode;
3984 }
3985 return 0;
3986 }
3987 SANE_Status
sane_start(SANE_Handle handle)3988 sane_start (SANE_Handle handle)
3989 {
3990 Coolscan_t *scanner = handle;
3991 int fds[2];
3992
3993 DBG (10, "sane_start\n");
3994 if (scanner->scanning == SANE_TRUE)
3995 return SANE_STATUS_DEVICE_BUSY;
3996
3997 if (scanner->sfd < 0)
3998 { /* first call */
3999 if (sanei_scsi_open (scanner->sane.name,
4000 &(scanner->sfd),
4001 sense_handler, 0) != SANE_STATUS_GOOD)
4002 {
4003 DBG (1, "sane_start: open of %s failed:\n",
4004 scanner->sane.name);
4005 return SANE_STATUS_INVAL;
4006 }
4007 }
4008 scanner->scanning = SANE_TRUE;
4009
4010
4011 if (coolscan_check_values (scanner) != 0)
4012 { /* Verify values */
4013 DBG (1, "ERROR: invalid scan-values\n");
4014 scanner->scanning = SANE_FALSE;
4015 coolscan_give_scanner (scanner);
4016 sanei_scsi_close (scanner->sfd);
4017 scanner->sfd = -1;
4018 return SANE_STATUS_INVAL;
4019 }
4020
4021 if (coolscan_grab_scanner (scanner))
4022 {
4023 sanei_scsi_close (scanner->sfd);
4024 scanner->sfd = -1;
4025 DBG (5, "WARNING: unable to reserve scanner: device busy\n");
4026 scanner->scanning = SANE_FALSE;
4027 return SANE_STATUS_DEVICE_BUSY;
4028 }
4029
4030 /* hoho, step 2c, -perm */
4031 coolscan_object_feed (scanner);
4032
4033 swap_res (scanner);
4034 if (!scanner->preview)
4035 { if(scanner->autofocus & 0x02)
4036 { coolscan_autofocus (scanner);
4037 }
4038 }
4039 else
4040 {
4041 if(scanner->autofocus & 0x01)
4042 { coolscan_autofocus (scanner);
4043 }
4044 if (scanner->prescan) {
4045 prescan (scanner);
4046 if(scanner->LS<2)
4047 { get_internal_info(scanner);
4048 }
4049 coolscan_get_window_param (scanner,1);
4050 }
4051 }
4052 /*read_LUT(scanner); */
4053 if(scanner->LS<2)
4054 { send_LUT (scanner);
4055 coolscan_set_window_param (scanner, 0);
4056 coolscan_get_window_param (scanner,0);
4057 coolscan_start_scan (scanner);
4058 }
4059 else
4060 { coolscan_set_window_param (scanner, 0);
4061 send_LUT (scanner);
4062 Calc_fix_LUT(scanner);
4063 coolscan_start_scan (scanner);
4064 wait_scanner (scanner);
4065 coolscan_get_window_param (scanner,0);
4066 }
4067
4068 DBG (10, "bytes per line = %d\n", scan_bytes_per_line (scanner));
4069 DBG (10, "pixels_per_line = %d\n", pixels_per_line (scanner));
4070 DBG (10, "lines = %d\n", lines_per_scan (scanner));
4071 DBG (10, "negative = %d\n", scanner->negative);
4072 DBG (10, "brightness (halftone) = %d\n", scanner->brightness);
4073 DBG (10, "contrast (halftone) = %d\n", scanner->contrast);
4074 DBG (10, "fast preview function = %d\n", scanner->preview);
4075
4076 /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */
4077 if (pipe (fds) < 0)
4078 {
4079 DBG (1, "ERROR: could not create pipe\n");
4080
4081 swap_res (scanner);
4082 scanner->scanning = SANE_FALSE;
4083 coolscan_give_scanner (scanner);
4084 sanei_scsi_close (scanner->sfd);
4085 scanner->sfd = -1;
4086 return SANE_STATUS_IO_ERROR;
4087 }
4088
4089 scanner->pipe = fds[0];
4090 scanner->reader_fds = fds[1];
4091 scanner->reader_pid = sanei_thread_begin( reader_process, (void*)scanner );
4092 if (!sanei_thread_is_valid (scanner->reader_pid))
4093 {
4094 DBG (1, "sane_start: sanei_thread_begin failed (%s)\n",
4095 strerror (errno));
4096 return SANE_STATUS_NO_MEM;
4097 }
4098
4099 if (sanei_thread_is_forked ())
4100 {
4101 close (scanner->reader_fds);
4102 scanner->reader_fds = -1;
4103 }
4104
4105 return SANE_STATUS_GOOD;
4106 }
4107
4108
4109 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)4110 sane_read (SANE_Handle handle, SANE_Byte * buf,
4111 SANE_Int max_len, SANE_Int * len)
4112 {
4113 Coolscan_t *scanner = handle;
4114 ssize_t nread;
4115
4116 *len = 0;
4117
4118 nread = read (scanner->pipe, buf, max_len);
4119 DBG (10, "sane_read: read %ld bytes\n", (long) nread);
4120
4121 if (!(scanner->scanning))
4122 {
4123 return do_cancel (scanner);
4124 }
4125
4126 if (nread < 0)
4127 {
4128 if (errno == EAGAIN)
4129 {
4130 return SANE_STATUS_GOOD;
4131 }
4132 else
4133 {
4134 do_cancel (scanner);
4135 return SANE_STATUS_IO_ERROR;
4136 }
4137 }
4138
4139 *len = nread;
4140
4141 if (nread == 0)
4142 return do_eof (scanner); /* close pipe */
4143
4144 return SANE_STATUS_GOOD;
4145 }
4146
4147 void
sane_cancel(SANE_Handle handle)4148 sane_cancel (SANE_Handle handle)
4149 {
4150 Coolscan_t *s = handle;
4151
4152 if (sanei_thread_is_valid (s->reader_pid))
4153 {
4154 sanei_thread_kill ( s->reader_pid );
4155 sanei_thread_waitpid( s->reader_pid, NULL );
4156 sanei_thread_invalidate (s->reader_pid);
4157 }
4158 swap_res (s);
4159 s->scanning = SANE_FALSE;
4160 }
4161
4162
4163 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)4164 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
4165 {
4166 Coolscan_t *scanner = handle;
4167
4168 DBG (10, "sane_set_io_mode: non_blocking=%d\n", non_blocking);
4169
4170 if (!scanner->scanning)
4171 return SANE_STATUS_INVAL;
4172
4173 if (fcntl (scanner->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
4174 return SANE_STATUS_IO_ERROR;
4175
4176 return SANE_STATUS_GOOD;
4177 }
4178
4179 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)4180 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
4181 {
4182 Coolscan_t *scanner = handle;
4183
4184 DBG (10, "sane_get_select_fd\n");
4185
4186 if (!scanner->scanning)
4187 {
4188 return SANE_STATUS_INVAL;
4189 }
4190 *fd = scanner->pipe;
4191
4192 return SANE_STATUS_GOOD;
4193 }
4194