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