Ejemplo n.º 1
0
/* This is the parent function, who calls most of the functions below.
   It returns GP_ERROR if it cannot get the camera data, and GP_OK otherwise.
   The subroutines will print out more detained information should they fail.
*/
int dimagev_get_camera_data(dimagev_t *dimagev) {
	dimagev_packet *p, *raw;
	unsigned char char_buffer;

	/* Check the device. */
	if ( dimagev->dev == NULL ) {
		GP_DEBUG( "dimagev_get_camera_data::device not valid");
		return GP_ERROR_BAD_PARAMETERS;
	}

	/* Let's say hello and get the current status. */
	if ( ( p = dimagev_make_packet(DIMAGEV_GET_DATA, 1, 0)) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_data::unable to allocate packet");
		return GP_ERROR_NO_MEMORY;
	}

	if ( gp_port_write(dimagev->dev, (char*)p->buffer, p->length) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_data::unable to write packet");
		free(p);
		return GP_ERROR_IO;
	} else if ( gp_port_read(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_data::no response from camera");
		free(p);
		return GP_ERROR_IO;
	}

	free(p);

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_camera_data::camera did not acknowledge transmission");
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_camera_data::camera cancels transmission");
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_camera_data::camera responded with unknown value %x", char_buffer);
			return GP_ERROR_IO;
	}

	if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_data::unable to read packet");
		return GP_ERROR_IO;
	}

	char_buffer = DIMAGEV_EOT;
	if ( gp_port_write(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_data::unable to send EOT");
		free(p);
		return GP_ERROR_IO;
	}
		
	if ( gp_port_read(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_data::no response from camera");
		free(p);
		return GP_ERROR_IO;
	}

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_camera_data::camera did not acknowledge transmission");
			free(p);
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_camera_data::camera cancels transmission");
			free(p);
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_camera_data::camera responded with unknown value %x", char_buffer);
			free(p);
			return GP_ERROR_IO;
	}

	if ( ( raw = dimagev_strip_packet(p) ) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_data::unable to strip data packet");
		free(p);
		return GP_ERROR;
	}

	if ( ( dimagev->data = dimagev_import_camera_data(raw->buffer)) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_data::unable to read camera data");
		free(raw);
		free(p);
		return GP_ERROR;
	}

	/* Sure it *should* get freed automagically, but why take the risk? */
	free(p);
	free(raw);

	return GP_OK;
}
Ejemplo n.º 2
0
/* This function sends the contents of a dimagev_data_t to the current camera.
   This allows many changes to be made (e.g. entering host mode and record
   mode) while only sending a single set_data command.
*/
int dimagev_send_data(dimagev_t *dimagev) {
	dimagev_packet *p;
	unsigned char *export_data, char_buffer;


	if ( dimagev == NULL ) {
		GP_DEBUG( "dimagev_send_data::unable to use NULL dimagev_t");
		return GP_ERROR_BAD_PARAMETERS;
	}

	if ( ( export_data = dimagev_export_camera_data(dimagev->data) ) == NULL ) {
		GP_DEBUG( "dimagev_send_data::unable to export camera data");
		return GP_ERROR;
	}

	dimagev_dump_camera_data(dimagev->data);

	if ( ( p = dimagev_make_packet(DIMAGEV_SET_DATA, 1, 0) ) == NULL ) {
		GP_DEBUG( "dimagev_send_data::unable to create set_data packet");
		free(export_data);
		return GP_ERROR_NO_MEMORY;
	}

	if ( gp_port_write(dimagev->dev, (char*)p->buffer, p->length) < GP_OK ) {
		GP_DEBUG( "dimagev_send_data::unable to send set_data packet");
		free(p);
		free(export_data);
		return GP_ERROR_IO;
	} else if ( gp_port_read(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_send_data::no response from camera - trying to send NAK");
		free(p);
		free(export_data);
		return GP_ERROR_IO;
	}
		
	free(p);

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_send_data::camera did not acknowledge transmission");
			free(export_data);
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_send_data::camera cancels transmission");
			free(export_data);
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_send_data::camera responded with unknown value %x", char_buffer);
			free(export_data);
			return GP_ERROR_IO;
	}

	if ( ( p = dimagev_make_packet(export_data, 9, 1) ) == NULL ) {
		GP_DEBUG( "dimagev_send_data::unable to create set_data packet");
		free(export_data);
		return GP_ERROR_NO_MEMORY;
	}

	free(export_data);

	if ( gp_port_write(dimagev->dev, (char*)p->buffer, p->length) < GP_OK ) {
		GP_DEBUG( "dimagev_send_data::unable to send data packet");
		free(p);
		return GP_ERROR_IO;
	}

	free(p);
		
	if ( gp_port_read(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_send_data::no response from camera");
		return GP_ERROR_IO;
	}

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_send_data::camera did not acknowledge transmission");
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_send_data::camera cancels transmission");
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_send_data::camera responded with unknown value %x", char_buffer);
			return GP_ERROR_IO;
	}


	char_buffer = DIMAGEV_EOT;
	if ( gp_port_write(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_send_data::unable to send EOT");
		return GP_ERROR_IO;
	}
		
	if ( gp_port_read(dimagev->dev, (char*)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_send_data::no response from camera");
		return GP_ERROR_IO;
	}

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_send_data::camera did not acknowledge transmission");
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_send_data::camera cancels transmission");
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_send_data::camera responded with unknown value %x", char_buffer);
			return GP_ERROR_IO;
	}

	if ( sleep(3) != 0 ) {
		GP_DEBUG( "dimagev_send_data::sleep() returned non-zero value");
	}

	return GP_OK;
}
Ejemplo n.º 3
0
/* This is the parent function, who calls most of the functions below.
   It returns GP_ERROR if it cannot get the camera data, and GP_OK otherwise.
   The subroutines will print out more detained information should they fail. */
int dimagev_get_camera_info(dimagev_t *dimagev) {
	dimagev_packet *p, *raw;
	unsigned char char_buffer;

	/* Check the device. */
	if ( dimagev->dev == NULL ) {
		GP_DEBUG( "dimagev_get_camera_info::device not valid");
		return GP_ERROR_BAD_PARAMETERS;
	}

	/* Make sure that the old info struct is fred, and allocate a new one. */
	/*
	if ( dimagev->info != NULL ) {
		free(dimagev->info);
	}
	*/

	/* Let's say hello and get the current status. */
	if ( ( p = dimagev_make_packet(DIMAGEV_INQUIRY, 1, 0)) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_info::unable to allocate packet");
		return GP_ERROR_IO;
	}

	if ( gp_port_write(dimagev->dev, p->buffer, p->length) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_info::unable to write packet");
		free(p);
		return GP_ERROR_IO;
	} else if ( gp_port_read(dimagev->dev, &char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_info::no response from camera");
		free(p);
		return GP_ERROR_IO;
	}

	free(p);

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			/* Keep trying until a CAN is issued. */
			GP_DEBUG( "dimagev_get_camera_info::camera did not acknowledge transmission");
			return dimagev_get_camera_info(dimagev);
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_camera_info::camera cancels transmission");
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_camera_info::camera responded with unknown value %x", char_buffer);
			return GP_ERROR_IO;
	}

	if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_info::unable to read packet");
		return GP_ERROR_IO;
	}

	char_buffer = DIMAGEV_EOT;
	if ( gp_port_write(dimagev->dev, &char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_info::unable to send EOT");
		free(p);
		return GP_ERROR_IO;
	}
		
	if ( gp_port_read(dimagev->dev, &char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_camera_info::no response from camera");
		free(p);
		return GP_ERROR_IO;
	}

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_camera_info::camera did not acknowledge transmission");
			free(p);
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_camera_info::camera cancels transmission");
			free(p);
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_camera_info::camera responded with unknown value %x", char_buffer);
			free(p);
			return GP_ERROR_IO;
	}

	if ( ( raw = dimagev_strip_packet(p) ) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_info::unable to strip data packet");
		free(p);
		return GP_ERROR_NO_MEMORY;
	}

	if ( ( dimagev->info = dimagev_import_camera_info(raw->buffer) ) == NULL ) {
		GP_DEBUG( "dimagev_get_camera_info::unable to read camera info");
		free(p);
		free(raw);
		return GP_ERROR;
	}

	/* Sure it *should* get fred automagically, but why take the risk? */
	free(p);
	free(raw);

	return GP_OK;
}
Ejemplo n.º 4
0
int dimagev_delete_picture(dimagev_t *dimagev, int file_number) {
    dimagev_packet *p, *raw;
    unsigned char command_buffer[3];
    char char_buffer = 0;

    if ( dimagev == NULL ) {
        GP_DEBUG( "dimagev_delete_picture::unable to use NULL dimagev_t");
        return GP_ERROR_BAD_PARAMETERS;
    }

    dimagev_dump_camera_status(dimagev->status);
    /* An image can only be deleted if the card is normal or full. */
    if ( dimagev->status->card_status > (unsigned char) 1 ) {
        GP_DEBUG( "dimagev_delete_picture::memory card does not permit deletion");
        return GP_ERROR;
    }

    if ( dimagev->data->host_mode != (unsigned char) 1 ) {

        dimagev->data->host_mode = (unsigned char) 1;

        if ( dimagev_send_data(dimagev) < GP_OK ) {
            GP_DEBUG( "dimagev_delete_picture::unable to set host mode");
            return GP_ERROR_IO;
        }
    }


    /* First make the command packet. */
    command_buffer[0] = 0x05;
    command_buffer[1] = (unsigned char)( file_number / 256 );
    command_buffer[2] = (unsigned char)( file_number % 256 );
    if ( ( p = dimagev_make_packet(command_buffer, 3, 0) ) == NULL ) {
        GP_DEBUG( "dimagev_delete_picture::unable to allocate command packet");
        return GP_ERROR_NO_MEMORY;
    }

    if ( gp_port_write(dimagev->dev, (char *)p->buffer, p->length) < GP_OK ) {
        GP_DEBUG( "dimagev_delete_picture::unable to send set_data packet");
        free(p);
        return GP_ERROR_IO;
    } else if ( gp_port_read(dimagev->dev, &char_buffer, 1) < GP_OK ) {
        GP_DEBUG( "dimagev_delete_picture::no response from camera");
        free(p);
        return GP_ERROR_IO;
    }

    free(p);

    switch ( char_buffer ) {
    case DIMAGEV_ACK:
        break;
    case DIMAGEV_NAK:
        GP_DEBUG( "dimagev_delete_picture::camera did not acknowledge transmission");
        return GP_ERROR_IO;
    case DIMAGEV_CAN:
        GP_DEBUG( "dimagev_delete_picture::camera cancels transmission");
        return GP_ERROR_IO;
    default:
        GP_DEBUG( "dimagev_delete_picture::camera responded with unknown value %x", char_buffer);
        return GP_ERROR_IO;
    }


    if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
        GP_DEBUG( "dimagev_delete_picture::unable to read packet");
        return GP_ERROR_IO;
    }

    if ( ( raw = dimagev_strip_packet(p) ) == NULL ) {
        GP_DEBUG( "dimagev_delete_picture::unable to strip packet");
        free(p);
        return GP_ERROR;
    }

    free(p);

    if ( raw->buffer[0] != (unsigned char) 0 ) {
        GP_DEBUG( "dimagev_delete_picture::delete returned error code");
        free(raw);
        return GP_ERROR_NO_MEMORY;
    }
    free(raw);

    char_buffer=DIMAGEV_EOT;
    if ( gp_port_write(dimagev->dev, &char_buffer, 1) < GP_OK ) {
        GP_DEBUG( "dimagev_delete_picture::unable to send ACK");
        return GP_ERROR_IO;
    }

    if ( gp_port_read(dimagev->dev, &char_buffer, 1) < GP_OK ) {
        GP_DEBUG( "dimagev_delete_picture::no response from camera");
        return GP_ERROR_IO;
    }

    switch ( char_buffer ) {
    case DIMAGEV_ACK:
        break;
    case DIMAGEV_NAK:
        GP_DEBUG( "dimagev_delete_picture::camera did not acknowledge transmission");
        return GP_ERROR_IO;
    case DIMAGEV_CAN:
        GP_DEBUG( "dimagev_delete_picture::camera cancels transmission");
        return GP_ERROR_IO;
    default:
        GP_DEBUG( "dimagev_delete_picture::camera responded with unknown value %x", char_buffer);
        return GP_ERROR_IO;
    }

    return GP_OK;
}
Ejemplo n.º 5
0
int dimagev_get_picture(dimagev_t *dimagev, int file_number, CameraFile *file) {
	int total_packets, i;
	unsigned long size = 0;
	dimagev_packet *p, *r;
	unsigned char char_buffer, command_buffer[3];
	char *data;

	if ( dimagev->data->host_mode != (unsigned char) 1 ) {

		dimagev->data->host_mode = (unsigned char) 1;

		if ( dimagev_send_data(dimagev) < GP_OK ) {
			GP_DEBUG( "dimagev_get_picture::unable to set host mode");
			return GP_ERROR_IO;
		}
	}

	GP_DEBUG( "dimagev_get_picture::file_number is %d", file_number);

	/* Maybe check if it exists? Check the file type? */
	
	/* First make the command packet. */
	command_buffer[0] = 0x04;
	command_buffer[1] = (unsigned char)( file_number / 256 );
	command_buffer[2] = (unsigned char)( file_number % 256 );
	if ( ( p = dimagev_make_packet(command_buffer, 3, 0) ) == NULL ) {
		GP_DEBUG( "dimagev_get_picture::unable to allocate command packet");
		return GP_ERROR_NO_MEMORY;
	}

	if ( gp_port_write(dimagev->dev, (char *)p->buffer, p->length) < GP_OK ) {
		GP_DEBUG( "dimagev_get_picture::unable to send set_data packet");
		free(p);
		return GP_ERROR_IO;
	} else if ( gp_port_read(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_picture::no response from camera");
		free(p);
		return GP_ERROR_IO;
	}
		
	free(p);

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_picture::camera did not acknowledge transmission");
			return dimagev_get_picture(dimagev, file_number, file);
/*			return GP_ERROR_IO;*/
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_picture::camera cancels transmission");
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_picture::camera responded with unknown value %x", char_buffer);
			return GP_ERROR_IO;
	}

	if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
		GP_DEBUG( "dimagev_get_picture::unable to read packet");
		return GP_ERROR_IO;
	}

	if ( ( r = dimagev_strip_packet(p) ) == NULL ) {
		GP_DEBUG( "dimagev_get_picture::unable to strip packet");
		free(p);
		return GP_ERROR_NO_MEMORY;
	}
		
	free(p);

	total_packets = (int) r->buffer[0];

	/* Allocate an extra byte just in case. */
	if ( ( data = malloc((size_t)((993 * total_packets) + 1)) ) == NULL ) {
		GP_DEBUG( "dimagev_get_picture::unable to allocate buffer for file");
		free(r);
		return GP_ERROR_NO_MEMORY;
	}

	memcpy(data, &(r->buffer[1]), (size_t) r->length );
	size += ( r->length - 2 );

	free(r);

	for ( i = 0 ; i < ( total_packets -1 ) ; i++ ) {
		char_buffer=DIMAGEV_ACK;
		if ( gp_port_write(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
			GP_DEBUG( "dimagev_get_picture::unable to send ACK");
			free(data);
			return GP_ERROR_IO;
		}
	
		if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
			/*
			GP_DEBUG( "dimagev_get_picture::unable to read packet");
			return GP_ERROR_IO;
			*/

			GP_DEBUG( "dimagev_get_picture::sending NAK to get retry");
			char_buffer=DIMAGEV_NAK;
			if ( gp_port_write(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
				GP_DEBUG( "dimagev_get_picture::unable to send NAK");
				free(data);
				return GP_ERROR_IO;
			}

			if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
				GP_DEBUG( "dimagev_get_picture::unable to read packet");
				free(data);
				return GP_ERROR_IO;
			}
		}

		if ( ( r = dimagev_strip_packet(p) ) == NULL ) {
			GP_DEBUG( "dimagev_get_picture::unable to strip packet");
			free(data);
			free(p);
			return GP_ERROR_NO_MEMORY;
		}
		
		free(p);

		memcpy(&( data[ ( size + 1) ] ), r->buffer, (size_t) r->length );
		size += r->length;

		free(r);
	}

	size++;

	char_buffer=DIMAGEV_EOT;
	if ( gp_port_write(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_picture::unable to send ACK");
		free(data);
		return GP_ERROR_IO;
	}

	if ( gp_port_read(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_picture::no response from camera");
		free(data);
		return GP_ERROR_IO;
	}
		
	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_picture::camera did not acknowledge transmission");
			free(data);
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_picture::camera cancels transmission");
			free(data);
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_picture::camera responded with unknown value %x", char_buffer);
			free(data);
			return GP_ERROR_IO;
	}

	gp_file_set_data_and_size (file, data, size);

	return GP_OK;
}
Ejemplo n.º 6
0
int dimagev_get_thumbnail(dimagev_t *dimagev, int file_number, CameraFile *file) {
	dimagev_packet *p, *r;
	unsigned char char_buffer, command_buffer[3], *ycrcb_data;
	char *data;
	long int size = 0;

	if ( dimagev->data->host_mode != (unsigned char) 1 ) {

		dimagev->data->host_mode = (unsigned char) 1;

		if ( dimagev_send_data(dimagev) < GP_OK ) {
			GP_DEBUG( "dimagev_get_thumbnail::unable to set host mode");
			return GP_ERROR_IO;
		}
	}

	/* First make the command packet. */
	command_buffer[0] = 0x0d;
	command_buffer[1] = (unsigned char)( file_number / 256 );
	command_buffer[2] = (unsigned char)( file_number % 256 );
	if ( ( p = dimagev_make_packet(command_buffer, 3, 0) ) == NULL ) {
		GP_DEBUG( "dimagev_get_thumbnail::unable to allocate command packet");
		return GP_ERROR_NO_MEMORY;
	}

	if ( gp_port_write(dimagev->dev, (char *)p->buffer, p->length) < GP_OK ) {
		GP_DEBUG( "dimagev_get_thumbnail::unable to send set_data packet");
		free(p);
		return GP_ERROR_IO;
	} else if ( gp_port_read(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_thumbnail::no response from camera");
		free(p);
		return GP_ERROR_IO;
	}
		
	free(p);

	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_thumbnail::camera did not acknowledge transmission");
			return dimagev_get_thumbnail(dimagev, file_number, file);
/*			return GP_ERROR_IO;*/
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_thumbnail::camera cancels transmission");
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_thumbnail::camera responded with unknown value %x", char_buffer);
			return GP_ERROR_IO;
	}

	if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
		GP_DEBUG( "dimagev_get_thumbnail::unable to read packet");
		return GP_ERROR_IO;
	}

	if ( ( r = dimagev_strip_packet(p) ) == NULL ) {
		GP_DEBUG( "dimagev_get_thumbnail::unable to strip packet");
		free(p);
		return GP_ERROR_NO_MEMORY;
	}
		
	free(p);

	/* Unlike normal images, we are guaranteed 9600 bytes *exactly*. */

	/* Allocate an extra byte just in case. */
	if ( ( ycrcb_data = malloc(9600) ) == NULL ) {
		GP_DEBUG( "dimagev_get_thumbnail::unable to allocate buffer for file");
		free(r);
		return GP_ERROR_NO_MEMORY;
	}

	memcpy(ycrcb_data, r->buffer, (size_t) r->length );
	size +=  r->length - 1 ;

	free(r);

	while ( size < 9599 ) {

		char_buffer=DIMAGEV_ACK;
		if ( gp_port_write(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
			GP_DEBUG( "dimagev_get_thumbnail::unable to send ACK");
			free(ycrcb_data);
			return GP_ERROR_IO;
		}
	
		if ( ( p = dimagev_read_packet(dimagev) ) == NULL ) {
			GP_DEBUG( "dimagev_get_thumbnail::unable to read packet");
			free(ycrcb_data);
			return GP_ERROR_IO;
		}

		if ( ( r = dimagev_strip_packet(p) ) == NULL ) {
			GP_DEBUG( "dimagev_get_thumbnail::unable to strip packet");
			free(p);
			free(ycrcb_data);
			return GP_ERROR_NO_MEMORY;
		}
		
		free(p);

		memcpy(&( ycrcb_data[ ( size + 1) ] ), r->buffer, (size_t) r->length );
		size += r->length;

		free(r);

		GP_DEBUG( "dimagev_get_thumbnail::current file size is %ld", size);
	}

	size++;

	char_buffer=DIMAGEV_EOT;
	if ( gp_port_write(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_thumbnail::unable to send ACK");
		free(ycrcb_data);
		return GP_ERROR_IO;
	}

	if ( gp_port_read(dimagev->dev, (char *)&char_buffer, 1) < GP_OK ) {
		GP_DEBUG( "dimagev_get_thumbnail::no response from camera");
		free(ycrcb_data);
		return GP_ERROR_IO;
	}
		
	switch ( char_buffer ) {
		case DIMAGEV_ACK:
			break;
		case DIMAGEV_NAK:
			GP_DEBUG( "dimagev_get_thumbnail::camera did not acknowledge transmission");
			free(ycrcb_data);
			return GP_ERROR_IO;
		case DIMAGEV_CAN:
			GP_DEBUG( "dimagev_get_thumbnail::camera cancels transmission");
			free(ycrcb_data);
			return GP_ERROR_IO;
		default:
			GP_DEBUG( "dimagev_get_thumbnail::camera responded with unknown value %x", char_buffer);
			free(ycrcb_data);
			return GP_ERROR_IO;
	}

	data = (char *)dimagev_ycbcr_to_ppm(ycrcb_data);
	size = 14413;

	gp_file_set_data_and_size (file, data, size);

	return GP_OK;
}