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