1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   Copyright (C) 1998 Milon Firikis based on David Mosberger-Tang previous
4141cc406Sopenharmony_ci   Work on mustek.c file from the SANE package.
5141cc406Sopenharmony_ci
6141cc406Sopenharmony_ci   This file is part of the SANE package.
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
9141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
10141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
11141cc406Sopenharmony_ci   License, or (at your option) any later version.
12141cc406Sopenharmony_ci
13141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
14141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
15141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16141cc406Sopenharmony_ci   General Public License for more details.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
19141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
22141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
23141cc406Sopenharmony_ci
24141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
25141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
26141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
27141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
28141cc406Sopenharmony_ci   account of linking the SANE library code into it.
29141cc406Sopenharmony_ci
30141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
31141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
32141cc406Sopenharmony_ci   License.
33141cc406Sopenharmony_ci
34141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
35141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
36141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
37141cc406Sopenharmony_ci
38141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
39141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
40141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ci   This file implements a SANE backend for Apple flatbed scanners.  */
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci#include "../include/sane/config.h"
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci#include <ctype.h>
47141cc406Sopenharmony_ci#include <errno.h>
48141cc406Sopenharmony_ci#include <fcntl.h>
49141cc406Sopenharmony_ci#include <limits.h>
50141cc406Sopenharmony_ci#include <signal.h>
51141cc406Sopenharmony_ci#include <stdio.h>
52141cc406Sopenharmony_ci#include <stdlib.h>
53141cc406Sopenharmony_ci#include <string.h>
54141cc406Sopenharmony_ci#include <unistd.h>
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci#include <sys/time.h>
57141cc406Sopenharmony_ci#include <sys/types.h>
58141cc406Sopenharmony_ci#include <sys/wait.h>
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci#include "../include/_stdint.h"
61141cc406Sopenharmony_ci
62141cc406Sopenharmony_ci#include "../include/sane/sane.h"
63141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
64141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
65141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h"
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci
68141cc406Sopenharmony_ci/* SCSI commands that the Apple scanners understand: */
69141cc406Sopenharmony_ci#define APPLE_SCSI_TEST_UNIT_READY	0x00
70141cc406Sopenharmony_ci#define APPLE_SCSI_REQUEST_SENSE	0x03
71141cc406Sopenharmony_ci#define APPLE_SCSI_INQUIRY		0x12
72141cc406Sopenharmony_ci#define APPLE_SCSI_MODE_SELECT		0x15
73141cc406Sopenharmony_ci#define APPLE_SCSI_RESERVE		0x16
74141cc406Sopenharmony_ci#define APPLE_SCSI_RELEASE		0x17
75141cc406Sopenharmony_ci#define APPLE_SCSI_START		0x1b
76141cc406Sopenharmony_ci#define APPLE_SCSI_AREA_AND_WINDOWS	0x24
77141cc406Sopenharmony_ci#define APPLE_SCSI_READ_SCANNED_DATA	0x28
78141cc406Sopenharmony_ci#define APPLE_SCSI_GET_DATA_STATUS	0x34
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_ci
81141cc406Sopenharmony_ci#define INQ_LEN	0x60
82141cc406Sopenharmony_ci
83141cc406Sopenharmony_ci#define ENABLE(OPTION)  s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE
84141cc406Sopenharmony_ci#define DISABLE(OPTION) s->opt[OPTION].cap |=  SANE_CAP_INACTIVE
85141cc406Sopenharmony_ci#define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0)
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_ci#define XQSTEP(XRES,BPP) (SANE_Int) (((double) (8*1200)) / ((double) (XRES*BPP)))
88141cc406Sopenharmony_ci#define YQSTEP(YRES) (SANE_Int) (((double) (1200)) / ((double) (YRES)))
89141cc406Sopenharmony_ci
90141cc406Sopenharmony_ci
91141cc406Sopenharmony_ci/* Very low info, Apple Scanners only */
92141cc406Sopenharmony_ci
93141cc406Sopenharmony_ci/* TODO: Ok I admit it. I am not so clever to do this operations with bitwised
94141cc406Sopenharmony_ci   operators. Sorry. */
95141cc406Sopenharmony_ci
96141cc406Sopenharmony_ci#define STORE8(p,v)				\
97141cc406Sopenharmony_ci  {						\
98141cc406Sopenharmony_ci  *(p)=(v);					\
99141cc406Sopenharmony_ci  }
100141cc406Sopenharmony_ci
101141cc406Sopenharmony_ci#define STORE16(p,v)				\
102141cc406Sopenharmony_ci  {						\
103141cc406Sopenharmony_ci  *(p)=(v)/256;					\
104141cc406Sopenharmony_ci  *(p+1)=(v-*(p)*256);				\
105141cc406Sopenharmony_ci  }
106141cc406Sopenharmony_ci
107141cc406Sopenharmony_ci#define STORE24(p,v)				\
108141cc406Sopenharmony_ci  {						\
109141cc406Sopenharmony_ci  *(p)=(v)/65536;				\
110141cc406Sopenharmony_ci  *(p+1)=(v-*(p)*65536)/256;			\
111141cc406Sopenharmony_ci  *(p+2)=(v-*(p)*65536-*(p+1)*256);		\
112141cc406Sopenharmony_ci  }
113141cc406Sopenharmony_ci
114141cc406Sopenharmony_ci
115141cc406Sopenharmony_ci#define STORE32(p,v)				\
116141cc406Sopenharmony_ci  {						\
117141cc406Sopenharmony_ci  *(p)=(v)/16777216;				\
118141cc406Sopenharmony_ci  *(p+1)=(v-*(p)*16777216)/65536;		\
119141cc406Sopenharmony_ci  *(p+2)=(v-*(p)*16777216-*(p+1)*65536)/256;	\
120141cc406Sopenharmony_ci  *(p+3)=(v-*(p)*16777216-*(p+1)*65536-*(p+2)*256);\
121141cc406Sopenharmony_ci  }
122141cc406Sopenharmony_ci
123141cc406Sopenharmony_ci#define READ24(p) *(p)*65536 + *(p+1)*256 + *(p+2)
124141cc406Sopenharmony_ci
125141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
126141cc406Sopenharmony_ci
127141cc406Sopenharmony_ci#ifndef PATH_MAX
128141cc406Sopenharmony_ci# define PATH_MAX	1024
129141cc406Sopenharmony_ci#endif
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h"
132141cc406Sopenharmony_ci#define APPLE_CONFIG_FILE "apple.conf"
133141cc406Sopenharmony_ci
134141cc406Sopenharmony_ci#include "apple.h"
135141cc406Sopenharmony_ci
136141cc406Sopenharmony_ci
137141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0;
138141cc406Sopenharmony_cistatic int num_devices;
139141cc406Sopenharmony_cistatic Apple_Device *first_dev;
140141cc406Sopenharmony_cistatic Apple_Scanner *first_handle;
141141cc406Sopenharmony_ci
142141cc406Sopenharmony_ci
143141cc406Sopenharmony_cistatic SANE_String_Const mode_list[6];
144141cc406Sopenharmony_ci
145141cc406Sopenharmony_cistatic SANE_String_Const SupportedModel[] =
146141cc406Sopenharmony_ci{
147141cc406Sopenharmony_ci"3",
148141cc406Sopenharmony_ci"AppleScanner 4bit, 16 Shades of Gray",
149141cc406Sopenharmony_ci"OneScanner 8bit, 256 Shades of Gray",
150141cc406Sopenharmony_ci"ColorOneScanner, RGB color 8bit per band",
151141cc406Sopenharmony_ciNULL
152141cc406Sopenharmony_ci};
153141cc406Sopenharmony_ci
154141cc406Sopenharmony_cistatic const SANE_String_Const graymap_list[] =
155141cc406Sopenharmony_ci{
156141cc406Sopenharmony_ci  "dark", "normal", "light",
157141cc406Sopenharmony_ci  0
158141cc406Sopenharmony_ci};
159141cc406Sopenharmony_ci
160141cc406Sopenharmony_ci#if 0
161141cc406Sopenharmony_cistatic const SANE_Int resbit4_list[] =
162141cc406Sopenharmony_ci{
163141cc406Sopenharmony_ci  5,
164141cc406Sopenharmony_ci  75, 100, 150, 200, 300
165141cc406Sopenharmony_ci};
166141cc406Sopenharmony_ci
167141cc406Sopenharmony_cistatic const SANE_Int resbit1_list[] =
168141cc406Sopenharmony_ci{
169141cc406Sopenharmony_ci  17,
170141cc406Sopenharmony_ci  75, 90, 100, 120, 135, 150, 165, 180, 195,
171141cc406Sopenharmony_ci  200, 210, 225, 240, 255, 270, 285, 300
172141cc406Sopenharmony_ci};
173141cc406Sopenharmony_ci#endif
174141cc406Sopenharmony_ci
175141cc406Sopenharmony_cistatic const SANE_Int resbit_list[] =
176141cc406Sopenharmony_ci{
177141cc406Sopenharmony_ci  5,
178141cc406Sopenharmony_ci  75, 100, 150, 200, 300
179141cc406Sopenharmony_ci};
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_cistatic const SANE_String_Const speed_list[] =
182141cc406Sopenharmony_ci{
183141cc406Sopenharmony_ci  "normal", "high", "high wo H/S",
184141cc406Sopenharmony_ci  0
185141cc406Sopenharmony_ci};
186141cc406Sopenharmony_ci
187141cc406Sopenharmony_cistatic SANE_String_Const halftone_pattern_list[6];
188141cc406Sopenharmony_ci
189141cc406Sopenharmony_cistatic const SANE_String_Const color_sensor_list[] =
190141cc406Sopenharmony_ci{
191141cc406Sopenharmony_ci  "All", "Red", "Green", "Blue",
192141cc406Sopenharmony_ci  0
193141cc406Sopenharmony_ci};
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_ci/* NOTE: This is used for Brightness, Contrast, Threshold, AutoBackAdj
196141cc406Sopenharmony_ci   and 0 is the default value */
197141cc406Sopenharmony_cistatic const SANE_Range byte_range =
198141cc406Sopenharmony_ci{
199141cc406Sopenharmony_ci  1, 255, 1
200141cc406Sopenharmony_ci};
201141cc406Sopenharmony_ci
202141cc406Sopenharmony_cistatic const SANE_Range u8_range =
203141cc406Sopenharmony_ci{
204141cc406Sopenharmony_ci  0,				/* minimum */
205141cc406Sopenharmony_ci  255,				/* maximum */
206141cc406Sopenharmony_ci  0				/* quantization */
207141cc406Sopenharmony_ci};
208141cc406Sopenharmony_ci
209141cc406Sopenharmony_ci
210141cc406Sopenharmony_ci/* NOTE: However I can select from different lists during the hardware
211141cc406Sopenharmony_ci   probing time. */
212141cc406Sopenharmony_ci
213141cc406Sopenharmony_ci
214141cc406Sopenharmony_ci
215141cc406Sopenharmony_ci
216141cc406Sopenharmony_cistatic const uint8_t inquiry[] =
217141cc406Sopenharmony_ci{
218141cc406Sopenharmony_ci  APPLE_SCSI_INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00
219141cc406Sopenharmony_ci};
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_cistatic const uint8_t test_unit_ready[] =
222141cc406Sopenharmony_ci{
223141cc406Sopenharmony_ci  APPLE_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00
224141cc406Sopenharmony_ci};
225141cc406Sopenharmony_ci
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_ci#if 0
228141cc406Sopenharmony_ciSANE_Int
229141cc406Sopenharmony_cixqstep (unsigned int Xres, unsigned int bpp)
230141cc406Sopenharmony_ci{
231141cc406Sopenharmony_ci  return (SANE_Int) ((double) (8 * 1200)) / ((double) (Xres * bpp));
232141cc406Sopenharmony_ci}
233141cc406Sopenharmony_ci
234141cc406Sopenharmony_ci
235141cc406Sopenharmony_ciSANE_Int
236141cc406Sopenharmony_ciyqstep (unsigned int Yres, unsigned int bpp)
237141cc406Sopenharmony_ci{
238141cc406Sopenharmony_ci  return (SANE_Int) ((double) (1200)) / ((double) (Yres));
239141cc406Sopenharmony_ci}
240141cc406Sopenharmony_ci#endif
241141cc406Sopenharmony_ci
242141cc406Sopenharmony_ci
243141cc406Sopenharmony_ci
244141cc406Sopenharmony_ci/* The functions below return the quantized value of x,y in scanners dots
245141cc406Sopenharmony_ci   aka 1/1200 of an inch */
246141cc406Sopenharmony_ci
247141cc406Sopenharmony_cistatic SANE_Int
248141cc406Sopenharmony_cixquant (double x, unsigned int Xres, unsigned int bpp, int dir)
249141cc406Sopenharmony_ci{
250141cc406Sopenharmony_ci  double tmp;
251141cc406Sopenharmony_ci  unsigned int t;
252141cc406Sopenharmony_ci
253141cc406Sopenharmony_ci  tmp = (double) x *Xres * bpp / (double) 8;
254141cc406Sopenharmony_ci  t = (unsigned int) tmp;
255141cc406Sopenharmony_ci
256141cc406Sopenharmony_ci  if (tmp - ((double) t) >= 0.1)
257141cc406Sopenharmony_ci    if (dir)
258141cc406Sopenharmony_ci      t++;;
259141cc406Sopenharmony_ci
260141cc406Sopenharmony_ci  return t * 8 * 1200 / (Xres * bpp);
261141cc406Sopenharmony_ci}
262141cc406Sopenharmony_ci
263141cc406Sopenharmony_ci
264141cc406Sopenharmony_ci
265141cc406Sopenharmony_cistatic SANE_Int
266141cc406Sopenharmony_ciyquant (double y, unsigned int Yres, int dir)
267141cc406Sopenharmony_ci{
268141cc406Sopenharmony_ci  double tmp;
269141cc406Sopenharmony_ci  unsigned int t;
270141cc406Sopenharmony_ci
271141cc406Sopenharmony_ci  tmp = (double) y *Yres;
272141cc406Sopenharmony_ci  t = (unsigned int) tmp;
273141cc406Sopenharmony_ci
274141cc406Sopenharmony_ci  if (tmp - ((double) t) >= 0.1)
275141cc406Sopenharmony_ci    if (dir)
276141cc406Sopenharmony_ci      t++;;
277141cc406Sopenharmony_ci
278141cc406Sopenharmony_ci  return t * 1200 / Yres;
279141cc406Sopenharmony_ci}
280141cc406Sopenharmony_ci
281141cc406Sopenharmony_cistatic SANE_Status
282141cc406Sopenharmony_ciwait_ready (int fd)
283141cc406Sopenharmony_ci{
284141cc406Sopenharmony_ci#define MAX_WAITING_TIME	60	/* one minute, at most */
285141cc406Sopenharmony_ci  struct timeval now, start;
286141cc406Sopenharmony_ci  SANE_Status status;
287141cc406Sopenharmony_ci
288141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
289141cc406Sopenharmony_cireturn SANE_STATUS_GOOD;
290141cc406Sopenharmony_ci#else
291141cc406Sopenharmony_ci
292141cc406Sopenharmony_ci  gettimeofday (&start, 0);
293141cc406Sopenharmony_ci
294141cc406Sopenharmony_ci  while (1)
295141cc406Sopenharmony_ci    {
296141cc406Sopenharmony_ci      DBG (USER_MESSAGE, "wait_ready: sending TEST_UNIT_READY\n");
297141cc406Sopenharmony_ci
298141cc406Sopenharmony_ci      status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready),
299141cc406Sopenharmony_ci			       0, 0);
300141cc406Sopenharmony_ci      switch (status)
301141cc406Sopenharmony_ci	{
302141cc406Sopenharmony_ci	default:
303141cc406Sopenharmony_ci	  /* Ignore errors while waiting for scanner to become ready.
304141cc406Sopenharmony_ci	     Some SCSI drivers return EIO while the scanner is
305141cc406Sopenharmony_ci	     returning to the home position.  */
306141cc406Sopenharmony_ci	  DBG (ERROR_MESSAGE, "wait_ready: test unit ready failed (%s)\n",
307141cc406Sopenharmony_ci	       sane_strstatus (status));
308141cc406Sopenharmony_ci	  /* fall through */
309141cc406Sopenharmony_ci	case SANE_STATUS_DEVICE_BUSY:
310141cc406Sopenharmony_ci	  gettimeofday (&now, 0);
311141cc406Sopenharmony_ci	  if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME)
312141cc406Sopenharmony_ci	    {
313141cc406Sopenharmony_ci	      DBG (ERROR_MESSAGE, "wait_ready: timed out after %lu seconds\n",
314141cc406Sopenharmony_ci		   (u_long) now.tv_sec - start.tv_sec);
315141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
316141cc406Sopenharmony_ci	    }
317141cc406Sopenharmony_ci	  usleep (100000);	/* retry after 100ms */
318141cc406Sopenharmony_ci	  break;
319141cc406Sopenharmony_ci
320141cc406Sopenharmony_ci	case SANE_STATUS_GOOD:
321141cc406Sopenharmony_ci	  return status;
322141cc406Sopenharmony_ci	}
323141cc406Sopenharmony_ci    }
324141cc406Sopenharmony_ci  return SANE_STATUS_INVAL;
325141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
326141cc406Sopenharmony_ci}
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_cistatic SANE_Status
329141cc406Sopenharmony_cisense_handler (int scsi_fd, u_char * result, void *arg)
330141cc406Sopenharmony_ci{
331141cc406Sopenharmony_ci  (void) scsi_fd;			/* silence gcc */
332141cc406Sopenharmony_ci  (void) arg;				/* silence gcc */
333141cc406Sopenharmony_ci
334141cc406Sopenharmony_ci  switch (result[2] & 0x0F)
335141cc406Sopenharmony_ci    {
336141cc406Sopenharmony_ci    case 0:
337141cc406Sopenharmony_ci      DBG (USER_MESSAGE, "Sense: No sense Error\n");
338141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
339141cc406Sopenharmony_ci    case 2:
340141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Sense: Scanner not ready\n");
341141cc406Sopenharmony_ci      return SANE_STATUS_DEVICE_BUSY;
342141cc406Sopenharmony_ci    case 4:
343141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Sense: Hardware Error. Read more...\n");
344141cc406Sopenharmony_ci      return SANE_STATUS_IO_ERROR;
345141cc406Sopenharmony_ci    case 5:
346141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Sense: Illegall request\n");
347141cc406Sopenharmony_ci      return SANE_STATUS_UNSUPPORTED;
348141cc406Sopenharmony_ci    case 6:
349141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Sense: Unit Attention (Wait until scanner "
350141cc406Sopenharmony_ci	   "boots)\n");
351141cc406Sopenharmony_ci      return SANE_STATUS_DEVICE_BUSY;
352141cc406Sopenharmony_ci    case 9:
353141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Sense: Vendor Unique. Read more...\n");
354141cc406Sopenharmony_ci      return SANE_STATUS_IO_ERROR;
355141cc406Sopenharmony_ci    default:
356141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Sense: Unknown Sense Key. Read more...\n");
357141cc406Sopenharmony_ci      return SANE_STATUS_IO_ERROR;
358141cc406Sopenharmony_ci    }
359141cc406Sopenharmony_ci
360141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
361141cc406Sopenharmony_ci}
362141cc406Sopenharmony_ci
363141cc406Sopenharmony_ci
364141cc406Sopenharmony_cistatic SANE_Status
365141cc406Sopenharmony_cirequest_sense (Apple_Scanner * s)
366141cc406Sopenharmony_ci{
367141cc406Sopenharmony_ci  uint8_t cmd[6];
368141cc406Sopenharmony_ci  uint8_t result[22];
369141cc406Sopenharmony_ci  size_t size = sizeof (result);
370141cc406Sopenharmony_ci  SANE_Status status;
371141cc406Sopenharmony_ci
372141cc406Sopenharmony_ci  memset (cmd, 0, sizeof (cmd));
373141cc406Sopenharmony_ci  memset (result, 0, sizeof (result));
374141cc406Sopenharmony_ci
375141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
376141cc406Sopenharmony_cireturn SANE_STATUS_GOOD;
377141cc406Sopenharmony_ci#else
378141cc406Sopenharmony_ci
379141cc406Sopenharmony_ci  cmd[0] = APPLE_SCSI_REQUEST_SENSE;
380141cc406Sopenharmony_ci  STORE8 (cmd + 4, sizeof (result));
381141cc406Sopenharmony_ci  sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), result, &size);
382141cc406Sopenharmony_ci
383141cc406Sopenharmony_ci  if (result[7] != 14)
384141cc406Sopenharmony_ci    {
385141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Additional Length %u\n", (unsigned int) result[7]);
386141cc406Sopenharmony_ci      status = SANE_STATUS_IO_ERROR;
387141cc406Sopenharmony_ci    }
388141cc406Sopenharmony_ci
389141cc406Sopenharmony_ci
390141cc406Sopenharmony_ci  status = sense_handler (s->fd, result, NULL);
391141cc406Sopenharmony_ci  if (status == SANE_STATUS_IO_ERROR)
392141cc406Sopenharmony_ci    {
393141cc406Sopenharmony_ci
394141cc406Sopenharmony_ci/* Now we are checking for Hardware and Vendor Unique Errors for all models */
395141cc406Sopenharmony_ci/* First check the common Error conditions */
396141cc406Sopenharmony_ci
397141cc406Sopenharmony_ci      if (result[18] & 0x80)
398141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Sense: Dim Light (output of lamp below 70%%).\n");
399141cc406Sopenharmony_ci
400141cc406Sopenharmony_ci      if (result[18] & 0x40)
401141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Sense: No Light at all.\n");
402141cc406Sopenharmony_ci
403141cc406Sopenharmony_ci      if (result[18] & 0x20)
404141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Sense: No Home.\n");
405141cc406Sopenharmony_ci
406141cc406Sopenharmony_ci      if (result[18] & 0x10)
407141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Sense: No Limit. Tried to scan out of range.\n");
408141cc406Sopenharmony_ci
409141cc406Sopenharmony_ci
410141cc406Sopenharmony_ci      switch (s->hw->ScannerModel)
411141cc406Sopenharmony_ci	{
412141cc406Sopenharmony_ci	case APPLESCANNER:
413141cc406Sopenharmony_ci	  if (result[18] & 0x08)
414141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: Shade Error. Failed Calibration.\n");
415141cc406Sopenharmony_ci	  if (result[18] & 0x04)
416141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: ROM Error.\n");
417141cc406Sopenharmony_ci	  if (result[18] & 0x02)
418141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: RAM Error.\n");
419141cc406Sopenharmony_ci	  if (result[18] & 0x01)
420141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: CPU Error.\n");
421141cc406Sopenharmony_ci	  if (result[19] & 0x80)
422141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: DIPP Error.\n");
423141cc406Sopenharmony_ci	  if (result[19] & 0x40)
424141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: DMA Error.\n");
425141cc406Sopenharmony_ci	  if (result[19] & 0x20)
426141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: GA1 Error.\n");
427141cc406Sopenharmony_ci	  break;
428141cc406Sopenharmony_ci	case ONESCANNER:
429141cc406Sopenharmony_ci	  if (result[18] & 0x08)
430141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: CCD clock generator failed.\n");
431141cc406Sopenharmony_ci	  if (result[18] & 0x04)
432141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: LRAM (Line RAM) Error.\n");
433141cc406Sopenharmony_ci	  if (result[18] & 0x02)
434141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: CRAM (Correction RAM) Error.\n");
435141cc406Sopenharmony_ci	  if (result[18] & 0x01)
436141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: ROM Error.\n");
437141cc406Sopenharmony_ci	  if (result[19] & 0x08)
438141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: SRAM Error.\n");
439141cc406Sopenharmony_ci	  if (result[19] & 0x04)
440141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: CPU Error.\n");
441141cc406Sopenharmony_ci	  break;
442141cc406Sopenharmony_ci	case COLORONESCANNER:
443141cc406Sopenharmony_ci	  if (result[18] & 0x08)
444141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: Calibration cirquit cannot "
445141cc406Sopenharmony_ci		 "support normal shading.\n");
446141cc406Sopenharmony_ci	  if (result[18] & 0x04)
447141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: PSRAM (Correction RAM) Error.\n");
448141cc406Sopenharmony_ci	  if (result[18] & 0x02)
449141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: SRAM Error.\n");
450141cc406Sopenharmony_ci	  if (result[18] & 0x01)
451141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: ROM Error.\n");
452141cc406Sopenharmony_ci	  if (result[19] & 0x10)
453141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: ICP (CPU) Error.\n");
454141cc406Sopenharmony_ci	  if (result[19] & 0x02)
455141cc406Sopenharmony_ci	    DBG (ERROR_MESSAGE, "Sense: Over light. (Too bright lamp ?).\n");
456141cc406Sopenharmony_ci	  break;
457141cc406Sopenharmony_ci	default:
458141cc406Sopenharmony_ci	  DBG (ERROR_MESSAGE,
459141cc406Sopenharmony_ci	       "Sense: Unselected Scanner model. Please report this.\n");
460141cc406Sopenharmony_ci	  break;
461141cc406Sopenharmony_ci	}
462141cc406Sopenharmony_ci    }
463141cc406Sopenharmony_ci
464141cc406Sopenharmony_ci  DBG (USER_MESSAGE, "Sense: Optical gain %u.\n", (unsigned int) result[20]);
465141cc406Sopenharmony_ci  return status;
466141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
467141cc406Sopenharmony_ci}
468141cc406Sopenharmony_ci
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_ci
471141cc406Sopenharmony_ci
472141cc406Sopenharmony_ci
473141cc406Sopenharmony_cistatic SANE_Status
474141cc406Sopenharmony_ciattach (const char *devname, Apple_Device ** devp, int may_wait)
475141cc406Sopenharmony_ci{
476141cc406Sopenharmony_ci  char result[INQ_LEN];
477141cc406Sopenharmony_ci  const char *model_name = result + 44;
478141cc406Sopenharmony_ci  int fd, apple_scanner, fw_revision;
479141cc406Sopenharmony_ci  Apple_Device *dev;
480141cc406Sopenharmony_ci  SANE_Status status;
481141cc406Sopenharmony_ci  size_t size;
482141cc406Sopenharmony_ci
483141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
484141cc406Sopenharmony_ci    if (strcmp (dev->sane.name, devname) == 0)
485141cc406Sopenharmony_ci      {
486141cc406Sopenharmony_ci	if (devp)
487141cc406Sopenharmony_ci	  *devp = dev;
488141cc406Sopenharmony_ci	return SANE_STATUS_GOOD;
489141cc406Sopenharmony_ci      }
490141cc406Sopenharmony_ci
491141cc406Sopenharmony_ci  DBG (USER_MESSAGE, "attach: opening %s\n", devname);
492141cc406Sopenharmony_ci
493141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
494141cc406Sopenharmony_ciresult[0]=0x06;
495141cc406Sopenharmony_cistrcpy(result +  8, "APPLE   ");
496141cc406Sopenharmony_ci
497141cc406Sopenharmony_ciif (APPLE_MODEL_SELECT==APPLESCANNER)
498141cc406Sopenharmony_ci  strcpy(result + 16, "SCANNER A9M0337 ");
499141cc406Sopenharmony_ciif (APPLE_MODEL_SELECT==ONESCANNER)
500141cc406Sopenharmony_ci  strcpy(result + 16, "SCANNER II      ");
501141cc406Sopenharmony_ciif (APPLE_MODEL_SELECT==COLORONESCANNER)
502141cc406Sopenharmony_ci  strcpy(result + 16, "SCANNER III     ");
503141cc406Sopenharmony_ci
504141cc406Sopenharmony_ci#else
505141cc406Sopenharmony_ci  status = sanei_scsi_open (devname, &fd, sense_handler, 0);
506141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
507141cc406Sopenharmony_ci    {
508141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "attach: open failed (%s)\n",
509141cc406Sopenharmony_ci	   sane_strstatus (status));
510141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
511141cc406Sopenharmony_ci    }
512141cc406Sopenharmony_ci
513141cc406Sopenharmony_ci  if (may_wait)
514141cc406Sopenharmony_ci    wait_ready (fd);
515141cc406Sopenharmony_ci
516141cc406Sopenharmony_ci  DBG (USER_MESSAGE, "attach: sending INQUIRY\n");
517141cc406Sopenharmony_ci  size = sizeof (result);
518141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size);
519141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
520141cc406Sopenharmony_ci    {
521141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "attach: inquiry failed (%s)\n",
522141cc406Sopenharmony_ci	   sane_strstatus (status));
523141cc406Sopenharmony_ci      sanei_scsi_close (fd);
524141cc406Sopenharmony_ci      return status;
525141cc406Sopenharmony_ci    }
526141cc406Sopenharmony_ci
527141cc406Sopenharmony_ci  status = wait_ready (fd);
528141cc406Sopenharmony_ci  sanei_scsi_close (fd);
529141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
530141cc406Sopenharmony_ci    return status;
531141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
532141cc406Sopenharmony_ci
533141cc406Sopenharmony_ci  /* check for old format: */
534141cc406Sopenharmony_ci  apple_scanner = (strncmp (result + 8, "APPLE   ", 8) == 0);
535141cc406Sopenharmony_ci  model_name = result + 16;
536141cc406Sopenharmony_ci
537141cc406Sopenharmony_ci  apple_scanner = apple_scanner && (result[0] == 0x06);
538141cc406Sopenharmony_ci
539141cc406Sopenharmony_ci  if (!apple_scanner)
540141cc406Sopenharmony_ci    {
541141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "attach: device doesn't look like an Apple scanner"
542141cc406Sopenharmony_ci	   "(result[0]=%#02x)\n", result[0]);
543141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
544141cc406Sopenharmony_ci    }
545141cc406Sopenharmony_ci
546141cc406Sopenharmony_ci  /* get firmware revision as BCD number: */
547141cc406Sopenharmony_ci  fw_revision =
548141cc406Sopenharmony_ci    (result[32] - '0') << 8 | (result[34] - '0') << 4 | (result[35] - '0');
549141cc406Sopenharmony_ci  DBG (USER_MESSAGE, "attach: firmware revision %d.%02x\n",
550141cc406Sopenharmony_ci       fw_revision >> 8, fw_revision & 0xff);
551141cc406Sopenharmony_ci
552141cc406Sopenharmony_ci  dev = malloc (sizeof (*dev));
553141cc406Sopenharmony_ci  if (!dev)
554141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
555141cc406Sopenharmony_ci
556141cc406Sopenharmony_ci  memset (dev, 0, sizeof (*dev));
557141cc406Sopenharmony_ci
558141cc406Sopenharmony_ci  dev->sane.name = strdup (devname);
559141cc406Sopenharmony_ci  dev->sane.vendor = "Apple";
560141cc406Sopenharmony_ci  dev->sane.model = strndup (model_name, 16);
561141cc406Sopenharmony_ci  dev->sane.type = "flatbed scanner";
562141cc406Sopenharmony_ci
563141cc406Sopenharmony_ci  dev->x_range.min = 0;
564141cc406Sopenharmony_ci  dev->x_range.max = SANE_FIX (8.51 * MM_PER_INCH);
565141cc406Sopenharmony_ci  dev->x_range.quant = 0;
566141cc406Sopenharmony_ci
567141cc406Sopenharmony_ci  dev->y_range.min = 0;
568141cc406Sopenharmony_ci  dev->y_range.max = SANE_FIX (14.0 * MM_PER_INCH);
569141cc406Sopenharmony_ci  dev->y_range.quant = 0;
570141cc406Sopenharmony_ci
571141cc406Sopenharmony_ci  dev->MaxHeight = 16800;
572141cc406Sopenharmony_ci
573141cc406Sopenharmony_ci  if (strncmp (model_name, "SCANNER A9M0337 ", 16) == 0)
574141cc406Sopenharmony_ci    {
575141cc406Sopenharmony_ci      dev->ScannerModel = APPLESCANNER;
576141cc406Sopenharmony_ci      dev->dpi_range.min = SANE_FIX (75);
577141cc406Sopenharmony_ci      dev->dpi_range.max = SANE_FIX (300);
578141cc406Sopenharmony_ci      dev->dpi_range.quant = SANE_FIX (1);
579141cc406Sopenharmony_ci      dev->MaxWidth = 10208;
580141cc406Sopenharmony_ci    }
581141cc406Sopenharmony_ci  else if (strncmp (model_name, "SCANNER II      ", 16) == 0)
582141cc406Sopenharmony_ci    {
583141cc406Sopenharmony_ci      dev->ScannerModel = ONESCANNER;
584141cc406Sopenharmony_ci      dev->dpi_range.min = SANE_FIX (72);
585141cc406Sopenharmony_ci      dev->dpi_range.max = SANE_FIX (300);
586141cc406Sopenharmony_ci      dev->dpi_range.quant = SANE_FIX (1);
587141cc406Sopenharmony_ci      dev->MaxWidth = 10200;
588141cc406Sopenharmony_ci    }
589141cc406Sopenharmony_ci  else if (strncmp (model_name, "SCANNER III     ", 16) == 0)
590141cc406Sopenharmony_ci    {
591141cc406Sopenharmony_ci      dev->ScannerModel = COLORONESCANNER;
592141cc406Sopenharmony_ci      dev->dpi_range.min = SANE_FIX (72);
593141cc406Sopenharmony_ci      dev->dpi_range.max = SANE_FIX (300);
594141cc406Sopenharmony_ci      dev->dpi_range.quant = SANE_FIX (1);
595141cc406Sopenharmony_ci      dev->MaxWidth = 10200;
596141cc406Sopenharmony_ci    }
597141cc406Sopenharmony_ci  else
598141cc406Sopenharmony_ci    {
599141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE,
600141cc406Sopenharmony_ci	   "attach: Cannot found Apple scanner in the neighborhood\n");
601141cc406Sopenharmony_ci      free (dev);
602141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
603141cc406Sopenharmony_ci    }
604141cc406Sopenharmony_ci
605141cc406Sopenharmony_ci  DBG (USER_MESSAGE, "attach: found Apple scanner model %s (%s)\n",
606141cc406Sopenharmony_ci       dev->sane.model, dev->sane.type);
607141cc406Sopenharmony_ci
608141cc406Sopenharmony_ci  ++num_devices;
609141cc406Sopenharmony_ci  dev->next = first_dev;
610141cc406Sopenharmony_ci  first_dev = dev;
611141cc406Sopenharmony_ci
612141cc406Sopenharmony_ci  if (devp)
613141cc406Sopenharmony_ci    *devp = dev;
614141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
615141cc406Sopenharmony_ci}
616141cc406Sopenharmony_ci
617141cc406Sopenharmony_cistatic size_t
618141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[])
619141cc406Sopenharmony_ci{
620141cc406Sopenharmony_ci  size_t size, max_size = 0;
621141cc406Sopenharmony_ci  int i;
622141cc406Sopenharmony_ci
623141cc406Sopenharmony_ci  for (i = 0; strings[i]; ++i)
624141cc406Sopenharmony_ci    {
625141cc406Sopenharmony_ci      size = strlen (strings[i]) + 1;
626141cc406Sopenharmony_ci      if (size > max_size)
627141cc406Sopenharmony_ci	max_size = size;
628141cc406Sopenharmony_ci    }
629141cc406Sopenharmony_ci  return max_size;
630141cc406Sopenharmony_ci}
631141cc406Sopenharmony_ci
632141cc406Sopenharmony_ci
633141cc406Sopenharmony_cistatic SANE_Status
634141cc406Sopenharmony_ciscan_area_and_windows (Apple_Scanner * s)
635141cc406Sopenharmony_ci{
636141cc406Sopenharmony_ci  uint8_t cmd[10 + 8 + 42];
637141cc406Sopenharmony_ci#define CMD cmd + 0
638141cc406Sopenharmony_ci#define WH  cmd + 10
639141cc406Sopenharmony_ci#define WP  WH + 8
640141cc406Sopenharmony_ci
641141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
642141cc406Sopenharmony_cireturn SANE_STATUS_GOOD;
643141cc406Sopenharmony_ci#else
644141cc406Sopenharmony_ci
645141cc406Sopenharmony_ci  /* setup SCSI command (except length): */
646141cc406Sopenharmony_ci  memset (cmd, 0, sizeof (cmd));
647141cc406Sopenharmony_ci  cmd[0] = APPLE_SCSI_AREA_AND_WINDOWS;
648141cc406Sopenharmony_ci
649141cc406Sopenharmony_ci
650141cc406Sopenharmony_ci  if (s->hw->ScannerModel == COLORONESCANNER)
651141cc406Sopenharmony_ci    {
652141cc406Sopenharmony_ci      STORE24 (CMD + 6, 50);
653141cc406Sopenharmony_ci      STORE16 (WH + 6, 42);
654141cc406Sopenharmony_ci    }
655141cc406Sopenharmony_ci  else
656141cc406Sopenharmony_ci    {
657141cc406Sopenharmony_ci      STORE24 (CMD + 6, 48);
658141cc406Sopenharmony_ci      STORE16 (WH + 6, 40);
659141cc406Sopenharmony_ci    }
660141cc406Sopenharmony_ci
661141cc406Sopenharmony_ci/* Store resolution. First X, the Y */
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  STORE16 (WP + 2, s->val[OPT_RESOLUTION].w);
664141cc406Sopenharmony_ci  STORE16 (WP + 4, s->val[OPT_RESOLUTION].w);
665141cc406Sopenharmony_ci
666141cc406Sopenharmony_ci/* Now the Scanner Window in Scanner Parameters */
667141cc406Sopenharmony_ci
668141cc406Sopenharmony_ci  STORE32 (WP + 6, s->ULx);
669141cc406Sopenharmony_ci  STORE32 (WP + 10, s->ULy);
670141cc406Sopenharmony_ci  STORE32 (WP + 14, s->Width);
671141cc406Sopenharmony_ci  STORE32 (WP + 18, s->Height);
672141cc406Sopenharmony_ci
673141cc406Sopenharmony_ci/* Now The Enhansment Group */
674141cc406Sopenharmony_ci
675141cc406Sopenharmony_ci  STORE8 (WP + 22, s->val[OPT_BRIGHTNESS].w);
676141cc406Sopenharmony_ci  STORE8 (WP + 23, s->val[OPT_THRESHOLD].w);
677141cc406Sopenharmony_ci  STORE8 (WP + 24, s->val[OPT_CONTRAST].w);
678141cc406Sopenharmony_ci
679141cc406Sopenharmony_ci/* The Mode */
680141cc406Sopenharmony_ci
681141cc406Sopenharmony_ci  if      (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART))
682141cc406Sopenharmony_ci    STORE8 (WP + 25, 0)
683141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE))
684141cc406Sopenharmony_ci    STORE8 (WP + 25, 1)
685141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) ||
686141cc406Sopenharmony_ci	   !strcmp (s->val[OPT_MODE].s, "Gray16"))
687141cc406Sopenharmony_ci    STORE8 (WP + 25, 2)
688141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_MODE].s, "BiColor"))
689141cc406Sopenharmony_ci    STORE8 (WP + 25, 3)
690141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR))
691141cc406Sopenharmony_ci    STORE8 (WP + 25, 5)
692141cc406Sopenharmony_ci  else
693141cc406Sopenharmony_ci    {
694141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Cannot much mode %s\n", s->val[OPT_MODE].s);
695141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
696141cc406Sopenharmony_ci    }
697141cc406Sopenharmony_ci
698141cc406Sopenharmony_ci  STORE8 (WP + 26, s->bpp)
699141cc406Sopenharmony_ci
700141cc406Sopenharmony_ci/* HalfTone */
701141cc406Sopenharmony_ciif (s->hw->ScannerModel != COLORONESCANNER)
702141cc406Sopenharmony_ci  {
703141cc406Sopenharmony_ci  if	  (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "spiral4x4"))
704141cc406Sopenharmony_ci    STORE16 (WP + 27, 0)
705141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "bayer4x4"))
706141cc406Sopenharmony_ci    STORE16 (WP + 27, 1)
707141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "download"))
708141cc406Sopenharmony_ci    STORE16 (WP + 27, 1)
709141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "spiral8x8"))
710141cc406Sopenharmony_ci    STORE16 (WP + 27, 3)
711141cc406Sopenharmony_ci  else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "bayer8x8"))
712141cc406Sopenharmony_ci    STORE16 (WP + 27, 4)
713141cc406Sopenharmony_ci  else
714141cc406Sopenharmony_ci    {
715141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Cannot much haftone pattern %s\n",
716141cc406Sopenharmony_ci					s->val[OPT_HALFTONE_PATTERN].s);
717141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
718141cc406Sopenharmony_ci    }
719141cc406Sopenharmony_ci  }
720141cc406Sopenharmony_ci/* Padding Type */
721141cc406Sopenharmony_ci  STORE8 (WP + 29, 3);
722141cc406Sopenharmony_ci
723141cc406Sopenharmony_ci  if (s->hw->ScannerModel == COLORONESCANNER)
724141cc406Sopenharmony_ci    {
725141cc406Sopenharmony_ci    if (s->val[OPT_VOLT_REF].w)
726141cc406Sopenharmony_ci      {
727141cc406Sopenharmony_ci      STORE8(WP+40,s->val[OPT_VOLT_REF_TOP].w);
728141cc406Sopenharmony_ci      STORE8(WP+41,s->val[OPT_VOLT_REF_BOTTOM].w);
729141cc406Sopenharmony_ci      }
730141cc406Sopenharmony_ci    else
731141cc406Sopenharmony_ci      {
732141cc406Sopenharmony_ci      STORE8(WP+40,0);
733141cc406Sopenharmony_ci      STORE8(WP+41,0);
734141cc406Sopenharmony_ci      }
735141cc406Sopenharmony_ci    return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0);
736141cc406Sopenharmony_ci    }
737141cc406Sopenharmony_ci  else
738141cc406Sopenharmony_ci    return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd) - 2, 0, 0);
739141cc406Sopenharmony_ci
740141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
741141cc406Sopenharmony_ci}
742141cc406Sopenharmony_ci
743141cc406Sopenharmony_cistatic SANE_Status
744141cc406Sopenharmony_cimode_select (Apple_Scanner * s)
745141cc406Sopenharmony_ci{
746141cc406Sopenharmony_ci  uint8_t cmd[6 + 12];
747141cc406Sopenharmony_ci#define CMD cmd + 0
748141cc406Sopenharmony_ci#define PP  cmd + 6
749141cc406Sopenharmony_ci
750141cc406Sopenharmony_ci  /* setup SCSI command (except length): */
751141cc406Sopenharmony_ci  memset (cmd, 0, sizeof (cmd));
752141cc406Sopenharmony_ci  cmd[0] = APPLE_SCSI_MODE_SELECT;
753141cc406Sopenharmony_ci
754141cc406Sopenharmony_ci/* Apple Hardware Magic */
755141cc406Sopenharmony_ci  STORE8 (CMD + 1, 0x10);
756141cc406Sopenharmony_ci
757141cc406Sopenharmony_ci/* Parameter list length */
758141cc406Sopenharmony_ci  STORE8 (CMD + 4, 12);
759141cc406Sopenharmony_ci
760141cc406Sopenharmony_ci  STORE8 (PP + 5, 6);
761141cc406Sopenharmony_ci
762141cc406Sopenharmony_ci  if (s->val[OPT_LAMP].w) *(PP+8) |= 1;
763141cc406Sopenharmony_ci
764141cc406Sopenharmony_ci  switch (s->hw->ScannerModel)
765141cc406Sopenharmony_ci    {
766141cc406Sopenharmony_ci    case APPLESCANNER:
767141cc406Sopenharmony_ci      if      (!strcmp (s->val[OPT_GRAYMAP].s, "dark"))
768141cc406Sopenharmony_ci	STORE8 (PP + 6, 0)
769141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_GRAYMAP].s, "normal"))
770141cc406Sopenharmony_ci	STORE8 (PP + 6, 1)
771141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_GRAYMAP].s, "light"))
772141cc406Sopenharmony_ci	STORE8 (PP + 6, 2)
773141cc406Sopenharmony_ci      else
774141cc406Sopenharmony_ci	{
775141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Cannot mach GrayMap Function %s\n",
776141cc406Sopenharmony_ci						s->val[OPT_GRAYMAP].s);
777141cc406Sopenharmony_ci	return SANE_STATUS_INVAL;
778141cc406Sopenharmony_ci	}
779141cc406Sopenharmony_ci				/* And the auto background threshold */
780141cc406Sopenharmony_ci      STORE8 (PP + 7, s->val[OPT_AUTOBACKGROUND_THRESHOLD].w)
781141cc406Sopenharmony_ci      break;
782141cc406Sopenharmony_ci    case ONESCANNER:
783141cc406Sopenharmony_ci      if (s->val[OPT_LED].w) *(PP+7) |= 4;
784141cc406Sopenharmony_ci      if (s->val[OPT_CCD].w) *(PP+8) |= 2;
785141cc406Sopenharmony_ci      if      (!strcmp (s->val[OPT_SPEED].s, "high"))
786141cc406Sopenharmony_ci	*(PP+8) |= 4;
787141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_SPEED].s, "high wo H/S"))
788141cc406Sopenharmony_ci	*(PP+8) |= 8;
789141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_SPEED].s, "normal"))
790141cc406Sopenharmony_ci	{ /* Do nothing. Zeros are great */}
791141cc406Sopenharmony_ci      else
792141cc406Sopenharmony_ci	{
793141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Cannot mach speed selection %s\n",
794141cc406Sopenharmony_ci						s->val[OPT_SPEED].s);
795141cc406Sopenharmony_ci	return SANE_STATUS_INVAL;
796141cc406Sopenharmony_ci	}
797141cc406Sopenharmony_ci      break;
798141cc406Sopenharmony_ci    case COLORONESCANNER:
799141cc406Sopenharmony_ci      if (s->val[OPT_LED].w)		*(PP+7) |= 4;
800141cc406Sopenharmony_ci      if (!s->val[OPT_CUSTOM_GAMMA].w)	*(PP+7) |= 2;
801141cc406Sopenharmony_ci      if (!s->val[OPT_CUSTOM_CCT].w)	*(PP+7) |= 1;
802141cc406Sopenharmony_ci      if (s->val[OPT_MTF_CIRCUIT].w)	*(PP+8) |= 16;
803141cc406Sopenharmony_ci      if (s->val[OPT_ICP].w)		*(PP+8) |= 8;
804141cc406Sopenharmony_ci      if (s->val[OPT_POLARITY].w)	*(PP+8) |= 4;
805141cc406Sopenharmony_ci      if (s->val[OPT_CCD].w)		*(PP+8) |= 2;
806141cc406Sopenharmony_ci
807141cc406Sopenharmony_ci      if      (!strcmp (s->val[OPT_COLOR_SENSOR].s, "All"))
808141cc406Sopenharmony_ci	STORE8 (PP + 9, 0)
809141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "Red"))
810141cc406Sopenharmony_ci	STORE8 (PP + 9, 1)
811141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "Green"))
812141cc406Sopenharmony_ci	STORE8 (PP + 9, 2)
813141cc406Sopenharmony_ci      else if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "Blue"))
814141cc406Sopenharmony_ci	STORE8 (PP + 9, 3)
815141cc406Sopenharmony_ci      else
816141cc406Sopenharmony_ci	{
817141cc406Sopenharmony_ci	DBG (ERROR_MESSAGE, "Cannot mach Color Sensor for gray scans %s\n",
818141cc406Sopenharmony_ci						s->val[OPT_COLOR_SENSOR].s);
819141cc406Sopenharmony_ci	return SANE_STATUS_INVAL;
820141cc406Sopenharmony_ci	}
821141cc406Sopenharmony_ci
822141cc406Sopenharmony_ci      break;
823141cc406Sopenharmony_ci    default:
824141cc406Sopenharmony_ci      DBG(ERROR_MESSAGE,"Bad Scanner.\n");
825141cc406Sopenharmony_ci      break;
826141cc406Sopenharmony_ci    }
827141cc406Sopenharmony_ci
828141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
829141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
830141cc406Sopenharmony_ci#else
831141cc406Sopenharmony_ci  return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0);
832141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
833141cc406Sopenharmony_ci
834141cc406Sopenharmony_ci}
835141cc406Sopenharmony_ci
836141cc406Sopenharmony_cistatic SANE_Status
837141cc406Sopenharmony_cistart_scan (Apple_Scanner * s)
838141cc406Sopenharmony_ci{
839141cc406Sopenharmony_ci  SANE_Status status;
840141cc406Sopenharmony_ci  uint8_t start[7];
841141cc406Sopenharmony_ci
842141cc406Sopenharmony_ci
843141cc406Sopenharmony_ci  memset (start, 0, sizeof (start));
844141cc406Sopenharmony_ci  start[0] = APPLE_SCSI_START;
845141cc406Sopenharmony_ci  start[4] = 1;
846141cc406Sopenharmony_ci
847141cc406Sopenharmony_ci  switch (s->hw->ScannerModel)
848141cc406Sopenharmony_ci    {
849141cc406Sopenharmony_ci    case APPLESCANNER:
850141cc406Sopenharmony_ci      if (s->val[OPT_WAIT].w)  start[5]=0x80;
851141cc406Sopenharmony_ci      /* NOT TODO  NoHome */
852141cc406Sopenharmony_ci      break;
853141cc406Sopenharmony_ci    case ONESCANNER:
854141cc406Sopenharmony_ci      if (!s->val[OPT_CALIBRATE].w)  start[5]=0x20;
855141cc406Sopenharmony_ci      break;
856141cc406Sopenharmony_ci    case COLORONESCANNER:
857141cc406Sopenharmony_ci      break;
858141cc406Sopenharmony_ci    default:
859141cc406Sopenharmony_ci      DBG(ERROR_MESSAGE,"Bad Scanner.\n");
860141cc406Sopenharmony_ci      break;
861141cc406Sopenharmony_ci    }
862141cc406Sopenharmony_ci
863141cc406Sopenharmony_ci
864141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
865141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
866141cc406Sopenharmony_ci#else
867141cc406Sopenharmony_ci  status = sanei_scsi_cmd (s->fd, start, sizeof (start), 0, 0);
868141cc406Sopenharmony_ci  return status;
869141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
870141cc406Sopenharmony_ci}
871141cc406Sopenharmony_ci
872141cc406Sopenharmony_cistatic SANE_Status
873141cc406Sopenharmony_cicalc_parameters (Apple_Scanner * s)
874141cc406Sopenharmony_ci{
875141cc406Sopenharmony_ci  SANE_String val = s->val[OPT_MODE].s;
876141cc406Sopenharmony_ci  SANE_Status status = SANE_STATUS_GOOD;
877141cc406Sopenharmony_ci  SANE_Bool OutOfRangeX, OutOfRangeY, Protect = SANE_TRUE;
878141cc406Sopenharmony_ci  SANE_Int xqstep, yqstep;
879141cc406Sopenharmony_ci
880141cc406Sopenharmony_ci  DBG (FLOW_CONTROL, "Entering calc_parameters\n");
881141cc406Sopenharmony_ci
882141cc406Sopenharmony_ci  if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART))
883141cc406Sopenharmony_ci    {
884141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
885141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
886141cc406Sopenharmony_ci      s->params.depth = 1;
887141cc406Sopenharmony_ci      s->bpp = 1;
888141cc406Sopenharmony_ci    }
889141cc406Sopenharmony_ci  else if (!strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE))
890141cc406Sopenharmony_ci    {
891141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
892141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
893141cc406Sopenharmony_ci      s->params.depth = 1;
894141cc406Sopenharmony_ci      s->bpp = 1;
895141cc406Sopenharmony_ci    }
896141cc406Sopenharmony_ci  else if (!strcmp (val, "Gray16"))
897141cc406Sopenharmony_ci    {
898141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
899141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
900141cc406Sopenharmony_ci      s->params.depth = 8;
901141cc406Sopenharmony_ci      s->bpp = 4;
902141cc406Sopenharmony_ci    }
903141cc406Sopenharmony_ci  else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY))
904141cc406Sopenharmony_ci    {
905141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
906141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_GRAY;
907141cc406Sopenharmony_ci      s->params.depth = 8;
908141cc406Sopenharmony_ci      s->bpp = 8;
909141cc406Sopenharmony_ci    }
910141cc406Sopenharmony_ci  else if (!strcmp (val, "BiColor"))
911141cc406Sopenharmony_ci    {
912141cc406Sopenharmony_ci      s->params.last_frame = SANE_TRUE;
913141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_RGB;
914141cc406Sopenharmony_ci      s->params.depth = 24;
915141cc406Sopenharmony_ci      s->bpp = 3;
916141cc406Sopenharmony_ci    }
917141cc406Sopenharmony_ci  else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR))
918141cc406Sopenharmony_ci    {
919141cc406Sopenharmony_ci      s->params.last_frame = SANE_FALSE;
920141cc406Sopenharmony_ci      s->params.format = SANE_FRAME_RED;
921141cc406Sopenharmony_ci      s->params.depth = 24;
922141cc406Sopenharmony_ci      s->bpp = 24;
923141cc406Sopenharmony_ci    }
924141cc406Sopenharmony_ci  else
925141cc406Sopenharmony_ci    {
926141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "calc_parameters: Invalid mode %s\n", (char *) val);
927141cc406Sopenharmony_ci      status = SANE_STATUS_INVAL;
928141cc406Sopenharmony_ci    }
929141cc406Sopenharmony_ci
930141cc406Sopenharmony_ci  s->ulx = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH;
931141cc406Sopenharmony_ci  s->uly = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH;
932141cc406Sopenharmony_ci  s->wx = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH - s->ulx;
933141cc406Sopenharmony_ci  s->wy = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH - s->uly;
934141cc406Sopenharmony_ci
935141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "Desired [%g,%g] to +[%g,%g]\n",
936141cc406Sopenharmony_ci       s->ulx, s->uly, s->wx, s->wy);
937141cc406Sopenharmony_ci
938141cc406Sopenharmony_ci  xqstep = XQSTEP (s->val[OPT_RESOLUTION].w, s->bpp);
939141cc406Sopenharmony_ci  yqstep = YQSTEP (s->val[OPT_RESOLUTION].w);
940141cc406Sopenharmony_ci
941141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "Quantization steps of [%u,%u].\n", xqstep, yqstep);
942141cc406Sopenharmony_ci
943141cc406Sopenharmony_ci  s->ULx = xquant (s->ulx, s->val[OPT_RESOLUTION].w, s->bpp, 0);
944141cc406Sopenharmony_ci  s->Width = xquant (s->wx, s->val[OPT_RESOLUTION].w, s->bpp, 1);
945141cc406Sopenharmony_ci  s->ULy = yquant (s->uly, s->val[OPT_RESOLUTION].w, 0);
946141cc406Sopenharmony_ci  s->Height = yquant (s->wy, s->val[OPT_RESOLUTION].w, 1);
947141cc406Sopenharmony_ci
948141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "Scanner [%u,%u] to +[%u,%u]\n",
949141cc406Sopenharmony_ci       s->ULx, s->ULy, s->Width, s->Height);
950141cc406Sopenharmony_ci
951141cc406Sopenharmony_ci  do
952141cc406Sopenharmony_ci    {
953141cc406Sopenharmony_ci
954141cc406Sopenharmony_ci      OutOfRangeX = SANE_FALSE;
955141cc406Sopenharmony_ci      OutOfRangeY = SANE_FALSE;
956141cc406Sopenharmony_ci
957141cc406Sopenharmony_ci      if (s->ULx + s->Width > s->hw->MaxWidth)
958141cc406Sopenharmony_ci	{
959141cc406Sopenharmony_ci	  OutOfRangeX = SANE_TRUE;
960141cc406Sopenharmony_ci	  Protect = SANE_FALSE;
961141cc406Sopenharmony_ci	  s->Width -= xqstep;
962141cc406Sopenharmony_ci	}
963141cc406Sopenharmony_ci
964141cc406Sopenharmony_ci      if (s->ULy + s->Height > s->hw->MaxHeight)
965141cc406Sopenharmony_ci	{
966141cc406Sopenharmony_ci	  OutOfRangeY = SANE_TRUE;
967141cc406Sopenharmony_ci	  Protect = SANE_FALSE;
968141cc406Sopenharmony_ci	  s->Height -= yqstep;
969141cc406Sopenharmony_ci	}
970141cc406Sopenharmony_ci
971141cc406Sopenharmony_ci      DBG (VARIABLE_CONTROL, "Adapting to [%u,%u] to +[%u,%u]\n",
972141cc406Sopenharmony_ci	   s->ULx, s->ULy, s->Width, s->Height);
973141cc406Sopenharmony_ci
974141cc406Sopenharmony_ci    }
975141cc406Sopenharmony_ci  while (OutOfRangeX || OutOfRangeY);
976141cc406Sopenharmony_ci
977141cc406Sopenharmony_ci  s->ulx = (double) s->ULx / 1200;
978141cc406Sopenharmony_ci  s->uly = (double) s->ULy / 1200;
979141cc406Sopenharmony_ci  s->wx = (double) s->Width / 1200;
980141cc406Sopenharmony_ci  s->wy = (double) s->Height / 1200;
981141cc406Sopenharmony_ci
982141cc406Sopenharmony_ci
983141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "Real [%g,%g] to +[%g,%g]\n",
984141cc406Sopenharmony_ci       s->ulx, s->uly, s->wx, s->wy);
985141cc406Sopenharmony_ci
986141cc406Sopenharmony_ci
987141cc406Sopenharmony_ci/*
988141cc406Sopenharmony_ci
989141cc406Sopenharmony_ci   TODO: Remove this ugly hack (Protect). Read to learn why!
990141cc406Sopenharmony_ci
991141cc406Sopenharmony_ci   NOTE: I hate the Fixed Sane type. This type gave me a terrible
992141cc406Sopenharmony_ci   headache and a difficult bug to find out. The xscanimage frontend
993141cc406Sopenharmony_ci   was looping and segfaulting all the time with random order. The
994141cc406Sopenharmony_ci   problem was the following:
995141cc406Sopenharmony_ci
996141cc406Sopenharmony_ci   * You select new let's say BR_X
997141cc406Sopenharmony_ci   * sane_control_option returns info inexact (always for BR_X) but
998141cc406Sopenharmony_ci     does not modify val because it fits under the constrained
999141cc406Sopenharmony_ci     quantization.
1000141cc406Sopenharmony_ci
1001141cc406Sopenharmony_ci   Hm... Well sane_control doesn't change the (double) value of val
1002141cc406Sopenharmony_ci   but the Fixed interpatation may have been change (by 1 or something
1003141cc406Sopenharmony_ci   small).
1004141cc406Sopenharmony_ci
1005141cc406Sopenharmony_ci   So now we should protect the val if the change is smaller than the
1006141cc406Sopenharmony_ci   quantization step or better under the SANE_[UN]FIX accuracy.
1007141cc406Sopenharmony_ci
1008141cc406Sopenharmony_ci   Looks like for two distinct val (Fixed) values we get the same
1009141cc406Sopenharmony_ci   double. How come ?
1010141cc406Sopenharmony_ci
1011141cc406Sopenharmony_ci   This hack fixed the looping situation. Unfortunately SIGSEGV
1012141cc406Sopenharmony_ci   remains when you touch the slice bars (thouhg not all the
1013141cc406Sopenharmony_ci   time). But it's OK if you select scan_area from the preview window
1014141cc406Sopenharmony_ci   (cool).
1015141cc406Sopenharmony_ci
1016141cc406Sopenharmony_ci */
1017141cc406Sopenharmony_ci
1018141cc406Sopenharmony_ci  if (!Protect)
1019141cc406Sopenharmony_ci    {
1020141cc406Sopenharmony_ci      s->val[OPT_TL_X].w = SANE_FIX (s->ulx * MM_PER_INCH);
1021141cc406Sopenharmony_ci      s->val[OPT_TL_Y].w = SANE_FIX (s->uly * MM_PER_INCH);
1022141cc406Sopenharmony_ci      s->val[OPT_BR_X].w = SANE_FIX ((s->ulx + s->wx) * MM_PER_INCH);
1023141cc406Sopenharmony_ci      s->val[OPT_BR_Y].w = SANE_FIX ((s->uly + s->wy) * MM_PER_INCH);
1024141cc406Sopenharmony_ci    }
1025141cc406Sopenharmony_ci  else
1026141cc406Sopenharmony_ci    DBG (VARIABLE_CONTROL, "Not adapted. Protecting\n");
1027141cc406Sopenharmony_ci
1028141cc406Sopenharmony_ci
1029141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "GUI [%g,%g] to [%g,%g]\n",
1030141cc406Sopenharmony_ci       SANE_UNFIX (s->val[OPT_TL_X].w),
1031141cc406Sopenharmony_ci       SANE_UNFIX (s->val[OPT_TL_Y].w),
1032141cc406Sopenharmony_ci       SANE_UNFIX (s->val[OPT_BR_X].w),
1033141cc406Sopenharmony_ci       SANE_UNFIX (s->val[OPT_BR_Y].w));
1034141cc406Sopenharmony_ci
1035141cc406Sopenharmony_ci  /* NOTE: remember that AppleScanners quantize the scan area to be a
1036141cc406Sopenharmony_ci     byte multiple */
1037141cc406Sopenharmony_ci
1038141cc406Sopenharmony_ci
1039141cc406Sopenharmony_ci  s->params.pixels_per_line = s->Width * s->val[OPT_RESOLUTION].w / 1200;
1040141cc406Sopenharmony_ci  s->params.lines = s->Height * s->val[OPT_RESOLUTION].w / 1200;
1041141cc406Sopenharmony_ci  s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8;
1042141cc406Sopenharmony_ci
1043141cc406Sopenharmony_ci
1044141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "format=%d\n", s->params.format);
1045141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "last_frame=%d\n", s->params.last_frame);
1046141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "lines=%d\n", s->params.lines);
1047141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "depth=%d (%d)\n", s->params.depth, s->bpp);
1048141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "pixels_per_line=%d\n", s->params.pixels_per_line);
1049141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "bytes_per_line=%d\n", s->params.bytes_per_line);
1050141cc406Sopenharmony_ci  DBG (VARIABLE_CONTROL, "Pixels %dx%dx%d\n",
1051141cc406Sopenharmony_ci       s->params.pixels_per_line, s->params.lines, 1 << s->params.depth);
1052141cc406Sopenharmony_ci
1053141cc406Sopenharmony_ci  DBG (FLOW_CONTROL, "Leaving calc_parameters\n");
1054141cc406Sopenharmony_ci  return status;
1055141cc406Sopenharmony_ci}
1056141cc406Sopenharmony_ci
1057141cc406Sopenharmony_ci
1058141cc406Sopenharmony_ci
1059141cc406Sopenharmony_cistatic SANE_Status
1060141cc406Sopenharmony_cigamma_update(SANE_Handle handle)
1061141cc406Sopenharmony_ci{
1062141cc406Sopenharmony_ciApple_Scanner *s = handle;
1063141cc406Sopenharmony_ci
1064141cc406Sopenharmony_ci
1065141cc406Sopenharmony_ciif (s->hw->ScannerModel == COLORONESCANNER)
1066141cc406Sopenharmony_ci  {
1067141cc406Sopenharmony_ci  if (	!strcmp(s->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_GRAY)	||
1068141cc406Sopenharmony_ci	!strcmp(s->val[OPT_MODE].s,"Gray16")	 )
1069141cc406Sopenharmony_ci    {
1070141cc406Sopenharmony_ci    ENABLE (OPT_CUSTOM_GAMMA);
1071141cc406Sopenharmony_ci    if (s->val[OPT_CUSTOM_GAMMA].w)
1072141cc406Sopenharmony_ci      {
1073141cc406Sopenharmony_ci      ENABLE (OPT_DOWNLOAD_GAMMA);
1074141cc406Sopenharmony_ci      if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"All"))
1075141cc406Sopenharmony_ci	{
1076141cc406Sopenharmony_ci	ENABLE (OPT_GAMMA_VECTOR_R);
1077141cc406Sopenharmony_ci	ENABLE (OPT_GAMMA_VECTOR_G);
1078141cc406Sopenharmony_ci	ENABLE (OPT_GAMMA_VECTOR_B);
1079141cc406Sopenharmony_ci	}
1080141cc406Sopenharmony_ci      if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"Red"))
1081141cc406Sopenharmony_ci	{
1082141cc406Sopenharmony_ci	ENABLE (OPT_GAMMA_VECTOR_R);
1083141cc406Sopenharmony_ci	DISABLE(OPT_GAMMA_VECTOR_G);
1084141cc406Sopenharmony_ci	DISABLE (OPT_GAMMA_VECTOR_B);
1085141cc406Sopenharmony_ci	}
1086141cc406Sopenharmony_ci      if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"Green"))
1087141cc406Sopenharmony_ci	{
1088141cc406Sopenharmony_ci	DISABLE (OPT_GAMMA_VECTOR_R);
1089141cc406Sopenharmony_ci	ENABLE (OPT_GAMMA_VECTOR_G);
1090141cc406Sopenharmony_ci	DISABLE (OPT_GAMMA_VECTOR_B);
1091141cc406Sopenharmony_ci	}
1092141cc406Sopenharmony_ci      if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"Blue"))
1093141cc406Sopenharmony_ci	{
1094141cc406Sopenharmony_ci	DISABLE (OPT_GAMMA_VECTOR_R);
1095141cc406Sopenharmony_ci	DISABLE (OPT_GAMMA_VECTOR_G);
1096141cc406Sopenharmony_ci	ENABLE (OPT_GAMMA_VECTOR_B);
1097141cc406Sopenharmony_ci	}
1098141cc406Sopenharmony_ci      }
1099141cc406Sopenharmony_ci    else /* Not custom gamma */
1100141cc406Sopenharmony_ci      {
1101141cc406Sopenharmony_ci      goto discustom;
1102141cc406Sopenharmony_ci      }
1103141cc406Sopenharmony_ci    }
1104141cc406Sopenharmony_ci  else if (!strcmp(s->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_COLOR))
1105141cc406Sopenharmony_ci    {
1106141cc406Sopenharmony_ci    ENABLE (OPT_CUSTOM_GAMMA);
1107141cc406Sopenharmony_ci    if (s->val[OPT_CUSTOM_GAMMA].w)
1108141cc406Sopenharmony_ci      {
1109141cc406Sopenharmony_ci      ENABLE (OPT_DOWNLOAD_GAMMA);
1110141cc406Sopenharmony_ci      ENABLE (OPT_GAMMA_VECTOR_R);
1111141cc406Sopenharmony_ci      ENABLE (OPT_GAMMA_VECTOR_G);
1112141cc406Sopenharmony_ci      ENABLE (OPT_GAMMA_VECTOR_B);
1113141cc406Sopenharmony_ci      }
1114141cc406Sopenharmony_ci    else /* Not custom gamma */
1115141cc406Sopenharmony_ci      {
1116141cc406Sopenharmony_ci      goto discustom;
1117141cc406Sopenharmony_ci      }
1118141cc406Sopenharmony_ci    }
1119141cc406Sopenharmony_ci  else /* Not Gamma capable mode */
1120141cc406Sopenharmony_ci    {
1121141cc406Sopenharmony_ci    goto disall;
1122141cc406Sopenharmony_ci    }
1123141cc406Sopenharmony_ci  }	/* Not Gamma capable Scanner */
1124141cc406Sopenharmony_cielse
1125141cc406Sopenharmony_ci  {
1126141cc406Sopenharmony_cidisall:
1127141cc406Sopenharmony_ci  DISABLE (OPT_CUSTOM_GAMMA);
1128141cc406Sopenharmony_cidiscustom:
1129141cc406Sopenharmony_ci  DISABLE (OPT_GAMMA_VECTOR_R);
1130141cc406Sopenharmony_ci  DISABLE (OPT_GAMMA_VECTOR_G);
1131141cc406Sopenharmony_ci  DISABLE (OPT_GAMMA_VECTOR_B);
1132141cc406Sopenharmony_ci  DISABLE (OPT_DOWNLOAD_GAMMA);
1133141cc406Sopenharmony_ci  }
1134141cc406Sopenharmony_ci
1135141cc406Sopenharmony_cireturn SANE_STATUS_GOOD;
1136141cc406Sopenharmony_ci}
1137141cc406Sopenharmony_ci
1138141cc406Sopenharmony_ci
1139141cc406Sopenharmony_cistatic SANE_Status
1140141cc406Sopenharmony_cimode_update (SANE_Handle handle, char *val)
1141141cc406Sopenharmony_ci{
1142141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
1143141cc406Sopenharmony_ci  SANE_Bool cct=SANE_FALSE;
1144141cc406Sopenharmony_ci  SANE_Bool UseThreshold=SANE_FALSE;
1145141cc406Sopenharmony_ci
1146141cc406Sopenharmony_ci  DISABLE(OPT_COLOR_SENSOR);
1147141cc406Sopenharmony_ci
1148141cc406Sopenharmony_ci  if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART))
1149141cc406Sopenharmony_ci    {
1150141cc406Sopenharmony_ci      if (s->hw->ScannerModel == APPLESCANNER)
1151141cc406Sopenharmony_ci	ENABLE (OPT_AUTOBACKGROUND);
1152141cc406Sopenharmony_ci      else
1153141cc406Sopenharmony_ci	DISABLE (OPT_AUTOBACKGROUND);
1154141cc406Sopenharmony_ci      DISABLE (OPT_HALFTONE_PATTERN);
1155141cc406Sopenharmony_ci
1156141cc406Sopenharmony_ci      UseThreshold=SANE_TRUE;
1157141cc406Sopenharmony_ci    }
1158141cc406Sopenharmony_ci  else if (!strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE))
1159141cc406Sopenharmony_ci    {
1160141cc406Sopenharmony_ci      DISABLE (OPT_AUTOBACKGROUND);
1161141cc406Sopenharmony_ci      ENABLE (OPT_HALFTONE_PATTERN);
1162141cc406Sopenharmony_ci    }
1163141cc406Sopenharmony_ci  else if (!strcmp (val, "Gray16") || !strcmp (val, SANE_VALUE_SCAN_MODE_GRAY))
1164141cc406Sopenharmony_ci    {
1165141cc406Sopenharmony_ci      DISABLE (OPT_AUTOBACKGROUND);
1166141cc406Sopenharmony_ci      DISABLE (OPT_HALFTONE_PATTERN);
1167141cc406Sopenharmony_ci      if (s->hw->ScannerModel == COLORONESCANNER)
1168141cc406Sopenharmony_ci	ENABLE(OPT_COLOR_SENSOR);
1169141cc406Sopenharmony_ci
1170141cc406Sopenharmony_ci    }				/* End of Gray */
1171141cc406Sopenharmony_ci  else if (!strcmp (val, "BiColor"))
1172141cc406Sopenharmony_ci    {
1173141cc406Sopenharmony_ci      DISABLE (OPT_AUTOBACKGROUND);
1174141cc406Sopenharmony_ci      DISABLE (OPT_HALFTONE_PATTERN);
1175141cc406Sopenharmony_ci      UseThreshold=SANE_TRUE;
1176141cc406Sopenharmony_ci    }
1177141cc406Sopenharmony_ci  else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR))
1178141cc406Sopenharmony_ci    {
1179141cc406Sopenharmony_ci      DISABLE (OPT_AUTOBACKGROUND);
1180141cc406Sopenharmony_ci      DISABLE (OPT_HALFTONE_PATTERN);
1181141cc406Sopenharmony_ci      cct=SANE_TRUE;
1182141cc406Sopenharmony_ci    }
1183141cc406Sopenharmony_ci  else
1184141cc406Sopenharmony_ci    {
1185141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "Invalid mode %s\n", (char *) val);
1186141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1187141cc406Sopenharmony_ci    }
1188141cc406Sopenharmony_ci
1189141cc406Sopenharmony_ci/* Second hand dependencies of mode option */
1190141cc406Sopenharmony_ci/* Looks like code doubling */
1191141cc406Sopenharmony_ci
1192141cc406Sopenharmony_ci
1193141cc406Sopenharmony_ci  if (UseThreshold)
1194141cc406Sopenharmony_ci    {
1195141cc406Sopenharmony_ci      DISABLE (OPT_BRIGHTNESS);
1196141cc406Sopenharmony_ci      DISABLE (OPT_CONTRAST);
1197141cc406Sopenharmony_ci      DISABLE (OPT_VOLT_REF);
1198141cc406Sopenharmony_ci      DISABLE (OPT_VOLT_REF_TOP);
1199141cc406Sopenharmony_ci      DISABLE (OPT_VOLT_REF_BOTTOM);
1200141cc406Sopenharmony_ci
1201141cc406Sopenharmony_ci     if (IS_ACTIVE (OPT_AUTOBACKGROUND) && s->val[OPT_AUTOBACKGROUND].w)
1202141cc406Sopenharmony_ci      {
1203141cc406Sopenharmony_ci      DISABLE (OPT_THRESHOLD);
1204141cc406Sopenharmony_ci      ENABLE (OPT_AUTOBACKGROUND_THRESHOLD);
1205141cc406Sopenharmony_ci      }
1206141cc406Sopenharmony_ci    else
1207141cc406Sopenharmony_ci      {
1208141cc406Sopenharmony_ci      ENABLE (OPT_THRESHOLD);
1209141cc406Sopenharmony_ci      DISABLE (OPT_AUTOBACKGROUND_THRESHOLD);
1210141cc406Sopenharmony_ci      }
1211141cc406Sopenharmony_ci    }
1212141cc406Sopenharmony_ci  else
1213141cc406Sopenharmony_ci    {
1214141cc406Sopenharmony_ci      DISABLE (OPT_THRESHOLD);
1215141cc406Sopenharmony_ci      DISABLE (OPT_AUTOBACKGROUND_THRESHOLD);
1216141cc406Sopenharmony_ci
1217141cc406Sopenharmony_ci      if (s->hw->ScannerModel == COLORONESCANNER)
1218141cc406Sopenharmony_ci	{
1219141cc406Sopenharmony_ci	ENABLE (OPT_VOLT_REF);
1220141cc406Sopenharmony_ci	if (s->val[OPT_VOLT_REF].w)
1221141cc406Sopenharmony_ci	  {
1222141cc406Sopenharmony_ci	  ENABLE (OPT_VOLT_REF_TOP);
1223141cc406Sopenharmony_ci	  ENABLE (OPT_VOLT_REF_BOTTOM);
1224141cc406Sopenharmony_ci	  DISABLE (OPT_BRIGHTNESS);
1225141cc406Sopenharmony_ci	  DISABLE (OPT_CONTRAST);
1226141cc406Sopenharmony_ci	  }
1227141cc406Sopenharmony_ci	else
1228141cc406Sopenharmony_ci	  {
1229141cc406Sopenharmony_ci	  DISABLE (OPT_VOLT_REF_TOP);
1230141cc406Sopenharmony_ci	  DISABLE (OPT_VOLT_REF_BOTTOM);
1231141cc406Sopenharmony_ci	  ENABLE (OPT_BRIGHTNESS);
1232141cc406Sopenharmony_ci	  ENABLE (OPT_CONTRAST);
1233141cc406Sopenharmony_ci	  }
1234141cc406Sopenharmony_ci	}
1235141cc406Sopenharmony_ci      else
1236141cc406Sopenharmony_ci        {
1237141cc406Sopenharmony_ci	ENABLE (OPT_BRIGHTNESS);
1238141cc406Sopenharmony_ci	ENABLE (OPT_CONTRAST);
1239141cc406Sopenharmony_ci        }
1240141cc406Sopenharmony_ci    }
1241141cc406Sopenharmony_ci
1242141cc406Sopenharmony_ci
1243141cc406Sopenharmony_ci  if (IS_ACTIVE (OPT_HALFTONE_PATTERN) &&
1244141cc406Sopenharmony_ci      !strcmp (s->val[OPT_HALFTONE_PATTERN].s, "download"))
1245141cc406Sopenharmony_ci    ENABLE (OPT_HALFTONE_FILE);
1246141cc406Sopenharmony_ci  else
1247141cc406Sopenharmony_ci    DISABLE (OPT_HALFTONE_FILE);
1248141cc406Sopenharmony_ci
1249141cc406Sopenharmony_ci  if (cct)
1250141cc406Sopenharmony_ci    ENABLE (OPT_CUSTOM_CCT);
1251141cc406Sopenharmony_ci  else
1252141cc406Sopenharmony_ci    DISABLE (OPT_CUSTOM_CCT);
1253141cc406Sopenharmony_ci
1254141cc406Sopenharmony_ci  if (cct && s->val[OPT_CUSTOM_CCT].w)
1255141cc406Sopenharmony_ci    {
1256141cc406Sopenharmony_ci    ENABLE(OPT_CCT);
1257141cc406Sopenharmony_ci    ENABLE(OPT_DOWNLOAD_CCT);
1258141cc406Sopenharmony_ci    }
1259141cc406Sopenharmony_ci  else
1260141cc406Sopenharmony_ci    {
1261141cc406Sopenharmony_ci    DISABLE(OPT_CCT);
1262141cc406Sopenharmony_ci    DISABLE(OPT_DOWNLOAD_CCT);
1263141cc406Sopenharmony_ci    }
1264141cc406Sopenharmony_ci
1265141cc406Sopenharmony_ci
1266141cc406Sopenharmony_ci  gamma_update (s);
1267141cc406Sopenharmony_ci  calc_parameters (s);
1268141cc406Sopenharmony_ci
1269141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1270141cc406Sopenharmony_ci
1271141cc406Sopenharmony_ci}
1272141cc406Sopenharmony_ci
1273141cc406Sopenharmony_ci
1274141cc406Sopenharmony_ci
1275141cc406Sopenharmony_ci
1276141cc406Sopenharmony_cistatic SANE_Status
1277141cc406Sopenharmony_ciinit_options (Apple_Scanner * s)
1278141cc406Sopenharmony_ci{
1279141cc406Sopenharmony_ci  int i;
1280141cc406Sopenharmony_ci
1281141cc406Sopenharmony_ci  memset (s->opt, 0, sizeof (s->opt));
1282141cc406Sopenharmony_ci  memset (s->val, 0, sizeof (s->val));
1283141cc406Sopenharmony_ci
1284141cc406Sopenharmony_ci  for (i = 0; i < NUM_OPTIONS; ++i)
1285141cc406Sopenharmony_ci    {
1286141cc406Sopenharmony_ci      s->opt[i].size = sizeof (SANE_Word);
1287141cc406Sopenharmony_ci      s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1288141cc406Sopenharmony_ci    }
1289141cc406Sopenharmony_ci
1290141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
1291141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
1292141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
1293141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
1294141cc406Sopenharmony_ci  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
1295141cc406Sopenharmony_ci
1296141cc406Sopenharmony_ci  /* Hardware detect Information  group: */
1297141cc406Sopenharmony_ci
1298141cc406Sopenharmony_ci  s->opt[OPT_HWDETECT_GROUP].title = "Hardware";
1299141cc406Sopenharmony_ci  s->opt[OPT_HWDETECT_GROUP].desc = "Detected during hardware probing";
1300141cc406Sopenharmony_ci  s->opt[OPT_HWDETECT_GROUP].type = SANE_TYPE_GROUP;
1301141cc406Sopenharmony_ci  s->opt[OPT_HWDETECT_GROUP].cap = 0;
1302141cc406Sopenharmony_ci  s->opt[OPT_HWDETECT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1303141cc406Sopenharmony_ci
1304141cc406Sopenharmony_ci  s->opt[OPT_MODEL].name = "model";
1305141cc406Sopenharmony_ci  s->opt[OPT_MODEL].title = "Model";
1306141cc406Sopenharmony_ci  s->opt[OPT_MODEL].desc = "Model and capabilities";
1307141cc406Sopenharmony_ci  s->opt[OPT_MODEL].type = SANE_TYPE_STRING;
1308141cc406Sopenharmony_ci  s->opt[OPT_MODEL].cap = SANE_CAP_SOFT_DETECT;
1309141cc406Sopenharmony_ci  s->opt[OPT_MODEL].constraint_type = SANE_CONSTRAINT_NONE;
1310141cc406Sopenharmony_ci  s->opt[OPT_MODEL].size = max_string_size (SupportedModel);
1311141cc406Sopenharmony_ci  s->val[OPT_MODEL].s = strdup (SupportedModel[s->hw->ScannerModel]);
1312141cc406Sopenharmony_ci
1313141cc406Sopenharmony_ci
1314141cc406Sopenharmony_ci  /* "Mode" group: */
1315141cc406Sopenharmony_ci
1316141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].title = "Scan Mode";
1317141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].desc = "";
1318141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
1319141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].cap = 0;
1320141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1321141cc406Sopenharmony_ci
1322141cc406Sopenharmony_ci  halftone_pattern_list[0]="spiral4x4";
1323141cc406Sopenharmony_ci  halftone_pattern_list[1]="bayer4x4";
1324141cc406Sopenharmony_ci  halftone_pattern_list[2]="download";
1325141cc406Sopenharmony_ci  halftone_pattern_list[3]=NULL;
1326141cc406Sopenharmony_ci
1327141cc406Sopenharmony_ci
1328141cc406Sopenharmony_ci  switch (s->hw->ScannerModel)
1329141cc406Sopenharmony_ci    {
1330141cc406Sopenharmony_ci    case APPLESCANNER:
1331141cc406Sopenharmony_ci      mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART;
1332141cc406Sopenharmony_ci      mode_list[1]=SANE_VALUE_SCAN_MODE_HALFTONE;
1333141cc406Sopenharmony_ci      mode_list[2]="Gray16";
1334141cc406Sopenharmony_ci      mode_list[3]=NULL;
1335141cc406Sopenharmony_ci      break;
1336141cc406Sopenharmony_ci    case ONESCANNER:
1337141cc406Sopenharmony_ci      mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART;
1338141cc406Sopenharmony_ci      mode_list[1]=SANE_VALUE_SCAN_MODE_HALFTONE;
1339141cc406Sopenharmony_ci      mode_list[2]="Gray16";
1340141cc406Sopenharmony_ci      mode_list[3]=SANE_VALUE_SCAN_MODE_GRAY;
1341141cc406Sopenharmony_ci      mode_list[4]=NULL;
1342141cc406Sopenharmony_ci      halftone_pattern_list[3]="spiral8x8";
1343141cc406Sopenharmony_ci      halftone_pattern_list[4]="bayer8x8";
1344141cc406Sopenharmony_ci      halftone_pattern_list[5]=NULL;
1345141cc406Sopenharmony_ci      break;
1346141cc406Sopenharmony_ci    case COLORONESCANNER:
1347141cc406Sopenharmony_ci      mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART;
1348141cc406Sopenharmony_ci      mode_list[1]="Gray16";
1349141cc406Sopenharmony_ci      mode_list[2]=SANE_VALUE_SCAN_MODE_GRAY;
1350141cc406Sopenharmony_ci      mode_list[3]="BiColor";
1351141cc406Sopenharmony_ci      mode_list[4]=SANE_VALUE_SCAN_MODE_COLOR;
1352141cc406Sopenharmony_ci      mode_list[5]=NULL;
1353141cc406Sopenharmony_ci      break;
1354141cc406Sopenharmony_ci    default:
1355141cc406Sopenharmony_ci      break;
1356141cc406Sopenharmony_ci    }
1357141cc406Sopenharmony_ci
1358141cc406Sopenharmony_ci
1359141cc406Sopenharmony_ci  /* scan mode */
1360141cc406Sopenharmony_ci  s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
1361141cc406Sopenharmony_ci  s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
1362141cc406Sopenharmony_ci  s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
1363141cc406Sopenharmony_ci  s->opt[OPT_MODE].type = SANE_TYPE_STRING;
1364141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1365141cc406Sopenharmony_ci  s->opt[OPT_MODE].size = max_string_size (mode_list);
1366141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint.string_list = mode_list;
1367141cc406Sopenharmony_ci  s->val[OPT_MODE].s = strdup (mode_list[0]);
1368141cc406Sopenharmony_ci
1369141cc406Sopenharmony_ci
1370141cc406Sopenharmony_ci  /* resolution */
1371141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
1372141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
1373141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
1374141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
1375141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
1376141cc406Sopenharmony_ci/* TODO: Build the constraints on resolution in a smart way */
1377141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
1378141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION].constraint.word_list = resbit_list;
1379141cc406Sopenharmony_ci  s->val[OPT_RESOLUTION].w = resbit_list[1];
1380141cc406Sopenharmony_ci
1381141cc406Sopenharmony_ci  /* preview */
1382141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
1383141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
1384141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
1385141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1386141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
1387141cc406Sopenharmony_ci  s->val[OPT_PREVIEW].w = SANE_FALSE;
1388141cc406Sopenharmony_ci
1389141cc406Sopenharmony_ci  /* "Geometry" group: */
1390141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
1391141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].desc = "";
1392141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
1393141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
1394141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1395141cc406Sopenharmony_ci
1396141cc406Sopenharmony_ci  /* top-left x */
1397141cc406Sopenharmony_ci  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
1398141cc406Sopenharmony_ci  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
1399141cc406Sopenharmony_ci  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
1400141cc406Sopenharmony_ci  s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
1401141cc406Sopenharmony_ci  s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
1402141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
1403141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint.range = &s->hw->x_range;
1404141cc406Sopenharmony_ci  s->val[OPT_TL_X].w = 0;
1405141cc406Sopenharmony_ci
1406141cc406Sopenharmony_ci  /* top-left y */
1407141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
1408141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
1409141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
1410141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
1411141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
1412141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1413141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range;
1414141cc406Sopenharmony_ci  s->val[OPT_TL_Y].w = 0;
1415141cc406Sopenharmony_ci
1416141cc406Sopenharmony_ci  /* bottom-right x */
1417141cc406Sopenharmony_ci  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
1418141cc406Sopenharmony_ci  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
1419141cc406Sopenharmony_ci  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
1420141cc406Sopenharmony_ci  s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
1421141cc406Sopenharmony_ci  s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
1422141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
1423141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint.range = &s->hw->x_range;
1424141cc406Sopenharmony_ci  s->val[OPT_BR_X].w = s->hw->x_range.max;
1425141cc406Sopenharmony_ci
1426141cc406Sopenharmony_ci  /* bottom-right y */
1427141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
1428141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
1429141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
1430141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
1431141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
1432141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1433141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range;
1434141cc406Sopenharmony_ci  s->val[OPT_BR_Y].w = s->hw->y_range.max;
1435141cc406Sopenharmony_ci
1436141cc406Sopenharmony_ci
1437141cc406Sopenharmony_ci  /* "Enhancement" group: */
1438141cc406Sopenharmony_ci
1439141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
1440141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
1441141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
1442141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
1443141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1444141cc406Sopenharmony_ci
1445141cc406Sopenharmony_ci  /* brightness */
1446141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
1447141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
1448141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
1449141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
1450141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
1451141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
1452141cc406Sopenharmony_ci  s->opt[OPT_BRIGHTNESS].constraint.range = &byte_range;
1453141cc406Sopenharmony_ci  s->val[OPT_BRIGHTNESS].w = 128;
1454141cc406Sopenharmony_ci
1455141cc406Sopenharmony_ci  /* contrast */
1456141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
1457141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
1458141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST
1459141cc406Sopenharmony_ci    " This option is active for halftone/Grayscale modes only.";
1460141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
1461141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
1462141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
1463141cc406Sopenharmony_ci  s->opt[OPT_CONTRAST].constraint.range = &byte_range;
1464141cc406Sopenharmony_ci  s->val[OPT_CONTRAST].w = 1;
1465141cc406Sopenharmony_ci
1466141cc406Sopenharmony_ci  /* threshold */
1467141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
1468141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
1469141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
1470141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
1471141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
1472141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
1473141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].constraint.range = &byte_range;
1474141cc406Sopenharmony_ci  s->val[OPT_THRESHOLD].w = 128;
1475141cc406Sopenharmony_ci
1476141cc406Sopenharmony_ci  /* AppleScanner Only options */
1477141cc406Sopenharmony_ci
1478141cc406Sopenharmony_ci  /* GrayMap Enhance */
1479141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].name = "graymap";
1480141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].title = "GrayMap";
1481141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].desc = "Fixed Gamma Enhancing";
1482141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].type = SANE_TYPE_STRING;
1483141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1484141cc406Sopenharmony_ci  if (s->hw->ScannerModel != APPLESCANNER)
1485141cc406Sopenharmony_ci    s->opt[OPT_GRAYMAP].cap |= SANE_CAP_INACTIVE;
1486141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].constraint.string_list = graymap_list;
1487141cc406Sopenharmony_ci  s->opt[OPT_GRAYMAP].size = max_string_size (graymap_list);
1488141cc406Sopenharmony_ci  s->val[OPT_GRAYMAP].s = strdup (graymap_list[1]);
1489141cc406Sopenharmony_ci
1490141cc406Sopenharmony_ci  /* Enable auto background adjustment */
1491141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND].name = "abj";
1492141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND].title = "Use Auto Background Adjustment";
1493141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND].desc =
1494141cc406Sopenharmony_ci      "Enables/Disables the Auto Background Adjustment feature";
1495141cc406Sopenharmony_ci  if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)
1496141cc406Sopenharmony_ci      || (s->hw->ScannerModel != APPLESCANNER))
1497141cc406Sopenharmony_ci    DISABLE (OPT_AUTOBACKGROUND);
1498141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND].type = SANE_TYPE_BOOL;
1499141cc406Sopenharmony_ci  s->val[OPT_AUTOBACKGROUND].w = SANE_FALSE;
1500141cc406Sopenharmony_ci
1501141cc406Sopenharmony_ci  /* auto background adjustment threshold */
1502141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].name = "abjthreshold";
1503141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].title = "Auto Background Adjustment Threshold";
1504141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].desc = "Selects the automatically adjustable threshold";
1505141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].type = SANE_TYPE_INT;
1506141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].unit = SANE_UNIT_NONE;
1507141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
1508141cc406Sopenharmony_ci
1509141cc406Sopenharmony_ci  if (!IS_ACTIVE (OPT_AUTOBACKGROUND) ||
1510141cc406Sopenharmony_ci      s->val[OPT_AUTOBACKGROUND].w == SANE_FALSE)
1511141cc406Sopenharmony_ci    s->opt[OPT_AUTOBACKGROUND_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1512141cc406Sopenharmony_ci
1513141cc406Sopenharmony_ci  s->opt[OPT_AUTOBACKGROUND_THRESHOLD].constraint.range = &byte_range;
1514141cc406Sopenharmony_ci  s->val[OPT_AUTOBACKGROUND_THRESHOLD].w = 64;
1515141cc406Sopenharmony_ci
1516141cc406Sopenharmony_ci
1517141cc406Sopenharmony_ci  /* AppleScanner & OneScanner options  */
1518141cc406Sopenharmony_ci
1519141cc406Sopenharmony_ci  /* Select HalfTone Pattern  */
1520141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
1521141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
1522141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
1523141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list);
1524141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
1525141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_AUTOMATIC;
1526141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1527141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list;
1528141cc406Sopenharmony_ci  s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]);
1529141cc406Sopenharmony_ci
1530141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=APPLESCANNER && s->hw->ScannerModel!=ONESCANNER)
1531141cc406Sopenharmony_ci    s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1532141cc406Sopenharmony_ci
1533141cc406Sopenharmony_ci
1534141cc406Sopenharmony_ci  /* halftone pattern file */
1535141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_FILE].name = "halftone-pattern-file";
1536141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_FILE].title = "Halftone Pattern File";
1537141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_FILE].desc =
1538141cc406Sopenharmony_ci    "Download and use the specified file as halftone pattern";
1539141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_FILE].type = SANE_TYPE_STRING;
1540141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_FILE].cap |= SANE_CAP_INACTIVE;
1541141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE_FILE].size = 256;
1542141cc406Sopenharmony_ci  s->val[OPT_HALFTONE_FILE].s = "halftone.pgm";
1543141cc406Sopenharmony_ci
1544141cc406Sopenharmony_ci  /* Use volt_ref */
1545141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF].name = "volt-ref";
1546141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF].title = "Volt Reference";
1547141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF].desc ="It's brightness equivalent.";
1548141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF].type = SANE_TYPE_BOOL;
1549141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1550141cc406Sopenharmony_ci    s->opt[OPT_VOLT_REF].cap |= SANE_CAP_INACTIVE;
1551141cc406Sopenharmony_ci  s->val[OPT_VOLT_REF].w = SANE_FALSE;
1552141cc406Sopenharmony_ci
1553141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].name = "volt-ref-top";
1554141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].title = "Top Voltage Reference";
1555141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].desc = "I really do not know.";
1556141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].type = SANE_TYPE_INT;
1557141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].unit = SANE_UNIT_NONE;
1558141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER || s->val[OPT_VOLT_REF].w==SANE_FALSE)
1559141cc406Sopenharmony_ci    s->opt[OPT_VOLT_REF_TOP].cap |= SANE_CAP_INACTIVE;
1560141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].constraint_type = SANE_CONSTRAINT_RANGE;
1561141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_TOP].constraint.range = &byte_range;
1562141cc406Sopenharmony_ci  s->val[OPT_VOLT_REF_TOP].w = 255;
1563141cc406Sopenharmony_ci
1564141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].name = "volt-ref-bottom";
1565141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].title = "Bottom Voltage Reference";
1566141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].desc = "I really do not know.";
1567141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].type = SANE_TYPE_INT;
1568141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].unit = SANE_UNIT_NONE;
1569141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER || s->val[OPT_VOLT_REF].w==SANE_FALSE)
1570141cc406Sopenharmony_ci    s->opt[OPT_VOLT_REF_BOTTOM].cap |= SANE_CAP_INACTIVE;
1571141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE;
1572141cc406Sopenharmony_ci  s->opt[OPT_VOLT_REF_BOTTOM].constraint.range = &byte_range;
1573141cc406Sopenharmony_ci  s->val[OPT_VOLT_REF_BOTTOM].w = 1;
1574141cc406Sopenharmony_ci
1575141cc406Sopenharmony_ci/* Misc Functions: Advanced */
1576141cc406Sopenharmony_ci
1577141cc406Sopenharmony_ci  s->opt[OPT_MISC_GROUP].title = "Miscallaneous";
1578141cc406Sopenharmony_ci  s->opt[OPT_MISC_GROUP].desc = "";
1579141cc406Sopenharmony_ci  s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP;
1580141cc406Sopenharmony_ci  s->opt[OPT_MISC_GROUP].cap = SANE_CAP_ADVANCED;
1581141cc406Sopenharmony_ci  s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1582141cc406Sopenharmony_ci
1583141cc406Sopenharmony_ci
1584141cc406Sopenharmony_ci  /* Turn On lamp  during scan: All scanners */
1585141cc406Sopenharmony_ci  s->opt[OPT_LAMP].name = "lamp";
1586141cc406Sopenharmony_ci  s->opt[OPT_LAMP].title = "Lamp";
1587141cc406Sopenharmony_ci  s->opt[OPT_LAMP].desc = "Hold the lamp on during scans.";
1588141cc406Sopenharmony_ci  s->opt[OPT_LAMP].type = SANE_TYPE_BOOL;
1589141cc406Sopenharmony_ci  s->val[OPT_LAMP].w = SANE_FALSE;
1590141cc406Sopenharmony_ci
1591141cc406Sopenharmony_ci  /* AppleScanner Only options */
1592141cc406Sopenharmony_ci
1593141cc406Sopenharmony_ci  /* Wait for button to be pressed before scanning */
1594141cc406Sopenharmony_ci  s->opt[OPT_WAIT].name = "wait";
1595141cc406Sopenharmony_ci  s->opt[OPT_WAIT].title = "Wait";
1596141cc406Sopenharmony_ci  s->opt[OPT_WAIT].desc = "You may issue the scan command but the actual "
1597141cc406Sopenharmony_ci  "scan will not start unless you press the button in the front of the "
1598141cc406Sopenharmony_ci  "scanner. It is a useful feature when you want to make a network scan (?) "
1599141cc406Sopenharmony_ci  "In the mean time you may halt your computer waiting for the SCSI bus "
1600141cc406Sopenharmony_ci  "to be free. If this happens just press the scanner button.";
1601141cc406Sopenharmony_ci  s->opt[OPT_WAIT].type = SANE_TYPE_BOOL;
1602141cc406Sopenharmony_ci  if (s->hw->ScannerModel != APPLESCANNER)
1603141cc406Sopenharmony_ci    s->opt[OPT_WAIT].cap |= SANE_CAP_INACTIVE;
1604141cc406Sopenharmony_ci  s->val[OPT_WAIT].w = SANE_FALSE;
1605141cc406Sopenharmony_ci
1606141cc406Sopenharmony_ci
1607141cc406Sopenharmony_ci  /* OneScanner Only options */
1608141cc406Sopenharmony_ci
1609141cc406Sopenharmony_ci  /* Calibrate before scanning ? */
1610141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATE].name = "calibrate";
1611141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATE].title = "Calibrate";
1612141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATE].desc = "You may avoid the calibration before "
1613141cc406Sopenharmony_ci      "scanning but this will lead you to lower image quality.";
1614141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATE].type = SANE_TYPE_BOOL;
1615141cc406Sopenharmony_ci  if (s->hw->ScannerModel != ONESCANNER)
1616141cc406Sopenharmony_ci    s->opt[OPT_CALIBRATE].cap |= SANE_CAP_INACTIVE;
1617141cc406Sopenharmony_ci  s->val[OPT_CALIBRATE].w = SANE_TRUE;
1618141cc406Sopenharmony_ci
1619141cc406Sopenharmony_ci  /* speed */
1620141cc406Sopenharmony_ci  s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED;
1621141cc406Sopenharmony_ci  s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED;
1622141cc406Sopenharmony_ci  s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED;
1623141cc406Sopenharmony_ci  s->opt[OPT_SPEED].type = SANE_TYPE_STRING;
1624141cc406Sopenharmony_ci  if (s->hw->ScannerModel != ONESCANNER)
1625141cc406Sopenharmony_ci    s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE;
1626141cc406Sopenharmony_ci  s->opt[OPT_SPEED].size = max_string_size (speed_list);
1627141cc406Sopenharmony_ci  s->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1628141cc406Sopenharmony_ci  s->opt[OPT_SPEED].constraint.string_list = speed_list;
1629141cc406Sopenharmony_ci  s->val[OPT_SPEED].s = strdup (speed_list[0]);
1630141cc406Sopenharmony_ci
1631141cc406Sopenharmony_ci  /* OneScanner & ColorOneScanner (LED && CCD) */
1632141cc406Sopenharmony_ci
1633141cc406Sopenharmony_ci  /* LED ? */
1634141cc406Sopenharmony_ci  s->opt[OPT_LED].name = "led";
1635141cc406Sopenharmony_ci  s->opt[OPT_LED].title = "LED";
1636141cc406Sopenharmony_ci  s->opt[OPT_LED].desc ="This option controls the setting of the ambler LED.";
1637141cc406Sopenharmony_ci  s->opt[OPT_LED].type = SANE_TYPE_BOOL;
1638141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=ONESCANNER && s->hw->ScannerModel!=COLORONESCANNER)
1639141cc406Sopenharmony_ci    s->opt[OPT_LED].cap |= SANE_CAP_INACTIVE;
1640141cc406Sopenharmony_ci  s->val[OPT_LED].w = SANE_TRUE;
1641141cc406Sopenharmony_ci
1642141cc406Sopenharmony_ci  /* CCD Power ? */
1643141cc406Sopenharmony_ci  s->opt[OPT_CCD].name = "ccd";
1644141cc406Sopenharmony_ci  s->opt[OPT_CCD].title = "CCD Power";
1645141cc406Sopenharmony_ci  s->opt[OPT_CCD].desc ="This option controls the power to the CCD array.";
1646141cc406Sopenharmony_ci  s->opt[OPT_CCD].type = SANE_TYPE_BOOL;
1647141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=ONESCANNER && s->hw->ScannerModel!=COLORONESCANNER)
1648141cc406Sopenharmony_ci    s->opt[OPT_CCD].cap |= SANE_CAP_INACTIVE;
1649141cc406Sopenharmony_ci  s->val[OPT_CCD].w = SANE_TRUE;
1650141cc406Sopenharmony_ci
1651141cc406Sopenharmony_ci  /*  Use MTF Circuit */
1652141cc406Sopenharmony_ci  s->opt[OPT_MTF_CIRCUIT].name = "mtf";
1653141cc406Sopenharmony_ci  s->opt[OPT_MTF_CIRCUIT].title = "MTF Circuit";
1654141cc406Sopenharmony_ci  s->opt[OPT_MTF_CIRCUIT].desc ="Turns the MTF (Modulation Transfer Function) "
1655141cc406Sopenharmony_ci						"peaking circuit on or off.";
1656141cc406Sopenharmony_ci  s->opt[OPT_MTF_CIRCUIT].type = SANE_TYPE_BOOL;
1657141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1658141cc406Sopenharmony_ci    s->opt[OPT_MTF_CIRCUIT].cap |= SANE_CAP_INACTIVE;
1659141cc406Sopenharmony_ci  s->val[OPT_MTF_CIRCUIT].w = SANE_TRUE;
1660141cc406Sopenharmony_ci
1661141cc406Sopenharmony_ci
1662141cc406Sopenharmony_ci  /* Use ICP */
1663141cc406Sopenharmony_ci  s->opt[OPT_ICP].name = "icp";
1664141cc406Sopenharmony_ci  s->opt[OPT_ICP].title = "ICP";
1665141cc406Sopenharmony_ci  s->opt[OPT_ICP].desc ="What is an ICP anyway?";
1666141cc406Sopenharmony_ci  s->opt[OPT_ICP].type = SANE_TYPE_BOOL;
1667141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1668141cc406Sopenharmony_ci    s->opt[OPT_ICP].cap |= SANE_CAP_INACTIVE;
1669141cc406Sopenharmony_ci  s->val[OPT_ICP].w = SANE_TRUE;
1670141cc406Sopenharmony_ci
1671141cc406Sopenharmony_ci
1672141cc406Sopenharmony_ci  /* Data Polarity */
1673141cc406Sopenharmony_ci  s->opt[OPT_POLARITY].name = "polarity";
1674141cc406Sopenharmony_ci  s->opt[OPT_POLARITY].title = "Data Polarity";
1675141cc406Sopenharmony_ci  s->opt[OPT_POLARITY].desc = "Reverse black and white.";
1676141cc406Sopenharmony_ci  s->opt[OPT_POLARITY].type = SANE_TYPE_BOOL;
1677141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1678141cc406Sopenharmony_ci    s->opt[OPT_POLARITY].cap |= SANE_CAP_INACTIVE;
1679141cc406Sopenharmony_ci  s->val[OPT_POLARITY].w = SANE_FALSE;
1680141cc406Sopenharmony_ci
1681141cc406Sopenharmony_ci
1682141cc406Sopenharmony_ci/* Color Functions: Advanced */
1683141cc406Sopenharmony_ci
1684141cc406Sopenharmony_ci  s->opt[OPT_COLOR_GROUP].title = SANE_VALUE_SCAN_MODE_COLOR;
1685141cc406Sopenharmony_ci  s->opt[OPT_COLOR_GROUP].desc = "";
1686141cc406Sopenharmony_ci  s->opt[OPT_COLOR_GROUP].type = SANE_TYPE_GROUP;
1687141cc406Sopenharmony_ci  s->opt[OPT_COLOR_GROUP].cap = SANE_CAP_ADVANCED;
1688141cc406Sopenharmony_ci  s->opt[OPT_COLOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1689141cc406Sopenharmony_ci
1690141cc406Sopenharmony_ci#ifdef CALIBRATION_FUNCTIONALITY
1691141cc406Sopenharmony_ci  /* OneScanner calibration vector */
1692141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].name = "calibration-vector";
1693141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].title = "Calibration Vector";
1694141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].desc = "Calibration vector for the CCD array.";
1695141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].type = SANE_TYPE_INT;
1696141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=ONESCANNER)
1697141cc406Sopenharmony_ci    s->opt[OPT_CALIBRATION_VECTOR].cap |= SANE_CAP_INACTIVE;
1698141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].unit = SANE_UNIT_NONE;
1699141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].size = 2550 * sizeof (SANE_Word);
1700141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
1701141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR].constraint.range = &u8_range;
1702141cc406Sopenharmony_ci  s->val[OPT_CALIBRATION_VECTOR].wa = s->calibration_vector;
1703141cc406Sopenharmony_ci
1704141cc406Sopenharmony_ci  /* ColorOneScanner calibration vector per band */
1705141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].name = "calibration-vector-red";
1706141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].title = "Calibration Vector for Red";
1707141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].desc = "Calibration vector for the CCD array.";
1708141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].type = SANE_TYPE_INT;
1709141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1710141cc406Sopenharmony_ci    s->opt[OPT_CALIBRATION_VECTOR_RED].cap |= SANE_CAP_INACTIVE;
1711141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].unit = SANE_UNIT_NONE;
1712141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].size = 2700 * sizeof (SANE_Word);
1713141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].constraint_type = SANE_CONSTRAINT_RANGE;
1714141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_RED].constraint.range = &u8_range;
1715141cc406Sopenharmony_ci  s->val[OPT_CALIBRATION_VECTOR_RED].wa = s->calibration_vector_red;
1716141cc406Sopenharmony_ci
1717141cc406Sopenharmony_ci  /* ColorOneScanner calibration vector per band */
1718141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].name = "calibration-vector-green";
1719141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].title = "Calibration Vector for Green";
1720141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].desc = "Calibration vector for the CCD array.";
1721141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].type = SANE_TYPE_INT;
1722141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1723141cc406Sopenharmony_ci    s->opt[OPT_CALIBRATION_VECTOR].cap |= SANE_CAP_INACTIVE;
1724141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].unit = SANE_UNIT_NONE;
1725141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].size = 2700 * sizeof (SANE_Word);
1726141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].constraint_type = SANE_CONSTRAINT_RANGE;
1727141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_GREEN].constraint.range = &u8_range;
1728141cc406Sopenharmony_ci  s->val[OPT_CALIBRATION_VECTOR_GREEN].wa = s->calibration_vector_green;
1729141cc406Sopenharmony_ci
1730141cc406Sopenharmony_ci  /* ColorOneScanner calibration vector per band */
1731141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].name = "calibration-vector-blue";
1732141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].title = "Calibration Vector for Blue";
1733141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].desc = "Calibration vector for the CCD array.";
1734141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].type = SANE_TYPE_INT;
1735141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1736141cc406Sopenharmony_ci    s->opt[OPT_CALIBRATION_VECTOR_BLUE].cap |= SANE_CAP_INACTIVE;
1737141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].unit = SANE_UNIT_NONE;
1738141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].size = 2700 * sizeof (SANE_Word);
1739141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].constraint_type = SANE_CONSTRAINT_RANGE;
1740141cc406Sopenharmony_ci  s->opt[OPT_CALIBRATION_VECTOR_BLUE].constraint.range = &u8_range;
1741141cc406Sopenharmony_ci  s->val[OPT_CALIBRATION_VECTOR_BLUE].wa = s->calibration_vector_blue;
1742141cc406Sopenharmony_ci#endif /* CALIBRATION_FUNCTIONALITY */
1743141cc406Sopenharmony_ci
1744141cc406Sopenharmony_ci  /* Action: Download calibration vector */
1745141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].name = "download-calibration";
1746141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].title = "Download Calibration Vector";
1747141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].desc = "Download calibration vector to scanner";
1748141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].type = SANE_TYPE_BUTTON;
1749141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=ONESCANNER && s->hw->ScannerModel!=COLORONESCANNER)
1750141cc406Sopenharmony_ci    s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].cap |= SANE_CAP_INACTIVE;
1751141cc406Sopenharmony_ci
1752141cc406Sopenharmony_ci  /* custom-cct table */
1753141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_CCT].name = "custom-cct";
1754141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_CCT].title = "Use Custom CCT";
1755141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_CCT].desc ="Determines whether a builtin "
1756141cc406Sopenharmony_ci	"or a custom 3x3 Color Correction Table (CCT) should be used.";
1757141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_CCT].type = SANE_TYPE_BOOL;
1758141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_CCT].cap |= SANE_CAP_INACTIVE;
1759141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1760141cc406Sopenharmony_ci    s->opt[OPT_CUSTOM_CCT].cap |= SANE_CAP_INACTIVE;
1761141cc406Sopenharmony_ci  s->val[OPT_CUSTOM_CCT].w = SANE_FALSE;
1762141cc406Sopenharmony_ci
1763141cc406Sopenharmony_ci
1764141cc406Sopenharmony_ci  /* CCT */
1765141cc406Sopenharmony_ci  s->opt[OPT_CCT].name = "cct";
1766141cc406Sopenharmony_ci  s->opt[OPT_CCT].title = "3x3 Color Correction Table";
1767141cc406Sopenharmony_ci  s->opt[OPT_CCT].desc = "TODO: Color Correction is currently unsupported";
1768141cc406Sopenharmony_ci  s->opt[OPT_CCT].type = SANE_TYPE_FIXED;
1769141cc406Sopenharmony_ci  s->opt[OPT_CCT].cap |= SANE_CAP_INACTIVE;
1770141cc406Sopenharmony_ci  s->opt[OPT_CCT].unit = SANE_UNIT_NONE;
1771141cc406Sopenharmony_ci  s->opt[OPT_CCT].size = 9 * sizeof (SANE_Word);
1772141cc406Sopenharmony_ci  s->opt[OPT_CCT].constraint_type = SANE_CONSTRAINT_RANGE;
1773141cc406Sopenharmony_ci  s->opt[OPT_CCT].constraint.range = &u8_range;
1774141cc406Sopenharmony_ci  s->val[OPT_CCT].wa = s->cct3x3;
1775141cc406Sopenharmony_ci
1776141cc406Sopenharmony_ci
1777141cc406Sopenharmony_ci  /* Action: custom 3x3 color correction table */
1778141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CCT].name = "download-3x3";
1779141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CCT].title = "Download 3x3 CCT";
1780141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CCT].desc = "Download 3x3 color correction table";
1781141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_CCT].type = SANE_TYPE_BUTTON;
1782141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1783141cc406Sopenharmony_ci    s->opt[OPT_DOWNLOAD_CCT].cap |= SANE_CAP_INACTIVE;
1784141cc406Sopenharmony_ci
1785141cc406Sopenharmony_ci
1786141cc406Sopenharmony_ci  /* custom-gamma table */
1787141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
1788141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
1789141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
1790141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
1791141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
1792141cc406Sopenharmony_ci  s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE;
1793141cc406Sopenharmony_ci
1794141cc406Sopenharmony_ci  /* red gamma vector */
1795141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
1796141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
1797141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
1798141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
1799141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
1800141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
1801141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word);
1802141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
1803141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range;
1804141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[0][0];
1805141cc406Sopenharmony_ci
1806141cc406Sopenharmony_ci  /* green gamma vector */
1807141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
1808141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
1809141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
1810141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
1811141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
1812141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
1813141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word);
1814141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
1815141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range;
1816141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[1][0];
1817141cc406Sopenharmony_ci
1818141cc406Sopenharmony_ci  /* blue gamma vector */
1819141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
1820141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
1821141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
1822141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
1823141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
1824141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
1825141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word);
1826141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
1827141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range;
1828141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[2][0];
1829141cc406Sopenharmony_ci
1830141cc406Sopenharmony_ci  /* Action: download gamma vectors table */
1831141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_GAMMA].name = "download-gamma";
1832141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_GAMMA].title = "Download Gamma Vector(s)";
1833141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_GAMMA].desc = "Download Gamma Vector(s).";
1834141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_GAMMA].type = SANE_TYPE_BUTTON;
1835141cc406Sopenharmony_ci  s->opt[OPT_DOWNLOAD_GAMMA].cap |= SANE_CAP_INACTIVE;
1836141cc406Sopenharmony_ci
1837141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].name = "color-sensor";
1838141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].title = "Gray scan with";
1839141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].desc = "Select the color sensor to scan in gray mode.";
1840141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].type = SANE_TYPE_STRING;
1841141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].unit = SANE_UNIT_NONE;
1842141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].size = max_string_size (color_sensor_list);
1843141cc406Sopenharmony_ci  if (s->hw->ScannerModel!=COLORONESCANNER)
1844141cc406Sopenharmony_ci    s->opt[OPT_COLOR_SENSOR].cap |= SANE_CAP_INACTIVE;
1845141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1846141cc406Sopenharmony_ci  s->opt[OPT_COLOR_SENSOR].constraint.string_list = color_sensor_list;
1847141cc406Sopenharmony_ci  s->val[OPT_COLOR_SENSOR].s = strdup(color_sensor_list[2]);
1848141cc406Sopenharmony_ci
1849141cc406Sopenharmony_ci
1850141cc406Sopenharmony_ci  mode_update (s, s->val[OPT_MODE].s);
1851141cc406Sopenharmony_ci
1852141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1853141cc406Sopenharmony_ci}
1854141cc406Sopenharmony_ci
1855141cc406Sopenharmony_cistatic SANE_Status
1856141cc406Sopenharmony_ciattach_one (const char *dev)
1857141cc406Sopenharmony_ci{
1858141cc406Sopenharmony_ci  attach (dev, 0, SANE_FALSE);
1859141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1860141cc406Sopenharmony_ci}
1861141cc406Sopenharmony_ci
1862141cc406Sopenharmony_ciSANE_Status
1863141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
1864141cc406Sopenharmony_ci{
1865141cc406Sopenharmony_ci  char dev_name[PATH_MAX];
1866141cc406Sopenharmony_ci  size_t len;
1867141cc406Sopenharmony_ci  FILE *fp;
1868141cc406Sopenharmony_ci
1869141cc406Sopenharmony_ci  (void) authorize;			/* silence gcc */
1870141cc406Sopenharmony_ci
1871141cc406Sopenharmony_ci  DBG_INIT ();
1872141cc406Sopenharmony_ci
1873141cc406Sopenharmony_ci  if (version_code)
1874141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
1875141cc406Sopenharmony_ci
1876141cc406Sopenharmony_ci  fp = sanei_config_open (APPLE_CONFIG_FILE);
1877141cc406Sopenharmony_ci  if (!fp)
1878141cc406Sopenharmony_ci    {
1879141cc406Sopenharmony_ci      /* default to /dev/scanner instead of insisting on config file */
1880141cc406Sopenharmony_ci      attach ("/dev/scanner", 0, SANE_FALSE);
1881141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
1882141cc406Sopenharmony_ci    }
1883141cc406Sopenharmony_ci
1884141cc406Sopenharmony_ci  while (sanei_config_read (dev_name, sizeof (dev_name), fp))
1885141cc406Sopenharmony_ci    {
1886141cc406Sopenharmony_ci      if (dev_name[0] == '#')	/* ignore line comments */
1887141cc406Sopenharmony_ci	continue;
1888141cc406Sopenharmony_ci
1889141cc406Sopenharmony_ci      len = strlen (dev_name);
1890141cc406Sopenharmony_ci
1891141cc406Sopenharmony_ci      if (!len)
1892141cc406Sopenharmony_ci	continue;		/* ignore empty lines */
1893141cc406Sopenharmony_ci
1894141cc406Sopenharmony_ci      if (strncmp (dev_name, "option", 6) == 0
1895141cc406Sopenharmony_ci	  && isspace (dev_name[6]))
1896141cc406Sopenharmony_ci	{
1897141cc406Sopenharmony_ci	  const char *str = dev_name + 7;
1898141cc406Sopenharmony_ci
1899141cc406Sopenharmony_ci	  while (isspace (*str))
1900141cc406Sopenharmony_ci	    ++str;
1901141cc406Sopenharmony_ci
1902141cc406Sopenharmony_ci	  continue;
1903141cc406Sopenharmony_ci	}
1904141cc406Sopenharmony_ci
1905141cc406Sopenharmony_ci      sanei_config_attach_matching_devices (dev_name, attach_one);
1906141cc406Sopenharmony_ci    }
1907141cc406Sopenharmony_ci  fclose (fp);
1908141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1909141cc406Sopenharmony_ci}
1910141cc406Sopenharmony_ci
1911141cc406Sopenharmony_civoid
1912141cc406Sopenharmony_cisane_exit (void)
1913141cc406Sopenharmony_ci{
1914141cc406Sopenharmony_ci  Apple_Device *dev, *next;
1915141cc406Sopenharmony_ci
1916141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = next)
1917141cc406Sopenharmony_ci    {
1918141cc406Sopenharmony_ci      next = dev->next;
1919141cc406Sopenharmony_ci      free ((void *) dev->sane.name);
1920141cc406Sopenharmony_ci      free ((void *) dev->sane.model);
1921141cc406Sopenharmony_ci      free (dev);
1922141cc406Sopenharmony_ci    }
1923141cc406Sopenharmony_ci  if (devlist)
1924141cc406Sopenharmony_ci    free (devlist);
1925141cc406Sopenharmony_ci}
1926141cc406Sopenharmony_ci
1927141cc406Sopenharmony_ciSANE_Status
1928141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1929141cc406Sopenharmony_ci{
1930141cc406Sopenharmony_ci  Apple_Device *dev;
1931141cc406Sopenharmony_ci  int i;
1932141cc406Sopenharmony_ci
1933141cc406Sopenharmony_ci  (void) local_only;			/* silence gcc */
1934141cc406Sopenharmony_ci
1935141cc406Sopenharmony_ci  if (devlist)
1936141cc406Sopenharmony_ci    free (devlist);
1937141cc406Sopenharmony_ci
1938141cc406Sopenharmony_ci  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
1939141cc406Sopenharmony_ci  if (!devlist)
1940141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
1941141cc406Sopenharmony_ci
1942141cc406Sopenharmony_ci  i = 0;
1943141cc406Sopenharmony_ci  for (dev = first_dev; i < num_devices; dev = dev->next)
1944141cc406Sopenharmony_ci    devlist[i++] = &dev->sane;
1945141cc406Sopenharmony_ci  devlist[i++] = 0;
1946141cc406Sopenharmony_ci
1947141cc406Sopenharmony_ci  *device_list = devlist;
1948141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1949141cc406Sopenharmony_ci}
1950141cc406Sopenharmony_ci
1951141cc406Sopenharmony_ciSANE_Status
1952141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle)
1953141cc406Sopenharmony_ci{
1954141cc406Sopenharmony_ci  Apple_Device *dev;
1955141cc406Sopenharmony_ci  SANE_Status status;
1956141cc406Sopenharmony_ci  Apple_Scanner *s;
1957141cc406Sopenharmony_ci  int i, j;
1958141cc406Sopenharmony_ci
1959141cc406Sopenharmony_ci  if (devicename[0])
1960141cc406Sopenharmony_ci    {
1961141cc406Sopenharmony_ci      for (dev = first_dev; dev; dev = dev->next)
1962141cc406Sopenharmony_ci	if (strcmp (dev->sane.name, devicename) == 0)
1963141cc406Sopenharmony_ci	  break;
1964141cc406Sopenharmony_ci
1965141cc406Sopenharmony_ci      if (!dev)
1966141cc406Sopenharmony_ci	{
1967141cc406Sopenharmony_ci	  status = attach (devicename, &dev, SANE_TRUE);
1968141cc406Sopenharmony_ci	  if (status != SANE_STATUS_GOOD)
1969141cc406Sopenharmony_ci	    return status;
1970141cc406Sopenharmony_ci	}
1971141cc406Sopenharmony_ci    }
1972141cc406Sopenharmony_ci  else
1973141cc406Sopenharmony_ci    /* empty devicname -> use first device */
1974141cc406Sopenharmony_ci    dev = first_dev;
1975141cc406Sopenharmony_ci
1976141cc406Sopenharmony_ci  if (!dev)
1977141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
1978141cc406Sopenharmony_ci
1979141cc406Sopenharmony_ci  s = malloc (sizeof (*s));
1980141cc406Sopenharmony_ci  if (!s)
1981141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
1982141cc406Sopenharmony_ci  memset (s, 0, sizeof (*s));
1983141cc406Sopenharmony_ci  s->fd = -1;
1984141cc406Sopenharmony_ci  s->hw = dev;
1985141cc406Sopenharmony_ci  for (i = 0; i < 3; ++i)
1986141cc406Sopenharmony_ci    for (j = 0; j < 256; ++j)
1987141cc406Sopenharmony_ci      s->gamma_table[i][j] = j;
1988141cc406Sopenharmony_ci
1989141cc406Sopenharmony_ci  init_options (s);
1990141cc406Sopenharmony_ci
1991141cc406Sopenharmony_ci  /* insert newly opened handle into list of open handles: */
1992141cc406Sopenharmony_ci  s->next = first_handle;
1993141cc406Sopenharmony_ci  first_handle = s;
1994141cc406Sopenharmony_ci
1995141cc406Sopenharmony_ci  *handle = s;
1996141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1997141cc406Sopenharmony_ci}
1998141cc406Sopenharmony_ci
1999141cc406Sopenharmony_civoid
2000141cc406Sopenharmony_cisane_close (SANE_Handle handle)
2001141cc406Sopenharmony_ci{
2002141cc406Sopenharmony_ci  Apple_Scanner *prev, *s;
2003141cc406Sopenharmony_ci
2004141cc406Sopenharmony_ci  /* remove handle from list of open handles: */
2005141cc406Sopenharmony_ci  prev = 0;
2006141cc406Sopenharmony_ci  for (s = first_handle; s; s = s->next)
2007141cc406Sopenharmony_ci    {
2008141cc406Sopenharmony_ci      if (s == handle)
2009141cc406Sopenharmony_ci	break;
2010141cc406Sopenharmony_ci      prev = s;
2011141cc406Sopenharmony_ci    }
2012141cc406Sopenharmony_ci  if (!s)
2013141cc406Sopenharmony_ci    {
2014141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "close: invalid handle %p\n", handle);
2015141cc406Sopenharmony_ci      return;			/* oops, not a handle we know about */
2016141cc406Sopenharmony_ci    }
2017141cc406Sopenharmony_ci
2018141cc406Sopenharmony_ci  if (prev)
2019141cc406Sopenharmony_ci    prev->next = s->next;
2020141cc406Sopenharmony_ci  else
2021141cc406Sopenharmony_ci    first_handle = s->next;
2022141cc406Sopenharmony_ci
2023141cc406Sopenharmony_ci  free (handle);
2024141cc406Sopenharmony_ci}
2025141cc406Sopenharmony_ci
2026141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
2027141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2028141cc406Sopenharmony_ci{
2029141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
2030141cc406Sopenharmony_ci
2031141cc406Sopenharmony_ci  if ((unsigned) option >= NUM_OPTIONS)
2032141cc406Sopenharmony_ci    return 0;
2033141cc406Sopenharmony_ci  return s->opt + option;
2034141cc406Sopenharmony_ci}
2035141cc406Sopenharmony_ci
2036141cc406Sopenharmony_ciSANE_Status
2037141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
2038141cc406Sopenharmony_ci		     SANE_Action action, void *val, SANE_Int * info)
2039141cc406Sopenharmony_ci{
2040141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
2041141cc406Sopenharmony_ci  SANE_Status status;
2042141cc406Sopenharmony_ci  SANE_Word cap;
2043141cc406Sopenharmony_ci
2044141cc406Sopenharmony_ci
2045141cc406Sopenharmony_ci  DBG (FLOW_CONTROL, "(%s): Entering on control_option for option %s (%d).\n",
2046141cc406Sopenharmony_ci       (action == SANE_ACTION_GET_VALUE) ? "get" : "set",
2047141cc406Sopenharmony_ci       s->opt[option].name, option);
2048141cc406Sopenharmony_ci
2049141cc406Sopenharmony_ci  if (val || action == SANE_ACTION_GET_VALUE)
2050141cc406Sopenharmony_ci    switch (s->opt[option].type)
2051141cc406Sopenharmony_ci      {
2052141cc406Sopenharmony_ci      case SANE_TYPE_STRING:
2053141cc406Sopenharmony_ci	DBG (FLOW_CONTROL, "Value %s\n", (action == SANE_ACTION_GET_VALUE) ?
2054141cc406Sopenharmony_ci	  s->val[option].s : (char *) val);
2055141cc406Sopenharmony_ci	break;
2056141cc406Sopenharmony_ci      case SANE_TYPE_FIXED:
2057141cc406Sopenharmony_ci	{
2058141cc406Sopenharmony_ci	double v1, v2;
2059141cc406Sopenharmony_ci	SANE_Fixed f;
2060141cc406Sopenharmony_ci	v1 = SANE_UNFIX (s->val[option].w);
2061141cc406Sopenharmony_ci	f = *(SANE_Fixed *) val;
2062141cc406Sopenharmony_ci	v2 = SANE_UNFIX (f);
2063141cc406Sopenharmony_ci	DBG (FLOW_CONTROL, "Value %g (Fixed)\n",
2064141cc406Sopenharmony_ci	     (action == SANE_ACTION_GET_VALUE) ? v1 : v2);
2065141cc406Sopenharmony_ci	break;
2066141cc406Sopenharmony_ci	}
2067141cc406Sopenharmony_ci      default:
2068141cc406Sopenharmony_ci	DBG (FLOW_CONTROL, "Value %u (Int).\n",
2069141cc406Sopenharmony_ci		(action == SANE_ACTION_GET_VALUE)
2070141cc406Sopenharmony_ci			? s->val[option].w : *(SANE_Int *) val);
2071141cc406Sopenharmony_ci	break;
2072141cc406Sopenharmony_ci      }
2073141cc406Sopenharmony_ci
2074141cc406Sopenharmony_ci
2075141cc406Sopenharmony_ci  if (info)
2076141cc406Sopenharmony_ci    *info = 0;
2077141cc406Sopenharmony_ci
2078141cc406Sopenharmony_ci  if (s->scanning)
2079141cc406Sopenharmony_ci    return SANE_STATUS_DEVICE_BUSY;
2080141cc406Sopenharmony_ci
2081141cc406Sopenharmony_ci  if (option >= NUM_OPTIONS)
2082141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
2083141cc406Sopenharmony_ci
2084141cc406Sopenharmony_ci  cap = s->opt[option].cap;
2085141cc406Sopenharmony_ci
2086141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (cap))
2087141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
2088141cc406Sopenharmony_ci
2089141cc406Sopenharmony_ci
2090141cc406Sopenharmony_ci  if (action == SANE_ACTION_GET_VALUE)
2091141cc406Sopenharmony_ci    {
2092141cc406Sopenharmony_ci      switch (option)
2093141cc406Sopenharmony_ci	{
2094141cc406Sopenharmony_ci	  /* word options: */
2095141cc406Sopenharmony_ci	case OPT_NUM_OPTS:
2096141cc406Sopenharmony_ci	case OPT_RESOLUTION:
2097141cc406Sopenharmony_ci	case OPT_PREVIEW:
2098141cc406Sopenharmony_ci	case OPT_TL_X:
2099141cc406Sopenharmony_ci	case OPT_TL_Y:
2100141cc406Sopenharmony_ci	case OPT_BR_X:
2101141cc406Sopenharmony_ci	case OPT_BR_Y:
2102141cc406Sopenharmony_ci	case OPT_BRIGHTNESS:
2103141cc406Sopenharmony_ci	case OPT_CONTRAST:
2104141cc406Sopenharmony_ci	case OPT_THRESHOLD:
2105141cc406Sopenharmony_ci	case OPT_AUTOBACKGROUND:
2106141cc406Sopenharmony_ci	case OPT_AUTOBACKGROUND_THRESHOLD:
2107141cc406Sopenharmony_ci	case OPT_VOLT_REF:
2108141cc406Sopenharmony_ci	case OPT_VOLT_REF_TOP:
2109141cc406Sopenharmony_ci	case OPT_VOLT_REF_BOTTOM:
2110141cc406Sopenharmony_ci
2111141cc406Sopenharmony_ci	case OPT_LAMP:
2112141cc406Sopenharmony_ci	case OPT_WAIT:
2113141cc406Sopenharmony_ci	case OPT_CALIBRATE:
2114141cc406Sopenharmony_ci	case OPT_LED:
2115141cc406Sopenharmony_ci	case OPT_CCD:
2116141cc406Sopenharmony_ci	case OPT_MTF_CIRCUIT:
2117141cc406Sopenharmony_ci	case OPT_ICP:
2118141cc406Sopenharmony_ci	case OPT_POLARITY:
2119141cc406Sopenharmony_ci
2120141cc406Sopenharmony_ci	case OPT_CUSTOM_CCT:
2121141cc406Sopenharmony_ci	case OPT_CUSTOM_GAMMA:
2122141cc406Sopenharmony_ci	  *(SANE_Word *) val = s->val[option].w;
2123141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2124141cc406Sopenharmony_ci
2125141cc406Sopenharmony_ci	  /* word-array options: */
2126141cc406Sopenharmony_ci
2127141cc406Sopenharmony_ci	case OPT_CCT:
2128141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_R:
2129141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_G:
2130141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_B:
2131141cc406Sopenharmony_ci	  memcpy (val, s->val[option].wa, s->opt[option].size);
2132141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2133141cc406Sopenharmony_ci
2134141cc406Sopenharmony_ci	  /* string options: */
2135141cc406Sopenharmony_ci
2136141cc406Sopenharmony_ci	case OPT_MODE:
2137141cc406Sopenharmony_ci/*
2138141cc406Sopenharmony_ciTODO: This is to protect the mode string to be ruined from the dll?
2139141cc406Sopenharmony_cibackend. I do not know why. It's definitely an overkill and should be
2140141cc406Sopenharmony_cieliminated.
2141141cc406Sopenharmony_ci	  status = sanei_constrain_value (s->opt + option, s->val[option].s,
2142141cc406Sopenharmony_ci					  info);
2143141cc406Sopenharmony_ci*/
2144141cc406Sopenharmony_ci	case OPT_MODEL:
2145141cc406Sopenharmony_ci	case OPT_GRAYMAP:
2146141cc406Sopenharmony_ci	case OPT_HALFTONE_PATTERN:
2147141cc406Sopenharmony_ci	case OPT_HALFTONE_FILE:
2148141cc406Sopenharmony_ci	case OPT_SPEED:
2149141cc406Sopenharmony_ci	case OPT_COLOR_SENSOR:
2150141cc406Sopenharmony_ci	  strcpy (val, s->val[option].s);
2151141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2152141cc406Sopenharmony_ci
2153141cc406Sopenharmony_ci/* Some Buttons */
2154141cc406Sopenharmony_ci	case OPT_DOWNLOAD_CALIBRATION_VECTOR:
2155141cc406Sopenharmony_ci	case OPT_DOWNLOAD_CCT:
2156141cc406Sopenharmony_ci	case OPT_DOWNLOAD_GAMMA:
2157141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2158141cc406Sopenharmony_ci
2159141cc406Sopenharmony_ci	}
2160141cc406Sopenharmony_ci    }
2161141cc406Sopenharmony_ci  else if (action == SANE_ACTION_SET_VALUE)
2162141cc406Sopenharmony_ci    {
2163141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (cap))
2164141cc406Sopenharmony_ci	return SANE_STATUS_INVAL;
2165141cc406Sopenharmony_ci
2166141cc406Sopenharmony_ci      status = sanei_constrain_value (s->opt + option, val, info);
2167141cc406Sopenharmony_ci
2168141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2169141cc406Sopenharmony_ci	return status;
2170141cc406Sopenharmony_ci
2171141cc406Sopenharmony_ci
2172141cc406Sopenharmony_ci      switch (option)
2173141cc406Sopenharmony_ci	{
2174141cc406Sopenharmony_ci	  /* (mostly) side-effect-free word options: */
2175141cc406Sopenharmony_ci	case OPT_RESOLUTION:
2176141cc406Sopenharmony_ci	case OPT_TL_X:
2177141cc406Sopenharmony_ci	case OPT_TL_Y:
2178141cc406Sopenharmony_ci	case OPT_BR_X:
2179141cc406Sopenharmony_ci	case OPT_BR_Y:
2180141cc406Sopenharmony_ci
2181141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Word *) val;
2182141cc406Sopenharmony_ci	  calc_parameters (s);
2183141cc406Sopenharmony_ci
2184141cc406Sopenharmony_ci	  if (info)
2185141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_PARAMS
2186141cc406Sopenharmony_ci	      | SANE_INFO_RELOAD_OPTIONS
2187141cc406Sopenharmony_ci	      | SANE_INFO_INEXACT;
2188141cc406Sopenharmony_ci
2189141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2190141cc406Sopenharmony_ci
2191141cc406Sopenharmony_ci	  /* fall through */
2192141cc406Sopenharmony_ci	case OPT_BRIGHTNESS:
2193141cc406Sopenharmony_ci	case OPT_CONTRAST:
2194141cc406Sopenharmony_ci	case OPT_THRESHOLD:
2195141cc406Sopenharmony_ci	case OPT_AUTOBACKGROUND_THRESHOLD:
2196141cc406Sopenharmony_ci	case OPT_VOLT_REF_TOP:
2197141cc406Sopenharmony_ci	case OPT_VOLT_REF_BOTTOM:
2198141cc406Sopenharmony_ci	case OPT_LAMP:
2199141cc406Sopenharmony_ci	case OPT_WAIT:
2200141cc406Sopenharmony_ci	case OPT_CALIBRATE:
2201141cc406Sopenharmony_ci	case OPT_LED:
2202141cc406Sopenharmony_ci	case OPT_CCD:
2203141cc406Sopenharmony_ci	case OPT_MTF_CIRCUIT:
2204141cc406Sopenharmony_ci	case OPT_ICP:
2205141cc406Sopenharmony_ci	case OPT_POLARITY:
2206141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Word *) val;
2207141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2208141cc406Sopenharmony_ci
2209141cc406Sopenharmony_ci	  /* Simple Strings */
2210141cc406Sopenharmony_ci	case OPT_GRAYMAP:
2211141cc406Sopenharmony_ci	case OPT_HALFTONE_FILE:
2212141cc406Sopenharmony_ci	case OPT_SPEED:
2213141cc406Sopenharmony_ci	  if (s->val[option].s)
2214141cc406Sopenharmony_ci	    free (s->val[option].s);
2215141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2216141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2217141cc406Sopenharmony_ci
2218141cc406Sopenharmony_ci	  /* Boolean */
2219141cc406Sopenharmony_ci	case OPT_PREVIEW:
2220141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Bool *) val;
2221141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2222141cc406Sopenharmony_ci
2223141cc406Sopenharmony_ci
2224141cc406Sopenharmony_ci	  /* side-effect-free word-array options: */
2225141cc406Sopenharmony_ci	case OPT_CCT:
2226141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_R:
2227141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_G:
2228141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_B:
2229141cc406Sopenharmony_ci	  memcpy (s->val[option].wa, val, s->opt[option].size);
2230141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2231141cc406Sopenharmony_ci
2232141cc406Sopenharmony_ci
2233141cc406Sopenharmony_ci	  /* options with light side-effects: */
2234141cc406Sopenharmony_ci
2235141cc406Sopenharmony_ci	case OPT_HALFTONE_PATTERN:
2236141cc406Sopenharmony_ci	  if (info)
2237141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS;
2238141cc406Sopenharmony_ci	  if (s->val[option].s)
2239141cc406Sopenharmony_ci	    free (s->val[option].s);
2240141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2241141cc406Sopenharmony_ci	  if (!strcmp (val, "download"))
2242141cc406Sopenharmony_ci	    {
2243141cc406Sopenharmony_ci	      return SANE_STATUS_UNSUPPORTED;
2244141cc406Sopenharmony_ci	      /* TODO: ENABLE(OPT_HALFTONE_FILE); */
2245141cc406Sopenharmony_ci	    }
2246141cc406Sopenharmony_ci	  else
2247141cc406Sopenharmony_ci	    DISABLE (OPT_HALFTONE_FILE);
2248141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2249141cc406Sopenharmony_ci
2250141cc406Sopenharmony_ci	case OPT_AUTOBACKGROUND:
2251141cc406Sopenharmony_ci	  if (info)
2252141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS;
2253141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Bool *) val;
2254141cc406Sopenharmony_ci	  if (*(SANE_Bool *) val)
2255141cc406Sopenharmony_ci	    {
2256141cc406Sopenharmony_ci	      DISABLE (OPT_THRESHOLD);
2257141cc406Sopenharmony_ci	      ENABLE (OPT_AUTOBACKGROUND_THRESHOLD);
2258141cc406Sopenharmony_ci	    }
2259141cc406Sopenharmony_ci	  else
2260141cc406Sopenharmony_ci	    {
2261141cc406Sopenharmony_ci	      ENABLE (OPT_THRESHOLD);
2262141cc406Sopenharmony_ci	      DISABLE (OPT_AUTOBACKGROUND_THRESHOLD);
2263141cc406Sopenharmony_ci	    }
2264141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2265141cc406Sopenharmony_ci	case OPT_VOLT_REF:
2266141cc406Sopenharmony_ci	  if (info)
2267141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS;
2268141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Bool *) val;
2269141cc406Sopenharmony_ci	  if (*(SANE_Bool *) val)
2270141cc406Sopenharmony_ci	    {
2271141cc406Sopenharmony_ci	    DISABLE(OPT_BRIGHTNESS);
2272141cc406Sopenharmony_ci	    DISABLE(OPT_CONTRAST);
2273141cc406Sopenharmony_ci	    ENABLE(OPT_VOLT_REF_TOP);
2274141cc406Sopenharmony_ci	    ENABLE(OPT_VOLT_REF_BOTTOM);
2275141cc406Sopenharmony_ci	    }
2276141cc406Sopenharmony_ci	  else
2277141cc406Sopenharmony_ci	    {
2278141cc406Sopenharmony_ci	    ENABLE(OPT_BRIGHTNESS);
2279141cc406Sopenharmony_ci	    ENABLE(OPT_CONTRAST);
2280141cc406Sopenharmony_ci	    DISABLE(OPT_VOLT_REF_TOP);
2281141cc406Sopenharmony_ci	    DISABLE(OPT_VOLT_REF_BOTTOM);
2282141cc406Sopenharmony_ci	    }
2283141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2284141cc406Sopenharmony_ci
2285141cc406Sopenharmony_ci/* Actions: Buttons */
2286141cc406Sopenharmony_ci
2287141cc406Sopenharmony_ci	case OPT_DOWNLOAD_CALIBRATION_VECTOR:
2288141cc406Sopenharmony_ci	case OPT_DOWNLOAD_CCT:
2289141cc406Sopenharmony_ci	case OPT_DOWNLOAD_GAMMA:
2290141cc406Sopenharmony_ci	  /* TODO: fix {down/up}loads */
2291141cc406Sopenharmony_ci	  return SANE_STATUS_UNSUPPORTED;
2292141cc406Sopenharmony_ci
2293141cc406Sopenharmony_ci	case OPT_CUSTOM_CCT:
2294141cc406Sopenharmony_ci	  s->val[OPT_CUSTOM_CCT].w=*(SANE_Word *) val;
2295141cc406Sopenharmony_ci	  if (s->val[OPT_CUSTOM_CCT].w)
2296141cc406Sopenharmony_ci	    {
2297141cc406Sopenharmony_ci		ENABLE(OPT_CCT);
2298141cc406Sopenharmony_ci		ENABLE(OPT_DOWNLOAD_CCT);
2299141cc406Sopenharmony_ci	    }
2300141cc406Sopenharmony_ci	  else
2301141cc406Sopenharmony_ci	    {
2302141cc406Sopenharmony_ci		DISABLE(OPT_CCT);
2303141cc406Sopenharmony_ci		DISABLE(OPT_DOWNLOAD_CCT);
2304141cc406Sopenharmony_ci	    }
2305141cc406Sopenharmony_ci	  if (info)
2306141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS;
2307141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2308141cc406Sopenharmony_ci
2309141cc406Sopenharmony_ci	case OPT_CUSTOM_GAMMA:
2310141cc406Sopenharmony_ci	  s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val;
2311141cc406Sopenharmony_ci	  gamma_update(s);
2312141cc406Sopenharmony_ci	  if (info)
2313141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS;
2314141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2315141cc406Sopenharmony_ci
2316141cc406Sopenharmony_ci	case OPT_COLOR_SENSOR:
2317141cc406Sopenharmony_ci	  if (s->val[option].s)
2318141cc406Sopenharmony_ci	    free (s->val[option].s);
2319141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2320141cc406Sopenharmony_ci	  gamma_update(s);
2321141cc406Sopenharmony_ci	  if (info)
2322141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2323141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2324141cc406Sopenharmony_ci
2325141cc406Sopenharmony_ci	  /* HEAVY (RADIOACTIVE) SIDE EFFECTS: CHECKME */
2326141cc406Sopenharmony_ci	case OPT_MODE:
2327141cc406Sopenharmony_ci	  if (s->val[option].s)
2328141cc406Sopenharmony_ci	    free (s->val[option].s);
2329141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2330141cc406Sopenharmony_ci
2331141cc406Sopenharmony_ci	  status = mode_update (s, val);
2332141cc406Sopenharmony_ci	  if (status != SANE_STATUS_GOOD)
2333141cc406Sopenharmony_ci	    return status;
2334141cc406Sopenharmony_ci
2335141cc406Sopenharmony_ci	  if (info)
2336141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2337141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2338141cc406Sopenharmony_ci
2339141cc406Sopenharmony_ci	}			/* End of switch */
2340141cc406Sopenharmony_ci    }				/* End of SET_VALUE */
2341141cc406Sopenharmony_ci  return SANE_STATUS_INVAL;
2342141cc406Sopenharmony_ci}
2343141cc406Sopenharmony_ci
2344141cc406Sopenharmony_ciSANE_Status
2345141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
2346141cc406Sopenharmony_ci{
2347141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
2348141cc406Sopenharmony_ci
2349141cc406Sopenharmony_ci  DBG (FLOW_CONTROL, "Entering sane_get_parameters\n");
2350141cc406Sopenharmony_ci  calc_parameters (s);
2351141cc406Sopenharmony_ci
2352141cc406Sopenharmony_ci
2353141cc406Sopenharmony_ci  if (params)
2354141cc406Sopenharmony_ci    *params = s->params;
2355141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2356141cc406Sopenharmony_ci}
2357141cc406Sopenharmony_ci
2358141cc406Sopenharmony_ciSANE_Status
2359141cc406Sopenharmony_cisane_start (SANE_Handle handle)
2360141cc406Sopenharmony_ci{
2361141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
2362141cc406Sopenharmony_ci  SANE_Status status;
2363141cc406Sopenharmony_ci
2364141cc406Sopenharmony_ci  /* First make sure we have a current parameter set.  Some of the
2365141cc406Sopenharmony_ci     parameters will be overwritten below, but that's OK.  */
2366141cc406Sopenharmony_ci
2367141cc406Sopenharmony_ci  calc_parameters (s);
2368141cc406Sopenharmony_ci
2369141cc406Sopenharmony_ci  if (s->fd < 0)
2370141cc406Sopenharmony_ci    {
2371141cc406Sopenharmony_ci      /* this is the first (and maybe only) pass... */
2372141cc406Sopenharmony_ci
2373141cc406Sopenharmony_ci      status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0);
2374141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2375141cc406Sopenharmony_ci	{
2376141cc406Sopenharmony_ci	  DBG (ERROR_MESSAGE, "open: open of %s failed: %s\n",
2377141cc406Sopenharmony_ci	       s->hw->sane.name, sane_strstatus (status));
2378141cc406Sopenharmony_ci	  return status;
2379141cc406Sopenharmony_ci	}
2380141cc406Sopenharmony_ci    }
2381141cc406Sopenharmony_ci
2382141cc406Sopenharmony_ci  status = wait_ready (s->fd);
2383141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
2384141cc406Sopenharmony_ci    {
2385141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "open: wait_ready() failed: %s\n",
2386141cc406Sopenharmony_ci	   sane_strstatus (status));
2387141cc406Sopenharmony_ci      goto stop_scanner_and_return;
2388141cc406Sopenharmony_ci    }
2389141cc406Sopenharmony_ci
2390141cc406Sopenharmony_ci  status = mode_select (s);
2391141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
2392141cc406Sopenharmony_ci    {
2393141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "sane_start: mode_select command failed: %s\n",
2394141cc406Sopenharmony_ci	   sane_strstatus (status));
2395141cc406Sopenharmony_ci      goto stop_scanner_and_return;
2396141cc406Sopenharmony_ci    }
2397141cc406Sopenharmony_ci
2398141cc406Sopenharmony_ci  status = scan_area_and_windows (s);
2399141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
2400141cc406Sopenharmony_ci    {
2401141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "open: set scan area command failed: %s\n",
2402141cc406Sopenharmony_ci	   sane_strstatus (status));
2403141cc406Sopenharmony_ci      goto stop_scanner_and_return;
2404141cc406Sopenharmony_ci    }
2405141cc406Sopenharmony_ci
2406141cc406Sopenharmony_ci  status = request_sense (s);
2407141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
2408141cc406Sopenharmony_ci    {
2409141cc406Sopenharmony_ci      DBG (ERROR_MESSAGE, "sane_start: request_sense revealed error: %s\n",
2410141cc406Sopenharmony_ci	   sane_strstatus (status));
2411141cc406Sopenharmony_ci      goto stop_scanner_and_return;
2412141cc406Sopenharmony_ci    }
2413141cc406Sopenharmony_ci
2414141cc406Sopenharmony_ci  s->scanning = SANE_TRUE;
2415141cc406Sopenharmony_ci  s->AbortedByUser = SANE_FALSE;
2416141cc406Sopenharmony_ci
2417141cc406Sopenharmony_ci  status = start_scan (s);
2418141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
2419141cc406Sopenharmony_ci    goto stop_scanner_and_return;
2420141cc406Sopenharmony_ci
2421141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2422141cc406Sopenharmony_ci
2423141cc406Sopenharmony_cistop_scanner_and_return:
2424141cc406Sopenharmony_ci  s->scanning = SANE_FALSE;
2425141cc406Sopenharmony_ci  s->AbortedByUser = SANE_FALSE;
2426141cc406Sopenharmony_ci  return status;
2427141cc406Sopenharmony_ci}
2428141cc406Sopenharmony_ci
2429141cc406Sopenharmony_ciSANE_Status
2430141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
2431141cc406Sopenharmony_ci	   SANE_Int * len)
2432141cc406Sopenharmony_ci{
2433141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
2434141cc406Sopenharmony_ci  SANE_Status status;
2435141cc406Sopenharmony_ci
2436141cc406Sopenharmony_ci  uint8_t get_data_status[10];
2437141cc406Sopenharmony_ci  uint8_t read[10];
2438141cc406Sopenharmony_ci
2439141cc406Sopenharmony_ci#ifdef RESERVE_RELEASE_HACK
2440141cc406Sopenharmony_ci  uint8_t reserve[6];
2441141cc406Sopenharmony_ci  uint8_t release[6];
2442141cc406Sopenharmony_ci#endif
2443141cc406Sopenharmony_ci
2444141cc406Sopenharmony_ci  uint8_t result[12];
2445141cc406Sopenharmony_ci  size_t size;
2446141cc406Sopenharmony_ci  SANE_Int data_length = 0;
2447141cc406Sopenharmony_ci  SANE_Int data_av = 0;
2448141cc406Sopenharmony_ci  SANE_Int offset = 0;
2449141cc406Sopenharmony_ci  SANE_Int rread = 0;
2450141cc406Sopenharmony_ci  SANE_Bool Pseudo8bit = SANE_FALSE;
2451141cc406Sopenharmony_ci
2452141cc406Sopenharmony_ci#ifdef NEUTRALIZE_BACKEND
2453141cc406Sopenharmony_ci  *len=max_len;
2454141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2455141cc406Sopenharmony_ci
2456141cc406Sopenharmony_ci#else
2457141cc406Sopenharmony_ci  *len = 0;
2458141cc406Sopenharmony_ci  if (!s->scanning) return SANE_STATUS_EOF;
2459141cc406Sopenharmony_ci
2460141cc406Sopenharmony_ci
2461141cc406Sopenharmony_ci  if (!strcmp (s->val[OPT_MODE].s, "Gray16"))
2462141cc406Sopenharmony_ci    Pseudo8bit = SANE_TRUE;
2463141cc406Sopenharmony_ci
2464141cc406Sopenharmony_ci  /* TODO: The current function only implements for APPLESCANNER In
2465141cc406Sopenharmony_ci     order to use the COLORONESCANNER you have to study the docs to
2466141cc406Sopenharmony_ci     see how it the parameters get modified before scan. From this
2467141cc406Sopenharmony_ci     starting point it should be trivial to use a ONESCANNER int the
2468141cc406Sopenharmony_ci     gray256 mode but I don't have one from these pets in home.  MF */
2469141cc406Sopenharmony_ci
2470141cc406Sopenharmony_ci
2471141cc406Sopenharmony_ci  memset (get_data_status, 0, sizeof (get_data_status));
2472141cc406Sopenharmony_ci  get_data_status[0] = APPLE_SCSI_GET_DATA_STATUS;
2473141cc406Sopenharmony_ci  get_data_status[1] = 1;	/* Wait */
2474141cc406Sopenharmony_ci  STORE24 (get_data_status + 6, sizeof (result));
2475141cc406Sopenharmony_ci
2476141cc406Sopenharmony_ci  memset (read, 0, sizeof (read));
2477141cc406Sopenharmony_ci  read[0] = APPLE_SCSI_READ_SCANNED_DATA;
2478141cc406Sopenharmony_ci
2479141cc406Sopenharmony_ci
2480141cc406Sopenharmony_ci#ifdef RESERVE_RELEASE_HACK
2481141cc406Sopenharmony_ci  memset (reserve, 0, sizeof (reserve));
2482141cc406Sopenharmony_ci  reserve[0] = APPLE_SCSI_RESERVE;
2483141cc406Sopenharmony_ci
2484141cc406Sopenharmony_ci  reserve[1]=CONTROLLER_SCSI_ID;
2485141cc406Sopenharmony_ci  reserve[1]=reserve[1] << 1;
2486141cc406Sopenharmony_ci  reserve[1]|=SETTHIRDPARTY;
2487141cc406Sopenharmony_ci
2488141cc406Sopenharmony_ci  memset (release, 0, sizeof (release));
2489141cc406Sopenharmony_ci  release[0] = APPLE_SCSI_RELEASE;
2490141cc406Sopenharmony_ci  release[1]=CONTROLLER_SCSI_ID;
2491141cc406Sopenharmony_ci  release[1]=reserve[1] << 1;
2492141cc406Sopenharmony_ci  release[1]|=SETTHIRDPARTY;
2493141cc406Sopenharmony_ci
2494141cc406Sopenharmony_ci#endif
2495141cc406Sopenharmony_ci
2496141cc406Sopenharmony_ci  do
2497141cc406Sopenharmony_ci    {
2498141cc406Sopenharmony_ci      size = sizeof (result);
2499141cc406Sopenharmony_ci      status = sanei_scsi_cmd (s->fd, get_data_status,
2500141cc406Sopenharmony_ci			       sizeof (get_data_status), result, &size);
2501141cc406Sopenharmony_ci
2502141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2503141cc406Sopenharmony_ci	return status;
2504141cc406Sopenharmony_ci      if (!size)
2505141cc406Sopenharmony_ci	{
2506141cc406Sopenharmony_ci	  DBG (ERROR_MESSAGE, "sane_read: cannot get_data_status.\n");
2507141cc406Sopenharmony_ci	  return SANE_STATUS_IO_ERROR;
2508141cc406Sopenharmony_ci	}
2509141cc406Sopenharmony_ci
2510141cc406Sopenharmony_ci      data_length = READ24 (result);
2511141cc406Sopenharmony_ci      data_av = READ24 (result + 9);
2512141cc406Sopenharmony_ci
2513141cc406Sopenharmony_ci      if (data_length)
2514141cc406Sopenharmony_ci	{
2515141cc406Sopenharmony_ci	  /* if (result[3] & 1)	Scanner Blocked: Retrieve data */
2516141cc406Sopenharmony_ci	  if ((result[3] & 1) || data_av)
2517141cc406Sopenharmony_ci	    {
2518141cc406Sopenharmony_ci	      DBG (IO_MESSAGE,
2519141cc406Sopenharmony_ci		   "sane_read: (status) Available in scanner buffer %u.\n",
2520141cc406Sopenharmony_ci		   data_av);
2521141cc406Sopenharmony_ci
2522141cc406Sopenharmony_ci	      if (Pseudo8bit)
2523141cc406Sopenharmony_ci		if ((data_av << 1) + offset > max_len)
2524141cc406Sopenharmony_ci		  rread = (max_len - offset) >> 1;
2525141cc406Sopenharmony_ci		else
2526141cc406Sopenharmony_ci		  rread = data_av;
2527141cc406Sopenharmony_ci	      else if (data_av + offset > max_len)
2528141cc406Sopenharmony_ci		rread = max_len - offset;
2529141cc406Sopenharmony_ci	      else
2530141cc406Sopenharmony_ci		rread = data_av;
2531141cc406Sopenharmony_ci
2532141cc406Sopenharmony_ci	      DBG (IO_MESSAGE,
2533141cc406Sopenharmony_ci		   "sane_read: (action) Actual read request for %u bytes.\n",
2534141cc406Sopenharmony_ci		   rread);
2535141cc406Sopenharmony_ci
2536141cc406Sopenharmony_ci	      size = rread;
2537141cc406Sopenharmony_ci
2538141cc406Sopenharmony_ci	      STORE24 (read + 6, rread);
2539141cc406Sopenharmony_ci
2540141cc406Sopenharmony_ci#ifdef RESERVE_RELEASE_HACK
2541141cc406Sopenharmony_ci	      {
2542141cc406Sopenharmony_ci	      SANE_Status status;
2543141cc406Sopenharmony_ci	      DBG(IO_MESSAGE,"Reserving the SCSI bus.\n");
2544141cc406Sopenharmony_ci	      status=sanei_scsi_cmd (s->fd,reserve,sizeof(reserve),0,0);
2545141cc406Sopenharmony_ci	      DBG(IO_MESSAGE,"Reserving... status:= %d\n",status);
2546141cc406Sopenharmony_ci	      }
2547141cc406Sopenharmony_ci#endif /* RESERVE_RELEASE_HACK */
2548141cc406Sopenharmony_ci
2549141cc406Sopenharmony_ci	      status = sanei_scsi_cmd (s->fd, read, sizeof (read),
2550141cc406Sopenharmony_ci				       buf + offset, &size);
2551141cc406Sopenharmony_ci
2552141cc406Sopenharmony_ci#ifdef RESERVE_RELEASE_HACK
2553141cc406Sopenharmony_ci	      {
2554141cc406Sopenharmony_ci	      SANE_Status status;
2555141cc406Sopenharmony_ci	      DBG(IO_MESSAGE,"Releasing the SCSI bus.\n");
2556141cc406Sopenharmony_ci	      status=sanei_scsi_cmd (s->fd,release,sizeof(release),0,0);
2557141cc406Sopenharmony_ci	      DBG(IO_MESSAGE,"Releasing... status:= %d\n",status);
2558141cc406Sopenharmony_ci	      }
2559141cc406Sopenharmony_ci#endif /* RESERVE_RELEASE_HACK */
2560141cc406Sopenharmony_ci
2561141cc406Sopenharmony_ci
2562141cc406Sopenharmony_ci	      if (Pseudo8bit)
2563141cc406Sopenharmony_ci		{
2564141cc406Sopenharmony_ci		  SANE_Int byte;
2565141cc406Sopenharmony_ci		  SANE_Int pos = offset + (rread << 1) - 1;
2566141cc406Sopenharmony_ci		  SANE_Byte B;
2567141cc406Sopenharmony_ci		  for (byte = offset + rread - 1; byte >= offset; byte--)
2568141cc406Sopenharmony_ci		    {
2569141cc406Sopenharmony_ci		      B = buf[byte];
2570141cc406Sopenharmony_ci		      buf[pos--] = 255 - (B << 4);   /* low (right) nibble */
2571141cc406Sopenharmony_ci		      buf[pos--] = 255 - (B & 0xF0); /* high (left) nibble */
2572141cc406Sopenharmony_ci		    }
2573141cc406Sopenharmony_ci		  offset += size << 1;
2574141cc406Sopenharmony_ci		}
2575141cc406Sopenharmony_ci	      else
2576141cc406Sopenharmony_ci		offset += size;
2577141cc406Sopenharmony_ci
2578141cc406Sopenharmony_ci	      DBG (IO_MESSAGE, "sane_read: Buffer %u of %u full %g%%\n",
2579141cc406Sopenharmony_ci		   offset, max_len, (double) (offset * 100. / max_len));
2580141cc406Sopenharmony_ci	    }
2581141cc406Sopenharmony_ci	}
2582141cc406Sopenharmony_ci    }
2583141cc406Sopenharmony_ci  while (offset < max_len && data_length != 0 && !s->AbortedByUser);
2584141cc406Sopenharmony_ci
2585141cc406Sopenharmony_ci
2586141cc406Sopenharmony_ci  if (s->AbortedByUser)
2587141cc406Sopenharmony_ci    {
2588141cc406Sopenharmony_ci      s->scanning = SANE_FALSE;
2589141cc406Sopenharmony_ci      status = sanei_scsi_cmd (s->fd, test_unit_ready,
2590141cc406Sopenharmony_ci			       sizeof (test_unit_ready), 0, 0);
2591141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2592141cc406Sopenharmony_ci	return status;
2593141cc406Sopenharmony_ci      return SANE_STATUS_CANCELLED;
2594141cc406Sopenharmony_ci    }
2595141cc406Sopenharmony_ci
2596141cc406Sopenharmony_ci  if (!data_length)		/* If not blocked */
2597141cc406Sopenharmony_ci    {
2598141cc406Sopenharmony_ci      s->scanning = SANE_FALSE;
2599141cc406Sopenharmony_ci
2600141cc406Sopenharmony_ci      DBG (IO_MESSAGE, "sane_read: (status) Oups! No more data...");
2601141cc406Sopenharmony_ci      if (!offset)
2602141cc406Sopenharmony_ci	{
2603141cc406Sopenharmony_ci	  *len = 0;
2604141cc406Sopenharmony_ci	  DBG (IO_MESSAGE, "EOF\n");
2605141cc406Sopenharmony_ci	  return SANE_STATUS_EOF;
2606141cc406Sopenharmony_ci	}
2607141cc406Sopenharmony_ci      else
2608141cc406Sopenharmony_ci	{
2609141cc406Sopenharmony_ci	  *len = offset;
2610141cc406Sopenharmony_ci	  DBG (IO_MESSAGE, "GOOD\n");
2611141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2612141cc406Sopenharmony_ci	}
2613141cc406Sopenharmony_ci    }
2614141cc406Sopenharmony_ci
2615141cc406Sopenharmony_ci
2616141cc406Sopenharmony_ci  DBG (FLOW_CONTROL,
2617141cc406Sopenharmony_ci       "sane_read: Normal Exiting (?), Aborted=%u, data_length=%u\n",
2618141cc406Sopenharmony_ci       s->AbortedByUser, data_length);
2619141cc406Sopenharmony_ci  *len = offset;
2620141cc406Sopenharmony_ci
2621141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2622141cc406Sopenharmony_ci
2623141cc406Sopenharmony_ci#endif /* NEUTRALIZE_BACKEND */
2624141cc406Sopenharmony_ci}
2625141cc406Sopenharmony_ci
2626141cc406Sopenharmony_civoid
2627141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
2628141cc406Sopenharmony_ci{
2629141cc406Sopenharmony_ci  Apple_Scanner *s = handle;
2630141cc406Sopenharmony_ci
2631141cc406Sopenharmony_ci  if (s->scanning)
2632141cc406Sopenharmony_ci    {
2633141cc406Sopenharmony_ci      if (s->AbortedByUser)
2634141cc406Sopenharmony_ci	{
2635141cc406Sopenharmony_ci	  DBG (FLOW_CONTROL,
2636141cc406Sopenharmony_ci	       "sane_cancel: Already Aborted. Please Wait...\n");
2637141cc406Sopenharmony_ci	}
2638141cc406Sopenharmony_ci      else
2639141cc406Sopenharmony_ci	{
2640141cc406Sopenharmony_ci	  s->scanning=SANE_FALSE;
2641141cc406Sopenharmony_ci	  s->AbortedByUser = SANE_TRUE;
2642141cc406Sopenharmony_ci	  DBG (FLOW_CONTROL, "sane_cancel: Signal Caught! Aborting...\n");
2643141cc406Sopenharmony_ci	}
2644141cc406Sopenharmony_ci    }
2645141cc406Sopenharmony_ci  else
2646141cc406Sopenharmony_ci    {
2647141cc406Sopenharmony_ci      if (s->AbortedByUser)
2648141cc406Sopenharmony_ci	{
2649141cc406Sopenharmony_ci	  DBG (FLOW_CONTROL, "sane_cancel: Scan has not been Initiated yet, "
2650141cc406Sopenharmony_ci	       "or it is already aborted.\n");
2651141cc406Sopenharmony_ci	  s->AbortedByUser = SANE_FALSE;
2652141cc406Sopenharmony_ci	  sanei_scsi_cmd (s->fd, test_unit_ready,
2653141cc406Sopenharmony_ci				sizeof (test_unit_ready), 0, 0);
2654141cc406Sopenharmony_ci	}
2655141cc406Sopenharmony_ci      else
2656141cc406Sopenharmony_ci	{
2657141cc406Sopenharmony_ci	  DBG (FLOW_CONTROL, "sane_cancel: Scan has not been Initiated "
2658141cc406Sopenharmony_ci	       "yet (or it's over).\n");
2659141cc406Sopenharmony_ci	}
2660141cc406Sopenharmony_ci    }
2661141cc406Sopenharmony_ci
2662141cc406Sopenharmony_ci  return;
2663141cc406Sopenharmony_ci}
2664141cc406Sopenharmony_ci
2665141cc406Sopenharmony_ciSANE_Status
2666141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2667141cc406Sopenharmony_ci{
2668141cc406Sopenharmony_ciDBG (FLOW_CONTROL,"sane_set_io_mode: Entering.\n");
2669141cc406Sopenharmony_ci
2670141cc406Sopenharmony_ci (void) handle;				/* silence gcc */
2671141cc406Sopenharmony_ci
2672141cc406Sopenharmony_ciif (non_blocking)
2673141cc406Sopenharmony_ci  {
2674141cc406Sopenharmony_ci  DBG (FLOW_CONTROL, "sane_set_io_mode: Don't call me please. "
2675141cc406Sopenharmony_ci       "Unimplemented function\n");
2676141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
2677141cc406Sopenharmony_ci  }
2678141cc406Sopenharmony_ci
2679141cc406Sopenharmony_cireturn SANE_STATUS_GOOD;
2680141cc406Sopenharmony_ci}
2681141cc406Sopenharmony_ci
2682141cc406Sopenharmony_ciSANE_Status
2683141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2684141cc406Sopenharmony_ci{
2685141cc406Sopenharmony_ci  (void) handle;			/* silence gcc */
2686141cc406Sopenharmony_ci  (void) fd;				/* silence gcc */
2687141cc406Sopenharmony_ci
2688141cc406Sopenharmony_ci  DBG (FLOW_CONTROL, "sane_get_select_fd: Don't call me please. "
2689141cc406Sopenharmony_ci       "Unimplemented function\n");
2690141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
2691141cc406Sopenharmony_ci}
2692