diff options
author | Hubert Figuiere <hub@figuiere.net> | 2002-08-26 12:40:18 +0000 |
---|---|---|
committer | Hubert Figuiere <hub@figuiere.net> | 2002-08-26 12:40:18 +0000 |
commit | e67cd255e67305a30a56f838ffb9181947a1b7c4 (patch) | |
tree | a21706a1bd080281fea60ff207ca7ba57d16d77b | |
parent | 4ee5075150f0732dbb306fa79c636bf600bd4bdd (diff) | |
download | libgphoto2-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-- | MAINTAINERS | 3 | ||||
-rw-r--r-- | camlibs/kodak/CAMERAS | 6 | ||||
-rw-r--r-- | camlibs/kodak/Makefile.am | 2 | ||||
-rw-r--r-- | camlibs/kodak/dc210/ChangeLog | 5 | ||||
-rw-r--r-- | camlibs/kodak/dc210/Makefile.am | 2 | ||||
-rw-r--r-- | camlibs/kodak/dc210/dc210.c | 891 | ||||
-rw-r--r-- | camlibs/kodak/dc210/dc210.h | 203 | ||||
-rw-r--r-- | camlibs/kodak/dc210/kodak.df | 2 | ||||
-rw-r--r-- | camlibs/kodak/dc210/library.c | 1636 | ||||
-rw-r--r-- | camlibs/kodak/dc210/library.h | 125 | ||||
-rw-r--r-- | camlibs/kodak/dc210/makefile.os2 | 22 | ||||
-rw-r--r-- | camlibs/makefile.os2 | 3 | ||||
-rw-r--r-- | configure.in | 1 |
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, ¤t); - 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"), §ion); + 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"), §ion); + 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"), §ion); + 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"), §ion); + 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 |