1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) 1998, Feico W. Dillema
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 Ricoh flatbed scanners.
42141cc406Sopenharmony_ci*/
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci#include "../include/sane/config.h"
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci#include <limits.h>
47141cc406Sopenharmony_ci#include <stdlib.h>
48141cc406Sopenharmony_ci#include <stdarg.h>
49141cc406Sopenharmony_ci#include <string.h>
50141cc406Sopenharmony_ci#include <time.h>
51141cc406Sopenharmony_ci#include <sys/time.h>
52141cc406Sopenharmony_ci#include <unistd.h>
53141cc406Sopenharmony_ci#include <ctype.h>
54141cc406Sopenharmony_ci
55141cc406Sopenharmony_ci#include "../include/sane/sane.h"
56141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
57141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h"
58141cc406Sopenharmony_ci
59141cc406Sopenharmony_ci#define BACKEND_NAME ricoh
60141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
61141cc406Sopenharmony_ci
62141cc406Sopenharmony_ci#ifndef PATH_MAX
63141cc406Sopenharmony_ci# define PATH_MAX	1024
64141cc406Sopenharmony_ci#endif
65141cc406Sopenharmony_ci
66141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h"
67141cc406Sopenharmony_ci#define RICOH_CONFIG_FILE "ricoh.conf"
68141cc406Sopenharmony_ci
69141cc406Sopenharmony_ci#include "ricoh.h"
70141cc406Sopenharmony_ci
71141cc406Sopenharmony_ci#define MAX(a,b)	((a) > (b) ? (a) : (b))
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_cistatic const SANE_Device **devlist = NULL;
74141cc406Sopenharmony_cistatic int num_devices = 0;
75141cc406Sopenharmony_cistatic Ricoh_Device *first_dev = NULL;
76141cc406Sopenharmony_cistatic Ricoh_Scanner *first_handle = NULL;
77141cc406Sopenharmony_cistatic int is50 = 0;
78141cc406Sopenharmony_ci
79141cc406Sopenharmony_ci#include "ricoh-scsi.c"
80141cc406Sopenharmony_ci
81141cc406Sopenharmony_cistatic size_t
82141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[])
83141cc406Sopenharmony_ci{
84141cc406Sopenharmony_ci  size_t size, max_size = 0;
85141cc406Sopenharmony_ci  int i;
86141cc406Sopenharmony_ci  DBG (11, ">> max_string_size\n");
87141cc406Sopenharmony_ci
88141cc406Sopenharmony_ci  for (i = 0; strings[i]; ++i)
89141cc406Sopenharmony_ci    {
90141cc406Sopenharmony_ci      size = strlen (strings[i]) + 1;
91141cc406Sopenharmony_ci      if (size > max_size)
92141cc406Sopenharmony_ci        max_size = size;
93141cc406Sopenharmony_ci    }
94141cc406Sopenharmony_ci
95141cc406Sopenharmony_ci  DBG (11, "<< max_string_size\n");
96141cc406Sopenharmony_ci  return max_size;
97141cc406Sopenharmony_ci}
98141cc406Sopenharmony_ci
99141cc406Sopenharmony_cistatic SANE_Status
100141cc406Sopenharmony_ciattach (const char *devnam, Ricoh_Device ** devp)
101141cc406Sopenharmony_ci{
102141cc406Sopenharmony_ci  SANE_Status status;
103141cc406Sopenharmony_ci  Ricoh_Device *dev;
104141cc406Sopenharmony_ci
105141cc406Sopenharmony_ci  int fd;
106141cc406Sopenharmony_ci  struct inquiry_data ibuf;
107141cc406Sopenharmony_ci  struct measurements_units_page mup;
108141cc406Sopenharmony_ci  struct ricoh_window_data wbuf;
109141cc406Sopenharmony_ci  size_t buf_size;
110141cc406Sopenharmony_ci  char *str;
111141cc406Sopenharmony_ci  DBG (11, ">> attach\n");
112141cc406Sopenharmony_ci
113141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
114141cc406Sopenharmony_ci    {
115141cc406Sopenharmony_ci      if (strcmp (dev->sane.name, devnam) == 0)
116141cc406Sopenharmony_ci        {
117141cc406Sopenharmony_ci          if (devp)
118141cc406Sopenharmony_ci            *devp = dev;
119141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
120141cc406Sopenharmony_ci        }
121141cc406Sopenharmony_ci    }
122141cc406Sopenharmony_ci
123141cc406Sopenharmony_ci  DBG (3, "attach: opening %s\n", devnam);
124141cc406Sopenharmony_ci  status = sanei_scsi_open (devnam, &fd, NULL, NULL);
125141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
126141cc406Sopenharmony_ci    {
127141cc406Sopenharmony_ci      DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
128141cc406Sopenharmony_ci      return (status);
129141cc406Sopenharmony_ci    }
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci  DBG (3, "attach: sending INQUIRY\n");
132141cc406Sopenharmony_ci  memset (&ibuf, 0, sizeof (ibuf));
133141cc406Sopenharmony_ci  buf_size = sizeof(ibuf);
134141cc406Sopenharmony_ci  status = inquiry (fd, &ibuf, &buf_size);
135141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
136141cc406Sopenharmony_ci    {
137141cc406Sopenharmony_ci      DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status));
138141cc406Sopenharmony_ci      sanei_scsi_close (fd);
139141cc406Sopenharmony_ci      return (status);
140141cc406Sopenharmony_ci    }
141141cc406Sopenharmony_ci
142141cc406Sopenharmony_ci  if (ibuf.devtype != 6
143141cc406Sopenharmony_ci      || strncmp ((char *)ibuf.vendor, "RICOH", 5) != 0
144141cc406Sopenharmony_ci      || (strncmp ((char *)ibuf.product, "IS50", 4) != 0
145141cc406Sopenharmony_ci	  && strncmp ((char *)ibuf.product, "IS60", 4) != 0))
146141cc406Sopenharmony_ci    {
147141cc406Sopenharmony_ci      DBG (1, "attach: device doesn't look like the Ricoh scanner I know\n");
148141cc406Sopenharmony_ci      sanei_scsi_close (fd);
149141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
150141cc406Sopenharmony_ci    }
151141cc406Sopenharmony_ci  is50 = (strncmp ((char *)ibuf.product, "IS50", 4) == 0);
152141cc406Sopenharmony_ci
153141cc406Sopenharmony_ci  DBG (3, "attach: sending TEST_UNIT_READY\n");
154141cc406Sopenharmony_ci  status = test_unit_ready (fd);
155141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
156141cc406Sopenharmony_ci    {
157141cc406Sopenharmony_ci      DBG (1, "attach: test unit ready failed (%s)\n",
158141cc406Sopenharmony_ci           sane_strstatus (status));
159141cc406Sopenharmony_ci      sanei_scsi_close (fd);
160141cc406Sopenharmony_ci      return (status);
161141cc406Sopenharmony_ci    }
162141cc406Sopenharmony_ci
163141cc406Sopenharmony_ci  DBG (3, "attach: sending OBJECT POSITION\n");
164141cc406Sopenharmony_ci  status = object_position (fd);
165141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
166141cc406Sopenharmony_ci    {
167141cc406Sopenharmony_ci      DBG (1, "attach: OBJECT POSITION failed\n");
168141cc406Sopenharmony_ci      sanei_scsi_close (fd);
169141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
170141cc406Sopenharmony_ci    }
171141cc406Sopenharmony_ci
172141cc406Sopenharmony_ci  memset (&mup, 0, sizeof (mup));
173141cc406Sopenharmony_ci  mup.page_code = MEASUREMENTS_PAGE;
174141cc406Sopenharmony_ci  mup.parameter_length = 0x06;
175141cc406Sopenharmony_ci  mup.bmu = INCHES;
176141cc406Sopenharmony_ci  mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
177141cc406Sopenharmony_ci  mup.mud[1] = (DEFAULT_MUD & 0xff);
178141cc406Sopenharmony_ci
179141cc406Sopenharmony_ci#if 0
180141cc406Sopenharmony_ci  DBG (3, "attach: sending MODE SELECT\n");
181141cc406Sopenharmony_ci  status = mode_select (fd, (struct mode_pages *) &mup);
182141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
183141cc406Sopenharmony_ci    {
184141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SELECT failed\n");
185141cc406Sopenharmony_ci      sanei_scsi_close (fd);
186141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
187141cc406Sopenharmony_ci    }
188141cc406Sopenharmony_ci#endif
189141cc406Sopenharmony_ci
190141cc406Sopenharmony_ci#if 0
191141cc406Sopenharmony_ci  DBG (3, "attach: sending MODE SENSE\n");
192141cc406Sopenharmony_ci  memset (&mup, 0, sizeof (mup));
193141cc406Sopenharmony_ci  status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE);
194141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
195141cc406Sopenharmony_ci    {
196141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SENSE failed\n");
197141cc406Sopenharmony_ci      sanei_scsi_close (fd);
198141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
199141cc406Sopenharmony_ci    }
200141cc406Sopenharmony_ci#endif
201141cc406Sopenharmony_ci
202141cc406Sopenharmony_ci  DBG (3, "attach: sending GET WINDOW\n");
203141cc406Sopenharmony_ci  memset (&wbuf, 0, sizeof (wbuf));
204141cc406Sopenharmony_ci  status = get_window (fd, &wbuf);
205141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
206141cc406Sopenharmony_ci    {
207141cc406Sopenharmony_ci      DBG (1, "attach: GET_WINDOW failed %d\n", status);
208141cc406Sopenharmony_ci      sanei_scsi_close (fd);
209141cc406Sopenharmony_ci      DBG (11, "<< attach\n");
210141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
211141cc406Sopenharmony_ci    }
212141cc406Sopenharmony_ci
213141cc406Sopenharmony_ci  sanei_scsi_close (fd);
214141cc406Sopenharmony_ci
215141cc406Sopenharmony_ci  dev = malloc (sizeof (*dev));
216141cc406Sopenharmony_ci  if (!dev)
217141cc406Sopenharmony_ci    return (SANE_STATUS_NO_MEM);
218141cc406Sopenharmony_ci  memset (dev, 0, sizeof (*dev));
219141cc406Sopenharmony_ci
220141cc406Sopenharmony_ci  dev->sane.name = strdup (devnam);
221141cc406Sopenharmony_ci  dev->sane.vendor = "RICOH";
222141cc406Sopenharmony_ci
223141cc406Sopenharmony_ci  size_t prod_rev_size = sizeof(ibuf.product) + sizeof(ibuf.revision) + 1;
224141cc406Sopenharmony_ci  str = malloc (prod_rev_size);
225141cc406Sopenharmony_ci  if (str)
226141cc406Sopenharmony_ci    {
227141cc406Sopenharmony_ci      snprintf (str, prod_rev_size, "%.*s%.*s",
228141cc406Sopenharmony_ci                (int) sizeof(ibuf.product), (const char *) ibuf.product,
229141cc406Sopenharmony_ci                (int) sizeof(ibuf.revision), (const char *) ibuf.revision);
230141cc406Sopenharmony_ci    }
231141cc406Sopenharmony_ci  dev->sane.model = str;
232141cc406Sopenharmony_ci  dev->sane.type = "flatbed scanner";
233141cc406Sopenharmony_ci
234141cc406Sopenharmony_ci  DBG (5, "dev->sane.name = %s\n", dev->sane.name);
235141cc406Sopenharmony_ci  DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor);
236141cc406Sopenharmony_ci  DBG (5, "dev->sane.model = %s\n", dev->sane.model);
237141cc406Sopenharmony_ci  DBG (5, "dev->sane.type = %s\n", dev->sane.type);
238141cc406Sopenharmony_ci
239141cc406Sopenharmony_ci  dev->info.xres_default = _2btol(wbuf.x_res);
240141cc406Sopenharmony_ci  dev->info.yres_default = _2btol(wbuf.y_res);
241141cc406Sopenharmony_ci  dev->info.image_mode_default = wbuf.image_comp;
242141cc406Sopenharmony_ci
243141cc406Sopenharmony_ci  /* if you throw the MRIF bit the brightness control reverses too */
244141cc406Sopenharmony_ci  /* so I reverse the reversal in software for symmetry's sake */
245141cc406Sopenharmony_ci  /* I should make this into an option */
246141cc406Sopenharmony_ci
247141cc406Sopenharmony_ci  if (wbuf.image_comp == RICOH_GRAYSCALE || wbuf.image_comp == RICOH_DITHERED_MONOCHROME)
248141cc406Sopenharmony_ci    {
249141cc406Sopenharmony_ci      dev->info.brightness_default = 256 - wbuf.brightness;
250141cc406Sopenharmony_ci      if (is50)
251141cc406Sopenharmony_ci	dev->info.contrast_default = wbuf.contrast;
252141cc406Sopenharmony_ci      else
253141cc406Sopenharmony_ci	dev->info.contrast_default = 256 - wbuf.contrast;
254141cc406Sopenharmony_ci    }
255141cc406Sopenharmony_ci  else /* wbuf.image_comp == RICOH_BINARY_MONOCHROME */
256141cc406Sopenharmony_ci    {
257141cc406Sopenharmony_ci      dev->info.brightness_default = wbuf.brightness;
258141cc406Sopenharmony_ci      dev->info.contrast_default = wbuf.contrast;
259141cc406Sopenharmony_ci    }
260141cc406Sopenharmony_ci
261141cc406Sopenharmony_ci#if 1
262141cc406Sopenharmony_ci  dev->info.bmu = mup.bmu;
263141cc406Sopenharmony_ci  dev->info.mud = _2btol(mup.mud);
264141cc406Sopenharmony_ci  if (dev->info.mud == 0) {
265141cc406Sopenharmony_ci    /* The RICOH says it uses points as default Basic Measurement Unit */
266141cc406Sopenharmony_ci    /* but gives a Measurement Unit Divisor of zero */
267141cc406Sopenharmony_ci    /* So, we set it to the default (SCSI-standard) of 1200 */
268141cc406Sopenharmony_ci    /* with BMU in inches, i.e. 1200 points equal 1 inch */
269141cc406Sopenharmony_ci    dev->info.bmu = INCHES;
270141cc406Sopenharmony_ci    dev->info.mud = DEFAULT_MUD;
271141cc406Sopenharmony_ci  }
272141cc406Sopenharmony_ci#else
273141cc406Sopenharmony_ci    dev->info.bmu = INCHES;
274141cc406Sopenharmony_ci    dev->info.mud = DEFAULT_MUD;
275141cc406Sopenharmony_ci#endif
276141cc406Sopenharmony_ci
277141cc406Sopenharmony_ci  DBG (5, "xres_default=%d\n", dev->info.xres_default);
278141cc406Sopenharmony_ci  DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max);
279141cc406Sopenharmony_ci  DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min);
280141cc406Sopenharmony_ci
281141cc406Sopenharmony_ci  DBG (5, "yres_default=%d\n", dev->info.yres_default);
282141cc406Sopenharmony_ci  DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max);
283141cc406Sopenharmony_ci  DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min);
284141cc406Sopenharmony_ci
285141cc406Sopenharmony_ci  DBG (5, "x_range.max=%d\n", dev->info.x_range.max);
286141cc406Sopenharmony_ci  DBG (5, "y_range.max=%d\n", dev->info.y_range.max);
287141cc406Sopenharmony_ci
288141cc406Sopenharmony_ci  DBG (5, "image_mode=%d\n", dev->info.image_mode_default);
289141cc406Sopenharmony_ci
290141cc406Sopenharmony_ci  DBG (5, "brightness=%d\n", dev->info.brightness_default);
291141cc406Sopenharmony_ci  DBG (5, "contrast=%d\n", dev->info.contrast_default);
292141cc406Sopenharmony_ci
293141cc406Sopenharmony_ci  DBG (5, "bmu=%d\n", dev->info.bmu);
294141cc406Sopenharmony_ci  DBG (5, "mud=%d\n", dev->info.mud);
295141cc406Sopenharmony_ci
296141cc406Sopenharmony_ci  ++num_devices;
297141cc406Sopenharmony_ci  dev->next = first_dev;
298141cc406Sopenharmony_ci  first_dev = dev;
299141cc406Sopenharmony_ci
300141cc406Sopenharmony_ci  if (devp)
301141cc406Sopenharmony_ci    *devp = dev;
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ci  DBG (11, "<< attach\n");
304141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
305141cc406Sopenharmony_ci}
306141cc406Sopenharmony_ci
307141cc406Sopenharmony_cistatic SANE_Status
308141cc406Sopenharmony_ciattach_one(const char *devnam)
309141cc406Sopenharmony_ci{
310141cc406Sopenharmony_ci  attach (devnam, NULL);
311141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
312141cc406Sopenharmony_ci}
313141cc406Sopenharmony_ci
314141cc406Sopenharmony_cistatic SANE_Status
315141cc406Sopenharmony_ciinit_options (Ricoh_Scanner * s)
316141cc406Sopenharmony_ci{
317141cc406Sopenharmony_ci  int i;
318141cc406Sopenharmony_ci  DBG (11, ">> init_options\n");
319141cc406Sopenharmony_ci
320141cc406Sopenharmony_ci  memset (s->opt, 0, sizeof (s->opt));
321141cc406Sopenharmony_ci  memset (s->val, 0, sizeof (s->val));
322141cc406Sopenharmony_ci
323141cc406Sopenharmony_ci  for (i = 0; i < NUM_OPTIONS; ++i)
324141cc406Sopenharmony_ci    {
325141cc406Sopenharmony_ci      s->opt[i].size = sizeof (SANE_Word);
326141cc406Sopenharmony_ci      s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
327141cc406Sopenharmony_ci    }
328141cc406Sopenharmony_ci
329141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
330141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
331141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
332141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
333141cc406Sopenharmony_ci  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
334141cc406Sopenharmony_ci
335141cc406Sopenharmony_ci  /* "Mode" group: */
336141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].title = "Scan Mode";
337141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].desc = "";
338141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
339141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].cap = 0;
340141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_ci  /* scan mode */
343141cc406Sopenharmony_ci  s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
344141cc406Sopenharmony_ci  s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
345141cc406Sopenharmony_ci  s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
346141cc406Sopenharmony_ci  s->opt[OPT_MODE].type = SANE_TYPE_STRING;
347141cc406Sopenharmony_ci  s->opt[OPT_MODE].size = max_string_size (mode_list);
348141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
349141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint.string_list = mode_list;
350141cc406Sopenharmony_ci  s->val[OPT_MODE].s = strdup (mode_list[s->hw->info.image_mode_default]);
351141cc406Sopenharmony_ci
352141cc406Sopenharmony_ci  /* x resolution */
353141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].name = "X" SANE_NAME_SCAN_RESOLUTION;
354141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].title = "X " SANE_TITLE_SCAN_RESOLUTION;
355141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
356141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
357141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
358141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
359141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint.range = &is60_res_range;
360141cc406Sopenharmony_ci  s->val[OPT_X_RESOLUTION].w = s->hw->info.xres_default;
361141cc406Sopenharmony_ci  if (is50)
362141cc406Sopenharmony_ci    s->opt[OPT_X_RESOLUTION].constraint.range = &is50_res_range;
363141cc406Sopenharmony_ci  else
364141cc406Sopenharmony_ci    s->opt[OPT_X_RESOLUTION].constraint.range = &is60_res_range;
365141cc406Sopenharmony_ci
366141cc406Sopenharmony_ci  /* y resolution */
367141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION;
368141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION;
369141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
370141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
371141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
372141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
373141cc406Sopenharmony_ci  s->val[OPT_Y_RESOLUTION].w =  s->hw->info.yres_default;
374141cc406Sopenharmony_ci  if (is50)
375141cc406Sopenharmony_ci    s->opt[OPT_Y_RESOLUTION].constraint.range = &is50_res_range;
376141cc406Sopenharmony_ci  else
377141cc406Sopenharmony_ci    s->opt[OPT_Y_RESOLUTION].constraint.range = &is60_res_range;
378141cc406Sopenharmony_ci
379141cc406Sopenharmony_ci  /* "Geometry" group: */
380141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
381141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].desc = "";
382141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
383141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
384141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
385141cc406Sopenharmony_ci
386141cc406Sopenharmony_ci  /* top-left x */
387141cc406Sopenharmony_ci  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
388141cc406Sopenharmony_ci  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
389141cc406Sopenharmony_ci  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
390141cc406Sopenharmony_ci  s->opt[OPT_TL_X].type = SANE_TYPE_INT;
391141cc406Sopenharmony_ci  s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
392141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
393141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint.range = &default_x_range;
394141cc406Sopenharmony_ci  s->val[OPT_TL_X].w = 0;
395141cc406Sopenharmony_ci
396141cc406Sopenharmony_ci  /* top-left y */
397141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
398141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
399141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
400141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].type = SANE_TYPE_INT;
401141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
402141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
403141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint.range = &default_y_range;
404141cc406Sopenharmony_ci  s->val[OPT_TL_Y].w = 0;
405141cc406Sopenharmony_ci
406141cc406Sopenharmony_ci  /* bottom-right x */
407141cc406Sopenharmony_ci  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
408141cc406Sopenharmony_ci  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
409141cc406Sopenharmony_ci  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
410141cc406Sopenharmony_ci  s->opt[OPT_BR_X].type = SANE_TYPE_INT;
411141cc406Sopenharmony_ci  s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
412141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
413141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint.range = &default_x_range;
414141cc406Sopenharmony_ci  s->val[OPT_BR_X].w = default_x_range.max;
415141cc406Sopenharmony_ci
416141cc406Sopenharmony_ci  /* bottom-right y */
417141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
418141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
419141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
420141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].type = SANE_TYPE_INT;
421141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
422141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
423141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint.range = &default_y_range;
424141cc406Sopenharmony_ci  s->val[OPT_BR_Y].w = default_y_range.max;
425141cc406Sopenharmony_ci
426141cc406Sopenharmony_ci  /* "Enhancement" group: */
427141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
428141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
429141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
430141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
431141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
432141cc406Sopenharmony_ci
433141cc406Sopenharmony_ci  /* brightness */
434141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
435141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
436141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
437141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
438141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
439141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
440141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range;
441141cc406Sopenharmony_ci  s->val[OPT_BRIGHTNESS].w =  s->hw->info.brightness_default;
442141cc406Sopenharmony_ci
443141cc406Sopenharmony_ci  /* contrast */
444141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
445141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
446141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
447141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
448141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
449141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
450141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].constraint.range = &u8_range;
451141cc406Sopenharmony_ci  s->val[OPT_CONTRAST].w =  s->hw->info.contrast_default;
452141cc406Sopenharmony_ci
453141cc406Sopenharmony_ci  DBG (11, "<< init_options\n");
454141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
455141cc406Sopenharmony_ci}
456141cc406Sopenharmony_ci
457141cc406Sopenharmony_cistatic SANE_Status
458141cc406Sopenharmony_cido_cancel (Ricoh_Scanner * s)
459141cc406Sopenharmony_ci{
460141cc406Sopenharmony_ci  SANE_Status status;
461141cc406Sopenharmony_ci  DBG (11, ">> do_cancel\n");
462141cc406Sopenharmony_ci
463141cc406Sopenharmony_ci  DBG (3, "cancel: sending OBJECT POSITION\n");
464141cc406Sopenharmony_ci  status = object_position (s->fd);
465141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
466141cc406Sopenharmony_ci    {
467141cc406Sopenharmony_ci      DBG (1, "cancel: OBJECT POSITION failed\n");
468141cc406Sopenharmony_ci    }
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_ci  s->scanning = SANE_FALSE;
471141cc406Sopenharmony_ci
472141cc406Sopenharmony_ci  if (s->fd >= 0)
473141cc406Sopenharmony_ci    {
474141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
475141cc406Sopenharmony_ci      s->fd = -1;
476141cc406Sopenharmony_ci    }
477141cc406Sopenharmony_ci
478141cc406Sopenharmony_ci  DBG (11, "<< do_cancel\n");
479141cc406Sopenharmony_ci  return (SANE_STATUS_CANCELLED);
480141cc406Sopenharmony_ci}
481141cc406Sopenharmony_ci
482141cc406Sopenharmony_ciSANE_Status
483141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
484141cc406Sopenharmony_ci{
485141cc406Sopenharmony_ci  char devnam[PATH_MAX] = "/dev/scanner";
486141cc406Sopenharmony_ci  FILE *fp;
487141cc406Sopenharmony_ci
488141cc406Sopenharmony_ci  (void) authorize;		/* silence gcc */
489141cc406Sopenharmony_ci
490141cc406Sopenharmony_ci  DBG_INIT ();
491141cc406Sopenharmony_ci  DBG (11, ">> sane_init\n");
492141cc406Sopenharmony_ci
493141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION
494141cc406Sopenharmony_ci  DBG (2, "sane_init: " PACKAGE " " VERSION "\n");
495141cc406Sopenharmony_ci#endif
496141cc406Sopenharmony_ci
497141cc406Sopenharmony_ci  if (version_code)
498141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
499141cc406Sopenharmony_ci
500141cc406Sopenharmony_ci  fp = sanei_config_open(RICOH_CONFIG_FILE);
501141cc406Sopenharmony_ci  if (fp)
502141cc406Sopenharmony_ci    {
503141cc406Sopenharmony_ci      char line[PATH_MAX], *lp;
504141cc406Sopenharmony_ci      size_t len;
505141cc406Sopenharmony_ci
506141cc406Sopenharmony_ci      /* read config file */
507141cc406Sopenharmony_ci      while (sanei_config_read (line, sizeof (line), fp))
508141cc406Sopenharmony_ci        {
509141cc406Sopenharmony_ci          if (line[0] == '#')           /* ignore line comments */
510141cc406Sopenharmony_ci            continue;
511141cc406Sopenharmony_ci          len = strlen (line);
512141cc406Sopenharmony_ci
513141cc406Sopenharmony_ci          if (!len)
514141cc406Sopenharmony_ci            continue;                   /* ignore empty lines */
515141cc406Sopenharmony_ci
516141cc406Sopenharmony_ci	  /* skip white space: */
517141cc406Sopenharmony_ci	  for (lp = line; isspace(*lp); ++lp)
518141cc406Sopenharmony_ci            ;
519141cc406Sopenharmony_ci          strcpy (devnam, lp);
520141cc406Sopenharmony_ci        }
521141cc406Sopenharmony_ci      fclose (fp);
522141cc406Sopenharmony_ci    }
523141cc406Sopenharmony_ci  sanei_config_attach_matching_devices (devnam, attach_one);
524141cc406Sopenharmony_ci  DBG (11, "<< sane_init\n");
525141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
526141cc406Sopenharmony_ci}
527141cc406Sopenharmony_ci
528141cc406Sopenharmony_civoid
529141cc406Sopenharmony_cisane_exit (void)
530141cc406Sopenharmony_ci{
531141cc406Sopenharmony_ci  Ricoh_Device *dev, *next;
532141cc406Sopenharmony_ci  DBG (11, ">> sane_exit\n");
533141cc406Sopenharmony_ci
534141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = next)
535141cc406Sopenharmony_ci    {
536141cc406Sopenharmony_ci      next = dev->next;
537141cc406Sopenharmony_ci      free ((void *) dev->sane.name);
538141cc406Sopenharmony_ci      free ((void *) dev->sane.model);
539141cc406Sopenharmony_ci      free (dev);
540141cc406Sopenharmony_ci    }
541141cc406Sopenharmony_ci
542141cc406Sopenharmony_ci  if (devlist)
543141cc406Sopenharmony_ci    free (devlist);
544141cc406Sopenharmony_ci
545141cc406Sopenharmony_ci  DBG (11, "<< sane_exit\n");
546141cc406Sopenharmony_ci}
547141cc406Sopenharmony_ci
548141cc406Sopenharmony_ciSANE_Status
549141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
550141cc406Sopenharmony_ci{
551141cc406Sopenharmony_ci  Ricoh_Device *dev;
552141cc406Sopenharmony_ci  int i;
553141cc406Sopenharmony_ci
554141cc406Sopenharmony_ci  (void) local_only;		/* silence gcc */
555141cc406Sopenharmony_ci
556141cc406Sopenharmony_ci  DBG (11, ">> sane_get_devices\n");
557141cc406Sopenharmony_ci
558141cc406Sopenharmony_ci  if (devlist)
559141cc406Sopenharmony_ci    free (devlist);
560141cc406Sopenharmony_ci  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
561141cc406Sopenharmony_ci  if (!devlist)
562141cc406Sopenharmony_ci    return (SANE_STATUS_NO_MEM);
563141cc406Sopenharmony_ci
564141cc406Sopenharmony_ci  i = 0;
565141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
566141cc406Sopenharmony_ci    devlist[i++] = &dev->sane;
567141cc406Sopenharmony_ci  devlist[i++] = 0;
568141cc406Sopenharmony_ci
569141cc406Sopenharmony_ci  *device_list = devlist;
570141cc406Sopenharmony_ci
571141cc406Sopenharmony_ci  DBG (11, "<< sane_get_devices\n");
572141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
573141cc406Sopenharmony_ci}
574141cc406Sopenharmony_ci
575141cc406Sopenharmony_ciSANE_Status
576141cc406Sopenharmony_cisane_open (SANE_String_Const devnam, SANE_Handle * handle)
577141cc406Sopenharmony_ci{
578141cc406Sopenharmony_ci  SANE_Status status;
579141cc406Sopenharmony_ci  Ricoh_Device *dev;
580141cc406Sopenharmony_ci  Ricoh_Scanner *s;
581141cc406Sopenharmony_ci  DBG (11, ">> sane_open\n");
582141cc406Sopenharmony_ci
583141cc406Sopenharmony_ci  if (devnam[0] == '\0')
584141cc406Sopenharmony_ci    {
585141cc406Sopenharmony_ci      for (dev = first_dev; dev; dev = dev->next)
586141cc406Sopenharmony_ci        {
587141cc406Sopenharmony_ci          if (strcmp (dev->sane.name, devnam) == 0)
588141cc406Sopenharmony_ci            break;
589141cc406Sopenharmony_ci        }
590141cc406Sopenharmony_ci
591141cc406Sopenharmony_ci      if (!dev)
592141cc406Sopenharmony_ci        {
593141cc406Sopenharmony_ci          status = attach (devnam, &dev);
594141cc406Sopenharmony_ci          if (status != SANE_STATUS_GOOD)
595141cc406Sopenharmony_ci            return (status);
596141cc406Sopenharmony_ci        }
597141cc406Sopenharmony_ci    }
598141cc406Sopenharmony_ci  else
599141cc406Sopenharmony_ci    {
600141cc406Sopenharmony_ci      dev = first_dev;
601141cc406Sopenharmony_ci    }
602141cc406Sopenharmony_ci
603141cc406Sopenharmony_ci  if (!dev)
604141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
605141cc406Sopenharmony_ci
606141cc406Sopenharmony_ci  s = malloc (sizeof (*s));
607141cc406Sopenharmony_ci  if (!s)
608141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
609141cc406Sopenharmony_ci  memset (s, 0, sizeof (*s));
610141cc406Sopenharmony_ci
611141cc406Sopenharmony_ci  s->fd = -1;
612141cc406Sopenharmony_ci  s->hw = dev;
613141cc406Sopenharmony_ci
614141cc406Sopenharmony_ci  init_options (s);
615141cc406Sopenharmony_ci
616141cc406Sopenharmony_ci  s->next = first_handle;
617141cc406Sopenharmony_ci  first_handle = s;
618141cc406Sopenharmony_ci
619141cc406Sopenharmony_ci  *handle = s;
620141cc406Sopenharmony_ci
621141cc406Sopenharmony_ci  DBG (11, "<< sane_open\n");
622141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
623141cc406Sopenharmony_ci}
624141cc406Sopenharmony_ci
625141cc406Sopenharmony_civoid
626141cc406Sopenharmony_cisane_close (SANE_Handle handle)
627141cc406Sopenharmony_ci{
628141cc406Sopenharmony_ci  Ricoh_Scanner *s = (Ricoh_Scanner *) handle;
629141cc406Sopenharmony_ci  DBG (11, ">> sane_close\n");
630141cc406Sopenharmony_ci
631141cc406Sopenharmony_ci  if (s->fd != -1)
632141cc406Sopenharmony_ci    sanei_scsi_close (s->fd);
633141cc406Sopenharmony_ci  free (s);
634141cc406Sopenharmony_ci
635141cc406Sopenharmony_ci  DBG (11, ">> sane_close\n");
636141cc406Sopenharmony_ci}
637141cc406Sopenharmony_ci
638141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
639141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
640141cc406Sopenharmony_ci{
641141cc406Sopenharmony_ci  Ricoh_Scanner *s = handle;
642141cc406Sopenharmony_ci  DBG (11, ">> sane_get_option_descriptor\n");
643141cc406Sopenharmony_ci
644141cc406Sopenharmony_ci  if ((unsigned) option >= NUM_OPTIONS)
645141cc406Sopenharmony_ci    return (0);
646141cc406Sopenharmony_ci
647141cc406Sopenharmony_ci  DBG (11, "<< sane_get_option_descriptor\n");
648141cc406Sopenharmony_ci  return (s->opt + option);
649141cc406Sopenharmony_ci}
650141cc406Sopenharmony_ci
651141cc406Sopenharmony_ciSANE_Status
652141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
653141cc406Sopenharmony_ci                     SANE_Action action, void *val, SANE_Int * info)
654141cc406Sopenharmony_ci{
655141cc406Sopenharmony_ci  Ricoh_Scanner *s = handle;
656141cc406Sopenharmony_ci  SANE_Status status;
657141cc406Sopenharmony_ci  SANE_Word cap;
658141cc406Sopenharmony_ci  DBG (11, ">> sane_control_option\n");
659141cc406Sopenharmony_ci
660141cc406Sopenharmony_ci  if (info)
661141cc406Sopenharmony_ci    *info = 0;
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  if (s->scanning)
664141cc406Sopenharmony_ci    return (SANE_STATUS_DEVICE_BUSY);
665141cc406Sopenharmony_ci  if (option >= NUM_OPTIONS)
666141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
667141cc406Sopenharmony_ci
668141cc406Sopenharmony_ci  cap = s->opt[option].cap;
669141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (cap))
670141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
671141cc406Sopenharmony_ci
672141cc406Sopenharmony_ci  if (action == SANE_ACTION_GET_VALUE)
673141cc406Sopenharmony_ci    {
674141cc406Sopenharmony_ci      switch (option)
675141cc406Sopenharmony_ci        {
676141cc406Sopenharmony_ci          /* word options: */
677141cc406Sopenharmony_ci        case OPT_X_RESOLUTION:
678141cc406Sopenharmony_ci        case OPT_Y_RESOLUTION:
679141cc406Sopenharmony_ci        case OPT_TL_X:
680141cc406Sopenharmony_ci        case OPT_TL_Y:
681141cc406Sopenharmony_ci        case OPT_BR_X:
682141cc406Sopenharmony_ci        case OPT_BR_Y:
683141cc406Sopenharmony_ci        case OPT_NUM_OPTS:
684141cc406Sopenharmony_ci        case OPT_BRIGHTNESS:
685141cc406Sopenharmony_ci        case OPT_CONTRAST:
686141cc406Sopenharmony_ci          *(SANE_Word *) val = s->val[option].w;
687141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
688141cc406Sopenharmony_ci
689141cc406Sopenharmony_ci          /* string options: */
690141cc406Sopenharmony_ci        case OPT_MODE:
691141cc406Sopenharmony_ci          strcpy (val, s->val[option].s);
692141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
693141cc406Sopenharmony_ci        }
694141cc406Sopenharmony_ci    }
695141cc406Sopenharmony_ci  else if (action == SANE_ACTION_SET_VALUE)
696141cc406Sopenharmony_ci    {
697141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (cap))
698141cc406Sopenharmony_ci        return (SANE_STATUS_INVAL);
699141cc406Sopenharmony_ci
700141cc406Sopenharmony_ci      status = sanei_constrain_value (s->opt + option, val, info);
701141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
702141cc406Sopenharmony_ci        return status;
703141cc406Sopenharmony_ci
704141cc406Sopenharmony_ci      switch (option)
705141cc406Sopenharmony_ci        {
706141cc406Sopenharmony_ci          /* (mostly) side-effect-free word options: */
707141cc406Sopenharmony_ci        case OPT_X_RESOLUTION:
708141cc406Sopenharmony_ci        case OPT_Y_RESOLUTION:
709141cc406Sopenharmony_ci        case OPT_TL_X:
710141cc406Sopenharmony_ci        case OPT_TL_Y:
711141cc406Sopenharmony_ci        case OPT_BR_X:
712141cc406Sopenharmony_ci        case OPT_BR_Y:
713141cc406Sopenharmony_ci          if (info && s->val[option].w != *(SANE_Word *) val)
714141cc406Sopenharmony_ci            *info |= SANE_INFO_RELOAD_PARAMS;
715141cc406Sopenharmony_ci          /* fall through */
716141cc406Sopenharmony_ci        case OPT_NUM_OPTS:
717141cc406Sopenharmony_ci        case OPT_BRIGHTNESS:
718141cc406Sopenharmony_ci        case OPT_CONTRAST:
719141cc406Sopenharmony_ci          s->val[option].w = *(SANE_Word *) val;
720141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
721141cc406Sopenharmony_ci
722141cc406Sopenharmony_ci        case OPT_MODE:
723141cc406Sopenharmony_ci          if (info && strcmp (s->val[option].s, (SANE_String) val))
724141cc406Sopenharmony_ci            *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
725141cc406Sopenharmony_ci          if (s->val[option].s)
726141cc406Sopenharmony_ci            free (s->val[option].s);
727141cc406Sopenharmony_ci          s->val[option].s = strdup (val);
728141cc406Sopenharmony_ci          return (SANE_STATUS_GOOD);
729141cc406Sopenharmony_ci        }
730141cc406Sopenharmony_ci    }
731141cc406Sopenharmony_ci
732141cc406Sopenharmony_ci  DBG (11, "<< sane_control_option\n");
733141cc406Sopenharmony_ci  return (SANE_STATUS_INVAL);
734141cc406Sopenharmony_ci}
735141cc406Sopenharmony_ci
736141cc406Sopenharmony_ciSANE_Status
737141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
738141cc406Sopenharmony_ci{
739141cc406Sopenharmony_ci  Ricoh_Scanner *s = handle;
740141cc406Sopenharmony_ci  DBG (11, ">> sane_get_parameters\n");
741141cc406Sopenharmony_ci
742141cc406Sopenharmony_ci  if (!s->scanning)
743141cc406Sopenharmony_ci    {
744141cc406Sopenharmony_ci      int width, length, xres, yres;
745141cc406Sopenharmony_ci      const char *mode;
746141cc406Sopenharmony_ci
747141cc406Sopenharmony_ci      memset (&s->params, 0, sizeof (s->params));
748141cc406Sopenharmony_ci
749141cc406Sopenharmony_ci      width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
750141cc406Sopenharmony_ci      length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
751141cc406Sopenharmony_ci      xres = s->val[OPT_X_RESOLUTION].w;
752141cc406Sopenharmony_ci      yres = s->val[OPT_Y_RESOLUTION].w;
753141cc406Sopenharmony_ci
754141cc406Sopenharmony_ci      /* make best-effort guess at what parameters will look like once
755141cc406Sopenharmony_ci         scanning starts.  */
756141cc406Sopenharmony_ci      if (xres > 0 && yres > 0 && width > 0 && length > 0)
757141cc406Sopenharmony_ci        {
758141cc406Sopenharmony_ci          s->params.pixels_per_line = width * xres / s->hw->info.mud;
759141cc406Sopenharmony_ci          s->params.lines = length * yres / s->hw->info.mud;
760141cc406Sopenharmony_ci        }
761141cc406Sopenharmony_ci
762141cc406Sopenharmony_ci      mode = s->val[OPT_MODE].s;
763141cc406Sopenharmony_ci      if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0 || strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
764141cc406Sopenharmony_ci        {
765141cc406Sopenharmony_ci          s->params.format = SANE_FRAME_GRAY;
766141cc406Sopenharmony_ci          s->params.bytes_per_line = s->params.pixels_per_line / 8;
767141cc406Sopenharmony_ci	  /* the Ricoh truncates to the byte boundary, so: chop! */
768141cc406Sopenharmony_ci          s->params.pixels_per_line = s->params.bytes_per_line * 8;
769141cc406Sopenharmony_ci          s->params.depth = 1;
770141cc406Sopenharmony_ci        }
771141cc406Sopenharmony_ci      else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */
772141cc406Sopenharmony_ci        {
773141cc406Sopenharmony_ci          s->params.format = SANE_FRAME_GRAY;
774141cc406Sopenharmony_ci          s->params.bytes_per_line = s->params.pixels_per_line;
775141cc406Sopenharmony_ci          s->params.depth = 8;
776141cc406Sopenharmony_ci        }
777141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
778141cc406Sopenharmony_ci    }
779141cc406Sopenharmony_ci
780141cc406Sopenharmony_ci  if (params)
781141cc406Sopenharmony_ci    *params = s->params;
782141cc406Sopenharmony_ci
783141cc406Sopenharmony_ci  DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
784141cc406Sopenharmony_ci       "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
785141cc406Sopenharmony_ci       s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
786141cc406Sopenharmony_ci
787141cc406Sopenharmony_ci  DBG (11, "<< sane_get_parameters\n");
788141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
789141cc406Sopenharmony_ci}
790141cc406Sopenharmony_ci
791141cc406Sopenharmony_ci
792141cc406Sopenharmony_ciSANE_Status
793141cc406Sopenharmony_cisane_start (SANE_Handle handle)
794141cc406Sopenharmony_ci{
795141cc406Sopenharmony_ci  char *mode_str;
796141cc406Sopenharmony_ci  Ricoh_Scanner *s = handle;
797141cc406Sopenharmony_ci  SANE_Status status;
798141cc406Sopenharmony_ci  struct ricoh_window_data wbuf;
799141cc406Sopenharmony_ci  struct measurements_units_page mup;
800141cc406Sopenharmony_ci
801141cc406Sopenharmony_ci  DBG (11, ">> sane_start\n");
802141cc406Sopenharmony_ci
803141cc406Sopenharmony_ci  /* First make sure we have a current parameter set.  Some of the
804141cc406Sopenharmony_ci     parameters will be overwritten below, but that's OK.  */
805141cc406Sopenharmony_ci  status = sane_get_parameters (s, 0);
806141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
807141cc406Sopenharmony_ci    return status;
808141cc406Sopenharmony_ci
809141cc406Sopenharmony_ci  status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
810141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
811141cc406Sopenharmony_ci    {
812141cc406Sopenharmony_ci      DBG (1, "open of %s failed: %s\n",
813141cc406Sopenharmony_ci           s->hw->sane.name, sane_strstatus (status));
814141cc406Sopenharmony_ci      return (status);
815141cc406Sopenharmony_ci    }
816141cc406Sopenharmony_ci
817141cc406Sopenharmony_ci  mode_str = s->val[OPT_MODE].s;
818141cc406Sopenharmony_ci  s->xres = s->val[OPT_X_RESOLUTION].w;
819141cc406Sopenharmony_ci  s->yres = s->val[OPT_Y_RESOLUTION].w;
820141cc406Sopenharmony_ci  s->ulx = s->val[OPT_TL_X].w;
821141cc406Sopenharmony_ci  s->uly = s->val[OPT_TL_Y].w;
822141cc406Sopenharmony_ci  s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
823141cc406Sopenharmony_ci  s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
824141cc406Sopenharmony_ci  s->brightness = s->val[OPT_BRIGHTNESS].w;
825141cc406Sopenharmony_ci  s->contrast = s->val[OPT_CONTRAST].w;
826141cc406Sopenharmony_ci  s->bpp = s->params.depth;
827141cc406Sopenharmony_ci  if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0)
828141cc406Sopenharmony_ci    {
829141cc406Sopenharmony_ci      s->image_composition = RICOH_BINARY_MONOCHROME;
830141cc406Sopenharmony_ci    }
831141cc406Sopenharmony_ci  else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
832141cc406Sopenharmony_ci    {
833141cc406Sopenharmony_ci      s->image_composition = RICOH_DITHERED_MONOCHROME;
834141cc406Sopenharmony_ci    }
835141cc406Sopenharmony_ci  else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0)
836141cc406Sopenharmony_ci    {
837141cc406Sopenharmony_ci      s->image_composition = RICOH_GRAYSCALE;
838141cc406Sopenharmony_ci    }
839141cc406Sopenharmony_ci
840141cc406Sopenharmony_ci  memset (&wbuf, 0, sizeof (wbuf));
841141cc406Sopenharmony_ci  _lto2b(sizeof(wbuf) - 8, wbuf.len);
842141cc406Sopenharmony_ci  _lto2b(s->xres, wbuf.x_res);
843141cc406Sopenharmony_ci  _lto2b(s->yres, wbuf.y_res);
844141cc406Sopenharmony_ci  _lto4b(s->ulx, wbuf.x_org);
845141cc406Sopenharmony_ci  _lto4b(s->uly, wbuf.y_org);
846141cc406Sopenharmony_ci  _lto4b(s->width, wbuf.width);
847141cc406Sopenharmony_ci  _lto4b(s->length, wbuf.length);
848141cc406Sopenharmony_ci
849141cc406Sopenharmony_ci  wbuf.image_comp = s->image_composition;
850141cc406Sopenharmony_ci  /* if you throw the MRIF bit the brightness control reverses too */
851141cc406Sopenharmony_ci  /* so I reverse the reversal in software for symmetry's sake */
852141cc406Sopenharmony_ci  if (wbuf.image_comp == RICOH_GRAYSCALE || wbuf.image_comp == RICOH_DITHERED_MONOCHROME)
853141cc406Sopenharmony_ci    {
854141cc406Sopenharmony_ci      if (wbuf.image_comp == RICOH_GRAYSCALE)
855141cc406Sopenharmony_ci	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x90;
856141cc406Sopenharmony_ci      if (wbuf.image_comp == RICOH_DITHERED_MONOCHROME)
857141cc406Sopenharmony_ci	wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10;
858141cc406Sopenharmony_ci      wbuf.brightness = 256 - (SANE_Byte) s->brightness;
859141cc406Sopenharmony_ci      if (is50)
860141cc406Sopenharmony_ci        wbuf.contrast = (SANE_Byte) s->contrast;
861141cc406Sopenharmony_ci      else
862141cc406Sopenharmony_ci        wbuf.contrast = 256 - (SANE_Byte) s->contrast;
863141cc406Sopenharmony_ci    }
864141cc406Sopenharmony_ci  else /* wbuf.image_comp == RICOH_BINARY_MONOCHROME */
865141cc406Sopenharmony_ci    {
866141cc406Sopenharmony_ci      wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00;
867141cc406Sopenharmony_ci      wbuf.brightness = (SANE_Byte) s->brightness;
868141cc406Sopenharmony_ci      wbuf.contrast = (SANE_Byte) s->contrast;
869141cc406Sopenharmony_ci    }
870141cc406Sopenharmony_ci
871141cc406Sopenharmony_ci  wbuf.threshold = 0;
872141cc406Sopenharmony_ci  wbuf.bits_per_pixel = s->bpp;
873141cc406Sopenharmony_ci
874141cc406Sopenharmony_ci  wbuf.halftone_pattern[0] = 2;
875141cc406Sopenharmony_ci  wbuf.halftone_pattern[1] = 0;
876141cc406Sopenharmony_ci  wbuf.pad_type = 3;
877141cc406Sopenharmony_ci  wbuf.bit_ordering[0] = 0;
878141cc406Sopenharmony_ci  wbuf.bit_ordering[1] = 3;
879141cc406Sopenharmony_ci
880141cc406Sopenharmony_ci  DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
881141cc406Sopenharmony_ci  DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
882141cc406Sopenharmony_ci  DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
883141cc406Sopenharmony_ci  DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
884141cc406Sopenharmony_ci  DBG (5, "width=%d\n", _4btol(wbuf.width));
885141cc406Sopenharmony_ci  DBG (5, "length=%d\n", _4btol(wbuf.length));
886141cc406Sopenharmony_ci  DBG (5, "image_comp=%d\n", wbuf.image_comp);
887141cc406Sopenharmony_ci
888141cc406Sopenharmony_ci  DBG (11, "sane_start: sending SET WINDOW\n");
889141cc406Sopenharmony_ci  status = set_window (s->fd, &wbuf);
890141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
891141cc406Sopenharmony_ci    {
892141cc406Sopenharmony_ci      DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
893141cc406Sopenharmony_ci      return (status);
894141cc406Sopenharmony_ci    }
895141cc406Sopenharmony_ci
896141cc406Sopenharmony_ci  DBG (11, "sane_start: sending GET WINDOW\n");
897141cc406Sopenharmony_ci  memset (&wbuf, 0, sizeof (wbuf));
898141cc406Sopenharmony_ci  status = get_window (s->fd, &wbuf);
899141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
900141cc406Sopenharmony_ci    {
901141cc406Sopenharmony_ci      DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
902141cc406Sopenharmony_ci      return (status);
903141cc406Sopenharmony_ci    }
904141cc406Sopenharmony_ci  DBG (5, "xres=%d\n", _2btol(wbuf.x_res));
905141cc406Sopenharmony_ci  DBG (5, "yres=%d\n", _2btol(wbuf.y_res));
906141cc406Sopenharmony_ci  DBG (5, "ulx=%d\n", _4btol(wbuf.x_org));
907141cc406Sopenharmony_ci  DBG (5, "uly=%d\n", _4btol(wbuf.y_org));
908141cc406Sopenharmony_ci  DBG (5, "width=%d\n", _4btol(wbuf.width));
909141cc406Sopenharmony_ci  DBG (5, "length=%d\n", _4btol(wbuf.length));
910141cc406Sopenharmony_ci  DBG (5, "image_comp=%d\n", wbuf.image_comp);
911141cc406Sopenharmony_ci
912141cc406Sopenharmony_ci  DBG (11, "sane_start: sending MODE SELECT\n");
913141cc406Sopenharmony_ci  memset (&mup, 0, sizeof (mup));
914141cc406Sopenharmony_ci  mup.page_code = MEASUREMENTS_PAGE;
915141cc406Sopenharmony_ci  mup.parameter_length = 0x06;
916141cc406Sopenharmony_ci  mup.bmu = INCHES;
917141cc406Sopenharmony_ci  mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff;
918141cc406Sopenharmony_ci  mup.mud[1] = (DEFAULT_MUD & 0xff);
919141cc406Sopenharmony_ci
920141cc406Sopenharmony_ci  status = mode_select (s->fd, (struct mode_pages *) &mup);
921141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
922141cc406Sopenharmony_ci    {
923141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SELECT failed\n");
924141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
925141cc406Sopenharmony_ci    }
926141cc406Sopenharmony_ci
927141cc406Sopenharmony_ci  status = trigger_scan (s->fd);
928141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
929141cc406Sopenharmony_ci    {
930141cc406Sopenharmony_ci      DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
931141cc406Sopenharmony_ci      return (status);
932141cc406Sopenharmony_ci    }
933141cc406Sopenharmony_ci
934141cc406Sopenharmony_ci  /* Wait for scanner to become ready to transmit data */
935141cc406Sopenharmony_ci  status = ricoh_wait_ready (s);
936141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
937141cc406Sopenharmony_ci    {
938141cc406Sopenharmony_ci      DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status));
939141cc406Sopenharmony_ci      return (status);
940141cc406Sopenharmony_ci    }
941141cc406Sopenharmony_ci
942141cc406Sopenharmony_ci  s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
943141cc406Sopenharmony_ci
944141cc406Sopenharmony_ci  DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
945141cc406Sopenharmony_ci       "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
946141cc406Sopenharmony_ci       s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w);
947141cc406Sopenharmony_ci
948141cc406Sopenharmony_ci  s->scanning = SANE_TRUE;
949141cc406Sopenharmony_ci
950141cc406Sopenharmony_ci  DBG (11, "<< sane_start\n");
951141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
952141cc406Sopenharmony_ci}
953141cc406Sopenharmony_ci
954141cc406Sopenharmony_ciSANE_Status
955141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
956141cc406Sopenharmony_ci           SANE_Int * len)
957141cc406Sopenharmony_ci{
958141cc406Sopenharmony_ci  Ricoh_Scanner *s = handle;
959141cc406Sopenharmony_ci  SANE_Status status;
960141cc406Sopenharmony_ci  size_t nread;
961141cc406Sopenharmony_ci  DBG (11, ">> sane_read\n");
962141cc406Sopenharmony_ci
963141cc406Sopenharmony_ci  *len = 0;
964141cc406Sopenharmony_ci
965141cc406Sopenharmony_ci  DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read);
966141cc406Sopenharmony_ci
967141cc406Sopenharmony_ci  if (s->bytes_to_read == 0)
968141cc406Sopenharmony_ci    {
969141cc406Sopenharmony_ci      do_cancel (s);
970141cc406Sopenharmony_ci      return (SANE_STATUS_EOF);
971141cc406Sopenharmony_ci    }
972141cc406Sopenharmony_ci
973141cc406Sopenharmony_ci  if (!s->scanning) {
974141cc406Sopenharmony_ci    DBG (11, "sane_read: scanning is false!\n");
975141cc406Sopenharmony_ci    return (do_cancel (s));
976141cc406Sopenharmony_ci  }
977141cc406Sopenharmony_ci
978141cc406Sopenharmony_ci  nread = max_len;
979141cc406Sopenharmony_ci  if (nread > s->bytes_to_read)
980141cc406Sopenharmony_ci    nread = s->bytes_to_read;
981141cc406Sopenharmony_ci
982141cc406Sopenharmony_ci  DBG (11, "sane_read: read %ld bytes\n", (u_long) nread);
983141cc406Sopenharmony_ci  status = read_data (s->fd, buf, &nread);
984141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
985141cc406Sopenharmony_ci    {
986141cc406Sopenharmony_ci      DBG (11, "sane_read: read error\n");
987141cc406Sopenharmony_ci      do_cancel (s);
988141cc406Sopenharmony_ci      return (SANE_STATUS_IO_ERROR);
989141cc406Sopenharmony_ci    }
990141cc406Sopenharmony_ci  *len = nread;
991141cc406Sopenharmony_ci  s->bytes_to_read -= nread;
992141cc406Sopenharmony_ci
993141cc406Sopenharmony_ci  DBG (11, "<< sane_read\n");
994141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
995141cc406Sopenharmony_ci}
996141cc406Sopenharmony_ci
997141cc406Sopenharmony_civoid
998141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
999141cc406Sopenharmony_ci{
1000141cc406Sopenharmony_ci  Ricoh_Scanner *s = handle;
1001141cc406Sopenharmony_ci  DBG (11, ">> sane_cancel\n");
1002141cc406Sopenharmony_ci
1003141cc406Sopenharmony_ci  s->scanning = SANE_FALSE;
1004141cc406Sopenharmony_ci
1005141cc406Sopenharmony_ci  DBG (11, "<< sane_cancel\n");
1006141cc406Sopenharmony_ci}
1007141cc406Sopenharmony_ci
1008141cc406Sopenharmony_ciSANE_Status
1009141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1010141cc406Sopenharmony_ci{
1011141cc406Sopenharmony_ci  (void) handle;		/* silence gcc */
1012141cc406Sopenharmony_ci  (void) non_blocking;		/* silence gcc */
1013141cc406Sopenharmony_ci
1014141cc406Sopenharmony_ci  DBG (5, ">> sane_set_io_mode\n");
1015141cc406Sopenharmony_ci  DBG (5, "<< sane_set_io_mode\n");
1016141cc406Sopenharmony_ci
1017141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1018141cc406Sopenharmony_ci}
1019141cc406Sopenharmony_ci
1020141cc406Sopenharmony_ciSANE_Status
1021141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1022141cc406Sopenharmony_ci{
1023141cc406Sopenharmony_ci  (void) handle;		/* silence gcc */
1024141cc406Sopenharmony_ci  (void) fd;			/* silence gcc */
1025141cc406Sopenharmony_ci
1026141cc406Sopenharmony_ci  DBG (5, ">> sane_get_select_fd\n");
1027141cc406Sopenharmony_ci  DBG (5, "<< sane_get_select_fd\n");
1028141cc406Sopenharmony_ci
1029141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1030141cc406Sopenharmony_ci}
1031