1 /***************************************************************************
2  * SANE - Scanner Access Now Easy.
3 
4    dc210.c
5 
6    11/11/98
7 
8    This file (C) 1998 Brian J. Murrell
9 
10    This file is part of the SANE package.
11 
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of the
15    License, or (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful, but
18    WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <https://www.gnu.org/licenses/>.
24 
25    As a special exception, the authors of SANE give permission for
26    additional uses of the libraries contained in this release of SANE.
27 
28    The exception is that, if you link a SANE library with other files
29    to produce an executable, this does not by itself cause the
30    resulting executable to be covered by the GNU General Public
31    License.  Your use of that executable is in no way restricted on
32    account of linking the SANE library code into it.
33 
34    This exception does not, however, invalidate any other reasons why
35    the executable file might be covered by the GNU General Public
36    License.
37 
38    If you submit changes to SANE to the maintainers to be included in
39    a subsequent release, you agree by submitting the changes that
40    those changes may be distributed with this exception intact.
41 
42    If you write modifications of your own for SANE, it is your choice
43    whether to permit this exception to apply to your modifications.
44    If you do not wish that, delete this exception notice.
45 
46  ***************************************************************************
47 
48    This file implements a SANE backend for the Kodak DC-210
49    digital camera.  THIS IS EXTREMELY ALPHA CODE!  USE AT YOUR OWN RISK!!
50 
51    (feedback to:  sane-dc210@interlinx.bc.ca
52 
53    This backend is based somewhat on the dc25 backend included in this
54    package by Peter Fales
55 
56  ***************************************************************************/
57 
58 #include "../include/sane/config.h"
59 
60 #include <stdlib.h>
61 #include <string.h>
62 #include <stdio.h>
63 #include <unistd.h>
64 #include <fcntl.h>
65 #include <limits.h>
66 #include "../include/sane/sanei_jpeg.h"
67 #include <sys/ioctl.h>
68 
69 #include "../include/sane/sane.h"
70 #include "../include/sane/sanei.h"
71 #include "../include/sane/saneopts.h"
72 
73 #define BACKEND_NAME	dc210
74 #include "../include/sane/sanei_backend.h"
75 
76 #include "dc210.h"
77 
78 #ifndef PATH_MAX
79 # define PATH_MAX	1024
80 #endif
81 
82 #define MAGIC			(void *)0xab730324
83 #define DC210_CONFIG_FILE 	"dc210.conf"
84 #define THUMBSIZE		20736
85 
86 #ifdef B115200
87 # define DEFAULT_BAUD_RATE	B115200
88 #else
89 # define DEFAULT_BAUD_RATE	B38400
90 #endif
91 
92 #if defined (__sgi)
93 # define DEFAULT_TTY		"/dev/ttyd1"	/* Irix */
94 #elif defined (__sun)
95 # define DEFAULT_TTY		"/dev/term/a"	/* Solaris */
96 #elif defined (hpux)
97 # define DEFAULT_TTY		"/dev/tty1d0"	/* HP-UX */
98 #elif defined (__osf__)
99 # define DEFAULT_TTY		"/dev/tty00"	/* Digital UNIX */
100 #else
101 # define DEFAULT_TTY		"/dev/ttyS0"	/* Linux */
102 #endif
103 
104 static SANE_Bool is_open = 0;
105 
106 static SANE_Bool dc210_opt_thumbnails;
107 static SANE_Bool dc210_opt_snap;
108 static SANE_Bool dc210_opt_lowres;
109 static SANE_Bool dc210_opt_erase;
110 static SANE_Bool dumpinquiry;
111 
112 static struct jpeg_decompress_struct cinfo;
113 static djpeg_dest_ptr dest_mgr = NULL;
114 
115 static unsigned long cmdrespause = 250000UL;	/* pause after sending cmd */
116 static unsigned long breakpause = 1000000UL;	/* pause after sending break */
117 
118 static int bytes_in_buffer;
119 static int bytes_read_from_buffer;
120 static int total_bytes_read;
121 
122 static DC210 Camera;
123 
124 static SANE_Range image_range = {
125   0,
126   14,
127   0
128 };
129 
130 static SANE_Option_Descriptor sod[] = {
131   {
132    SANE_NAME_NUM_OPTIONS,
133    SANE_TITLE_NUM_OPTIONS,
134    SANE_DESC_NUM_OPTIONS,
135    SANE_TYPE_INT,
136    SANE_UNIT_NONE,
137    sizeof (SANE_Word),
138    SANE_CAP_SOFT_DETECT,
139    SANE_CONSTRAINT_NONE,
140    {NULL}
141    }
142   ,
143 
144 #define D25_OPT_IMAGE_SELECTION 1
145   {
146    "",
147    "Image Selection",
148    "Selection of the image to load.",
149    SANE_TYPE_GROUP,
150    SANE_UNIT_NONE,
151    0,
152    0,
153    SANE_CONSTRAINT_NONE,
154    {NULL}
155    }
156   ,
157 
158 #define DC210_OPT_IMAGE_NUMBER 2
159   {
160    "image",
161    "Image Number",
162    "Select Image Number to load from camera",
163    SANE_TYPE_INT,
164    SANE_UNIT_NONE,
165    4,
166    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
167    SANE_CONSTRAINT_RANGE,
168    {(void *) & image_range}
169    }
170   ,
171 
172 #define DC210_OPT_THUMBS 3
173   {
174    "thumbs",
175    "Load Thumbnail",
176    "Load the image as thumbnail.",
177    SANE_TYPE_BOOL,
178    SANE_UNIT_NONE,
179    sizeof (SANE_Word),
180    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
181    SANE_CONSTRAINT_NONE,
182    {NULL}
183    }
184   ,
185 #define DC210_OPT_SNAP 4
186   {
187    "snap",
188    "Snap new picture",
189    "Take new picture and download it",
190    SANE_TYPE_BOOL,
191    SANE_UNIT_NONE,
192    sizeof (SANE_Word),
193    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ ,
194    SANE_CONSTRAINT_NONE,
195    {NULL}
196    }
197   ,
198 #define DC210_OPT_LOWRES 5
199   {
200    "lowres",
201    "Low Resolution",
202    "Resolution of new pictures",
203    SANE_TYPE_BOOL,
204    SANE_UNIT_NONE,
205    sizeof (SANE_Word),
206    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE
207    /* | SANE_CAP_ADVANCED */ ,
208    SANE_CONSTRAINT_NONE,
209    {NULL}
210    }
211   ,
212 
213 #define DC210_OPT_ERASE 6
214   {
215    "erase",
216    "Erase",
217    "Erase the picture after downloading",
218    SANE_TYPE_BOOL,
219    SANE_UNIT_NONE,
220    sizeof (SANE_Word),
221    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
222    SANE_CONSTRAINT_NONE,
223    {NULL}
224    }
225   ,
226 
227 #define DC210_OPT_DEFAULT 7
228   {
229    "default-enhancements",
230    "Defaults",
231    "Set default values for enhancement controls.",
232    SANE_TYPE_BUTTON,
233    SANE_UNIT_NONE,
234    0,
235    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
236    SANE_CONSTRAINT_NONE,
237    {NULL}
238    }
239   ,
240 #define DC210_OPT_INIT_DC210 8
241   {
242    "camera-init",
243    "Re-establish Communications",
244    "Re-establish communications with camera (in case of timeout, etc.)",
245    SANE_TYPE_BUTTON,
246    SANE_UNIT_NONE,
247    0,
248    SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
249    SANE_CONSTRAINT_NONE,
250    {NULL}
251    }
252 };
253 
254 static SANE_Parameters parms = {
255   SANE_FRAME_RGB,
256   0,
257   0,				/* Number of bytes returned per scan line: */
258   0,				/* Number of pixels per scan line.  */
259   0,				/* Number of lines for the current scan.  */
260   8,				/* Number of bits per sample. */
261 };
262 
263 
264 
265 
266 static unsigned char shoot_pck[] = SHOOT_PCK;
267 static unsigned char init_pck[] = INIT_PCK;
268 static unsigned char thumb_pck[] = THUMBS_PCK;
269 static unsigned char pic_pck[] = PICS_PCK;
270 static unsigned char pic_info_pck[] = PICS_INFO_PCK;
271 static unsigned char info_pck[] = INFO_PCK;
272 static unsigned char erase_pck[] = ERASE_PCK;
273 static unsigned char res_pck[] = RES_PCK;
274 
275 static struct pkt_speed speeds[] = SPEEDS;
276 static struct termios tty_orig;
277 
278 #include <sys/time.h>
279 #include <unistd.h>
280 
281 static int
send_pck(int fd, unsigned char *pck)282 send_pck (int fd, unsigned char *pck)
283 {
284   int n;
285   unsigned char r = 0xf0;	/* prime the loop with a "camera busy" */
286 
287   /* keep trying if camera says it's busy */
288   while (r == 0xf0)
289     {
290       /*
291          * Not quite sure why we need this, but the program works a whole
292          * lot better (at least on the DC210)  with this short delay.
293        */
294 
295       if (write (fd, (char *) pck, 8) != 8)
296 	{
297 	  DBG (2, "send_pck: error: write returned -1\n");
298 	  return -1;
299 	}
300       /* need to wait before we read command result */
301       usleep (cmdrespause);
302 
303       if ((n = read (fd, (char *) &r, 1)) != 1)
304 	{
305 	  DBG (2, "send_pck: error: read returned -1\n");
306 	  return -1;
307 	}
308     }
309   return (r == 0xd1) ? 0 : -1;
310 }
311 
312 static int
init_dc210(DC210 * camera)313 init_dc210 (DC210 * camera)
314 {
315   struct termios tty_new;
316   int speed_index;
317 
318   for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++)
319     {
320       if (speeds[speed_index].baud == camera->baud)
321 	{
322 	  init_pck[2] = speeds[speed_index].pkt_code[0];
323 	  init_pck[3] = speeds[speed_index].pkt_code[1];
324 	  break;
325 	}
326     }
327 
328   if (init_pck[2] == 0)
329     {
330       DBG (2, "unsupported baud rate.\n");
331       return -1;
332     }
333 
334   /*
335      Open device file.
336    */
337   if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1)
338     {
339       DBG (2, "init_dc210: error: could not open %s for read/write\n",
340 	   camera->tty_name);
341       return -1;
342     }
343   /*
344      Save old device information to restore when we are done.
345    */
346   if (tcgetattr (camera->fd, &tty_orig) == -1)
347     {
348       DBG (2, "init_dc210: error: could not get attributes\n");
349       return -1;
350     }
351 
352   memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios));
353   /*
354      We need the device to be raw. 8 bits even parity on 9600 baud to start.
355    */
356 #ifdef HAVE_CFMAKERAW
357   cfmakeraw (&tty_new);
358 #else
359   /* Modified to set the port REALLY as required. Code inspired by
360      the gPhoto2 serial port setup */
361 
362   /* input control settings */
363   tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC |
364                       IXANY | IXON | IXOFF | INPCK | ISTRIP);
365   tty_new.c_iflag |= (BRKINT | IGNPAR);
366   /* output control settings */
367   tty_new.c_oflag &= ~OPOST;
368   /* hardware control settings */
369   tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8;
370   tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB);
371 # if defined(__sgi)
372   tty_new.c_cflag &= ~CNEW_RTSCTS;
373 # else
374 /* OS/2 doesn't have CRTSCTS - will this work for them? */
375 #  ifdef CRTSCTS
376   tty_new.c_cflag &= ~CRTSCTS;
377 #  endif
378 # endif
379   tty_new.c_cflag |= CLOCAL | CREAD;
380 #endif
381   /* line discipline settings */
382   tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE |
383                        ECHOK | IEXTEN);
384   tty_new.c_cc[VMIN] = 0;
385   tty_new.c_cc[VTIME] = 5;
386   cfsetospeed (&tty_new, B9600);
387   cfsetispeed (&tty_new, B9600);
388 
389   if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
390     {
391       DBG (2, "init_dc210: error: could not set attributes\n");
392       return -1;
393     }
394 
395   /* send a break to get it back to a known state */
396   /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK,
397    * and TCSBRKP, but that is system dependent.  e.g. on irix a non-zero
398    * value does a drain instead of a break.  A zero value is universally
399    * used to send a break.
400    */
401 
402 #ifdef HAVE_TCSENDBREAK
403   tcsendbreak (camera->fd, 0);
404 # if defined(__sgi)
405   tcdrain (camera->fd);
406 # endif
407 # elif defined(TCSBRKP)
408   ioctl (camera->fd, TCSBRKP, 0);
409 # elif defined(TCSBRK)
410   ioctl (camera->fd, TCSBRK, 0);
411 #endif
412 
413    /* and wait for it to recover from the break */
414 
415 #ifdef HAVE_USLEEP
416   usleep (breakpause);
417 #else
418   sleep (1);
419 #endif
420 
421   if (send_pck (camera->fd, init_pck) == -1)
422     {
423       /*
424        *    The camera always powers up at 9600, so we try
425        *      that first.  However, it may be already set to
426        *      a different speed.  Try the entries in the table:
427        */
428 
429       for (speed_index = NELEMS (speeds) - 1; speed_index > 0; speed_index--)
430 	{
431 	  int x;
432 	  DBG (3, "init_dc210: changing speed to %d\n",
433 	       (int) speeds[speed_index].baud);
434 
435 	  cfsetospeed (&tty_new, speeds[speed_index].baud);
436 	  cfsetispeed (&tty_new, speeds[speed_index].baud);
437 
438 	  if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
439 	    {
440 	      DBG (2, "init_dc210: error: could not set attributes\n");
441 	      return -1;
442 	    }
443 	  for (x = 0; x < 3; x++)
444 	    if (send_pck (camera->fd, init_pck) != -1)
445 	      break;
446 	}
447 
448       if (speed_index == 0)
449 	{
450 	  tcsetattr (camera->fd, TCSANOW, &tty_orig);
451 	  DBG (2, "init_dc210: error: no suitable baud rate\n");
452 	  return -1;
453 	}
454     }
455   /*
456      Set speed to requested speed.
457    */
458   cfsetospeed (&tty_new, Camera.baud);
459   cfsetispeed (&tty_new, Camera.baud);
460 
461   if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1)
462     {
463       DBG (2, "init_dc210: error: could not set attributes\n");
464       return -1;
465     }
466 
467   return camera->fd;
468 }
469 
470 static void
close_dc210(int fd)471 close_dc210 (int fd)
472 {
473   /*
474    *    Put the camera back to 9600 baud
475    */
476 
477   if (close (fd) == -1)
478     {
479       DBG (4, "close_dc210: error: could not close device\n");
480     }
481 }
482 
483 int
get_info(DC210 * camera)484 get_info (DC210 * camera)
485 {
486 
487   char f[] = "get_info";
488   unsigned char buf[256];
489 
490   if (send_pck (camera->fd, info_pck) == -1)
491     {
492       DBG (2, "%s: error: send_pck returned -1\n", f);
493       return -1;
494     }
495 
496   DBG (9, "%s: read info packet\n", f);
497 
498   if (read_data (camera->fd, buf, 256) == -1)
499     {
500       DBG (2, "%s: error: read_data returned -1\n", f);
501       return -1;
502     }
503 
504   if (end_of_data (camera->fd) == -1)
505     {
506       DBG (2, "%s: error: end_of_data returned -1\n", f);
507       return -1;
508     }
509 
510   camera->model = buf[1];
511   camera->ver_major = buf[2];
512   camera->ver_minor = buf[3];
513   camera->pic_taken = buf[56] << 8 | buf[57];
514   camera->pic_left = buf[72] << 8 | buf[73];
515   camera->flags.low_res = buf[22];
516   camera->flags.low_batt = buf[8];
517 
518   return 0;
519 }
520 
521 static int
read_data(int fd, unsigned char *buf, int sz)522 read_data (int fd, unsigned char *buf, int sz)
523 {
524   unsigned char ccsum;
525   unsigned char rcsum;
526   unsigned char c;
527   int n;
528   int r = 0;
529   int i;
530 
531 /* read the control byte */
532   if (read (fd, &c, 1) != 1)
533     {
534       DBG (2,
535 	   "read_data: error: read for packet control byte returned bad status\n");
536       return -1;
537     }
538   if (c != 1)
539     {
540       DBG (2, "read_data: error: incorrect packet control byte: %02x\n", c);
541       return -1;
542     }
543   for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; n += r)
544     ;
545 
546   if (r <= 0)
547     {
548       DBG (2, "read_data: error: read returned -1\n");
549       return -1;
550     }
551 
552   if (n < sz || read (fd, &rcsum, 1) != 1)
553     {
554       DBG (2, "read_data: error: buffer underrun or no checksum\n");
555       return -1;
556     }
557 
558   for (i = 0, ccsum = 0; i < n; i++)
559     ccsum ^= buf[i];
560 
561   if (ccsum != rcsum)
562     {
563       DBG (2, "read_data: error: bad checksum (%02x !=%02x)\n", rcsum, ccsum);
564       return -1;
565     }
566 
567   c = 0xd2;
568 
569   if (write (fd, (char *) &c, 1) != 1)
570     {
571       DBG (2, "read_data: error: write ack\n");
572       return -1;
573     }
574 
575   return 0;
576 }
577 
578 static int
end_of_data(int fd)579 end_of_data (int fd)
580 {
581   unsigned char c;
582 
583   do
584     {				/* loop until the camera isn't busy */
585       if (read (fd, &c, 1) != 1)
586 	{
587 	  DBG (2, "end_of_data: error: read returned -1\n");
588 	  return -1;
589 	}
590       if (c == 0)		/* got successful end of data */
591 	return 0;		/* return success */
592       sleep (1);		/* not too fast */
593     }
594   while (c == 0xf0);
595 
596   /* Accck!  Not busy, but not a good end of data either */
597   if (c != 0)
598     {
599       DBG (2, "end_of_data: error: bad EOD from camera (%02x)\n",
600 	   (unsigned) c);
601       return -1;
602     }
603   return 0;			/* should never get here but shut gcc -Wall up */
604 }
605 
606 static int
erase(int fd)607 erase (int fd)
608 {
609   if (send_pck (fd, erase_pck) == -1)
610     {
611       DBG (3, "erase: error: send_pck returned -1\n");
612       return -1;
613     }
614 
615   if (end_of_data (fd) == -1)
616     {
617       DBG (3, "erase: error: end_of_data returned -1\n");
618       return -1;
619     }
620 
621   return 0;
622 }
623 
624 static int
change_res(int fd, unsigned char res)625 change_res (int fd, unsigned char res)
626 {
627   char f[] = "change_res";
628 
629   DBG (127, "%s called\n", f);
630   if (res != 0 && res != 1)
631     {
632       DBG (3, "%s: error: unsupported resolution\n", f);
633       return -1;
634     }
635 
636   /* cameras resolution semantics are opposite of ours */
637   res = !res;
638   DBG (127, "%s: setting res to %d\n", f, res);
639   res_pck[2] = res;
640 
641   if (send_pck (fd, res_pck) == -1)
642     {
643       DBG (4, "%s: error: send_pck returned -1\n", f);
644     }
645 
646   if (end_of_data (fd) == -1)
647     {
648       DBG (4, "%s: error: end_of_data returned -1\n", f);
649     }
650   return 0;
651 }
652 
653 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize)654 sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize)
655 {
656 
657   char f[] = "sane_init";
658   char dev_name[PATH_MAX], *p;
659   size_t len;
660   FILE *fp;
661   int baud;
662 
663   DBG_INIT ();
664 
665   if (version_code)
666     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
667 
668   fp = sanei_config_open (DC210_CONFIG_FILE);
669 
670   /* defaults */
671   Camera.baud = DEFAULT_BAUD_RATE;
672   Camera.tty_name = DEFAULT_TTY;
673 
674   if (!fp)
675     {
676       /* default to /dev/whatever instead of insisting on config file */
677       DBG (1, "%s:  missing config file '%s'\n", f, DC210_CONFIG_FILE);
678     }
679   else
680     {
681       while (sanei_config_read (dev_name, sizeof (dev_name), fp))
682 	{
683 	  dev_name[sizeof (dev_name) - 1] = '\0';
684 	  DBG (20, "%s:  config- %s\n", f, dev_name);
685 
686 	  if (dev_name[0] == '#')
687 	    continue;		/* ignore line comments */
688 	  len = strlen (dev_name);
689 	  if (!len)
690 	    continue;		/* ignore empty lines */
691 	  if (strncmp (dev_name, "port=", 5) == 0)
692 	    {
693 	      p = strchr (dev_name, '/');
694 	      if (p)
695 		Camera.tty_name = strdup (p);
696 	      DBG (20, "Config file port=%s\n", Camera.tty_name);
697 	    }
698 	  else if (strncmp (dev_name, "baud=", 5) == 0)
699 	    {
700 	      baud = atoi (&dev_name[5]);
701 	      switch (baud)
702 		{
703 		case 9600:
704 		  Camera.baud = B9600;
705 		  break;
706 		case 19200:
707 		  Camera.baud = B19200;
708 		  break;
709 		case 38400:
710 		  Camera.baud = B38400;
711 		  break;
712 #ifdef B57600
713 		case 57600:
714 		  Camera.baud = B57600;
715 		  break;
716 #endif
717 #ifdef B115200
718 		case 115200:
719 		  Camera.baud = B115200;
720 		  break;
721 #endif
722 		}
723 	      DBG (20, "Config file baud=%d\n", Camera.baud);
724 	    }
725 	  else if (strcmp (dev_name, "dumpinquiry") == 0)
726 	    {
727 	      dumpinquiry = SANE_TRUE;
728 	    }
729 	  else if (strncmp (dev_name, "cmdrespause=", 12) == 0)
730 	    {
731 	      cmdrespause = atoi (&dev_name[12]);
732 	      DBG (20, "Config file cmdrespause=%lu\n", cmdrespause);
733 	    }
734 	  else if (strncmp (dev_name, "breakpause=", 11) == 0)
735 	    {
736 	      breakpause = atoi (&dev_name[11]);
737 	      DBG (20, "Config file breakpause=%lu\n", breakpause);
738 	    }
739 	}
740       fclose (fp);
741     }
742 
743   if (init_dc210 (&Camera) == -1)
744     return SANE_STATUS_INVAL;
745 
746   if (get_info (&Camera) == -1)
747     {
748       DBG (2, "error: could not get info\n");
749       close_dc210 (Camera.fd);
750       return SANE_STATUS_INVAL;
751     }
752   if (Camera.pic_taken == 0)
753     {
754       sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
755       image_range.min = 0;
756       image_range.max = 0;
757     }
758   else
759     {
760       sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
761       image_range.min = 1;
762       image_range.max = Camera.pic_taken;
763     }
764 
765 
766   /* load the current images array */
767   Camera.Pictures = get_pictures_info ();
768 
769   if (Camera.pic_taken == 0)
770     {
771       Camera.current_picture_number = 0;
772       parms.bytes_per_line = 0;
773       parms.pixels_per_line = 0;
774       parms.lines = 0;
775     }
776   else
777     {
778       Camera.current_picture_number = 1;
779       if (Camera.Pictures[Camera.current_picture_number - 1].low_res)
780 	{
781 	  parms.bytes_per_line = 640 * 3;
782 	  parms.pixels_per_line = 640;
783 	  parms.lines = 480;
784 	}
785       else
786 	{
787 	  parms.bytes_per_line = 1152 * 3;
788 	  parms.pixels_per_line = 1152;
789 	  parms.lines = 864;
790 	}
791     }
792 
793   if (dumpinquiry)
794     {
795       DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n");
796       DBG (0, "Model...........: DC%x\n", Camera.model);
797       DBG (0, "Firmware version: %d.%d\n", Camera.ver_major,
798 	   Camera.ver_minor);
799       DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken,
800 	   Camera.pic_taken + Camera.pic_left);
801       DBG (0, "Resolution......: %s\n",
802 	   Camera.flags.low_res ? "low" : "high");
803       DBG (0, "Battery state...: %s\n",
804 	   Camera.flags.low_batt ? "low" : "good");
805     }
806 
807   return SANE_STATUS_GOOD;
808 }
809 
810 void
sane_exit(void)811 sane_exit (void)
812 {
813 }
814 
815 /* Device select/open/close */
816 
817 static const SANE_Device dev[] = {
818   {
819    "0",
820    "Kodak",
821    "DC-210",
822    "still camera"},
823 };
824 
825 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only)826 sane_get_devices (const SANE_Device *** device_list,
827 		  SANE_Bool __sane_unused__ local_only)
828 {
829   static const SANE_Device *devlist[] = {
830     dev + 0, 0
831   };
832 
833   DBG (127, "sane_get_devices called\n");
834 
835   *device_list = devlist;
836   return SANE_STATUS_GOOD;
837 }
838 
839 SANE_Status
sane_open(SANE_String_Const devicename, SANE_Handle * handle)840 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
841 {
842   int i;
843 
844   DBG (127, "sane_open for device %s\n", devicename);
845   if (!devicename[0])
846     {
847       i = 0;
848     }
849   else
850     {
851       for (i = 0; i < NELEMS (dev); ++i)
852 	{
853 	  if (strcmp (devicename, dev[i].name) == 0)
854 	    {
855 	      break;
856 	    }
857 	}
858     }
859 
860   if (i >= NELEMS (dev))
861     {
862       return SANE_STATUS_INVAL;
863     }
864 
865   if (is_open)
866     {
867       return SANE_STATUS_DEVICE_BUSY;
868     }
869 
870   is_open = 1;
871   *handle = MAGIC;
872 
873   DBG (3, "sane_open: pictures taken=%d\n", Camera.pic_taken);
874 
875   return SANE_STATUS_GOOD;
876 }
877 
878 void
sane_close(SANE_Handle handle)879 sane_close (SANE_Handle handle)
880 {
881   DBG (127, "sane_close called\n");
882   if (handle == MAGIC)
883     is_open = 0;
884 
885   DBG (127, "sane_close returning\n");
886 }
887 
888 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)889 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
890 {
891   if (handle != MAGIC || !is_open)
892     return NULL;		/* wrong device */
893   if (option < 0 || option >= NELEMS (sod))
894     return NULL;
895   return &sod[option];
896 }
897 
898 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info)899 sane_control_option (SANE_Handle handle, SANE_Int option,
900 		     SANE_Action action, void *value, SANE_Int * info)
901 {
902   SANE_Int myinfo = 0;
903   SANE_Status status;
904 
905   DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n",
906        handle, sod[option].title,
907        (action ==
908 	SANE_ACTION_SET_VALUE ? "SET" : (action ==
909 					 SANE_ACTION_GET_VALUE ? "GET" :
910 					 "SETAUTO")), value, (void *)info);
911 
912   if (handle != MAGIC || !is_open)
913     return SANE_STATUS_INVAL;	/* Unknown handle ... */
914 
915   if (option < 0 || option >= NELEMS (sod))
916     return SANE_STATUS_INVAL;	/* Unknown option ... */
917 
918   switch (action)
919     {
920     case SANE_ACTION_SET_VALUE:
921       status = sanei_constrain_value (sod + option, value, &myinfo);
922       if (status != SANE_STATUS_GOOD)
923 	{
924 	  DBG (1, "Constraint error in control_option\n");
925 	  return status;
926 	}
927 
928       switch (option)
929 	{
930 	case DC210_OPT_IMAGE_NUMBER:
931 	  Camera.current_picture_number = *(SANE_Word *) value;
932 	  myinfo |= SANE_INFO_RELOAD_PARAMS;
933 	  /* get the image's resolution */
934 
935 	  if (Camera.Pictures[Camera.current_picture_number - 1].low_res)
936 	    {
937 	      parms.bytes_per_line = 640 * 3;
938 	      parms.pixels_per_line = 640;
939 	      parms.lines = 480;
940 	    }
941 	  else
942 	    {
943 	      parms.bytes_per_line = 1152 * 3;
944 	      parms.pixels_per_line = 1152;
945 	      parms.lines = 864;
946 	    }
947 	  break;
948 
949 	case DC210_OPT_THUMBS:
950 	  dc210_opt_thumbnails = !!*(SANE_Word *) value;
951 	  myinfo |= SANE_INFO_RELOAD_PARAMS;
952 
953 	  if (dc210_opt_thumbnails)
954 	    {
955 	      /*
956 	       * DC210 thumbnail are 96x72x8x3
957 	       */
958 	      parms.bytes_per_line = 96 * 3;
959 	      parms.pixels_per_line = 96;
960 	      parms.lines = 72;
961 	    }
962 	  else
963 	    {
964 	      if (Camera.Pictures[Camera.current_picture_number - 1].low_res)
965 		{
966 		  parms.bytes_per_line = 640 * 3;
967 		  parms.pixels_per_line = 640;
968 		  parms.lines = 480;
969 		}
970 	      else
971 		{
972 		  parms.bytes_per_line = 1152 * 3;
973 		  parms.pixels_per_line = 1152;
974 		  parms.lines = 864;
975 		}
976 	    }
977 	  break;
978 
979 	case DC210_OPT_SNAP:
980 	  dc210_opt_snap = !!*(SANE_Word *) value;
981 	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
982 	  /* if we are snapping a new one */
983 	  if (dc210_opt_snap)
984 	    {
985 	      /* activate the resolution setting */
986 	      sod[DC210_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE;
987 	      /* and de-activate the image number selector */
988 	      sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
989 	    }
990 	  else
991 	    {
992 	      /* deactivate the resolution setting */
993 	      sod[DC210_OPT_LOWRES].cap |= SANE_CAP_INACTIVE;
994 	      /* and activate the image number selector */
995 	      sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
996 	    }
997 	  /* set params according to resolution settings */
998 	  if (dc210_opt_lowres)
999 	    {
1000 	      parms.bytes_per_line = 640 * 3;
1001 	      parms.pixels_per_line = 640;
1002 	      parms.lines = 480;
1003 	    }
1004 	  else
1005 	    {
1006 	      parms.bytes_per_line = 1152 * 3;
1007 	      parms.pixels_per_line = 1152;
1008 	      parms.lines = 864;
1009 	    }
1010 	  break;
1011 
1012 	case DC210_OPT_LOWRES:
1013 	  dc210_opt_lowres = !!*(SANE_Word *) value;
1014 	  myinfo |= SANE_INFO_RELOAD_PARAMS;
1015 
1016 	  if (!dc210_opt_thumbnails)
1017 	    {
1018 
1019 /* XXX - change the number of pictures left depending on resolution
1020    perhaps just call get_info again?
1021  */
1022 	      if (dc210_opt_lowres)
1023 		{
1024 		  parms.bytes_per_line = 640 * 3;
1025 		  parms.pixels_per_line = 640;
1026 		  parms.lines = 480;
1027 		}
1028 	      else
1029 		{
1030 		  parms.bytes_per_line = 1152 * 3;
1031 		  parms.pixels_per_line = 1152;
1032 		  parms.lines = 864;
1033 		}
1034 
1035 	    }
1036 	  break;
1037 
1038 	case DC210_OPT_ERASE:
1039 	  dc210_opt_erase = !!*(SANE_Word *) value;
1040 	  break;
1041 
1042 	case DC210_OPT_DEFAULT:
1043 	  DBG (1, "Fixme: Set all defaults here!\n");
1044 	  break;
1045 	case DC210_OPT_INIT_DC210:
1046 	  if ((Camera.fd = init_dc210 (&Camera)) == -1)
1047 	    {
1048 	      return SANE_STATUS_INVAL;
1049 	    }
1050 	  break;
1051 
1052 	default:
1053 	  return SANE_STATUS_INVAL;
1054 	}
1055       break;
1056 
1057     case SANE_ACTION_GET_VALUE:
1058       switch (option)
1059 	{
1060 	case 0:
1061 	  *(SANE_Word *) value = NELEMS (sod);
1062 	  break;
1063 
1064 	case DC210_OPT_IMAGE_NUMBER:
1065 	  *(SANE_Word *) value = Camera.current_picture_number;
1066 	  break;
1067 
1068 	case DC210_OPT_THUMBS:
1069 	  *(SANE_Word *) value = dc210_opt_thumbnails;
1070 	  break;
1071 
1072 	case DC210_OPT_SNAP:
1073 	  *(SANE_Word *) value = dc210_opt_snap;
1074 	  break;
1075 
1076 	case DC210_OPT_LOWRES:
1077 	  *(SANE_Word *) value = dc210_opt_lowres;
1078 	  break;
1079 
1080 	case DC210_OPT_ERASE:
1081 	  *(SANE_Word *) value = dc210_opt_erase;
1082 	  break;
1083 
1084 	default:
1085 	  return SANE_STATUS_INVAL;
1086 	}
1087       break;
1088 
1089     case SANE_ACTION_SET_AUTO:
1090       switch (option)
1091 	{
1092 	default:
1093 	  return SANE_STATUS_UNSUPPORTED;	/* We are DUMB */
1094 	}
1095     }
1096 
1097   if (info)
1098     *info = myinfo;
1099 
1100   return SANE_STATUS_GOOD;
1101 }
1102 
1103 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)1104 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1105 {
1106   int rc = SANE_STATUS_GOOD;
1107 
1108   DBG (127, "sane_get_params called\n");
1109 
1110   if (handle != MAGIC || !is_open)
1111     rc = SANE_STATUS_INVAL;	/* Unknown handle ... */
1112 
1113   parms.last_frame = SANE_TRUE;	/* Have no idea what this does */
1114   *params = parms;
1115   DBG (127, "sane_get_params return %d\n", rc);
1116   return rc;
1117 }
1118 
1119 typedef struct
1120 {
1121   struct jpeg_source_mgr pub;
1122   JOCTET *buffer;
1123 }
1124 my_source_mgr;
1125 typedef my_source_mgr *my_src_ptr;
1126 
1127 METHODDEF (void)
sanei_jpeg_init_source(j_decompress_ptr __sane_unused__ cinfo)1128 sanei_jpeg_init_source (j_decompress_ptr __sane_unused__ cinfo)
1129 {
1130   /* nothing to do */
1131 }
1132 
METHODDEFnull1133 METHODDEF (boolean) sanei_jpeg_fill_input_buffer (j_decompress_ptr cinfo)
1134 {
1135 
1136   my_src_ptr src = (my_src_ptr) cinfo->src;
1137 
1138   if (read_data (Camera.fd, src->buffer, 1024) == -1)
1139     {
1140       DBG (5, "sane_start: read_data failed\n");
1141       src->buffer[0] = (JOCTET) 0xFF;
1142       src->buffer[1] = (JOCTET) JPEG_EOI;
1143       return FALSE;
1144     }
1145   src->pub.next_input_byte = src->buffer;
1146   src->pub.bytes_in_buffer = 1024;
1147 
1148   return TRUE;
1149 }
1150 
1151 METHODDEF (void)
sanei_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)1152 sanei_jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
1153 {
1154 
1155   my_src_ptr src = (my_src_ptr) cinfo->src;
1156 
1157   if (num_bytes > 0)
1158     {
1159       while (num_bytes > (long) src->pub.bytes_in_buffer)
1160 	{
1161 	  num_bytes -= (long) src->pub.bytes_in_buffer;
1162 	  (void) sanei_jpeg_fill_input_buffer (cinfo);
1163 	}
1164     }
1165   src->pub.next_input_byte += (size_t) num_bytes;
1166   src->pub.bytes_in_buffer -= (size_t) num_bytes;
1167 }
1168 
1169 METHODDEF (void)
sanei_jpeg_term_source(j_decompress_ptr __sane_unused__ cinfo)1170 sanei_jpeg_term_source (j_decompress_ptr __sane_unused__ cinfo)
1171 {
1172   /* no work necessary here */
1173 }
1174 
1175 SANE_Status
sane_start(SANE_Handle handle)1176 sane_start (SANE_Handle handle)
1177 {
1178 
1179   DBG (127, "sane_start called\n");
1180   if (handle != MAGIC || !is_open ||
1181       (Camera.current_picture_number == 0 && dc210_opt_snap == SANE_FALSE))
1182     return SANE_STATUS_INVAL;	/* Unknown handle ... */
1183 
1184   if (Camera.scanning)
1185     return SANE_STATUS_EOF;
1186 
1187   if (dc210_opt_snap)
1188     {
1189 
1190       /*
1191        * Don't allow picture unless there is room in the
1192        * camera.
1193        */
1194       if (Camera.pic_left == 0)
1195 	{
1196 	  DBG (3, "No room to store new picture\n");
1197 	  return SANE_STATUS_INVAL;
1198 	}
1199 
1200 
1201       if (snap_pic (Camera.fd) != SANE_STATUS_GOOD)
1202 	{
1203 	  DBG (1, "Failed to snap new picture\n");
1204 	  return SANE_STATUS_INVAL;
1205 	}
1206     }
1207 
1208   if (dc210_opt_thumbnails)
1209     {
1210 
1211       thumb_pck[3] = (unsigned char) Camera.current_picture_number - 1;
1212       thumb_pck[4] = 1;
1213 
1214       if (send_pck (Camera.fd, thumb_pck) == -1)
1215 	{
1216 	  DBG (4, "sane_start: error: send_pck returned -1\n");
1217 	  return SANE_STATUS_INVAL;
1218 	}
1219 
1220       parms.bytes_per_line = 96 * 3;
1221       parms.pixels_per_line = 96;
1222       parms.lines = 72;
1223 
1224       bytes_in_buffer = 0;
1225       bytes_read_from_buffer = 0;
1226 
1227     }
1228   else
1229     {
1230       my_src_ptr src;
1231 
1232       struct jpeg_error_mgr jerr;
1233 
1234       pic_pck[3] = (unsigned char) Camera.current_picture_number - 1;
1235 
1236       if (send_pck (Camera.fd, pic_pck) == -1)
1237 	{
1238 	  DBG (4, "sane_start: error: send_pck returned -1\n");
1239 	  return SANE_STATUS_INVAL;
1240 	}
1241       cinfo.err = jpeg_std_error (&jerr);
1242       jpeg_create_decompress (&cinfo);
1243 
1244       cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr));
1245       src = (my_src_ptr) cinfo.src;
1246 
1247       src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) &
1248 							  cinfo,
1249 							  JPOOL_PERMANENT,
1250 							  1024 *
1251 							  sizeof (JOCTET));
1252       src->pub.init_source = sanei_jpeg_init_source;
1253       src->pub.fill_input_buffer = sanei_jpeg_fill_input_buffer;
1254       src->pub.skip_input_data = sanei_jpeg_skip_input_data;
1255       src->pub.resync_to_restart = jpeg_resync_to_restart;	/* default */
1256       src->pub.term_source = sanei_jpeg_term_source;
1257       src->pub.bytes_in_buffer = 0;
1258       src->pub.next_input_byte = NULL;
1259 
1260       (void) jpeg_read_header (&cinfo, TRUE);
1261       dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo);
1262       (void) jpeg_start_decompress (&cinfo);
1263     }
1264 
1265   Camera.scanning = SANE_TRUE;	/* don't overlap scan requests */
1266   total_bytes_read = 0;
1267 
1268   return SANE_STATUS_GOOD;
1269 }
1270 
1271 SANE_Status
sane_read(SANE_Handle __sane_unused__ handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length)1272 sane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data,
1273 	   SANE_Int max_length, SANE_Int * length)
1274 {
1275 
1276   static char buffer[1024];
1277 
1278   if (dc210_opt_thumbnails)
1279     {
1280       if (total_bytes_read == THUMBSIZE)
1281 	{
1282 	  if (dc210_opt_erase)
1283 	    {
1284 	      if (erase (Camera.fd) == -1)
1285 		{
1286 		  DBG (1, "Failed to erase memory\n");
1287 		  return SANE_STATUS_INVAL;
1288 		}
1289 	      Camera.pic_taken--;
1290 	      Camera.pic_left++;
1291 	      Camera.current_picture_number = Camera.pic_taken;
1292 	      image_range.max--;
1293 	    }
1294 	  return SANE_STATUS_EOF;
1295 	}
1296 
1297       *length = 0;
1298       if (!(bytes_in_buffer - bytes_read_from_buffer))
1299 	{
1300 	  if (read_data (Camera.fd, (unsigned char *) buffer, 1024) == -1)
1301 	    {
1302 	      DBG (5, "sane_read: read_data failed\n");
1303 	      return SANE_STATUS_INVAL;
1304 	    }
1305 	  bytes_in_buffer = 1024;
1306 	  bytes_read_from_buffer = 0;
1307 	}
1308 
1309       while (bytes_read_from_buffer < bytes_in_buffer &&
1310 	     max_length && total_bytes_read < THUMBSIZE)
1311 	{
1312 	  *data++ = buffer[bytes_read_from_buffer++];
1313 	  (*length)++;
1314 	  max_length--;
1315 	  total_bytes_read++;
1316 	}
1317 
1318       if (total_bytes_read == THUMBSIZE)
1319 	{
1320 	  if (end_of_data (Camera.fd) == -1)
1321 	    {
1322 	      DBG (4, "sane_read: end_of_data error\n");
1323 	      return SANE_STATUS_INVAL;
1324 	    }
1325 	  else
1326 	    {
1327 	      return SANE_STATUS_GOOD;
1328 	    }
1329 	}
1330       else
1331 	{
1332 	  return SANE_STATUS_GOOD;
1333 	}
1334     }
1335   else
1336     {
1337       int lines = 0;
1338 
1339       if (cinfo.output_scanline >= cinfo.output_height)
1340 	{
1341 	  /* clean up comms with the camera */
1342 	  if (end_of_data (Camera.fd) == -1)
1343 	    {
1344 	      DBG (2, "sane_read: error: end_of_data returned -1\n");
1345 	      return SANE_STATUS_INVAL;
1346 	    }
1347 	  if (dc210_opt_erase)
1348 	    {
1349 	      DBG (127, "sane_read bp%d, erase image\n", __LINE__);
1350 	      if (erase (Camera.fd) == -1)
1351 		{
1352 		  DBG (1, "Failed to erase memory\n");
1353 		  return SANE_STATUS_INVAL;
1354 		}
1355 	      Camera.pic_taken--;
1356 	      Camera.pic_left++;
1357 	      Camera.current_picture_number = Camera.pic_taken;
1358 	      image_range.max--;
1359 	    }
1360 	  return SANE_STATUS_EOF;
1361 	}
1362 
1363 /* XXX - we should read more than 1 line at a time here */
1364       lines = 1;
1365       (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines);
1366       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) data);
1367       *length = cinfo.output_width * cinfo.output_components * lines;
1368 
1369       return SANE_STATUS_GOOD;
1370 
1371     }
1372 }
1373 
1374 void
sane_cancel(SANE_Handle __sane_unused__ handle)1375 sane_cancel (SANE_Handle __sane_unused__ handle)
1376 {
1377   DBG (127, "sane_cancel() called\n");
1378   if (Camera.scanning)
1379     Camera.scanning = SANE_FALSE;	/* done with scan */
1380   else
1381     DBG (127, "sane_cancel() aborted, scanner not scanning\n");
1382 }
1383 
1384 SANE_Status
sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking)1385 sane_set_io_mode (SANE_Handle __sane_unused__ handle,
1386 		  SANE_Bool __sane_unused__ non_blocking)
1387 {
1388   return SANE_STATUS_UNSUPPORTED;
1389 }
1390 
1391 SANE_Status
sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)1392 sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd)
1393 {
1394   return SANE_STATUS_UNSUPPORTED;
1395 }
1396 
1397 static PictureInfo *
get_pictures_info(void)1398 get_pictures_info (void)
1399 {
1400 
1401   char f[] = "get_pictures_info";
1402   unsigned int p;
1403   PictureInfo *pics;
1404 
1405   if ((pics = (PictureInfo *) malloc (Camera.pic_taken *
1406 				      sizeof (PictureInfo))) == NULL)
1407     {
1408       DBG (4, "%s: error: allocate memory for pictures array\n", f);
1409       return NULL;
1410     }
1411 
1412   for (p = 0; p < (unsigned int) Camera.pic_taken; p++)
1413     {
1414       if (get_picture_info (pics + p, p) == -1)
1415 	{
1416 	  free (pics);
1417 	  return NULL;
1418 	}
1419     }
1420 
1421   return pics;
1422 }
1423 
1424 static int
get_picture_info(PictureInfo * pic, int p)1425 get_picture_info (PictureInfo * pic, int p)
1426 {
1427 
1428   char f[] = "get_picture_info";
1429   static char buffer[256];
1430 
1431   DBG (4, "%s: info for pic #%d\n", f, p);
1432 
1433   pic_info_pck[3] = (unsigned char) p;
1434 
1435   if (send_pck (Camera.fd, pic_info_pck) == -1)
1436     {
1437       DBG (4, "%s: error: send_pck returned -1\n", f);
1438       return -1;
1439     }
1440 
1441   if (read_data (Camera.fd, (unsigned char *) buffer, 256) == -1)
1442     {
1443       DBG (2, "%s: error: read_data returned -1\n", f);
1444       return -1;
1445     }
1446 
1447   if (end_of_data (Camera.fd) == -1)
1448     {
1449       DBG (2, "%s: error: end_of_data returned -1\n", f);
1450       return -1;
1451     }
1452 
1453   if (buffer[3] == 0)
1454     {
1455       pic->low_res = SANE_TRUE;
1456     }
1457   else if (buffer[3] == 1)
1458     {
1459       pic->low_res = SANE_FALSE;
1460     }
1461   else
1462     {
1463       DBG (2, "%s: error: unknown resolution code %u\n", f, buffer[3]);
1464       return -1;
1465     }
1466   pic->size = (buffer[8] & 0xFF) << 24;
1467   pic->size |= (buffer[9] & 0xFF) << 16;
1468   pic->size |= (buffer[10] & 0xFF) << 8;
1469   pic->size |= (buffer[11] & 0xFF);
1470 
1471   return 0;
1472 }
1473 
1474 static SANE_Status
snap_pic(int fd)1475 snap_pic (int fd)
1476 {
1477 
1478   char f[] = "snap_pic";
1479 
1480   /* make sure camera is set to our settings state */
1481   if (change_res (Camera.fd, dc210_opt_lowres) == -1)
1482     {
1483       DBG (1, "%s: Failed to set resolution\n", f);
1484       return SANE_STATUS_INVAL;
1485     }
1486 
1487   /* take the picture */
1488   if (send_pck (fd, shoot_pck) == -1)
1489     {
1490       DBG (4, "%s: error: send_pck returned -1\n", f);
1491       return SANE_STATUS_INVAL;
1492     }
1493   else
1494     {
1495       if (end_of_data (Camera.fd) == -1)
1496 	{
1497 	  DBG (2, "%s: error: end_of_data returned -1\n", f);
1498 	  return SANE_STATUS_INVAL;
1499 	}
1500     }
1501   Camera.pic_taken++;
1502   Camera.pic_left--;
1503   Camera.current_picture_number = Camera.pic_taken;
1504   image_range.max++;
1505   sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE;
1506 
1507   /* add this one to the Pictures array */
1508   if ((Camera.Pictures =
1509        (PictureInfo *) realloc (Camera.Pictures,
1510 				Camera.pic_taken * sizeof (PictureInfo))) ==
1511       NULL)
1512     {
1513       DBG (4, "%s: error: allocate memory for pictures array\n", f);
1514       return SANE_STATUS_INVAL;
1515     }
1516 
1517   if (get_picture_info (Camera.Pictures + Camera.pic_taken,
1518 			Camera.pic_taken) == -1)
1519     {
1520       DBG (1, "%s: Failed to get new picture info\n", f);
1521       /* XXX - I guess we should try to erase the image here */
1522       return SANE_STATUS_INVAL;
1523     }
1524 
1525   return SANE_STATUS_GOOD;
1526 }
1527