diff options
author | Hubert Figuiere <hub@figuiere.net> | 2003-02-26 22:13:04 +0000 |
---|---|---|
committer | Hubert Figuiere <hub@figuiere.net> | 2003-02-26 22:13:04 +0000 |
commit | 4d6541bb869c9df9225968ac70dc8f48f878d9ed (patch) | |
tree | d85678c8378ac99b63c6c58a961574175c5a77d9 | |
parent | ad24c31303790cec9eab49eb23402958bdbc73fe (diff) | |
download | libgphoto2-4d6541bb869c9df9225968ac70dc8f48f878d9ed.tar.gz |
First revision of PDR-M11 driver
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@6260 67ed7778-7388-44ab-90cf-0a291f65f57c
-rw-r--r-- | camlibs/toshiba/Makefile.am | 3 | ||||
-rw-r--r-- | camlibs/toshiba/pdrm11/Makefile.am | 11 | ||||
-rw-r--r-- | camlibs/toshiba/pdrm11/README | 36 | ||||
-rw-r--r-- | camlibs/toshiba/pdrm11/library.c | 318 | ||||
-rw-r--r-- | camlibs/toshiba/pdrm11/pdrm11.c | 228 | ||||
-rw-r--r-- | camlibs/toshiba/pdrm11/pdrm11.h | 72 |
6 files changed, 668 insertions, 0 deletions
diff --git a/camlibs/toshiba/Makefile.am b/camlibs/toshiba/Makefile.am new file mode 100644 index 000000000..93d31d41a --- /dev/null +++ b/camlibs/toshiba/Makefile.am @@ -0,0 +1,3 @@ +## Process this file with automake to generate a GNU Makefile + +SUBDIRS = pdrm11 diff --git a/camlibs/toshiba/pdrm11/Makefile.am b/camlibs/toshiba/pdrm11/Makefile.am new file mode 100644 index 000000000..ad074bf2f --- /dev/null +++ b/camlibs/toshiba/pdrm11/Makefile.am @@ -0,0 +1,11 @@ +camlib_LTLIBRARIES = libgphoto2_toshiba.la + +INCLUDES = \ + -I$(top_srcdir)/intl \ + -I$(top_srcdir)/libgphoto2_port/libgphoto2_port \ + -I$(top_srcdir)/libgphoto2 \ + -I$(top_builddir)/libgphoto2 + +libgphoto2_toshiba_la_SOURCES = library.c pdrm11.c +libgphoto2_toshiba_la_LDFLAGS = -module -avoid-version +libgphoto2_toshiba_la_LIBADD = $(top_builddir)/libgphoto2/libgphoto2.la diff --git a/camlibs/toshiba/pdrm11/README b/camlibs/toshiba/pdrm11/README new file mode 100644 index 000000000..3234bf935 --- /dev/null +++ b/camlibs/toshiba/pdrm11/README @@ -0,0 +1,36 @@ +This is the driver for the toshiba pdr-m11 camera. It's not the greatest +camera, but it is enough for me. + +What works: +I can get a list of filenames, download thumbnails, and download jpegs. + +What doesn't work: +Tiff files don't seem to work at all. Deleting a file only works sometimes. + + +The camera appears to be a 16bit little-endian processor (based on guesses from the data it sends back.) + +--------SIGNALS-------------------- + +-signal-----length-----read/write---------data---------------- + +1f40 0 w (used in init) +1f30 0 w (used in init) + +9300 0 w (sent right before retrieving a picture) +9b00 0 w (sent right before retrieving a thumbnail) + +ad00 8 r 30 01 <2picNum> 01 00 00 00 + +ae00 2 w 01 00 (always follows a b200) +b200 2 w <2picNum> (select a picture) + +b600 10 r 00 00 <number of pictures> 00 ?? ?? ?? ?? +b900 26 r 00 00 <12filename> 20 00 20 00 <4LengthOfPic> 64 46 3f 2e +ba40 2 r 00 00 (used in delete) +bf01 2 r 00 00 +d000 4 r 01 30 00 25 (check if camera is ready? (30 and 00 don't change 01 and 25 signal ready) +e600 14 r ?? ?? ?? ?? ?? ?? ?? <2ThumbSize> ?? ?? ?? ?? ?? +d700 0 w ping +d800 0 w ping (there is a d800 followed by a d701) +d701 0 w (ping?) diff --git a/camlibs/toshiba/pdrm11/library.c b/camlibs/toshiba/pdrm11/library.c new file mode 100644 index 000000000..7e91009dc --- /dev/null +++ b/camlibs/toshiba/pdrm11/library.c @@ -0,0 +1,318 @@ +/* library.c -- copied from the template + * + * Copyright © 2003 David Hogue <david@jawa.gotdns.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "pdrm11.h" + +#include <stdint.h> + +#include <gphoto2.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 + + +#define GP_MODULE "Toshiba" + +int +camera_id (CameraText *id) +{ + strcpy(id->text, "toshiba-pdrm11"); + + return (GP_OK); +} + + +int +camera_abilities (CameraAbilitiesList *list) +{ + CameraAbilities a; + + memset(&a, 0, sizeof(a)); + strcpy(a.model, "Toshiba:PDR-M11"); + a.status = GP_DRIVER_STATUS_TESTING; + a.port = GP_PORT_USB; + a.speed[0] = 0; + a.usb_vendor = 0x1132; + a.usb_product = 0x4337; + a.operations = GP_OPERATION_NONE; + a.file_operations = GP_FILE_OPERATION_DELETE | + GP_FILE_OPERATION_PREVIEW; + a.folder_operations = GP_FOLDER_OPERATION_NONE; + + gp_abilities_list_append(list, a); + + return (GP_OK); +} + + +static int +camera_exit (Camera *camera, GPContext *context) +{ + return (GP_OK); +} + + +static int +get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileType type, CameraFile *file, void *data, + GPContext *context) +{ + int picNum; + int ret; + Camera *camera = data; + + switch(type){ + case GP_FILE_TYPE_PREVIEW: + case GP_FILE_TYPE_NORMAL: + picNum = gp_filesystem_number(fs, folder, filename, context) + 1; + ret = pdrm11_get_file (fs, filename, type, file, camera->port, picNum); + return(ret); + default: + return GP_ERROR_NOT_SUPPORTED; + } +} + + +static int +put_file_func (CameraFilesystem *fs, const char *folder, CameraFile *file, + void *data, GPContext *context) +{ + GP_DEBUG("put_file_func"); + return (GP_OK); +} + + +static int +delete_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context) +{ + int picNum; + int ret; + Camera *camera = data; + + + return (GP_ERROR_NOT_SUPPORTED); + + picNum = gp_filesystem_number(fs, folder, filename, context) + 1; + ret = pdrm11_delete_file(camera->port, picNum); + return (GP_OK); +} + + +static int +delete_all_func (CameraFilesystem *fs, const char *folder, void *data, + GPContext *context) +{ + /*Camera *camera = data;*/ + GP_DEBUG("deleta_all_func"); + + /* + * Delete all files in the given folder. If your camera doesn't have + * such a functionality, just don't implement this function. + */ + + return (GP_OK); +} + + +static int +camera_config_get (Camera *camera, CameraWidget **window, GPContext *context) +{ + GP_DEBUG("camera_config_get"); + gp_widget_new (GP_WIDGET_WINDOW, "Camera Configuration", window); + + + /* Append your sections and widgets here. */ + + return (GP_OK); +} + + +static int +camera_config_set (Camera *camera, CameraWidget *window, GPContext *context) +{ + GP_DEBUG("camera_config_set"); + /* + * Check if the widgets' values have changed. If yes, tell the camera. + */ + + return (GP_OK); +} + + +static int +camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) +{ + GP_DEBUG("camera_capture_preview"); + return (GP_OK); +} + + +static int +camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, + GPContext *context) +{ + GP_DEBUG("camera_capture"); + return (GP_OK); +} + + +static int +camera_summary (Camera *camera, CameraText *summary, GPContext *context) +{ + GP_DEBUG("camera_summary"); + /* + * Fill out the summary with some information about the current + * state of the camera (like pictures taken, etc.). + */ + + return (GP_OK); +} + + +static int +camera_manual (Camera *camera, CameraText *manual, GPContext *context) +{ + GP_DEBUG("camera_manual"); + /* + * If you would like to tell the user some information about how + * to use the camera or the driver, this is the place to do. + */ + + return (GP_OK); +} + + +static int +camera_about (Camera *camera, CameraText *about, GPContext *context) +{ + strcpy (about->text, _("Toshiba\n" + "David Hogue <david@jawa.gotdns.org>\n" + "Toshiba pdr-m11 driver.\n")); + + return (GP_OK); +} + + +static int +get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, + CameraFileInfo *info, void *data, GPContext *context) +{ + /* Camera *camera = data; */ + time_t now; + + GP_DEBUG("get_info_func"); + + now = time(NULL); + GP_DEBUG("now: 0x%x", now); + info->file.mtime = now; + + info->file.fields = GP_FILE_INFO_MTIME; + + + return (GP_OK); +} + + +static int +set_info_func (CameraFilesystem *fs, const char *folder, const char *file, + CameraFileInfo info, void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + GP_DEBUG("set_info_func"); + + /* Set the file info here from <info> */ + + + return (GP_OK); +} + + + +static int +folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context) +{ + /*Camera *camera = data;*/ + GP_DEBUG("folder_list_func"); + + /* List your folders here */ + + return (GP_OK); +} + + + +static int +file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, + void *data, GPContext *context) +{ + Camera *camera = data; + int ret; + + ret = pdrm11_get_filenames(camera->port, list); + return (GP_OK); +} + + + +int +camera_init (Camera *camera, GPContext *context) +{ + int ret; + + /* First, set up all the function pointers */ + camera->functions->exit = camera_exit; + camera->functions->get_config = camera_config_get; + camera->functions->set_config = camera_config_set; + camera->functions->capture = camera_capture; + camera->functions->capture_preview = camera_capture_preview; + camera->functions->summary = camera_summary; + camera->functions->manual = camera_manual; + camera->functions->about = camera_about; + + /* Now, tell the filesystem where to get lists, files and info */ + gp_filesystem_set_list_funcs (camera->fs, file_list_func, + folder_list_func, camera); + gp_filesystem_set_info_funcs (camera->fs, get_info_func, set_info_func, + camera); + gp_filesystem_set_file_funcs (camera->fs, get_file_func, + delete_file_func, camera); + gp_filesystem_set_folder_funcs (camera->fs, put_file_func, + delete_all_func, NULL, NULL, camera); + + + + ret = pdrm11_init(camera->port); + return(ret); +} diff --git a/camlibs/toshiba/pdrm11/pdrm11.c b/camlibs/toshiba/pdrm11/pdrm11.c new file mode 100644 index 000000000..a96eb0860 --- /dev/null +++ b/camlibs/toshiba/pdrm11/pdrm11.c @@ -0,0 +1,228 @@ +/* pdrm11.c -- interfaces directly with the camera + * + * Copyright © 2003 David Hogue <david@jawa.gotdns.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "pdrm11.h" + +#include <string.h> +#include <unistd.h> + +#include <gphoto2.h> +#include <gphoto2-endian.h> + +#define GP_MODULE "pdrm11" +#define ETIMEDOUT 110 + +int pdrm11_init(GPPort *port) +{ + unsigned char buf[20]; + int timeout = 50; + + gp_port_set_timeout(port,1000); + + /* exactly what windows driver does */ + gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, buf, 4); + gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_PING3, 0, NULL, 0); + gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, buf, 4); + gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_INIT1, 0, NULL, 0); + gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, buf, 4); + gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_INIT2, 0, NULL, 0); + gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_READY, 0, buf, 4); + + gp_port_usb_msg_read (port, 0x01, PDRM11_CMD_ZERO, 0, buf, 2); + if(buf[0] || buf[1]) { + /* I haven't seen anything other than 00 00 yet + * unless the connection is bad */ + GP_DEBUG("PDRM11_CMD_ZERO: %x %x", buf[0], buf[1]); + return(GP_ERROR); + } + + + /* wait til the camera is ready */ + do { + usleep(200000); + GP_DEBUG("waiting..."); + + timeout--; + if( gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_READY, 0, buf, 4) == -ETIMEDOUT ) + timeout = 0; + } while( !((buf[3] == 0x25) && (buf[0] == 1)) && timeout ); + + /* what good is this? */ + usleep(400000); + + if(!timeout) + return(GP_ERROR_TIMEOUT); + else + return(GP_OK); +} + + + +int pdrm11_get_filenames(GPPort *port, CameraList *list) +{ + int i, j; + uint32_t numPics; + char name[20]; + char buf[30]; + + + gp_port_set_timeout(port, 10000); + CHECK(gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_NUMPICS, 0, buf, 10)); + /* trying to remain endian friendly */ + numPics = le16atoh(&buf[2]) + (le16atoh(&buf[0]) * 1024); + GP_DEBUG("found %d pictures", numPics); + + CHECK(gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_INFO, 1, buf, 8)); + + + for(i=1; i<numPics+1; i++) { + CHECK( pdrm11_select_file(port, i) ); + + /* the filename is 12 chars starting at the third byte */ + CHECK(gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_FILENAME, i, buf, 26)); + for(j=0; j<12; j+=2) { + name[j] = buf[j+2+1]; + name[j+1] = buf[j+2]; + } + name[12] = '\0'; + + GP_DEBUG(name); + gp_list_append(list, name, NULL); + } + + + return(GP_OK); +} + + + + +int pdrm11_select_file(GPPort *port, uint16_t file) +{ + uint16_t picNum = htole16(file); + /* need to write 01 00 after the picture number */ + uint16_t one = htole16(1); + + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_SELECT_PIC1, file, (char*)&picNum, 2) ); + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_SELECT_PIC2, file, (char*)&one, 2) ); + + return(GP_OK); +} + + + +int pdrm11_ping(GPPort *port) +{ + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_PING1, 1, NULL, 0) ); + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_PING2, 1, NULL, 0) ); + + return(GP_OK); +} + + + +int pdrm11_get_file(CameraFilesystem *fs, const char *filename, CameraFileType type, + CameraFile *file, GPPort *port, uint16_t picNum) +{ + uint32_t size = 0; + uint16_t thumbsize = 0; + uint8_t buf[30]; + uint8_t *image; + uint8_t temp; + int i; + int ret; + + + gp_port_set_timeout(port,10000); + CHECK( pdrm11_select_file(port, picNum) ); + + if(type == GP_FILE_TYPE_PREVIEW) { + CHECK( gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_THUMBSIZE, picNum, buf, 14) ); + thumbsize = le16atoh( &buf[8] ); + size = (uint32_t)thumbsize + 1; + } else { + CHECK( gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_GET_FILESIZE, picNum, buf, 26) ); + /* FIXME this is probably wrong on big-endian (camera being 16-bit) */ + size = le32atoh( &buf[18] ); + } + + GP_DEBUG("size: %d 0x%x", size, size); + + image = malloc(sizeof(char)*size); + if(!image) + return(GP_ERROR_NO_MEMORY); + + + + if(type == GP_FILE_TYPE_PREVIEW) { + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_GET_THUMB, picNum, NULL, 0) ); + } else { + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_GET_PIC, picNum, NULL, 0) ); + } + + ret = gp_port_read(port, image, size); + if(ret != size) { + GP_DEBUG("failed to read from port. Giving it one more try..."); + ret = gp_port_read(port, image, size); + if(ret != size) { + GP_DEBUG("gp_port_read returned %d 0x%x. size: %d 0x%x", ret, ret, size, size); + return(GP_ERROR_IO_READ); + } + } + + /* swap the bytes for the thumbnail, but not the file */ + if(type == GP_FILE_TYPE_PREVIEW) { + for(i=0; i<size; i+=2) { + temp = image[i]; + image[i] = image[i+1]; + image[i+1] = temp; + } + } + + + gp_file_set_mime_type(file, GP_MIME_JPEG); + gp_file_set_data_and_size(file, image, size); + + return(GP_OK); +} + + + +int pdrm11_delete_file(GPPort *port, int picNum) +{ + uint8_t buf[2]; + + /* for some reason the windows driver sends b200 twice + * once in pdrm11_select_file and once before. dunno why */ + CHECK( gp_port_usb_msg_write(port, 0x01, PDRM11_CMD_SELECT_PIC1, picNum, (char*)&picNum, 2) ); + CHECK( pdrm11_select_file(port, picNum) ); + + /* should always be 00 00 */ + gp_port_usb_msg_read(port, 0x01, PDRM11_CMD_DELETE, picNum, buf, 2); + if( (buf[0] != 0) || (buf[1] !=0) ) { + GP_DEBUG("should have read 00 00. actually read %2x %2x.", buf[0], buf[1]); + return(GP_ERROR); + } + + + return(GP_OK); +} + diff --git a/camlibs/toshiba/pdrm11/pdrm11.h b/camlibs/toshiba/pdrm11/pdrm11.h new file mode 100644 index 000000000..fe7dad769 --- /dev/null +++ b/camlibs/toshiba/pdrm11/pdrm11.h @@ -0,0 +1,72 @@ +/* pdrm11.h -- interfaces directly with the camera + * + * Copyright © 2003 David Hogue <david@jawa.gotdns.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 __PDRM11_H__ +#define __PDRM11_H__ + +#include "config.h" +#include <gphoto2.h> +#include <stdint.h> + +/* once in a while a gp_port command will fail and then work on a + * second try this tries to run the command twice and returns the + * error code if it fails the second time */ +#define CHECK(result) { \ + int res; \ + res = result; \ + if (res < 0) { \ + res = result; \ + if (res < 0) { \ + GP_DEBUG("%s--%d: %s returned 0x%x", __FILE__, __LINE__, __STRING(result), res); \ + return res; \ + } \ + } \ +} + +#define PDRM11_CMD_INIT1 htole16( 0x1f40 ) +#define PDRM11_CMD_INIT2 htole16( 0x1f30 ) +#define PDRM11_CMD_GET_PIC htole16( 0x9300 ) +#define PDRM11_CMD_GET_THUMB htole16( 0x9b00 ) +#define PDRM11_CMD_GET_INFO htole16( 0xad00 ) +#define PDRM11_CMD_SELECT_PIC2 htole16( 0xae00 ) +#define PDRM11_CMD_SELECT_PIC1 htole16( 0xb200 ) +#define PDRM11_CMD_GET_NUMPICS htole16( 0xb600 ) +#define PDRM11_CMD_GET_FILENAME htole16( 0xb900 ) +#define PDRM11_CMD_GET_FILESIZE htole16( 0xb900 ) +#define PDRM11_CMD_DELETE htole16( 0xba40 ) +#define PDRM11_CMD_ZERO htole16( 0xbf01 ) /* not sure what this is, but it almost always returns 00 00 */ +#define PDRM11_CMD_READY htole16( 0xd000 ) +#define PDRM11_CMD_GET_THUMBSIZE htole16( 0xe600 ) +#define PDRM11_CMD_PING1 htole16( 0xd700 ) +#define PDRM11_CMD_PING2 htole16( 0xd800 ) +#define PDRM11_CMD_PING3 htole16( 0xd701 ) + + +int pdrm11_init(GPPort *port); +int pdrm11_select_file(GPPort *port, uint16_t file); +int pdrm11_ping(GPPort *port); +int pdrm11_get_file(CameraFilesystem *fs, const char *filename, CameraFileType type, + CameraFile *file, GPPort *port, uint16_t picNum); +int pdrm11_get_filenames(GPPort *port, CameraList *list); +int pdrm11_delete_file(GPPort *port, int picNum); + + + +#endif /* __PDRM11_H__ */ |