1 /* dc240.c
2 *
3 * Copyright (C) 2001,2002 Hubert Figuiere <hfiguiere@teaser.fr>
4 * Copyright (C) 2000,2001,2002 Scott Fritzinger
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 */
21
22 /*
23 Kodak DC 240/280/3400/5000 driver.
24 Maintainer:
25 Hubert Figuiere <hfiguiere@teaser.fr>
26 */
27
28 #include "config.h"
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include <gphoto2/gphoto2.h>
35 #include <gphoto2/gphoto2-port.h>
36
37 #ifdef ENABLE_NLS
38 # include <libintl.h>
39 # undef _
40 # define _(String) dgettext (GETTEXT_PACKAGE, String)
41 # ifdef gettext_noop
42 # define N_(String) gettext_noop (String)
43 # else
44 # define N_(String) (String)
45 # endif
46 #else
47 # define textdomain(String) (String)
48 # define gettext(String) (String)
49 # define dgettext(Domain,Message) (Message)
50 # define dcgettext(Domain,Message,Type) (Message)
51 # define bindtextdomain(Domain,Directory) (Domain)
52 # define _(String) (String)
53 # define N_(String) (String)
54 #endif
55
56 #include "dc240.h"
57 #include "library.h"
58
59 int
camera_id(CameraText * id)60 camera_id (CameraText *id)
61 {
62 strcpy(id->text, "kodak-dc240");
63
64 return (GP_OK);
65 }
66
67 static const struct camera_to_usb {
68 char *name;
69 unsigned short idVendor;
70 unsigned short idProduct;
71 } camera_to_usb[] = {
72 { "Kodak:DC240", 0x040A, 0x0120 },
73 { "Kodak:DC280", 0x040A, 0x0130 },
74 { "Kodak:DC3400", 0x040A, 0x0132 },
75 { "Kodak:DC5000", 0x040A, 0x0131 },
76 { NULL, 0, 0 }
77 };
78
79 /*
80 Abilities are based upon what we can do with a DC240.
81 Later cameras have a superset of the DC240 feature and are not
82 currently supported.
83 */
84 int
camera_abilities(CameraAbilitiesList * list)85 camera_abilities (CameraAbilitiesList *list)
86 {
87 CameraAbilities a;
88 int i;
89
90 for (i = 0; camera_to_usb[i].name; i++)
91 {
92 memset (&a, 0, sizeof (a));
93 strcpy(a.model, camera_to_usb[i].name);
94 a.status = GP_DRIVER_STATUS_PRODUCTION;
95 a.port = GP_PORT_SERIAL | GP_PORT_USB;
96 a.speed[0] = 9600;
97 a.speed[1] = 19200;
98 a.speed[2] = 38400;
99 a.speed[3] = 57600;
100 a.speed[4] = 115200;
101 a.speed[5] = 0;
102 a.usb_vendor = camera_to_usb[i].idVendor;
103 a.usb_product = camera_to_usb[i].idProduct;
104 a.operations = GP_OPERATION_CAPTURE_IMAGE;
105 a.file_operations = GP_FILE_OPERATION_DELETE |
106 GP_FILE_OPERATION_PREVIEW;
107 a.folder_operations = GP_FOLDER_OPERATION_NONE;
108
109 gp_abilities_list_append(list, a);
110 }
111 return (GP_OK);
112 }
113
114 static int
camera_exit(Camera * camera,GPContext * context)115 camera_exit (Camera *camera, GPContext *context)
116 {
117 dc240_close (camera, context);
118
119 return (GP_OK);
120 }
121
122 static int
folder_list_func(CameraFilesystem * fs,const char * folder,CameraList * list,void * data,GPContext * context)123 folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
124 void *data, GPContext *context)
125 {
126 Camera *camera = data;
127
128 return dc240_get_directory_list(camera, list, folder, 0x10, context);
129 }
130
131 static int
file_list_func(CameraFilesystem * fs,const char * folder,CameraList * list,void * data,GPContext * context)132 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
133 void *data, GPContext *context)
134 {
135 Camera *camera = data;
136
137 return dc240_get_directory_list(camera, list, folder, 0x00, context);
138 }
139
140 static int
get_file_func(CameraFilesystem * fs,const char * folder,const char * filename,CameraFileType type,CameraFile * file,void * data,GPContext * context)141 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
142 CameraFileType type, CameraFile *file, void *data,
143 GPContext *context)
144 {
145 Camera *camera = data;
146
147 switch (type) {
148 case GP_FILE_TYPE_NORMAL:
149 case GP_FILE_TYPE_RAW:
150 return dc240_file_action (camera, DC240_ACTION_IMAGE, file,
151 folder, filename, context);
152 case GP_FILE_TYPE_PREVIEW:
153 return dc240_file_action (camera, DC240_ACTION_PREVIEW, file,
154 folder, (char*) filename, context);
155 default:
156 return GP_ERROR_NOT_SUPPORTED;
157 }
158 }
159
160 static int
delete_file_func(CameraFilesystem * fs,const char * folder,const char * filename,void * data,GPContext * context)161 delete_file_func (CameraFilesystem *fs, const char *folder,
162 const char *filename, void *data, GPContext *context)
163 {
164 Camera *camera = data;
165
166 return (dc240_file_action (camera, DC240_ACTION_DELETE, NULL, folder,
167 filename, context));
168 }
169
170 static int
camera_capture(Camera * camera,CameraCaptureType type,CameraFilePath * path,GPContext * context)171 camera_capture (Camera *camera, CameraCaptureType type,
172 CameraFilePath *path, GPContext *context)
173 {
174 int result;
175
176 if (type != GP_CAPTURE_IMAGE)
177 return (GP_ERROR_NOT_SUPPORTED);
178
179 /* Capture the image */
180 result = dc240_capture (camera, path, context);
181 if (result < 0)
182 return (result);
183
184 /* Tell the filesystem about it */
185 result = gp_filesystem_append (camera->fs, path->folder, path->name, context);
186 if (result < 0)
187 return (result);
188
189 return (GP_OK);
190 }
191
192 static int
camera_summary(Camera * camera,CameraText * summary,GPContext * context)193 camera_summary (Camera *camera, CameraText *summary, GPContext *context)
194 {
195 char buf [32 * 1024];
196 char temp [1024];
197 int retval;
198 DC240StatusTable table;
199
200 retval = dc240_get_status (camera, &table, context);
201 if (retval == GP_OK) {
202 sprintf (buf, _("Model: Kodak %s\n"), dc240_convert_type_to_camera(table.cameraType));
203 sprintf (temp, _("Firmware version: %d.%02d\n"), table.fwVersInt, table.fwVersDec);
204 strcat (buf, temp);
205 sprintf (temp, _("Battery status: %s, AC Adapter: %s\n"),
206 dc240_get_battery_status_str(table.battStatus),
207 dc240_get_ac_status_str(table.acAdapter));
208 strcat (buf, temp);
209 sprintf (temp, _("Number of pictures: %d\n"), table.numPict);
210 strcat (buf, temp);
211 sprintf (temp, _("Space remaining: High: %d, Medium: %d, Low: %d\n"),
212 table.remPictHigh, table.remPictMed, table.remPictLow);
213 strcat (buf, temp);
214
215 sprintf (temp, _("Memory card status (%d): %s\n"), table.memCardStatus,
216 dc240_get_memcard_status_str(table.memCardStatus));
217 strcat (buf, temp);
218
219 sprintf (temp, _("Total pictures captured: %d, Flashes fired: %d\n"),
220 table.totalPictTaken, table.totalStrobeFired);
221 strcat (buf, temp);
222
223
224 strcpy(summary->text, buf);
225 }
226 return retval;
227 }
228
229 static int
camera_about(Camera * camera,CameraText * about,GPContext * context)230 camera_about (Camera *camera, CameraText *about, GPContext *context)
231 {
232 strcpy (about->text,
233 _("Kodak DC240 Camera Library\n"
234 "Scott Fritzinger <scottf@gphoto.net> and Hubert Figuiere <hfiguiere@teaser.fr>\n"
235 "Camera Library for the Kodak DC240, DC280, DC3400 and DC5000 cameras.\n"
236 "Rewritten and updated for gPhoto2."));
237
238 return (GP_OK);
239 }
240
241 static CameraFilesystemFuncs fsfuncs = {
242 .file_list_func = file_list_func,
243 .folder_list_func = folder_list_func,
244 .get_file_func = get_file_func,
245 .del_file_func = delete_file_func
246 };
247
248 int
camera_init(Camera * camera,GPContext * context)249 camera_init (Camera *camera, GPContext *context)
250 {
251 int ret, selected_speed = 0;
252 GPPortSettings settings;
253
254 /* First, set up all the function pointers */
255 camera->functions->exit = camera_exit;
256 camera->functions->capture = camera_capture;
257 camera->functions->summary = camera_summary;
258 camera->functions->about = camera_about;
259
260 /* Set up the CameraFilesystem */
261 gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
262
263 ret = gp_port_get_settings (camera->port, &settings);
264 if (ret < 0)
265 return (ret);
266 switch (camera->port->type) {
267 case GP_PORT_SERIAL:
268
269 /* Remember the selected speed */
270 selected_speed = settings.serial.speed;
271
272 settings.serial.speed = 9600;
273 settings.serial.bits = 8;
274 settings.serial.parity = 0;
275 settings.serial.stopbits = 1;
276 break;
277 case GP_PORT_USB:
278 settings.usb.inep = 0x82;
279 settings.usb.outep = 0x01;
280 settings.usb.config = 1;
281 settings.usb.interface = 0;
282 settings.usb.altsetting = 0;
283 break;
284 default:
285 return (GP_ERROR_UNKNOWN_PORT);
286 }
287
288 ret = gp_port_set_settings (camera->port, settings);
289 if (ret < 0)
290 return (ret);
291
292 ret = gp_port_set_timeout (camera->port, TIMEOUT);
293 if (ret < 0)
294 return (ret);
295
296 if (camera->port->type == GP_PORT_SERIAL) {
297 char buf[8];
298 /* Reset the camera to 9600 */
299 gp_port_send_break(camera->port, 1);
300
301 /* Used to have a 1500 msec pause here to give
302 * the camera time to reset - but, since
303 * the serial port sometimes returns a garbage
304 * character or two after the break, we do
305 * a couple of TIMEOUT (750 msec) pauses here
306 * force the delay as well as flush the port
307 */
308 gp_port_read(camera->port, buf, 8);
309 gp_port_read(camera->port, buf, 8);
310
311 ret = dc240_set_speed (camera, selected_speed);
312 if (ret < 0)
313 return (ret);
314 }
315
316 /* Open the CF card */
317 ret = dc240_open (camera);
318 if (ret < 0)
319 return (ret);
320
321 ret = dc240_packet_set_size (camera, HPBS+2);
322 if (ret < 0)
323 return (ret);
324
325 return (GP_OK);
326 }
327