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