1 /* sane - Scanner Access Now Easy.
2 
3    This file is part of the SANE package.
4 
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18    As a special exception, the authors of SANE give permission for
19    additional uses of the libraries contained in this release of SANE.
20 
21    The exception is that, if you link a SANE library with other files
22    to produce an executable, this does not by itself cause the
23    resulting executable to be covered by the GNU General Public
24    License.  Your use of that executable is in no way restricted on
25    account of linking the SANE library code into it.
26 
27    This exception does not, however, invalidate any other reasons why
28    the executable file might be covered by the GNU General Public
29    License.
30 
31    If you submit changes to SANE to the maintainers to be included in
32    a subsequent release, you agree by submitting the changes that
33    those changes may be distributed with this exception intact.
34 
35    If you write modifications of your own for SANE, it is your choice
36    whether to permit this exception to apply to your modifications.
37    If you do not wish that, delete this exception notice.
38 */
39 
40 /*
41    This file implements a SANE backend for the Ibm 2456 flatbed scanner,
42    written by mf <massifr@tiscalinet.it>. It derives from the backend for
43    Ricoh flatbed scanners written by Feico W. Dillema.
44 
45    Currently maintained by Henning Meier-Geinitz <henning@meier-geinitz.de>.
46 */
47 
48 #define BUILD 5
49 
50 #include "../include/sane/config.h"
51 
52 #include <limits.h>
53 #include <stdlib.h>
54 #include <stdarg.h>
55 #include <string.h>
56 #include <sys/time.h>
57 #include <unistd.h>
58 #include <ctype.h>
59 
60 #include "../include/sane/sane.h"
61 #include "../include/sane/saneopts.h"
62 #include "../include/sane/sanei_scsi.h"
63 
64 #define BACKEND_NAME ibm
65 #include "../include/sane/sanei_backend.h"
66 
67 #ifndef PATH_MAX
68 # define PATH_MAX	1024
69 #endif
70 
71 #include "../include/sane/sanei_config.h"
72 #define IBM_CONFIG_FILE "ibm.conf"
73 
74 #include "ibm.h"
75 #include "ibm-scsi.c"
76 
77 #define MAX(a,b)	((a) > (b) ? (a) : (b))
78 
79 static int num_devices = 0;
80 static Ibm_Device *first_dev = NULL;
81 static Ibm_Scanner *first_handle = NULL;
82 /* static int is50 = 0; */
83 
84 
85 static size_t
max_string_size(const SANE_String_Const strings[])86 max_string_size (const SANE_String_Const strings[])
87 {
88   size_t size, max_size = 0;
89   int i;
90   DBG (11, ">> max_string_size\n");
91 
92   for (i = 0; strings[i]; ++i)
93     {
94       size = strlen (strings[i]) + 1;
95       if (size > max_size)
96         max_size = size;
97     }
98 
99   DBG (11, "<< max_string_size\n");
100   return max_size;
101 }
102 
103 static SANE_Status
attach(const char *devnam, Ibm_Device ** devp)104 attach (const char *devnam, Ibm_Device ** devp)
105 {
106   SANE_Status status;
107   Ibm_Device *dev;
108 
109   int fd;
110   struct inquiry_data ibuf;
111   struct measurements_units_page mup;
112   struct ibm_window_data wbuf;
113   size_t buf_size;
114   char *str;
115   DBG (11, ">> attach\n");
116 
117   for (dev = first_dev; dev; dev = dev->next)
118     {
119       if (strcmp (dev->sane.name, devnam) == 0)
120         {
121           if (devp)
122             *devp = dev;
123           return (SANE_STATUS_GOOD);
124         }
125     }
126 
127   DBG (3, "attach: opening %s\n", devnam);
128   status = sanei_scsi_open (devnam, &fd, NULL, NULL);
129   if (status != SANE_STATUS_GOOD)
130     {
131       DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
132       return (status);
133     }
134 
135   DBG (3, "attach: sending INQUIRY\n");
136   memset (&ibuf, 0, sizeof (ibuf));
137   buf_size = sizeof(ibuf);
138 /* next line by mf */
139   ibuf.byte2 = 2;
140   status = inquiry (fd, &ibuf, &buf_size);
141   if (status != SANE_STATUS_GOOD)
142     {
143       DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status));
144       sanei_scsi_close (fd);
145       return (status);
146     }
147 
148   if (ibuf.devtype != 6)
149     {
150       DBG (1, "attach: device \"%s\" is not a scanner\n", devnam);
151       sanei_scsi_close (fd);
152       return (SANE_STATUS_INVAL);
153     }
154 
155   if (!(
156 	(strncmp ((char *)ibuf.vendor, "IBM", 3) ==0
157          && strncmp ((char *)ibuf.product, "2456", 4) == 0)
158         || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0
159 	    && strncmp ((char *)ibuf.product, "IS420", 5) == 0)
160         || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0
161 	    && strncmp ((char *)ibuf.product, "IS410", 5) == 0)
162         || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0
163 	    && strncmp ((char *)ibuf.product, "IS430", 5) == 0)
164 	))
165     {
166       DBG (1, "attach: device \"%s\" doesn't look like a scanner I know\n",
167 	   devnam);
168       sanei_scsi_close (fd);
169       return (SANE_STATUS_INVAL);
170     }
171 
172   DBG (3, "attach: sending TEST_UNIT_READY\n");
173   status = test_unit_ready (fd);
174   if (status != SANE_STATUS_GOOD)
175     {
176       DBG (1, "attach: test unit ready failed (%s)\n",
177            sane_strstatus (status));
178       sanei_scsi_close (fd);
179       return (status);
180     }
181   /*
182    * Causes a problem with RICOH IS420
183    * Ignore this function ... seems to work ok
184    * Suggested to George Murphy george@topfloor.ie by henning
185    */
186   if (strncmp((char *)ibuf.vendor, "RICOH", 5) != 0
187       && strncmp((char *)ibuf.product, "IS420", 5) != 0)
188     {
189       DBG (3, "attach: sending OBJECT POSITION\n");
190       status = object_position (fd, OBJECT_POSITION_UNLOAD);
191       if (status != SANE_STATUS_GOOD)
192     	{
193 	  DBG (1, "attach: OBJECT POSITION failed\n");
194 	  sanei_scsi_close (fd);
195 	  return (SANE_STATUS_INVAL);
196     	}
197     }
198 
199   memset (&mup, 0, sizeof (mup));
200   mup.page_code = MEASUREMENTS_PAGE;
201   mup.parameter_length = 0x06;
202   mup.bmu = INCHES;
203   mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
204   mup.mud[1] = (DEFAULT_MUD & 0xff);
205 
206 #if 0
207   DBG (3, "attach: sending MODE SELECT\n");
208   status = mode_select (fd, (struct mode_pages *) &mup);
209   if (status != SANE_STATUS_GOOD)
210     {
211       DBG (1, "attach: MODE_SELECT failed\n");
212       sanei_scsi_close (fd);
213       return (SANE_STATUS_INVAL);
214     }
215 #endif
216 
217 #if 0
218   DBG (3, "attach: sending MODE SENSE\n");
219   memset (&mup, 0, sizeof (mup));
220   status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE);
221   if (status != SANE_STATUS_GOOD)
222     {
223       DBG (1, "attach: MODE_SENSE failed\n");
224       sanei_scsi_close (fd);
225       return (SANE_STATUS_INVAL);
226     }
227 #endif
228 
229   DBG (3, "attach: sending GET WINDOW\n");
230   memset (&wbuf, 0, sizeof (wbuf));
231   status = get_window (fd, &wbuf);
232   if (status != SANE_STATUS_GOOD)
233     {
234       DBG (1, "attach: GET_WINDOW failed %d\n", status);
235       sanei_scsi_close (fd);
236       DBG (11, "<< attach\n");
237       return (SANE_STATUS_INVAL);
238     }
239 
240   sanei_scsi_close (fd);
241 
242   dev = malloc (sizeof (*dev));
243   if (!dev)
244     return (SANE_STATUS_NO_MEM);
245   memset (dev, 0, sizeof (*dev));
246 
247   dev->sane.name = strdup (devnam);
248   dev->sane.vendor = "IBM";
249 
250   size_t prod_rev_size = sizeof(ibuf.product) + sizeof(ibuf.revision) + 1;
251   str = malloc (prod_rev_size);
252   if (str)
253     {
254       snprintf (str, prod_rev_size, "%.*s%.*s",
255                 (int) sizeof(ibuf.product), (const char *) ibuf.product,
256                 (int) sizeof(ibuf.revision), (const char *) ibuf.revision);
257     }
258   dev->sane.model = str;
259   dev->sane.type = "flatbed scanner";
260 
261   DBG (5, "dev->sane.name = %s\n", dev->sane.name);
262   DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor);
263   DBG (5, "dev->sane.model = %s\n", dev->sane.model);
264   DBG (5, "dev->sane.type = %s\n", dev->sane.type);
265 
266   dev->info.xres_default = _2btol(wbuf.x_res);
267   dev->info.yres_default = _2btol(wbuf.y_res);
268   dev->info.image_mode_default = wbuf.image_comp;
269 
270   /* if you throw the MRIF bit the brightness control reverses too */
271   /* so I reverse the reversal in software for symmetry's sake */
272   /* I should make this into an option */
273 
274   if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME)
275     {
276       dev->info.brightness_default = 256 - wbuf.brightness;
277 /*
278       if (is50)
279 	dev->info.contrast_default = wbuf.contrast;
280       else
281 */
282       dev->info.contrast_default = 256 - wbuf.contrast;
283     }
284   else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
285     {
286       dev->info.brightness_default = wbuf.brightness;
287       dev->info.contrast_default = wbuf.contrast;
288     }
289 
290 /* da rivedere
291   dev->info.adf_default = wbuf.adf_state;
292 */
293   dev->info.adf_default = ADF_UNUSED;
294   dev->info.adf_default = IBM_PAPER_USER_DEFINED;
295 
296 #if 1
297   dev->info.bmu = mup.bmu;
298   dev->info.mud = _2btol(mup.mud);
299   if (dev->info.mud == 0) {
300     /* The Ricoh says it uses points as default Basic Measurement Unit */
301     /* but gives a Measurement Unit Divisor of zero */
302     /* So, we set it to the default (SCSI-standard) of 1200 */
303     /* with BMU in inches, i.e. 1200 points equal 1 inch */
304     dev->info.bmu = INCHES;
305     dev->info.mud = DEFAULT_MUD;
306   }
307 #else
308     dev->info.bmu = INCHES;
309     dev->info.mud = DEFAULT_MUD;
310 #endif
311 
312   DBG (5, "xres_default=%d\n", dev->info.xres_default);
313   DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max);
314   DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min);
315 
316   DBG (5, "yres_default=%d\n", dev->info.yres_default);
317   DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max);
318   DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min);
319 
320   DBG (5, "x_range.max=%d\n", dev->info.x_range.max);
321   DBG (5, "y_range.max=%d\n", dev->info.y_range.max);
322 
323   DBG (5, "image_mode=%d\n", dev->info.image_mode_default);
324 
325   DBG (5, "brightness=%d\n", dev->info.brightness_default);
326   DBG (5, "contrast=%d\n", dev->info.contrast_default);
327 
328   DBG (5, "adf_state=%d\n", dev->info.adf_default);
329 
330   DBG (5, "bmu=%d\n", dev->info.bmu);
331   DBG (5, "mud=%d\n", dev->info.mud);
332 
333   ++num_devices;
334   dev->next = first_dev;
335   first_dev = dev;
336 
337   if (devp)
338     *devp = dev;
339 
340   DBG (11, "<< attach\n");
341   return (SANE_STATUS_GOOD);
342 }
343 
344 static SANE_Status
attach_one(const char *devnam)345 attach_one(const char *devnam)
346 {
347   attach (devnam, NULL);
348   return SANE_STATUS_GOOD;
349 }
350 
351 static SANE_Status
init_options(Ibm_Scanner * s)352 init_options (Ibm_Scanner * s)
353 {
354   int i;
355   DBG (11, ">> init_options\n");
356 
357   memset (s->opt, 0, sizeof (s->opt));
358   memset (s->val, 0, sizeof (s->val));
359 
360   for (i = 0; i < NUM_OPTIONS; ++i)
361     {
362       s->opt[i].size = sizeof (SANE_Word);
363       s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
364     }
365 
366   s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
367   s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
368   s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
369   s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
370   s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
371 
372   /* "Mode" group: */
373   s->opt[OPT_MODE_GROUP].title = "Scan Mode";
374   s->opt[OPT_MODE_GROUP].desc = "";
375   s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
376   s->opt[OPT_MODE_GROUP].cap = 0;
377   s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
378 
379   /* scan mode */
380   s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
381   s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
382   s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
383   s->opt[OPT_MODE].type = SANE_TYPE_STRING;
384   s->opt[OPT_MODE].size = max_string_size (mode_list);
385   s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
386   s->opt[OPT_MODE].constraint.string_list = mode_list;
387   s->val[OPT_MODE].s = strdup (mode_list[s->hw->info.image_mode_default]);
388 
389   /* x resolution */
390   s->opt[OPT_X_RESOLUTION].name = "X" SANE_NAME_SCAN_RESOLUTION;
391   s->opt[OPT_X_RESOLUTION].title = "X " SANE_TITLE_SCAN_RESOLUTION;
392   s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
393   s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
394   s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
395   s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
396   s->opt[OPT_X_RESOLUTION].constraint.range = &ibm2456_res_range;
397   s->val[OPT_X_RESOLUTION].w = s->hw->info.xres_default;
398 /*
399   if (is50)
400     s->opt[OPT_X_RESOLUTION].constraint.range = &is50_res_range;
401   else
402 */
403   s->opt[OPT_X_RESOLUTION].constraint.range = &ibm2456_res_range;
404 
405   /* y resolution */
406   s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION;
407   s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION;
408   s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
409   s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
410   s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
411   s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
412   s->val[OPT_Y_RESOLUTION].w =  s->hw->info.yres_default;
413   s->opt[OPT_Y_RESOLUTION].constraint.range = &ibm2456_res_range;
414 
415   /* adf */
416   s->opt[OPT_ADF].name = "adf";
417   s->opt[OPT_ADF].title = "Use ADF";
418   s->opt[OPT_ADF].desc = "Uses the automatic document feeder.";
419   s->opt[OPT_ADF].type = SANE_TYPE_BOOL;
420   s->opt[OPT_ADF].unit = SANE_UNIT_NONE;
421   s->opt[OPT_ADF].constraint_type = SANE_CONSTRAINT_NONE;
422   s->val[OPT_ADF].b =  s->hw->info.adf_default;
423 
424   /* "Geometry" group: */
425   s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
426   s->opt[OPT_GEOMETRY_GROUP].desc = "";
427   s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
428   s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
429   s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
430 
431   /* paper */
432   s->opt[OPT_PAPER].name = "paper";
433   s->opt[OPT_PAPER].title = "Paper format";
434   s->opt[OPT_PAPER].desc = "Sets the paper format.";
435   s->opt[OPT_PAPER].type = SANE_TYPE_STRING;
436   s->opt[OPT_PAPER].size = max_string_size (paper_list);
437   s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST;
438   s->opt[OPT_PAPER].constraint.string_list = paper_list;
439   s->val[OPT_PAPER].s = strdup (paper_list[s->hw->info.paper_default]);
440 
441   /* top-left x */
442   s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
443   s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
444   s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
445   s->opt[OPT_TL_X].type = SANE_TYPE_INT;
446   s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
447   s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
448   s->opt[OPT_TL_X].constraint.range = &default_x_range;
449   s->val[OPT_TL_X].w = 0;
450 
451   /* top-left y */
452   s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
453   s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
454   s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
455   s->opt[OPT_TL_Y].type = SANE_TYPE_INT;
456   s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
457   s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
458   s->opt[OPT_TL_Y].constraint.range = &default_y_range;
459   s->val[OPT_TL_Y].w = 0;
460 
461   /* bottom-right x */
462   s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
463   s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
464   s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
465   s->opt[OPT_BR_X].type = SANE_TYPE_INT;
466   s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
467   s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
468   s->opt[OPT_BR_X].constraint.range = &default_x_range;
469   s->val[OPT_BR_X].w = default_x_range.max;
470 
471   /* bottom-right y */
472   s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
473   s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
474   s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
475   s->opt[OPT_BR_Y].type = SANE_TYPE_INT;
476   s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
477   s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
478   s->opt[OPT_BR_Y].constraint.range = &default_y_range;
479   s->val[OPT_BR_Y].w = default_y_range.max;
480 
481   /* "Enhancement" group: */
482   s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
483   s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
484   s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
485   s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
486   s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
487 
488   /* brightness */
489   s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
490   s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
491   s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
492   s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
493   s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
494   s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
495   s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range;
496   s->val[OPT_BRIGHTNESS].w =  s->hw->info.brightness_default;
497 
498   /* contrast */
499   s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
500   s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
501   s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
502   s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
503   s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
504   s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
505   s->opt[OPT_CONTRAST].constraint.range = &u8_range;
506   s->val[OPT_CONTRAST].w =  s->hw->info.contrast_default;
507 
508   DBG (11, "<< init_options\n");
509   return SANE_STATUS_GOOD;
510 }
511 
512 static SANE_Status
do_cancel(Ibm_Scanner * s)513 do_cancel (Ibm_Scanner * s)
514 {
515   SANE_Status status;
516   DBG (11, ">> do_cancel\n");
517 
518   DBG (3, "cancel: sending OBJECT POSITION\n");
519   status = object_position (s->fd, OBJECT_POSITION_UNLOAD);
520   if (status != SANE_STATUS_GOOD)
521     {
522       DBG (1, "cancel: OBJECT POSITION failed\n");
523     }
524 
525   s->scanning = SANE_FALSE;
526 
527   if (s->fd >= 0)
528     {
529       sanei_scsi_close (s->fd);
530       s->fd = -1;
531     }
532 
533   DBG (11, "<< do_cancel\n");
534   return (SANE_STATUS_CANCELLED);
535 }
536 
537 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize)538 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
539 {
540   char devnam[PATH_MAX] = "/dev/scanner";
541   FILE *fp;
542 
543   DBG_INIT ();
544   DBG (11, ">> sane_init (authorize %s null)\n", (authorize) ? "!=" : "==");
545 
546 #if defined PACKAGE && defined VERSION
547   DBG (2, "sane_init: ibm backend version %d.%d-%d ("
548        PACKAGE " " VERSION ")\n", SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
549 #endif
550 
551   if (version_code)
552     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
553 
554   fp = sanei_config_open(IBM_CONFIG_FILE);
555   if (fp)
556     {
557       char line[PATH_MAX], *lp;
558       size_t len;
559 
560       /* read config file */
561       while (sanei_config_read (line, sizeof (line), fp))
562         {
563           if (line[0] == '#')           /* ignore line comments */
564             continue;
565           len = strlen (line);
566 
567           if (!len)
568             continue;                   /* ignore empty lines */
569 
570 	  /* skip white space: */
571 	  for (lp = line; isspace(*lp); ++lp)
572             ;
573           strcpy (devnam, lp);
574         }
575       fclose (fp);
576     }
577   sanei_config_attach_matching_devices (devnam, attach_one);
578   DBG (11, "<< sane_init\n");
579   return SANE_STATUS_GOOD;
580 }
581 
582 void
sane_exit(void)583 sane_exit (void)
584 {
585   Ibm_Device *dev, *next;
586   DBG (11, ">> sane_exit\n");
587 
588   for (dev = first_dev; dev; dev = next)
589     {
590       next = dev->next;
591       free ((void *) dev->sane.name);
592       free ((void *) dev->sane.model);
593       free (dev);
594     }
595 
596   DBG (11, "<< sane_exit\n");
597 }
598 
599 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only)600 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
601 {
602   static const SANE_Device **devlist = 0;
603   Ibm_Device *dev;
604   int i;
605   DBG (11, ">> sane_get_devices (local_only = %d)\n", local_only);
606 
607   if (devlist)
608     free (devlist);
609   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
610   if (!devlist)
611     return (SANE_STATUS_NO_MEM);
612 
613   i = 0;
614   for (dev = first_dev; dev; dev = dev->next)
615     devlist[i++] = &dev->sane;
616   devlist[i++] = 0;
617 
618   *device_list = devlist;
619 
620   DBG (11, "<< sane_get_devices\n");
621   return SANE_STATUS_GOOD;
622 }
623 
624 SANE_Status
sane_open(SANE_String_Const devnam, SANE_Handle * handle)625 sane_open (SANE_String_Const devnam, SANE_Handle * handle)
626 {
627   SANE_Status status;
628   Ibm_Device *dev;
629   Ibm_Scanner *s;
630   DBG (11, ">> sane_open\n");
631 
632   if (devnam[0] == '\0')
633     {
634       for (dev = first_dev; dev; dev = dev->next)
635         {
636           if (strcmp (dev->sane.name, devnam) == 0)
637             break;
638         }
639 
640       if (!dev)
641         {
642           status = attach (devnam, &dev);
643           if (status != SANE_STATUS_GOOD)
644             return (status);
645         }
646     }
647   else
648     {
649       dev = first_dev;
650     }
651 
652   if (!dev)
653     return (SANE_STATUS_INVAL);
654 
655   s = malloc (sizeof (*s));
656   if (!s)
657     return SANE_STATUS_NO_MEM;
658   memset (s, 0, sizeof (*s));
659 
660   s->fd = -1;
661   s->hw = dev;
662 
663   init_options (s);
664 
665   s->next = first_handle;
666   first_handle = s;
667 
668   *handle = s;
669 
670   DBG (11, "<< sane_open\n");
671   return SANE_STATUS_GOOD;
672 }
673 
674 void
sane_close(SANE_Handle handle)675 sane_close (SANE_Handle handle)
676 {
677   Ibm_Scanner *s = (Ibm_Scanner *) handle;
678   DBG (11, ">> sane_close\n");
679 
680   if (s->fd != -1)
681     sanei_scsi_close (s->fd);
682   free (s);
683 
684   DBG (11, ">> sane_close\n");
685 }
686 
687 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)688 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
689 {
690   Ibm_Scanner *s = handle;
691   DBG (11, ">> sane_get_option_descriptor\n");
692 
693   if ((unsigned) option >= NUM_OPTIONS)
694     return (0);
695 
696   DBG (11, "<< sane_get_option_descriptor\n");
697   return (s->opt + option);
698 }
699 
700 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info)701 sane_control_option (SANE_Handle handle, SANE_Int option,
702                      SANE_Action action, void *val, SANE_Int * info)
703 {
704   Ibm_Scanner *s = handle;
705   SANE_Status status;
706   SANE_Word cap;
707   DBG (11, ">> sane_control_option\n");
708 
709   if (info)
710     *info = 0;
711 
712   if (s->scanning)
713     return (SANE_STATUS_DEVICE_BUSY);
714   if (option >= NUM_OPTIONS)
715     return (SANE_STATUS_INVAL);
716 
717   cap = s->opt[option].cap;
718   if (!SANE_OPTION_IS_ACTIVE (cap))
719     return (SANE_STATUS_INVAL);
720 
721   if (action == SANE_ACTION_GET_VALUE)
722     {
723       DBG (11, "sane_control_option get_value\n");
724       switch (option)
725         {
726           /* word options: */
727         case OPT_X_RESOLUTION:
728         case OPT_Y_RESOLUTION:
729         case OPT_TL_X:
730         case OPT_TL_Y:
731         case OPT_BR_X:
732         case OPT_BR_Y:
733         case OPT_NUM_OPTS:
734         case OPT_BRIGHTNESS:
735         case OPT_CONTRAST:
736           *(SANE_Word *) val = s->val[option].w;
737           return (SANE_STATUS_GOOD);
738 
739           /* bool options: */
740 	case OPT_ADF:
741           *(SANE_Bool *) val = s->val[option].b;
742           return (SANE_STATUS_GOOD);
743 
744           /* string options: */
745         case OPT_MODE:
746 	case OPT_PAPER:
747           strcpy (val, s->val[option].s);
748           return (SANE_STATUS_GOOD);
749         }
750     }
751   else {
752     DBG (11, "sane_control_option set_value\n");
753     if (action == SANE_ACTION_SET_VALUE)
754     {
755       if (!SANE_OPTION_IS_SETTABLE (cap))
756         return (SANE_STATUS_INVAL);
757 
758       status = sanei_constrain_value (s->opt + option, val, info);
759       if (status != SANE_STATUS_GOOD)
760         return status;
761 
762       switch (option)
763         {
764           /* (mostly) side-effect-free word options: */
765         case OPT_X_RESOLUTION:
766         case OPT_Y_RESOLUTION:
767           if (info && s->val[option].w != *(SANE_Word *) val)
768             *info |= SANE_INFO_RELOAD_PARAMS;
769           s->val[option].w = *(SANE_Word *) val;
770           return (SANE_STATUS_GOOD);
771 
772 	case OPT_TL_X:
773         case OPT_TL_Y:
774         case OPT_BR_X:
775         case OPT_BR_Y:
776           if (info && s->val[option].w != *(SANE_Word *) val)
777             *info |= SANE_INFO_RELOAD_PARAMS;
778           s->val[option].w = *(SANE_Word *) val;
779 	  /* resets the paper format to user defined */
780 	  if (strcmp(s->val[OPT_PAPER].s, paper_list[IBM_PAPER_USER_DEFINED]) != 0)
781 	    {
782 	      if (info)
783 		*info |= SANE_INFO_RELOAD_OPTIONS;
784               if (s->val[OPT_PAPER].s)
785                 free (s->val[OPT_PAPER].s);
786               s->val[OPT_PAPER].s = strdup (paper_list[IBM_PAPER_USER_DEFINED]);
787 	    }
788           return (SANE_STATUS_GOOD);
789 
790 	case OPT_NUM_OPTS:
791         case OPT_BRIGHTNESS:
792         case OPT_CONTRAST:
793           s->val[option].w = *(SANE_Word *) val;
794           return (SANE_STATUS_GOOD);
795 
796         case OPT_MODE:
797           if (info && strcmp (s->val[option].s, (SANE_String) val))
798             *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
799           if (s->val[option].s)
800             free (s->val[option].s);
801           s->val[option].s = strdup (val);
802           return (SANE_STATUS_GOOD);
803 
804 	case OPT_ADF:
805 	  s->val[option].b = *(SANE_Bool *) val;
806 	  if (*(SANE_Bool *) val)
807 	    s->adf_state = ADF_ARMED;
808           else
809 	    s->adf_state = ADF_UNUSED;
810 	  return (SANE_STATUS_GOOD);
811 
812 	case OPT_PAPER:
813           if (info && strcmp (s->val[option].s, (SANE_String) val))
814             *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
815           if (s->val[option].s)
816             free (s->val[option].s);
817           s->val[option].s = strdup (val);
818 	  if (strcmp (s->val[OPT_PAPER].s, "User") != 0)
819 	    {
820               s->val[OPT_TL_X].w = 0;
821 	      s->val[OPT_TL_Y].w = 0;
822 	    if (strcmp (s->val[OPT_PAPER].s, "A3") == 0)
823 	      {
824                 s->val[OPT_BR_X].w = PAPER_A3_W;
825 	        s->val[OPT_BR_Y].w = PAPER_A3_H;
826 	      }
827 	    else if (strcmp (s->val[OPT_PAPER].s, "A4") == 0)
828 	      {
829                 s->val[OPT_BR_X].w = PAPER_A4_W;
830 	        s->val[OPT_BR_Y].w = PAPER_A4_H;
831 	      }
832 	    else if (strcmp (s->val[OPT_PAPER].s, "A4R") == 0)
833 	      {
834                 s->val[OPT_BR_X].w = PAPER_A4R_W;
835 	        s->val[OPT_BR_Y].w = PAPER_A4R_H;
836 	      }
837 	    else if (strcmp (s->val[OPT_PAPER].s, "A5") == 0)
838 	      {
839                 s->val[OPT_BR_X].w = PAPER_A5_W;
840 	        s->val[OPT_BR_Y].w = PAPER_A5_H;
841 	      }
842 	    else if (strcmp (s->val[OPT_PAPER].s, "A5R") == 0)
843 	      {
844                 s->val[OPT_BR_X].w = PAPER_A5R_W;
845 	        s->val[OPT_BR_Y].w = PAPER_A5R_H;
846   	      }
847 	    else if (strcmp (s->val[OPT_PAPER].s, "A6") == 0)
848 	      {
849                 s->val[OPT_BR_X].w = PAPER_A6_W;
850 	        s->val[OPT_BR_Y].w = PAPER_A6_H;
851 	      }
852 	    else if (strcmp (s->val[OPT_PAPER].s, "B4") == 0)
853 	      {
854                 s->val[OPT_BR_X].w = PAPER_B4_W;
855 	        s->val[OPT_BR_Y].w = PAPER_B4_H;
856 	      }
857 	    else if (strcmp (s->val[OPT_PAPER].s, "Legal") == 0)
858 	      {
859                 s->val[OPT_BR_X].w = PAPER_LEGAL_W;
860 	        s->val[OPT_BR_Y].w = PAPER_LEGAL_H;
861 	      }
862 	    else if (strcmp (s->val[OPT_PAPER].s, "Letter") == 0)
863 	      {
864                 s->val[OPT_BR_X].w = PAPER_LETTER_W;
865 	        s->val[OPT_BR_Y].w = PAPER_LETTER_H;
866 	      }
867 	  }
868 	  return (SANE_STATUS_GOOD);
869         }
870 
871     }
872   }
873 
874   DBG (11, "<< sane_control_option\n");
875   return (SANE_STATUS_INVAL);
876 }
877 
878 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)879 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
880 {
881   Ibm_Scanner *s = handle;
882   DBG (11, ">> sane_get_parameters\n");
883 
884   if (!s->scanning)
885     {
886       int width, length, xres, yres;
887       const char *mode;
888 
889       memset (&s->params, 0, sizeof (s->params));
890 
891       width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
892       length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
893       xres = s->val[OPT_X_RESOLUTION].w;
894       yres = s->val[OPT_Y_RESOLUTION].w;
895 
896       /* make best-effort guess at what parameters will look like once
897          scanning starts.  */
898       if (xres > 0 && yres > 0 && width > 0 && length > 0)
899         {
900           s->params.pixels_per_line = width * xres / s->hw->info.mud;
901           s->params.lines = length * yres / s->hw->info.mud;
902         }
903 
904       mode = s->val[OPT_MODE].s;
905       if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) ||
906 	  (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE)) == 0)
907         {
908           s->params.format = SANE_FRAME_GRAY;
909           s->params.bytes_per_line = s->params.pixels_per_line / 8;
910 	  /* the Ibm truncates to the byte boundary, so: chop! */
911           s->params.pixels_per_line = s->params.bytes_per_line * 8;
912           s->params.depth = 1;
913         }
914       else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */
915         {
916           s->params.format = SANE_FRAME_GRAY;
917           s->params.bytes_per_line = s->params.pixels_per_line;
918           s->params.depth = 8;
919         }
920       s->params.last_frame = SANE_TRUE;
921     }
922   else
923     DBG (5, "sane_get_parameters: scanning, so can't get params\n");
924 
925   if (params)
926     *params = s->params;
927 
928   DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
929        "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
930        s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
931 
932   DBG (11, "<< sane_get_parameters\n");
933   return (SANE_STATUS_GOOD);
934 }
935 
936 
937 SANE_Status
sane_start(SANE_Handle handle)938 sane_start (SANE_Handle handle)
939 {
940   char *mode_str;
941   Ibm_Scanner *s = handle;
942   SANE_Status status;
943   struct ibm_window_data wbuf;
944   struct measurements_units_page mup;
945 
946   DBG (11, ">> sane_start\n");
947 
948   /* First make sure we have a current parameter set.  Some of the
949      parameters will be overwritten below, but that's OK.  */
950   status = sane_get_parameters (s, 0);
951   if (status != SANE_STATUS_GOOD)
952     return status;
953 
954   status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
955   if (status != SANE_STATUS_GOOD)
956     {
957       DBG (1, "open of %s failed: %s\n",
958            s->hw->sane.name, sane_strstatus (status));
959       return (status);
960     }
961 
962   mode_str = s->val[OPT_MODE].s;
963   s->xres = s->val[OPT_X_RESOLUTION].w;
964   s->yres = s->val[OPT_Y_RESOLUTION].w;
965   s->ulx = s->val[OPT_TL_X].w;
966   s->uly = s->val[OPT_TL_Y].w;
967   s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
968   s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
969   s->brightness = s->val[OPT_BRIGHTNESS].w;
970   s->contrast = s->val[OPT_CONTRAST].w;
971   s->bpp = s->params.depth;
972   if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0)
973     {
974       s->image_composition = IBM_BINARY_MONOCHROME;
975     }
976   else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
977     {
978       s->image_composition = IBM_DITHERED_MONOCHROME;
979     }
980   else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0)
981     {
982       s->image_composition = IBM_GRAYSCALE;
983     }
984 
985   memset (&wbuf, 0, sizeof (wbuf));
986 /* next line commented out by mf */
987 /*  _lto2b(sizeof(wbuf) - 8, wbuf.len); */
988 /* next line by mf */
989   _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */
990   _lto2b(s->xres, wbuf.x_res);
991   _lto2b(s->yres, wbuf.y_res);
992   _lto4b(s->ulx, wbuf.x_org);
993   _lto4b(s->uly, wbuf.y_org);
994   _lto4b(s->width, wbuf.width);
995   _lto4b(s->length, wbuf.length);
996 
997   wbuf.image_comp = s->image_composition;
998   /* if you throw the MRIF bit the brightness control reverses too */
999   /* so I reverse the reversal in software for symmetry's sake */
1000   if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME)
1001     {
1002       if (wbuf.image_comp == IBM_GRAYSCALE)
1003 	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */
1004       if (wbuf.image_comp == IBM_DITHERED_MONOCHROME)
1005 	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10;
1006       wbuf.brightness = 256 - (SANE_Byte) s->brightness;
1007 /*
1008       if (is50)
1009         wbuf.contrast = (SANE_Byte) s->contrast;
1010       else
1011 */
1012       wbuf.contrast = 256 - (SANE_Byte) s->contrast;
1013     }
1014   else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
1015     {
1016       wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00;
1017       wbuf.brightness = (SANE_Byte) s->brightness;
1018       wbuf.contrast = (SANE_Byte) s->contrast;
1019     }
1020 
1021   wbuf.threshold = 0;
1022   wbuf.bits_per_pixel = s->bpp;
1023 
1024   wbuf.halftone_code = 2;     /* diithering */
1025   wbuf.halftone_id = 0x0A;    /* 8x8 Bayer pattenr */
1026   wbuf.pad_type = 3;
1027   wbuf.bit_ordering[0] = 0;
1028   wbuf.bit_ordering[1] = 7;   /* modified by mf (it was 3) */
1029 
1030   DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
1031   DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
1032   DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
1033   DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
1034   DBG (5, "width=%d\n", _4btol(wbuf.width));
1035   DBG (5, "length=%d\n", _4btol(wbuf.length));
1036   DBG (5, "image_comp=%d\n", wbuf.image_comp);
1037 
1038   DBG (11, "sane_start: sending SET WINDOW\n");
1039   status = set_window (s->fd, &wbuf);
1040   if (status != SANE_STATUS_GOOD)
1041     {
1042       DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
1043       return (status);
1044     }
1045 
1046   DBG (11, "sane_start: sending GET WINDOW\n");
1047   memset (&wbuf, 0, sizeof (wbuf));
1048   status = get_window (s->fd, &wbuf);
1049   if (status != SANE_STATUS_GOOD)
1050     {
1051       DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
1052       return (status);
1053     }
1054   DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
1055   DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
1056   DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
1057   DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
1058   DBG (5, "width=%d\n", _4btol(wbuf.width));
1059   DBG (5, "length=%d\n", _4btol(wbuf.length));
1060   DBG (5, "image_comp=%d\n", wbuf.image_comp);
1061 
1062   DBG (11, "sane_start: sending MODE SELECT\n");
1063   memset (&mup, 0, sizeof (mup));
1064   mup.page_code = MEASUREMENTS_PAGE;
1065   mup.parameter_length = 0x06;
1066   mup.bmu = INCHES;
1067   mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
1068   mup.mud[1] = (DEFAULT_MUD & 0xff);
1069 /* next lines by mf */
1070   mup.adf_page_code = 0x26;
1071   mup.adf_parameter_length = 6;
1072   if (s->adf_state == ADF_ARMED)
1073     mup.adf_control = 1;
1074   else
1075     mup.adf_control = 0;
1076 /* end lines by mf */
1077 
1078   status = mode_select (s->fd, (struct mode_pages *) &mup);
1079   if (status != SANE_STATUS_GOOD)
1080     {
1081       DBG (1, "attach: MODE_SELECT failed\n");
1082       return (SANE_STATUS_INVAL);
1083     }
1084 
1085   status = trigger_scan (s->fd);
1086   if (status != SANE_STATUS_GOOD)
1087     {
1088       DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
1089       /* next line introduced not to freeze xscanimage */
1090       do_cancel(s);
1091       return status;
1092     }
1093 
1094   /* Wait for scanner to become ready to transmit data */
1095   status = ibm_wait_ready (s);
1096   if (status != SANE_STATUS_GOOD)
1097     {
1098       DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status));
1099       return (status);
1100     }
1101 
1102   s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
1103 
1104   DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
1105        "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
1106        s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
1107 
1108   s->scanning = SANE_TRUE;
1109 
1110   DBG (11, "<< sane_start\n");
1111   return (SANE_STATUS_GOOD);
1112 }
1113 
1114 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)1115 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
1116            SANE_Int * len)
1117 {
1118   Ibm_Scanner *s = handle;
1119   SANE_Status status;
1120   size_t nread;
1121   DBG (11, ">> sane_read\n");
1122 
1123   *len = 0;
1124 
1125   DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read);
1126 
1127   if (s->bytes_to_read == 0)
1128     {
1129       do_cancel (s);
1130       return (SANE_STATUS_EOF);
1131     }
1132 
1133   if (!s->scanning) {
1134     DBG (11, "sane_read: scanning is false!\n");
1135     return (do_cancel (s));
1136   }
1137 
1138   nread = max_len;
1139   if (nread > s->bytes_to_read)
1140     nread = s->bytes_to_read;
1141 
1142   DBG (11, "sane_read: read %ld bytes\n", (u_long) nread);
1143   status = read_data (s->fd, buf, &nread);
1144   if (status != SANE_STATUS_GOOD)
1145     {
1146       DBG (11, "sane_read: read error\n");
1147       do_cancel (s);
1148       return (SANE_STATUS_IO_ERROR);
1149     }
1150   *len = nread;
1151   s->bytes_to_read -= nread;
1152 
1153   DBG (11, "<< sane_read\n");
1154   return (SANE_STATUS_GOOD);
1155 }
1156 
1157 void
sane_cancel(SANE_Handle handle)1158 sane_cancel (SANE_Handle handle)
1159 {
1160   Ibm_Scanner *s = handle;
1161   DBG (11, ">> sane_cancel\n");
1162 
1163   s->scanning = SANE_FALSE;
1164 
1165   DBG (11, "<< sane_cancel\n");
1166 }
1167 
1168 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)1169 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1170 {
1171   DBG (5, ">> sane_set_io_mode (handle = %p, non_blocking = %d)\n",
1172        handle, non_blocking);
1173   DBG (5, "<< sane_set_io_mode\n");
1174 
1175   return SANE_STATUS_UNSUPPORTED;
1176 }
1177 
1178 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int * fd)1179 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1180 {
1181   DBG (5, ">> sane_get_select_fd (handle = %p, fd = %p)\n",
1182        handle, (void *) fd);
1183   DBG (5, "<< sane_get_select_fd\n");
1184 
1185   return SANE_STATUS_UNSUPPORTED;
1186 }
1187