diff options
author | Peter Kajberg <pbk@odense.kollegienet.dk> | 2002-08-14 00:46:30 +0000 |
---|---|---|
committer | Peter Kajberg <pbk@odense.kollegienet.dk> | 2002-08-14 00:46:30 +0000 |
commit | 3eab8c56b1aafa201204f704f89077648ca60748 (patch) | |
tree | deaad188d57449afbf9e7de9ebd039b59891bd6b /camlibs | |
parent | d208ed8fcd4a1e9013c7e021fd2fd859a321de45 (diff) | |
download | libgphoto2-3eab8c56b1aafa201204f704f89077648ca60748.tar.gz |
Import of the new pccam600 driver
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@5007 67ed7778-7388-44ab-90cf-0a291f65f57c
Diffstat (limited to 'camlibs')
-rw-r--r-- | camlibs/pccam600/ChangeLog | 8 | ||||
-rw-r--r-- | camlibs/pccam600/Makefile.am | 10 | ||||
-rw-r--r-- | camlibs/pccam600/README | 6 | ||||
-rw-r--r-- | camlibs/pccam600/library.c | 321 | ||||
-rw-r--r-- | camlibs/pccam600/pccam600.c | 233 | ||||
-rw-r--r-- | camlibs/pccam600/pccam600.h | 46 |
6 files changed, 624 insertions, 0 deletions
diff --git a/camlibs/pccam600/ChangeLog b/camlibs/pccam600/ChangeLog new file mode 100644 index 000000000..e4f4ce51d --- /dev/null +++ b/camlibs/pccam600/ChangeLog @@ -0,0 +1,8 @@ +This software is based upon usbsniffing, and therefore is +marked EXPERIMENTAL. + +Any comments email me at pbk@odense.kollegienet.dk + +09/08-2002 + Først release of the library. + As this is the first release there might be errors, please report them. diff --git a/camlibs/pccam600/Makefile.am b/camlibs/pccam600/Makefile.am new file mode 100644 index 000000000..fd2de87b7 --- /dev/null +++ b/camlibs/pccam600/Makefile.am @@ -0,0 +1,10 @@ +camlibdir = $(libdir)/gphoto2/$(VERSION) +camlib_LTLIBRARIES = libgphoto2_pccam600.la + +INCLUDES = \ + -I$(top_srcdir)/libgphoto2_port/libgphoto2_port \ + -I$(top_srcdir)/libgphoto2 + +libgphoto2_pccam600_la_SOURCES = pccam600.c pccam600.h library.c +libgphoto2_pccam600_la_LDFLAGS = -module -avoid-version +libgphoto2_pccam600_la_LIBADD = $(top_builddir)/libgphoto2/libgphoto2.la diff --git a/camlibs/pccam600/README b/camlibs/pccam600/README new file mode 100644 index 000000000..7000001f9 --- /dev/null +++ b/camlibs/pccam600/README @@ -0,0 +1,6 @@ +This software is based upon usbsniffing, and therefore is +marked EXPERIMENTAL. +The format of the WAV file is IMA ADPCM (code=0x11) also called DVI ADPCM, +and can be converted with sox -i inputfile outputfile. +The format of the RAW files is unknown so if anyone finds/knows a way +to decode it please contact me.
\ No newline at end of file diff --git a/camlibs/pccam600/library.c b/camlibs/pccam600/library.c new file mode 100644 index 000000000..ddcf7da0f --- /dev/null +++ b/camlibs/pccam600/library.c @@ -0,0 +1,321 @@ +/****************************************************************/ +/* library.c - Gphoto2 library for the Creative PC-CAM600 */ +/* */ +/* */ +/* Author: Peter Kajberg <pbk@odense.kollegienet.dk> */ +/* */ +/* 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. */ +/* */ +/* Please notice that camera commands was sniffed by use of a */ +/* usbsniffer under windows. This is an experimental driver and */ +/* a work in progess(I hope :)) */ +/* */ +/* 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 <config.h> + +#include "pccam600.h" + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> + +#include <gphoto2.h> +#include <gphoto2-port.h> + +#define GP_MODULE "pccam600" + +#ifdef ENABLE_NLS +# include <libintl.h> +# undef _ +# define _(String) dgettext (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 + + + +#define QUALITY_LO 0x56 +#define QUALITY_ME 0x58 +#define QUALITY_HI 0x45 + +struct models{ + char *name; + unsigned short idVendor; + unsigned short idProduct; + char serial; +} models[] = { + {"Creative PC-CAM600",0x041e,0x400b,0}, + {NULL,0,0,0} +}; + +int camera_id(CameraText *id) +{ + strcpy(id->text, "Creative PC-CAM600"); + return (GP_OK); +} + +int camera_abilities(CameraAbilitiesList *list) +{ + int i; + CameraAbilities a; + for(i=0; models[i].name; i++) { + memset(&a , 0, sizeof(CameraAbilities)); + strcpy(a.model, models[i].name); + a.status = GP_DRIVER_STATUS_EXPERIMENTAL; + a.port = GP_PORT_USB; + a.speed[0] = 0; + a.usb_vendor = models[i].idVendor; + a.usb_product = models[i].idProduct; + a.operations = GP_OPERATION_NONE; + a.folder_operations = GP_FOLDER_OPERATION_NONE; + a.file_operations = GP_FILE_OPERATION_DELETE; + gp_abilities_list_append(list, a); + } + return GP_OK; +} + +static int camera_exit(Camera *camera, GPContext *context){ + int ret; + ret = pccam600_close(camera->port, context); + return ret; +} + +static int file_list_func (CameraFilesystem *fs, const char *folder, + CameraList *list, void *data, GPContext *context){ + + Camera *camera = data; + CameraFileInfo info; + int ret,n,i,nr_of_blocks; + int offset = 64; + char *temp; + char buffer[512]; + FileEntry *file_entry; + file_entry = (malloc(sizeof(FileEntry))); + if ( (nr_of_blocks = pccam600_get_file_list(camera->port, context)) < 0 ){ + gp_log(GP_LOG_DEBUG,"pccam600","pccam600->get_file_list return <0"); + return GP_ERROR; + } + for (n = 0; n != nr_of_blocks; n++) + { + ret = pccam600_read_data(camera->port, buffer); + for (i = offset; i <= 512-32; i=i+32) + { + memcpy(file_entry,&(buffer)[i],32); + /*Fileentry valid? */ + if( !((file_entry->state & 0x02) != 2) && + !((file_entry->state & 0x08) == 8) ) + { + info.file.fields = 0; + temp = &(file_entry->name)[5]; + if (strncmp(temp,"JPG",3) == 0) + { + memcpy(&(file_entry->name)[5],".jpg",4); + strcpy(info.file.type,GP_MIME_JPEG); + info.file.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT; + if (file_entry->quality == QUALITY_LO) + { + info.file.width = 640; + info.file.height = 480; + } + else if(file_entry->quality == QUALITY_ME) + { + info.file.width = 1024; + info.file.height = 768; + } + } + else if (strncmp(temp,"AVI",3) == 0) + { + memcpy(&(file_entry->name)[5],".avi",4); + info.file.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT; + info.file.height = 352; + info.file.width = 288; + strcpy(info.file.type, GP_MIME_AVI); + } + else if (strncmp(temp,"WAV",3) == 0) + { + memcpy(&(file_entry->name)[5],".wav",4); + strcpy(info.file.type, GP_MIME_WAV); + info.file.height = 0; + } + else if (strncmp(temp,"RAW",3) == 0) + { + memcpy(&(file_entry->name)[5],".raw",4); + info.file.width = 1280; + info.file.height = 960; + info.file.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT; + strcpy(info.file.type, GP_MIME_RAW); + } + strcpy(info.file.name,file_entry->name); + gp_filesystem_append(fs,folder,info.file.name,context); + info.preview.fields = 0; + info.file.size = (file_entry->size[1]*256+ + file_entry->size[0]) * 256; + info.file.permissions = GP_FILE_PERM_READ | GP_FILE_PERM_DELETE; + info.file.fields |= GP_FILE_INFO_SIZE | GP_FILE_INFO_PERMISSIONS + |GP_FILE_INFO_TYPE | GP_FILE_INFO_NAME ; + ret = gp_filesystem_set_info_noop(fs, folder, info, context); + } + } + offset = 0; + } + return GP_OK; +} + +static int camera_get_file (Camera *camera, GPContext *context, int index, + unsigned char **data, int *size) +{ + unsigned char buffer[512]; + int nr_of_blocks = 0; + int n,id,canceled=0; + int picturebuffersize = 0; + int offset = 0; + nr_of_blocks = pccam600_get_file(camera->port,context,index); + if (nr_of_blocks < 0) + return GP_ERROR_FILE_NOT_FOUND; + picturebuffersize = nr_of_blocks * 512; + id = gp_context_progress_start(context,nr_of_blocks,_("Downloading file..")); + *data= malloc(picturebuffersize+1); + memset(*data,0,picturebuffersize+1); + for (n = 0; n != nr_of_blocks; n++){ + pccam600_read_data(camera->port, buffer); + memmove(&(*data)[offset],buffer,512); + offset = offset + 512; + gp_context_progress_update(context,id,n); + if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) + { + /* Keep reading data or else data will be invalid next time*/ + canceled = 1; + } + } + *size = offset; + gp_context_progress_stop(context,id); + if (canceled) return GP_ERROR_CANCEL; + 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; + unsigned char *data = NULL; + int size,ret,index; + size = 0; + index = gp_filesystem_number(fs, folder, filename, context); + if (index < 0) + return index; + switch(type) + { + case GP_FILE_TYPE_NORMAL: + ret=camera_get_file(camera, context, index, &data, &size); + break; + default: + return GP_ERROR_NOT_SUPPORTED; + } + gp_file_set_data_and_size(file, data, size); + gp_file_set_name (file, filename); + return GP_OK; +} + +static int camera_summary(Camera *camera, CameraText *summary, GPContext *context) +{ + int totalmem; + int freemem; + int ret; + char summary_text[256]; + ret = pccam600_get_mem_info(camera->port,context,&totalmem,&freemem); + snprintf(summary_text,sizeof(summary_text), + (" Total memory is %8d bytes.\n Free memory is %8d bytes."), + totalmem,freemem ); + strcat(summary->text,summary_text); + return GP_OK; +} + +static int camera_manual(Camera *camera, CameraText *manual, GPContext *context){ + strcpy(manual->text, _("Manual Not Implemented Yet")); + return GP_OK; +} + +static int camera_about(Camera *camera, CameraText *about, GPContext *context) +{ + strcpy(about->text, + _("Creative PC-CAM600\n Author:Peter Kajberg\n email:<pbk@odense.kollegienet.dk>\n")); + return GP_OK; +} +static int +get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileInfo *info, void *data, GPContext *context) +{ + + return GP_OK; +} + +static int delete_file_func(CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context){ + int index,ret; + + Camera *camera = data; + index = gp_filesystem_number(fs, folder, filename, context); + gp_log(GP_LOG_DEBUG,"pccam","deleting '%s' in '%s'.. index:%d",filename, folder,index); + ret = pccam600_delete_file(camera->port, context, index); + return GP_OK; +} + +int camera_init(Camera *camera, GPContext *context){ + GPPortSettings settings; + int ret = 0; + camera->functions->exit = camera_exit; + camera->functions->summary = camera_summary; + camera->functions->manual = camera_manual; + camera->functions->about = camera_about; + gp_log (GP_LOG_DEBUG, "pccam", "Initializing the camera\n"); + switch (camera->port->type) + { + case GP_PORT_USB: + ret = gp_port_get_settings(camera->port,&settings); + if (ret < 0) return ret; + settings.usb.inep = 0x82; + settings.usb.outep = 0x03; + settings.usb.config = 1; + settings.usb.interface = 1; + settings.usb.altsetting = 0; + ret=gp_port_set_settings(camera->port,settings); + if (ret<0) return ret; + break; + case GP_PORT_SERIAL: + return GP_ERROR_IO_SUPPORTED_SERIAL; + default: + return GP_ERROR_NOT_SUPPORTED; + } + ret = pccam600_init(camera->port, context); + if (ret < 0) return ret; + gp_filesystem_set_info_funcs (camera->fs, get_info_func,NULL, camera); + gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL, camera); + gp_filesystem_set_file_funcs (camera->fs, get_file_func, delete_file_func, + camera); + return GP_OK; +} diff --git a/camlibs/pccam600/pccam600.c b/camlibs/pccam600/pccam600.c new file mode 100644 index 000000000..1eadeeb82 --- /dev/null +++ b/camlibs/pccam600/pccam600.c @@ -0,0 +1,233 @@ +/****************************************************************/ +/* pccam600.c - Gphoto2 library for the Creative PC-CAM600 */ +/* */ +/* */ +/* Author: Peter Kajberg <pbk@odense.kollegienet.dk> */ +/* */ +/* 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. */ +/* */ +/* Please notice that camera commands was sniffed by use of a */ +/* usbsniffer under windows. This is an experimental driver and */ +/* a work in progess(I hope :)) */ +/* */ +/* 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 <config.h> +#include <string.h> + + +#include "pccam600.h" + +#include <gphoto2.h> +#include <gphoto2-port.h> +#include <gphoto2-port-log.h> + +#define GP_MODULE "pccam600" + +#ifdef ENABLE_NLS +# include <libintl.h> +# undef _ +# define _(String) dgettext (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 + +#define REPORT_ERROR(context,function,text,data1,data2) \ +{ \ + gp_context_error (context, _(function ":" text),data1,data2); \ + return (GP_ERROR); \ +} +/* + *waits until the status value is 0 or 8. + *if status == 0xb0 or 0x40 we will wait some more + */ +void pccam600_wait_for_status(GPPort *port){ + int ret; + unsigned char status = 1; + while(status != 0x00){ + gp_port_set_timeout(port,3000); + ret = gp_port_usb_msg_read(port,0x06,0x00,0x00,&status,1); + if (status == 0 || status == 8) + return; + if (status == 0xb0){ + gp_port_set_timeout(port,200000); + ret = gp_port_usb_msg_read(port,0x06,0x00,0x00,&status,1); + } + if (status == 0x40){ + gp_port_set_timeout(port,400000); + ret = gp_port_usb_msg_read(port,0x06,0x00,0x00,&status,1); + } + } +} + +/* + *Deletes a file. The first file has index = 2. + */ +int pccam600_delete_file(GPPort *port, GPContext *context, int index){ + unsigned char response[4]; + int ret; + index = index + 2; + gp_port_set_timeout(port,200000); + ret = gp_port_usb_msg_write(port,0x09,index,0x1001,NULL,0x00); + pccam600_wait_for_status(port); + gp_port_set_timeout(port, 400000); + ret = gp_port_usb_msg_read(port,0x60,0x00,0x03,response,0x04); + pccam600_wait_for_status(port); + ret = gp_port_usb_msg_read(port,0x60,0x00,0x04,response,0x04); + pccam600_wait_for_status(port); + return GP_OK; +} + +int pccam600_get_mem_info(GPPort *port, GPContext *context, int *totalmem, + int *freemem) +{ + unsigned char response[4]; + int ret; + gp_port_set_timeout(port, 400000); + ret = gp_port_usb_msg_read(port,0x60,0x00,0x03,response,0x04); + *totalmem = response[2]*65536+response[1]*256+response[0]; + pccam600_wait_for_status(port); + ret = gp_port_usb_msg_read(port,0x60,0x00,0x04,response,0x04); + *freemem = response[2]*65536+response[1]*256+response[0]; + pccam600_wait_for_status(port); + return GP_OK; +} + +/* + * + */ +int pccam600_get_file_list(GPPort *port, GPContext *context){ + unsigned char response[4]; + int ret, nr_of_blocks; + gp_port_set_timeout(port,500); + ret = gp_port_usb_msg_write(port,0x08,0x00,0x1021,NULL,0x00); + pccam600_wait_for_status(port); + gp_port_set_timeout(port, 200000); + ret = gp_port_usb_msg_write(port,0x08,0x00,0x1021,NULL,0x00); + pccam600_wait_for_status(port); + ret = gp_port_usb_msg_read(port,0x08,0x00,0x1000,response,0x04); + nr_of_blocks = response[2]*256+response[1]; + if (nr_of_blocks == 0){ + gp_log(GP_LOG_DEBUG,"pccam600 library: pccam600_get_file_list", + "nr_of_blocks is 0"); + REPORT_ERROR(context,"pccam600_init","Expected > %d blocks got %d", + 0,nr_of_blocks); + } + return nr_of_blocks / 2; +} + +int pccam600_get_file(GPPort *port, GPContext *context, int index){ + unsigned char response[4]; + int ret,nr_of_blocks; + index = index + 2; + if (index < 2) + REPORT_ERROR(context, + "pccam600_get_file","got index %d but expected index > %d", + index,2); + gp_port_set_timeout(port,200000); + ret = gp_port_usb_msg_read(port,0x08,index,0x1001,response,0x04); + gp_port_set_timeout(port,3000); + ret = gp_port_usb_msg_write(port,0x04,0x00,0x00,NULL,0x00); + pccam600_wait_for_status(port); + gp_port_set_timeout(port,200000); + ret = gp_port_usb_msg_read(port,0x08,index,0x1002,response,0x04); + ret = gp_port_usb_msg_read(port,0x08,index,0x1001,response,0x04); + nr_of_blocks = response[2]*256+response[1]; + if (nr_of_blocks == 0){ + gp_log(GP_LOG_DEBUG, + "pccam600 library: pccam600_get_file","nr_of_msg is 0"); + REPORT_ERROR(context,"pccam600_init","Expected > %d blocks got %d", + 0,nr_of_blocks); + } + return nr_of_blocks / 2; +} + +/* + *Reads bulk data from the camera in 512bytes chunks. + */ +int pccam600_read_data(GPPort *port, unsigned char *buffer){ + int ret; + gp_port_set_timeout(port,500); + ret = gp_port_read(port,buffer,512); + return GP_OK; +} + +/* + * + */ +int pccam600_close(GPPort *port, GPContext *context){ + int ret; + gp_port_set_timeout(port,500); + ret = gp_port_usb_msg_write(port,0x08,0x00,0xf0,NULL,0x00); + if (ret < 0) + REPORT_ERROR(context, + "pccam600_close","return value was %d instead of %d", + ret,0); + pccam600_wait_for_status(port); + return GP_OK; +} + +/* + *Sets up the camera and then read 32 512bytes blocks. + *Why it is read those 32 blocks I dont know. Just + *doing what the windows driver does :). + */ +int pccam600_init(GPPort *port, GPContext *context){ + unsigned char response[4]; + unsigned char buffer[512]; + int nr_of_blocks; + int ret,i; + gp_port_set_timeout(port,100); + ret = gp_port_usb_msg_write(port,0x0e,0x00,0x01,NULL,0x0); + ret = gp_port_usb_msg_write(port,0x08,0x00,0xff,NULL,0x0); + pccam600_wait_for_status(port); + if (ret <0) return ret; + gp_port_set_timeout(port,100000); + ret = gp_port_usb_msg_read(port,0x08,0x00,0xff,response,0x1); + gp_port_set_timeout(port,500); + ret = gp_port_usb_msg_write(port,0x08,0x00,0x1020,NULL,0x0); + pccam600_wait_for_status(port); + gp_port_set_timeout(port,200000); + ret = gp_port_usb_msg_read(port,0x08,0x00,0x1000,response,0x4); + nr_of_blocks = response[2]*256+response[1]; + nr_of_blocks = 512 / nr_of_blocks; + gp_log(GP_LOG_DEBUG,"pccam600 library: init","nr_of_blocks %d",nr_of_blocks); + if (nr_of_blocks == 0){ + REPORT_ERROR(context,"pccam600_init","Expected %d blocks got %d", + 64,nr_of_blocks); + } + gp_port_set_timeout(port,500); + for (i = 0; i<nr_of_blocks; i++){ + ret = gp_port_read(port, buffer,512); + if (ret < 0){ + gp_log(GP_LOG_DEBUG, + "pccam600 library: init"," gp_port_read returned %d:", + ret); + REPORT_ERROR(context,"pccam600 init", + "Unexpected error: gp_port_read returned %d instead of %d", + ret,0); + } + } + return GP_OK; + +} diff --git a/camlibs/pccam600/pccam600.h b/camlibs/pccam600/pccam600.h new file mode 100644 index 000000000..ebc702971 --- /dev/null +++ b/camlibs/pccam600/pccam600.h @@ -0,0 +1,46 @@ +/* pccam600.h + * + * This library is free software; you can redistribute and/or + * modify it inder the terms of the GNU Lesser Genreral Public + * License as publiced 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 warrenty of + * MERCHANTABULITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * lesser General Public License for more details. + * + * Author: Peter Kajberg <pbk@odense.kollegienet.dk> + */ + +#ifndef __PCCAM600_H__ +#define __PCCAM600_H__ + +#include <gphoto2.h> +#include <gphoto2-port.h> + +typedef struct { + unsigned char state; /*delete or ok*/ + unsigned char unk1; + unsigned char quality; + unsigned char name[9]; + unsigned char unk2[4]; + + unsigned char unk3[10]; + unsigned char unk4[2]; + unsigned char unk5; + unsigned char size[2]; + unsigned char unk6; +} FileEntry; + +void pccam600_wait_for_status(GPPort *port); +int pccam600_init(GPPort *port, GPContext *context); +int pccam600_close(GPPort *port, GPContext *context); +int pccam600_get_file_list(GPPort *port, GPContext *context); +int pccam600_delete_file(GPPort *port, GPContext *context, int index); +int pccam600_read_data(GPPort *port, unsigned char *buffer); +int pccam600_get_file(GPPort *port, GPContext *context, int index); +int pccam600_get_mem_info(GPPort *port, GPContext *context, int *totalmem, + int *freemem); +#endif /* __PCCAM600_H__ */ + |