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