* Initial import of camlib driver from

Vincent Sanders <vince@kyllikki.org>


git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@5906 67ed7778-7388-44ab-90cf-0a291f65f57c
This commit is contained in:
Marcus Meissner
2002-12-03 08:02:50 +00:00
parent 9eeded73c0
commit 77a2ceff4b
8 changed files with 733 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
Makefile.in
Makefile
*.lo
*.la
.deps
.libs

View File

@@ -0,0 +1,4 @@
2002-12-03 Marcus Meissner <marcus@jet.franken.de>
* Initial import of camlib driver written by
Vincent Sanders <vince@kyllikki.org>

View File

@@ -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

154
camlibs/stv0674/Protocol Normal file
View File

@@ -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

225
camlibs/stv0674/library.c Normal file
View File

@@ -0,0 +1,225 @@
/*
* STV0674 Vision Camera Chipset Driver
* Copyright (C) 2000 Adam Harrison <adam@antispin.org>
*
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gphoto2.h>
#include <gphoto2-port.h>
#include "stv0674.h"
#include "library.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
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<whole;current+=1)
{
ret = gp_port_usb_msg_write (port,
CMDID_READ_IMAGE,
READ_IMAGE_VALUE_READ,
0,
imagno,
8);
if (ret < GP_OK)
return ret;
gp_port_read(port, &data[current*0x1000], 0x1000);
}
if(remain)
{
setval(&imagno[4],remain);/* we want remaining bytes */
ret = gp_port_usb_msg_write (port,
CMDID_READ_IMAGE,
READ_IMAGE_VALUE_READ,
0,
imagno,
8);
if (ret < GP_OK)
return ret;
gp_port_read(port, &data[current*0x1000], remain);
}
gp_file_append(file, data, size);
free(data);
ret = gp_port_usb_msg_write (port, CMDID_FINISH_READ, 0, 0, imagno, 4);
if (ret < GP_OK)
return ret;
return GP_OK;
}
int stv0674_get_image_preview(GPPort *port, int image_no, CameraFile *file)
{
return GP_OK;
}
int stv0674_capture(GPPort *port)
{
return GP_OK;
}
int stv0674_capture_preview(GPPort *port, char **data, int *size)
{
return GP_OK;
}
int stv0674_delete_all(GPPort *port) {
/* return stv0674_try_cmd(port,CMDID_SET_IMAGE_INDEX,0,NULL,0);*/
return GP_OK;
}
int stv0674_summary(GPPort *port, char *txt)
{
return GP_OK;
}

36
camlibs/stv0674/library.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* STV0674 Vision Camera Chipset Driver
* Copyright (C) 2002 Vincent Sanders <vince@kyllikki.org>
*
* 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 <gphoto2-port.h>
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

261
camlibs/stv0674/stv0674.c Normal file
View File

@@ -0,0 +1,261 @@
/*
* STV0674 Camera Chipset Driver
* Copyright (C) 2002 Vincent Sanders <vince@kyllikki.org>
*
* 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <gphoto2.h>
#include <gphoto2-port.h>
#include <gphoto2-library.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
#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 <vince@kyllikki.org>\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);
}

36
camlibs/stv0674/stv0674.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* STV0674 Camera Chipset Driver
* Copyright (C) 2000 Vince Sanders <vince@kyllikki.org>
*
* 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