Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / jamcam / library.c
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., 59 Temple Place - Suite 330, */
23 /* Boston, MA 02111-1307, 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 <unistd.h>
33 #include <math.h>
34
35 #include "library.h"
36
37 #ifdef ENABLE_NLS
38 #  include <libintl.h>
39 #  undef _
40 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
41 #  ifdef gettext_noop
42 #    define N_(String) gettext_noop (String)
43 #  else
44 #    define N_(String) (String)
45 #  endif
46 #else
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)
54 #endif
55
56 #define GP_MODULE
57
58 static struct jamcam_file jamcam_files[1024];
59 static int jamcam_count = 0;
60 static int jamcam_mmc_card_size = 0;
61
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);
67
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;
73
74         return( value );
75 }
76
77 static int jamcam_get_int_at_pos( unsigned char *buf, int pos ) {
78         int ret = 0;
79
80         ret += buf[pos + 0];
81         ret += buf[pos + 1] * 256;
82         ret += buf[pos + 2] * 256 * 256;
83         ret += buf[pos + 3] * 256 * 256 * 256;
84
85         return( ret );
86 }
87
88 static int jamcam_set_usb_mem_pointer( Camera *camera, int position ) {
89         char reply[8];
90
91         GP_DEBUG ("* jamcam_set_usb_mem_pointer");
92         GP_DEBUG ("*** position:  %d (0x%x)",
93                 position, position);
94
95         gp_port_usb_msg_write( camera->port,
96                 0xa1,
97                 ( position       ) & 0xffff,
98                 ( position >> 16 ) & 0xffff,
99                 NULL, 0 );
100
101         gp_port_usb_msg_read( camera->port,
102                 0xa0,
103                 0,
104                 0,
105                 reply, 8 );
106
107         return( GP_OK );
108 }
109
110
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;
116         int data_incr;
117         int width;
118         int height;
119
120         GP_DEBUG ("* jamcam_mmc_card_file_count");
121
122         memset( buf, 0, sizeof( buf ));
123
124         switch( camera->port->type ) {
125                 default:
126                 case GP_PORT_SERIAL:
127                         memcpy( buf, "KB00", 4 );
128                         jamcam_set_int_at_pos( buf, 4, position );
129                         jamcam_write_packet( camera, buf, 8 );
130
131                         jamcam_read_packet( camera, reply, 16 );
132
133                         while( memcmp( reply, "KB", 2 ) == 0 ) {
134                                 width  = (reply[5] * 256) + reply[4];
135                                 height = (reply[7] * 256) + reply[6];
136
137                                 data_incr = jamcam_get_int_at_pos( reply, 8 );
138
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;
143
144                                 jamcam_count++;
145
146                                 position += data_incr;
147
148                                 jamcam_set_int_at_pos( buf, 4, position );
149                                 jamcam_write_packet( camera, buf, 8 );
150                         
151                                 jamcam_read_packet( camera, reply, 16 );
152                         }
153                         break;
154
155                 case GP_PORT_USB:
156                         gp_port_usb_msg_write( camera->port,
157                                 0xa5,
158                                 0x0005,
159                                 0x0000,
160                                 NULL, 0 );
161
162                         jamcam_set_usb_mem_pointer( camera, position );
163
164                         CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
165
166                         width  = (reply[13] * 256) + reply[12];
167                         height = (reply[15] * 256) + reply[14];
168
169                         jamcam_set_usb_mem_pointer( camera, position + 8 );
170
171                         CHECK( gp_port_read (camera->port, (char*)reply, 512 ));
172
173                         gp_port_usb_msg_write( camera->port,
174                                 0xa5,
175                                 0x0006,
176                                 0x0000,
177                                 NULL, 0 );
178
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 );
184
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;
189                                 jamcam_count++;
190
191                                 position += data_incr;
192
193                                 gp_port_usb_msg_write( camera->port,
194                                         0xa5,
195                                         0x0005,
196                                         0x0000,
197                                         NULL, 0 );
198
199                                 jamcam_set_usb_mem_pointer( camera, position );
200
201                                 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
202
203                                 width  = (reply[13] * 256) + reply[12];
204                                 height = (reply[15] * 256) + reply[14];
205
206                                 jamcam_set_usb_mem_pointer( camera, position + 8 );
207
208                                 CHECK( gp_port_read (camera->port, (char*)reply, 512 ));
209
210                                 gp_port_usb_msg_write( camera->port,
211                                         0xa5,
212                                         0x0006,
213                                         0x0000,
214                                         NULL, 0 );
215                         }
216                         break;
217         }
218
219         GP_DEBUG (              "*** returning with jamcam_count = %d", jamcam_count);
220         return( 0 );
221 }
222
223 int jamcam_file_count (Camera *camera) {
224         unsigned char buf[16];
225         unsigned char reply[16];
226         int position = 0;
227         int data_incr;
228         int width;
229         int height;
230         int last_offset_size = 0;
231
232         GP_DEBUG ("* jamcam_file_count");
233
234         jamcam_count = 0;
235
236         memset( buf, 0, sizeof( buf ));
237
238         switch( camera->port->type ) {
239                 default:
240                 case GP_PORT_SERIAL:
241                         memcpy( buf, "KB00", 4 );
242                         jamcam_set_int_at_pos( buf, 4, position );
243                         jamcam_write_packet( camera, buf, 8 );
244
245                         jamcam_read_packet( camera, reply, 16 );
246
247                         while( reply[0] == 'K' ) {
248                                 width  = (reply[5] * 256) + reply[4];
249                                 height = (reply[7] * 256) + reply[6];
250
251                                 data_incr = jamcam_get_int_at_pos( reply, 8 );
252
253                                 last_offset_size = data_incr;
254
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;
259
260                                 jamcam_count++;
261
262                                 position += data_incr;
263
264                                 jamcam_set_int_at_pos( buf, 4, position );
265                                 jamcam_write_packet( camera, buf, 8 );
266                         
267                                 jamcam_read_packet( camera, reply, 16 );
268                         }
269
270                         /* the v3 camera uses 0x3fdf0 data increments so check for MMC */
271                         if ( last_offset_size == 0x03fdf0 ) {
272                                 jamcam_query_mmc_card( camera );
273                         }
274                         break;
275
276                 case GP_PORT_USB:
277                         jamcam_set_usb_mem_pointer( camera, position );
278
279                         CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
280
281                         width  = (reply[13] * 256) + reply[12];
282                         height = (reply[15] * 256) + reply[14];
283
284                         jamcam_set_usb_mem_pointer( camera, position + 8 );
285
286                         CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
287
288                         while(reply[0] != 0xff ) {
289                                 data_incr = jamcam_get_int_at_pos( reply, 0 );
290
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;
295                                 jamcam_count++;
296
297                                 position += data_incr;
298
299                                 jamcam_set_usb_mem_pointer( camera, position );
300
301                                 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
302
303                                 width  = (reply[13] * 256) + reply[12];
304                                 height = (reply[15] * 256) + reply[14];
305
306                                 jamcam_set_usb_mem_pointer( camera, position + 8 );
307
308                                 CHECK( gp_port_read (camera->port, (char*)reply, 0x10 ));
309                         }
310                         break;
311         }
312
313         if ( jamcam_mmc_card_size ) {
314                 jamcam_count += jamcam_mmc_card_file_count( camera );
315         }
316
317         GP_DEBUG (              "*** returning jamcam_count = %d", jamcam_count);
318         return( jamcam_count );
319 }
320
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];
325         int new_start;
326         int new_end;
327         int bytes_read = 0;
328         int bytes_to_read;
329         int bytes_left = length;
330         int res = GP_OK;
331         unsigned int id = 0;
332
333         GP_DEBUG ("* jamcam_fetch_memory");
334         GP_DEBUG ("  * start:  %d (0x%x)",
335                 start, start);
336         GP_DEBUG ("  * length: %d (0x%x)",
337                 length, length);
338
339         if ( length > 1000 )
340                 id = gp_context_progress_start (context, length,
341                         _("Downloading data..."));
342
343         while( bytes_left ) {
344                 switch( camera->port->type ) {
345                         default:
346                         case GP_PORT_SERIAL:
347                                 bytes_to_read =
348                                         bytes_left > SER_PKT_SIZE ? SER_PKT_SIZE : bytes_left;
349
350                                 memset( packet, 0, sizeof( packet ));
351                                 memcpy( packet, "KB01", 4 );
352
353                                 new_start = start + bytes_read;
354                                 new_end   = start + bytes_read + bytes_to_read - 1;
355
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 );
359
360                                 jamcam_write_packet( camera, packet, 12 );
361
362                                 CHECK (jamcam_read_packet( camera, data + bytes_read,
363                                         bytes_to_read ));
364                                 break;
365                         case GP_PORT_USB:
366                                 bytes_to_read = bytes_left > USB_PKT_SIZE ? USB_PKT_SIZE : bytes_left;
367
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 ));
373
374
375                                 jamcam_set_usb_mem_pointer( camera, start + bytes_read );
376                                 CHECK( gp_port_read (camera->port, (char*)data + bytes_read, bytes_to_read ));
377
378
379                                 break;
380                 }
381                                 
382                 bytes_left -= bytes_to_read;
383                 bytes_read += bytes_to_read;
384
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");
391                                 break;
392                         }
393                 }
394         }
395
396         if ( length > 1000 )
397                 gp_context_progress_stop (context, id);
398
399         if ( res == GP_OK ) {
400                 GP_DEBUG ("  * returning OK");
401         }
402         return( res );
403 }
404
405 int jamcam_request_image( Camera *camera, CameraFile *file,
406                 char *buf, int *len, int number, GPContext *context ) {
407         int position;
408         int result;
409         unsigned char *tmp_buf;
410
411         GP_DEBUG ("* jamcam_request_image");
412         tmp_buf = malloc(640*480*3);
413
414         position = jamcam_files[number].position;
415
416         /* don't know why this is necessary, but do it anyway */
417         if ( camera->port->type == GP_PORT_USB ) {
418                 position += 8;
419         }
420
421         if ( camera->port->type == GP_PORT_USB ) {
422                 gp_port_usb_msg_write( camera->port,
423                         0xa5,
424                         0x0005,
425                         0x0000,
426                         NULL, 0 );
427         }
428         
429         result = jamcam_fetch_memory( camera, file, tmp_buf, position,
430                 jamcam_files[number].data_incr, context );
431
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,
435                         0xa5,
436                         0x0006,
437                         0x0000,
438                         NULL, 0 );
439         }
440
441         if ( result == GP_OK ) {
442                 *len = jamcam_files[number].width * jamcam_files[number].height;
443                 memcpy( buf, tmp_buf + 0x10, *len );
444         }
445         free (tmp_buf);
446
447         return( result );
448 }
449
450 struct jamcam_file *jamcam_file_info(Camera *camera, int number)
451 {
452         GP_DEBUG(" * jamcam_file_info, nr is %d", number);
453         return( &jamcam_files[number] );
454 }
455
456 int jamcam_request_thumbnail( Camera *camera, CameraFile *file,
457                 char *buf, int *len, int number, GPContext *context ) {
458         unsigned char line[2048];
459         char packet[16];
460         int position;
461         int x, y;
462         int res = GP_OK;
463         char *ptr;
464         int bytes_to_read;
465         unsigned int id;
466
467         GP_DEBUG ("* jamcam_request_thumbnail");
468
469         memset( packet, 0, sizeof( packet ));
470
471         position = jamcam_files[number].position + 0x10;
472
473         *len = 4800;
474
475         ptr = buf;
476
477         if ( camera->port->type == GP_PORT_USB ) {
478                 /* windows driver does this sometimes */
479                 gp_port_usb_msg_write( camera->port,
480                         0xa5,
481                         0x0005,
482                         0x0000,
483                         NULL, 0 );
484
485                 /* just read one row of data at a time */
486                 bytes_to_read = jamcam_files[number].width;
487         } else {
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;
492                 } else {
493                         /* just read one row of data at a time */
494                         bytes_to_read = jamcam_files[number].width;
495                 }
496         }
497
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 );
504
505                 gp_context_progress_update (context, id, y);
506                 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
507                         res = GP_ERROR_CANCEL;
508                         break;
509                 }
510
511                 if ( jamcam_files[number].width == 600 ) {
512                         for( x = 22; x < 578 ; x += 7 ) {
513                                 *(ptr++) = line[x];
514                         }
515                         position += 7 * 600;
516                 } else {
517                         for( x = 0; x < 320 ; ) {
518                                 *(ptr++) = line[x];
519                                 x += 3;
520                                 *(ptr++) = line[x];
521                                 x += 5;
522                         }
523
524                         if ( y % 2 ) {
525                                 position += 5 * 320;
526                         } else {
527                                 position += 3 * 320;
528                         }
529                 }
530         }
531         gp_context_progress_stop (context, id);
532
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,
536                         0xa5,
537                         0x0006,
538                         0x0000,
539                         NULL, 0 );
540         }
541
542         return( res );
543 }
544
545 static int jamcam_write_packet (Camera *camera, unsigned char *packet, int length) {
546         int ret, r;
547
548         GP_DEBUG ("* jamcam_write_packet");
549
550         for (r = 0; r < RETRIES; r++) {
551                 ret = gp_port_write (camera->port, (char*)packet, length);
552                 if (ret == GP_ERROR_TIMEOUT)
553                         continue;
554
555                 return (ret);
556         }
557
558         return (GP_ERROR_TIMEOUT);
559 }
560
561 static int jamcam_read_packet (Camera *camera, unsigned char *packet, int length) {
562         int r = 0;
563         int bytes_read;
564
565         GP_DEBUG ("* jamcam_read_packet");
566         GP_DEBUG ("*** length: %d (0x%x)",
567                 length, length);
568
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)
572                         continue;
573                 if (bytes_read < 0)
574                         return (bytes_read);
575
576                 if ( bytes_read == length ) {
577                         return( GP_OK );
578                 }
579         }
580
581         return (GP_ERROR_TIMEOUT);
582 }
583
584
585 int jamcam_enq (Camera *camera)
586 {
587         int ret, r = 0;
588         unsigned char buf[16];
589
590         GP_DEBUG ("* jamcam_enq");
591
592         memset( buf, 0, 16 );
593
594         switch( camera->port->type ) {
595                 default:
596                 case GP_PORT_SERIAL:
597                         for (r = 0; r < RETRIES; r++) {
598                                 memcpy (buf, "KB99", 4 );
599
600                                 ret = jamcam_write_packet (camera, buf, 4);
601                                 if (ret == GP_ERROR_TIMEOUT)
602                                         continue;
603                                 if (ret != GP_OK)
604                                         return (ret);
605
606                                 ret = jamcam_read_packet (camera, buf, 4);
607                                 if (ret == GP_ERROR_TIMEOUT)
608                                         continue;
609                                 if (ret != GP_OK)
610                                         return (ret);
611
612                                 if ( !memcmp( buf, "KIDB", 4 )) {
613                                         return (GP_OK);
614                                 }
615                         }
616                         return (GP_ERROR_CORRUPTED_DATA);
617                         break;
618
619                 case GP_PORT_USB:
620                         for (r = 0; r < RETRIES; r++) {
621                                 gp_port_usb_msg_write( camera->port,
622                                         0xa5,
623                                         0x0004,
624                                         0x0000,
625                                         NULL, 0 );
626                                 jamcam_set_usb_mem_pointer( camera, 0x0000 );
627
628                                 CHECK( gp_port_read( camera->port, (char *)buf, 0x0c ));
629
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 );
639
640                                         if ( jamcam_mmc_card_size ) {
641                                                 GP_DEBUG (                                                      "* jamcam_enq, MMC card size = %d",
642                                                         jamcam_mmc_card_size );
643                                         }
644
645                                         return (GP_OK);
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 */
649                                         return (GP_OK);
650                                 } else if (( buf[0] == 0xf0 ) &&
651                                                  ( buf[1] == 0xfd ) &&
652                                                  ( buf[2] == 0x03 )) {
653                                         return( GP_OK );
654                                 }
655                         }
656                         return (GP_ERROR_CORRUPTED_DATA);
657                         break;
658         }
659
660         return (GP_ERROR_TIMEOUT);
661 }
662
663 static int jamcam_query_mmc_card (Camera *camera)
664 {
665         int ret, r = 0;
666         unsigned char buf[16];
667
668         GP_DEBUG ("* jamcam_query_mmc_card");
669
670         /* usb port doesn't need this packet, this info found in enquiry reply */
671         if ( camera->port->type == GP_PORT_USB ) {
672                 return( GP_OK );
673         }
674
675         memcpy( buf, "KB04", 4 );
676
677         for (r = 0; r < RETRIES; r++) {
678
679                 ret = jamcam_write_packet (camera, buf, 4);
680                 if (ret == GP_ERROR_TIMEOUT)
681                         continue;
682                 if (ret != GP_OK)
683                         return (ret);
684
685                 ret = jamcam_read_packet (camera, buf, 4);
686                 if (ret == GP_ERROR_TIMEOUT)
687                         continue;
688                 if (ret != GP_OK)
689                         return (ret);
690
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 );
693
694                 if ( jamcam_mmc_card_size ) {
695                         GP_DEBUG ("* jamcam_query_mmc_card, MMC card size = %d",
696                                 jamcam_mmc_card_size );
697                 }
698
699                 return (GP_OK);
700         }
701         return (GP_ERROR_TIMEOUT);
702 }
703