Source code upload
[framework/connectivity/libgphoto2.git] / camlibs / casio / casio-qv-commands.c
1 /* casio-qv-commands.c
2  *
3  * Copyright © 2001 Lutz Müller
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, 
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details. 
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 #include "config.h"
21 #include "casio-qv-commands.h"
22
23 #include <stdlib.h>
24
25 #define STX 0x02
26 #define ETX 0x03
27 #define ENQ 0x05
28 #define ACK 0x06
29 #define DC2 0x12
30 #define NAK 0x15
31 #define ETB 0x17
32 #define UNKNOWN1 0xfe
33 #define UNKNOWN2 0xe0
34
35 #define CASIO_QV_RETRIES 5
36
37 #define CR(result) {int r = (result); if (r < 0) return (r);}
38
39 int
40 QVping (Camera *camera)
41 {
42         unsigned char c;
43         int result = GP_OK, i = 0;
44
45         /* Send ENQ and wait for ACK */
46         while (1) {
47                 c = ENQ;
48                 CR (gp_port_write (camera->port, &c, 1));
49                 result = gp_port_read (camera->port, &c, 1);
50
51                 /* If we got ACK, everything is fine. */
52                 if (result >= 0) {
53                         switch (c) {
54                         case ACK:
55                         case ENQ:
56                                 
57                                 /*
58                                  * According to gphoto, we need to wait
59                                  * for ACK. But the camera of 
60                                  * David Wolfskill <david@catwhisker.org>
61                                  * seems to return ENQ after some NAK.
62                                  */
63                                 return (GP_OK);
64
65                         case NAK:
66
67                                 /* The camera is not yet ready. */
68                                 break;
69
70                         case UNKNOWN1:
71                         case UNKNOWN2:
72
73                                 /* 
74                                  * David Wolfskill <david@catwhisker.org>
75                                  * has seen those two bytes if one sends
76                                  * only ENQs to the camera. The camera first
77                                  * answers with some NAKs, then with some
78                                  * ACKs, and finally with UNKNOWN1 and 
79                                  * UNKNOWN2.
80                                  */
81                                 while (gp_port_read (camera->port, &c, 1) >= 0);
82                                 break;
83
84                         default:
85                                 while (gp_port_read (camera->port, &c, 1) >= 0);
86                                 break;
87                         }
88                 }
89
90                 if (++i < CASIO_QV_RETRIES)
91                         continue;
92
93                 /* If we got an error from libgphoto2_port, pass it along */
94                 CR (result);
95
96                 /* Return some error code */
97                 return (GP_ERROR_CORRUPTED_DATA);
98         }
99 }
100
101 static int
102 QVsend (Camera *camera, unsigned char *cmd, int cmd_len,
103                                unsigned char *buf, int buf_len)
104 {
105         unsigned char c;
106         int checksum;
107         const unsigned char *cmd_end;
108
109         /* The camera does not insist on a ping each command, but */
110         /* sometimes it hangs up without one.                     */
111         CR (QVping (camera));
112
113         /* Write the request and calculate the checksum */
114         CR (gp_port_write (camera->port, cmd, cmd_len));
115         for (cmd_end = cmd+cmd_len, checksum = 0; cmd < cmd_end; ++cmd)
116                 checksum += *cmd;
117
118         /* Read the checksum */
119         CR (gp_port_read (camera->port, &c, 1));
120         if (c != (unsigned char)(~checksum))
121                 return (GP_ERROR_CORRUPTED_DATA);
122
123         /* Send ACK */
124         c = ACK;
125         CR (gp_port_write (camera->port, &c, 1));
126
127         /* Receive the answer */
128         if (buf_len)
129                 CR (gp_port_read (camera->port, buf, buf_len));
130
131         return (GP_OK);
132 }
133
134 static int
135 QVblockrecv (Camera *camera, unsigned char **buf, unsigned long int *buf_len)
136 {
137         /* XXX - does the caller know to free *buf in case of an error? */
138         unsigned char c;
139         int retries, pos;
140
141         retries = 0;
142         *buf = NULL;
143         *buf_len = 0;
144         pos = 0;
145
146         /* Send DC2 */
147         c = DC2;
148         CR (gp_port_write (camera->port, &c, 1));
149
150         while (1) {
151                 unsigned char buffer[2];
152                 int size, i;
153                 int sum;
154                 unsigned char *new;
155
156                 /* Read STX */
157                 CR (gp_port_read (camera->port, &c, 1));
158                 if (c != STX) {
159                         retries++;
160                         c = NAK;
161                         CR (gp_port_write (camera->port, &c, 1));
162                         if (retries > CASIO_QV_RETRIES)
163                                 return (GP_ERROR_CORRUPTED_DATA);
164                         else
165                                 continue;
166                 }
167
168                 /* Read sector size */
169                 CR (gp_port_read (camera->port, buffer, 2));
170                 size = (buffer[0] << 8) | buffer[1];
171                 sum = buffer[0] + buffer[1];
172
173                 /* Allocate the memory */
174                 new = (unsigned char*)realloc (*buf, sizeof (char) * (*buf_len + size));
175                 if (new == (unsigned char*)0) {
176                         if (*buf != (unsigned char*)0) free(*buf);
177                         return (GP_ERROR_NO_MEMORY);
178                 }
179                 *buf = new;
180                 *buf_len += size;
181
182                 /* Get the sector */
183                 CR (gp_port_read (camera->port, *buf + pos, size));
184                 for (i = 0; i < size; i++)
185                         sum += (*buf)[i + pos];
186
187                 /* Get EOT or ETX and the checksum */
188                 CR (gp_port_read (camera->port, buffer, 2));
189                 sum += buffer[0];
190
191                 /* Verify the checksum */
192                 if ((unsigned char)(~sum) != buffer[1]) {
193                         retries++;
194                         c = NAK;
195                         CR (gp_port_write (camera->port, &c, 1));
196                         if (retries > CASIO_QV_RETRIES)
197                                 return (GP_ERROR_CORRUPTED_DATA);
198                         else
199                                 continue;
200                 }       
201
202                 /* Acknowledge and prepare for next packet */
203                 c = ACK;
204                 CR (gp_port_write (camera->port, &c, 1));
205                 pos += size;
206
207                 /* Are we done? */
208                 if (buffer[0] == ETX)
209                         break;          /* Yes */
210                 else if (buffer[0] == ETB)
211                         continue;       /* No  */
212                 else
213                         return (GP_ERROR_CORRUPTED_DATA);
214         }
215
216         return (GP_OK);
217 }
218
219 int
220 QVbattery (Camera *camera, float *battery)
221 {
222         unsigned char cmd[6];
223         unsigned char b;
224
225         cmd[0] = 'R';
226         cmd[1] = 'B';
227         cmd[2] = ENQ;
228         cmd[3] = 0xff;
229         cmd[4] = 0xfe;
230         cmd[5] = 0xe6;
231         CR (QVsend (camera, cmd, 6, &b, 1));
232         *battery = b / 16.;
233
234         return (GP_OK);
235 }
236
237 int
238 QVrevision (Camera *camera, long int *revision)
239 {
240         unsigned char cmd[2];
241         unsigned char buf[4];
242
243         cmd[0] = 'S';
244         cmd[1] = 'U';
245         CR (QVsend (camera, cmd, 2, buf, 4));
246         *revision = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
247
248         return (GP_OK);
249 }
250
251 int
252 QVnumpic (Camera *camera)
253 {
254         unsigned char cmd[2];
255         unsigned char b;
256
257         cmd[0] = 'M';
258         cmd[1] = 'P';
259         CR (QVsend (camera, cmd, 2, &b, 1));
260
261         return (b);
262 }
263
264 int
265 QVpicattr (Camera *camera, int n, unsigned char *picattr)
266 {
267         unsigned char cmd[4];
268         unsigned char b;
269
270         cmd[0] = 'D';
271         cmd[1] = 'Y';
272         cmd[2] = STX;
273         cmd[3] = n+1;
274         CR (QVsend (camera, cmd, 4, &b, 1));
275         *picattr = b;
276
277         return (GP_OK);
278 }
279
280 int
281 QVshowpic (Camera *camera, int n)
282 {
283         unsigned char cmd[3];
284
285         cmd[0] = 'D';
286         cmd[1] = 'A';
287         cmd[2] = n+1;
288         CR (QVsend (camera, cmd, 3, NULL, 0));
289
290         return (GP_OK);
291 }
292
293 int
294 QVsetpic (Camera *camera)
295 {
296         unsigned char cmd[2];
297
298         cmd[0] = 'D';
299         cmd[1] = 'L';
300         CR (QVsend (camera, cmd, 2, NULL, 0));
301
302         return (GP_OK);
303 }
304
305 int
306 QVgetCAMpic (Camera *camera, unsigned char **data, unsigned long int *size, int fine)
307 {
308         unsigned char cmd[2];
309
310         cmd[0] = 'M';
311         cmd[1] = fine ? 'g' : 'G';
312         CR (QVsend (camera, cmd, 2, NULL, 0));
313         CR (QVblockrecv (camera, data, size));
314
315         return (GP_OK);
316 }
317
318 int
319 QVgetYCCpic (Camera *camera, unsigned char **data, unsigned long int *size)
320 {
321         unsigned char cmd[2];
322
323         cmd[0] = 'M';
324         cmd[1] = 'K';
325         CR (QVsend (camera, cmd, 2, NULL, 0));
326         CR (QVblockrecv (camera, data, size));
327
328         return (GP_OK);
329 }
330
331 int
332 QVdelete (Camera *camera, int n)
333 {
334         unsigned char cmd[4];
335
336         cmd[0] = 'D';
337         cmd[1] = 'F';
338         cmd[2] = n+1;
339         cmd[3] = 0xff;
340         CR (QVsend (camera, cmd, 4, NULL, 0));
341
342         return (GP_OK);
343 }
344
345 int
346 QVprotect (Camera *camera, int n, int on)
347 {
348         unsigned char cmd[4];
349
350         cmd[0] = 'D';
351         cmd[1] = 'Y';
352         cmd[2] = on ? 1 : 0;
353         cmd[3] = n+1;
354         CR (QVsend (camera, cmd, 4, NULL, 0));
355
356         return (GP_OK);
357 }
358
359 int
360 QVsize (Camera *camera, long int *size)
361 {
362         unsigned char cmd[2];
363         unsigned char buf[4];
364
365         cmd[0] = 'E';
366         cmd[1] = 'M';
367         CR (QVsend (camera, cmd, 2, buf, 4));
368         *size = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
369
370         return (GP_OK);
371 }
372
373 int
374 QVcapture (Camera *camera)
375 {
376         unsigned char cmd[2];
377         unsigned char b;
378
379         cmd[0] = 'D';
380         cmd[1] = 'R';
381         CR (QVsend (camera, cmd, 2, &b, 1));
382
383         return (GP_OK);
384 }
385
386 int
387 QVstatus (Camera *camera, char *status)
388 {
389         unsigned char cmd[3];
390         
391         cmd[0] = 'D';
392         cmd[1] = 'S';
393         cmd[2] = STX;
394         CR (QVsend (camera, cmd, 3, status, 2));
395
396         return (GP_OK);
397 }
398
399 int
400 QVreset (Camera *camera)
401 {
402         unsigned char cmd[2];
403         
404         cmd[0] = 'Q';
405         cmd[1] = 'R';
406         CR (QVsend (camera, cmd, 2, NULL, 0));
407
408         return (GP_OK);
409 }
410
411 int
412 QVsetspeed (Camera *camera, int speed)
413 {
414         unsigned char cmd[3];
415         gp_port_settings settings;
416
417         cmd[0] = 'C';
418         cmd[1] = 'B';
419         switch (speed) {
420         case   9600: cmd[2] = 46; break;
421         case  19200: cmd[2] = 22; break;
422         case  38400: cmd[2] = 11; break;
423         case  57600: cmd[2] =  7; break;
424         case 115200: cmd[2] =  3; break;
425         default: return (GP_ERROR_NOT_SUPPORTED);
426         }
427         CR (QVsend (camera, cmd, 3, NULL, 0));
428
429         CR (gp_port_get_settings (camera->port, &settings));
430         settings.serial.speed = speed;
431         CR (gp_port_set_settings (camera->port, settings));
432
433         CR (QVping (camera));
434
435         return (GP_OK);
436 }