1 /****************************************************************/
2 /* coolshot.c - Gphoto2 library for accessing the Panasonic     */
3 /*              Coolshot KXL-600A & KXL-601A digital cameras.   */
4 /*                                                              */
5 /* Copyright 2001 Chris Pinkham                                 */
6 /*                                                              */
7 /* Author: Chris Pinkham <cpinkham@infi.net>                    */
8 /*                                                              */
9 /* This library is free software; you can redistribute it       */
10 /* and/or modify it under the terms of the GNU Library General  */
11 /* Public License as published by the Free Software Foundation; */
12 /* either version 2 of the License, or (at your option) any     */
13 /* later version.                                               */
14 /*                                                              */
15 /* This library is distributed in the hope that it will be      */
16 /* useful, but WITHOUT ANY WARRANTY; without even the implied   */
17 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      */
18 /* PURPOSE.  See the GNU Library General Public License for     */
19 /* more details.                                                */
20 /*                                                              */
21 /* You should have received a copy of the GNU Library General   */
22 /* Public License along with this library; if not, write to the */
23 /* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,*/
24 /* Boston, MA  02110-1301  USA					*/
25 /****************************************************************/
26 
27 #include "config.h"
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <gphoto2/gphoto2.h>
33 
34 #ifdef ENABLE_NLS
35 #  include <libintl.h>
36 #  undef _
37 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
38 #  ifdef gettext_noop
39 #    define N_(String) gettext_noop (String)
40 #  else
41 #    define N_(String) (String)
42 #  endif
43 #else
44 #  define _(String) (String)
45 #  define N_(String) (String)
46 #endif
47 
48 #include "library.h"
49 
50 #define GP_MODULE "coolshot"
51 
52 #define TIMEOUT	      2000
53 #define DEFAULT_SPEED 9600
54 
55 #define COOLSHOT_VERSION "0.4"
56 #define COOLSHOT_LAST_MOD "09/06/2001 02:28 EST"
57 
58 /* define what cameras we support */
59 static char *coolshot_cameras[] = {
60 	"Panasonic:Coolshot KXL-600A",
61 	"Panasonic:Coolshot KXL-601A",
62 	""
63 };
64 
65 struct _CameraPrivateLibrary {
66 	int speed;
67 };
68 
camera_id(CameraText * id)69 int camera_id (CameraText *id)
70 {
71 	/* GP_DEBUG ("* camera_id"); */
72 
73 	strcpy (id->text, "coolshot");
74 
75 	return (GP_OK);
76 }
77 
camera_abilities(CameraAbilitiesList * list)78 int camera_abilities (CameraAbilitiesList *list)
79 {
80 	int x = 0;
81 	char *ptr;
82 	CameraAbilities a;
83 
84 	/* GP_DEBUG ("* camera_abilities"); */
85 
86 	ptr = coolshot_cameras[x++];
87 	while (*ptr) {
88 		memset(&a, 0, sizeof(a));
89 		strcpy (a.model, ptr );
90 		a.status = GP_DRIVER_STATUS_PRODUCTION;
91 		a.port     = GP_PORT_SERIAL;
92 		a.speed[0] = 9600;
93 		a.speed[1] = 19200;
94 		a.speed[2] = 38400;
95 		a.speed[3] = 57600;
96 		a.speed[4] = 115200;
97 		a.speed[5] = 0;
98 
99 		/* fixme, need to set these operations lists to correct values */
100 		a.operations        = 	GP_OPERATION_NONE;
101 		a.file_operations   = 	GP_FILE_OPERATION_PREVIEW;
102 
103 		/* fixme, believe supports GP_FOLDER_PUT_FILE */
104 		a.folder_operations = 	GP_FOLDER_OPERATION_NONE;
105 
106 		gp_abilities_list_append (list, a);
107 
108 		ptr = coolshot_cameras[x++];
109 	}
110 
111 	return (GP_OK);
112 }
113 
camera_start(Camera * camera)114 static int camera_start (Camera *camera)
115 {
116 	GP_DEBUG ("* camera_start");
117 
118 	/* coolshot_sb sets to default speed if speed == 0 */
119 	CHECK (coolshot_sb (camera, camera->pl->speed));
120 	return( GP_OK );
121 }
122 
camera_stop(Camera * camera)123 static int camera_stop (Camera *camera)
124 {
125 	GP_DEBUG ("* camera_stop");
126 
127 	CHECK (coolshot_sb( camera, DEFAULT_SPEED));
128 	return (GP_OK);
129 }
130 
file_list_func(CameraFilesystem * fs,const char * folder,CameraList * list,void * data,GPContext * context)131 static int file_list_func (CameraFilesystem *fs, const char *folder,
132 			   CameraList *list, void *data, GPContext *context)
133 {
134 	Camera *camera = data;
135 	int count;
136 
137 	GP_DEBUG ("* file_list_func");
138 	GP_DEBUG ("*** folder: %s", folder);
139 
140 	CHECK (camera_start (camera));
141 	CHECK (count = coolshot_file_count (camera));
142 	CHECK (gp_list_populate (list, "pic_%04i.jpg", count));
143 
144 	return (camera_stop (camera));
145 }
146 
get_info_func(CameraFilesystem * fs,const char * folder,const char * filename,CameraFileInfo * info,void * data,GPContext * context)147 static int get_info_func (CameraFilesystem *fs, const char *folder,
148 		const char *filename, CameraFileInfo *info, void *data,
149 		GPContext *context)
150 {
151 	Camera *camera = data;
152 	int n;
153 
154 	GP_DEBUG ("* get_info_func");
155 	GP_DEBUG ("*** folder: %s", folder);
156 	GP_DEBUG ("*** filename: %s",filename);
157 
158 	CHECK (camera_start (camera));
159 
160 	/* Get the file number from the CameraFileSystem */
161 	CHECK (n = gp_filesystem_number (camera->fs, folder, filename,
162 					 context));
163 
164 	/* fixme, get file size also */
165 	info->file.fields = GP_FILE_INFO_TYPE;
166 	strcpy (info->file.type, GP_MIME_JPEG );
167 
168 	info->preview.fields = GP_FILE_INFO_TYPE;
169 	strcpy (info->preview.type, GP_MIME_JPEG);
170 
171 	return (camera_stop (camera));
172 }
173 
camera_exit(Camera * camera,GPContext * context)174 static int camera_exit (Camera *camera, GPContext *context)
175 {
176 	if (camera->pl) {
177 		free (camera->pl);
178 		camera->pl = NULL;
179 	}
180 
181 	return (GP_OK);
182 }
183 
get_file_func(CameraFilesystem * fs,const char * folder,const char * filename,CameraFileType type,CameraFile * file,void * user_data,GPContext * context)184 static int get_file_func (CameraFilesystem *fs, const char *folder,
185 			  const char *filename, CameraFileType type,
186 			  CameraFile *file, void *user_data, GPContext *context)
187 {
188 	Camera *camera = user_data;
189 	char data[128000];
190 	int size, n;
191 
192 	GP_DEBUG ("* camera_file_get");
193 	GP_DEBUG ("*** folder: %s", folder);
194 	GP_DEBUG ("*** filename: %s",filename);
195 	GP_DEBUG ("*** type: %d", type);
196 
197 	CHECK (camera_start (camera));
198 
199 	if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
200 		camera_stop (camera);
201 		return (GP_ERROR_CANCEL);
202 	}
203 
204 	/*
205 	 * Get the file number from the CameraFileSystem (and increment
206 	 * because we need numbers starting with 1)
207 	 */
208 	CHECK (n = gp_filesystem_number (camera->fs, folder, filename,
209 					 context));
210 	n++;
211 
212 	switch (type) {
213 	case GP_FILE_TYPE_PREVIEW:
214 		CHECK (coolshot_request_thumbnail (camera, file, data, &size, n, context));
215 		CHECK (coolshot_build_thumbnail (data, &size));
216 		CHECK (gp_file_set_mime_type (file, GP_MIME_PPM));
217 		break;
218 
219 	case GP_FILE_TYPE_NORMAL:
220 		CHECK (coolshot_request_image (camera, file, data, &size, n, context));
221 		CHECK (gp_file_set_mime_type (file, GP_MIME_JPEG));
222 		break;
223 	default:
224 		return (GP_ERROR_NOT_SUPPORTED);
225 	}
226 
227 	CHECK (gp_file_append (file, data, size));
228 
229 	return (camera_stop (camera));
230 }
231 
camera_summary(Camera * camera,CameraText * summary,GPContext * context)232 static int camera_summary (Camera *camera, CameraText *summary,
233 			   GPContext *context)
234 {
235 	int count;
236 	char tmp[1024];
237 
238 	GP_DEBUG ("* camera_summary");
239 
240 	CHECK (camera_start (camera));
241 
242 	/* possibly get # pics, mem free, etc. */
243 	count = coolshot_file_count (camera);
244 
245 	sprintf (tmp, "Frames Taken     : %4d\n", count);
246 	strcat (summary->text, tmp );
247 
248 	return (camera_stop (camera));
249 }
250 
camera_about(Camera * camera,CameraText * about,GPContext * context)251 static int camera_about (Camera *camera, CameraText *about, GPContext *context)
252 {
253 	GP_DEBUG ("* camera_about");
254 
255 	strcpy (about->text,
256 		_("coolshot library v" COOLSHOT_VERSION
257 		" " COOLSHOT_LAST_MOD "\n"
258 		"Chris Pinkham <cpinkham@infi.net>\n"
259 		"Support for Panasonic Coolshot digital cameras\n"
260 		"based on reverse engineering serial protocol.\n"
261 		"\n"));
262 
263 	return (GP_OK);
264 }
265 
266 static CameraFilesystemFuncs fsfuncs = {
267 	.file_list_func = file_list_func,
268 	.get_file_func = get_file_func,
269 	.get_info_func = get_info_func,
270 };
271 
camera_init(Camera * camera,GPContext * context)272 int camera_init (Camera *camera, GPContext *context)
273 {
274 	int count;
275 	GPPortSettings settings;
276 
277 	/* First, set up all the function pointers */
278 	camera->functions->exit 	= camera_exit;
279 	camera->functions->summary	= camera_summary;
280 	camera->functions->about 	= camera_about;
281 
282 	camera->pl = malloc (sizeof (CameraPrivateLibrary));
283 	if (!camera->pl)
284 		return (GP_ERROR_NO_MEMORY);
285 
286 	/* Set up the port and remember the requested speed */
287 	CHECK (gp_port_get_settings (camera->port, &settings));
288 	camera->pl->speed = settings.serial.speed;
289 	settings.serial.speed 	 = DEFAULT_SPEED;
290 	settings.serial.bits 	 = 8;
291 	settings.serial.parity 	 = 0;
292 	settings.serial.stopbits = 1;
293 	CHECK (gp_port_set_settings (camera->port, settings));
294 	CHECK (gp_port_set_timeout (camera->port, TIMEOUT));
295 
296 	/* check to see if camera is really there */
297 	CHECK (coolshot_enq (camera));
298 
299 	coolshot_sm (camera);
300 
301 	/* get number of images */
302 	CHECK (count = coolshot_file_count (camera));
303 
304 	CHECK (camera_start (camera));
305 	CHECK (gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera));
306 
307 	/* coolshot_sb sets to default speed if speed == 0 */
308 	CHECK (coolshot_sb (camera, camera->pl->speed));
309 
310 	return (camera_stop (camera));
311 }
312