1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 1997 Gordon Matzigkeit
3    Copyright (C) 1997 David Mosberger-Tang
4    This file is part of the SANE package.
5 
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <https://www.gnu.org/licenses/>.
18 
19    As a special exception, the authors of SANE give permission for
20    additional uses of the libraries contained in this release of SANE.
21 
22    The exception is that, if you link a SANE library with other files
23    to produce an executable, this does not by itself cause the
24    resulting executable to be covered by the GNU General Public
25    License.  Your use of that executable is in no way restricted on
26    account of linking the SANE library code into it.
27 
28    This exception does not, however, invalidate any other reasons why
29    the executable file might be covered by the GNU General Public
30    License.
31 
32    If you submit changes to SANE to the maintainers to be included in
33    a subsequent release, you agree by submitting the changes that
34    those changes may be distributed with this exception intact.
35 
36    If you write modifications of your own for SANE, it is your choice
37    whether to permit this exception to apply to your modifications.
38    If you do not wish that, delete this exception notice.  */
39 
40 #include "../include/sane/config.h"
41 
42 #include <limits.h>
43 #include <stdlib.h>
44 #include <string.h>
45 extern int errno;
46 
47 #include "../include/sane/sane.h"
48 #include "../include/sane/saneopts.h"
49 
50 #include <unistd.h>
51 #include <fcntl.h>
52 
53 #include "../include/sane/sanei_backend.h"
54 
55 #ifndef PATH_MAX
56 # define PATH_MAX	1024
57 #endif
58 
59 #include "../include/sane/sanei_config.h"
60 #define PINT_CONFIG_FILE "pint.conf"
61 
62 #include "pint.h"
63 
64 #define DECIPOINTS_PER_MM	(720.0 / MM_PER_INCH)
65 #define TWELVEHUNDS_PER_MM	(1200.0 / MM_PER_INCH)
66 
67 
68 static int num_devices;
69 static PINT_Device *first_dev;
70 static PINT_Scanner *first_handle;
71 
72 /* A zero-terminated list of valid scanner modes. */
73 static SANE_String_Const mode_list[8];
74 
75 static const SANE_Range s7_range =
76   {
77     -127,				/* minimum */
78      127,				/* maximum */
79        1				/* quantization */
80   };
81 
82 static size_t
max_string_size(const SANE_String_Const strings[])83 max_string_size (const SANE_String_Const strings[])
84 {
85   size_t size, max_size = 0;
86   int i;
87 
88   for (i = 0; strings[i]; ++i)
89     {
90       size = strlen (strings[i]) + 1;
91       if (size > max_size)
92 	max_size = size;
93     }
94   return max_size;
95 }
96 
97 static SANE_Status
attach(const char *devname, PINT_Device **devp)98 attach (const char *devname, PINT_Device **devp)
99 {
100   int fd;
101   long lastguess, inc;
102   PINT_Device *dev;
103   struct scan_io scanio;
104 
105   for (dev = first_dev; dev; dev = dev->next)
106     if (strcmp (dev->sane.name, devname) == 0)
107       {
108 	if (devp)
109 	  *devp = dev;
110 	return SANE_STATUS_GOOD;
111       }
112 
113   DBG(3, "attach: opening %s\n", devname);
114   fd = open (devname, O_RDONLY, 0);
115   if (fd < 0)
116     {
117       DBG(1, "attach: open failed (%s)\n", strerror (errno));
118       return SANE_STATUS_INVAL;
119     }
120 
121   DBG(3, "attach: sending SCIOCGET\n");
122   if (ioctl (fd, SCIOCGET, &scanio) < 0)
123     {
124       DBG(1, "attach: get status failed (%s)\n", strerror (errno));
125       close (fd);
126       return SANE_STATUS_INVAL;
127     }
128 
129   dev = malloc (sizeof (*dev));
130   if (!dev)
131     return SANE_STATUS_NO_MEM;
132 
133   memset(dev, 0, sizeof (*dev));
134 
135   /* Copy the original scanner state to the device structure. */
136   memcpy (&dev->scanio, &scanio, sizeof (dev->scanio));
137 
138   /* FIXME: PINT currently has no good way to determine maxima and minima.
139      So, do binary searches to find out what limits the driver has. */
140 
141   /* Assume that minimum range of x and y is 0. */
142   dev->x_range.min = SANE_FIX (0);
143   dev->y_range.min = SANE_FIX (0);
144   dev->x_range.quant = 0;
145   dev->y_range.quant = 0;
146 
147   /* x range */
148   inc = 8.5 * 1200;
149 
150   /* Converge on the maximum scan width. */
151   while ((inc /= 2) != 0)
152     {
153       /* Move towards the extremum until we overflow. */
154       do
155 	{
156 	  lastguess = scanio.scan_width;
157 	  scanio.scan_width += inc;
158 	}
159       while (ioctl (fd, SCIOCSET, &scanio) >= 0);
160 
161       /* Pick the last valid guess, divide by two, and try again. */
162       scanio.scan_width = lastguess;
163     }
164   dev->x_range.max = SANE_FIX (scanio.scan_width / TWELVEHUNDS_PER_MM);
165 
166   /* y range */
167   inc = 11 * 1200;
168   while ((inc /= 2) != 0)
169     {
170       do
171 	{
172 	  lastguess = scanio.scan_height;
173 	  scanio.scan_height += inc;
174 	}
175       while (ioctl (fd, SCIOCSET, &scanio) >= 0);
176       scanio.scan_height = lastguess;
177     }
178   dev->y_range.max = SANE_FIX (scanio.scan_height / TWELVEHUNDS_PER_MM);
179 
180   /* Converge on the minimum scan resolution. */
181   dev->dpi_range.quant = 1;
182 
183   if (scanio.scan_x_resolution > scanio.scan_y_resolution)
184     scanio.scan_x_resolution = scanio.scan_y_resolution;
185   else
186     scanio.scan_y_resolution = scanio.scan_x_resolution;
187 
188   inc = -scanio.scan_x_resolution;
189   while ((inc /= 2) != 0)
190     {
191       do
192 	{
193 	  lastguess = scanio.scan_x_resolution;
194 	  scanio.scan_x_resolution = scanio.scan_y_resolution += inc;
195 	}
196       while (ioctl (fd, SCIOCSET, &scanio) >= 0);
197       scanio.scan_x_resolution = scanio.scan_y_resolution = lastguess;
198     }
199   dev->dpi_range.min = scanio.scan_x_resolution;
200 
201   /* Converge on the maximum scan resolution. */
202   inc = 600;
203   while ((inc /= 2) != 0)
204     {
205       do
206 	{
207 	  lastguess = scanio.scan_x_resolution;
208 	  scanio.scan_x_resolution = scanio.scan_y_resolution += inc;
209 	}
210       while (ioctl (fd, SCIOCSET, &scanio) >= 0);
211       scanio.scan_x_resolution = scanio.scan_y_resolution = lastguess;
212     }
213   dev->dpi_range.max = scanio.scan_x_resolution;
214 
215   /* Determine the valid scan modes for mode_list. */
216   lastguess = 0;
217 #define CHECK_MODE(flag,modename) \
218   scanio.scan_image_mode = flag; \
219   if (ioctl (fd, SCIOCSET, &scanio) >= 0) \
220     mode_list[lastguess ++] = modename
221 
222   CHECK_MODE(SIM_BINARY_MONOCHROME, SANE_VALUE_SCAN_MODE_LINEART);
223   CHECK_MODE(SIM_DITHERED_MONOCHROME, SANE_VALUE_SCAN_MODE_HALFTONE);
224   CHECK_MODE(SIM_GRAYSCALE, SANE_VALUE_SCAN_MODE_GRAY);
225   CHECK_MODE(SIM_COLOR, SANE_VALUE_SCAN_MODE_COLOR);
226   CHECK_MODE(SIM_RED, "Red");
227   CHECK_MODE(SIM_GREEN, "Green");
228   CHECK_MODE(SIM_BLUE, "Blue");
229 #undef CHECK_MODE
230 
231   /* Zero-terminate the list of modes. */
232   mode_list[lastguess] = 0;
233 
234   /* Restore the scanner state. */
235   if (ioctl (fd, SCIOCSET, &dev->scanio))
236     DBG (2, "cannot reset original scanner state: %s\n", strerror (errno));
237   close (fd);
238 
239   dev->sane.name   = strdup (devname);
240 
241   /* Determine vendor. */
242   switch (scanio.scan_scanner_type)
243     {
244     case EPSON_ES300C:
245       dev->sane.vendor = "Epson";
246       break;
247 
248     case FUJITSU_M3096G:
249       dev->sane.vendor = "Fujitsu";
250       break;
251 
252     case HP_SCANJET_IIC:
253       dev->sane.vendor = "HP";
254       break;
255 
256     case IBM_2456:
257       dev->sane.vendor = "IBM";
258       break;
259 
260     case MUSTEK_06000CX:
261     case MUSTEK_12000CX:
262       dev->sane.vendor = "Mustek";
263       break;
264 
265     case RICOH_FS1:
266     case RICOH_IS410:
267     case RICOH_IS50:
268       dev->sane.vendor = "Ricoh";
269       break;
270 
271     case SHARP_JX600:
272       dev->sane.vendor = "Sharp";
273       break;
274 
275     case UMAX_UC630:
276     case UMAX_UG630:
277       dev->sane.vendor = "UMAX";
278       break;
279 
280     default:
281       dev->sane.vendor = "PINT";
282     }
283 
284   /* Determine model. */
285   switch (scanio.scan_scanner_type)
286     {
287     case EPSON_ES300C:
288       dev->sane.vendor = "Epson";
289       break;
290 
291     case FUJITSU_M3096G:
292       dev->sane.model = "M3096G";
293       break;
294 
295     case HP_SCANJET_IIC:
296       dev->sane.model = "ScanJet IIc";
297       break;
298 
299     case IBM_2456:
300       dev->sane.vendor = "IBM";
301       break;
302 
303     case MUSTEK_06000CX:
304     case MUSTEK_12000CX:
305       dev->sane.vendor = "Mustek";
306       break;
307 
308     case RICOH_FS1:
309       dev->sane.model = "FS1";
310       break;
311 
312     case RICOH_IS410:
313       dev->sane.model = "IS-410";
314       break;
315 
316     case RICOH_IS50:
317       dev->sane.vendor = "Ricoh";
318       break;
319 
320     case SHARP_JX600:
321       dev->sane.vendor = "Sharp";
322       break;
323 
324     case UMAX_UC630:
325     case UMAX_UG630:
326       dev->sane.vendor = "UMAX";
327       break;
328 
329     default:
330       dev->sane.model = "unknown";
331     }
332 
333   /* Determine the scanner type. */
334   switch (scanio.scan_scanner_type)
335     {
336     case HP_SCANJET_IIC:
337       dev->sane.type = "flatbed scanner";
338 
339       /* FIXME: which of these are flatbed or handhelds? */
340     case EPSON_ES300C:
341     case FUJITSU_M3096G:
342     case IBM_2456:
343     case MUSTEK_06000CX:
344     case MUSTEK_12000CX:
345     case RICOH_FS1:
346     case RICOH_IS410:
347     case RICOH_IS50:
348     case SHARP_JX600:
349     case UMAX_UC630:
350     case UMAX_UG630:
351     default:
352       dev->sane.type = "generic scanner";
353     }
354 
355   DBG(1, "attach: found %s %s, x=%g-%gmm, y=%g-%gmm, "
356       "resolution=%d-%ddpi\n", dev->sane.vendor, dev->sane.model,
357       SANE_UNFIX (dev->x_range.min), SANE_UNFIX (dev->x_range.max),
358       SANE_UNFIX (dev->y_range.min), SANE_UNFIX (dev->y_range.max),
359       dev->dpi_range.min, dev->dpi_range.max);
360 
361   ++num_devices;
362   dev->next = first_dev;
363   first_dev = dev;
364 
365   if (devp)
366     *devp = dev;
367   return SANE_STATUS_GOOD;
368 }
369 
370 static SANE_Status
init_options(PINT_Scanner *s)371 init_options (PINT_Scanner *s)
372 {
373   int i;
374   int x0, x1, y0, y1;
375 
376   memset (s->opt, 0, sizeof (s->opt));
377   memset (s->val, 0, sizeof (s->val));
378 
379   for (i = 0; i < NUM_OPTIONS; ++i)
380     {
381       s->opt[i].size = sizeof (SANE_Word);
382       s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
383     }
384 
385   s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
386   s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
387   s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
388   s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
389   s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
390 
391   /* "Mode" group: */
392   s->opt[OPT_MODE_GROUP].title = "Scan Mode";
393   s->opt[OPT_MODE_GROUP].desc = "";
394   s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
395   s->opt[OPT_MODE_GROUP].cap = 0;
396   s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
397 
398   /* scan mode */
399   s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
400   s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
401   s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
402   s->opt[OPT_MODE].type = SANE_TYPE_STRING;
403   s->opt[OPT_MODE].size = max_string_size (mode_list);
404   s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
405   s->opt[OPT_MODE].constraint.string_list = mode_list;
406 
407   /* Translate the current PINT mode into a string. */
408   switch (s->hw->scanio.scan_image_mode)
409     {
410     case SIM_BINARY_MONOCHROME:
411       s->val[OPT_MODE].s = strdup (mode_list[0]);
412       break;
413 
414     case SIM_DITHERED_MONOCHROME:
415       s->val[OPT_MODE].s = strdup (mode_list[1]);
416       break;
417 
418     case SIM_COLOR:
419       s->val[OPT_MODE].s = strdup (mode_list[3]);
420       break;
421 
422     case SIM_RED:
423       s->val[OPT_MODE].s = strdup (mode_list[4]);
424       break;
425 
426     case SIM_GREEN:
427       s->val[OPT_MODE].s = strdup (mode_list[5]);
428       break;
429 
430     case SIM_BLUE:
431       s->val[OPT_MODE].s = strdup (mode_list[6]);
432       break;
433 
434     case SIM_GRAYSCALE:
435     default:
436       s->val[OPT_MODE].s = strdup (mode_list[2]);
437     }
438 
439   /* resolution */
440   s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
441   s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
442   s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
443   s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
444   s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
445   s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
446   s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range;
447   s->val[OPT_RESOLUTION].w =
448     (s->hw->scanio.scan_x_resolution > s->hw->scanio.scan_y_resolution) ?
449     s->hw->scanio.scan_x_resolution : s->hw->scanio.scan_y_resolution;
450 
451   /* "Geometry" group: */
452 
453   s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
454   s->opt[OPT_GEOMETRY_GROUP].desc = "";
455   s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
456   s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
457   s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
458 
459   /* Calculate the x and y millimetre coordinates from the scanio. */
460   x0 = SANE_FIX (s->hw->scanio.scan_x_origin / TWELVEHUNDS_PER_MM);
461   y0 = SANE_FIX (s->hw->scanio.scan_y_origin / TWELVEHUNDS_PER_MM);
462   x1 = SANE_FIX ((s->hw->scanio.scan_x_origin + s->hw->scanio.scan_width)
463 		 / TWELVEHUNDS_PER_MM);
464   y1 = SANE_FIX ((s->hw->scanio.scan_y_origin + s->hw->scanio.scan_height)
465 		 / TWELVEHUNDS_PER_MM);
466 
467   /* top-left x */
468   s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
469   s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
470   s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
471   s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
472   s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
473   s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
474   s->opt[OPT_TL_X].constraint.range = &s->hw->x_range;
475   s->val[OPT_TL_X].w = x0;
476 
477   /* top-left y */
478   s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
479   s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
480   s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
481   s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
482   s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
483   s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
484   s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range;
485   s->val[OPT_TL_Y].w = y0;
486 
487   /* bottom-right x */
488   s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
489   s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
490   s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
491   s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
492   s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
493   s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
494   s->opt[OPT_BR_X].constraint.range = &s->hw->x_range;
495   s->val[OPT_BR_X].w = x1;
496 
497   /* bottom-right y */
498   s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
499   s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
500   s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
501   s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
502   s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
503   s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
504   s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range;
505   s->val[OPT_BR_Y].w = y1;
506 
507   /* "Enhancement" group: */
508 
509   s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
510   s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
511   s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
512   s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
513   s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
514 
515   /* brightness */
516   s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
517   s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
518   s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
519   s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
520   s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
521   s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
522   s->opt[OPT_BRIGHTNESS].constraint.range = &s7_range;
523   s->val[OPT_BRIGHTNESS].w = s->hw->scanio.scan_brightness - 128;
524 
525   /* contrast */
526   s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
527   s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
528   s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
529   s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
530   s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
531   s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
532   s->opt[OPT_CONTRAST].constraint.range = &s7_range;
533   s->val[OPT_CONTRAST].w = s->hw->scanio.scan_contrast - 128;
534   return SANE_STATUS_GOOD;
535 }
536 
537 static SANE_Status
do_cancel(PINT_Scanner *s)538 do_cancel (PINT_Scanner *s)
539 {
540   /* FIXME: PINT doesn't have any good way to cancel ScanJets right now. */
541 #define gobble_up_buf_len 1024
542   char buf[gobble_up_buf_len];
543 
544   /* Send the restart code. */
545   buf[0] = ioctl (s->fd, SCIOCRESTART, 0);
546 
547   if (!s->scanning)
548     return SANE_STATUS_CANCELLED;
549 
550   s->scanning = SANE_FALSE;
551 
552   /* Read to the end of the file. */
553   while (read (s->fd, buf, gobble_up_buf_len) > 0)
554     ;
555 #undef gobble_up_buf_len
556 
557   /* Finally, close the file descriptor. */
558   if (s->fd >= 0)
559     {
560       close (s->fd);
561       s->fd = -1;
562     }
563   return SANE_STATUS_CANCELLED;
564 }
565 
566 SANE_Status
sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize)567 sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize)
568 {
569   char dev_name[PATH_MAX];
570   size_t len;
571   FILE *fp;
572 
573   DBG_INIT();
574 
575   if (version_code)
576     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
577 
578   fp = sanei_config_open (PINT_CONFIG_FILE);
579   if (!fp)
580     {
581       /* default to /dev/scanner instead of insisting on config file */
582       attach ("/dev/scanner", 0);
583       return SANE_STATUS_GOOD;
584     }
585 
586   while (sanei_config_read (dev_name, sizeof (dev_name), fp))
587     {
588       if (dev_name[0] == '#')		/* ignore line comments */
589 	continue;
590       len = strlen (dev_name);
591 
592       if (!len)
593 	continue;			/* ignore empty lines */
594 
595       attach (dev_name, 0);
596     }
597   fclose (fp);
598   return SANE_STATUS_GOOD;
599 }
600 
601 void
sane_exit(void)602 sane_exit (void)
603 {
604   PINT_Device *dev, *next;
605 
606   for (dev = first_dev; dev; dev = next)
607     {
608       next = dev->next;
609       free ((void *) dev->sane.name);
610       free (dev);
611     }
612 }
613 
614 SANE_Status
sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)615 sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only)
616 {
617   static const SANE_Device **devlist = 0;
618   PINT_Device *dev;
619   int i;
620 
621   if (devlist)
622     free (devlist);
623 
624   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
625   if (!devlist)
626     return SANE_STATUS_NO_MEM;
627 
628   i = 0;
629   for (dev = first_dev; i < num_devices; dev = dev->next)
630     devlist[i++] = &dev->sane;
631   devlist[i++] = 0;
632 
633   *device_list = devlist;
634   return SANE_STATUS_GOOD;
635 }
636 
637 SANE_Status
sane_open(SANE_String_Const devicename, SANE_Handle *handle)638 sane_open (SANE_String_Const devicename, SANE_Handle *handle)
639 {
640   SANE_Status status;
641   PINT_Device *dev;
642   PINT_Scanner *s;
643 
644   if (devicename[0])
645     {
646       for (dev = first_dev; dev; dev = dev->next)
647 	if (strcmp (dev->sane.name, devicename) == 0)
648 	  break;
649 
650       if (!dev)
651 	{
652 	  status = attach (devicename, &dev);
653 	  if (status != SANE_STATUS_GOOD)
654 	    return status;
655 	}
656     }
657   else
658     /* empty devicename -> use first device */
659     dev = first_dev;
660 
661   if (!dev)
662     return SANE_STATUS_INVAL;
663 
664   s = malloc (sizeof (*s));
665   if (!s)
666     return SANE_STATUS_NO_MEM;
667   memset (s, 0, sizeof (*s));
668   s->hw = dev;
669   s->fd = -1;
670 
671   init_options (s);
672 
673   /* insert newly opened handle into list of open handles: */
674   s->next = first_handle;
675   first_handle = s;
676 
677   *handle = s;
678   return SANE_STATUS_GOOD;
679 }
680 
681 void
sane_close(SANE_Handle handle)682 sane_close (SANE_Handle handle)
683 {
684   PINT_Scanner *prev, *s;
685 
686   /* remove handle from list of open handles: */
687   prev = 0;
688   for (s = first_handle; s; s = s->next)
689     {
690       if (s == handle)
691 	break;
692       prev = s;
693     }
694   if (!s)
695     {
696       DBG(1, "close: invalid handle %p\n", handle);
697       return;		/* oops, not a handle we know about */
698     }
699 
700   if (s->scanning)
701     do_cancel (handle);
702 
703   if (prev)
704     prev->next = s->next;
705   else
706     first_handle = s->next;
707 
708   free (handle);
709 }
710 
711 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)712 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
713 {
714   PINT_Scanner *s = handle;
715 
716   if ((unsigned) option >= NUM_OPTIONS)
717     return 0;
718   return s->opt + option;
719 }
720 
721 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int *info)722 sane_control_option (SANE_Handle handle, SANE_Int option,
723 		     SANE_Action action, void *val, SANE_Int *info)
724 {
725   PINT_Scanner *s = handle;
726   SANE_Status status;
727   SANE_Word cap;
728 
729   if (info)
730     *info = 0;
731 
732   if (s->scanning)
733     return SANE_STATUS_DEVICE_BUSY;
734 
735   if (option >= NUM_OPTIONS)
736     return SANE_STATUS_INVAL;
737 
738   cap = s->opt[option].cap;
739 
740   if (!SANE_OPTION_IS_ACTIVE (cap))
741     return SANE_STATUS_INVAL;
742 
743   if (action == SANE_ACTION_GET_VALUE)
744     {
745       switch (option)
746 	{
747 	  /* word options: */
748 	case OPT_RESOLUTION:
749 	case OPT_TL_X:
750 	case OPT_TL_Y:
751 	case OPT_BR_X:
752 	case OPT_BR_Y:
753 	case OPT_NUM_OPTS:
754 	case OPT_BRIGHTNESS:
755 	case OPT_CONTRAST:
756 	  *(SANE_Word *) val = s->val[option].w;
757 	  return SANE_STATUS_GOOD;
758 
759 	  /* string options: */
760 	case OPT_MODE:
761 	  strcpy (val, s->val[option].s);
762 	  return SANE_STATUS_GOOD;
763 	}
764     }
765   else if (action == SANE_ACTION_SET_VALUE)
766     {
767       if (!SANE_OPTION_IS_SETTABLE (cap))
768 	return SANE_STATUS_INVAL;
769 
770       status = sanei_constrain_value (s->opt + option, val, info);
771       if (status != SANE_STATUS_GOOD)
772 	return status;
773 
774       switch (option)
775 	{
776 	  /* (mostly) side-effect-free word options: */
777 	case OPT_RESOLUTION:
778 	case OPT_TL_X:
779 	case OPT_TL_Y:
780 	case OPT_BR_X:
781 	case OPT_BR_Y:
782 	  if (info)
783 	    *info |= SANE_INFO_RELOAD_PARAMS;
784 	  /* fall through */
785 	case OPT_NUM_OPTS:
786 	case OPT_BRIGHTNESS:
787 	case OPT_CONTRAST:
788 	  s->val[option].w = *(SANE_Word *) val;
789 	  return SANE_STATUS_GOOD;
790 
791 	case OPT_MODE:
792 	  if (s->val[option].s)
793 	    free (s->val[option].s);
794 	  s->val[option].s = strdup (val);
795 	  if (info)
796 	    *info |= SANE_INFO_RELOAD_PARAMS;
797 	  return SANE_STATUS_GOOD;
798 	}
799     }
800   return SANE_STATUS_INVAL;
801 }
802 
803 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)804 sane_get_parameters (SANE_Handle handle, SANE_Parameters *params)
805 {
806   PINT_Scanner *s = handle;
807   struct scan_io scanio;
808 
809   if (!s->scanning)
810     {
811       u_long x0, y0, width, height;
812       const char *mode;
813 
814       /* Grab the scanio for this device. */
815       if (s->fd < 0)
816 	{
817 	  s->fd = open (s->hw->sane.name, O_RDONLY, 0);
818 	  if (s->fd < 0)
819 	    {
820 	      DBG(1, "open of %s failed: %s\n",
821 		  s->hw->sane.name, strerror (errno));
822 	      return SANE_STATUS_INVAL;
823 	    }
824 	}
825 
826       if (ioctl (s->fd, SCIOCGET, &scanio) < 0)
827 	{
828 	  DBG(1, "getting scanner state failed: %s", strerror (errno));
829 	  return SANE_STATUS_INVAL;
830 	}
831 
832       memset (&s->params, 0, sizeof (s->params));
833 
834       /* FIXME: there is some lossage here: the parameters change due to
835 	 roundoff errors between converting to fixed point millimetres
836 	 and back. */
837       x0 = SANE_UNFIX (s->val[OPT_TL_X].w * TWELVEHUNDS_PER_MM);
838       y0 = SANE_UNFIX (s->val[OPT_TL_Y].w * TWELVEHUNDS_PER_MM);
839       width  = SANE_UNFIX ((s->val[OPT_BR_X].w - s->val[OPT_TL_X].w)
840 			   * TWELVEHUNDS_PER_MM);
841       height = SANE_UNFIX ((s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w)
842 			   * TWELVEHUNDS_PER_MM);
843 
844       /* x and y dpi: */
845       scanio.scan_x_resolution = s->val[OPT_RESOLUTION].w;
846       scanio.scan_y_resolution = s->val[OPT_RESOLUTION].w;
847 
848       /* set scan extents, in 1/1200'ths of an inch */
849       scanio.scan_x_origin = x0;
850       scanio.scan_y_origin = y0;
851       scanio.scan_width = width;
852       scanio.scan_height = height;
853 
854       /* brightness and contrast */
855       scanio.scan_brightness = s->val[OPT_BRIGHTNESS].w + 128;
856       scanio.scan_contrast = s->val[OPT_CONTRAST].w + 128;
857 
858       /* set the scan image mode */
859       mode = s->val[OPT_MODE].s;
860       if (!strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART))
861 	{
862 	  s->params.format = SANE_FRAME_GRAY;
863 	  scanio.scan_image_mode = SIM_BINARY_MONOCHROME;
864 	}
865       else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE))
866 	{
867 	  s->params.format = SANE_FRAME_GRAY;
868 	  scanio.scan_image_mode = SIM_DITHERED_MONOCHROME;
869 	}
870       else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY))
871 	{
872 	  s->params.format = SANE_FRAME_GRAY;
873 	  scanio.scan_image_mode = SIM_GRAYSCALE;
874 	}
875       else if (!strcmp (mode, "Red"))
876 	{
877 	  s->params.format = SANE_FRAME_RED;
878 	  scanio.scan_image_mode = SIM_RED;
879 	}
880       else if (!strcmp (mode, "Green"))
881 	{
882 	  s->params.format = SANE_FRAME_GREEN;
883 	  scanio.scan_image_mode = SIM_GREEN;
884 	}
885       else if (!strcmp (mode, "Blue"))
886 	{
887 	  s->params.format = SANE_FRAME_BLUE;
888 	  scanio.scan_image_mode = SIM_BLUE;
889 	}
890       else
891 	{
892 	  s->params.format = SANE_FRAME_RGB;
893 	  scanio.scan_image_mode = SIM_COLOR;
894 	}
895 
896       /* inquire resulting size of image after setting it up */
897       if (ioctl (s->fd, SCIOCSET, &scanio) < 0)
898 	{
899 	  DBG(1, "setting scan parameters failed: %s", strerror (errno));
900 	  return SANE_STATUS_INVAL;
901 	}
902       if (ioctl (s->fd, SCIOCGET, &scanio) < 0)
903 	{
904 	  DBG(1, "getting scan parameters failed: %s", strerror (errno));
905 	  return SANE_STATUS_INVAL;
906 	}
907 
908       /* Save all the PINT-computed values. */
909       s->params.pixels_per_line = scanio.scan_pixels_per_line;
910       s->params.bytes_per_line =
911 	(scanio.scan_bits_per_pixel * scanio.scan_pixels_per_line + 7) / 8;
912       s->params.lines = scanio.scan_lines;
913       s->params.depth = (scanio.scan_image_mode == SIM_COLOR) ?
914 	scanio.scan_bits_per_pixel / 3 : scanio.scan_bits_per_pixel;
915 
916       /* FIXME: this will need to be different for hand scanners. */
917       s->params.last_frame = SANE_TRUE;
918     }
919   if (params)
920     *params = s->params;
921   return SANE_STATUS_GOOD;
922 }
923 
924 SANE_Status
sane_start(SANE_Handle handle)925 sane_start (SANE_Handle handle)
926 {
927   PINT_Scanner *s = handle;
928   SANE_Status status;
929 
930   /* First make sure we have a current parameter set.  This call actually
931      uses the PINT driver to do the calculations, so we trust its results. */
932   status = sane_get_parameters (s, 0);
933   if (status != SANE_STATUS_GOOD)
934     return status;
935 
936   DBG(1, "%d pixels per line, %d bytes, %d lines high, dpi=%d\n",
937       s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines,
938       s->val[OPT_RESOLUTION].w);
939 
940   /* The scan is triggered in sane_read. */
941   s->scanning = SANE_TRUE;
942   return SANE_STATUS_GOOD;
943 }
944 
945 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len)946 sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len)
947 {
948   PINT_Scanner *s = handle;
949   ssize_t nread;
950 
951   *len = 0;
952 
953   if (!s->scanning)
954     return do_cancel (s);
955 
956   /* Verrry simple.  Just suck up all the data PINT passes to us. */
957   nread = read (s->fd, buf, max_len);
958   if (nread <= 0)
959     {
960       do_cancel (s);
961       return (nread == 0) ? SANE_STATUS_EOF : SANE_STATUS_IO_ERROR;
962     }
963 
964   *len = nread;
965   return SANE_STATUS_GOOD;
966 }
967 
968 void
sane_cancel(SANE_Handle handle)969 sane_cancel (SANE_Handle handle)
970 {
971   PINT_Scanner *s = handle;
972   do_cancel (s);
973 }
974 
975 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)976 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
977 {
978   return SANE_STATUS_UNSUPPORTED;
979 }
980 
981 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int *fd)982 sane_get_select_fd (SANE_Handle handle, SANE_Int *fd)
983 {
984   return SANE_STATUS_UNSUPPORTED;
985 }
986