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