1 /* library.c
2  *
3  * Copyright (C) 2000,2001,2002 donn morrison - dmorriso@gulf.uvic.ca
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 
21 /****************************************************
22  * kodak dc3200 digital camera driver library       *
23  * for gphoto2                                      *
24  *                                                  *
25  * author: donn morrison - dmorriso@gulf.uvic.ca    *
26  * date: dec 2000 - jan 2002                        *
27  * license: gpl                                     *
28  * version: 1.6                                     *
29  *                                                  *
30  ****************************************************/
31 
32 #include "config.h"
33 #include "library.h"
34 
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <stdio.h>
39 #include <fcntl.h>
40 #include <string.h>
41 #include <errno.h>
42 
43 #include "dc3200.h"
44 
45 #ifdef ENABLE_NLS
46 #  include <libintl.h>
47 #  undef _
48 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
49 #  ifdef gettext_noop
50 #    define N_(String) gettext_noop (String)
51 #  else
52 #    define N_(String) (String)
53 #  endif
54 #else
55 #  define _(String) (String)
56 #  define N_(String) (String)
57 #endif
58 
59 /*
60  * FIXME: Use properly sized integer types. The dc3200 code used lots
61  *        of u_char, u_long, u_int, which may be wrong on non-32bit systems.
62  */
63 
64 /* #define DEBUG */
65 
66 /*
67  * dc3200_set_speed
68  *
69  * handshakes a baud rate with the camera
70  *
71  */
dc3200_set_speed(Camera * camera,int baudrate)72 int dc3200_set_speed(Camera *camera, int baudrate)
73 {
74 	int baudcode = C9600;
75 	unsigned char resp[INI_PACKET_LEN], msg[INI_PACKET_LEN];
76 	int resp_len = INI_PACKET_LEN, msg_len = INI_PACKET_LEN;
77 
78 	msg[0] = 0xAF;
79 	msg[1] = 0x00;
80 
81 	switch(baudrate) {
82 	case 9600:
83 		baudcode = C9600;
84 		break;
85 	case 19200:
86 		baudcode = C19200;
87 		break;
88 	case 38400:
89 		baudcode = C38400;
90 		break;
91 	case 57600:
92 		baudcode = C57600;
93 		break;
94 	case 115200:
95 		baudcode = C115200;
96 		break;
97 	default:
98 		printf("unsupported baudrate: %d.\n", baudrate);
99 		return GP_ERROR;
100 	}
101 
102 	msg[2] = baudcode;
103 
104 	/* send our preferred baud rate */
105 	if(dc3200_send_command(camera, msg, msg_len, resp, &resp_len) == GP_ERROR)
106 		return GP_ERROR;
107 	/* the camera responds with our preferred baud rate or its
108 	 * maximum baud rate, whichever is lowest
109 	 */
110 
111 	/* compile a confirmation packet */
112 	msg[0] = 0x9F;
113 	msg[1] = 0x00;
114 	if(resp_len == 2) {
115 		msg_len = 2;
116 	} else {
117 		/* calculate reply baud handshake */
118 		msg[2] = (resp[2] + 1) / 2;
119 		msg_len = INI_PACKET_LEN;
120 	}
121 
122 	if(dc3200_send_command(camera, msg, msg_len, resp, &resp_len) == GP_ERROR)
123 		return GP_ERROR;
124 
125 	if(resp_len == 2) {
126 		/* set the handshaked baudrate
127 		 * supports only 9600
128 		 */
129 		return C9600;
130 	} else if(resp[1] == 0x01) {
131 		/* set the handshaked baudrate */
132 		return (resp[2]*2) - 1;
133 	} else {
134 		/* unknown baud */
135 		return GP_ERROR;
136 	}
137 
138 	return GP_ERROR;
139 }
140 
141 /*
142  * dc3200_setup
143  *
144  * sends two commands essential for survival
145  *
146  */
dc3200_setup(Camera * camera)147 int dc3200_setup(Camera *camera)
148 {
149 	/*
150 	 * some strange commands that must be
151 	 * completed after initialization and
152 	 * before any camera access
153 	 *
154 	 * version info? ...
155 	 *
156 	 */
157 
158 	unsigned char cmd1[5] = {0x01, 0, 0x01, 0x00, 0x0F};
159 	unsigned char cmd2[8] = {0x01, 0, 0x80, 0x00, 0x01, 0x81, 0x00, 0x03};
160 
161 	unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN];
162 	int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN;
163 
164 	cmd1[1] = dc3200_calc_seqnum(camera);
165 	cmd2[1] = dc3200_calc_seqnum(camera);
166 
167 	if(dc3200_send_command(camera, cmd1, sizeof(cmd1), ack, &ack_len) == GP_ERROR)
168 		return GP_ERROR;
169 	if(dc3200_check_ack(camera, ack, ack_len) == GP_ERROR)
170 		return GP_ERROR;
171 	if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
172 		return GP_ERROR;
173 	if(dc3200_send_ack(camera, resp[1]) == GP_ERROR)
174 		return GP_ERROR;
175 
176 	if(dc3200_send_command(camera, cmd2, sizeof(cmd2), ack, &ack_len) == GP_ERROR)
177 		return GP_ERROR;
178 	if(dc3200_check_ack(camera, ack, ack_len) == GP_ERROR)
179 		return GP_ERROR;
180 	if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
181 		return GP_ERROR;
182 	if(dc3200_send_ack(camera, resp[1]) == GP_ERROR)
183 		return GP_ERROR;
184 
185 	/* set the cmd sequence number */
186 	camera->pl->cmd_seqnum = 0;
187 	camera->pl->rec_seqnum = 0;
188 
189 	return GP_OK;
190 }
191 
192 
193 /*
194  * dc3200_get_data
195  *
196  * retrieves data from the camera as either file
197  * data or file/folder list data
198  *
199  */
200 
201 	/* command to retrieve directory listing
202 	unsigned char list_pkt[DEF_PACKET_LEN] = {0x01, dc3200_calc_seqnum(camera), 0x80, 0x00, 0x20, 0x03, 26 + strlen(filename),
203 							0xc1, 0x50, 0x00, 0x00, 0x00, 0x00, 19 + strlen(filename),
204 							0x04, 0x01, 0x00, 0x01, 0x00, 0x01, 0x60, 0x01, 0x00, 0x01, 0x00, 0x05,
205 							0x00, 0x00, 0x00, 2 + strlen(filename), 0x01};
206 	*/
207 	/* command to get the picture
208 	unsigned char get_pkt[DEF_PACKET_LEN] = {0x01, calc_seqnum(), 0x80, 0x00, 0x20, 0x03, 26 + strlen(filename),
209 	                        0xC1, 0x50, 0x00, 0x00, 0x00, 0x00, 19 + strlen(filename),
210 							0x04, 0x01,	0x00, 0x01, 0x01, 0x04, 0x60, 0x10, 0x00, 0x01, 0x00, 0x05,
211 							0x00, 0x00, 0x00, 2 + strlen(filename), 0x01};
212 	*/
213 
dc3200_get_data(Camera * camera,unsigned char ** data,unsigned long * data_len,int command,const char * folder,const char * filename)214 int dc3200_get_data(Camera *camera, unsigned char **data, unsigned long *data_len, int command, const char *folder, const char *filename)
215 {
216 	unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN];
217 	int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN;
218 	unsigned long num_left = 0;
219 	int data_start_pos = 0;
220 	unsigned char *ptr_data = NULL;
221 	unsigned int pid = 0;
222 
223 	/* command bytes */
224 	unsigned char cb1=0x00,cb2=0x00,cb3=0x00;
225 
226 	/* packet parts */
227 	unsigned char pkt_hdr[7];
228 	unsigned char pkt_typ[7];
229 	unsigned char pkt_cmd[12];
230 	unsigned char pkt_len[5];
231 
232 	unsigned char *packet;
233 	int packet_len;
234 	char *file = NULL;
235 	char *ptr = NULL;
236 
237 	if(folder) {
238 		if(filename) {
239 			file = malloc(strlen(folder) + strlen(filename) + 2);
240 			if(!file)
241 				return GP_ERROR;
242 
243 			/* concatenate the folder + filename */
244 			strcpy(file, folder);
245 			/* append the filename */
246 			if(folder[strlen(folder)-1] != '\\')
247 				strcat(file, "\\");
248 			strcat(file, filename);
249 
250 		} else {
251 			file = strdup(folder);
252 			if(!file)
253 				return GP_ERROR;
254 		}
255 	} else {
256 		return GP_ERROR;
257 	}
258 
259 	/* change all /'s to \'s */
260 	while((ptr = strchr(file, '/'))) {
261 		ptr[0] = '\\';
262 	}
263 
264 	/* there should not be a trailing '\', except for root folder */
265 	if(strlen(file) > 1 && file[strlen(file)-1] == '\\')
266 		file[strlen(file)-1] = 0;
267 
268 	switch (command) {
269 	case CMD_GET_PREVIEW:
270 		cb1 = 0x02; cb2 = 0x70; cb3 = 0x11;
271 		break;
272 	case CMD_GET_FILE:
273 		cb1 = 0x01; cb2 = 0x60; cb3 = 0x10;
274 		break;
275 	case CMD_LIST_FILES:
276 		cb1 = 0x01; cb2 = 0x60; cb3 = 0x01;
277 		break;
278 	}
279 
280 	camera->pl->cmd_seqnum++;
281 
282 	pkt_hdr[0] = 0x01;
283 	pkt_hdr[1] = dc3200_calc_seqnum(camera);
284 	pkt_hdr[2] = 0x80; pkt_hdr[3] = 0x00; pkt_hdr[4] = 0x20; pkt_hdr[5] = 0x03;
285 	pkt_hdr[6] = 26 + strlen(file);
286 
287 	pkt_typ[0] = 0xC1;
288 	pkt_typ[1] = 0x50;
289 	pkt_typ[2] = 0x00; pkt_typ[3] = 0x00; pkt_typ[4] = 0x00; pkt_typ[5] = 0x00;
290 	pkt_typ[6] = 19 + strlen(file);
291 
292 	pkt_cmd[0]  = 0x04; pkt_cmd[1]  =  cb1; /* cmd */
293 	pkt_cmd[2]  = 0x00; pkt_cmd[3]  = 0x01;	/* ??? */
294 	pkt_cmd[4]  = (camera->pl->cmd_seqnum >> 8) & 0xff; pkt_cmd[5]  = camera->pl->cmd_seqnum & 0xff; /* SEQ */
295 	pkt_cmd[6]  =  cb2; pkt_cmd[7]  =  cb3;	/* cmd */
296 	pkt_cmd[8]  = 0x00; pkt_cmd[9]  = 0x01;	/* ??? */
297 	pkt_cmd[10] = 0x00; pkt_cmd[11] = 0x05;	/* ??? */
298 
299 	pkt_len[0] = 0x00; pkt_len[1] = 0x00; pkt_len[2] = 0x00;
300 	pkt_len[3] = strlen(file) + 2;
301 	pkt_len[4] = 0x01;
302 
303 	packet_len = sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd) + sizeof(pkt_len) + strlen(file) + 2;
304 	packet = malloc(packet_len);
305 	if(!packet) {
306 		free(file);
307 		return GP_ERROR;
308 	}
309 
310 	/* clear packet */
311 	memset(packet, 0, packet_len);
312 
313 	/* copy pkt parts into packet */
314 	memcpy(packet, pkt_hdr, sizeof(pkt_hdr));
315 	memcpy(packet + sizeof(pkt_hdr), pkt_typ, sizeof(pkt_typ));
316 	memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ), pkt_cmd, sizeof(pkt_cmd));
317 	memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd), pkt_len, sizeof(pkt_len));
318 	memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd) + sizeof(pkt_len), file, strlen(file));
319 
320 	free(file);
321 
322 	/* send the command to list files */
323 	if(dc3200_send_command(camera, packet, packet_len, ack, &ack_len) == GP_ERROR){
324 		free(packet);
325 		return GP_ERROR;
326 	}
327 
328 	free(packet);
329 
330 	do {
331 		resp_len = DEF_PACKET_LEN;
332 		if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) {
333 			return GP_ERROR;
334 		}
335 
336 		if(dc3200_send_ack(camera, resp[1]) == GP_ERROR) {
337 			return GP_ERROR;
338 		}
339 
340 		if(resp[1] == camera->pl->rec_seqnum)
341 			continue;
342 
343 		camera->pl->rec_seqnum = resp[1];
344 
345 		/*
346 		 * we decide what action to take based on
347 		 * the number of packets we are expecting
348 		 *
349 		 * resp[7] holds this info
350 		 *
351 		 */
352 		switch(resp[7]) {
353 		case 0xC1:
354 			/*
355 			 * SINGLE PACKET
356 			 */
357 
358 			/* get the total list length from the data header */
359 			*data_len = bytes_to_l(resp[26], resp[27], resp[28], resp[29]);
360 			num_left = 0;
361 			data_start_pos = 31;
362 			*data_len -= 1;
363 
364 			/* allocate a buffer to store all this data */
365 			*data = malloc(*data_len);
366 			if(*data == NULL) {
367 				return GP_ERROR;
368 			}
369 
370 			ptr_data = *data;
371 
372 			/* copy this portion of the data */
373 			memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
374 			/* incr the buff ptr */
375 			ptr_data += resp_len - data_start_pos;
376 			break;
377 
378 		case 0x41:
379 			/*
380 			 * MULTIPACKET, START
381 			 */
382 
383 			/* get the total list length from the data header */
384 			*data_len = bytes_to_l(resp[34], resp[35], resp[36], resp[37]);
385 			num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]);
386 			data_start_pos = 39;
387 			*data_len -= 1;
388 
389 			/* allocate a buffer to store all this data */
390 			*data = malloc(*data_len);
391 			if(*data == NULL) {
392 				return GP_ERROR;
393 			}
394 
395 			ptr_data = *data;
396 
397 			/* copy this portion of the data */
398 			memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
399 			/* incr the data ptr */
400 			ptr_data += resp_len - data_start_pos;
401 
402 			/* update gphoto2 frontend */
403 			if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW)
404 			{
405 				pid = gp_context_progress_start(camera->pl->context,(int)*data_len,"%s", filename);
406 				gp_context_progress_update(camera->pl->context, pid, ptr_data - *data);
407 				if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) {
408 					free(*data);
409 					dc3200_cancel_get_data(camera);
410 					return GP_ERROR_CANCEL;
411 				}
412 			}
413 			break;
414 		case 0x01:
415 			/*
416 			 * MULTIPACKET, MIDDLE
417 			 */
418 			/* calculate the number of packets remaining */
419 			num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]);
420 			data_start_pos = 16;
421 
422 			if(*data == NULL) {
423 				return GP_ERROR;
424 			}
425 
426 			/* copy this portion of the data */
427 			memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
428 			/* incr the buff ptr */
429 			ptr_data += resp_len - data_start_pos;
430 
431 			/* update gphoto2 frontend */
432 			if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW)
433 			{
434 				gp_context_progress_update(camera->pl->context, pid, ptr_data - *data);
435 				if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) {
436 					free(*data);
437 					dc3200_cancel_get_data(camera);
438 					return GP_ERROR_CANCEL;
439 				}
440 			}
441 			break;
442 		case 0x81:
443 			/*
444 			 * MULTIPACKET, END
445 			 */
446 			/* calculate the number of packets remaining */
447 			num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]);
448 			data_start_pos = 16;
449 
450 			if(*data == NULL) {
451 				return GP_ERROR;
452 			}
453 
454 			/* copy this portion of the data */
455 			memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos);
456 			/* incr the buff ptr */
457 			ptr_data += resp_len - data_start_pos;
458 
459 			/* update gphoto2 frontend */
460 			if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW)
461 			{
462 				gp_context_progress_update(camera->pl->context, pid, ptr_data - *data);
463 				if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) {
464 					free(*data);
465 					dc3200_cancel_get_data(camera);
466 					return GP_ERROR_CANCEL;
467 				}
468 			}
469 			break;
470 		default:
471 			return GP_ERROR;
472 		}
473 	} while(num_left > 1);
474 
475 	if(pid != 0 && (command == CMD_GET_FILE || command == CMD_GET_PREVIEW))
476 		gp_context_progress_stop(camera->pl->context, pid);
477 
478 	return GP_OK;
479 }
480 
481 /*
482  * dc3200_cancel_get_data
483  *
484  * stops a get data command
485  *
486  */
dc3200_cancel_get_data(Camera * camera)487 int dc3200_cancel_get_data(Camera *camera)
488 {
489 	unsigned char pkt[20] = {0x01, 0, 0x80, 0x00, 0x20, 0x03, 0x0d, 0xc1, 0x50, 0xc0,
490 		0x00, 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x01, 0, 0};
491 	unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN];
492 	int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN;
493 
494 	pkt[1] = dc3200_calc_seqnum(camera);
495 	pkt[18] = (camera->pl->cmd_seqnum >> 8) & 0xff;
496 	pkt[19] = camera->pl->cmd_seqnum & 0xff;
497 
498 	/* wait a bit ... */
499 	sleep(1);
500 
501 	/* clear the buffer */
502 	dc3200_clear_read_buffer(camera);
503 
504 	if(dc3200_send_command(camera, (unsigned char *)pkt, 20, ack, &ack_len) == GP_ERROR)
505 		return GP_ERROR;
506 
507 	if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
508 		return GP_ERROR;
509 	else
510 		dc3200_send_ack(camera, resp[1]);
511 
512 	resp_len = DEF_PACKET_LEN;
513 	if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR)
514 		return GP_ERROR;
515 	else
516 		dc3200_send_ack(camera, resp[1]);
517 
518 	return GP_OK;
519 }
520 
521 /*
522  * dc3200_send_command
523  *
524  * if cmd == NULL || cmd_len == 0, send_command waits for a response
525  * otherwise, it sends a command and waits for an acknowledgement
526  *
527  */
dc3200_send_command(Camera * camera,unsigned char * cmd,int cmd_len,unsigned char * ack,int * ack_len)528 int dc3200_send_command(Camera *camera, unsigned char *cmd, int cmd_len, unsigned char *ack, int *ack_len)
529 {
530 	int sends, reads;
531 	int buff_len = *ack_len;
532 	int received = 0;
533 	unsigned char *buff = NULL;
534 
535 	buff = malloc(sizeof(unsigned char) * *ack_len);
536 	if(buff == NULL) {
537 		return GP_ERROR;
538 	}
539 
540 	sends = SEND_RETRIES;
541 
542 	while(sends > 0) {
543 		reads = READ_RETRIES;
544 		/* check that we are actually sending a command
545 		 * and not just waiting for data
546 		 */
547 		if(cmd != NULL && cmd_len > 0) {
548 			/* clear the read buffer */
549 			dc3200_clear_read_buffer(camera);
550 
551 			/* send the command */
552 			dc3200_send_packet(camera, cmd, cmd_len);
553 		}
554 
555 		/* wait for response */
556 		while(reads > 0) {
557 			if(dc3200_recv_packet(camera, buff, &buff_len) != GP_ERROR) {
558 				received = 1;
559 				break;
560 			}
561 			reads--;
562 		}
563 
564 		if(received) {
565 			if(buff_len > *ack_len) {
566 				/* buffer size too small */
567 				free(buff);
568 				return GP_ERROR;
569 			}
570 
571 			/* sukksess */
572 			*ack_len = buff_len;
573 			memcpy(ack, buff, buff_len);
574 			free(buff);
575 			return GP_OK;
576 		} else {
577 			sends--;
578 		}
579 	}
580 
581 	/* send failed */
582 	free(buff);
583 	return GP_ERROR;
584 }
585 
586 /*
587  * dc3200_recv_response
588  *
589  * receives a response from a previous command
590  *
591  */
dc3200_recv_response(Camera * camera,unsigned char * resp,int * resp_len)592 int dc3200_recv_response(Camera *camera, unsigned char *resp, int *resp_len)
593 {
594 	return dc3200_send_command(camera, NULL, 0, resp, resp_len);
595 }
596 
597 /*
598  * dc3200_send_ack
599  *
600  * sends an ack packet
601  *
602  */
dc3200_send_ack(Camera * camera,int seqnum)603 int dc3200_send_ack(Camera *camera, int seqnum)
604 {
605 	unsigned char ack[ACK_PACKET_LEN];
606 	ack[0] = 0x01;
607 	ack[1] = seqnum + 16;
608 
609 	return dc3200_send_packet(camera, ack, sizeof(ack));
610 }
611 
612 /*
613  * dc3200_check_ack
614  *
615  * checks an ack packet (well ok not really)
616  *
617  */
dc3200_check_ack(Camera * camera,unsigned char * ack,int ack_len)618 int dc3200_check_ack(Camera *camera, unsigned char *ack, int ack_len)
619 {
620 	return GP_OK;
621 }
622 
623 /*
624  * dc3200_send_packet
625  *
626  * compiles a packet from data and sends it
627  *
628  */
dc3200_send_packet(Camera * camera,unsigned char * data,int data_len)629 int dc3200_send_packet(Camera *camera, unsigned char *data, int data_len)
630 {
631 	int res;
632 
633 	int buff_len = data_len;
634 	unsigned char *buff = NULL;
635 
636 	buff = malloc(sizeof(unsigned char) * buff_len);
637 	if(!buff)
638 		return GP_ERROR;
639 
640 	memcpy(buff, data, buff_len);
641 
642 	/* compile this into a packet */
643 	res = dc3200_compile_packet(camera, &buff, &buff_len);
644 	if(res == GP_ERROR)
645 		return res;
646 
647 #ifdef DEBUG
648 	dump_buffer(buff, buff_len, "s", 16);
649 #endif
650 	res = gp_port_write(camera->port, (char *)buff, data_len + 3);
651 	free(buff);
652 	return res;
653 }
654 
655 /*
656  * dc3200_recv_packet
657  *
658  * waits for a packet to arrive, checks it, and returns it
659  *
660  */
dc3200_recv_packet(Camera * camera,unsigned char * data,int * data_len)661 int dc3200_recv_packet(Camera *camera, unsigned char *data, int *data_len)
662 {
663 	int complete = 0;
664 	int num_read = 0, res = 0, fails = 0;
665 
666 	/* allocate storage for size, checksum, and EOP */
667 	unsigned char *buff = NULL;
668 
669 	buff = malloc(sizeof(unsigned char) * (*data_len + 3));
670 	if(buff == NULL)
671 		return GP_ERROR;
672 
673 	memset(buff, 0, *data_len + 3);
674 
675 	/*
676 	 * - read data until we get an 0xFF
677 	 * - process packet
678 	 *
679 	 */
680 
681 	res = gp_port_read(camera->port, (char *)&buff[num_read], 1);
682 
683 	while(res >= 0 && fails < READ_RETRIES) {
684 		if(res == 0) {
685 			/* read nothing */
686 			fails++;
687 		} else {
688 			/* reset # of fails */
689 			fails = 0;
690 			num_read++;
691 			if(buff[num_read-1] == 0xFF) {
692 				complete = 1;
693 				break;
694 			}
695 			if(num_read == *data_len + 3) {
696 				/* we've reached the buffer limit */
697 				complete = 0;
698 				break;
699 			}
700 		}
701 		res = gp_port_read(camera->port, (char *)&buff[num_read], 1);
702 	}
703 
704 	if(!complete) {
705 		/* packet incomplete */
706 		free(buff);
707 		return GP_ERROR;
708 	}
709 
710 #ifdef DEBUG
711 	dump_buffer(buff, num_read, "r", 16);
712 #endif
713 
714 	if(dc3200_process_packet(camera, buff, &num_read) == GP_ERROR) {
715 		free(buff);
716 		return GP_ERROR;
717 	}
718 
719 	/* save the last successful packet received time */
720 	time(&(camera->pl->last));
721 
722 	memcpy(data, buff, *data_len);
723 
724 	/* return with new packet size */
725 	*data_len = num_read;
726 
727 	free(buff);
728 	return GP_OK;
729 }
730 
731 /*
732  * dc3200_compile_packet
733  *
734  * changes 0xFF -> 0xFE 0x01
735  *         0xFE -> 0xFE 0x00
736  * adds packet length, checksum, and EOP (0xFF)
737  *
738  */
dc3200_compile_packet(Camera * camera,unsigned char ** data,int * data_len)739 int dc3200_compile_packet(Camera *camera, unsigned char **data, int *data_len)
740 {
741 	int count, i, j;
742 	unsigned char *new_data = NULL;
743 	unsigned char *tmp_ptr  = NULL;
744 
745 	/* realloc + 2 for len and checksum */
746 	*data_len += 2;
747 
748 	tmp_ptr = (unsigned char*)realloc(*data, *data_len);
749 	if(tmp_ptr == NULL)
750 		return GP_ERROR;
751 
752 	*data = tmp_ptr;
753 
754 	/* add length, checksum */
755 	(*data)[*data_len - 2] = *data_len - 2;
756 	(*data)[*data_len - 1] = dc3200_calc_checksum(camera, *data, *data_len - 1);
757 
758 	/* this is a hack to fix the 0xFF/0xFE problem.
759 	 * we adjust a "don't care" byte so the checksum
760 	 * is not 0xFF or 0xFE
761 	 */
762 	if((*data)[*data_len - 1] >= 0xFE) {
763 		if(*data_len > 19) {
764 			(*data)[19] += 2;
765 			(*data)[*data_len - 1] = dc3200_calc_checksum(camera, *data, *data_len - 1);
766 			printf("adjusting checksum to %02x\n", (*data)[*data_len - 1]);
767 		}
768 	}
769 
770 	/* count number of 0xfe's and 0xff's */
771 	count = 0;
772 	for(i=0;i<*data_len; i++) {
773 		if((*data)[i] == 0xFE || (*data)[i] == 0xFF)
774 			count++;
775 	}
776 
777 	new_data = (unsigned char*)malloc(*data_len + count + 3); /* 3 for length, checksum, EOP */
778 	if(!new_data)
779 		return GP_ERROR;
780 
781 	j = 0;
782 	for(i=0;i<*data_len; i++) {
783 		if((*data)[i] == 0xFE || (*data)[i] == 0xFF) {
784 			printf("(*data)[i]        == %02x\n", (*data)[i]);
785 			printf("(*data)[i] - 0xFE == %02x\n", (*data)[i] - 0xFE);
786 			new_data[j++] = 0xFE;
787 			new_data[j++] = (*data)[i] - 0xFE;
788 		} else {
789 			new_data[j++] = (*data)[i];
790 		}
791 	}
792 
793 	/* adjust the new packet count */
794 	*data_len += count + 1;
795 
796 	new_data[*data_len - 1] = 0xFF;
797 
798 	/* free the old packet data */
799 	free(*data);
800 
801 	/* set the ptr */
802 	*data = new_data;
803 
804 	return GP_OK;
805 }
806 
807 /*
808  * dc3200_process_packet
809  *
810  * changes 0xFE 0x01 -> 0xFF
811  *         0xFE 0x00 -> 0xFE
812  * checks & removes packet length, checksum, EOP (0xFF)
813  *
814  */
dc3200_process_packet(Camera * camera,unsigned char * data,int * data_len)815 int dc3200_process_packet(Camera *camera, unsigned char *data, int *data_len)
816 {
817 	int count = 0, i;
818 	int length, checksum;
819 	unsigned char *buff;
820 
821 	if(data == NULL || *data_len < 1) {
822 		return GP_ERROR;
823 	}
824 
825 	/* allocate a new buffer */
826 	buff = (unsigned char*)malloc(sizeof(unsigned char) * *data_len);
827 	if(!buff)
828 		return GP_ERROR;
829 
830 	/* change 0xFE 0x00 | 0x01 -> 0xFF | 0xFE */
831 	for(i=0; i<*data_len; i++) {
832 		if(data[i] == 0xFE) {
833 			if(i<*data_len-1) { /* so we don't run out of array bounds */
834 				if(data[i+1] == 0x00) {
835 					buff[count] = 0xFE;
836 					/* advance i so we don't pick up the trailing byte */
837 					i++;
838 					/* incr count */
839 					count++;
840 				} else if(data[i+1] == 0x01) {
841 					buff[count] = 0xFF;
842 					i++;
843 					count++;
844 				}
845 			} else {
846 				/* we've found an 0xFE but there is no trailing byte */
847 				free(buff);
848 				return GP_ERROR;
849 			}
850 		} else {
851 			buff[count] = data[i];
852 			count++;
853 		}
854 	}
855 
856 	/* copy over the old buffer */
857 	memcpy(data, buff, count);
858 
859 	length = data[count - 3];
860 	checksum = data[count - 2];
861 
862 	/* make sure its a valid packet */
863 	if(length != count - 3 || checksum != dc3200_calc_checksum(camera, data, count - 2)) {
864 		printf("%02x=%02x %02x=%02x\n", length, count - 3, checksum, dc3200_calc_checksum(camera, data, count - 2));
865 		free(buff);
866 		return GP_ERROR;
867 	}
868 
869 	/* adjust packet size, strip length, checksum, EOP */
870 	*data_len = count - 3;
871 
872 	free(buff);
873 	return GP_OK;
874 }
875 
876 /*
877  * dc3200_calc_checksum
878  *
879  * calculates the checksum for a byte array
880  *
881  */
dc3200_calc_checksum(Camera * camera,unsigned char * buffer,int len)882 int dc3200_calc_checksum(Camera *camera, unsigned char * buffer, int len)
883 {
884 	int sum = 0, i;
885 
886 	for(i=0; i<len; i++) {
887 		sum += buffer[i];
888 	}
889 
890 	sum = -sum + 0xFF;
891 	if(sum < 0) sum = sum & 0xFF;
892 
893 	return sum;
894 }
895 
896 /*
897  * dc3200_calc_seqnum
898  *
899  * calculates the seqnum for a packet
900  *
901  */
dc3200_calc_seqnum(Camera * camera)902 int dc3200_calc_seqnum(Camera *camera)
903 {
904 	if(camera->pl->pkt_seqnum >= 0x1F || camera->pl->pkt_seqnum < 0x10) {
905 		camera->pl->pkt_seqnum = 0x10;
906 		return camera->pl->pkt_seqnum;
907 	} else {
908 		camera->pl->pkt_seqnum++;
909 		return camera->pl->pkt_seqnum;
910 	}
911 }
912 
913 /*
914  * dc3200_keep_alive
915  *
916  * sends and receives a ping packet to keep the
917  * camera awake
918  *
919  */
dc3200_keep_alive(Camera * camera)920 int dc3200_keep_alive(Camera *camera)
921 {
922 	unsigned char ka[ACK_PACKET_LEN]; /* keepalive */
923 	unsigned char ak[ACK_PACKET_LEN]; /* keepalive ack */
924 	int ak_len = ACK_PACKET_LEN;
925 
926 	ka[0] = 0xCF;
927 	ka[1] = 0x01;
928 
929 	/* send keep alive packet */
930 	if(dc3200_send_command(camera, ka, sizeof(ka), ak, &ak_len) == GP_ERROR) {
931 		return GP_ERROR;
932 	}
933 
934 	/* check the ack (should be same packet) */
935 	if(memcmp(ak,ka,ak_len) == 0) {
936 		return GP_OK;
937 	}
938 
939 	return GP_ERROR;
940 }
941 
942 /*
943  * dc3200_clear_read_buffer
944  *
945  * clears data in the read buffer by reading it out
946  *
947  * there is definitely a better way to accomplish this...
948  *
949  */
dc3200_clear_read_buffer(Camera * camera)950 int dc3200_clear_read_buffer(Camera *camera)
951 {
952 	unsigned char byte;
953 	int count = 0;
954 
955 	gp_port_set_timeout(camera->port, 0);
956 
957 	while(gp_port_read(camera->port, (char *)&byte, 1) > 0)
958 		count++;
959 
960 	if(count > 0)
961 		printf("cleared %d bytes from read buffer\n", count);
962 
963 	gp_port_set_timeout(camera->port, TIMEOUT);
964 
965 	return GP_OK;
966 }
967 
968 /*
969  * dump_buffer
970  *
971  * displays a byte array nicely formatted in hex format
972  *
973  */
dump_buffer(unsigned char * buffer,int len,char * title,int bytesperline)974 int dump_buffer(unsigned char * buffer, int len, char * title, int bytesperline)
975 {
976 	char spacer[80];
977 	int i;
978 
979 	memset(spacer, 0, sizeof(spacer));
980 	memset(spacer, ' ', strlen(title)+2);
981 
982 	printf("%s: ", title);
983 
984 	for(i=0; i<len; i++) {
985 		if(i%bytesperline==0 && i > 0) {
986 			printf("\n%s", spacer);
987 		}
988 		printf("%02x ", buffer[i]);
989 	}
990 
991 	printf("\n");
992 
993 	printf("%s: ", title);
994 
995 	for(i=0; i<len; i++) {
996 		if(i%bytesperline==0 && i > 0) {
997 			printf("\n%s", spacer);
998 		}
999 		if(buffer[i] >= 0x20 && buffer[i] < 0x7F) {
1000 			printf("%c", buffer[i]);
1001 		} else {
1002 			printf(".");
1003 		}
1004 	}
1005 
1006 	printf("\n");
1007 
1008 	return GP_OK;
1009 }
1010 
bytes_to_l(int a,int b,int c,int d)1011 unsigned long bytes_to_l(int a, int b, int c, int d)
1012 {
1013 	unsigned long res = a;
1014 	res = res << 24 | b << 16 | c << 8 | d;
1015 	return res;
1016 }
1017