Files
libgphoto2/camlibs/kodak/dc3200/library.c
2020-05-25 17:55:09 +02:00

1021 lines
23 KiB
C

/* library.c
*
* Copyright (C) 2000,2001,2002 donn morrison - dmorriso@gulf.uvic.ca
*
* 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
*/
/****************************************************
* kodak dc3200 digital camera driver library *
* for gphoto2 *
* *
* author: donn morrison - dmorriso@gulf.uvic.ca *
* date: dec 2000 - jan 2002 *
* license: gpl *
* version: 1.6 *
* *
****************************************************/
#include "config.h"
#include "library.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "dc3200.h"
#ifdef ENABLE_NLS
# include <libintl.h>
# undef _
# define _(String) dgettext (GETTEXT_PACKAGE, String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define _(String) (String)
# define N_(String) (String)
#endif
/*
* FIXME: Use properly sized integer types. The dc3200 code used lots
* of u_char, u_long, u_int, which may be wrong on non-32bit systems.
*/
/* #define DEBUG */
/*
* dc3200_set_speed
*
* handshakes a baud rate with the camera
*
*/
int dc3200_set_speed(Camera *camera, int baudrate)
{
int baudcode = C9600;
unsigned char resp[INI_PACKET_LEN], msg[INI_PACKET_LEN];
int resp_len = INI_PACKET_LEN, msg_len = INI_PACKET_LEN;
msg[0] = 0xAF;
msg[1] = 0x00;
switch(baudrate) {
case 9600:
baudcode = C9600;
break;
case 19200:
baudcode = C19200;
break;
case 38400:
baudcode = C38400;
break;
case 57600:
baudcode = C57600;
break;
case 115200:
baudcode = C115200;
break;
default:
printf("unsupported baudrate: %d.\n", baudrate);
return GP_ERROR;
}
msg[2] = baudcode;
/* send our preferred baud rate */
if(dc3200_send_command(camera, msg, msg_len, resp, &resp_len) == GP_ERROR)
return GP_ERROR;
/* the camera responds with our preferred baud rate or its
* maximum baud rate, whichever is lowest
*/
/* compile a confirmation packet */
msg[0] = 0x9F;
msg[1] = 0x00;
if(resp_len == 2) {
msg_len = 2;
} else {
/* calculate reply baud handshake */
msg[2] = (resp[2] + 1) / 2;
msg_len = INI_PACKET_LEN;
}
if(dc3200_send_command(camera, msg, msg_len, resp, &resp_len) == GP_ERROR)
return GP_ERROR;
if(resp_len == 2) {
/* set the handshaked baudrate
* supports only 9600
*/
return C9600;
} else if(resp[1] == 0x01) {
/* set the handshaked baudrate */
return (resp[2]*2) - 1;
} else {
/* unknown baud */
return GP_ERROR;
}
return GP_ERROR;
}
/*
* dc3200_setup
*
* sends two commands essential for survival
*
*/
int dc3200_setup(Camera *camera)
{
/*
* some strange commands that must be
* completed after initialization and
* before any camera access
*
* version info? ...
*
*/
unsigned char cmd1[5] = {0x01, 0, 0x01, 0x00, 0x0F};
unsigned char cmd2[8] = {0x01, 0, 0x80, 0x00, 0x01, 0x81, 0x00, 0x03};
unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN];
int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN;
cmd1[1] = dc3200_calc_seqnum(camera);
cmd2[1] = dc3200_calc_seqnum(camera);
if(dc3200_send_command(camera, cmd1, sizeof(cmd1), ack, &ack_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_check_ack(camera, ack, ack_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_send_ack(camera, resp[1]) == GP_ERROR)
return GP_ERROR;
if(dc3200_send_command(camera, cmd2, sizeof(cmd2), ack, &ack_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_check_ack(camera, ack, ack_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_send_ack(camera, resp[1]) == GP_ERROR)
return GP_ERROR;
/* set the cmd sequence number */
camera->pl->cmd_seqnum = 0;
camera->pl->rec_seqnum = 0;
return GP_OK;
}
/*
* dc3200_get_data
*
* retrieves data from the camera as either file
* data or file/folder list data
*
*/
/* command to retrieve directory listing
unsigned char list_pkt[DEF_PACKET_LEN] = {0x01, dc3200_calc_seqnum(camera), 0x80, 0x00, 0x20, 0x03, 26 + strlen(filename),
0xc1, 0x50, 0x00, 0x00, 0x00, 0x00, 19 + strlen(filename),
0x04, 0x01, 0x00, 0x01, 0x00, 0x01, 0x60, 0x01, 0x00, 0x01, 0x00, 0x05,
0x00, 0x00, 0x00, 2 + strlen(filename), 0x01};
*/
/* command to get the picture
unsigned char get_pkt[DEF_PACKET_LEN] = {0x01, calc_seqnum(), 0x80, 0x00, 0x20, 0x03, 26 + strlen(filename),
0xC1, 0x50, 0x00, 0x00, 0x00, 0x00, 19 + strlen(filename),
0x04, 0x01, 0x00, 0x01, 0x01, 0x04, 0x60, 0x10, 0x00, 0x01, 0x00, 0x05,
0x00, 0x00, 0x00, 2 + strlen(filename), 0x01};
*/
int dc3200_get_data(Camera *camera, unsigned char **data, unsigned long *data_len, int command, const char *folder, const char *filename)
{
unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN];
int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN;
unsigned long num_left = 0;
int data_start_pos = 0;
unsigned char *ptr_data = NULL;
unsigned int pid = 0;
/* command bytes */
unsigned char cb1=0x00,cb2=0x00,cb3=0x00;
/* packet parts */
unsigned char pkt_hdr[7];
unsigned char pkt_typ[7];
unsigned char pkt_cmd[12];
unsigned char pkt_len[5];
unsigned char *packet;
int packet_len;
char *file = NULL;
char *ptr = NULL;
if(folder) {
if(filename) {
file = malloc(strlen(folder) + strlen(filename) + 2);
if(!file)
return GP_ERROR;
/* concatenate the folder + filename */
strncpy(file, folder, strlen(folder));
file[strlen(folder)] = 0;
/* append the filename */
if(folder[strlen(folder)-1] != '\\')
strcat(file, "\\");
strncat(file, filename, strlen(filename));
} else {
file = malloc(strlen(folder) + 2);
if(!file)
return GP_ERROR;
strncpy(file, folder, strlen(folder));
file[strlen(folder)] = 0;
}
} else {
return GP_ERROR;
}
/* change all /'s to \'s */
while((ptr = strchr(file, '/'))) {
ptr[0] = '\\';
}
/* there should not be a trailing '\', except for root folder */
if(strlen(file) > 1 && file[strlen(file)-1] == '\\')
file[strlen(file)-1] = 0;
switch (command) {
case CMD_GET_PREVIEW:
cb1 = 0x02; cb2 = 0x70; cb3 = 0x11;
break;
case CMD_GET_FILE:
cb1 = 0x01; cb2 = 0x60; cb3 = 0x10;
break;
case CMD_LIST_FILES:
cb1 = 0x01; cb2 = 0x60; cb3 = 0x01;
break;
}
camera->pl->cmd_seqnum++;
pkt_hdr[0] = 0x01;
pkt_hdr[1] = dc3200_calc_seqnum(camera);
pkt_hdr[2] = 0x80; pkt_hdr[3] = 0x00; pkt_hdr[4] = 0x20; pkt_hdr[5] = 0x03;
pkt_hdr[6] = 26 + strlen(file);
pkt_typ[0] = 0xC1;
pkt_typ[1] = 0x50;
pkt_typ[2] = 0x00; pkt_typ[3] = 0x00; pkt_typ[4] = 0x00; pkt_typ[5] = 0x00;
pkt_typ[6] = 19 + strlen(file);
pkt_cmd[0] = 0x04; pkt_cmd[1] = cb1; /* cmd */
pkt_cmd[2] = 0x00; pkt_cmd[3] = 0x01; /* ??? */
pkt_cmd[4] = (camera->pl->cmd_seqnum >> 8) & 0xff; pkt_cmd[5] = camera->pl->cmd_seqnum & 0xff; /* SEQ */
pkt_cmd[6] = cb2; pkt_cmd[7] = cb3; /* cmd */
pkt_cmd[8] = 0x00; pkt_cmd[9] = 0x01; /* ??? */
pkt_cmd[10] = 0x00; pkt_cmd[11] = 0x05; /* ??? */
pkt_len[0] = 0x00; pkt_len[1] = 0x00; pkt_len[2] = 0x00;
pkt_len[3] = strlen(file) + 2;
pkt_len[4] = 0x01;
packet_len = sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd) + sizeof(pkt_len) + strlen(file) + 2;
packet = malloc(packet_len);
if(!packet) {
free(file);
return GP_ERROR;
}
/* clear packet */
memset(packet, 0, packet_len);
/* copy pkt parts into packet */
memcpy(packet, pkt_hdr, sizeof(pkt_hdr));
memcpy(packet + sizeof(pkt_hdr), pkt_typ, sizeof(pkt_typ));
memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ), pkt_cmd, sizeof(pkt_cmd));
memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd), pkt_len, sizeof(pkt_len));
memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd) + sizeof(pkt_len), file, strlen(file));
free(file);
/* send the command to list files */
if(dc3200_send_command(camera, packet, packet_len, ack, &ack_len) == GP_ERROR){
free(packet);
return GP_ERROR;
}
free(packet);
do {
resp_len = DEF_PACKET_LEN;
if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) {
return GP_ERROR;
}
if(dc3200_send_ack(camera, resp[1]) == GP_ERROR) {
return GP_ERROR;
}
if(resp[1] == camera->pl->rec_seqnum)
continue;
camera->pl->rec_seqnum = resp[1];
/*
* we decide what action to take based on
* the number of packets we are expecting
*
* resp[7] holds this info
*
*/
switch(resp[7]) {
case 0xC1:
/*
* SINGLE PACKET
*/
/* get the total list length from the data header */
*data_len = bytes_to_l(resp[26], resp[27], resp[28], resp[29]);
num_left = 0;
data_start_pos = 31;
*data_len -= 1;
/* allocate a buffer to store all this data */
*data = malloc(*data_len);
if(*data == NULL) {
return GP_ERROR;
}
ptr_data = *data;
/* copy this portion of the data */
memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
/* incr the buff ptr */
ptr_data += resp_len - data_start_pos;
break;
case 0x41:
/*
* MULTIPACKET, START
*/
/* get the total list length from the data header */
*data_len = bytes_to_l(resp[34], resp[35], resp[36], resp[37]);
num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]);
data_start_pos = 39;
*data_len -= 1;
/* allocate a buffer to store all this data */
*data = malloc(*data_len);
if(*data == NULL) {
return GP_ERROR;
}
ptr_data = *data;
/* copy this portion of the data */
memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
/* incr the data ptr */
ptr_data += resp_len - data_start_pos;
/* update gphoto2 frontend */
if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW)
{
pid = gp_context_progress_start(camera->pl->context,(int)*data_len,"%s", filename);
gp_context_progress_update(camera->pl->context, pid, ptr_data - *data);
if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) {
free(*data);
dc3200_cancel_get_data(camera);
return GP_ERROR_CANCEL;
}
}
break;
case 0x01:
/*
* MULTIPACKET, MIDDLE
*/
/* calculate the number of packets remaining */
num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]);
data_start_pos = 16;
if(*data == NULL) {
return GP_ERROR;
}
/* copy this portion of the data */
memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
/* incr the buff ptr */
ptr_data += resp_len - data_start_pos;
/* update gphoto2 frontend */
if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW)
{
gp_context_progress_update(camera->pl->context, pid, ptr_data - *data);
if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) {
free(*data);
dc3200_cancel_get_data(camera);
return GP_ERROR_CANCEL;
}
}
break;
case 0x81:
/*
* MULTIPACKET, END
*/
/* calculate the number of packets remaining */
num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]);
data_start_pos = 16;
if(*data == NULL) {
return GP_ERROR;
}
/* copy this portion of the data */
memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
/* incr the buff ptr */
ptr_data += resp_len - data_start_pos;
/* update gphoto2 frontend */
if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW)
{
gp_context_progress_update(camera->pl->context, pid, ptr_data - *data);
if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) {
free(*data);
dc3200_cancel_get_data(camera);
return GP_ERROR_CANCEL;
}
}
break;
default:
return GP_ERROR;
}
} while(num_left > 1);
if(pid != 0 && (command == CMD_GET_FILE || command == CMD_GET_PREVIEW))
gp_context_progress_stop(camera->pl->context, pid);
return GP_OK;
}
/*
* dc3200_cancel_get_data
*
* stops a get data command
*
*/
int dc3200_cancel_get_data(Camera *camera)
{
unsigned char pkt[20] = {0x01, 0, 0x80, 0x00, 0x20, 0x03, 0x0d, 0xc1, 0x50, 0xc0,
0x00, 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x01, 0, 0};
unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN];
int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN;
pkt[1] = dc3200_calc_seqnum(camera);
pkt[18] = (camera->pl->cmd_seqnum >> 8) & 0xff;
pkt[19] = camera->pl->cmd_seqnum & 0xff;
/* wait a bit ... */
sleep(1);
/* clear the buffer */
dc3200_clear_read_buffer(camera);
if(dc3200_send_command(camera, (unsigned char *)pkt, 20, ack, &ack_len) == GP_ERROR)
return GP_ERROR;
if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
return GP_ERROR;
else
dc3200_send_ack(camera, resp[1]);
resp_len = DEF_PACKET_LEN;
if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
return GP_ERROR;
else
dc3200_send_ack(camera, resp[1]);
return GP_OK;
}
/*
* dc3200_send_command
*
* if cmd == NULL || cmd_len == 0, send_command waits for a response
* otherwise, it sends a command and waits for an acknowledgement
*
*/
int dc3200_send_command(Camera *camera, unsigned char *cmd, int cmd_len, unsigned char *ack, int *ack_len)
{
int sends, reads;
int buff_len = *ack_len;
int received = 0;
unsigned char *buff = NULL;
buff = malloc(sizeof(unsigned char) * *ack_len);
if(buff == NULL) {
return GP_ERROR;
}
sends = SEND_RETRIES;
while(sends > 0) {
reads = READ_RETRIES;
/* check that we are actually sending a command
* and not just waiting for data
*/
if(cmd != NULL && cmd_len > 0) {
/* clear the read buffer */
dc3200_clear_read_buffer(camera);
/* send the command */
dc3200_send_packet(camera, cmd, cmd_len);
}
/* wait for response */
while(reads > 0) {
if(dc3200_recv_packet(camera, buff, &buff_len) != GP_ERROR) {
received = 1;
break;
}
reads--;
}
if(received) {
if(buff_len > *ack_len) {
/* buffer size too small */
free(buff);
return GP_ERROR;
}
/* sukksess */
*ack_len = buff_len;
memcpy(ack, buff, buff_len);
free(buff);
return GP_OK;
} else {
sends--;
}
}
/* send failed */
free(buff);
return GP_ERROR;
}
/*
* dc3200_recv_response
*
* receives a response from a previous command
*
*/
int dc3200_recv_response(Camera *camera, unsigned char *resp, int *resp_len)
{
return dc3200_send_command(camera, NULL, 0, resp, resp_len);
}
/*
* dc3200_send_ack
*
* sends an ack packet
*
*/
int dc3200_send_ack(Camera *camera, int seqnum)
{
unsigned char ack[ACK_PACKET_LEN];
ack[0] = 0x01;
ack[1] = seqnum + 16;
return dc3200_send_packet(camera, ack, sizeof(ack));
}
/*
* dc3200_check_ack
*
* checks an ack packet (well ok not really)
*
*/
int dc3200_check_ack(Camera *camera, unsigned char *ack, int ack_len)
{
return GP_OK;
}
/*
* dc3200_send_packet
*
* compiles a packet from data and sends it
*
*/
int dc3200_send_packet(Camera *camera, unsigned char *data, int data_len)
{
int res;
int buff_len = data_len;
unsigned char *buff = NULL;
buff = malloc(sizeof(unsigned char) * buff_len);
if(!buff)
return GP_ERROR;
memcpy(buff, data, buff_len);
/* compile this into a packet */
res = dc3200_compile_packet(camera, &buff, &buff_len);
if(res == GP_ERROR)
return res;
#ifdef DEBUG
dump_buffer(buff, buff_len, "s", 16);
#endif
res = gp_port_write(camera->port, (char *)buff, data_len + 3);
free(buff);
return res;
}
/*
* dc3200_recv_packet
*
* waits for a packet to arrive, checks it, and returns it
*
*/
int dc3200_recv_packet(Camera *camera, unsigned char *data, int *data_len)
{
int complete = 0;
int num_read = 0, res = 0, fails = 0;
/* allocate storage for size, checksum, and EOP */
unsigned char *buff = NULL;
buff = malloc(sizeof(unsigned char) * (*data_len + 3));
if(buff == NULL)
return GP_ERROR;
memset(buff, 0, *data_len + 3);
/*
* - read data until we get an 0xFF
* - process packet
*
*/
res = gp_port_read(camera->port, (char *)&buff[num_read], 1);
while(res >= 0 && fails < READ_RETRIES) {
if(res == 0) {
/* read nothing */
fails++;
} else {
/* reset # of fails */
fails = 0;
num_read++;
if(buff[num_read-1] == 0xFF) {
complete = 1;
break;
}
if(num_read == *data_len + 3) {
/* we've reached the buffer limit */
complete = 0;
break;
}
}
res = gp_port_read(camera->port, (char *)&buff[num_read], 1);
}
if(!complete) {
/* packet incomplete */
free(buff);
return GP_ERROR;
}
#ifdef DEBUG
dump_buffer(buff, num_read, "r", 16);
#endif
if(dc3200_process_packet(camera, buff, &num_read) == GP_ERROR) {
free(buff);
return GP_ERROR;
}
/* save the last successful packet received time */
time(&(camera->pl->last));
memcpy(data, buff, *data_len);
/* return with new packet size */
*data_len = num_read;
free(buff);
return GP_OK;
}
/*
* dc3200_compile_packet
*
* changes 0xFF -> 0xFE 0x01
* 0xFE -> 0xFE 0x00
* adds packet length, checksum, and EOP (0xFF)
*
*/
int dc3200_compile_packet(Camera *camera, unsigned char **data, int *data_len)
{
int count, i, j;
unsigned char *new_data = NULL;
unsigned char *tmp_ptr = NULL;
/* realloc + 2 for len and checksum */
*data_len += 2;
tmp_ptr = (unsigned char*)realloc(*data, *data_len);
if(tmp_ptr == NULL)
return GP_ERROR;
*data = tmp_ptr;
/* add length, checksum */
(*data)[*data_len - 2] = *data_len - 2;
(*data)[*data_len - 1] = dc3200_calc_checksum(camera, *data, *data_len - 1);
/* this is a hack to fix the 0xFF/0xFE problem.
* we adjust a "don't care" byte so the checksum
* is not 0xFF or 0xFE
*/
if((*data)[*data_len - 1] >= 0xFE) {
if(*data_len > 19) {
(*data)[19] += 2;
(*data)[*data_len - 1] = dc3200_calc_checksum(camera, *data, *data_len - 1);
printf("adjusting checksum to %02x\n", (*data)[*data_len - 1]);
}
}
/* count number of 0xfe's and 0xff's */
count = 0;
for(i=0;i<*data_len; i++) {
if((*data)[i] == 0xFE || (*data)[i] == 0xFF)
count++;
}
new_data = (unsigned char*)malloc(*data_len + count + 3); /* 3 for length, checksum, EOP */
if(!new_data)
return GP_ERROR;
j = 0;
for(i=0;i<*data_len; i++) {
if((*data)[i] == 0xFE || (*data)[i] == 0xFF) {
printf("(*data)[i] == %02x\n", (*data)[i]);
printf("(*data)[i] - 0xFE == %02x\n", (*data)[i] - 0xFE);
new_data[j++] = 0xFE;
new_data[j++] = (*data)[i] - 0xFE;
} else {
new_data[j++] = (*data)[i];
}
}
/* adjust the new packet count */
*data_len += count + 1;
new_data[*data_len - 1] = 0xFF;
/* free the old packet data */
free(*data);
/* set the ptr */
*data = new_data;
return GP_OK;
}
/*
* dc3200_process_packet
*
* changes 0xFE 0x01 -> 0xFF
* 0xFE 0x00 -> 0xFE
* checks & removes packet length, checksum, EOP (0xFF)
*
*/
int dc3200_process_packet(Camera *camera, unsigned char *data, int *data_len)
{
int count = 0, i;
int length, checksum;
unsigned char *buff;
if(data == NULL || *data_len < 1) {
return GP_ERROR;
}
/* allocate a new buffer */
buff = (unsigned char*)malloc(sizeof(unsigned char) * *data_len);
if(!buff)
return GP_ERROR;
/* change 0xFE 0x00 | 0x01 -> 0xFF | 0xFE */
for(i=0; i<*data_len; i++) {
if(data[i] == 0xFE) {
if(i<*data_len-1) { /* so we don't run out of array bounds */
if(data[i+1] == 0x00) {
buff[count] = 0xFE;
/* advance i so we don't pick up the trailing byte */
i++;
/* incr count */
count++;
} else if(data[i+1] == 0x01) {
buff[count] = 0xFF;
i++;
count++;
}
} else {
/* we've found an 0xFE but there is no trailing byte */
free(buff);
return GP_ERROR;
}
} else {
buff[count] = data[i];
count++;
}
}
/* copy over the old buffer */
memcpy(data, buff, count);
length = data[count - 3];
checksum = data[count - 2];
/* make sure its a valid packet */
if(length != count - 3 || checksum != dc3200_calc_checksum(camera, data, count - 2)) {
printf("%02x=%02x %02x=%02x\n", length, count - 3, checksum, dc3200_calc_checksum(camera, data, count - 2));
free(buff);
return GP_ERROR;
}
/* adjust packet size, strip length, checksum, EOP */
*data_len = count - 3;
free(buff);
return GP_OK;
}
/*
* dc3200_calc_checksum
*
* calculates the checksum for a byte array
*
*/
int dc3200_calc_checksum(Camera *camera, unsigned char * buffer, int len)
{
int sum = 0, i;
for(i=0; i<len; i++) {
sum += buffer[i];
}
sum = -sum + 0xFF;
if(sum < 0) sum = sum & 0xFF;
return sum;
}
/*
* dc3200_calc_seqnum
*
* calculates the seqnum for a packet
*
*/
int dc3200_calc_seqnum(Camera *camera)
{
if(camera->pl->pkt_seqnum >= 0x1F || camera->pl->pkt_seqnum < 0x10) {
camera->pl->pkt_seqnum = 0x10;
return camera->pl->pkt_seqnum;
} else {
camera->pl->pkt_seqnum++;
return camera->pl->pkt_seqnum;
}
}
/*
* dc3200_keep_alive
*
* sends and receives a ping packet to keep the
* camera awake
*
*/
int dc3200_keep_alive(Camera *camera)
{
unsigned char ka[ACK_PACKET_LEN]; /* keepalive */
unsigned char ak[ACK_PACKET_LEN]; /* keepalive ack */
int ak_len = ACK_PACKET_LEN;
ka[0] = 0xCF;
ka[1] = 0x01;
/* send keep alive packet */
if(dc3200_send_command(camera, ka, sizeof(ka), ak, &ak_len) == GP_ERROR) {
return GP_ERROR;
}
/* check the ack (should be same packet) */
if(memcmp(ak,ka,ak_len) == 0) {
return GP_OK;
}
return GP_ERROR;
}
/*
* dc3200_clear_read_buffer
*
* clears data in the read buffer by reading it out
*
* there is definitely a better way to accomplish this...
*
*/
int dc3200_clear_read_buffer(Camera *camera)
{
unsigned char byte;
int count = 0;
gp_port_set_timeout(camera->port, 0);
while(gp_port_read(camera->port, (char *)&byte, 1) > 0)
count++;
if(count > 0)
printf("cleared %d bytes from read buffer\n", count);
gp_port_set_timeout(camera->port, TIMEOUT);
return GP_OK;
}
/*
* dump_buffer
*
* displays a byte array nicely formatted in hex format
*
*/
int dump_buffer(unsigned char * buffer, int len, char * title, int bytesperline)
{
char spacer[80];
int i;
memset(spacer, 0, sizeof(spacer));
memset(spacer, ' ', strlen(title)+2);
printf("%s: ", title);
for(i=0; i<len; i++) {
if(i%bytesperline==0 && i > 0) {
printf("\n%s", spacer);
}
printf("%02x ", buffer[i]);
}
printf("\n");
printf("%s: ", title);
for(i=0; i<len; i++) {
if(i%bytesperline==0 && i > 0) {
printf("\n%s", spacer);
}
if(buffer[i] >= 0x20 && buffer[i] < 0x7F) {
printf("%c", buffer[i]);
} else {
printf(".");
}
}
printf("\n");
return GP_OK;
}
unsigned long bytes_to_l(int a, int b, int c, int d)
{
unsigned long res = a;
res = res << 24 | b << 16 | c << 8 | d;
return res;
}