1 /****************************************************************/
2 /* library.c  - Gphoto2 library for the KBGear JamCam v2 and v3 */
3 /*                                                              */
4 /* Copyright 2001 Chris Pinkham                                 */
5 /*                                                              */
6 /* Author: Chris Pinkham <cpinkham@infi.net>                    */
7 /*                                                              */
8 /* This library is free software; you can redistribute it       */
9 /* and/or modify it under the terms of the GNU Library General  */
10 /* Public License as published by the Free Software Foundation; */
11 /* either version 2 of the License, or (at your option) any     */
12 /* later version.                                               */
13 /*                                                              */
14 /* This library is distributed in the hope that it will be      */
15 /* useful, but WITHOUT ANY WARRANTY; without even the implied   */
16 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      */
17 /* PURPOSE.  See the GNU Library General Public License for     */
18 /* more details.                                                */
19 /*                                                              */
20 /* You should have received a copy of the GNU Library General   */
21 /* Public License along with this library; if not, write to the */
22 /* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,*/
23 /* Boston, MA  02110-1301  USA					*/
24 /****************************************************************/
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <gphoto2/gphoto2.h>
31 #include <time.h>
32 #include <math.h>
33 
34 #include "library.h"
35 
36 #ifdef ENABLE_NLS
37 #  include <libintl.h>
38 #  undef _
39 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
40 #  ifdef gettext_noop
41 #    define N_(String) gettext_noop (String)
42 #  else
43 #    define N_(String) (String)
44 #  endif
45 #else
46 #  define textdomain(String) (String)
47 #  define gettext(String) (String)
48 #  define dgettext(Domain,Message) (Message)
49 #  define dcgettext(Domain,Message,Type) (Message)
50 #  define bindtextdomain(Domain,Directory) (Domain)
51 #  define _(String) (String)
52 #  define N_(String) (String)
53 #endif
54 
55 #define GP_MODULE
56 
57 static struct jamcam_file jamcam_files[1024];
58 static unsigned int jamcam_count = 0;
59 static int jamcam_mmc_card_size = 0;
60 
61 static int jamcam_read_packet (Camera *camera, unsigned char *packet, int length);
62 static int jamcam_write_packet (Camera *camera, unsigned char *packet, int length);
63 static int jamcam_fetch_memory( Camera *camera, CameraFile *file,
64 		unsigned char *data, unsigned int start, unsigned int length, GPContext *context);
65 static int jamcam_query_mmc_card (Camera *camera);
66 
jamcam_set_int_at_pos(unsigned char * buf,int pos,int value)67 static int jamcam_set_int_at_pos( unsigned char *buf, int pos, int value ) {
68 	buf[pos + 0] = ( value       ) & 0xff;
69 	buf[pos + 1] = ( value >>  8 ) & 0xff;
70 	buf[pos + 2] = ( value >> 16 ) & 0xff;
71 	buf[pos + 3] = ( value >> 24 ) & 0xff;
72 
73 	return value;
74 }
75 
jamcam_get_int_at_pos(unsigned char * buf,int pos)76 static unsigned int jamcam_get_int_at_pos( unsigned char *buf, int pos ) {
77 	int ret = 0;
78 
79 	ret += buf[pos + 0];
80 	ret += buf[pos + 1] * 256;
81 	ret += buf[pos + 2] * 256 * 256;
82 	ret += buf[pos + 3] * 256 * 256 * 256;
83 
84 	return ret;
85 }
86 
jamcam_set_usb_mem_pointer(Camera * camera,unsigned int position)87 static int jamcam_set_usb_mem_pointer( Camera *camera, unsigned int position ) {
88 	char reply[8];
89 
90 	GP_DEBUG ("* jamcam_set_usb_mem_pointer");
91 	GP_DEBUG ("*** position:  %d (0x%x)",
92 		position, position);
93 
94 	gp_port_usb_msg_write( camera->port,
95 		0xa1,
96 		( position       ) & 0xffff,
97 		( position >> 16 ) & 0xffff,
98 		NULL, 0 );
99 
100 	gp_port_usb_msg_read( camera->port,
101 		0xa0,
102 		0,
103 		0,
104 		reply, 8 );
105 
106 	return GP_OK;
107 }
108 
109 
110 /* get the number of images on the mmc card */
jamcam_mmc_card_file_count(Camera * camera)111 static int jamcam_mmc_card_file_count (Camera *camera) {
112 	unsigned char buf[16];
113 	unsigned char reply[512];
114 	unsigned int position = 0x40000000;
115 	unsigned int data_incr;
116 	unsigned int width;
117 	unsigned int height;
118 
119 	GP_DEBUG ("* jamcam_mmc_card_file_count");
120 
121 	memset( buf, 0, sizeof( buf ));
122 
123 	switch( camera->port->type ) {
124 		default:
125 		case GP_PORT_SERIAL:
126 			memcpy( buf, "KB00", 4 );
127 			jamcam_set_int_at_pos( buf, 4, position );
128 			jamcam_write_packet( camera, buf, 8 );
129 
130 			jamcam_read_packet( camera, reply, 16 );
131 
132 			while( memcmp( reply, "KB", 2 ) == 0 ) {
133 				width  = (reply[5] * 256) + reply[4];
134 				height = (reply[7] * 256) + reply[6];
135 
136 				data_incr = jamcam_get_int_at_pos( reply, 8 );
137 
138 				jamcam_files[jamcam_count].position = position;
139 				jamcam_files[jamcam_count].width = width;
140 				jamcam_files[jamcam_count].height = height;
141 				jamcam_files[jamcam_count].data_incr = data_incr;
142 
143 				if (jamcam_count+1 >= sizeof(jamcam_files)/sizeof(jamcam_files[0]))
144 					break;
145 				jamcam_count++;
146 
147 				position += data_incr;
148 
149 				jamcam_set_int_at_pos( buf, 4, position );
150 				jamcam_write_packet( camera, buf, 8 );
151 
152 				jamcam_read_packet( camera, reply, 16 );
153 			}
154 			break;
155 
156 		case GP_PORT_USB:
157 			gp_port_usb_msg_write( camera->port,
158 				0xa5,
159 				0x0005,
160 				0x0000,
161 				NULL, 0 );
162 
163 			jamcam_set_usb_mem_pointer( camera, position );
164 
165 			CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
166 
167 			width  = (reply[13] * 256) + reply[12];
168 			height = (reply[15] * 256) + reply[14];
169 
170 			jamcam_set_usb_mem_pointer( camera, position + 8 );
171 
172 			CHECK( gp_port_read (camera->port, (char*)reply, 512 ));
173 
174 			gp_port_usb_msg_write( camera->port,
175 				0xa5,
176 				0x0006,
177 				0x0000,
178 				NULL, 0 );
179 
180 			while((reply[0] != 0xff ) &&
181 			      (reply[0] != 0xaa ) &&
182 				  ((reply[0] != 0x00 ) ||
183 				   (reply[1] != 0x00 ))) {
184 				data_incr = jamcam_get_int_at_pos( reply, 0 );
185 
186 				jamcam_files[jamcam_count].position = position;
187 				jamcam_files[jamcam_count].width = width;
188 				jamcam_files[jamcam_count].height = height;
189 				jamcam_files[jamcam_count].data_incr = data_incr;
190 				if (jamcam_count+1 >= sizeof(jamcam_files)/sizeof(jamcam_files[0]))
191 					break;
192 				jamcam_count++;
193 
194 				position += data_incr;
195 
196 				gp_port_usb_msg_write( camera->port,
197 					0xa5,
198 					0x0005,
199 					0x0000,
200 					NULL, 0 );
201 
202 				jamcam_set_usb_mem_pointer( camera, position );
203 
204 				CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
205 
206 				width  = (reply[13] * 256) + reply[12];
207 				height = (reply[15] * 256) + reply[14];
208 
209 				jamcam_set_usb_mem_pointer( camera, position + 8 );
210 
211 				CHECK( gp_port_read (camera->port, (char*)reply, 512 ));
212 
213 				gp_port_usb_msg_write( camera->port,
214 					0xa5,
215 					0x0006,
216 					0x0000,
217 					NULL, 0 );
218 			}
219 			break;
220 	}
221 
222 	GP_DEBUG (		"*** returning with jamcam_count = %u", jamcam_count);
223 	return( 0 );
224 }
225 
jamcam_file_count(Camera * camera)226 int jamcam_file_count (Camera *camera) {
227 	unsigned char buf[16];
228 	unsigned char reply[16];
229 	int position = 0;
230 	int data_incr;
231 	int width;
232 	int height;
233 	int last_offset_size = 0;
234 
235 	GP_DEBUG ("* jamcam_file_count");
236 
237 	jamcam_count = 0;
238 
239 	memset( buf, 0, sizeof( buf ));
240 
241 	switch( camera->port->type ) {
242 		default:
243 		case GP_PORT_SERIAL:
244 			memcpy( buf, "KB00", 4 );
245 			jamcam_set_int_at_pos( buf, 4, position );
246 			jamcam_write_packet( camera, buf, 8 );
247 
248 			jamcam_read_packet( camera, reply, 16 );
249 
250 			while( reply[0] == 'K' ) {
251 				width  = (reply[5] * 256) + reply[4];
252 				height = (reply[7] * 256) + reply[6];
253 
254 				data_incr = jamcam_get_int_at_pos( reply, 8 );
255 
256 				last_offset_size = data_incr;
257 
258 				jamcam_files[jamcam_count].position = position;
259 				jamcam_files[jamcam_count].width = width;
260 				jamcam_files[jamcam_count].height = height;
261 				jamcam_files[jamcam_count].data_incr = data_incr;
262 				if (jamcam_count+1 >= sizeof(jamcam_files)/sizeof(jamcam_files[0]))
263 					break;
264 
265 				jamcam_count++;
266 
267 				position += data_incr;
268 
269 				jamcam_set_int_at_pos( buf, 4, position );
270 				jamcam_write_packet( camera, buf, 8 );
271 
272 				jamcam_read_packet( camera, reply, 16 );
273 			}
274 
275 			/* the v3 camera uses 0x3fdf0 data increments so check for MMC */
276 			if ( last_offset_size == 0x03fdf0 ) {
277 				jamcam_query_mmc_card( camera );
278 			}
279 			break;
280 
281 		case GP_PORT_USB:
282 			jamcam_set_usb_mem_pointer( camera, position );
283 
284 			CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
285 
286 			width  = (reply[13] * 256) + reply[12];
287 			height = (reply[15] * 256) + reply[14];
288 
289 			jamcam_set_usb_mem_pointer( camera, position + 8 );
290 
291 			CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
292 
293 			while(reply[0] != 0xff ) {
294 				data_incr = jamcam_get_int_at_pos( reply, 0 );
295 
296 				jamcam_files[jamcam_count].position = position;
297 				jamcam_files[jamcam_count].width = width;
298 				jamcam_files[jamcam_count].height = height;
299 				jamcam_files[jamcam_count].data_incr = data_incr;
300 				if (jamcam_count+1 >= sizeof(jamcam_files)/sizeof(jamcam_files[0]))
301 					break;
302 				jamcam_count++;
303 
304 				position += data_incr;
305 
306 				jamcam_set_usb_mem_pointer( camera, position );
307 
308 				CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
309 
310 				width  = (reply[13] * 256) + reply[12];
311 				height = (reply[15] * 256) + reply[14];
312 
313 				jamcam_set_usb_mem_pointer( camera, position + 8 );
314 
315 				CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
316 			}
317 			break;
318 	}
319 
320 	if ( jamcam_mmc_card_size ) {
321 		jamcam_count += jamcam_mmc_card_file_count( camera );
322 	}
323 
324 	GP_DEBUG (		"*** returning jamcam_count = %u", jamcam_count);
325 	return( jamcam_count );
326 }
327 
jamcam_fetch_memory(Camera * camera,CameraFile * file,unsigned char * data,unsigned int start,unsigned int length,GPContext * context)328 static int jamcam_fetch_memory( Camera *camera, CameraFile *file,
329 		unsigned char *data, unsigned int start, unsigned int length, GPContext *context) {
330 	unsigned char tmp_buf[16];
331 	unsigned char packet[16];
332 	unsigned int new_start;
333 	unsigned int new_end;
334 	unsigned int bytes_read = 0;
335 	unsigned int bytes_to_read;
336 	unsigned int bytes_left = length;
337 	int res = GP_OK;
338 	unsigned int id = 0;
339 
340 	GP_DEBUG ("* jamcam_fetch_memory");
341 	GP_DEBUG ("  * start:  %d (0x%x)",
342 		start, start);
343 	GP_DEBUG ("  * length: %d (0x%x)",
344 		length, length);
345 
346 	if ( length > 1000 )
347 		id = gp_context_progress_start (context, length,
348 			_("Downloading data..."));
349 
350 	while( bytes_left ) {
351 		switch( camera->port->type ) {
352 			default:
353 			case GP_PORT_SERIAL:
354 				bytes_to_read =
355 					bytes_left > SER_PKT_SIZE ? SER_PKT_SIZE : bytes_left;
356 
357 				memset( packet, 0, sizeof( packet ));
358 				memcpy( packet, "KB01", 4 );
359 
360 				new_start = start + bytes_read;
361 				new_end   = start + bytes_read + bytes_to_read - 1;
362 
363 				/* start and end (inclusive) */
364 				jamcam_set_int_at_pos( packet, 4, new_start );
365 				jamcam_set_int_at_pos( packet, 8, new_end );
366 
367 				jamcam_write_packet( camera, packet, 12 );
368 
369 				CHECK (jamcam_read_packet( camera, data + bytes_read,
370 					bytes_to_read ));
371 				break;
372 			case GP_PORT_USB:
373 				bytes_to_read = bytes_left > USB_PKT_SIZE ? USB_PKT_SIZE : bytes_left;
374 
375 				/* for some reason this priming read fixes an offset problem */
376 				/* in the images, we are only reading the first 16 bytes of  */
377 				/* data twice by doing this, so I don't know why it works    */
378 				jamcam_set_usb_mem_pointer( camera, start + bytes_read );
379 				CHECK( gp_port_read (camera->port, (char*)tmp_buf, 16 ));
380 
381 
382 				jamcam_set_usb_mem_pointer( camera, start + bytes_read );
383 				CHECK( gp_port_read (camera->port, (char*)data + bytes_read, bytes_to_read ));
384 
385 
386 				break;
387 		}
388 
389 		bytes_left -= bytes_to_read;
390 		bytes_read += bytes_to_read;
391 
392 		/* hate this hardcoded, but don't want to update here */
393 		/* when downloading parts of a thumbnail              */
394 		if ( length > 1000 ) {
395 			gp_context_progress_update (context, id, bytes_read);
396 			if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
397 				GP_DEBUG ("  * CANCELED");
398 				break;
399 			}
400 		}
401 	}
402 
403 	if ( length > 1000 )
404 		gp_context_progress_stop (context, id);
405 
406 	if ( res == GP_OK ) {
407 		GP_DEBUG ("  * returning OK");
408 	}
409 	return res;
410 }
411 
jamcam_request_image(Camera * camera,CameraFile * file,char * buf,unsigned int * len,int number,GPContext * context)412 int jamcam_request_image( Camera *camera, CameraFile *file,
413 		char *buf, unsigned int *len, int number, GPContext *context ) {
414 	unsigned int position;
415 	int result;
416 	unsigned char *tmp_buf;
417 
418 	GP_DEBUG ("* jamcam_request_image");
419 	tmp_buf = malloc(640*480*3);
420 
421 	position = jamcam_files[number].position;
422 
423 	/* don't know why this is necessary, but do it anyway */
424 	if ( camera->port->type == GP_PORT_USB ) {
425 		position += 8;
426 	}
427 
428 	if ( camera->port->type == GP_PORT_USB ) {
429 		gp_port_usb_msg_write( camera->port,
430 			0xa5,
431 			0x0005,
432 			0x0000,
433 			NULL, 0 );
434 	}
435 	if (jamcam_files[number].data_incr <= 640*480*3)
436 		result = jamcam_fetch_memory( camera, file, tmp_buf, position,
437 			jamcam_files[number].data_incr, context );
438 	else
439 		result = GP_ERROR;
440 
441 	/* this seems to reset the camera to a sane status */
442 	if ( camera->port->type == GP_PORT_USB ) {
443 		gp_port_usb_msg_write( camera->port,
444 			0xa5,
445 			0x0006,
446 			0x0000,
447 			NULL, 0 );
448 	}
449 
450 	if ( result == GP_OK ) {
451 		*len = jamcam_files[number].width * jamcam_files[number].height;
452 		if (*len < 640*480*3)
453 			memcpy( buf, tmp_buf + 0x10, *len );
454 	}
455 	free (tmp_buf);
456 
457 	return result;
458 }
459 
jamcam_file_info(Camera * camera,int number)460 struct jamcam_file *jamcam_file_info(Camera *camera, int number)
461 {
462 	GP_DEBUG(" * jamcam_file_info, nr is %d", number);
463 	return( &jamcam_files[number] );
464 }
465 
jamcam_request_thumbnail(Camera * camera,CameraFile * file,char * buf,unsigned int * len,int number,GPContext * context)466 int jamcam_request_thumbnail( Camera *camera, CameraFile *file,
467 		char *buf, unsigned int *len, int number, GPContext *context ) {
468 	unsigned char line[2048];
469 	char packet[16];
470 	unsigned int position;
471 	int x, y;
472 	int res = GP_OK;
473 	char *ptr;
474 	unsigned int bytes_to_read;
475 	unsigned int id;
476 
477 	GP_DEBUG ("* jamcam_request_thumbnail");
478 
479 	memset( packet, 0, sizeof( packet ));
480 
481 	position = jamcam_files[number].position + 0x10;
482 
483 	*len = 4800;
484 
485 	ptr = buf;
486 
487 	if ( camera->port->type == GP_PORT_USB ) {
488 		/* windows driver does this sometimes */
489 		gp_port_usb_msg_write( camera->port,
490 			0xa5,
491 			0x0005,
492 			0x0000,
493 			NULL, 0 );
494 
495 		/* just read one row of data at a time */
496 		bytes_to_read = jamcam_files[number].width;
497 	} else {
498 		/* MMC card is quirky, need to fetch larger amounts of data */
499 		if ( position >= 0x40000000 ) {
500 			/* serial with mmc card needs bigger packets */
501 			bytes_to_read = 2048;
502 		} else {
503 			/* just read one row of data at a time */
504 			bytes_to_read = jamcam_files[number].width;
505 		}
506 	}
507 
508 	if (bytes_to_read > sizeof(line)) {
509 		res = GP_ERROR;
510 		goto resetcam;
511 	}
512 
513 	/* fetch thumbnail lines and build the thumbnail */
514 	position += 10 * jamcam_files[number].width;
515 	id = gp_context_progress_start (context, 60.,
516 					_("Downloading thumbnail..."));
517 	for( y = 0 ; y < 60 ; y++ ) {
518 		jamcam_fetch_memory( camera, file, line, position, bytes_to_read, context );
519 
520 		gp_context_progress_update (context, id, y);
521 		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
522 			res = GP_ERROR_CANCEL;
523 			break;
524 		}
525 
526 		if ( jamcam_files[number].width == 600 ) {
527 			for( x = 22; x < 578 ; x += 7 ) {
528 				*(ptr++) = line[x];
529 			}
530 			position += 7 * 600;
531 		} else {
532 			for( x = 0; x < 320 ; ) {
533 				*(ptr++) = line[x];
534 				x += 3;
535 				*(ptr++) = line[x];
536 				x += 5;
537 			}
538 
539 			if ( y % 2 ) {
540 				position += 5 * 320;
541 			} else {
542 				position += 3 * 320;
543 			}
544 		}
545 	}
546 	gp_context_progress_stop (context, id);
547 
548 resetcam:
549 	/* this seems to reset the camera to a sane status */
550 	if ( camera->port->type == GP_PORT_USB ) {
551 		gp_port_usb_msg_write( camera->port,
552 			0xa5,
553 			0x0006,
554 			0x0000,
555 			NULL, 0 );
556 	}
557 
558 	return res;
559 }
560 
jamcam_write_packet(Camera * camera,unsigned char * packet,int length)561 static int jamcam_write_packet (Camera *camera, unsigned char *packet, int length) {
562 	int ret, r;
563 
564 	GP_DEBUG ("* jamcam_write_packet");
565 
566 	for (r = 0; r < RETRIES; r++) {
567 		ret = gp_port_write (camera->port, (char*)packet, length);
568 		if (ret == GP_ERROR_TIMEOUT)
569 			continue;
570 
571 		return (ret);
572 	}
573 
574 	return (GP_ERROR_TIMEOUT);
575 }
576 
jamcam_read_packet(Camera * camera,unsigned char * packet,int length)577 static int jamcam_read_packet (Camera *camera, unsigned char *packet, int length) {
578 	int r = 0;
579 	int bytes_read;
580 
581 	GP_DEBUG ("* jamcam_read_packet");
582 	GP_DEBUG ("*** length: %d (0x%x)",
583 		length, length);
584 
585 	for (r = 0; r < RETRIES; r++) {
586 		bytes_read = gp_port_read (camera->port, (char*)packet, length);
587 		if (bytes_read == GP_ERROR_TIMEOUT)
588 			continue;
589 		if (bytes_read < 0)
590 			return (bytes_read);
591 
592 		if ( bytes_read == length ) {
593 			return( GP_OK );
594 		}
595 	}
596 
597 	return (GP_ERROR_TIMEOUT);
598 }
599 
600 
jamcam_enq(Camera * camera)601 int jamcam_enq (Camera *camera)
602 {
603 	int ret, r = 0;
604 	unsigned char buf[16];
605 
606 	GP_DEBUG ("* jamcam_enq");
607 
608 	memset( buf, 0, 16 );
609 
610 	switch( camera->port->type ) {
611 		default:
612 		case GP_PORT_SERIAL:
613 			for (r = 0; r < RETRIES; r++) {
614 				memcpy (buf, "KB99", 4 );
615 
616 				ret = jamcam_write_packet (camera, buf, 4);
617 				if (ret == GP_ERROR_TIMEOUT)
618 					continue;
619 				if (ret != GP_OK)
620 					return (ret);
621 
622 				ret = jamcam_read_packet (camera, buf, 4);
623 				if (ret == GP_ERROR_TIMEOUT)
624 					continue;
625 				if (ret != GP_OK)
626 					return (ret);
627 
628 				if ( !memcmp( buf, "KIDB", 4 )) {
629 					return (GP_OK);
630 				}
631 			}
632 			return (GP_ERROR_CORRUPTED_DATA);
633 			break;
634 
635 		case GP_PORT_USB:
636 			for (r = 0; r < RETRIES; r++) {
637 				gp_port_usb_msg_write( camera->port,
638 					0xa5,
639 					0x0004,
640 					0x0000,
641 					NULL, 0 );
642 				jamcam_set_usb_mem_pointer( camera, 0x0000 );
643 
644 				CHECK( gp_port_read( camera->port, (char *)buf, 0x0c ));
645 
646 				if (( !memcmp( buf, "KB00", 4 )) ||
647 					(( buf[0] == 0xff ) && ( buf[1] == 0xff ) &&
648 					 ( buf[2] == 0xff ) && ( buf[3] == 0xff ) &&
649 					 ( buf[4] == 0xff ) && ( buf[5] == 0xff ) &&
650 					 ( buf[6] == 0xff ) && ( buf[7] == 0xff ))) {
651 					/* found a JamCam v3 camera */
652 					/* reply contains 4-bytes with MMC card size if present */
653 					/* set to 0 if none */
654 					jamcam_mmc_card_size = jamcam_get_int_at_pos( buf, 8 );
655 
656 					if ( jamcam_mmc_card_size ) {
657 						GP_DEBUG (							"* jamcam_enq, MMC card size = %d",
658 							jamcam_mmc_card_size );
659 					}
660 
661 					return (GP_OK);
662 				} else if ( !memcmp( buf + 8, "KB00", 4 )) {
663 					/* found a JamCam v2 camera */
664 					/* JamCam v2 doesn't support MMC card so no need to check */
665 					return (GP_OK);
666 				} else if (( buf[0] == 0xf0 ) &&
667 						 ( buf[1] == 0xfd ) &&
668 						 ( buf[2] == 0x03 )) {
669 					return( GP_OK );
670 				}
671 			}
672 			return (GP_ERROR_CORRUPTED_DATA);
673 			break;
674 	}
675 
676 	return (GP_ERROR_TIMEOUT);
677 }
678 
jamcam_query_mmc_card(Camera * camera)679 static int jamcam_query_mmc_card (Camera *camera)
680 {
681 	int ret, r = 0;
682 	unsigned char buf[16];
683 
684 	GP_DEBUG ("* jamcam_query_mmc_card");
685 
686 	/* usb port doesn't need this packet, this info found in enquiry reply */
687 	if ( camera->port->type == GP_PORT_USB ) {
688 		return( GP_OK );
689 	}
690 
691 	memcpy( buf, "KB04", 4 );
692 
693 	for (r = 0; r < RETRIES; r++) {
694 
695 		ret = jamcam_write_packet (camera, buf, 4);
696 		if (ret == GP_ERROR_TIMEOUT)
697 			continue;
698 		if (ret != GP_OK)
699 			return (ret);
700 
701 		ret = jamcam_read_packet (camera, buf, 4);
702 		if (ret == GP_ERROR_TIMEOUT)
703 			continue;
704 		if (ret != GP_OK)
705 			return (ret);
706 
707 		/* reply is 4-byte int showing length of MMC card if any, 0 if none */
708 		jamcam_mmc_card_size = jamcam_get_int_at_pos( buf, 0 );
709 
710 		if ( jamcam_mmc_card_size ) {
711 			GP_DEBUG ("* jamcam_query_mmc_card, MMC card size = %d",
712 				jamcam_mmc_card_size );
713 		}
714 
715 		return (GP_OK);
716 	}
717 	return (GP_ERROR_TIMEOUT);
718 }
719 
720