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, V_MINOR, BUILD);
549 #endif
550 
551   if (version_code)
552     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_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           strcpy (devnam, lp);
573         }
574       fclose (fp);
575     }
576   sanei_config_attach_matching_devices (devnam, attach_one);
577   DBG (11, "<< sane_init\n");
578   return SANE_STATUS_GOOD;
579 }
580 
581 void
sane_exit(void)582 sane_exit (void)
583 {
584   Ibm_Device *dev, *next;
585   DBG (11, ">> sane_exit\n");
586 
587   for (dev = first_dev; dev; dev = next)
588     {
589       next = dev->next;
590       free ((void *) dev->sane.name);
591       free ((void *) dev->sane.model);
592       free (dev);
593     }
594 
595   DBG (11, "<< sane_exit\n");
596 }
597 
598 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)599 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
600 {
601   static const SANE_Device **devlist = 0;
602   Ibm_Device *dev;
603   int i;
604   DBG (11, ">> sane_get_devices (local_only = %d)\n", local_only);
605 
606   if (devlist)
607     free (devlist);
608   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
609   if (!devlist)
610     return (SANE_STATUS_NO_MEM);
611 
612   i = 0;
613   for (dev = first_dev; dev; dev = dev->next)
614     devlist[i++] = &dev->sane;
615   devlist[i++] = 0;
616 
617   *device_list = devlist;
618 
619   DBG (11, "<< sane_get_devices\n");
620   return SANE_STATUS_GOOD;
621 }
622 
623 SANE_Status
sane_open(SANE_String_Const devnam,SANE_Handle * handle)624 sane_open (SANE_String_Const devnam, SANE_Handle * handle)
625 {
626   SANE_Status status;
627   Ibm_Device *dev;
628   Ibm_Scanner *s;
629   DBG (11, ">> sane_open\n");
630 
631   if (devnam[0] == '\0')
632     {
633       for (dev = first_dev; dev; dev = dev->next)
634         {
635           if (strcmp (dev->sane.name, devnam) == 0)
636             break;
637         }
638 
639       if (!dev)
640         {
641           status = attach (devnam, &dev);
642           if (status != SANE_STATUS_GOOD)
643             return (status);
644         }
645     }
646   else
647     {
648       dev = first_dev;
649     }
650 
651   if (!dev)
652     return (SANE_STATUS_INVAL);
653 
654   s = malloc (sizeof (*s));
655   if (!s)
656     return SANE_STATUS_NO_MEM;
657   memset (s, 0, sizeof (*s));
658 
659   s->fd = -1;
660   s->hw = dev;
661 
662   init_options (s);
663 
664   s->next = first_handle;
665   first_handle = s;
666 
667   *handle = s;
668 
669   DBG (11, "<< sane_open\n");
670   return SANE_STATUS_GOOD;
671 }
672 
673 void
sane_close(SANE_Handle handle)674 sane_close (SANE_Handle handle)
675 {
676   Ibm_Scanner *s = (Ibm_Scanner *) handle;
677   DBG (11, ">> sane_close\n");
678 
679   if (s->fd != -1)
680     sanei_scsi_close (s->fd);
681   free (s);
682 
683   DBG (11, ">> sane_close\n");
684 }
685 
686 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)687 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
688 {
689   Ibm_Scanner *s = handle;
690   DBG (11, ">> sane_get_option_descriptor\n");
691 
692   if ((unsigned) option >= NUM_OPTIONS)
693     return (0);
694 
695   DBG (11, "<< sane_get_option_descriptor\n");
696   return (s->opt + option);
697 }
698 
699 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)700 sane_control_option (SANE_Handle handle, SANE_Int option,
701                      SANE_Action action, void *val, SANE_Int * info)
702 {
703   Ibm_Scanner *s = handle;
704   SANE_Status status;
705   SANE_Word cap;
706   DBG (11, ">> sane_control_option\n");
707 
708   if (info)
709     *info = 0;
710 
711   if (s->scanning)
712     return (SANE_STATUS_DEVICE_BUSY);
713   if (option >= NUM_OPTIONS)
714     return (SANE_STATUS_INVAL);
715 
716   cap = s->opt[option].cap;
717   if (!SANE_OPTION_IS_ACTIVE (cap))
718     return (SANE_STATUS_INVAL);
719 
720   if (action == SANE_ACTION_GET_VALUE)
721     {
722       DBG (11, "sane_control_option get_value\n");
723       switch (option)
724         {
725           /* word options: */
726         case OPT_X_RESOLUTION:
727         case OPT_Y_RESOLUTION:
728         case OPT_TL_X:
729         case OPT_TL_Y:
730         case OPT_BR_X:
731         case OPT_BR_Y:
732         case OPT_NUM_OPTS:
733         case OPT_BRIGHTNESS:
734         case OPT_CONTRAST:
735           *(SANE_Word *) val = s->val[option].w;
736           return (SANE_STATUS_GOOD);
737 
738           /* bool options: */
739 	case OPT_ADF:
740           *(SANE_Bool *) val = s->val[option].b;
741           return (SANE_STATUS_GOOD);
742 
743           /* string options: */
744         case OPT_MODE:
745 	case OPT_PAPER:
746           strcpy (val, s->val[option].s);
747           return (SANE_STATUS_GOOD);
748         }
749     }
750   else {
751     DBG (11, "sane_control_option set_value\n");
752     if (action == SANE_ACTION_SET_VALUE)
753     {
754       if (!SANE_OPTION_IS_SETTABLE (cap))
755         return (SANE_STATUS_INVAL);
756 
757       status = sanei_constrain_value (s->opt + option, val, info);
758       if (status != SANE_STATUS_GOOD)
759         return status;
760 
761       switch (option)
762         {
763           /* (mostly) side-effect-free word options: */
764         case OPT_X_RESOLUTION:
765         case OPT_Y_RESOLUTION:
766           if (info && s->val[option].w != *(SANE_Word *) val)
767             *info |= SANE_INFO_RELOAD_PARAMS;
768           s->val[option].w = *(SANE_Word *) val;
769           return (SANE_STATUS_GOOD);
770 
771 	case OPT_TL_X:
772         case OPT_TL_Y:
773         case OPT_BR_X:
774         case OPT_BR_Y:
775           if (info && s->val[option].w != *(SANE_Word *) val)
776             *info |= SANE_INFO_RELOAD_PARAMS;
777           s->val[option].w = *(SANE_Word *) val;
778 	  /* resets the paper format to user defined */
779 	  if (strcmp(s->val[OPT_PAPER].s, paper_list[IBM_PAPER_USER_DEFINED]) != 0)
780 	    {
781 	      if (info)
782 		*info |= SANE_INFO_RELOAD_OPTIONS;
783               if (s->val[OPT_PAPER].s)
784                 free (s->val[OPT_PAPER].s);
785               s->val[OPT_PAPER].s = strdup (paper_list[IBM_PAPER_USER_DEFINED]);
786 	    }
787           return (SANE_STATUS_GOOD);
788 
789 	case OPT_NUM_OPTS:
790         case OPT_BRIGHTNESS:
791         case OPT_CONTRAST:
792           s->val[option].w = *(SANE_Word *) val;
793           return (SANE_STATUS_GOOD);
794 
795         case OPT_MODE:
796           if (info && strcmp (s->val[option].s, (SANE_String) val))
797             *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
798           if (s->val[option].s)
799             free (s->val[option].s);
800           s->val[option].s = strdup (val);
801           return (SANE_STATUS_GOOD);
802 
803 	case OPT_ADF:
804 	  s->val[option].b = *(SANE_Bool *) val;
805 	  if (*(SANE_Bool *) val)
806 	    s->adf_state = ADF_ARMED;
807           else
808 	    s->adf_state = ADF_UNUSED;
809 	  return (SANE_STATUS_GOOD);
810 
811 	case OPT_PAPER:
812           if (info && strcmp (s->val[option].s, (SANE_String) val))
813             *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
814           if (s->val[option].s)
815             free (s->val[option].s);
816           s->val[option].s = strdup (val);
817 	  if (strcmp (s->val[OPT_PAPER].s, "User") != 0)
818 	    {
819               s->val[OPT_TL_X].w = 0;
820 	      s->val[OPT_TL_Y].w = 0;
821 	    if (strcmp (s->val[OPT_PAPER].s, "A3") == 0)
822 	      {
823                 s->val[OPT_BR_X].w = PAPER_A3_W;
824 	        s->val[OPT_BR_Y].w = PAPER_A3_H;
825 	      }
826 	    else if (strcmp (s->val[OPT_PAPER].s, "A4") == 0)
827 	      {
828                 s->val[OPT_BR_X].w = PAPER_A4_W;
829 	        s->val[OPT_BR_Y].w = PAPER_A4_H;
830 	      }
831 	    else if (strcmp (s->val[OPT_PAPER].s, "A4R") == 0)
832 	      {
833                 s->val[OPT_BR_X].w = PAPER_A4R_W;
834 	        s->val[OPT_BR_Y].w = PAPER_A4R_H;
835 	      }
836 	    else if (strcmp (s->val[OPT_PAPER].s, "A5") == 0)
837 	      {
838                 s->val[OPT_BR_X].w = PAPER_A5_W;
839 	        s->val[OPT_BR_Y].w = PAPER_A5_H;
840 	      }
841 	    else if (strcmp (s->val[OPT_PAPER].s, "A5R") == 0)
842 	      {
843                 s->val[OPT_BR_X].w = PAPER_A5R_W;
844 	        s->val[OPT_BR_Y].w = PAPER_A5R_H;
845   	      }
846 	    else if (strcmp (s->val[OPT_PAPER].s, "A6") == 0)
847 	      {
848                 s->val[OPT_BR_X].w = PAPER_A6_W;
849 	        s->val[OPT_BR_Y].w = PAPER_A6_H;
850 	      }
851 	    else if (strcmp (s->val[OPT_PAPER].s, "B4") == 0)
852 	      {
853                 s->val[OPT_BR_X].w = PAPER_B4_W;
854 	        s->val[OPT_BR_Y].w = PAPER_B4_H;
855 	      }
856 	    else if (strcmp (s->val[OPT_PAPER].s, "Legal") == 0)
857 	      {
858                 s->val[OPT_BR_X].w = PAPER_LEGAL_W;
859 	        s->val[OPT_BR_Y].w = PAPER_LEGAL_H;
860 	      }
861 	    else if (strcmp (s->val[OPT_PAPER].s, "Letter") == 0)
862 	      {
863                 s->val[OPT_BR_X].w = PAPER_LETTER_W;
864 	        s->val[OPT_BR_Y].w = PAPER_LETTER_H;
865 	      }
866 	  }
867 	  return (SANE_STATUS_GOOD);
868         }
869 
870     }
871   }
872 
873   DBG (11, "<< sane_control_option\n");
874   return (SANE_STATUS_INVAL);
875 }
876 
877 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)878 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
879 {
880   Ibm_Scanner *s = handle;
881   DBG (11, ">> sane_get_parameters\n");
882 
883   if (!s->scanning)
884     {
885       int width, length, xres, yres;
886       const char *mode;
887 
888       memset (&s->params, 0, sizeof (s->params));
889 
890       width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
891       length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
892       xres = s->val[OPT_X_RESOLUTION].w;
893       yres = s->val[OPT_Y_RESOLUTION].w;
894 
895       /* make best-effort guess at what parameters will look like once
896          scanning starts.  */
897       if (xres > 0 && yres > 0 && width > 0 && length > 0)
898         {
899           s->params.pixels_per_line = width * xres / s->hw->info.mud;
900           s->params.lines = length * yres / s->hw->info.mud;
901         }
902 
903       mode = s->val[OPT_MODE].s;
904       if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) ||
905 	  (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE)) == 0)
906         {
907           s->params.format = SANE_FRAME_GRAY;
908           s->params.bytes_per_line = s->params.pixels_per_line / 8;
909 	  /* the Ibm truncates to the byte boundary, so: chop! */
910           s->params.pixels_per_line = s->params.bytes_per_line * 8;
911           s->params.depth = 1;
912         }
913       else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */
914         {
915           s->params.format = SANE_FRAME_GRAY;
916           s->params.bytes_per_line = s->params.pixels_per_line;
917           s->params.depth = 8;
918         }
919       s->params.last_frame = SANE_TRUE;
920     }
921   else
922     DBG (5, "sane_get_parameters: scanning, so can't get params\n");
923 
924   if (params)
925     *params = s->params;
926 
927   DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
928        "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
929        s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
930 
931   DBG (11, "<< sane_get_parameters\n");
932   return (SANE_STATUS_GOOD);
933 }
934 
935 
936 SANE_Status
sane_start(SANE_Handle handle)937 sane_start (SANE_Handle handle)
938 {
939   char *mode_str;
940   Ibm_Scanner *s = handle;
941   SANE_Status status;
942   struct ibm_window_data wbuf;
943   struct measurements_units_page mup;
944 
945   DBG (11, ">> sane_start\n");
946 
947   /* First make sure we have a current parameter set.  Some of the
948      parameters will be overwritten below, but that's OK.  */
949   status = sane_get_parameters (s, 0);
950   if (status != SANE_STATUS_GOOD)
951     return status;
952 
953   status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
954   if (status != SANE_STATUS_GOOD)
955     {
956       DBG (1, "open of %s failed: %s\n",
957            s->hw->sane.name, sane_strstatus (status));
958       return (status);
959     }
960 
961   mode_str = s->val[OPT_MODE].s;
962   s->xres = s->val[OPT_X_RESOLUTION].w;
963   s->yres = s->val[OPT_Y_RESOLUTION].w;
964   s->ulx = s->val[OPT_TL_X].w;
965   s->uly = s->val[OPT_TL_Y].w;
966   s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
967   s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
968   s->brightness = s->val[OPT_BRIGHTNESS].w;
969   s->contrast = s->val[OPT_CONTRAST].w;
970   s->bpp = s->params.depth;
971   if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0)
972     {
973       s->image_composition = IBM_BINARY_MONOCHROME;
974     }
975   else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
976     {
977       s->image_composition = IBM_DITHERED_MONOCHROME;
978     }
979   else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0)
980     {
981       s->image_composition = IBM_GRAYSCALE;
982     }
983 
984   memset (&wbuf, 0, sizeof (wbuf));
985 /* next line commented out by mf */
986 /*  _lto2b(sizeof(wbuf) - 8, wbuf.len); */
987 /* next line by mf */
988   _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */
989   _lto2b(s->xres, wbuf.x_res);
990   _lto2b(s->yres, wbuf.y_res);
991   _lto4b(s->ulx, wbuf.x_org);
992   _lto4b(s->uly, wbuf.y_org);
993   _lto4b(s->width, wbuf.width);
994   _lto4b(s->length, wbuf.length);
995 
996   wbuf.image_comp = s->image_composition;
997   /* if you throw the MRIF bit the brightness control reverses too */
998   /* so I reverse the reversal in software for symmetry's sake */
999   if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME)
1000     {
1001       if (wbuf.image_comp == IBM_GRAYSCALE)
1002 	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */
1003       if (wbuf.image_comp == IBM_DITHERED_MONOCHROME)
1004 	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10;
1005       wbuf.brightness = 256 - (SANE_Byte) s->brightness;
1006 /*
1007       if (is50)
1008         wbuf.contrast = (SANE_Byte) s->contrast;
1009       else
1010 */
1011       wbuf.contrast = 256 - (SANE_Byte) s->contrast;
1012     }
1013   else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
1014     {
1015       wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00;
1016       wbuf.brightness = (SANE_Byte) s->brightness;
1017       wbuf.contrast = (SANE_Byte) s->contrast;
1018     }
1019 
1020   wbuf.threshold = 0;
1021   wbuf.bits_per_pixel = s->bpp;
1022 
1023   wbuf.halftone_code = 2;     /* diithering */
1024   wbuf.halftone_id = 0x0A;    /* 8x8 Bayer pattenr */
1025   wbuf.pad_type = 3;
1026   wbuf.bit_ordering[0] = 0;
1027   wbuf.bit_ordering[1] = 7;   /* modified by mf (it was 3) */
1028 
1029   DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
1030   DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
1031   DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
1032   DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
1033   DBG (5, "width=%d\n", _4btol(wbuf.width));
1034   DBG (5, "length=%d\n", _4btol(wbuf.length));
1035   DBG (5, "image_comp=%d\n", wbuf.image_comp);
1036 
1037   DBG (11, "sane_start: sending SET WINDOW\n");
1038   status = set_window (s->fd, &wbuf);
1039   if (status != SANE_STATUS_GOOD)
1040     {
1041       DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
1042       return (status);
1043     }
1044 
1045   DBG (11, "sane_start: sending GET WINDOW\n");
1046   memset (&wbuf, 0, sizeof (wbuf));
1047   status = get_window (s->fd, &wbuf);
1048   if (status != SANE_STATUS_GOOD)
1049     {
1050       DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
1051       return (status);
1052     }
1053   DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
1054   DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
1055   DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
1056   DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
1057   DBG (5, "width=%d\n", _4btol(wbuf.width));
1058   DBG (5, "length=%d\n", _4btol(wbuf.length));
1059   DBG (5, "image_comp=%d\n", wbuf.image_comp);
1060 
1061   DBG (11, "sane_start: sending MODE SELECT\n");
1062   memset (&mup, 0, sizeof (mup));
1063   mup.page_code = MEASUREMENTS_PAGE;
1064   mup.parameter_length = 0x06;
1065   mup.bmu = INCHES;
1066   mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
1067   mup.mud[1] = (DEFAULT_MUD & 0xff);
1068 /* next lines by mf */
1069   mup.adf_page_code = 0x26;
1070   mup.adf_parameter_length = 6;
1071   if (s->adf_state == ADF_ARMED)
1072     mup.adf_control = 1;
1073   else
1074     mup.adf_control = 0;
1075 /* end lines by mf */
1076 
1077   status = mode_select (s->fd, (struct mode_pages *) &mup);
1078   if (status != SANE_STATUS_GOOD)
1079     {
1080       DBG (1, "attach: MODE_SELECT failed\n");
1081       return (SANE_STATUS_INVAL);
1082     }
1083 
1084   status = trigger_scan (s->fd);
1085   if (status != SANE_STATUS_GOOD)
1086     {
1087       DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
1088       /* next line introduced not to freeze xscanimage */
1089       do_cancel(s);
1090       return status;
1091     }
1092 
1093   /* Wait for scanner to become ready to transmit data */
1094   status = ibm_wait_ready (s);
1095   if (status != SANE_STATUS_GOOD)
1096     {
1097       DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status));
1098       return (status);
1099     }
1100 
1101   s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
1102 
1103   DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
1104        "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
1105        s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
1106 
1107   s->scanning = SANE_TRUE;
1108 
1109   DBG (11, "<< sane_start\n");
1110   return (SANE_STATUS_GOOD);
1111 }
1112 
1113 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)1114 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
1115            SANE_Int * len)
1116 {
1117   Ibm_Scanner *s = handle;
1118   SANE_Status status;
1119   size_t nread;
1120   DBG (11, ">> sane_read\n");
1121 
1122   *len = 0;
1123 
1124   DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read);
1125 
1126   if (s->bytes_to_read == 0)
1127     {
1128       do_cancel (s);
1129       return (SANE_STATUS_EOF);
1130     }
1131 
1132   if (!s->scanning) {
1133     DBG (11, "sane_read: scanning is false!\n");
1134     return (do_cancel (s));
1135   }
1136 
1137   nread = max_len;
1138   if (nread > s->bytes_to_read)
1139     nread = s->bytes_to_read;
1140 
1141   DBG (11, "sane_read: read %ld bytes\n", (u_long) nread);
1142   status = read_data (s->fd, buf, &nread);
1143   if (status != SANE_STATUS_GOOD)
1144     {
1145       DBG (11, "sane_read: read error\n");
1146       do_cancel (s);
1147       return (SANE_STATUS_IO_ERROR);
1148     }
1149   *len = nread;
1150   s->bytes_to_read -= nread;
1151 
1152   DBG (11, "<< sane_read\n");
1153   return (SANE_STATUS_GOOD);
1154 }
1155 
1156 void
sane_cancel(SANE_Handle handle)1157 sane_cancel (SANE_Handle handle)
1158 {
1159   Ibm_Scanner *s = handle;
1160   DBG (11, ">> sane_cancel\n");
1161 
1162   s->scanning = SANE_FALSE;
1163 
1164   DBG (11, "<< sane_cancel\n");
1165 }
1166 
1167 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)1168 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1169 {
1170   DBG (5, ">> sane_set_io_mode (handle = %p, non_blocking = %d)\n",
1171        handle, non_blocking);
1172   DBG (5, "<< sane_set_io_mode\n");
1173 
1174   return SANE_STATUS_UNSUPPORTED;
1175 }
1176 
1177 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)1178 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1179 {
1180   DBG (5, ">> sane_get_select_fd (handle = %p, fd = %p)\n",
1181        handle, (void *) fd);
1182   DBG (5, "<< sane_get_select_fd\n");
1183 
1184   return SANE_STATUS_UNSUPPORTED;
1185 }
1186