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