1141cc406Sopenharmony_ci/***************************************************************************
2141cc406Sopenharmony_ci * _S_A_N_E - Scanner Access Now Easy.
3141cc406Sopenharmony_ci
4141cc406Sopenharmony_ci   dc240.c
5141cc406Sopenharmony_ci
6141cc406Sopenharmony_ci   03/12/01 - Peter Fales
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci   Based on the dc210 driver, (C) 1998 Brian J. Murrell (which is
9141cc406Sopenharmony_ci	based on dc25 driver (C) 1998 by Peter Fales)
10141cc406Sopenharmony_ci
11141cc406Sopenharmony_ci   This file (C) 2001 by Peter Fales
12141cc406Sopenharmony_ci
13141cc406Sopenharmony_ci   This file is part of the SANE package.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
16141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
17141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
18141cc406Sopenharmony_ci   License, or (at your option) any later version.
19141cc406Sopenharmony_ci
20141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
21141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
22141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23141cc406Sopenharmony_ci   General Public License for more details.
24141cc406Sopenharmony_ci
25141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
26141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
27141cc406Sopenharmony_ci
28141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
29141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
32141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
33141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
34141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
35141cc406Sopenharmony_ci   account of linking the SANE library code into it.
36141cc406Sopenharmony_ci
37141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
38141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
39141cc406Sopenharmony_ci   License.
40141cc406Sopenharmony_ci
41141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
42141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
43141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
46141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
47141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
48141cc406Sopenharmony_ci
49141cc406Sopenharmony_ci ***************************************************************************
50141cc406Sopenharmony_ci
51141cc406Sopenharmony_ci   This file implements a SANE backend for the Kodak DC-240
52141cc406Sopenharmony_ci   digital camera.  THIS IS EXTREMELY ALPHA CODE!  USE AT YOUR OWN RISK!!
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_ci   (feedback to:  dc240-devel@fales-lorenz.net)
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci   This backend is based somewhat on the dc25 backend included in this
57141cc406Sopenharmony_ci   package by Peter Fales, and the dc210 backend by Brian J. Murrell
58141cc406Sopenharmony_ci
59141cc406Sopenharmony_ci ***************************************************************************/
60141cc406Sopenharmony_ci
61141cc406Sopenharmony_ci#include "../include/sane/config.h"
62141cc406Sopenharmony_ci
63141cc406Sopenharmony_ci#include <stdlib.h>
64141cc406Sopenharmony_ci#include <string.h>
65141cc406Sopenharmony_ci#include <stdio.h>
66141cc406Sopenharmony_ci#include <unistd.h>
67141cc406Sopenharmony_ci#include <fcntl.h>
68141cc406Sopenharmony_ci#include <limits.h>
69141cc406Sopenharmony_ci#include "../include/sane/sanei_jpeg.h"
70141cc406Sopenharmony_ci#include <sys/ioctl.h>
71141cc406Sopenharmony_ci
72141cc406Sopenharmony_ci#include "../include/sane/sane.h"
73141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
74141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
75141cc406Sopenharmony_ci
76141cc406Sopenharmony_ci#define BACKEND_NAME	dc240
77141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
78141cc406Sopenharmony_ci
79141cc406Sopenharmony_ci#include "dc240.h"
80141cc406Sopenharmony_ci
81141cc406Sopenharmony_ci#ifndef PATH_MAX
82141cc406Sopenharmony_ci# define PATH_MAX	1024
83141cc406Sopenharmony_ci#endif
84141cc406Sopenharmony_ci
85141cc406Sopenharmony_ci#define MAGIC			(void *)0xab730324
86141cc406Sopenharmony_ci#define DC240_CONFIG_FILE 	"dc240.conf"
87141cc406Sopenharmony_ci#define THUMBSIZE		20736
88141cc406Sopenharmony_ci
89141cc406Sopenharmony_ci#ifdef B115200
90141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE	B115200
91141cc406Sopenharmony_ci#else
92141cc406Sopenharmony_ci# define DEFAULT_BAUD_RATE	B38400
93141cc406Sopenharmony_ci#endif
94141cc406Sopenharmony_ci
95141cc406Sopenharmony_ci#if defined (__sgi)
96141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/ttyd1"	/* Irix */
97141cc406Sopenharmony_ci#elif defined (__sun)
98141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/term/a"	/* Solaris */
99141cc406Sopenharmony_ci#elif defined (hpux)
100141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/tty1d0"	/* HP-UX */
101141cc406Sopenharmony_ci#elif defined (__osf__)
102141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/tty00"	/* Digital UNIX */
103141cc406Sopenharmony_ci#else
104141cc406Sopenharmony_ci# define DEFAULT_TTY		"/dev/ttyS0"	/* Linux */
105141cc406Sopenharmony_ci#endif
106141cc406Sopenharmony_ci
107141cc406Sopenharmony_cistatic SANE_Bool is_open = 0;
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_thumbnails;
110141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_snap;
111141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_lowres;
112141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_erase;
113141cc406Sopenharmony_cistatic SANE_Bool dc240_opt_autoinc;
114141cc406Sopenharmony_cistatic SANE_Bool dumpinquiry;
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_cistatic struct jpeg_decompress_struct cinfo;
117141cc406Sopenharmony_cistatic djpeg_dest_ptr dest_mgr = NULL;
118141cc406Sopenharmony_ci
119141cc406Sopenharmony_cistatic unsigned long cmdrespause = 250000UL;	/* pause after sending cmd */
120141cc406Sopenharmony_cistatic unsigned long breakpause = 1000000UL;	/* pause after sending break */
121141cc406Sopenharmony_ci
122141cc406Sopenharmony_cistatic DC240 Camera;
123141cc406Sopenharmony_ci
124141cc406Sopenharmony_cistatic SANE_Range image_range = {
125141cc406Sopenharmony_ci  0,
126141cc406Sopenharmony_ci  0,
127141cc406Sopenharmony_ci  0
128141cc406Sopenharmony_ci};
129141cc406Sopenharmony_ci
130141cc406Sopenharmony_cistatic SANE_String **folder_list;
131141cc406Sopenharmony_cistatic SANE_Int current_folder = 0;
132141cc406Sopenharmony_ci
133141cc406Sopenharmony_cistatic SANE_Option_Descriptor sod[] = {
134141cc406Sopenharmony_ci  {
135141cc406Sopenharmony_ci   SANE_NAME_NUM_OPTIONS,
136141cc406Sopenharmony_ci   SANE_TITLE_NUM_OPTIONS,
137141cc406Sopenharmony_ci   SANE_DESC_NUM_OPTIONS,
138141cc406Sopenharmony_ci   SANE_TYPE_INT,
139141cc406Sopenharmony_ci   SANE_UNIT_NONE,
140141cc406Sopenharmony_ci   sizeof (SANE_Word),
141141cc406Sopenharmony_ci   SANE_CAP_SOFT_DETECT,
142141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
143141cc406Sopenharmony_ci   {NULL}
144141cc406Sopenharmony_ci   }
145141cc406Sopenharmony_ci  ,
146141cc406Sopenharmony_ci
147141cc406Sopenharmony_ci#define DC240_OPT_IMAGE_SELECTION 1
148141cc406Sopenharmony_ci  {
149141cc406Sopenharmony_ci   "",
150141cc406Sopenharmony_ci   "Image Selection",
151141cc406Sopenharmony_ci   "Selection of the image to load.",
152141cc406Sopenharmony_ci   SANE_TYPE_GROUP,
153141cc406Sopenharmony_ci   SANE_UNIT_NONE,
154141cc406Sopenharmony_ci   0,
155141cc406Sopenharmony_ci   0,
156141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
157141cc406Sopenharmony_ci   {NULL}
158141cc406Sopenharmony_ci   }
159141cc406Sopenharmony_ci  ,
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_ci#define DC240_OPT_FOLDER 2
162141cc406Sopenharmony_ci  {
163141cc406Sopenharmony_ci   "folder",
164141cc406Sopenharmony_ci   "Folder",
165141cc406Sopenharmony_ci   "Select folder within camera",
166141cc406Sopenharmony_ci   SANE_TYPE_STRING,
167141cc406Sopenharmony_ci   SANE_UNIT_NONE,
168141cc406Sopenharmony_ci   256,
169141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
170141cc406Sopenharmony_ci   SANE_CONSTRAINT_STRING_LIST,
171141cc406Sopenharmony_ci   {NULL}
172141cc406Sopenharmony_ci   }
173141cc406Sopenharmony_ci  ,
174141cc406Sopenharmony_ci
175141cc406Sopenharmony_ci#define DC240_OPT_IMAGE_NUMBER 3
176141cc406Sopenharmony_ci  {
177141cc406Sopenharmony_ci   "image",
178141cc406Sopenharmony_ci   "Image Number",
179141cc406Sopenharmony_ci   "Select Image Number to load from camera",
180141cc406Sopenharmony_ci   SANE_TYPE_INT,
181141cc406Sopenharmony_ci   SANE_UNIT_NONE,
182141cc406Sopenharmony_ci   4,
183141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
184141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
185141cc406Sopenharmony_ci   {(SANE_String_Const *) & image_range}	/* this is ANSI conformant! */
186141cc406Sopenharmony_ci   }
187141cc406Sopenharmony_ci  ,
188141cc406Sopenharmony_ci
189141cc406Sopenharmony_ci#define DC240_OPT_THUMBS 4
190141cc406Sopenharmony_ci  {
191141cc406Sopenharmony_ci   "thumbs",
192141cc406Sopenharmony_ci   "Load Thumbnail",
193141cc406Sopenharmony_ci   "Load the image as thumbnail.",
194141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
195141cc406Sopenharmony_ci   SANE_UNIT_NONE,
196141cc406Sopenharmony_ci   sizeof (SANE_Word),
197141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
198141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
199141cc406Sopenharmony_ci   {NULL}
200141cc406Sopenharmony_ci   }
201141cc406Sopenharmony_ci  ,
202141cc406Sopenharmony_ci#define DC240_OPT_SNAP 5
203141cc406Sopenharmony_ci  {
204141cc406Sopenharmony_ci   "snap",
205141cc406Sopenharmony_ci   "Snap new picture",
206141cc406Sopenharmony_ci   "Take new picture and download it",
207141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
208141cc406Sopenharmony_ci   SANE_UNIT_NONE,
209141cc406Sopenharmony_ci   sizeof (SANE_Word),
210141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ ,
211141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
212141cc406Sopenharmony_ci   {NULL}
213141cc406Sopenharmony_ci   }
214141cc406Sopenharmony_ci  ,
215141cc406Sopenharmony_ci#define DC240_OPT_LOWRES 6
216141cc406Sopenharmony_ci  {
217141cc406Sopenharmony_ci   "lowres",
218141cc406Sopenharmony_ci   "Low Resolution",
219141cc406Sopenharmony_ci   "Resolution of new pictures",
220141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
221141cc406Sopenharmony_ci   SANE_UNIT_NONE,
222141cc406Sopenharmony_ci   sizeof (SANE_Word),
223141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE
224141cc406Sopenharmony_ci   /* | SANE_CAP_ADVANCED */ ,
225141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
226141cc406Sopenharmony_ci   {NULL}
227141cc406Sopenharmony_ci   }
228141cc406Sopenharmony_ci  ,
229141cc406Sopenharmony_ci
230141cc406Sopenharmony_ci#define DC240_OPT_ERASE 7
231141cc406Sopenharmony_ci  {
232141cc406Sopenharmony_ci   "erase",
233141cc406Sopenharmony_ci   "Erase",
234141cc406Sopenharmony_ci   "Erase the picture after downloading",
235141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
236141cc406Sopenharmony_ci   SANE_UNIT_NONE,
237141cc406Sopenharmony_ci   sizeof (SANE_Word),
238141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
239141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
240141cc406Sopenharmony_ci   {NULL}
241141cc406Sopenharmony_ci   }
242141cc406Sopenharmony_ci  ,
243141cc406Sopenharmony_ci
244141cc406Sopenharmony_ci#define DC240_OPT_DEFAULT 8
245141cc406Sopenharmony_ci  {
246141cc406Sopenharmony_ci   "default-enhancements",
247141cc406Sopenharmony_ci   "Defaults",
248141cc406Sopenharmony_ci   "Set default values for enhancement controls.",
249141cc406Sopenharmony_ci   SANE_TYPE_BUTTON,
250141cc406Sopenharmony_ci   SANE_UNIT_NONE,
251141cc406Sopenharmony_ci   0,
252141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
253141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
254141cc406Sopenharmony_ci   {NULL}
255141cc406Sopenharmony_ci   }
256141cc406Sopenharmony_ci  ,
257141cc406Sopenharmony_ci
258141cc406Sopenharmony_ci#define DC240_OPT_INIT_DC240 9
259141cc406Sopenharmony_ci  {
260141cc406Sopenharmony_ci   "camera-init",
261141cc406Sopenharmony_ci   "Re-establish Communications",
262141cc406Sopenharmony_ci   "Re-establish communications with camera (in case of timeout, etc.)",
263141cc406Sopenharmony_ci   SANE_TYPE_BUTTON,
264141cc406Sopenharmony_ci   SANE_UNIT_NONE,
265141cc406Sopenharmony_ci   0,
266141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
267141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
268141cc406Sopenharmony_ci   {NULL}
269141cc406Sopenharmony_ci   }
270141cc406Sopenharmony_ci  ,
271141cc406Sopenharmony_ci
272141cc406Sopenharmony_ci#define DC240_OPT_AUTOINC 10
273141cc406Sopenharmony_ci  {
274141cc406Sopenharmony_ci   "autoinc",
275141cc406Sopenharmony_ci   "Auto Increment",
276141cc406Sopenharmony_ci   "Increment image number after each scan",
277141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
278141cc406Sopenharmony_ci   SANE_UNIT_NONE,
279141cc406Sopenharmony_ci   sizeof (SANE_Word),
280141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED,
281141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
282141cc406Sopenharmony_ci   {NULL}
283141cc406Sopenharmony_ci   }
284141cc406Sopenharmony_ci  ,
285141cc406Sopenharmony_ci
286141cc406Sopenharmony_ci};
287141cc406Sopenharmony_ci
288141cc406Sopenharmony_cistatic SANE_Parameters parms = {
289141cc406Sopenharmony_ci  SANE_FRAME_RGB,
290141cc406Sopenharmony_ci  0,
291141cc406Sopenharmony_ci  0,				/* Number of bytes returned per scan line: */
292141cc406Sopenharmony_ci  0,				/* Number of pixels per scan line.  */
293141cc406Sopenharmony_ci  0,				/* Number of lines for the current scan.  */
294141cc406Sopenharmony_ci  8,				/* Number of bits per sample. */
295141cc406Sopenharmony_ci};
296141cc406Sopenharmony_ci
297141cc406Sopenharmony_ci
298141cc406Sopenharmony_ci
299141cc406Sopenharmony_ci
300141cc406Sopenharmony_cistatic SANE_Byte shoot_pck[] = SHOOT_PCK;
301141cc406Sopenharmony_cistatic SANE_Byte init_pck[] = INIT_PCK;
302141cc406Sopenharmony_cistatic SANE_Byte thumb_pck[] = THUMBS_PCK;
303141cc406Sopenharmony_cistatic SANE_Byte pic_pck[] = PICS_PCK;
304141cc406Sopenharmony_cistatic SANE_Byte pic_info_pck[] = PICS_INFO_PCK;
305141cc406Sopenharmony_cistatic SANE_Byte info_pck[] = INFO_PCK;
306141cc406Sopenharmony_cistatic SANE_Byte erase_pck[] = ERASE_PCK;
307141cc406Sopenharmony_cistatic SANE_Byte res_pck[] = RES_PCK;
308141cc406Sopenharmony_cistatic SANE_Byte open_card_pck[] = OPEN_CARD_PCK;
309141cc406Sopenharmony_cistatic SANE_Byte read_dir_pck[] = READ_DIR_PCK;
310141cc406Sopenharmony_ci
311141cc406Sopenharmony_cistatic struct pkt_speed speeds[] = SPEEDS;
312141cc406Sopenharmony_cistatic struct termios tty_orig;
313141cc406Sopenharmony_ci
314141cc406Sopenharmony_ciSANE_Byte dir_buf2[2 + CAMDIRENTRYSIZE * DIRENTRIES];
315141cc406Sopenharmony_ci
316141cc406Sopenharmony_cistatic struct cam_dirlist *dir_head = NULL;
317141cc406Sopenharmony_ci
318141cc406Sopenharmony_cistatic SANE_Byte info_buf[256];
319141cc406Sopenharmony_cistatic SANE_Byte name_buf[60];
320141cc406Sopenharmony_ci
321141cc406Sopenharmony_ci#include <sys/time.h>
322141cc406Sopenharmony_ci#include <unistd.h>
323141cc406Sopenharmony_ci
324141cc406Sopenharmony_cistatic SANE_Int
325141cc406Sopenharmony_cisend_pck (SANE_Int fd, SANE_Byte * pck)
326141cc406Sopenharmony_ci{
327141cc406Sopenharmony_ci  SANE_Int n;
328141cc406Sopenharmony_ci  SANE_Byte r = 0xf0;		/* prime the loop with a "camera busy" */
329141cc406Sopenharmony_ci
330141cc406Sopenharmony_ci  DBG (127, "send_pck<%x %x %x %x %x %x %x %x>\n",
331141cc406Sopenharmony_ci       pck[0], pck[1], pck[2], pck[3], pck[4], pck[5], pck[6], pck[7]);
332141cc406Sopenharmony_ci
333141cc406Sopenharmony_ci  /* keep trying if camera says it's busy */
334141cc406Sopenharmony_ci  while (r == 0xf0)
335141cc406Sopenharmony_ci    {
336141cc406Sopenharmony_ci      if (write (fd, (char *) pck, 8) != 8)
337141cc406Sopenharmony_ci	{
338141cc406Sopenharmony_ci	  DBG (1, "send_pck: error: write returned -1\n");
339141cc406Sopenharmony_ci	  return -1;
340141cc406Sopenharmony_ci	}
341141cc406Sopenharmony_ci      /* need to wait before we read command result */
342141cc406Sopenharmony_ci      usleep (cmdrespause);
343141cc406Sopenharmony_ci
344141cc406Sopenharmony_ci      if ((n = read (fd, (char *) &r, 1)) != 1)
345141cc406Sopenharmony_ci	{
346141cc406Sopenharmony_ci	  DBG (1, "send_pck: error: read returned -1\n");
347141cc406Sopenharmony_ci	  return -1;
348141cc406Sopenharmony_ci	}
349141cc406Sopenharmony_ci    }
350141cc406Sopenharmony_ci  DBG (127, "send_pck: read one byte result from camera =  %x\n", r);
351141cc406Sopenharmony_ci  return (r == 0xd1) ? 0 : -1;
352141cc406Sopenharmony_ci}
353141cc406Sopenharmony_ci
354141cc406Sopenharmony_cistatic SANE_Int
355141cc406Sopenharmony_ciinit_dc240 (DC240 * camera)
356141cc406Sopenharmony_ci{
357141cc406Sopenharmony_ci  struct termios tty_new;
358141cc406Sopenharmony_ci  SANE_Int speed_index;
359141cc406Sopenharmony_ci  SANE_Char buf[5], n;
360141cc406Sopenharmony_ci
361141cc406Sopenharmony_ci  DBG (1, "DC-240 Backend 05/16/01\n");
362141cc406Sopenharmony_ci
363141cc406Sopenharmony_ci  for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++)
364141cc406Sopenharmony_ci    {
365141cc406Sopenharmony_ci      if (speeds[speed_index].baud == camera->baud)
366141cc406Sopenharmony_ci	{
367141cc406Sopenharmony_ci	  init_pck[2] = speeds[speed_index].pkt_code[0];
368141cc406Sopenharmony_ci	  init_pck[3] = speeds[speed_index].pkt_code[1];
369141cc406Sopenharmony_ci	  break;
370141cc406Sopenharmony_ci	}
371141cc406Sopenharmony_ci    }
372141cc406Sopenharmony_ci
373141cc406Sopenharmony_ci  if (init_pck[2] == 0)
374141cc406Sopenharmony_ci    {
375141cc406Sopenharmony_ci      DBG (1, "unsupported baud rate.\n");
376141cc406Sopenharmony_ci      return -1;
377141cc406Sopenharmony_ci    }
378141cc406Sopenharmony_ci
379141cc406Sopenharmony_ci  /*
380141cc406Sopenharmony_ci     Open device file.
381141cc406Sopenharmony_ci   */
382141cc406Sopenharmony_ci  if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1)
383141cc406Sopenharmony_ci    {
384141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: could not open %s for read/write\n",
385141cc406Sopenharmony_ci	   camera->tty_name);
386141cc406Sopenharmony_ci      return -1;
387141cc406Sopenharmony_ci    }
388141cc406Sopenharmony_ci  /*
389141cc406Sopenharmony_ci     Save old device information to restore when we are done.
390141cc406Sopenharmony_ci   */
391141cc406Sopenharmony_ci  if (tcgetattr (camera->fd, &tty_orig) == -1)
392141cc406Sopenharmony_ci    {
393141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: could not get attributes\n");
394141cc406Sopenharmony_ci      return -1;
395141cc406Sopenharmony_ci    }
396141cc406Sopenharmony_ci
397141cc406Sopenharmony_ci  memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios));
398141cc406Sopenharmony_ci  /*
399141cc406Sopenharmony_ci     We need the device to be raw. 8 bits even parity on 9600 baud to start.
400141cc406Sopenharmony_ci   */
401141cc406Sopenharmony_ci#ifdef HAVE_CFMAKERAW
402141cc406Sopenharmony_ci  cfmakeraw (&tty_new);
403141cc406Sopenharmony_ci#else
404141cc406Sopenharmony_ci  /* Modified to set the port REALLY as required (9600, 8b, 1sb, NO parity).
405141cc406Sopenharmony_ci     Code inspired by the gPhoto2 serial port setup */
406141cc406Sopenharmony_ci
407141cc406Sopenharmony_ci  /* input control settings */
408141cc406Sopenharmony_ci  tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC |
409141cc406Sopenharmony_ci                      IXANY | IXON | IXOFF | INPCK | ISTRIP);
410141cc406Sopenharmony_ci  tty_new.c_iflag |= (BRKINT | IGNPAR);
411141cc406Sopenharmony_ci  /* output control settings */
412141cc406Sopenharmony_ci  tty_new.c_oflag &= ~OPOST;
413141cc406Sopenharmony_ci  /* hardware control settings */
414141cc406Sopenharmony_ci  tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8;
415141cc406Sopenharmony_ci  tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB);
416141cc406Sopenharmony_ci# if defined(__sgi)
417141cc406Sopenharmony_ci  tty_new.c_cflag &= ~CNEW_RTSCTS;
418141cc406Sopenharmony_ci# else
419141cc406Sopenharmony_ci/* OS/2 doesn't have CRTSCTS - will this work for them? */
420141cc406Sopenharmony_ci#  ifdef CRTSCTS
421141cc406Sopenharmony_ci  tty_new.c_cflag &= ~CRTSCTS;
422141cc406Sopenharmony_ci#  endif
423141cc406Sopenharmony_ci# endif
424141cc406Sopenharmony_ci  tty_new.c_cflag |= CLOCAL | CREAD;
425141cc406Sopenharmony_ci#endif
426141cc406Sopenharmony_ci  /* line discipline settings */
427141cc406Sopenharmony_ci  tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE |
428141cc406Sopenharmony_ci                       ECHOK | IEXTEN);
429141cc406Sopenharmony_ci  tty_new.c_cc[VMIN] = 0;
430141cc406Sopenharmony_ci  tty_new.c_cc[VTIME] = 5;
431141cc406Sopenharmony_ci  cfsetospeed (&tty_new, B9600);
432141cc406Sopenharmony_ci  cfsetispeed (&tty_new, B9600);
433141cc406Sopenharmony_ci
434141cc406Sopenharmony_ci  if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
435141cc406Sopenharmony_ci    {
436141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: could not set attributes\n");
437141cc406Sopenharmony_ci      return -1;
438141cc406Sopenharmony_ci    }
439141cc406Sopenharmony_ci
440141cc406Sopenharmony_ci  /* send a break to get it back to a known state */
441141cc406Sopenharmony_ci  /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK,
442141cc406Sopenharmony_ci   * and TCSBRKP, but that is system dependent.  e.g. on irix a non-zero
443141cc406Sopenharmony_ci   * value does a drain instead of a break.  A zero value is universally
444141cc406Sopenharmony_ci   * used to send a break.
445141cc406Sopenharmony_ci   */
446141cc406Sopenharmony_ci
447141cc406Sopenharmony_ci#ifdef HAVE_TCSENDBREAK
448141cc406Sopenharmony_ci  tcsendbreak (camera->fd, 0);
449141cc406Sopenharmony_ci# if defined(__sgi)
450141cc406Sopenharmony_ci  tcdrain (camera->fd);
451141cc406Sopenharmony_ci# endif
452141cc406Sopenharmony_ci# elif defined(TCSBRKP)
453141cc406Sopenharmony_ci  ioctl (camera->fd, TCSBRKP, 0);
454141cc406Sopenharmony_ci# elif defined(TCSBRK)
455141cc406Sopenharmony_ci  ioctl (camera->fd, TCSBRK, 0);
456141cc406Sopenharmony_ci#endif
457141cc406Sopenharmony_ci
458141cc406Sopenharmony_ci  /* and wait for it to recover from the break */
459141cc406Sopenharmony_ci
460141cc406Sopenharmony_ci#ifdef HAVE_USLEEP
461141cc406Sopenharmony_ci  usleep (breakpause);
462141cc406Sopenharmony_ci#else
463141cc406Sopenharmony_ci  sleep (1);
464141cc406Sopenharmony_ci#endif
465141cc406Sopenharmony_ci
466141cc406Sopenharmony_ci  /* We seem to get some garbage following the break, so
467141cc406Sopenharmony_ci   * read anything pending */
468141cc406Sopenharmony_ci
469141cc406Sopenharmony_ci  n = read (camera->fd, buf, 5);
470141cc406Sopenharmony_ci
471141cc406Sopenharmony_ci  DBG (127, "init_dc240 flushed %d bytes: %x %x %x %x %x\n", n, buf[0],
472141cc406Sopenharmony_ci       buf[1], buf[2], buf[3], buf[4]);
473141cc406Sopenharmony_ci
474141cc406Sopenharmony_ci  if (send_pck (camera->fd, init_pck) == -1)
475141cc406Sopenharmony_ci    {
476141cc406Sopenharmony_ci      /*
477141cc406Sopenharmony_ci       *    The camera always powers up at 9600, so we try
478141cc406Sopenharmony_ci       *      that first.  However, it may be already set to
479141cc406Sopenharmony_ci       *      a different speed.  Try the entries in the table:
480141cc406Sopenharmony_ci       */
481141cc406Sopenharmony_ci
482141cc406Sopenharmony_ci      tcsetattr (camera->fd, TCSANOW, &tty_orig);
483141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: no response from camera\n");
484141cc406Sopenharmony_ci      return -1;
485141cc406Sopenharmony_ci    }
486141cc406Sopenharmony_ci
487141cc406Sopenharmony_ci  n = read (camera->fd, buf, 5);
488141cc406Sopenharmony_ci  DBG (127, "init_dc240 flushed %d bytes: %x %x %x %x %x\n", n, buf[0],
489141cc406Sopenharmony_ci       buf[1], buf[2], buf[3], buf[4]);
490141cc406Sopenharmony_ci
491141cc406Sopenharmony_ci  /*
492141cc406Sopenharmony_ci     Set speed to requested speed.
493141cc406Sopenharmony_ci   */
494141cc406Sopenharmony_ci  cfsetospeed (&tty_new, Camera.baud);
495141cc406Sopenharmony_ci  cfsetispeed (&tty_new, Camera.baud);
496141cc406Sopenharmony_ci
497141cc406Sopenharmony_ci  if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
498141cc406Sopenharmony_ci    {
499141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: could not set attributes\n");
500141cc406Sopenharmony_ci      return -1;
501141cc406Sopenharmony_ci    }
502141cc406Sopenharmony_ci
503141cc406Sopenharmony_ci
504141cc406Sopenharmony_ci  if (send_pck (camera->fd, open_card_pck) == -1)
505141cc406Sopenharmony_ci    {
506141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: send_pck returned -1\n");
507141cc406Sopenharmony_ci      return -1;
508141cc406Sopenharmony_ci    }
509141cc406Sopenharmony_ci
510141cc406Sopenharmony_ci  if (end_of_data (camera->fd) == -1)
511141cc406Sopenharmony_ci    {
512141cc406Sopenharmony_ci      DBG (1, "init_dc240: error: end_of_data returned -1\n");
513141cc406Sopenharmony_ci      return -1;
514141cc406Sopenharmony_ci    }
515141cc406Sopenharmony_ci
516141cc406Sopenharmony_ci  return camera->fd;
517141cc406Sopenharmony_ci
518141cc406Sopenharmony_ci}
519141cc406Sopenharmony_ci
520141cc406Sopenharmony_cistatic void
521141cc406Sopenharmony_ciclose_dc240 (SANE_Int fd)
522141cc406Sopenharmony_ci{
523141cc406Sopenharmony_ci  /*
524141cc406Sopenharmony_ci   *    Put the camera back to 9600 baud
525141cc406Sopenharmony_ci   */
526141cc406Sopenharmony_ci
527141cc406Sopenharmony_ci  if (close (fd) == -1)
528141cc406Sopenharmony_ci    {
529141cc406Sopenharmony_ci      DBG (1, "close_dc240: error: could not close device\n");
530141cc406Sopenharmony_ci    }
531141cc406Sopenharmony_ci}
532141cc406Sopenharmony_ci
533141cc406Sopenharmony_ciint
534141cc406Sopenharmony_ciget_info (DC240 * camera)
535141cc406Sopenharmony_ci{
536141cc406Sopenharmony_ci
537141cc406Sopenharmony_ci  SANE_Char f[] = "get_info";
538141cc406Sopenharmony_ci  SANE_Byte buf[256];
539141cc406Sopenharmony_ci  SANE_Int n;
540141cc406Sopenharmony_ci  struct cam_dirlist *e;
541141cc406Sopenharmony_ci
542141cc406Sopenharmony_ci  if (send_pck (camera->fd, info_pck) == -1)
543141cc406Sopenharmony_ci    {
544141cc406Sopenharmony_ci      DBG (1, "%s: error: send_pck returned -1\n", f);
545141cc406Sopenharmony_ci      return -1;
546141cc406Sopenharmony_ci    }
547141cc406Sopenharmony_ci
548141cc406Sopenharmony_ci  DBG (9, "%s: read info packet\n", f);
549141cc406Sopenharmony_ci
550141cc406Sopenharmony_ci  if (read_data (camera->fd, buf, 256) == -1)
551141cc406Sopenharmony_ci    {
552141cc406Sopenharmony_ci      DBG (1, "%s: error: read_data returned -1\n", f);
553141cc406Sopenharmony_ci      return -1;
554141cc406Sopenharmony_ci    }
555141cc406Sopenharmony_ci
556141cc406Sopenharmony_ci  if (end_of_data (camera->fd) == -1)
557141cc406Sopenharmony_ci    {
558141cc406Sopenharmony_ci      DBG (1, "%s: error: end_of_data returned -1\n", f);
559141cc406Sopenharmony_ci      return -1;
560141cc406Sopenharmony_ci    }
561141cc406Sopenharmony_ci
562141cc406Sopenharmony_ci  camera->model = buf[1];
563141cc406Sopenharmony_ci
564141cc406Sopenharmony_ci  if (camera->model != 0x5)
565141cc406Sopenharmony_ci    {
566141cc406Sopenharmony_ci      DBG (0,
567141cc406Sopenharmony_ci	   "Camera model (%d) is not DC-240 (5).  "
568141cc406Sopenharmony_ci	   "Only the DC-240 is supported by this driver.\n", camera->model);
569141cc406Sopenharmony_ci    }
570141cc406Sopenharmony_ci
571141cc406Sopenharmony_ci  camera->ver_major = buf[2];
572141cc406Sopenharmony_ci  camera->ver_minor = buf[3];
573141cc406Sopenharmony_ci  camera->pic_taken = buf[14] << 8 | buf[15];
574141cc406Sopenharmony_ci  DBG (4, "pic_taken=%d\n", camera->pic_taken);
575141cc406Sopenharmony_ci  camera->pic_left = buf[64] << 8 | buf[65];
576141cc406Sopenharmony_ci  DBG (4, "pictures left (at current res)=%d\n", camera->pic_left);
577141cc406Sopenharmony_ci  camera->flags.low_batt = buf[8];
578141cc406Sopenharmony_ci  DBG (4, "battery=%d (0=OK, 1=weak, 2=empty)\n", camera->flags.low_batt);
579141cc406Sopenharmony_ci  DBG (4, "AC adapter status=%d\n", buf[9]);
580141cc406Sopenharmony_ci  dc240_opt_lowres = !buf[79];
581141cc406Sopenharmony_ci
582141cc406Sopenharmony_ci  if (Camera.pic_taken == 0)
583141cc406Sopenharmony_ci    {
584141cc406Sopenharmony_ci      sod[DC240_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
585141cc406Sopenharmony_ci      image_range.min = 0;
586141cc406Sopenharmony_ci      image_range.max = 0;
587141cc406Sopenharmony_ci    }
588141cc406Sopenharmony_ci  else
589141cc406Sopenharmony_ci    {
590141cc406Sopenharmony_ci      sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
591141cc406Sopenharmony_ci      image_range.min = 1;
592141cc406Sopenharmony_ci      image_range.max = Camera.pic_taken;
593141cc406Sopenharmony_ci    }
594141cc406Sopenharmony_ci
595141cc406Sopenharmony_ci  n = read_dir ("\\PCCARD\\DCIM\\*.*");
596141cc406Sopenharmony_ci
597141cc406Sopenharmony_ci  /* If we've already got a folder_list, free it up before starting
598141cc406Sopenharmony_ci   * the new one
599141cc406Sopenharmony_ci   */
600141cc406Sopenharmony_ci  if (folder_list != NULL)
601141cc406Sopenharmony_ci    {
602141cc406Sopenharmony_ci      int tmp;
603141cc406Sopenharmony_ci      for (tmp = 0; folder_list[tmp]; tmp++)
604141cc406Sopenharmony_ci	{
605141cc406Sopenharmony_ci	  free (folder_list[tmp]);
606141cc406Sopenharmony_ci	}
607141cc406Sopenharmony_ci      free (folder_list);
608141cc406Sopenharmony_ci    }
609141cc406Sopenharmony_ci
610141cc406Sopenharmony_ci  folder_list = (SANE_String * *)malloc ((n + 1) * sizeof (SANE_String *));
611141cc406Sopenharmony_ci  for (e = dir_head, n = 0; e; e = e->next, n++)
612141cc406Sopenharmony_ci    {
613141cc406Sopenharmony_ci      folder_list[n] = (SANE_String *) strdup (e->name);
614141cc406Sopenharmony_ci      if (strchr ((char *) folder_list[n], ' '))
615141cc406Sopenharmony_ci	{
616141cc406Sopenharmony_ci	  *strchr ((char *) folder_list[n], ' ') = '\0';
617141cc406Sopenharmony_ci	}
618141cc406Sopenharmony_ci    }
619141cc406Sopenharmony_ci  folder_list[n] = NULL;
620141cc406Sopenharmony_ci  sod[DC240_OPT_FOLDER].constraint.string_list =
621141cc406Sopenharmony_ci    (SANE_String_Const *) folder_list;
622141cc406Sopenharmony_ci
623141cc406Sopenharmony_ci  return 0;
624141cc406Sopenharmony_ci
625141cc406Sopenharmony_ci}
626141cc406Sopenharmony_ci
627141cc406Sopenharmony_ci/* NEW */
628141cc406Sopenharmony_cistatic SANE_Int
629141cc406Sopenharmony_ciread_data (SANE_Int fd, SANE_Byte * buf, SANE_Int sz)
630141cc406Sopenharmony_ci{
631141cc406Sopenharmony_ci  SANE_Byte ccsum;
632141cc406Sopenharmony_ci  SANE_Byte rcsum;
633141cc406Sopenharmony_ci  SANE_Byte c;
634141cc406Sopenharmony_ci  SANE_Int retries = 0;
635141cc406Sopenharmony_ci  SANE_Int n;
636141cc406Sopenharmony_ci  SANE_Int r = 0;
637141cc406Sopenharmony_ci  SANE_Int i;
638141cc406Sopenharmony_ci
639141cc406Sopenharmony_ci  while (retries++ < 5)
640141cc406Sopenharmony_ci    {
641141cc406Sopenharmony_ci
642141cc406Sopenharmony_ci      /*
643141cc406Sopenharmony_ci       * If this is not the first time through, then it must be
644141cc406Sopenharmony_ci       * a retry - signal the camera that we didn't like what
645141cc406Sopenharmony_ci       * we got.  In either case, start filling the packet
646141cc406Sopenharmony_ci       */
647141cc406Sopenharmony_ci      if (retries != 1)
648141cc406Sopenharmony_ci	{
649141cc406Sopenharmony_ci
650141cc406Sopenharmony_ci	  DBG (2, "Attempt retry %d\n", retries);
651141cc406Sopenharmony_ci	  c = 0xe3;
652141cc406Sopenharmony_ci	  if (write (fd, (char *) &c, 1) != 1)
653141cc406Sopenharmony_ci	    {
654141cc406Sopenharmony_ci	      DBG (1, "read_data: error: write ack\n");
655141cc406Sopenharmony_ci	      return -1;
656141cc406Sopenharmony_ci	    }
657141cc406Sopenharmony_ci
658141cc406Sopenharmony_ci	}
659141cc406Sopenharmony_ci
660141cc406Sopenharmony_ci      /* read the control byte */
661141cc406Sopenharmony_ci      if (read (fd, &c, 1) != 1)
662141cc406Sopenharmony_ci	{
663141cc406Sopenharmony_ci	  DBG (3,
664141cc406Sopenharmony_ci	       "read_data: error: "
665141cc406Sopenharmony_ci	       "read for packet control byte returned bad stat!us\n");
666141cc406Sopenharmony_ci	  return -1;
667141cc406Sopenharmony_ci	}
668141cc406Sopenharmony_ci      if (c != 1 && c != 0)
669141cc406Sopenharmony_ci	{
670141cc406Sopenharmony_ci	  DBG (1, "read_data: error: incorrect packet control byte: %02x\n",
671141cc406Sopenharmony_ci	       c);
672141cc406Sopenharmony_ci	  return -1;
673141cc406Sopenharmony_ci	}
674141cc406Sopenharmony_ci
675141cc406Sopenharmony_ci      for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0;
676141cc406Sopenharmony_ci	   n += r);
677141cc406Sopenharmony_ci
678141cc406Sopenharmony_ci      if (r <= 0)
679141cc406Sopenharmony_ci	{
680141cc406Sopenharmony_ci	  DBG (2, "read_data: warning: read returned -1\n");
681141cc406Sopenharmony_ci	  continue;
682141cc406Sopenharmony_ci	}
683141cc406Sopenharmony_ci
684141cc406Sopenharmony_ci      if (n < sz || read (fd, &rcsum, 1) != 1)
685141cc406Sopenharmony_ci	{
686141cc406Sopenharmony_ci	  DBG (2, "read_data: warning: buffer underrun or no checksum\n");
687141cc406Sopenharmony_ci	  continue;
688141cc406Sopenharmony_ci	}
689141cc406Sopenharmony_ci
690141cc406Sopenharmony_ci      for (i = 0, ccsum = 0; i < n; i++)
691141cc406Sopenharmony_ci	ccsum ^= buf[i];
692141cc406Sopenharmony_ci
693141cc406Sopenharmony_ci      if (ccsum != rcsum)
694141cc406Sopenharmony_ci	{
695141cc406Sopenharmony_ci	  DBG (2,
696141cc406Sopenharmony_ci	       "read_data: warning: "
697141cc406Sopenharmony_ci	       "bad checksum (got %02x != expected %02x)\n", rcsum, ccsum);
698141cc406Sopenharmony_ci	  continue;
699141cc406Sopenharmony_ci	}
700141cc406Sopenharmony_ci
701141cc406Sopenharmony_ci      /* If we got this far, then the packet is OK */
702141cc406Sopenharmony_ci      break;
703141cc406Sopenharmony_ci
704141cc406Sopenharmony_ci
705141cc406Sopenharmony_ci    }
706141cc406Sopenharmony_ci
707141cc406Sopenharmony_ci  c = 0xd2;
708141cc406Sopenharmony_ci
709141cc406Sopenharmony_ci  if (write (fd, (char *) &c, 1) != 1)
710141cc406Sopenharmony_ci    {
711141cc406Sopenharmony_ci      DBG (1, "read_data: error: write ack\n");
712141cc406Sopenharmony_ci      return -1;
713141cc406Sopenharmony_ci    }
714141cc406Sopenharmony_ci
715141cc406Sopenharmony_ci  return 0;
716141cc406Sopenharmony_ci}
717141cc406Sopenharmony_ci
718141cc406Sopenharmony_cistatic SANE_Int
719141cc406Sopenharmony_ciend_of_data (SANE_Int fd)
720141cc406Sopenharmony_ci{
721141cc406Sopenharmony_ci  SANE_Int n;
722141cc406Sopenharmony_ci  SANE_Byte c;
723141cc406Sopenharmony_ci
724141cc406Sopenharmony_ci  do
725141cc406Sopenharmony_ci    {				/* loop until the camera isn't busy */
726141cc406Sopenharmony_ci      if ((n = read (fd, &c, 1)) == -1)
727141cc406Sopenharmony_ci	{
728141cc406Sopenharmony_ci	  DBG (1, "end_of_data: error: read returned -1\n");
729141cc406Sopenharmony_ci	  return -1;
730141cc406Sopenharmony_ci	}
731141cc406Sopenharmony_ci      if (n == 1 && c == 0)	/* got successful end of data */
732141cc406Sopenharmony_ci	return 0;		/* return success */
733141cc406Sopenharmony_ci      if (n == 1)
734141cc406Sopenharmony_ci	{
735141cc406Sopenharmony_ci	  DBG (127, "end_of_data: got %x while waiting\n", c);
736141cc406Sopenharmony_ci	}
737141cc406Sopenharmony_ci      else
738141cc406Sopenharmony_ci	{
739141cc406Sopenharmony_ci	  DBG (127, "end_of_data: waiting...\n");
740141cc406Sopenharmony_ci	}
741141cc406Sopenharmony_ci      sleep (1);		/* not too fast */
742141cc406Sopenharmony_ci    }
743141cc406Sopenharmony_ci/* It's not documented, but we see a d1 after snapping a picture */
744141cc406Sopenharmony_ci  while (c == 0xf0 || c == 0xd1);
745141cc406Sopenharmony_ci
746141cc406Sopenharmony_ci  /* Accck!  Not busy, but not a good end of data either */
747141cc406Sopenharmony_ci  if (c != 0)
748141cc406Sopenharmony_ci    {
749141cc406Sopenharmony_ci      DBG (1, "end_of_data: error: bad EOD from camera (%02x)\n",
750141cc406Sopenharmony_ci	   (unsigned) c);
751141cc406Sopenharmony_ci      return -1;
752141cc406Sopenharmony_ci    }
753141cc406Sopenharmony_ci  return 0;			/* should never get here but shut gcc -Wall up */
754141cc406Sopenharmony_ci}
755141cc406Sopenharmony_ci
756141cc406Sopenharmony_cistatic SANE_Int
757141cc406Sopenharmony_cierase (SANE_Int fd)
758141cc406Sopenharmony_ci{
759141cc406Sopenharmony_ci  if (send_pck (fd, erase_pck) == -1)
760141cc406Sopenharmony_ci    {
761141cc406Sopenharmony_ci      DBG (1, "erase: error: send_pck returned -1\n");
762141cc406Sopenharmony_ci      return -1;
763141cc406Sopenharmony_ci    }
764141cc406Sopenharmony_ci
765141cc406Sopenharmony_ci  if (send_data (name_buf) == -1)
766141cc406Sopenharmony_ci    {
767141cc406Sopenharmony_ci      DBG (1, "erase: error: send_data returned -1\n");
768141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
769141cc406Sopenharmony_ci    }
770141cc406Sopenharmony_ci
771141cc406Sopenharmony_ci  if (end_of_data (fd) == -1)
772141cc406Sopenharmony_ci    {
773141cc406Sopenharmony_ci      DBG (1, "erase: error: end_of_data returned -1\n");
774141cc406Sopenharmony_ci      return -1;
775141cc406Sopenharmony_ci    }
776141cc406Sopenharmony_ci
777141cc406Sopenharmony_ci  return 0;
778141cc406Sopenharmony_ci}
779141cc406Sopenharmony_ci
780141cc406Sopenharmony_cistatic SANE_Int
781141cc406Sopenharmony_cichange_res (SANE_Int fd, SANE_Byte res)
782141cc406Sopenharmony_ci{
783141cc406Sopenharmony_ci  SANE_Char f[] = "change_res";
784141cc406Sopenharmony_ci
785141cc406Sopenharmony_ci  DBG (127, "%s called, low_res=%d\n", f, res);
786141cc406Sopenharmony_ci
787141cc406Sopenharmony_ci  if (res != 0 && res != 1)
788141cc406Sopenharmony_ci    {
789141cc406Sopenharmony_ci      DBG (1, "%s: error: unsupported resolution\n", f);
790141cc406Sopenharmony_ci      return -1;
791141cc406Sopenharmony_ci    }
792141cc406Sopenharmony_ci
793141cc406Sopenharmony_ci  /* cameras resolution semantics are opposite of ours */
794141cc406Sopenharmony_ci  res = !res;
795141cc406Sopenharmony_ci  DBG (127, "%s: setting res to %d\n", f, res);
796141cc406Sopenharmony_ci  res_pck[2] = res;
797141cc406Sopenharmony_ci
798141cc406Sopenharmony_ci  if (send_pck (fd, res_pck) == -1)
799141cc406Sopenharmony_ci    {
800141cc406Sopenharmony_ci      DBG (1, "%s: error: send_pck returned -1\n", f);
801141cc406Sopenharmony_ci    }
802141cc406Sopenharmony_ci
803141cc406Sopenharmony_ci  if (end_of_data (fd) == -1)
804141cc406Sopenharmony_ci    {
805141cc406Sopenharmony_ci      DBG (1, "%s: error: end_of_data returned -1\n", f);
806141cc406Sopenharmony_ci    }
807141cc406Sopenharmony_ci  return 0;
808141cc406Sopenharmony_ci}
809141cc406Sopenharmony_ci
810141cc406Sopenharmony_ciSANE_Status
811141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize)
812141cc406Sopenharmony_ci{
813141cc406Sopenharmony_ci
814141cc406Sopenharmony_ci  SANE_Char f[] = "sane_init";
815141cc406Sopenharmony_ci  SANE_Char dev_name[PATH_MAX], *p;
816141cc406Sopenharmony_ci  size_t len;
817141cc406Sopenharmony_ci  FILE *fp;
818141cc406Sopenharmony_ci  SANE_Int baud;
819141cc406Sopenharmony_ci
820141cc406Sopenharmony_ci  DBG_INIT ();
821141cc406Sopenharmony_ci
822141cc406Sopenharmony_ci  if (version_code)
823141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
824141cc406Sopenharmony_ci
825141cc406Sopenharmony_ci  fp = sanei_config_open (DC240_CONFIG_FILE);
826141cc406Sopenharmony_ci
827141cc406Sopenharmony_ci  /* defaults */
828141cc406Sopenharmony_ci  Camera.baud = DEFAULT_BAUD_RATE;
829141cc406Sopenharmony_ci  Camera.tty_name = DEFAULT_TTY;
830141cc406Sopenharmony_ci
831141cc406Sopenharmony_ci  if (!fp)
832141cc406Sopenharmony_ci    {
833141cc406Sopenharmony_ci      /* default to /dev/whatever instead of insisting on config file */
834141cc406Sopenharmony_ci      DBG (1, "%s:  missing config file '%s'\n", f, DC240_CONFIG_FILE);
835141cc406Sopenharmony_ci    }
836141cc406Sopenharmony_ci  else
837141cc406Sopenharmony_ci    {
838141cc406Sopenharmony_ci      while (sanei_config_read (dev_name, sizeof (dev_name), fp))
839141cc406Sopenharmony_ci	{
840141cc406Sopenharmony_ci	  dev_name[sizeof (dev_name) - 1] = '\0';
841141cc406Sopenharmony_ci	  DBG (20, "%s:  config- %s\n", f, dev_name);
842141cc406Sopenharmony_ci
843141cc406Sopenharmony_ci	  if (dev_name[0] == '#')
844141cc406Sopenharmony_ci	    continue;		/* ignore line comments */
845141cc406Sopenharmony_ci	  len = strlen (dev_name);
846141cc406Sopenharmony_ci	  if (!len)
847141cc406Sopenharmony_ci	    continue;		/* ignore empty lines */
848141cc406Sopenharmony_ci	  if (strncmp (dev_name, "port=", 5) == 0)
849141cc406Sopenharmony_ci	    {
850141cc406Sopenharmony_ci	      p = strchr (dev_name, '/');
851141cc406Sopenharmony_ci	      if (p)
852141cc406Sopenharmony_ci		Camera.tty_name = strdup (p);
853141cc406Sopenharmony_ci	      DBG (20, "Config file port=%s\n", Camera.tty_name);
854141cc406Sopenharmony_ci	    }
855141cc406Sopenharmony_ci	  else if (strncmp (dev_name, "baud=", 5) == 0)
856141cc406Sopenharmony_ci	    {
857141cc406Sopenharmony_ci	      baud = atoi (&dev_name[5]);
858141cc406Sopenharmony_ci	      switch (baud)
859141cc406Sopenharmony_ci		{
860141cc406Sopenharmony_ci		case 9600:
861141cc406Sopenharmony_ci		  Camera.baud = B9600;
862141cc406Sopenharmony_ci		  break;
863141cc406Sopenharmony_ci		case 19200:
864141cc406Sopenharmony_ci		  Camera.baud = B19200;
865141cc406Sopenharmony_ci		  break;
866141cc406Sopenharmony_ci		case 38400:
867141cc406Sopenharmony_ci		  Camera.baud = B38400;
868141cc406Sopenharmony_ci		  break;
869141cc406Sopenharmony_ci#ifdef B57600
870141cc406Sopenharmony_ci		case 57600:
871141cc406Sopenharmony_ci		  Camera.baud = B57600;
872141cc406Sopenharmony_ci		  break;
873141cc406Sopenharmony_ci#endif
874141cc406Sopenharmony_ci#ifdef B115200
875141cc406Sopenharmony_ci		case 115200:
876141cc406Sopenharmony_ci		  Camera.baud = B115200;
877141cc406Sopenharmony_ci		  break;
878141cc406Sopenharmony_ci#endif
879141cc406Sopenharmony_ci		}
880141cc406Sopenharmony_ci	      DBG (20, "Config file baud=%d\n", Camera.baud);
881141cc406Sopenharmony_ci	    }
882141cc406Sopenharmony_ci	  else if (strcmp (dev_name, "dumpinquiry") == 0)
883141cc406Sopenharmony_ci	    {
884141cc406Sopenharmony_ci	      dumpinquiry = SANE_TRUE;
885141cc406Sopenharmony_ci	    }
886141cc406Sopenharmony_ci	  else if (strncmp (dev_name, "cmdrespause=", 12) == 0)
887141cc406Sopenharmony_ci	    {
888141cc406Sopenharmony_ci	      cmdrespause = atoi (&dev_name[12]);
889141cc406Sopenharmony_ci	      DBG (20, "Config file cmdrespause=%lu\n", cmdrespause);
890141cc406Sopenharmony_ci	    }
891141cc406Sopenharmony_ci	  else if (strncmp (dev_name, "breakpause=", 11) == 0)
892141cc406Sopenharmony_ci	    {
893141cc406Sopenharmony_ci	      breakpause = atoi (&dev_name[11]);
894141cc406Sopenharmony_ci	      DBG (20, "Config file breakpause=%lu\n", breakpause);
895141cc406Sopenharmony_ci	    }
896141cc406Sopenharmony_ci	}
897141cc406Sopenharmony_ci      fclose (fp);
898141cc406Sopenharmony_ci    }
899141cc406Sopenharmony_ci
900141cc406Sopenharmony_ci  if (init_dc240 (&Camera) == -1)
901141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
902141cc406Sopenharmony_ci
903141cc406Sopenharmony_ci  if (get_info (&Camera) == -1)
904141cc406Sopenharmony_ci    {
905141cc406Sopenharmony_ci      DBG (1, "error: could not get info\n");
906141cc406Sopenharmony_ci      close_dc240 (Camera.fd);
907141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
908141cc406Sopenharmony_ci    }
909141cc406Sopenharmony_ci
910141cc406Sopenharmony_ci  /* load the current images array */
911141cc406Sopenharmony_ci  get_pictures_info ();
912141cc406Sopenharmony_ci
913141cc406Sopenharmony_ci  if (Camera.pic_taken == 0)
914141cc406Sopenharmony_ci    {
915141cc406Sopenharmony_ci      Camera.current_picture_number = 0;
916141cc406Sopenharmony_ci      parms.bytes_per_line = 0;
917141cc406Sopenharmony_ci      parms.pixels_per_line = 0;
918141cc406Sopenharmony_ci      parms.lines = 0;
919141cc406Sopenharmony_ci    }
920141cc406Sopenharmony_ci  else
921141cc406Sopenharmony_ci    {
922141cc406Sopenharmony_ci      Camera.current_picture_number = 1;
923141cc406Sopenharmony_ci      set_res (Camera.Pictures[Camera.current_picture_number - 1].low_res);
924141cc406Sopenharmony_ci    }
925141cc406Sopenharmony_ci
926141cc406Sopenharmony_ci  if (dumpinquiry)
927141cc406Sopenharmony_ci    {
928141cc406Sopenharmony_ci      DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n");
929141cc406Sopenharmony_ci      DBG (0, "Model...........: DC%s\n", "240");
930141cc406Sopenharmony_ci      DBG (0, "Firmware version: %d.%d\n", Camera.ver_major,
931141cc406Sopenharmony_ci	   Camera.ver_minor);
932141cc406Sopenharmony_ci      DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken,
933141cc406Sopenharmony_ci	   Camera.pic_taken + Camera.pic_left);
934141cc406Sopenharmony_ci      DBG (0, "Battery state...: %s\n",
935141cc406Sopenharmony_ci	   Camera.flags.low_batt == 0 ? "good" : (Camera.flags.low_batt ==
936141cc406Sopenharmony_ci						  1 ? "weak" : "empty"));
937141cc406Sopenharmony_ci    }
938141cc406Sopenharmony_ci
939141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
940141cc406Sopenharmony_ci}
941141cc406Sopenharmony_ci
942141cc406Sopenharmony_civoid
943141cc406Sopenharmony_cisane_exit (void)
944141cc406Sopenharmony_ci{
945141cc406Sopenharmony_ci}
946141cc406Sopenharmony_ci
947141cc406Sopenharmony_ci/* Device select/open/close */
948141cc406Sopenharmony_ci
949141cc406Sopenharmony_cistatic const SANE_Device dev[] = {
950141cc406Sopenharmony_ci  {
951141cc406Sopenharmony_ci   "0",
952141cc406Sopenharmony_ci   "Kodak",
953141cc406Sopenharmony_ci   "DC-240",
954141cc406Sopenharmony_ci   "still camera"},
955141cc406Sopenharmony_ci};
956141cc406Sopenharmony_ci
957141cc406Sopenharmony_cistatic const SANE_Device *devlist[] = {
958141cc406Sopenharmony_ci  dev + 0, 0
959141cc406Sopenharmony_ci};
960141cc406Sopenharmony_ci
961141cc406Sopenharmony_ciSANE_Status
962141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool
963141cc406Sopenharmony_ci		  __sane_unused__ local_only)
964141cc406Sopenharmony_ci{
965141cc406Sopenharmony_ci
966141cc406Sopenharmony_ci  DBG (127, "sane_get_devices called\n");
967141cc406Sopenharmony_ci
968141cc406Sopenharmony_ci  *device_list = devlist;
969141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
970141cc406Sopenharmony_ci}
971141cc406Sopenharmony_ci
972141cc406Sopenharmony_ciSANE_Status
973141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle)
974141cc406Sopenharmony_ci{
975141cc406Sopenharmony_ci  SANE_Int i;
976141cc406Sopenharmony_ci
977141cc406Sopenharmony_ci  DBG (127, "sane_open for device %s\n", devicename);
978141cc406Sopenharmony_ci  if (!devicename[0])
979141cc406Sopenharmony_ci    {
980141cc406Sopenharmony_ci      i = 0;
981141cc406Sopenharmony_ci    }
982141cc406Sopenharmony_ci  else
983141cc406Sopenharmony_ci    {
984141cc406Sopenharmony_ci      for (i = 0; i < NELEMS (dev); ++i)
985141cc406Sopenharmony_ci	{
986141cc406Sopenharmony_ci	  if (strcmp (devicename, dev[i].name) == 0)
987141cc406Sopenharmony_ci	    {
988141cc406Sopenharmony_ci	      break;
989141cc406Sopenharmony_ci	    }
990141cc406Sopenharmony_ci	}
991141cc406Sopenharmony_ci    }
992141cc406Sopenharmony_ci
993141cc406Sopenharmony_ci  if (i >= NELEMS (dev))
994141cc406Sopenharmony_ci    {
995141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
996141cc406Sopenharmony_ci    }
997141cc406Sopenharmony_ci
998141cc406Sopenharmony_ci  if (is_open)
999141cc406Sopenharmony_ci    {
1000141cc406Sopenharmony_ci      return SANE_STATUS_DEVICE_BUSY;
1001141cc406Sopenharmony_ci    }
1002141cc406Sopenharmony_ci
1003141cc406Sopenharmony_ci  is_open = 1;
1004141cc406Sopenharmony_ci  *handle = MAGIC;
1005141cc406Sopenharmony_ci
1006141cc406Sopenharmony_ci  DBG (4, "sane_open: pictures taken=%d\n", Camera.pic_taken);
1007141cc406Sopenharmony_ci
1008141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1009141cc406Sopenharmony_ci}
1010141cc406Sopenharmony_ci
1011141cc406Sopenharmony_civoid
1012141cc406Sopenharmony_cisane_close (SANE_Handle handle)
1013141cc406Sopenharmony_ci{
1014141cc406Sopenharmony_ci  DBG (127, "sane_close called\n");
1015141cc406Sopenharmony_ci  if (handle == MAGIC)
1016141cc406Sopenharmony_ci    is_open = 0;
1017141cc406Sopenharmony_ci
1018141cc406Sopenharmony_ci  DBG (127, "sane_close returning\n");
1019141cc406Sopenharmony_ci}
1020141cc406Sopenharmony_ci
1021141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
1022141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1023141cc406Sopenharmony_ci{
1024141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
1025141cc406Sopenharmony_ci    return NULL;		/* wrong device */
1026141cc406Sopenharmony_ci  if (option < 0 || option >= NELEMS (sod))
1027141cc406Sopenharmony_ci    return NULL;
1028141cc406Sopenharmony_ci  return &sod[option];
1029141cc406Sopenharmony_ci}
1030141cc406Sopenharmony_ci
1031141cc406Sopenharmony_cistatic SANE_Int myinfo = 0;
1032141cc406Sopenharmony_ci
1033141cc406Sopenharmony_ciSANE_Status
1034141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
1035141cc406Sopenharmony_ci		     SANE_Action action, void *value, SANE_Int * info)
1036141cc406Sopenharmony_ci{
1037141cc406Sopenharmony_ci  SANE_Status status;
1038141cc406Sopenharmony_ci
1039141cc406Sopenharmony_ci  if (option < 0 || option >= NELEMS (sod))
1040141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown option ... */
1041141cc406Sopenharmony_ci
1042141cc406Sopenharmony_ci  /* Need to put this DBG line after the range check on option */
1043141cc406Sopenharmony_ci  DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n",
1044141cc406Sopenharmony_ci       handle, sod[option].title,
1045141cc406Sopenharmony_ci       (action ==
1046141cc406Sopenharmony_ci	SANE_ACTION_SET_VALUE ? "SET" : (action ==
1047141cc406Sopenharmony_ci					 SANE_ACTION_GET_VALUE ? "GET" :
1048141cc406Sopenharmony_ci					 "SETAUTO")), value, (void *) info);
1049141cc406Sopenharmony_ci
1050141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
1051141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown handle ... */
1052141cc406Sopenharmony_ci
1053141cc406Sopenharmony_ci  switch (action)
1054141cc406Sopenharmony_ci    {
1055141cc406Sopenharmony_ci    case SANE_ACTION_SET_VALUE:
1056141cc406Sopenharmony_ci
1057141cc406Sopenharmony_ci      /* Can't set disabled options */
1058141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_ACTIVE (sod[option].cap))
1059141cc406Sopenharmony_ci	{
1060141cc406Sopenharmony_ci	  return (SANE_STATUS_INVAL);
1061141cc406Sopenharmony_ci	}
1062141cc406Sopenharmony_ci
1063141cc406Sopenharmony_ci      /* initialize info to zero - we'll OR in various values later */
1064141cc406Sopenharmony_ci      if (info)
1065141cc406Sopenharmony_ci	*info = 0;
1066141cc406Sopenharmony_ci
1067141cc406Sopenharmony_ci      status = sanei_constrain_value (sod + option, value, &myinfo);
1068141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
1069141cc406Sopenharmony_ci	{
1070141cc406Sopenharmony_ci	  DBG (2, "Constraint error in control_option\n");
1071141cc406Sopenharmony_ci	  return status;
1072141cc406Sopenharmony_ci	}
1073141cc406Sopenharmony_ci
1074141cc406Sopenharmony_ci      switch (option)
1075141cc406Sopenharmony_ci	{
1076141cc406Sopenharmony_ci	case DC240_OPT_IMAGE_NUMBER:
1077141cc406Sopenharmony_ci	  if (*(SANE_Word *) value <= Camera.pic_taken)
1078141cc406Sopenharmony_ci	    Camera.current_picture_number = *(SANE_Word *) value;
1079141cc406Sopenharmony_ci	  else
1080141cc406Sopenharmony_ci	    Camera.current_picture_number = Camera.pic_taken;
1081141cc406Sopenharmony_ci
1082141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
1083141cc406Sopenharmony_ci
1084141cc406Sopenharmony_ci	  /* get the image's resolution, unless the camera has no
1085141cc406Sopenharmony_ci	   * pictures yet
1086141cc406Sopenharmony_ci	   */
1087141cc406Sopenharmony_ci	  if (Camera.pic_taken != 0)
1088141cc406Sopenharmony_ci	    {
1089141cc406Sopenharmony_ci	      set_res (Camera.
1090141cc406Sopenharmony_ci		       Pictures[Camera.current_picture_number - 1].low_res);
1091141cc406Sopenharmony_ci	    }
1092141cc406Sopenharmony_ci	  break;
1093141cc406Sopenharmony_ci
1094141cc406Sopenharmony_ci	case DC240_OPT_THUMBS:
1095141cc406Sopenharmony_ci	  dc240_opt_thumbnails = !!*(SANE_Word *) value;
1096141cc406Sopenharmony_ci
1097141cc406Sopenharmony_ci	  /* Thumbnail forces an image size change: */
1098141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
1099141cc406Sopenharmony_ci
1100141cc406Sopenharmony_ci	  if (Camera.pic_taken != 0)
1101141cc406Sopenharmony_ci	    {
1102141cc406Sopenharmony_ci	      set_res (Camera.
1103141cc406Sopenharmony_ci		       Pictures[Camera.current_picture_number - 1].low_res);
1104141cc406Sopenharmony_ci	    }
1105141cc406Sopenharmony_ci	  break;
1106141cc406Sopenharmony_ci
1107141cc406Sopenharmony_ci	case DC240_OPT_SNAP:
1108141cc406Sopenharmony_ci	  switch (*(SANE_Bool *) value)
1109141cc406Sopenharmony_ci	    {
1110141cc406Sopenharmony_ci	    case SANE_TRUE:
1111141cc406Sopenharmony_ci	      dc240_opt_snap = SANE_TRUE;
1112141cc406Sopenharmony_ci	      break;
1113141cc406Sopenharmony_ci	    case SANE_FALSE:
1114141cc406Sopenharmony_ci	      dc240_opt_snap = SANE_FALSE;
1115141cc406Sopenharmony_ci	      break;
1116141cc406Sopenharmony_ci	    default:
1117141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1118141cc406Sopenharmony_ci	    }
1119141cc406Sopenharmony_ci
1120141cc406Sopenharmony_ci	  /* Snap forces new image size and changes image range */
1121141cc406Sopenharmony_ci
1122141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1123141cc406Sopenharmony_ci	  /* if we are snapping a new one */
1124141cc406Sopenharmony_ci	  if (dc240_opt_snap)
1125141cc406Sopenharmony_ci	    {
1126141cc406Sopenharmony_ci	      /* activate the resolution setting */
1127141cc406Sopenharmony_ci	      sod[DC240_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE;
1128141cc406Sopenharmony_ci	      /* and de-activate the image number selector */
1129141cc406Sopenharmony_ci	      sod[DC240_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
1130141cc406Sopenharmony_ci	    }
1131141cc406Sopenharmony_ci	  else
1132141cc406Sopenharmony_ci	    {
1133141cc406Sopenharmony_ci	      /* deactivate the resolution setting */
1134141cc406Sopenharmony_ci	      sod[DC240_OPT_LOWRES].cap |= SANE_CAP_INACTIVE;
1135141cc406Sopenharmony_ci	      /* and activate the image number selector */
1136141cc406Sopenharmony_ci	      sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
1137141cc406Sopenharmony_ci	    }
1138141cc406Sopenharmony_ci	  /* set params according to resolution settings */
1139141cc406Sopenharmony_ci	  set_res (dc240_opt_lowres);
1140141cc406Sopenharmony_ci
1141141cc406Sopenharmony_ci	  break;
1142141cc406Sopenharmony_ci
1143141cc406Sopenharmony_ci	case DC240_OPT_LOWRES:
1144141cc406Sopenharmony_ci	  dc240_opt_lowres = !!*(SANE_Word *) value;
1145141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
1146141cc406Sopenharmony_ci
1147141cc406Sopenharmony_ci/* XXX - change the number of pictures left depending on resolution
1148141cc406Sopenharmony_ci   perhaps just call get_info again?
1149141cc406Sopenharmony_ci*/
1150141cc406Sopenharmony_ci	  set_res (dc240_opt_lowres);
1151141cc406Sopenharmony_ci
1152141cc406Sopenharmony_ci	  break;
1153141cc406Sopenharmony_ci
1154141cc406Sopenharmony_ci	case DC240_OPT_ERASE:
1155141cc406Sopenharmony_ci	  dc240_opt_erase = !!*(SANE_Word *) value;
1156141cc406Sopenharmony_ci	  break;
1157141cc406Sopenharmony_ci
1158141cc406Sopenharmony_ci	case DC240_OPT_AUTOINC:
1159141cc406Sopenharmony_ci	  dc240_opt_autoinc = !!*(SANE_Word *) value;
1160141cc406Sopenharmony_ci	  break;
1161141cc406Sopenharmony_ci
1162141cc406Sopenharmony_ci	case DC240_OPT_FOLDER:
1163141cc406Sopenharmony_ci	  DBG (1, "FIXME set folder not implemented yet\n");
1164141cc406Sopenharmony_ci	  break;
1165141cc406Sopenharmony_ci
1166141cc406Sopenharmony_ci	case DC240_OPT_DEFAULT:
1167141cc406Sopenharmony_ci	  dc240_opt_thumbnails = 0;
1168141cc406Sopenharmony_ci	  dc240_opt_snap = 0;
1169141cc406Sopenharmony_ci
1170141cc406Sopenharmony_ci	  /* deactivate the resolution setting */
1171141cc406Sopenharmony_ci	  sod[DC240_OPT_LOWRES].cap |= SANE_CAP_INACTIVE;
1172141cc406Sopenharmony_ci	  /* and activate the image number selector */
1173141cc406Sopenharmony_ci	  sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
1174141cc406Sopenharmony_ci
1175141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1176141cc406Sopenharmony_ci
1177141cc406Sopenharmony_ci	  DBG (1, "Fixme: Set all defaults here!\n");
1178141cc406Sopenharmony_ci	  break;
1179141cc406Sopenharmony_ci
1180141cc406Sopenharmony_ci	case DC240_OPT_INIT_DC240:
1181141cc406Sopenharmony_ci	  if ((Camera.fd = init_dc240 (&Camera)) == -1)
1182141cc406Sopenharmony_ci	    {
1183141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1184141cc406Sopenharmony_ci	    }
1185141cc406Sopenharmony_ci	  if (get_info (&Camera) == -1)
1186141cc406Sopenharmony_ci	    {
1187141cc406Sopenharmony_ci	      DBG (1, "error: could not get info\n");
1188141cc406Sopenharmony_ci	      close_dc240 (Camera.fd);
1189141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1190141cc406Sopenharmony_ci	    }
1191141cc406Sopenharmony_ci
1192141cc406Sopenharmony_ci	  /* load the current images array */
1193141cc406Sopenharmony_ci	  get_pictures_info ();
1194141cc406Sopenharmony_ci
1195141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1196141cc406Sopenharmony_ci	  break;
1197141cc406Sopenharmony_ci
1198141cc406Sopenharmony_ci	default:
1199141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1200141cc406Sopenharmony_ci	}
1201141cc406Sopenharmony_ci      break;
1202141cc406Sopenharmony_ci
1203141cc406Sopenharmony_ci    case SANE_ACTION_GET_VALUE:
1204141cc406Sopenharmony_ci      /* Can't return status for disabled options */
1205141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_ACTIVE (sod[option].cap))
1206141cc406Sopenharmony_ci	{
1207141cc406Sopenharmony_ci	  return (SANE_STATUS_INVAL);
1208141cc406Sopenharmony_ci	}
1209141cc406Sopenharmony_ci
1210141cc406Sopenharmony_ci      switch (option)
1211141cc406Sopenharmony_ci	{
1212141cc406Sopenharmony_ci	case 0:
1213141cc406Sopenharmony_ci	  *(SANE_Word *) value = NELEMS (sod);
1214141cc406Sopenharmony_ci	  break;
1215141cc406Sopenharmony_ci
1216141cc406Sopenharmony_ci	case DC240_OPT_IMAGE_NUMBER:
1217141cc406Sopenharmony_ci	  *(SANE_Word *) value = Camera.current_picture_number;
1218141cc406Sopenharmony_ci	  break;
1219141cc406Sopenharmony_ci
1220141cc406Sopenharmony_ci	case DC240_OPT_THUMBS:
1221141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc240_opt_thumbnails;
1222141cc406Sopenharmony_ci	  break;
1223141cc406Sopenharmony_ci
1224141cc406Sopenharmony_ci	case DC240_OPT_SNAP:
1225141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc240_opt_snap;
1226141cc406Sopenharmony_ci	  break;
1227141cc406Sopenharmony_ci
1228141cc406Sopenharmony_ci	case DC240_OPT_LOWRES:
1229141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc240_opt_lowres;
1230141cc406Sopenharmony_ci	  break;
1231141cc406Sopenharmony_ci
1232141cc406Sopenharmony_ci	case DC240_OPT_ERASE:
1233141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc240_opt_erase;
1234141cc406Sopenharmony_ci	  break;
1235141cc406Sopenharmony_ci
1236141cc406Sopenharmony_ci	case DC240_OPT_AUTOINC:
1237141cc406Sopenharmony_ci	  *(SANE_Word *) value = dc240_opt_autoinc;
1238141cc406Sopenharmony_ci	  break;
1239141cc406Sopenharmony_ci
1240141cc406Sopenharmony_ci	case DC240_OPT_FOLDER:
1241141cc406Sopenharmony_ci	  strcpy ((char *) value, (char *) folder_list[current_folder]);
1242141cc406Sopenharmony_ci	  break;
1243141cc406Sopenharmony_ci
1244141cc406Sopenharmony_ci	default:
1245141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1246141cc406Sopenharmony_ci	}
1247141cc406Sopenharmony_ci      break;
1248141cc406Sopenharmony_ci
1249141cc406Sopenharmony_ci    case SANE_ACTION_SET_AUTO:
1250141cc406Sopenharmony_ci      switch (option)
1251141cc406Sopenharmony_ci	{
1252141cc406Sopenharmony_ci	default:
1253141cc406Sopenharmony_ci	  return SANE_STATUS_UNSUPPORTED;	/* We are DUMB */
1254141cc406Sopenharmony_ci	}
1255141cc406Sopenharmony_ci    }
1256141cc406Sopenharmony_ci
1257141cc406Sopenharmony_ci  if (info && action == SANE_ACTION_SET_VALUE)
1258141cc406Sopenharmony_ci    {
1259141cc406Sopenharmony_ci      *info = myinfo;
1260141cc406Sopenharmony_ci      myinfo = 0;
1261141cc406Sopenharmony_ci    }
1262141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1263141cc406Sopenharmony_ci}
1264141cc406Sopenharmony_ci
1265141cc406Sopenharmony_ciSANE_Status
1266141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1267141cc406Sopenharmony_ci{
1268141cc406Sopenharmony_ci  SANE_Int rc = SANE_STATUS_GOOD;
1269141cc406Sopenharmony_ci
1270141cc406Sopenharmony_ci  DBG (127, "sane_get_params called, wid=%d,height=%d\n",
1271141cc406Sopenharmony_ci       parms.pixels_per_line, parms.lines);
1272141cc406Sopenharmony_ci
1273141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
1274141cc406Sopenharmony_ci    rc = SANE_STATUS_INVAL;	/* Unknown handle ... */
1275141cc406Sopenharmony_ci
1276141cc406Sopenharmony_ci  parms.last_frame = SANE_TRUE;	/* Have no idea what this does */
1277141cc406Sopenharmony_ci  *params = parms;
1278141cc406Sopenharmony_ci  DBG (127, "sane_get_params return %d\n", rc);
1279141cc406Sopenharmony_ci  return rc;
1280141cc406Sopenharmony_ci}
1281141cc406Sopenharmony_ci
1282141cc406Sopenharmony_citypedef struct
1283141cc406Sopenharmony_ci{
1284141cc406Sopenharmony_ci  struct jpeg_source_mgr pub;
1285141cc406Sopenharmony_ci  JOCTET *buffer;
1286141cc406Sopenharmony_ci}
1287141cc406Sopenharmony_cimy_source_mgr;
1288141cc406Sopenharmony_citypedef my_source_mgr *my_src_ptr;
1289141cc406Sopenharmony_ci
1290141cc406Sopenharmony_ciMETHODDEF (void)
1291141cc406Sopenharmony_cijpeg_init_source (j_decompress_ptr __sane_unused__ cinfo)
1292141cc406Sopenharmony_ci{
1293141cc406Sopenharmony_ci  /* nothing to do */
1294141cc406Sopenharmony_ci}
1295141cc406Sopenharmony_ci
1296141cc406Sopenharmony_ciMETHODDEF (boolean) jpeg_fill_input_buffer (j_decompress_ptr cinfo)
1297141cc406Sopenharmony_ci{
1298141cc406Sopenharmony_ci
1299141cc406Sopenharmony_ci  my_src_ptr src = (my_src_ptr) cinfo->src;
1300141cc406Sopenharmony_ci
1301141cc406Sopenharmony_ci  if (read_data (Camera.fd, src->buffer, 512) == -1)
1302141cc406Sopenharmony_ci    {
1303141cc406Sopenharmony_ci      DBG (5, "sane_start: read_data failed\n");
1304141cc406Sopenharmony_ci      src->buffer[0] = (JOCTET) 0xFF;
1305141cc406Sopenharmony_ci      src->buffer[1] = (JOCTET) JPEG_EOI;
1306141cc406Sopenharmony_ci      return FALSE;
1307141cc406Sopenharmony_ci    }
1308141cc406Sopenharmony_ci  src->pub.next_input_byte = src->buffer;
1309141cc406Sopenharmony_ci  src->pub.bytes_in_buffer = 512;
1310141cc406Sopenharmony_ci
1311141cc406Sopenharmony_ci  return TRUE;
1312141cc406Sopenharmony_ci}
1313141cc406Sopenharmony_ci
1314141cc406Sopenharmony_ciMETHODDEF (void) jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
1315141cc406Sopenharmony_ci{
1316141cc406Sopenharmony_ci
1317141cc406Sopenharmony_ci  my_src_ptr src = (my_src_ptr) cinfo->src;
1318141cc406Sopenharmony_ci
1319141cc406Sopenharmony_ci  if (num_bytes > 0)
1320141cc406Sopenharmony_ci    {
1321141cc406Sopenharmony_ci      while (num_bytes > (long) src->pub.bytes_in_buffer)
1322141cc406Sopenharmony_ci	{
1323141cc406Sopenharmony_ci	  num_bytes -= (long) src->pub.bytes_in_buffer;
1324141cc406Sopenharmony_ci	  (void) jpeg_fill_input_buffer (cinfo);
1325141cc406Sopenharmony_ci	}
1326141cc406Sopenharmony_ci    }
1327141cc406Sopenharmony_ci  src->pub.next_input_byte += (size_t) num_bytes;
1328141cc406Sopenharmony_ci  src->pub.bytes_in_buffer -= (size_t) num_bytes;
1329141cc406Sopenharmony_ci}
1330141cc406Sopenharmony_ci
1331141cc406Sopenharmony_cistatic SANE_Byte linebuffer[HIGHRES_WIDTH * 3];
1332141cc406Sopenharmony_cistatic SANE_Int linebuffer_size = 0;
1333141cc406Sopenharmony_cistatic SANE_Int linebuffer_index = 0;
1334141cc406Sopenharmony_ci
1335141cc406Sopenharmony_ci
1336141cc406Sopenharmony_ciMETHODDEF (void)
1337141cc406Sopenharmony_cijpeg_term_source (j_decompress_ptr __sane_unused__ cinfo)
1338141cc406Sopenharmony_ci{
1339141cc406Sopenharmony_ci  /* no work necessary here */
1340141cc406Sopenharmony_ci}
1341141cc406Sopenharmony_ci
1342141cc406Sopenharmony_ciSANE_Status
1343141cc406Sopenharmony_cisane_start (SANE_Handle handle)
1344141cc406Sopenharmony_ci{
1345141cc406Sopenharmony_ci  SANE_Int i;
1346141cc406Sopenharmony_ci
1347141cc406Sopenharmony_ci  DBG (127, "sane_start called\n");
1348141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open ||
1349141cc406Sopenharmony_ci      (Camera.current_picture_number == 0 && dc240_opt_snap == SANE_FALSE))
1350141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown handle ... */
1351141cc406Sopenharmony_ci
1352141cc406Sopenharmony_ci  if (Camera.scanning)
1353141cc406Sopenharmony_ci    return SANE_STATUS_EOF;
1354141cc406Sopenharmony_ci
1355141cc406Sopenharmony_ci/*
1356141cc406Sopenharmony_ci * This shouldn't normally happen, but we allow it as a special case
1357141cc406Sopenharmony_ci * when batch/autoinc are in effect.  The first illegal picture number
1358141cc406Sopenharmony_ci * terminates the scan
1359141cc406Sopenharmony_ci */
1360141cc406Sopenharmony_ci  if (Camera.current_picture_number > Camera.pic_taken)
1361141cc406Sopenharmony_ci    {
1362141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1363141cc406Sopenharmony_ci    }
1364141cc406Sopenharmony_ci
1365141cc406Sopenharmony_ci  if (dc240_opt_snap)
1366141cc406Sopenharmony_ci    {
1367141cc406Sopenharmony_ci      /*
1368141cc406Sopenharmony_ci       * Don't allow picture unless there is room in the
1369141cc406Sopenharmony_ci       * camera.
1370141cc406Sopenharmony_ci       */
1371141cc406Sopenharmony_ci      if (Camera.pic_left == 0)
1372141cc406Sopenharmony_ci	{
1373141cc406Sopenharmony_ci	  DBG (3, "No room to store new picture\n");
1374141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1375141cc406Sopenharmony_ci	}
1376141cc406Sopenharmony_ci
1377141cc406Sopenharmony_ci
1378141cc406Sopenharmony_ci      if (snap_pic (Camera.fd) == SANE_STATUS_INVAL)
1379141cc406Sopenharmony_ci	{
1380141cc406Sopenharmony_ci	  DBG (1, "Failed to snap new picture\n");
1381141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1382141cc406Sopenharmony_ci	}
1383141cc406Sopenharmony_ci    }
1384141cc406Sopenharmony_ci
1385141cc406Sopenharmony_ci  if (dc240_opt_thumbnails)
1386141cc406Sopenharmony_ci    {
1387141cc406Sopenharmony_ci
1388141cc406Sopenharmony_ci      if (send_pck (Camera.fd, thumb_pck) == -1)
1389141cc406Sopenharmony_ci	{
1390141cc406Sopenharmony_ci	  DBG (1, "sane_start: error: send_pck returned -1\n");
1391141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1392141cc406Sopenharmony_ci	}
1393141cc406Sopenharmony_ci
1394141cc406Sopenharmony_ci      /* Picture size should have been set when thumbnails were
1395141cc406Sopenharmony_ci       * selected.  But, check just in case
1396141cc406Sopenharmony_ci       */
1397141cc406Sopenharmony_ci
1398141cc406Sopenharmony_ci      if (parms.pixels_per_line != 160 ||
1399141cc406Sopenharmony_ci	  parms.bytes_per_line != 160 * 3 || parms.lines != 120)
1400141cc406Sopenharmony_ci	{
1401141cc406Sopenharmony_ci	  DBG (1, "sane_start: fixme! thumbnail image size is wrong\n");
1402141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1403141cc406Sopenharmony_ci	}
1404141cc406Sopenharmony_ci    }
1405141cc406Sopenharmony_ci  else
1406141cc406Sopenharmony_ci    {
1407141cc406Sopenharmony_ci      if (send_pck (Camera.fd, pic_pck) == -1)
1408141cc406Sopenharmony_ci	{
1409141cc406Sopenharmony_ci	  DBG (1, "sane_start: error: send_pck returned -1\n");
1410141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1411141cc406Sopenharmony_ci	}
1412141cc406Sopenharmony_ci
1413141cc406Sopenharmony_ci    }
1414141cc406Sopenharmony_ci  {
1415141cc406Sopenharmony_ci    my_src_ptr src;
1416141cc406Sopenharmony_ci
1417141cc406Sopenharmony_ci    struct jpeg_error_mgr jerr;
1418141cc406Sopenharmony_ci    SANE_Int n;
1419141cc406Sopenharmony_ci    SANE_Char f[] = "sane_start";
1420141cc406Sopenharmony_ci    SANE_Char path[256];
1421141cc406Sopenharmony_ci    struct cam_dirlist *e;
1422141cc406Sopenharmony_ci    name_buf[0] = 0x80;
1423141cc406Sopenharmony_ci
1424141cc406Sopenharmony_ci    for (n = 1, e = dir_head; e; n++, e = e->next)
1425141cc406Sopenharmony_ci      {
1426141cc406Sopenharmony_ci	if (n == Camera.current_picture_number)
1427141cc406Sopenharmony_ci	  break;
1428141cc406Sopenharmony_ci      }
1429141cc406Sopenharmony_ci
1430141cc406Sopenharmony_ci    strcpy (path, "\\PCCARD\\DCIM\\");
1431141cc406Sopenharmony_ci    strcat (path, (char *) folder_list[current_folder]);
1432141cc406Sopenharmony_ci    strcat (path, "\\");
1433141cc406Sopenharmony_ci    strcat (path, e->name);
1434141cc406Sopenharmony_ci    path[strlen (path) - 3] = '\0';
1435141cc406Sopenharmony_ci    strcat (path, ".JPG");
1436141cc406Sopenharmony_ci
1437141cc406Sopenharmony_ci    DBG (9, "%s: pic to read is %d name is %s\n", f, n, path);
1438141cc406Sopenharmony_ci
1439141cc406Sopenharmony_ci    strcpy ((char *) &name_buf[1], path);
1440141cc406Sopenharmony_ci    for (i = 49; i <= 56; i++)
1441141cc406Sopenharmony_ci      {
1442141cc406Sopenharmony_ci	name_buf[i] = 0xff;
1443141cc406Sopenharmony_ci      }
1444141cc406Sopenharmony_ci
1445141cc406Sopenharmony_ci    if (send_data (name_buf) == -1)
1446141cc406Sopenharmony_ci      {
1447141cc406Sopenharmony_ci	DBG (1, "%s: error: send_data returned -1\n", f);
1448141cc406Sopenharmony_ci	return SANE_STATUS_INVAL;
1449141cc406Sopenharmony_ci      }
1450141cc406Sopenharmony_ci
1451141cc406Sopenharmony_ci    cinfo.err = jpeg_std_error (&jerr);
1452141cc406Sopenharmony_ci    jpeg_create_decompress (&cinfo);
1453141cc406Sopenharmony_ci
1454141cc406Sopenharmony_ci    cinfo.src =
1455141cc406Sopenharmony_ci      (struct jpeg_source_mgr *) (*cinfo.mem->
1456141cc406Sopenharmony_ci				  alloc_small) ((j_common_ptr) & cinfo,
1457141cc406Sopenharmony_ci						JPOOL_PERMANENT,
1458141cc406Sopenharmony_ci						sizeof (my_source_mgr));
1459141cc406Sopenharmony_ci    src = (my_src_ptr) cinfo.src;
1460141cc406Sopenharmony_ci
1461141cc406Sopenharmony_ci    src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) &
1462141cc406Sopenharmony_ci							cinfo,
1463141cc406Sopenharmony_ci							JPOOL_PERMANENT,
1464141cc406Sopenharmony_ci							1024 *
1465141cc406Sopenharmony_ci							sizeof (JOCTET));
1466141cc406Sopenharmony_ci    src->pub.init_source = jpeg_init_source;
1467141cc406Sopenharmony_ci    src->pub.fill_input_buffer = jpeg_fill_input_buffer;
1468141cc406Sopenharmony_ci    src->pub.skip_input_data = jpeg_skip_input_data;
1469141cc406Sopenharmony_ci    src->pub.resync_to_restart = jpeg_resync_to_restart;	/* default */
1470141cc406Sopenharmony_ci    src->pub.term_source = jpeg_term_source;
1471141cc406Sopenharmony_ci    src->pub.bytes_in_buffer = 0;
1472141cc406Sopenharmony_ci    src->pub.next_input_byte = NULL;
1473141cc406Sopenharmony_ci
1474141cc406Sopenharmony_ci    (void) jpeg_read_header (&cinfo, TRUE);
1475141cc406Sopenharmony_ci    dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo);
1476141cc406Sopenharmony_ci    (void) jpeg_start_decompress (&cinfo);
1477141cc406Sopenharmony_ci
1478141cc406Sopenharmony_ci    linebuffer_size = 0;
1479141cc406Sopenharmony_ci    linebuffer_index = 0;
1480141cc406Sopenharmony_ci  }
1481141cc406Sopenharmony_ci
1482141cc406Sopenharmony_ci  Camera.scanning = SANE_TRUE;	/* don't overlap scan requests */
1483141cc406Sopenharmony_ci
1484141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1485141cc406Sopenharmony_ci}
1486141cc406Sopenharmony_ci
1487141cc406Sopenharmony_ciSANE_Status
1488141cc406Sopenharmony_cisane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data,
1489141cc406Sopenharmony_ci	   SANE_Int max_length, SANE_Int * length)
1490141cc406Sopenharmony_ci{
1491141cc406Sopenharmony_ci  SANE_Int lines = 0;
1492141cc406Sopenharmony_ci  SANE_Char filename_buf[256];
1493141cc406Sopenharmony_ci
1494141cc406Sopenharmony_ci  if (Camera.scanning == SANE_FALSE)
1495141cc406Sopenharmony_ci    {
1496141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1497141cc406Sopenharmony_ci    }
1498141cc406Sopenharmony_ci
1499141cc406Sopenharmony_ci  /* If there is anything in the buffer, satisfy the read from there */
1500141cc406Sopenharmony_ci  if (linebuffer_size && linebuffer_index < linebuffer_size)
1501141cc406Sopenharmony_ci    {
1502141cc406Sopenharmony_ci      *length = linebuffer_size - linebuffer_index;
1503141cc406Sopenharmony_ci
1504141cc406Sopenharmony_ci      if (*length > max_length)
1505141cc406Sopenharmony_ci	{
1506141cc406Sopenharmony_ci	  *length = max_length;
1507141cc406Sopenharmony_ci	}
1508141cc406Sopenharmony_ci      memcpy (data, linebuffer + linebuffer_index, *length);
1509141cc406Sopenharmony_ci      linebuffer_index += *length;
1510141cc406Sopenharmony_ci
1511141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
1512141cc406Sopenharmony_ci    }
1513141cc406Sopenharmony_ci
1514141cc406Sopenharmony_ci  if (cinfo.output_scanline >= cinfo.output_height)
1515141cc406Sopenharmony_ci    {
1516141cc406Sopenharmony_ci      *length = 0;
1517141cc406Sopenharmony_ci
1518141cc406Sopenharmony_ci      /* clean up comms with the camera */
1519141cc406Sopenharmony_ci      if (end_of_data (Camera.fd) == -1)
1520141cc406Sopenharmony_ci	{
1521141cc406Sopenharmony_ci	  DBG (1, "sane_read: error: end_of_data returned -1\n");
1522141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1523141cc406Sopenharmony_ci	}
1524141cc406Sopenharmony_ci      if (dc240_opt_erase)
1525141cc406Sopenharmony_ci	{
1526141cc406Sopenharmony_ci	  DBG (127, "sane_read bp%d, erase image\n", __LINE__);
1527141cc406Sopenharmony_ci	  if (erase (Camera.fd) == -1)
1528141cc406Sopenharmony_ci	    {
1529141cc406Sopenharmony_ci	      DBG (1, "Failed to erase memory\n");
1530141cc406Sopenharmony_ci	      return SANE_STATUS_INVAL;
1531141cc406Sopenharmony_ci	    }
1532141cc406Sopenharmony_ci	  Camera.pic_taken--;
1533141cc406Sopenharmony_ci	  Camera.pic_left++;
1534141cc406Sopenharmony_ci	  Camera.current_picture_number = Camera.pic_taken;
1535141cc406Sopenharmony_ci	  image_range.max--;
1536141cc406Sopenharmony_ci
1537141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1538141cc406Sopenharmony_ci	  strcpy ((char *) filename_buf,
1539141cc406Sopenharmony_ci		  strrchr ((char *) name_buf + 1, '\\') + 1);
1540141cc406Sopenharmony_ci	  strcpy (strrchr ((char *) filename_buf, '.'), "JPG");
1541141cc406Sopenharmony_ci	  dir_delete ((SANE_String) filename_buf);
1542141cc406Sopenharmony_ci
1543141cc406Sopenharmony_ci	}
1544141cc406Sopenharmony_ci      if (dc240_opt_autoinc)
1545141cc406Sopenharmony_ci	{
1546141cc406Sopenharmony_ci	  if (Camera.current_picture_number <= Camera.pic_taken)
1547141cc406Sopenharmony_ci	    {
1548141cc406Sopenharmony_ci	      Camera.current_picture_number++;
1549141cc406Sopenharmony_ci
1550141cc406Sopenharmony_ci	      myinfo |= SANE_INFO_RELOAD_PARAMS;
1551141cc406Sopenharmony_ci
1552141cc406Sopenharmony_ci	      /* get the image's resolution */
1553141cc406Sopenharmony_ci	      set_res (Camera.Pictures[Camera.current_picture_number - 1].
1554141cc406Sopenharmony_ci		       low_res);
1555141cc406Sopenharmony_ci	    }
1556141cc406Sopenharmony_ci	  DBG (4, "Increment count to %d (total %d)\n",
1557141cc406Sopenharmony_ci	       Camera.current_picture_number, Camera.pic_taken);
1558141cc406Sopenharmony_ci	}
1559141cc406Sopenharmony_ci      return SANE_STATUS_EOF;
1560141cc406Sopenharmony_ci    }
1561141cc406Sopenharmony_ci
1562141cc406Sopenharmony_ci/* XXX - we should read more than 1 line at a time here */
1563141cc406Sopenharmony_ci  lines = 1;
1564141cc406Sopenharmony_ci  (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines);
1565141cc406Sopenharmony_ci  (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) linebuffer);
1566141cc406Sopenharmony_ci
1567141cc406Sopenharmony_ci  *length = cinfo.output_width * cinfo.output_components * lines;
1568141cc406Sopenharmony_ci  linebuffer_size = *length;
1569141cc406Sopenharmony_ci  linebuffer_index = 0;
1570141cc406Sopenharmony_ci
1571141cc406Sopenharmony_ci  if (*length > max_length)
1572141cc406Sopenharmony_ci    {
1573141cc406Sopenharmony_ci      *length = max_length;
1574141cc406Sopenharmony_ci    }
1575141cc406Sopenharmony_ci  memcpy (data, linebuffer + linebuffer_index, *length);
1576141cc406Sopenharmony_ci  linebuffer_index += *length;
1577141cc406Sopenharmony_ci
1578141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1579141cc406Sopenharmony_ci}
1580141cc406Sopenharmony_ci
1581141cc406Sopenharmony_civoid
1582141cc406Sopenharmony_cisane_cancel (SANE_Handle __sane_unused__ handle)
1583141cc406Sopenharmony_ci{
1584141cc406Sopenharmony_ci  unsigned char cancel_byte[] = { 0xe4 };
1585141cc406Sopenharmony_ci
1586141cc406Sopenharmony_ci  if (Camera.scanning)
1587141cc406Sopenharmony_ci    {
1588141cc406Sopenharmony_ci
1589141cc406Sopenharmony_ci      /* Flush any pending data from the camera before continuing */
1590141cc406Sopenharmony_ci      {
1591141cc406Sopenharmony_ci	SANE_Int n;
1592141cc406Sopenharmony_ci	SANE_Char flush[1024];
1593141cc406Sopenharmony_ci	do
1594141cc406Sopenharmony_ci	  {
1595141cc406Sopenharmony_ci	    sleep (1);
1596141cc406Sopenharmony_ci	    n = read (Camera.fd, flush, 1024);
1597141cc406Sopenharmony_ci	    if (n > 0)
1598141cc406Sopenharmony_ci	      {
1599141cc406Sopenharmony_ci		DBG (127, "%s: flushed %d bytes\n", "sane_cancel", n);
1600141cc406Sopenharmony_ci	      }
1601141cc406Sopenharmony_ci	    else
1602141cc406Sopenharmony_ci	      {
1603141cc406Sopenharmony_ci		DBG (127, "%s: nothing to flush\n", "sane_cancel");
1604141cc406Sopenharmony_ci	      }
1605141cc406Sopenharmony_ci	  }
1606141cc406Sopenharmony_ci	while (n > 0);
1607141cc406Sopenharmony_ci      }
1608141cc406Sopenharmony_ci
1609141cc406Sopenharmony_ci      if (cinfo.output_scanline < cinfo.output_height)
1610141cc406Sopenharmony_ci	{
1611141cc406Sopenharmony_ci	  write (Camera.fd, cancel_byte, 1);
1612141cc406Sopenharmony_ci	}
1613141cc406Sopenharmony_ci
1614141cc406Sopenharmony_ci      Camera.scanning = SANE_FALSE;	/* done with scan */
1615141cc406Sopenharmony_ci    }
1616141cc406Sopenharmony_ci  else
1617141cc406Sopenharmony_ci    DBG (4, "sane_cancel: not scanning - nothing to do\n");
1618141cc406Sopenharmony_ci}
1619141cc406Sopenharmony_ci
1620141cc406Sopenharmony_ciSANE_Status
1621141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool
1622141cc406Sopenharmony_ci		  __sane_unused__ non_blocking)
1623141cc406Sopenharmony_ci{
1624141cc406Sopenharmony_ci  /* sane_set_io_mode() is only valid during a scan */
1625141cc406Sopenharmony_ci  if (Camera.scanning)
1626141cc406Sopenharmony_ci    {
1627141cc406Sopenharmony_ci      if (non_blocking == SANE_FALSE)
1628141cc406Sopenharmony_ci	{
1629141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
1630141cc406Sopenharmony_ci	}
1631141cc406Sopenharmony_ci      else
1632141cc406Sopenharmony_ci	{
1633141cc406Sopenharmony_ci	  return SANE_STATUS_UNSUPPORTED;
1634141cc406Sopenharmony_ci	}
1635141cc406Sopenharmony_ci    }
1636141cc406Sopenharmony_ci  else
1637141cc406Sopenharmony_ci    {
1638141cc406Sopenharmony_ci      /* We aren't currently scanning */
1639141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1640141cc406Sopenharmony_ci    }
1641141cc406Sopenharmony_ci}
1642141cc406Sopenharmony_ci
1643141cc406Sopenharmony_ciSANE_Status
1644141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)
1645141cc406Sopenharmony_ci{
1646141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1647141cc406Sopenharmony_ci}
1648141cc406Sopenharmony_ci
1649141cc406Sopenharmony_ci/*
1650141cc406Sopenharmony_ci * get_pictures_info - load information about all pictures currently in
1651141cc406Sopenharmony_ci *			camera:  Mainly the mapping of picture number
1652141cc406Sopenharmony_ci *			to picture name, and the resolution of each picture.
1653141cc406Sopenharmony_ci */
1654141cc406Sopenharmony_cistatic PictureInfo *
1655141cc406Sopenharmony_ciget_pictures_info (void)
1656141cc406Sopenharmony_ci{
1657141cc406Sopenharmony_ci  SANE_Char f[] = "get_pictures_info";
1658141cc406Sopenharmony_ci  SANE_Char path[256];
1659141cc406Sopenharmony_ci  SANE_Int num_pictures;
1660141cc406Sopenharmony_ci  SANE_Int p;
1661141cc406Sopenharmony_ci  PictureInfo *pics;
1662141cc406Sopenharmony_ci
1663141cc406Sopenharmony_ci  if (Camera.Pictures)
1664141cc406Sopenharmony_ci    {
1665141cc406Sopenharmony_ci      free (Camera.Pictures);
1666141cc406Sopenharmony_ci      Camera.Pictures = NULL;
1667141cc406Sopenharmony_ci    }
1668141cc406Sopenharmony_ci
1669141cc406Sopenharmony_ci  strcpy (path, "\\PCCARD\\DCIM\\");
1670141cc406Sopenharmony_ci  strcat (path, (char *) folder_list[current_folder]);
1671141cc406Sopenharmony_ci  strcat (path, "\\*.*");
1672141cc406Sopenharmony_ci
1673141cc406Sopenharmony_ci  num_pictures = read_dir (path);
1674141cc406Sopenharmony_ci  if (num_pictures != Camera.pic_taken)
1675141cc406Sopenharmony_ci    {
1676141cc406Sopenharmony_ci      DBG (2,
1677141cc406Sopenharmony_ci	   "%s: warning: Number of pictures in directory (%d) doesn't match camera status table (%d).  Using directory count\n",
1678141cc406Sopenharmony_ci	   f, num_pictures, Camera.pic_taken);
1679141cc406Sopenharmony_ci      Camera.pic_taken = num_pictures;
1680141cc406Sopenharmony_ci      image_range.max = num_pictures;
1681141cc406Sopenharmony_ci    }
1682141cc406Sopenharmony_ci
1683141cc406Sopenharmony_ci  if ((pics = (PictureInfo *) malloc (Camera.pic_taken *
1684141cc406Sopenharmony_ci				      sizeof (PictureInfo))) == NULL)
1685141cc406Sopenharmony_ci    {
1686141cc406Sopenharmony_ci      DBG (1, "%s: error: allocate memory for pictures array\n", f);
1687141cc406Sopenharmony_ci      return NULL;
1688141cc406Sopenharmony_ci    }
1689141cc406Sopenharmony_ci
1690141cc406Sopenharmony_ci  for (p = 0; p < Camera.pic_taken; p++)
1691141cc406Sopenharmony_ci    {
1692141cc406Sopenharmony_ci      if (get_picture_info (pics + p, p) == -1)
1693141cc406Sopenharmony_ci	{
1694141cc406Sopenharmony_ci	  free (pics);
1695141cc406Sopenharmony_ci	  return NULL;
1696141cc406Sopenharmony_ci	}
1697141cc406Sopenharmony_ci    }
1698141cc406Sopenharmony_ci
1699141cc406Sopenharmony_ci  Camera.Pictures = pics;
1700141cc406Sopenharmony_ci  return pics;
1701141cc406Sopenharmony_ci}
1702141cc406Sopenharmony_ci
1703141cc406Sopenharmony_cistatic SANE_Int
1704141cc406Sopenharmony_ciget_picture_info (PictureInfo * pic, SANE_Int p)
1705141cc406Sopenharmony_ci{
1706141cc406Sopenharmony_ci
1707141cc406Sopenharmony_ci  SANE_Char f[] = "get_picture_info";
1708141cc406Sopenharmony_ci  SANE_Int n;
1709141cc406Sopenharmony_ci  struct cam_dirlist *e;
1710141cc406Sopenharmony_ci
1711141cc406Sopenharmony_ci  DBG (4, "%s: info for pic #%d\n", f, p);
1712141cc406Sopenharmony_ci
1713141cc406Sopenharmony_ci  for (n = 0, e = dir_head; e && n < p; n++, e = e->next)
1714141cc406Sopenharmony_ci    ;
1715141cc406Sopenharmony_ci
1716141cc406Sopenharmony_ci  DBG (4, "Name is %s\n", e->name);
1717141cc406Sopenharmony_ci
1718141cc406Sopenharmony_ci  read_info (e->name);
1719141cc406Sopenharmony_ci
1720141cc406Sopenharmony_ci  /* Validate picture info
1721141cc406Sopenharmony_ci   * byte 0 - 1 == picture info
1722141cc406Sopenharmony_ci   * byte 1 - 5 == DC240 Camera
1723141cc406Sopenharmony_ci   * byte 2 - 3 == JFIF file
1724141cc406Sopenharmony_ci   * byte 6 - 0 == Image is complete
1725141cc406Sopenharmony_ci   */
1726141cc406Sopenharmony_ci  if (info_buf[0] != 1 || info_buf[1] != 5 || info_buf[2] != 3
1727141cc406Sopenharmony_ci      || info_buf[6] != 0)
1728141cc406Sopenharmony_ci    {
1729141cc406Sopenharmony_ci
1730141cc406Sopenharmony_ci      DBG (1, "%s: error: Image %s does not come from a DC-240.\n", f,
1731141cc406Sopenharmony_ci	   e->name);
1732141cc406Sopenharmony_ci      return -1;
1733141cc406Sopenharmony_ci    }
1734141cc406Sopenharmony_ci
1735141cc406Sopenharmony_ci  pic->low_res = info_buf[3] == 0 ? SANE_TRUE : SANE_FALSE;
1736141cc406Sopenharmony_ci
1737141cc406Sopenharmony_ci  /*
1738141cc406Sopenharmony_ci   * byte 12 - Year MSB
1739141cc406Sopenharmony_ci   * byte 13 - Year LSB
1740141cc406Sopenharmony_ci   * byte 14 - Month
1741141cc406Sopenharmony_ci   * byte 15 - Day
1742141cc406Sopenharmony_ci   * byte 16 - Hour
1743141cc406Sopenharmony_ci   * byte 17 - Minute
1744141cc406Sopenharmony_ci   * byte 18 - Second
1745141cc406Sopenharmony_ci   */
1746141cc406Sopenharmony_ci  DBG (1, "Picture %d taken %02d/%02d/%02d %02d:%02d:%02d\n",
1747141cc406Sopenharmony_ci       p, info_buf[14],
1748141cc406Sopenharmony_ci       info_buf[15], (info_buf[12] << 8) + info_buf[13],
1749141cc406Sopenharmony_ci       info_buf[16], info_buf[17], info_buf[18]);
1750141cc406Sopenharmony_ci
1751141cc406Sopenharmony_ci  return 0;
1752141cc406Sopenharmony_ci}
1753141cc406Sopenharmony_ci
1754141cc406Sopenharmony_ci/*
1755141cc406Sopenharmony_ci * snap_pic - take a picture (and call get_pictures_info to re-create
1756141cc406Sopenharmony_ci *		the directory related data structures)
1757141cc406Sopenharmony_ci */
1758141cc406Sopenharmony_cistatic SANE_Status
1759141cc406Sopenharmony_cisnap_pic (SANE_Int fd)
1760141cc406Sopenharmony_ci{
1761141cc406Sopenharmony_ci
1762141cc406Sopenharmony_ci  SANE_Char f[] = "snap_pic";
1763141cc406Sopenharmony_ci
1764141cc406Sopenharmony_ci#if 0
1765141cc406Sopenharmony_ci/* Just checking... It looks like after snapping the picture, we
1766141cc406Sopenharmony_ci * get two "d1" ACK responses back, even though the documentation seems
1767141cc406Sopenharmony_ci * to say that there should only be one.  I thought the first one could
1768141cc406Sopenharmony_ci * have been an unread response from an earlier command, so I
1769141cc406Sopenharmony_ci * I tried flushing any data here.  Still seeing the multiple
1770141cc406Sopenharmony_ci * d1 bytes, however...
1771141cc406Sopenharmony_ci */
1772141cc406Sopenharmony_ci  {
1773141cc406Sopenharmony_ci    SANE_Int n;
1774141cc406Sopenharmony_ci    SANE_Char flush[10];
1775141cc406Sopenharmony_ci    n = read (Camera.fd, flush, 10);
1776141cc406Sopenharmony_ci    if (n > 0)
1777141cc406Sopenharmony_ci      {
1778141cc406Sopenharmony_ci	DBG (127, "%s: flushed %d bytes\n", f, n);
1779141cc406Sopenharmony_ci      }
1780141cc406Sopenharmony_ci    else
1781141cc406Sopenharmony_ci      {
1782141cc406Sopenharmony_ci	DBG (127, "%s: nothing to flush\n", f);
1783141cc406Sopenharmony_ci      }
1784141cc406Sopenharmony_ci  }
1785141cc406Sopenharmony_ci#endif
1786141cc406Sopenharmony_ci
1787141cc406Sopenharmony_ci  /* make sure camera is set to our settings state */
1788141cc406Sopenharmony_ci  if (change_res (Camera.fd, dc240_opt_lowres) == -1)
1789141cc406Sopenharmony_ci    {
1790141cc406Sopenharmony_ci      DBG (1, "%s: Failed to set resolution\n", f);
1791141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1792141cc406Sopenharmony_ci    }
1793141cc406Sopenharmony_ci
1794141cc406Sopenharmony_ci  /* take the picture */
1795141cc406Sopenharmony_ci  if (send_pck (fd, shoot_pck) == -1)
1796141cc406Sopenharmony_ci    {
1797141cc406Sopenharmony_ci      DBG (1, "%s: error: send_pck returned -1\n", f);
1798141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1799141cc406Sopenharmony_ci    }
1800141cc406Sopenharmony_ci  else
1801141cc406Sopenharmony_ci    {
1802141cc406Sopenharmony_ci      if (end_of_data (Camera.fd) == -1)
1803141cc406Sopenharmony_ci	{
1804141cc406Sopenharmony_ci	  DBG (1, "%s: error: end_of_data returned -1\n", f);
1805141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1806141cc406Sopenharmony_ci	}
1807141cc406Sopenharmony_ci    }
1808141cc406Sopenharmony_ci  Camera.pic_taken++;
1809141cc406Sopenharmony_ci  Camera.pic_left--;
1810141cc406Sopenharmony_ci  Camera.current_picture_number = Camera.pic_taken;
1811141cc406Sopenharmony_ci  image_range.max++;
1812141cc406Sopenharmony_ci  sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
1813141cc406Sopenharmony_ci
1814141cc406Sopenharmony_ci  /* add this one to the Pictures array */
1815141cc406Sopenharmony_ci
1816141cc406Sopenharmony_ci  if (get_pictures_info () == NULL)
1817141cc406Sopenharmony_ci    {
1818141cc406Sopenharmony_ci      DBG (1, "%s: Failed to get new picture info\n", f);
1819141cc406Sopenharmony_ci      /* XXX - I guess we should try to erase the image here */
1820141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1821141cc406Sopenharmony_ci    }
1822141cc406Sopenharmony_ci
1823141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1824141cc406Sopenharmony_ci}
1825141cc406Sopenharmony_ci
1826141cc406Sopenharmony_ci/*
1827141cc406Sopenharmony_ci * read_dir - read a list of file names from the specified directory
1828141cc406Sopenharmony_ci * 		and create a linked list of file name entries in
1829141cc406Sopenharmony_ci *		alphabetical order.  The first entry in the list will
1830141cc406Sopenharmony_ci *		be "picture #1", etc.
1831141cc406Sopenharmony_ci */
1832141cc406Sopenharmony_cistatic SANE_Int
1833141cc406Sopenharmony_ciread_dir (SANE_String dir)
1834141cc406Sopenharmony_ci{
1835141cc406Sopenharmony_ci  SANE_Int retval = 0;
1836141cc406Sopenharmony_ci  SANE_Byte buf[256];
1837141cc406Sopenharmony_ci  SANE_Byte *next_buf;
1838141cc406Sopenharmony_ci  SANE_Int i, entries;
1839141cc406Sopenharmony_ci  SANE_Byte r = 0xf0;		/* prime the loop with a "camera busy" */
1840141cc406Sopenharmony_ci  SANE_Char f[] = "read_dir";
1841141cc406Sopenharmony_ci  struct cam_dirlist *e, *next;
1842141cc406Sopenharmony_ci
1843141cc406Sopenharmony_ci  /* Free up current list */
1844141cc406Sopenharmony_ci  for (e = dir_head; e; e = next)
1845141cc406Sopenharmony_ci    {
1846141cc406Sopenharmony_ci      DBG (127, "%s: free entry %s\n", f, e->name);
1847141cc406Sopenharmony_ci      next = e->next;
1848141cc406Sopenharmony_ci      free (e);
1849141cc406Sopenharmony_ci    }
1850141cc406Sopenharmony_ci  dir_head = NULL;
1851141cc406Sopenharmony_ci
1852141cc406Sopenharmony_ci  if (send_pck (Camera.fd, read_dir_pck) == -1)
1853141cc406Sopenharmony_ci    {
1854141cc406Sopenharmony_ci      DBG (1, "%s: error: send_pck returned -1\n", f);
1855141cc406Sopenharmony_ci      return -1;
1856141cc406Sopenharmony_ci    }
1857141cc406Sopenharmony_ci
1858141cc406Sopenharmony_ci  buf[0] = 0x80;
1859141cc406Sopenharmony_ci  strcpy ((char *) &buf[1], dir);
1860141cc406Sopenharmony_ci  for (i = 49; i <= 56; i++)
1861141cc406Sopenharmony_ci    {
1862141cc406Sopenharmony_ci      buf[i] = 0xff;
1863141cc406Sopenharmony_ci    }
1864141cc406Sopenharmony_ci
1865141cc406Sopenharmony_ci  if (send_data (buf) == -1)
1866141cc406Sopenharmony_ci    {
1867141cc406Sopenharmony_ci      DBG (1, "%s: error: send_data returned -1\n", f);
1868141cc406Sopenharmony_ci      return -1;
1869141cc406Sopenharmony_ci    }
1870141cc406Sopenharmony_ci
1871141cc406Sopenharmony_ci
1872141cc406Sopenharmony_ci  if (read_data (Camera.fd, (SANE_Byte *) & dir_buf2, 256) == -1)
1873141cc406Sopenharmony_ci    {
1874141cc406Sopenharmony_ci      DBG (1, "%s: error: read_data returned -1\n", f);
1875141cc406Sopenharmony_ci      return -1;
1876141cc406Sopenharmony_ci    }
1877141cc406Sopenharmony_ci
1878141cc406Sopenharmony_ci  entries = (dir_buf2[0] << 8) + dir_buf2[1];
1879141cc406Sopenharmony_ci  DBG (127, "%s: result of dir read is %x, number of entries=%d\n", f, r,
1880141cc406Sopenharmony_ci       entries);
1881141cc406Sopenharmony_ci
1882141cc406Sopenharmony_ci  if (entries > 1001)
1883141cc406Sopenharmony_ci    {
1884141cc406Sopenharmony_ci      DBG (1, "%s: error: more than 999 pictures not supported yet\n", f);
1885141cc406Sopenharmony_ci      return -1;
1886141cc406Sopenharmony_ci    }
1887141cc406Sopenharmony_ci
1888141cc406Sopenharmony_ci  /* Determine if it's time to read another 256 byte buffer from the camera */
1889141cc406Sopenharmony_ci
1890141cc406Sopenharmony_ci  next_buf = ((SANE_Byte *) & dir_buf2) + 256;
1891141cc406Sopenharmony_ci  while (dir_buf2 + 2 + CAMDIRENTRYSIZE * entries >= (SANE_Byte *) next_buf)
1892141cc406Sopenharmony_ci    {
1893141cc406Sopenharmony_ci
1894141cc406Sopenharmony_ci      DBG (127, "%s: reading additional directory buffer\n", f);
1895141cc406Sopenharmony_ci      if (read_data (Camera.fd, next_buf, 256) == -1)
1896141cc406Sopenharmony_ci	{
1897141cc406Sopenharmony_ci	  DBG (1, "%s: error: read_data returned -1\n", f);
1898141cc406Sopenharmony_ci	  return -1;
1899141cc406Sopenharmony_ci	}
1900141cc406Sopenharmony_ci      next_buf += 256;
1901141cc406Sopenharmony_ci    }
1902141cc406Sopenharmony_ci
1903141cc406Sopenharmony_ci  for (i = 0; i < entries; i++)
1904141cc406Sopenharmony_ci
1905141cc406Sopenharmony_ci    {
1906141cc406Sopenharmony_ci      /* Hack: I don't know what attr is used for, so setting it
1907141cc406Sopenharmony_ci       * to zero is a convenient way to put in the null terminator
1908141cc406Sopenharmony_ci       */
1909141cc406Sopenharmony_ci      get_attr (i) = 0;
1910141cc406Sopenharmony_ci      DBG (127, "%s: entry=%s\n", f, get_name (i));
1911141cc406Sopenharmony_ci
1912141cc406Sopenharmony_ci      if ((get_name (i))[0] == '.')
1913141cc406Sopenharmony_ci	{
1914141cc406Sopenharmony_ci	  continue;
1915141cc406Sopenharmony_ci	}
1916141cc406Sopenharmony_ci
1917141cc406Sopenharmony_ci      if (dir_insert
1918141cc406Sopenharmony_ci	  ((struct cam_dirent *) &dir_buf2[2 + CAMDIRENTRYSIZE * i]) != 0)
1919141cc406Sopenharmony_ci	{
1920141cc406Sopenharmony_ci	  DBG (1, "%s: error: failed to insert dir entry\n", f);
1921141cc406Sopenharmony_ci	  return -1;
1922141cc406Sopenharmony_ci	}
1923141cc406Sopenharmony_ci      retval++;
1924141cc406Sopenharmony_ci    }
1925141cc406Sopenharmony_ci
1926141cc406Sopenharmony_ci  if (end_of_data (Camera.fd) == -1)
1927141cc406Sopenharmony_ci    {
1928141cc406Sopenharmony_ci      DBG (1, "%s: error: end_of_data returned -1\n", f);
1929141cc406Sopenharmony_ci      return -1;
1930141cc406Sopenharmony_ci    }
1931141cc406Sopenharmony_ci
1932141cc406Sopenharmony_ci  return retval;
1933141cc406Sopenharmony_ci}
1934141cc406Sopenharmony_ci
1935141cc406Sopenharmony_ci/*
1936141cc406Sopenharmony_ci * read_info - read the info block from camera for the specified file
1937141cc406Sopenharmony_ci */
1938141cc406Sopenharmony_cistatic SANE_Int
1939141cc406Sopenharmony_ciread_info (SANE_String fname)
1940141cc406Sopenharmony_ci{
1941141cc406Sopenharmony_ci  SANE_Byte buf[256];
1942141cc406Sopenharmony_ci  SANE_Int i;
1943141cc406Sopenharmony_ci  SANE_Char f[] = "read_info";
1944141cc406Sopenharmony_ci  SANE_Char path[256];
1945141cc406Sopenharmony_ci
1946141cc406Sopenharmony_ci  strcpy (path, "\\PCCARD\\DCIM\\");
1947141cc406Sopenharmony_ci  strcat (path, (char *) folder_list[current_folder]);
1948141cc406Sopenharmony_ci  strcat (path, "\\");
1949141cc406Sopenharmony_ci  strcat (path, fname);
1950141cc406Sopenharmony_ci  path[strlen (path) - 3] = '\0';
1951141cc406Sopenharmony_ci  strcat (path, ".JPG");
1952141cc406Sopenharmony_ci
1953141cc406Sopenharmony_ci  if (send_pck (Camera.fd, pic_info_pck) == -1)
1954141cc406Sopenharmony_ci    {
1955141cc406Sopenharmony_ci      DBG (1, "%s: error: send_pck returned -1\n", f);
1956141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1957141cc406Sopenharmony_ci    }
1958141cc406Sopenharmony_ci
1959141cc406Sopenharmony_ci  buf[0] = 0x80;
1960141cc406Sopenharmony_ci  strcpy ((char *) &buf[1], path);
1961141cc406Sopenharmony_ci  for (i = 49; i <= 56; i++)
1962141cc406Sopenharmony_ci    {
1963141cc406Sopenharmony_ci      buf[i] = 0xff;
1964141cc406Sopenharmony_ci    }
1965141cc406Sopenharmony_ci
1966141cc406Sopenharmony_ci  if (send_data (buf) == -1)
1967141cc406Sopenharmony_ci    {
1968141cc406Sopenharmony_ci      DBG (1, "%s: error: send_data returned -1\n", f);
1969141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1970141cc406Sopenharmony_ci    }
1971141cc406Sopenharmony_ci
1972141cc406Sopenharmony_ci  if (read_data (Camera.fd, info_buf, 256) != 0)
1973141cc406Sopenharmony_ci    {
1974141cc406Sopenharmony_ci      DBG (1, "%s: error: Failed in read_data\n", f);
1975141cc406Sopenharmony_ci      return -1;
1976141cc406Sopenharmony_ci    }
1977141cc406Sopenharmony_ci
1978141cc406Sopenharmony_ci  DBG (9, "%s: data type=%d, cam type=%d, file type=%d\n", f,
1979141cc406Sopenharmony_ci       info_buf[0], info_buf[1], info_buf[2]);
1980141cc406Sopenharmony_ci
1981141cc406Sopenharmony_ci  if (end_of_data (Camera.fd) == -1)
1982141cc406Sopenharmony_ci    {
1983141cc406Sopenharmony_ci      DBG (1, "%s: error: end_of_data returned -1\n", f);
1984141cc406Sopenharmony_ci      return -1;
1985141cc406Sopenharmony_ci    }
1986141cc406Sopenharmony_ci
1987141cc406Sopenharmony_ci  return 0;
1988141cc406Sopenharmony_ci}
1989141cc406Sopenharmony_ci
1990141cc406Sopenharmony_ci
1991141cc406Sopenharmony_ci/*
1992141cc406Sopenharmony_ci * send_data - Send a data block - assumes all data blocks to camera
1993141cc406Sopenharmony_ci *		are 60 bytes long
1994141cc406Sopenharmony_ci */
1995141cc406Sopenharmony_ci
1996141cc406Sopenharmony_cistatic SANE_Int
1997141cc406Sopenharmony_cisend_data (SANE_Byte * buf)
1998141cc406Sopenharmony_ci{
1999141cc406Sopenharmony_ci  SANE_Byte r = 0xf0;		/* prime the loop with a "camera busy" */
2000141cc406Sopenharmony_ci  SANE_Int i, n;
2001141cc406Sopenharmony_ci  SANE_Byte csum;
2002141cc406Sopenharmony_ci  SANE_Char f[] = "send_data";
2003141cc406Sopenharmony_ci
2004141cc406Sopenharmony_ci  for (i = 1, csum = 0; i < 59; i++)
2005141cc406Sopenharmony_ci    {
2006141cc406Sopenharmony_ci      csum ^= buf[i];
2007141cc406Sopenharmony_ci    }
2008141cc406Sopenharmony_ci  buf[59] = csum;
2009141cc406Sopenharmony_ci  DBG (127, "%s: about to send data block\n", f);
2010141cc406Sopenharmony_ci
2011141cc406Sopenharmony_ci  /* keep trying if camera says it's busy */
2012141cc406Sopenharmony_ci  while (r == 0xf0)
2013141cc406Sopenharmony_ci    {
2014141cc406Sopenharmony_ci      if (write (Camera.fd, (char *) buf, 60) != 60)
2015141cc406Sopenharmony_ci	{
2016141cc406Sopenharmony_ci	  DBG (1, "%s: error: write returned -1\n", f);
2017141cc406Sopenharmony_ci	  return -1;
2018141cc406Sopenharmony_ci	}
2019141cc406Sopenharmony_ci
2020141cc406Sopenharmony_ci      /* need to wait before we read command result */
2021141cc406Sopenharmony_ci#ifdef HAVE_USLEEP
2022141cc406Sopenharmony_ci      usleep (cmdrespause);
2023141cc406Sopenharmony_ci#else
2024141cc406Sopenharmony_ci      sleep (1);
2025141cc406Sopenharmony_ci#endif
2026141cc406Sopenharmony_ci
2027141cc406Sopenharmony_ci      if ((n = read (Camera.fd, (char *) &r, 1)) != 1)
2028141cc406Sopenharmony_ci	{
2029141cc406Sopenharmony_ci	  DBG (1, "%s: error: read returned -1\n", f);
2030141cc406Sopenharmony_ci	  return -1;
2031141cc406Sopenharmony_ci	}
2032141cc406Sopenharmony_ci    }
2033141cc406Sopenharmony_ci
2034141cc406Sopenharmony_ci  if (r != 0xd2)
2035141cc406Sopenharmony_ci    {
2036141cc406Sopenharmony_ci      DBG (1, "%s: error: bad response to send_data (%d)\n", f, r);
2037141cc406Sopenharmony_ci      return -1;
2038141cc406Sopenharmony_ci    }
2039141cc406Sopenharmony_ci
2040141cc406Sopenharmony_ci  return 0;
2041141cc406Sopenharmony_ci}
2042141cc406Sopenharmony_ci
2043141cc406Sopenharmony_ci/*
2044141cc406Sopenharmony_ci * dir_insert - Add (in alphabetical order) a directory entry to the
2045141cc406Sopenharmony_ci * 		current list of entries.
2046141cc406Sopenharmony_ci */
2047141cc406Sopenharmony_cistatic SANE_Int
2048141cc406Sopenharmony_cidir_insert (struct cam_dirent *entry)
2049141cc406Sopenharmony_ci{
2050141cc406Sopenharmony_ci  struct cam_dirlist *cur, *e;
2051141cc406Sopenharmony_ci
2052141cc406Sopenharmony_ci  cur = (struct cam_dirlist *) malloc (sizeof (struct cam_dirlist));
2053141cc406Sopenharmony_ci  if (cur == NULL)
2054141cc406Sopenharmony_ci    {
2055141cc406Sopenharmony_ci      DBG (1, "dir_insert: error: could not malloc entry\n");
2056141cc406Sopenharmony_ci      return -1;
2057141cc406Sopenharmony_ci    }
2058141cc406Sopenharmony_ci
2059141cc406Sopenharmony_ci  strcpy (cur->name, entry->name);
2060141cc406Sopenharmony_ci  DBG (127, "dir_insert: name is %s\n", cur->name);
2061141cc406Sopenharmony_ci
2062141cc406Sopenharmony_ci  cur->next = NULL;
2063141cc406Sopenharmony_ci
2064141cc406Sopenharmony_ci  if (dir_head == NULL)
2065141cc406Sopenharmony_ci    {
2066141cc406Sopenharmony_ci      dir_head = cur;
2067141cc406Sopenharmony_ci    }
2068141cc406Sopenharmony_ci  else if (strcmp (cur->name, dir_head->name) < 0)
2069141cc406Sopenharmony_ci    {
2070141cc406Sopenharmony_ci      cur->next = dir_head;
2071141cc406Sopenharmony_ci      dir_head = cur;
2072141cc406Sopenharmony_ci      return 0;
2073141cc406Sopenharmony_ci    }
2074141cc406Sopenharmony_ci  else
2075141cc406Sopenharmony_ci    {
2076141cc406Sopenharmony_ci      for (e = dir_head; e->next; e = e->next)
2077141cc406Sopenharmony_ci	{
2078141cc406Sopenharmony_ci	  if (strcmp (e->next->name, cur->name) > 0)
2079141cc406Sopenharmony_ci	    {
2080141cc406Sopenharmony_ci	      cur->next = e->next;
2081141cc406Sopenharmony_ci	      e->next = cur;
2082141cc406Sopenharmony_ci	      return 0;
2083141cc406Sopenharmony_ci	    }
2084141cc406Sopenharmony_ci	}
2085141cc406Sopenharmony_ci      e->next = cur;
2086141cc406Sopenharmony_ci    }
2087141cc406Sopenharmony_ci  return 0;
2088141cc406Sopenharmony_ci}
2089141cc406Sopenharmony_ci
2090141cc406Sopenharmony_ci/*
2091141cc406Sopenharmony_ci *  dir_delete - Delete a directory entry from the linked list of file
2092141cc406Sopenharmony_ci * 		names
2093141cc406Sopenharmony_ci */
2094141cc406Sopenharmony_cistatic SANE_Int
2095141cc406Sopenharmony_cidir_delete (SANE_String fname)
2096141cc406Sopenharmony_ci{
2097141cc406Sopenharmony_ci  struct cam_dirlist *cur, *e;
2098141cc406Sopenharmony_ci
2099141cc406Sopenharmony_ci  DBG (127, "dir_delete:  %s\n", fname);
2100141cc406Sopenharmony_ci
2101141cc406Sopenharmony_ci  if (strcmp (fname, dir_head->name) == 0)
2102141cc406Sopenharmony_ci    {
2103141cc406Sopenharmony_ci      cur = dir_head;
2104141cc406Sopenharmony_ci      dir_head = dir_head->next;
2105141cc406Sopenharmony_ci      free (cur);
2106141cc406Sopenharmony_ci      return 0;
2107141cc406Sopenharmony_ci    }
2108141cc406Sopenharmony_ci
2109141cc406Sopenharmony_ci  for (e = dir_head; e->next; e = e->next)
2110141cc406Sopenharmony_ci    {
2111141cc406Sopenharmony_ci      if (strcmp (fname, e->next->name) == 0)
2112141cc406Sopenharmony_ci	{
2113141cc406Sopenharmony_ci	  cur = e->next;
2114141cc406Sopenharmony_ci	  e->next = e->next->next;
2115141cc406Sopenharmony_ci	  free (cur);
2116141cc406Sopenharmony_ci	  return (0);
2117141cc406Sopenharmony_ci	}
2118141cc406Sopenharmony_ci    }
2119141cc406Sopenharmony_ci  DBG (1, "dir_delete: Couldn't find entry %s in dir list\n", fname);
2120141cc406Sopenharmony_ci  return -1;
2121141cc406Sopenharmony_ci}
2122141cc406Sopenharmony_ci
2123141cc406Sopenharmony_ci/*
2124141cc406Sopenharmony_ci *  set_res - set picture size depending on resolution settings
2125141cc406Sopenharmony_ci */
2126141cc406Sopenharmony_cistatic void
2127141cc406Sopenharmony_ciset_res (SANE_Int lowres)
2128141cc406Sopenharmony_ci{
2129141cc406Sopenharmony_ci  if (dc240_opt_thumbnails)
2130141cc406Sopenharmony_ci    {
2131141cc406Sopenharmony_ci      parms.bytes_per_line = 160 * 3;
2132141cc406Sopenharmony_ci      parms.pixels_per_line = 160;
2133141cc406Sopenharmony_ci      parms.lines = 120;
2134141cc406Sopenharmony_ci    }
2135141cc406Sopenharmony_ci  else if (lowres)
2136141cc406Sopenharmony_ci    {
2137141cc406Sopenharmony_ci      parms.bytes_per_line = LOWRES_WIDTH * 3;
2138141cc406Sopenharmony_ci      parms.pixels_per_line = LOWRES_WIDTH;
2139141cc406Sopenharmony_ci      parms.lines = LOWRES_HEIGHT;
2140141cc406Sopenharmony_ci    }
2141141cc406Sopenharmony_ci  else
2142141cc406Sopenharmony_ci    {
2143141cc406Sopenharmony_ci      parms.bytes_per_line = HIGHRES_WIDTH * 3;
2144141cc406Sopenharmony_ci      parms.pixels_per_line = HIGHRES_WIDTH;
2145141cc406Sopenharmony_ci      parms.lines = HIGHRES_HEIGHT;
2146141cc406Sopenharmony_ci    }
2147141cc406Sopenharmony_ci}
2148