This is basically a continuation of the work from #1002 but her for the camlibs directory. The purpose was to replace spaces as a means for indentation with tab characters. Note: there are some files which are still offending the general rule but are (mostly) consistent within themselves. I let them be for the moment. Fixing them would basically replace the whole file. Also: there are still a ton of whitespace related inconsistencies like "x=10" vs "x = 10" or "func(10)" vs "func (10)". This is a whitespace only change (if you include newlines as whitespace).
284 lines
7.5 KiB
C
284 lines
7.5 KiB
C
/* clicksmart.c
|
|
*
|
|
* part of libgphoto2/camlibs/clicksmart310
|
|
*
|
|
* Copyright (C) 2006 Theodore Kilgore <kilgota@auburn.edu>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include <gphoto2/gphoto2.h>
|
|
#include <gphoto2/gphoto2-port.h>
|
|
|
|
#include "clicksmart.h"
|
|
#include "spca50x-jpeg-header.h"
|
|
|
|
#define GP_MODULE "clicksmart310"
|
|
|
|
#define CS_INIT 0x8000
|
|
#define CS_INIT2 0xd41
|
|
#define CS_NUM_PICS 0xd40
|
|
#define CS_CH_READY 0xd00
|
|
#define CS_CH_CLEAR 0xd05
|
|
#define CS_READCLOSE 0x8303
|
|
|
|
static int
|
|
CLICKSMART_READ (GPPort *port, int index, char *data)
|
|
{
|
|
gp_port_usb_msg_interface_read(port, 0, 0, index, data, 1);
|
|
return GP_OK;
|
|
}
|
|
|
|
static int
|
|
CLICKSMART_READ_STATUS (GPPort *port, char *data)
|
|
{
|
|
return gp_port_usb_msg_interface_read(port, 0, 0, CS_CH_READY, data, 1);
|
|
}
|
|
|
|
int clicksmart_init (GPPort *port, CameraPrivateLibrary *priv)
|
|
{
|
|
int i, cat_size;
|
|
int full_reads;
|
|
int short_read;
|
|
unsigned char *temp_catalog;
|
|
unsigned char *buffer;
|
|
char c = 0;
|
|
|
|
GP_DEBUG("Running clicksmart_init\n");
|
|
|
|
CLICKSMART_READ(port, CS_INIT, &c);
|
|
/* We are supposed to get a response of 0x44 ???*/
|
|
CLICKSMART_READ(port, CS_INIT2, &c);
|
|
CLICKSMART_READ(port, CS_NUM_PICS, &c);
|
|
|
|
priv->num_pics = (unsigned)c;
|
|
full_reads = (unsigned)c/2;
|
|
short_read = (unsigned)c%2;
|
|
cat_size = (unsigned)c*0x10;
|
|
temp_catalog = malloc(cat_size);
|
|
if (!temp_catalog)
|
|
return GP_ERROR_NO_MEMORY;
|
|
memset (temp_catalog, 0, cat_size);
|
|
|
|
/* now we need to get and put away the catalog data. */
|
|
|
|
CLICKSMART_READ_STATUS (port, &c);
|
|
gp_port_usb_msg_interface_write(port, 6, 0, 9, NULL, 0);
|
|
while (c != 1) {
|
|
int r;
|
|
if ((r = CLICKSMART_READ_STATUS (port, &c)) < GP_OK)
|
|
return r;
|
|
}
|
|
buffer = malloc(0x200);
|
|
if (!buffer) {
|
|
free (temp_catalog);
|
|
return GP_ERROR_NO_MEMORY;
|
|
}
|
|
/*
|
|
* The catalog data is downloaded in reverse order, which needs to be
|
|
* straightened out.
|
|
*/
|
|
for (i=0; i < full_reads; i++) {
|
|
memset (buffer, 0, 0x200);
|
|
gp_port_read(port, (char *)buffer, 0x200);
|
|
memcpy (temp_catalog + cat_size - (2*i+1)*0x10, buffer, 0x10);
|
|
memcpy (temp_catalog + cat_size - (2*i+2)*0x10, buffer+0x100,
|
|
0x10);
|
|
}
|
|
if (short_read) {
|
|
memset (buffer, 0, 0x200);
|
|
gp_port_read(port, (char *)buffer, 0x100);
|
|
memcpy (temp_catalog, buffer, 0x10);
|
|
}
|
|
priv->catalog = temp_catalog;
|
|
|
|
clicksmart_reset(port);
|
|
free (buffer);
|
|
GP_DEBUG("Leaving clicksmart_init\n");
|
|
|
|
return GP_OK;
|
|
}
|
|
|
|
|
|
int clicksmart_get_res_setting (CameraPrivateLibrary *priv, int n)
|
|
{
|
|
GP_DEBUG("running clicksmart_get_res_setting for picture %i\n", n+1);
|
|
/*
|
|
* QCIF (176x144) returns 1, or if the entry is a clip frame, then 3
|
|
* and CIF (352x288) returns 0.
|
|
*/
|
|
return priv->catalog[16*n];
|
|
}
|
|
|
|
int
|
|
clicksmart_read_pic_data (CameraPrivateLibrary *priv, GPPort *port,
|
|
unsigned char **data, int n)
|
|
{
|
|
unsigned int offset=0;
|
|
char c;
|
|
unsigned int size = 0;
|
|
unsigned int remainder = 0;
|
|
|
|
GP_DEBUG("running clicksmart_read_picture_data for picture %i\n", n+1);
|
|
|
|
CLICKSMART_READ_STATUS (port, &c);
|
|
|
|
GP_DEBUG("ClickSmart Read Status at beginning %d\n", c);
|
|
|
|
gp_port_usb_msg_interface_write(port, 6, 0x1fff - n, 1, NULL, 0);
|
|
c = 0;
|
|
while (c != 1) {
|
|
int r;
|
|
if ((r = CLICKSMART_READ_STATUS (port, &c)) < GP_OK)
|
|
return r;
|
|
}
|
|
/* Get the size of the data and calculate the size to download, which
|
|
* is the next multiple of 0x100. Only for the hi-res photos is the
|
|
* true data size actually given.
|
|
*/
|
|
|
|
size=(priv->catalog[16*n + 12] * 0x100)+(priv->catalog[16*n + 11]);
|
|
if (size == 0) /* for lo-res photos the above calculation gives 0 */
|
|
size = (priv->catalog[16*n + 5] * 0x100);
|
|
if (size == 0) /* this means data corruption */
|
|
return GP_ERROR;
|
|
|
|
remainder = size%0x200;
|
|
|
|
GP_DEBUG("size: %x, remainder: %x\n", size, remainder);
|
|
*data = calloc(size + 0x100,1);
|
|
if (!*data) return GP_ERROR;
|
|
/* Download the data */
|
|
while (offset < size-remainder) {
|
|
GP_DEBUG("offset: %x\n", offset);
|
|
if (gp_port_read(port, (char *)*data + offset, 0x200) < GP_OK)
|
|
break;
|
|
offset = offset + 0x200;
|
|
}
|
|
|
|
remainder=((remainder+0xff)/0x100)*0x100;
|
|
GP_DEBUG("Second remainder: %x\n", remainder);
|
|
if (remainder)
|
|
gp_port_read(port, (char *)*data + offset, remainder);
|
|
|
|
gp_port_usb_msg_interface_read(port, 0, 0, CS_READCLOSE, &c, 1);
|
|
gp_port_usb_msg_interface_write(port, 0, 2, CS_CH_READY, NULL, 0);
|
|
|
|
/*
|
|
* For lo-res photos the camera does not tell us the true size, but
|
|
* when the data has ended the excess bytes downloaded are all
|
|
* 00. The photo processing works better if these are suppressed.
|
|
*/
|
|
|
|
if (priv->catalog[16*n]) {
|
|
while ((size > 1) && (*data)[size-1] == 0)
|
|
size--;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
int
|
|
clicksmart_delete_all_pics (GPPort *port)
|
|
{
|
|
gp_port_usb_msg_interface_write(port, 0, 2, CS_CH_READY, NULL, 0);
|
|
gp_port_usb_msg_interface_write(port, 2, 0, 5, NULL, 0);
|
|
return GP_OK;
|
|
}
|
|
|
|
int
|
|
clicksmart_reset (GPPort *port)
|
|
{
|
|
char c;
|
|
/* Release current register */
|
|
CLICKSMART_READ (port, CS_READCLOSE, &c);
|
|
gp_port_usb_msg_interface_write(port, 0, 2, CS_CH_READY, NULL, 0);
|
|
CLICKSMART_READ (port, CS_CH_CLEAR, &c);
|
|
CLICKSMART_READ (port, CS_CH_CLEAR, &c);
|
|
return GP_OK;
|
|
}
|
|
|
|
/* create_jpeg_from_data adapted from camlibs/spca50x */
|
|
|
|
int create_jpeg_from_data (unsigned char * dst, unsigned char * src,
|
|
int qIndex, int w, int h, unsigned char format,
|
|
int o_size, int *size,
|
|
int omit_huffman_table, int omit_escape)
|
|
{
|
|
int i = 0;
|
|
unsigned char *start;
|
|
unsigned char value;
|
|
start = dst;
|
|
|
|
/* copy the header from the template */
|
|
memcpy (dst, SPCA50xJPGDefaultHeaderPart1,
|
|
SPCA50X_JPG_DEFAULT_HEADER_PART1_LENGTH);
|
|
|
|
/* modify quantization table */
|
|
memcpy (dst + 7, SPCA50xQTable[qIndex * 2], 64);
|
|
memcpy (dst + 72, SPCA50xQTable[qIndex * 2 + 1], 64);
|
|
dst += SPCA50X_JPG_DEFAULT_HEADER_PART1_LENGTH;
|
|
|
|
/* copy Huffman table */
|
|
if (!omit_huffman_table) {
|
|
memcpy (dst, SPCA50xJPGDefaultHeaderPart2,
|
|
SPCA50X_JPG_DEFAULT_HEADER_PART2_LENGTH);
|
|
dst += SPCA50X_JPG_DEFAULT_HEADER_PART2_LENGTH;
|
|
}
|
|
memcpy (dst, SPCA50xJPGDefaultHeaderPart3,
|
|
SPCA50X_JPG_DEFAULT_HEADER_PART3_LENGTH);
|
|
|
|
/* modify the image width, height */
|
|
*(dst + 8) = w & 0xFF; /* Image width low byte */
|
|
*(dst + 7) = w >> 8 & 0xFF; /* Image width high byte */
|
|
*(dst + 6) = h & 0xFF; /* Image height low byte */
|
|
*(dst + 5) = h >> 8 & 0xFF; /* Image height high byte */
|
|
|
|
/* set the format */
|
|
*(dst + 11) = format;
|
|
|
|
/* point to real JPG compress data start position and copy */
|
|
dst += SPCA50X_JPG_DEFAULT_HEADER_PART3_LENGTH;
|
|
|
|
for (i = 0; i < o_size; i++) {
|
|
if (dst - start >= *size) return GP_ERROR;
|
|
value = *(src + i) & 0xFF;
|
|
*(dst) = value;
|
|
dst++;
|
|
|
|
if (value == 0xFF && !omit_escape) {
|
|
if (dst - start >= *size) return GP_ERROR;
|
|
*(dst) = 0x00;
|
|
dst++;
|
|
}
|
|
}
|
|
if (dst + 2 - start >= *size) return GP_ERROR;
|
|
|
|
/* Add end of image marker */
|
|
*(dst++) = 0xFF;
|
|
*(dst++) = 0xD9;
|
|
|
|
*size = dst - start;
|
|
return GP_OK;
|
|
}
|