Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / spca50x / spca50x-sdram.c
1 /****************************************************************/
2 /* spca50x_sdram.c - Gphoto2 library for cameras with sunplus   */
3 /*             spca50x chips                                    */
4 /*                                                              */
5 /* Copyright © 2002, 2003 Till Adam                             */
6 /*                                                              */
7 /* Author: Till Adam <till@adam-lilienthal.de>                  */
8 /*                                                              */
9 /* This library is free software; you can redistribute it       */
10 /* and/or modify it under the terms of the GNU Library General  */
11 /* Public License as published by the Free Software Foundation; */
12 /* either version 2 of the License, or (at your option) any     */
13 /* later version.                                               */
14 /*                                                              */
15 /* This library is distributed in the hope that it will be      */
16 /* useful, but WITHOUT ANY WARRANTY; without even the implied   */
17 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      */
18 /* PURPOSE.  See the GNU Library General Public License for     */
19 /* more details.                                                */
20 /*                                                              */
21 /* You should have received a copy of the GNU Library General   */
22 /* Public License along with this library; if not, write to the */
23 /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
24 /* Boston, MA 02111-1307, USA.                                  */
25 /****************************************************************/
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <gphoto2/gphoto2.h>
32 #include "gphoto2-endian.h"
33
34 #include "spca50x.h"
35 #include "spca50x-sdram.h"
36 #include "spca50x-registers.h"
37 #include "spca50x-avi-header.h"
38
39 #ifdef ENABLE_NLS
40 #  include <libintl.h>
41 #  undef _
42 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
43 #  ifdef gettext_noop
44 #    define N_(String) gettext_noop (String)
45 #  else
46 #    define N_(String) (String)
47 #  endif
48 #else
49 #  define textdomain(String) (String)
50 #  define gettext(String) (String)
51 #  define dgettext(Domain,Message) (Message)
52 #  define dcgettext(Domain,Message,Type) (Message)
53 #  define bindtextdomain(Domain,Directory) (Domain)
54 #  define _(String) (String)
55 #  define N_(String) (String)
56 #endif
57
58 #define GP_MODULE "spca50x"
59 static int spca50x_mode_set_idle (CameraPrivateLibrary * lib);
60 static int spca50x_is_idle (CameraPrivateLibrary * lib);
61 static int spca50x_mode_set_download (CameraPrivateLibrary * lib);
62 static int spca50x_download_data (CameraPrivateLibrary * lib, uint32_t start,
63                                  unsigned int size, uint8_t * buf);
64 static int spca50x_get_FATs (CameraPrivateLibrary * lib, int dramtype);
65 static int spca50x_sdram_get_file_count_and_fat_count
66                             (CameraPrivateLibrary * lib, int dramtype);
67 static int spca50x_get_avi_thumbnail (CameraPrivateLibrary * lib,
68                                      uint8_t ** buf, unsigned int *len,
69                                      struct SPCA50xFile *g_file);
70 static int spca50x_get_image_thumbnail (CameraPrivateLibrary * lib,
71                                        uint8_t ** buf, unsigned int *len,
72                                        struct SPCA50xFile *g_file);
73 static int spca50x_get_avi (CameraPrivateLibrary * lib, uint8_t ** buf,
74                            unsigned int *len, struct SPCA50xFile *g_file);
75 static int spca50x_get_image (CameraPrivateLibrary * lib, uint8_t ** buf,
76                              unsigned int *len, struct SPCA50xFile *g_file);
77 static inline uint8_t *put_dword (uint8_t * ptr, uint32_t value);
78
79
80 static int
81 spca50x_sdram_get_fat_page (CameraPrivateLibrary * lib, int index,
82                             int dramtype, uint8_t *p)
83 {
84         switch (dramtype) {
85                 case 4: /* 128 Mbit */
86                         CHECK (spca50x_download_data
87                                         (lib, 0x7fff80 -
88                                          index * 0x80,
89                                          SPCA50X_FAT_PAGE_SIZE, p));
90                         break;
91                 case 3: /* 64 Mbit */
92                         CHECK (spca50x_download_data
93                                         (lib, 0x3fff80 -
94                                          index * 0x80,
95                                          SPCA50X_FAT_PAGE_SIZE, p));
96                         break;
97                 default:
98                         break;
99         }
100
101         return GP_OK;
102 }
103
104 static int
105 spca50x_sdram_get_file_count_and_fat_count (CameraPrivateLibrary * lib,
106                                             int dramtype)
107 {
108         uint8_t theFat[256];
109
110         lib->num_fats = 0;
111         lib->num_files_on_sdram = 0;
112
113         if (lib->bridge == BRIDGE_SPCA500){
114                 uint8_t lower, upper;
115
116                 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x5, 0, 0, NULL, 0));
117                 sleep (1);
118                 CHECK (gp_port_usb_msg_read
119                                 (lib->gpdev, 0, 0, 0xe15,
120                                  (uint8_t *) & lib->num_files_on_sdram, 1));
121                 LE32TOH (lib->num_files_on_sdram);
122
123                 /*  get fatscount */
124                 CHECK (gp_port_usb_msg_write
125                                 (lib->gpdev, 0x05, 0x0000, 0x0008, NULL, 0));
126                 sleep (1);
127                 CHECK (gp_port_usb_msg_read
128                                 (lib->gpdev, 0, 0, 0x0e19,
129                                  (uint8_t *) & lower, 1));
130                 CHECK (gp_port_usb_msg_read
131                                 (lib->gpdev, 0, 0, 0x0e20,
132                                  (uint8_t *) & upper, 1));
133
134                 lib->num_fats = ((upper & 0xFF << 8) | (lower & 0xFF));
135         } else {
136                 while (1) {
137                         CHECK (spca50x_sdram_get_fat_page (lib, lib->num_fats,
138                                                     dramtype, theFat));
139                         if (theFat[0] == 0xFF)
140                                 break;
141
142                         if (theFat[0] == 0x08 || theFat[0] == 0x00)
143                                 lib->num_files_on_sdram++;
144
145                         lib->num_fats++;
146                 }
147         }
148         return (GP_OK);
149 }
150
151 int
152 spca50x_sdram_delete_file (CameraPrivateLibrary * lib, unsigned int index)
153 {
154         struct SPCA50xFile *g_file;
155         uint16_t fat_index;
156
157         CHECK (spca50x_sdram_get_file_info (lib, index, &g_file));
158
159         if (lib->bridge == BRIDGE_SPCA500)
160                 fat_index = 0x70FF - g_file->fat_start - 1;
161         else                    /* if (lib->bridge == BRIDGE_SPCA504) */
162                 fat_index = 0xD8000 - g_file->fat_start - 1;
163
164         CHECK (gp_port_usb_msg_write
165                (lib->gpdev, 0x06, fat_index, 0x0007, NULL, 0));
166         sleep (1);
167
168         /* Reread fats the next time it is accessed */
169         lib->dirty_sdram = 1;
170
171         return GP_OK;
172 }
173
174 int
175 spca50x_sdram_delete_all (CameraPrivateLibrary * lib)
176 {
177         if (lib->fw_rev == 2) {
178                 CHECK (gp_port_usb_msg_write
179                        (lib->gpdev, 0x71, 0x0000, 0x0000, NULL, 0));
180
181         } else {
182                 CHECK (gp_port_usb_msg_write
183                        (lib->gpdev, 0x02, 0x0000, 0x0005, NULL, 0));
184         }
185         sleep (3);
186
187         /* Reread fats the next time it is accessed */
188         lib->dirty_sdram = 1;
189         return GP_OK;
190 }
191
192 int
193 spca50x_sdram_request_file (CameraPrivateLibrary * lib, uint8_t ** buf,
194                      unsigned int *len, unsigned int number, int *type)
195 {
196         struct SPCA50xFile *g_file;
197
198         CHECK (spca50x_sdram_get_file_info (lib, number, &g_file));
199
200         *type = g_file->mime_type;
201         if (g_file->mime_type == SPCA50X_FILE_TYPE_AVI)
202                 return (spca50x_get_avi (lib, buf, len, g_file));
203         else
204                 return (spca50x_get_image (lib, buf, len, g_file));
205 }
206
207 static int
208 spca50x_get_image (CameraPrivateLibrary * lib, uint8_t ** buf,
209                   unsigned int *len, struct SPCA50xFile *g_file)
210 {
211         uint8_t *p, *lp_jpg;
212         uint8_t qIndex = 0, format;
213         uint32_t start;
214         uint8_t *mybuf;
215         int size, o_size, file_size, ret;
216         int omit_escape = 0;
217
218         p = g_file->fat;
219
220         /* get the position in memory where the image is */
221         start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100;
222         start *= 128;
223
224         /* decode the image size */
225         if (lib->bridge == BRIDGE_SPCA500) {
226                 o_size = size = (p[5] & 0xff) * 0x100 + (p[6] & 0xff) * 0x10000;
227                 qIndex = p[7] & 0x0f;
228         } else {
229                 o_size = size =
230                                 (p[13] & 0xff) * 0x10000
231                                 + (p[12] & 0xff) * 0x100
232                                 + (p[11] & 0xff);
233                 if (lib->fw_rev == 1) {
234                         qIndex = p[7] & 0x0f;
235                 } else if (lib->fw_rev == 2) {
236                         omit_escape = 1;
237                         qIndex = p[10] & 0x0f;
238                 }
239         }
240
241         format = 0x21;
242
243         /* align */
244         if (size % 64 != 0)
245                 size = ((size / 64) + 1) * 64;
246
247         file_size = size + SPCA50X_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
248
249         /* slurp in the image */
250         mybuf = malloc (size);
251         if (!mybuf)
252                 return GP_ERROR_NO_MEMORY;
253
254         if (lib->bridge == BRIDGE_SPCA504) {
255                 ret = spca50x_download_data (lib, start, size, mybuf);
256                 if (ret < GP_OK) {
257                         free (mybuf);
258                         return ret;
259                 }
260         } else if (lib->bridge == BRIDGE_SPCA500) {
261                 /* find the file index on the camera */
262                 int index;
263
264                 index = (g_file->fat - lib->fats) / SPCA50X_FAT_PAGE_SIZE;
265                 spca50x_reset (lib);
266                 /* trigger upload of image at that index */
267                 ret = gp_port_usb_msg_write (lib->gpdev, 0x06,
268                                               0x70FF - index, 0x01, NULL, 0);
269                 if (ret < GP_OK) {
270                         free (mybuf);
271                         return ret;
272                 }
273                 sleep (1);
274                 ret = gp_port_read (lib->gpdev, mybuf, size);
275                 if (ret < GP_OK) {
276                         free (mybuf);
277                         return ret;
278                 }
279                 /* the smallest ones are in a different format */
280                 if ((p[20] & 0xff) == 2)
281                         format = 0x22;
282         }
283         /* now build a jpeg */
284         lp_jpg = malloc (file_size);
285         if (!lp_jpg) {
286                 free (mybuf);
287                 return GP_ERROR_NO_MEMORY;
288         }
289         create_jpeg_from_data (lp_jpg, mybuf, qIndex, g_file->width,
290                                g_file->height, format, o_size, &file_size,
291                                0, omit_escape);
292
293         free (mybuf);
294         lp_jpg = realloc (lp_jpg, file_size);
295         *buf = lp_jpg;
296         *len = file_size;
297
298         return (GP_OK);
299 }
300
301 static int
302 spca50x_get_avi (CameraPrivateLibrary * lib, uint8_t ** buf,
303                 unsigned int *len, struct SPCA50xFile *g_file)
304 {
305         int i, j, length, ret;
306         int frame_count = 0, frames_per_fat = 0, fn = 0;
307         int size = 0;
308         int file_size;
309         int index_size;
310         uint32_t frame_size = 0, frame_width = 0, frame_height = 0;
311         uint32_t total_frame_size = 0;
312         uint32_t start = 0;
313         uint8_t *p, *mybuf, *avi, *start_of_file, *start_of_frame, *data;
314         uint8_t qIndex;
315         uint8_t *avi_index, *avi_index_ptr;
316         uint8_t index_item[16];
317
318         /* FIXME */
319         if (lib->bridge == BRIDGE_SPCA500)
320                 return GP_ERROR_NOT_SUPPORTED;
321
322         p = g_file->fat;
323
324         if (lib->fw_rev == 2)
325                 qIndex = p[10] & 0x0f;
326         else
327                 qIndex = p[7] & 0x0f;
328
329         avi = mybuf = start_of_file = data = NULL;
330
331         /* get the position in memory where the movie is */
332         start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100;
333         start *= 128;
334
335         /* Frame w and h and qIndex dont change, so just use the values
336          * of the first frame */
337         frame_width = (p[8] & 0xFF) * 16;
338         frame_height = (p[9] & 0xFF) * 16;
339
340         /* Each movie consists of a number of frames, and can have more than
341          * one fat page. Iterate over all fat pages for this movie and count
342          * all frames in all fats. Same for size. */
343         for (i = g_file->fat_start; i <= g_file->fat_end; i++) {
344                 frames_per_fat = (p[49] & 0xFF) * 0x100 + (p[48] & 0xFF);
345                 frame_count += frames_per_fat;
346                 size += (p[13] & 0xFF) * 0x10000 + (p[12] & 0xFF) * 0x100 +
347                         (p[11] & 0xFF);
348                 if (frames_per_fat < 60)
349                         break;
350                 p += SPCA50X_FAT_PAGE_SIZE;
351         }
352         /* align */
353         size = (size + 63) & 0xffffffc0;
354
355         /* mem for index */
356         index_size = frame_count * 16;
357         avi_index_ptr = avi_index = malloc (index_size);
358         if (!avi_index)
359                 return GP_ERROR_NO_MEMORY;
360
361         /* slurp in the movie */
362         mybuf = malloc (size);
363         if (!mybuf) {
364                 free (avi_index);
365                 return GP_ERROR_NO_MEMORY;
366         }
367
368         ret = spca50x_download_data (lib, start, size, mybuf);
369         if (ret < GP_OK) {
370                 free (avi_index);
371                 free (mybuf);
372                 return ret;
373         }
374
375         /* Now write our data to a file with an avi header */
376         file_size = size + SPCA50X_AVI_HEADER_LENGTH
377                 + (SPCA50X_JPG_DEFAULT_HEADER_LENGTH * frame_count)
378                 + 8 + index_size        /* for index chunk */
379                 + 1024 * 10 * frame_count;
380
381         avi = malloc (file_size);
382         if (!avi) {
383                 free (avi_index);
384                 free (mybuf);
385                 return GP_ERROR_NO_MEMORY;
386         }
387
388         start_of_file = avi;
389
390         /* prepare index item */
391         put_dword (index_item, 0x63643030);     /* 00dc */
392         put_dword (index_item + 4, 0x10);       /*  KEYFRAME */
393
394         /* copy the header from the template */
395         memcpy (avi, SPCA50xAviHeader, SPCA50X_AVI_HEADER_LENGTH);
396
397         /* put the width and height into the riff header */
398         put_dword(avi + 0x40, frame_width);
399         put_dword(avi + 0x44, frame_height);
400
401         /* and at 0xb0 and 0xb4 */
402         put_dword(avi + 0xb0, frame_width);
403         put_dword(avi + 0xb4, frame_height);
404
405         avi += SPCA50X_AVI_HEADER_LENGTH;
406
407         /* Reset to the first fat */
408         p = g_file->fat;
409         data = mybuf;
410
411         /* Iterate over fats and frames in each fat and build a jpeg for
412          * each frame. Add the jpeg to the avi and write an index entry. */
413         for (i = g_file->fat_start; i <= g_file->fat_end; i++) {
414                 frames_per_fat = ((p[49] & 0xFF) * 0x100 + (p[48] & 0xFF));
415
416                 /* frames per fat might be lying, so double check how
417                    many frames were already processed */
418                 if (frames_per_fat > 60 || frames_per_fat == 0
419                     || fn + frames_per_fat > frame_count)
420                         break;
421
422                 for (j = 0; j < frames_per_fat; j++) {
423                         frame_size = ((p[52 + j * 3] & 0xFF) * 0x10000)
424                                 + ((p[51 + j * 3] & 0xFF) * 0x100) +
425                                 (p[50 + j * 3] & 0xFF);
426
427                         memcpy (avi, SPCA50xAviFrameHeader,
428                                         SPCA50X_AVI_FRAME_HEADER_LENGTH);
429
430                         avi += SPCA50X_AVI_FRAME_HEADER_LENGTH;
431                         start_of_frame = avi;
432
433                         /* jpeg starts here */
434                         create_jpeg_from_data (avi, data, qIndex, frame_width,
435                                                frame_height, 0x22, frame_size,
436                                                &length, 1, 0);
437
438                         data += (frame_size + 7) & 0xfffffff8;
439                         avi += length;
440                         /* Make sure the next frame is aligned */
441                         if ((avi - start_of_frame) % 2 != 0)
442                                 avi++;
443
444                         /* Now we know the real frame size after escaping and
445                          * adding the EOI marker. Put it in the frame header. */
446                         frame_size = avi - start_of_frame;
447                         put_dword (start_of_frame - 4, frame_size);
448                         put_dword (index_item + 8,
449                                    start_of_frame - start_of_file -
450                                    SPCA50X_AVI_HEADER_LENGTH - 4);
451                         put_dword (index_item + 12, frame_size);
452                         memcpy (avi_index_ptr, index_item, 16);
453                         avi_index_ptr += 16;
454                         fn++;
455                 }
456                 p += SPCA50X_FAT_PAGE_SIZE;
457         }
458         total_frame_size = avi - (start_of_file + SPCA50X_AVI_HEADER_LENGTH - 4);
459         put_dword (start_of_file + SPCA50X_AVI_HEADER_LENGTH - 8,
460                    total_frame_size);
461
462         avi = put_dword (avi, 0x31786469);      /* idx1 */
463         avi = put_dword (avi, index_size);
464         memcpy (avi, avi_index, index_size);
465         avi += index_size;
466         free (avi_index);
467         put_dword (start_of_file + 0x30, frame_count);
468         put_dword (start_of_file + 0x8c, frame_count);
469
470         /* And reuse total_frame_size for the file size RIFF marker at offset
471          * 4 */
472         total_frame_size = avi - (start_of_file + 4);
473         put_dword (start_of_file + 4, total_frame_size);
474
475         free (mybuf);
476         start_of_file = realloc (start_of_file, avi - start_of_file);
477         *buf = start_of_file;
478         *len = avi - start_of_file;
479         return (GP_OK);
480 }
481
482 int
483 spca50x_sdram_request_thumbnail (CameraPrivateLibrary * lib, uint8_t ** buf,
484                           unsigned int *len, unsigned int number, int *type)
485 {
486         struct SPCA50xFile *g_file;
487
488         CHECK (spca50x_sdram_get_file_info (lib, number, &g_file));
489
490         *type = g_file->mime_type;
491         if (g_file->mime_type == SPCA50X_FILE_TYPE_AVI) {
492                 return (spca50x_get_avi_thumbnail (lib, buf, len, g_file));
493         } else {
494
495                 /* the spca500 stores the quality in p[20], the rest of them
496                  * in [p40].  We need to check for the smallest resolution of
497                  * the mini, since resolution does not have thumbnails.
498                  * Download the full image instead.
499                  * Low:    320x240                2
500                  * Middle: 640x480                0
501                  * High:  1024x768 (interpolated) 1*/
502                 if (lib->bridge == BRIDGE_SPCA500
503                     && (g_file->fat[20] & 0xFF) == 2) {
504                         return (spca50x_get_image (lib, buf, len, g_file));
505
506                 } else {
507                         return (spca50x_get_image_thumbnail
508                                 (lib, buf, len, g_file));
509                 }
510         }
511 }
512
513
514 static int
515 spca50x_get_avi_thumbnail (CameraPrivateLibrary * lib, uint8_t ** buf,
516                           unsigned int *len, struct SPCA50xFile *g_file)
517 {
518         uint8_t *p, *lp_jpg;
519         uint8_t qIndex;
520         uint32_t start;
521         uint8_t *mybuf;
522         int size, o_size, file_size;
523         int w, h, ret;
524
525         /* FIXME */
526         if (lib->bridge == BRIDGE_SPCA500)
527                 return GP_ERROR_NOT_SUPPORTED;
528
529         p = g_file->fat;
530
531         /* get the position in memory where the image is */
532         start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100;
533         start *= 128;
534
535         /* decode the image size */
536         o_size = size =
537                 (p[52] & 0xff) * 0x10000 + (p[51] & 0xff) * 0x100 +
538                 (p[50] & 0xff);
539         qIndex = p[7] & 0x0f;
540         w = (int) ((p[8] & 0xFF) * 16);
541         h = (int) ((p[9] & 0xFF) * 16);
542
543         /* align */
544         if (size % 64 != 0)
545                 size = ((size / 64) + 1) * 64;
546
547         file_size = size + SPCA50X_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
548
549         /* slurp in the image */
550         mybuf = malloc (size);
551         if (!mybuf)
552                 return GP_ERROR_NO_MEMORY;
553
554         ret = spca50x_download_data (lib, start, size, mybuf);
555         if (ret < GP_OK) {
556                 free (mybuf);
557                 return ret;
558         }
559
560         /* now build a jpeg */
561         lp_jpg = malloc (file_size);
562         if (!lp_jpg) {
563                 free (mybuf);
564                 return GP_ERROR_NO_MEMORY;
565         }
566
567         create_jpeg_from_data (lp_jpg, mybuf, qIndex, g_file->width,
568                                g_file->height, 0x22, o_size, &file_size, 0, 0);
569         free (mybuf);
570         lp_jpg = realloc (lp_jpg, file_size);
571         *buf = lp_jpg;
572         *len = file_size;
573
574         return (GP_OK);
575 }
576
577
578 static int
579 spca50x_get_image_thumbnail (CameraPrivateLibrary * lib, uint8_t ** buf,
580                             unsigned int *len, struct SPCA50xFile *g_file)
581 {
582         unsigned int size;
583         uint8_t *p;
584         uint32_t start;
585         uint8_t *mybuf = NULL;
586         uint8_t *tmp;
587         unsigned int t_width, t_height;
588         uint8_t *yuv_p;
589         uint8_t *rgb_p;
590         int headerlength, ret;
591
592         p = g_file->fat;
593
594         start = (p[3] & 0xff) + (p[4] & 0xff) * 0x100;
595         start *= 128;
596
597         size = g_file->width * g_file->height * 2 / 64;
598         t_width = g_file->width / 8;
599         t_height = g_file->height / 8;
600         /* Adjust the headerlenght */
601         headerlength = 13;
602         if (t_width > 99) headerlength++;
603         if (t_height > 99) headerlength++;
604
605         /* align */
606         if (size % 64 != 0)
607                 size = ((size / 64) + 1) * 64;
608
609         mybuf = malloc (size);
610
611         if (lib->bridge == BRIDGE_SPCA504) {
612                 ret = spca50x_download_data (lib, start, size, mybuf);
613                 if (ret < GP_OK) {
614                         free (mybuf);
615                         return ret;
616                 }
617         } else if (lib->bridge == BRIDGE_SPCA500) {
618                 /* find the file index on the camera */
619                 int index;
620
621                 index = (g_file->fat - lib->fats) / SPCA50X_FAT_PAGE_SIZE;
622                 spca50x_reset (lib);
623                 /* trigger upload of thumbnail at that index */
624                 ret = gp_port_usb_msg_write (lib->gpdev, 0x06,
625                                               0x70FF - index, 0x09, NULL, 0);
626                 if (ret < GP_OK) {
627                         free (mybuf);
628                         return ret;
629                 }
630                 sleep (1);
631                 ret = gp_port_read (lib->gpdev, mybuf, size);
632                 if (ret < GP_OK) {
633                         free (mybuf);
634                         return ret;
635                 }
636         }
637         *len = t_width * t_height * 3 + headerlength;
638         *buf = malloc (*len);
639         if (!*buf) {
640                 free (mybuf);
641                 return (GP_ERROR_NO_MEMORY);
642         }
643
644         tmp = *buf;
645         snprintf (tmp, *len, "P6 %d %d 255\n", t_width, t_height);
646         tmp += headerlength;
647
648         yuv_p = mybuf;
649         rgb_p = tmp;
650         while (yuv_p < mybuf + (t_width * t_height * 2)) {
651                 unsigned int u, v, y, y2;
652                 unsigned int r, g, b;
653
654                 y = yuv_p[0];
655                 y2 = yuv_p[1];
656                 u = yuv_p[2];
657                 v = yuv_p[3];
658
659                 CHECK (yuv2rgb (y, u, v, &r, &g, &b));
660                 *rgb_p++ = r;
661                 *rgb_p++ = g;
662                 *rgb_p++ = b;
663
664                 CHECK (yuv2rgb (y2, u, v, &r, &g, &b));
665                 *rgb_p++ = r;
666                 *rgb_p++ = g;
667                 *rgb_p++ = b;
668
669                 yuv_p += 4;
670         }
671
672         free (mybuf);
673         return (GP_OK);
674 }
675
676
677 int
678 spca50x_sdram_get_info (CameraPrivateLibrary * lib)
679 {
680         unsigned int index;
681         uint8_t dramtype = 0;
682         uint8_t *p;
683         uint32_t start_page, end_page;
684         uint8_t file_type;
685
686         GP_DEBUG ("* spca50x_sdram_get_info");
687
688         if (lib->bridge == BRIDGE_SPCA504) {
689                 if (!spca50x_is_idle (lib))
690                         spca50x_mode_set_idle (lib);
691
692                 spca50x_mode_set_download (lib);
693
694                 CHECK (gp_port_usb_msg_write
695                        (lib->gpdev, 0x00, 0x0001, SPCA50X_REG_AutoPbSize, NULL,
696                         0));
697
698                 CHECK (gp_port_usb_msg_read
699                        (lib->gpdev, 0, 0, SPCA50X_REG_DramType,
700                         (uint8_t *) & dramtype, 1));
701                 dramtype &= 0xFF;
702         }
703
704         CHECK (spca50x_sdram_get_file_count_and_fat_count (lib, dramtype));
705
706         if (lib->num_files_on_sdram > 0) {
707                 CHECK (spca50x_get_FATs (lib, dramtype));
708
709                 index = lib->files[lib->num_files_on_sdram - 1].fat_end;
710                 p = lib->fats + SPCA50X_FAT_PAGE_SIZE * index;
711                 /* p now points to the fat of the last image of the last file */
712
713                 file_type = p[0];
714                 start_page = ((p[2] & 0xFF) << 8) | (p[1] & 0xFF);
715                 end_page = start_page + (((p[6] & 0xFF) << 8) | (p[5] & 0xFF));
716                 if (file_type == SPCA50X_FILE_TYPE_IMAGE)
717                         end_page = end_page + 0xA0;
718
719                 lib->size_used = (end_page - 0x2800) * SPCA50X_FAT_PAGE_SIZE;
720         } else
721                 lib->size_used = 0;
722
723         lib->size_free =
724                 16 * 1024 * 1024 - 0x2800 * SPCA50X_FAT_PAGE_SIZE - lib->size_used;
725         lib->dirty_sdram = 0;
726
727         return GP_OK;
728 }
729
730 int
731 spca50x_sdram_get_file_info (CameraPrivateLibrary * lib, unsigned int index,
732                       struct SPCA50xFile **g_file)
733 {
734         if (lib->dirty_sdram)
735                 CHECK (spca50x_sdram_get_info (lib));
736         *g_file = &(lib->files[index]);
737         return GP_OK;
738 }
739 static int
740 spca50x_mode_set_idle (CameraPrivateLibrary * lib)
741 {
742         CHECK (gp_port_usb_msg_write
743                (lib->gpdev, 0, SPCA50X_CamMode_Idle, SPCA50X_REG_CamMode, NULL,
744                 0));
745         return GP_OK;
746 }
747
748 static int
749 spca50x_is_idle (CameraPrivateLibrary * lib)
750 {
751         int mode;
752
753         CHECK (gp_port_usb_msg_read
754                (lib->gpdev, 0, 0, SPCA50X_REG_CamMode, (uint8_t *) & mode, 1));
755
756         return mode == SPCA50X_CamMode_Idle ? 1 : 0;
757 }
758
759 static int
760 spca50x_mode_set_download (CameraPrivateLibrary * lib)
761 {
762         CHECK (gp_port_usb_msg_write
763                (lib->gpdev, 0, SPCA50X_CamMode_Upload, SPCA50X_REG_CamMode, NULL,
764                 0));
765         return GP_OK;
766 }
767
768 static int
769 spca50x_download_data (CameraPrivateLibrary * lib, uint32_t start,
770                       unsigned int size, uint8_t * buf)
771 {
772
773         uint8_t foo;
774         uint8_t vlcAddressL, vlcAddressM, vlcAddressH;
775
776         if (!spca50x_is_idle (lib))
777                 spca50x_mode_set_idle (lib);
778
779         spca50x_mode_set_download (lib);
780
781         foo = size & 0xFF;
782         CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo,
783                                       SPCA50X_REG_SdramSizeL, NULL, 0));
784         foo = (size >> 8) & 0xFF;
785         CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo,
786                                       SPCA50X_REG_SdramSizeM, NULL, 0));
787         foo = (size >> 16) & 0xFF;
788         CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo,
789                                       SPCA50X_REG_SdramSizeH, NULL, 0));
790
791         CHECK (gp_port_usb_msg_read
792                (lib->gpdev, 0, 0, SPCA50X_REG_VlcAddressL,
793                 (uint8_t *) & vlcAddressL, 1));
794         CHECK (gp_port_usb_msg_read
795                (lib->gpdev, 0, 0, SPCA50X_REG_VlcAddressM,
796                 (uint8_t *) & vlcAddressM, 1));
797         CHECK (gp_port_usb_msg_read
798                (lib->gpdev, 0, 0, SPCA50X_REG_VlcAddressH,
799                 (uint8_t *) & vlcAddressH, 1));
800
801         foo = start & 0xFF;
802         CHECK (gp_port_usb_msg_write
803                (lib->gpdev, 0, foo, SPCA50X_REG_VlcAddressL, NULL, 0));
804         foo = (start >> 8) & 0xFF;
805         CHECK (gp_port_usb_msg_write
806                (lib->gpdev, 0, foo, SPCA50X_REG_VlcAddressM, NULL, 0));
807         foo = (start >> 16) & 0xFF;
808         CHECK (gp_port_usb_msg_write
809                (lib->gpdev, 0, foo, SPCA50X_REG_VlcAddressH, NULL, 0));
810
811         /* Set mode to ram -> usb */
812         CHECK (gp_port_usb_msg_write
813                (lib->gpdev, 0, SPCA50X_DramUsb, SPCA50X_REG_PbSrc, NULL, 0));
814         /* and pull the trigger */
815         CHECK (gp_port_usb_msg_write
816                (lib->gpdev, 0, SPCA50X_TrigDramFifo, SPCA50X_REG_Trigger, NULL,
817                 0));
818
819         CHECK (gp_port_read (lib->gpdev, buf, size));
820
821         CHECK (gp_port_usb_msg_write
822                (lib->gpdev, 0, vlcAddressL, SPCA50X_REG_VlcAddressL, NULL, 0));
823         CHECK (gp_port_usb_msg_write
824                (lib->gpdev, 0, vlcAddressM, SPCA50X_REG_VlcAddressM, NULL, 0));
825         CHECK (gp_port_usb_msg_write
826                (lib->gpdev, 0, vlcAddressH, SPCA50X_REG_VlcAddressH, NULL, 0));
827
828         spca50x_mode_set_idle (lib);
829         return GP_OK;
830 }
831
832 static int
833 spca50x_get_FATs (CameraPrivateLibrary * lib, int dramtype)
834 {
835         uint8_t type;
836         unsigned int index = 0;
837         unsigned int file_index = 0;
838         uint8_t *p = NULL;
839         uint8_t buf[14];
840
841         /* Reset image and movie counter */
842         lib->num_images = lib->num_movies = 0;
843
844         if (lib->fats) {
845                 free (lib->fats);
846                 lib->fats = NULL;
847         }
848
849         if (lib->files) {
850                 free (lib->files);
851                 lib->files = NULL;
852         }
853
854         lib->fats = malloc (lib->num_fats * SPCA50X_FAT_PAGE_SIZE);
855         lib->files = malloc (lib->num_files_on_sdram * sizeof (struct SPCA50xFile));
856
857         p = lib->fats;
858         if (lib->bridge == BRIDGE_SPCA504) {
859                 while (index < lib->num_fats) {
860                         CHECK (spca50x_sdram_get_fat_page (lib, index,
861                                                 dramtype, p));
862                         if (p[0] == 0xFF)
863                                 break;
864
865                         index++;
866                         p += SPCA50X_FAT_PAGE_SIZE;
867                 }
868         } else if (lib->bridge == BRIDGE_SPCA500) {
869                 /* for the spca500, download the whole fat in one go. */
870                 spca50x_reset (lib);
871                 CHECK (gp_port_usb_msg_write
872                        (lib->gpdev, 0x05, 0x00, 0x07, NULL, 0));
873                 sleep (1);
874                 CHECK (gp_port_read
875                        (lib->gpdev, lib->fats,
876                         lib->num_fats * SPCA50X_FAT_PAGE_SIZE));
877         }
878
879         p = lib->fats;
880         index = 0;
881
882         while (index < lib->num_fats) {
883
884                 type = p[0];
885                 /* While the spca504a indicates start of avi as 0x08 and cont.
886                  * of avi as 0x80, the spca500 uses 0x03 for both. Each frame
887                  * gets its own fat table with a sequence number at p[18]. */
888                 if ((type == 0x80) || (type == 0x03 && (p[18] != 0x00))) {
889                         /* continuation of an avi */
890                         lib->files[file_index - 1].fat_end = index;
891                 } else {
892                         /* its an image */
893                         if (type == 0x00 || type == 0x01) {
894                                 snprintf (buf, 13, "Image%03d.jpg",
895                                           ++lib->num_images);
896                                 lib->files[file_index].mime_type =
897                                         SPCA50X_FILE_TYPE_IMAGE;
898                         } else if ((type == 0x08) || (type == 0x03)) {
899                                 /* its the start of an avi */
900                                 snprintf (buf, 13, "Movie%03d.avi",
901                                           ++lib->num_movies);
902                                 lib->files[file_index].mime_type =
903                                         SPCA50X_FILE_TYPE_AVI;
904                         }
905                         lib->files[file_index].fat = p;
906                         lib->files[file_index].fat_start = index;
907                         lib->files[file_index].fat_end = index;
908                         lib->files[file_index].name = strdup (buf);
909                         if (lib->bridge == BRIDGE_SPCA504) {
910                                 lib->files[file_index].width =
911                                         (p[8] & 0xFF) * 16;
912                                 lib->files[file_index].height =
913                                         (p[9] & 0xFF) * 16;
914                         } else if (lib->bridge == BRIDGE_SPCA500) {
915                                 int w, h;
916
917                                 if (p[20] == 2) {
918                                         w = 320;
919                                         h = 240;
920                                 } else {
921                                         w = 640;
922                                         h = 480;
923                                 }
924                                 lib->files[file_index].width = w;
925                                 lib->files[file_index].height = h;
926                         }
927                         lib->files[file_index].thumb = NULL;
928                         file_index++;
929                 }
930                 p += SPCA50X_FAT_PAGE_SIZE;
931                 index++;
932         }
933
934         return GP_OK;
935 }
936
937 static inline uint8_t *
938 put_dword (uint8_t * ptr, uint32_t value)
939 {
940         ptr[0] = (value & 0xff);
941         ptr[1] = (value & 0xff00) >> 8;
942         ptr[2] = (value & 0xff0000) >> 16;
943         ptr[3] = (value & 0xff000000) >> 24;
944         return ptr + 4;
945 }