From 77a2ceff4bf51422ff019fdcd3732e107fcd500d Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Tue, 3 Dec 2002 08:02:50 +0000 Subject: [PATCH] * Initial import of camlib driver from Vincent Sanders git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@5906 67ed7778-7388-44ab-90cf-0a291f65f57c --- camlibs/stv0674/.cvsignore | 7 + camlibs/stv0674/Changelog | 4 + camlibs/stv0674/Makefile.am | 10 ++ camlibs/stv0674/Protocol | 154 +++++++++++++++++++++ camlibs/stv0674/library.c | 225 +++++++++++++++++++++++++++++++ camlibs/stv0674/library.h | 36 +++++ camlibs/stv0674/stv0674.c | 261 ++++++++++++++++++++++++++++++++++++ camlibs/stv0674/stv0674.h | 36 +++++ 8 files changed, 733 insertions(+) create mode 100644 camlibs/stv0674/.cvsignore create mode 100644 camlibs/stv0674/Changelog create mode 100644 camlibs/stv0674/Makefile.am create mode 100644 camlibs/stv0674/Protocol create mode 100644 camlibs/stv0674/library.c create mode 100644 camlibs/stv0674/library.h create mode 100644 camlibs/stv0674/stv0674.c create mode 100644 camlibs/stv0674/stv0674.h diff --git a/camlibs/stv0674/.cvsignore b/camlibs/stv0674/.cvsignore new file mode 100644 index 000000000..bbd255484 --- /dev/null +++ b/camlibs/stv0674/.cvsignore @@ -0,0 +1,7 @@ +Makefile.in +Makefile +*.lo +*.la +.deps +.libs + diff --git a/camlibs/stv0674/Changelog b/camlibs/stv0674/Changelog new file mode 100644 index 000000000..14fa7f69d --- /dev/null +++ b/camlibs/stv0674/Changelog @@ -0,0 +1,4 @@ +2002-12-03 Marcus Meissner + + * Initial import of camlib driver written by + Vincent Sanders diff --git a/camlibs/stv0674/Makefile.am b/camlibs/stv0674/Makefile.am new file mode 100644 index 000000000..9fcf2cfa9 --- /dev/null +++ b/camlibs/stv0674/Makefile.am @@ -0,0 +1,10 @@ +camlib_LTLIBRARIES = libgphoto2_stv0674.la + +INCLUDES = \ + -I$(top_srcdir)/intl \ + -I$(top_srcdir)/libgphoto2_port/libgphoto2_port \ + -I$(top_srcdir)/libgphoto2 + +libgphoto2_stv0674_la_SOURCES = stv0674.c library.c +libgphoto2_stv0674_la_LDFLAGS = -module -avoid-version +libgphoto2_stv0674_la_LIBADD = $(top_builddir)/libgphoto2/libgphoto2.la diff --git a/camlibs/stv0674/Protocol b/camlibs/stv0674/Protocol new file mode 100644 index 000000000..faa157c12 --- /dev/null +++ b/camlibs/stv0674/Protocol @@ -0,0 +1,154 @@ +This is a quick and dirty reverse engineer of the ST microelectronics STV0674 +*NOTE* this is *not* the STV0680 that is a completely separate device! + +the current web page for this device is +http://www.vvl.co.uk/products/co-processors/674/674.htm + +As is becoming increasingly more common the chip vendors are being +right pains in the bum and forcing me to reverse engineer their +protocols from snoops rather than giving me the data sheet. If your in +a position to get the datasheet for this product please please do +improve this driver! + +So far this driver has only been tested on a l'espion xtra other +cameras may need more tweaks. + +The device has a single interface with several alternate configs, +alternate 1 has 3 endpoints :bulk in, bulk out and an interrupt. + +The driver selects alternate one and uses the bulk in endpoint for +data. Several control transactions are used to control the data +available on the bulk in pipe. + + +Most transactions are associated with an image number this is a 4 +byte MSB value which appears to start at *2* ie the first image is 00 +00 00 02. + +The image "header" is a block of data which is not associated with the +jpeg data at all but contains several pieces of information, some +important bits are: + + - image length (bytes 0x47(MSB) and 0x48) + - x size (0x49 (MSB) 0x4a) + - y size (0x4b (MSB) 0x4c + + +Control transactions +-------------------- + +Ping +---- +I assume this transaction is a "ping" as the windows driver seems to +perform this transaction like a nervous twitch, its done all over for +no good reason I can see, always with the same result + +The host reads a control transaction with 1 byte URB +bRequest = 0x80 +wValue=0x0000 +wIndex=0x0000 +wLength=0x0001 + +the returned URB: +byte 0 is always 0x00 + +Get header +---------- +This obtains a block of data which contains the image "header" + +The host writes a control transaction with 6 byte buffer + +bRequest = 0x0A +wValue=0x0000 +wIndex=0x0000 +wLength=0x0006 + +the data buffer has: +bytes 0-3 are image number +bytes 4-5 are length (MSB) this is always 0x56 in the doze driver + +the client may then read the "length" bytes from the bulk in pipe + +Set Image Number +---------------- +I believe this is used to select the image for some transactions that +don't explicitly set the image number themselves +This and the following are done immediately before each image download + +The host writes a control transaction with 4 byte buffer + +bRequest = 0x03 +wValue=0x0000 +wIndex=0x0000 +wLength=0x0004 + +the data buffer has: +bytes 0-3 are image number + +Unknown +------- +This *always* follows the above + +The host reads a control transaction with 2 byte buffer +bRequest = 0x86 +wValue=0x0000 +wIndex=0x0000 +wLength=0x0004 + +the data buffer has: +byte 0 is always 0x03 +byte 0 is always 0x01 + +Image header read +----------------- +This is performed before each image is read, its just a repeat of the +header obtained with the other request but its useful here for getting +the image size, the doze driver always does it here and if you don't it +breaks ;-) + +The host writes a control transaction with 8 byte buffer + +bRequest = 0x05 +wValue=0x00ff +wIndex=0x0000 +wLength=0x0008 + +the written URB contains: +bytes 0-3 are image number +bytes 4-7 are the length of data to read (always 0x200 for the header read) + +0x200 bytes are then read from the bulk in pipe, this seems to be an +extended header? + +Image read +---------- +This is identical to the image header read above except the wValue has +changed from 0xff to 0x08. The windows driver writes a series of these +commands asking for 0x1000 bytes of data a time, larger seems to +fail... so reading blocks of 0x1000 and a fragment of smaller seems to +be the best way to go. + +The host writes a control transaction with 8 byte buffer + +bRequest = 0x05 +wValue=0x0008 +wIndex=0x0000 +wLength=0x0008 + +the written URB contains: +bytes 0-3 are image number +bytes 4-7 are the length of data to read (0x1000 or less) + +read close +---------- +This transaction is performed at the end of the image read. + +The host writes a control transaction with 4 byte buffer + +bRequest = 0x09 +wValue=0x0000 +wIndex=0x0000 +wLength=0x0004 + +the data buffer has: +bytes 0-3 are image number diff --git a/camlibs/stv0674/library.c b/camlibs/stv0674/library.c new file mode 100644 index 000000000..2d7fca9b9 --- /dev/null +++ b/camlibs/stv0674/library.c @@ -0,0 +1,225 @@ +/* + * STV0674 Vision Camera Chipset Driver + * Copyright (C) 2000 Adam Harrison + * + * 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 + */ + +#include "config.h" + +#include +#include +#include + +#include +#include + +#include "stv0674.h" +#include "library.h" + +#ifdef ENABLE_NLS +# include +# 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 + + +int stv0674_ping(GPPort *port) +{ + int ret; + unsigned char reply[4]; + + ret = gp_port_usb_msg_read (port, CMDID_PING, 0, 0, reply, 1); + if (ret < GP_OK) + return ret; + + if(reply[0] != 0) + { + printf("CMDID_PING successful, but returned bad values?\n"); + return GP_ERROR_IO; + } + + return GP_OK; + +} + +int stv0674_file_count(GPPort *port, int *count) +{ + int ret; + unsigned char reply[4]; + + ret = gp_port_usb_msg_read (port, CMDID_ENUMERATE_IMAGES, 0, 0, reply, 4); + if (ret < GP_OK) + return ret; + + + *count= ((reply[3]) | (reply[2]<<8) | (reply[1]<<16) | (reply[0]<<24)); + + return GP_OK; +} + +/** + * Get image + */ +int stv0674_get_image_raw(GPPort *port, int image_no, CameraFile *file) +{ + return GP_OK; +} + +static int setval(unsigned char* where,unsigned long val) +{ + where[3]=(val & 0xff); + where[2]=((val >> 8) & 0xff); + where[1]=((val >> 16) & 0xff); + where[0]=((val >> 24) & 0xff); + return 0; +} + + +int stv0674_get_image(GPPort *port, int image_no, CameraFile *file) +{ + unsigned char header[0x200];/*block for header */ + int x,y,size; + + int whole,remain; + + int current; + + int ret; + unsigned char imagno[8]; + unsigned char reply[4]; + unsigned char * data; + + memset(imagno,0,8); + + image_no+=2; + + setval(imagno,image_no); + + + ret = gp_port_usb_msg_write (port, CMDID_SET_IMAGE, 0, 0, imagno, 4); + if (ret < GP_OK) + return ret; + + ret = gp_port_usb_msg_read (port, CMDID_IHAVENOIDEA, 0, 0, reply, 2); + if (ret < GP_OK) + return ret; + + setval(&imagno[4],0x200);/* we want 512 bytes */ + + ret = gp_port_usb_msg_write (port, + CMDID_READ_IMAGE, + READ_IMAGE_VALUE_RESET, + 0, + imagno, + 8); + if (ret < GP_OK) + return ret; + + gp_port_read(port, header, 0x200); + + size=(header[0x47]<<8) | header[0x48]; + + x=(header[0x49]<<8) | header[0x4a]; + y=(header[0x4b]<<8) | header[0x4c]; + + /*create data block */ + data=malloc(size); + if (!data) + return GP_ERROR_NO_MEMORY; + + setval(&imagno[4],0x1000);/* we want 4096 bytes */ + + whole=size / 0x1000; + remain=size % 0x1000; + + + for(current=0;current + * + * 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 + */ + +#ifndef LIBRARY_H +#define LIBRARY_H + +#include + +int stv0674_ping (GPPort *); +int stv0674_summary (GPPort *, char*); +int stv0674_file_count (GPPort *, int *count); +int stv0674_get_image (GPPort *, int image_no, CameraFile *file); +int stv0674_get_image_raw (GPPort *, int image_no, CameraFile *file); +int stv0674_get_image_preview (GPPort *, int image_no, CameraFile *file); + +int stv0674_capture_preview (GPPort *device, char **data, int *size); +int stv0674_capture (GPPort *port); +int stv0674_delete_all (GPPort *port); + +#endif diff --git a/camlibs/stv0674/stv0674.c b/camlibs/stv0674/stv0674.c new file mode 100644 index 000000000..606c882ae --- /dev/null +++ b/camlibs/stv0674/stv0674.c @@ -0,0 +1,261 @@ +/* + * STV0674 Camera Chipset Driver + * Copyright (C) 2002 Vincent Sanders + * + * 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 + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_NLS +# include +# 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 + +#include "stv0674.h" +#include "library.h" + +#define GP_MODULE "stv0674" + +struct camera_to_usb { + char *name; + unsigned short idVendor; + unsigned short idProduct; +} camera_to_usb[] = { + /* http://www.digitaldreamco.com/shop/xtra.htm, SVGA */ + { "l'espion xtra by DigitalDream", 0x05DA, 0x1020 } + +}; + +int camera_id (CameraText *id) +{ + strcpy(id->text, "STV0674"); + + return (GP_OK); +} + +int camera_abilities (CameraAbilitiesList *list) +{ + CameraAbilities a; + unsigned int i; + + for(i = 0; + i < (sizeof(camera_to_usb) / sizeof(struct camera_to_usb)); + i++) + { + + memset(&a, 0, sizeof(a)); + strcpy(a.model, camera_to_usb[i].name); + + a.port = GP_PORT_USB; + a.status = GP_DRIVER_STATUS_EXPERIMENTAL; + a.operations = GP_OPERATION_CAPTURE_IMAGE | + GP_OPERATION_CAPTURE_PREVIEW; + a.file_operations = GP_FILE_OPERATION_PREVIEW; + a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL; + + a.usb_vendor = camera_to_usb[i].idVendor; + a.usb_product = camera_to_usb[i].idProduct; + + gp_abilities_list_append(list, a); + } + + return (GP_OK); +} + + +static int file_list_func (CameraFilesystem *fs, const char *folder, + CameraList *list, void *data, GPContext *context) +{ + Camera *camera = data; + int count, result; + + + result = stv0674_file_count(camera->port, &count); + if (result < GP_OK) + { + GP_DEBUG("file count returnd %d\n",result); + return result; + } + + GP_DEBUG("count is %x\n",count); + + gp_list_populate(list, "image%03i.jpg", count); + + return (GP_OK); +} + + + +static int get_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, CameraFileType type, + CameraFile *file, void *user_data, GPContext *context) +{ + Camera *camera = user_data; + int image_no, result; + + image_no = gp_filesystem_number(camera->fs, folder, filename, context); + if(image_no < 0) + return image_no; + + gp_file_set_name (file, filename); + gp_file_set_mime_type (file, GP_MIME_JPEG); + switch (type) { + case GP_FILE_TYPE_NORMAL: + result = stv0674_get_image (camera->port, image_no, file); + break; + case GP_FILE_TYPE_RAW: + result = stv0674_get_image_raw (camera->port, image_no, file); + break; + case GP_FILE_TYPE_PREVIEW: + result = stv0674_get_image_preview (camera->port, image_no, file); + break; + default: + return (GP_ERROR_NOT_SUPPORTED); + } + return result; +} + +static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) +{ + int result; + int count,oldcount; + + if (type != GP_CAPTURE_IMAGE) + return (GP_ERROR_NOT_SUPPORTED); + result = stv0674_file_count(camera->port,&oldcount); + + result = stv0674_capture(camera->port); + if (result < 0) + return result; + + /* Just added a new picture... */ + result = stv0674_file_count(camera->port,&count); + if (count == oldcount) + return GP_ERROR; /* unclear what went wrong ... hmm */ + strcpy(path->folder,"/"); + sprintf(path->name,"image%03i.jpg",count); + + /* Tell the filesystem about it */ + result = gp_filesystem_append (camera->fs, path->folder, path->name, + context); + if (result < 0) + return (result); + + return (GP_OK); +} + +static int camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) +{ + char *data; + int size, result; + + result = stv0674_capture_preview (camera->port, &data, &size); + if (result < 0) + return result; + + gp_file_set_name (file, "capture.jpg"); + gp_file_set_mime_type (file, GP_MIME_JPEG); + gp_file_set_data_and_size (file, data, size); + + return (GP_OK); +} + +static int camera_summary (Camera *camera, CameraText *summary, GPContext *context) +{ + stv0674_summary(camera->port,summary->text); + return (GP_OK); +} + +static int camera_about (Camera *camera, CameraText *about, GPContext *context) +{ + strcpy (about->text, + _("STV0674\n" + "Vincent Sanders \n" + "Driver for cameras using the STV0674 processor ASIC.\n" + "Protocol reverse engineered using SnoopyPro\n")); + + return (GP_OK); +} + +static int +delete_all_func (CameraFilesystem *fs, const char* folder, void *data, + GPContext *context) +{ + Camera *camera = data; + if (strcmp (folder, "/")) + return (GP_ERROR_DIRECTORY_NOT_FOUND); + return stv0674_delete_all(camera->port); +} + +int camera_init (Camera *camera, GPContext *context) +{ + GPPortSettings settings; + int ret; + + /* First, set up all the function pointers */ + camera->functions->summary = camera_summary; + camera->functions->about = camera_about; + camera->functions->capture_preview = camera_capture_preview; + camera->functions->capture = camera_capture; + + gp_port_get_settings(camera->port, &settings); + switch(camera->port->type) { + case GP_PORT_USB: + /* Modify the default settings the core parsed */ + settings.usb.altsetting=1;/* we need to use interface 0 setting 1 */ + settings.usb.inep=2; + settings.usb.intep=3; + settings.usb.outep=5; + + /* Use the defaults the core parsed */ + break; + default: + return (GP_ERROR_UNKNOWN_PORT); + break; + } + + ret = gp_port_set_settings (camera->port, settings); + if (ret != GP_OK) { + gp_context_error (context, _("Could not apply USB settings")); + return ret; + } + + /* Set up the filesystem */ + gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL, camera); + gp_filesystem_set_file_funcs (camera->fs, get_file_func, NULL, camera); + + gp_filesystem_set_folder_funcs (camera->fs, NULL, delete_all_func, NULL, NULL, camera); + + /* test camera */ + ret = stv0674_ping(camera->port); + return (ret); +} diff --git a/camlibs/stv0674/stv0674.h b/camlibs/stv0674/stv0674.h new file mode 100644 index 000000000..afa48a226 --- /dev/null +++ b/camlibs/stv0674/stv0674.h @@ -0,0 +1,36 @@ +/* + * STV0674 Camera Chipset Driver + * Copyright (C) 2000 Vince Sanders + * + * 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 + */ + +#ifndef STV0674_H +#define STV0674_H + +#define CMDID_SET_IMAGE 0x3 +#define CMDID_READ_IMAGE 0x5 +#define READ_IMAGE_VALUE_RESET 0xff +#define READ_IMAGE_VALUE_READ 0x08 + +#define CMDID_FINISH_READ 0x9 + +#define CMDID_PING 0x80 + +#define CMDID_ENUMERATE_IMAGES 0x83 + +#define CMDID_IHAVENOIDEA 0x86 + +#endif