summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHubert Figuiere <hub@figuiere.net>2002-08-26 12:40:18 +0000
committerHubert Figuiere <hub@figuiere.net>2002-08-26 12:40:18 +0000
commite67cd255e67305a30a56f838ffb9181947a1b7c4 (patch)
treea21706a1bd080281fea60ff207ca7ba57d16d77b
parent4ee5075150f0732dbb306fa79c636bf600bd4bdd (diff)
downloadlibgphoto2-e67cd255e67305a30a56f838ffb9181947a1b7c4.tar.gz
New Kodak DC210 driver by Michael Koltan
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@5134 67ed7778-7388-44ab-90cf-0a291f65f57c
-rw-r--r--MAINTAINERS3
-rw-r--r--camlibs/kodak/CAMERAS6
-rw-r--r--camlibs/kodak/Makefile.am2
-rw-r--r--camlibs/kodak/dc210/ChangeLog5
-rw-r--r--camlibs/kodak/dc210/Makefile.am2
-rw-r--r--camlibs/kodak/dc210/dc210.c891
-rw-r--r--camlibs/kodak/dc210/dc210.h203
-rw-r--r--camlibs/kodak/dc210/kodak.df2
-rw-r--r--camlibs/kodak/dc210/library.c1636
-rw-r--r--camlibs/kodak/dc210/library.h125
-rw-r--r--camlibs/kodak/dc210/makefile.os222
-rw-r--r--camlibs/makefile.os23
-rw-r--r--configure.in1
13 files changed, 1925 insertions, 976 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 0549edfbd..9fff61b60 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -53,6 +53,9 @@ camlibs/kodak/dc120:
camlibs/kodak/dc240:
Hubert Figuiere <hfiguiere@teaser.fr>
+camlibs/largan/lmini
+ Hubert Figuiere <hfiguiere@teaser.fr>
+
camlibs/mustek:
Marcus Meissner <marcus@jet.franken.de>
diff --git a/camlibs/kodak/CAMERAS b/camlibs/kodak/CAMERAS
index 6f79003ab..a24adc196 100644
--- a/camlibs/kodak/CAMERAS
+++ b/camlibs/kodak/CAMERAS
@@ -7,14 +7,14 @@ kodak/dc240
DC-240, DC-280, DC-3400, DC-5000
kodak/dc120
DC-120
+kodak/dc210
+ DC-200 DC-210 DC-215
kodak/dc3200
DC-3200
ptp [*]
DC-4800, DX-3215, DX-3500, DX-3600, DX-3700, DX-3900
none
DC-3800 [**]
-dc210 [***]
- DC-200, DC-210, DC-215
dc20 [***]
DC-20, DC-25
@@ -24,6 +24,6 @@ dc20 [***]
implemented in jphoto. http://jphoto.sourceforge.net/
[**] DC-3800 can't be connected to a computer. Use CompactFlash
reader instead.
-[***] dc210 and dc20 no longer exists in gphoto2.
+[***] dc20 no longer exists in gphoto2.
diff --git a/camlibs/kodak/Makefile.am b/camlibs/kodak/Makefile.am
index 8ee1e71a3..5f647593c 100644
--- a/camlibs/kodak/Makefile.am
+++ b/camlibs/kodak/Makefile.am
@@ -1,5 +1,5 @@
## Process this file with automake to generate a GNU Makefile
-SUBDIRS = dc120 dc240 dc3200
+SUBDIRS = dc120 dc210 dc240 dc3200
EXTRA_DIST = CAMERAS
diff --git a/camlibs/kodak/dc210/ChangeLog b/camlibs/kodak/dc210/ChangeLog
new file mode 100644
index 000000000..cec467ee7
--- /dev/null
+++ b/camlibs/kodak/dc210/ChangeLog
@@ -0,0 +1,5 @@
+2002-08-24 Michael Koltan <koltan@gmx.de>
+
+ * first version submitted for testing
+
+
diff --git a/camlibs/kodak/dc210/Makefile.am b/camlibs/kodak/dc210/Makefile.am
index b22f5e963..d7616d3d0 100644
--- a/camlibs/kodak/dc210/Makefile.am
+++ b/camlibs/kodak/dc210/Makefile.am
@@ -1,3 +1,5 @@
+EXTRA_DIST = kodak.df makefile.os2
+
camlibdir = $(libdir)/gphoto2/$(VERSION)
camlib_LTLIBRARIES = libgphoto2_kodak_dc210.la
diff --git a/camlibs/kodak/dc210/dc210.c b/camlibs/kodak/dc210/dc210.c
index 374abfc52..f3960e285 100644
--- a/camlibs/kodak/dc210/dc210.c
+++ b/camlibs/kodak/dc210/dc210.c
@@ -1,12 +1,7 @@
-/*
- DC210 driver
- Copyright (c) 2001 Hubert Figuiere
- */
-
#include <config.h>
-#include <stdio.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <time.h>
@@ -16,8 +11,8 @@
#ifdef ENABLE_NLS
# include <libintl.h>
# undef _
-# define _(String) dgettext (PACKAGE, String)
# ifdef gettext_noop
+# define _(String) dgettext (PACKAGE, String)
# define N_(String) gettext_noop (String)
# else
# define _(String) (String)
@@ -29,385 +24,647 @@
#endif
#include "dc210.h"
-#include "library.h"
-int camera_id (CameraText *id)
-{
- strcpy(id->text, "REPLACE WITH UNIQUE LIBRARY ID");
-
- return (GP_OK);
-}
+char * exp_comp[] = {"-2.0 EV", "-1.5 EV", "-1.0 EV", "-0.5 EV", "AUTO", "+0.5 EV",
+ "+1.0 EV", "+1.5 EV", "+2.0 EV"};
-int camera_abilities (CameraAbilitiesList *list)
-{
- CameraAbilities a;
-
- memset(&a, 0, sizeof(a));
- strcpy(a.model, "Kodak DC210");
- a.port = GP_PORT_SERIAL;
- a.speed[0] = 9600;
- a.speed[1] = 19200;
- a.speed[2] = 38400;
- a.speed[3] = 57600;
- a.speed[4] = 115200;
- a.speed[5] = 0;
- a.operations = GP_OPERATION_CAPTURE_IMAGE;
- 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);
-}
+int camera_id (CameraText *id) {
-int camera_init (Camera *camera)
-{
- gp_port_settings settings;
+ strcpy(id->text, GP_MODULE);
- DC210Data *dd;
- int ret;
-
- if (!camera) {
- return (GP_ERROR);
- }
-
- dd = (DC210Data *)malloc (sizeof (DC210Data));
- if (dd == NULL) {
- return GP_ERROR;
- }
-
- /* First, set up all the function pointers */
- camera->functions->id = camera_id;
- camera->functions->abilities = camera_abilities;
- camera->functions->init = camera_init;
- camera->functions->exit = camera_exit;
- camera->functions->folder_list_folders = camera_folder_list_folders;
- camera->functions->folder_list_files = camera_folder_list_files;
- camera->functions->file_get = camera_file_get;
- camera->functions->file_delete = camera_file_delete;
-#if 0
- camera->functions->config_get = camera_config_get;
- camera->functions->config_set = camera_config_set;
- camera->functions->folder_config_get = camera_folder_config_get;
- camera->functions->folder_config_set = camera_folder_config_set;
- camera->functions->file_config_get = camera_file_config_get;
- camera->functions->file_config_set = camera_file_config_set;
-#endif
- camera->functions->capture = camera_capture;
- camera->functions->summary = camera_summary;
- camera->functions->manual = camera_manual;
- camera->functions->about = camera_about;
- camera->functions->result_as_string = camera_result_as_string;
-
- switch (camera->port->type) {
- case GP_PORT_SERIAL:
- if ((ret = gp_port_new(&(dd->dev), GP_PORT_SERIAL)) < 0) {
- free(dd);
- return (GP_ERROR);
- }
- strcpy(settings.serial.port, camera->port->path);
- settings.serial.speed = 9600;
- settings.serial.bits = 8;
- settings.serial.parity = 0;
- settings.serial.stopbits = 1;
- break;
- default:
- return GP_ERROR;
- break;
- }
+ return (GP_OK);
+}
- if (gp_port_settings_set(dd->dev, settings) == GP_ERROR) {
- gp_port_free(dd->dev);
- free(dd);
- return (GP_ERROR);
- }
+int camera_abilities (CameraAbilitiesList *list) {
- if (gp_port_open(dd->dev) == GP_ERROR) {
- gp_port_free(dd->dev);
- free(dd);
- return (GP_ERROR);
- }
+ CameraAbilities a;
- /* timeout is set to 1500 */
- gp_port_timeout_set (dd->dev, 1500);
+ memset (&a, 0, sizeof(a));
+ strcpy(a.model, "Kodak DC210");
+ a.status = GP_DRIVER_STATUS_EXPERIMENTAL;
+ a.port = GP_PORT_SERIAL;
+ a.speed[0] = 9600;
+ a.speed[1] = 19200;
+ a.speed[2] = 38400;
+ a.speed[3] = 57600;
+ a.speed[4] = 115200;
+ a.speed[5] = 0;
+ a.operations = GP_OPERATION_CAPTURE_IMAGE | GP_OPERATION_CONFIG;
+ a.file_operations = GP_FILE_OPERATION_NONE;
+ a.folder_operations = GP_FOLDER_OPERATION_NONE;
- /* Reset the camera to 9600 by sending a break. */
- gp_port_send_break(dd->dev, 1);
-
- /* Wait for it to reset */
- GP_SYSTEM_SLEEP(1500);
-
- if (kodak_dc210_open_camera(dd) == GP_ERROR) {
- gp_port_close(dd->dev);
- gp_port_free(dd->dev);
- free(dd);
- return (GP_ERROR);
- }
+ gp_abilities_list_append(list, a);
- camera->camlib_data = dd;
-
-
-
- return (GP_OK);
+ return (GP_OK);
}
-int camera_exit (Camera *camera)
+static int file_list_func (CameraFilesystem *fs, const char *folder,
+ CameraList *list, void *data, GPContext *context)
{
- int ret;
- DC210Data * dd = (DC210Data *)camera->camlib_data;
-
- ret = kodak_dc210_close_camera (dd);
-
- if (dd->dev) {
- gp_port_close(dd->dev);
- if (ret == GP_ERROR) {
- gp_debug_printf (GP_DEBUG_LOW, "dc210",
- "%s,%d: gp_port_close = %d",
- __FILE__, __LINE__, ret);
-
- }
- gp_port_free(dd->dev);
- }
- free(dd);
-
- return ret;
+ Camera *camera = data;
+
+ return dc210_get_filenames(camera, list, context);
+
}
-int camera_folder_list_folders (Camera *camera, const char *folder,
- CameraList *list)
+static int get_file_func (CameraFilesystem *fs, const char *folder,
+ const char *filename, CameraFileType type,
+ CameraFile *file, void *data, GPContext *context)
{
- /* there is only one folder */
- /* don't list */
- gp_debug_printf (GP_DEBUG_LOW, "dc210",
- "%s,%d: camera_folder_list_folders: unimplemented",
- __FILE__, __LINE__);
-
- return (GP_ERROR);
+ Camera *camera = data;
+
+ switch (type) {
+ case GP_FILE_TYPE_NORMAL:
+ return dc210_download_picture_by_name(camera, file, filename, 0, context);
+ case GP_FILE_TYPE_PREVIEW:
+ return dc210_download_picture_by_name(camera, file, filename, 1, context);
+ default:
+ return (GP_ERROR_NOT_SUPPORTED);
+ };
}
-int camera_folder_list_files (Camera *camera, const char *folder,
- CameraList *list)
+static int delete_file_func (CameraFilesystem *fs, const char *folder,
+ const char *filename, void *data,
+ GPContext *context)
{
- int ret;
- DC210Data * dd = (DC210Data *)camera->camlib_data;
+ Camera *camera = data;
- ret = kodak_dc210_get_directory_listing (dd, list);
-/* gp_debug_printf (GP_DEBUG_LOW, "dc210",
- "kodak_dc210_get_picture_info failed %d", ret);*/
- return ret;
-}
+ return dc210_delete_picture_by_name(camera, filename);
+};
-/*
- Possible ops are:
- -getPic 0;
- -getThumbnail 1;
- -delete 2;
- */
-static int _camera_file_op (Camera *camera, const char *folder,
- const char *filename, CameraFile *file, int op)
+static int get_info_func (CameraFilesystem *fs, const char *folder, const char *file,
+ CameraFileInfo *info, void *data, GPContext *context)
{
- int ret = GP_OK;
- int count = 0;
- int i;
- CameraList * list;
- const char * current;
- DC210Data * dd = (DC210Data *)camera->camlib_data;
-
- if (!dd) {
- gp_debug_printf (GP_DEBUG_LOW, "dc210", "%s,%d: unable to get dd",
- __FILE__, __LINE__);
- return GP_ERROR;
- }
-
- gp_list_new (&list);
- ret = kodak_dc210_get_directory_listing (dd, list);
- count = gp_list_count (list);
-
- for (i = 0; i < count; i++) {
- gp_list_get_name (list, i, &current);
- if (current == NULL) {
- /* ERROR */
- ret = GP_ERROR;
- break;
- }
-
- if (strcmp (current, filename) == 0) {
- /* picture found */
- switch (op) {
- case 0:
- ret = kodak_dc210_get_picture (dd, i, file);
- break;
- case 1:
- ret = kodak_dc210_get_thumbnail (dd, i, file);
- break;
- case 2:
- ret = kodak_dc210_delete_picture (dd, i);
- break;
- default:
- gp_debug_printf (GP_DEBUG_LOW, "dc210",
- "%s,%d: unknown file op = %d",
- __FILE__, __LINE__, op);
- /* DOH ! */
- break;
- }
- /* we found our file */
- break;
- }
- }
- gp_list_free (list);
- gp_debug_printf (GP_DEBUG_LOW, "dc210", "%s,%d: file op completed = %d",
- __FILE__, __LINE__, ret);
- return ret;
-}
-
+ Camera *camera = data;
+ int picno;
+ dc210_picture_info picinfo;
+
+ picno = dc210_get_picture_number(camera, file);
+
+ if (picno < 1) return GP_ERROR;
+
+ if (dc210_get_picture_info(camera, &picinfo, picno) == GP_ERROR)
+ return GP_ERROR;
+
+ info->preview.fields |= GP_FILE_INFO_TYPE;
+ info->preview.fields |= GP_FILE_INFO_NAME;
+ info->preview.fields |= GP_FILE_INFO_SIZE;
+ info->preview.fields |= GP_FILE_INFO_WIDTH;
+ info->preview.fields |= GP_FILE_INFO_HEIGHT;
+
+ strcpy(info->preview.type, GP_MIME_PPM);
+ info->preview.width = 96;
+ info->preview.height = 72;
+ info->preview.size = picinfo.preview_size;
+ strncpy(info->file.name, picinfo.image_name, 9);
+ strncpy(info->file.name + 9, "PPM\0", 4);
+
+ info->file.fields |= GP_FILE_INFO_TYPE;
+ info->file.fields |= GP_FILE_INFO_NAME;
+ info->file.fields |= GP_FILE_INFO_SIZE;
+ info->file.fields |= GP_FILE_INFO_WIDTH;
+ info->file.fields |= GP_FILE_INFO_HEIGHT;
+ info->file.fields |= GP_FILE_INFO_MTIME;
+
+ info->file.size = picinfo.picture_size;
+ switch(picinfo.file_type){
+ case DC210_FILE_TYPE_JPEG:
+ strcpy(info->file.type, GP_MIME_JPEG); break;
+ case DC210_FILE_TYPE_FPX:
+ strcpy(info->file.type, GP_MIME_UNKNOWN); break;
+ };
+ switch(picinfo.resolution){
+ case DC210_FILE_640:
+ info->file.width = 640;
+ info->file.height = 480;
+ break;
+ case DC210_FILE_1152:
+ info->file.width = 1152;
+ info->file.height = 864;
+ break;
+ };
+ strncpy(info->file.name, picinfo.image_name, 13);
+ info->file.mtime = picinfo.picture_time;
+
+ info->audio.fields |= GP_FILE_INFO_NONE;
+
+ return GP_OK;
+
+};
+
+
+static int
+camera_get_config (Camera *camera, CameraWidget **window, GPContext *context)
+{
+ CameraWidget *section, *widget;
+ CameraAbilities abilities;
+ GPPortSettings settings;
+ int i;
+ char * wvalue;
+ char stringbuffer[12];
+
+ dc210_status status;
+
+ if (dc210_get_status(camera, &status) == GP_ERROR) return GP_ERROR;
+
+ gp_widget_new (GP_WIDGET_WINDOW, _("Camera Configuration"), window);
+
+ gp_widget_new (GP_WIDGET_SECTION, _("File"), &section);
+ gp_widget_append (*window, section);
+
+ gp_widget_new (GP_WIDGET_RADIO, _("File type"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_add_choice (widget, _("JPEG"));
+ gp_widget_add_choice (widget, _("FlashPix"));
+
+ switch (status.file_type){
+ case DC210_FILE_TYPE_JPEG:
+ gp_widget_set_value (widget, _("JPEG")); break;
+ case DC210_FILE_TYPE_FPX:
+ gp_widget_set_value (widget, _("FlashPix")); break;
+ };
+ gp_widget_get_value (widget, &wvalue);
+
+ gp_widget_new (GP_WIDGET_RADIO, _("File resolution"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_add_choice (widget, _("640 x 480"));
+ gp_widget_add_choice (widget, _("1152 x 864"));
+
+ switch (status.resolution){
+ case DC210_FILE_640:
+ gp_widget_set_value (widget, _("640 x 480")); break;
+ case DC210_FILE_1152:
+ gp_widget_set_value (widget, _("1152 x 864")); break;
+ default:
+ DC210_DEBUG("Undefined value for file resolution.\n"); break;
+ };
+ gp_widget_get_value (widget, &wvalue);
+
+ gp_widget_new (GP_WIDGET_MENU, _("File compression"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_add_choice (widget, _("Low (best quality)"));
+ gp_widget_add_choice (widget, _("Medium (better quality)"));
+ gp_widget_add_choice (widget, _("High (good quality)"));
+
+ switch (status.compression_type){
+ case DC210_LOW_COMPRESSION:
+ gp_widget_set_value (widget, _("Low (best quality)")); break;
+ case DC210_MEDIUM_COMPRESSION:
+ gp_widget_set_value (widget, _("Medium (better quality)")); break;
+ case DC210_HIGH_COMPRESSION:
+ gp_widget_set_value (widget, _("High (good quality)")); break;
+ };
+ gp_widget_get_value (widget, &wvalue);
+
+ gp_widget_new (GP_WIDGET_SECTION, _("Capture"), &section);
+ gp_widget_append (*window, section);
+
+ gp_widget_new (GP_WIDGET_MENU, _("Zoom"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_add_choice (widget, _("58 mm"));
+ gp_widget_add_choice (widget, _("51 mm"));
+ gp_widget_add_choice (widget, _("41 mm"));
+ gp_widget_add_choice (widget, _("34 mm"));
+ gp_widget_add_choice (widget, _("29 mm"));
+ gp_widget_add_choice (widget, _("Macro"));
+
+ switch (status.zoom){
+ case DC210_ZOOM_58:
+ gp_widget_set_value (widget, _("58 mm")); break;
+ case DC210_ZOOM_51:
+ gp_widget_set_value (widget, _("51 mm")); break;
+ case DC210_ZOOM_41:
+ gp_widget_set_value (widget, _("41 mm")); break;
+ case DC210_ZOOM_34:
+ gp_widget_set_value (widget, _("34 mm")); break;
+ case DC210_ZOOM_29:
+ gp_widget_set_value (widget, _("29 mm")); break;
+ case DC210_ZOOM_MACRO:
+ gp_widget_set_value (widget, _("Macro")); break;
+ };
+ gp_widget_get_value (widget, &wvalue);
+
+ gp_widget_new (GP_WIDGET_MENU, _("Exposure compensation"), &widget);
+ gp_widget_append (section, widget);
+ for (i = 0; i < sizeof(exp_comp)/sizeof(*exp_comp); i++){
+ gp_widget_add_choice (widget, exp_comp[i]);
+ if (status.exp_compensation + 4 == i)
+ gp_widget_set_value (widget, exp_comp[i]);
+ };
+
+ gp_widget_new (GP_WIDGET_RADIO, _("Flash"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_add_choice (widget, _("Auto"));
+ gp_widget_add_choice (widget, _("Force"));
+ gp_widget_add_choice (widget, _("None"));
+
+ switch (status.flash){
+ case DC210_FLASH_AUTO:
+ gp_widget_set_value (widget, _("Auto")); break;
+ case DC210_FLASH_FORCE:
+ gp_widget_set_value (widget, _("Force")); break;
+ case DC210_FLASH_NONE:
+ gp_widget_set_value (widget, _("None")); break;
+ };
+ gp_widget_get_value (widget, &wvalue);
+
+ gp_widget_new (GP_WIDGET_RADIO, _("Red eye flash"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_add_choice (widget, _("On"));
+ gp_widget_add_choice (widget, _("Off"));
+
+ if (status.preflash)
+ gp_widget_set_value (widget, _("On"));
+ else
+ gp_widget_set_value (widget, _("Off"));
+ gp_widget_get_value (widget, &wvalue);
+
+ gp_widget_new (GP_WIDGET_SECTION, _("Other"), &section);
+ gp_widget_append (*window, section);
+
+ gp_widget_new (GP_WIDGET_BUTTON, "Set time to system time", &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, dc210_system_time_callback);
+ gp_widget_set_info (widget, _("Set clock in camera"));
+
+ gp_camera_get_abilities(camera, &abilities);
+ gp_port_get_settings (camera->port, &settings);
+ gp_widget_new (GP_WIDGET_MENU, _("Port speed"), &widget);
+ gp_widget_append (section, widget);
+ for (i = 0; i < sizeof(abilities.speed); i++){
+ if (abilities.speed[i] == 0) break;
+ snprintf(stringbuffer, 12, "%d", abilities.speed[i]);
+ gp_widget_add_choice (widget, stringbuffer);
+ if (settings.serial.speed == abilities.speed[i])
+ gp_widget_set_value (widget, stringbuffer);
+ };
+
+ gp_widget_new (GP_WIDGET_TEXT, _("Album name"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, status.album_name);
+ gp_widget_set_info (widget, _("Name to set on card when formatting."));
+
+ gp_widget_new (GP_WIDGET_BUTTON, _("Format compact flash"), &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, dc210_format_callback);
+ gp_widget_set_info (widget, _("Format card and set album name."));
+
+#ifdef DEBUG
+ gp_widget_new (GP_WIDGET_SECTION, _("Debug"), &section);
+ gp_widget_append (*window, section);
+
+ gp_widget_new (GP_WIDGET_TEXT, "Parameter 1", &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, "0");
+
+ gp_widget_new (GP_WIDGET_TEXT, "Parameter 2", &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, "0");
+
+ gp_widget_new (GP_WIDGET_TEXT, "Parameter 3", &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, "0");
+
+ gp_widget_new (GP_WIDGET_BUTTON, "Execute debug command", &widget);
+ gp_widget_append (section, widget);
+ gp_widget_set_value (widget, dc210_debug_callback);
+ gp_widget_set_info (widget, _("Execute predefined command\nwith parameter values."));
+#endif
-/* Get the file */
-int camera_file_get (Camera *camera, const char *folder, const char *filename,
- CameraFileType type, CameraFile *file)
-{
- switch (type)
- {
- case GP_FILE_TYPE_NORMAL:
- return _camera_file_op (camera, folder, filename, file, 0);
- break;
- case GP_FILE_TYPE_PREVIEW:
- return _camera_file_op (camera, folder, filename, file, 1);
- break;
- default:
- return GP_ERROR_NOT_SUPPORTED;
- }
+ return GP_OK;
}
-
-int camera_folder_put_file (Camera *camera, const char *folder,
- CameraFile *file)
+static int
+camera_set_config (Camera *camera, CameraWidget *window, GPContext *context)
{
- /* not supported */
- return GP_ERROR;
+ CameraWidget *w, *w2;
+ char *wvalue, *w2value;
+ int i;
+
+ gp_widget_get_child_by_label (window, _("File type"), &w);
+ if (gp_widget_changed (w)) {
+ gp_widget_get_value (w, &wvalue);
+ if (wvalue[0] == 'J')
+ dc210_set_file_type(camera, DC210_FILE_TYPE_JPEG);
+ else
+ dc210_set_file_type(camera, DC210_FILE_TYPE_FPX);
+ };
+
+ gp_widget_get_child_by_label (window, _("File resolution"), &w);
+ if (gp_widget_changed (w)) {
+ gp_widget_get_value (w, &wvalue);
+ switch(wvalue[0]){
+ case '6':
+ dc210_set_resolution(camera, DC210_FILE_640);
+ break;
+ case '1':
+ dc210_set_resolution(camera, DC210_FILE_1152);
+ break;
+ };
+ };
+
+ gp_widget_get_child_by_label (window, _("File compression"), &w);
+ if (gp_widget_changed (w)) {
+ gp_widget_get_value (w, &wvalue);
+ switch(wvalue[0]){
+ case 'L':
+ dc210_set_compression(camera, DC210_LOW_COMPRESSION);
+ break;
+ case 'M':
+ dc210_set_compression(camera, DC210_MEDIUM_COMPRESSION);
+ break;
+ case 'H':
+ dc210_set_compression(camera, DC210_HIGH_COMPRESSION);
+ };
+ };
+
+ gp_widget_get_child_by_label (window, _("Zoom"), &w);
+ if (gp_widget_changed (w)) {
+ gp_widget_get_value (w, &wvalue);
+ switch(wvalue[0]){
+ case '5':
+ if (wvalue[1] == '8')
+ dc210_set_zoom(camera, DC210_ZOOM_58);
+ else
+ dc210_set_zoom(camera, DC210_ZOOM_51);
+ break;
+ case '4':
+ dc210_set_zoom(camera, DC210_ZOOM_41);
+ break;
+ case '3':
+ dc210_set_zoom(camera, DC210_ZOOM_34);
+ break;
+ case '2':
+ dc210_set_zoom(camera, DC210_ZOOM_29);
+ break;
+ case 'M':
+ dc210_set_zoom(camera, DC210_ZOOM_MACRO);
+ break;
+ };
+ };
+
+ gp_widget_get_child_by_label (window, _("Exposure compensation"), &w);
+ if (gp_widget_changed (w)) {
+ gp_widget_get_value (w, &wvalue);
+ for (i = 0; i < sizeof(exp_comp)/sizeof(*exp_comp); i++){
+ if (strncmp(wvalue, exp_comp[i], 4) == 0){
+ dc210_set_exp_compensation(camera, i - 4);
+ break;
+ };
+ };
+ };
+
+ gp_widget_get_child_by_label (window, _("Port speed"), &w);
+ if (gp_widget_changed (w)) {
+ gp_widget_get_value (w, &wvalue);
+ dc210_set_speed(camera, atoi(wvalue));
+ };
+
+ gp_widget_get_child_by_label (window, _("Flash"), &w);
+ gp_widget_get_child_by_label (window, _("Red eye flash"), &w2);
+ if (gp_widget_changed (w) || gp_widget_changed(w2)) {
+ gp_widget_get_value (w, &wvalue);
+ gp_widget_get_value (w2, &w2value);
+ switch(wvalue[0]){
+ case 'A':
+ dc210_set_flash(camera, DC210_FLASH_AUTO,
+ w2value[1] == 'n' ? 1 : 0);
+ break;
+ case 'F':
+ dc210_set_flash(camera, DC210_FLASH_FORCE,
+ w2value[1] == 'n' ? 1 : 0);
+ break;
+ case 'N':
+ dc210_set_flash(camera, DC210_FLASH_NONE, 0);
+ gp_widget_set_value(w2, _("Off"));
+ break;
+ };
+ };
+
+ return GP_OK;
}
-int camera_file_delete (Camera *camera, const char *folder,
- const char *filename)
-{
- return _camera_file_op (camera, folder, filename, NULL, 2);
-}
+static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) {
-#if 0
-int camera_config_get (Camera *camera, CameraWidget **window)
-{
- *window = gp_widget_new (GP_WIDGET_WINDOW, "Camera Configuration");
+ if (type && type != GP_OPERATION_CAPTURE_IMAGE){
+ DC210_DEBUG("Unsupported action 0x%.2X\n", type);
+ return (GP_ERROR_NOT_SUPPORTED);
+ };
- // Append your sections and widgets here.
+ if (dc210_capture(camera, path, context) == GP_ERROR)
+ return GP_ERROR;
- return (GP_OK);
-}
+ if (gp_filesystem_append (camera->fs, path->folder, path->name, context) == GP_ERROR)
+ return GP_ERROR;;
-int camera_config_set (Camera *camera, CameraWidget *window)
-{
- // Check, if the widget's value have changed.
+ return (GP_OK);
- return (GP_OK);
}
-#endif
-int camera_capture (Camera *camera, int capture_type, CameraFilePath *path)
-{
- int ret = GP_OK;
- int numPicBefore;
- int numPicAfter;
- struct kodak_dc210_picture_info picInfo;
- DC210Data * dd = (DC210Data *)camera->camlib_data;
-
- /* find out how many pictures are in the camera so we can
- make sure a picture was taken later */
- numPicBefore = kodak_dc210_number_of_pictures(dd);
-
- /* take a picture -- it returns the picture number taken */
- numPicAfter = kodak_dc210_capture (dd);
-
- /* if a picture was taken then get the picture from the camera and
- then delete it */
- if (numPicBefore + 1 == numPicAfter)
- {
- strcpy (path->folder, "/");
- ret = kodak_dc210_get_picture_info (dd, numPicAfter, &picInfo);
- strncpy (path->name, picInfo.fileName, 12);
- path->name[12] = 0;
- }
-
- return ret;
-}
-
-int camera_summary (Camera *camera, CameraText *summary)
+static int camera_summary (Camera *camera, CameraText *summary,
+ GPContext *context)
{
static char summary_string[2048] = "";
char buff[1024];
- struct kodak_dc210_status status;
+ dc210_status status;
- DC210Data * dd = (DC210Data *)camera->camlib_data;
-
- if (kodak_dc210_get_camera_status (dd, &status))
+ if (GP_OK == dc210_get_status (camera, &status))
{
strcpy(summary_string,"Kodak DC210\n");
- snprintf(buff,1024,"Camera Identification: %s\n",status.camera_ident);
+ snprintf(buff,1024,"Pictures in camera: %d\n",
+ status.numPicturesInCamera);
strcat(summary_string,buff);
-
- snprintf(buff,1024,"Camera Type: %d\n",status.camera_type_id);
+
+ snprintf(buff,1024,"There is space for another\n %d low compressed\n %d medium compressed or\n %d high compressed pictures\n",
+ status.remainingLow, status.remainingMedium, status.remainingHigh);
strcat(summary_string,buff);
-
- snprintf(buff,1024,"Firmware: %d.%d\n",status.firmware_major,status.firmware_minor);
+
+ snprintf(buff,1024,"Total pictures taken: %d\n",
+ status.totalPicturesTaken);
strcat(summary_string,buff);
-
- snprintf(buff,1024,"Battery Status: %d\n",status.batteryStatusId);
+
+ snprintf(buff,1024,"Total flashes fired: %d\n",
+ status.totalFlashesFired);
strcat(summary_string,buff);
-
- snprintf(buff,1024,"AC Status: %d\n",status.acStatusId);
+
+ snprintf(buff,1024,"Firmware: %d.%d\n",status.firmwareMajor,status.firmwareMinor);
strcat(summary_string,buff);
+
+ switch (status.file_type){
+ case DC210_FILE_TYPE_JPEG:
+ snprintf(buff, 1024, "Filetype: JPEG ("); break;
+ case DC210_FILE_TYPE_FPX:
+ snprintf(buff, 1024, "Filetype: FlashPix ("); break;
+ };
+ strcat(summary_string, buff);
+
+ switch (status.compression_type){
+ case DC210_LOW_COMPRESSION:
+ snprintf(buff, 1024, "low compression, "); break;
+ case DC210_MEDIUM_COMPRESSION:
+ snprintf(buff, 1024, "medium compression, "); break;
+ case DC210_HIGH_COMPRESSION:
+ snprintf(buff, 1024, "high compression, "); break;
+ default:
+ snprintf(buff, 1024, "unknown compression %d, ", status.compression_type); break;
+ };
+ strcat(summary_string, buff);
- strftime(buff,1024,"Time: %a, %d %b %y %T\n",localtime((time_t *)&status.time));
+ switch (status.resolution){
+ case DC210_FILE_640:
+ snprintf(buff, 1024, "640x480 pixel)\n"); break;
+ case DC210_FILE_1152:
+ snprintf(buff, 1024, "1152x864 pixel)\n"); break;
+ default:
+ snprintf(buff, 1024, "unknown resolution %d)\n", status.resolution); break;
+ };
+ strcat(summary_string, buff);
+
+ if (status.fast_preview)
+ snprintf(buff, 1024, "Fast preview is on\n");
+ else
+ snprintf(buff, 1024, "Fast preview is off\n");
+ strcat(summary_string, buff);
+
+ switch (status.battery){
+ case 0: snprintf(buff,1024,"Battery charge is good\n"); break;
+ case 1: snprintf(buff,1024,"Battery charge is low\n"); break;
+ case 2: snprintf(buff,1024,"Battery is not charged\n"); break;
+ };
strcat(summary_string,buff);
- fprintf(stderr,"step 4\n");
- snprintf(buff,1024,"Total Pictures Taken: %d\n",status.totalPicturesTaken);
+ if (status.acstatus)
+ snprintf(buff,1024,"AC adapter is connected\n");
+ else
+ snprintf(buff,1024,"AC adapter is not connected\n");
strcat(summary_string,buff);
- snprintf(buff,1024,"Total Flashes Fired: %d\n",status.totalFlashesFired);
+ strftime(buff,1024,"Time: %a, %d %b %Y %T\n",
+ localtime((time_t *)&status.time));
strcat(summary_string,buff);
- snprintf(buff,1024,"Pictures in Camera: %d\n",status.num_pictures);
+ switch (status.zoom){
+ case DC210_ZOOM_58:
+ snprintf(buff, 1024, "Zoom: 58 mm\n"); break;
+ case DC210_ZOOM_51:
+ snprintf(buff, 1024, "Zoom: 51 mm\n"); break;
+ case DC210_ZOOM_41:
+ snprintf(buff, 1024, "Zoom: 41 mm\n"); break;
+ case DC210_ZOOM_34:
+ snprintf(buff, 1024, "Zoom: 34 mm\n"); break;
+ case DC210_ZOOM_29:
+ snprintf(buff, 1024, "Zoom: 29 mm\n"); break;
+ case DC210_ZOOM_MACRO:
+ snprintf(buff, 1024, "Zoom: macro\n"); break;
+ default:
+ snprintf(buff, 1024, "Unknown zoom mode %d\n",
+ status.zoom); break;
+ };
strcat(summary_string,buff);
+ if (status.exp_compensation > -5 && status.exp_compensation < 4)
+ snprintf(buff, 1024, "Exposure compensation: %s\n", exp_comp[status.exp_compensation + 4]);
+ else
+ snprintf(buff, 1024, "Exposure compensation: %d\n", status.exp_compensation);
+ strcat(summary_string,buff);
+
+ switch (status.flash){
+ case DC210_FLASH_AUTO:
+ snprintf(buff, 1024, "Flash mode: auto, "); break;
+ case DC210_FLASH_FORCE:
+ snprintf(buff, 1024, "Flash mode: force, "); break;
+ case DC210_FLASH_NONE:
+ snprintf(buff, 1024, "Flash mode: off\n"); break;
+ default:
+ snprintf(buff, 1024, "Unknown flash mode %d, ",
+ status.flash); break;
+ };
+ strcat(summary_string,buff);
+
+ if (status.flash != DC210_FLASH_NONE){
+ if (status.preflash)
+ snprintf(buff,1024,"red eye flash on\n");
+ else
+ snprintf(buff,1024,"red eye flash off\n");
+ strcat(summary_string,buff);
+ };
+
+ if (status.card_space == -1)
+ snprintf(buff, 1024, "No card in camera.\n");
+ else
+ snprintf(buff,1024,"Card name: %s\nFree space on card: %d kilobytes\n",
+ status.album_name,
+ status.card_space);
+
+ strcat(summary_string,buff);
+
}
+ else{
+ DC210_DEBUG("Couldn't get summary for camera\n");
+ };
- strcpy(summary->text, buff);
+ strcpy(summary->text, summary_string);
return (GP_OK);
}
-int camera_manual (Camera *camera, CameraText *manual)
+
+static int camera_manual (Camera *camera, CameraText *manual,
+ GPContext *context)
{
- strcpy(manual->text, _("No Manual Available"));
-
- return (GP_OK);
+ strcpy (manual->text, _("This library has been tested with a Kodak DC 215 Zoom camera. "
+ "It might work also with DC 200 and DC 210 cameras. "
+ "If you happen to have such a camera, please send a "
+ "message to koltan@gmx.de to let me know, if you have any "
+ "troubles with this driver library or if everything is okay."));
+
+ return (GP_OK);
}
-int camera_about (Camera *camera, CameraText *about)
+static int camera_about (Camera *camera, CameraText *about, GPContext *context)
{
strcpy(about->text,
- "Kodak DC210 Camera Library\n
-by Brian Hirt <bhirt@mobygames.com> http://www.mobygames.com\n
-gphoto2 port by Hubert Figuiere <hfiguiere@teaser.fr>");
-
+ _("Camera Library for the Kodak DC215 Zoom camera.\n"
+ "Michael Koltan <koltan@gmx.de>\n"));
+
return (GP_OK);
}
-char* camera_result_as_string (Camera *camera, int result)
-{
- if (result >= 0) return ("This is not an error...");
- if (-result < 100) return gp_result_as_string (result);
- return ("This is a template specific error.");
+int camera_init (Camera *camera, GPContext *context) {
+
+ /* First, set up all the function pointers */
+ camera->functions->get_config = camera_get_config;
+ camera->functions->set_config = camera_set_config;
+ camera->functions->capture = camera_capture;
+ camera->functions->summary = camera_summary;
+ camera->functions->manual = camera_manual;
+ camera->functions->about = camera_about;
+
+ 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);
+
+ if (dc210_set_speed (camera, 115200) == GP_ERROR) {
+ DC210_DEBUG("Error setting camera speed\n");
+ return GP_ERROR;
+ };
+
+
+ return (GP_OK);
}
+
+
+/****************************************************************************/
+
+
+
+
+
+
+
diff --git a/camlibs/kodak/dc210/dc210.h b/camlibs/kodak/dc210/dc210.h
index 55c16337e..cc989784d 100644
--- a/camlibs/kodak/dc210/dc210.h
+++ b/camlibs/kodak/dc210/dc210.h
@@ -1,15 +1,206 @@
+#ifndef _DC210_H_
+#define _DC210_H_
+typedef enum {
+ DC210_TOGGLE_OFF = 0,
+ DC210_TOGGLE_ON = 1
+} dc210_toggle_type;
-#ifndef __DC210_H__
-#define __DC210_H__
+typedef enum {
+ DC210_FILE_TYPE_JPEG = 3,
+ DC210_FILE_TYPE_FPX = 4
+} dc210_file_type_type;
-#include <gphoto2-port.h>
+typedef enum {
+ DC210_FLASH_AUTO = 0,
+ DC210_FLASH_FORCE = 1,
+ DC210_FLASH_NONE = 2
+} dc210_flash_type;
+typedef enum {
+ DC210_FILE_640 = 0,
+ DC210_FILE_1152 = 1
+} dc210_resolution_type;
+
+typedef enum {
+ DC210_LOW_COMPRESSION = 1,
+ DC210_MEDIUM_COMPRESSION = 2,
+ DC210_HIGH_COMPRESSION = 3
+
+} dc210_compression_type;
+
+typedef enum {
+ DC210_ZOOM_58 = 0,
+ DC210_ZOOM_51 = 1,
+ DC210_ZOOM_41 = 2,
+ DC210_ZOOM_34 = 3,
+ DC210_ZOOM_29 = 4,
+ DC210_ZOOM_MACRO = 37
+} dc210_zoom_type;
typedef struct {
- gp_port *dev;
- /* anything else? :P */
-} DC210Data;
+ char camera_type_id;
+ char firmwareMajor;
+ char firmwareMinor;
+ char fast_preview;
+ char battery;
+ char acstatus;
+ long int time;
+ dc210_zoom_type zoom;
+ char flash_charged;
+ dc210_compression_type compression_type;
+ char exp_compensation;
+ dc210_flash_type flash;
+ char preflash;
+ char exposure_compensation;
+ dc210_resolution_type resolution;
+ dc210_file_type_type file_type;
+ int totalPicturesTaken;
+ int totalFlashesFired;
+ int numPicturesInCamera;
+ int remainingLow;
+ int remainingMedium;
+ int remainingHigh;
+ int card_space;
+ char album_name[12];
+} dc210_status;
+
+typedef struct {
+ char camera_type;
+ dc210_file_type_type file_type;
+ dc210_resolution_type resolution;
+ dc210_compression_type compression;
+ int picture_number;
+ int picture_size;
+ int preview_size;
+ int picture_time;
+ char flash_used;
+ dc210_flash_type flash;
+ char preflash;
+ dc210_zoom_type zoom;
+ char f_number;
+ char battery;
+ int exposure_time;
+ char image_name[13];
+} dc210_picture_info ;
+
+#undef DEBUG
+#define TIMEOUT 1000
+#define RETRIES 5
+#define GP_MODULE "kodak-dc210"
+
+#ifdef DEBUG
+#define DC210_DEBUG(msg, params...) fprintf(stderr, msg, ##params)
+#else
+#define DC210_DEBUG GP_DEBUG
+#endif
+
+/* I really don't get it, why I have a shift of seven hours in
+ each direction to get/set the camara time correctly. I'm afraid
+ it's dependent on the timezone */
+
+/* #define CAMERA_EPOC 852094800*/
+#define CAMERA_GET_EPOC 852094800 - 25200
+#define CAMERA_SET_EPOC 852094800 + 25200
+
+/* Packet sizes */
+#define DC210_CMD_DATA_SIZE 58
+#define DC210_STATUS_SIZE 256
+#define DC210_PICINFO_SIZE 256
+#define DC210_DOWNLOAD_BLOCKSIZE 1024
+
+/* Commands */
+#define DC210_SET_RESOLUTION 0x36 /* implemented */
+#define DC210_SET_FILE_TYPE 0x37 /* implemented */
+#define DC210_SET_SPEED 0x41 /* implemented */
+#define DC210_SET_ALBUM_FILENAME 0x4A /* not yet implemented;
+ description seems to be wrong
+ returns fileinformation in a packet of size 256 */
+#define DC210_GET_PICTURE 0x64 /* implemented */
+#define DC210_GET_PICINFO 0x65 /* implemented */
+#define DC210_GET_THUMB 0x66 /* implemented */
+#define DC210_SET_QUALITY 0x71 /* implemented */
+#define DC210_SET_FLASH 0x72 /* implemented */
+#define DC210_SET_FOCUS 0x73 /* not acknowledged */
+#define DC210_SET_DELAY 0x74 /* implemented, but effect unknown */
+#define DC210_SET_TIME 0x75 /* implemented, but probably with timezone bug */
+#define DC210_SET_ZOOM 0x78 /* implemented */
+#define DC210_DELETE_PICTURE 0x7B /* implemented */
+#define DC210_TAKE_PICTURE 0x7C /* implemented */
+#define DC210_INITIALIZE 0x7E /* implemented, but effect unknown */
+#define DC210_GET_STATUS 0x7F /* implemented */
+#define DC210_SET_EXPOSURE 0x80 /* implemented */
+#define DC210_RESET 0x8A /* working, but not yet implemented */
+#define DC210_FIRMWARE_MODE_SET 0x8D /* working, but not yet implemented */
+
+
+/* untested commands */
+#define DC210_CARD_GET_PIC 0x91 /* needs unknown cmd packet */
+#define DC210_CARD_GET_PICINFO 0x92 /* needs unknown cmd packet */
+#define DC210_CARD_READ_THUMB 0x93 /* needs unknown cmd packet */
+#define DC210_CARD_FORMAT 0x95 /* needs unknown cmd packet */
+#define DC210_CARD_OPEN 0x96 /* is working, sets bit 3 in status[30] */
+#define DC210_CARD_CLOSE 0x97 /* is working, clears bit 3 in status[30] */
+#define DC210_CARD_GET_STATUS 0x98 /* is working, returns packet of size 16 */
+#define DC210_CARD_GET_DIRECTORY 0x99 /* needs unknown cmd packet */
+#define DC210_CARD_FILE_READ 0x9A /* needs unknown cmd packet */
+#define DC210_CARD_UNKNOWN_COMMAND1 0x9C /* needs unknown cmd packet */
+#define DC210_CARD_FILE_DEL 0x9D /* needs unknown cmd packet */
+#define DC210_CARD_UNKNOWN_COMMAND2 0x9E /* needs unknown cmd packet */
+
+/* Responses */
+#define DC210_COMMAND_COMPLETE 0x00
+#define DC210_PACKET_FOLLOWING 0x01
+#define DC210_CMD_PACKET_FOLLOWING 0x80
+#define DC210_CAMERA_READY 0x08
+#define DC210_COMMAND_ACK 0xD1
+#define DC210_CORRECT_PACKET 0xD2
+#define DC210_COMMAND_NAK 0xE1
+#define DC210_EXECUTION_ERROR 0xE2
+#define DC210_ILLEGAL_PACKET 0xE3
+#define DC210_CANCEL 0xE4
+#define DC210_BUSY 0xF0
+
+/* initialization */
+int dc210_initialize (Camera *camera);
+
+/* set procedures */
+int dc210_set_compression (Camera * camera, dc210_compression_type compression);
+int dc210_set_flash (Camera * camera, dc210_flash_type flash, char preflash);
+int dc210_set_zoom (Camera * camera, dc210_zoom_type zoom);
+int dc210_set_file_type (Camera * camera, dc210_file_type_type file_type);
+int dc210_set_resolution (Camera * camera, dc210_resolution_type res);
+int dc210_set_speed (Camera *camera, int speed);
+int dc210_set_delay (Camera * camera);
+int dc210_set_exp_compensation (Camera * camera, signed int compensation);
+
+/* information */
+int dc210_get_status (Camera *camera, dc210_status *status);
+int dc210_get_picture_info (Camera *camera, dc210_picture_info *picinfo, unsigned int picno);
+int dc210_get_filenames (Camera *camera, CameraList *list, GPContext *context);
+int dc210_get_picture_number (Camera *camera, const char * filename);
+
+/* picture actions */
+int dc210_capture (Camera *camera, CameraFilePath *path, GPContext *context);
+
+int dc210_download_picture (Camera * camera, CameraFile *file, unsigned int picno, int thumb, GPContext *context);
+int dc210_download_picture_by_name(Camera * camera, CameraFile *file, const char * filename, int thumb, GPContext *context);
+
+int dc210_delete_picture (Camera * camera, unsigned int picno);
+int dc210_delete_last_picture (Camera * camera );
+int dc210_delete_picture_by_name (Camera * camera, const char * filename );
+
+/* other actions */
+int dc210_format_card (Camera * camera, char * album_name, GPContext * context);
+
+/* callbacks */
+int dc210_system_time_callback (Camera * camera, CameraWidget * widget, GPContext * context);
+int dc210_format_callback(Camera * camera, CameraWidget * widget, GPContext * context);
+#ifdef DEBUG
+int dc210_debug_callback(Camera * camera, CameraWidget * widget, GPContext * context);
#endif
+
+#endif /* _DC210_H_ */
+
diff --git a/camlibs/kodak/dc210/kodak.df b/camlibs/kodak/dc210/kodak.df
new file mode 100644
index 000000000..41ff37597
--- /dev/null
+++ b/camlibs/kodak/dc210/kodak.df
@@ -0,0 +1,2 @@
+LIBRARY GPDC210
+EXPORTS
diff --git a/camlibs/kodak/dc210/library.c b/camlibs/kodak/dc210/library.c
index 5fdfb7199..143d73b3b 100644
--- a/camlibs/kodak/dc210/library.c
+++ b/camlibs/kodak/dc210/library.c
@@ -1,611 +1,1151 @@
-/*
- DC 210/215 driver library.
- by Hubert Figuiere <hfiguiere@teaser.fr>
- port of gphoto 0.4.x driver.
+#include <config.h>
- */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gphoto2.h>
#include "dc210.h"
-#include "config.h"
#include "library.h"
-#include <gphoto2.h>
+#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 textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+int dc210_cmd_error = 0;
+char ppmheader[] = "P6\n96 72\n255\n";
+char bmpheader[] = {
+ 0x42, 0x4d, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x48, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-#include <errno.h>
+#ifdef DEBUG
+int firststatus = 1;
+char oldstatus[DC210_STATUS_SIZE];
+#endif
-#ifdef HAVE_SELECT_H
-#include <sys/select.h>
-#endif /* HAVE_SELECT_H */
+/***************************************************************************
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else HAVE_SYS_TIME_H
-# include <time.h>
-# endif /* HAVE_SYS_TIME_H */
-#endif /* TIME_WITH_SYS_TIME */
-
-
-static int kodak_dc210_read (DC210Data * dd, unsigned char *buf, int nbytes);
-static int kodak_dc210_write_byte (DC210Data * dd, char b);
-static unsigned char kodak_dc210_checksum(char *packet,int length);
-static int kodak_dc210_set_port_speed(DC210Data * dd, int speed);
-static int kodak_dc210_command_complete (DC210Data * dd);
-static int kodak_dc210_read_packet (DC210Data * dd, char *packet, int length);
-
-static int kodak_dc210_send_command (DC210Data * dd, char command, char arg1, char arg2, char arg3, char arg4)
-{
- unsigned char ack;
- int success = TRUE;
-
- /* try to write 8 bytes in sequence to the camera */
- success = success && kodak_dc210_write_byte ( dd, command );
- success = success && kodak_dc210_write_byte ( dd, 0x00 );
- success = success && kodak_dc210_write_byte ( dd, arg1 );
- success = success && kodak_dc210_write_byte ( dd, arg2 );
- success = success && kodak_dc210_write_byte ( dd, arg3 );
- success = success && kodak_dc210_write_byte ( dd, arg4 );
- success = success && kodak_dc210_write_byte ( dd, 0x00 );
- success = success && kodak_dc210_write_byte ( dd, 0x1A );
-
- /* if the command was sent successfully to the camera, continue */
- if (success)
- {
- /* read ack from camera */
- success = kodak_dc210_read( dd, &ack, 1 );
-
- if (success)
- {
- /* make sure the ack is okay */
- if (ack != DC_COMMAND_ACK)
- {
- fprintf(stderr,"kodak_dc210_send_command - bad ack from camera\n");
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_send_command - failed to read ack from camera\n");
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_send_command - failed to send command to camera\n");
- success = FALSE;
- }
-
- return(success);
-}
+ Global in- and output procedures
-/*
- tell the camera to change the port speed,
- then set it.
- */
-static int kodak_dc210_set_port_speed(DC210Data * dd, int speed)
-{
- int success = 0;
- int arg1, arg2;
-
- gp_port_settings settings;
-
- if (gp_port_settings_get (dd->dev, &settings) == GP_ERROR) {
- return GP_ERROR;
- }
- settings.serial.speed = speed;
-
- switch (speed) {
- case 9600:
- arg1 = 0x96;
- arg2 = 0x00;
- break;
- case 19200:
- arg1 = 0x19;
- arg2 = 0x20;
- break;
- case 38400:
- arg1 = 0x38;
- arg2 = 0x40;
- break;
- case 57600:
- arg1 = 0x57;
- arg2 = 0x60;
- break;
- case 115200:
- arg1 = 0x11;
- arg2 = 0x52;
- break;
- default:
- /* speed not supported */
- return GP_ERROR;
- }
-
- success = kodak_dc210_send_command(dd, DC_SET_SPEED, arg1, arg2, 0x00, 0x00);
- if (success) {
- if (gp_port_settings_set (dd->dev, settings) == GP_ERROR) {
- return GP_ERROR;
- }
- }
- else {
- /* unable to change the speed */
- return GP_ERROR;
- }
- return GP_OK;
-}
+****************************************************************************/
+/* Utility procedures for command execution */
-static int kodak_dc210_command_complete (DC210Data * dd)
+static void dc210_cmd_init
+(char * cmd, unsigned char command_byte)
{
- int status = DC_BUSY;
- int success = TRUE;
-
- /* Wait for the camera to be ready. */
- do
- {
- success = kodak_dc210_read(dd, (char *)&status, 1);
- }
- while (success && (status == DC_BUSY));
-
- if (success)
- {
- if (status != DC_COMMAND_COMPLETE)
- {
- if (status == DC_ILLEGAL_PACKET)
- {
- fprintf(stderr,"kodak_dc210_command_complete - illegal packet received from host\n");
- }
- else
- {
- fprintf(stderr,"kodak_dc210_command_complete - command not completed\n");
- }
-
- /* status was not command complete - raise an error */
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_command_complete - failed to read status byte from camera\n");
- success = FALSE;
- }
-
- return(success);
-}
+ /* utility procedure to initalize a command string */
-static int kodak_dc210_read (DC210Data * dd, unsigned char *buf, int nbytes )
-{
- return (gp_port_read(dd->dev, buf, nbytes));
-}
+ memset (cmd, 0, 8);
+ cmd[0] = command_byte;
+ cmd[7] = 0x1a;
-static int kodak_dc210_write_byte (DC210Data * dd, char b )
-{
- return (gp_port_read(dd->dev, &b, 1));
-}
+};
-static int kodak_dc210_read_packet (DC210Data * dd, char *packet, int length)
+static int dc210_write_single_char
+(Camera *camera, unsigned char response)
{
- int success = TRUE;
- unsigned char sent_checksum;
- unsigned char computed_checksum;
- unsigned char control_byte;
-
- /* Read the control byte from the camera - and packet coming from
- the camera must ALWAYS be 0x01 according to Kodak Host Protocol. */
- if (kodak_dc210_read(dd, &control_byte, 1))
- {
- if (control_byte == PKT_CTRL_RECV)
- {
- if (kodak_dc210_read(dd, packet, length))
- {
- /* read the checksum from the camera */
- if (kodak_dc210_read(dd, &sent_checksum, 1))
- {
- computed_checksum = kodak_dc210_checksum(packet, length);
-
- if (sent_checksum != computed_checksum)
- {
- fprintf(stderr,"kodak_dc210_read_packet: bad checksum %d != %d\n",computed_checksum,sent_checksum);
- kodak_dc210_write_byte(dd, DC_ILLEGAL_PACKET);
- success = FALSE;
- }
- else
- {
- kodak_dc210_write_byte(dd, DC_CORRECT_PACKET);
- success = TRUE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_read_packet: failed to read checksum byte from camera\n");
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_read_packet: failed to read paket from camera\n");
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_read_packet - packet control byte invalid %x\n",control_byte);
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_read_packet - failed to read control byte from camera\n");
- success = FALSE;
- }
-
- return success;
-}
+ /* utility procedure to write a single character */
-static unsigned char kodak_dc210_checksum(char *packet,int length)
-{
-/* Computes the *primitave* kodak checksum using XOR - yuck. */
- unsigned char chksum = 0;
- int i;
-
- for (i = 0 ; i < length ; i++)
- {
- chksum ^= packet[i];
- }
-
- return chksum;
-}
+ int i;
+ for (i=0; i< RETRIES; i++){
+ if (gp_port_write(camera->port, &response, 1) >= 0)
+ return (GP_OK);
+ };
-/*
- open the camera. The port should already be open....
- set the speed to 115200
- */
-int kodak_dc210_open_camera (DC210Data * dd)
-{
- int ret;
+ return GP_ERROR;
- ret = kodak_dc210_send_command (dd, DC_INITIALIZE,0x00,0x00,0x00,0x00);
- ret = kodak_dc210_command_complete (dd);
- ret = kodak_dc210_set_port_speed (dd, 115200);
-
- return ret;
-}
+};
-/* Close the camera */
-int kodak_dc210_close_camera (DC210Data * dd)
+static int dc210_read_single_char
+(Camera *camera, unsigned char * response)
{
- return kodak_dc210_set_port_speed(dd, 9600);
-}
+ /* utility procedure to read a single character */
+
+ int i;
+ signed char error;
+
+ for (i = 0; i < RETRIES; i++){
+
+ error = gp_port_read(camera->port, response, 1);
+
+ if (error < 0){
+ if (error == GP_ERROR_TIMEOUT)
+ continue;
+ else{
+ DC210_DEBUG("Real bad error reading single character. Errornumber: %d\n", error);
+ return GP_ERROR;
+ };
+ };
+
+ return GP_OK;
+
+ };
+
+ return GP_ERROR;
+
+};
+
+/* Command execution */
-int kodak_dc210_number_of_pictures (DC210Data * dd)
+static int dc210_execute_command
+(Camera *camera, char *cmd)
{
- int numPics = 0;
- struct kodak_dc210_status status;
-
- kodak_dc210_get_camera_status (dd, &status);
-
- numPics = status.num_pictures;
-
- return(numPics);
-}
+ /* This procedure sends a command to the camera and
+ waits for acknowledgement. Calling procedures have
+ to check the returncode; if the command succeeded
+ there are three possible follow ups:
+ - Read a DC210_COMMAND_COMPLETE in case of
+ simple commands
+ - Send an additional command package in case of
+ sophisticated commands
+ - Read data from the camera
+ But all this depends on the command and should not
+ be mixed in this procedure. */
+
+ int i,k ;
+ unsigned char response;
+ signed char error;
+
+ dc210_cmd_error = DC210_CMD_OKAY;
+
+ for (i = 0; i < RETRIES; i++){
+
+ /* write command */
+ if (gp_port_write(camera->port, cmd, 8) < 0){
+ DC210_DEBUG("Could not write to port.\n");
+ dc210_cmd_error = DC210_WRITE_ERROR;
+ continue; /* try again */
+ };
+
+ for (k = 0; k < RETRIES; k++){
+ error = gp_port_read(camera->port, &response, 1);
+ if (error != 1){
+ if (error == GP_ERROR_TIMEOUT){
+ dc210_cmd_error = DC210_TIMEOUT_ERROR;
+ continue; /* wait a little bit longer */
+ }
+ else{
+ DC210_DEBUG("Real bad error reading answer. Errornumber: %d\n", error);
+ dc210_cmd_error = DC210_READ_ERROR;
+ return error;
+ };
+ };
+
+ switch (response){
+ case DC210_COMMAND_ACK:
+ DC210_DEBUG("Command 0x%02X acknowledged.\n", (unsigned char) cmd[0]);
+ return GP_OK; break; /* that's fine, just what we expected */
+ case DC210_COMMAND_NAK:
+ DC210_DEBUG("Sorry, but the camera seems not to understand the command 0x%02X\n", (unsigned char) cmd[0]);
+ dc210_cmd_error = DC210_NAK_ERROR;
+ break; /* anyway, send the command again */
+ default:
+ DC210_DEBUG("Strange. Unexpected response for command 0x%02X: 0x%02X\n", (unsigned char) cmd[0], response);
+ dc210_cmd_error = DC210_GARBAGE_ERROR;
+ return GP_ERROR;
+ break;
+ };
+ break;
+ };
+
+ };
+
+ /* command does definitely not work */
+
+ DC210_DEBUG("Command definitely didn't work.\n");
+
+ return GP_ERROR;
-/*
- Capture a picture and return the index of the picture
- in the gphoto form (1 based).
- */
-int kodak_dc210_capture(DC210Data * dd)
+};
+
+/* appropriate actions to a command */
+
+static int dc210_write_command_packet
+(Camera * camera, char * data)
{
- int ret;
- ret = kodak_dc210_send_command (dd, DC_TAKE_PICTURE,0x00,0x00,0x00,0x00);
- ret = kodak_dc210_command_complete (dd);
+ unsigned char checksum;
+ int i, error;
+ unsigned char answer;
- return kodak_dc210_number_of_pictures(dd);
-}
+ /* calculating checksum */
+ checksum = 0;
+ for (i = 0; i < DC210_CMD_DATA_SIZE; i ++){
+ checksum ^= data[i];
+ };
+
+ for (i = 0; i < RETRIES; i++){
+
+ /* write the startbyte */
+ dc210_write_single_char(camera, DC210_CMD_PACKET_FOLLOWING);
+
+ /* write packet */
+ gp_port_write(camera->port, data, DC210_CMD_DATA_SIZE);
+
+ /* write checksum */
+ dc210_write_single_char(camera, checksum);
+
+ /* read answer */
+
+ error = gp_port_read(camera->port, &answer, 1);
+
+ if (error < 0) return GP_ERROR;
+
+ if (answer == DC210_CORRECT_PACKET) return GP_OK;
+
+ if (answer != DC210_ILLEGAL_PACKET) {
+ DC210_DEBUG("Strange answer to command packet: 0x%02X.\n", answer);
+ return GP_ERROR;
+ };
-int kodak_dc210_get_picture_info (DC210Data * dd,
- int picNum,
- struct kodak_dc210_picture_info *picInfo)
+ };
+
+ DC210_DEBUG("Could not send command packet.\n");
+
+ return GP_ERROR;
+
+};
+
+static int dc210_wait_for_response
+(Camera *camera, int expect_busy, GPContext *context)
{
- unsigned char packet[256];
-
- picNum--;
+ /* Waits for a command to finish.
+ Expects either a timeout, a DC210_BUSY,
+ a DC210_COMMAND_COMPLETE od a
+ DC210_PACKET_FOLLOWING; all other answers
+ are considered errors */
- /* send picture info command, receive data, send ack */
- kodak_dc210_send_command (dd, DC_PICTURE_INFO, 0x00, (char)picNum, 0x00, 0x00);
- kodak_dc210_read_packet (dd, packet, 256);
- kodak_dc210_command_complete (dd);
-
- picInfo->resolution = packet[3];
- picInfo->compression = packet[4];
- picInfo->pictureNumber = (packet[6] << 8) + packet[7];
-
- picInfo->fileSize = ((long)packet[8] << 24) +
- ((long)packet[9] << 16) +
- ((long)packet[10] << 8) +
- (long)packet[11];
-
- picInfo->elapsedTime = ((long)packet[12] << 24) +
- ((long)packet[13] << 16) +
- ((long)packet[14] << 8) +
- (long)packet[15];
-
- strncpy(picInfo->fileName, packet + 32, 12);
- /* TODO handle error codes */
- return GP_OK;
-}
+ unsigned char response;
+ int counter = 0;
+ int progress_id = 0;
+
+ if (context != NULL)
+ progress_id = gp_context_progress_start (context, expect_busy, _("Waiting..."));
+
+ while (1){
+
+ if (dc210_read_single_char(camera, &response) < 0){
+ if (context != 0)
+ gp_context_progress_stop (context, progress_id);
+ return GP_ERROR;
+ };
+
+ switch (response){
+ case DC210_BUSY:
+ /* wait a little bit longer */
+ if (context != NULL && counter <= expect_busy)
+ gp_context_progress_update (context, progress_id, counter++);
+ break;
+ case DC210_COMMAND_COMPLETE:
+ case DC210_PACKET_FOLLOWING:
+ if (context != 0)
+ gp_context_progress_stop (context, progress_id);
+ return response;
+ break;
+ default:
+ if (context != 0)
+ gp_context_progress_stop (context, progress_id);
+ DC210_DEBUG("Command terminated with errorcode 0x%02X.\n", response);
+ return GP_ERROR;
+ };
+ };
+
+};
-int kodak_dc210_get_camera_status (DC210Data * dd,
- struct kodak_dc210_status *status)
+static int dc210_read_single_block
+(Camera *camera, unsigned char * b, int blocksize)
{
- unsigned char packet[256];
- int success = TRUE;
-
- if (kodak_dc210_send_command (dd, DC_STATUS, 0x00,0x00,0x00,0x00))
- {
- if (kodak_dc210_read_packet (dd, packet, 256))
- {
- kodak_dc210_command_complete (dd);
-
- memset((char*)status,0,sizeof(struct kodak_dc210_status));
-
- status->camera_type_id = packet[1];
- status->firmware_major = packet[2];
- status->firmware_minor = packet[3];
- status->batteryStatusId = packet[8];
- status->acStatusId = packet[9];
-
- /* seconds since unix epoc */
- status->time = CAMERA_EPOC + (
- packet[12] * 0x1000000 +
- packet[13] * 0x10000 +
- packet[14] * 0x100 +
- packet[15]) / 2;
-
- status->zoomMode = packet[15];
- status->flash_charged = packet[17];
- status->compression_mode_id = packet[18];
- status->flash_mode = packet[19];
- status->exposure_compensation = packet[20];
- status->picture_size = packet[21];
- status->file_Type = packet[22];
- status->totalPicturesTaken = packet[25] * 0x100 + packet[26];
- status->totalFlashesFired = packet[27] * 0x100 + packet[28];
- status->num_pictures = packet[56] * 0x100 + packet[57];
- strncpy(status->camera_ident,packet + 90,32);
- }
- else
- {
- fprintf(stderr,"kodak_dc210_get_camera_status: send command failed\n");
- success = FALSE;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_get_camera_status: send command failed\n");
- success = FALSE;
- }
-
- return success;
-}
+ int i, k, error;
+ char cs_read, cs_computed;
+
+ for (i = 0; i < RETRIES; i++){
+
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR)
+ return GP_ERROR;
-int kodak_dc210_get_thumbnail (DC210Data * dd, int picNum, CameraFile *file)
+ error = 1;
+ for (k = 0; k < RETRIES; k++){
+ if (gp_port_read(camera->port, b, blocksize) < 0){
+ continue;
+ };
+ error = 0;
+ break;
+ };
+
+ if (error) return GP_ERROR;
+
+ if (dc210_read_single_char(camera, &cs_read) < 0)
+ return GP_ERROR;
+
+ cs_computed = 0;
+ for (k = 0 ; k < blocksize; k++)
+ cs_computed ^= b[k];
+ if (cs_computed == cs_read){
+ dc210_write_single_char(camera, DC210_CORRECT_PACKET);
+ return GP_OK;
+ };
+
+ dc210_write_single_char(camera, DC210_ILLEGAL_PACKET);
+
+ };
+
+ return GP_ERROR;
+
+};
+
+static int dc210_read_to_file
+(Camera *camera, CameraFile * f, long int filesize, GPContext *context)
{
- struct kodak_dc210_picture_info picInfo;
- int i,j;
- int numRead = 0;
- int success = TRUE;
- int fileSize = 20736;
- int blockSize = 1024;
- char *picData;
- char *imData;
- char bmpHeader[] = {
- 0x42, 0x4d, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
- 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x48, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ int packets, k, l, fatal_error, packet_following;
+ unsigned int progress_id = 0;
+ unsigned char cs_read, cs_computed;
+ unsigned char b[DC210_DOWNLOAD_BLOCKSIZE];
+ int blocks = filesize / DC210_DOWNLOAD_BLOCKSIZE;
+ int remaining = filesize % DC210_DOWNLOAD_BLOCKSIZE;
- /* get information (size, name, etc) about the picture */
- kodak_dc210_get_picture_info (dd, picNum, &picInfo);
+ if (remaining) blocks++;
- /* the protocol expects 0..n-1, but this function is supplied 1..n */
- picNum--;
-
- /* allocate space for the thumbnail data */
- picData = (char *)malloc(fileSize + blockSize);
-
- /* allocate space for the image data */
- imData = (char *)malloc(fileSize + 54);
-
-
- if (kodak_dc210_send_command(dd, DC_PICTURE_THUMBNAIL, 0x00, (char)picNum, 0x01, 0x00))
- {
- while (success && (numRead < fileSize))
- {
- if (kodak_dc210_read_packet(dd, picData+numRead, blockSize))
- {
- numRead += blockSize;
- }
- else
- {
- fprintf(stderr,"kodak_dc210_get_thumbnail - bad packet read from camera\n");
- success = FALSE;
- }
- }
-
- /* get to see if the thumbnail was retrieved */
- if (success)
- {
- kodak_dc210_command_complete(dd);
-/* update_progress(100);*/
-
- memcpy(imData,bmpHeader, sizeof(bmpHeader));
-
- /* reverse the thumbnail data */
- /* not only is the data reversed but the image is flipped
- * left to right
- */
- for (i = 0; i < 72; i++) {
- for (j = 0; j < 96; j++) {
- imData[i*96*3+j*3+54] = picData[(71-i)*96*3+j*3+2];
- imData[i*96*3+j*3+54+1] = picData[(71-i)*96*3+j*3+1];
- imData[i*96*3+j*3+54+2] = picData[(71-i)*96*3+j*3];
- }
- }
-
- gp_file_append (file, imData, fileSize + 54);
- gp_file_set_mime_type (file, GP_MIME_BMP);
- gp_file_set_type (file, GP_FILE_TYPE_PREVIEW);
- strncpy(file->name, picInfo.fileName, 12);
- file->name[12] = 0;
- }
- }
- else
- {
- fprintf(stderr,"kodak_dc210_get_thumbnail: failed to get thumbnail command to camera\n");
- success = FALSE;
- }
-
- free (imData);
- free (picData);
-
- return GP_OK;
+ if (context != NULL)
+ progress_id = gp_context_progress_start (context, blocks, _("Getting data..."));
+
+ fatal_error = 0;
+ packets = 0;
+ while (1 == (packet_following = dc210_wait_for_response(camera, 0, NULL))){
+ fatal_error = 1;
+ for (k = 0; k < RETRIES; k++){
+ /* read packet */
+ if (gp_port_read(camera->port, b, DC210_DOWNLOAD_BLOCKSIZE) < 0)
+ continue;
+ /* read checksum */
+ if (dc210_read_single_char(camera, &cs_read) == GP_ERROR)
+ return GP_ERROR;
+ /* test checksum */
+ cs_computed = 0;
+ for (l = 0 ; l < DC210_DOWNLOAD_BLOCKSIZE; l++)
+ cs_computed ^= b[l];
+ if (cs_computed != cs_read){
+ dc210_write_single_char(camera, DC210_ILLEGAL_PACKET);
+ continue;
+ };
+ /* append to file */
+ if (packets == blocks - 1 && remaining)
+ gp_file_append(f, b, remaining);
+ else
+ gp_file_append(f, b, DC210_DOWNLOAD_BLOCKSIZE);
+ /* request next packet */
+ dc210_write_single_char(camera, DC210_CORRECT_PACKET);
+ fatal_error = 0;
+ if (context != NULL)
+ gp_context_progress_update (context, progress_id, packets);
+ packets++;
+ break;
+ };
+ if (fatal_error) break;
+ };
+
+ if (packet_following < 0)
+ fatal_error = 1;
+
+ if (context != 0)
+ gp_context_progress_stop (context, progress_id);
+
+ if (fatal_error) return GP_ERROR;
+
+ return GP_OK;
+
+};
+
+/***************************************************************************
+
+ Working procedures
+
+****************************************************************************/
+
+/***** Set procedures *****/
+
+static int dc210_set_option (Camera * camera, char command, unsigned int value, int valuesize){
+
+ char cmd[8];
+ dc210_cmd_init(cmd, command);
+
+ switch(valuesize){
+ case 0:
+ break;
+ case 1:
+ cmd[2] = value & 0xFF;
+ break;
+ case 2:
+ cmd[3] = value & 0xFF;
+ cmd[2] = (value >> 8) & 0xFF;
+ break;
+ case 4:
+ cmd[5] = value & 0xFF;
+ cmd[4] = (value >> 8) & 0xFF;
+ cmd[3] = (value >> 16) & 0xFF;
+ cmd[2] = (value >> 24) & 0xFF;
+ break;
+ default:
+ return GP_ERROR;
+ };
+
+ if (dc210_execute_command(camera, cmd) == GP_ERROR) return GP_ERROR;
+
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR) return GP_ERROR;
+
+ return GP_OK;
+
+};
+
+int dc210_set_compression (Camera * camera, dc210_compression_type compression){
+
+ return dc210_set_option(camera, DC210_SET_QUALITY, compression, 1);
+
+};
+
+int dc210_set_flash (Camera * camera, dc210_flash_type flash, char preflash){
+
+ if (flash != DC210_FLASH_NONE && preflash){
+ return dc210_set_option(camera, DC210_SET_FLASH, flash + 3, 1);
+ }
+ else
+ return dc210_set_option(camera, DC210_SET_FLASH, flash, 1);
+
+};
+
+int dc210_set_zoom (Camera * camera, dc210_zoom_type zoom){
+
+ return dc210_set_option(camera, DC210_SET_ZOOM, zoom, 1);
+
+};
+
+int dc210_set_file_type (Camera * camera, dc210_file_type_type file_type){
+
+ return dc210_set_option(camera, DC210_SET_FILE_TYPE, file_type, 1);
+
+};
+
+int dc210_set_resolution (Camera * camera, dc210_resolution_type res){
+
+ return dc210_set_option(camera, DC210_SET_RESOLUTION, res, 1);
+
+};
+
+int dc210_set_delay (Camera * camera){
+
+ /* This function works, but I do no have the slightest idea,
+ what the effect is / should be.
+ There is *no* delay, when you execute this function before
+ capturing. */
+
+ return dc210_set_option(camera, DC210_SET_DELAY, 10, 4);
+
+};
+
+int dc210_set_exp_compensation (Camera * camera, signed int compensation){
+
+ unsigned char param = abs(compensation);
+
+ if (compensation < 0) param |= 0x80;
+
+ return dc210_set_option(camera, DC210_SET_EXPOSURE, param, 1);
+
+};
+
+int dc210_system_time_callback (Camera * camera, CameraWidget * widget, GPContext * context){
+
+ return dc210_set_option(camera, DC210_SET_TIME, (time(NULL) - CAMERA_SET_EPOC) << 1, 4);
+
+};
+
+int dc210_initialize (Camera * camera){
+
+ /* this procedure works, but I don't know, if it has any
+ effect */
+
+ return dc210_set_option(camera, DC210_INITIALIZE, 0, 0);
+
+};
+
+
+int dc210_format_card (Camera * camera, char * album_name, GPContext * context){
+
+ char data[DC210_CMD_DATA_SIZE];
+ char cmd[8];
+ char * subst;
+ unsigned char answer[16];
+ unsigned char checksum_read, checksum;
+ int i;
+
+ memset (data, 0, DC210_CMD_DATA_SIZE);
+
+ /* Make the album name acceptable - we need at least 8 characters
+ which are not blank and there are no blanks allowed before the
+ last character.
+ */
+ if (album_name != NULL && strlen(album_name) > 0){
+ strncpy(data, album_name, 11);
+ /* substitute blanks in the first 8 characters*/
+ while (NULL != (subst = strchr(data, ' '))) *subst = '_';
+ if (strlen(data) < 8) strncat(data, "________", 8 - strlen(data));
+ };
+
+ DC210_DEBUG("Album name is '%s'\n", data);
+
+ dc210_cmd_init(cmd, DC210_CARD_FORMAT);
+
+ dc210_execute_command(camera, cmd);
+ dc210_write_command_packet(camera, data);
+ if (dc210_wait_for_response(camera, 3, context) == GP_ERROR) return GP_ERROR;
+
+ gp_port_read(camera->port, answer, 16);
+ gp_port_read(camera->port, &checksum_read, 1);
+ checksum = 0;
+
+ for (i = 0; i < 16; i++) checksum ^= answer[i];
+ if (checksum_read != checksum) return GP_ERROR;
+
+ DC210_DEBUG("Flash card formated.\n");
+
+ if (dc210_write_single_char(camera, DC210_CORRECT_PACKET) == GP_ERROR) return GP_ERROR;
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR) return GP_ERROR;
+
+ gp_filesystem_reset(camera->fs);
+
+ return GP_OK;
+
+};
+
+static int dc210_space_on_card(Camera * camera, int * space){
+
+ char cmd[8];
+ unsigned char answer[16];
+ unsigned char checksum_read, checksum;
+ int i, sectors;
+
+ dc210_cmd_init(cmd, DC210_CARD_GET_STATUS);
+
+ dc210_execute_command(camera, cmd);
+
+ *space = -1;
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR) return GP_ERROR;
+
+ gp_port_read(camera->port, answer, 16);
+ gp_port_read(camera->port, &checksum_read, 1);
+
+ checksum = 0;
+ for (i = 0; i < 16; i++) checksum ^= answer[i];
+
+ if (checksum_read != checksum)
+ DC210_DEBUG("Error reading card status.\n");
+ else
+ DC210_DEBUG("Card status correctly read.\n");
+
+ sectors = answer[2] * 0x1000000 + answer[3] * 0x10000 + answer[4] * 0x100 + answer[5];
+ *space = sectors >> 2; /* sectorsize seems to be 128, now we get kb */
+
+ DC210_DEBUG("Space on card: %d\n", *space);
+
+ if (dc210_write_single_char(camera, DC210_CORRECT_PACKET) == GP_ERROR) return GP_ERROR;
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR) return GP_ERROR;
+
+ return GP_OK;
+
+};
+
+int dc210_format_callback(Camera * camera, CameraWidget * widget, GPContext * context){
+
+ CameraWidget * window;
+ char * album_name;
+
+ gp_widget_get_root(widget, &window);
+
+ gp_widget_get_child_by_label (window, _("Album name"), &widget);
+ gp_widget_get_value (widget, &album_name);
+
+ return dc210_format_card(camera, album_name, context);
+
+};
+
+int dc210_set_speed (Camera *camera, int speed) {
+
+ unsigned char cmd[8];
+ int i;
+ GPPortSettings settings;
+ CameraAbilities abilities;
+ dc210_cmd_init(cmd, DC210_SET_SPEED);
+
+ switch (speed) {
+ case 0: /* Default */
+ case 9600:
+ cmd[2] = 0x96; cmd[3] = 0x00; break;
+ case 19200:
+ cmd[2] = 0x19; cmd[3] = 0x20; break;
+ case 38400:
+ cmd[2] = 0x38; cmd[3] = 0x40; break;
+ case 57600:
+ cmd[2] = 0x57; cmd[3] = 0x60; break;
+ case 115200:
+ cmd[2] = 0x11; cmd[3] = 0x52; break;
+ default:
+ return (GP_ERROR);
+ };
+
+ gp_port_get_settings (camera->port, &settings);
+
+ /* fast try, if we have initialized the speed already */
+ if (settings.serial.speed != 0){
+ if (dc210_execute_command(camera, cmd) != GP_ERROR){
+ settings.serial.speed = speed;
+ gp_port_set_settings (camera->port, settings);
+ return GP_OK;
+ };
+ };
+
+ /* okay, we need to try harder; test all available speed settings */
+
+ settings.serial.bits = 8;
+ settings.serial.parity = 0;
+ settings.serial.stopbits = 1;
+ gp_port_set_timeout (camera->port, TIMEOUT);
+
+ gp_camera_get_abilities(camera, &abilities);
+
+ for (i = 0; i < sizeof(abilities.speed); i++){
+
+ if (abilities.speed[i] == 0) break;
+
+ DC210_DEBUG("Trying to use speed %d\n", abilities.speed[i]);
+ settings.serial.speed = abilities.speed[i];
+
+ gp_port_set_settings (camera->port, settings);
+ gp_port_send_break (camera->port, 2);
+
+ if (dc210_execute_command(camera, cmd) == GP_ERROR){
+ if (dc210_cmd_error == DC210_GARBAGE_ERROR){
+ DC210_DEBUG("Obviously the port settings differ between camera and system.\n");
+ };
+ }
+ else{
+ DC210_DEBUG("Port speed %d seems to work!\n", abilities.speed[i]);
+ settings.serial.speed = speed;
+ gp_port_set_settings (camera->port, settings);
+ return GP_OK;
+ };
+ };
+
+ return GP_ERROR;
+
}
+/****** Picture actions *****/
+
+static int dc210_take_picture (Camera * camera, GPContext * context){
+ char cmd[8];
+ dc210_cmd_init(cmd, DC210_TAKE_PICTURE);
-int kodak_dc210_get_picture (DC210Data * dd, int picNum, CameraFile *file)
-/*
- int kodak_dc210_get_picture (DC210Data * dd, int thumbnail, const char *folder, const char *filename,
- CameraFile *file)
-*/
+ if (dc210_execute_command(camera, cmd) == GP_ERROR) return GP_ERROR;
+
+ if (dc210_wait_for_response(camera, 5, context) == GP_ERROR)
+ return GP_ERROR;
+
+ return GP_OK;
+
+};
+
+int dc210_delete_picture (Camera * camera, unsigned int picno){
+
+ char cmd[8];
+ dc210_status status;
+ unsigned int pic_offset = picno - 1;
+
+ dc210_cmd_init(cmd, DC210_DELETE_PICTURE);
+
+ cmd[3] = pic_offset & 0xFF;
+ cmd[2] = (pic_offset >> 8) & 0xFF;
+
+ if (dc210_get_status(camera, &status) == GP_ERROR)
+ return GP_ERROR;
+
+ if (picno > status.numPicturesInCamera)
+ return GP_ERROR;
+
+ if (dc210_execute_command(camera, cmd) == GP_ERROR)
+ return GP_ERROR;
+
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR)
+ return GP_ERROR;
+
+ return GP_OK;
+
+};
+
+int dc210_delete_last_picture (Camera * camera ){
+
+ dc210_status status;
+
+ if (dc210_get_status(camera, &status) == GP_ERROR)
+ return GP_ERROR;
+
+ if (0 == status.numPicturesInCamera)
+ return GP_ERROR;
+
+ return dc210_delete_picture(camera, status.numPicturesInCamera);
+
+};
+
+int dc210_delete_picture_by_name (Camera * camera, const char * filename ){
+
+ int picno = dc210_get_picture_number(camera, filename);
+
+ if (picno < 1) return GP_ERROR;
+
+ return dc210_delete_picture(camera, picno);
+
+};
+
+int dc210_download_picture
+(Camera * camera, CameraFile *file, unsigned int picno, int thumb, GPContext *context)
{
- int blockSize;
- int fileSize;
- int numRead;
- int numBytes;
- struct kodak_dc210_picture_info picInfo;
- char *picData;
- char name [13];
-
- /* get information (size, name, etc) about the picture */
- kodak_dc210_get_picture_info (dd, picNum, &picInfo);
-
- /* DC210 addresses pictures 0..n-1 instead of 1..n */
- picNum--;
-
- /* send the command to start transfering the picture */
- kodak_dc210_send_command(dd, DC_PICTURE_DOWNLOAD, 0x00, (char)picNum, 0x00, 0x00);
-
- fileSize = picInfo.fileSize;
- blockSize = 1024;
- picData = (char *)malloc(blockSize);
- numRead = 0;
+
+ dc210_status status;
+ dc210_picture_info picinfo;
+ char cmd[8];
+ unsigned int pic_offset = picno - 1;
-/* update_progress(0);*/
- while (numRead < fileSize)
- {
- kodak_dc210_read_packet(dd, picData, blockSize);
- numRead += blockSize;
- if (numRead > fileSize) {
- numBytes = fileSize % blockSize;
- }
- else {
- numBytes = blockSize;
- }
+ if (thumb)
+ dc210_cmd_init(cmd, DC210_GET_THUMB);
+ else
+ dc210_cmd_init(cmd, DC210_GET_PICTURE);
- gp_file_append(file, picData, numBytes);
+ cmd[3] = pic_offset & 0xFF;
+ cmd[2] = (pic_offset >> 8) & 0xFF;
+ if (thumb) cmd[4] = 1; /* colour image instead of grayscale */
- }
- free (picData);
- fprintf(stderr,"%d/%d\n",numRead,fileSize);
- kodak_dc210_command_complete (dd);
+ if (dc210_get_status(camera, &status) == GP_ERROR)
+ return GP_ERROR;
- gp_file_set_mime_type (file, GP_MIME_JPEG);
- gp_file_set_type (file, GP_FILE_TYPE_NORMAL);
- strncpy (name, picInfo.fileName, 12);
- name[12] = 0;
- gp_file_set_name (file, name);
+ if (picno > status.numPicturesInCamera)
+ return GP_ERROR;
- return GP_OK;
-}
+ if (dc210_get_picture_info(camera, &picinfo, picno) == GP_ERROR)
+ return GP_ERROR;
+
+ gp_file_set_name(file, picinfo.image_name);
+
+ dc210_execute_command(camera, cmd);
+ if (thumb){
+
+ /* The windows bitmaps byte order differs from the one
+ the camera delivers, so the following seems to be rotated:
+
+ gp_file_set_mime_type(file, GP_MIME_BMP);
+ gp_file_append(file, bmpheader, sizeof(bmpheader));
+
+ We use ppm instead, which is very friendly and needs
+ nothing more than the correct header */
+
+ gp_file_set_mime_type(file, GP_MIME_PPM);
+ gp_file_append(file, ppmheader, sizeof(ppmheader));
+ dc210_read_to_file(camera, file, 96 * 72 * 3, NULL);
+ }
+ else
+ dc210_read_to_file(camera, file, picinfo.picture_size, context);
+
+ return GP_OK;
+
+};
+
+int dc210_download_picture_by_name(Camera * camera, CameraFile *file, const char * filename, int thumb, GPContext *context){
-int kodak_dc210_delete_picture (DC210Data * dd, int picNum)
+ int picno = 0;
+
+ picno = dc210_get_picture_number(camera, filename);
+
+ if (picno < 1) return GP_ERROR;
+
+ if (dc210_download_picture(camera, file, picno, thumb, context) == GP_ERROR) return GP_ERROR;
+
+ return GP_OK;
+
+};
+
+int dc210_capture (Camera *camera, CameraFilePath *path, GPContext *context)
{
- picNum--;
+
+ dc210_status status;
+ dc210_picture_info picinfo;
+
+ if (dc210_take_picture(camera, context) == GP_ERROR)
+ return GP_ERROR;
+
+ if (dc210_get_status(camera, &status) == GP_ERROR) return GP_ERROR;
+
+ if (dc210_get_picture_info(camera, &picinfo, status.numPicturesInCamera) == GP_ERROR) return GP_ERROR;
+
+ strcpy(path->folder, "/");
+ strcpy(path->name, picinfo.image_name);
+
+ return GP_OK;
+
+};
+
+/***** Retrieve information *****/
+
+int dc210_get_picture_number (Camera *camera, const char * filename){
+
+ dc210_status status;
+ dc210_picture_info picinfo;
+ int i;
+
+ if (dc210_get_status(camera, &status) == GP_ERROR) return -1;
+
+ for (i = 1; i <= status.numPicturesInCamera; i++){
+
+ if (dc210_get_picture_info(camera, &picinfo, i) == GP_ERROR) return -1;
- kodak_dc210_send_command (dd,DC_ERASE_IMAGE_IN_CARD,0x00,(char)picNum,0x00,0x00);
- kodak_dc210_command_complete (dd);
- return (1);
-}
+ if (strcmp(picinfo.image_name, filename) == 0){
+ return i;
+ };
+
+ };
+
+ return -1;
-/*
- By default all image on DC210 are in \DCIMAGES. So well list
- all the pictures as if they where on a flat file system.
- */
-int kodak_dc210_get_directory_listing (DC210Data *dd, CameraList *list)
+};
+
+int dc210_get_filenames (Camera *camera, CameraList *list, GPContext *context)
{
- int ret = GP_OK;
- int num, i;
- struct kodak_dc210_picture_info picInfo;
- char fileName [13];
-
- num = kodak_dc210_number_of_pictures (dd);
- for (i = 0; i < num; i++) {
- ret = kodak_dc210_get_picture_info (dd, i, &picInfo);
- if (ret == GP_OK) {
- strncpy (fileName, picInfo.fileName, 12);
- fileName[12] = 0;
- gp_list_append(list, fileName, NULL);
- }
- else {
- gp_debug_printf (GP_DEBUG_LOW, "dc210",
- "kodak_dc210_get_picture_info failed %d", ret);
- break;
+ dc210_status status;
+ dc210_picture_info picinfo;
+ int i;
+
+ if (dc210_get_status(camera, &status) == GP_ERROR)
+ return GP_ERROR;
+
+ if (status.numPicturesInCamera == 0){
+ return GP_OK;
+ };
+
+ for (i = 1; i <= status.numPicturesInCamera; i++){
+ if (dc210_get_picture_info(camera, &picinfo, i) == GP_ERROR)
+ return GP_ERROR;
+ gp_list_append(list, picinfo.image_name, NULL);
+ };
+
+ return GP_OK;
+
+};
+
+int dc210_get_picture_info (Camera *camera, dc210_picture_info *picinfo, unsigned int picno) {
+
+ char cmd[8];
+ unsigned char data[DC210_PICINFO_SIZE];
+ unsigned int pic_offset = picno - 1;
+
+ dc210_cmd_init(cmd, DC210_GET_PICINFO);
+ cmd[3] = pic_offset & 0xFF;
+ cmd[2] = (pic_offset >> 8) & 0xFF;
+
+ if (dc210_execute_command(camera, cmd) == GP_ERROR) return GP_ERROR;
+
+ if (dc210_read_single_block(camera, data, DC210_PICINFO_SIZE) == GP_ERROR)
+ return GP_ERROR;
+
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR)
+ return GP_ERROR;
+
+ picinfo->camera_type = data[1];
+ picinfo->file_type = data[2];
+ picinfo->resolution = data[3];
+ picinfo->compression = data[4];
+ picinfo->picture_number = data[6] * 0x100 + data[7];
+ picinfo->picture_size = data[8] * 0x1000000 + data[9] * 0x10000 + data[10] * 0x100 + data[11];
+ picinfo->preview_size = 96 * 72 * 3 + sizeof(ppmheader);
+ picinfo->picture_time = CAMERA_GET_EPOC + ((data[12] * 0x1000000 + data[13] * 0x10000 + data[14] * 0x100 + data[15]) >> 1);
+ picinfo->flash_used = data[16];
+ picinfo->flash = data[17];
+ picinfo->preflash = (data[17] > 2);
+ if (picinfo->preflash) picinfo->flash -= 3;
+ picinfo->zoom = data[21];
+ picinfo->f_number = data[26];
+ picinfo->battery = data[27];
+ picinfo->exposure_time = data[28] * 0x1000000 + data[29] * 0x10000 + data[30] * 0x100 + data[31];
+ strncpy(picinfo->image_name, &data[32], 12);
+ picinfo->image_name[12] = 0;
+
+ return GP_OK;
+
+};
+
+int dc210_get_status (Camera *camera, dc210_status *status) {
+
+#ifdef DEBUG
+ int i;
+#endif
+
+ char data[DC210_STATUS_SIZE];
+ char cmd[8];
+
+ dc210_cmd_init(cmd, DC210_GET_STATUS);
+
+ if (dc210_execute_command(camera, cmd) == GP_ERROR) return GP_ERROR;
+
+ if (dc210_read_single_block(camera, data, DC210_STATUS_SIZE) == GP_ERROR)
+ return GP_ERROR;
+
+ if (dc210_wait_for_response(camera, 0, NULL) == GP_ERROR)
+ return GP_ERROR;
+
+#ifdef DEBUG
+ if (firststatus){
+ firststatus = 0;
}
- }
- return ret;
-}
+ else{
+ for (i = 0; i < DC210_STATUS_SIZE; i++){
+ if (oldstatus[i] != data[i] && (i < 12 || i > 15)){
+ DC210_DEBUG("Statusdata differs at offset %03d (old: 0x%02X, new: 0x%02X)\n",
+ i, (unsigned char) oldstatus[i], (unsigned char) data[i]);
+ };
+ };
+ };
+ memcpy(oldstatus, data, DC210_STATUS_SIZE);
+#endif
+ status->firmwareMajor = data[2];
+ status->firmwareMinor = data[3];
+ status->fast_preview = data[8];
+ status->battery = data[9];
+ status->acstatus = data[10];
+
+ /* seconds since unix epoc */
+ status->time = CAMERA_GET_EPOC + ((unsigned char) data[12] * 0x1000000 +
+ (unsigned char) data[13] * 0x10000 +
+ (unsigned char) data[14] * 0x100 +
+ (unsigned char) data[15]) / 2;
+
+ status->zoom = data[16];
+ status->compression_type = data[19];
+ status->flash = data[20];
+ status->exp_compensation = data[21] & 0x7F;
+ if (data[21] & 0x80) status->exp_compensation *= -1;
+ status->preflash = (data[20] > 2);
+ if (status->preflash) status->flash -= 3;
+ status->resolution = data[22];
+ status->file_type = data[23];
+ status->totalPicturesTaken = (unsigned char) data[25] * 0x100 + (unsigned char) data[26];
+ status->totalFlashesFired = (unsigned char) data[27] * 0x100 + (unsigned char) data[28];
+ status->numPicturesInCamera = (unsigned char) data[56] * 0x100 + (unsigned char) data[57];
+ status->remainingLow = (unsigned char) data[68] * 0x100 + (unsigned char) data[69];
+ status->remainingMedium = (unsigned char) data[70] * 0x100 + (unsigned char) data[71];
+ status->remainingHigh = (unsigned char) data[72] * 0x100 + (unsigned char) data[73];
+ strncpy(status->album_name, &data[77], 11);
+
+ if (dc210_space_on_card(camera, &status->card_space) == GP_ERROR)
+ DC210_DEBUG("No card in camera.\n");
+
+ status->album_name[11] = 0;
+ return GP_OK;
-#if 0
-struct Image *kodak_dc210_get_preview ()
-{
- int numPicBefore;
- int numPicAfter;
- struct Image *im = NULL;
-
- /* find out how many pictures are in the camera so we can
- make sure a picture was taken later */
- numPicBefore = kodak_dc210_number_of_pictures();
-
- /* take a picture -- it returns the picture number taken */
- numPicAfter = kodak_dc210_take_picture();
-
- /* if a picture was taken then get the picture from the camera and
- then delete it */
- if (numPicBefore + 1 == numPicAfter)
- {
- im = kodak_dc210_get_picture (numPicAfter,0);
- kodak_dc210_delete_picture (numPicAfter);
- }
-
- return(im);
}
-#endif
+/* Debugging stuff, not really needed in the driver */
+
+#ifdef DEBUG
+
+static int dc210_read_dummy_packet(Camera * camera){
+
+ int i;
+ signed char error;
+ unsigned char answer, lastanswer, checksum;
+
+ checksum = 0;
+ lastanswer = 0;
+ for ( i = 0; i < 2048; i++){
+
+ error = gp_port_read(camera->port, &answer, 1);
+
+ if (error < 0){
+ DC210_DEBUG("Packet read exhausted. Packet size: %d\n", i-1);
+ if (checksum == lastanswer)
+ DC210_DEBUG("Checksum is okay. Sending okay.\n");
+ else
+ DC210_DEBUG("Checksum is not okay. Sending correct packet anyway.\n");
+ answer = DC210_CORRECT_PACKET;
+ gp_port_write(camera->port, &answer, 1);
+ return GP_OK;
+ };
+ DC210_DEBUG(" Byte %03d: 0x%02X", i, answer);
+ if (answer > 32)
+ DC210_DEBUG(" (%c)", answer);
+ DC210_DEBUG("\n");
+ checksum ^= lastanswer;
+ lastanswer = answer;
+ };
+
+ DC210_DEBUG("Packet too long. Sending cancel.\n");
+ answer = DC210_CANCEL;
+ gp_port_write(camera->port, &answer, 1);
+
+ return GP_OK;
+
+};
+
+static int dc210_test_command
+(Camera * camera, unsigned char cmdbyte, unsigned char modifier, unsigned int value, int size){
+
+ unsigned char cmd[8];
+ unsigned char answer;
+ signed char error;
+ int packetcount = 0;
+ char dummy_cmd_packet[DC210_CMD_DATA_SIZE];
+
+ memset (dummy_cmd_packet, 0, DC210_CMD_DATA_SIZE);
+
+ dc210_cmd_init(cmd, cmdbyte);
+
+ cmd[1] = modifier;
+
+ switch(size){
+ case 0:
+ break;
+ case 1:
+ cmd[2] = value & 0xFF;
+ break;
+ case 2:
+ cmd[3] = value & 0xFF;
+ cmd[2] = (value >> 8) & 0xFF;
+ break;
+ case 4:
+ cmd[5] = value & 0xFF;
+ cmd[4] = (value >> 8) & 0xFF;
+ cmd[3] = (value >> 16) & 0xFF;
+ cmd[2] = (value >> 24) & 0xFF;
+ break;
+ default:
+ return GP_ERROR;
+ };
+
+ /* okay, write the command and wait for acknowledge */
+
+ gp_port_write(camera->port, cmd, 8);
+
+ error = gp_port_read(camera->port, &answer, 1);
+
+ if (error < 0){
+ DC210_DEBUG("Command 0x%02X produced port read error %d",
+ cmdbyte, error);
+ return GP_OK;
+ };
+
+ switch (answer){
+ case DC210_COMMAND_ACK:
+ DC210_DEBUG("Okay, command 0x%02X acknowledged.\n", cmdbyte);
+ break;
+ case DC210_COMMAND_NAK:
+ DC210_DEBUG("Sorry, command 0x%02X not acknowledged.\n", cmdbyte);
+ return GP_OK;
+ default:
+ DC210_DEBUG("Unexpected response 0x%02X to command 0x%02X.\n",
+ answer, cmdbyte);
+ return GP_OK;
+ };
+
+ wait_finish:
+ error = gp_port_read(camera->port, &answer, 1);
+
+ if (error < 0){
+ DC210_DEBUG("Command 0x%02X produced port read error %d\n",
+ cmdbyte, error);
+ DC210_DEBUG("Probably the command expects a command package.\n");
+ DC210_DEBUG("Sending one...\n");
+ dc210_write_command_packet(camera, dummy_cmd_packet);
+ goto wait_finish;
+ };
+
+ switch(answer){
+ case DC210_COMMAND_COMPLETE:
+ DC210_DEBUG("Okay. Command has been accepted and executed.\n");
+ return GP_OK;
+ case DC210_EXECUTION_ERROR:
+ DC210_DEBUG("Sorry. An error occurred while executing command.\n");
+ return GP_OK;
+ case DC210_CORRECT_PACKET:
+ DC210_DEBUG("Okay. Packet successfully received.\n");
+ goto wait_finish;
+ case DC210_PACKET_FOLLOWING:
+ DC210_DEBUG("My, my, you got more than you bargained for. ");
+ DC210_DEBUG("Awaiting packet...\n");
+ dc210_read_dummy_packet(camera);
+ DC210_DEBUG("Read %d packets.\n", ++packetcount);
+ goto wait_finish;
+ case DC210_BUSY:
+ DC210_DEBUG("Camera is busy.\n");
+ goto wait_finish;
+ default:
+ DC210_DEBUG("Unexpected response 0x%02X to command 0x%02X.\n",
+ answer, cmdbyte);
+ return GP_OK;
+ };
+};
+
+int dc210_debug_callback(Camera * camera, CameraWidget * widget, GPContext * context){
+
+ /*CameraFile *file;*/
+ CameraWidget * window;
+ char * s_param1, *s_param2, *s_param3;
+ int param1, param2, param3;
+ int value;
+ dc210_status status;
+
+ gp_widget_get_root(widget, &window);
+
+ gp_widget_get_child_by_label (window, _("Parameter 1"), &widget);
+ gp_widget_get_value (widget, &s_param1);
+ param1 = atoi(s_param1);
+
+ gp_widget_get_child_by_label (window, _("Parameter 2"), &widget);
+ gp_widget_get_value (widget, &s_param2);
+ param2 = atoi(s_param2);
+
+ gp_widget_get_child_by_label (window, _("Parameter 3"), &widget);
+ gp_widget_get_value (widget, &s_param3);
+ param3 = atoi(s_param3);
+
+ /* Put the stuff you want to test here */
+ dc210_get_status(camera, &status);
+ dc210_space_on_card(camera, &value);
+ dc210_get_status(camera, &status);
+
+ return GP_OK;
+
+};
+
+#endif
diff --git a/camlibs/kodak/dc210/library.h b/camlibs/kodak/dc210/library.h
index 498500256..ee38e19be 100644
--- a/camlibs/kodak/dc210/library.h
+++ b/camlibs/kodak/dc210/library.h
@@ -1,109 +1,32 @@
-
-
#ifndef _DC210_LIBRARY_H_
#define _DC210_LIBRARY_H_
-#include <gphoto2.h>
-
-#define CAMERA_EPOC 852094800
-
-/* camera types */
-#define CAMERA_TYPE_DC50_CAMERA_TYPE 0x01
-#define CAMERA_TYPE_DC120_CAMERA_TYPE 0x02
-#define CAMERA_TYPE_DC200_CAMERA_TYPE 0x03
-#define CAMERA_TYPE_DC210_CAMERA_TYPE 0x04
-
-
-/* Control bytes */
-#define PKT_CTRL_RECV 0x01
-#define PKT_CTRL_SEND 0x00
-#define PKT_CTRL_EOF 0x80
-#define PKT_CTRL_CANCEL 0xFF
-
-
-/* Kodak System Codes */
-#define DC_COMMAND_COMPLETE 0x00
-#define DC_COMMAND_ACK 0xD1
-#define DC_CORRECT_PACKET 0xD2
-#define DC_COMMAND_NAK 0xE1
-#define DC_COMMAND_EXEC_ERROR 0xE2
-#define DC_ILLEGAL_PACKET 0xE3
-#define DC_CANCEL 0xE4
-#define DC_BUSY 0xF0
-
-/* Kodak System Commands */
-#define DC_SET_RESOLUTION 0x36
-#define DC_SET_SPEED 0x41
-#define DC_PICTURE_DOWNLOAD 0x64
-#define DC_PICTURE_INFO 0x65
-#define DC_PICTURE_THUMBNAIL 0x66
-#define DC_SET_SOMETHING 0x75
-#define DC_TAKE_PICTURE 0x7C
-#define DC_ERASE 0x7A
-#define DC_ERASE_IMAGE_IN_CARD 0x7B
-#define DC_INITIALIZE 0x7E
-#define DC_STATUS 0x7F
-#define DC_SET_CAMERA_ID 0x9E
-
-
-
-
-/* This struct is not safe if it is used to dump what is
- read from the camera */
-struct kodak_dc210_status {
- char camera_type_id; /* 1 */
- char firmware_major; /* 2 */
- char firmware_minor; /* 3 */
- char batteryStatusId; /* 8 battery status */
- char acStatusId; /* 9 */
- unsigned long time; /* 11-14 */
- char zoomMode; /* 15 */
- char flash_charged; /* 17 */
- char compression_mode_id; /* 18 */
- char flash_mode; /* 19 */
- char exposure_compensation; /* 20 */
- char picture_size; /* 21 */
- char file_Type; /* 22 */
- unsigned short totalPicturesTaken; /* 25-26 */
- unsigned short totalFlashesFired; /* 27-28 */
- unsigned short num_pictures; /* 56-57 */
- char camera_ident[32]; /* 90-122 */
-};
-
-struct kodak_dc210_picture_info {
- char reserved_1[3];
- char resolution;
- char compression;
- char reserved_2;
- short pictureNumber;
- int fileSize;
- int elapsedTime;
- char reserved_3[16];
- char fileName[12];
- char reserved_4[222];
-};
-
-
-int kodak_dc210_open_camera (DC210Data * dd);
-int kodak_dc210_close_camera (DC210Data * dd);
-
-int kodak_dc210_get_picture_info (DC210Data * dd,
- int picNum,
- struct kodak_dc210_picture_info *picInfo);
-int kodak_dc210_get_picture (DC210Data * dd, int picNum, CameraFile *file);
-int kodak_dc210_get_thumbnail (DC210Data * dd, int picNum, CameraFile *file);
-int kodak_dc210_number_of_pictures (DC210Data * dd);
-int kodak_dc210_get_directory_listing (DC210Data *dd, CameraList *list);
-int kodak_dc210_capture (DC210Data * dd);
-int kodak_dc210_delete_picture (DC210Data * dd, int picNum);
-
-int kodak_dc210_get_camera_status (DC210Data * dd,
- struct kodak_dc210_status *status);
-
+#define DC210_CMD_OKAY 0
+#define DC210_WRITE_ERROR -1
+#define DC210_READ_ERROR -2
+#define DC210_TIMEOUT_ERROR -3
+#define DC210_NAK_ERROR -4
+#define DC210_GARBAGE_ERROR -5
+
+static void dc210_cmd_init(char *cmd, unsigned char command_byte);
+static int dc210_write_single_char (Camera *camera, unsigned char response);
+static int dc210_write_command_packet(Camera * camera, char * data);
+static int dc210_execute_command (Camera *camera, char *cmd);
+static int dc210_read_single_char (Camera *camera, unsigned char * p);
+static int dc210_wait_for_response (Camera *camera, int expect_busy, GPContext *context);
+static int dc210_read_to_file (Camera *camera, CameraFile * f, long int filesize, GPContext *context);
+static int dc210_read_single_block (Camera *camera, unsigned char * b, int blocksize);
+static int dc210_take_picture (Camera * camera, GPContext *context);
+static int dc210_set_option (Camera * camera, char command, unsigned int value, int valuesize);
+static int dc210_space_on_card(Camera * camera, int * space);
+
+#ifdef DEBUG
+static int dc210_read_dummy_packet(Camera * camera);
+static int dc210_test_command(Camera * camera, unsigned char cmdbyte, unsigned char modifier,
+ unsigned int value, int size);
#endif
-
-
+#endif /* _DC210_LIBRARY_H_ */
diff --git a/camlibs/kodak/dc210/makefile.os2 b/camlibs/kodak/dc210/makefile.os2
new file mode 100644
index 000000000..9d57a7aec
--- /dev/null
+++ b/camlibs/kodak/dc210/makefile.os2
@@ -0,0 +1,22 @@
+BASEPATH=..\..\..
+
+all: start \
+ dll \
+ end
+
+!include $(BASEPATH)\os2mak.inc
+
+dll: $(CAMLIBS)\gpdc210.dll
+
+library.o : library.c
+ $(CC) -o $@ library.c $(CCFLAGS)
+
+dc210.o : dc210.c
+ $(CC) -o $@ dc210.c $(CCFLAGS)
+
+kodak.def: dc210.o
+ copy kodak.df kodak.def
+ emxexp $** >> kodak.def
+
+$(CAMLIBS)\gpdc210.dll: kodak.def library.o dc210.o
+ $(LINK) $(DLLLINKFLAGS) -o $@ $** $(LIBS)
diff --git a/camlibs/makefile.os2 b/camlibs/makefile.os2
index f12f6f269..d213cb261 100644
--- a/camlibs/makefile.os2
+++ b/camlibs/makefile.os2
@@ -31,6 +31,9 @@ dll:
@cd kodak\dc120
@nmake -nologo -f makefile.os2
@cd..\..
+ @cd kodak\dc210
+ @nmake -nologo -f makefile.os2
+ @cd..\..
@cd kodak\dc240
@nmake -nologo -f makefile.os2
@cd..\..
diff --git a/configure.in b/configure.in
index 8462a99a4..d2d1d591b 100644
--- a/configure.in
+++ b/configure.in
@@ -311,6 +311,7 @@ camlibs/jamcam/Makefile
camlibs/jd11/Makefile
camlibs/kodak/Makefile
camlibs/kodak/dc120/Makefile
+camlibs/kodak/dc210/Makefile
camlibs/kodak/dc240/Makefile
camlibs/kodak/dc3200/Makefile
camlibs/konica/Makefile