1 /* casio-qv-commands.c
2 *
3 * Copyright 2001 Lutz Mueller
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., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 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
QVping(Camera * camera)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, (char *)&c, 1));
49 result = gp_port_read (camera->port, (char *)&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, (char *)&c, 1) >= 0);
82 break;
83
84 default:
85 while (gp_port_read (camera->port, (char *)&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
QVsend(Camera * camera,unsigned char * cmd,int cmd_len,unsigned char * buf,int buf_len)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, (char *)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, (char *)&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, (char *)&c, 1));
126
127 /* Receive the answer */
128 if (buf_len)
129 CR (gp_port_read (camera->port, (char *)buf, buf_len));
130
131 return (GP_OK);
132 }
133
134 static int
QVblockrecv(Camera * camera,unsigned char ** buf,unsigned long int * buf_len)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, (char *)&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, (char *)&c, 1));
158 if (c != STX) {
159 retries++;
160 c = NAK;
161 CR (gp_port_write (camera->port, (char *)&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, (char *)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, (char *)*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, (char *)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, (char *)&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, (char *)&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
QVbattery(Camera * camera,float * battery)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
QVrevision(Camera * camera,long int * revision)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
QVnumpic(Camera * camera)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
QVpicattr(Camera * camera,int n,unsigned char * picattr)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
QVshowpic(Camera * camera,int n)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
QVsetpic(Camera * camera)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
QVgetCAMpic(Camera * camera,unsigned char ** data,unsigned long int * size,int fine)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
QVgetYCCpic(Camera * camera,unsigned char ** data,unsigned long int * size)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
QVdelete(Camera * camera,int n)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
QVprotect(Camera * camera,int n,int on)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
QVsize(Camera * camera,long int * size)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
QVcapture(Camera * camera)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
QVstatus(Camera * camera,char * status)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, (unsigned char *)status, 2));
395
396 return (GP_OK);
397 }
398
399 int
QVreset(Camera * camera)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
QVsetspeed(Camera * camera,int speed)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 }
437