1 /****************************************************************/
2 /* spca50x_flash.c - Gphoto2 library for cameras with a sunplus */
3 /* spca50x chip and flash memory */
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> */
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 */
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 */
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 /****************************************************************/
34 #include <gphoto2/gphoto2.h>
35 #include <gphoto2/gphoto2-port.h>
36 #include <gphoto2/gphoto2-port-log.h>
37 #include "gphoto2-endian.h"
39 #define GP_MODULE "spca50x"
41 #include "spca50x-flash.h"
43 /* forward declarations... local to this file */
45 spca500_flash_84D_get_file_info (CameraPrivateLibrary * lib, int index,
46 int *w, int *h, int *t, int *sz);
48 /* dsc-350_get_file func. */
50 spca500_flash_84D_get_file (CameraPrivateLibrary * pl,
51 uint8_t ** data, unsigned int *len, int index, int thumbnail);
53 /*****************************************************************************/
55 free_files (CameraPrivateLibrary *pl)
59 for (i = 0; i < pl->num_files_on_flash; i++){
60 if(pl->files[i].thumb) free (pl->files[i].thumb);
67 spca50x_flash_wait_for_ready(CameraPrivateLibrary *pl)
69 /* FIXME tweak this. What is reasonable? 30 s seems a bit long */
74 if (pl->bridge == BRIDGE_SPCA500) {
75 CHECK (gp_port_usb_msg_read (pl->gpdev,
77 (char*)&ready, 0x01));
79 if (pl->fw_rev == 1) {
80 CHECK (gp_port_usb_msg_read (pl->gpdev,
82 (char*)&ready, 0x01));
84 CHECK (gp_port_usb_msg_read (pl->gpdev,
86 (char*)&ready, 0x01));
96 spca500_flash_84D_wait_while_busy(CameraPrivateLibrary *pl)
102 CHECK (gp_port_usb_msg_read (pl->gpdev,
103 0x00, 0x0000, 0x0100,
104 (char*)&ready, 0x01));
113 spca50x_flash_get_TOC(CameraPrivateLibrary *pl, int *filecount)
115 uint16_t n_toc_entries;
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;
124 pl->num_files_on_flash = 0;
126 if (pl->bridge == BRIDGE_SPCA500) { /* for dsc350 type cams */
128 CHECK (gp_port_usb_msg_write (pl->gpdev,
129 0x00, 0x0080, 0x0100,
131 /* trigger TOC upload */
132 CHECK (gp_port_usb_msg_write (pl->gpdev,
133 0x05, 0x0000, 0x000d,
135 toc_size = 0x100; /* always 256 for the dsc-350 cams */
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;
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;
153 /* If empty, return now */
154 if (n_toc_entries == 0)
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,
163 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x54,
164 n_toc_entries, 0x0001,
167 /* slurp it in. Supposedly there's 32 bytes in each entry. */
168 toc_size = n_toc_entries * 32;
171 if (toc_size % 512 != 0)
172 toc_size = ((toc_size / 512) + 1) * 512;
175 free (pl->flash_toc);
176 pl->flash_toc = malloc(toc_size);
178 return GP_ERROR_NO_MEMORY;
180 CHECK (spca50x_flash_wait_for_ready(pl));
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));
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 */
190 /* NOTE: using calloc to ensure new block is "empty" */
191 pl->files = calloc (1, *filecount * sizeof (struct SPCA50xFile));
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));
198 /* record that TOC has been updated - clear the "dirty" flag */
199 pl->num_files_on_flash = *filecount;
207 spca50x_flash_get_filecount (CameraPrivateLibrary *pl, int *filecount)
209 uint16_t response = 0;
211 if (pl->bridge == BRIDGE_SPCA500) { /* dsc350 cams */
212 return spca50x_flash_get_TOC (pl, filecount);
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 */
221 *filecount = response/2;
223 CHECK (gp_port_usb_msg_read (pl->gpdev,
224 0x54, 0x0000, 0x0000,
225 (char*)&response, 0x02));
227 *filecount = response;
234 spca500_flash_delete_file (CameraPrivateLibrary *pl, int index)
236 if (pl->bridge == BRIDGE_SPCA500) {
238 CHECK (gp_port_usb_msg_write (pl->gpdev,
239 0x00, 0x0080, 0x0100,
242 /* trigger image delete */
243 CHECK (gp_port_usb_msg_write (pl->gpdev,
244 0x07, (index + 1), 0x000a,
248 CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0));
250 /* invalidate TOC/info cache */
254 /* not supported on the 504 style cams */
255 return GP_ERROR_NOT_SUPPORTED;
257 } /* spca500_flash_delete_file */
260 spca50x_flash_delete_all (CameraPrivateLibrary *pl, GPContext *context)
262 if (pl->bridge == BRIDGE_SPCA500) { /* dsc350 cams */
264 CHECK (gp_port_usb_msg_write (pl->gpdev,
265 0x00, 0x0080, 0x0100,
268 /* delete all command */
269 CHECK (gp_port_usb_msg_write (pl->gpdev,
270 0x07, 0xffff, 0x000a,
273 /* wait until the camera is not busy any more */
274 CHECK (spca500_flash_84D_wait_while_busy(pl));
276 if (pl->fw_rev == 1) {
277 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x1, 0x0, 0x1, NULL, 0x0));
279 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x52, 0x0, 0x0, NULL, 0x0));
283 /* invalidate TOC/info cache */
289 spca500_flash_capture (CameraPrivateLibrary *pl)
291 if (pl->bridge == BRIDGE_SPCA500) {
293 CHECK (gp_port_usb_msg_write (pl->gpdev,
294 0x00, 0x0080, 0x0100,
297 /* trigger image capture */
298 CHECK (gp_port_usb_msg_write (pl->gpdev,
299 0x03, 0x0000, 0x0004,
302 /* wait until the camera is not busy any more */
303 CHECK (spca500_flash_84D_wait_while_busy(pl));
305 /* invalidate TOC/info cache */
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,
314 /* wait until the camera is not busy any more */
315 /* spca50x_flash_wait_for_ready doesn't work here */
318 /* invalidate TOC/info cache */
322 /* not supported on the 504 style cams, but procedure used by
323 * SPCA504_PD will probably work */
324 return GP_ERROR_NOT_SUPPORTED;
329 spca50x_flash_get_file_name (CameraPrivateLibrary *pl, int index, char *name)
332 if (pl->bridge == BRIDGE_SPCA500) {
334 int w, h, type, size;
336 memset (p, 0, sizeof(p));
337 /* dsc350 - get the file info, so we can set the file type
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));
343 else if (type < 6){ /* for multi-frame images */
344 snprintf (p, sizeof(p), "Img%03d-4.jpg", (index + 1));
346 else if (type < 8){ /* for avi */
347 snprintf (p, sizeof(p), "Mov%03d.avi", (index + 1));
350 snprintf (p, sizeof(p), "Unknown");
352 memcpy (name, p, sizeof(p) );
354 if (pl->fw_rev == 1) {
355 p = pl->flash_toc + index*2*32;
357 p = pl->flash_toc + index*32;
361 memcpy (name+9, p+8, 3);
367 /* extract ascii-encoded number from file name */
369 spca50x_flash_get_number_from_file_name (CameraPrivateLibrary *pl, int index, int *file_number)
373 CHECK (spca50x_flash_get_file_name (pl, index, name));
374 if(sscanf(&(name[4]), "%d", file_number) != 1) /* skip "DSC_" */
380 spca500_flash_84D_get_file_info (CameraPrivateLibrary * pl, int index,
381 int *w, int *h, int *t, int *sz)
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 ;
397 } else if (pl->dirty_flash != 0){ /* should never happen, but just in case... */
398 CHECK(spca50x_flash_get_TOC (pl, &i));
400 /* asking for a picture that doesn't exist */
405 /* ...else we must query the cam the hard way... */
407 CHECK (gp_port_usb_msg_write (pl->gpdev,
408 0x00, 0x0080, 0x0100,
410 /* trigger Thumbnail upload */
411 CHECK (gp_port_usb_msg_write (pl->gpdev,
412 0x07, (index + 1), 0x0000,
414 /* NOTE: must use (index + 1) here as the cam indexes images from 1,
415 * whereas libgphoto2 indexes from 0.... */
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+ */
422 /* Read the rest of the header... and discard it */
423 CHECK (gp_port_read (pl->gpdev, waste, 256));
425 /* Now we have to read in the thumbnail data anyway -
426 so we might as well store it for later */
430 if (pl->files[index].thumb){
431 free (pl->files[index].thumb); /* discard any previous thumbnail data */
432 pl->files[index].thumb = NULL;
434 buf = malloc (38 * 256); /* create a new buffer to hold the thumbnail data */
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));
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));
447 pl->files[index].thumb = NULL;
449 } /* end of thumbnail storing loop */
452 CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100,
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);
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 */
467 case 0: /* this will be 320 x 240 single-frame */
471 case 1: /* this will be 640 x 480 single-frame */
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? */
484 case 3: /* this will be 320 x 240 multi-frame */
488 case 4: /* this will be 640 x 480 multi-frame */
492 case 5: /* this will be 1024 x 768 multi-frame */
493 /* See notes above! */
499 case 6: /* ??? TAKE A GUESS!!! 160 x 120 avi ??? MUST verify this sometime.... */
503 case 7: /* this is 320 x 240 avi */
508 *t = 99; /* or something equally invalid... */
511 *sz = 0; /* if we don't know what it is, it can't have a size! */
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;
527 } /* end of spca500_flash_84D_get_file_info */
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 */
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;
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 */
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.
547 w = ((p2[0x0c] & 0xff) + (p2[0x0d] & 0xff) * 0x100) / 8;
548 h = ((p2[0x0e] & 0xff) + (p2[0x0f] & 0xff) * 0x100) / 8;
551 /* Allow for a long header; get the true length later.
554 alloc_size = w * h * 3 + hdrlen;
555 tmp = malloc (alloc_size);
557 return GP_ERROR_NO_MEMORY;
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.
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 ) {
572 rgb_p = tmp + hdrlen;
573 while (yuv_p < buf + file_size) {
574 uint32_t u, v, y, y2;
582 CHECK (yuv2rgb (y, u, v, &r, &g, &b));
587 CHECK (yuv2rgb (y2, u, v, &r, &g, &b));
599 } /* spca50x_process_thumbnail */
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 */
607 uint8_t qIndex = 0, format;
610 int w = pl->files[index].width;
611 int h = pl->files[index].height;
613 /* qindex == 2 seems to be right for all the dsc350 images - so far!!! */
614 qIndex = 2 ; /* FIXME - what to do about Qtable stuff? */
616 /* decode the image size */
618 format = 0x21; /* for 640 size images */
620 format = 0x22; /* for 320 x 240 size images */
623 file_size = buf_size + SPCA50X_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10;
625 /* now build a jpeg */
626 lp_jpg = malloc (file_size);
628 return GP_ERROR_NO_MEMORY;
630 create_jpeg_from_data (lp_jpg, buf, qIndex, w,
631 h, format, buf_size, &file_size,
634 lp_jpg = realloc (lp_jpg, file_size);
642 spca500_flash_84D_get_file (CameraPrivateLibrary * pl,
643 uint8_t ** data, unsigned int *len, int index, int thumbnail)
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! */
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) */
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 */
666 buf = pl->files[index].thumb;
667 pl->files[index].thumb = NULL; /* we will release buf, so this pointer must be "emptied" */
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,
676 /* trigger image upload */
678 CHECK (gp_port_usb_msg_write (pl->gpdev,
679 0x07, (index + 1), 0x0000, /* code 0 gets the thumbnail */
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 */
689 CHECK (spca50x_flash_wait_for_ready(pl));
691 /* read the header from the cam */
692 CHECK (gp_port_read (pl->gpdev, tbuf, 256)); /* always 256 for the DSC-350+ */
694 /* Read the rest of the header... and discard it */
695 CHECK (gp_port_read (pl->gpdev, tbuf, 256));
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. */
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 */
710 /* create a buffer to hold all the read in data */
711 buf = malloc (blks * 256);
713 return GP_ERROR_NO_MEMORY;
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));
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));
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) {
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));
743 } /* end of spca500_flash_84D_get_file */
747 spca50x_flash_get_file_dimensions (CameraPrivateLibrary *pl, int index, int *w, int *h)
751 if (pl->bridge == BRIDGE_SPCA500) { /* for dsc 350 cams */
753 return spca500_flash_84D_get_file_info (pl, index, w, h, &type, &size);
756 if (pl->fw_rev == 1) {
757 p = pl->flash_toc + index*2*32;
759 p = pl->flash_toc + index*32;
762 *w = (p[0x0c] & 0xff) + (p[0x0d] & 0xff) * 0x100;
763 *h = (p[0x0e] & 0xff) + (p[0x0f] & 0xff) * 0x100;
768 spca50x_flash_get_file_size (CameraPrivateLibrary *pl, int index, int *size)
772 if (pl->bridge == BRIDGE_SPCA500) { /* for dsc350 cams */
774 return spca500_flash_84D_get_file_info (pl, index, &w, &h, &type, size);
777 if (pl->fw_rev == 1) {
778 p = pl->flash_toc + index*2*32;
780 p = pl->flash_toc + index*32;
783 *size = (p[0x1c] & 0xff)
784 + (p[0x1d] & 0xff) * 0x100
785 + (p[0x1e] & 0xff) * 0x10000
786 + (p[0x1f] & 0xff) * 0x1000000;
792 spca50x_flash_get_file (CameraPrivateLibrary *lib, GPContext *context,
793 uint8_t ** data, unsigned int *len, int index, int thumbnail)
795 uint32_t file_size = 0, aligned_size = 0;
800 if (lib->bridge == BRIDGE_SPCA500) { /* for dsc 350 cams */
801 return spca500_flash_84D_get_file (lib, data, len, index, thumbnail);
804 if (lib->fw_rev != 1 && thumbnail)
805 return GP_ERROR_NOT_SUPPORTED;
808 p = lib->flash_toc + (index*2+1) * 32;
810 if (lib->fw_rev == 1) {
811 p = lib->flash_toc + index*2*32;
813 p = lib->flash_toc + index*32;
817 aligned_size = file_size =
819 + (p[0x1d] & 0xff) * 0x100
820 + (p[0x1e] & 0xff) * 0x10000;
822 /* Trigger upload of image data */
824 CHECK (gp_port_usb_msg_write (lib->gpdev,
825 0x0c, index+1, 0x0006, NULL, 0x00));
827 if (lib->fw_rev == 1) {
828 CHECK (gp_port_usb_msg_write (lib->gpdev,
829 0x0a, index+1, 0x000d, NULL, 0x00));
831 if(lib->bridge != BRIDGE_SPCA504B_PD) {
832 CHECK (gp_port_usb_msg_write (lib->gpdev,
833 0x54, index+1, 0x0002, NULL, 0x00));
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));
843 if ((lib->fw_rev == 1) || (lib->bridge == BRIDGE_SPCA504B_PD)) {
849 if (file_size % align_to != 0)
850 aligned_size = ((file_size / align_to) + 1) * align_to;
852 buf = malloc (aligned_size);
854 return GP_ERROR_NO_MEMORY;
856 ret = spca50x_flash_wait_for_ready(lib);
861 ret = gp_port_read (lib->gpdev, buf, aligned_size);
866 /* For images, we are done now, thumbnails need to be converted from
867 * yuv to rgb and a pbm header added. */
869 ret = spca50x_process_thumbnail (lib, data, len, buf, file_size, index);
885 spca50x_flash_close (CameraPrivateLibrary *pl, GPContext *context)
887 if (pl->fw_rev == 1) {
888 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x01, 0x2306,
890 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x00, 0x0d04,
893 /* Anything we need to do? */
897 if (!pl->dirty_flash && pl->bridge == BRIDGE_SPCA500) {
898 /* check if we need to free the file info buffers */
906 * Initialize the camera and write the jpeg registers. Read them back in to
907 * check whether the values are set correctly (wtf?)
910 spca50x_flash_init (CameraPrivateLibrary *pl, GPContext *context)
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 }
983 int len = sizeof (jpReg) / sizeof (jpReg[0]);
987 if (pl->fw_rev == 1) {
988 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0000, 0x2000,
990 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0013, 0x2301,
992 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0001, 0x2883,
995 for (i=0 ; i<len ; i++) {
996 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00,
997 jpReg[i].val, jpReg[i].reg,
999 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x00, 0x0000,
1000 jpReg[i].reg, bytes, 0x01));
1002 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0001, 0x2501,
1004 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0000, 0x2306,
1006 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x08, 0x0000, 0x0006,
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,
1016 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001,
1018 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001,
1022 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x000f,
1032 /* firmware detection */
1033 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x20, 0x0000, 0x0000,
1035 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x20, 0x0000, 0x0000,
1037 CHECK (gp_port_usb_msg_read (pl->gpdev, 0x21, 0x0000, 0x0000,
1041 * The cam is supposed to sync up with the computer time here
1042 * somehow, or at least that's what we think. */
1045 ftm = localtime(&t);
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. */
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);
1062 CHECK (gp_port_usb_msg_write (pl->gpdev, 0x29, 0x0000,
1067 pl->dirty_flash = 1;