1141cc406Sopenharmony_ci/***************************************************************************
2141cc406Sopenharmony_ci * SANE - Scanner Access Now Easy.
3141cc406Sopenharmony_ci
4141cc406Sopenharmony_ci   dc210.c
5141cc406Sopenharmony_ci
6141cc406Sopenharmony_ci   11/11/98
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci   This file (C) 1998 Brian J. Murrell
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This file is part of the SANE package.
11141cc406Sopenharmony_ci
12141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
13141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
14141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
15141cc406Sopenharmony_ci   License, or (at your option) any later version.
16141cc406Sopenharmony_ci
17141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
18141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
19141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20141cc406Sopenharmony_ci   General Public License for more details.
21141cc406Sopenharmony_ci
22141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
23141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
24141cc406Sopenharmony_ci
25141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
26141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
27141cc406Sopenharmony_ci
28141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
29141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
30141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
31141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
32141cc406Sopenharmony_ci   account of linking the SANE library code into it.
33141cc406Sopenharmony_ci
34141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
35141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
36141cc406Sopenharmony_ci   License.
37141cc406Sopenharmony_ci
38141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
39141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
40141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
43141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
44141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci ***************************************************************************
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci   This file implements a SANE backend for the Kodak DC-210
49141cc406Sopenharmony_ci   digital camera.  THIS IS EXTREMELY ALPHA CODE!  USE AT YOUR OWN RISK!!
50141cc406Sopenharmony_ci
51141cc406Sopenharmony_ci   (feedback to:  sane-dc210@interlinx.bc.ca
52141cc406Sopenharmony_ci
53141cc406Sopenharmony_ci   This backend is based somewhat on the dc25 backend included in this
54141cc406Sopenharmony_ci   package by Peter Fales
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci ***************************************************************************/
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci#include "../include/sane/config.h"
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci#include <stdlib.h>
61141cc406Sopenharmony_ci#include <string.h>
62141cc406Sopenharmony_ci#include <stdio.h>
63141cc406Sopenharmony_ci#include <unistd.h>
64141cc406Sopenharmony_ci#include <fcntl.h>
65141cc406Sopenharmony_ci#include <limits.h>
66141cc406Sopenharmony_ci#include "../include/sane/sanei_jpeg.h"
67141cc406Sopenharmony_ci#include <sys/ioctl.h>
68141cc406Sopenharmony_ci
69141cc406Sopenharmony_ci#include "../include/sane/sane.h"
70141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
71141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_ci#define BACKEND_NAME	dc210
74141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
75141cc406Sopenharmony_ci
76141cc406Sopenharmony_ci#include "dc210.h"
77141cc406Sopenharmony_ci
78141cc406Sopenharmony_ci#ifndef PATH_MAX
79141cc406Sopenharmony_ci# define PATH_MAX	1024
80141cc406Sopenharmony_ci#endif
81141cc406Sopenharmony_ci
82141cc406Sopenharmony_ci#define MAGIC			(void *)0xab730324
83141cc406Sopenharmony_ci#define DC210_CONFIG_FILE 	"dc210.conf"
84141cc406Sopenharmony_ci#define THUMBSIZE		20736
85141cc406Sopenharmony_ci
86141cc406Sopenharmony_ci#ifdef B115200
87141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE	B115200
88141cc406Sopenharmony_ci#else
89141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE	B38400
90141cc406Sopenharmony_ci#endif
91141cc406Sopenharmony_ci
92141cc406Sopenharmony_ci#if defined (__sgi)
93141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/ttyd1"	/* Irix */
94141cc406Sopenharmony_ci#elif defined (__sun)
95141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/term/a"	/* Solaris */
96141cc406Sopenharmony_ci#elif defined (hpux)
97141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/tty1d0"	/* HP-UX */
98141cc406Sopenharmony_ci#elif defined (__osf__)
99141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/tty00"	/* Digital UNIX */
100141cc406Sopenharmony_ci#else
101141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/ttyS0"	/* Linux */
102141cc406Sopenharmony_ci#endif
103141cc406Sopenharmony_ci
104141cc406Sopenharmony_cistatic SANE_Bool is_open = 0;
105141cc406Sopenharmony_ci
106141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_thumbnails;
107141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_snap;
108141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_lowres;
109141cc406Sopenharmony_cistatic SANE_Bool dc210_opt_erase;
110141cc406Sopenharmony_cistatic SANE_Bool dumpinquiry;
111141cc406Sopenharmony_ci
112141cc406Sopenharmony_cistatic struct jpeg_decompress_struct cinfo;
113141cc406Sopenharmony_cistatic djpeg_dest_ptr dest_mgr = NULL;
114141cc406Sopenharmony_ci
115141cc406Sopenharmony_cistatic unsigned long cmdrespause = 250000UL;	/* pause after sending cmd */
116141cc406Sopenharmony_cistatic unsigned long breakpause = 1000000UL;	/* pause after sending break */
117141cc406Sopenharmony_ci
118141cc406Sopenharmony_cistatic int bytes_in_buffer;
119141cc406Sopenharmony_cistatic int bytes_read_from_buffer;
120141cc406Sopenharmony_cistatic int total_bytes_read;
121141cc406Sopenharmony_ci
122141cc406Sopenharmony_cistatic DC210 Camera;
123141cc406Sopenharmony_ci
124141cc406Sopenharmony_cistatic SANE_Range image_range = {
125141cc406Sopenharmony_ci  0,
126141cc406Sopenharmony_ci  14,
127141cc406Sopenharmony_ci  0
128141cc406Sopenharmony_ci};
129141cc406Sopenharmony_ci
130141cc406Sopenharmony_cistatic SANE_Option_Descriptor sod[] = {
131141cc406Sopenharmony_ci  {
132141cc406Sopenharmony_ci   SANE_NAME_NUM_OPTIONS,
133141cc406Sopenharmony_ci   SANE_TITLE_NUM_OPTIONS,
134141cc406Sopenharmony_ci   SANE_DESC_NUM_OPTIONS,
135141cc406Sopenharmony_ci   SANE_TYPE_INT,
136141cc406Sopenharmony_ci   SANE_UNIT_NONE,
137141cc406Sopenharmony_ci   sizeof (SANE_Word),
138141cc406Sopenharmony_ci   SANE_CAP_SOFT_DETECT,
139141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
140141cc406Sopenharmony_ci   {NULL}
141141cc406Sopenharmony_ci   }
142141cc406Sopenharmony_ci  ,
143141cc406Sopenharmony_ci
144141cc406Sopenharmony_ci#define D25_OPT_IMAGE_SELECTION 1
145141cc406Sopenharmony_ci  {
146141cc406Sopenharmony_ci   "",
147141cc406Sopenharmony_ci   "Image Selection",
148141cc406Sopenharmony_ci   "Selection of the image to load.",
149141cc406Sopenharmony_ci   SANE_TYPE_GROUP,
150141cc406Sopenharmony_ci   SANE_UNIT_NONE,
151141cc406Sopenharmony_ci   0,
152141cc406Sopenharmony_ci   0,
153141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
154141cc406Sopenharmony_ci   {NULL}
155141cc406Sopenharmony_ci   }
156141cc406Sopenharmony_ci  ,
157141cc406Sopenharmony_ci
158141cc406Sopenharmony_ci#define DC210_OPT_IMAGE_NUMBER 2
159141cc406Sopenharmony_ci  {
160141cc406Sopenharmony_ci   "image",
161141cc406Sopenharmony_ci   "Image Number",
162141cc406Sopenharmony_ci   "Select Image Number to load from camera",
163141cc406Sopenharmony_ci   SANE_TYPE_INT,
164141cc406Sopenharmony_ci   SANE_UNIT_NONE,
165141cc406Sopenharmony_ci   4,
166141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
167141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
168141cc406Sopenharmony_ci   {(void *) & image_range}
169141cc406Sopenharmony_ci   }
170141cc406Sopenharmony_ci  ,
171141cc406Sopenharmony_ci
172141cc406Sopenharmony_ci#define DC210_OPT_THUMBS 3
173141cc406Sopenharmony_ci  {
174141cc406Sopenharmony_ci   "thumbs",
175141cc406Sopenharmony_ci   "Load Thumbnail",
176141cc406Sopenharmony_ci   "Load the image as thumbnail.",
177141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
178141cc406Sopenharmony_ci   SANE_UNIT_NONE,
179141cc406Sopenharmony_ci   sizeof (SANE_Word),
180141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
181141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
182141cc406Sopenharmony_ci   {NULL}
183141cc406Sopenharmony_ci   }
184141cc406Sopenharmony_ci  ,
185141cc406Sopenharmony_ci#define DC210_OPT_SNAP 4
186141cc406Sopenharmony_ci  {
187141cc406Sopenharmony_ci   "snap",
188141cc406Sopenharmony_ci   "Snap new picture",
189141cc406Sopenharmony_ci   "Take new picture and download it",
190141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
191141cc406Sopenharmony_ci   SANE_UNIT_NONE,
192141cc406Sopenharmony_ci   sizeof (SANE_Word),
193141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ ,
194141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
195141cc406Sopenharmony_ci   {NULL}
196141cc406Sopenharmony_ci   }
197141cc406Sopenharmony_ci  ,
198141cc406Sopenharmony_ci#define DC210_OPT_LOWRES 5
199141cc406Sopenharmony_ci  {
200141cc406Sopenharmony_ci   "lowres",
201141cc406Sopenharmony_ci   "Low Resolution",
202141cc406Sopenharmony_ci   "Resolution of new pictures",
203141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
204141cc406Sopenharmony_ci   SANE_UNIT_NONE,
205141cc406Sopenharmony_ci   sizeof (SANE_Word),
206141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE
207141cc406Sopenharmony_ci   /* | SANE_CAP_ADVANCED */ ,
208141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
209141cc406Sopenharmony_ci   {NULL}
210141cc406Sopenharmony_ci   }
211141cc406Sopenharmony_ci  ,
212141cc406Sopenharmony_ci
213141cc406Sopenharmony_ci#define DC210_OPT_ERASE 6
214141cc406Sopenharmony_ci  {
215141cc406Sopenharmony_ci   "erase",
216141cc406Sopenharmony_ci   "Erase",
217141cc406Sopenharmony_ci   "Erase the picture after downloading",
218141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
219141cc406Sopenharmony_ci   SANE_UNIT_NONE,
220141cc406Sopenharmony_ci   sizeof (SANE_Word),
221141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
222141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
223141cc406Sopenharmony_ci   {NULL}
224141cc406Sopenharmony_ci   }
225141cc406Sopenharmony_ci  ,
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_ci#define DC210_OPT_DEFAULT 7
228141cc406Sopenharmony_ci  {
229141cc406Sopenharmony_ci   "default-enhancements",
230141cc406Sopenharmony_ci   "Defaults",
231141cc406Sopenharmony_ci   "Set default values for enhancement controls.",
232141cc406Sopenharmony_ci   SANE_TYPE_BUTTON,
233141cc406Sopenharmony_ci   SANE_UNIT_NONE,
234141cc406Sopenharmony_ci   0,
235141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
236141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
237141cc406Sopenharmony_ci   {NULL}
238141cc406Sopenharmony_ci   }
239141cc406Sopenharmony_ci  ,
240141cc406Sopenharmony_ci#define DC210_OPT_INIT_DC210 8
241141cc406Sopenharmony_ci  {
242141cc406Sopenharmony_ci   "camera-init",
243141cc406Sopenharmony_ci   "Re-establish Communications",
244141cc406Sopenharmony_ci   "Re-establish communications with camera (in case of timeout, etc.)",
245141cc406Sopenharmony_ci   SANE_TYPE_BUTTON,
246141cc406Sopenharmony_ci   SANE_UNIT_NONE,
247141cc406Sopenharmony_ci   0,
248141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
249141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
250141cc406Sopenharmony_ci   {NULL}
251141cc406Sopenharmony_ci   }
252141cc406Sopenharmony_ci};
253141cc406Sopenharmony_ci
254141cc406Sopenharmony_cistatic SANE_Parameters parms = {
255141cc406Sopenharmony_ci  SANE_FRAME_RGB,
256141cc406Sopenharmony_ci  0,
257141cc406Sopenharmony_ci  0,				/* Number of bytes returned per scan line: */
258141cc406Sopenharmony_ci  0,				/* Number of pixels per scan line.  */
259141cc406Sopenharmony_ci  0,				/* Number of lines for the current scan.  */
260141cc406Sopenharmony_ci  8,				/* Number of bits per sample. */
261141cc406Sopenharmony_ci};
262141cc406Sopenharmony_ci
263141cc406Sopenharmony_ci
264141cc406Sopenharmony_ci
265141cc406Sopenharmony_ci
266141cc406Sopenharmony_cistatic unsigned char shoot_pck[] = SHOOT_PCK;
267141cc406Sopenharmony_cistatic unsigned char init_pck[] = INIT_PCK;
268141cc406Sopenharmony_cistatic unsigned char thumb_pck[] = THUMBS_PCK;
269141cc406Sopenharmony_cistatic unsigned char pic_pck[] = PICS_PCK;
270141cc406Sopenharmony_cistatic unsigned char pic_info_pck[] = PICS_INFO_PCK;
271141cc406Sopenharmony_cistatic unsigned char info_pck[] = INFO_PCK;
272141cc406Sopenharmony_cistatic unsigned char erase_pck[] = ERASE_PCK;
273141cc406Sopenharmony_cistatic unsigned char res_pck[] = RES_PCK;
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_cistatic struct pkt_speed speeds[] = SPEEDS;
276141cc406Sopenharmony_cistatic struct termios tty_orig;
277141cc406Sopenharmony_ci
278141cc406Sopenharmony_ci#include <sys/time.h>
279141cc406Sopenharmony_ci#include <unistd.h>
280141cc406Sopenharmony_ci
281141cc406Sopenharmony_cistatic int
282141cc406Sopenharmony_cisend_pck (int fd, unsigned char *pck)
283141cc406Sopenharmony_ci{
284141cc406Sopenharmony_ci  int n;
285141cc406Sopenharmony_ci  unsigned char r = 0xf0;	/* prime the loop with a "camera busy" */
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_ci  /* keep trying if camera says it's busy */
288141cc406Sopenharmony_ci  while (r == 0xf0)
289141cc406Sopenharmony_ci    {
290141cc406Sopenharmony_ci      /*
291141cc406Sopenharmony_ci         * Not quite sure why we need this, but the program works a whole
292141cc406Sopenharmony_ci         * lot better (at least on the DC210)  with this short delay.
293141cc406Sopenharmony_ci       */
294141cc406Sopenharmony_ci
295141cc406Sopenharmony_ci      if (write (fd, (char *) pck, 8) != 8)
296141cc406Sopenharmony_ci	{
297141cc406Sopenharmony_ci	  DBG (2, "send_pck: error: write returned -1\n");
298141cc406Sopenharmony_ci	  return -1;
299141cc406Sopenharmony_ci	}
300141cc406Sopenharmony_ci      /* need to wait before we read command result */
301141cc406Sopenharmony_ci      usleep (cmdrespause);
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ci      if ((n = read (fd, (char *) &r, 1)) != 1)
304141cc406Sopenharmony_ci	{
305141cc406Sopenharmony_ci	  DBG (2, "send_pck: error: read returned -1\n");
306141cc406Sopenharmony_ci	  return -1;
307141cc406Sopenharmony_ci	}
308141cc406Sopenharmony_ci    }
309141cc406Sopenharmony_ci  return (r == 0xd1) ? 0 : -1;
310141cc406Sopenharmony_ci}
311141cc406Sopenharmony_ci
312141cc406Sopenharmony_cistatic int
313141cc406Sopenharmony_ciinit_dc210 (DC210 * camera)
314141cc406Sopenharmony_ci{
315141cc406Sopenharmony_ci  struct termios tty_new;
316141cc406Sopenharmony_ci  int speed_index;
317141cc406Sopenharmony_ci
318141cc406Sopenharmony_ci  for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++)
319141cc406Sopenharmony_ci    {
320141cc406Sopenharmony_ci      if (speeds[speed_index].baud == camera->baud)
321141cc406Sopenharmony_ci	{
322141cc406Sopenharmony_ci	  init_pck[2] = speeds[speed_index].pkt_code[0];
323141cc406Sopenharmony_ci	  init_pck[3] = speeds[speed_index].pkt_code[1];
324141cc406Sopenharmony_ci	  break;
325141cc406Sopenharmony_ci	}
326141cc406Sopenharmony_ci    }
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci  if (init_pck[2] == 0)
329141cc406Sopenharmony_ci    {
330141cc406Sopenharmony_ci      DBG (2, "unsupported baud rate.\n");
331141cc406Sopenharmony_ci      return -1;
332141cc406Sopenharmony_ci    }
333141cc406Sopenharmony_ci
334141cc406Sopenharmony_ci  /*
335141cc406Sopenharmony_ci     Open device file.
336141cc406Sopenharmony_ci   */
337141cc406Sopenharmony_ci  if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1)
338141cc406Sopenharmony_ci    {
339141cc406Sopenharmony_ci      DBG (2, "init_dc210: error: could not open %s for read/write\n",
340141cc406Sopenharmony_ci	   camera->tty_name);
341141cc406Sopenharmony_ci      return -1;
342141cc406Sopenharmony_ci    }
343141cc406Sopenharmony_ci  /*
344141cc406Sopenharmony_ci     Save old device information to restore when we are done.
345141cc406Sopenharmony_ci   */
346141cc406Sopenharmony_ci  if (tcgetattr (camera->fd, &tty_orig) == -1)
347141cc406Sopenharmony_ci    {
348141cc406Sopenharmony_ci      DBG (2, "init_dc210: error: could not get attributes\n");
349141cc406Sopenharmony_ci      return -1;
350141cc406Sopenharmony_ci    }
351141cc406Sopenharmony_ci
352141cc406Sopenharmony_ci  memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios));
353141cc406Sopenharmony_ci  /*
354141cc406Sopenharmony_ci     We need the device to be raw. 8 bits even parity on 9600 baud to start.
355141cc406Sopenharmony_ci   */
356141cc406Sopenharmony_ci#ifdef HAVE_CFMAKERAW
357141cc406Sopenharmony_ci  cfmakeraw (&tty_new);
358141cc406Sopenharmony_ci#else
359141cc406Sopenharmony_ci  /* Modified to set the port REALLY as required. Code inspired by
360141cc406Sopenharmony_ci     the gPhoto2 serial port setup */
361141cc406Sopenharmony_ci
362141cc406Sopenharmony_ci  /* input control settings */
363141cc406Sopenharmony_ci  tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC |
364141cc406Sopenharmony_ci                      IXANY | IXON | IXOFF | INPCK | ISTRIP);
365141cc406Sopenharmony_ci  tty_new.c_iflag |= (BRKINT | IGNPAR);
366141cc406Sopenharmony_ci  /* output control settings */
367141cc406Sopenharmony_ci  tty_new.c_oflag &= ~OPOST;
368141cc406Sopenharmony_ci  /* hardware control settings */
369141cc406Sopenharmony_ci  tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8;
370141cc406Sopenharmony_ci  tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB);
371141cc406Sopenharmony_ci# if defined(__sgi)
372141cc406Sopenharmony_ci  tty_new.c_cflag &= ~CNEW_RTSCTS;
373141cc406Sopenharmony_ci# else
374141cc406Sopenharmony_ci/* OS/2 doesn't have CRTSCTS - will this work for them? */
375141cc406Sopenharmony_ci#  ifdef CRTSCTS
376141cc406Sopenharmony_ci  tty_new.c_cflag &= ~CRTSCTS;
377141cc406Sopenharmony_ci#  endif
378141cc406Sopenharmony_ci# endif
379141cc406Sopenharmony_ci  tty_new.c_cflag |= CLOCAL | CREAD;
380141cc406Sopenharmony_ci#endif
381141cc406Sopenharmony_ci  /* line discipline settings */
382141cc406Sopenharmony_ci  tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE |
383141cc406Sopenharmony_ci                       ECHOK | IEXTEN);
384141cc406Sopenharmony_ci  tty_new.c_cc[VMIN] = 0;
385141cc406Sopenharmony_ci  tty_new.c_cc[VTIME] = 5;
386141cc406Sopenharmony_ci  cfsetospeed (&tty_new, B9600);
387141cc406Sopenharmony_ci  cfsetispeed (&tty_new, B9600);
388141cc406Sopenharmony_ci
389141cc406Sopenharmony_ci  if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
390141cc406Sopenharmony_ci    {
391141cc406Sopenharmony_ci      DBG (2, "init_dc210: error: could not set attributes\n");
392141cc406Sopenharmony_ci      return -1;
393141cc406Sopenharmony_ci    }
394141cc406Sopenharmony_ci
395141cc406Sopenharmony_ci  /* send a break to get it back to a known state */
396141cc406Sopenharmony_ci  /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK,
397141cc406Sopenharmony_ci   * and TCSBRKP, but that is system dependent.  e.g. on irix a non-zero
398141cc406Sopenharmony_ci   * value does a drain instead of a break.  A zero value is universally
399141cc406Sopenharmony_ci   * used to send a break.
400141cc406Sopenharmony_ci   */
401141cc406Sopenharmony_ci
402141cc406Sopenharmony_ci#ifdef HAVE_TCSENDBREAK
403141cc406Sopenharmony_ci  tcsendbreak (camera->fd, 0);
404141cc406Sopenharmony_ci# if defined(__sgi)
405141cc406Sopenharmony_ci  tcdrain (camera->fd);
406141cc406Sopenharmony_ci# endif
407141cc406Sopenharmony_ci# elif defined(TCSBRKP)
408141cc406Sopenharmony_ci  ioctl (camera->fd, TCSBRKP, 0);
409141cc406Sopenharmony_ci# elif defined(TCSBRK)
410141cc406Sopenharmony_ci  ioctl (camera->fd, TCSBRK, 0);
411141cc406Sopenharmony_ci#endif
412141cc406Sopenharmony_ci
413141cc406Sopenharmony_ci   /* and wait for it to recover from the break */
414141cc406Sopenharmony_ci
415141cc406Sopenharmony_ci#ifdef HAVE_USLEEP
416141cc406Sopenharmony_ci  usleep (breakpause);
417141cc406Sopenharmony_ci#else
418141cc406Sopenharmony_ci  sleep (1);
419141cc406Sopenharmony_ci#endif
420141cc406Sopenharmony_ci
421141cc406Sopenharmony_ci  if (send_pck (camera->fd, init_pck) == -1)
422141cc406Sopenharmony_ci    {
423141cc406Sopenharmony_ci      /*
424141cc406Sopenharmony_ci       *    The camera always powers up at 9600, so we try
425141cc406Sopenharmony_ci       *      that first.  However, it may be already set to
426141cc406Sopenharmony_ci       *      a different speed.  Try the entries in the table:
427141cc406Sopenharmony_ci       */
428141cc406Sopenharmony_ci
429141cc406Sopenharmony_ci      for (speed_index = NELEMS (speeds) - 1; speed_index > 0; speed_index--)
430141cc406Sopenharmony_ci	{
431141cc406Sopenharmony_ci	  int x;
432141cc406Sopenharmony_ci	  DBG (3, "init_dc210: changing speed to %d\n",
433141cc406Sopenharmony_ci	       (int) speeds[speed_index].baud);
434141cc406Sopenharmony_ci
435141cc406Sopenharmony_ci	  cfsetospeed (&tty_new, speeds[speed_index].baud);
436141cc406Sopenharmony_ci	  cfsetispeed (&tty_new, speeds[speed_index].baud);
437141cc406Sopenharmony_ci
438141cc406Sopenharmony_ci	  if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
439141cc406Sopenharmony_ci	    {
440141cc406Sopenharmony_ci	      DBG (2, "init_dc210: error: could not set attributes\n");
441141cc406Sopenharmony_ci	      return -1;
442141cc406Sopenharmony_ci	    }
443141cc406Sopenharmony_ci	  for (x = 0; x < 3; x++)
444141cc406Sopenharmony_ci	    if (send_pck (camera->fd, init_pck) != -1)
445141cc406Sopenharmony_ci	      break;
446141cc406Sopenharmony_ci	}
447141cc406Sopenharmony_ci
448141cc406Sopenharmony_ci      if (speed_index == 0)
449141cc406Sopenharmony_ci	{
450141cc406Sopenharmony_ci	  tcsetattr (camera->fd, TCSANOW, &tty_orig);
451141cc406Sopenharmony_ci	  DBG (2, "init_dc210: error: no suitable baud rate\n");
452141cc406Sopenharmony_ci	  return -1;
453141cc406Sopenharmony_ci	}
454141cc406Sopenharmony_ci    }
455141cc406Sopenharmony_ci  /*
456141cc406Sopenharmony_ci     Set speed to requested speed.
457141cc406Sopenharmony_ci   */
458141cc406Sopenharmony_ci  cfsetospeed (&tty_new, Camera.baud);
459141cc406Sopenharmony_ci  cfsetispeed (&tty_new, Camera.baud);
460141cc406Sopenharmony_ci
461141cc406Sopenharmony_ci  if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
462141cc406Sopenharmony_ci    {
463141cc406Sopenharmony_ci      DBG (2, "init_dc210: error: could not set attributes\n");
464141cc406Sopenharmony_ci      return -1;
465141cc406Sopenharmony_ci    }
466141cc406Sopenharmony_ci
467141cc406Sopenharmony_ci  return camera->fd;
468141cc406Sopenharmony_ci}
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_cistatic void
471141cc406Sopenharmony_ciclose_dc210 (int fd)
472141cc406Sopenharmony_ci{
473141cc406Sopenharmony_ci  /*
474141cc406Sopenharmony_ci   *    Put the camera back to 9600 baud
475141cc406Sopenharmony_ci   */
476141cc406Sopenharmony_ci
477141cc406Sopenharmony_ci  if (close (fd) == -1)
478141cc406Sopenharmony_ci    {
479141cc406Sopenharmony_ci      DBG (4, "close_dc210: error: could not close device\n");
480141cc406Sopenharmony_ci    }
481141cc406Sopenharmony_ci}
482141cc406Sopenharmony_ci
483141cc406Sopenharmony_ciint
484141cc406Sopenharmony_ciget_info (DC210 * camera)
485141cc406Sopenharmony_ci{
486141cc406Sopenharmony_ci
487141cc406Sopenharmony_ci  char f[] = "get_info";
488141cc406Sopenharmony_ci  unsigned char buf[256];
489141cc406Sopenharmony_ci
490141cc406Sopenharmony_ci  if (send_pck (camera->fd, info_pck) == -1)
491141cc406Sopenharmony_ci    {
492141cc406Sopenharmony_ci      DBG (2, "%s: error: send_pck returned -1\n", f);
493141cc406Sopenharmony_ci      return -1;
494141cc406Sopenharmony_ci    }
495141cc406Sopenharmony_ci
496141cc406Sopenharmony_ci  DBG (9, "%s: read info packet\n", f);
497141cc406Sopenharmony_ci
498141cc406Sopenharmony_ci  if (read_data (camera->fd, buf, 256) == -1)
499141cc406Sopenharmony_ci    {
500141cc406Sopenharmony_ci      DBG (2, "%s: error: read_data returned -1\n", f);
501141cc406Sopenharmony_ci      return -1;
502141cc406Sopenharmony_ci    }
503141cc406Sopenharmony_ci
504141cc406Sopenharmony_ci  if (end_of_data (camera->fd) == -1)
505141cc406Sopenharmony_ci    {
506141cc406Sopenharmony_ci      DBG (2, "%s: error: end_of_data returned -1\n", f);
507141cc406Sopenharmony_ci      return -1;
508141cc406Sopenharmony_ci    }
509141cc406Sopenharmony_ci
510141cc406Sopenharmony_ci  camera->model = buf[1];
511141cc406Sopenharmony_ci  camera->ver_major = buf[2];
512141cc406Sopenharmony_ci  camera->ver_minor = buf[3];
513141cc406Sopenharmony_ci  camera->pic_taken = buf[56] << 8 | buf[57];
514141cc406Sopenharmony_ci  camera->pic_left = buf[72] << 8 | buf[73];
515141cc406Sopenharmony_ci  camera->flags.low_res = buf[22];
516141cc406Sopenharmony_ci  camera->flags.low_batt = buf[8];
517141cc406Sopenharmony_ci
518141cc406Sopenharmony_ci  return 0;
519141cc406Sopenharmony_ci}
520141cc406Sopenharmony_ci
521141cc406Sopenharmony_cistatic int
522141cc406Sopenharmony_ciread_data (int fd, unsigned char *buf, int sz)
523141cc406Sopenharmony_ci{
524141cc406Sopenharmony_ci  unsigned char ccsum;
525141cc406Sopenharmony_ci  unsigned char rcsum;
526141cc406Sopenharmony_ci  unsigned char c;
527141cc406Sopenharmony_ci  int n;
528141cc406Sopenharmony_ci  int r = 0;
529141cc406Sopenharmony_ci  int i;
530141cc406Sopenharmony_ci
531141cc406Sopenharmony_ci/* read the control byte */
532141cc406Sopenharmony_ci  if (read (fd, &c, 1) != 1)
533141cc406Sopenharmony_ci    {
534141cc406Sopenharmony_ci      DBG (2,
535141cc406Sopenharmony_ci	   "read_data: error: read for packet control byte returned bad status\n");
536141cc406Sopenharmony_ci      return -1;
537141cc406Sopenharmony_ci    }
538141cc406Sopenharmony_ci  if (c != 1)
539141cc406Sopenharmony_ci    {
540141cc406Sopenharmony_ci      DBG (2, "read_data: error: incorrect packet control byte: %02x\n", c);
541141cc406Sopenharmony_ci      return -1;
542141cc406Sopenharmony_ci    }
543141cc406Sopenharmony_ci  for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; n += r)
544141cc406Sopenharmony_ci    ;
545141cc406Sopenharmony_ci
546141cc406Sopenharmony_ci  if (r <= 0)
547141cc406Sopenharmony_ci    {
548141cc406Sopenharmony_ci      DBG (2, "read_data: error: read returned -1\n");
549141cc406Sopenharmony_ci      return -1;
550141cc406Sopenharmony_ci    }
551141cc406Sopenharmony_ci
552141cc406Sopenharmony_ci  if (n < sz || read (fd, &rcsum, 1) != 1)
553141cc406Sopenharmony_ci    {
554141cc406Sopenharmony_ci      DBG (2, "read_data: error: buffer underrun or no checksum\n");
555141cc406Sopenharmony_ci      return -1;
556141cc406Sopenharmony_ci    }
557141cc406Sopenharmony_ci
558141cc406Sopenharmony_ci  for (i = 0, ccsum = 0; i < n; i++)
559141cc406Sopenharmony_ci    ccsum ^= buf[i];
560141cc406Sopenharmony_ci
561141cc406Sopenharmony_ci  if (ccsum != rcsum)
562141cc406Sopenharmony_ci    {
563141cc406Sopenharmony_ci      DBG (2, "read_data: error: bad checksum (%02x !=%02x)\n", rcsum, ccsum);
564141cc406Sopenharmony_ci      return -1;
565141cc406Sopenharmony_ci    }
566141cc406Sopenharmony_ci
567141cc406Sopenharmony_ci  c = 0xd2;
568141cc406Sopenharmony_ci
569141cc406Sopenharmony_ci  if (write (fd, (char *) &c, 1) != 1)
570141cc406Sopenharmony_ci    {
571141cc406Sopenharmony_ci      DBG (2, "read_data: error: write ack\n");
572141cc406Sopenharmony_ci      return -1;
573141cc406Sopenharmony_ci    }
574141cc406Sopenharmony_ci
575141cc406Sopenharmony_ci  return 0;
576141cc406Sopenharmony_ci}
577141cc406Sopenharmony_ci
578141cc406Sopenharmony_cistatic int
579141cc406Sopenharmony_ciend_of_data (int fd)
580141cc406Sopenharmony_ci{
581141cc406Sopenharmony_ci  unsigned char c;
582141cc406Sopenharmony_ci
583141cc406Sopenharmony_ci  do
584141cc406Sopenharmony_ci    {				/* loop until the camera isn't busy */
585141cc406Sopenharmony_ci      if (read (fd, &c, 1) != 1)
586141cc406Sopenharmony_ci	{
587141cc406Sopenharmony_ci	  DBG (2, "end_of_data: error: read returned -1\n");
588141cc406Sopenharmony_ci	  return -1;
589141cc406Sopenharmony_ci	}
590141cc406Sopenharmony_ci      if (c == 0)		/* got successful end of data */
591141cc406Sopenharmony_ci	return 0;		/* return success */
592141cc406Sopenharmony_ci      sleep (1);		/* not too fast */
593141cc406Sopenharmony_ci    }
594141cc406Sopenharmony_ci  while (c == 0xf0);
595141cc406Sopenharmony_ci
596141cc406Sopenharmony_ci  /* Accck!  Not busy, but not a good end of data either */
597141cc406Sopenharmony_ci  if (c != 0)
598141cc406Sopenharmony_ci    {
599141cc406Sopenharmony_ci      DBG (2, "end_of_data: error: bad EOD from camera (%02x)\n",
600141cc406Sopenharmony_ci	   (unsigned) c);
601141cc406Sopenharmony_ci      return -1;
602141cc406Sopenharmony_ci    }
603141cc406Sopenharmony_ci  return 0;			/* should never get here but shut gcc -Wall up */
604141cc406Sopenharmony_ci}
605141cc406Sopenharmony_ci
606141cc406Sopenharmony_cistatic int
607141cc406Sopenharmony_cierase (int fd)
608141cc406Sopenharmony_ci{
609141cc406Sopenharmony_ci  if (send_pck (fd, erase_pck) == -1)
610141cc406Sopenharmony_ci    {
611141cc406Sopenharmony_ci      DBG (3, "erase: error: send_pck returned -1\n");
612141cc406Sopenharmony_ci      return -1;
613141cc406Sopenharmony_ci    }
614141cc406Sopenharmony_ci
615141cc406Sopenharmony_ci  if (end_of_data (fd) == -1)
616141cc406Sopenharmony_ci    {
617141cc406Sopenharmony_ci      DBG (3, "erase: error: end_of_data returned -1\n");
618141cc406Sopenharmony_ci      return -1;
619141cc406Sopenharmony_ci    }
620141cc406Sopenharmony_ci
621141cc406Sopenharmony_ci  return 0;
622141cc406Sopenharmony_ci}
623141cc406Sopenharmony_ci
624141cc406Sopenharmony_cistatic int
625141cc406Sopenharmony_cichange_res (int fd, unsigned char res)
626141cc406Sopenharmony_ci{
627141cc406Sopenharmony_ci  char f[] = "change_res";
628141cc406Sopenharmony_ci
629141cc406Sopenharmony_ci  DBG (127, "%s called\n", f);
630141cc406Sopenharmony_ci  if (res != 0 && res != 1)
631141cc406Sopenharmony_ci    {
632141cc406Sopenharmony_ci      DBG (3, "%s: error: unsupported resolution\n", f);
633141cc406Sopenharmony_ci      return -1;
634141cc406Sopenharmony_ci    }
635141cc406Sopenharmony_ci
636141cc406Sopenharmony_ci  /* cameras resolution semantics are opposite of ours */
637141cc406Sopenharmony_ci  res = !res;
638141cc406Sopenharmony_ci  DBG (127, "%s: setting res to %d\n", f, res);
639141cc406Sopenharmony_ci  res_pck[2] = res;
640141cc406Sopenharmony_ci
641141cc406Sopenharmony_ci  if (send_pck (fd, res_pck) == -1)
642141cc406Sopenharmony_ci    {
643141cc406Sopenharmony_ci      DBG (4, "%s: error: send_pck returned -1\n", f);
644141cc406Sopenharmony_ci    }
645141cc406Sopenharmony_ci
646141cc406Sopenharmony_ci  if (end_of_data (fd) == -1)
647141cc406Sopenharmony_ci    {
648141cc406Sopenharmony_ci      DBG (4, "%s: error: end_of_data returned -1\n", f);
649141cc406Sopenharmony_ci    }
650141cc406Sopenharmony_ci  return 0;
651141cc406Sopenharmony_ci}
652141cc406Sopenharmony_ci
653141cc406Sopenharmony_ciSANE_Status
654141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize)
655141cc406Sopenharmony_ci{
656141cc406Sopenharmony_ci
657141cc406Sopenharmony_ci  char f[] = "sane_init";
658141cc406Sopenharmony_ci  char dev_name[PATH_MAX], *p;
659141cc406Sopenharmony_ci  size_t len;
660141cc406Sopenharmony_ci  FILE *fp;
661141cc406Sopenharmony_ci  int baud;
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  DBG_INIT ();
664141cc406Sopenharmony_ci
665141cc406Sopenharmony_ci  if (version_code)
666141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
667141cc406Sopenharmony_ci
668141cc406Sopenharmony_ci  fp = sanei_config_open (DC210_CONFIG_FILE);
669141cc406Sopenharmony_ci
670141cc406Sopenharmony_ci  /* defaults */
671141cc406Sopenharmony_ci  Camera.baud = DEFAULT_BAUD_RATE;
672141cc406Sopenharmony_ci  Camera.tty_name = DEFAULT_TTY;
673141cc406Sopenharmony_ci
674141cc406Sopenharmony_ci  if (!fp)
675141cc406Sopenharmony_ci    {
676141cc406Sopenharmony_ci      /* default to /dev/whatever instead of insisting on config file */
677141cc406Sopenharmony_ci      DBG (1, "%s:  missing config file '%s'\n", f, DC210_CONFIG_FILE);
678141cc406Sopenharmony_ci    }
679141cc406Sopenharmony_ci  else
680141cc406Sopenharmony_ci    {
681141cc406Sopenharmony_ci      while (sanei_config_read (dev_name, sizeof (dev_name), fp))
682141cc406Sopenharmony_ci	{
683141cc406Sopenharmony_ci	  dev_name[sizeof (dev_name) - 1] = '\0';
684141cc406Sopenharmony_ci	  DBG (20, "%s:  config- %s\n", f, dev_name);
685141cc406Sopenharmony_ci
686141cc406Sopenharmony_ci	  if (dev_name[0] == '#')
687141cc406Sopenharmony_ci	    continue;		/* ignore line comments */
688141cc406Sopenharmony_ci	  len = strlen (dev_name);
689141cc406Sopenharmony_ci	  if (!len)
690141cc406Sopenharmony_ci	    continue;		/* ignore empty lines */
691141cc406Sopenharmony_ci	  if (strncmp (dev_name, "port=", 5) == 0)
692141cc406Sopenharmony_ci	    {
693141cc406Sopenharmony_ci	      p = strchr (dev_name, '/');
694141cc406Sopenharmony_ci	      if (p)
695141cc406Sopenharmony_ci		Camera.tty_name = strdup (p);
696141cc406Sopenharmony_ci	      DBG (20, "Config file port=%s\n", Camera.tty_name);
697141cc406Sopenharmony_ci	    }
698141cc406Sopenharmony_ci	  else if (strncmp (dev_name, "baud=", 5) == 0)
699141cc406Sopenharmony_ci	    {
700141cc406Sopenharmony_ci	      baud = atoi (&dev_name[5]);
701141cc406Sopenharmony_ci	      switch (baud)
702141cc406Sopenharmony_ci		{
703141cc406Sopenharmony_ci		case 9600:
704141cc406Sopenharmony_ci		  Camera.baud = B9600;
705141cc406Sopenharmony_ci		  break;
706141cc406Sopenharmony_ci		case 19200:
707141cc406Sopenharmony_ci		  Camera.baud = B19200;
708141cc406Sopenharmony_ci		  break;
709141cc406Sopenharmony_ci		case 38400:
710141cc406Sopenharmony_ci		  Camera.baud = B38400;
711141cc406Sopenharmony_ci		  break;
712141cc406Sopenharmony_ci#ifdef B57600
713141cc406Sopenharmony_ci		case 57600:
714141cc406Sopenharmony_ci		  Camera.baud = B57600;
715141cc406Sopenharmony_ci		  break;
716141cc406Sopenharmony_ci#endif
717141cc406Sopenharmony_ci#ifdef B115200
718141cc406Sopenharmony_ci		case 115200:
719141cc406Sopenharmony_ci		  Camera.baud = B115200;
720141cc406Sopenharmony_ci		  break;
721141cc406Sopenharmony_ci#endif
722141cc406Sopenharmony_ci		}
723141cc406Sopenharmony_ci	      DBG (20, "Config file baud=%d\n", Camera.baud);
724141cc406Sopenharmony_ci	    }
725141cc406Sopenharmony_ci	  else if (strcmp (dev_name, "dumpinquiry") == 0)
726141cc406Sopenharmony_ci	    {
727141cc406Sopenharmony_ci	      dumpinquiry = SANE_TRUE;
728141cc406Sopenharmony_ci	    }
729141cc406Sopenharmony_ci	  else if (strncmp (dev_name, "cmdrespause=", 12) == 0)
730141cc406Sopenharmony_ci	    {
731141cc406Sopenharmony_ci	      cmdrespause = atoi (&dev_name[12]);
732141cc406Sopenharmony_ci	      DBG (20, "Config file cmdrespause=%lu\n", cmdrespause);
733141cc406Sopenharmony_ci	    }
734141cc406Sopenharmony_ci	  else if (strncmp (dev_name, "breakpause=", 11) == 0)
735141cc406Sopenharmony_ci	    {
736141cc406Sopenharmony_ci	      breakpause = atoi (&dev_name[11]);
737141cc406Sopenharmony_ci	      DBG (20, "Config file breakpause=%lu\n", breakpause);
738141cc406Sopenharmony_ci	    }
739141cc406Sopenharmony_ci	}
740141cc406Sopenharmony_ci      fclose (fp);
741141cc406Sopenharmony_ci    }
742141cc406Sopenharmony_ci
743141cc406Sopenharmony_ci  if (init_dc210 (&Camera) == -1)
744141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
745141cc406Sopenharmony_ci
746141cc406Sopenharmony_ci  if (get_info (&Camera) == -1)
747141cc406Sopenharmony_ci    {
748141cc406Sopenharmony_ci      DBG (2, "error: could not get info\n");
749141cc406Sopenharmony_ci      close_dc210 (Camera.fd);
750141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
751141cc406Sopenharmony_ci    }
752141cc406Sopenharmony_ci  if (Camera.pic_taken == 0)
753141cc406Sopenharmony_ci    {
754141cc406Sopenharmony_ci      sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
755141cc406Sopenharmony_ci      image_range.min = 0;
756141cc406Sopenharmony_ci      image_range.max = 0;
757141cc406Sopenharmony_ci    }
758141cc406Sopenharmony_ci  else
759141cc406Sopenharmony_ci    {
760141cc406Sopenharmony_ci      sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
761141cc406Sopenharmony_ci      image_range.min = 1;
762141cc406Sopenharmony_ci      image_range.max = Camera.pic_taken;
763141cc406Sopenharmony_ci    }
764141cc406Sopenharmony_ci
765141cc406Sopenharmony_ci
766141cc406Sopenharmony_ci  /* load the current images array */
767141cc406Sopenharmony_ci  Camera.Pictures = get_pictures_info ();
768141cc406Sopenharmony_ci
769141cc406Sopenharmony_ci  if (Camera.pic_taken == 0)
770141cc406Sopenharmony_ci    {
771141cc406Sopenharmony_ci      Camera.current_picture_number = 0;
772141cc406Sopenharmony_ci      parms.bytes_per_line = 0;
773141cc406Sopenharmony_ci      parms.pixels_per_line = 0;
774141cc406Sopenharmony_ci      parms.lines = 0;
775141cc406Sopenharmony_ci    }
776141cc406Sopenharmony_ci  else
777141cc406Sopenharmony_ci    {
778141cc406Sopenharmony_ci      Camera.current_picture_number = 1;
779141cc406Sopenharmony_ci      if (Camera.Pictures[Camera.current_picture_number - 1].low_res)
780141cc406Sopenharmony_ci	{
781141cc406Sopenharmony_ci	  parms.bytes_per_line = 640 * 3;
782141cc406Sopenharmony_ci	  parms.pixels_per_line = 640;
783141cc406Sopenharmony_ci	  parms.lines = 480;
784141cc406Sopenharmony_ci	}
785141cc406Sopenharmony_ci      else
786141cc406Sopenharmony_ci	{
787141cc406Sopenharmony_ci	  parms.bytes_per_line = 1152 * 3;
788141cc406Sopenharmony_ci	  parms.pixels_per_line = 1152;
789141cc406Sopenharmony_ci	  parms.lines = 864;
790141cc406Sopenharmony_ci	}
791141cc406Sopenharmony_ci    }
792141cc406Sopenharmony_ci
793141cc406Sopenharmony_ci  if (dumpinquiry)
794141cc406Sopenharmony_ci    {
795141cc406Sopenharmony_ci      DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n");
796141cc406Sopenharmony_ci      DBG (0, "Model...........: DC%x\n", Camera.model);
797141cc406Sopenharmony_ci      DBG (0, "Firmware version: %d.%d\n", Camera.ver_major,
798141cc406Sopenharmony_ci	   Camera.ver_minor);
799141cc406Sopenharmony_ci      DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken,
800141cc406Sopenharmony_ci	   Camera.pic_taken + Camera.pic_left);
801141cc406Sopenharmony_ci      DBG (0, "Resolution......: %s\n",
802141cc406Sopenharmony_ci	   Camera.flags.low_res ? "low" : "high");
803141cc406Sopenharmony_ci      DBG (0, "Battery state...: %s\n",
804141cc406Sopenharmony_ci	   Camera.flags.low_batt ? "low" : "good");
805141cc406Sopenharmony_ci    }
806141cc406Sopenharmony_ci
807141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
808141cc406Sopenharmony_ci}
809141cc406Sopenharmony_ci
810141cc406Sopenharmony_civoid
811141cc406Sopenharmony_cisane_exit (void)
812141cc406Sopenharmony_ci{
813141cc406Sopenharmony_ci}
814141cc406Sopenharmony_ci
815141cc406Sopenharmony_ci/* Device select/open/close */
816141cc406Sopenharmony_ci
817141cc406Sopenharmony_cistatic const SANE_Device dev[] = {
818141cc406Sopenharmony_ci  {
819141cc406Sopenharmony_ci   "0",
820141cc406Sopenharmony_ci   "Kodak",
821141cc406Sopenharmony_ci   "DC-210",
822141cc406Sopenharmony_ci   "still camera"},
823141cc406Sopenharmony_ci};
824141cc406Sopenharmony_ci
825141cc406Sopenharmony_ciSANE_Status
826141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list,
827141cc406Sopenharmony_ci		  SANE_Bool __sane_unused__ local_only)
828141cc406Sopenharmony_ci{
829141cc406Sopenharmony_ci  static const SANE_Device *devlist[] = {
830141cc406Sopenharmony_ci    dev + 0, 0
831141cc406Sopenharmony_ci  };
832141cc406Sopenharmony_ci
833141cc406Sopenharmony_ci  DBG (127, "sane_get_devices called\n");
834141cc406Sopenharmony_ci
835141cc406Sopenharmony_ci  *device_list = devlist;
836141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
837141cc406Sopenharmony_ci}
838141cc406Sopenharmony_ci
839141cc406Sopenharmony_ciSANE_Status
840141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle)
841141cc406Sopenharmony_ci{
842141cc406Sopenharmony_ci  int i;
843141cc406Sopenharmony_ci
844141cc406Sopenharmony_ci  DBG (127, "sane_open for device %s\n", devicename);
845141cc406Sopenharmony_ci  if (!devicename[0])
846141cc406Sopenharmony_ci    {
847141cc406Sopenharmony_ci      i = 0;
848141cc406Sopenharmony_ci    }
849141cc406Sopenharmony_ci  else
850141cc406Sopenharmony_ci    {
851141cc406Sopenharmony_ci      for (i = 0; i < NELEMS (dev); ++i)
852141cc406Sopenharmony_ci	{
853141cc406Sopenharmony_ci	  if (strcmp (devicename, dev[i].name) == 0)
854141cc406Sopenharmony_ci	    {
855141cc406Sopenharmony_ci	      break;
856141cc406Sopenharmony_ci	    }
857141cc406Sopenharmony_ci	}
858141cc406Sopenharmony_ci    }
859141cc406Sopenharmony_ci
860141cc406Sopenharmony_ci  if (i >= NELEMS (dev))
861141cc406Sopenharmony_ci    {
862141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
863141cc406Sopenharmony_ci    }
864141cc406Sopenharmony_ci
865141cc406Sopenharmony_ci  if (is_open)
866141cc406Sopenharmony_ci    {
867141cc406Sopenharmony_ci      return SANE_STATUS_DEVICE_BUSY;
868141cc406Sopenharmony_ci    }
869141cc406Sopenharmony_ci
870141cc406Sopenharmony_ci  is_open = 1;
871141cc406Sopenharmony_ci  *handle = MAGIC;
872141cc406Sopenharmony_ci
873141cc406Sopenharmony_ci  DBG (3, "sane_open: pictures taken=%d\n", Camera.pic_taken);
874141cc406Sopenharmony_ci
875141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
876141cc406Sopenharmony_ci}
877141cc406Sopenharmony_ci
878141cc406Sopenharmony_civoid
879141cc406Sopenharmony_cisane_close (SANE_Handle handle)
880141cc406Sopenharmony_ci{
881141cc406Sopenharmony_ci  DBG (127, "sane_close called\n");
882141cc406Sopenharmony_ci  if (handle == MAGIC)
883141cc406Sopenharmony_ci    is_open = 0;
884141cc406Sopenharmony_ci
885141cc406Sopenharmony_ci  DBG (127, "sane_close returning\n");
886141cc406Sopenharmony_ci}
887141cc406Sopenharmony_ci
888141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
889141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
890141cc406Sopenharmony_ci{
891141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
892141cc406Sopenharmony_ci    return NULL;		/* wrong device */
893141cc406Sopenharmony_ci  if (option < 0 || option >= NELEMS (sod))
894141cc406Sopenharmony_ci    return NULL;
895141cc406Sopenharmony_ci  return &sod[option];
896141cc406Sopenharmony_ci}
897141cc406Sopenharmony_ci
898141cc406Sopenharmony_ciSANE_Status
899141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
900141cc406Sopenharmony_ci		     SANE_Action action, void *value, SANE_Int * info)
901141cc406Sopenharmony_ci{
902141cc406Sopenharmony_ci  SANE_Int myinfo = 0;
903141cc406Sopenharmony_ci  SANE_Status status;
904141cc406Sopenharmony_ci
905141cc406Sopenharmony_ci  DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n",
906141cc406Sopenharmony_ci       handle, sod[option].title,
907141cc406Sopenharmony_ci       (action ==
908141cc406Sopenharmony_ci	SANE_ACTION_SET_VALUE ? "SET" : (action ==
909141cc406Sopenharmony_ci					 SANE_ACTION_GET_VALUE ? "GET" :
910141cc406Sopenharmony_ci					 "SETAUTO")), value, (void *)info);
911141cc406Sopenharmony_ci
912141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
913141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown handle ... */
914141cc406Sopenharmony_ci
915141cc406Sopenharmony_ci  if (option < 0 || option >= NELEMS (sod))
916141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown option ... */
917141cc406Sopenharmony_ci
918141cc406Sopenharmony_ci  switch (action)
919141cc406Sopenharmony_ci    {
920141cc406Sopenharmony_ci    case SANE_ACTION_SET_VALUE:
921141cc406Sopenharmony_ci      status = sanei_constrain_value (sod + option, value, &myinfo);
922141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
923141cc406Sopenharmony_ci	{
924141cc406Sopenharmony_ci	  DBG (1, "Constraint error in control_option\n");
925141cc406Sopenharmony_ci	  return status;
926141cc406Sopenharmony_ci	}
927141cc406Sopenharmony_ci
928141cc406Sopenharmony_ci      switch (option)
929141cc406Sopenharmony_ci	{
930141cc406Sopenharmony_ci	case DC210_OPT_IMAGE_NUMBER:
931141cc406Sopenharmony_ci	  Camera.current_picture_number = *(SANE_Word *) value;
932141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
933141cc406Sopenharmony_ci	  /* get the image's resolution */
934141cc406Sopenharmony_ci
935141cc406Sopenharmony_ci	  if (Camera.Pictures[Camera.current_picture_number - 1].low_res)
936141cc406Sopenharmony_ci	    {
937141cc406Sopenharmony_ci	      parms.bytes_per_line = 640 * 3;
938141cc406Sopenharmony_ci	      parms.pixels_per_line = 640;
939141cc406Sopenharmony_ci	      parms.lines = 480;
940141cc406Sopenharmony_ci	    }
941141cc406Sopenharmony_ci	  else
942141cc406Sopenharmony_ci	    {
943141cc406Sopenharmony_ci	      parms.bytes_per_line = 1152 * 3;
944141cc406Sopenharmony_ci	      parms.pixels_per_line = 1152;
945141cc406Sopenharmony_ci	      parms.lines = 864;
946141cc406Sopenharmony_ci	    }
947141cc406Sopenharmony_ci	  break;
948141cc406Sopenharmony_ci
949141cc406Sopenharmony_ci	case DC210_OPT_THUMBS:
950141cc406Sopenharmony_ci	  dc210_opt_thumbnails = !!*(SANE_Word *) value;
951141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
952141cc406Sopenharmony_ci
953141cc406Sopenharmony_ci	  if (dc210_opt_thumbnails)
954141cc406Sopenharmony_ci	    {
955141cc406Sopenharmony_ci	      /*
956141cc406Sopenharmony_ci	       * DC210 thumbnail are 96x72x8x3
957141cc406Sopenharmony_ci	       */
958141cc406Sopenharmony_ci	      parms.bytes_per_line = 96 * 3;
959141cc406Sopenharmony_ci	      parms.pixels_per_line = 96;
960141cc406Sopenharmony_ci	      parms.lines = 72;
961141cc406Sopenharmony_ci	    }
962141cc406Sopenharmony_ci	  else
963141cc406Sopenharmony_ci	    {
964141cc406Sopenharmony_ci	      if (Camera.Pictures[Camera.current_picture_number - 1].low_res)
965141cc406Sopenharmony_ci		{
966141cc406Sopenharmony_ci		  parms.bytes_per_line = 640 * 3;
967141cc406Sopenharmony_ci		  parms.pixels_per_line = 640;
968141cc406Sopenharmony_ci		  parms.lines = 480;
969141cc406Sopenharmony_ci		}
970141cc406Sopenharmony_ci	      else
971141cc406Sopenharmony_ci		{
972141cc406Sopenharmony_ci		  parms.bytes_per_line = 1152 * 3;
973141cc406Sopenharmony_ci		  parms.pixels_per_line = 1152;
974141cc406Sopenharmony_ci		  parms.lines = 864;
975141cc406Sopenharmony_ci		}
976141cc406Sopenharmony_ci	    }
977141cc406Sopenharmony_ci	  break;
978141cc406Sopenharmony_ci
979141cc406Sopenharmony_ci	case DC210_OPT_SNAP:
980141cc406Sopenharmony_ci	  dc210_opt_snap = !!*(SANE_Word *) value;
981141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
982141cc406Sopenharmony_ci	  /* if we are snapping a new one */
983141cc406Sopenharmony_ci	  if (dc210_opt_snap)
984141cc406Sopenharmony_ci	    {
985141cc406Sopenharmony_ci	      /* activate the resolution setting */
986141cc406Sopenharmony_ci	      sod[DC210_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE;
987141cc406Sopenharmony_ci	      /* and de-activate the image number selector */
988141cc406Sopenharmony_ci	      sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
989141cc406Sopenharmony_ci	    }
990141cc406Sopenharmony_ci	  else
991141cc406Sopenharmony_ci	    {
992141cc406Sopenharmony_ci	      /* deactivate the resolution setting */
993141cc406Sopenharmony_ci	      sod[DC210_OPT_LOWRES].cap |= SANE_CAP_INACTIVE;
994141cc406Sopenharmony_ci	      /* and activate the image number selector */
995141cc406Sopenharmony_ci	      sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
996141cc406Sopenharmony_ci	    }
997141cc406Sopenharmony_ci	  /* set params according to resolution settings */
998141cc406Sopenharmony_ci	  if (dc210_opt_lowres)
999141cc406Sopenharmony_ci	    {
1000141cc406Sopenharmony_ci	      parms.bytes_per_line = 640 * 3;
1001141cc406Sopenharmony_ci	      parms.pixels_per_line = 640;
1002141cc406Sopenharmony_ci	      parms.lines = 480;
1003141cc406Sopenharmony_ci	    }
1004141cc406Sopenharmony_ci	  else
1005141cc406Sopenharmony_ci	    {
1006141cc406Sopenharmony_ci	      parms.bytes_per_line = 1152 * 3;
1007141cc406Sopenharmony_ci	      parms.pixels_per_line = 1152;
1008141cc406Sopenharmony_ci	      parms.lines = 864;
1009141cc406Sopenharmony_ci	    }
1010141cc406Sopenharmony_ci	  break;
1011141cc406Sopenharmony_ci
1012141cc406Sopenharmony_ci	case DC210_OPT_LOWRES:
1013141cc406Sopenharmony_ci	  dc210_opt_lowres = !!*(SANE_Word *) value;
1014141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
1015141cc406Sopenharmony_ci
1016141cc406Sopenharmony_ci	  if (!dc210_opt_thumbnails)
1017141cc406Sopenharmony_ci	    {
1018141cc406Sopenharmony_ci
1019141cc406Sopenharmony_ci/* XXX - change the number of pictures left depending on resolution
1020141cc406Sopenharmony_ci   perhaps just call get_info again?
1021141cc406Sopenharmony_ci */
1022141cc406Sopenharmony_ci	      if (dc210_opt_lowres)
1023141cc406Sopenharmony_ci		{
1024141cc406Sopenharmony_ci		  parms.bytes_per_line = 640 * 3;
1025141cc406Sopenharmony_ci		  parms.pixels_per_line = 640;
1026141cc406Sopenharmony_ci		  parms.lines = 480;
1027141cc406Sopenharmony_ci		}
1028141cc406Sopenharmony_ci	      else
1029141cc406Sopenharmony_ci		{
1030141cc406Sopenharmony_ci		  parms.bytes_per_line = 1152 * 3;
1031141cc406Sopenharmony_ci		  parms.pixels_per_line = 1152;
1032141cc406Sopenharmony_ci		  parms.lines = 864;
1033141cc406Sopenharmony_ci		}
1034141cc406Sopenharmony_ci
1035141cc406Sopenharmony_ci	    }
1036141cc406Sopenharmony_ci	  break;
1037141cc406Sopenharmony_ci
1038141cc406Sopenharmony_ci	case DC210_OPT_ERASE:
1039141cc406Sopenharmony_ci	  dc210_opt_erase = !!*(SANE_Word *) value;
1040141cc406Sopenharmony_ci	  break;
1041141cc406Sopenharmony_ci
1042141cc406Sopenharmony_ci	case DC210_OPT_DEFAULT:
1043141cc406Sopenharmony_ci	  DBG (1, "Fixme: Set all defaults here!\n");
1044141cc406Sopenharmony_ci	  break;
1045141cc406Sopenharmony_ci	case DC210_OPT_INIT_DC210:
1046141cc406Sopenharmony_ci	  if ((Camera.fd = init_dc210 (&Camera)) == -1)
1047141cc406Sopenharmony_ci	    {
1048141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1049141cc406Sopenharmony_ci	    }
1050141cc406Sopenharmony_ci	  break;
1051141cc406Sopenharmony_ci
1052141cc406Sopenharmony_ci	default:
1053141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1054141cc406Sopenharmony_ci	}
1055141cc406Sopenharmony_ci      break;
1056141cc406Sopenharmony_ci
1057141cc406Sopenharmony_ci    case SANE_ACTION_GET_VALUE:
1058141cc406Sopenharmony_ci      switch (option)
1059141cc406Sopenharmony_ci	{
1060141cc406Sopenharmony_ci	case 0:
1061141cc406Sopenharmony_ci	  *(SANE_Word *) value = NELEMS (sod);
1062141cc406Sopenharmony_ci	  break;
1063141cc406Sopenharmony_ci
1064141cc406Sopenharmony_ci	case DC210_OPT_IMAGE_NUMBER:
1065141cc406Sopenharmony_ci	  *(SANE_Word *) value = Camera.current_picture_number;
1066141cc406Sopenharmony_ci	  break;
1067141cc406Sopenharmony_ci
1068141cc406Sopenharmony_ci	case DC210_OPT_THUMBS:
1069141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc210_opt_thumbnails;
1070141cc406Sopenharmony_ci	  break;
1071141cc406Sopenharmony_ci
1072141cc406Sopenharmony_ci	case DC210_OPT_SNAP:
1073141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc210_opt_snap;
1074141cc406Sopenharmony_ci	  break;
1075141cc406Sopenharmony_ci
1076141cc406Sopenharmony_ci	case DC210_OPT_LOWRES:
1077141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc210_opt_lowres;
1078141cc406Sopenharmony_ci	  break;
1079141cc406Sopenharmony_ci
1080141cc406Sopenharmony_ci	case DC210_OPT_ERASE:
1081141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc210_opt_erase;
1082141cc406Sopenharmony_ci	  break;
1083141cc406Sopenharmony_ci
1084141cc406Sopenharmony_ci	default:
1085141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1086141cc406Sopenharmony_ci	}
1087141cc406Sopenharmony_ci      break;
1088141cc406Sopenharmony_ci
1089141cc406Sopenharmony_ci    case SANE_ACTION_SET_AUTO:
1090141cc406Sopenharmony_ci      switch (option)
1091141cc406Sopenharmony_ci	{
1092141cc406Sopenharmony_ci	default:
1093141cc406Sopenharmony_ci	  return SANE_STATUS_UNSUPPORTED;	/* We are DUMB */
1094141cc406Sopenharmony_ci	}
1095141cc406Sopenharmony_ci    }
1096141cc406Sopenharmony_ci
1097141cc406Sopenharmony_ci  if (info)
1098141cc406Sopenharmony_ci    *info = myinfo;
1099141cc406Sopenharmony_ci
1100141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1101141cc406Sopenharmony_ci}
1102141cc406Sopenharmony_ci
1103141cc406Sopenharmony_ciSANE_Status
1104141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1105141cc406Sopenharmony_ci{
1106141cc406Sopenharmony_ci  int rc = SANE_STATUS_GOOD;
1107141cc406Sopenharmony_ci
1108141cc406Sopenharmony_ci  DBG (127, "sane_get_params called\n");
1109141cc406Sopenharmony_ci
1110141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
1111141cc406Sopenharmony_ci    rc = SANE_STATUS_INVAL;	/* Unknown handle ... */
1112141cc406Sopenharmony_ci
1113141cc406Sopenharmony_ci  parms.last_frame = SANE_TRUE;	/* Have no idea what this does */
1114141cc406Sopenharmony_ci  *params = parms;
1115141cc406Sopenharmony_ci  DBG (127, "sane_get_params return %d\n", rc);
1116141cc406Sopenharmony_ci  return rc;
1117141cc406Sopenharmony_ci}
1118141cc406Sopenharmony_ci
1119141cc406Sopenharmony_citypedef struct
1120141cc406Sopenharmony_ci{
1121141cc406Sopenharmony_ci  struct jpeg_source_mgr pub;
1122141cc406Sopenharmony_ci  JOCTET *buffer;
1123141cc406Sopenharmony_ci}
1124141cc406Sopenharmony_cimy_source_mgr;
1125141cc406Sopenharmony_citypedef my_source_mgr *my_src_ptr;
1126141cc406Sopenharmony_ci
1127141cc406Sopenharmony_ciMETHODDEF (void)
1128141cc406Sopenharmony_cisanei_jpeg_init_source (j_decompress_ptr __sane_unused__ cinfo)
1129141cc406Sopenharmony_ci{
1130141cc406Sopenharmony_ci  /* nothing to do */
1131141cc406Sopenharmony_ci}
1132141cc406Sopenharmony_ci
1133141cc406Sopenharmony_ciMETHODDEF (boolean) sanei_jpeg_fill_input_buffer (j_decompress_ptr cinfo)
1134141cc406Sopenharmony_ci{
1135141cc406Sopenharmony_ci
1136141cc406Sopenharmony_ci  my_src_ptr src = (my_src_ptr) cinfo->src;
1137141cc406Sopenharmony_ci
1138141cc406Sopenharmony_ci  if (read_data (Camera.fd, src->buffer, 1024) == -1)
1139141cc406Sopenharmony_ci    {
1140141cc406Sopenharmony_ci      DBG (5, "sane_start: read_data failed\n");
1141141cc406Sopenharmony_ci      src->buffer[0] = (JOCTET) 0xFF;
1142141cc406Sopenharmony_ci      src->buffer[1] = (JOCTET) JPEG_EOI;
1143141cc406Sopenharmony_ci      return FALSE;
1144141cc406Sopenharmony_ci    }
1145141cc406Sopenharmony_ci  src->pub.next_input_byte = src->buffer;
1146141cc406Sopenharmony_ci  src->pub.bytes_in_buffer = 1024;
1147141cc406Sopenharmony_ci
1148141cc406Sopenharmony_ci  return TRUE;
1149141cc406Sopenharmony_ci}
1150141cc406Sopenharmony_ci
1151141cc406Sopenharmony_ciMETHODDEF (void)
1152141cc406Sopenharmony_cisanei_jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
1153141cc406Sopenharmony_ci{
1154141cc406Sopenharmony_ci
1155141cc406Sopenharmony_ci  my_src_ptr src = (my_src_ptr) cinfo->src;
1156141cc406Sopenharmony_ci
1157141cc406Sopenharmony_ci  if (num_bytes > 0)
1158141cc406Sopenharmony_ci    {
1159141cc406Sopenharmony_ci      while (num_bytes > (long) src->pub.bytes_in_buffer)
1160141cc406Sopenharmony_ci	{
1161141cc406Sopenharmony_ci	  num_bytes -= (long) src->pub.bytes_in_buffer;
1162141cc406Sopenharmony_ci	  (void) sanei_jpeg_fill_input_buffer (cinfo);
1163141cc406Sopenharmony_ci	}
1164141cc406Sopenharmony_ci    }
1165141cc406Sopenharmony_ci  src->pub.next_input_byte += (size_t) num_bytes;
1166141cc406Sopenharmony_ci  src->pub.bytes_in_buffer -= (size_t) num_bytes;
1167141cc406Sopenharmony_ci}
1168141cc406Sopenharmony_ci
1169141cc406Sopenharmony_ciMETHODDEF (void)
1170141cc406Sopenharmony_cisanei_jpeg_term_source (j_decompress_ptr __sane_unused__ cinfo)
1171141cc406Sopenharmony_ci{
1172141cc406Sopenharmony_ci  /* no work necessary here */
1173141cc406Sopenharmony_ci}
1174141cc406Sopenharmony_ci
1175141cc406Sopenharmony_ciSANE_Status
1176141cc406Sopenharmony_cisane_start (SANE_Handle handle)
1177141cc406Sopenharmony_ci{
1178141cc406Sopenharmony_ci
1179141cc406Sopenharmony_ci  DBG (127, "sane_start called\n");
1180141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open ||
1181141cc406Sopenharmony_ci      (Camera.current_picture_number == 0 && dc210_opt_snap == SANE_FALSE))
1182141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown handle ... */
1183141cc406Sopenharmony_ci
1184141cc406Sopenharmony_ci  if (Camera.scanning)
1185141cc406Sopenharmony_ci    return SANE_STATUS_EOF;
1186141cc406Sopenharmony_ci
1187141cc406Sopenharmony_ci  if (dc210_opt_snap)
1188141cc406Sopenharmony_ci    {
1189141cc406Sopenharmony_ci
1190141cc406Sopenharmony_ci      /*
1191141cc406Sopenharmony_ci       * Don't allow picture unless there is room in the
1192141cc406Sopenharmony_ci       * camera.
1193141cc406Sopenharmony_ci       */
1194141cc406Sopenharmony_ci      if (Camera.pic_left == 0)
1195141cc406Sopenharmony_ci	{
1196141cc406Sopenharmony_ci	  DBG (3, "No room to store new picture\n");
1197141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1198141cc406Sopenharmony_ci	}
1199141cc406Sopenharmony_ci
1200141cc406Sopenharmony_ci
1201141cc406Sopenharmony_ci      if (snap_pic (Camera.fd) != SANE_STATUS_GOOD)
1202141cc406Sopenharmony_ci	{
1203141cc406Sopenharmony_ci	  DBG (1, "Failed to snap new picture\n");
1204141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1205141cc406Sopenharmony_ci	}
1206141cc406Sopenharmony_ci    }
1207141cc406Sopenharmony_ci
1208141cc406Sopenharmony_ci  if (dc210_opt_thumbnails)
1209141cc406Sopenharmony_ci    {
1210141cc406Sopenharmony_ci
1211141cc406Sopenharmony_ci      thumb_pck[3] = (unsigned char) Camera.current_picture_number - 1;
1212141cc406Sopenharmony_ci      thumb_pck[4] = 1;
1213141cc406Sopenharmony_ci
1214141cc406Sopenharmony_ci      if (send_pck (Camera.fd, thumb_pck) == -1)
1215141cc406Sopenharmony_ci	{
1216141cc406Sopenharmony_ci	  DBG (4, "sane_start: error: send_pck returned -1\n");
1217141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1218141cc406Sopenharmony_ci	}
1219141cc406Sopenharmony_ci
1220141cc406Sopenharmony_ci      parms.bytes_per_line = 96 * 3;
1221141cc406Sopenharmony_ci      parms.pixels_per_line = 96;
1222141cc406Sopenharmony_ci      parms.lines = 72;
1223141cc406Sopenharmony_ci
1224141cc406Sopenharmony_ci      bytes_in_buffer = 0;
1225141cc406Sopenharmony_ci      bytes_read_from_buffer = 0;
1226141cc406Sopenharmony_ci
1227141cc406Sopenharmony_ci    }
1228141cc406Sopenharmony_ci  else
1229141cc406Sopenharmony_ci    {
1230141cc406Sopenharmony_ci      my_src_ptr src;
1231141cc406Sopenharmony_ci
1232141cc406Sopenharmony_ci      struct jpeg_error_mgr jerr;
1233141cc406Sopenharmony_ci
1234141cc406Sopenharmony_ci      pic_pck[3] = (unsigned char) Camera.current_picture_number - 1;
1235141cc406Sopenharmony_ci
1236141cc406Sopenharmony_ci      if (send_pck (Camera.fd, pic_pck) == -1)
1237141cc406Sopenharmony_ci	{
1238141cc406Sopenharmony_ci	  DBG (4, "sane_start: error: send_pck returned -1\n");
1239141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1240141cc406Sopenharmony_ci	}
1241141cc406Sopenharmony_ci      cinfo.err = jpeg_std_error (&jerr);
1242141cc406Sopenharmony_ci      jpeg_create_decompress (&cinfo);
1243141cc406Sopenharmony_ci
1244141cc406Sopenharmony_ci      cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr));
1245141cc406Sopenharmony_ci      src = (my_src_ptr) cinfo.src;
1246141cc406Sopenharmony_ci
1247141cc406Sopenharmony_ci      src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) &
1248141cc406Sopenharmony_ci							  cinfo,
1249141cc406Sopenharmony_ci							  JPOOL_PERMANENT,
1250141cc406Sopenharmony_ci							  1024 *
1251141cc406Sopenharmony_ci							  sizeof (JOCTET));
1252141cc406Sopenharmony_ci      src->pub.init_source = sanei_jpeg_init_source;
1253141cc406Sopenharmony_ci      src->pub.fill_input_buffer = sanei_jpeg_fill_input_buffer;
1254141cc406Sopenharmony_ci      src->pub.skip_input_data = sanei_jpeg_skip_input_data;
1255141cc406Sopenharmony_ci      src->pub.resync_to_restart = jpeg_resync_to_restart;	/* default */
1256141cc406Sopenharmony_ci      src->pub.term_source = sanei_jpeg_term_source;
1257141cc406Sopenharmony_ci      src->pub.bytes_in_buffer = 0;
1258141cc406Sopenharmony_ci      src->pub.next_input_byte = NULL;
1259141cc406Sopenharmony_ci
1260141cc406Sopenharmony_ci      (void) jpeg_read_header (&cinfo, TRUE);
1261141cc406Sopenharmony_ci      dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo);
1262141cc406Sopenharmony_ci      (void) jpeg_start_decompress (&cinfo);
1263141cc406Sopenharmony_ci    }
1264141cc406Sopenharmony_ci
1265141cc406Sopenharmony_ci  Camera.scanning = SANE_TRUE;	/* don't overlap scan requests */
1266141cc406Sopenharmony_ci  total_bytes_read = 0;
1267141cc406Sopenharmony_ci
1268141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1269141cc406Sopenharmony_ci}
1270141cc406Sopenharmony_ci
1271141cc406Sopenharmony_ciSANE_Status
1272141cc406Sopenharmony_cisane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data,
1273141cc406Sopenharmony_ci	   SANE_Int max_length, SANE_Int * length)
1274141cc406Sopenharmony_ci{
1275141cc406Sopenharmony_ci
1276141cc406Sopenharmony_ci  static char buffer[1024];
1277141cc406Sopenharmony_ci
1278141cc406Sopenharmony_ci  if (dc210_opt_thumbnails)
1279141cc406Sopenharmony_ci    {
1280141cc406Sopenharmony_ci      if (total_bytes_read == THUMBSIZE)
1281141cc406Sopenharmony_ci	{
1282141cc406Sopenharmony_ci	  if (dc210_opt_erase)
1283141cc406Sopenharmony_ci	    {
1284141cc406Sopenharmony_ci	      if (erase (Camera.fd) == -1)
1285141cc406Sopenharmony_ci		{
1286141cc406Sopenharmony_ci		  DBG (1, "Failed to erase memory\n");
1287141cc406Sopenharmony_ci		  return SANE_STATUS_INVAL;
1288141cc406Sopenharmony_ci		}
1289141cc406Sopenharmony_ci	      Camera.pic_taken--;
1290141cc406Sopenharmony_ci	      Camera.pic_left++;
1291141cc406Sopenharmony_ci	      Camera.current_picture_number = Camera.pic_taken;
1292141cc406Sopenharmony_ci	      image_range.max--;
1293141cc406Sopenharmony_ci	    }
1294141cc406Sopenharmony_ci	  return SANE_STATUS_EOF;
1295141cc406Sopenharmony_ci	}
1296141cc406Sopenharmony_ci
1297141cc406Sopenharmony_ci      *length = 0;
1298141cc406Sopenharmony_ci      if (!(bytes_in_buffer - bytes_read_from_buffer))
1299141cc406Sopenharmony_ci	{
1300141cc406Sopenharmony_ci	  if (read_data (Camera.fd, (unsigned char *) buffer, 1024) == -1)
1301141cc406Sopenharmony_ci	    {
1302141cc406Sopenharmony_ci	      DBG (5, "sane_read: read_data failed\n");
1303141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1304141cc406Sopenharmony_ci	    }
1305141cc406Sopenharmony_ci	  bytes_in_buffer = 1024;
1306141cc406Sopenharmony_ci	  bytes_read_from_buffer = 0;
1307141cc406Sopenharmony_ci	}
1308141cc406Sopenharmony_ci
1309141cc406Sopenharmony_ci      while (bytes_read_from_buffer < bytes_in_buffer &&
1310141cc406Sopenharmony_ci	     max_length && total_bytes_read < THUMBSIZE)
1311141cc406Sopenharmony_ci	{
1312141cc406Sopenharmony_ci	  *data++ = buffer[bytes_read_from_buffer++];
1313141cc406Sopenharmony_ci	  (*length)++;
1314141cc406Sopenharmony_ci	  max_length--;
1315141cc406Sopenharmony_ci	  total_bytes_read++;
1316141cc406Sopenharmony_ci	}
1317141cc406Sopenharmony_ci
1318141cc406Sopenharmony_ci      if (total_bytes_read == THUMBSIZE)
1319141cc406Sopenharmony_ci	{
1320141cc406Sopenharmony_ci	  if (end_of_data (Camera.fd) == -1)
1321141cc406Sopenharmony_ci	    {
1322141cc406Sopenharmony_ci	      DBG (4, "sane_read: end_of_data error\n");
1323141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1324141cc406Sopenharmony_ci	    }
1325141cc406Sopenharmony_ci	  else
1326141cc406Sopenharmony_ci	    {
1327141cc406Sopenharmony_ci	      return SANE_STATUS_GOOD;
1328141cc406Sopenharmony_ci	    }
1329141cc406Sopenharmony_ci	}
1330141cc406Sopenharmony_ci      else
1331141cc406Sopenharmony_ci	{
1332141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
1333141cc406Sopenharmony_ci	}
1334141cc406Sopenharmony_ci    }
1335141cc406Sopenharmony_ci  else
1336141cc406Sopenharmony_ci    {
1337141cc406Sopenharmony_ci      int lines = 0;
1338141cc406Sopenharmony_ci
1339141cc406Sopenharmony_ci      if (cinfo.output_scanline >= cinfo.output_height)
1340141cc406Sopenharmony_ci	{
1341141cc406Sopenharmony_ci	  /* clean up comms with the camera */
1342141cc406Sopenharmony_ci	  if (end_of_data (Camera.fd) == -1)
1343141cc406Sopenharmony_ci	    {
1344141cc406Sopenharmony_ci	      DBG (2, "sane_read: error: end_of_data returned -1\n");
1345141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1346141cc406Sopenharmony_ci	    }
1347141cc406Sopenharmony_ci	  if (dc210_opt_erase)
1348141cc406Sopenharmony_ci	    {
1349141cc406Sopenharmony_ci	      DBG (127, "sane_read bp%d, erase image\n", __LINE__);
1350141cc406Sopenharmony_ci	      if (erase (Camera.fd) == -1)
1351141cc406Sopenharmony_ci		{
1352141cc406Sopenharmony_ci		  DBG (1, "Failed to erase memory\n");
1353141cc406Sopenharmony_ci		  return SANE_STATUS_INVAL;
1354141cc406Sopenharmony_ci		}
1355141cc406Sopenharmony_ci	      Camera.pic_taken--;
1356141cc406Sopenharmony_ci	      Camera.pic_left++;
1357141cc406Sopenharmony_ci	      Camera.current_picture_number = Camera.pic_taken;
1358141cc406Sopenharmony_ci	      image_range.max--;
1359141cc406Sopenharmony_ci	    }
1360141cc406Sopenharmony_ci	  return SANE_STATUS_EOF;
1361141cc406Sopenharmony_ci	}
1362141cc406Sopenharmony_ci
1363141cc406Sopenharmony_ci/* XXX - we should read more than 1 line at a time here */
1364141cc406Sopenharmony_ci      lines = 1;
1365141cc406Sopenharmony_ci      (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines);
1366141cc406Sopenharmony_ci      (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) data);
1367141cc406Sopenharmony_ci      *length = cinfo.output_width * cinfo.output_components * lines;
1368141cc406Sopenharmony_ci
1369141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
1370141cc406Sopenharmony_ci
1371141cc406Sopenharmony_ci    }
1372141cc406Sopenharmony_ci}
1373141cc406Sopenharmony_ci
1374141cc406Sopenharmony_civoid
1375141cc406Sopenharmony_cisane_cancel (SANE_Handle __sane_unused__ handle)
1376141cc406Sopenharmony_ci{
1377141cc406Sopenharmony_ci  DBG (127, "sane_cancel() called\n");
1378141cc406Sopenharmony_ci  if (Camera.scanning)
1379141cc406Sopenharmony_ci    Camera.scanning = SANE_FALSE;	/* done with scan */
1380141cc406Sopenharmony_ci  else
1381141cc406Sopenharmony_ci    DBG (127, "sane_cancel() aborted, scanner not scanning\n");
1382141cc406Sopenharmony_ci}
1383141cc406Sopenharmony_ci
1384141cc406Sopenharmony_ciSANE_Status
1385141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle,
1386141cc406Sopenharmony_ci		  SANE_Bool __sane_unused__ non_blocking)
1387141cc406Sopenharmony_ci{
1388141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1389141cc406Sopenharmony_ci}
1390141cc406Sopenharmony_ci
1391141cc406Sopenharmony_ciSANE_Status
1392141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)
1393141cc406Sopenharmony_ci{
1394141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1395141cc406Sopenharmony_ci}
1396141cc406Sopenharmony_ci
1397141cc406Sopenharmony_cistatic PictureInfo *
1398141cc406Sopenharmony_ciget_pictures_info (void)
1399141cc406Sopenharmony_ci{
1400141cc406Sopenharmony_ci
1401141cc406Sopenharmony_ci  char f[] = "get_pictures_info";
1402141cc406Sopenharmony_ci  unsigned int p;
1403141cc406Sopenharmony_ci  PictureInfo *pics;
1404141cc406Sopenharmony_ci
1405141cc406Sopenharmony_ci  if ((pics = (PictureInfo *) malloc (Camera.pic_taken *
1406141cc406Sopenharmony_ci				      sizeof (PictureInfo))) == NULL)
1407141cc406Sopenharmony_ci    {
1408141cc406Sopenharmony_ci      DBG (4, "%s: error: allocate memory for pictures array\n", f);
1409141cc406Sopenharmony_ci      return NULL;
1410141cc406Sopenharmony_ci    }
1411141cc406Sopenharmony_ci
1412141cc406Sopenharmony_ci  for (p = 0; p < (unsigned int) Camera.pic_taken; p++)
1413141cc406Sopenharmony_ci    {
1414141cc406Sopenharmony_ci      if (get_picture_info (pics + p, p) == -1)
1415141cc406Sopenharmony_ci	{
1416141cc406Sopenharmony_ci	  free (pics);
1417141cc406Sopenharmony_ci	  return NULL;
1418141cc406Sopenharmony_ci	}
1419141cc406Sopenharmony_ci    }
1420141cc406Sopenharmony_ci
1421141cc406Sopenharmony_ci  return pics;
1422141cc406Sopenharmony_ci}
1423141cc406Sopenharmony_ci
1424141cc406Sopenharmony_cistatic int
1425141cc406Sopenharmony_ciget_picture_info (PictureInfo * pic, int p)
1426141cc406Sopenharmony_ci{
1427141cc406Sopenharmony_ci
1428141cc406Sopenharmony_ci  char f[] = "get_picture_info";
1429141cc406Sopenharmony_ci  static char buffer[256];
1430141cc406Sopenharmony_ci
1431141cc406Sopenharmony_ci  DBG (4, "%s: info for pic #%d\n", f, p);
1432141cc406Sopenharmony_ci
1433141cc406Sopenharmony_ci  pic_info_pck[3] = (unsigned char) p;
1434141cc406Sopenharmony_ci
1435141cc406Sopenharmony_ci  if (send_pck (Camera.fd, pic_info_pck) == -1)
1436141cc406Sopenharmony_ci    {
1437141cc406Sopenharmony_ci      DBG (4, "%s: error: send_pck returned -1\n", f);
1438141cc406Sopenharmony_ci      return -1;
1439141cc406Sopenharmony_ci    }
1440141cc406Sopenharmony_ci
1441141cc406Sopenharmony_ci  if (read_data (Camera.fd, (unsigned char *) buffer, 256) == -1)
1442141cc406Sopenharmony_ci    {
1443141cc406Sopenharmony_ci      DBG (2, "%s: error: read_data returned -1\n", f);
1444141cc406Sopenharmony_ci      return -1;
1445141cc406Sopenharmony_ci    }
1446141cc406Sopenharmony_ci
1447141cc406Sopenharmony_ci  if (end_of_data (Camera.fd) == -1)
1448141cc406Sopenharmony_ci    {
1449141cc406Sopenharmony_ci      DBG (2, "%s: error: end_of_data returned -1\n", f);
1450141cc406Sopenharmony_ci      return -1;
1451141cc406Sopenharmony_ci    }
1452141cc406Sopenharmony_ci
1453141cc406Sopenharmony_ci  if (buffer[3] == 0)
1454141cc406Sopenharmony_ci    {
1455141cc406Sopenharmony_ci      pic->low_res = SANE_TRUE;
1456141cc406Sopenharmony_ci    }
1457141cc406Sopenharmony_ci  else if (buffer[3] == 1)
1458141cc406Sopenharmony_ci    {
1459141cc406Sopenharmony_ci      pic->low_res = SANE_FALSE;
1460141cc406Sopenharmony_ci    }
1461141cc406Sopenharmony_ci  else
1462141cc406Sopenharmony_ci    {
1463141cc406Sopenharmony_ci      DBG (2, "%s: error: unknown resolution code %u\n", f, buffer[3]);
1464141cc406Sopenharmony_ci      return -1;
1465141cc406Sopenharmony_ci    }
1466141cc406Sopenharmony_ci  pic->size = (buffer[8] & 0xFF) << 24;
1467141cc406Sopenharmony_ci  pic->size |= (buffer[9] & 0xFF) << 16;
1468141cc406Sopenharmony_ci  pic->size |= (buffer[10] & 0xFF) << 8;
1469141cc406Sopenharmony_ci  pic->size |= (buffer[11] & 0xFF);
1470141cc406Sopenharmony_ci
1471141cc406Sopenharmony_ci  return 0;
1472141cc406Sopenharmony_ci}
1473141cc406Sopenharmony_ci
1474141cc406Sopenharmony_cistatic SANE_Status
1475141cc406Sopenharmony_cisnap_pic (int fd)
1476141cc406Sopenharmony_ci{
1477141cc406Sopenharmony_ci
1478141cc406Sopenharmony_ci  char f[] = "snap_pic";
1479141cc406Sopenharmony_ci
1480141cc406Sopenharmony_ci  /* make sure camera is set to our settings state */
1481141cc406Sopenharmony_ci  if (change_res (Camera.fd, dc210_opt_lowres) == -1)
1482141cc406Sopenharmony_ci    {
1483141cc406Sopenharmony_ci      DBG (1, "%s: Failed to set resolution\n", f);
1484141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1485141cc406Sopenharmony_ci    }
1486141cc406Sopenharmony_ci
1487141cc406Sopenharmony_ci  /* take the picture */
1488141cc406Sopenharmony_ci  if (send_pck (fd, shoot_pck) == -1)
1489141cc406Sopenharmony_ci    {
1490141cc406Sopenharmony_ci      DBG (4, "%s: error: send_pck returned -1\n", f);
1491141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1492141cc406Sopenharmony_ci    }
1493141cc406Sopenharmony_ci  else
1494141cc406Sopenharmony_ci    {
1495141cc406Sopenharmony_ci      if (end_of_data (Camera.fd) == -1)
1496141cc406Sopenharmony_ci	{
1497141cc406Sopenharmony_ci	  DBG (2, "%s: error: end_of_data returned -1\n", f);
1498141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1499141cc406Sopenharmony_ci	}
1500141cc406Sopenharmony_ci    }
1501141cc406Sopenharmony_ci  Camera.pic_taken++;
1502141cc406Sopenharmony_ci  Camera.pic_left--;
1503141cc406Sopenharmony_ci  Camera.current_picture_number = Camera.pic_taken;
1504141cc406Sopenharmony_ci  image_range.max++;
1505141cc406Sopenharmony_ci  sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
1506141cc406Sopenharmony_ci
1507141cc406Sopenharmony_ci  /* add this one to the Pictures array */
1508141cc406Sopenharmony_ci  if ((Camera.Pictures =
1509141cc406Sopenharmony_ci       (PictureInfo *) realloc (Camera.Pictures,
1510141cc406Sopenharmony_ci				Camera.pic_taken * sizeof (PictureInfo))) ==
1511141cc406Sopenharmony_ci      NULL)
1512141cc406Sopenharmony_ci    {
1513141cc406Sopenharmony_ci      DBG (4, "%s: error: allocate memory for pictures array\n", f);
1514141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1515141cc406Sopenharmony_ci    }
1516141cc406Sopenharmony_ci
1517141cc406Sopenharmony_ci  if (get_picture_info (Camera.Pictures + Camera.pic_taken,
1518141cc406Sopenharmony_ci			Camera.pic_taken) == -1)
1519141cc406Sopenharmony_ci    {
1520141cc406Sopenharmony_ci      DBG (1, "%s: Failed to get new picture info\n", f);
1521141cc406Sopenharmony_ci      /* XXX - I guess we should try to erase the image here */
1522141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1523141cc406Sopenharmony_ci    }
1524141cc406Sopenharmony_ci
1525141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1526141cc406Sopenharmony_ci}
1527