1 /* sane - Scanner Access Now Easy.
2
3 This file (C) 1997 Ingo Schneider
4 (C) 1998 Karl Anders Øygard
5
6 This file is part of the SANE package.
7
8 SANE is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2 of the License, or (at your
11 option) any later version.
12
13 SANE is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with sane; see the file COPYING.
20 If not, see <https://www.gnu.org/licenses/>.
21
22 This file implements a SANE backend for AGFA Focus flatbed scanners. */
23
24 #include "../include/sane/config.h"
25
26 #include <signal.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <sys/types.h>
33
34 #include "../include/sane/sane.h"
35 #include "../include/sane/sanei.h"
36 #include "../include/sane/sanei_config.h"
37 #include "../include/sane/saneopts.h"
38 #include "../include/sane/sanei_scsi.h"
39 #include "../include/sane/sanei_thread.h"
40
41 #define BACKEND_NAME agfafocus
42 #include "../include/sane/sanei_backend.h"
43
44 #include "agfafocus.h"
45
46 #ifndef PATH_MAX
47 # define PATH_MAX 1024
48 #endif
49
50
51 #undef Byte
52 #define Byte SANE_Byte
53
54 static const SANE_Device **devlist = 0;
55 static int num_devices;
56 static AgfaFocus_Device *agfafocus_devices;
57
58 static const SANE_String_Const focus_mode_list[] =
59 {
60 "Lineart", "Gray (6 bit)",
61 0
62 };
63
64 static const SANE_String_Const focusii_mode_list[] =
65 {
66 "Lineart", "Gray (6 bit)", "Gray (8 bit)",
67 0
68 };
69
70 static const SANE_String_Const focuscolor_mode_list[] =
71 {
72 "Lineart", "Gray (6 bit)", "Gray (8 bit)", "Color (18 bit)", "Color (24 bit)",
73 0
74 };
75
76 static const SANE_String_Const halftone_list[] =
77 {
78 "None", "Dispersed dot 4x4", "Round (Clustered dot 4x4)", "Diamond (Clustered dot 4x4)",
79 0
80 };
81
82 static const SANE_String_Const halftone_upload_list[] =
83 {
84 "None", "Dispersed dot 4x4", "Round (Clustered dot 4x4)", "Diamond (Clustered dot 4x4)",
85 0
86 };
87
88 static const SANE_String_Const source_list[] =
89 {
90 "Opaque/Normal", "Transparency",
91 0
92 };
93
94 static const SANE_String_Const quality_list[] =
95 {
96 "Low", "Normal", "High",
97 0
98 };
99
100 static size_t
max_string_size(const SANE_String_Const strings[])101 max_string_size (const SANE_String_Const strings[])
102 {
103 size_t size, max_size = 0;
104 int i;
105 DBG (11, ">> max_string_size\n");
106
107 for (i = 0; strings[i]; ++i)
108 {
109 size = strlen (strings[i]) + 1;
110 if (size > max_size)
111 max_size = size;
112 }
113
114 DBG (11, "<< max_string_size\n");
115 return max_size;
116 }
117
118 /* sets loc_s bytes long value at offset loc in scsi command to value size */
119 static void
set_size(Byte * loc,int loc_s,size_t size)120 set_size (Byte * loc, int loc_s, size_t size)
121 {
122 int i;
123
124 for (i = 0; i < loc_s; i++)
125 {
126 loc[loc_s - i - 1] = (size >> (i * 8)) & 0xff;
127 }
128 }
129
130 /* gets loc_s bytes long value from loc in scsi command */
131 static int
get_size(Byte * loc,int loc_s)132 get_size (Byte * loc, int loc_s)
133 {
134 int i;
135 int j = 0;
136
137 for (i = 0; i < loc_s; i++)
138 {
139 j = (j << 8) + (loc[i] & 0xff);
140 }
141
142 return j;
143 }
144
145 static long
reserve_unit(int fd)146 reserve_unit (int fd)
147 {
148 struct
149 {
150 /* Command */
151 Byte cmd;
152 Byte lun;
153 Byte res[2];
154 Byte tr_len;
155 Byte ctrl;
156 }
157 scsi_reserve;
158
159 memset (&scsi_reserve, 0, sizeof (scsi_reserve));
160
161 scsi_reserve.cmd = 0x16; /* RELEASE */
162
163 DBG (3, "reserve_unit()\n");
164 return sanei_scsi_cmd (fd, &scsi_reserve, sizeof (scsi_reserve), 0, 0);
165 }
166
167 static long
release_unit(int fd)168 release_unit (int fd)
169 {
170 struct
171 {
172 /* Command */
173 Byte cmd;
174 Byte lun;
175 Byte res[2];
176 Byte tr_len;
177 Byte ctrl;
178 }
179 scsi_release;
180
181 memset (&scsi_release, 0, sizeof (scsi_release));
182
183 scsi_release.cmd = 0x17; /* RELEASE */
184
185 DBG (3, "release_unit()\n");
186 return sanei_scsi_cmd (fd, &scsi_release, sizeof (scsi_release), 0, 0);
187 }
188
189 static SANE_Status
test_ready(int fd)190 test_ready (int fd)
191 {
192 SANE_Status status;
193 int try;
194
195 struct
196 {
197 /* Command */
198 Byte cmd;
199 Byte lun;
200 Byte res[2];
201 Byte tr_len;
202 Byte ctrl;
203 }
204 scsi_test_ready;
205
206 memset (&scsi_test_ready, 0, sizeof (scsi_test_ready));
207
208 scsi_test_ready.cmd = 0x00; /* TEST UNIT READY */
209
210 for (try = 0; try < 1000; ++try)
211 {
212 DBG (3, "test_ready: sending TEST_UNIT_READY\n");
213 status = sanei_scsi_cmd (fd, &scsi_test_ready, sizeof (scsi_test_ready),
214 0, 0);
215
216 switch (status)
217 {
218 case SANE_STATUS_DEVICE_BUSY:
219 usleep (100000); /* retry after 100ms */
220 break;
221
222 case SANE_STATUS_GOOD:
223 return status;
224
225 default:
226 DBG (1, "test_ready: test unit ready failed (%s)\n",
227 sane_strstatus (status));
228 return status;
229 }
230 }
231
232 DBG (1, "test_ready: timed out after %d attempts\n", try);
233 return SANE_STATUS_IO_ERROR;
234 }
235
236 static SANE_Status
sense_handler(int scsi_fd,u_char * result,void * arg)237 sense_handler (int scsi_fd, u_char *result, void *arg)
238 {
239 (void) scsi_fd; /* silence gcc */
240 (void) arg; /* silence gcc */
241
242 if (result[0])
243 {
244 DBG (0, "sense_handler() : sense code = %02x\n", result[0]);
245 return SANE_STATUS_IO_ERROR;
246 }
247 else
248 {
249 return SANE_STATUS_GOOD;
250 }
251 }
252
253 static SANE_Status
stop_scan(int fd)254 stop_scan (int fd)
255 {
256 (void) fd; /* silence gcc */
257
258 /* XXX don't know how to stop the scanner. To be tested ! */
259 #if 0
260 const Byte scsi_rewind[] =
261 {
262 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
263 };
264 DBG (1, "Trying to stop scanner...\n");
265 return sanei_scsi_cmd (fd, scsi_rewind, sizeof (scsi_rewind), 0, 0);
266 #else
267 return SANE_STATUS_GOOD;
268 #endif
269 }
270
271
272 static SANE_Status
start_scan(int fd,SANE_Bool cont)273 start_scan (int fd, SANE_Bool cont)
274 {
275 struct
276 {
277 /* Command */
278 Byte cmd;
279 Byte lun;
280 Byte res[2];
281 Byte tr_len;
282 Byte ctrl;
283
284 /* Data */
285 Byte wid;
286 }
287 scsi_start_scan;
288
289 memset (&scsi_start_scan, 0, sizeof (scsi_start_scan));
290
291 scsi_start_scan.cmd = 0x1b; /* SCAN */
292 scsi_start_scan.tr_len = 1;
293 scsi_start_scan.wid = 0;
294 scsi_start_scan.ctrl = (cont == SANE_TRUE) ? 0x80 : 0x00;
295
296 DBG (1, "Starting scanner ...\n");
297 return sanei_scsi_cmd (fd, &scsi_start_scan, sizeof (scsi_start_scan), 0, 0);
298 }
299
300 static void
wait_ready(int fd)301 wait_ready (int fd)
302 {
303 struct
304 {
305 Byte bytes[2]; /* Total # of bytes */
306 Byte scan[2]; /* ms to complete - driver sleep time */
307 } result;
308
309 size_t size = sizeof (result);
310 SANE_Status status;
311
312 struct {
313 Byte cmd;
314 Byte lun;
315 Byte data_type;
316 Byte re1[3];
317 Byte tr_len[3];
318 Byte ctrl;
319 } cmd;
320
321 memset (&cmd, 0, sizeof (cmd));
322
323 cmd.cmd = 0x28; /* READ */
324 cmd.data_type = 0x80; /* get scan time */
325
326 set_size (cmd.tr_len, 3, sizeof (result));
327
328 while (1)
329 {
330 status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd),
331 &result, &size);
332
333 if (status != SANE_STATUS_GOOD || size != sizeof (result))
334 {
335 /*
336 Command failed, the assembler code of the windows scan library
337 ignores this condition, and so do I
338 */
339 break;
340 }
341 else
342 {
343 /* left is the amount of seconds left till the scanner is
344 ready * 100 */
345 int left = get_size (result.scan, 2);
346
347 DBG (1, "wait_ready() : %d left...\n", left);
348
349 if (!left)
350 break;
351 /* We delay only for half the given time */
352 else if (left < 200)
353 usleep (left * 5000);
354 else
355 sleep (left / 200);
356 }
357 }
358
359 return;
360 }
361
362 static SANE_Status
get_read_sizes(int fd,int * lines_available,int * bpl,int * total_lines)363 get_read_sizes (int fd, int *lines_available, int *bpl, int *total_lines)
364 {
365 struct {
366 Byte reserved1[8];
367 Byte line_width[2];
368 Byte total_lines[2];
369 Byte cur_line[2];
370 Byte lines_this_block[2];
371 Byte reserved[8];
372 } read_sizes;
373
374 const Byte scsi_read[] =
375 {
376 0x28, 0x00, /* opcode, lun */
377 0x81, /* data type 81 == read time left */
378 0x00, 0x00, 0x00, /* reserved */
379 0x00, 0x00, sizeof (read_sizes), /* transfer length */
380 0x00, /* control byte */
381 };
382
383 size_t size = sizeof (read_sizes);
384 SANE_Status status;
385
386 status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read), &read_sizes, &size);
387
388 if (status != SANE_STATUS_GOOD || size != sizeof (read_sizes))
389 {
390 /* Command failed */
391 return SANE_STATUS_IO_ERROR;
392 }
393 else
394 {
395 *lines_available = get_size (read_sizes.lines_this_block, 2);
396 *bpl = get_size (read_sizes.cur_line, 2);
397 if (total_lines)
398 *total_lines = get_size (read_sizes.total_lines, 2);
399 }
400
401 DBG (1, "get_read_sizes() : %d of %d, %d\n",
402 *lines_available, total_lines ? *total_lines : -1, *bpl);
403
404 return SANE_STATUS_GOOD;
405 }
406
407 static SANE_Status
set_window(AgfaFocus_Scanner * s)408 set_window (AgfaFocus_Scanner * s)
409 /* This function sets and sends the window for scanning */
410 {
411 double pixels_per_mm = (double) s->val[OPT_RESOLUTION].w / MM_PER_INCH;
412
413 SANE_Bool auto_bright = s->val[OPT_AUTO_BRIGHTNESS].b;
414 SANE_Bool auto_contr = s->val[OPT_AUTO_CONTRAST].b;
415
416 /* ranges down 255 (dark) down to 1(bright) */
417 int brightness = auto_bright ? 0 : (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)
418 * -1.27 + 128.5);
419 /* ranges from 1 (little contrast) up to 255 (much contrast) */
420 int contrast = auto_contr ? 0 : (SANE_UNFIX (s->val[OPT_CONTRAST].w)
421 * 1.27 + 128.5);
422
423 int width;
424
425 /* ranges from 40 (dark) down to 0 (bright) */
426 int bright_adjust = (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) * -20.0) / 100.0 + 20.0;
427
428 /* ranges from 20 (little contrast) down to -20 = 235 (much contrast) */
429 int contr_adjust = (SANE_UNFIX (s->val[OPT_CONTRAST].w) * -20.0) / 100.0;
430
431 /* Warning ! The following structure SEEMS to be a valid SCSI-2 SET_WINDOW
432 command. But e.g. the limits for the window are only 2 Bytes instead
433 of 4. The scanner was built at about 1990, so SCSI-2 wasn't available
434 for development... */
435
436 struct
437 {
438 Byte cmd;
439 Byte lun;
440 Byte re1[4];
441 Byte tr_len[3];
442 Byte ctrl;
443
444 Byte re2[6];
445 Byte wd_len[2];
446
447 struct
448 {
449 Byte wid; /* Window ID */
450 Byte autobit; /* Window creation */
451
452 Byte x_axis_res[2]; /* X resolution */
453 Byte y_axis_res[2]; /* X resolution */
454
455 Byte x_axis_ul[2]; /* X upper left */
456 Byte y_axis_ul[2]; /* Y upper left */
457
458 Byte wwidth[2]; /* Width */
459 Byte wlength[2]; /* Length */
460
461 Byte contrast; /* Contrast */
462 Byte dummy1;
463 Byte intensity; /* Intensity */
464
465 Byte image_comp; /* Image composition (0, 2, 5) */
466 Byte bpp; /* Bits per pixel */
467
468 Byte tonecurve; /* Tone curve (0 - 8) */
469 Byte ht_pattern; /* Halftone pattern */
470 Byte paddingtype; /* Padding type */
471
472 Byte bitordering[2]; /* Bit ordering (0 = left to right) */
473 Byte comprtype; /* Compression type */
474 Byte comprarg; /* Compression argument */
475
476 Byte dummy2[6];
477 Byte edge; /* Sharpening (0 - 7) */
478 Byte dummy3;
479
480 Byte bright_adjust; /* */
481 Byte contr_adjust; /* */
482
483 Byte imagewidthtruncation; /* */
484
485 Byte dummy4;
486 Byte quality_type; /* 0 normal, 1 high, 255 low */
487 Byte red_att;
488 Byte green_att;
489 Byte blue_att;
490
491 Byte dummy5[5];
492 Byte color_planes;
493 Byte orig_type;
494 Byte fixturetype;
495 Byte exposure[2];
496 Byte defocus[2];
497 Byte dummy6[4];
498 Byte descreen_factor;
499
500 Byte packing_word_length;
501 Byte packing_number_of_pixels;
502 Byte packing_color_mode;
503 Byte strokenab;
504 Byte rotatenab;
505 Byte autostrokenab;
506 Byte dummy7;
507 }
508 wd;
509
510 }
511 cmd;
512
513 memset (&cmd, 0, sizeof (cmd));
514
515 cmd.cmd = 0x24; /* SET WINDOW PARAMETERS */
516
517 switch (s->hw->type)
518 {
519 case AGFAGRAY64:
520 case AGFALINEART:
521 case AGFAGRAY256:
522 set_size (cmd.tr_len, 3, 36 + 8);
523 set_size (cmd.wd_len, 2, 36);
524 break;
525
526 case AGFACOLOR:
527 set_size (cmd.tr_len, 3, 65 + 8);
528 set_size (cmd.wd_len, 2, 65);
529 break;
530 }
531
532 /* Resolution. Original comment in German: Aufloesung */
533 set_size (cmd.wd.x_axis_res, 2, s->val[OPT_RESOLUTION].w);
534 set_size (cmd.wd.y_axis_res, 2, s->val[OPT_RESOLUTION].w);
535
536 /* Scan window position/size. Original comment in German:
537 Fensterposition / Groesse */
538 set_size (cmd.wd.x_axis_ul, 2,
539 SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5);
540 set_size (cmd.wd.y_axis_ul, 2,
541 SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5);
542
543 width = (SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * pixels_per_mm) + 0.5;
544
545 if (s->bpp == 1 && width % 8)
546 width += 8 - width % 8;
547
548 set_size (cmd.wd.wwidth, 2, width);
549 set_size (cmd.wd.wlength, 2, SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w)
550 * pixels_per_mm + 0.5);
551
552 cmd.wd.bpp = s->bpp;
553
554 if (s->mode == COLOR18BIT ||
555 s->mode == COLOR24BIT)
556 {
557 cmd.wd.paddingtype = 3;
558 cmd.wd.ht_pattern = 3;
559
560 cmd.wd.red_att = s->r_att;
561 cmd.wd.blue_att = s->g_att;
562 cmd.wd.green_att = s->b_att;
563 cmd.wd.color_planes = 0x0e;
564
565 set_size (cmd.wd.exposure, 2, s->exposure);
566
567 cmd.wd.packing_word_length = 1;
568 cmd.wd.packing_number_of_pixels = 1;
569 cmd.wd.packing_color_mode = 2;
570
571 if (s->bpp == 6)
572 cmd.wd.edge = s->edge;
573
574 DBG (3,
575 "Setting parameters: imc %d, bpp %d, res %d, exp %d, attenuation [%d, %d, %d], edge %d\n",
576 s->image_composition, s->bpp, s->val[OPT_RESOLUTION].w,
577 s->exposure, cmd.wd.red_att, cmd.wd.blue_att, cmd.wd.green_att, s->edge);
578 }
579 else
580 {
581 if (s->bpp == 1)
582 cmd.wd.ht_pattern = s->halftone;
583 else
584 cmd.wd.ht_pattern = 3;
585
586 cmd.wd.intensity = brightness;
587 cmd.wd.contrast = contrast;
588
589 cmd.wd.contr_adjust = contr_adjust;
590 cmd.wd.bright_adjust = bright_adjust;
591
592 cmd.wd.tonecurve = s->tonecurve;
593 cmd.wd.paddingtype = 3;
594 cmd.wd.edge = s->edge;
595
596 if (s->lin_log)
597 cmd.wd.dummy3 = 0x02;
598
599 DBG (3,
600 "Setting parameters: imc %d, bpp %d, res %d, bri %d, con %d, bad %d, cad %d, ht %d, edge %d\n",
601 s->image_composition, s->bpp, s->val[OPT_RESOLUTION].w,
602 brightness, contrast, bright_adjust, contr_adjust, s->halftone, s->edge);
603 }
604
605 cmd.wd.image_comp = s->image_composition;
606 cmd.wd.quality_type = s->quality;
607 cmd.wd.orig_type = s->original;
608
609 return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0);
610 }
611
612 /* Tell scanner to scan more data. */
613
614 static SANE_Status
request_more_data(AgfaFocus_Scanner * s)615 request_more_data (AgfaFocus_Scanner * s)
616 {
617 SANE_Status status;
618 int lines_available;
619 int bytes_per_line;
620
621 status = start_scan (s->fd, SANE_TRUE);
622 if (status != SANE_STATUS_GOOD)
623 return status;
624
625 if (!s->hw->disconnect)
626 wait_ready (s->fd);
627
628 status = get_read_sizes (s->fd, &lines_available, &bytes_per_line, 0);
629
630 if (!lines_available)
631 return SANE_STATUS_INVAL;
632
633 s->lines_available = lines_available;
634
635 return SANE_STATUS_GOOD;
636 }
637
638 static SANE_Status
upload_dither_matrix(AgfaFocus_Scanner * s,int rows,int cols,int * dither_matrix)639 upload_dither_matrix (AgfaFocus_Scanner * s, int rows, int cols, int *dither_matrix)
640 {
641 struct {
642 Byte cmd;
643 Byte lun;
644 Byte data_type;
645 Byte re1[3];
646 Byte tr_len[3];
647 Byte ctrl;
648
649 struct {
650 Byte nrrows[2];
651 Byte nrcols[2];
652
653 struct {
654 Byte data[2];
655 } element[256];
656 } wd;
657 } cmd;
658
659 SANE_Status status;
660 int i;
661
662 memset (&cmd, 0, sizeof (cmd));
663
664 cmd.cmd = 0x2a; /* WRITE */
665 cmd.data_type = 0x81; /* upload dither matrix */
666
667 set_size (cmd.tr_len, 3, 4 + (2 * rows * cols));
668 set_size (cmd.wd.nrrows, 2, rows);
669 set_size (cmd.wd.nrcols, 2, cols);
670
671 for (i = 0; i < cols * rows; ++i)
672 set_size (cmd.wd.element[i].data, 2, dither_matrix[i]);
673
674 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0);
675
676 if (status != SANE_STATUS_GOOD)
677 /* Command failed */
678 return SANE_STATUS_IO_ERROR;
679
680 DBG (1, "upload_dither_matrix(): uploaded dither matrix: %d, %d\n", rows, cols);
681
682 return SANE_STATUS_GOOD;
683 }
684
685 #if 0
686 static SANE_Status
687 upload_tonecurve (AgfaFocus_Scanner * s, int color_type, int input, int output, int dither_matrix[256])
688 {
689 struct {
690 Byte cmd;
691 Byte lun;
692 Byte re1[4];
693 Byte tr_len[3];
694 Byte ctrl;
695
696 Byte re2[6];
697 Byte wd_len[2];
698
699 struct {
700 Byte color_type[2];
701 Byte nrinput[2];
702 Byte nroutput[2];
703
704 struct {
705 Byte data[2];
706 } outputval[256];
707 } wd;
708 } cmd;
709
710 SANE_Status status;
711 int i, j;
712
713 memset (&cmd, 0, sizeof (cmd));
714
715 cmd.cmd = 0x80;
716
717 set_size (cmd.tr_len, 3, sizeof (cmd.wd));
718 set_size (cmd.wd.nrrows, 2, rows);
719 set_size (cmd.wd.nrrows, 2, cols);
720
721 for (i = 0; i < cols; ++i)
722 for (j = 0; j < rows; ++j)
723 set_size (cmd.wd.element[j + i * rows].data, 2, dither_matrix[j + i * rows]);
724
725 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0);
726
727 if (status != SANE_STATUS_GOOD)
728 /* * Command failed * */
729 return SANE_STATUS_IO_ERROR;
730
731 DBG (1, "upload_dither_matrix(): uploaded dither matrix\n");
732
733 return SANE_STATUS_GOOD;
734 }
735 #endif
736
737 /* May only be called when there is at least one row of data to
738 be read.
739
740 Original comment in German: Darf nur aufgerufen werden, wenn
741 wirklich noch Zeilen zu scannen/lesen sind ! */
742 static SANE_Status
read_data(AgfaFocus_Scanner * s,SANE_Byte * buf,int lines,int bpl)743 read_data (AgfaFocus_Scanner * s, SANE_Byte *buf, int lines, int bpl)
744 {
745 struct {
746 Byte cmd;
747 Byte lun;
748 Byte re1[4];
749 Byte tr_len[3];
750 Byte ctrl;
751 } cmd;
752
753 SANE_Status status;
754 size_t size;
755 unsigned int i;
756
757 memset (&cmd, 0, sizeof (cmd));
758
759 cmd.cmd = 0x28; /* READ */
760
761 set_size (cmd.tr_len, 3, lines);
762 size = lines * bpl;
763
764 status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, &size);
765
766 if (status != SANE_STATUS_GOOD)
767 {
768 DBG (1, "sanei_scsi_cmd() = %d\n", status);
769 return SANE_STATUS_IO_ERROR;
770 }
771
772 if (size != ((unsigned int) lines * bpl))
773 {
774 DBG (1, "sanei_scsi_cmd(): got %lu bytes, expected %d\n",
775 (u_long) size, lines * bpl);
776 return SANE_STATUS_INVAL;
777 }
778
779 DBG (1, "Got %lu bytes\n", (u_long) size);
780
781 /* Reverse: */
782 if (s->bpp != 1)
783 {
784 if (s->bpp != 6)
785 for (i = 0; i < size; i++)
786 buf[i] = 255 - buf[i];
787 else
788 for (i = 0; i < size; i++)
789 buf[i] = 255 - ((buf[i] * 256.0f) / 64.0f);
790 }
791
792 s->lines_available -= lines;
793
794 return SANE_STATUS_GOOD;
795 }
796
797
798 static SANE_Status
attach(const char * devname,AgfaFocus_Device ** devp)799 attach (const char *devname, AgfaFocus_Device ** devp)
800 {
801 #define ATTACH_SCSI_INQ_LEN 55
802 const Byte scsi_inquiry[] =
803 {
804 0x12, 0x00, 0x00, 0x00, ATTACH_SCSI_INQ_LEN, 0x00
805 };
806 Byte result[ATTACH_SCSI_INQ_LEN];
807
808 int fd;
809 AgfaFocus_Device *dev;
810 SANE_Status status;
811 size_t size;
812 int i;
813
814 for (dev = agfafocus_devices; dev; dev = dev->next)
815 if (strcmp (dev->sane.name, devname) == 0)
816 {
817 if (devp)
818 *devp = dev;
819 return SANE_STATUS_GOOD;
820 }
821
822 DBG (3, "attach: opening %s\n", devname);
823 status = sanei_scsi_open (devname, &fd, sense_handler, 0);
824 if (status != SANE_STATUS_GOOD)
825 {
826 DBG (1, "attach: open failed (%s)\n", sane_strstatus (status));
827 return SANE_STATUS_INVAL;
828 }
829
830 DBG (4, "attach: sending INQUIRY\n");
831 size = sizeof (result);
832 status = sanei_scsi_cmd (fd, scsi_inquiry, sizeof (scsi_inquiry),
833 result, &size);
834 if (status != SANE_STATUS_GOOD || size != ATTACH_SCSI_INQ_LEN)
835 {
836 DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status));
837 sanei_scsi_close (fd);
838 return status;
839 }
840
841 status = test_ready (fd);
842 sanei_scsi_close (fd);
843 if (status != SANE_STATUS_GOOD)
844 return status;
845
846 /* The structure send by the scanner after inquiry is not SCSI-2
847 compatible. The standard manufacturer/model fields are no ASCII
848 strings, but ? At offset 36 my SIEMENS scanner identifies as an
849 AGFA one ?! */
850
851 if (result[0] != 6 || strncmp ((char *)result + 36, "AGFA0", 5))
852 {
853 DBG (1, "attach: device doesn't look like a Siemens 9036 scanner\n");
854 return SANE_STATUS_INVAL;
855 }
856
857 DBG (4, "Inquiry data:\n");
858 DBG (4, "-----------\n");
859 for (i = 5; i < 55; i += 10)
860 DBG (4, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
861 result[i], result[i + 1], result[i + 2], result[i + 3], result[i + 4],
862 result[i + 5], result[i + 6], result[i + 7], result[i + 8],
863 result[i + 9]);
864
865 dev = malloc (sizeof (*dev));
866
867 if (!dev)
868 return SANE_STATUS_NO_MEM;
869
870 memset (dev, 0, sizeof (*dev));
871
872 dev->sane.name = strdup (devname);
873 if (!strncmp ((char *)result + 36, "AGFA01", 6)) {
874 dev->sane.vendor = "AGFA";
875 dev->sane.model = "Focus GS Scanner (6 bit)";
876 dev->upload_user_defines = SANE_TRUE;
877 dev->type = AGFAGRAY64;
878 } else if (!strncmp ((char *)result + 36, "AGFA02", 6)) {
879 dev->sane.vendor = "AGFA";
880 dev->sane.model = "Focus Lineart Scanner";
881 dev->upload_user_defines = SANE_FALSE;
882 dev->type = AGFALINEART;
883 } else if (!strncmp ((char *)result + 36, "AGFA03", 6)) {
884 dev->sane.vendor = "AGFA";
885 dev->sane.model = "Focus II";
886 dev->upload_user_defines = SANE_TRUE;
887 dev->type = AGFAGRAY256;
888 } else if (!strncmp ((char *)result + 36, "AGFA04", 6)) {
889 dev->sane.vendor = "AGFA";
890 dev->sane.model = "Focus Color";
891 dev->upload_user_defines = SANE_TRUE;
892 dev->type = AGFACOLOR;
893 } else {
894 free (dev);
895 DBG (1, "attach: device looks like an AGFA scanner, but wasn't recognised\n");
896 return SANE_STATUS_INVAL;
897 }
898 dev->sane.type = "flatbed scanner";
899
900 dev->transparent = result[45] & 0x80 ? SANE_TRUE : SANE_FALSE;
901 dev->analoglog = result[46] & 0x80 ? SANE_TRUE : SANE_FALSE;
902 dev->tos5 = result[46] & 0x05 ? SANE_TRUE : SANE_FALSE;
903 dev->quality = result[47] & 0x40 ? SANE_TRUE : SANE_FALSE;
904 dev->disconnect = result[47] & 0x80 ? SANE_TRUE : SANE_FALSE;
905
906 DBG (4, "\n");
907 DBG (4, "scan modes:\n");
908 DBG (4, "-----------\n");
909 DBG (4, "three pass color mode: %s\n", dev->type >= AGFACOLOR ? "yes" : "no");
910 DBG (4, "8 bit gray mode: %s\n", dev->type >= AGFAGRAY64 ? "yes" : "no");
911 DBG (4, "uploadable matrices: %s\n", dev->upload_user_defines ? "yes" : "no");
912 DBG (4, "transparency: %s\n", dev->transparent ? "yes" : "no");
913 DBG (4, "disconnect: %s\n", dev->disconnect ? "yes" : "no");
914 DBG (4, "quality calibration: %s\n", dev->quality ? "yes" : "no");
915
916 dev->handle = 0;
917
918 DBG (3, "attach: found AgfaFocus scanner model\n");
919
920 ++num_devices;
921 dev->next = agfafocus_devices;
922 agfafocus_devices = dev;
923
924 if (devp)
925 *devp = dev;
926
927 return SANE_STATUS_GOOD;
928 }
929
930 static SANE_Status
do_eof(AgfaFocus_Scanner * s)931 do_eof (AgfaFocus_Scanner *s)
932 {
933 if (s->pipe >= 0)
934 {
935 close (s->pipe);
936 s->pipe = -1;
937 }
938 return SANE_STATUS_EOF;
939 }
940
941
942 static SANE_Status
do_cancel(AgfaFocus_Scanner * s)943 do_cancel (AgfaFocus_Scanner * s)
944 {
945 s->scanning = SANE_FALSE;
946 s->pass = 0;
947
948 do_eof (s);
949
950 if (sanei_thread_is_valid (s->reader_pid))
951 {
952 int exit_status;
953
954 /* ensure child knows it's time to stop: */
955 sanei_thread_kill (s->reader_pid);
956 sanei_thread_waitpid (s->reader_pid, &exit_status);
957 sanei_thread_invalidate(s->reader_pid);
958 }
959
960 if (s->fd >= 0)
961 {
962 stop_scan (s->fd);
963 release_unit (s->fd);
964 sanei_scsi_close (s->fd);
965 s->fd = -1;
966 }
967
968 return SANE_STATUS_CANCELLED;
969 }
970
971
972 static SANE_Status
init_options(AgfaFocus_Scanner * s)973 init_options (AgfaFocus_Scanner * s)
974 {
975 int i;
976
977 /* Hardware Limitations: must be static ! */
978 static const SANE_Int dpi_list[] =
979 {8, 100, 200, 300, 400, 500, 600, 700, 800};
980
981 static const SANE_Range percentage_range =
982 {
983 SANE_FIX(-100), /* minimum */
984 SANE_FIX(100), /* maximum */
985 SANE_FIX(1) /* quantization */
986 };
987
988 static const SANE_Range sharpen_range =
989 {0, 7, 1};
990 static const SANE_Range exposure_range =
991 {0, 100, 0};
992 static const SANE_Range attenuation_range =
993 {
994 SANE_FIX(0), /* minimum */
995 SANE_FIX(100), /* maximum */
996 SANE_FIX(1) /* quantization */
997 };
998
999
1000 static const SANE_Range x_range =
1001 {0, SANE_FIX (8.27 * MM_PER_INCH), 0};
1002 static const SANE_Range y_range =
1003 {0, SANE_FIX (12.72 * MM_PER_INCH), 0};
1004
1005 /* ------ */
1006
1007 memset (s->opt, 0, sizeof (s->opt));
1008 memset (s->val, 0, sizeof (s->val));
1009
1010 for (i = 0; i < NUM_OPTIONS; ++i)
1011 {
1012 s->opt[i].size = sizeof (SANE_Word);
1013 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1014 }
1015
1016 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
1017 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
1018 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
1019 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
1020 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
1021
1022 /* "Mode" group: */
1023
1024 s->opt[OPT_MODE_GROUP].title = "Scan Mode";
1025 s->opt[OPT_MODE_GROUP].desc = "";
1026 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
1027 s->opt[OPT_MODE_GROUP].cap = 0;
1028 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1029
1030 /* scan mode */
1031 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
1032 s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
1033 s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
1034 s->opt[OPT_MODE].type = SANE_TYPE_STRING;
1035
1036 switch (s->hw->type)
1037 {
1038 case AGFACOLOR:
1039 s->opt[OPT_MODE].size = max_string_size (focuscolor_mode_list);
1040 s->opt[OPT_MODE].constraint.string_list = focuscolor_mode_list;
1041 s->val[OPT_MODE].s = strdup (focuscolor_mode_list[0]);
1042 break;
1043 case AGFAGRAY256:
1044 s->opt[OPT_MODE].size = max_string_size (focusii_mode_list);
1045 s->opt[OPT_MODE].constraint.string_list = focusii_mode_list;
1046 s->val[OPT_MODE].s = strdup (focusii_mode_list[0]);
1047 break;
1048 default:
1049 s->opt[OPT_MODE].size = max_string_size (focus_mode_list);
1050 s->opt[OPT_MODE].constraint.string_list = focus_mode_list;
1051 s->val[OPT_MODE].s = strdup (focus_mode_list[0]);
1052 break;
1053 }
1054
1055 s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1056
1057 /* resolution */
1058 s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
1059 s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
1060 s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
1061 s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
1062 s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
1063 s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
1064 s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
1065 s->val[OPT_RESOLUTION].w = 100;
1066
1067 s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
1068 s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
1069 s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
1070 s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
1071 s->opt[OPT_SOURCE].unit = SANE_UNIT_NONE;
1072 if (!s->hw->transparent)
1073 s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE;
1074 else
1075 s->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
1076 s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1077 s->opt[OPT_SOURCE].constraint.string_list = source_list;
1078 s->opt[OPT_SOURCE].size = max_string_size (source_list);
1079 s->val[OPT_SOURCE].s = strdup (source_list[0]);
1080
1081 /* "Geometry" group: */
1082 s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
1083 s->opt[OPT_GEOMETRY_GROUP].desc = "";
1084 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
1085 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
1086 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1087
1088 /* top-left x */
1089 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
1090 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
1091 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
1092 s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
1093 s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
1094 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
1095 s->opt[OPT_TL_X].constraint.range = &x_range;
1096 s->val[OPT_TL_X].w = 0;
1097
1098 /* top-left y */
1099 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
1100 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
1101 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
1102 s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
1103 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
1104 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1105 s->opt[OPT_TL_Y].constraint.range = &y_range;
1106 s->val[OPT_TL_Y].w = 0;
1107
1108 /* bottom-right x */
1109 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
1110 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
1111 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
1112 s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
1113 s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
1114 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
1115 s->opt[OPT_BR_X].constraint.range = &x_range;
1116 s->val[OPT_BR_X].w = x_range.max;
1117
1118 /* bottom-right y */
1119 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
1120 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
1121 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
1122 s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
1123 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
1124 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1125 s->opt[OPT_BR_Y].constraint.range = &y_range;
1126 s->val[OPT_BR_Y].w = y_range.max;
1127
1128 /* "Enhancement" group: */
1129 s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
1130 s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
1131 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
1132 s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
1133 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1134
1135 /* exposure */
1136 s->opt[OPT_EXPOSURE].name = "exposure";
1137 s->opt[OPT_EXPOSURE].title = "Exposure";
1138 s->opt[OPT_EXPOSURE].desc = "Analog exposure control.";
1139 s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT;
1140 s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
1141 s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT;
1142 s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
1143 s->opt[OPT_EXPOSURE].constraint.range = &exposure_range;
1144 s->val[OPT_EXPOSURE].w = 23;
1145
1146 /* brightness automatic correct */
1147 s->opt[OPT_AUTO_BRIGHTNESS].name = "adjust-bright";
1148 s->opt[OPT_AUTO_BRIGHTNESS].title = "Automatic brightness correction";
1149 s->opt[OPT_AUTO_BRIGHTNESS].desc = "Turns on automatic brightness correction of "
1150 "the acquired image. This makes the scanner do a two pass scan to analyse the "
1151 "brightness of the image before it's scanned.";
1152 s->opt[OPT_AUTO_BRIGHTNESS].type = SANE_TYPE_BOOL;
1153 s->val[OPT_AUTO_BRIGHTNESS].b = SANE_FALSE;
1154
1155 /* contrast automatic correct */
1156 s->opt[OPT_AUTO_CONTRAST].name = "adjust-contr";
1157 s->opt[OPT_AUTO_CONTRAST].title = "Automatic contrast correction";
1158 s->opt[OPT_AUTO_CONTRAST].desc = "Turns on automatic contrast correction of "
1159 "the acquired image. This makes the scanner do a two pass scan to analyse "
1160 "the contrast of the image to be scanned.";
1161 s->opt[OPT_AUTO_CONTRAST].type = SANE_TYPE_BOOL;
1162 s->val[OPT_AUTO_CONTRAST].b = SANE_FALSE;
1163
1164 /* brightness */
1165 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
1166 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
1167 s->opt[OPT_BRIGHTNESS].desc = "Controls the brightness of the acquired image. "
1168 "When automatic brightness is enabled, this can be used to adjust the selected brightness.";
1169 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
1170 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
1171 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
1172 s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range;
1173 s->val[OPT_BRIGHTNESS].w = 0;
1174
1175 /* contrast */
1176 s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
1177 s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
1178 s->opt[OPT_CONTRAST].desc = "Controls the contrast of the acquired image. "
1179 "When automatic contrast is enabled, this can be used to adjust the selected contrast.";
1180 s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED;
1181 s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
1182 s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
1183 s->opt[OPT_CONTRAST].constraint.range = &percentage_range;
1184 s->val[OPT_CONTRAST].w = 0;
1185
1186 /* halftone patterns */
1187 s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
1188 s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
1189 s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
1190 s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
1191 s->opt[OPT_HALFTONE_PATTERN].size = 32;
1192 s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1193 if (s->hw->upload_user_defines)
1194 {
1195 s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_upload_list;
1196 s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_upload_list[0]);
1197 }
1198 else
1199 {
1200 s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_list;
1201 s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_list[0]);
1202 }
1203
1204 /* red-attenuation */
1205 s->opt[OPT_ATTENUATION_RED].name = "red-attenuation";
1206 s->opt[OPT_ATTENUATION_RED].title = "Red attenuation";
1207 s->opt[OPT_ATTENUATION_RED].desc = "Controls the red attenuation of the acquired image. "
1208 "Higher values mean less impact on scanned image.";
1209 s->opt[OPT_ATTENUATION_RED].type = SANE_TYPE_FIXED;
1210 s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE;
1211 s->opt[OPT_ATTENUATION_RED].unit = SANE_UNIT_PERCENT;
1212 s->opt[OPT_ATTENUATION_RED].constraint_type = SANE_CONSTRAINT_RANGE;
1213 s->opt[OPT_ATTENUATION_RED].constraint.range = &attenuation_range;
1214 s->val[OPT_ATTENUATION_RED].w = SANE_FIX (50.0);
1215
1216 /* green-attenuation */
1217 s->opt[OPT_ATTENUATION_GREEN].name = "green-attenuation";
1218 s->opt[OPT_ATTENUATION_GREEN].title = "Green attenuation";
1219 s->opt[OPT_ATTENUATION_GREEN].desc = "Controls the green attenuation of the acquired image. "
1220 "Higher values mean less impact on scanned image.";
1221 s->opt[OPT_ATTENUATION_GREEN].type = SANE_TYPE_FIXED;
1222 s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE;
1223 s->opt[OPT_ATTENUATION_GREEN].unit = SANE_UNIT_PERCENT;
1224 s->opt[OPT_ATTENUATION_GREEN].constraint_type = SANE_CONSTRAINT_RANGE;
1225 s->opt[OPT_ATTENUATION_GREEN].constraint.range = &attenuation_range;
1226 s->val[OPT_ATTENUATION_GREEN].w = SANE_FIX (50.0);
1227
1228 /* blue-attenuation */
1229 s->opt[OPT_ATTENUATION_BLUE].name = "blue-attenuation";
1230 s->opt[OPT_ATTENUATION_BLUE].title = "Blue attenuation";
1231 s->opt[OPT_ATTENUATION_BLUE].desc = "Controls the blue attenuation of the acquired image. "
1232 "Higher values mean less impact on scanned image.";
1233 s->opt[OPT_ATTENUATION_BLUE].type = SANE_TYPE_FIXED;
1234 s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE;
1235 s->opt[OPT_ATTENUATION_BLUE].unit = SANE_UNIT_PERCENT;
1236 s->opt[OPT_ATTENUATION_BLUE].constraint_type = SANE_CONSTRAINT_RANGE;
1237 s->opt[OPT_ATTENUATION_BLUE].constraint.range = &attenuation_range;
1238 s->val[OPT_ATTENUATION_BLUE].w = SANE_FIX (50.0);
1239
1240 /* quality-calibration */
1241 s->opt[OPT_QUALITY].name = SANE_NAME_QUALITY_CAL;
1242 s->opt[OPT_QUALITY].title = SANE_TITLE_QUALITY_CAL;
1243 s->opt[OPT_QUALITY].desc = "Controls the calibration that will be done in the "
1244 "scanner. Less calibration result in faster scanner times.";
1245 s->opt[OPT_QUALITY].type = SANE_TYPE_STRING;
1246 s->opt[OPT_QUALITY].size = 32;
1247 if (!s->hw->quality)
1248 s->opt[OPT_QUALITY].cap |= SANE_CAP_INACTIVE;
1249 else
1250 s->opt[OPT_QUALITY].cap &= ~SANE_CAP_INACTIVE;
1251 s->opt[OPT_QUALITY].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1252 s->opt[OPT_QUALITY].constraint.string_list = quality_list;
1253 s->val[OPT_QUALITY].s = strdup (quality_list[1]);
1254
1255 /* sharpening */
1256 s->opt[OPT_SHARPEN].name = "sharpen";
1257 s->opt[OPT_SHARPEN].title = "Sharpening";
1258 s->opt[OPT_SHARPEN].desc = "Controls the sharpening that will be "
1259 "done by the video processor in the scanner.";
1260 s->opt[OPT_SHARPEN].type = SANE_TYPE_INT;
1261 s->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE;
1262 s->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_RANGE;
1263 s->opt[OPT_SHARPEN].constraint.range = &sharpen_range;
1264 s->val[OPT_SHARPEN].w = 1;
1265
1266 return SANE_STATUS_GOOD;
1267 }
1268
1269 static SANE_Status
attach_one(const char * dev)1270 attach_one (const char *dev)
1271 {
1272 attach (dev, 0);
1273 return SANE_STATUS_GOOD;
1274 }
1275
1276 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)1277 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
1278 {
1279 char dev_name[PATH_MAX];
1280 size_t len;
1281 FILE *fp;
1282
1283 (void) authorize; /* silence gcc */
1284
1285 DBG_INIT ();
1286
1287 sanei_thread_init ();
1288
1289 if (version_code)
1290 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
1291
1292 fp = sanei_config_open ("agfafocus.conf");
1293 if (!fp)
1294 {
1295 /* default to /dev/scanner instead of insisting on config file */
1296 attach ("/dev/scanner", 0);
1297 return SANE_STATUS_GOOD;
1298 }
1299
1300 while (sanei_config_read (dev_name, sizeof (dev_name), fp))
1301 {
1302 if (dev_name[0] == '#') /* ignore line comments */
1303 continue;
1304 len = strlen (dev_name);
1305
1306 if (!len)
1307 continue; /* ignore empty lines */
1308
1309 sanei_config_attach_matching_devices (dev_name, attach_one);
1310 }
1311 fclose (fp);
1312 return SANE_STATUS_GOOD;
1313 }
1314
1315 void
sane_exit(void)1316 sane_exit (void)
1317 {
1318 AgfaFocus_Device *dev, *next;
1319
1320 for (dev = agfafocus_devices; dev; dev = next)
1321 {
1322 next = dev->next;
1323 if (dev->handle)
1324 sane_close (dev->handle);
1325 free (dev);
1326 }
1327
1328 if (devlist)
1329 free (devlist);
1330 }
1331
1332 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)1333 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1334 {
1335 AgfaFocus_Device *dev;
1336 int i;
1337
1338 (void) local_only; /* silence gcc */
1339
1340 if (devlist)
1341 free (devlist);
1342
1343 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
1344 if (!devlist)
1345 return SANE_STATUS_NO_MEM;
1346
1347 for (dev = agfafocus_devices, i = 0; i < num_devices; dev = dev->next)
1348 devlist[i++] = &dev->sane;
1349 devlist[i++] = 0;
1350
1351 *device_list = devlist;
1352 return SANE_STATUS_GOOD;
1353 }
1354
1355 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)1356 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
1357 {
1358 AgfaFocus_Device *dev;
1359 SANE_Status status;
1360 AgfaFocus_Scanner *s;
1361
1362 if (devicename[0])
1363 {
1364 status = attach (devicename, &dev);
1365 if (status != SANE_STATUS_GOOD)
1366 return status;
1367 }
1368 else
1369 {
1370 /* empty devicname -> use first device */
1371 dev = agfafocus_devices;
1372 }
1373
1374 if (!dev)
1375 return SANE_STATUS_INVAL;
1376
1377 if (dev->handle)
1378 return SANE_STATUS_DEVICE_BUSY;
1379
1380 s = malloc (sizeof (*s));
1381 if (!s)
1382 return SANE_STATUS_NO_MEM;
1383
1384 memset (s, 0, sizeof (*s));
1385 s->scanning = SANE_FALSE;
1386
1387 s->fd = -1;
1388 s->hw = dev;
1389 s->hw->handle = s;
1390
1391 init_options (s);
1392
1393 *handle = s;
1394 return SANE_STATUS_GOOD;
1395 }
1396
1397 void
sane_close(SANE_Handle handle)1398 sane_close (SANE_Handle handle)
1399 {
1400 AgfaFocus_Scanner *s = handle;
1401
1402 if (s->scanning)
1403 do_cancel (handle);
1404
1405 s->hw->handle = 0;
1406
1407 free (handle);
1408 }
1409
1410 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)1411 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1412 {
1413 AgfaFocus_Scanner *s = handle;
1414
1415 if ((unsigned) option >= NUM_OPTIONS)
1416 return 0;
1417 return s->opt + option;
1418 }
1419
1420 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)1421 sane_control_option (SANE_Handle handle, SANE_Int option,
1422 SANE_Action action, void *val, SANE_Int * info)
1423 {
1424 AgfaFocus_Scanner *s = handle;
1425 SANE_Status status;
1426
1427 if (info)
1428 *info = 0;
1429
1430 if (s->scanning)
1431 return SANE_STATUS_DEVICE_BUSY;
1432
1433 if (option >= NUM_OPTIONS || !SANE_OPTION_IS_ACTIVE (s->opt[option].cap))
1434 return SANE_STATUS_UNSUPPORTED;
1435
1436 if (action == SANE_ACTION_GET_VALUE)
1437 {
1438 switch (option)
1439 {
1440 case OPT_RESOLUTION:
1441 case OPT_TL_X:
1442 case OPT_TL_Y:
1443 case OPT_BR_X:
1444 case OPT_BR_Y:
1445 case OPT_NUM_OPTS:
1446 case OPT_BRIGHTNESS:
1447 case OPT_CONTRAST:
1448 case OPT_SHARPEN:
1449 case OPT_EXPOSURE:
1450 case OPT_ATTENUATION_RED:
1451 case OPT_ATTENUATION_GREEN:
1452 case OPT_ATTENUATION_BLUE:
1453 *(SANE_Word *) val = s->val[option].w;
1454 break;
1455 case OPT_AUTO_BRIGHTNESS:
1456 case OPT_AUTO_CONTRAST:
1457 *(SANE_Bool *) val = s->val[option].b;
1458 break;
1459 case OPT_MODE:
1460 case OPT_HALFTONE_PATTERN:
1461 case OPT_QUALITY:
1462 case OPT_SOURCE:
1463 strcpy (val, s->val[option].s);
1464 return (SANE_STATUS_GOOD);
1465 default:
1466 return SANE_STATUS_UNSUPPORTED;
1467 }
1468
1469 }
1470 else if (action == SANE_ACTION_SET_VALUE)
1471 {
1472 if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap))
1473 return SANE_STATUS_UNSUPPORTED;
1474
1475 status = sanei_constrain_value (s->opt + option, val, info);
1476 if (status != SANE_STATUS_GOOD)
1477 return status;
1478
1479 switch (option)
1480 {
1481 case OPT_RESOLUTION:
1482 case OPT_TL_X:
1483 case OPT_TL_Y:
1484 case OPT_BR_X:
1485 case OPT_BR_Y:
1486 if (info)
1487 *info |= SANE_INFO_RELOAD_PARAMS;
1488 // fall through
1489 case OPT_SHARPEN:
1490 case OPT_EXPOSURE:
1491 case OPT_ATTENUATION_RED:
1492 case OPT_ATTENUATION_GREEN:
1493 case OPT_ATTENUATION_BLUE:
1494 case OPT_BRIGHTNESS:
1495 case OPT_CONTRAST:
1496 s->val[option].w = *(SANE_Word *) val;
1497 break;
1498 case OPT_AUTO_BRIGHTNESS:
1499 case OPT_AUTO_CONTRAST:
1500 s->val[option].b = *(SANE_Bool *) val;
1501 break;
1502 case OPT_MODE:
1503 if (strcmp (s->val[option].s, (SANE_String) val))
1504 {
1505 if (info)
1506 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1507
1508 if (s->val[option].s)
1509 free (s->val[option].s);
1510
1511 s->val[option].s = strdup (val);
1512
1513 if (strcmp (s->val[option].s, "Gray (6 bit)") == 0)
1514 s->mode = GRAY6BIT;
1515 else if (strcmp (s->val[option].s, "Gray (8 bit)") == 0)
1516 s->mode = GRAY8BIT;
1517 else if (strcmp (s->val[option].s, "Color (18 bit)") == 0)
1518 s->mode = COLOR18BIT;
1519 else if (strcmp (s->val[option].s, "Color (24 bit)") == 0)
1520 s->mode = COLOR24BIT;
1521 else
1522 s->mode = LINEART;
1523
1524 switch (s->mode)
1525 {
1526 case LINEART:
1527 s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
1528 s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE;
1529 s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
1530 s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE;
1531 s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE;
1532 s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE;
1533 s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1534 s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1535 s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1536 s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1537 break;
1538
1539 case GRAY6BIT:
1540 s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE;
1541 s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
1542 s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE;
1543 s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE;
1544 s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE;
1545 s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1546 s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1547 s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1548 s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1549 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1550 break;
1551
1552 case GRAY8BIT:
1553 s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1554 s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1555 s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1556 s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1557 s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
1558 s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE;
1559 s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE;
1560 s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE;
1561 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1562 s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE;
1563 break;
1564
1565 case COLOR18BIT:
1566 s->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
1567 s->opt[OPT_ATTENUATION_RED].cap &= ~SANE_CAP_INACTIVE;
1568 s->opt[OPT_ATTENUATION_GREEN].cap &= ~SANE_CAP_INACTIVE;
1569 s->opt[OPT_ATTENUATION_BLUE].cap &= ~SANE_CAP_INACTIVE;
1570 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
1571 s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
1572 s->opt[OPT_AUTO_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
1573 s->opt[OPT_AUTO_CONTRAST].cap |= SANE_CAP_INACTIVE;
1574 s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE;
1575 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1576 break;
1577
1578 case COLOR24BIT:
1579 s->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE;
1580 s->opt[OPT_ATTENUATION_RED].cap &= ~SANE_CAP_INACTIVE;
1581 s->opt[OPT_ATTENUATION_GREEN].cap &= ~SANE_CAP_INACTIVE;
1582 s->opt[OPT_ATTENUATION_BLUE].cap &= ~SANE_CAP_INACTIVE;
1583 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
1584 s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
1585 s->opt[OPT_AUTO_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
1586 s->opt[OPT_AUTO_CONTRAST].cap |= SANE_CAP_INACTIVE;
1587 s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE;
1588 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1589 break;
1590 }
1591 }
1592 break;
1593 case OPT_SOURCE:
1594 case OPT_QUALITY:
1595 case OPT_HALFTONE_PATTERN:
1596 if (info && strcmp (s->val[option].s, (SANE_String) val))
1597 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1598 if (s->val[option].s)
1599 free (s->val[option].s);
1600 s->val[option].s = strdup (val);
1601 break;
1602 default:
1603 return SANE_STATUS_UNSUPPORTED;
1604 }
1605
1606 }
1607 else
1608 {
1609 return SANE_STATUS_UNSUPPORTED;
1610 }
1611
1612 return SANE_STATUS_GOOD;
1613 }
1614
1615 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1616 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1617 {
1618 AgfaFocus_Scanner *s = handle;
1619
1620 if (!s->scanning)
1621 {
1622 double width, height, dpi;
1623 const char *quality;
1624 const char *original;
1625
1626 memset (&s->params, 0, sizeof (s->params));
1627
1628 width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w);
1629 height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w);
1630 dpi = s->val[OPT_RESOLUTION].w;
1631
1632 /* make best-effort guess at what parameters will look like once
1633 scanning starts. */
1634 if (dpi > 0.0 && width > 0.0 && height > 0.0)
1635 {
1636 double dots_per_mm = dpi / MM_PER_INCH;
1637
1638 s->params.pixels_per_line = width * dots_per_mm + 0.5;
1639 s->params.lines = height * dots_per_mm + 0.5;
1640 }
1641
1642 /* Should we specify calibration quality? */
1643
1644 if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_QUALITY].cap))
1645 {
1646 DBG(3, " -------------- setting quality\n");
1647 quality = s->val[OPT_QUALITY].s;
1648 if (strcmp (quality, "Low") == 0 )
1649 s->quality = 255;
1650 else if (strcmp (quality, "High") == 0)
1651 s->quality = 1;
1652 else
1653 s->quality = 0;
1654 }
1655 else
1656 s->quality = 0;
1657
1658 /* Should we select source type? */
1659
1660 if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_SOURCE].cap))
1661 {
1662 DBG(3, " -------------- setting source\n");
1663 original = s->val[OPT_SOURCE].s;
1664 if (strcmp (original, "Transparency") == 0)
1665 s->original = 0;
1666 else
1667 s->original = 1;
1668 }
1669 else
1670 s->original = 0;
1671
1672 s->exposure = ((s->val[OPT_EXPOSURE].w * (255.0f - 80.0f)) / 100.0f) + 80.0f;
1673 s->r_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_RED].w) * 20.0f) / 100.0f;
1674 s->g_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_GREEN].w) * 20.0f) / 100.0f;
1675 s->b_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_BLUE].w) * 20.0f) / 100.0f;
1676 s->tonecurve = 0;
1677
1678 switch (s->mode)
1679 {
1680 case LINEART:
1681 {
1682 const char *halftone;
1683
1684 s->image_composition = 0;
1685
1686 /* in 1 bpp mode, lines need to be 8 pixel length */
1687
1688 if (s->params.pixels_per_line % 8)
1689 s->params.pixels_per_line += 8 - (s->params.pixels_per_line % 8);
1690
1691 s->params.format = SANE_FRAME_GRAY;
1692 s->params.bytes_per_line = s->params.pixels_per_line / 8;
1693 s->bpp = s->params.depth = 1;
1694
1695 halftone = s->val[OPT_HALFTONE_PATTERN].s;
1696 if (strcmp (halftone, "1") == 0 )
1697 s->halftone = 1;
1698 else if (strcmp (halftone, "Dispersed dot 4x4") == 0)
1699 s->halftone = 2;
1700 else if (strcmp (halftone, "Round (Clustered dot 4x4)") == 0)
1701 s->halftone = 3;
1702 else if (strcmp (halftone, "Diamond (Clustered dot 4x4)") == 0)
1703 s->halftone = 4;
1704 else if (strcmp (halftone, "User defined") == 0)
1705 s->halftone = 5;
1706 else
1707 s->halftone = 0;
1708
1709 s->edge = s->val[OPT_SHARPEN].w;
1710 }
1711 break;
1712
1713 case GRAY6BIT:
1714 s->image_composition = 2;
1715
1716 s->params.format = SANE_FRAME_GRAY;
1717 s->params.bytes_per_line = s->params.pixels_per_line;
1718 s->bpp = 6;
1719 s->params.depth = 8;
1720 s->edge = s->val[OPT_SHARPEN].w;
1721
1722 break;
1723
1724 case GRAY8BIT:
1725 s->image_composition = 2;
1726
1727 s->params.format = SANE_FRAME_GRAY;
1728 s->params.bytes_per_line = s->params.pixels_per_line;
1729 s->bpp = s->params.depth = 8;
1730
1731 break;
1732
1733 case COLOR18BIT:
1734 s->image_composition = 5;
1735
1736 s->params.format = SANE_FRAME_RED;
1737 s->params.bytes_per_line = s->params.pixels_per_line;
1738 s->bpp = 6;
1739 s->params.depth = 8;
1740 s->edge = s->val[OPT_SHARPEN].w;
1741
1742 break;
1743
1744 case COLOR24BIT:
1745 s->image_composition = 5;
1746
1747 s->params.format = SANE_FRAME_RED;
1748 s->params.bytes_per_line = s->params.pixels_per_line;
1749 s->bpp = s->params.depth = 8;
1750
1751 break;
1752 }
1753
1754 s->pass = 0;
1755
1756 /*s->params.bytes_per_line =
1757 (s->params.pixels_per_line + (8 - s->params.depth))
1758 / (8 / s->params.depth);*/
1759 }
1760 else
1761 if (s->mode == COLOR18BIT ||
1762 s->mode == COLOR24BIT)
1763 s->params.format = SANE_FRAME_RED + s->pass;
1764
1765 s->params.last_frame = (s->params.format != SANE_FRAME_RED && s->params.format != SANE_FRAME_GREEN);
1766
1767 if (params)
1768 *params = s->params;
1769 return SANE_STATUS_GOOD;
1770 }
1771
1772 /* This function is executed as a child process. The reason this is
1773 executed as a subprocess is because some (most?) generic SCSI
1774 interfaces block a SCSI request until it has completed. With a
1775 subprocess, we can let it block waiting for the request to finish
1776 while the main process can go about to do more important things
1777 (such as recognizing when the user presses a cancel button).
1778
1779
1780 WARNING: Since this is executed as a subprocess, it's NOT possible
1781 to update any of the variables in the main process (in particular
1782 the scanner state cannot be updated). */
1783 static int
reader_process(void * scanner)1784 reader_process (void *scanner)
1785 {
1786 AgfaFocus_Scanner *s = (AgfaFocus_Scanner *) scanner;
1787 int fd = s->reader_pipe;
1788
1789 SANE_Status status;
1790 SANE_Byte *data;
1791 int lines_read = 0;
1792 int lines_per_buffer;
1793 int bytes_per_line = 0, total_lines = 0;
1794 int i;
1795 sigset_t sigterm_set;
1796 sigset_t ignore_set;
1797 struct SIGACTION act;
1798
1799 if (sanei_thread_is_forked()) close (s->pipe);
1800
1801 sigfillset (&ignore_set);
1802 sigdelset (&ignore_set, SIGTERM);
1803 #if defined (__APPLE__) && defined (__MACH__)
1804 sigdelset (&ignore_set, SIGUSR2);
1805 #endif
1806 sigprocmask (SIG_SETMASK, &ignore_set, 0);
1807
1808 memset (&act, 0, sizeof (act));
1809 sigaction (SIGTERM, &act, 0);
1810
1811 sigemptyset (&sigterm_set);
1812 sigaddset (&sigterm_set, SIGTERM);
1813
1814 if (!s->hw->disconnect)
1815 wait_ready (s->fd);
1816
1817 status = get_read_sizes (s->fd, &s->lines_available, &bytes_per_line, &total_lines);
1818 if (status != SANE_STATUS_GOOD)
1819 {
1820 DBG (1, "open: get_read_sizes() failed: %s\n",
1821 sane_strstatus (status));
1822 do_cancel (s);
1823 close (fd);
1824 return 1;
1825 }
1826
1827 if (!s->lines_available || !bytes_per_line || !total_lines || bytes_per_line < s->params.bytes_per_line)
1828 {
1829 DBG (1, "open: invalid sizes: %d, %d, %d\n",
1830 s->lines_available, bytes_per_line, total_lines);
1831 do_cancel (s);
1832 close (fd);
1833 return 1;
1834 }
1835
1836 lines_per_buffer = sanei_scsi_max_request_size / bytes_per_line;
1837 if (!lines_per_buffer)
1838 {
1839 close (fd);
1840 return 2; /* resolution is too high */
1841 }
1842
1843 data = malloc (lines_per_buffer * bytes_per_line);
1844 if (!data)
1845 {
1846 DBG (1, "open malloc(%lu) failed.\n", (u_long) lines_per_buffer * bytes_per_line);
1847 do_cancel (s);
1848 close (fd);
1849 return 1;
1850 }
1851
1852 while (lines_read < s->params.lines)
1853 {
1854 int lines = lines_per_buffer;
1855
1856 if (s->lines_available == 0)
1857 {
1858 /* No lines in scanner? Scan some more */
1859 status = request_more_data (s);
1860
1861 if (status != SANE_STATUS_GOOD)
1862 {
1863 close (fd);
1864 return 1;
1865 }
1866 }
1867
1868 /* We only request as many lines as there are already scanned */
1869 if (lines > s->lines_available)
1870 lines = s->lines_available;
1871
1872 DBG (1, "Requesting %d lines, in scanner: %d, total: %d\n", lines,
1873 s->lines_available, s->params.lines);
1874
1875 status = read_data (s, data, lines, bytes_per_line);
1876
1877 if (status != SANE_STATUS_GOOD)
1878 {
1879 DBG (1, "sane_read: read_data() failed (%s)\n",
1880 sane_strstatus (status));
1881 do_cancel (s);
1882 close (fd);
1883 return 1;
1884 }
1885
1886 /* Sometimes the scanner will return more bytes per line than
1887 requested, so we copy only what we wanted. */
1888
1889 for (i = 0; i < lines; i++)
1890 if (write (fd, data + i * bytes_per_line, s->params.bytes_per_line) != s->params.bytes_per_line)
1891 {
1892 do_cancel (s);
1893 close (fd);
1894 return 1;
1895 }
1896
1897 lines_read += lines;
1898 }
1899
1900 close (fd);
1901 return 0;
1902 }
1903
1904 SANE_Status
sane_start(SANE_Handle handle)1905 sane_start (SANE_Handle handle)
1906 {
1907 AgfaFocus_Scanner *s = handle;
1908 SANE_Status status;
1909 int fds[2];
1910
1911 /* First make sure we have a current parameter set. Some of the
1912 parameters will be overwritten below, but that's OK. */
1913
1914 status = sane_get_parameters (s, 0);
1915 if (status != SANE_STATUS_GOOD)
1916 return status;
1917
1918 /* don't initialise scanner if we're doing a three-pass scan */
1919
1920 if (s->pass == 0)
1921 {
1922 if (s->fd < 0)
1923 {
1924 status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0);
1925 if (status != SANE_STATUS_GOOD)
1926 {
1927 DBG (1, "open: open of %s failed: %s\n",
1928 s->hw->sane.name, sane_strstatus (status));
1929 s->fd = -1;
1930 return status;
1931 }
1932 }
1933
1934 status = test_ready (s->fd);
1935 if (status != SANE_STATUS_GOOD)
1936 {
1937 DBG (1, "open: test_ready() failed: %s\n", sane_strstatus (status));
1938 sanei_scsi_close (s->fd);
1939 s->fd = -1;
1940 return status;
1941 }
1942
1943 status = reserve_unit (s->fd);
1944 if (status != SANE_STATUS_GOOD)
1945 {
1946 DBG (1, "open: reserve_unit() failed: %s\n", sane_strstatus (status));
1947 sanei_scsi_close (s->fd);
1948 s->fd = -1;
1949 return status;
1950 }
1951
1952 status = set_window (s);
1953 if (status != SANE_STATUS_GOOD)
1954 {
1955 DBG (1, "open: set_window() failed: %s\n", sane_strstatus (status));
1956 release_unit (s->fd);
1957 sanei_scsi_close (s->fd);
1958 s->fd = -1;
1959 return status;
1960 }
1961
1962 {
1963 int matrix[256] = {
1964 2, 60, 16, 56, 3, 57, 13, 53,
1965 34, 18, 48, 32, 35, 19, 45, 29,
1966 10, 50, 6, 63, 11, 51, 7, 61,
1967 42, 26, 38, 22, 43, 27, 39, 23,
1968 4, 58, 14, 54, 1, 59, 15, 55,
1969 36, 20, 46, 30, 33, 17, 47, 31,
1970 12, 52, 8, 62, 9, 49, 5, 63,
1971 44, 28, 40, 24, 41, 25, 37, 21
1972 };
1973
1974 status = upload_dither_matrix (s, 8, 8, matrix);
1975 if (status != SANE_STATUS_GOOD)
1976 {
1977 DBG (1, "open: upload_dither_matrix() failed: %s\n", sane_strstatus (status));
1978 release_unit (s->fd);
1979 sanei_scsi_close (s->fd);
1980 s->fd = -1;
1981 return status;
1982 }
1983 }
1984
1985 s->scanning = SANE_TRUE;
1986
1987 status = start_scan (s->fd, SANE_FALSE);
1988 if (status != SANE_STATUS_GOOD)
1989 {
1990 DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status));
1991 do_cancel (s);
1992 return status;
1993 }
1994 }
1995 else
1996 {
1997 /* continue three-pass scan */
1998
1999 status = start_scan (s->fd, SANE_TRUE);
2000 if (status != SANE_STATUS_GOOD)
2001 {
2002 DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status));
2003 do_cancel (s);
2004 return status;
2005 }
2006 }
2007
2008 if (pipe (fds) < 0)
2009 return SANE_STATUS_IO_ERROR;
2010
2011 s->pipe = fds[0];
2012 s->reader_pipe = fds[1];
2013 s->reader_pid = sanei_thread_begin (reader_process, (void *) s);
2014
2015 if (sanei_thread_is_forked()) close (s->reader_pipe);
2016
2017 return SANE_STATUS_GOOD;
2018 }
2019
2020 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)2021 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
2022 SANE_Int * len)
2023 {
2024 AgfaFocus_Scanner *s = handle;
2025 ssize_t nread;
2026
2027 *len = 0;
2028
2029 nread = read (s->pipe, buf, max_len);
2030 DBG (3, "read %ld bytes\n", (long) nread);
2031
2032 if (!s->scanning)
2033 return do_cancel (s);
2034
2035 if (nread < 0) {
2036 if (errno == EAGAIN) {
2037 return SANE_STATUS_GOOD;
2038 } else {
2039 do_cancel (s);
2040 return SANE_STATUS_IO_ERROR;
2041 }
2042 }
2043
2044 *len = nread;
2045
2046 if (nread == 0) {
2047 s->pass++;
2048 return do_eof (s);
2049 }
2050 return SANE_STATUS_GOOD;
2051 }
2052
2053 void
sane_cancel(SANE_Handle handle)2054 sane_cancel (SANE_Handle handle)
2055 {
2056 AgfaFocus_Scanner *s = handle;
2057
2058 if (sanei_thread_is_valid (s->reader_pid))
2059 sanei_thread_kill (s->reader_pid);
2060 s->scanning = SANE_FALSE;
2061 }
2062
2063 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)2064 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2065 {
2066 AgfaFocus_Scanner *s = handle;
2067
2068 if (!s->scanning)
2069 return SANE_STATUS_INVAL;
2070
2071 if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
2072 return SANE_STATUS_IO_ERROR;
2073
2074 return SANE_STATUS_GOOD;
2075 }
2076
2077 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)2078 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2079 {
2080 AgfaFocus_Scanner *s = handle;
2081
2082 if (!s->scanning)
2083 return SANE_STATUS_INVAL;
2084
2085 *fd = s->pipe;
2086 return SANE_STATUS_GOOD;
2087 }
2088