1 /****************************************************************/
2 /* library.c - Gphoto2 library for the KBGear JamCam v2 and v3 */
4 /* Copyright © 2001 Chris Pinkham */
6 /* Author: Chris Pinkham <cpinkham@infi.net> */
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 */
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 */
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., 59 Temple Place - Suite 330, */
23 /* Boston, MA 02111-1307, USA. */
24 /****************************************************************/
30 #include <gphoto2/gphoto2.h>
40 # define _(String) dgettext (GETTEXT_PACKAGE, String)
42 # define N_(String) gettext_noop (String)
44 # define N_(String) (String)
47 # define textdomain(String) (String)
48 # define gettext(String) (String)
49 # define dgettext(Domain,Message) (Message)
50 # define dcgettext(Domain,Message,Type) (Message)
51 # define bindtextdomain(Domain,Directory) (Domain)
52 # define _(String) (String)
53 # define N_(String) (String)
58 static struct jamcam_file jamcam_files[1024];
59 static int jamcam_count = 0;
60 static int jamcam_mmc_card_size = 0;
62 static int jamcam_read_packet (Camera *camera, unsigned char *packet, int length);
63 static int jamcam_write_packet (Camera *camera, unsigned char *packet, int length);
64 static int jamcam_fetch_memory( Camera *camera, CameraFile *file,
65 unsigned char *data, int start, int length, GPContext *context);
66 static int jamcam_query_mmc_card (Camera *camera);
68 static int jamcam_set_int_at_pos( unsigned char *buf, int pos, int value ) {
69 buf[pos + 0] = ( value ) & 0xff;
70 buf[pos + 1] = ( value >> 8 ) & 0xff;
71 buf[pos + 2] = ( value >> 16 ) & 0xff;
72 buf[pos + 3] = ( value >> 24 ) & 0xff;
77 static int jamcam_get_int_at_pos( unsigned char *buf, int pos ) {
81 ret += buf[pos + 1] * 256;
82 ret += buf[pos + 2] * 256 * 256;
83 ret += buf[pos + 3] * 256 * 256 * 256;
88 static int jamcam_set_usb_mem_pointer( Camera *camera, int position ) {
91 GP_DEBUG ("* jamcam_set_usb_mem_pointer");
92 GP_DEBUG ("*** position: %d (0x%x)",
95 gp_port_usb_msg_write( camera->port,
97 ( position ) & 0xffff,
98 ( position >> 16 ) & 0xffff,
101 gp_port_usb_msg_read( camera->port,
111 /* get the number of images on the mmc card */
112 static int jamcam_mmc_card_file_count (Camera *camera) {
113 unsigned char buf[16];
114 unsigned char reply[512];
115 unsigned int position = 0x40000000;
120 GP_DEBUG ("* jamcam_mmc_card_file_count");
122 memset( buf, 0, sizeof( buf ));
124 switch( camera->port->type ) {
127 memcpy( buf, "KB00", 4 );
128 jamcam_set_int_at_pos( buf, 4, position );
129 jamcam_write_packet( camera, buf, 8 );
131 jamcam_read_packet( camera, reply, 16 );
133 while( memcmp( reply, "KB", 2 ) == 0 ) {
134 width = (reply[5] * 256) + reply[4];
135 height = (reply[7] * 256) + reply[6];
137 data_incr = jamcam_get_int_at_pos( reply, 8 );
139 jamcam_files[jamcam_count].position = position;
140 jamcam_files[jamcam_count].width = width;
141 jamcam_files[jamcam_count].height = height;
142 jamcam_files[jamcam_count].data_incr = data_incr;
146 position += data_incr;
148 jamcam_set_int_at_pos( buf, 4, position );
149 jamcam_write_packet( camera, buf, 8 );
151 jamcam_read_packet( camera, reply, 16 );
156 gp_port_usb_msg_write( camera->port,
162 jamcam_set_usb_mem_pointer( camera, position );
164 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
166 width = (reply[13] * 256) + reply[12];
167 height = (reply[15] * 256) + reply[14];
169 jamcam_set_usb_mem_pointer( camera, position + 8 );
171 CHECK( gp_port_read (camera->port, (char*)reply, 512 ));
173 gp_port_usb_msg_write( camera->port,
179 while((reply[0] != 0xff ) &&
180 (reply[0] != 0xaa ) &&
181 ((reply[0] != 0x00 ) ||
182 (reply[1] != 0x00 ))) {
183 data_incr = jamcam_get_int_at_pos( reply, 0 );
185 jamcam_files[jamcam_count].position = position;
186 jamcam_files[jamcam_count].width = width;
187 jamcam_files[jamcam_count].height = height;
188 jamcam_files[jamcam_count].data_incr = data_incr;
191 position += data_incr;
193 gp_port_usb_msg_write( camera->port,
199 jamcam_set_usb_mem_pointer( camera, position );
201 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
203 width = (reply[13] * 256) + reply[12];
204 height = (reply[15] * 256) + reply[14];
206 jamcam_set_usb_mem_pointer( camera, position + 8 );
208 CHECK( gp_port_read (camera->port, (char*)reply, 512 ));
210 gp_port_usb_msg_write( camera->port,
219 GP_DEBUG ( "*** returning with jamcam_count = %d", jamcam_count);
223 int jamcam_file_count (Camera *camera) {
224 unsigned char buf[16];
225 unsigned char reply[16];
230 int last_offset_size = 0;
232 GP_DEBUG ("* jamcam_file_count");
236 memset( buf, 0, sizeof( buf ));
238 switch( camera->port->type ) {
241 memcpy( buf, "KB00", 4 );
242 jamcam_set_int_at_pos( buf, 4, position );
243 jamcam_write_packet( camera, buf, 8 );
245 jamcam_read_packet( camera, reply, 16 );
247 while( reply[0] == 'K' ) {
248 width = (reply[5] * 256) + reply[4];
249 height = (reply[7] * 256) + reply[6];
251 data_incr = jamcam_get_int_at_pos( reply, 8 );
253 last_offset_size = data_incr;
255 jamcam_files[jamcam_count].position = position;
256 jamcam_files[jamcam_count].width = width;
257 jamcam_files[jamcam_count].height = height;
258 jamcam_files[jamcam_count].data_incr = data_incr;
262 position += data_incr;
264 jamcam_set_int_at_pos( buf, 4, position );
265 jamcam_write_packet( camera, buf, 8 );
267 jamcam_read_packet( camera, reply, 16 );
270 /* the v3 camera uses 0x3fdf0 data increments so check for MMC */
271 if ( last_offset_size == 0x03fdf0 ) {
272 jamcam_query_mmc_card( camera );
277 jamcam_set_usb_mem_pointer( camera, position );
279 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
281 width = (reply[13] * 256) + reply[12];
282 height = (reply[15] * 256) + reply[14];
284 jamcam_set_usb_mem_pointer( camera, position + 8 );
286 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
288 while(reply[0] != 0xff ) {
289 data_incr = jamcam_get_int_at_pos( reply, 0 );
291 jamcam_files[jamcam_count].position = position;
292 jamcam_files[jamcam_count].width = width;
293 jamcam_files[jamcam_count].height = height;
294 jamcam_files[jamcam_count].data_incr = data_incr;
297 position += data_incr;
299 jamcam_set_usb_mem_pointer( camera, position );
301 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
303 width = (reply[13] * 256) + reply[12];
304 height = (reply[15] * 256) + reply[14];
306 jamcam_set_usb_mem_pointer( camera, position + 8 );
308 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
313 if ( jamcam_mmc_card_size ) {
314 jamcam_count += jamcam_mmc_card_file_count( camera );
317 GP_DEBUG ( "*** returning jamcam_count = %d", jamcam_count);
318 return( jamcam_count );
321 static int jamcam_fetch_memory( Camera *camera, CameraFile *file,
322 unsigned char *data, int start, int length, GPContext *context) {
323 unsigned char tmp_buf[16];
324 unsigned char packet[16];
329 int bytes_left = length;
333 GP_DEBUG ("* jamcam_fetch_memory");
334 GP_DEBUG (" * start: %d (0x%x)",
336 GP_DEBUG (" * length: %d (0x%x)",
340 id = gp_context_progress_start (context, length,
341 _("Downloading data..."));
343 while( bytes_left ) {
344 switch( camera->port->type ) {
348 bytes_left > SER_PKT_SIZE ? SER_PKT_SIZE : bytes_left;
350 memset( packet, 0, sizeof( packet ));
351 memcpy( packet, "KB01", 4 );
353 new_start = start + bytes_read;
354 new_end = start + bytes_read + bytes_to_read - 1;
356 /* start and end (inclusive) */
357 jamcam_set_int_at_pos( packet, 4, new_start );
358 jamcam_set_int_at_pos( packet, 8, new_end );
360 jamcam_write_packet( camera, packet, 12 );
362 CHECK (jamcam_read_packet( camera, data + bytes_read,
366 bytes_to_read = bytes_left > USB_PKT_SIZE ? USB_PKT_SIZE : bytes_left;
368 /* for some reason this priming read fixes an offset problem */
369 /* in the images, we are only reading the first 16 bytes of */
370 /* data twice by doing this, so I don't know why it works */
371 jamcam_set_usb_mem_pointer( camera, start + bytes_read );
372 CHECK( gp_port_read (camera->port, (char*)tmp_buf, 16 ));
375 jamcam_set_usb_mem_pointer( camera, start + bytes_read );
376 CHECK( gp_port_read (camera->port, (char*)data + bytes_read, bytes_to_read ));
382 bytes_left -= bytes_to_read;
383 bytes_read += bytes_to_read;
385 /* hate this hardcoded, but don't want to update here */
386 /* when downloading parts of a thumbnail */
387 if ( length > 1000 ) {
388 gp_context_progress_update (context, id, bytes_read);
389 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
390 GP_DEBUG (" * CANCELED");
397 gp_context_progress_stop (context, id);
399 if ( res == GP_OK ) {
400 GP_DEBUG (" * returning OK");
405 int jamcam_request_image( Camera *camera, CameraFile *file,
406 char *buf, int *len, int number, GPContext *context ) {
409 unsigned char *tmp_buf;
411 GP_DEBUG ("* jamcam_request_image");
412 tmp_buf = malloc(640*480*3);
414 position = jamcam_files[number].position;
416 /* don't know why this is necessary, but do it anyway */
417 if ( camera->port->type == GP_PORT_USB ) {
421 if ( camera->port->type == GP_PORT_USB ) {
422 gp_port_usb_msg_write( camera->port,
429 result = jamcam_fetch_memory( camera, file, tmp_buf, position,
430 jamcam_files[number].data_incr, context );
432 /* this seems to reset the camera to a sane status */
433 if ( camera->port->type == GP_PORT_USB ) {
434 gp_port_usb_msg_write( camera->port,
441 if ( result == GP_OK ) {
442 *len = jamcam_files[number].width * jamcam_files[number].height;
443 memcpy( buf, tmp_buf + 0x10, *len );
450 struct jamcam_file *jamcam_file_info(Camera *camera, int number)
452 GP_DEBUG(" * jamcam_file_info, nr is %d", number);
453 return( &jamcam_files[number] );
456 int jamcam_request_thumbnail( Camera *camera, CameraFile *file,
457 char *buf, int *len, int number, GPContext *context ) {
458 unsigned char line[2048];
467 GP_DEBUG ("* jamcam_request_thumbnail");
469 memset( packet, 0, sizeof( packet ));
471 position = jamcam_files[number].position + 0x10;
477 if ( camera->port->type == GP_PORT_USB ) {
478 /* windows driver does this sometimes */
479 gp_port_usb_msg_write( camera->port,
485 /* just read one row of data at a time */
486 bytes_to_read = jamcam_files[number].width;
488 /* MMC card is quirky, need to fetch larger amounts of data */
489 if ( position >= 0x40000000 ) {
490 /* serial with mmc card needs bigger packets */
491 bytes_to_read = 2048;
493 /* just read one row of data at a time */
494 bytes_to_read = jamcam_files[number].width;
498 /* fetch thumbnail lines and build the thumbnail */
499 position += 10 * jamcam_files[number].width;
500 id = gp_context_progress_start (context, 60.,
501 _("Downloading thumbnail..."));
502 for( y = 0 ; y < 60 ; y++ ) {
503 jamcam_fetch_memory( camera, file, line, position, bytes_to_read, context );
505 gp_context_progress_update (context, id, y);
506 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
507 res = GP_ERROR_CANCEL;
511 if ( jamcam_files[number].width == 600 ) {
512 for( x = 22; x < 578 ; x += 7 ) {
517 for( x = 0; x < 320 ; ) {
531 gp_context_progress_stop (context, id);
533 /* this seems to reset the camera to a sane status */
534 if ( camera->port->type == GP_PORT_USB ) {
535 gp_port_usb_msg_write( camera->port,
545 static int jamcam_write_packet (Camera *camera, unsigned char *packet, int length) {
548 GP_DEBUG ("* jamcam_write_packet");
550 for (r = 0; r < RETRIES; r++) {
551 ret = gp_port_write (camera->port, (char*)packet, length);
552 if (ret == GP_ERROR_TIMEOUT)
558 return (GP_ERROR_TIMEOUT);
561 static int jamcam_read_packet (Camera *camera, unsigned char *packet, int length) {
565 GP_DEBUG ("* jamcam_read_packet");
566 GP_DEBUG ("*** length: %d (0x%x)",
569 for (r = 0; r < RETRIES; r++) {
570 bytes_read = gp_port_read (camera->port, (char*)packet, length);
571 if (bytes_read == GP_ERROR_TIMEOUT)
576 if ( bytes_read == length ) {
581 return (GP_ERROR_TIMEOUT);
585 int jamcam_enq (Camera *camera)
588 unsigned char buf[16];
590 GP_DEBUG ("* jamcam_enq");
592 memset( buf, 0, 16 );
594 switch( camera->port->type ) {
597 for (r = 0; r < RETRIES; r++) {
598 memcpy (buf, "KB99", 4 );
600 ret = jamcam_write_packet (camera, buf, 4);
601 if (ret == GP_ERROR_TIMEOUT)
606 ret = jamcam_read_packet (camera, buf, 4);
607 if (ret == GP_ERROR_TIMEOUT)
612 if ( !memcmp( buf, "KIDB", 4 )) {
616 return (GP_ERROR_CORRUPTED_DATA);
620 for (r = 0; r < RETRIES; r++) {
621 gp_port_usb_msg_write( camera->port,
626 jamcam_set_usb_mem_pointer( camera, 0x0000 );
628 CHECK( gp_port_read( camera->port, (char *)buf, 0x0c ));
630 if (( !memcmp( buf, "KB00", 4 )) ||
631 (( buf[0] == 0xff ) && ( buf[1] == 0xff ) &&
632 ( buf[2] == 0xff ) && ( buf[3] == 0xff ) &&
633 ( buf[4] == 0xff ) && ( buf[5] == 0xff ) &&
634 ( buf[6] == 0xff ) && ( buf[7] == 0xff ))) {
635 /* found a JamCam v3 camera */
636 /* reply contains 4-bytes with MMC card size if present */
637 /* set to 0 if none */
638 jamcam_mmc_card_size = jamcam_get_int_at_pos( buf, 8 );
640 if ( jamcam_mmc_card_size ) {
641 GP_DEBUG ( "* jamcam_enq, MMC card size = %d",
642 jamcam_mmc_card_size );
646 } else if ( !memcmp( buf + 8, "KB00", 4 )) {
647 /* found a JamCam v2 camera */
648 /* JamCam v2 doesn't support MMC card so no need to check */
650 } else if (( buf[0] == 0xf0 ) &&
651 ( buf[1] == 0xfd ) &&
652 ( buf[2] == 0x03 )) {
656 return (GP_ERROR_CORRUPTED_DATA);
660 return (GP_ERROR_TIMEOUT);
663 static int jamcam_query_mmc_card (Camera *camera)
666 unsigned char buf[16];
668 GP_DEBUG ("* jamcam_query_mmc_card");
670 /* usb port doesn't need this packet, this info found in enquiry reply */
671 if ( camera->port->type == GP_PORT_USB ) {
675 memcpy( buf, "KB04", 4 );
677 for (r = 0; r < RETRIES; r++) {
679 ret = jamcam_write_packet (camera, buf, 4);
680 if (ret == GP_ERROR_TIMEOUT)
685 ret = jamcam_read_packet (camera, buf, 4);
686 if (ret == GP_ERROR_TIMEOUT)
691 /* reply is 4-byte int showing length of MMC card if any, 0 if none */
692 jamcam_mmc_card_size = jamcam_get_int_at_pos( buf, 0 );
694 if ( jamcam_mmc_card_size ) {
695 GP_DEBUG ("* jamcam_query_mmc_card, MMC card size = %d",
696 jamcam_mmc_card_size );
701 return (GP_ERROR_TIMEOUT);