1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1998, Feico W. Dillema
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 Ricoh flatbed scanners.
42 */
43
44 #include "../include/sane/config.h"
45
46 #include <limits.h>
47 #include <stdlib.h>
48 #include <stdarg.h>
49 #include <string.h>
50 #include <time.h>
51 #include <sys/time.h>
52 #include <unistd.h>
53 #include <ctype.h>
54
55 #include "../include/sane/sane.h"
56 #include "../include/sane/saneopts.h"
57 #include "../include/sane/sanei_scsi.h"
58
59 #define BACKEND_NAME ricoh
60 #include "../include/sane/sanei_backend.h"
61
62 #ifndef PATH_MAX
63 # define PATH_MAX 1024
64 #endif
65
66 #include "../include/sane/sanei_config.h"
67 #define RICOH_CONFIG_FILE "ricoh.conf"
68
69 #include "ricoh.h"
70
71 #define MAX(a,b) ((a) > (b) ? (a) : (b))
72
73 static const SANE_Device **devlist = NULL;
74 static int num_devices = 0;
75 static Ricoh_Device *first_dev = NULL;
76 static Ricoh_Scanner *first_handle = NULL;
77 static int is50 = 0;
78
79 #include "ricoh-scsi.c"
80
81 static size_t
max_string_size(const SANE_String_Const strings[])82 max_string_size (const SANE_String_Const strings[])
83 {
84 size_t size, max_size = 0;
85 int i;
86 DBG (11, ">> max_string_size\n");
87
88 for (i = 0; strings[i]; ++i)
89 {
90 size = strlen (strings[i]) + 1;
91 if (size > max_size)
92 max_size = size;
93 }
94
95 DBG (11, "<< max_string_size\n");
96 return max_size;
97 }
98
99 static SANE_Status
attach(const char *devnam, Ricoh_Device ** devp)100 attach (const char *devnam, Ricoh_Device ** devp)
101 {
102 SANE_Status status;
103 Ricoh_Device *dev;
104
105 int fd;
106 struct inquiry_data ibuf;
107 struct measurements_units_page mup;
108 struct ricoh_window_data wbuf;
109 size_t buf_size;
110 char *str;
111 DBG (11, ">> attach\n");
112
113 for (dev = first_dev; dev; dev = dev->next)
114 {
115 if (strcmp (dev->sane.name, devnam) == 0)
116 {
117 if (devp)
118 *devp = dev;
119 return (SANE_STATUS_GOOD);
120 }
121 }
122
123 DBG (3, "attach: opening %s\n", devnam);
124 status = sanei_scsi_open (devnam, &fd, NULL, NULL);
125 if (status != SANE_STATUS_GOOD)
126 {
127 DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
128 return (status);
129 }
130
131 DBG (3, "attach: sending INQUIRY\n");
132 memset (&ibuf, 0, sizeof (ibuf));
133 buf_size = sizeof(ibuf);
134 status = inquiry (fd, &ibuf, &buf_size);
135 if (status != SANE_STATUS_GOOD)
136 {
137 DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status));
138 sanei_scsi_close (fd);
139 return (status);
140 }
141
142 if (ibuf.devtype != 6
143 || strncmp ((char *)ibuf.vendor, "RICOH", 5) != 0
144 || (strncmp ((char *)ibuf.product, "IS50", 4) != 0
145 && strncmp ((char *)ibuf.product, "IS60", 4) != 0))
146 {
147 DBG (1, "attach: device doesn't look like the Ricoh scanner I know\n");
148 sanei_scsi_close (fd);
149 return (SANE_STATUS_INVAL);
150 }
151 is50 = (strncmp ((char *)ibuf.product, "IS50", 4) == 0);
152
153 DBG (3, "attach: sending TEST_UNIT_READY\n");
154 status = test_unit_ready (fd);
155 if (status != SANE_STATUS_GOOD)
156 {
157 DBG (1, "attach: test unit ready failed (%s)\n",
158 sane_strstatus (status));
159 sanei_scsi_close (fd);
160 return (status);
161 }
162
163 DBG (3, "attach: sending OBJECT POSITION\n");
164 status = object_position (fd);
165 if (status != SANE_STATUS_GOOD)
166 {
167 DBG (1, "attach: OBJECT POSITION failed\n");
168 sanei_scsi_close (fd);
169 return (SANE_STATUS_INVAL);
170 }
171
172 memset (&mup, 0, sizeof (mup));
173 mup.page_code = MEASUREMENTS_PAGE;
174 mup.parameter_length = 0x06;
175 mup.bmu = INCHES;
176 mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
177 mup.mud[1] = (DEFAULT_MUD & 0xff);
178
179 #if 0
180 DBG (3, "attach: sending MODE SELECT\n");
181 status = mode_select (fd, (struct mode_pages *) &mup);
182 if (status != SANE_STATUS_GOOD)
183 {
184 DBG (1, "attach: MODE_SELECT failed\n");
185 sanei_scsi_close (fd);
186 return (SANE_STATUS_INVAL);
187 }
188 #endif
189
190 #if 0
191 DBG (3, "attach: sending MODE SENSE\n");
192 memset (&mup, 0, sizeof (mup));
193 status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE);
194 if (status != SANE_STATUS_GOOD)
195 {
196 DBG (1, "attach: MODE_SENSE failed\n");
197 sanei_scsi_close (fd);
198 return (SANE_STATUS_INVAL);
199 }
200 #endif
201
202 DBG (3, "attach: sending GET WINDOW\n");
203 memset (&wbuf, 0, sizeof (wbuf));
204 status = get_window (fd, &wbuf);
205 if (status != SANE_STATUS_GOOD)
206 {
207 DBG (1, "attach: GET_WINDOW failed %d\n", status);
208 sanei_scsi_close (fd);
209 DBG (11, "<< attach\n");
210 return (SANE_STATUS_INVAL);
211 }
212
213 sanei_scsi_close (fd);
214
215 dev = malloc (sizeof (*dev));
216 if (!dev)
217 return (SANE_STATUS_NO_MEM);
218 memset (dev, 0, sizeof (*dev));
219
220 dev->sane.name = strdup (devnam);
221 dev->sane.vendor = "RICOH";
222
223 size_t prod_rev_size = sizeof(ibuf.product) + sizeof(ibuf.revision) + 1;
224 str = malloc (prod_rev_size);
225 if (str)
226 {
227 snprintf (str, prod_rev_size, "%.*s%.*s",
228 (int) sizeof(ibuf.product), (const char *) ibuf.product,
229 (int) sizeof(ibuf.revision), (const char *) ibuf.revision);
230 }
231 dev->sane.model = str;
232 dev->sane.type = "flatbed scanner";
233
234 DBG (5, "dev->sane.name = %s\n", dev->sane.name);
235 DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor);
236 DBG (5, "dev->sane.model = %s\n", dev->sane.model);
237 DBG (5, "dev->sane.type = %s\n", dev->sane.type);
238
239 dev->info.xres_default = _2btol(wbuf.x_res);
240 dev->info.yres_default = _2btol(wbuf.y_res);
241 dev->info.image_mode_default = wbuf.image_comp;
242
243 /* if you throw the MRIF bit the brightness control reverses too */
244 /* so I reverse the reversal in software for symmetry's sake */
245 /* I should make this into an option */
246
247 if (wbuf.image_comp == RICOH_GRAYSCALE || wbuf.image_comp == RICOH_DITHERED_MONOCHROME)
248 {
249 dev->info.brightness_default = 256 - wbuf.brightness;
250 if (is50)
251 dev->info.contrast_default = wbuf.contrast;
252 else
253 dev->info.contrast_default = 256 - wbuf.contrast;
254 }
255 else /* wbuf.image_comp == RICOH_BINARY_MONOCHROME */
256 {
257 dev->info.brightness_default = wbuf.brightness;
258 dev->info.contrast_default = wbuf.contrast;
259 }
260
261 #if 1
262 dev->info.bmu = mup.bmu;
263 dev->info.mud = _2btol(mup.mud);
264 if (dev->info.mud == 0) {
265 /* The RICOH says it uses points as default Basic Measurement Unit */
266 /* but gives a Measurement Unit Divisor of zero */
267 /* So, we set it to the default (SCSI-standard) of 1200 */
268 /* with BMU in inches, i.e. 1200 points equal 1 inch */
269 dev->info.bmu = INCHES;
270 dev->info.mud = DEFAULT_MUD;
271 }
272 #else
273 dev->info.bmu = INCHES;
274 dev->info.mud = DEFAULT_MUD;
275 #endif
276
277 DBG (5, "xres_default=%d\n", dev->info.xres_default);
278 DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max);
279 DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min);
280
281 DBG (5, "yres_default=%d\n", dev->info.yres_default);
282 DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max);
283 DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min);
284
285 DBG (5, "x_range.max=%d\n", dev->info.x_range.max);
286 DBG (5, "y_range.max=%d\n", dev->info.y_range.max);
287
288 DBG (5, "image_mode=%d\n", dev->info.image_mode_default);
289
290 DBG (5, "brightness=%d\n", dev->info.brightness_default);
291 DBG (5, "contrast=%d\n", dev->info.contrast_default);
292
293 DBG (5, "bmu=%d\n", dev->info.bmu);
294 DBG (5, "mud=%d\n", dev->info.mud);
295
296 ++num_devices;
297 dev->next = first_dev;
298 first_dev = dev;
299
300 if (devp)
301 *devp = dev;
302
303 DBG (11, "<< attach\n");
304 return (SANE_STATUS_GOOD);
305 }
306
307 static SANE_Status
attach_one(const char *devnam)308 attach_one(const char *devnam)
309 {
310 attach (devnam, NULL);
311 return SANE_STATUS_GOOD;
312 }
313
314 static SANE_Status
init_options(Ricoh_Scanner * s)315 init_options (Ricoh_Scanner * s)
316 {
317 int i;
318 DBG (11, ">> init_options\n");
319
320 memset (s->opt, 0, sizeof (s->opt));
321 memset (s->val, 0, sizeof (s->val));
322
323 for (i = 0; i < NUM_OPTIONS; ++i)
324 {
325 s->opt[i].size = sizeof (SANE_Word);
326 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
327 }
328
329 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
330 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
331 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
332 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
333 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
334
335 /* "Mode" group: */
336 s->opt[OPT_MODE_GROUP].title = "Scan Mode";
337 s->opt[OPT_MODE_GROUP].desc = "";
338 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
339 s->opt[OPT_MODE_GROUP].cap = 0;
340 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
341
342 /* scan mode */
343 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
344 s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
345 s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
346 s->opt[OPT_MODE].type = SANE_TYPE_STRING;
347 s->opt[OPT_MODE].size = max_string_size (mode_list);
348 s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
349 s->opt[OPT_MODE].constraint.string_list = mode_list;
350 s->val[OPT_MODE].s = strdup (mode_list[s->hw->info.image_mode_default]);
351
352 /* x resolution */
353 s->opt[OPT_X_RESOLUTION].name = "X" SANE_NAME_SCAN_RESOLUTION;
354 s->opt[OPT_X_RESOLUTION].title = "X " SANE_TITLE_SCAN_RESOLUTION;
355 s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
356 s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
357 s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
358 s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
359 s->opt[OPT_X_RESOLUTION].constraint.range = &is60_res_range;
360 s->val[OPT_X_RESOLUTION].w = s->hw->info.xres_default;
361 if (is50)
362 s->opt[OPT_X_RESOLUTION].constraint.range = &is50_res_range;
363 else
364 s->opt[OPT_X_RESOLUTION].constraint.range = &is60_res_range;
365
366 /* y resolution */
367 s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION;
368 s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION;
369 s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
370 s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
371 s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
372 s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
373 s->val[OPT_Y_RESOLUTION].w = s->hw->info.yres_default;
374 if (is50)
375 s->opt[OPT_Y_RESOLUTION].constraint.range = &is50_res_range;
376 else
377 s->opt[OPT_Y_RESOLUTION].constraint.range = &is60_res_range;
378
379 /* "Geometry" group: */
380 s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
381 s->opt[OPT_GEOMETRY_GROUP].desc = "";
382 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
383 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
384 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
385
386 /* top-left x */
387 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
388 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
389 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
390 s->opt[OPT_TL_X].type = SANE_TYPE_INT;
391 s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
392 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
393 s->opt[OPT_TL_X].constraint.range = &default_x_range;
394 s->val[OPT_TL_X].w = 0;
395
396 /* top-left y */
397 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
398 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
399 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
400 s->opt[OPT_TL_Y].type = SANE_TYPE_INT;
401 s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
402 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
403 s->opt[OPT_TL_Y].constraint.range = &default_y_range;
404 s->val[OPT_TL_Y].w = 0;
405
406 /* bottom-right x */
407 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
408 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
409 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
410 s->opt[OPT_BR_X].type = SANE_TYPE_INT;
411 s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
412 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
413 s->opt[OPT_BR_X].constraint.range = &default_x_range;
414 s->val[OPT_BR_X].w = default_x_range.max;
415
416 /* bottom-right y */
417 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
418 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
419 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
420 s->opt[OPT_BR_Y].type = SANE_TYPE_INT;
421 s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
422 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
423 s->opt[OPT_BR_Y].constraint.range = &default_y_range;
424 s->val[OPT_BR_Y].w = default_y_range.max;
425
426 /* "Enhancement" group: */
427 s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
428 s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
429 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
430 s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
431 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
432
433 /* brightness */
434 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
435 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
436 s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
437 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
438 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
439 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
440 s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range;
441 s->val[OPT_BRIGHTNESS].w = s->hw->info.brightness_default;
442
443 /* contrast */
444 s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
445 s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
446 s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
447 s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
448 s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
449 s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
450 s->opt[OPT_CONTRAST].constraint.range = &u8_range;
451 s->val[OPT_CONTRAST].w = s->hw->info.contrast_default;
452
453 DBG (11, "<< init_options\n");
454 return SANE_STATUS_GOOD;
455 }
456
457 static SANE_Status
do_cancel(Ricoh_Scanner * s)458 do_cancel (Ricoh_Scanner * s)
459 {
460 SANE_Status status;
461 DBG (11, ">> do_cancel\n");
462
463 DBG (3, "cancel: sending OBJECT POSITION\n");
464 status = object_position (s->fd);
465 if (status != SANE_STATUS_GOOD)
466 {
467 DBG (1, "cancel: OBJECT POSITION failed\n");
468 }
469
470 s->scanning = SANE_FALSE;
471
472 if (s->fd >= 0)
473 {
474 sanei_scsi_close (s->fd);
475 s->fd = -1;
476 }
477
478 DBG (11, "<< do_cancel\n");
479 return (SANE_STATUS_CANCELLED);
480 }
481
482 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize)483 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
484 {
485 char devnam[PATH_MAX] = "/dev/scanner";
486 FILE *fp;
487
488 (void) authorize; /* silence gcc */
489
490 DBG_INIT ();
491 DBG (11, ">> sane_init\n");
492
493 #if defined PACKAGE && defined VERSION
494 DBG (2, "sane_init: " PACKAGE " " VERSION "\n");
495 #endif
496
497 if (version_code)
498 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
499
500 fp = sanei_config_open(RICOH_CONFIG_FILE);
501 if (fp)
502 {
503 char line[PATH_MAX], *lp;
504 size_t len;
505
506 /* read config file */
507 while (sanei_config_read (line, sizeof (line), fp))
508 {
509 if (line[0] == '#') /* ignore line comments */
510 continue;
511 len = strlen (line);
512
513 if (!len)
514 continue; /* ignore empty lines */
515
516 /* skip white space: */
517 for (lp = line; isspace(*lp); ++lp)
518 ;
519 strcpy (devnam, lp);
520 }
521 fclose (fp);
522 }
523 sanei_config_attach_matching_devices (devnam, attach_one);
524 DBG (11, "<< sane_init\n");
525 return SANE_STATUS_GOOD;
526 }
527
528 void
sane_exit(void)529 sane_exit (void)
530 {
531 Ricoh_Device *dev, *next;
532 DBG (11, ">> sane_exit\n");
533
534 for (dev = first_dev; dev; dev = next)
535 {
536 next = dev->next;
537 free ((void *) dev->sane.name);
538 free ((void *) dev->sane.model);
539 free (dev);
540 }
541
542 if (devlist)
543 free (devlist);
544
545 DBG (11, "<< sane_exit\n");
546 }
547
548 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only)549 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
550 {
551 Ricoh_Device *dev;
552 int i;
553
554 (void) local_only; /* silence gcc */
555
556 DBG (11, ">> sane_get_devices\n");
557
558 if (devlist)
559 free (devlist);
560 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
561 if (!devlist)
562 return (SANE_STATUS_NO_MEM);
563
564 i = 0;
565 for (dev = first_dev; dev; dev = dev->next)
566 devlist[i++] = &dev->sane;
567 devlist[i++] = 0;
568
569 *device_list = devlist;
570
571 DBG (11, "<< sane_get_devices\n");
572 return SANE_STATUS_GOOD;
573 }
574
575 SANE_Status
sane_open(SANE_String_Const devnam, SANE_Handle * handle)576 sane_open (SANE_String_Const devnam, SANE_Handle * handle)
577 {
578 SANE_Status status;
579 Ricoh_Device *dev;
580 Ricoh_Scanner *s;
581 DBG (11, ">> sane_open\n");
582
583 if (devnam[0] == '\0')
584 {
585 for (dev = first_dev; dev; dev = dev->next)
586 {
587 if (strcmp (dev->sane.name, devnam) == 0)
588 break;
589 }
590
591 if (!dev)
592 {
593 status = attach (devnam, &dev);
594 if (status != SANE_STATUS_GOOD)
595 return (status);
596 }
597 }
598 else
599 {
600 dev = first_dev;
601 }
602
603 if (!dev)
604 return (SANE_STATUS_INVAL);
605
606 s = malloc (sizeof (*s));
607 if (!s)
608 return SANE_STATUS_NO_MEM;
609 memset (s, 0, sizeof (*s));
610
611 s->fd = -1;
612 s->hw = dev;
613
614 init_options (s);
615
616 s->next = first_handle;
617 first_handle = s;
618
619 *handle = s;
620
621 DBG (11, "<< sane_open\n");
622 return SANE_STATUS_GOOD;
623 }
624
625 void
sane_close(SANE_Handle handle)626 sane_close (SANE_Handle handle)
627 {
628 Ricoh_Scanner *s = (Ricoh_Scanner *) handle;
629 DBG (11, ">> sane_close\n");
630
631 if (s->fd != -1)
632 sanei_scsi_close (s->fd);
633 free (s);
634
635 DBG (11, ">> sane_close\n");
636 }
637
638 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)639 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
640 {
641 Ricoh_Scanner *s = handle;
642 DBG (11, ">> sane_get_option_descriptor\n");
643
644 if ((unsigned) option >= NUM_OPTIONS)
645 return (0);
646
647 DBG (11, "<< sane_get_option_descriptor\n");
648 return (s->opt + option);
649 }
650
651 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info)652 sane_control_option (SANE_Handle handle, SANE_Int option,
653 SANE_Action action, void *val, SANE_Int * info)
654 {
655 Ricoh_Scanner *s = handle;
656 SANE_Status status;
657 SANE_Word cap;
658 DBG (11, ">> sane_control_option\n");
659
660 if (info)
661 *info = 0;
662
663 if (s->scanning)
664 return (SANE_STATUS_DEVICE_BUSY);
665 if (option >= NUM_OPTIONS)
666 return (SANE_STATUS_INVAL);
667
668 cap = s->opt[option].cap;
669 if (!SANE_OPTION_IS_ACTIVE (cap))
670 return (SANE_STATUS_INVAL);
671
672 if (action == SANE_ACTION_GET_VALUE)
673 {
674 switch (option)
675 {
676 /* word options: */
677 case OPT_X_RESOLUTION:
678 case OPT_Y_RESOLUTION:
679 case OPT_TL_X:
680 case OPT_TL_Y:
681 case OPT_BR_X:
682 case OPT_BR_Y:
683 case OPT_NUM_OPTS:
684 case OPT_BRIGHTNESS:
685 case OPT_CONTRAST:
686 *(SANE_Word *) val = s->val[option].w;
687 return (SANE_STATUS_GOOD);
688
689 /* string options: */
690 case OPT_MODE:
691 strcpy (val, s->val[option].s);
692 return (SANE_STATUS_GOOD);
693 }
694 }
695 else if (action == SANE_ACTION_SET_VALUE)
696 {
697 if (!SANE_OPTION_IS_SETTABLE (cap))
698 return (SANE_STATUS_INVAL);
699
700 status = sanei_constrain_value (s->opt + option, val, info);
701 if (status != SANE_STATUS_GOOD)
702 return status;
703
704 switch (option)
705 {
706 /* (mostly) side-effect-free word options: */
707 case OPT_X_RESOLUTION:
708 case OPT_Y_RESOLUTION:
709 case OPT_TL_X:
710 case OPT_TL_Y:
711 case OPT_BR_X:
712 case OPT_BR_Y:
713 if (info && s->val[option].w != *(SANE_Word *) val)
714 *info |= SANE_INFO_RELOAD_PARAMS;
715 /* fall through */
716 case OPT_NUM_OPTS:
717 case OPT_BRIGHTNESS:
718 case OPT_CONTRAST:
719 s->val[option].w = *(SANE_Word *) val;
720 return (SANE_STATUS_GOOD);
721
722 case OPT_MODE:
723 if (info && strcmp (s->val[option].s, (SANE_String) val))
724 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
725 if (s->val[option].s)
726 free (s->val[option].s);
727 s->val[option].s = strdup (val);
728 return (SANE_STATUS_GOOD);
729 }
730 }
731
732 DBG (11, "<< sane_control_option\n");
733 return (SANE_STATUS_INVAL);
734 }
735
736 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)737 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
738 {
739 Ricoh_Scanner *s = handle;
740 DBG (11, ">> sane_get_parameters\n");
741
742 if (!s->scanning)
743 {
744 int width, length, xres, yres;
745 const char *mode;
746
747 memset (&s->params, 0, sizeof (s->params));
748
749 width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
750 length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
751 xres = s->val[OPT_X_RESOLUTION].w;
752 yres = s->val[OPT_Y_RESOLUTION].w;
753
754 /* make best-effort guess at what parameters will look like once
755 scanning starts. */
756 if (xres > 0 && yres > 0 && width > 0 && length > 0)
757 {
758 s->params.pixels_per_line = width * xres / s->hw->info.mud;
759 s->params.lines = length * yres / s->hw->info.mud;
760 }
761
762 mode = s->val[OPT_MODE].s;
763 if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0 || strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
764 {
765 s->params.format = SANE_FRAME_GRAY;
766 s->params.bytes_per_line = s->params.pixels_per_line / 8;
767 /* the Ricoh truncates to the byte boundary, so: chop! */
768 s->params.pixels_per_line = s->params.bytes_per_line * 8;
769 s->params.depth = 1;
770 }
771 else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */
772 {
773 s->params.format = SANE_FRAME_GRAY;
774 s->params.bytes_per_line = s->params.pixels_per_line;
775 s->params.depth = 8;
776 }
777 s->params.last_frame = SANE_TRUE;
778 }
779
780 if (params)
781 *params = s->params;
782
783 DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
784 "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
785 s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
786
787 DBG (11, "<< sane_get_parameters\n");
788 return (SANE_STATUS_GOOD);
789 }
790
791
792 SANE_Status
sane_start(SANE_Handle handle)793 sane_start (SANE_Handle handle)
794 {
795 char *mode_str;
796 Ricoh_Scanner *s = handle;
797 SANE_Status status;
798 struct ricoh_window_data wbuf;
799 struct measurements_units_page mup;
800
801 DBG (11, ">> sane_start\n");
802
803 /* First make sure we have a current parameter set. Some of the
804 parameters will be overwritten below, but that's OK. */
805 status = sane_get_parameters (s, 0);
806 if (status != SANE_STATUS_GOOD)
807 return status;
808
809 status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
810 if (status != SANE_STATUS_GOOD)
811 {
812 DBG (1, "open of %s failed: %s\n",
813 s->hw->sane.name, sane_strstatus (status));
814 return (status);
815 }
816
817 mode_str = s->val[OPT_MODE].s;
818 s->xres = s->val[OPT_X_RESOLUTION].w;
819 s->yres = s->val[OPT_Y_RESOLUTION].w;
820 s->ulx = s->val[OPT_TL_X].w;
821 s->uly = s->val[OPT_TL_Y].w;
822 s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
823 s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
824 s->brightness = s->val[OPT_BRIGHTNESS].w;
825 s->contrast = s->val[OPT_CONTRAST].w;
826 s->bpp = s->params.depth;
827 if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0)
828 {
829 s->image_composition = RICOH_BINARY_MONOCHROME;
830 }
831 else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
832 {
833 s->image_composition = RICOH_DITHERED_MONOCHROME;
834 }
835 else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0)
836 {
837 s->image_composition = RICOH_GRAYSCALE;
838 }
839
840 memset (&wbuf, 0, sizeof (wbuf));
841 _lto2b(sizeof(wbuf) - 8, wbuf.len);
842 _lto2b(s->xres, wbuf.x_res);
843 _lto2b(s->yres, wbuf.y_res);
844 _lto4b(s->ulx, wbuf.x_org);
845 _lto4b(s->uly, wbuf.y_org);
846 _lto4b(s->width, wbuf.width);
847 _lto4b(s->length, wbuf.length);
848
849 wbuf.image_comp = s->image_composition;
850 /* if you throw the MRIF bit the brightness control reverses too */
851 /* so I reverse the reversal in software for symmetry's sake */
852 if (wbuf.image_comp == RICOH_GRAYSCALE || wbuf.image_comp == RICOH_DITHERED_MONOCHROME)
853 {
854 if (wbuf.image_comp == RICOH_GRAYSCALE)
855 wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x90;
856 if (wbuf.image_comp == RICOH_DITHERED_MONOCHROME)
857 wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10;
858 wbuf.brightness = 256 - (SANE_Byte) s->brightness;
859 if (is50)
860 wbuf.contrast = (SANE_Byte) s->contrast;
861 else
862 wbuf.contrast = 256 - (SANE_Byte) s->contrast;
863 }
864 else /* wbuf.image_comp == RICOH_BINARY_MONOCHROME */
865 {
866 wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00;
867 wbuf.brightness = (SANE_Byte) s->brightness;
868 wbuf.contrast = (SANE_Byte) s->contrast;
869 }
870
871 wbuf.threshold = 0;
872 wbuf.bits_per_pixel = s->bpp;
873
874 wbuf.halftone_pattern[0] = 2;
875 wbuf.halftone_pattern[1] = 0;
876 wbuf.pad_type = 3;
877 wbuf.bit_ordering[0] = 0;
878 wbuf.bit_ordering[1] = 3;
879
880 DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
881 DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
882 DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
883 DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
884 DBG (5, "width=%d\n", _4btol(wbuf.width));
885 DBG (5, "length=%d\n", _4btol(wbuf.length));
886 DBG (5, "image_comp=%d\n", wbuf.image_comp);
887
888 DBG (11, "sane_start: sending SET WINDOW\n");
889 status = set_window (s->fd, &wbuf);
890 if (status != SANE_STATUS_GOOD)
891 {
892 DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
893 return (status);
894 }
895
896 DBG (11, "sane_start: sending GET WINDOW\n");
897 memset (&wbuf, 0, sizeof (wbuf));
898 status = get_window (s->fd, &wbuf);
899 if (status != SANE_STATUS_GOOD)
900 {
901 DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
902 return (status);
903 }
904 DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
905 DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
906 DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
907 DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
908 DBG (5, "width=%d\n", _4btol(wbuf.width));
909 DBG (5, "length=%d\n", _4btol(wbuf.length));
910 DBG (5, "image_comp=%d\n", wbuf.image_comp);
911
912 DBG (11, "sane_start: sending MODE SELECT\n");
913 memset (&mup, 0, sizeof (mup));
914 mup.page_code = MEASUREMENTS_PAGE;
915 mup.parameter_length = 0x06;
916 mup.bmu = INCHES;
917 mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
918 mup.mud[1] = (DEFAULT_MUD & 0xff);
919
920 status = mode_select (s->fd, (struct mode_pages *) &mup);
921 if (status != SANE_STATUS_GOOD)
922 {
923 DBG (1, "attach: MODE_SELECT failed\n");
924 return (SANE_STATUS_INVAL);
925 }
926
927 status = trigger_scan (s->fd);
928 if (status != SANE_STATUS_GOOD)
929 {
930 DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
931 return (status);
932 }
933
934 /* Wait for scanner to become ready to transmit data */
935 status = ricoh_wait_ready (s);
936 if (status != SANE_STATUS_GOOD)
937 {
938 DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status));
939 return (status);
940 }
941
942 s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
943
944 DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
945 "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
946 s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
947
948 s->scanning = SANE_TRUE;
949
950 DBG (11, "<< sane_start\n");
951 return (SANE_STATUS_GOOD);
952 }
953
954 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)955 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
956 SANE_Int * len)
957 {
958 Ricoh_Scanner *s = handle;
959 SANE_Status status;
960 size_t nread;
961 DBG (11, ">> sane_read\n");
962
963 *len = 0;
964
965 DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read);
966
967 if (s->bytes_to_read == 0)
968 {
969 do_cancel (s);
970 return (SANE_STATUS_EOF);
971 }
972
973 if (!s->scanning) {
974 DBG (11, "sane_read: scanning is false!\n");
975 return (do_cancel (s));
976 }
977
978 nread = max_len;
979 if (nread > s->bytes_to_read)
980 nread = s->bytes_to_read;
981
982 DBG (11, "sane_read: read %ld bytes\n", (u_long) nread);
983 status = read_data (s->fd, buf, &nread);
984 if (status != SANE_STATUS_GOOD)
985 {
986 DBG (11, "sane_read: read error\n");
987 do_cancel (s);
988 return (SANE_STATUS_IO_ERROR);
989 }
990 *len = nread;
991 s->bytes_to_read -= nread;
992
993 DBG (11, "<< sane_read\n");
994 return (SANE_STATUS_GOOD);
995 }
996
997 void
sane_cancel(SANE_Handle handle)998 sane_cancel (SANE_Handle handle)
999 {
1000 Ricoh_Scanner *s = handle;
1001 DBG (11, ">> sane_cancel\n");
1002
1003 s->scanning = SANE_FALSE;
1004
1005 DBG (11, "<< sane_cancel\n");
1006 }
1007
1008 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)1009 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1010 {
1011 (void) handle; /* silence gcc */
1012 (void) non_blocking; /* silence gcc */
1013
1014 DBG (5, ">> sane_set_io_mode\n");
1015 DBG (5, "<< sane_set_io_mode\n");
1016
1017 return SANE_STATUS_UNSUPPORTED;
1018 }
1019
1020 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int * fd)1021 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1022 {
1023 (void) handle; /* silence gcc */
1024 (void) fd; /* silence gcc */
1025
1026 DBG (5, ">> sane_get_select_fd\n");
1027 DBG (5, "<< sane_get_select_fd\n");
1028
1029 return SANE_STATUS_UNSUPPORTED;
1030 }
1031