From f89149e818f28c01acb862ec922cde7c4f439780 Mon Sep 17 00:00:00 2001 From: Raymond Penners Date: Fri, 21 Sep 2001 21:30:11 +0000 Subject: [PATCH] Added Sony DSC-F55/MSAC-SR1 git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@2292 67ed7778-7388-44ab-90cf-0a291f65f57c --- AUTHORS | 4 + ChangeLog | 8 + MAINTAINERS | 3 + camlibs/sonydscf55/Makefile.am | 13 + camlibs/sonydscf55/TODO | 22 + camlibs/sonydscf55/camera.c | 246 ++++++++++++ camlibs/sonydscf55/nls.h | 45 +++ camlibs/sonydscf55/sony.c | 709 +++++++++++++++++++++++++++++++++ camlibs/sonydscf55/sony.h | 61 +++ configure.in | 5 +- 10 files changed, 1114 insertions(+), 2 deletions(-) create mode 100644 camlibs/sonydscf55/Makefile.am create mode 100644 camlibs/sonydscf55/TODO create mode 100644 camlibs/sonydscf55/camera.c create mode 100644 camlibs/sonydscf55/nls.h create mode 100644 camlibs/sonydscf55/sony.c create mode 100644 camlibs/sonydscf55/sony.h diff --git a/AUTHORS b/AUTHORS index 8ffcaa3b9..56c2206a8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -45,3 +45,7 @@ gpio serial code Gus Hartmann Minolta Dimage V library + +Raymond Penners +gPhoto2 port of the Sony DSC-F55 library + diff --git a/ChangeLog b/ChangeLog index 0020c1296..d17b78341 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2001-09-21 Raymond Penners + + * AUTHORS + MAINTAINERS + configure.in + camlibs/sonydscf55/*: added camera library for Sony DSC-F55 + and Sony's Serial Port Adaptor MSAC-SR1 for the Sony DCR-PC100. + 2001-09-18 Chris Pinkham * camlibs/canon/psa50.c diff --git a/MAINTAINERS b/MAINTAINERS index aa73964e0..a6d22b8f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -47,6 +47,9 @@ camlibs/polaroid: camlibs/sierra: Scott Fritzinger +camlibs/sonydscf55: + Raymond Penners + Bug reports on sourceforge: Hubert Figuiere diff --git a/camlibs/sonydscf55/Makefile.am b/camlibs/sonydscf55/Makefile.am new file mode 100644 index 000000000..ddc0becf2 --- /dev/null +++ b/camlibs/sonydscf55/Makefile.am @@ -0,0 +1,13 @@ +camlibdir = $(prefix)/lib/gphoto2 +camlib_LTLIBRARIES = libgphoto2_sony_dscf55.la + +INCLUDES = -I$(top_srcdir)/include + +libgphoto2_sony_dscf55_la_SOURCES = \ + sony.c sony.h camera.c nls.h + +libgphoto2_sony_dscf55_la_LDFLAGS =\ + -avoid-version\ + -L$(shell pwd)/$(top_builddir)/libgphoto2/@dotlibs@ + +libgphoto2_sony_dscf55_la_LIBADD = -lgphoto2 diff --git a/camlibs/sonydscf55/TODO b/camlibs/sonydscf55/TODO new file mode 100644 index 000000000..7989b63b3 --- /dev/null +++ b/camlibs/sonydscf55/TODO @@ -0,0 +1,22 @@ +* The original 0.4 driver contained code for downloading MPEG files. +Unfortunately, that code did not work correctly when using an Sony +MSAC-SR1 in combination with memory sticks from a Sony DCR-PC100. In this +case, when the device is queried for a list of MPEG files it lists the +JPEG still images. For now, the MPEG code has been left out. + +* The driver has only been tested on a Sony MSAC-SR1 Serial Port +Adaptor with Sony DCR PC-100 memory sticks. Test it on a Sony DSC-F55. + +* Fix all FIXME's + +* Add calls to gp_frontend_status() + +* In cases where an error occurs during transfer, the driver can get +out of sync with the device. From that point on, the driver is unable +to successfully initialise the driver, even for new gPhoto sessions. A +reboot (power-off, power-on) of the MSAC-SR1 device helps. See if it +is possible to do a proper init in such a case. + +-- +Raymond Penners -*- raymond@dotsphinx.com -*- http://www.dotsphinx.com + diff --git a/camlibs/sonydscf55/camera.c b/camlibs/sonydscf55/camera.c new file mode 100644 index 000000000..fdf23884a --- /dev/null +++ b/camlibs/sonydscf55/camera.c @@ -0,0 +1,246 @@ +/* Sony DSC-F55 & MSAC-SR1 - gPhoto2 camera library + * Copyright (C) 2001 Raymond Penners + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include "sony.h" +#include "nls.h" + + +int camera_id(CameraText * id) +{ + strcpy(id->text, SONY_CAMERA_ID); + return (GP_OK); +} + +int camera_abilities(CameraAbilitiesList * list) +{ + static const char *models[] = { + "Sony DSC-F55", + SONY_MODEL_MSAC_SR1 + }; + int i; + + for (i = 0; i < sizeof(models) / sizeof(models[i]); i++) { + CameraAbilities *a; + + gp_abilities_new(&a); + strcpy(a->model, models[i]); + a->port = GP_PORT_SERIAL; + a->speed[0] = 0; + a->operations = GP_OPERATION_NONE; + a->file_operations = GP_FILE_OPERATION_PREVIEW; + a->folder_operations = GP_FOLDER_OPERATION_NONE; + gp_abilities_list_append(list, a); + } + + return (GP_OK); +} + +/** + * De-initialises camera + */ +int camera_exit(Camera * camera) +{ + int rc = GP_OK; + if (camera) { + SonyData *data = sony_data(camera); + if (data) { + if (data->dev) { + if (data->initialized) { + sony_exit(camera); + data->initialized = FALSE; + } + + rc = gp_port_free(data->dev); + if (rc == GP_OK) + data->dev = NULL; + } + if (rc == GP_OK && data->fs) { + rc = gp_filesystem_free(data->fs); + if (rc == GP_OK) + data->fs = NULL; + } + if (rc == GP_OK) { + free(data); + camera->camlib_data = NULL; + } + } + } + return rc; +} + + + +int camera_about(Camera * camera, CameraText * about) +{ + strcpy(about->text, + _("Sony DSC-F55/505 gPhoto library\n" + "Supports Sony MSAC-SR1 and Memory Stick used by DCR-PC100\n" + "Originally written by Mark Davies \n" + "gPhoto2 port by Raymond Penners ")); + + return (GP_OK); +} + +int +camera_folder_list_files(Camera * camera, const char *folder, + CameraList * list) +{ + int rc; + SonyData *b = (SonyData *) camera->camlib_data; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "camera_folder_list_files()"); + rc = sony_image_count(camera); + if (rc != GP_ERROR) { + int count, x; + + count = rc; + + /* Populate the filesystem */ + gp_filesystem_populate(b->fs, "/", SONY_FILE_NAME_FMT, + count); + for (x = 0; x < gp_filesystem_count(b->fs, folder); x++) + { + const char *name; + gp_filesystem_name(b->fs, folder, x, &name); + gp_list_append(list, name, NULL); + } + rc = GP_OK; + } + return rc; +} + +int +camera_file_get(Camera * camera, const char *folder, const char *filename, + CameraFileType type, CameraFile * file) +{ + int num; + int rc = GP_ERROR; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "camera_file_get(\"%s/%s\")", folder, filename); + num = + gp_filesystem_number(sony_data(camera)->fs, folder, filename); + if (num >= 0) { + num++; + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "file %s has id %d", filename, num); + + switch (type) { + case GP_FILE_TYPE_NORMAL: + rc = sony_image_get(camera, num, file); + break; + case GP_FILE_TYPE_PREVIEW: + rc = sony_thumbnail_get(camera, num, file); + break; + default: + rc = GP_ERROR_NOT_SUPPORTED; + } + + + if (rc == GP_OK) { + gp_file_set_name (file, filename); + } + } + return rc; +} + + + +int +camera_file_get_info(Camera * camera, const char *folder, + const char *filename, CameraFileInfo * info) +{ + int num, rc = GP_ERROR; + + num = + gp_filesystem_number(sony_data(camera)->fs, folder, filename); + if (num >= 0) { + num++; + rc = sony_image_info(camera, num, info); + } + return rc; +} + +/** + * Initialises camera + */ +int camera_init(Camera * camera) +{ + gp_port_settings settings; + int ret; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, "Initialising %s", + camera->model); + + camera->functions->exit = camera_exit; + camera->functions->about = camera_about; + camera->functions->folder_list_files = camera_folder_list_files; + camera->functions->file_get = camera_file_get; + camera->functions->file_get_info = camera_file_get_info; + + camera->camlib_data = NULL; + + camera->camlib_data = (SonyData *) malloc(sizeof(SonyData)); + if (camera->camlib_data) { + SonyData *b = sony_data(camera); + + b->sequence_id = 0; + b->dev = NULL; + b->fs = NULL; + b->initialized = FALSE; + + b->msac_sr1 = !strcmp(camera->model, SONY_MODEL_MSAC_SR1); + + if ((ret = gp_port_new(&(b->dev), GP_PORT_SERIAL)) >= 0) { + gp_port_timeout_set(b->dev, 5000); + strcpy(settings.serial.port, camera->port_info->path); + + settings.serial.speed = 9600; + settings.serial.bits = 8; + settings.serial.parity = 0; + settings.serial.stopbits = 1; + + gp_port_settings_set(b->dev, settings); + if (gp_port_open(b->dev) == GP_OK) { + /* Create the filesystem */ + if (gp_filesystem_new (&b->fs) == GP_OK) { + if (sony_init(camera) == GP_OK) { + return GP_OK; + } + } + } + + } + } + camera_exit(camera); + return (GP_ERROR); +} + +/* + * Local Variables: + * c-file-style:"linux" + * indent-tabs-mode:t + * End: + */ diff --git a/camlibs/sonydscf55/nls.h b/camlibs/sonydscf55/nls.h new file mode 100644 index 000000000..2d21eb944 --- /dev/null +++ b/camlibs/sonydscf55/nls.h @@ -0,0 +1,45 @@ +/* Sony DSC-F55 & MSAC-SR1 - gPhoto2 camera library + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef NLS_H +#define NLS_H + +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define _(String) (String) +# define N_(String) (String) +# endif +#else +# define _(String) (String) +# define N_(String) (String) +#endif + + +#endif /* NLS_H */ + +/* + * Local Variables: + * c-file-style:"linux" + * indent-tabs-mode:t + * End: + */ diff --git a/camlibs/sonydscf55/sony.c b/camlibs/sonydscf55/sony.c new file mode 100644 index 000000000..d3bb426f7 --- /dev/null +++ b/camlibs/sonydscf55/sony.c @@ -0,0 +1,709 @@ +/* Sony DSC-F55 & MSAC-SR1 - gPhoto2 camera library + * Copyright (C) 2001 Raymond Penners + * Copyright (C) 2000 Mark Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include "sony.h" + +/** + * Constants + */ +#define SONY_CONVERSE_RETRY 5 + +#define SONY_INVALID_CHECKSUM 0x40 +#define SONY_INVALID_SEQUENCE 0x41 +#define SONY_RESET_SEQUENCE 0x42 +#define SONY_RESEND_PACKET 0x43 + +#define SONY_ESCAPE_CHAR 0x7d +#define SONY_START_CHAR 0xc0 +#define SONY_END_CHAR 0xc1 + +static unsigned char START_PACKET = 192; +static unsigned char END_PACKET = 193; + +static char ESC_START_STRING[] = { 0x7d, 0xe0 }; +static char ESC_END_STRING[] = { 0x7d, 0xe1 }; +static char ESC_ESC_STRING[] = { 0x7d, 0x5d }; + +static unsigned char PacketCodes[2] = { 192, 193 }; + +Packet CameraInvalid = { 0, 2, {131, 125}, 93 }; +Packet ResendPacket = { 0, 4, {129, 2, '1', 0}, 'L' }; + + +#if defined(USE_ALL_TYPES) +static unsigned char EmailImage[] = + { 0, 2, 2, 0, 16, '/', 'M', 'S', 'S', 'O', 'N', 'Y', '/', 'I', 'M', +'C', + 'I', 'F', '1', '0', '0' +}; +#endif + + +static unsigned char IdentString[] = + { 0, 1, 1, 'S', 'O', 'N', 'Y', ' ', ' ', ' ', ' ', ' ' }; +static unsigned char EmptyPacket[] = { 0 }; /* null packet */ +static unsigned char SetTransferRate[] = { 0, 1, 3, 0 }; +static unsigned char SendImageCount[] = { 0, 2, 1 }; +static unsigned char StillImage[] = + { 0, 2, 2, 0, 14, '/', 'D', 'C', 'I', 'M', '/', '1', '0', '0', 'M', +'S', + 'D', 'C', 'F' +}; +static unsigned char MpegImage[] = + { 0, 2, 2, 0, 16, '/', 'M', 'S', 'S', 'O', 'N', 'Y', '/', 'M', 'O', +'M', + 'L', '0', '0', '0', '1' +}; +static unsigned char SelectImage[] = { 0, 2, 48, 0, 0, 0, 0 }; +static unsigned char SendImage[] = { 0, 2, '1', 0, 1, 0, 0 }; +static unsigned char SendNextImagePacket[] = { 0, 2, '1', 0 }; +static unsigned char SendThumbnail[] = { 0, 2, '0', 0 }; + +#if 0 +static unsigned char SelectCamera[] = { 0, 1, 2 }; +static unsigned char DownloadComplete[] = { 0, 2, '0', 255 }; +static unsigned char X10Camera[] = { 0, 1, 5 }; + +static unsigned char X5Camera[] = { 0, 2, 1 }; +static unsigned char X13Camera[] = { 0, 2, 18 }; + +#endif + + +/** + * This array contains the expected packet sequence code to to be applied/ + * checked for. + */ +static const unsigned char sony_sequence[] = + { 14, 0, 32, 34, 66, 68, 100, 102, 134, 136, 168, 170, 202, 204, 236, +238, + 255 +}; + + +#ifdef __linux__ +static const int baud_rate = 115200; +#else +# ifdef __sun__ +static const int baud_rate = 38400; +# else +static const int baud_rate = 9600; +# endif +#endif + + + + + +/** + * Returns transfer rate ID + */ +static int sony_baud_to_id(long baud) +{ + int r; + + switch (baud) { + case 115200: + r = 4; + break; + case 57600: + r = 3; + break; /* FIXME ??? */ + case 38400: + r = 2; + break; /* works on sun */ + case 19200: + r = 1; + break; /* works on sun */ + default: + case 9600: + r = 0; + break; /* works on sun */ + } + return r; +} + + +/** + * Reads a byte + */ +static int sony_read_byte(Camera * camera, unsigned char *b) +{ + int n = gp_port_read(sony_data(camera)->dev, b, 1); + if (n != 1) + return GP_ERROR; + else + return GP_OK; +} + + + +/** + * Returns the checksum for a packet + */ +static unsigned char sony_packet_checksum(Packet * p) +{ + unsigned short int o = 0; + unsigned long int sum = 0; + + sum = 0; + + while (o < p->length) + sum += p->buffer[o++]; + + return 256 - (sum & 255); +} + +/** + * Returns TRUE iff the packet is valid + */ +static int sony_packet_validate(Camera * camera, Packet * p) +{ + unsigned char c = sony_packet_checksum(p); + + if (c != p->checksum) { + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "sony_packet_validate: invalid checksum"); + return SONY_INVALID_CHECKSUM; + } + + if (129 == p->buffer[0]) { + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "sony_packet_validate: resend packet"); + return SONY_RESEND_PACKET; + } + + if (sony_sequence[sony_data(camera)->sequence_id] != p->buffer[0]) { + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "sony_packet_validate: invalid sequence"); + return SONY_INVALID_SEQUENCE; + } + + return GP_OK; +} + +/** + * Constructs a packet. + */ +static int +sony_packet_make(Camera * camera, Packet * p, unsigned char *buffer, + unsigned short int length) +{ + SonyData *data = sony_data(camera); + p->length = 0; + + while (length--) + p->buffer[p->length++] = *(buffer++); + + if (255 == sony_sequence[++(data->sequence_id)]) + data->sequence_id = 0; + + p->buffer[0] = sony_sequence[data->sequence_id++]; + + if (255 == sony_sequence[data->sequence_id]) + data->sequence_id = 0; + + p->checksum = sony_packet_checksum(p); + + return TRUE; +} + +/** + * Reads a packet. + */ +static int sony_packet_read(Camera * camera, Packet * pack) +{ + unsigned int n; + unsigned char byte = 0; + static Packet p; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "sony_packet_read()"); + p.length = 0; + + for (n = 0; n < 2; n++) { + for (byte = 0; byte != (unsigned char) PacketCodes[n];) { + if (sony_read_byte(camera, &byte) == GP_ERROR) { + return FALSE; + } + + if (n > 0) { + if (SONY_ESCAPE_CHAR == byte) { + unsigned char extra; + + sony_read_byte(camera, &extra); + + switch (extra) { + case 1: + case 7: + case 0xe1: + case 0xe0: + extra &= 0xcf; + p.buffer[p.length++] = + extra; + continue; + case 0x5d: + p.buffer[p.length++] = + byte; + continue; + default: + p.buffer[p.length++] = + byte; + p.buffer[p.length++] = + extra; + continue; + } + } else + p.buffer[p.length++] = byte; + } + } + } + + p.length -= 2; + p.checksum = p.buffer[p.length]; + + memcpy(pack, &p, sizeof(Packet)); + return TRUE; +} + +/** + * Sends a packet + */ +static int sony_packet_write(Camera * camera, Packet * p) +{ + unsigned short int count; + SonyData *data; + int rc; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "sony_packet_write()"); + data = sony_data(camera); + + rc = gp_port_write(data->dev, &START_PACKET, 1); + + p->buffer[p->length] = p->checksum; + + for (count = 0; count < p->length + 1 && rc != GP_ERROR; count++) { + switch ((unsigned char) p->buffer[count]) { + case SONY_ESCAPE_CHAR: + rc = gp_port_write(data->dev, ESC_ESC_STRING, 2); + break; + + case SONY_START_CHAR: + rc = gp_port_write(data->dev, ESC_START_STRING, 2); + break; + + case SONY_END_CHAR: + rc = gp_port_write(data->dev, ESC_END_STRING, 2); + break; + + default: + rc = gp_port_write(data->dev, + (char *) &p->buffer[count], 1); + break; + } + } + if (rc != GP_ERROR) + rc = gp_port_write(data->dev, (char *) &END_PACKET, 1); + return rc; +} + +/** + * Communicates packets + */ +static int +sony_converse(Camera * camera, Packet * out, unsigned char *str, int len) +{ + Packet ps; + char old_sequence = 33; + int sequence_count = 0; + int invalid_sequence = 0; + int count; + SonyData *data = sony_data(camera); + int rc; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, "sony_converse()"); + sony_packet_make(camera, &ps, str, len); + + for (count = 0; count < SONY_CONVERSE_RETRY; count++) { + rc = sony_packet_write(camera, &ps); + + if (rc == GP_OK) { + if (sony_packet_read(camera, out)) { + switch (sony_packet_validate(camera, out)) { + case SONY_INVALID_CHECKSUM: + if (invalid_sequence) { + sony_packet_make(camera, + &ps, str, + len); + break; + } + + gp_debug_printf(GP_DEBUG_LOW, + SONY_CAMERA_ID, + "Checksum invalid"); + ps.buffer[0] = 129; + ps.checksum = + sony_packet_checksum(&ps); + break; + + case SONY_INVALID_SEQUENCE: + if (sony_data(camera)->msac_sr1) { + invalid_sequence = 1; + sony_packet_make(camera, + &ps, str, + len); + break; + } + + if (old_sequence == out->buffer[0]) + sequence_count++; + else if (0 == sequence_count) + old_sequence = + out->buffer[0]; + + if (sequence_count == 4) { + gp_debug_printf + (GP_DEBUG_LOW, + SONY_CAMERA_ID, + "Attempting to reset sequence id - image may be corrupt."); + data->sequence_id = 0; + + while (sony_sequence + [data-> + sequence_id] != + old_sequence) + data-> + sequence_id++; + + return GP_OK; + } + + gp_debug_printf(GP_DEBUG_LOW, + SONY_CAMERA_ID, + "Invalid Sequence"); + ps.buffer[0] = 129; + ps.checksum = + sony_packet_checksum(&ps); + break; + + case SONY_RESET_SEQUENCE: + data->sequence_id = 0; + return GP_OK; + + case SONY_RESEND_PACKET: + gp_debug_printf(GP_DEBUG_LOW, + SONY_CAMERA_ID, + "Resending Packet"); + break; + + case GP_OK: + return GP_OK; + + default: + gp_debug_printf(GP_DEBUG_LOW, + SONY_CAMERA_ID, + "Unknown Error"); + break; + } + } else { + /* printf("Incomplete packet\n"); */ + ps.buffer[0] = 129; + ps.checksum = sony_packet_checksum(&ps); + } + } + } + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "Failed to read packet during transfer."); + + return GP_ERROR; +} + + +/** + * Sets baud rate + */ +static int sony_baud_port_set(Camera * camera, long baud) +{ + gp_port *dev; + gp_port_settings settings; + + dev = sony_data(camera)->dev; + + gp_port_settings_get(dev, &settings); + settings.serial.speed = baud; + gp_port_settings_set(dev, settings); + + usleep(70000); + + return GP_OK; +} + +/** + * Sets baud rate + */ +static int sony_baud_set(Camera * camera, long baud) +{ + Packet dp; + int rc; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, "sony_baud_set(%ld)", + baud); + // FIXME + SetTransferRate[3] = sony_baud_to_id(baud); + + rc = sony_converse(camera, &dp, SetTransferRate, 4); + if (rc == GP_OK) { + sony_baud_port_set(camera, baud); + rc = sony_converse(camera, &dp, EmptyPacket, 1); + usleep(100000); /* 50000 was good too, jw */ + } + return rc; +} + +/** + * Initialises camera + */ +int sony_init(Camera * camera) +{ + int count = 0; + Packet dp; + SonyData *data = sony_data(camera); + + gp_port_flush(data->dev, 0); + + for (count = 0; count < 3; count++) { + data->sequence_id = 0; + + if (sony_converse(camera, &dp, IdentString, 12) == GP_OK) { + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "Init OK"); + data->initialized = TRUE; + return GP_OK; + } + usleep(2000); + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, + "Init - Fail %u", count + 1); + } + return GP_ERROR; +} + +/** + * Reset the camera sequence count and baud rate. + */ +int sony_exit(Camera * camera) +{ + Packet dp; + SonyData *data = sony_data(camera); + int rc; + + rc = sony_baud_set(camera, 9600); + while (rc == GP_OK && data->sequence_id > 0) { + rc = sony_converse(camera, &dp, EmptyPacket, 1); + } + return rc; +} + +/** + * Return count of images taken. + */ +static int +sony_item_count(Camera * camera, unsigned char *from, int from_len) +{ + Packet dp; + int rc; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, "sony_item_count()"); + rc = sony_converse(camera, &dp, SetTransferRate, 4); + if (rc == GP_OK) { + rc = sony_converse(camera, &dp, from, from_len); + if (rc == GP_OK) { + rc = sony_converse(camera, &dp, SendImageCount, 3); + if (rc == GP_OK) { + int nr = (int) dp.buffer[5]; + gp_debug_printf(GP_DEBUG_LOW, + SONY_CAMERA_ID, + "count = %d", nr); + return nr; + } + } + } + return GP_ERROR; +} + + +/** + * Returns number of still images + */ +int sony_image_count(Camera * camera) +{ + return sony_item_count(camera, StillImage, sizeof(StillImage)); +} + + +/** + * Returns number of still images + */ +int sony_mpeg_count(Camera * camera) +{ + return sony_item_count(camera, MpegImage, sizeof(MpegImage)); +} + + +/** + * Fetches an image. + */ +static int +sony_file_get(Camera * camera, int imageid, int thumbnail, + CameraFile * file) +{ + int sc; /* count of bytes to skip at start of packet */ + Packet dp; + int rc; + + gp_debug_printf(GP_DEBUG_LOW, SONY_CAMERA_ID, "sony_file_get()"); + rc = gp_file_clean(file); + if (rc == GP_OK) { + gp_file_set_mime_type (file, GP_MIME_JPEG); + // FIXME: There appears to be a file name at dp.buffer+5 + // after a SelectImage. We could use that for the real + // file name instead of our own mockup ("dsc%d.jpg"). + sprintf(file->name, SONY_FILE_NAME_FMT, imageid); + + sony_baud_set(camera, baud_rate); + + rc = sony_converse(camera, &dp, StillImage, 19); + if (rc == GP_OK) { + if (thumbnail) { + sc = 0x247; + + // FIXME + SelectImage[4] = imageid; + sony_converse(camera, &dp, SelectImage, 7); + + gp_debug_printf(GP_DEBUG_LOW, + SONY_CAMERA_ID, + "XYZ %11.11s", + dp.buffer + 5); + + if (sony_data(camera)->msac_sr1) { + gp_file_append(file, + "\xff\xd8\xff", 3); + } + + for (;;) { + sony_converse(camera, &dp, + SendThumbnail, 4); + + gp_file_append(file, + (char *) dp.buffer + + sc, dp.length - sc); + sc = 7; + + if (3 == dp.buffer[4]) + break; + } + } else { + sc = 11; + + // FIXME + SendImage[4] = imageid; + sony_converse(camera, &dp, SendImage, 7); + + for (;;) { + gp_file_append(file, + (char *) dp.buffer + + sc, dp.length - sc); + sc = 7; + + if (3 == dp.buffer[4]) + break; + + sony_converse(camera, &dp, + SendNextImagePacket, + 4); + } + } + } + sony_baud_set(camera, 9600); + + if (rc != GP_OK) { + gp_file_clean(file); + } + } + return rc; +} + +/** + * Fetches an image. + */ +int sony_thumbnail_get(Camera * camera, int imageid, CameraFile * file) +{ + return sony_file_get(camera, imageid, TRUE, file); +} + +/** + * Fetches an image. + */ +int sony_image_get(Camera * camera, int imageid, CameraFile * file) +{ + return sony_file_get(camera, imageid, FALSE, file); +} + + +/** + * Fetches image details. + */ +int sony_image_info(Camera * camera, int imageid, CameraFileInfo * info) +{ + unsigned int l = 0; + int rc; + Packet dp; + + // FIXME + SelectImage[4] = imageid; + rc = sony_converse(camera, &dp, SelectImage, 7); + if (rc == GP_OK) { + l = (l << 8) | dp.buffer[16]; + l = (l << 8) | dp.buffer[17]; + l = (l << 8) | dp.buffer[18]; + l = (l << 8) | dp.buffer[19]; + + info->file.fields = GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE; + info->file.size = l; + strcpy (info->file.type, GP_MIME_JPEG); + + info->preview.fields = 0; + } + return rc; +} + + + +/* + * Local Variables: + * c-file-style:"linux" + * indent-tabs-mode:t + * End: + */ diff --git a/camlibs/sonydscf55/sony.h b/camlibs/sonydscf55/sony.h new file mode 100644 index 000000000..22e9bde4a --- /dev/null +++ b/camlibs/sonydscf55/sony.h @@ -0,0 +1,61 @@ +/* Sony DSC-F55 & MSAC-SR1 - gPhoto2 camera library + * Copyright (C) 2000 Mark Davies + * Copyright (C) 2001 Raymond Penners + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef SONY_H +#define SONY_H + +#define SONY_CAMERA_ID "sonydscf55" +#define SONY_MODEL_MSAC_SR1 "Sony MSAC-SR1" + +#define SONY_FILE_NAME_FMT "dsc%05d.jpg" + +typedef struct _tagPacket { + int valid; + int length; + unsigned char buffer[16384]; + unsigned char checksum; +} Packet; + +typedef struct { + gp_port *dev; + CameraFilesystem *fs; + + unsigned short int sequence_id; + int msac_sr1; + int initialized; +} SonyData; + +int sony_init(Camera * camera); +int sony_exit(Camera * camera); +int sony_image_count(Camera * camera); +int sony_mpeg_count(Camera * camera); +int sony_image_get(Camera * camera, int imageid, CameraFile * file); +int sony_thumbnail_get(Camera * camera, int imageid, CameraFile * file); +int sony_image_info(Camera * camera, int imageid, CameraFileInfo * info); + +#define sony_data(c) ((SonyData *)((c)->camlib_data)) + +#endif /* SONY_H */ + +/* + * Local Variables: + * c-file-style:"linux" + * indent-tabs-mode:t + * End: + */ diff --git a/configure.in b/configure.in index c097ddd2a..1aec11a58 100644 --- a/configure.in +++ b/configure.in @@ -90,7 +90,7 @@ AC_SUBST(dotlibs) dnl Find out which drivers to compile -camlibs='agfa-cl18 barbie canon casio dimera directory sierra jamcam konica panasonic polaroid digita kodak minolta samsung stv0680 sonydscf1' +camlibs='agfa-cl18 barbie canon casio dimera directory sierra jamcam konica panasonic polaroid digita kodak minolta samsung stv0680 sonydscf1 sonydscf55' AC_SUBST(SUBDIRS_CAMLIBS) for i in $camlibs; do d=`echo $i | $TR a-z A-Z` @@ -105,7 +105,7 @@ AC_ARG_WITH(drivers, [ agfa-cl18, barbie, canon, casio, digita, dimera,] [ directory, jamcam, kodak, konica, minolta,] [ panasonic, polaroid, samsung, sierra, sonydscf1,] - [ stv0680 ], + [ sonydscf55, stv0680 ], drivers="$withval", drivers="all") if test "$drivers" = "all"; then for i in $camlibs; do @@ -187,6 +187,7 @@ camlibs/polaroid/Makefile camlibs/samsung/Makefile camlibs/sierra/Makefile camlibs/sonydscf1/Makefile +camlibs/sonydscf55/Makefile camlibs/stv0680/Makefile frontends/Makefile frontends/command-line/Makefile