/* dc240.c * * Copyright (C) 2001,2002 Hubert Figuiere * Copyright (C) 2000,2001,2002 Scott Fritzinger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ /* Kodak DC 240/280/3400/5000 driver. Maintainer: Hubert Figuiere */ #include "config.h" #include #include #include #include #include #ifdef ENABLE_NLS # include # undef _ # define _(String) dgettext (GETTEXT_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 "dc240.h" #include "library.h" int camera_id (CameraText *id) { strcpy(id->text, "kodak-dc240"); return (GP_OK); } static const struct camera_to_usb { char *name; unsigned short idVendor; unsigned short idProduct; } camera_to_usb[] = { { "Kodak:DC240", 0x040A, 0x0120 }, { "Kodak:DC280", 0x040A, 0x0130 }, { "Kodak:DC3400", 0x040A, 0x0132 }, { "Kodak:DC5000", 0x040A, 0x0131 }, { NULL, 0, 0 } }; /* Abilities are based upon what we can do with a DC240. Later cameras have a superset of the DC240 feature and are not currently supported. */ int camera_abilities (CameraAbilitiesList *list) { CameraAbilities a; int i; for (i = 0; camera_to_usb[i].name; i++) { memset (&a, 0, sizeof (a)); strcpy(a.model, camera_to_usb[i].name); a.status = GP_DRIVER_STATUS_PRODUCTION; a.port = GP_PORT_SERIAL | GP_PORT_USB; 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.usb_vendor = camera_to_usb[i].idVendor; a.usb_product = camera_to_usb[i].idProduct; 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); } static int camera_exit (Camera *camera, GPContext *context) { dc240_close (camera, context); return (GP_OK); } static int folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, void *data, GPContext *context) { Camera *camera = data; return dc240_get_directory_list(camera, list, folder, 0x10, context); } static int file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, void *data, GPContext *context) { Camera *camera = data; return dc240_get_directory_list(camera, list, folder, 0x00, context); } static int get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *data, GPContext *context) { Camera *camera = data; switch (type) { case GP_FILE_TYPE_NORMAL: case GP_FILE_TYPE_RAW: return dc240_file_action (camera, DC240_ACTION_IMAGE, file, folder, filename, context); case GP_FILE_TYPE_PREVIEW: return dc240_file_action (camera, DC240_ACTION_PREVIEW, file, folder, (char*) filename, context); default: return GP_ERROR_NOT_SUPPORTED; } } static int delete_file_func (CameraFilesystem *fs, const char *folder, const char *filename, void *data, GPContext *context) { Camera *camera = data; return (dc240_file_action (camera, DC240_ACTION_DELETE, NULL, folder, filename, context)); } static int camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path, GPContext *context) { int result; if (type != GP_CAPTURE_IMAGE) return (GP_ERROR_NOT_SUPPORTED); /* Capture the image */ result = dc240_capture (camera, path, context); if (result < 0) return (result); /* Tell the filesystem about it */ result = gp_filesystem_append (camera->fs, path->folder, path->name, context); if (result < 0) return (result); return (GP_OK); } static int camera_summary (Camera *camera, CameraText *summary, GPContext *context) { char buf [32 * 1024]; char temp [1024]; int retval; DC240StatusTable table; retval = dc240_get_status (camera, &table, context); if (retval == GP_OK) { sprintf (buf, _("Model: Kodak %s\n"), dc240_convert_type_to_camera(table.cameraType)); sprintf (temp, _("Firmware version: %d.%02d\n"), table.fwVersInt, table.fwVersDec); strcat (buf, temp); sprintf (temp, _("Battery status: %s, AC Adapter: %s\n"), dc240_get_battery_status_str(table.battStatus), dc240_get_ac_status_str(table.acAdapter)); strcat (buf, temp); sprintf (temp, _("Number of pictures: %d\n"), table.numPict); strcat (buf, temp); sprintf (temp, _("Space remaining: High: %d, Medium: %d, Low: %d\n"), table.remPictHigh, table.remPictMed, table.remPictLow); strcat (buf, temp); sprintf (temp, _("Memory card status (%d): %s\n"), table.memCardStatus, dc240_get_memcard_status_str(table.memCardStatus)); strcat (buf, temp); sprintf (temp, _("Total pictures captured: %d, Flashes fired: %d\n"), table.totalPictTaken, table.totalStrobeFired); strcat (buf, temp); strcpy(summary->text, buf); } return retval; } static int camera_about (Camera *camera, CameraText *about, GPContext *context) { strcpy (about->text, _("Kodak DC240 Camera Library\n" "Scott Fritzinger and Hubert Figuiere \n" "Camera Library for the Kodak DC240, DC280, DC3400 and DC5000 cameras.\n" "Rewritten and updated for gPhoto2.")); return (GP_OK); } static CameraFilesystemFuncs fsfuncs = { .file_list_func = file_list_func, .folder_list_func = folder_list_func, .get_file_func = get_file_func, .del_file_func = delete_file_func }; int camera_init (Camera *camera, GPContext *context) { int ret, selected_speed = 0; GPPortSettings settings; /* First, set up all the function pointers */ camera->functions->exit = camera_exit; camera->functions->capture = camera_capture; camera->functions->summary = camera_summary; camera->functions->about = camera_about; /* Set up the CameraFilesystem */ gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); ret = gp_port_get_settings (camera->port, &settings); if (ret < 0) return (ret); switch (camera->port->type) { case GP_PORT_SERIAL: /* Remember the selected speed */ selected_speed = settings.serial.speed; settings.serial.speed = 9600; settings.serial.bits = 8; settings.serial.parity = 0; settings.serial.stopbits = 1; break; case GP_PORT_USB: settings.usb.inep = 0x82; settings.usb.outep = 0x01; settings.usb.config = 1; settings.usb.interface = 0; settings.usb.altsetting = 0; break; default: return (GP_ERROR_UNKNOWN_PORT); } ret = gp_port_set_settings (camera->port, settings); if (ret < 0) return (ret); ret = gp_port_set_timeout (camera->port, TIMEOUT); if (ret < 0) return (ret); if (camera->port->type == GP_PORT_SERIAL) { char buf[8]; /* Reset the camera to 9600 */ gp_port_send_break(camera->port, 1); /* Used to have a 1500 msec pause here to give * the camera time to reset - but, since * the serial port sometimes returns a garbage * character or two after the break, we do * a couple of TIMEOUT (750 msec) pauses here * force the delay as well as flush the port */ gp_port_read(camera->port, buf, 8); gp_port_read(camera->port, buf, 8); ret = dc240_set_speed (camera, selected_speed); if (ret < 0) return (ret); } /* Open the CF card */ ret = dc240_open (camera); if (ret < 0) return (ret); ret = dc240_packet_set_size (camera, HPBS+2); if (ret < 0) return (ret); return (GP_OK); }