1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci*/
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci/*
41141cc406Sopenharmony_ci   This file implements a SANE backend for the Ibm 2456 flatbed scanner,
42141cc406Sopenharmony_ci   written by mf <massifr@tiscalinet.it>. It derives from the backend for
43141cc406Sopenharmony_ci   Ricoh flatbed scanners written by Feico W. Dillema.
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_ci   Currently maintained by Henning Meier-Geinitz <henning@meier-geinitz.de>.
46141cc406Sopenharmony_ci*/
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci#define BUILD 5
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include "../include/sane/config.h"
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci#include <limits.h>
53141cc406Sopenharmony_ci#include <stdlib.h>
54141cc406Sopenharmony_ci#include <stdarg.h>
55141cc406Sopenharmony_ci#include <string.h>
56141cc406Sopenharmony_ci#include <sys/time.h>
57141cc406Sopenharmony_ci#include <unistd.h>
58141cc406Sopenharmony_ci#include <ctype.h>
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci#include "../include/sane/sane.h"
61141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
62141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h"
63141cc406Sopenharmony_ci
64141cc406Sopenharmony_ci#define BACKEND_NAME ibm
65141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci#ifndef PATH_MAX
68141cc406Sopenharmony_ci# define PATH_MAX	1024
69141cc406Sopenharmony_ci#endif
70141cc406Sopenharmony_ci
71141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h"
72141cc406Sopenharmony_ci#define IBM_CONFIG_FILE "ibm.conf"
73141cc406Sopenharmony_ci
74141cc406Sopenharmony_ci#include "ibm.h"
75141cc406Sopenharmony_ci#include "ibm-scsi.c"
76141cc406Sopenharmony_ci
77141cc406Sopenharmony_ci#define MAX(a,b)	((a) > (b) ? (a) : (b))
78141cc406Sopenharmony_ci
79141cc406Sopenharmony_cistatic int num_devices = 0;
80141cc406Sopenharmony_cistatic Ibm_Device *first_dev = NULL;
81141cc406Sopenharmony_cistatic Ibm_Scanner *first_handle = NULL;
82141cc406Sopenharmony_ci/* static int is50 = 0; */
83141cc406Sopenharmony_ci
84141cc406Sopenharmony_ci
85141cc406Sopenharmony_cistatic size_t
86141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[])
87141cc406Sopenharmony_ci{
88141cc406Sopenharmony_ci  size_t size, max_size = 0;
89141cc406Sopenharmony_ci  int i;
90141cc406Sopenharmony_ci  DBG (11, ">> max_string_size\n");
91141cc406Sopenharmony_ci
92141cc406Sopenharmony_ci  for (i = 0; strings[i]; ++i)
93141cc406Sopenharmony_ci    {
94141cc406Sopenharmony_ci      size = strlen (strings[i]) + 1;
95141cc406Sopenharmony_ci      if (size > max_size)
96141cc406Sopenharmony_ci        max_size = size;
97141cc406Sopenharmony_ci    }
98141cc406Sopenharmony_ci
99141cc406Sopenharmony_ci  DBG (11, "<< max_string_size\n");
100141cc406Sopenharmony_ci  return max_size;
101141cc406Sopenharmony_ci}
102141cc406Sopenharmony_ci
103141cc406Sopenharmony_cistatic SANE_Status
104141cc406Sopenharmony_ciattach (const char *devnam, Ibm_Device ** devp)
105141cc406Sopenharmony_ci{
106141cc406Sopenharmony_ci  SANE_Status status;
107141cc406Sopenharmony_ci  Ibm_Device *dev;
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_ci  int fd;
110141cc406Sopenharmony_ci  struct inquiry_data ibuf;
111141cc406Sopenharmony_ci  struct measurements_units_page mup;
112141cc406Sopenharmony_ci  struct ibm_window_data wbuf;
113141cc406Sopenharmony_ci  size_t buf_size;
114141cc406Sopenharmony_ci  char *str;
115141cc406Sopenharmony_ci  DBG (11, ">> attach\n");
116141cc406Sopenharmony_ci
117141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
118141cc406Sopenharmony_ci    {
119141cc406Sopenharmony_ci      if (strcmp (dev->sane.name, devnam) == 0)
120141cc406Sopenharmony_ci        {
121141cc406Sopenharmony_ci          if (devp)
122141cc406Sopenharmony_ci            *devp = dev;
123141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
124141cc406Sopenharmony_ci        }
125141cc406Sopenharmony_ci    }
126141cc406Sopenharmony_ci
127141cc406Sopenharmony_ci  DBG (3, "attach: opening %s\n", devnam);
128141cc406Sopenharmony_ci  status = sanei_scsi_open (devnam, &fd, NULL, NULL);
129141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
130141cc406Sopenharmony_ci    {
131141cc406Sopenharmony_ci      DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
132141cc406Sopenharmony_ci      return (status);
133141cc406Sopenharmony_ci    }
134141cc406Sopenharmony_ci
135141cc406Sopenharmony_ci  DBG (3, "attach: sending INQUIRY\n");
136141cc406Sopenharmony_ci  memset (&ibuf, 0, sizeof (ibuf));
137141cc406Sopenharmony_ci  buf_size = sizeof(ibuf);
138141cc406Sopenharmony_ci/* next line by mf */
139141cc406Sopenharmony_ci  ibuf.byte2 = 2;
140141cc406Sopenharmony_ci  status = inquiry (fd, &ibuf, &buf_size);
141141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
142141cc406Sopenharmony_ci    {
143141cc406Sopenharmony_ci      DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status));
144141cc406Sopenharmony_ci      sanei_scsi_close (fd);
145141cc406Sopenharmony_ci      return (status);
146141cc406Sopenharmony_ci    }
147141cc406Sopenharmony_ci
148141cc406Sopenharmony_ci  if (ibuf.devtype != 6)
149141cc406Sopenharmony_ci    {
150141cc406Sopenharmony_ci      DBG (1, "attach: device \"%s\" is not a scanner\n", devnam);
151141cc406Sopenharmony_ci      sanei_scsi_close (fd);
152141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
153141cc406Sopenharmony_ci    }
154141cc406Sopenharmony_ci
155141cc406Sopenharmony_ci  if (!(
156141cc406Sopenharmony_ci	(strncmp ((char *)ibuf.vendor, "IBM", 3) ==0
157141cc406Sopenharmony_ci         && strncmp ((char *)ibuf.product, "2456", 4) == 0)
158141cc406Sopenharmony_ci        || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0
159141cc406Sopenharmony_ci	    && strncmp ((char *)ibuf.product, "IS420", 5) == 0)
160141cc406Sopenharmony_ci        || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0
161141cc406Sopenharmony_ci	    && strncmp ((char *)ibuf.product, "IS410", 5) == 0)
162141cc406Sopenharmony_ci        || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0
163141cc406Sopenharmony_ci	    && strncmp ((char *)ibuf.product, "IS430", 5) == 0)
164141cc406Sopenharmony_ci	))
165141cc406Sopenharmony_ci    {
166141cc406Sopenharmony_ci      DBG (1, "attach: device \"%s\" doesn't look like a scanner I know\n",
167141cc406Sopenharmony_ci	   devnam);
168141cc406Sopenharmony_ci      sanei_scsi_close (fd);
169141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
170141cc406Sopenharmony_ci    }
171141cc406Sopenharmony_ci
172141cc406Sopenharmony_ci  DBG (3, "attach: sending TEST_UNIT_READY\n");
173141cc406Sopenharmony_ci  status = test_unit_ready (fd);
174141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
175141cc406Sopenharmony_ci    {
176141cc406Sopenharmony_ci      DBG (1, "attach: test unit ready failed (%s)\n",
177141cc406Sopenharmony_ci           sane_strstatus (status));
178141cc406Sopenharmony_ci      sanei_scsi_close (fd);
179141cc406Sopenharmony_ci      return (status);
180141cc406Sopenharmony_ci    }
181141cc406Sopenharmony_ci  /*
182141cc406Sopenharmony_ci   * Causes a problem with RICOH IS420
183141cc406Sopenharmony_ci   * Ignore this function ... seems to work ok
184141cc406Sopenharmony_ci   * Suggested to George Murphy george@topfloor.ie by henning
185141cc406Sopenharmony_ci   */
186141cc406Sopenharmony_ci  if (strncmp((char *)ibuf.vendor, "RICOH", 5) != 0
187141cc406Sopenharmony_ci      && strncmp((char *)ibuf.product, "IS420", 5) != 0)
188141cc406Sopenharmony_ci    {
189141cc406Sopenharmony_ci      DBG (3, "attach: sending OBJECT POSITION\n");
190141cc406Sopenharmony_ci      status = object_position (fd, OBJECT_POSITION_UNLOAD);
191141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
192141cc406Sopenharmony_ci    	{
193141cc406Sopenharmony_ci	  DBG (1, "attach: OBJECT POSITION failed\n");
194141cc406Sopenharmony_ci	  sanei_scsi_close (fd);
195141cc406Sopenharmony_ci	  return (SANE_STATUS_INVAL);
196141cc406Sopenharmony_ci    	}
197141cc406Sopenharmony_ci    }
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_ci  memset (&mup, 0, sizeof (mup));
200141cc406Sopenharmony_ci  mup.page_code = MEASUREMENTS_PAGE;
201141cc406Sopenharmony_ci  mup.parameter_length = 0x06;
202141cc406Sopenharmony_ci  mup.bmu = INCHES;
203141cc406Sopenharmony_ci  mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
204141cc406Sopenharmony_ci  mup.mud[1] = (DEFAULT_MUD & 0xff);
205141cc406Sopenharmony_ci
206141cc406Sopenharmony_ci#if 0
207141cc406Sopenharmony_ci  DBG (3, "attach: sending MODE SELECT\n");
208141cc406Sopenharmony_ci  status = mode_select (fd, (struct mode_pages *) &mup);
209141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
210141cc406Sopenharmony_ci    {
211141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SELECT failed\n");
212141cc406Sopenharmony_ci      sanei_scsi_close (fd);
213141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
214141cc406Sopenharmony_ci    }
215141cc406Sopenharmony_ci#endif
216141cc406Sopenharmony_ci
217141cc406Sopenharmony_ci#if 0
218141cc406Sopenharmony_ci  DBG (3, "attach: sending MODE SENSE\n");
219141cc406Sopenharmony_ci  memset (&mup, 0, sizeof (mup));
220141cc406Sopenharmony_ci  status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE);
221141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
222141cc406Sopenharmony_ci    {
223141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SENSE failed\n");
224141cc406Sopenharmony_ci      sanei_scsi_close (fd);
225141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
226141cc406Sopenharmony_ci    }
227141cc406Sopenharmony_ci#endif
228141cc406Sopenharmony_ci
229141cc406Sopenharmony_ci  DBG (3, "attach: sending GET WINDOW\n");
230141cc406Sopenharmony_ci  memset (&wbuf, 0, sizeof (wbuf));
231141cc406Sopenharmony_ci  status = get_window (fd, &wbuf);
232141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
233141cc406Sopenharmony_ci    {
234141cc406Sopenharmony_ci      DBG (1, "attach: GET_WINDOW failed %d\n", status);
235141cc406Sopenharmony_ci      sanei_scsi_close (fd);
236141cc406Sopenharmony_ci      DBG (11, "<< attach\n");
237141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
238141cc406Sopenharmony_ci    }
239141cc406Sopenharmony_ci
240141cc406Sopenharmony_ci  sanei_scsi_close (fd);
241141cc406Sopenharmony_ci
242141cc406Sopenharmony_ci  dev = malloc (sizeof (*dev));
243141cc406Sopenharmony_ci  if (!dev)
244141cc406Sopenharmony_ci    return (SANE_STATUS_NO_MEM);
245141cc406Sopenharmony_ci  memset (dev, 0, sizeof (*dev));
246141cc406Sopenharmony_ci
247141cc406Sopenharmony_ci  dev->sane.name = strdup (devnam);
248141cc406Sopenharmony_ci  dev->sane.vendor = "IBM";
249141cc406Sopenharmony_ci
250141cc406Sopenharmony_ci  size_t prod_rev_size = sizeof(ibuf.product) + sizeof(ibuf.revision) + 1;
251141cc406Sopenharmony_ci  str = malloc (prod_rev_size);
252141cc406Sopenharmony_ci  if (str)
253141cc406Sopenharmony_ci    {
254141cc406Sopenharmony_ci      snprintf (str, prod_rev_size, "%.*s%.*s",
255141cc406Sopenharmony_ci                (int) sizeof(ibuf.product), (const char *) ibuf.product,
256141cc406Sopenharmony_ci                (int) sizeof(ibuf.revision), (const char *) ibuf.revision);
257141cc406Sopenharmony_ci    }
258141cc406Sopenharmony_ci  dev->sane.model = str;
259141cc406Sopenharmony_ci  dev->sane.type = "flatbed scanner";
260141cc406Sopenharmony_ci
261141cc406Sopenharmony_ci  DBG (5, "dev->sane.name = %s\n", dev->sane.name);
262141cc406Sopenharmony_ci  DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor);
263141cc406Sopenharmony_ci  DBG (5, "dev->sane.model = %s\n", dev->sane.model);
264141cc406Sopenharmony_ci  DBG (5, "dev->sane.type = %s\n", dev->sane.type);
265141cc406Sopenharmony_ci
266141cc406Sopenharmony_ci  dev->info.xres_default = _2btol(wbuf.x_res);
267141cc406Sopenharmony_ci  dev->info.yres_default = _2btol(wbuf.y_res);
268141cc406Sopenharmony_ci  dev->info.image_mode_default = wbuf.image_comp;
269141cc406Sopenharmony_ci
270141cc406Sopenharmony_ci  /* if you throw the MRIF bit the brightness control reverses too */
271141cc406Sopenharmony_ci  /* so I reverse the reversal in software for symmetry's sake */
272141cc406Sopenharmony_ci  /* I should make this into an option */
273141cc406Sopenharmony_ci
274141cc406Sopenharmony_ci  if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME)
275141cc406Sopenharmony_ci    {
276141cc406Sopenharmony_ci      dev->info.brightness_default = 256 - wbuf.brightness;
277141cc406Sopenharmony_ci/*
278141cc406Sopenharmony_ci      if (is50)
279141cc406Sopenharmony_ci	dev->info.contrast_default = wbuf.contrast;
280141cc406Sopenharmony_ci      else
281141cc406Sopenharmony_ci*/
282141cc406Sopenharmony_ci      dev->info.contrast_default = 256 - wbuf.contrast;
283141cc406Sopenharmony_ci    }
284141cc406Sopenharmony_ci  else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
285141cc406Sopenharmony_ci    {
286141cc406Sopenharmony_ci      dev->info.brightness_default = wbuf.brightness;
287141cc406Sopenharmony_ci      dev->info.contrast_default = wbuf.contrast;
288141cc406Sopenharmony_ci    }
289141cc406Sopenharmony_ci
290141cc406Sopenharmony_ci/* da rivedere
291141cc406Sopenharmony_ci  dev->info.adf_default = wbuf.adf_state;
292141cc406Sopenharmony_ci*/
293141cc406Sopenharmony_ci  dev->info.adf_default = ADF_UNUSED;
294141cc406Sopenharmony_ci  dev->info.adf_default = IBM_PAPER_USER_DEFINED;
295141cc406Sopenharmony_ci
296141cc406Sopenharmony_ci#if 1
297141cc406Sopenharmony_ci  dev->info.bmu = mup.bmu;
298141cc406Sopenharmony_ci  dev->info.mud = _2btol(mup.mud);
299141cc406Sopenharmony_ci  if (dev->info.mud == 0) {
300141cc406Sopenharmony_ci    /* The Ricoh says it uses points as default Basic Measurement Unit */
301141cc406Sopenharmony_ci    /* but gives a Measurement Unit Divisor of zero */
302141cc406Sopenharmony_ci    /* So, we set it to the default (SCSI-standard) of 1200 */
303141cc406Sopenharmony_ci    /* with BMU in inches, i.e. 1200 points equal 1 inch */
304141cc406Sopenharmony_ci    dev->info.bmu = INCHES;
305141cc406Sopenharmony_ci    dev->info.mud = DEFAULT_MUD;
306141cc406Sopenharmony_ci  }
307141cc406Sopenharmony_ci#else
308141cc406Sopenharmony_ci    dev->info.bmu = INCHES;
309141cc406Sopenharmony_ci    dev->info.mud = DEFAULT_MUD;
310141cc406Sopenharmony_ci#endif
311141cc406Sopenharmony_ci
312141cc406Sopenharmony_ci  DBG (5, "xres_default=%d\n", dev->info.xres_default);
313141cc406Sopenharmony_ci  DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max);
314141cc406Sopenharmony_ci  DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min);
315141cc406Sopenharmony_ci
316141cc406Sopenharmony_ci  DBG (5, "yres_default=%d\n", dev->info.yres_default);
317141cc406Sopenharmony_ci  DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max);
318141cc406Sopenharmony_ci  DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min);
319141cc406Sopenharmony_ci
320141cc406Sopenharmony_ci  DBG (5, "x_range.max=%d\n", dev->info.x_range.max);
321141cc406Sopenharmony_ci  DBG (5, "y_range.max=%d\n", dev->info.y_range.max);
322141cc406Sopenharmony_ci
323141cc406Sopenharmony_ci  DBG (5, "image_mode=%d\n", dev->info.image_mode_default);
324141cc406Sopenharmony_ci
325141cc406Sopenharmony_ci  DBG (5, "brightness=%d\n", dev->info.brightness_default);
326141cc406Sopenharmony_ci  DBG (5, "contrast=%d\n", dev->info.contrast_default);
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci  DBG (5, "adf_state=%d\n", dev->info.adf_default);
329141cc406Sopenharmony_ci
330141cc406Sopenharmony_ci  DBG (5, "bmu=%d\n", dev->info.bmu);
331141cc406Sopenharmony_ci  DBG (5, "mud=%d\n", dev->info.mud);
332141cc406Sopenharmony_ci
333141cc406Sopenharmony_ci  ++num_devices;
334141cc406Sopenharmony_ci  dev->next = first_dev;
335141cc406Sopenharmony_ci  first_dev = dev;
336141cc406Sopenharmony_ci
337141cc406Sopenharmony_ci  if (devp)
338141cc406Sopenharmony_ci    *devp = dev;
339141cc406Sopenharmony_ci
340141cc406Sopenharmony_ci  DBG (11, "<< attach\n");
341141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
342141cc406Sopenharmony_ci}
343141cc406Sopenharmony_ci
344141cc406Sopenharmony_cistatic SANE_Status
345141cc406Sopenharmony_ciattach_one(const char *devnam)
346141cc406Sopenharmony_ci{
347141cc406Sopenharmony_ci  attach (devnam, NULL);
348141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
349141cc406Sopenharmony_ci}
350141cc406Sopenharmony_ci
351141cc406Sopenharmony_cistatic SANE_Status
352141cc406Sopenharmony_ciinit_options (Ibm_Scanner * s)
353141cc406Sopenharmony_ci{
354141cc406Sopenharmony_ci  int i;
355141cc406Sopenharmony_ci  DBG (11, ">> init_options\n");
356141cc406Sopenharmony_ci
357141cc406Sopenharmony_ci  memset (s->opt, 0, sizeof (s->opt));
358141cc406Sopenharmony_ci  memset (s->val, 0, sizeof (s->val));
359141cc406Sopenharmony_ci
360141cc406Sopenharmony_ci  for (i = 0; i < NUM_OPTIONS; ++i)
361141cc406Sopenharmony_ci    {
362141cc406Sopenharmony_ci      s->opt[i].size = sizeof (SANE_Word);
363141cc406Sopenharmony_ci      s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
364141cc406Sopenharmony_ci    }
365141cc406Sopenharmony_ci
366141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
367141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
368141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
369141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
370141cc406Sopenharmony_ci  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
371141cc406Sopenharmony_ci
372141cc406Sopenharmony_ci  /* "Mode" group: */
373141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].title = "Scan Mode";
374141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].desc = "";
375141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
376141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].cap = 0;
377141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
378141cc406Sopenharmony_ci
379141cc406Sopenharmony_ci  /* scan mode */
380141cc406Sopenharmony_ci  s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
381141cc406Sopenharmony_ci  s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
382141cc406Sopenharmony_ci  s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
383141cc406Sopenharmony_ci  s->opt[OPT_MODE].type = SANE_TYPE_STRING;
384141cc406Sopenharmony_ci  s->opt[OPT_MODE].size = max_string_size (mode_list);
385141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
386141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint.string_list = mode_list;
387141cc406Sopenharmony_ci  s->val[OPT_MODE].s = strdup (mode_list[s->hw->info.image_mode_default]);
388141cc406Sopenharmony_ci
389141cc406Sopenharmony_ci  /* x resolution */
390141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].name = "X" SANE_NAME_SCAN_RESOLUTION;
391141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].title = "X " SANE_TITLE_SCAN_RESOLUTION;
392141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
393141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
394141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
395141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
396141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint.range = &ibm2456_res_range;
397141cc406Sopenharmony_ci  s->val[OPT_X_RESOLUTION].w = s->hw->info.xres_default;
398141cc406Sopenharmony_ci/*
399141cc406Sopenharmony_ci  if (is50)
400141cc406Sopenharmony_ci    s->opt[OPT_X_RESOLUTION].constraint.range = &is50_res_range;
401141cc406Sopenharmony_ci  else
402141cc406Sopenharmony_ci*/
403141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint.range = &ibm2456_res_range;
404141cc406Sopenharmony_ci
405141cc406Sopenharmony_ci  /* y resolution */
406141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION;
407141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION;
408141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
409141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
410141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
411141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
412141cc406Sopenharmony_ci  s->val[OPT_Y_RESOLUTION].w =  s->hw->info.yres_default;
413141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].constraint.range = &ibm2456_res_range;
414141cc406Sopenharmony_ci
415141cc406Sopenharmony_ci  /* adf */
416141cc406Sopenharmony_ci  s->opt[OPT_ADF].name = "adf";
417141cc406Sopenharmony_ci  s->opt[OPT_ADF].title = "Use ADF";
418141cc406Sopenharmony_ci  s->opt[OPT_ADF].desc = "Uses the automatic document feeder.";
419141cc406Sopenharmony_ci  s->opt[OPT_ADF].type = SANE_TYPE_BOOL;
420141cc406Sopenharmony_ci  s->opt[OPT_ADF].unit = SANE_UNIT_NONE;
421141cc406Sopenharmony_ci  s->opt[OPT_ADF].constraint_type = SANE_CONSTRAINT_NONE;
422141cc406Sopenharmony_ci  s->val[OPT_ADF].b =  s->hw->info.adf_default;
423141cc406Sopenharmony_ci
424141cc406Sopenharmony_ci  /* "Geometry" group: */
425141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
426141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].desc = "";
427141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
428141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
429141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
430141cc406Sopenharmony_ci
431141cc406Sopenharmony_ci  /* paper */
432141cc406Sopenharmony_ci  s->opt[OPT_PAPER].name = "paper";
433141cc406Sopenharmony_ci  s->opt[OPT_PAPER].title = "Paper format";
434141cc406Sopenharmony_ci  s->opt[OPT_PAPER].desc = "Sets the paper format.";
435141cc406Sopenharmony_ci  s->opt[OPT_PAPER].type = SANE_TYPE_STRING;
436141cc406Sopenharmony_ci  s->opt[OPT_PAPER].size = max_string_size (paper_list);
437141cc406Sopenharmony_ci  s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST;
438141cc406Sopenharmony_ci  s->opt[OPT_PAPER].constraint.string_list = paper_list;
439141cc406Sopenharmony_ci  s->val[OPT_PAPER].s = strdup (paper_list[s->hw->info.paper_default]);
440141cc406Sopenharmony_ci
441141cc406Sopenharmony_ci  /* top-left x */
442141cc406Sopenharmony_ci  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
443141cc406Sopenharmony_ci  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
444141cc406Sopenharmony_ci  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
445141cc406Sopenharmony_ci  s->opt[OPT_TL_X].type = SANE_TYPE_INT;
446141cc406Sopenharmony_ci  s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
447141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
448141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint.range = &default_x_range;
449141cc406Sopenharmony_ci  s->val[OPT_TL_X].w = 0;
450141cc406Sopenharmony_ci
451141cc406Sopenharmony_ci  /* top-left y */
452141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
453141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
454141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
455141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].type = SANE_TYPE_INT;
456141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
457141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
458141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint.range = &default_y_range;
459141cc406Sopenharmony_ci  s->val[OPT_TL_Y].w = 0;
460141cc406Sopenharmony_ci
461141cc406Sopenharmony_ci  /* bottom-right x */
462141cc406Sopenharmony_ci  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
463141cc406Sopenharmony_ci  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
464141cc406Sopenharmony_ci  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
465141cc406Sopenharmony_ci  s->opt[OPT_BR_X].type = SANE_TYPE_INT;
466141cc406Sopenharmony_ci  s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
467141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
468141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint.range = &default_x_range;
469141cc406Sopenharmony_ci  s->val[OPT_BR_X].w = default_x_range.max;
470141cc406Sopenharmony_ci
471141cc406Sopenharmony_ci  /* bottom-right y */
472141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
473141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
474141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
475141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].type = SANE_TYPE_INT;
476141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
477141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
478141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint.range = &default_y_range;
479141cc406Sopenharmony_ci  s->val[OPT_BR_Y].w = default_y_range.max;
480141cc406Sopenharmony_ci
481141cc406Sopenharmony_ci  /* "Enhancement" group: */
482141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
483141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
484141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
485141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
486141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
487141cc406Sopenharmony_ci
488141cc406Sopenharmony_ci  /* brightness */
489141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
490141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
491141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
492141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
493141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
494141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
495141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range;
496141cc406Sopenharmony_ci  s->val[OPT_BRIGHTNESS].w =  s->hw->info.brightness_default;
497141cc406Sopenharmony_ci
498141cc406Sopenharmony_ci  /* contrast */
499141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
500141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
501141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
502141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
503141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
504141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
505141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].constraint.range = &u8_range;
506141cc406Sopenharmony_ci  s->val[OPT_CONTRAST].w =  s->hw->info.contrast_default;
507141cc406Sopenharmony_ci
508141cc406Sopenharmony_ci  DBG (11, "<< init_options\n");
509141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
510141cc406Sopenharmony_ci}
511141cc406Sopenharmony_ci
512141cc406Sopenharmony_cistatic SANE_Status
513141cc406Sopenharmony_cido_cancel (Ibm_Scanner * s)
514141cc406Sopenharmony_ci{
515141cc406Sopenharmony_ci  SANE_Status status;
516141cc406Sopenharmony_ci  DBG (11, ">> do_cancel\n");
517141cc406Sopenharmony_ci
518141cc406Sopenharmony_ci  DBG (3, "cancel: sending OBJECT POSITION\n");
519141cc406Sopenharmony_ci  status = object_position (s->fd, OBJECT_POSITION_UNLOAD);
520141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
521141cc406Sopenharmony_ci    {
522141cc406Sopenharmony_ci      DBG (1, "cancel: OBJECT POSITION failed\n");
523141cc406Sopenharmony_ci    }
524141cc406Sopenharmony_ci
525141cc406Sopenharmony_ci  s->scanning = SANE_FALSE;
526141cc406Sopenharmony_ci
527141cc406Sopenharmony_ci  if (s->fd >= 0)
528141cc406Sopenharmony_ci    {
529141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
530141cc406Sopenharmony_ci      s->fd = -1;
531141cc406Sopenharmony_ci    }
532141cc406Sopenharmony_ci
533141cc406Sopenharmony_ci  DBG (11, "<< do_cancel\n");
534141cc406Sopenharmony_ci  return (SANE_STATUS_CANCELLED);
535141cc406Sopenharmony_ci}
536141cc406Sopenharmony_ci
537141cc406Sopenharmony_ciSANE_Status
538141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
539141cc406Sopenharmony_ci{
540141cc406Sopenharmony_ci  char devnam[PATH_MAX] = "/dev/scanner";
541141cc406Sopenharmony_ci  FILE *fp;
542141cc406Sopenharmony_ci
543141cc406Sopenharmony_ci  DBG_INIT ();
544141cc406Sopenharmony_ci  DBG (11, ">> sane_init (authorize %s null)\n", (authorize) ? "!=" : "==");
545141cc406Sopenharmony_ci
546141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION
547141cc406Sopenharmony_ci  DBG (2, "sane_init: ibm backend version %d.%d-%d ("
548141cc406Sopenharmony_ci       PACKAGE " " VERSION ")\n", SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
549141cc406Sopenharmony_ci#endif
550141cc406Sopenharmony_ci
551141cc406Sopenharmony_ci  if (version_code)
552141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
553141cc406Sopenharmony_ci
554141cc406Sopenharmony_ci  fp = sanei_config_open(IBM_CONFIG_FILE);
555141cc406Sopenharmony_ci  if (fp)
556141cc406Sopenharmony_ci    {
557141cc406Sopenharmony_ci      char line[PATH_MAX], *lp;
558141cc406Sopenharmony_ci      size_t len;
559141cc406Sopenharmony_ci
560141cc406Sopenharmony_ci      /* read config file */
561141cc406Sopenharmony_ci      while (sanei_config_read (line, sizeof (line), fp))
562141cc406Sopenharmony_ci        {
563141cc406Sopenharmony_ci          if (line[0] == '#')           /* ignore line comments */
564141cc406Sopenharmony_ci            continue;
565141cc406Sopenharmony_ci          len = strlen (line);
566141cc406Sopenharmony_ci
567141cc406Sopenharmony_ci          if (!len)
568141cc406Sopenharmony_ci            continue;                   /* ignore empty lines */
569141cc406Sopenharmony_ci
570141cc406Sopenharmony_ci	  /* skip white space: */
571141cc406Sopenharmony_ci	  for (lp = line; isspace(*lp); ++lp)
572141cc406Sopenharmony_ci            ;
573141cc406Sopenharmony_ci          strcpy (devnam, lp);
574141cc406Sopenharmony_ci        }
575141cc406Sopenharmony_ci      fclose (fp);
576141cc406Sopenharmony_ci    }
577141cc406Sopenharmony_ci  sanei_config_attach_matching_devices (devnam, attach_one);
578141cc406Sopenharmony_ci  DBG (11, "<< sane_init\n");
579141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
580141cc406Sopenharmony_ci}
581141cc406Sopenharmony_ci
582141cc406Sopenharmony_civoid
583141cc406Sopenharmony_cisane_exit (void)
584141cc406Sopenharmony_ci{
585141cc406Sopenharmony_ci  Ibm_Device *dev, *next;
586141cc406Sopenharmony_ci  DBG (11, ">> sane_exit\n");
587141cc406Sopenharmony_ci
588141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = next)
589141cc406Sopenharmony_ci    {
590141cc406Sopenharmony_ci      next = dev->next;
591141cc406Sopenharmony_ci      free ((void *) dev->sane.name);
592141cc406Sopenharmony_ci      free ((void *) dev->sane.model);
593141cc406Sopenharmony_ci      free (dev);
594141cc406Sopenharmony_ci    }
595141cc406Sopenharmony_ci
596141cc406Sopenharmony_ci  DBG (11, "<< sane_exit\n");
597141cc406Sopenharmony_ci}
598141cc406Sopenharmony_ci
599141cc406Sopenharmony_ciSANE_Status
600141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
601141cc406Sopenharmony_ci{
602141cc406Sopenharmony_ci  static const SANE_Device **devlist = 0;
603141cc406Sopenharmony_ci  Ibm_Device *dev;
604141cc406Sopenharmony_ci  int i;
605141cc406Sopenharmony_ci  DBG (11, ">> sane_get_devices (local_only = %d)\n", local_only);
606141cc406Sopenharmony_ci
607141cc406Sopenharmony_ci  if (devlist)
608141cc406Sopenharmony_ci    free (devlist);
609141cc406Sopenharmony_ci  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
610141cc406Sopenharmony_ci  if (!devlist)
611141cc406Sopenharmony_ci    return (SANE_STATUS_NO_MEM);
612141cc406Sopenharmony_ci
613141cc406Sopenharmony_ci  i = 0;
614141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
615141cc406Sopenharmony_ci    devlist[i++] = &dev->sane;
616141cc406Sopenharmony_ci  devlist[i++] = 0;
617141cc406Sopenharmony_ci
618141cc406Sopenharmony_ci  *device_list = devlist;
619141cc406Sopenharmony_ci
620141cc406Sopenharmony_ci  DBG (11, "<< sane_get_devices\n");
621141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
622141cc406Sopenharmony_ci}
623141cc406Sopenharmony_ci
624141cc406Sopenharmony_ciSANE_Status
625141cc406Sopenharmony_cisane_open (SANE_String_Const devnam, SANE_Handle * handle)
626141cc406Sopenharmony_ci{
627141cc406Sopenharmony_ci  SANE_Status status;
628141cc406Sopenharmony_ci  Ibm_Device *dev;
629141cc406Sopenharmony_ci  Ibm_Scanner *s;
630141cc406Sopenharmony_ci  DBG (11, ">> sane_open\n");
631141cc406Sopenharmony_ci
632141cc406Sopenharmony_ci  if (devnam[0] == '\0')
633141cc406Sopenharmony_ci    {
634141cc406Sopenharmony_ci      for (dev = first_dev; dev; dev = dev->next)
635141cc406Sopenharmony_ci        {
636141cc406Sopenharmony_ci          if (strcmp (dev->sane.name, devnam) == 0)
637141cc406Sopenharmony_ci            break;
638141cc406Sopenharmony_ci        }
639141cc406Sopenharmony_ci
640141cc406Sopenharmony_ci      if (!dev)
641141cc406Sopenharmony_ci        {
642141cc406Sopenharmony_ci          status = attach (devnam, &dev);
643141cc406Sopenharmony_ci          if (status != SANE_STATUS_GOOD)
644141cc406Sopenharmony_ci            return (status);
645141cc406Sopenharmony_ci        }
646141cc406Sopenharmony_ci    }
647141cc406Sopenharmony_ci  else
648141cc406Sopenharmony_ci    {
649141cc406Sopenharmony_ci      dev = first_dev;
650141cc406Sopenharmony_ci    }
651141cc406Sopenharmony_ci
652141cc406Sopenharmony_ci  if (!dev)
653141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
654141cc406Sopenharmony_ci
655141cc406Sopenharmony_ci  s = malloc (sizeof (*s));
656141cc406Sopenharmony_ci  if (!s)
657141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
658141cc406Sopenharmony_ci  memset (s, 0, sizeof (*s));
659141cc406Sopenharmony_ci
660141cc406Sopenharmony_ci  s->fd = -1;
661141cc406Sopenharmony_ci  s->hw = dev;
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  init_options (s);
664141cc406Sopenharmony_ci
665141cc406Sopenharmony_ci  s->next = first_handle;
666141cc406Sopenharmony_ci  first_handle = s;
667141cc406Sopenharmony_ci
668141cc406Sopenharmony_ci  *handle = s;
669141cc406Sopenharmony_ci
670141cc406Sopenharmony_ci  DBG (11, "<< sane_open\n");
671141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
672141cc406Sopenharmony_ci}
673141cc406Sopenharmony_ci
674141cc406Sopenharmony_civoid
675141cc406Sopenharmony_cisane_close (SANE_Handle handle)
676141cc406Sopenharmony_ci{
677141cc406Sopenharmony_ci  Ibm_Scanner *s = (Ibm_Scanner *) handle;
678141cc406Sopenharmony_ci  DBG (11, ">> sane_close\n");
679141cc406Sopenharmony_ci
680141cc406Sopenharmony_ci  if (s->fd != -1)
681141cc406Sopenharmony_ci    sanei_scsi_close (s->fd);
682141cc406Sopenharmony_ci  free (s);
683141cc406Sopenharmony_ci
684141cc406Sopenharmony_ci  DBG (11, ">> sane_close\n");
685141cc406Sopenharmony_ci}
686141cc406Sopenharmony_ci
687141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
688141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
689141cc406Sopenharmony_ci{
690141cc406Sopenharmony_ci  Ibm_Scanner *s = handle;
691141cc406Sopenharmony_ci  DBG (11, ">> sane_get_option_descriptor\n");
692141cc406Sopenharmony_ci
693141cc406Sopenharmony_ci  if ((unsigned) option >= NUM_OPTIONS)
694141cc406Sopenharmony_ci    return (0);
695141cc406Sopenharmony_ci
696141cc406Sopenharmony_ci  DBG (11, "<< sane_get_option_descriptor\n");
697141cc406Sopenharmony_ci  return (s->opt + option);
698141cc406Sopenharmony_ci}
699141cc406Sopenharmony_ci
700141cc406Sopenharmony_ciSANE_Status
701141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
702141cc406Sopenharmony_ci                     SANE_Action action, void *val, SANE_Int * info)
703141cc406Sopenharmony_ci{
704141cc406Sopenharmony_ci  Ibm_Scanner *s = handle;
705141cc406Sopenharmony_ci  SANE_Status status;
706141cc406Sopenharmony_ci  SANE_Word cap;
707141cc406Sopenharmony_ci  DBG (11, ">> sane_control_option\n");
708141cc406Sopenharmony_ci
709141cc406Sopenharmony_ci  if (info)
710141cc406Sopenharmony_ci    *info = 0;
711141cc406Sopenharmony_ci
712141cc406Sopenharmony_ci  if (s->scanning)
713141cc406Sopenharmony_ci    return (SANE_STATUS_DEVICE_BUSY);
714141cc406Sopenharmony_ci  if (option >= NUM_OPTIONS)
715141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
716141cc406Sopenharmony_ci
717141cc406Sopenharmony_ci  cap = s->opt[option].cap;
718141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (cap))
719141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
720141cc406Sopenharmony_ci
721141cc406Sopenharmony_ci  if (action == SANE_ACTION_GET_VALUE)
722141cc406Sopenharmony_ci    {
723141cc406Sopenharmony_ci      DBG (11, "sane_control_option get_value\n");
724141cc406Sopenharmony_ci      switch (option)
725141cc406Sopenharmony_ci        {
726141cc406Sopenharmony_ci          /* word options: */
727141cc406Sopenharmony_ci        case OPT_X_RESOLUTION:
728141cc406Sopenharmony_ci        case OPT_Y_RESOLUTION:
729141cc406Sopenharmony_ci        case OPT_TL_X:
730141cc406Sopenharmony_ci        case OPT_TL_Y:
731141cc406Sopenharmony_ci        case OPT_BR_X:
732141cc406Sopenharmony_ci        case OPT_BR_Y:
733141cc406Sopenharmony_ci        case OPT_NUM_OPTS:
734141cc406Sopenharmony_ci        case OPT_BRIGHTNESS:
735141cc406Sopenharmony_ci        case OPT_CONTRAST:
736141cc406Sopenharmony_ci          *(SANE_Word *) val = s->val[option].w;
737141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
738141cc406Sopenharmony_ci
739141cc406Sopenharmony_ci          /* bool options: */
740141cc406Sopenharmony_ci	case OPT_ADF:
741141cc406Sopenharmony_ci          *(SANE_Bool *) val = s->val[option].b;
742141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
743141cc406Sopenharmony_ci
744141cc406Sopenharmony_ci          /* string options: */
745141cc406Sopenharmony_ci        case OPT_MODE:
746141cc406Sopenharmony_ci	case OPT_PAPER:
747141cc406Sopenharmony_ci          strcpy (val, s->val[option].s);
748141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
749141cc406Sopenharmony_ci        }
750141cc406Sopenharmony_ci    }
751141cc406Sopenharmony_ci  else {
752141cc406Sopenharmony_ci    DBG (11, "sane_control_option set_value\n");
753141cc406Sopenharmony_ci    if (action == SANE_ACTION_SET_VALUE)
754141cc406Sopenharmony_ci    {
755141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (cap))
756141cc406Sopenharmony_ci        return (SANE_STATUS_INVAL);
757141cc406Sopenharmony_ci
758141cc406Sopenharmony_ci      status = sanei_constrain_value (s->opt + option, val, info);
759141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
760141cc406Sopenharmony_ci        return status;
761141cc406Sopenharmony_ci
762141cc406Sopenharmony_ci      switch (option)
763141cc406Sopenharmony_ci        {
764141cc406Sopenharmony_ci          /* (mostly) side-effect-free word options: */
765141cc406Sopenharmony_ci        case OPT_X_RESOLUTION:
766141cc406Sopenharmony_ci        case OPT_Y_RESOLUTION:
767141cc406Sopenharmony_ci          if (info && s->val[option].w != *(SANE_Word *) val)
768141cc406Sopenharmony_ci            *info |= SANE_INFO_RELOAD_PARAMS;
769141cc406Sopenharmony_ci          s->val[option].w = *(SANE_Word *) val;
770141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
771141cc406Sopenharmony_ci
772141cc406Sopenharmony_ci	case OPT_TL_X:
773141cc406Sopenharmony_ci        case OPT_TL_Y:
774141cc406Sopenharmony_ci        case OPT_BR_X:
775141cc406Sopenharmony_ci        case OPT_BR_Y:
776141cc406Sopenharmony_ci          if (info && s->val[option].w != *(SANE_Word *) val)
777141cc406Sopenharmony_ci            *info |= SANE_INFO_RELOAD_PARAMS;
778141cc406Sopenharmony_ci          s->val[option].w = *(SANE_Word *) val;
779141cc406Sopenharmony_ci	  /* resets the paper format to user defined */
780141cc406Sopenharmony_ci	  if (strcmp(s->val[OPT_PAPER].s, paper_list[IBM_PAPER_USER_DEFINED]) != 0)
781141cc406Sopenharmony_ci	    {
782141cc406Sopenharmony_ci	      if (info)
783141cc406Sopenharmony_ci		*info |= SANE_INFO_RELOAD_OPTIONS;
784141cc406Sopenharmony_ci              if (s->val[OPT_PAPER].s)
785141cc406Sopenharmony_ci                free (s->val[OPT_PAPER].s);
786141cc406Sopenharmony_ci              s->val[OPT_PAPER].s = strdup (paper_list[IBM_PAPER_USER_DEFINED]);
787141cc406Sopenharmony_ci	    }
788141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
789141cc406Sopenharmony_ci
790141cc406Sopenharmony_ci	case OPT_NUM_OPTS:
791141cc406Sopenharmony_ci        case OPT_BRIGHTNESS:
792141cc406Sopenharmony_ci        case OPT_CONTRAST:
793141cc406Sopenharmony_ci          s->val[option].w = *(SANE_Word *) val;
794141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
795141cc406Sopenharmony_ci
796141cc406Sopenharmony_ci        case OPT_MODE:
797141cc406Sopenharmony_ci          if (info && strcmp (s->val[option].s, (SANE_String) val))
798141cc406Sopenharmony_ci            *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
799141cc406Sopenharmony_ci          if (s->val[option].s)
800141cc406Sopenharmony_ci            free (s->val[option].s);
801141cc406Sopenharmony_ci          s->val[option].s = strdup (val);
802141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
803141cc406Sopenharmony_ci
804141cc406Sopenharmony_ci	case OPT_ADF:
805141cc406Sopenharmony_ci	  s->val[option].b = *(SANE_Bool *) val;
806141cc406Sopenharmony_ci	  if (*(SANE_Bool *) val)
807141cc406Sopenharmony_ci	    s->adf_state = ADF_ARMED;
808141cc406Sopenharmony_ci          else
809141cc406Sopenharmony_ci	    s->adf_state = ADF_UNUSED;
810141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
811141cc406Sopenharmony_ci
812141cc406Sopenharmony_ci	case OPT_PAPER:
813141cc406Sopenharmony_ci          if (info && strcmp (s->val[option].s, (SANE_String) val))
814141cc406Sopenharmony_ci            *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
815141cc406Sopenharmony_ci          if (s->val[option].s)
816141cc406Sopenharmony_ci            free (s->val[option].s);
817141cc406Sopenharmony_ci          s->val[option].s = strdup (val);
818141cc406Sopenharmony_ci	  if (strcmp (s->val[OPT_PAPER].s, "User") != 0)
819141cc406Sopenharmony_ci	    {
820141cc406Sopenharmony_ci              s->val[OPT_TL_X].w = 0;
821141cc406Sopenharmony_ci	      s->val[OPT_TL_Y].w = 0;
822141cc406Sopenharmony_ci	    if (strcmp (s->val[OPT_PAPER].s, "A3") == 0)
823141cc406Sopenharmony_ci	      {
824141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_A3_W;
825141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_A3_H;
826141cc406Sopenharmony_ci	      }
827141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "A4") == 0)
828141cc406Sopenharmony_ci	      {
829141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_A4_W;
830141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_A4_H;
831141cc406Sopenharmony_ci	      }
832141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "A4R") == 0)
833141cc406Sopenharmony_ci	      {
834141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_A4R_W;
835141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_A4R_H;
836141cc406Sopenharmony_ci	      }
837141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "A5") == 0)
838141cc406Sopenharmony_ci	      {
839141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_A5_W;
840141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_A5_H;
841141cc406Sopenharmony_ci	      }
842141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "A5R") == 0)
843141cc406Sopenharmony_ci	      {
844141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_A5R_W;
845141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_A5R_H;
846141cc406Sopenharmony_ci  	      }
847141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "A6") == 0)
848141cc406Sopenharmony_ci	      {
849141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_A6_W;
850141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_A6_H;
851141cc406Sopenharmony_ci	      }
852141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "B4") == 0)
853141cc406Sopenharmony_ci	      {
854141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_B4_W;
855141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_B4_H;
856141cc406Sopenharmony_ci	      }
857141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "Legal") == 0)
858141cc406Sopenharmony_ci	      {
859141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_LEGAL_W;
860141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_LEGAL_H;
861141cc406Sopenharmony_ci	      }
862141cc406Sopenharmony_ci	    else if (strcmp (s->val[OPT_PAPER].s, "Letter") == 0)
863141cc406Sopenharmony_ci	      {
864141cc406Sopenharmony_ci                s->val[OPT_BR_X].w = PAPER_LETTER_W;
865141cc406Sopenharmony_ci	        s->val[OPT_BR_Y].w = PAPER_LETTER_H;
866141cc406Sopenharmony_ci	      }
867141cc406Sopenharmony_ci	  }
868141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
869141cc406Sopenharmony_ci        }
870141cc406Sopenharmony_ci
871141cc406Sopenharmony_ci    }
872141cc406Sopenharmony_ci  }
873141cc406Sopenharmony_ci
874141cc406Sopenharmony_ci  DBG (11, "<< sane_control_option\n");
875141cc406Sopenharmony_ci  return (SANE_STATUS_INVAL);
876141cc406Sopenharmony_ci}
877141cc406Sopenharmony_ci
878141cc406Sopenharmony_ciSANE_Status
879141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
880141cc406Sopenharmony_ci{
881141cc406Sopenharmony_ci  Ibm_Scanner *s = handle;
882141cc406Sopenharmony_ci  DBG (11, ">> sane_get_parameters\n");
883141cc406Sopenharmony_ci
884141cc406Sopenharmony_ci  if (!s->scanning)
885141cc406Sopenharmony_ci    {
886141cc406Sopenharmony_ci      int width, length, xres, yres;
887141cc406Sopenharmony_ci      const char *mode;
888141cc406Sopenharmony_ci
889141cc406Sopenharmony_ci      memset (&s->params, 0, sizeof (s->params));
890141cc406Sopenharmony_ci
891141cc406Sopenharmony_ci      width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
892141cc406Sopenharmony_ci      length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
893141cc406Sopenharmony_ci      xres = s->val[OPT_X_RESOLUTION].w;
894141cc406Sopenharmony_ci      yres = s->val[OPT_Y_RESOLUTION].w;
895141cc406Sopenharmony_ci
896141cc406Sopenharmony_ci      /* make best-effort guess at what parameters will look like once
897141cc406Sopenharmony_ci         scanning starts.  */
898141cc406Sopenharmony_ci      if (xres > 0 && yres > 0 && width > 0 && length > 0)
899141cc406Sopenharmony_ci        {
900141cc406Sopenharmony_ci          s->params.pixels_per_line = width * xres / s->hw->info.mud;
901141cc406Sopenharmony_ci          s->params.lines = length * yres / s->hw->info.mud;
902141cc406Sopenharmony_ci        }
903141cc406Sopenharmony_ci
904141cc406Sopenharmony_ci      mode = s->val[OPT_MODE].s;
905141cc406Sopenharmony_ci      if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) ||
906141cc406Sopenharmony_ci	  (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE)) == 0)
907141cc406Sopenharmony_ci        {
908141cc406Sopenharmony_ci          s->params.format = SANE_FRAME_GRAY;
909141cc406Sopenharmony_ci          s->params.bytes_per_line = s->params.pixels_per_line / 8;
910141cc406Sopenharmony_ci	  /* the Ibm truncates to the byte boundary, so: chop! */
911141cc406Sopenharmony_ci          s->params.pixels_per_line = s->params.bytes_per_line * 8;
912141cc406Sopenharmony_ci          s->params.depth = 1;
913141cc406Sopenharmony_ci        }
914141cc406Sopenharmony_ci      else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */
915141cc406Sopenharmony_ci        {
916141cc406Sopenharmony_ci          s->params.format = SANE_FRAME_GRAY;
917141cc406Sopenharmony_ci          s->params.bytes_per_line = s->params.pixels_per_line;
918141cc406Sopenharmony_ci          s->params.depth = 8;
919141cc406Sopenharmony_ci        }
920141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
921141cc406Sopenharmony_ci    }
922141cc406Sopenharmony_ci  else
923141cc406Sopenharmony_ci    DBG (5, "sane_get_parameters: scanning, so can't get params\n");
924141cc406Sopenharmony_ci
925141cc406Sopenharmony_ci  if (params)
926141cc406Sopenharmony_ci    *params = s->params;
927141cc406Sopenharmony_ci
928141cc406Sopenharmony_ci  DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
929141cc406Sopenharmony_ci       "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
930141cc406Sopenharmony_ci       s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
931141cc406Sopenharmony_ci
932141cc406Sopenharmony_ci  DBG (11, "<< sane_get_parameters\n");
933141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
934141cc406Sopenharmony_ci}
935141cc406Sopenharmony_ci
936141cc406Sopenharmony_ci
937141cc406Sopenharmony_ciSANE_Status
938141cc406Sopenharmony_cisane_start (SANE_Handle handle)
939141cc406Sopenharmony_ci{
940141cc406Sopenharmony_ci  char *mode_str;
941141cc406Sopenharmony_ci  Ibm_Scanner *s = handle;
942141cc406Sopenharmony_ci  SANE_Status status;
943141cc406Sopenharmony_ci  struct ibm_window_data wbuf;
944141cc406Sopenharmony_ci  struct measurements_units_page mup;
945141cc406Sopenharmony_ci
946141cc406Sopenharmony_ci  DBG (11, ">> sane_start\n");
947141cc406Sopenharmony_ci
948141cc406Sopenharmony_ci  /* First make sure we have a current parameter set.  Some of the
949141cc406Sopenharmony_ci     parameters will be overwritten below, but that's OK.  */
950141cc406Sopenharmony_ci  status = sane_get_parameters (s, 0);
951141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
952141cc406Sopenharmony_ci    return status;
953141cc406Sopenharmony_ci
954141cc406Sopenharmony_ci  status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
955141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
956141cc406Sopenharmony_ci    {
957141cc406Sopenharmony_ci      DBG (1, "open of %s failed: %s\n",
958141cc406Sopenharmony_ci           s->hw->sane.name, sane_strstatus (status));
959141cc406Sopenharmony_ci      return (status);
960141cc406Sopenharmony_ci    }
961141cc406Sopenharmony_ci
962141cc406Sopenharmony_ci  mode_str = s->val[OPT_MODE].s;
963141cc406Sopenharmony_ci  s->xres = s->val[OPT_X_RESOLUTION].w;
964141cc406Sopenharmony_ci  s->yres = s->val[OPT_Y_RESOLUTION].w;
965141cc406Sopenharmony_ci  s->ulx = s->val[OPT_TL_X].w;
966141cc406Sopenharmony_ci  s->uly = s->val[OPT_TL_Y].w;
967141cc406Sopenharmony_ci  s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
968141cc406Sopenharmony_ci  s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
969141cc406Sopenharmony_ci  s->brightness = s->val[OPT_BRIGHTNESS].w;
970141cc406Sopenharmony_ci  s->contrast = s->val[OPT_CONTRAST].w;
971141cc406Sopenharmony_ci  s->bpp = s->params.depth;
972141cc406Sopenharmony_ci  if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0)
973141cc406Sopenharmony_ci    {
974141cc406Sopenharmony_ci      s->image_composition = IBM_BINARY_MONOCHROME;
975141cc406Sopenharmony_ci    }
976141cc406Sopenharmony_ci  else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
977141cc406Sopenharmony_ci    {
978141cc406Sopenharmony_ci      s->image_composition = IBM_DITHERED_MONOCHROME;
979141cc406Sopenharmony_ci    }
980141cc406Sopenharmony_ci  else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0)
981141cc406Sopenharmony_ci    {
982141cc406Sopenharmony_ci      s->image_composition = IBM_GRAYSCALE;
983141cc406Sopenharmony_ci    }
984141cc406Sopenharmony_ci
985141cc406Sopenharmony_ci  memset (&wbuf, 0, sizeof (wbuf));
986141cc406Sopenharmony_ci/* next line commented out by mf */
987141cc406Sopenharmony_ci/*  _lto2b(sizeof(wbuf) - 8, wbuf.len); */
988141cc406Sopenharmony_ci/* next line by mf */
989141cc406Sopenharmony_ci  _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */
990141cc406Sopenharmony_ci  _lto2b(s->xres, wbuf.x_res);
991141cc406Sopenharmony_ci  _lto2b(s->yres, wbuf.y_res);
992141cc406Sopenharmony_ci  _lto4b(s->ulx, wbuf.x_org);
993141cc406Sopenharmony_ci  _lto4b(s->uly, wbuf.y_org);
994141cc406Sopenharmony_ci  _lto4b(s->width, wbuf.width);
995141cc406Sopenharmony_ci  _lto4b(s->length, wbuf.length);
996141cc406Sopenharmony_ci
997141cc406Sopenharmony_ci  wbuf.image_comp = s->image_composition;
998141cc406Sopenharmony_ci  /* if you throw the MRIF bit the brightness control reverses too */
999141cc406Sopenharmony_ci  /* so I reverse the reversal in software for symmetry's sake */
1000141cc406Sopenharmony_ci  if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME)
1001141cc406Sopenharmony_ci    {
1002141cc406Sopenharmony_ci      if (wbuf.image_comp == IBM_GRAYSCALE)
1003141cc406Sopenharmony_ci	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */
1004141cc406Sopenharmony_ci      if (wbuf.image_comp == IBM_DITHERED_MONOCHROME)
1005141cc406Sopenharmony_ci	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10;
1006141cc406Sopenharmony_ci      wbuf.brightness = 256 - (SANE_Byte) s->brightness;
1007141cc406Sopenharmony_ci/*
1008141cc406Sopenharmony_ci      if (is50)
1009141cc406Sopenharmony_ci        wbuf.contrast = (SANE_Byte) s->contrast;
1010141cc406Sopenharmony_ci      else
1011141cc406Sopenharmony_ci*/
1012141cc406Sopenharmony_ci      wbuf.contrast = 256 - (SANE_Byte) s->contrast;
1013141cc406Sopenharmony_ci    }
1014141cc406Sopenharmony_ci  else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */
1015141cc406Sopenharmony_ci    {
1016141cc406Sopenharmony_ci      wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00;
1017141cc406Sopenharmony_ci      wbuf.brightness = (SANE_Byte) s->brightness;
1018141cc406Sopenharmony_ci      wbuf.contrast = (SANE_Byte) s->contrast;
1019141cc406Sopenharmony_ci    }
1020141cc406Sopenharmony_ci
1021141cc406Sopenharmony_ci  wbuf.threshold = 0;
1022141cc406Sopenharmony_ci  wbuf.bits_per_pixel = s->bpp;
1023141cc406Sopenharmony_ci
1024141cc406Sopenharmony_ci  wbuf.halftone_code = 2;     /* diithering */
1025141cc406Sopenharmony_ci  wbuf.halftone_id = 0x0A;    /* 8x8 Bayer pattenr */
1026141cc406Sopenharmony_ci  wbuf.pad_type = 3;
1027141cc406Sopenharmony_ci  wbuf.bit_ordering[0] = 0;
1028141cc406Sopenharmony_ci  wbuf.bit_ordering[1] = 7;   /* modified by mf (it was 3) */
1029141cc406Sopenharmony_ci
1030141cc406Sopenharmony_ci  DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
1031141cc406Sopenharmony_ci  DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
1032141cc406Sopenharmony_ci  DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
1033141cc406Sopenharmony_ci  DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
1034141cc406Sopenharmony_ci  DBG (5, "width=%d\n", _4btol(wbuf.width));
1035141cc406Sopenharmony_ci  DBG (5, "length=%d\n", _4btol(wbuf.length));
1036141cc406Sopenharmony_ci  DBG (5, "image_comp=%d\n", wbuf.image_comp);
1037141cc406Sopenharmony_ci
1038141cc406Sopenharmony_ci  DBG (11, "sane_start: sending SET WINDOW\n");
1039141cc406Sopenharmony_ci  status = set_window (s->fd, &wbuf);
1040141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1041141cc406Sopenharmony_ci    {
1042141cc406Sopenharmony_ci      DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
1043141cc406Sopenharmony_ci      return (status);
1044141cc406Sopenharmony_ci    }
1045141cc406Sopenharmony_ci
1046141cc406Sopenharmony_ci  DBG (11, "sane_start: sending GET WINDOW\n");
1047141cc406Sopenharmony_ci  memset (&wbuf, 0, sizeof (wbuf));
1048141cc406Sopenharmony_ci  status = get_window (s->fd, &wbuf);
1049141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1050141cc406Sopenharmony_ci    {
1051141cc406Sopenharmony_ci      DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
1052141cc406Sopenharmony_ci      return (status);
1053141cc406Sopenharmony_ci    }
1054141cc406Sopenharmony_ci  DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
1055141cc406Sopenharmony_ci  DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
1056141cc406Sopenharmony_ci  DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
1057141cc406Sopenharmony_ci  DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
1058141cc406Sopenharmony_ci  DBG (5, "width=%d\n", _4btol(wbuf.width));
1059141cc406Sopenharmony_ci  DBG (5, "length=%d\n", _4btol(wbuf.length));
1060141cc406Sopenharmony_ci  DBG (5, "image_comp=%d\n", wbuf.image_comp);
1061141cc406Sopenharmony_ci
1062141cc406Sopenharmony_ci  DBG (11, "sane_start: sending MODE SELECT\n");
1063141cc406Sopenharmony_ci  memset (&mup, 0, sizeof (mup));
1064141cc406Sopenharmony_ci  mup.page_code = MEASUREMENTS_PAGE;
1065141cc406Sopenharmony_ci  mup.parameter_length = 0x06;
1066141cc406Sopenharmony_ci  mup.bmu = INCHES;
1067141cc406Sopenharmony_ci  mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
1068141cc406Sopenharmony_ci  mup.mud[1] = (DEFAULT_MUD & 0xff);
1069141cc406Sopenharmony_ci/* next lines by mf */
1070141cc406Sopenharmony_ci  mup.adf_page_code = 0x26;
1071141cc406Sopenharmony_ci  mup.adf_parameter_length = 6;
1072141cc406Sopenharmony_ci  if (s->adf_state == ADF_ARMED)
1073141cc406Sopenharmony_ci    mup.adf_control = 1;
1074141cc406Sopenharmony_ci  else
1075141cc406Sopenharmony_ci    mup.adf_control = 0;
1076141cc406Sopenharmony_ci/* end lines by mf */
1077141cc406Sopenharmony_ci
1078141cc406Sopenharmony_ci  status = mode_select (s->fd, (struct mode_pages *) &mup);
1079141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1080141cc406Sopenharmony_ci    {
1081141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SELECT failed\n");
1082141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
1083141cc406Sopenharmony_ci    }
1084141cc406Sopenharmony_ci
1085141cc406Sopenharmony_ci  status = trigger_scan (s->fd);
1086141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1087141cc406Sopenharmony_ci    {
1088141cc406Sopenharmony_ci      DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
1089141cc406Sopenharmony_ci      /* next line introduced not to freeze xscanimage */
1090141cc406Sopenharmony_ci      do_cancel(s);
1091141cc406Sopenharmony_ci      return status;
1092141cc406Sopenharmony_ci    }
1093141cc406Sopenharmony_ci
1094141cc406Sopenharmony_ci  /* Wait for scanner to become ready to transmit data */
1095141cc406Sopenharmony_ci  status = ibm_wait_ready (s);
1096141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1097141cc406Sopenharmony_ci    {
1098141cc406Sopenharmony_ci      DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status));
1099141cc406Sopenharmony_ci      return (status);
1100141cc406Sopenharmony_ci    }
1101141cc406Sopenharmony_ci
1102141cc406Sopenharmony_ci  s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
1103141cc406Sopenharmony_ci
1104141cc406Sopenharmony_ci  DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
1105141cc406Sopenharmony_ci       "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
1106141cc406Sopenharmony_ci       s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
1107141cc406Sopenharmony_ci
1108141cc406Sopenharmony_ci  s->scanning = SANE_TRUE;
1109141cc406Sopenharmony_ci
1110141cc406Sopenharmony_ci  DBG (11, "<< sane_start\n");
1111141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
1112141cc406Sopenharmony_ci}
1113141cc406Sopenharmony_ci
1114141cc406Sopenharmony_ciSANE_Status
1115141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
1116141cc406Sopenharmony_ci           SANE_Int * len)
1117141cc406Sopenharmony_ci{
1118141cc406Sopenharmony_ci  Ibm_Scanner *s = handle;
1119141cc406Sopenharmony_ci  SANE_Status status;
1120141cc406Sopenharmony_ci  size_t nread;
1121141cc406Sopenharmony_ci  DBG (11, ">> sane_read\n");
1122141cc406Sopenharmony_ci
1123141cc406Sopenharmony_ci  *len = 0;
1124141cc406Sopenharmony_ci
1125141cc406Sopenharmony_ci  DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read);
1126141cc406Sopenharmony_ci
1127141cc406Sopenharmony_ci  if (s->bytes_to_read == 0)
1128141cc406Sopenharmony_ci    {
1129141cc406Sopenharmony_ci      do_cancel (s);
1130141cc406Sopenharmony_ci      return (SANE_STATUS_EOF);
1131141cc406Sopenharmony_ci    }
1132141cc406Sopenharmony_ci
1133141cc406Sopenharmony_ci  if (!s->scanning) {
1134141cc406Sopenharmony_ci    DBG (11, "sane_read: scanning is false!\n");
1135141cc406Sopenharmony_ci    return (do_cancel (s));
1136141cc406Sopenharmony_ci  }
1137141cc406Sopenharmony_ci
1138141cc406Sopenharmony_ci  nread = max_len;
1139141cc406Sopenharmony_ci  if (nread > s->bytes_to_read)
1140141cc406Sopenharmony_ci    nread = s->bytes_to_read;
1141141cc406Sopenharmony_ci
1142141cc406Sopenharmony_ci  DBG (11, "sane_read: read %ld bytes\n", (u_long) nread);
1143141cc406Sopenharmony_ci  status = read_data (s->fd, buf, &nread);
1144141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1145141cc406Sopenharmony_ci    {
1146141cc406Sopenharmony_ci      DBG (11, "sane_read: read error\n");
1147141cc406Sopenharmony_ci      do_cancel (s);
1148141cc406Sopenharmony_ci      return (SANE_STATUS_IO_ERROR);
1149141cc406Sopenharmony_ci    }
1150141cc406Sopenharmony_ci  *len = nread;
1151141cc406Sopenharmony_ci  s->bytes_to_read -= nread;
1152141cc406Sopenharmony_ci
1153141cc406Sopenharmony_ci  DBG (11, "<< sane_read\n");
1154141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
1155141cc406Sopenharmony_ci}
1156141cc406Sopenharmony_ci
1157141cc406Sopenharmony_civoid
1158141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
1159141cc406Sopenharmony_ci{
1160141cc406Sopenharmony_ci  Ibm_Scanner *s = handle;
1161141cc406Sopenharmony_ci  DBG (11, ">> sane_cancel\n");
1162141cc406Sopenharmony_ci
1163141cc406Sopenharmony_ci  s->scanning = SANE_FALSE;
1164141cc406Sopenharmony_ci
1165141cc406Sopenharmony_ci  DBG (11, "<< sane_cancel\n");
1166141cc406Sopenharmony_ci}
1167141cc406Sopenharmony_ci
1168141cc406Sopenharmony_ciSANE_Status
1169141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1170141cc406Sopenharmony_ci{
1171141cc406Sopenharmony_ci  DBG (5, ">> sane_set_io_mode (handle = %p, non_blocking = %d)\n",
1172141cc406Sopenharmony_ci       handle, non_blocking);
1173141cc406Sopenharmony_ci  DBG (5, "<< sane_set_io_mode\n");
1174141cc406Sopenharmony_ci
1175141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1176141cc406Sopenharmony_ci}
1177141cc406Sopenharmony_ci
1178141cc406Sopenharmony_ciSANE_Status
1179141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1180141cc406Sopenharmony_ci{
1181141cc406Sopenharmony_ci  DBG (5, ">> sane_get_select_fd (handle = %p, fd = %p)\n",
1182141cc406Sopenharmony_ci       handle, (void *) fd);
1183141cc406Sopenharmony_ci  DBG (5, "<< sane_get_select_fd\n");
1184141cc406Sopenharmony_ci
1185141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1186141cc406Sopenharmony_ci}
1187