Files
libgphoto2/camlibs/minolta/dimagev/packet.c
Arnaud Launay b9d58ca88b replace (c) and (C) by �
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@5969 67ed7778-7388-44ab-90cf-0a291f65f57c
2002-12-15 11:45:10 +00:00

226 lines
7.3 KiB
C

/**********************************************************************
* Minolta Dimage V digital camera communication library *
* Copyright © 2000,2001 Gus Hartmann *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public *
* License along with this program; if not, write to the Free *
* Software Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
* *
**********************************************************************/
/* $Id$ */
#include "config.h"
#include "dimagev.h"
#define GP_MODULE "dimagev"
/* This function takes an array of unsigned chars, as well as the length, and
creates a dimagev_packet ready for sending to the camera. Packets must be
of the form below:
bytes
--------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 through ( n-4) | n-3 | n-2 | n-1 |
--------------------------------------------------------------------
| STX | Seq | Length | Payload | Checksum | ETX |
--------------------------------------------------------------------
STX and ETX are defined in dimage.h; their values are 0x02 and 0x03.
Seq is the sequence number; start at zero.
Payload is the good stuff.
Checksum is the sum of all bytes 0 through ( n-4 ) mod 65536.
A packet must be at least eight bytes, with at least one byte of payload.
*/
dimagev_packet *dimagev_make_packet(unsigned char *buffer, unsigned int length, unsigned int seq) {
unsigned int i=0, checksum=0;
dimagev_packet *p;
if ( ( p = calloc(1, sizeof(dimagev_packet) ) ) == NULL ) {
GP_DEBUG("dimagev_make_packet::unable to allocate packet");
return NULL;
}
p->length = length + 7;
p->buffer[0] = DIMAGEV_STX;
p->buffer[1] = seq & 0x000000ff;
p->buffer[2] = ( p->length & 0x0000ff00) >> 8;
p->buffer[3] = p->length & 0x000000ff;
memcpy(&(p->buffer[4]), buffer, (unsigned int) length);
/* Now the footer. */
for (i=0 ; i < p->length - 3 ; i++ )
{
checksum += (unsigned int) p->buffer[i];
}
p->buffer[(p->length - 3)] = (unsigned char) ((checksum & 0x0000ff00) >> 8 );
p->buffer[(p->length - 2)] = (unsigned char) ( checksum & 0x000000ff );
p->buffer[(p->length - 1)] = (unsigned char) DIMAGEV_ETX;
return p;
}
/* dimagev_verify_packet(): return GP_OK if valid packet, GP_ERROR otherwise. */
int dimagev_verify_packet(dimagev_packet *p) {
int i=0;
unsigned short correct_checksum=0, current_checksum=0;
/* All packets must start with DIMAGEV_STX and end with DIMAGEV_ETX. It's an easy check. */
if ( ( p->buffer[0] != (unsigned char) DIMAGEV_STX ) || ( p->buffer[(p->length - 1)] != (unsigned char) DIMAGEV_ETX ) ) {
GP_DEBUG( "dimagev_verify_packet::packet missing STX and/or ETX");
return GP_ERROR_CORRUPTED_DATA;
}
correct_checksum = (p->buffer[(p->length - 3)] * 256) + p->buffer[(p->length - 2)];
for ( i = 0 ; i < ( p->length - 3 ) ; i++ ) {
current_checksum += p->buffer[i];
}
if ( current_checksum != correct_checksum ) {
GP_DEBUG( "dimagev_verify_packet::checksum bytes were %02x%02x, checksum was %d, should be %d", p->buffer[( p->length - 3) ], p->buffer[ ( p->length -2 ) ], current_checksum, correct_checksum);
return GP_ERROR_CORRUPTED_DATA;
} else {
return GP_OK;
}
}
dimagev_packet *dimagev_read_packet(dimagev_t *dimagev) {
dimagev_packet *p;
unsigned char char_buffer;
if ( ( p = malloc(sizeof(dimagev_packet)) ) == NULL ) {
GP_DEBUG("dimagev_read_packet::unable to allocate packet");
return NULL;
}
if ( gp_port_read(dimagev->dev, p->buffer, 4) < GP_OK ) {
GP_DEBUG( "dimagev_read_packet::unable to read packet header - will try to send NAK");
free(p);
/* Send a NAK */
char_buffer = DIMAGEV_NAK;
if ( gp_port_write(dimagev->dev, &char_buffer, 1) < GP_OK ) {
GP_DEBUG( "dimagev_read_packet::unable to send NAK");
return NULL;
}
/* Who likes recursion? */
return ( p = dimagev_read_packet(dimagev));
}
p->length = ( p->buffer[2] * 256 ) + ( p->buffer[3] );
if ( gp_port_read(dimagev->dev, &(p->buffer[4]), ( p->length - 4)) < GP_OK ) {
GP_DEBUG( "dimagev_read_packet::unable to read packet body - will try to send NAK");
free(p);
/* Send a NAK */
char_buffer = DIMAGEV_NAK;
if ( gp_port_write(dimagev->dev, &char_buffer, 1) < GP_OK ) {
GP_DEBUG( "dimagev_read_packet::unable to send NAK");
return NULL;
}
/* Who likes recursion? */
return ( p = dimagev_read_packet(dimagev));
}
/* Now we *should* have a packet. Let's do a sanity check. */
if ( dimagev_verify_packet(p) < GP_OK ) {
GP_DEBUG( "dimagev_read_packet::got an invalid packet - will try to send NAK");
free(p);
/* Send a NAK */
char_buffer = DIMAGEV_NAK;
if ( gp_port_write(dimagev->dev, &char_buffer, 1) < GP_OK ) {
GP_DEBUG( "dimagev_read_packet::unable to send NAK");
return NULL;
}
/* Who likes recursion? */
return ( p = dimagev_read_packet(dimagev));
}
return p;
}
void dimagev_dump_packet(dimagev_packet *p) {
int i=0;
printf("Packet length is %d\n", p->length);
for ( i = 0 ; i < p->length ; i++ ) {
printf("%02x ",(unsigned int) p->buffer[i]);
}
printf("\n");
return;
}
dimagev_packet *dimagev_strip_packet(dimagev_packet *p) {
dimagev_packet *stripped;
/* All camera packets must start with DIMAGEV_STX and end with DIMAGEV_ETX. */
/* Packets used as strings shouldn't have these. It's an easy check. */
if ( ( p->buffer[0] != (unsigned char) DIMAGEV_STX ) || ( p->buffer[(p->length - 1)] != (unsigned char) DIMAGEV_ETX ) ) {
return NULL;
}
if ( ( stripped = malloc(sizeof(dimagev_packet)) ) == NULL ) {
GP_DEBUG("dimagev_strip_packet::unable to allocate destination packet");
return NULL;
}
stripped->length = ( p->length - 7 );
memcpy(stripped->buffer, &(p->buffer[4]), stripped->length);
return stripped;
}
unsigned char dimagev_decimal_to_bcd(unsigned char decimal) {
unsigned char bcd = (unsigned char) 0;
int tensdigit = 0;
if ( decimal > (unsigned char) 99 ) {
/* No good way to handle this. */
return (unsigned char) 0;
} else {
tensdigit = decimal / 10;
bcd = tensdigit * 16;
bcd += decimal % 10;
return bcd;
}
}
unsigned char dimagev_bcd_to_decimal(unsigned char bcd) {
if ( bcd > 99 ) {
/* The highest value that we can handle in BCD */
return (unsigned char) 99;
} else {
return ((bcd/16)*10 + (bcd%16));
}
}
int dimagev_packet_sequence(dimagev_packet *p) {
return (int) p->buffer[1];
}