1 /****************************************************************/
2 /* spca50x_sdram.c - Gphoto2 library for cameras with sunplus */
5 /* Copyright © 2002, 2003 Till Adam */
7 /* Author: Till Adam <till@adam-lilienthal.de> */
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 */
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 */
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 /****************************************************************/
31 #include <gphoto2/gphoto2.h>
32 #include "gphoto2-endian.h"
35 #include "spca50x-sdram.h"
36 #include "spca50x-registers.h"
37 #include "spca50x-avi-header.h"
42 # define _(String) dgettext (GETTEXT_PACKAGE, String)
44 # define N_(String) gettext_noop (String)
46 # define N_(String) (String)
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)
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);
81 spca50x_sdram_get_fat_page (CameraPrivateLibrary * lib, int index,
82 int dramtype, uint8_t *p)
85 case 4: /* 128 Mbit */
86 CHECK (spca50x_download_data
89 SPCA50X_FAT_PAGE_SIZE, p));
92 CHECK (spca50x_download_data
95 SPCA50X_FAT_PAGE_SIZE, p));
105 spca50x_sdram_get_file_count_and_fat_count (CameraPrivateLibrary * lib,
111 lib->num_files_on_sdram = 0;
113 if (lib->bridge == BRIDGE_SPCA500){
114 uint8_t lower, upper;
116 CHECK (gp_port_usb_msg_write (lib->gpdev, 0x5, 0, 0, NULL, 0));
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);
124 CHECK (gp_port_usb_msg_write
125 (lib->gpdev, 0x05, 0x0000, 0x0008, NULL, 0));
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));
134 lib->num_fats = ((upper & 0xFF << 8) | (lower & 0xFF));
137 CHECK (spca50x_sdram_get_fat_page (lib, lib->num_fats,
139 if (theFat[0] == 0xFF)
142 if (theFat[0] == 0x08 || theFat[0] == 0x00)
143 lib->num_files_on_sdram++;
152 spca50x_sdram_delete_file (CameraPrivateLibrary * lib, unsigned int index)
154 struct SPCA50xFile *g_file;
157 CHECK (spca50x_sdram_get_file_info (lib, index, &g_file));
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;
164 CHECK (gp_port_usb_msg_write
165 (lib->gpdev, 0x06, fat_index, 0x0007, NULL, 0));
168 /* Reread fats the next time it is accessed */
169 lib->dirty_sdram = 1;
175 spca50x_sdram_delete_all (CameraPrivateLibrary * lib)
177 if (lib->fw_rev == 2) {
178 CHECK (gp_port_usb_msg_write
179 (lib->gpdev, 0x71, 0x0000, 0x0000, NULL, 0));
182 CHECK (gp_port_usb_msg_write
183 (lib->gpdev, 0x02, 0x0000, 0x0005, NULL, 0));
187 /* Reread fats the next time it is accessed */
188 lib->dirty_sdram = 1;
193 spca50x_sdram_request_file (CameraPrivateLibrary * lib, uint8_t ** buf,
194 unsigned int *len, unsigned int number, int *type)
196 struct SPCA50xFile *g_file;
198 CHECK (spca50x_sdram_get_file_info (lib, number, &g_file));
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));
204 return (spca50x_get_image (lib, buf, len, g_file));
208 spca50x_get_image (CameraPrivateLibrary * lib, uint8_t ** buf,
209 unsigned int *len, struct SPCA50xFile *g_file)
212 uint8_t qIndex = 0, format;
215 int size, o_size, file_size, ret;
220 /* get the position in memory where the image is */
221 start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100;
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;
230 (p[13] & 0xff) * 0x10000
231 + (p[12] & 0xff) * 0x100
233 if (lib->fw_rev == 1) {
234 qIndex = p[7] & 0x0f;
235 } else if (lib->fw_rev == 2) {
237 qIndex = p[10] & 0x0f;
245 size = ((size / 64) + 1) * 64;
247 file_size = size + SPCA50X_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
249 /* slurp in the image */
250 mybuf = malloc (size);
252 return GP_ERROR_NO_MEMORY;
254 if (lib->bridge == BRIDGE_SPCA504) {
255 ret = spca50x_download_data (lib, start, size, mybuf);
260 } else if (lib->bridge == BRIDGE_SPCA500) {
261 /* find the file index on the camera */
264 index = (g_file->fat - lib->fats) / SPCA50X_FAT_PAGE_SIZE;
266 /* trigger upload of image at that index */
267 ret = gp_port_usb_msg_write (lib->gpdev, 0x06,
268 0x70FF - index, 0x01, NULL, 0);
274 ret = gp_port_read (lib->gpdev, mybuf, size);
279 /* the smallest ones are in a different format */
280 if ((p[20] & 0xff) == 2)
283 /* now build a jpeg */
284 lp_jpg = malloc (file_size);
287 return GP_ERROR_NO_MEMORY;
289 create_jpeg_from_data (lp_jpg, mybuf, qIndex, g_file->width,
290 g_file->height, format, o_size, &file_size,
294 lp_jpg = realloc (lp_jpg, file_size);
302 spca50x_get_avi (CameraPrivateLibrary * lib, uint8_t ** buf,
303 unsigned int *len, struct SPCA50xFile *g_file)
305 int i, j, length, ret;
306 int frame_count = 0, frames_per_fat = 0, fn = 0;
310 uint32_t frame_size = 0, frame_width = 0, frame_height = 0;
311 uint32_t total_frame_size = 0;
313 uint8_t *p, *mybuf, *avi, *start_of_file, *start_of_frame, *data;
315 uint8_t *avi_index, *avi_index_ptr;
316 uint8_t index_item[16];
319 if (lib->bridge == BRIDGE_SPCA500)
320 return GP_ERROR_NOT_SUPPORTED;
324 if (lib->fw_rev == 2)
325 qIndex = p[10] & 0x0f;
327 qIndex = p[7] & 0x0f;
329 avi = mybuf = start_of_file = data = NULL;
331 /* get the position in memory where the movie is */
332 start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100;
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;
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 +
348 if (frames_per_fat < 60)
350 p += SPCA50X_FAT_PAGE_SIZE;
353 size = (size + 63) & 0xffffffc0;
356 index_size = frame_count * 16;
357 avi_index_ptr = avi_index = malloc (index_size);
359 return GP_ERROR_NO_MEMORY;
361 /* slurp in the movie */
362 mybuf = malloc (size);
365 return GP_ERROR_NO_MEMORY;
368 ret = spca50x_download_data (lib, start, size, mybuf);
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;
381 avi = malloc (file_size);
385 return GP_ERROR_NO_MEMORY;
390 /* prepare index item */
391 put_dword (index_item, 0x63643030); /* 00dc */
392 put_dword (index_item + 4, 0x10); /* KEYFRAME */
394 /* copy the header from the template */
395 memcpy (avi, SPCA50xAviHeader, SPCA50X_AVI_HEADER_LENGTH);
397 /* put the width and height into the riff header */
398 put_dword(avi + 0x40, frame_width);
399 put_dword(avi + 0x44, frame_height);
401 /* and at 0xb0 and 0xb4 */
402 put_dword(avi + 0xb0, frame_width);
403 put_dword(avi + 0xb4, frame_height);
405 avi += SPCA50X_AVI_HEADER_LENGTH;
407 /* Reset to the first fat */
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));
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)
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);
427 memcpy (avi, SPCA50xAviFrameHeader,
428 SPCA50X_AVI_FRAME_HEADER_LENGTH);
430 avi += SPCA50X_AVI_FRAME_HEADER_LENGTH;
431 start_of_frame = avi;
433 /* jpeg starts here */
434 create_jpeg_from_data (avi, data, qIndex, frame_width,
435 frame_height, 0x22, frame_size,
438 data += (frame_size + 7) & 0xfffffff8;
440 /* Make sure the next frame is aligned */
441 if ((avi - start_of_frame) % 2 != 0)
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);
456 p += SPCA50X_FAT_PAGE_SIZE;
458 total_frame_size = avi - (start_of_file + SPCA50X_AVI_HEADER_LENGTH - 4);
459 put_dword (start_of_file + SPCA50X_AVI_HEADER_LENGTH - 8,
462 avi = put_dword (avi, 0x31786469); /* idx1 */
463 avi = put_dword (avi, index_size);
464 memcpy (avi, avi_index, index_size);
467 put_dword (start_of_file + 0x30, frame_count);
468 put_dword (start_of_file + 0x8c, frame_count);
470 /* And reuse total_frame_size for the file size RIFF marker at offset
472 total_frame_size = avi - (start_of_file + 4);
473 put_dword (start_of_file + 4, total_frame_size);
476 start_of_file = realloc (start_of_file, avi - start_of_file);
477 *buf = start_of_file;
478 *len = avi - start_of_file;
483 spca50x_sdram_request_thumbnail (CameraPrivateLibrary * lib, uint8_t ** buf,
484 unsigned int *len, unsigned int number, int *type)
486 struct SPCA50xFile *g_file;
488 CHECK (spca50x_sdram_get_file_info (lib, number, &g_file));
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));
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.
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));
507 return (spca50x_get_image_thumbnail
508 (lib, buf, len, g_file));
515 spca50x_get_avi_thumbnail (CameraPrivateLibrary * lib, uint8_t ** buf,
516 unsigned int *len, struct SPCA50xFile *g_file)
522 int size, o_size, file_size;
526 if (lib->bridge == BRIDGE_SPCA500)
527 return GP_ERROR_NOT_SUPPORTED;
531 /* get the position in memory where the image is */
532 start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100;
535 /* decode the image size */
537 (p[52] & 0xff) * 0x10000 + (p[51] & 0xff) * 0x100 +
539 qIndex = p[7] & 0x0f;
540 w = (int) ((p[8] & 0xFF) * 16);
541 h = (int) ((p[9] & 0xFF) * 16);
545 size = ((size / 64) + 1) * 64;
547 file_size = size + SPCA50X_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
549 /* slurp in the image */
550 mybuf = malloc (size);
552 return GP_ERROR_NO_MEMORY;
554 ret = spca50x_download_data (lib, start, size, mybuf);
560 /* now build a jpeg */
561 lp_jpg = malloc (file_size);
564 return GP_ERROR_NO_MEMORY;
567 create_jpeg_from_data (lp_jpg, mybuf, qIndex, g_file->width,
568 g_file->height, 0x22, o_size, &file_size, 0, 0);
570 lp_jpg = realloc (lp_jpg, file_size);
579 spca50x_get_image_thumbnail (CameraPrivateLibrary * lib, uint8_t ** buf,
580 unsigned int *len, struct SPCA50xFile *g_file)
585 uint8_t *mybuf = NULL;
587 unsigned int t_width, t_height;
590 int headerlength, ret;
594 start = (p[3] & 0xff) + (p[4] & 0xff) * 0x100;
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 */
602 if (t_width > 99) headerlength++;
603 if (t_height > 99) headerlength++;
607 size = ((size / 64) + 1) * 64;
609 mybuf = malloc (size);
611 if (lib->bridge == BRIDGE_SPCA504) {
612 ret = spca50x_download_data (lib, start, size, mybuf);
617 } else if (lib->bridge == BRIDGE_SPCA500) {
618 /* find the file index on the camera */
621 index = (g_file->fat - lib->fats) / SPCA50X_FAT_PAGE_SIZE;
623 /* trigger upload of thumbnail at that index */
624 ret = gp_port_usb_msg_write (lib->gpdev, 0x06,
625 0x70FF - index, 0x09, NULL, 0);
631 ret = gp_port_read (lib->gpdev, mybuf, size);
637 *len = t_width * t_height * 3 + headerlength;
638 *buf = malloc (*len);
641 return (GP_ERROR_NO_MEMORY);
645 snprintf (tmp, *len, "P6 %d %d 255\n", t_width, t_height);
650 while (yuv_p < mybuf + (t_width * t_height * 2)) {
651 unsigned int u, v, y, y2;
652 unsigned int r, g, b;
659 CHECK (yuv2rgb (y, u, v, &r, &g, &b));
664 CHECK (yuv2rgb (y2, u, v, &r, &g, &b));
678 spca50x_sdram_get_info (CameraPrivateLibrary * lib)
681 uint8_t dramtype = 0;
683 uint32_t start_page, end_page;
686 GP_DEBUG ("* spca50x_sdram_get_info");
688 if (lib->bridge == BRIDGE_SPCA504) {
689 if (!spca50x_is_idle (lib))
690 spca50x_mode_set_idle (lib);
692 spca50x_mode_set_download (lib);
694 CHECK (gp_port_usb_msg_write
695 (lib->gpdev, 0x00, 0x0001, SPCA50X_REG_AutoPbSize, NULL,
698 CHECK (gp_port_usb_msg_read
699 (lib->gpdev, 0, 0, SPCA50X_REG_DramType,
700 (uint8_t *) & dramtype, 1));
704 CHECK (spca50x_sdram_get_file_count_and_fat_count (lib, dramtype));
706 if (lib->num_files_on_sdram > 0) {
707 CHECK (spca50x_get_FATs (lib, dramtype));
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 */
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;
719 lib->size_used = (end_page - 0x2800) * SPCA50X_FAT_PAGE_SIZE;
724 16 * 1024 * 1024 - 0x2800 * SPCA50X_FAT_PAGE_SIZE - lib->size_used;
725 lib->dirty_sdram = 0;
731 spca50x_sdram_get_file_info (CameraPrivateLibrary * lib, unsigned int index,
732 struct SPCA50xFile **g_file)
734 if (lib->dirty_sdram)
735 CHECK (spca50x_sdram_get_info (lib));
736 *g_file = &(lib->files[index]);
740 spca50x_mode_set_idle (CameraPrivateLibrary * lib)
742 CHECK (gp_port_usb_msg_write
743 (lib->gpdev, 0, SPCA50X_CamMode_Idle, SPCA50X_REG_CamMode, NULL,
749 spca50x_is_idle (CameraPrivateLibrary * lib)
753 CHECK (gp_port_usb_msg_read
754 (lib->gpdev, 0, 0, SPCA50X_REG_CamMode, (uint8_t *) & mode, 1));
756 return mode == SPCA50X_CamMode_Idle ? 1 : 0;
760 spca50x_mode_set_download (CameraPrivateLibrary * lib)
762 CHECK (gp_port_usb_msg_write
763 (lib->gpdev, 0, SPCA50X_CamMode_Upload, SPCA50X_REG_CamMode, NULL,
769 spca50x_download_data (CameraPrivateLibrary * lib, uint32_t start,
770 unsigned int size, uint8_t * buf)
774 uint8_t vlcAddressL, vlcAddressM, vlcAddressH;
776 if (!spca50x_is_idle (lib))
777 spca50x_mode_set_idle (lib);
779 spca50x_mode_set_download (lib);
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));
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));
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));
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,
819 CHECK (gp_port_read (lib->gpdev, buf, size));
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));
828 spca50x_mode_set_idle (lib);
833 spca50x_get_FATs (CameraPrivateLibrary * lib, int dramtype)
836 unsigned int index = 0;
837 unsigned int file_index = 0;
841 /* Reset image and movie counter */
842 lib->num_images = lib->num_movies = 0;
854 lib->fats = malloc (lib->num_fats * SPCA50X_FAT_PAGE_SIZE);
855 lib->files = malloc (lib->num_files_on_sdram * sizeof (struct SPCA50xFile));
858 if (lib->bridge == BRIDGE_SPCA504) {
859 while (index < lib->num_fats) {
860 CHECK (spca50x_sdram_get_fat_page (lib, index,
866 p += SPCA50X_FAT_PAGE_SIZE;
868 } else if (lib->bridge == BRIDGE_SPCA500) {
869 /* for the spca500, download the whole fat in one go. */
871 CHECK (gp_port_usb_msg_write
872 (lib->gpdev, 0x05, 0x00, 0x07, NULL, 0));
875 (lib->gpdev, lib->fats,
876 lib->num_fats * SPCA50X_FAT_PAGE_SIZE));
882 while (index < lib->num_fats) {
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;
893 if (type == 0x00 || type == 0x01) {
894 snprintf (buf, 13, "Image%03d.jpg",
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",
902 lib->files[file_index].mime_type =
903 SPCA50X_FILE_TYPE_AVI;
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 =
912 lib->files[file_index].height =
914 } else if (lib->bridge == BRIDGE_SPCA500) {
924 lib->files[file_index].width = w;
925 lib->files[file_index].height = h;
927 lib->files[file_index].thumb = NULL;
930 p += SPCA50X_FAT_PAGE_SIZE;
937 static inline uint8_t *
938 put_dword (uint8_t * ptr, uint32_t value)
940 ptr[0] = (value & 0xff);
941 ptr[1] = (value & 0xff00) >> 8;
942 ptr[2] = (value & 0xff0000) >> 16;
943 ptr[3] = (value & 0xff000000) >> 24;