3 * Copyright © 2000 James McKenzie
4 * Copyright © 2001 Lutz Müller
5 * Copyright © 2002 Marcus Meissner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
28 #include <gphoto2/gphoto2-library.h>
31 #define SDSC_START 0x43
32 #define SDSC_NEXT 0x53
33 #define SDSC_BINARY 0x06
34 #define SDSC_RETRANSMIT 0x15
36 #define SDSC_BLOCKSIZE 0x400
37 #define SDSC_INFOSIZE 0x080
39 #define SDSC_TIMEOUT 500
40 #define SDSC_RETRIES 3
42 /* Our own error codes */
43 #define SDSC_ERROR_EOF -1001
45 #define CHECK_RESULT(result) {int r = result; if (r < 0) return (r);}
50 # define _(String) dgettext (GETTEXT_PACKAGE, String)
52 # define N_(String) gettext_noop (String)
54 # define N_(String) (String)
57 # define _(String) (String)
58 # define N_(String) (String)
62 SDSC_send (GPPort *port, unsigned char command)
64 CHECK_RESULT (gp_port_write (port, &command, 1));
70 SDSC_receive (GPPort *port, unsigned char *buf, int length)
73 int i, result = GP_OK;
75 for (i = 0; i < SDSC_RETRIES; i++) {
77 /* Read the header (3 bytes) and check for EOF */
78 CHECK_RESULT (gp_port_read (port, tmp, 1));
80 return (SDSC_ERROR_EOF);
81 result = gp_port_read (port, tmp, 2);
83 CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
88 result = gp_port_read (port, buf, length);
90 CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
94 /* Read footer (2 bytes) */
95 result = gp_port_read (port, tmp, 2);
97 CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
107 is_null (unsigned char *buf)
118 SDSC_initialize (GPPort *port)
120 unsigned char buffer[SDSC_INFOSIZE];
122 /* Read out a header */
124 CHECK_RESULT (SDSC_send (port, SDSC_NEXT));
125 CHECK_RESULT (SDSC_send (port, SDSC_START));
126 CHECK_RESULT (SDSC_receive (port, buffer, SDSC_INFOSIZE));
127 } while (!is_null (buffer));
132 camera_id (CameraText *id)
134 strcpy (id->text, "samsung");
139 static const struct {
142 {"Samsung:digimax 800k"},
143 {"Dynatron:Dynacam 800"},
144 {"Jenoptik:JD12 800ff"},
150 camera_abilities (CameraAbilitiesList *list)
155 for (i = 0; models[i].model; i++) {
156 memset (&a, 0, sizeof(a));
157 strcpy (a.model, models[i].model);
158 a.status = GP_DRIVER_STATUS_PRODUCTION;
159 a.port = GP_PORT_SERIAL;
162 a.operations = GP_OPERATION_NONE;
163 a.file_operations = GP_FILE_OPERATION_NONE;
164 a.folder_operations = GP_FOLDER_OPERATION_NONE;
165 CHECK_RESULT (gp_abilities_list_append (list, a));
171 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
172 CameraFileType type, CameraFile *file, void *user_data,
175 Camera *camera = user_data;
178 unsigned char buffer[SDSC_BLOCKSIZE], first[SDSC_BLOCKSIZE];
179 long int size, curread;
182 if (type != GP_FILE_TYPE_NORMAL)
183 return (GP_ERROR_NOT_SUPPORTED);
185 /* Seek the header of our file */
187 CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
188 CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
189 CHECK_RESULT (SDSC_receive (camera->port, buffer, SDSC_INFOSIZE));
190 if (!strcmp(buffer,filename))
192 if (is_null(buffer)) { /* skipped to the end of the camera? */
193 /* Since we start at a random position, we wrap around. */
196 /* We are at the first item again, so break. */
197 if (havefirst && !strcmp(first,buffer))
198 return GP_ERROR_BAD_PARAMETERS;
201 strcpy(first,buffer);
204 /* The buffer header has
205 * filename (8.3 DOS format and \0)
206 * filesize (as ascii number) and \0
208 /* Extract the size of the file */
209 sscanf(buffer+12,"%ld",&size);
210 /* Put the camera into image mode */
211 CHECK_RESULT (SDSC_send (camera->port, SDSC_BINARY));
212 CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
214 pid = gp_context_progress_start(context,size,_("Downloading image..."));
219 /* Read data and check for EOF */
220 result = SDSC_receive (camera->port, buffer, SDSC_BLOCKSIZE);
221 if (result == SDSC_ERROR_EOF)
225 gp_file_append(file,buffer,SDSC_BLOCKSIZE);
226 curread += SDSC_BLOCKSIZE;
227 gp_context_progress_update(context, pid, curread);
228 if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL)
229 return GP_ERROR_CANCEL;
230 CHECK_RESULT (SDSC_send (camera->port, SDSC_BINARY));
232 gp_context_progress_stop(context, pid);
233 CHECK_RESULT (gp_file_set_mime_type (file, GP_MIME_JPEG));
238 camera_about (Camera *camera, CameraText *about, GPContext *context)
240 /* Translators: please write 'M"uller' and 'Mei"sner' (that
241 is, with u-umlaut and eszett resp.) if your charset
242 allows it. If not, use "Mueller" and "Meissner". */
243 strcpy (about->text, _("The Samsung digimax 800k driver has "
244 "been written by James McKenzie "
245 "<james@fishsoup.dhs.org> for gphoto. "
246 "Lutz Mueller <lutz@users.sourceforge.net> ported it to "
247 "gphoto2. Marcus Meissner <marcus@jet.franken.de> fixed "
248 "and enhanced the port.")
255 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
256 void *data, GPContext *context)
258 unsigned char buffer[SDSC_INFOSIZE];
259 Camera *camera = data;
262 CHECK_RESULT (SDSC_initialize (camera->port));
264 /* Count the pictures */
266 CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
267 CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
268 CHECK_RESULT (SDSC_receive (camera->port,
269 buffer, SDSC_INFOSIZE));
270 if (is_null (buffer))
272 gp_list_append(list, buffer, NULL);
278 get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
279 CameraFileInfo *info, void *data, GPContext *context)
281 Camera *camera = data;
283 unsigned char buffer[SDSC_INFOSIZE], first[SDSC_INFOSIZE];
285 info->file.fields = GP_FILE_INFO_NONE;
286 /* Don't rewind, just go forward until we find it.
287 * Works way better for linear queries.
290 CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
291 CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
292 CHECK_RESULT (SDSC_receive (camera->port,buffer,SDSC_INFOSIZE));
293 if (is_null (buffer))
295 if (!strcmp(buffer,filename)) {
296 info->file.fields = GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT | GP_FILE_INFO_SIZE | GP_FILE_INFO_NAME;
297 info->file.width = 1024;
298 info->file.height = 768;
299 strcpy(info->file.type,GP_MIME_JPEG);
300 strcpy(info->file.name,buffer);
301 sscanf(buffer+12,"%ld",&info->file.size);
304 /* We are at the first item again */
305 if (havefirst && !strcmp(first,buffer))
309 strcpy(first,buffer);
315 static CameraFilesystemFuncs fsfuncs = {
316 .file_list_func = file_list_func,
317 .get_file_func = get_file_func,
318 .get_info_func = get_info_func
322 camera_init (Camera *camera, GPContext *context)
324 GPPortSettings settings;
326 /* First, set up all the function pointers */
327 camera->functions->about = camera_about;
329 /* Now, tell the filesystem where to get lists and info */
330 gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
333 CHECK_RESULT (gp_port_get_settings (camera->port, &settings));
334 settings.serial.speed = 115200;
335 settings.serial.bits = 8;
336 settings.serial.parity = 0;
337 settings.serial.stopbits= 1;
338 CHECK_RESULT (gp_port_set_settings (camera->port, settings));
339 CHECK_RESULT (gp_port_set_timeout (camera->port, SDSC_TIMEOUT));
340 /* Open the port and check if the camera is there */
341 CHECK_RESULT (SDSC_initialize (camera->port));