1 /* Sony DSC-F55 & MSAC-SR1 - gPhoto2 camera library
2  * Copyright 2001, 2002, 2004 Raymond Penners <raymond@dotsphinx.com>
3  * Copyright 2000 Mark Davies <mdavies@dial.pipex.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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 <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include <gphoto2/gphoto2.h>
30 #include "sony.h"
31 
32 #define GP_MODULE "sony55"
33 
34 /**
35  * Constants
36  */
37 #define SONY_CONVERSE_RETRY 5
38 
39 #define SONY_INVALID_CHECKSUM	0x40
40 #define SONY_INVALID_SEQUENCE	0x41
41 #define SONY_RESET_SEQUENCE	0x42
42 #define SONY_RESEND_PACKET	0x43
43 
44 #define SONY_ESCAPE_CHAR		0x7d
45 #define SONY_START_CHAR		0xc0
46 #define SONY_END_CHAR		0xc1
47 
48 
49 static const unsigned char START_PACKET = 192;
50 static const unsigned char END_PACKET = 193;
51 
52 static const char ESC_START_STRING[] = { 0x7d, 0xe0 };
53 static const char ESC_END_STRING[] = { 0x7d, 0xe1 };
54 static const char ESC_ESC_STRING[] = { 0x7d, 0x5d };
55 
56 static const unsigned char PacketCodes[2] = { 192, 193 };
57 
58 
59 #if defined(USE_ALL_TYPES)
60 static unsigned char EmailImage[] =
61     { 0, 2, 2, 0, 16, '/', 'M', 'S', 'S', 'O', 'N', 'Y', '/', 'I', 'M',
62 'C',
63 	'I', 'F', '1', '0', '0'
64 };
65 #endif
66 
67 
68 static unsigned char IdentString[] =
69     { 0, 1, 1, 'S', 'O', 'N', 'Y', ' ', ' ', ' ', ' ', ' ' };
70 static unsigned char EmptyPacket[] = { 0 };	/* null packet */
71 static unsigned char SetTransferRate[] = { 0, 1, 3, 0 };
72 static unsigned char SendImageCount[] = { 0, 2, 1 };
73 static unsigned char StillImage[] =
74     { 0, 2, 2, 0, 14, '/', 'D', 'C', 'I', 'M', '/', '1', '0', '0', 'M',
75 'S',
76 	'D', 'C', 'F'
77 };
78 static unsigned char MpegImage[] =
79     { 0, 2, 2, 0, 16, '/', 'M', 'S', 'S', 'O', 'N', 'Y', '/', 'M', 'O',
80 'M',
81 	'L', '0', '0', '0', '1'
82 };
83 static unsigned char SelectImage[] = { 0, 2, 48, 0, 0, 0, 0 };
84 static unsigned char SendImage[] = { 0, 2, '1', 0, 1, 0, 0 };
85 static unsigned char SendNextImagePacket[] = { 0, 2, '1', 0 };
86 static unsigned char SendThumbnail[] = { 0, 2, '0', 0 };
87 
88 #if 0
89 static unsigned char SelectCamera[] = { 0, 1, 2 };
90 static unsigned char DownloadComplete[] = { 0, 2, '0', 255 };
91 static unsigned char X10Camera[] = { 0, 1, 5 };
92 
93 static unsigned char X5Camera[] = { 0, 2, 1 };
94 static unsigned char X13Camera[] = { 0, 2, 18 };
95 
96 #endif
97 
98 
99 /*
100  * This array contains the expected packet sequence code to be applied/
101  * checked for.
102  */
103 static const unsigned char sony_sequence[] =
104     { 14, 0, 32, 34, 66, 68, 100, 102, 134, 136, 168, 170, 202, 204, 236,
105 238,
106 	255
107 };
108 
109 
110 #ifdef __linux__
111 static const int baud_rate = 115200;
112 #else
113 # ifdef __sun__
114 static const int baud_rate = 38400;
115 # else
116 static const int baud_rate = 9600;
117 # endif
118 #endif
119 
120 
121 
122 
123 
124 /**
125  * Returns transfer rate ID
126  */
127 static int
sony_baud_to_id(long baud)128 sony_baud_to_id(long baud)
129 {
130 	int r;
131 
132 	switch (baud) {
133 	case 115200:
134 		r = 4;
135 		break;
136 	case 57600:
137 		r = 3;
138 		break;		/* FIXME ??? */
139 	case 38400:
140 		r = 2;
141 		break;		/* works on sun */
142 	case 19200:
143 		r = 1;
144 		break;		/* works on sun */
145 	default:
146 	case 9600:
147 		r = 0;
148 		break;		/* works on sun */
149 	}
150 	return r;
151 }
152 
153 
154 /**
155  * Reads a byte
156  */
157 static int
sony_read_byte(Camera * camera,unsigned char * b)158 sony_read_byte(Camera * camera, unsigned char *b)
159 {
160 	int n = gp_port_read(camera->port, (char *)b, 1);
161 	if (n != 1)
162 		return GP_ERROR;
163 	else
164 		return GP_OK;
165 }
166 
167 
168 
169 /**
170  * Returns the checksum for a packet
171  */
172 static unsigned char
sony_packet_checksum(Packet * p)173 sony_packet_checksum(Packet * p)
174 {
175 	unsigned short int o = 0;
176 	unsigned long int sum = 0;
177 
178 	sum = 0;
179 
180 	while (o < p->length)
181 		sum += p->buffer[o++];
182 
183 	return 256 - (sum & 255);
184 }
185 
186 /**
187  * Returns TRUE iff the packet is valid
188  */
189 static int
sony_packet_validate(Camera * camera,Packet * p)190 sony_packet_validate(Camera * camera, Packet * p)
191 {
192 	unsigned char c = sony_packet_checksum(p);
193 
194 	if (c != p->checksum) {
195 		GP_DEBUG(
196 				"sony_packet_validate: invalid checksum");
197 		return SONY_INVALID_CHECKSUM;
198 	}
199 
200 	if (129 == p->buffer[0]) {
201 		GP_DEBUG(
202 				"sony_packet_validate: resend packet");
203 		return SONY_RESEND_PACKET;
204 	}
205 
206 	if (sony_sequence[camera->pl->sequence_id] != p->buffer[0]) {
207 		GP_DEBUG(
208 				"sony_packet_validate: invalid sequence");
209 		return SONY_INVALID_SEQUENCE;
210 	}
211 
212 	return GP_OK;
213 }
214 
215 /**
216  * Constructs a packet.
217  */
218 static int
sony_packet_make(Camera * camera,Packet * p,unsigned char * buffer,unsigned short int length)219 sony_packet_make(Camera * camera, Packet * p, unsigned char *buffer,
220 		 unsigned short int length)
221 {
222 	p->length = 0;
223 
224 	while (length--)
225 		p->buffer[p->length++] = *(buffer++);
226 
227 	if (255 == sony_sequence[++(camera->pl->sequence_id)])
228 		camera->pl->sequence_id = 0;
229 
230 	p->buffer[0] = sony_sequence[camera->pl->sequence_id++];
231 
232 	if (255 == sony_sequence[camera->pl->sequence_id])
233 		camera->pl->sequence_id = 0;
234 
235 	p->checksum = sony_packet_checksum(p);
236 
237 	return TRUE;
238 }
239 
240 /**
241  * Reads a packet.
242  */
sony_packet_read(Camera * camera,Packet * pack)243 static int sony_packet_read(Camera * camera, Packet * pack)
244 {
245 	unsigned int n;
246 	unsigned char byte = 0;
247 	static Packet p;
248 
249 	GP_DEBUG(
250 			"sony_packet_read()");
251 	p.length = 0;
252 
253 	for (n = 0; n < 2; n++) {
254 		for (byte = 0; byte != (unsigned char) PacketCodes[n];) {
255 			if (sony_read_byte(camera, &byte) == GP_ERROR) {
256 				return FALSE;
257 			}
258 
259 			if (n > 0) {
260 				if (SONY_ESCAPE_CHAR == byte) {
261 					unsigned char extra;
262 
263 					sony_read_byte(camera, &extra);
264 
265 					switch (extra) {
266 					case 1:
267 					case 7:
268 					case 0xe1:
269 					case 0xe0:
270 						extra &= 0xcf;
271 						p.buffer[p.length++] =
272 						    extra;
273 						continue;
274 					case 0x5d:
275 						p.buffer[p.length++] =
276 						    byte;
277 						continue;
278 					default:
279 						p.buffer[p.length++] =
280 						    byte;
281 						p.buffer[p.length++] =
282 						    extra;
283 						continue;
284 					}
285 				} else
286 					p.buffer[p.length++] = byte;
287 			}
288 		}
289 	}
290 
291 	p.length -= 2;
292 	p.checksum = p.buffer[p.length];
293 
294 	memcpy(pack, &p, sizeof(Packet));
295 	return TRUE;
296 }
297 
298 /**
299  * Sends a packet
300  */
301 static int
sony_packet_write(Camera * camera,Packet * p)302 sony_packet_write(Camera * camera, Packet * p)
303 {
304 	unsigned short int count;
305 	int rc;
306 
307 	GP_DEBUG(
308 			"sony_packet_write()");
309 
310         /**
311 	 * This usleep is necessary when using (relatively) fast CPUs,
312 	 * as P4 2Ghz. Without it gphoto2 stops with a segmentation fault
313 	 * and the --debug message sony_packet_validate: invalid sequence
314 	 * Failed to read packet during transfer. The delay is somewhat
315 	 * arbitrary. (alberto-g@(remove_me)inventati.org)
316 	 **/
317 	usleep(10000);
318 
319 	rc = gp_port_write(camera->port, (char *)&START_PACKET, 1);
320 
321 	p->buffer[p->length] = p->checksum;
322 
323 	for (count = 0; count < p->length + 1 && rc != GP_ERROR; count++) {
324 		switch ((unsigned char) p->buffer[count]) {
325 		case SONY_ESCAPE_CHAR:
326 			rc = gp_port_write(camera->port, ESC_ESC_STRING, 2);
327 			break;
328 
329 		case SONY_START_CHAR:
330 			rc = gp_port_write(camera->port, ESC_START_STRING, 2);
331 			break;
332 
333 		case SONY_END_CHAR:
334 			rc = gp_port_write(camera->port, ESC_END_STRING, 2);
335 			break;
336 
337 		default:
338 			rc = gp_port_write(camera->port,
339 					   (char *) &p->buffer[count], 1);
340 			break;
341 		}
342 	}
343 	if (rc != GP_ERROR)
344 		rc = gp_port_write(camera->port, (char *) &END_PACKET, 1);
345 	return rc;
346 }
347 
348 /**
349  * Communicates packets
350  */
351 static int
sony_converse(Camera * camera,Packet * out,unsigned char * str,int len)352 sony_converse(Camera * camera, Packet * out, unsigned char *str, int len)
353 {
354 	Packet ps;
355 	char old_sequence = 33;
356 	int sequence_count = 0;
357 	int invalid_sequence = 0;
358 	int count;
359 	int rc;
360 
361 	GP_DEBUG( "sony_converse()");
362 	sony_packet_make(camera, &ps, str, len);
363 
364 	for (count = 0; count < SONY_CONVERSE_RETRY; count++) {
365 		rc = sony_packet_write(camera, &ps);
366 
367 		if (rc == GP_OK) {
368 			if (sony_packet_read(camera, out)) {
369 				switch (sony_packet_validate(camera, out)) {
370 				case SONY_INVALID_CHECKSUM:
371 					if (invalid_sequence) {
372 						sony_packet_make(camera,
373 								 &ps, str,
374 								 len);
375 						break;
376 					}
377 
378 					GP_DEBUG ("Checksum invalid");
379 					ps.buffer[0] = 129;
380 					ps.checksum =
381 					    sony_packet_checksum(&ps);
382 					break;
383 
384 				case SONY_INVALID_SEQUENCE:
385 					if (camera->pl->model
386 					    != SONY_MODEL_DSC_F55) {
387 						invalid_sequence = 1;
388 						sony_packet_make(camera,
389 								 &ps, str,
390 								 len);
391 						break;
392 					}
393 
394 					if (old_sequence == out->buffer[0])
395 						sequence_count++;
396 					else if (0 == sequence_count)
397 						old_sequence =
398 						    out->buffer[0];
399 
400 					if (sequence_count == 4) {
401 						GP_DEBUG ("Attempting to reset sequence id - image may be corrupt.");
402 						camera->pl->sequence_id = 0;
403 
404 						while (sony_sequence
405 						       [camera->pl->
406 							sequence_id] !=
407 						       old_sequence)
408 							camera->pl->
409 							    sequence_id++;
410 
411 						return GP_OK;
412 					}
413 					GP_DEBUG ("Invalid Sequence");
414 					ps.buffer[0] = 129;
415 					ps.checksum =
416 					    sony_packet_checksum(&ps);
417 					break;
418 
419 				case SONY_RESET_SEQUENCE:
420 					camera->pl->sequence_id = 0;
421 					return GP_OK;
422 
423 				case SONY_RESEND_PACKET:
424 					GP_DEBUG ("Resending Packet");
425 					break;
426 
427 				case GP_OK:
428 					return GP_OK;
429 
430 				default:
431 					GP_DEBUG ("Unknown Error");
432 					break;
433 				}
434 			} else {
435 				/* printf("Incomplete packet\n"); */
436 				ps.buffer[0] = 129;
437 				ps.checksum = sony_packet_checksum(&ps);
438 			}
439 		}
440 	}
441 
442 	GP_DEBUG(
443 			"Failed to read packet during transfer.");
444 
445 	return GP_ERROR;
446 }
447 
448 
449 /**
450  * Sets baud rate
451  */
452 static int
sony_baud_port_set(Camera * camera,long baud)453 sony_baud_port_set(Camera * camera, long baud)
454 {
455 	gp_port_settings settings;
456 
457 	gp_port_get_settings(camera->port, &settings);
458 	settings.serial.speed = baud;
459 	gp_port_set_settings(camera->port, settings);
460 
461 	usleep(70000);
462 
463 	return GP_OK;
464 }
465 
466 /**
467  * Sets baud rate
468  */
469 static int
sony_baud_set(Camera * camera,long baud)470 sony_baud_set(Camera * camera, long baud)
471 {
472 	Packet dp;
473 	int rc;
474 
475 	GP_DEBUG( "sony_baud_set(%ld)",
476 			baud);
477 
478 	if (camera->pl->current_baud_rate != baud) {
479 		/* FIXME */
480 		SetTransferRate[3] = sony_baud_to_id(baud);
481 
482 		rc = sony_converse(camera, &dp, SetTransferRate, 4);
483 		if (rc == GP_OK) {
484 			sony_baud_port_set(camera, baud);
485 			rc = sony_converse(camera, &dp, EmptyPacket, 1);
486 			if (rc == GP_OK) {
487 				camera->pl->current_baud_rate = baud;
488 			}
489 			usleep(100000);	/* 50000 was good too, jw */
490 
491 		}
492 	}
493 	else {
494 		rc = GP_OK;
495 	}
496 	return rc;
497 }
498 
499 /**
500  * Port initialisation
501  */
502 static int
sony_init_port(Camera * camera)503 sony_init_port (Camera *camera)
504 {
505 	gp_port_settings settings;
506 	int rc;
507 
508 	rc = gp_port_set_timeout (camera->port, 5000);
509 	if (rc == GP_OK) {
510 
511 		gp_port_get_settings(camera->port, &settings);
512 
513 		settings.serial.speed = 9600;
514 		settings.serial.bits = 8;
515 		settings.serial.parity = 0;
516 		settings.serial.stopbits = 1;
517 
518 		rc = gp_port_set_settings(camera->port, settings);
519 		if (rc == GP_OK) {
520 			rc = gp_port_flush(camera->port, 0);
521 		}
522 	}
523 	return rc;
524 }
525 
526 /**
527  * Establish first contact (remember the prime directive? :)
528  */
529 static int
sony_init_first_contact(Camera * camera)530 sony_init_first_contact (Camera *camera)
531 {
532 	int count = 0;
533 	Packet dp;
534 	int rc = GP_ERROR;
535 
536 	for (count = 0; count < 3; count++) {
537 		camera->pl->sequence_id = 0;
538 
539 		rc = sony_converse(camera, &dp, IdentString, 12);
540 		if (rc == GP_OK) {
541 			GP_DEBUG(
542 					"Init OK");
543 			break;
544 		}
545 		usleep(2000);
546 		GP_DEBUG(
547 				"Init - Fail %u", count + 1);
548 	}
549 	return rc;
550 }
551 
552 /**
553  * Device supports MPEG?
554  */
555 static int
sony_is_mpeg_supported(Camera * camera)556 sony_is_mpeg_supported (Camera * camera)
557 {
558 	return camera->pl->model == SONY_MODEL_DSC_F55;
559 }
560 
561 /**
562  * Initialises camera
563  */
564 int
sony_init(Camera * camera,SonyModel model)565 sony_init (Camera * camera, SonyModel model)
566 {
567 	int rc;
568 	camera->pl->model = model;
569 	camera->pl->current_baud_rate = -1;
570 	camera->pl->current_mpeg_mode = -1;
571 
572 	rc = sony_init_port (camera);
573 	if (rc == GP_OK)
574 		rc = sony_init_first_contact (camera);
575 
576 	return rc;
577 }
578 
579 /**
580  * Reset the camera sequence count and baud rate.
581  */
582 int
sony_exit(Camera * camera)583 sony_exit(Camera * camera)
584 {
585 	Packet dp;
586 	int rc = GP_ERROR;
587 
588 	rc = sony_baud_set(camera, 9600);
589 	while (rc == GP_OK && camera->pl->sequence_id > 0) {
590 		rc = sony_converse(camera, &dp, EmptyPacket, 1);
591 	}
592 
593 	return rc;
594 }
595 
596 
597 static int
sony_set_file_mode(Camera * camera,SonyFileType file_type)598 sony_set_file_mode(Camera * camera, SonyFileType file_type)
599 {
600 	int rc = GP_OK;
601 	Packet dp;
602 	if (file_type == SONY_FILE_MPEG) {
603 		if (camera->pl->current_mpeg_mode != 1) {
604 			rc = sony_converse(camera, &dp, MpegImage, 21);
605 			if (rc == GP_OK) {
606 				camera->pl->current_mpeg_mode = 1;
607 			}
608 		}
609 	}
610 	else {
611 		if (camera->pl->current_mpeg_mode != 0) {
612 			rc = sony_converse(camera, &dp, StillImage, 19);
613 			if (rc == GP_OK) {
614 				camera->pl->current_mpeg_mode = 0;
615 			}
616 		}
617 	}
618 	return rc;
619 }
620 
621 
622 /**
623  * Return count of images taken.
624  */
625 int
sony_file_count(Camera * camera,SonyFileType file_type,int * count)626 sony_file_count(Camera * camera, SonyFileType file_type, int *count)
627 {
628 	Packet dp;
629 	int rc, nr;
630 
631 	GP_DEBUG( "sony_file_count()");
632 	if (file_type == SONY_FILE_MPEG && (! sony_is_mpeg_supported(camera))) {
633 		*count = 0;
634 		return GP_OK;
635 	}
636 	*count = -1;
637 	rc = sony_converse(camera, &dp, SetTransferRate, 4);
638 	if (rc != GP_OK)
639 		return rc;
640 	rc = sony_set_file_mode(camera, file_type);
641 	if (rc != GP_OK)
642 		return rc;
643 	rc = sony_converse(camera, &dp, SendImageCount, 3);
644 	if (rc != GP_OK)
645 		return rc;
646 	nr = dp.buffer[5] | (dp.buffer[4]<<8);
647 	GP_DEBUG ("count = %d", nr);
648 	*count = nr;
649 	return GP_OK;
650 }
651 
652 
653 
654 /**
655  * Fetches file name.
656  */
657 int
sony_file_name_get(Camera * camera,int imageid,SonyFileType mpeg,char buf[13])658 sony_file_name_get(Camera *camera, int imageid, SonyFileType mpeg, char buf[13])
659 {
660 	Packet dp;
661 	int rc;
662 
663 	GP_DEBUG( "sony_file_name_get()");
664 	rc = sony_set_file_mode(camera, mpeg);
665 	if (rc != GP_OK)
666 		return rc;
667 	sony_baud_set(camera, baud_rate);
668 	/* FIXME: Not nice, changing global data like this. */
669 	SelectImage[3] = (imageid >> 8);
670 	SelectImage[4] = imageid & 0xff;
671 	rc = sony_converse(camera, &dp, SelectImage, 7);
672 	if (rc != GP_OK)
673 		return rc;
674 	memcpy(buf, &dp.buffer[5], 8);
675 	buf[8] = '.';
676 	memcpy(buf+9, &dp.buffer[5+8], 3);
677 	buf[12] = 0;
678 	return rc;
679 }
680 
681 
682 /**
683  * Is it an MPEG file?
684  */
685 int
sony_is_mpeg_file_name(const char * file_name)686 sony_is_mpeg_file_name(const char * file_name)
687 {
688 	return strncmp(file_name,"MOV",3)==0;
689 }
690 
691 
692 
693 /**
694  * Fetches an image.
695  */
696 static int
sony_file_get(Camera * camera,int imageid,int file_type,CameraFile * file,GPContext * context)697 sony_file_get(Camera * camera, int imageid, int file_type,
698 	      CameraFile * file, GPContext *context)
699 {
700 	int sc;			/* count of bytes to skip at start of packet */
701 	Packet dp;
702 	int rc;
703 	char buffer[128];
704 
705 	GP_DEBUG( "sony_file_get()");
706 
707 	rc = sony_set_file_mode(camera, file_type);
708 	if (rc != GP_OK) {
709 		return rc;
710 	}
711 
712 	if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
713 		return GP_ERROR_CANCEL;
714 	}
715 
716 	rc = gp_file_clean(file);
717 	if (rc == GP_OK) {
718 		gp_file_set_mime_type (file, GP_MIME_JPEG);
719 		/* The file name we specify here is not important,
720 		 * since the calling function, gp_filesystem_get_file_impl,
721 		 * overwrites it with the correct one.
722 		 */
723 		sprintf(buffer, SONY_FILE_NAME_FMT, imageid);
724 
725 		sony_baud_set(camera, baud_rate);
726 
727 		rc = sony_set_file_mode(camera, file_type);
728 		if (rc == GP_OK) {
729 			if (file_type == SONY_FILE_THUMBNAIL) {
730 				sc = 0x247;
731 				SelectImage[3] = (imageid >> 8);
732 				SelectImage[4] = imageid & 0xff;
733 				sony_converse(camera, &dp, SelectImage, 7);
734 
735 				if (camera->pl->model
736 				    != SONY_MODEL_DSC_F55) {
737 					gp_file_append(file,
738 						       "\xff\xd8\xff", 3);
739 				}
740 
741 				for (;;) {
742 					if (gp_context_cancel(context)
743 					    == GP_CONTEXT_FEEDBACK_CANCEL) {
744 
745 						rc = GP_ERROR_CANCEL;
746 						break;
747 					}
748 					gp_context_idle(context);
749 
750 					sony_converse(camera, &dp,
751 						      SendThumbnail, 4);
752 
753 					gp_file_append(file,
754 						       (char *) dp.buffer +
755 						       sc, dp.length - sc);
756 					sc = 7;
757 
758 					if (3 == dp.buffer[4])
759 						break;
760 				}
761 			} else {
762 				sc = 11;
763 
764 				SendImage[3] = (imageid >> 8);
765 				SendImage[4] = imageid;
766 				sony_converse(camera, &dp, SendImage, 7);
767 
768 				for (;;) {
769 					if (gp_context_cancel(context)
770 					    == GP_CONTEXT_FEEDBACK_CANCEL) {
771 
772 						rc = GP_ERROR_CANCEL;
773 						break;
774 					}
775 					gp_context_idle(context);
776 
777 					gp_file_append(file,
778 						       (char *) dp.buffer +
779 						       sc, dp.length - sc);
780 
781 					if (file_type == SONY_FILE_EXIF) {
782 						const char *fdata;
783 						unsigned long fsize;
784 
785 						gp_file_get_data_and_size
786 							(file, &fdata, &fsize);
787 						/* FIXME: 4096 is a rather */
788 						/* arbitrary value */
789 						if (fsize > 4096)
790 							break;
791 					}
792 
793 					sc = 7;
794 
795 					if (3 == dp.buffer[4])
796 						break;
797 
798 					sony_converse(camera, &dp,
799 						      SendNextImagePacket,
800 						      4);
801 				}
802 			}
803 		}
804 		sony_baud_set(camera, 9600);
805 
806 		if (rc != GP_OK) {
807 			gp_file_clean(file);
808 		}
809 	}
810 	return rc;
811 }
812 
813 /**
814  * Fetches a thumbnail image.
815  */
816 int
sony_thumbnail_get(Camera * camera,int imageid,CameraFile * file,GPContext * context)817 sony_thumbnail_get(Camera * camera, int imageid, CameraFile * file, GPContext *context)
818 {
819 	return sony_file_get(camera, imageid, SONY_FILE_THUMBNAIL, file, context);
820 }
821 
822 /**
823  * Fetches an image.
824  */
825 int
sony_image_get(Camera * camera,int imageid,CameraFile * file,GPContext * context)826 sony_image_get(Camera * camera, int imageid, CameraFile * file, GPContext *context)
827 {
828 	return sony_file_get(camera, imageid, SONY_FILE_IMAGE, file, context);
829 }
830 
831 /**
832  * Fetches EXIF information.
833  */
834 int
sony_exif_get(Camera * camera,int imageid,CameraFile * file,GPContext * context)835 sony_exif_get(Camera * camera, int imageid, CameraFile * file, GPContext *context)
836 {
837 	return sony_file_get(camera, imageid, SONY_FILE_EXIF, file, context);
838 }
839 
840 /**
841  * Fetches an Mpeg.
842  */
843 int
sony_mpeg_get(Camera * camera,int imageid,CameraFile * file,GPContext * context)844 sony_mpeg_get(Camera * camera, int imageid, CameraFile * file, GPContext *context)
845 {
846 	return sony_file_get(camera, imageid, SONY_FILE_MPEG, file, context);
847 }
848 
849 
850 /**
851  * Fetches image details.
852  */
853 int
sony_image_info(Camera * camera,int imageid,SonyFileType file_type,CameraFileInfo * info,GPContext * context)854 sony_image_info(Camera * camera, int imageid, SonyFileType file_type,
855 		CameraFileInfo * info, GPContext *context)
856 {
857 	unsigned int l = 0;
858 	int rc;
859 	Packet dp;
860 
861 	rc = sony_set_file_mode(camera, file_type);
862 	if (rc != GP_OK) {
863 		return rc;
864 	}
865 
866 	if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
867 		return GP_ERROR_CANCEL;
868 	}
869 
870 	SelectImage[3] = (imageid >> 8);
871 	SelectImage[4] =  imageid & 0xff;
872 	rc = sony_converse(camera, &dp, SelectImage, 7);
873 	if (rc == GP_OK) {
874 		l = (l << 8) | dp.buffer[16];
875 		l = (l << 8) | dp.buffer[17];
876 		l = (l << 8) | dp.buffer[18];
877 		l = (l << 8) | dp.buffer[19];
878 
879 		info->file.fields = GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE;
880 		info->file.size = l;
881 
882 		info->preview.fields = GP_FILE_INFO_TYPE;
883 
884 		if (file_type == SONY_FILE_MPEG) {
885 			strcpy (info->file.type, GP_MIME_AVI);
886 		}
887 		else {
888 			strcpy (info->file.type, GP_MIME_JPEG);
889 		}
890 	}
891 	return rc;
892 }
893 
894 
895 
896 /*
897  * Local Variables:
898  * c-file-style:"linux"
899  * indent-tabs-mode:t
900  * End:
901  */
902