Remove generated files
[framework/connectivity/libgphoto2.git] / camlibs / samsung / samsung.c
1 /* samsung.c
2  *
3  * Copyright © 2000 James McKenzie
4  * Copyright © 2001 Lutz Müller
5  * Copyright © 2002 Marcus Meissner
6  *
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.
11  *
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. 
16  *
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.
21  */
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include <gphoto2/gphoto2-library.h>
29
30 /* The commands */
31 #define SDSC_START      0x43
32 #define SDSC_NEXT     0x53
33 #define SDSC_BINARY     0x06
34 #define SDSC_RETRANSMIT 0x15
35
36 #define SDSC_BLOCKSIZE 0x400
37 #define SDSC_INFOSIZE  0x080
38
39 #define SDSC_TIMEOUT    500
40 #define SDSC_RETRIES      3
41
42 /* Our own error codes */
43 #define SDSC_ERROR_EOF -1001
44
45 #define CHECK_RESULT(result) {int r = result; if (r < 0) return (r);}
46
47 #ifdef ENABLE_NLS
48 #  include <libintl.h>
49 #  undef _
50 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
51 #  ifdef gettext_noop
52 #    define N_(String) gettext_noop (String)
53 #  else
54 #    define N_(String) (String)
55 #  endif
56 #else
57 #  define _(String) (String)
58 #  define N_(String) (String)
59 #endif
60
61 static int
62 SDSC_send (GPPort *port, unsigned char command)
63 {
64         CHECK_RESULT (gp_port_write (port, &command, 1));
65
66         return (GP_OK);
67 }
68
69 static int
70 SDSC_receive (GPPort *port, unsigned char *buf, int length)
71 {
72         char tmp[3];
73         int i, result = GP_OK;
74
75         for (i = 0; i < SDSC_RETRIES; i++) {
76
77                 /* Read the header (3 bytes) and check for EOF */
78                 CHECK_RESULT (gp_port_read (port, tmp, 1));
79                 if (tmp[0] == 0x04)
80                         return (SDSC_ERROR_EOF);
81                 result = gp_port_read (port, tmp, 2);
82                 if (result < 0) {
83                         CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
84                         continue;
85                 }
86
87                 /* Read data */
88                 result = gp_port_read (port, buf, length);
89                 if (result < 0) {
90                         CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
91                         continue;
92                 }
93
94                 /* Read footer (2 bytes) */
95                 result = gp_port_read (port, tmp, 2);
96                 if (result < 0) {
97                         CHECK_RESULT (SDSC_send (port, SDSC_RETRANSMIT));
98                         continue;
99                 }
100                 break;
101         }
102
103         return (result);
104 }
105
106 static int
107 is_null (unsigned char *buf)
108 {
109         int n = 128;
110         
111         while (n--)
112                 if (*(buf++))
113                         return (0);
114         return (1);
115 }
116
117 static int
118 SDSC_initialize (GPPort *port)
119 {
120         unsigned char buffer[SDSC_INFOSIZE];
121
122         /* Read out a header */
123         do {
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));
128         return (GP_OK);
129 }
130
131 int
132 camera_id (CameraText *id) 
133 {
134         strcpy (id->text, "samsung");
135
136         return (GP_OK);
137 }
138
139 static const struct {
140         const char *model;
141 } models[] = {
142         {"Samsung:digimax 800k"},
143         {"Dynatron:Dynacam 800"},
144         {"Jenoptik:JD12 800ff"},
145         {"Praktica:QD800"},
146         {NULL}
147 };
148
149 int
150 camera_abilities (CameraAbilitiesList *list) 
151 {
152         int i;
153         CameraAbilities a;
154
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;
160                 a.speed[0]              = 115200;
161                 a.speed[1]              = 0;
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));
166         }
167         return (GP_OK);
168 }
169
170 static int
171 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
172                CameraFileType type, CameraFile *file, void *user_data,
173                GPContext *context)
174 {
175         Camera *camera = user_data;
176         int result;
177         int havefirst = 0;
178         unsigned char buffer[SDSC_BLOCKSIZE], first[SDSC_BLOCKSIZE];
179         long int size, curread;
180         unsigned int pid;
181
182         if (type != GP_FILE_TYPE_NORMAL)
183                 return (GP_ERROR_NOT_SUPPORTED);
184
185         /* Seek the header of our file */
186         while (1) {
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))
191                     break;
192                 if (is_null(buffer)) { /* skipped to the end of the camera? */
193                     /* Since we start at a random position, we wrap around. */
194                     continue;
195                 }
196                 /* We are at the first item again, so break. */
197                 if (havefirst && !strcmp(first,buffer))
198                         return GP_ERROR_BAD_PARAMETERS;
199                 if (!havefirst) {
200                         havefirst = 1;
201                         strcpy(first,buffer);
202                 }
203         }
204         /* The buffer header has
205          * filename (8.3 DOS format and \0)
206          * filesize (as ascii number) and \0
207          */
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));
213
214         pid = gp_context_progress_start(context,size,_("Downloading image..."));
215
216         curread = 0;
217         /* Read data */
218         while (1) {
219                 /* Read data and check for EOF */
220                 result = SDSC_receive (camera->port, buffer, SDSC_BLOCKSIZE);
221                 if (result == SDSC_ERROR_EOF)
222                         break;
223                 if (result < 0)
224                         return result;
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));
231         }
232         gp_context_progress_stop(context, pid);
233         CHECK_RESULT (gp_file_set_mime_type (file, GP_MIME_JPEG));
234         return (GP_OK);
235 }
236
237 static int
238 camera_about (Camera *camera, CameraText *about, GPContext *context) 
239 {
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.")
249                 );
250
251         return (GP_OK);
252 }
253
254 static int
255 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
256                 void *data, GPContext *context)
257 {
258         unsigned char buffer[SDSC_INFOSIZE];
259         Camera *camera = data;
260
261         /* Rewind */
262         CHECK_RESULT (SDSC_initialize (camera->port)); 
263
264         /* Count the pictures */
265         while (1) {
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))
271                         break;
272                 gp_list_append(list, buffer, NULL);
273         }
274         return (GP_OK);
275 }
276
277 static int
278 get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
279                CameraFileInfo *info, void *data, GPContext *context)
280 {
281         Camera *camera = data;
282         int havefirst = 0;
283         unsigned char buffer[SDSC_INFOSIZE], first[SDSC_INFOSIZE];
284
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. 
288          */
289         while (1) {
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))
294                         continue;
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);
302                         return GP_OK;
303                 }
304                 /* We are at the first item again */
305                 if (havefirst && !strcmp(first,buffer))
306                         break;
307                 if (!havefirst) {
308                         havefirst = 1;
309                         strcpy(first,buffer);
310                 }
311         }
312         return (GP_OK);
313 }
314
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
319 };
320
321 int
322 camera_init (Camera *camera, GPContext *context) 
323 {
324         GPPortSettings settings;
325
326         /* First, set up all the function pointers */
327         camera->functions->about                = camera_about;
328
329         /* Now, tell the filesystem where to get lists and info */
330         gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
331
332         /* Some settings */
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));
342         return (GP_OK);
343 }