1 /* pdc700.c
2  *
3  * Copyright 2001 Lutz Mueller
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  */
20 
21 #define _DEFAULT_SOURCE
22 
23 #include "config.h"
24 
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <time.h>
29 
30 #include <gphoto2/gphoto2-library.h>
31 #include <gphoto2/gphoto2-port-log.h>
32 
33 #ifdef ENABLE_NLS
34 #  include <libintl.h>
35 #  undef _
36 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
37 #  ifdef gettext_noop
38 #    define N_(String) gettext_noop (String)
39 #  else
40 #    define N_(String) (String)
41 #  endif
42 #else
43 #  define textdomain(String) (String)
44 #  define gettext(String) (String)
45 #  define dgettext(Domain,Message) (Message)
46 #  define dcgettext(Domain,Message,Type) (Message)
47 #  define bindtextdomain(Domain,Directory) (Domain)
48 #  define _(String) (String)
49 #  define N_(String) (String)
50 #endif
51 
52 #define GP_MODULE "pdc700"
53 
54 #define PDC700_INIT	0x01
55 #define PDC700_INFO	0x02
56 #define PDC700_CONFIG   0x03
57 #define PDC700_BAUD	0x04
58 #define PDC700_PICINFO	0x05
59 #define PDC700_THUMB	0x06
60 #define PDC700_PIC	0x07
61 #define PDC700_DEL	0x09
62 #define PDC700_CAPTURE  0x0a
63 
64 #define RETRIES 5
65 
66 enum _PDCStatus {
67 	PDC_STATUS_FAIL = 0x00,
68 	PDC_STATUS_DONE = 0x01,
69 	PDC_STATUS_LAST = 0x02
70 };
71 typedef enum _PDCStatus PDCStatus;
72 
73 enum _PDCConf {
74 	PDC_CONF_FLASH    = 0x00,
75 	PDC_CONF_TIMER    = 0x01,
76 	PDC_CONF_CAPTION  = 0x02,
77 	PDC_CONF_LCD      = 0x03,
78 	PDC_CONF_QUALITY  = 0x04,
79 	PDC_CONF_TIME     = 0x05,
80 	PDC_CONF_POWEROFF = 0x06,
81 	PDC_CONF_SIZE     = 0x07
82 	/* I think we have them all... 8 and 9 return failure */
83 };
84 typedef enum _PDCConf PDCConf;
85 
86 enum _PDCBaud {
87 	PDC_BAUD_9600   = 0x00,
88 	PDC_BAUD_19200  = 0x01,
89 	PDC_BAUD_38400  = 0x02,
90 	PDC_BAUD_57600  = 0x03,
91 	PDC_BAUD_115200 = 0x04
92 };
93 typedef enum _PDCBaud PDCBaud;
94 
95 enum _PDCBool {
96 	PDC_BOOL_OFF = 0,
97 	PDC_BOOL_ON  = 1
98 };
99 typedef enum _PDCBool PDCBool;
100 
101 typedef struct _PDCDate PDCDate;
102 struct _PDCDate {
103 
104 	/*
105 	 * v2.45: Years since 1980
106 	 * V3.10: Years since 2000
107 	 */
108 	unsigned char year, month, day;
109 	unsigned char hour, minute, second;
110 };
111 
112 enum _PDCMode {
113 	PDC_MODE_PLAY   = 0,
114 	PDC_MODE_RECORD = 1,
115 	PDC_MODE_MENU   = 2
116 };
117 typedef enum _PDCMode PDCMode;
118 
119 enum _PDCQuality {
120 	PDC_QUALITY_NORMAL    = 0,
121 	PDC_QUALITY_FINE      = 1,
122 	PDC_QUALITY_SUPERFINE = 2
123 };
124 typedef enum _PDCQuality PDCQuality;
125 
126 enum _PDCSize {
127 	PDC_SIZE_VGA = 0,
128 	PDC_SIZE_XGA = 1,
129 };
130 typedef enum _PDCSize PDCSize;
131 
132 enum _PDCFlash {
133 	PDC_FLASH_AUTO = 0,
134 	PDC_FLASH_ON   = 1,
135 	PDC_FLASH_OFF  = 2
136 };
137 typedef enum _PDCFlash PDCFlash;
138 
139 typedef struct _PDCInfo PDCInfo;
140 struct _PDCInfo {
141 	unsigned int num_taken, num_free;
142 	unsigned char auto_poweroff;
143 	char version[6];
144 	unsigned char memory;
145 	PDCDate date;
146 	PDCMode mode;
147 	PDCQuality quality;
148 	PDCSize size;
149 	PDCFlash   flash;
150 	PDCBaud    speed;
151 	PDCBool caption, timer, lcd, ac_power;
152 };
153 
154 typedef struct _PDCPicInfo PDCPicInfo;
155 struct _PDCPicInfo {
156 	char version[6];
157 	unsigned int pic_size, thumb_size;
158 	unsigned char flash;
159 };
160 
161 #define IMAGE_QUALITY _("Image Quality")
162 #define IMAGE_SIZE    _("Image Size")
163 #define FLASH_SETTING _("Flash Setting")
164 #define LCD_STATE     _("LCD")
165 #define SELF_TIMER    _("Self Timer")
166 #define AUTO_POWEROFF _("Auto Power Off (minutes)")
167 #define SHOW_CAPTIONS _("Information")
168 
169 static const char *quality[] = {N_("normal"), N_("fine"), N_("superfine"),
170 				NULL};
171 static const char *flash[]   = {N_("auto"), N_("on"), N_("off"), NULL};
172 static const char *bool[]    = {N_("off"), N_("on"), NULL};
173 static const char *mode[]    = {N_("play"), N_("record"), N_("menu"), NULL};
174 static const char *power[]   = {N_("battery"), N_("a/c adaptor"), NULL};
175 /* no real need to translate those ... */
176 static const char *speed[]   = {"9600", "19200", "38400", "57600", "115200", NULL};
177 static const char *size[]    = {"VGA (640x480)", "XGA (1024x768", NULL};
178 
179 #define CR(result) {int __r=(result);if(__r<0) return (__r);}
180 #define CRF(result,d)      {int r=(result);if(r<0) {free(d);return(r);}}
181 
182 #define PDC_EPOCH(info) ((!strcmp ((info)->version, "v2.45")) ? 1980 : 2000)
183 
184 /*
185  * Every command sent to the camera begins with 0x40 followed by two bytes
186  * indicating the number of following bytes. Then follows the byte that
187  * indicates the command (see above defines), perhaps some parameters. The
188  * last byte is the checksum, the sum of all bytes between length bytes
189  * (3rd one) and the last one (checksum).
190  */
191 static int
calc_checksum(unsigned char * cmd,unsigned int len)192 calc_checksum (unsigned char *cmd, unsigned int len)
193 {
194 	unsigned int i;
195 	unsigned char checksum;
196 
197 	for (checksum = 0, i = 0; i < len; i++)
198 		checksum += cmd[i];
199 
200 	return (checksum);
201 }
202 
203 static int
pdc700_send(Camera * camera,unsigned char * cmd,unsigned int cmd_len)204 pdc700_send (Camera *camera, unsigned char *cmd, unsigned int cmd_len)
205 {
206 	/* Finish the command and send it */
207 	cmd[0] = 0x40;
208 	cmd[1] = (cmd_len - 3) >> 8;
209 	cmd[2] = (cmd_len - 3) & 0xff;
210 	cmd[cmd_len - 1] = calc_checksum (cmd + 3, cmd_len - 1 - 3);
211 	CR (gp_port_write (camera->port, (char *)cmd, cmd_len));
212 
213 	return (GP_OK);
214 }
215 
216 static int
pdc700_read(Camera * camera,unsigned char * cmd,unsigned char * b,unsigned int * b_len,PDCStatus * status,unsigned char * sequence_number,GPContext * context)217 pdc700_read (Camera *camera, unsigned char *cmd,
218 	     unsigned char *b, unsigned int *b_len,
219 	     PDCStatus *status, unsigned char *sequence_number,
220 	     GPContext *context)
221 {
222 	unsigned char header[3], checksum;
223 	unsigned int i;
224 
225 	/*
226 	 * Read the header (0x40 plus 2 bytes indicating how many bytes
227 	 * will follow)
228 	 */
229 	CR (gp_port_read (camera->port, (char *)header, 3));
230 	if (header[0] != 0x40) {
231 		gp_context_error (context, _("Received unexpected "
232 				     "header (%i)"), header[0]);
233 		return (GP_ERROR_CORRUPTED_DATA);
234 	}
235 	*b_len = (header[2] << 8) | header [1];
236 	if (*b_len > 2048) {
237 		GP_DEBUG ("length %d too large", *b_len);
238 		return GP_ERROR_CORRUPTED_DATA;
239 	}
240 
241 	/* Read the remaining bytes */
242 	CR (gp_port_read (camera->port, (char *)b, *b_len));
243 
244 	/*
245 	 * The first byte indicates if this the response for our command.
246 	 */
247 	if (b[0] != (0x80 | cmd[3])) {
248 		gp_context_error (context, _("Received unexpected response"));
249 		return (GP_ERROR_CORRUPTED_DATA);
250 	}
251 
252 	/* Will other packets follow? Has the transaction been successful? */
253 	*status = b[1];
254 
255 	/*
256 	 * If everything went ok and if we are downloading a picture or
257 	 * thumbnail, we got a sequence number (number of next packet).
258 	 */
259 	if ((*status != PDC_STATUS_FAIL) && ((cmd[3] == PDC700_THUMB) ||
260 					     (cmd[3] == PDC700_PIC)))
261 		*sequence_number = b[2];
262 	else
263 		sequence_number = NULL;
264 
265 	/* Check the checksum */
266 	for (checksum = i = 0; i < *b_len - 1; i++)
267 		checksum += b[i];
268 	if (checksum != b[*b_len - 1]) {
269 		gp_context_error (context, _("Checksum error"));
270 		return (GP_ERROR_CORRUPTED_DATA);
271 	}
272 
273 	/* Preserve only the actual data */
274 	*b_len -= (sequence_number ? 4 : 3);
275 	memmove (b, b + (sequence_number ? 3 : 2), *b_len);
276 
277 	return (GP_OK);
278 }
279 
280 static int
pdc700_transmit(Camera * camera,unsigned char * cmd,unsigned int cmd_len,unsigned char * buf,unsigned int * buf_len,GPContext * context)281 pdc700_transmit (Camera *camera, unsigned char *cmd, unsigned int cmd_len,
282 		 unsigned char *buf, unsigned int *buf_len, GPContext *context)
283 {
284 	unsigned char b[2048], n;
285 	unsigned int b_len, r;
286 	unsigned int target = *buf_len, id;
287 	int result;
288 	PDCStatus status;
289 
290 	status = PDC_STATUS_DONE;
291 	for (r = 0; r < RETRIES; r++) {
292 		if (status == PDC_STATUS_FAIL)
293 			GP_DEBUG ("Retrying (%i)...", r);
294 		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
295 			return GP_ERROR_CANCEL;
296 		CR (pdc700_send (camera, cmd, cmd_len));
297 		CR (pdc700_read (camera, cmd, b, &b_len, &status, &n, context));
298 		if (status != PDC_STATUS_FAIL)
299 			break;
300 	}
301 	if (status == PDC_STATUS_FAIL) {
302 		gp_context_error (context, _("The camera did not accept the "
303 				     "command."));
304 		return (GP_ERROR);
305 	}
306 
307 	/* Copy over the data */
308 	*buf_len = b_len;
309 	memcpy (buf, b, b_len);
310 
311 	/*
312 	 * Other packets will follow only in case of PDC700_THUMB or
313 	 * PDC700_PIC.
314 	 */
315 	if ((cmd[3] == PDC700_THUMB) || (cmd[3] == PDC700_PIC)) {
316 
317 		/* Get those other packets */
318 		r = 0;
319 		id = gp_context_progress_start (context, target,
320 						_("Downloading..."));
321 		while ((status != PDC_STATUS_LAST) && (r < RETRIES)) {
322 			GP_DEBUG ("Fetching sequence %i...", n);
323 			cmd[4] = status;
324 			cmd[5] = n;
325 			CR (pdc700_send (camera, cmd, 7));
326 
327 			/* Read data. */
328 			result = pdc700_read (camera, cmd, b, &b_len,
329 					      &status, &n, context);
330 
331 			/* Did libgphoto2(_port) report an error? */
332 			if (result < 0) {
333 				GP_DEBUG ("Read failed ('%s'). Trying again.",
334 					  gp_result_as_string (result));
335 				r++;
336 				continue;
337 			}
338 
339 			/* Did the camera report an error? */
340 			if (status == PDC_STATUS_FAIL) {
341 				GP_DEBUG ("Read failed: camera reported "
342 					  "failure. Trying again.");
343 				r++;
344 				continue;
345 			}
346 
347 			/* Read succeeded. Reset error counter */
348 			r = 0;
349 
350 			/*
351 			 * Sanity check: We should never read more bytes than
352 			 * targeted
353 			 */
354 			if (*buf_len + b_len > target) {
355 				gp_context_error (context, _("The camera "
356 					"sent more bytes than expected (%i)"),
357 					target);
358 				return (GP_ERROR_CORRUPTED_DATA);
359 			}
360 
361 			/* Copy over the data */
362 			memcpy (buf + *buf_len, b, b_len);
363 			*buf_len += b_len;
364 
365 			/*
366 			 * Update the progress bar and check for
367 			 * cancellation.
368 			 */
369 			gp_context_progress_update (context, id, *buf_len);
370 			if (gp_context_cancel (context) ==
371 						GP_CONTEXT_FEEDBACK_CANCEL) {
372 				cmd[4] = PDC_STATUS_LAST;
373 				cmd[5] = n;
374 				CR (pdc700_send (camera, cmd, 7));
375 				return (GP_ERROR_CANCEL);
376 			}
377 		}
378 
379 		/* Check if anything went wrong */
380 		if (status != PDC_STATUS_LAST)
381 			return (GP_ERROR_CORRUPTED_DATA);
382 
383 		/* Acknowledge last packet */
384 		cmd[4] = PDC_STATUS_LAST;
385 		cmd[5] = n;
386 		CR (pdc700_send (camera, cmd, 7));
387 
388 		gp_context_progress_stop (context, id);
389 	}
390 
391 	return (GP_OK);
392 }
393 
394 static int
pdc700_baud(Camera * camera,int baud,GPContext * context)395 pdc700_baud (Camera *camera, int baud, GPContext *context)
396 {
397 	unsigned char cmd[6];
398 	unsigned char buf[2048];
399 	unsigned int buf_len = 0;
400 
401 	cmd[3] = PDC700_BAUD;
402 	switch (baud) {
403 	case 115200:
404 		cmd[4] = PDC_BAUD_115200;
405 		break;
406 	case 57600:
407 		cmd[4] = PDC_BAUD_57600;
408 		break;
409 	case 38400:
410 		cmd[4] = PDC_BAUD_38400;
411 		break;
412 	case 19200:
413 		cmd[4] = PDC_BAUD_19200;
414 		break;
415 	case 9600:
416 		cmd[4] = PDC_BAUD_9600;
417 		break;
418 	default:
419 		return (GP_ERROR_IO_SERIAL_SPEED);
420 	}
421 	CR (pdc700_transmit (camera, cmd, 6, buf, &buf_len, context));
422 
423 	return (GP_OK);
424 }
425 
426 static int
pdc700_init(Camera * camera,GPContext * context)427 pdc700_init (Camera *camera, GPContext *context)
428 {
429 	unsigned int buf_len = 0;
430 	unsigned char cmd[5];
431 	unsigned char buf[2048];
432 
433 	cmd[3] = PDC700_INIT;
434 	CR (pdc700_transmit (camera, cmd, 5, buf, &buf_len, context));
435 
436 	return (GP_OK);
437 }
438 
439 static int
pdc700_picinfo(Camera * camera,unsigned int n,PDCPicInfo * info,GPContext * context)440 pdc700_picinfo (Camera *camera, unsigned int n, PDCPicInfo *info,
441 		GPContext *context)
442 {
443 	unsigned int buf_len = 0;
444 	unsigned char cmd[7];
445 	unsigned char buf[2048];
446 
447 	GP_DEBUG ("Getting info about picture %i...", n);
448 	cmd[3] = PDC700_PICINFO;
449 	cmd[4] = n;
450 	cmd[5] = n >> 8;
451 	CR (pdc700_transmit (camera, cmd, 7, buf, &buf_len, context));
452 
453 	/* We don't know about the meaning of buf[0-1] */
454 
455 	/* Check if this information is about the right picture */
456 	if (n != (unsigned int)(buf[2] | (buf[3] << 8))) {
457 		gp_context_error (context, _("Requested information about "
458 			"picture %i (= 0x%x), but got information about "
459 			"picture %i back"), n, cmd[4] | (cmd[5] << 8),
460 			buf[2] | (buf[3] << 8));
461 		return (GP_ERROR_CORRUPTED_DATA);
462 	}
463 
464 	/* Picture size */
465 	info->pic_size = buf[4] | (buf[5] << 8) |
466 			(buf[6] << 16) | (buf[7] << 24);
467 	GP_DEBUG ("Size of picture: %i", info->pic_size);
468 
469 	/* Flash used? */
470 	info->flash = buf[8];
471 	GP_DEBUG ("This picture has been taken with%s flash.",
472 		  buf[8] ? "" : "out");
473 
474 	/* The meaning of buf[9-17] is unknown */
475 
476 	/* Thumbnail size */
477 	info->thumb_size = buf[18] | (buf[19] <<  8) | (buf[20] << 16) |
478 			  (buf[21] << 24);
479 	GP_DEBUG ("Size of thumbnail: %i", info->thumb_size);
480 
481 	/* The meaning of buf[22] is unknown */
482 
483 	/* Version info */
484 	strncpy (info->version, (char *)&buf[23], 6);
485 
486 	/*
487 	 * Now follows some picture data we have yet to reverse
488 	 * engineer (buf[24-63]).
489 	 */
490 
491 	return (GP_OK);
492 }
493 
494 static int
pdc700_config(Camera * camera,PDCConf conf,unsigned char value,GPContext * context)495 pdc700_config (Camera *camera, PDCConf conf, unsigned char value, GPContext *context)
496 {
497 	unsigned char cmd[12];
498 	unsigned char buf[512];
499 	unsigned int buf_len = 0;
500 
501 	cmd[3] = PDC700_CONFIG;
502 	cmd[4] = conf;
503 	cmd[5] = value;
504 
505 	CR (pdc700_transmit (camera, cmd, 12, buf, &buf_len, context));
506 
507 	return GP_OK;
508 }
509 
510 
511 static int
pdc700_info(Camera * camera,PDCInfo * info,GPContext * context)512 pdc700_info (Camera *camera, PDCInfo *info, GPContext *context)
513 {
514 	unsigned int buf_len = 0;
515 	unsigned char buf[2048];
516 	unsigned char cmd[5];
517 
518 	cmd[3] = PDC700_INFO;
519 	CR (pdc700_transmit (camera, cmd, 5, buf, &buf_len, context));
520 
521 	/*
522 	 * buf[0-1,3]: We don't know. The following has been seen:
523 	 * 01 12 .. 01
524 	 * 01 20 .. 02
525 	 * 01 20 .. 02
526 	 */
527 
528  	info->memory = buf[2];
529 
530 	/* Power source state (make sure it's valid) */
531 	info->ac_power = buf[4];
532 	if (info->ac_power != 0 && info->ac_power != 1) {
533 		GP_DEBUG ("Unknown power source: %i", info->ac_power);
534 		info->ac_power = PDC_BOOL_OFF;
535 	}
536 
537  	info->auto_poweroff = buf[5];
538 
539 	/* Mode (make sure we know it) */
540 	info->mode = buf[6];
541 	if (info->mode < 0 || info->mode > 2) {
542 		GP_DEBUG ("Unknown mode setting: %i", info->mode);
543 		/* record mode is the power-on default -gi */
544 		info->mode = PDC_MODE_RECORD;
545 	}
546 
547 	/* Flash (make sure we know it) */
548 	info->flash = buf[7];
549 	if (info->flash < 0 || info->flash > 2) {
550 		GP_DEBUG ("Unknown flash setting: %i", info->flash);
551 		info->flash = PDC_FLASH_AUTO;
552 	}
553 
554 	/* Protocol version */
555 	strncpy (info->version, (char *)&buf[8], 6);
556 
557 	/* buf[14-15]: We don't know. Seems to be always 00 00 */
558 
559 	/* Pictures */
560 	info->num_taken = buf[16] | (buf[17] << 8);
561 	info->num_free = buf[18] | (buf[19] << 8);
562 
563 	/* Date */
564 	info->date.year   = buf[20];
565 	info->date.month  = buf[21];
566 	info->date.day    = buf[22];
567 	info->date.hour   = buf[23];
568 	info->date.minute = buf[24];
569 	info->date.second = buf[25];
570 
571 	/* Speed (kind of bogus as we already know about it) */
572 	info->speed = buf[26];
573 	if (info->speed < 0 || info->speed > 4) {
574 		GP_DEBUG ("Unknown speed: %i", info->speed);
575 		info->speed = PDC_BAUD_9600;
576 	}
577 
578 	/* Caption/Information state (make sure it's valid) */
579 	info->caption = buf[27];
580 	if (info->caption != 0 && info->caption != 1) {
581 		GP_DEBUG ("Unknown caption state: %i", info->caption);
582 		info->caption = PDC_BOOL_OFF;
583 	}
584 
585 	/*
586 	 * buf[28-31]: We don't know. Below are some samples:
587 	 *
588 	 * f8 b2 64 03
589 	 *
590 	 * c6 03 86 28
591 	 *
592 	 * 3a 7f 65 83
593 	 *
594 	 * 23 25 66 83
595 	 */
596 
597 	/* Timer state (make sure it's valid) */
598 	info->timer = buf[32];
599 	if (info->timer != 0 && info->timer != 1) {
600 		GP_DEBUG ("Unknown timer state %i", info->timer);
601 		info->timer = PDC_BOOL_OFF;
602 	}
603 
604 	/* LCD state (make sure it's valid) */
605 	info->lcd = buf[33];
606 	if (info->lcd != 0 && info->lcd != 1) {
607 		GP_DEBUG ("Unknown LCD state %i", info->lcd);
608 		info->lcd = PDC_BOOL_OFF;
609 	}
610 
611 	/* Quality (make sure we know it) */
612 	info->quality = buf[34];
613 	if (info->quality < 0 || info->quality > 2) {
614 		GP_DEBUG ("Unknown quality: %i", info->quality);
615 		info->quality = PDC_QUALITY_NORMAL;
616 	}
617 
618 	/* Here follow lots of 0s */
619 
620 	info->size = 0;
621 
622 	return (GP_OK);
623 }
624 
625 static int
pdc700_set_date(Camera * camera,time_t time,GPContext * context)626 pdc700_set_date (Camera *camera, time_t time, GPContext *context)
627 {
628 	unsigned char cmd[15];
629 	unsigned char buf[512];
630 	unsigned int buf_len = 0;
631 	struct tm *tm;
632 	PDCInfo info;
633 
634 	CR (pdc700_info (camera, &info, context));
635 
636 	tm = localtime(&time);
637 
638 	cmd[3]  = PDC700_CONFIG;
639 	cmd[4]  = PDC_CONF_TIME;
640 
641 	cmd[5]  = (tm->tm_year + 1900) - PDC_EPOCH(&info);
642 	cmd[6]  = tm->tm_mon + 1;
643 	cmd[7]  = tm->tm_mday;
644 	cmd[8]  = tm->tm_hour;
645 	cmd[9]  = tm->tm_min;
646 	cmd[10] = tm->tm_sec;
647 
648 	CR (pdc700_transmit (camera, cmd, 12, buf, &buf_len, context));
649 	return GP_OK;
650 }
651 
652 static int
pdc700_capture(Camera * camera,GPContext * context)653 pdc700_capture (Camera *camera, GPContext *context)
654 {
655         unsigned char cmd[5], buf[1024];
656         unsigned int buf_len = 0;
657 	int r = 0;
658 	int try;
659 	PDCInfo info;
660 
661         cmd[3] = PDC700_CAPTURE;
662 	cmd[4] = 0;
663 
664         CR (pdc700_transmit (camera, cmd, 5, buf, &buf_len, context));
665 
666 	/*
667 	 * This is rather hackish.  The camera needs a little time to recover
668 	 * after taking a picture.  I tried a general-purpose retry thing in
669 	 * pdc_transmit, but that got in the way during initialization.  So
670 	 * I'm leaving this ugly-but-works junk here for now.
671 	 */
672 	for (try = 0; try < 10; try++)
673 	  if ((r = pdc700_info(camera, &info, context)) == GP_OK)
674 	    break;
675 
676         return r;
677 };
678 
679 static int
pdc700_pic(Camera * camera,unsigned int n,unsigned char ** data,unsigned int * size,unsigned char thumb,GPContext * context)680 pdc700_pic (Camera *camera, unsigned int n,
681 	    unsigned char **data, unsigned int *size, unsigned char thumb,
682 	    GPContext *context)
683 {
684 	unsigned char cmd[8];
685 	int r;
686 	PDCPicInfo info;
687 
688 	/* Picture size? Allocate the memory */
689 	CR (pdc700_picinfo (camera, n, &info, context));
690 	*size = thumb ? info.thumb_size : info.pic_size;
691 	*data = malloc (sizeof (char) * *size);
692 	if (!*data)
693 		return (GP_ERROR_NO_MEMORY);
694 
695 	/* Get picture data */
696 	GP_DEBUG ("Getting picture %i...", n);
697 	cmd[3] = (thumb) ? PDC700_THUMB : PDC700_PIC;
698 	cmd[4] = 0; /* No idea what that byte is for */
699 	cmd[5] = n;
700 	cmd[6] = n >> 8;
701 	r = pdc700_transmit (camera, cmd, 8, *data, size, context);
702 	if (r < 0) {
703 		free (*data);
704 		return (r);
705 	}
706 
707 	return (GP_OK);
708 }
709 
710 static int
pdc700_delete(Camera * camera,unsigned int n,GPContext * context)711 pdc700_delete (Camera *camera, unsigned int n, GPContext *context)
712 {
713 	unsigned char cmd[6], buf[1024];
714 	unsigned int buf_len = 0;
715 
716 	cmd[3] = PDC700_DEL;
717 	cmd[4] = n;
718 	CR (pdc700_transmit (camera, cmd, 6, buf, &buf_len, context));
719 
720 	/*
721 	 * We get three bytes back but don't know the meaning of those.
722 	 * Perhaps some error codes with regard to read-only images?
723 	 */
724 
725 	return (GP_OK);
726 }
727 
728 int
camera_id(CameraText * id)729 camera_id (CameraText *id)
730 {
731 	strcpy (id->text, "Polaroid DC700");
732 
733 	return (GP_OK);
734 }
735 
736 static struct {
737 	const char *model;
738 	unsigned short usb_vendor;
739 	unsigned short usb_product;
740 
741 } models[] = {
742 	{"Polaroid:DC700", 0x784, 0x2888},
743 	{NULL, 0, 0}
744 };
745 
746 int
camera_abilities(CameraAbilitiesList * list)747 camera_abilities (CameraAbilitiesList *list)
748 {
749 	int i;
750 	CameraAbilities a;
751 
752 	for (i = 0; models[i].model; i++) {
753 		memset(&a, 0, sizeof(a));
754 		strcpy (a.model, models[i].model);
755 		a.status = GP_DRIVER_STATUS_PRODUCTION;
756 		a.port     = GP_PORT_SERIAL | GP_PORT_USB;
757 		a.usb_vendor = models[i].usb_vendor;
758 		a.usb_product= models[i].usb_product;
759 		a.speed[0] = 9600;
760 		a.speed[1] = 19200;
761 		a.speed[2] = 38400;
762 		a.speed[3] = 57600;
763 		a.speed[4] = 115200;
764 		a.operations        = GP_OPERATION_CAPTURE_IMAGE |
765                                       GP_OPERATION_CONFIG;
766 		a.file_operations   = GP_FILE_OPERATION_DELETE |
767 		                      GP_FILE_OPERATION_PREVIEW;
768 		a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL;
769 
770 		CR (gp_abilities_list_append (list, a));
771 	}
772 
773 	return (GP_OK);
774 }
775 
776 static void
pdc700_expand(unsigned char * src,unsigned char * dst)777 pdc700_expand (unsigned char *src, unsigned char *dst)
778 {
779 	int Y, Y2, U, V;
780 	int x, y;
781 
782 	for (y = 0; y < 60; y++)
783 		for (x = 0; x < 80; x += 2) {
784 			Y  = (char) src[0]; Y  += 128;
785 			U  = (char) src[1]; U  -= 0;
786 			Y2 = (char) src[2]; Y2 += 128;
787 			V  = (char) src[3]; V  -= 0;
788 
789 			if ((Y  > -16) && (Y  < 16)) Y  = 0;
790 			if ((Y2 > -16) && (Y2 < 16)) Y2 = 0;
791 			if ((U  > -16) && (U  < 16)) U  = 0;
792 			if ((V  > -16) && (V  < 16)) V  = 0;
793 
794 			dst[0] = Y + (1.402000 * V);
795 			dst[1] = Y - (0.344136 * U) - (0.714136 * V);
796 			dst[2] = Y + (1.772000 * U);
797 			dst += 3;
798 
799 			dst[0] = Y2 + (1.402000 * V);
800 			dst[1] = Y2 - (0.344136 * U) - (0.714136 * V);
801 			dst[2] = Y2 + (1.772000 * U);
802 			dst += 3;
803 
804 			src += 4;
805 		}
806 }
807 
808 static int
camera_capture(Camera * camera,CameraCaptureType type,CameraFilePath * path,GPContext * context)809 camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path,
810 		GPContext *context)
811 {
812 	int count;
813 	char buf[1024];
814 
815 	CR (pdc700_capture (camera, context));
816 
817 	/*
818 	 * We don't get any info back. However, we need to tell the
819 	 * CameraFilesystem that there is one additional picture.
820 	 */
821 	CR (count = gp_filesystem_count (camera->fs, "/", context));
822 	snprintf (buf, sizeof (buf), "PDC700%04i.jpg", count + 1);
823 	CR (gp_filesystem_append (camera->fs, "/", buf, context));
824 
825 	/* Now tell the frontend where to look for the image */
826 	strncpy (path->folder, "/", sizeof (path->folder));
827 	strncpy (path->name, buf, sizeof (path->name));
828 
829 	return (GP_OK);
830 }
831 
832 static int
del_file_func(CameraFilesystem * fs,const char * folder,const char * file,void * data,GPContext * context)833 del_file_func (CameraFilesystem *fs, const char *folder, const char *file,
834 	       void *data, GPContext *context)
835 {
836 	Camera *camera = data;
837 	int n;
838 
839 	/* We need picture numbers starting with 1 */
840 	CR (n = gp_filesystem_number (fs, folder, file, context));
841 	n++;
842 
843 	CR (pdc700_delete (camera, n, context));
844 
845 	return (GP_OK);
846 }
847 
848 static int
get_file_func(CameraFilesystem * fs,const char * folder,const char * filename,CameraFileType type,CameraFile * file,void * user_data,GPContext * context)849 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
850 	       CameraFileType type, CameraFile *file, void *user_data,
851 	       GPContext *context)
852 {
853 	Camera *camera = user_data;
854 	int n;
855 	unsigned int size;
856 	unsigned char *data = NULL;
857 
858 #if 0
859 	if (type == GP_FILE_TYPE_RAW)
860 		return (GP_ERROR_NOT_SUPPORTED);
861 #endif
862 
863 	/* Get the number of the picture from the filesystem */
864 	CR (n = gp_filesystem_number (camera->fs, folder, filename, context));
865 
866 	/* Get the file */
867 	CR (pdc700_pic (camera, n + 1, &data, &size,
868 			(type == GP_FILE_TYPE_NORMAL) ? 0 : 1, context));
869 	switch (type) {
870 	case GP_FILE_TYPE_NORMAL:
871 
872 		/* Files are always JPEG */
873 		CRF (gp_file_set_data_and_size (file, (char *)data, size), data);
874 		CR (gp_file_set_mime_type (file, GP_MIME_JPEG));
875 		break;
876 
877 	case GP_FILE_TYPE_PREVIEW:
878 
879 		/*
880 		 * Depending on the protocol version, we have different
881 		 * encodings.
882 		 */
883 		if ((data[0]        == 0xff) && (data[1]        == 0xd8) &&
884 		    (data[size - 2] == 0xff) && (data[size - 1] == 0xd9)) {
885 
886 			/* Image is JPEG */
887 			CRF (gp_file_set_data_and_size (file, (char *)data, size),
888 			     data);
889 			CR (gp_file_set_mime_type (file, GP_MIME_JPEG));
890 
891 		} else if (size == 9600) {
892 			const char header[] = "P6\n80 60\n255\n";
893 			unsigned char *ppm;
894 			unsigned int ppm_size;
895 
896 			/*
897 			 * Image is a YUF 2:1:1 format: 4 bytes for each 2
898 			 * pixels. Y0 U0 Y1 V0 Y2 U2 Y3 V2 Y4 U4 Y5 V4 ....
899 			 * So the first four bytes make up the first two
900 			 * pixels. You use Y0, U0, V0 to get pixel0 then Y1,
901 			 * U0, V0 to get pixel 2. Then onto the next 4-byte
902 			 * sequence.
903 			 */
904 			ppm_size = size * 3 / 2;
905 			ppm = malloc (sizeof (char) * ppm_size);
906 			if (!ppm) {
907 				free (data);
908 				return (GP_ERROR_NO_MEMORY);
909 			}
910 			pdc700_expand (data, ppm);
911 			free (data);
912 			CRF (gp_file_append (file, header, strlen (header)),
913 			     ppm);
914 			CRF (gp_file_append (file, (char *)ppm, ppm_size), ppm);
915 			free (ppm);
916 			CR (gp_file_set_mime_type (file, GP_MIME_PPM));
917 
918 		} else {
919 			free (data);
920 			gp_context_error (context, _("%i bytes of an "
921 				"unknown image format have been received. "
922 				"Please write to %s and ask for "
923 				"assistance."), size, MAIL_GPHOTO_DEVEL);
924 			return (GP_ERROR);
925 		}
926 		break;
927 
928 	case GP_FILE_TYPE_RAW:
929 #if 1
930 		CRF (gp_file_set_data_and_size (file, (char *)data, size), data);
931 		CR (gp_file_set_mime_type (file, GP_MIME_RAW));
932 		break;
933 #endif
934 	default:
935 		free (data);
936 		return (GP_ERROR_NOT_SUPPORTED);
937 	}
938 
939 	return (GP_OK);
940 }
941 
942 static int
camera_about(Camera * camera,CameraText * about,GPContext * context)943 camera_about (Camera *camera, CameraText *about, GPContext *context)
944 {
945 	strcpy (about->text, _("Download program for Polaroid DC700 camera. "
946 		"Originally written by Ryan Lantzer "
947 		"<rlantzer@umr.edu> for gphoto-4.x. Adapted for gphoto2 by "
948 		"Lutz Mueller <lutz@users.sf.net>."));
949 
950 	return (GP_OK);
951 }
952 
953 /*
954  * We encapsulate the process of adding an entire radio control.
955  */
956 static void
add_radio(CameraWidget * section,const char * blurb,const char ** opt,int selected)957 add_radio (CameraWidget *section, const char *blurb, const char **opt,
958 	   int selected)
959 {
960 	CameraWidget *child;
961 	int i;
962 
963 	gp_widget_new (GP_WIDGET_RADIO, blurb, &child);
964 
965 	for (i = 0; opt[i]; i++)
966 		gp_widget_add_choice (child, opt[i]);
967 
968 	gp_widget_set_value (child, (void *) opt[selected]);
969 	gp_widget_append (section, child);
970 }
971 
972 
973 static int
camera_get_config(Camera * camera,CameraWidget ** window,GPContext * context)974 camera_get_config (Camera *camera, CameraWidget **window, GPContext *context)
975 {
976 	CameraWidget *child;
977 	CameraWidget *section;
978 	float range;
979 	PDCInfo info;
980 	time_t time;
981 	struct tm tm;
982 	int xtime;
983 
984 	CR (pdc700_info (camera, &info, context));
985 
986 	gp_widget_new (GP_WIDGET_WINDOW, _("Camera Configuration"), window);
987 
988 	gp_widget_new (GP_WIDGET_SECTION, _("Camera"), &section);
989 	gp_widget_append (*window, section);
990 
991 	add_radio (section, LCD_STATE,     bool,    info.lcd);
992 	add_radio (section, SELF_TIMER,    bool,    info.timer);
993 	add_radio (section, SHOW_CAPTIONS, bool,    info.caption);
994 
995 	/* Auto poweroff */
996 	gp_widget_new (GP_WIDGET_RANGE, AUTO_POWEROFF, &child);
997 	gp_widget_set_range (child, 1., 99., 1.);
998 	range = (float) info.auto_poweroff;
999 	gp_widget_set_value (child, &range);
1000 	gp_widget_append (section, child);
1001 	gp_widget_set_info (child, _("How long will it take until the "
1002 				     "camera powers off?"));
1003 
1004 	gp_widget_new (GP_WIDGET_SECTION, _("Image"), &section);
1005 	gp_widget_append (*window, section);
1006 	add_radio (section, IMAGE_QUALITY, quality, info.quality);
1007 	add_radio (section, IMAGE_SIZE, size, info.size);
1008 	add_radio (section, FLASH_SETTING, flash,   info.flash);
1009 
1010 	gp_widget_new (GP_WIDGET_SECTION, _("Date and Time"), &section);
1011 	gp_widget_append (*window, section);
1012 
1013 	/* Date and time */
1014 	tm.tm_year = info.date.year +
1015 		((!strcmp (info.version, "v2.45")) ? 1980 : 2000) - 1900;
1016 	tm.tm_mon = info.date.month - 1;
1017 	tm.tm_mday = info.date.day;
1018 	tm.tm_hour = info.date.hour;
1019 	tm.tm_min = info.date.minute;
1020 	tm.tm_sec = info.date.second;
1021 	time = mktime (&tm);
1022 	GP_DEBUG ("time: %X", (unsigned int) time);
1023 	gp_widget_new (GP_WIDGET_DATE, _("Date and Time"), &child);
1024 	gp_widget_append (section, child);
1025 	xtime = time;
1026 	gp_widget_set_value (child, &xtime);
1027 	return GP_OK;
1028 }
1029 
1030 static int
which_radio_button(CameraWidget * window,const char * label,const char * const * opt)1031 which_radio_button (CameraWidget *window, const char *label,
1032 		    const char * const *opt)
1033 {
1034   	CameraWidget *child;
1035 	int i;
1036 	const char *value;
1037 
1038 	if (gp_widget_get_child_by_label (window, label, &child) != GP_OK)
1039 		return -1;
1040 
1041 	if (!gp_widget_changed (child))
1042 		return -1;
1043 
1044 	gp_widget_set_changed (child, FALSE);
1045 	gp_widget_get_value (child, &value);
1046 
1047 	for (i = 0; opt[i]; i++)
1048 		if (!strcmp (value, opt[i]))
1049 			return i;
1050 
1051 	return -1;
1052 }
1053 
1054 static int
camera_set_config(Camera * camera,CameraWidget * window,GPContext * context)1055 camera_set_config (Camera *camera, CameraWidget *window, GPContext *context)
1056 {
1057   	CameraWidget *child;
1058 	int i = 0, r;
1059 	float range;
1060 
1061 	if ((i = which_radio_button (window, IMAGE_QUALITY, quality)) >= 0)
1062 		CR (pdc700_config (camera, PDC_CONF_QUALITY,
1063 				   (unsigned char) i, context));
1064 
1065 	if ((i = which_radio_button (window, IMAGE_SIZE, size)) >= 0)
1066 		CR (pdc700_config (camera, PDC_CONF_SIZE,
1067 				   (unsigned char) i, context));
1068 
1069 	if ((i = which_radio_button (window, FLASH_SETTING, flash)) >= 0)
1070 		CR (pdc700_config (camera, PDC_CONF_FLASH,
1071 				   (unsigned char) i, context));
1072 
1073 	if ((i = which_radio_button (window, LCD_STATE, bool)) >= 0)
1074 		CR (pdc700_config (camera, PDC_CONF_LCD,
1075 				   (unsigned char) i, context));
1076 
1077 	if ((i = which_radio_button (window, SELF_TIMER, bool)) >= 0)
1078 		CR (pdc700_config (camera, PDC_CONF_TIMER,
1079 				   (unsigned char) i, context));
1080 
1081 	if ((i = which_radio_button (window, SHOW_CAPTIONS, bool)) >= 0)
1082 		CR (pdc700_config (camera, PDC_CONF_CAPTION,
1083 				   (unsigned char) i, context));
1084 
1085 	/* Auto poweroff */
1086 	r = gp_widget_get_child_by_label (window, AUTO_POWEROFF, &child);
1087 	if ((r == GP_OK) && gp_widget_changed (child)) {
1088 		gp_widget_set_changed (child, FALSE);
1089 		gp_widget_get_value (child, &range);
1090 		CR (pdc700_config (camera, PDC_CONF_POWEROFF,
1091 				   (unsigned char) range, context));
1092 	}
1093 
1094 	/* Date and time */
1095 	r = gp_widget_get_child_by_label (window, _("Date and Time"), &child);
1096 	if ((r == GP_OK) && gp_widget_changed (child)) {
1097 		gp_widget_set_changed (child, FALSE);
1098 		gp_widget_get_value (child, &i);
1099 		if (i != -1)
1100 		  pdc700_set_date(camera, (time_t) i, context);
1101 		else
1102 		  GP_DEBUG ("date widget returned -1, not setting datee/time");
1103 		/* GP_DEBUG ("Implement setting of date & time!"); */
1104 	}
1105 
1106 
1107 	return GP_OK;
1108 }
1109 
1110 static int
camera_summary(Camera * camera,CameraText * about,GPContext * context)1111 camera_summary (Camera *camera, CameraText *about, GPContext *context)
1112 {
1113 	PDCInfo info;
1114 
1115 	CR (pdc700_info (camera, &info, context));
1116 
1117 	sprintf (about->text, _(
1118 		"Date: %i/%02i/%02i %02i:%02i:%02i\n"
1119 		"Pictures taken: %i\n"
1120 		"Free pictures: %i\n"
1121 		"Software version: %s\n"
1122 		"Baudrate: %s\n"
1123 		"Memory: %i megabytes\n"
1124 		"Camera mode: %s\n"
1125 		"Image quality: %s\n"
1126 		"Flash setting: %s\n"
1127 		"Information: %s\n"
1128 		"Timer: %s\n"
1129 		"LCD: %s\n"
1130 		"Auto power off: %i minutes\n"
1131 		"Power source: %s"),
1132 		info.date.year + ((!strcmp (info.version, "v2.45")) ? 1980 :
1133 								      2000),
1134 		info.date.month, info.date.day,
1135 		info.date.hour, info.date.minute, info.date.second,
1136 		info.num_taken, info.num_free, info.version,
1137 		_(speed[info.speed]),
1138 		info.memory,
1139 		_(mode[info.mode]),
1140 		_(quality[info.quality]),
1141 		_(flash[info.flash]),
1142 		_(bool[info.caption]),
1143 		_(bool[info.timer]),
1144 		_(bool[info.lcd]),
1145 		info.auto_poweroff,
1146 		_(power[info.ac_power]));
1147 
1148 	return (GP_OK);
1149 }
1150 
1151 static int
file_list_func(CameraFilesystem * fs,const char * folder,CameraList * list,void * data,GPContext * context)1152 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
1153 		void *data, GPContext *context)
1154 {
1155 	Camera *camera = data;
1156 	PDCInfo info;
1157 
1158 	/* Fill the list */
1159 	CR (pdc700_info (camera, &info, context));
1160 	gp_list_populate (list, "PDC700%04i.jpg", info.num_taken);
1161 
1162 	return (GP_OK);
1163 }
1164 
1165 static int
get_info_func(CameraFilesystem * fs,const char * folder,const char * file,CameraFileInfo * info,void * data,GPContext * context)1166 get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
1167 	       CameraFileInfo *info, void *data, GPContext *context)
1168 {
1169 	int n;
1170 	Camera *camera = data;
1171 	PDCPicInfo pic_info;
1172 
1173 	/* Get the picture number from the CameraFilesystem */
1174 	CR (n = gp_filesystem_number (fs, folder, file, context));
1175 
1176 	CR (pdc700_picinfo (camera, n + 1, &pic_info, context));
1177 	info->file.fields = GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE;
1178 	info->preview.fields = GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE;
1179 	strcpy (info->file.type, GP_MIME_JPEG);
1180 	strcpy (info->preview.type, GP_MIME_JPEG);
1181 	info->file.size = pic_info.pic_size;
1182 	info->preview.size = pic_info.thumb_size;
1183 
1184 	return (GP_OK);
1185 }
1186 
1187 static CameraFilesystemFuncs fsfuncs = {
1188 	.file_list_func = file_list_func,
1189 	.get_info_func = get_info_func,
1190 	.get_file_func = get_file_func,
1191 	.del_file_func = del_file_func
1192 };
1193 
1194 int
camera_init(Camera * camera,GPContext * context)1195 camera_init (Camera *camera, GPContext *context)
1196 {
1197 	int result = GP_OK, i;
1198 	GPPortSettings settings;
1199 	int speeds[] = {115200, 9600, 57600, 19200, 38400};
1200 
1201         /* First, set up all the function pointers */
1202 	camera->functions->capture = camera_capture;
1203 	camera->functions->summary = camera_summary;
1204         camera->functions->about   = camera_about;
1205 	camera->functions->get_config = camera_get_config;
1206 	camera->functions->set_config = camera_set_config;
1207 
1208 	/* Now, tell the filesystem where to get lists and info */
1209 	gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
1210 
1211 	/* Check if the camera is really there */
1212 	CR (gp_port_get_settings (camera->port, &settings));
1213 	CR (gp_port_set_timeout (camera->port, 1000));
1214 
1215 	switch (camera->port->type) {
1216 	case GP_PORT_SERIAL:
1217 
1218 		/* Figure out current speed */
1219 		for (i = 0; i < 5; i++) {
1220 			settings.serial.speed = speeds[i];
1221 			CR (gp_port_set_settings (camera->port, settings));
1222 			result = pdc700_init (camera, context);
1223 			if (result == GP_OK)
1224 				break;
1225 		}
1226 		if (i == 5)
1227 			return (result);
1228 
1229 		/* Set the speed to the highest one */
1230 		if (speeds[i] < 115200) {
1231 			CR (pdc700_baud (camera, 115200, context));
1232 			settings.serial.speed = 115200;
1233 			CR (gp_port_set_settings (camera->port, settings));
1234 		}
1235 		break;
1236 	case GP_PORT_USB:
1237 		/* Use the defaults the core parsed */
1238 		CR (gp_port_set_settings (camera->port, settings));
1239 		CR (pdc700_init (camera, context));
1240 		break;
1241 	default:
1242 		gp_context_error (context, _("The requested port type (%i) "
1243 				     "is not supported by this driver."),
1244 				     camera->port->type);
1245 		return (GP_ERROR_NOT_SUPPORTED);
1246 	}
1247 
1248 	return (GP_OK);
1249 }
1250