Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / spca50x / spca50x-flash.c
1 /****************************************************************/
2 /* spca50x_flash.c - Gphoto2 library for cameras with a sunplus */
3 /*                   spca50x chip and flash memory              */
4 /*                                                              */
5 /*                                                              */
6 /* Authors: Till Adam <till@adam-lilienthal.de>                 */
7 /*          Ian MacArthur <ian@imm.uklinux.net>                 */
8 /*          John Maushammer <gphoto2@maushammer.com>            */
9 /* based on work done by:                                       */
10 /*          Mark A. Zimmerman <mark@foresthaven.com>            */
11 /*                                                              */
12 /* This library is free software; you can redistribute it       */
13 /* and/or modify it under the terms of the GNU Library General  */
14 /* Public License as published by the Free Software Foundation; */
15 /* either version 2 of the License, or (at your option) any     */
16 /* later version.                                               */
17 /*                                                              */
18 /* This library is distributed in the hope that it will be      */
19 /* useful, but WITHOUT ANY WARRANTY; without even the implied   */
20 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      */
21 /* PURPOSE.  See the GNU Library General Public License for     */
22 /* more details.                                                */
23 /*                                                              */
24 /* You should have received a copy of the GNU Library General   */
25 /* Public License along with this library; if not, write to the */
26 /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
27 /* Boston, MA 02111-1307, USA.                                  */
28 /****************************************************************/
29 #include "config.h"
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include <gphoto2/gphoto2.h>
35 #include <gphoto2/gphoto2-port.h>
36 #include <gphoto2/gphoto2-port-log.h>
37 #include "gphoto2-endian.h"
38
39 #define GP_MODULE "spca50x"
40 #include "spca50x.h"
41 #include "spca50x-flash.h"
42
43 /* forward declarations... local to this file */
44 static int
45 spca500_flash_84D_get_file_info (CameraPrivateLibrary * lib, int index,
46                                                         int *w, int *h, int *t, int *sz);
47
48 /* dsc-350_get_file func. */
49 static int
50 spca500_flash_84D_get_file (CameraPrivateLibrary * pl,
51                 uint8_t ** data, unsigned int *len, int index, int thumbnail);
52
53 /*****************************************************************************/
54 static void
55 free_files (CameraPrivateLibrary *pl)
56 {
57         int i;
58         if (pl->files) {
59                 for (i = 0; i < pl->num_files_on_flash; i++){
60                         if(pl->files[i].thumb) free (pl->files[i].thumb);
61                 }
62                 free(pl->files);
63         }
64 }
65
66 static int
67 spca50x_flash_wait_for_ready(CameraPrivateLibrary *pl)
68 {
69         /* FIXME tweak this. What is reasonable? 30 s seems a bit long */
70         int timeout = 30;
71         uint8_t ready = 0;
72         while (timeout--) {
73                 sleep(1);
74                 if (pl->bridge == BRIDGE_SPCA500) {
75                         CHECK (gp_port_usb_msg_read (pl->gpdev,
76                                                         0x00, 0x0000, 0x0101,
77                                                         (char*)&ready, 0x01));
78                 } else {
79                         if (pl->fw_rev == 1) {
80                                 CHECK (gp_port_usb_msg_read (pl->gpdev,
81                                                         0x0b, 0x0000, 0x0004,
82                                                         (char*)&ready, 0x01));
83                         } else {
84                                 CHECK (gp_port_usb_msg_read (pl->gpdev,
85                                                         0x21, 0x0000, 0x0000,
86                                                         (char*)&ready, 0x01));
87                         }
88                 }
89                 if (ready)
90                         return GP_OK;
91         }
92         return GP_ERROR;
93 }
94
95 static int
96 spca500_flash_84D_wait_while_busy(CameraPrivateLibrary *pl)
97 {
98         int timeout = 30;
99         uint8_t ready = 0;
100         while (timeout--) {
101                 sleep(1);
102         CHECK (gp_port_usb_msg_read (pl->gpdev,
103                                         0x00, 0x0000, 0x0100,
104                                         (char*)&ready, 0x01));
105
106                 if (ready == 0)
107                         return GP_OK;
108         }
109         return GP_ERROR;
110 }
111
112 int
113 spca50x_flash_get_TOC(CameraPrivateLibrary *pl, int *filecount)
114 {
115         uint16_t n_toc_entries;
116         int toc_size = 0;
117         if (pl->dirty_flash == 0){
118                 /* TOC has been read already, and stored in the pl,
119                    so let's not read it again unless "dirty" gets set,
120                    e.g. by a reset, delete or capture action... */
121                 *filecount = pl->num_files_on_flash;
122                 return GP_OK;
123         }
124         pl->num_files_on_flash = 0;
125
126         if (pl->bridge == BRIDGE_SPCA500) { /* for dsc350 type cams */
127                                 /* command mode */
128                 CHECK (gp_port_usb_msg_write (pl->gpdev,
129                                         0x00, 0x0080, 0x0100,
130                                         NULL, 0x00));
131                 /* trigger TOC upload */
132                 CHECK (gp_port_usb_msg_write (pl->gpdev,
133                                         0x05, 0x0000, 0x000d,
134                                         NULL, 0x00));
135                 toc_size = 0x100; /* always 256 for the dsc-350 cams */
136         } else {
137
138                 if (pl->fw_rev == 1) {
139                         CHECK (gp_port_usb_msg_read (pl->gpdev,
140                                                 0x0b, 0x0000, 0x0000,
141                                                 (char*)&n_toc_entries, 0x02));
142                         /* Each file gets two toc entries, one for the image,
143                            one for the thumbnail */
144                         LE16TOH (n_toc_entries);
145                         *filecount = n_toc_entries/2;
146                 } else {
147                         CHECK (gp_port_usb_msg_read (pl->gpdev,
148                                                 0x54, 0x0000, 0x0000,
149                                                 (char*)&n_toc_entries, 0x02));
150                         LE16TOH (n_toc_entries);
151                         *filecount = n_toc_entries;
152                 }
153                 /* If empty, return now */
154                 if (n_toc_entries == 0)
155                         return GP_OK;
156
157                 /* Request the TOC */
158                 if (pl->fw_rev == 1) {
159                         CHECK (gp_port_usb_msg_read (pl->gpdev, 0x0a,
160                                                 n_toc_entries, 0x000c,
161                                                 NULL, 0x00));
162                 } else {
163                         CHECK (gp_port_usb_msg_read (pl->gpdev, 0x54,
164                                                 n_toc_entries, 0x0001,
165                                                 NULL, 0x00));
166                 }
167                 /* slurp it in. Supposedly there's 32 bytes in each entry. */
168                 toc_size = n_toc_entries * 32;
169
170                 /* align */
171                 if (toc_size % 512 != 0)
172                         toc_size = ((toc_size / 512) + 1) * 512;
173         }
174         if (pl->flash_toc)
175                 free (pl->flash_toc);
176         pl->flash_toc = malloc(toc_size);
177         if (!pl->flash_toc)
178                 return GP_ERROR_NO_MEMORY;
179
180         CHECK (spca50x_flash_wait_for_ready(pl));
181
182         if (pl->bridge == BRIDGE_SPCA500) { /* For dsc350 type cams */
183                 /* read the TOC from the cam */
184                 CHECK (gp_port_read (pl->gpdev, pl->flash_toc, toc_size));
185                 /* reset to idle */
186                 CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0));
187                 *filecount = (int)pl->flash_toc[10];
188                 /* Now, create the files info buffer */
189                 free_files(pl);
190                 /* NOTE: using calloc to ensure new block is "empty" */
191                 pl->files = calloc (1, *filecount * sizeof (struct SPCA50xFile));
192                 if (!pl->files)
193                         return GP_ERROR_NO_MEMORY;
194         } else { /* all other cams with flash... */
195                 /* read the TOC from the cam */
196                 CHECK (gp_port_read (pl->gpdev, pl->flash_toc, toc_size));
197         }
198         /* record that TOC has been updated - clear the "dirty" flag */
199         pl->num_files_on_flash = *filecount;
200         pl->dirty_flash = 0;
201
202         return GP_OK;
203 }
204
205
206 int
207 spca50x_flash_get_filecount (CameraPrivateLibrary *pl, int *filecount)
208 {
209         uint16_t response = 0;
210
211         if (pl->bridge == BRIDGE_SPCA500) { /* dsc350 cams */
212                 return spca50x_flash_get_TOC (pl, filecount);
213         } else {
214                 if (pl->fw_rev == 1) {
215                         CHECK (gp_port_usb_msg_read (pl->gpdev,
216                                                 0x0b, 0x0000, 0x0000,
217                                                 (char*)&response, 0x02));
218                         /* Each file gets two toc entries, one for the
219                            image, one for the thumbnail */
220                         LE16TOH (response);
221                         *filecount = response/2;
222                 } else {
223                         CHECK (gp_port_usb_msg_read (pl->gpdev,
224                                                 0x54, 0x0000, 0x0000,
225                                                 (char*)&response, 0x02));
226                         LE16TOH (response);
227                         *filecount = response;
228                 }
229         }
230         return GP_OK;
231 }
232
233 int
234 spca500_flash_delete_file (CameraPrivateLibrary *pl, int index)
235 {
236         if (pl->bridge == BRIDGE_SPCA500) {
237                 /* command mode */
238                 CHECK (gp_port_usb_msg_write (pl->gpdev,
239                                         0x00, 0x0080, 0x0100,
240                                         NULL, 0x00));
241
242                 /* trigger image delete */
243                 CHECK (gp_port_usb_msg_write (pl->gpdev,
244                                         0x07, (index + 1), 0x000a,
245                                         NULL, 0x00));
246
247                 /* reset to idle */
248                 CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0));
249
250                 /* invalidate TOC/info cache */
251                 pl->dirty_flash = 1;
252                 return GP_OK;
253         } else {
254                 /* not supported on the 504 style cams */
255                 return GP_ERROR_NOT_SUPPORTED;
256         }
257 } /* spca500_flash_delete_file */
258
259 int
260 spca50x_flash_delete_all (CameraPrivateLibrary *pl, GPContext *context)
261 {
262         if (pl->bridge == BRIDGE_SPCA500) { /* dsc350 cams */
263                 /* command mode */
264                 CHECK (gp_port_usb_msg_write (pl->gpdev,
265                                         0x00, 0x0080, 0x0100,
266                                         NULL, 0x00));
267
268                 /* delete all command */
269                 CHECK (gp_port_usb_msg_write (pl->gpdev,
270                                         0x07, 0xffff, 0x000a,
271                                         NULL, 0x00));
272
273                 /* wait until the camera is not busy any more */
274                 CHECK (spca500_flash_84D_wait_while_busy(pl));
275         } else {
276                 if (pl->fw_rev == 1) {
277                         CHECK (gp_port_usb_msg_write (pl->gpdev, 0x1, 0x0, 0x1, NULL, 0x0));
278                 } else {
279                         CHECK (gp_port_usb_msg_write (pl->gpdev, 0x52, 0x0, 0x0, NULL, 0x0));
280                 }
281         }
282
283         /* invalidate TOC/info cache */
284         pl->dirty_flash = 1;
285         return GP_OK;
286 }
287
288 int
289 spca500_flash_capture (CameraPrivateLibrary *pl)
290 {
291         if (pl->bridge == BRIDGE_SPCA500) {
292                 /* command mode */
293                 CHECK (gp_port_usb_msg_write (pl->gpdev,
294                                         0x00, 0x0080, 0x0100,
295                                         NULL, 0x00));
296
297                 /* trigger image capture */
298                 CHECK (gp_port_usb_msg_write (pl->gpdev,
299                                         0x03, 0x0000, 0x0004,
300                                         NULL, 0x00));
301
302                 /* wait until the camera is not busy any more */
303                 CHECK (spca500_flash_84D_wait_while_busy(pl));
304
305                 /* invalidate TOC/info cache */
306                 pl->dirty_flash = 1;
307                 return GP_OK;
308         } else if (pl->bridge == BRIDGE_SPCA504B_PD) {
309                 /* trigger image capture */
310                 CHECK (gp_port_usb_msg_write (pl->gpdev,
311                                         0x51, 0x0000, 0x0000,
312                                         NULL, 0));
313
314                 /* wait until the camera is not busy any more */
315                 /* spca50x_flash_wait_for_ready doesn't work here */
316                 sleep(3);
317                 
318                 /* invalidate TOC/info cache */
319                 pl->dirty_flash = 1;
320                 return GP_OK;
321         } else {
322                 /* not supported on the 504 style cams, but procedure used by
323                  * SPCA504_PD will probably work */
324                 return GP_ERROR_NOT_SUPPORTED;
325         }
326 }
327
328 int
329 spca50x_flash_get_file_name (CameraPrivateLibrary *pl, int index, char *name)
330 {
331         uint8_t *p;
332         if (pl->bridge == BRIDGE_SPCA500) {
333                 char p[14];
334                 int w, h, type, size;
335
336                 memset (p, 0, sizeof(p));
337                 /* dsc350 - get the file info, so we can set the file type
338                    correctly */
339                 spca500_flash_84D_get_file_info (pl, index, &w, &h, &type, &size);
340                 if (type < 3){ /*  for single images */
341                         snprintf (p, sizeof(p), "Img%03d.jpg", (index + 1));
342                 }
343                 else if (type < 6){ /*  for multi-frame images */
344                         snprintf (p, sizeof(p), "Img%03d-4.jpg", (index + 1));
345                 }
346                 else if (type < 8){ /*  for avi */
347                         snprintf (p, sizeof(p), "Mov%03d.avi", (index + 1));
348                 }
349                 else{
350                         snprintf (p, sizeof(p), "Unknown");
351                 }
352                 memcpy (name, p, sizeof(p) );
353         } else {
354                 if (pl->fw_rev == 1) {
355                         p = pl->flash_toc + index*2*32;
356                 } else {
357                         p = pl->flash_toc + index*32;
358                 }
359                 memcpy (name, p, 8);
360                 name[8] = '.';
361                 memcpy (name+9, p+8, 3);
362                 name[12] = '\0';
363         }
364         return GP_OK;
365 }
366
367 /* extract ascii-encoded number from file name */
368 static int
369 spca50x_flash_get_number_from_file_name (CameraPrivateLibrary *pl, int index, int *file_number)
370 {
371         char name[13];
372
373         CHECK (spca50x_flash_get_file_name (pl, index, name));
374         if(sscanf(&(name[4]), "%d", file_number) != 1)    /* skip "DSC_" */
375                 return GP_ERROR;
376         return GP_OK;
377 }
378
379 static int
380 spca500_flash_84D_get_file_info (CameraPrivateLibrary * pl, int index,
381                                                         int *w, int *h, int *t, int *sz)
382 {
383         char hdr[260];
384         char waste[260];
385         int i;
386         unsigned long size;
387
388         /* First, check if the info. is already buffered in the cam private lib
389          * We DO NOT want to be fetching the entire thumbnail just to get the file size...*/
390          if ((pl->dirty_flash == 0) && (pl->files[index].type != 0)){
391                  /* This file must have been checked before */
392                 *w = pl->files[index].width ;
393                 *h = pl->files[index].height ;
394                 *t = pl->files[index].type ;
395                 *sz = pl->files[index].size ;
396                 return GP_OK;
397          } else if (pl->dirty_flash != 0){ /* should never happen, but just in case... */
398                 CHECK(spca50x_flash_get_TOC (pl, &i));
399                 if ( index >= i){
400                         /* asking for a picture that doesn't exist */
401                         return GP_ERROR;
402                 }
403          }
404
405         /* ...else we must query the cam the hard way... */
406         /* command mode */
407         CHECK (gp_port_usb_msg_write (pl->gpdev,
408                                 0x00, 0x0080, 0x0100,
409                                 NULL, 0x00));
410         /* trigger Thumbnail upload */
411         CHECK (gp_port_usb_msg_write (pl->gpdev,
412                                 0x07, (index + 1), 0x0000,
413                                 NULL, 0x00));
414         /* NOTE: must use (index + 1) here as the cam indexes images from 1,
415          * whereas libgphoto2 indexes from 0.... */
416
417         /* wait for ready */
418         CHECK (spca50x_flash_wait_for_ready(pl));
419         /* read the header from the cam */
420         CHECK (gp_port_read (pl->gpdev, hdr, 256)); /*  always 256 for the DSC-350+ */
421
422         /* Read the rest of the header... and discard it */
423         CHECK (gp_port_read (pl->gpdev, waste, 256));
424
425         /* Now we have to read in the thumbnail data anyway -
426            so we might as well store it for later */
427         {
428                 int j;
429                 uint8_t * buf;
430                 if (pl->files[index].thumb){
431                         free (pl->files[index].thumb); /* discard any previous thumbnail data */
432                         pl->files[index].thumb = NULL;
433                 }
434                 buf = malloc (38 * 256); /* create a new buffer to hold the thumbnail data */
435                 if (buf){
436                         j = 0;
437                         for (i = 0; i < 38; i++) { /* Now read in the image data */
438                                 /* read a buffer from the cam */
439                                 CHECK (gp_port_read (pl->gpdev, (char *)&buf[j], 256));
440                                 j += 256;
441                         }
442                         pl->files[index].thumb = buf;
443                 } else { /* couldn't get a buffer - read in the data anyway and discard it */
444                         for (i = 0; i < 38; i++) {/* Thumbnails ALWAYS download 38 blocks...*/
445                                 CHECK (gp_port_read (pl->gpdev, waste, 256));
446                         }
447                         pl->files[index].thumb = NULL;
448                 }
449         } /* end of thumbnail storing loop */
450
451         /* reset to idle */
452         CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100,
453                         NULL, 0x0));
454
455         /* OK, now we have a hdr we can work with... */
456         /* try and get the size */
457         size =  ((unsigned long)hdr[15] & 0xff)
458              + (((unsigned long)hdr[16] & 0xff) << 8)
459                  + (((unsigned long)hdr[17] & 0xff) << 16);
460         *sz = size;
461
462         /* Try and determine the file type */
463         /* Should enumerate the possible types properly, somewhere... */
464         i = (int)hdr[2]; /* should be the file type */
465         *t = i;
466         switch (i){
467         case 0: /*  this will be 320 x 240 single-frame */
468                 *w = 320;
469                 *h = 240;
470                 break;
471         case 1: /*  this will be 640 x 480 single-frame */
472                 *w = 640;
473                 *h = 480;
474                 break;
475         case 2: /*  this will be 1024 x 768 single-frame */
476 /* These are actually 640x480 pics - the win driver just expands them
477  * in the host before it stores them... What should we do here? Continue with that
478  * pretence, or tell the user the truth? */
479                 /* *w = 1024; */
480                 /* *h = 768; */
481                 *w = 640;
482                 *h = 480;
483                 break;
484         case 3: /*  this will be 320 x 240 multi-frame */
485                 *w = 320;
486                 *h = 240;
487                 break;
488         case 4: /*  this will be 640 x 480 multi-frame */
489                 *w = 640;
490                 *h = 480;
491                 break;
492         case 5: /*  this will be 1024 x 768 multi-frame */
493 /* See notes above! */
494                 /* *w = 1024; */
495                 /* *h = 768; */
496                 *w = 640;
497                 *h = 480;
498                 break;
499         case 6: /*  ??? TAKE A GUESS!!! 160 x 120 avi ??? MUST verify this sometime.... */
500                 *w = 160;
501                 *h = 120;
502                 break;
503         case 7: /*  this is 320 x 240 avi */
504                 *w = 320;
505                 *h = 240;
506                 break;
507         default:
508                 *t = 99; /*  or something equally invalid... */
509                 *w = 0;
510                 *h = 0;
511                 *sz = 0; /*  if we don't know what it is, it can't have a size! */
512                 break;
513         }
514
515         /* now add this new set of data to the info_cache */
516         if (pl->dirty_flash == 0){
517                 /* Only update the files cache if it exists, i.e. if dirty is zero */
518                 /* We should never get here if dirty is set, however ! */
519                 pl->files[index].type = *t;
520                 pl->files[index].width = *w;
521                 pl->files[index].height = *h;
522                 pl->files[index].size = *sz;
523         }
524
525         return GP_OK;
526
527 } /* end of spca500_flash_84D_get_file_info */
528
529 static int
530 spca50x_process_thumbnail (CameraPrivateLibrary *lib,   /*  context */
531                 uint8_t ** data, unsigned int *len,                     /*  return these items */
532                 uint8_t * buf, uint32_t file_size, int index)   /*  input these items */
533 {
534         uint32_t alloc_size, true_size, w, h, hdrlen;
535         uint8_t *tmp, *rgb_p, *yuv_p;
536         uint8_t *p2 = lib->flash_toc + index*2*32;
537
538         if (lib->bridge == BRIDGE_SPCA500) { /* for dsc 350 cams */
539                 w = 80; /* Always seems to be 80 x 60 for the DSC-350 cams */
540                 h = 60;
541         } else {
542                 /* thumbnails are generated from dc coefficients and are
543                  * therefore w/8 x h/8
544                  * Since the dimensions of the thumbnail in the TOC are
545                  * always [0,0], Use the TOC entry for the full image.
546  */
547                 w = ((p2[0x0c] & 0xff) + (p2[0x0d] & 0xff) * 0x100) / 8;
548                 h = ((p2[0x0e] & 0xff) + (p2[0x0f] & 0xff) * 0x100) / 8;
549         }
550
551         /* Allow for a long header; get the true length later.
552  */
553         hdrlen = 15;
554         alloc_size = w * h * 3 + hdrlen;
555         tmp = malloc (alloc_size);
556         if (!tmp)
557                 return GP_ERROR_NO_MEMORY;
558
559         /* Write the header and get its length. Then, verify that
560          * we allocated enough memory.
561          * This should never fail; it would be nice to have an error
562          * code like GP_ERROR_CAMLIB_INTERNAL for cases like this.
563  */
564         hdrlen = snprintf(tmp, alloc_size, "P6 %d %d 255\n", w, h);
565         true_size = w * h * 3 + hdrlen;
566         if ( true_size > alloc_size ) {
567                 free (tmp);
568                 return GP_ERROR;
569         }
570
571         yuv_p = buf;
572         rgb_p = tmp + hdrlen;
573         while (yuv_p < buf + file_size) {
574                 uint32_t u, v, y, y2;
575                 uint32_t r, g, b;
576
577                 y = yuv_p[0];
578                 y2 = yuv_p[1];
579                 u = yuv_p[2];
580                 v = yuv_p[3];
581
582                 CHECK (yuv2rgb (y, u, v, &r, &g, &b));
583                 *rgb_p++ = r;
584                 *rgb_p++ = g;
585                 *rgb_p++ = b;
586
587                 CHECK (yuv2rgb (y2, u, v, &r, &g, &b));
588                 *rgb_p++ = r;
589                 *rgb_p++ = g;
590                 *rgb_p++ = b;
591
592                 yuv_p += 4;
593         }
594         free (buf);
595         *data = tmp;
596         *len = true_size;
597
598         return GP_OK;
599 } /* spca50x_process_thumbnail */
600
601 static int
602 spca50x_flash_process_image (CameraPrivateLibrary *pl,  /*  context */
603                 uint8_t ** data, unsigned int *len,                             /*  return these items */
604                 uint8_t * buf, uint32_t buf_size, int index)    /*  input these items */
605 {
606         uint8_t *lp_jpg;
607         uint8_t qIndex = 0, format;
608         int file_size;
609
610         int w = pl->files[index].width;
611         int h = pl->files[index].height;
612
613         /* qindex == 2 seems to be right for all the dsc350 images - so far!!! */
614         qIndex = 2 ; /*  FIXME - what to do about Qtable stuff? */
615
616         /* decode the image size */
617         if (w > 320){
618                 format = 0x21; /*  for 640 size images */
619         } else {
620                 format = 0x22; /*  for 320 x 240 size images */
621         }
622
623         file_size = buf_size + SPCA50X_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
624
625         /* now build a jpeg */
626         lp_jpg = malloc (file_size);
627         if (!lp_jpg)
628                 return GP_ERROR_NO_MEMORY;
629
630         create_jpeg_from_data (lp_jpg, buf, qIndex, w,
631                                h, format, buf_size, &file_size,
632                                0, 0);
633         free (buf);
634         lp_jpg = realloc (lp_jpg, file_size);
635         *data = lp_jpg;
636         *len = file_size;
637
638         return (GP_OK);
639 }
640
641 static int
642 spca500_flash_84D_get_file (CameraPrivateLibrary * pl,
643                 uint8_t ** data, unsigned int *len, int index, int thumbnail)
644 {
645         char tbuf[260];         /*  for the file data blocks */
646         int i, j;               /*  general loop vars */
647         int blks;               /*  number of 256 byte blocks to fetch */
648         unsigned int sz;        /*  number of bytes in image */
649         uint8_t *buf;           /*  buffer for the read data */
650         int type;               /*  type of image reported by header */
651         int w, h;               /*  width, height of file being read */
652         int true_len;           /*  length determined by actually counting the loaded data! */
653
654         /* Check the info. first, so we KNOW the file type before we start to download it...! */
655         /* NOTE: The check should be really easy, as the info ought to be in the files info cache */
656         spca500_flash_84D_get_file_info (pl, index, &w, &h, &type, &sz);
657         if (type >= 3) { /* for now, only support single frame still images */
658                 return GP_ERROR_NOT_SUPPORTED;
659                 /* what to do for multi-frame images? (type 3, 4, 5) or avi's? (6, 7) */
660         }
661
662         /* OK, we've decided what type of file it is, now lets upload it... */
663         if ((thumbnail != 0) && (pl->files[index].thumb != NULL)){
664                 /* We can cheat here - we already have the thumbnail data in a cache, so don't load it again */
665                 blks = 38;
666                 buf = pl->files[index].thumb;
667                 pl->files[index].thumb = NULL; /* we will release buf, so this pointer must be "emptied" */
668         }
669         else {
670                 /* We need to download this data from the cam... */
671                 /* set command mode */
672                 CHECK (gp_port_usb_msg_write (pl->gpdev,
673                                         0x00, 0x0080, 0x0100,
674                                         NULL, 0x00));
675
676                 /* trigger image upload */
677                 if (thumbnail){
678                         CHECK (gp_port_usb_msg_write (pl->gpdev,
679                                         0x07, (index + 1), 0x0000,  /*  code 0 gets the thumbnail */
680                                         NULL, 0x00));
681                 } else {
682                         /* code for different image types...? */
683                         CHECK (gp_port_usb_msg_write (pl->gpdev,
684                                         0x07, (index + 1), 0x0001, /*  code 1 gets the main image */
685                                         NULL, 0x00));
686                 }
687
688                 /* wait for ready */
689                 CHECK (spca50x_flash_wait_for_ready(pl));
690
691                 /* read the header from the cam */
692                 CHECK (gp_port_read (pl->gpdev, tbuf, 256)); /*  always 256 for the DSC-350+ */
693
694                 /* Read the rest of the header... and discard it */
695                 CHECK (gp_port_read (pl->gpdev, tbuf, 256));
696
697                 if (thumbnail){
698                         blks = 38 ; /* always 38 blocks in a thumbnail with this setup */
699                         sz = 0; /* unknown, it's NOT recorded in the header or TOC as such... */
700                         /* Note the width/height of the thumbnail is fixed at 80 x 60 I believe. */
701                 }
702                 else { /* full image... */
703                         /* find nearest EVEN number of blocks bigger than the size */
704                         blks = (sz / 256) + 1;
705                         if ((blks & 1) != 0){ /* block count is odd, not allowed */
706                                 blks += 1;
707                         }
708                 }
709
710                 /* create a buffer to hold all the read in data */
711                 buf = malloc (blks * 256);
712                 if (!buf){
713                         return GP_ERROR_NO_MEMORY;
714                 }
715
716                 j = 0; /* k = 0; */
717                 /* Now read in the image data */
718                 for (i = 0; i < blks; i++) {
719                         /* read a buffer from the cam */
720                         CHECK (gp_port_read (pl->gpdev, (char *)&buf[j], 256));
721                         j += 256;
722                 }
723
724                 /* OK, that's all the data read in, set cam to idle */
725                 CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0));
726         }
727
728         /* Count how many bytes file really is! We use this to discard the padding zeros */
729         sz = (blks * 256) - 1;
730         /* look for the last non-zero byte in the file...
731          * I hope the file never *really* ends with a zero!*/
732         while (buf[sz] == 0) {
733                 sz -= 1;
734         }
735         true_len = sz + 1;
736
737         if (thumbnail) { /* post processing of thumbnail data */
738                 CHECK(spca50x_process_thumbnail (pl, data, len, buf, true_len, index));
739         } else { /* post processing of single frame images */
740                 CHECK(spca50x_flash_process_image (pl, data, len, buf, true_len, index));
741         }
742         return GP_OK;
743 } /* end of spca500_flash_84D_get_file */
744
745
746 int
747 spca50x_flash_get_file_dimensions (CameraPrivateLibrary *pl, int index, int *w, int *h)
748 {
749         uint8_t *p;
750
751         if (pl->bridge == BRIDGE_SPCA500) { /* for dsc 350 cams */
752                 int type, size;
753                 return spca500_flash_84D_get_file_info (pl, index, w, h, &type, &size);
754         }
755
756         if (pl->fw_rev == 1) {
757                 p = pl->flash_toc + index*2*32;
758         } else {
759                 p = pl->flash_toc + index*32;
760         }
761
762         *w = (p[0x0c] & 0xff) + (p[0x0d] & 0xff) * 0x100;
763         *h = (p[0x0e] & 0xff) + (p[0x0f] & 0xff) * 0x100;
764         return GP_OK;
765 }
766
767 int
768 spca50x_flash_get_file_size (CameraPrivateLibrary *pl, int index, int *size)
769 {
770         uint8_t *p;
771
772         if (pl->bridge == BRIDGE_SPCA500) { /* for dsc350 cams */
773                 int type, w, h;
774                 return spca500_flash_84D_get_file_info (pl, index, &w, &h, &type, size);
775         }
776
777         if (pl->fw_rev == 1) {
778                 p = pl->flash_toc + index*2*32;
779         } else {
780                 p = pl->flash_toc + index*32;
781         }
782
783         *size =   (p[0x1c] & 0xff)
784                 + (p[0x1d] & 0xff) * 0x100
785                 + (p[0x1e] & 0xff) * 0x10000
786                 + (p[0x1f] & 0xff) * 0x1000000;
787
788         return GP_OK;
789 }
790
791 int
792 spca50x_flash_get_file (CameraPrivateLibrary *lib, GPContext *context,
793                 uint8_t ** data, unsigned int *len, int index, int thumbnail)
794 {
795         uint32_t file_size = 0, aligned_size = 0;
796         uint8_t *p, *buf;
797         int file_number;
798         int align_to, ret;
799
800         if (lib->bridge == BRIDGE_SPCA500) { /* for dsc 350 cams */
801                 return spca500_flash_84D_get_file (lib, data, len, index, thumbnail);
802         }
803
804         if (lib->fw_rev != 1 && thumbnail)
805                 return GP_ERROR_NOT_SUPPORTED;
806
807         if (thumbnail) {
808                 p = lib->flash_toc + (index*2+1) * 32;
809         } else {
810                 if (lib->fw_rev == 1) {
811                         p = lib->flash_toc + index*2*32;
812                 } else {
813                         p = lib->flash_toc + index*32;
814                 }
815         }
816
817         aligned_size = file_size =
818                   (p[0x1c] & 0xff)
819                 + (p[0x1d] & 0xff) * 0x100
820                 + (p[0x1e] & 0xff) * 0x10000;
821
822         /* Trigger upload of image data */
823         if (thumbnail) {
824                 CHECK (gp_port_usb_msg_write (lib->gpdev,
825                                         0x0c, index+1, 0x0006, NULL, 0x00));
826         } else {
827                 if (lib->fw_rev == 1) {
828                         CHECK (gp_port_usb_msg_write (lib->gpdev,
829                                         0x0a, index+1, 0x000d, NULL, 0x00));
830                 } else {
831                         if(lib->bridge != BRIDGE_SPCA504B_PD) {
832                                 CHECK (gp_port_usb_msg_write (lib->gpdev,
833                                         0x54, index+1, 0x0002, NULL, 0x00));
834                         } else {
835                                 CHECK (spca50x_flash_get_number_from_file_name(
836                                         lib, index, &file_number));
837                                 CHECK (gp_port_usb_msg_write (lib->gpdev,
838                                         0x54, file_number, 0x0002, NULL, 0x00));
839                         }
840                 }
841         }
842
843         if ((lib->fw_rev == 1) || (lib->bridge == BRIDGE_SPCA504B_PD)) {
844                 align_to = 0x4000;
845         } else {
846                 align_to = 0x2000;
847         }
848         /* align */
849         if (file_size % align_to != 0)
850                 aligned_size = ((file_size / align_to) + 1) * align_to;
851
852         buf = malloc (aligned_size);
853         if (!buf)
854                 return GP_ERROR_NO_MEMORY;
855
856         ret = spca50x_flash_wait_for_ready(lib);
857         if (ret < GP_OK) {
858                 free (buf);
859                 return ret;
860         }
861         ret = gp_port_read (lib->gpdev, buf, aligned_size);
862         if (ret < GP_OK) {
863                 free (buf);
864                 return ret;
865         }
866         /* For images, we are done now, thumbnails need to be converted from
867          * yuv to rgb and a pbm header added. */
868         if (thumbnail) {
869                 ret = spca50x_process_thumbnail (lib, data, len, buf, file_size, index);
870                 if (ret < GP_OK) {
871                         free (buf);
872                         return ret;
873                 }
874         } else {
875                 *data = buf;
876                 *len = file_size;
877         }
878         return GP_OK;
879 }
880
881 /*
882  * Deinit camera
883  */
884 int
885 spca50x_flash_close (CameraPrivateLibrary *pl, GPContext *context)
886 {
887         if (pl->fw_rev == 1) {
888                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x01, 0x2306,
889                                         NULL, 0x00));
890                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x00, 0x0d04,
891                                         NULL, 0x00));
892         } else {
893                 /* Anything we need to do? */
894
895         }
896
897         if (!pl->dirty_flash && pl->bridge == BRIDGE_SPCA500) {
898                 /* check if we need to free the file info buffers */
899                 free_files(pl);
900         }
901         pl->dirty_flash = 1;
902         return GP_OK;
903 }
904
905 /*
906  * Initialize the camera and write the jpeg registers. Read them back in to
907  * check whether the values are set correctly (wtf?)
908  */
909 int
910 spca50x_flash_init (CameraPrivateLibrary *pl, GPContext *context)
911 {
912         struct JPREG {
913                 int reg;
914                 int val;
915         };
916         struct JPREG jpReg[] = {
917                 { 0x2800, 0x0005 },       { 0x2840, 0x0005 },
918                 { 0x2801, 0x0003 },       { 0x2841, 0x0005 },
919                 { 0x2802, 0x0003 },       { 0x2842, 0x0007 },
920                 { 0x2803, 0x0005 },       { 0x2843, 0x000e },
921                 { 0x2804, 0x0007 },       { 0x2844, 0x001e },
922                 { 0x2805, 0x000c },       { 0x2845, 0x001e },
923                 { 0x2806, 0x000f },       { 0x2846, 0x001e },
924                 { 0x2807, 0x0012 },       { 0x2847, 0x001e },
925                 { 0x2808, 0x0004 },       { 0x2848, 0x0005 },
926                 { 0x2809, 0x0004 },       { 0x2849, 0x0006 },
927                 { 0x280a, 0x0004 },       { 0x284a, 0x0008 },
928                 { 0x280b, 0x0006 },       { 0x284b, 0x0014 },
929                 { 0x280c, 0x0008 },       { 0x284c, 0x001e },
930                 { 0x280d, 0x0011 },       { 0x284d, 0x001e },
931                 { 0x280e, 0x0012 },       { 0x284e, 0x001e },
932                 { 0x280f, 0x0011 },       { 0x284f, 0x001e },
933                 { 0x2810, 0x0004 },       { 0x2850, 0x0007 },
934                 { 0x2811, 0x0004 },       { 0x2851, 0x0008 },
935                 { 0x2812, 0x0005 },       { 0x2852, 0x0011 },
936                 { 0x2813, 0x0007 },       { 0x2853, 0x001e },
937                 { 0x2814, 0x000c },       { 0x2854, 0x001e },
938                 { 0x2815, 0x0011 },       { 0x2855, 0x001e },
939                 { 0x2816, 0x0015 },       { 0x2856, 0x001e },
940                 { 0x2817, 0x0011 },       { 0x2857, 0x001e },
941                 { 0x2818, 0x0004 },       { 0x2858, 0x000e },
942                 { 0x2819, 0x0005 },       { 0x2859, 0x0014 },
943                 { 0x281a, 0x0007 },       { 0x285a, 0x001e },
944                 { 0x281b, 0x0009 },       { 0x285b, 0x001e },
945                 { 0x281c, 0x000f },       { 0x285c, 0x001e },
946                 { 0x281d, 0x001a },       { 0x285d, 0x001e },
947                 { 0x281e, 0x0018 },       { 0x285e, 0x001e },
948                 { 0x281f, 0x0013 },       { 0x285f, 0x001e },
949                 { 0x2820, 0x0005 },       { 0x2860, 0x001e },
950                 { 0x2821, 0x0007 },       { 0x2861, 0x001e },
951                 { 0x2822, 0x000b },       { 0x2862, 0x001e },
952                 { 0x2823, 0x0011 },       { 0x2863, 0x001e },
953                 { 0x2824, 0x0014 },       { 0x2864, 0x001e },
954                 { 0x2825, 0x0021 },       { 0x2865, 0x001e },
955                 { 0x2826, 0x001f },       { 0x2866, 0x001e },
956                 { 0x2827, 0x0017 },       { 0x2867, 0x001e },
957                 { 0x2828, 0x0007 },       { 0x2868, 0x001e },
958                 { 0x2829, 0x000b },       { 0x2869, 0x001e },
959                 { 0x282a, 0x0011 },       { 0x286a, 0x001e },
960                 { 0x282b, 0x0013 },       { 0x286b, 0x001e },
961                 { 0x282c, 0x0018 },       { 0x286c, 0x001e },
962                 { 0x282d, 0x001f },       { 0x286d, 0x001e },
963                 { 0x282e, 0x0022 },       { 0x286e, 0x001e },
964                 { 0x282f, 0x001c },       { 0x286f, 0x001e },
965                 { 0x2830, 0x000f },       { 0x2870, 0x001e },
966                 { 0x2831, 0x0013 },       { 0x2871, 0x001e },
967                 { 0x2832, 0x0017 },       { 0x2872, 0x001e },
968                 { 0x2833, 0x001a },       { 0x2873, 0x001e },
969                 { 0x2834, 0x001f },       { 0x2874, 0x001e },
970                 { 0x2835, 0x0024 },       { 0x2875, 0x001e },
971                 { 0x2836, 0x0024 },       { 0x2876, 0x001e },
972                 { 0x2837, 0x001e },       { 0x2877, 0x001e },
973                 { 0x2838, 0x0016 },       { 0x2878, 0x001e },
974                 { 0x2839, 0x001c },       { 0x2879, 0x001e },
975                 { 0x283a, 0x001d },       { 0x287a, 0x001e },
976                 { 0x283b, 0x001d },       { 0x287b, 0x001e },
977                 { 0x283c, 0x0022 },       { 0x287c, 0x001e },
978                 { 0x283d, 0x001e },       { 0x287d, 0x001e },
979                 { 0x283e, 0x001f },       { 0x287e, 0x001e },
980                 { 0x283f, 0x001e },       { 0x287f, 0x001e }
981         };
982
983         int len = sizeof (jpReg) / sizeof (jpReg[0]);
984         uint8_t bytes[4];
985         int i;
986
987         if (pl->fw_rev == 1) {
988                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0000, 0x2000,
989                                         NULL, 0x00));
990                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0013, 0x2301,
991                                         NULL, 0x00));
992                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0001, 0x2883,
993                                         NULL, 0x00));
994
995                 for (i=0 ; i<len ; i++) {
996                         CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00,
997                                                 jpReg[i].val, jpReg[i].reg,
998                                                 NULL, 0x00));
999                         CHECK (gp_port_usb_msg_read (pl->gpdev, 0x00, 0x0000,
1000                                                 jpReg[i].reg, bytes, 0x01));
1001                 }
1002                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0001, 0x2501,
1003                                         NULL, 0x00));
1004                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0000, 0x2306,
1005                                         NULL, 0x00));
1006                 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x08, 0x0000, 0x0006,
1007                                         NULL, 0x00));
1008
1009                 /* Read the same thing thrice, for whatever reason.
1010                  * From working on getting iso traffic working with this chip, I've found
1011                  * out, that 0x01, 0x0000, 0x0001 polls the chip for completion of a
1012                  * command. Unfortunately it is of yet unclear, what the exact procedure
1013                  * is. Until we know, let's keep this here. */
1014                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001,
1015                                         bytes, 0x01));
1016                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001,
1017                                         bytes, 0x01));
1018                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001,
1019                                         bytes, 0x01));
1020
1021                 /* Set to idle? */
1022                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x000f,
1023                                         NULL, 0x00));
1024
1025         } else {
1026
1027                 uint8_t bytes[7];
1028                 time_t t;
1029                 struct tm *ftm;
1030                 int i;
1031
1032                 /* firmware detection */
1033                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x20, 0x0000, 0x0000,
1034                                         bytes, 0x01));
1035                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x20, 0x0000, 0x0000,
1036                                         bytes, 0x05));
1037                 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x21, 0x0000, 0x0000,
1038                                         bytes, 0x01));
1039
1040                 /*
1041                  * The cam is supposed to sync up with the computer time here
1042                  * somehow, or at least that's what we think. */
1043
1044                 time(&t);
1045                 ftm = localtime(&t);
1046
1047                 bytes[0] = ftm->tm_sec;
1048                 bytes[1] = ftm->tm_min;
1049                 bytes[2] = ftm->tm_hour;
1050                 bytes[3] = 0;               /* what is that? either 0x0 or 0x6 */
1051                 bytes[4] = ftm->tm_mday;
1052                 bytes[5] = ftm->tm_mon+1;
1053                 bytes[6] = ftm->tm_year-100; /* stupido. Year is 1900 + tm_year.
1054                                                 We need two digits only. */
1055
1056
1057                 GP_DEBUG("Timestamp: %4d-%02d-%02d %2d:%02d:%02d",
1058                                 ftm->tm_year+1900,ftm->tm_mon+1,ftm->tm_mday,
1059                                 ftm->tm_hour,ftm->tm_min,ftm->tm_sec);
1060
1061                 for (i=0;i<7;i++)
1062                         CHECK (gp_port_usb_msg_write (pl->gpdev, 0x29, 0x0000,
1063                                                 i, bytes+i, 0x01));
1064
1065         }
1066
1067         pl->dirty_flash = 1;
1068         return GP_OK;
1069 }