int spca50x_flash_delete_all (CameraPrivateLibrary *pl, GPContext *context) { if (pl->bridge == BRIDGE_SPCA500) { /* dsc350 cams */ /* command mode */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0080, 0x0100, NULL, 0x00)); /* delete all command */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x07, 0xffff, 0x000a, NULL, 0x00)); /* wait until the camera is not busy any more */ CHECK (spca500_flash_84D_wait_while_busy(pl)); } else { if (pl->fw_rev == 1) { CHECK (gp_port_usb_msg_write (pl->gpdev, 0x1, 0x0, 0x1, NULL, 0x0)); } else { CHECK (gp_port_usb_msg_write (pl->gpdev, 0x52, 0x0, 0x0, NULL, 0x0)); } } /* invalidate TOC/info cache */ pl->dirty_flash = 1; return GP_OK; }
static int pdrm11_ping(GPPort *port) { CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_PING1, 1, NULL, 0) ); CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_PING2, 1, NULL, 0) ); return(GP_OK); }
int spca500_flash_delete_file (CameraPrivateLibrary *pl, int index) { if (pl->bridge == BRIDGE_SPCA500) { /* command mode */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0080, 0x0100, NULL, 0x00)); /* trigger image delete */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x07, (index + 1), 0x000a, NULL, 0x00)); /* reset to idle */ CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0)); /* invalidate TOC/info cache */ pl->dirty_flash = 1; return GP_OK; } else { /* not supported on the 504 style cams */ return GP_ERROR_NOT_SUPPORTED; } } /* spca500_flash_delete_file */
static int pdrm11_select_file(GPPort *port, uint16_t file) { char buf[10]; uint16_t picNum = htole16(file); uint16_t file_type; /* byte 4 of PDRM11_CMD_GET_INFO determines if the file is a jpeg or tiff */ CHECK(gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_INFO, file, buf, 8)); file_type = htole16(buf[4]); CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_SELECT_PIC1, file, (char*)&picNum, 2) ); CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_SELECT_PIC2, file, (char*)&file_type, 2) ); return(GP_OK); }
/* * delete file */ int sx330z_delete_file(Camera *camera, GPContext *context, const char *filename) { struct traveler_req req; /* struct traveler_ack ack;*/ uint8_t trxbuf[0x20]; int ret, id; req.always1 = 1; req.requesttype = SX330Z_REQUEST_DELETE; /* Delete */ req.offset = 0x0; req.size = 0x000; req.timestamp = 0x0; /* timestamp (doesn't matter)?*/ req.data = 0; sprintf(req.filename, "%.8s", filename); sprintf(&req.filename[8], "jpg"); /* discard . */ id = gp_context_progress_start(context, 2, "Deleting %s", filename); /* start context */ /* send delete request */ sx330z_fill_req(trxbuf,&req); ret = gp_port_usb_msg_write(camera->port, USB_REQ_RESERVED, SX330Z_REQUEST_DELETE, 0, (char *)trxbuf, 0x20); if (ret != 0x20) return(GP_ERROR); /* simple error handling */ gp_context_progress_update(context, id, 1); /* update context */ /* read 16 Byte acknowledge packet */ ret = gp_port_usb_msg_read(camera->port, USB_REQ_RESERVED, SX330Z_REQUEST_DELETE, 0, (char *)trxbuf, 0x10); if (ret != 0x10) return(GP_ERROR); gp_context_progress_stop(context, id); /* stop context */ return(GP_OK); } /* sx330z delete file */
int pdrm11_init(GPPort *port) { unsigned char buf[20]; int timeout = 50; gp_port_set_timeout(port,1000); /* exactly what windows driver does */ gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, (char *)buf, 4); gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_PING3, 0, NULL, 0); gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, (char *)buf, 4); gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_INIT1, 0, NULL, 0); gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, (char *)buf, 4); gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_INIT2, 0, NULL, 0); gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, (char *)buf, 4); gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_ZERO, 0, (char *)buf, 2); if(buf[0] || buf[1]) { /* I haven't seen anything other than 00 00 yet * unless the connection is bad */ GP_DEBUG("PDRM11_CMD_ZERO: %x %x", buf[0], buf[1]); return(GP_ERROR); } /* wait til the camera is ready */ do { usleep(200000); GP_DEBUG("waiting..."); timeout--; if( gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_READY, 0, (char *)buf, 4) == -ETIMEDOUT ) timeout = 0; } while( !((buf[3] == 0x25) && (buf[0] == 1)) && timeout ); /* what good is this? */ usleep(400000); if(!timeout) return(GP_ERROR_TIMEOUT); else return(GP_OK); }
/* * This function deletes all the images * supported (sdram, flash, card) * * Status: not verified */ static int enigma13_flash_delete_all(CameraFilesystem *fs, const char *folder, void *data, GPContext *context) { Camera *cam; gp_log(GP_LOG_DEBUG, "enigma13","Delete all files"); cam = data; CHECK (gp_port_usb_msg_write (cam->port, 0x52, 0x0, 0x0, NULL, 0x0) ); return GP_OK; }
/* * Deinit camera */ int spca50x_flash_close (CameraPrivateLibrary *pl, GPContext *context) { if (pl->fw_rev == 1) { CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x01, 0x2306, NULL, 0x00)); CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x00, 0x0d04, NULL, 0x00)); } else { /* Anything we need to do? */ } if (!pl->dirty_flash && pl->bridge == BRIDGE_SPCA500) { /* check if we need to free the file info buffers */ free_files(pl); } pl->dirty_flash = 1; return GP_OK; }
int spca500_flash_capture (CameraPrivateLibrary *pl) { if (pl->bridge == BRIDGE_SPCA500) { /* command mode */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0080, 0x0100, NULL, 0x00)); /* trigger image capture */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x03, 0x0000, 0x0004, NULL, 0x00)); /* wait until the camera is not busy any more */ CHECK (spca500_flash_84D_wait_while_busy(pl)); /* invalidate TOC/info cache */ pl->dirty_flash = 1; return GP_OK; } else if (pl->bridge == BRIDGE_SPCA504B_PD) { /* trigger image capture */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x51, 0x0000, 0x0000, NULL, 0)); /* wait until the camera is not busy any more */ /* spca50x_flash_wait_for_ready doesn't work here */ sleep(3); /* invalidate TOC/info cache */ pl->dirty_flash = 1; return GP_OK; } else { /* not supported on the 504 style cams, but procedure used by * SPCA504_PD will probably work */ return GP_ERROR_NOT_SUPPORTED; } }
/* * Get the table of contents (directory) from the cam * * Verified: Yes */ static int enigma13_get_toc(Camera *camera, int *filecount, char** toc) { char* flash_toc=NULL; int toc_size = 0; char buf[10]; uint16_t response = 0; int ret=1; CHECK(enigma13_wait_for_ready(camera)); CHECK (gp_port_usb_msg_read (camera->port, 0x54, 0x0000, 0x0000, (char*)&response, 0x02)); LE16TOH (response); *filecount = response; /* Calc toc size */ toc_size = (response) * 0x20; if (toc_size % 0x200 != 0) toc_size = ((toc_size / 0x200) + 1) * 0x200; CHECK(enigma13_wait_for_ready(camera)); CHECK (gp_port_usb_msg_write (camera->port, 0x54, response, 0x0001, NULL, 0x0000)); /* Wait until cam is ready to send the T.O.C */ usleep(ENIGMA13_WAIT_TOC_DELAY_MS * 1000); CHECK (gp_port_usb_msg_read (camera->port, 0x21, 0x0000, 0x0000, buf, 0x01)); if (buf[0]!=0x41) return GP_ERROR; CHECK (gp_port_usb_msg_read (camera->port, 0x21, 0x0000, 0x0002, buf, 0x01)); if (buf[0]!=0x01) return GP_ERROR; flash_toc = (char*)malloc(toc_size); if (!flash_toc) return GP_ERROR_NO_MEMORY; ret=gp_port_read (camera->port, flash_toc, toc_size); *toc= flash_toc; gp_log(GP_LOG_DEBUG, "enigma13","Byte transferred :%d ", ret); return ret; }
/* * Read block described by req */ static int sx330z_read_block(Camera *camera, GPContext *context, struct traveler_req *req, uint8_t *buf) { int ret; uint8_t trxbuf[0x20]; /* 1. send request */ sx330z_fill_req(trxbuf, req); ret = gp_port_usb_msg_write(camera->port, USB_REQ_RESERVED, req->requesttype, 0, (char *)trxbuf, 0x20); if (ret != 0x20) return(GP_ERROR_IO_WRITE); /* 2. read data */ ret = gp_port_read(camera->port, (char *)buf, req->size); if (ret != req->size)return(GP_ERROR_IO_READ); /* 3. read Ack */ ret = gp_port_read(camera->port, (char *)trxbuf, 0x10); if (ret != 0x10) return(GP_ERROR); /* FIXME : Security check ???*/ return(GP_OK); } /* read block */
int pdrm11_delete_file(GPPort *port, int picNum) { uint8_t buf[2]; /* for some reason the windows driver sends b200 twice * once in pdrm11_select_file and once before. dunno why */ CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_SELECT_PIC1, picNum, (char*)&picNum, 2) ); CHECK( pdrm11_select_file(port, picNum) ); /* should always be 00 00 */ gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_DELETE, picNum, (char *)buf, 2); if( (buf[0] != 0) || (buf[1] !=0) ) { GP_DEBUG("should have read 00 00. actually read %2x %2x.", buf[0], buf[1]); return(GP_ERROR); } return(GP_OK); }
/* * Function that downloads image * * Camera camera : camera structure * int index : image index ( in gphoto point of view) -1 for real index * char* toc : pointer to toc * char** img_buf : returned image data * int* img_size : returned image data size * */ static int enigma13_download_img(Camera *camera, char *toc, int index, char **img_data, int *img_size) { uint8_t *p; uint32_t file_size = 0, aligned_size = 0; char* buf=NULL; int align=0; char retbuf[2]; gp_log(GP_LOG_DEBUG, "enigma13","DOWNLOADING IMAGE NO %d",index); /* Offset for image informations . Each image has 16 bytes for name and 16 for size, and others*/ p = (uint8_t *)toc + (index*2)*32; /* real size from toc*/ aligned_size = file_size = (p[0x1c] & 0xff) + (p[0x1d] & 0xff) * 0x100 + (p[0x1e] & 0xff) * 0x10000; CHECK (gp_port_usb_msg_read (camera->port, 0x23, 0x0000, 0x64, retbuf, 0x01)); if (retbuf[0]==0x20){ align=ENIGMA13_BLK_CARD_ALIGN; gp_log(GP_LOG_DEBUG, "enigma13"," Image from card, alignement is set to %d bytes ",align); } else if (retbuf[0]==0x10){ align=ENIGMA13_BLK_FLASH_ALIGN; gp_log(GP_LOG_DEBUG, "enigma13"," Image from flash, alignement is set to %d bytes",align); } else { return GP_ERROR; } if (file_size % align != 0) aligned_size = ((file_size / align) + 1) * align; buf = (char*) malloc (aligned_size); if (!buf) return GP_ERROR_NO_MEMORY; CHECK_AND_FREE (gp_port_usb_msg_write (camera->port, 0x54, index+1, 2, NULL, 0x00), buf); usleep(ENIGMA13_WAIT_IMAGE_READY_MS * 1000); CHECK_AND_FREE (gp_port_usb_msg_read (camera->port, 0x21, 0x0000, 0x0000, buf, 0x01), buf); if (buf[0]!=0x41) { free (buf); return GP_ERROR; } CHECK_AND_FREE (gp_port_usb_msg_read (camera->port, 0x21, 0x0000, 0x0002, buf, 0x01), buf); if (buf[0]!=0x01) { free (buf); return GP_ERROR; } CHECK_AND_FREE (gp_port_usb_msg_read (camera->port, 0x21, 0x0000, 0x0002, buf, 0x01), buf); if (buf[0]!=0x01) { free (buf); return GP_ERROR; } gp_log(GP_LOG_DEBUG, "enigma13","READY FOR TRANSFER"); CHECK_AND_FREE (gp_port_read (camera->port, buf, aligned_size), buf); *img_data=buf; *img_size=file_size; return GP_OK; }
int spca50x_flash_get_TOC(CameraPrivateLibrary *pl, int *filecount) { uint16_t n_toc_entries; int toc_size = 0; if (pl->dirty_flash == 0){ /* TOC has been read already, and stored in the pl, so let's not read it again unless "dirty" gets set, e.g. by a reset, delete or capture action... */ *filecount = pl->num_files_on_flash; return GP_OK; } pl->num_files_on_flash = 0; if (pl->bridge == BRIDGE_SPCA500) { /* for dsc350 type cams */ /* command mode */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0080, 0x0100, NULL, 0x00)); /* trigger TOC upload */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x05, 0x0000, 0x000d, NULL, 0x00)); toc_size = 0x100; /* always 256 for the dsc-350 cams */ } else { if (pl->fw_rev == 1) { CHECK (gp_port_usb_msg_read (pl->gpdev, 0x0b, 0x0000, 0x0000, (char*)&n_toc_entries, 0x02)); /* Each file gets two toc entries, one for the image, one for the thumbnail */ LE16TOH (n_toc_entries); *filecount = n_toc_entries/2; } else { CHECK (gp_port_usb_msg_read (pl->gpdev, 0x54, 0x0000, 0x0000, (char*)&n_toc_entries, 0x02)); LE16TOH (n_toc_entries); *filecount = n_toc_entries; } /* If empty, return now */ if (n_toc_entries == 0) return GP_OK; /* Request the TOC */ if (pl->fw_rev == 1) { CHECK (gp_port_usb_msg_read (pl->gpdev, 0x0a, n_toc_entries, 0x000c, NULL, 0x00)); } else { CHECK (gp_port_usb_msg_read (pl->gpdev, 0x54, n_toc_entries, 0x0001, NULL, 0x00)); } /* slurp it in. Supposedly there's 32 bytes in each entry. */ toc_size = n_toc_entries * 32; /* align */ if (toc_size % 512 != 0) toc_size = ((toc_size / 512) + 1) * 512; } if (pl->flash_toc) free (pl->flash_toc); pl->flash_toc = malloc(toc_size); if (!pl->flash_toc) return GP_ERROR_NO_MEMORY; CHECK (spca50x_flash_wait_for_ready(pl)); if (pl->bridge == BRIDGE_SPCA500) { /* For dsc350 type cams */ /* read the TOC from the cam */ CHECK (gp_port_read (pl->gpdev, (char *)pl->flash_toc, toc_size)); /* reset to idle */ CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0)); *filecount = (int)pl->flash_toc[10]; /* Now, create the files info buffer */ free_files(pl); /* NOTE: using calloc to ensure new block is "empty" */ pl->files = calloc (1, *filecount * sizeof (struct SPCA50xFile)); if (!pl->files) return GP_ERROR_NO_MEMORY; } else { /* all other cams with flash... */ /* read the TOC from the cam */ CHECK (gp_port_read (pl->gpdev, (char *)pl->flash_toc, toc_size)); } /* record that TOC has been updated - clear the "dirty" flag */ pl->num_files_on_flash = *filecount; pl->dirty_flash = 0; return GP_OK; }
int pdrm11_get_file(CameraFilesystem *fs, const char *filename, CameraFileType type, CameraFile *file, GPPort *port, uint16_t picNum) { uint32_t size = 0; uint16_t thumbsize = 0; uint8_t buf[30]; uint8_t *image; uint8_t temp; int i; int ret; int file_type; gp_port_set_timeout(port,10000); CHECK( pdrm11_select_file(port, picNum) ); if(type == GP_FILE_TYPE_PREVIEW) { CHECK(gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_INFO, picNum, (char *)buf, 8)); file_type = buf[4]; CHECK( gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_THUMBSIZE, picNum, (char *)buf, 14) ); thumbsize = le16atoh( &buf[8] ); /* add 1 to file size only for jpeg thumbnails */ if(file_type == 1) { GP_DEBUG("thumbnail file_type: %s.", "jpeg"); size = (uint32_t)thumbsize + 1; } else if(file_type == 2) { /* NOTE: tiff thumbnails are 160x120 pixel 8bpc rgb images, NOT jpegs... */ GP_DEBUG("thumbnail file_type: %s.", "tiff"); size = (uint32_t)thumbsize; } else { GP_DEBUG("Unknown thumbnail file format!"); return(GP_ERROR_NOT_SUPPORTED); } } else if(type == GP_FILE_TYPE_NORMAL) { CHECK( gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_FILESIZE, picNum, (char *)buf, 26) ); size = le32atoh( &buf[18] ); } else { GP_DEBUG("Unsupported file type!"); return(GP_ERROR_NOT_SUPPORTED); } GP_DEBUG("size: %d 0x%x", size, size); image = malloc(sizeof(char)*size); if(!image) return(GP_ERROR_NO_MEMORY); if(type == GP_FILE_TYPE_PREVIEW) { CHECK_AND_FREE( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_GET_THUMB, picNum, NULL, 0), image ); } else { CHECK_AND_FREE( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_GET_PIC, picNum, NULL, 0), image ); } ret = gp_port_read(port, (char *)image, size); if(ret != size) { GP_DEBUG("failed to read from port. Giving it one more try..."); ret = gp_port_read(port, (char *)image, size); if(ret != size) { GP_DEBUG("gp_port_read returned %d 0x%x. size: %d 0x%x", ret, ret, size, size); free (image); return(GP_ERROR_IO_READ); } } /* swap the bytes for the thumbnail, but not the file */ if(type == GP_FILE_TYPE_PREVIEW) { for(i=0; i<size; i+=2) { temp = image[i]; image[i] = image[i+1]; image[i+1] = temp; } } gp_file_set_mime_type(file, GP_MIME_JPEG); gp_file_set_data_and_size(file, (char *)image, size); return(GP_OK); }
static int spca500_flash_84D_get_file_info (CameraPrivateLibrary * pl, int index, int *w, int *h, int *t, int *sz) { char hdr[260]; char waste[260]; int i; unsigned long size; /* First, check if the info. is already buffered in the cam private lib * We DO NOT want to be fetching the entire thumbnail just to get the file size...*/ if ((pl->dirty_flash == 0) && (pl->files[index].type != 0)){ /* This file must have been checked before */ *w = pl->files[index].width ; *h = pl->files[index].height ; *t = pl->files[index].type ; *sz = pl->files[index].size ; return GP_OK; } else if (pl->dirty_flash != 0){ /* should never happen, but just in case... */ CHECK(spca50x_flash_get_TOC (pl, &i)); if ( index >= i){ /* asking for a picture that doesn't exist */ return GP_ERROR; } } /* ...else we must query the cam the hard way... */ /* command mode */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0080, 0x0100, NULL, 0x00)); /* trigger Thumbnail upload */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x07, (index + 1), 0x0000, NULL, 0x00)); /* NOTE: must use (index + 1) here as the cam indexes images from 1, * whereas libgphoto2 indexes from 0.... */ /* wait for ready */ CHECK (spca50x_flash_wait_for_ready(pl)); /* read the header from the cam */ CHECK (gp_port_read (pl->gpdev, hdr, 256)); /* always 256 for the DSC-350+ */ /* Read the rest of the header... and discard it */ CHECK (gp_port_read (pl->gpdev, waste, 256)); /* Now we have to read in the thumbnail data anyway - so we might as well store it for later */ { int j; uint8_t * buf; if (pl->files[index].thumb){ free (pl->files[index].thumb); /* discard any previous thumbnail data */ pl->files[index].thumb = NULL; } buf = malloc (38 * 256); /* create a new buffer to hold the thumbnail data */ if (buf){ j = 0; for (i = 0; i < 38; i++) { /* Now read in the image data */ /* read a buffer from the cam */ CHECK (gp_port_read (pl->gpdev, (char *)&buf[j], 256)); j += 256; } pl->files[index].thumb = buf; } else { /* couldn't get a buffer - read in the data anyway and discard it */ for (i = 0; i < 38; i++) {/* Thumbnails ALWAYS download 38 blocks...*/ CHECK (gp_port_read (pl->gpdev, waste, 256)); } pl->files[index].thumb = NULL; } } /* end of thumbnail storing loop */ /* reset to idle */ CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0)); /* OK, now we have a hdr we can work with... */ /* try and get the size */ size = ((unsigned long)hdr[15] & 0xff) + (((unsigned long)hdr[16] & 0xff) << 8) + (((unsigned long)hdr[17] & 0xff) << 16); *sz = size; /* Try and determine the file type */ /* Should enumerate the possible types properly, somewhere... */ i = (int)hdr[2]; /* should be the file type */ *t = i; switch (i){ case 0: /* this will be 320 x 240 single-frame */ *w = 320; *h = 240; break; case 1: /* this will be 640 x 480 single-frame */ *w = 640; *h = 480; break; case 2: /* this will be 1024 x 768 single-frame */ /* These are actually 640x480 pics - the win driver just expands them * in the host before it stores them... What should we do here? Continue with that * pretence, or tell the user the truth? */ /* *w = 1024; */ /* *h = 768; */ *w = 640; *h = 480; break; case 3: /* this will be 320 x 240 multi-frame */ *w = 320; *h = 240; break; case 4: /* this will be 640 x 480 multi-frame */ *w = 640; *h = 480; break; case 5: /* this will be 1024 x 768 multi-frame */ /* See notes above! */ /* *w = 1024; */ /* *h = 768; */ *w = 640; *h = 480; break; case 6: /* ??? TAKE A GUESS!!! 160 x 120 avi ??? MUST verify this sometime.... */ *w = 160; *h = 120; break; case 7: /* this is 320 x 240 avi */ *w = 320; *h = 240; break; default: *t = 99; /* or something equally invalid... */ *w = 0; *h = 0; *sz = 0; /* if we don't know what it is, it can't have a size! */ break; } /* now add this new set of data to the info_cache */ if (pl->dirty_flash == 0){ /* Only update the files cache if it exists, i.e. if dirty is zero */ /* We should never get here if dirty is set, however ! */ pl->files[index].type = *t; pl->files[index].width = *w; pl->files[index].height = *h; pl->files[index].size = *sz; } return GP_OK; } /* end of spca500_flash_84D_get_file_info */
static int spca500_flash_84D_get_file (CameraPrivateLibrary * pl, uint8_t ** data, unsigned int *len, int index, int thumbnail) { char tbuf[260]; /* for the file data blocks */ int i, j; /* general loop vars */ int blks; /* number of 256 byte blocks to fetch */ int sz; /* number of bytes in image */ uint8_t *buf; /* buffer for the read data */ int type; /* type of image reported by header */ int w, h; /* width, height of file being read */ int true_len; /* length determined by actually counting the loaded data! */ /* Check the info. first, so we KNOW the file type before we start to download it...! */ /* NOTE: The check should be really easy, as the info ought to be in the files info cache */ spca500_flash_84D_get_file_info (pl, index, &w, &h, &type, &sz); if (type >= 3) { /* for now, only support single frame still images */ return GP_ERROR_NOT_SUPPORTED; /* what to do for multi-frame images? (type 3, 4, 5) or avi's? (6, 7) */ } /* OK, we've decided what type of file it is, now lets upload it... */ if ((thumbnail != 0) && (pl->files[index].thumb != NULL)){ /* We can cheat here - we already have the thumbnail data in a cache, so don't load it again */ blks = 38; buf = pl->files[index].thumb; pl->files[index].thumb = NULL; /* we will release buf, so this pointer must be "emptied" */ } else { /* We need to download this data from the cam... */ /* set command mode */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0080, 0x0100, NULL, 0x00)); /* trigger image upload */ if (thumbnail){ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x07, (index + 1), 0x0000, /* code 0 gets the thumbnail */ NULL, 0x00)); } else { /* code for different image types...? */ CHECK (gp_port_usb_msg_write (pl->gpdev, 0x07, (index + 1), 0x0001, /* code 1 gets the main image */ NULL, 0x00)); } /* wait for ready */ CHECK (spca50x_flash_wait_for_ready(pl)); /* read the header from the cam */ CHECK (gp_port_read (pl->gpdev, tbuf, 256)); /* always 256 for the DSC-350+ */ /* Read the rest of the header... and discard it */ CHECK (gp_port_read (pl->gpdev, tbuf, 256)); if (thumbnail){ blks = 38 ; /* always 38 blocks in a thumbnail with this setup */ sz = 0; /* unknown, it's NOT recorded in the header or TOC as such... */ /* Note the width/height of the thumbnail is fixed at 80 x 60 I believe. */ } else { /* full image... */ /* find nearest EVEN number of blocks bigger than the size */ blks = (sz / 256) + 1; if ((blks & 1) != 0){ /* block count is odd, not allowed */ blks += 1; } } /* create a buffer to hold all the read in data */ buf = malloc (blks * 256); if (!buf) return GP_ERROR_NO_MEMORY; j = 0; /* k = 0; */ /* Now read in the image data */ for (i = 0; i < blks; i++) { /* read a buffer from the cam */ CHECK (gp_port_read (pl->gpdev, (char *)&buf[j], 256)); j += 256; } /* OK, that's all the data read in, set cam to idle */ CHECK (gp_port_usb_msg_write(pl->gpdev, 0x00, 0x0000, 0x0100, NULL, 0x0)); } /* Count how many bytes file really is! We use this to discard the padding zeros */ sz = (blks * 256) - 1; /* look for the last non-zero byte in the file... * I hope the file never *really* ends with a zero!*/ while (buf[sz] == 0) { sz -= 1; } true_len = sz + 1; if (thumbnail) { /* post processing of thumbnail data */ CHECK(spca50x_process_thumbnail (pl, data, len, buf, true_len, index)); } else { /* post processing of single frame images */ CHECK(spca50x_flash_process_image (pl, data, len, buf, true_len, index)); } return GP_OK; } /* end of spca500_flash_84D_get_file */
/* * Initialize the camera and write the jpeg registers. Read them back in to * check whether the values are set correctly (wtf?) */ int spca50x_flash_init (CameraPrivateLibrary *pl, GPContext *context) { struct JPREG { int reg; int val; }; struct JPREG jpReg[] = { { 0x2800, 0x0005 }, { 0x2840, 0x0005 }, { 0x2801, 0x0003 }, { 0x2841, 0x0005 }, { 0x2802, 0x0003 }, { 0x2842, 0x0007 }, { 0x2803, 0x0005 }, { 0x2843, 0x000e }, { 0x2804, 0x0007 }, { 0x2844, 0x001e }, { 0x2805, 0x000c }, { 0x2845, 0x001e }, { 0x2806, 0x000f }, { 0x2846, 0x001e }, { 0x2807, 0x0012 }, { 0x2847, 0x001e }, { 0x2808, 0x0004 }, { 0x2848, 0x0005 }, { 0x2809, 0x0004 }, { 0x2849, 0x0006 }, { 0x280a, 0x0004 }, { 0x284a, 0x0008 }, { 0x280b, 0x0006 }, { 0x284b, 0x0014 }, { 0x280c, 0x0008 }, { 0x284c, 0x001e }, { 0x280d, 0x0011 }, { 0x284d, 0x001e }, { 0x280e, 0x0012 }, { 0x284e, 0x001e }, { 0x280f, 0x0011 }, { 0x284f, 0x001e }, { 0x2810, 0x0004 }, { 0x2850, 0x0007 }, { 0x2811, 0x0004 }, { 0x2851, 0x0008 }, { 0x2812, 0x0005 }, { 0x2852, 0x0011 }, { 0x2813, 0x0007 }, { 0x2853, 0x001e }, { 0x2814, 0x000c }, { 0x2854, 0x001e }, { 0x2815, 0x0011 }, { 0x2855, 0x001e }, { 0x2816, 0x0015 }, { 0x2856, 0x001e }, { 0x2817, 0x0011 }, { 0x2857, 0x001e }, { 0x2818, 0x0004 }, { 0x2858, 0x000e }, { 0x2819, 0x0005 }, { 0x2859, 0x0014 }, { 0x281a, 0x0007 }, { 0x285a, 0x001e }, { 0x281b, 0x0009 }, { 0x285b, 0x001e }, { 0x281c, 0x000f }, { 0x285c, 0x001e }, { 0x281d, 0x001a }, { 0x285d, 0x001e }, { 0x281e, 0x0018 }, { 0x285e, 0x001e }, { 0x281f, 0x0013 }, { 0x285f, 0x001e }, { 0x2820, 0x0005 }, { 0x2860, 0x001e }, { 0x2821, 0x0007 }, { 0x2861, 0x001e }, { 0x2822, 0x000b }, { 0x2862, 0x001e }, { 0x2823, 0x0011 }, { 0x2863, 0x001e }, { 0x2824, 0x0014 }, { 0x2864, 0x001e }, { 0x2825, 0x0021 }, { 0x2865, 0x001e }, { 0x2826, 0x001f }, { 0x2866, 0x001e }, { 0x2827, 0x0017 }, { 0x2867, 0x001e }, { 0x2828, 0x0007 }, { 0x2868, 0x001e }, { 0x2829, 0x000b }, { 0x2869, 0x001e }, { 0x282a, 0x0011 }, { 0x286a, 0x001e }, { 0x282b, 0x0013 }, { 0x286b, 0x001e }, { 0x282c, 0x0018 }, { 0x286c, 0x001e }, { 0x282d, 0x001f }, { 0x286d, 0x001e }, { 0x282e, 0x0022 }, { 0x286e, 0x001e }, { 0x282f, 0x001c }, { 0x286f, 0x001e }, { 0x2830, 0x000f }, { 0x2870, 0x001e }, { 0x2831, 0x0013 }, { 0x2871, 0x001e }, { 0x2832, 0x0017 }, { 0x2872, 0x001e }, { 0x2833, 0x001a }, { 0x2873, 0x001e }, { 0x2834, 0x001f }, { 0x2874, 0x001e }, { 0x2835, 0x0024 }, { 0x2875, 0x001e }, { 0x2836, 0x0024 }, { 0x2876, 0x001e }, { 0x2837, 0x001e }, { 0x2877, 0x001e }, { 0x2838, 0x0016 }, { 0x2878, 0x001e }, { 0x2839, 0x001c }, { 0x2879, 0x001e }, { 0x283a, 0x001d }, { 0x287a, 0x001e }, { 0x283b, 0x001d }, { 0x287b, 0x001e }, { 0x283c, 0x0022 }, { 0x287c, 0x001e }, { 0x283d, 0x001e }, { 0x287d, 0x001e }, { 0x283e, 0x001f }, { 0x287e, 0x001e }, { 0x283f, 0x001e }, { 0x287f, 0x001e } }; int len = sizeof (jpReg) / sizeof (jpReg[0]); uint8_t bytes[7]; int i; if (pl->fw_rev == 1) { CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0000, 0x2000, NULL, 0x00)); CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0013, 0x2301, NULL, 0x00)); CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0001, 0x2883, NULL, 0x00)); for (i=0 ; i<len ; i++) { CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, jpReg[i].val, jpReg[i].reg, NULL, 0x00)); CHECK (gp_port_usb_msg_read (pl->gpdev, 0x00, 0x0000, jpReg[i].reg, (char *)bytes, 0x01)); } CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0001, 0x2501, NULL, 0x00)); CHECK (gp_port_usb_msg_write (pl->gpdev, 0x00, 0x0000, 0x2306, NULL, 0x00)); CHECK (gp_port_usb_msg_write (pl->gpdev, 0x08, 0x0000, 0x0006, NULL, 0x00)); /* Read the same thing thrice, for whatever reason. * From working on getting iso traffic working with this chip, I've found * out, that 0x01, 0x0000, 0x0001 polls the chip for completion of a * command. Unfortunately it is of yet unclear, what the exact procedure * is. Until we know, let's keep this here. */ CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001, (char *)bytes, 0x01)); CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001, (char *)bytes, 0x01)); CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x0001, (char *)bytes, 0x01)); /* Set to idle? */ CHECK (gp_port_usb_msg_read (pl->gpdev, 0x01, 0x0000, 0x000f, NULL, 0x00)); } else { time_t t; struct tm *ftm; /* firmware detection */ CHECK (gp_port_usb_msg_read (pl->gpdev, 0x20, 0x0000, 0x0000, (char *)bytes, 0x01)); CHECK (gp_port_usb_msg_read (pl->gpdev, 0x20, 0x0000, 0x0000, (char *)bytes, 0x05)); CHECK (gp_port_usb_msg_read (pl->gpdev, 0x21, 0x0000, 0x0000, (char *)bytes, 0x01)); /* * The cam is supposed to sync up with the computer time here * somehow, or at least that's what we think. */ time(&t); ftm = localtime(&t); bytes[0] = ftm->tm_sec; bytes[1] = ftm->tm_min; bytes[2] = ftm->tm_hour; bytes[3] = 0; /* what is that? either 0x0 or 0x6 */ bytes[4] = ftm->tm_mday; bytes[5] = ftm->tm_mon+1; bytes[6] = ftm->tm_year-100; /* stupido. Year is 1900 + tm_year. We need two digits only. */ GP_DEBUG("Timestamp: %4d-%02d-%02d %2d:%02d:%02d", ftm->tm_year+1900,ftm->tm_mon+1,ftm->tm_mday, ftm->tm_hour,ftm->tm_min,ftm->tm_sec); for (i=0;i<7;i++) CHECK (gp_port_usb_msg_write (pl->gpdev, 0x29, 0x0000, i, (char *)bytes+i, 0x01)); } pl->dirty_flash = 1; return GP_OK; }
int spca50x_flash_get_file (CameraPrivateLibrary *lib, GPContext *context, uint8_t ** data, unsigned int *len, int index, int thumbnail) { uint32_t file_size = 0, aligned_size = 0; uint8_t *p, *buf; int file_number; int align_to, ret; if (lib->bridge == BRIDGE_SPCA500) { /* for dsc 350 cams */ return spca500_flash_84D_get_file (lib, data, len, index, thumbnail); } if (lib->fw_rev != 1 && thumbnail) return GP_ERROR_NOT_SUPPORTED; if (thumbnail) { p = lib->flash_toc + (index*2+1) * 32; } else { if (lib->fw_rev == 1) { p = lib->flash_toc + index*2*32; } else { p = lib->flash_toc + index*32; } } aligned_size = file_size = (p[0x1c] & 0xff) + (p[0x1d] & 0xff) * 0x100 + (p[0x1e] & 0xff) * 0x10000; /* Trigger upload of image data */ if (thumbnail) { CHECK (gp_port_usb_msg_write (lib->gpdev, 0x0c, index+1, 0x0006, NULL, 0x00)); } else { if (lib->fw_rev == 1) { CHECK (gp_port_usb_msg_write (lib->gpdev, 0x0a, index+1, 0x000d, NULL, 0x00)); } else { if(lib->bridge != BRIDGE_SPCA504B_PD) { CHECK (gp_port_usb_msg_write (lib->gpdev, 0x54, index+1, 0x0002, NULL, 0x00)); } else { CHECK (spca50x_flash_get_number_from_file_name( lib, index, &file_number)); CHECK (gp_port_usb_msg_write (lib->gpdev, 0x54, file_number, 0x0002, NULL, 0x00)); } } } if ((lib->fw_rev == 1) || (lib->bridge == BRIDGE_SPCA504B_PD)) { align_to = 0x4000; } else { align_to = 0x2000; } /* align */ if (file_size % align_to != 0) aligned_size = ((file_size / align_to) + 1) * align_to; buf = malloc (aligned_size); if (!buf) return GP_ERROR_NO_MEMORY; ret = spca50x_flash_wait_for_ready(lib); if (ret < GP_OK) { free (buf); return ret; } ret = gp_port_read (lib->gpdev, (char *)buf, aligned_size); if (ret < GP_OK) { free (buf); return ret; } /* For images, we are done now, thumbnails need to be converted from * yuv to rgb and a pbm header added. */ if (thumbnail) { ret = spca50x_process_thumbnail (lib, data, len, buf, file_size, index); if (ret < GP_OK) { free (buf); return ret; } } else { *data = buf; *len = file_size; } return GP_OK; }