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