1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <string.h>
5 #include <time.h>
6 #include <sys/types.h>
7 #include <termios.h>
8 #include <fcntl.h>
9 #include "dc20_hif.h"
10 
11 #define  Kb  1024
12 
13 /* GLOBAL VARIABLES ***************************************/
14 unsigned char inp_buff[INP_BUFF_SIZE];
15 unsigned char sts_res= 0, sts_bat= 0;
16 unsigned char sts_pic_cnt= 0, sts_pic_rem= 0;
17 unsigned char dc_type= 0x25;
18 unsigned char com_dev[128]= "/dev/cuaa0";
19 
20 
21 /* LOCAL VARIABLES ****************************************/
22 speed_t com_speed= B9600;
23 long com_baud, baud_save= 9600;
24 struct termios tty_param, old_tty;
25 int com_hdl;
26 
27 unsigned char cmd_init[]  = { 8, 0x41, 0, 0x96, 0, 0, 0, 0, 0x1A };
28 unsigned char cmd_status[]= { 8, 0x7F, 0, 0, 0, 0, 0, 0, 0x1A };
29 unsigned char cmd_shot[]  = { 8, 0x77, 0, 0, 0, 0, 0, 0, 0x1A };
30 unsigned char cmd_ldpic2[]= { 8, 0x51, 0, 0, 1, 0, 0, 0, 0x1A };  /* header + picture */
31 unsigned char cmd_ldpic1[]= { 8, 0x55, 0, 0, 1, 0, 0, 0, 0x1A };  /* header only */
32 unsigned char cmd_thumbn[]= { 8, 0x56, 0, 0, 1, 0, 0, 0, 0x1A };
33 unsigned char cmd_erase[] = { 8, 0x7A, 0, 0, 0, 0, 0, 0, 0x1A };
34 unsigned char cmd_lores[] = { 8, 0x71, 0, 1, 0, 0, 0, 0, 0x1A };
35 unsigned char cmd_hires[] = { 8, 0x71, 0, 0, 0, 0, 0, 0, 0x1A };
36 
37 /* LOCAL FUNCTIONS *****************************************/
38 
pause(int millisec)39 void pause(int millisec)
40 {
41 
42   long wait, goal;
43 
44   wait = ( (long) millisec * (long) CLOCKS_PER_SEC + 500) / 1000;
45   goal = wait + (long) clock();
46   while ( goal > (long) clock() )
47     ;
48 
49 }
50 
51 /* hardware specific functions *****************************/
52 
cxmit(unsigned char c)53 void cxmit(unsigned char c)
54 {
55   if (write(com_hdl, &c, 1) != 1)
56     perror("write");
57 }
58 
crcv(int * error)59 unsigned char crcv(int *error)
60 {
61   unsigned char c;
62 
63   if (read(com_hdl, &c, 1) == 1)
64     return c;
65   else
66     *error+= ERR_NO_DATA;
67 
68   return 0xFF;
69 }
70 
read_from_com(int nof_bytes)71 int read_from_com(int nof_bytes)
72 {
73   unsigned int i, k, retry= 5;
74   unsigned char chksum;
75 
76   while (retry--)
77   {
78     chksum= 0;
79 
80     /* i= read(com_hdl, inp_buff, nof_bytes); */
81     for (i= 0; i< nof_bytes; )
82     {
83       if ((k= read(com_hdl, &inp_buff[i], nof_bytes-i)) < 1)
84         break;
85       i+= k;
86     }
87 
88     if (i == nof_bytes)
89     {
90 
91       for (i= 0; i < nof_bytes; i++)
92         chksum^= inp_buff[i];
93 
94       if ( chksum == 0 )
95 	return nof_bytes;
96       else
97         i= nof_bytes - 1;
98     }
99 
100     if (retry)
101     {
102       cxmit(0xE3);
103     }
104   }
105 
106   return i;
107 }
108 
set_com_baud(long baud)109 void set_com_baud(long baud)
110 {
111   com_baud= baud;
112 
113   switch (baud)
114   {
115     case  9600 : com_speed= B9600; break;
116     case  19200: com_speed= B19200; break;
117     case  38400: com_speed= B38400; break;
118     case  57600: com_speed= B57600; break;
119     case 115200: com_speed= B115200; break;
120     default:     com_speed= B9600; baud= 9600;
121   }
122 
123   cfsetospeed(&tty_param, com_speed);
124   cfsetispeed(&tty_param, com_speed);
125 
126   if (tcsetattr(com_hdl, TCSANOW, &tty_param) == -1)
127   {
128     perror("tcsetattr");
129   }
130 }
131 
toggle_baud_rate(void)132 void toggle_baud_rate(void)
133 {
134   if (com_baud > 9600)
135   {
136     baud_save= com_baud;
137     set_com_baud(9600);
138   }
139   else
140   {
141     set_com_baud(baud_save);
142   }
143 }
144 
initcom(int com_nr,long baud)145 void initcom(int com_nr, long baud)
146 {
147   switch (com_nr)
148   {
149     case 1:  strcpy(com_dev, "/dev/cuaa0") ; break;
150     case 2:  strcpy(com_dev, "/dev/cuaa1") ; break;
151     case 3:  strcpy(com_dev, "/dev/cuaa2") ; break;
152     case 4:  strcpy(com_dev, "/dev/cuaa3") ; break;
153     default: strcpy(com_dev, "/dev/cuaa0") ; break;
154   }
155 
156   if ((com_hdl = open(com_dev, O_RDWR)) == -1)
157   {
158     perror("open");
159     fprintf(stderr, "Could not open %s for read/write.\n", com_dev);
160     exit(-1);
161   }
162 
163   cfmakeraw(&tty_param);
164   tty_param.c_oflag &= ~CSTOPB;
165   tty_param.c_cflag |= PARENB;
166   tty_param.c_cflag &= ~PARODD;
167   tty_param.c_cc[VMIN] = 0;
168   tty_param.c_cc[VTIME] = 15;
169   cfsetospeed(&tty_param, B9600);
170   cfsetispeed(&tty_param, B9600);
171 
172   tcgetattr(com_hdl, &old_tty);
173 
174   if (tcsetattr(com_hdl, TCSANOW, &tty_param) == -1)
175   {
176     perror("tcsetattr");
177     fprintf(stderr, "Could not init %s for camera access.\n", com_dev);
178     close(com_hdl);
179     exit(-1);
180   }
181 
182   set_com_baud(baud);
183 
184 }
185 
close_com(void)186 void close_com(void)
187 {
188   tcsetattr(com_hdl, TCSANOW, &old_tty);
189   close(com_hdl);
190 }
191 /* end of hardware specific functions *******************************/
192 
193 
194 /* GLOBAL FUNCTIONS ****************************************/
195 
send_cmd(unsigned char * cmd)196 int send_cmd(unsigned char *cmd)
197 {
198   int i, error= 0;
199 
200   pause(100);
201 
202   for (i=1; i<=cmd[0]; i++)
203   {
204     cxmit(cmd[i]);
205   }
206 
207   if (crcv(&error) != 0xD1)
208     if (dc_type == 0x20)
209       error+= ERR_DATA_WRONG;
210 
211   return error;
212 }
213 
init_dc20(int com_nr,long baud)214 int init_dc20(int com_nr, long baud)
215 {
216   int wait= 3;
217   int error=0;
218 
219   initcom(com_nr, 9600);
220 
221   while ( (error=(send_cmd(cmd_init)))!=0 && --wait) ;
222 
223   if (error)
224     return error;
225 
226   switch (baud)
227   {
228     case  19200: cmd_init[3]= 0x19; cmd_init[4]= 0x20; break;
229     case  38400: cmd_init[3]= 0x38; cmd_init[4]= 0x40; break;
230     case  57600: cmd_init[3]= 0x57; cmd_init[4]= 0x60; break;
231     case 115200: cmd_init[3]= 0x11; cmd_init[4]= 0x52; break;
232     default:     cmd_init[3]= 0x96; cmd_init[4]= 0x00; baud= 9600;
233   }
234 
235   wait= 3;
236   while ( (error=(send_cmd(cmd_init)))!=0 && --wait) ;
237   if (error)
238     return error;
239 
240   set_com_baud(baud);
241 
242   wait= 3;
243   while ( (error=(send_cmd(cmd_init)))!=0 && --wait) ;
244 
245   return error;
246 }
247 
248 
close_dc20(void)249 void close_dc20(void)
250 {
251   /* reset to 9600Baud */
252   cmd_init[3]= 0x96;
253   cmd_init[4]= 0x00;
254   send_cmd(cmd_init);
255 
256   set_com_baud(9600L);
257   close_com();
258 }
259 
get_status(void)260 int get_status(void)
261 {
262   int wait= 10;
263   int error=0, dmy;
264 
265   while ( (error=(send_cmd(cmd_init)))!=0 && --wait) ;
266 
267   if (error)
268     return error;
269 
270   wait= 10;
271   while ( (error=(send_cmd(cmd_status)))!=0 && --wait) ;
272   if (error)
273     return error;
274 
275   if (read_from_com( 257) != 257)
276   {
277     return ERR_PACKET_WRONG;
278   }
279 
280   cxmit(0xD2);
281 
282   crcv(&error);
283 
284   dc_type= inp_buff[1];
285   if (dc_type == 0x20)
286   {
287     sts_res= inp_buff[23];
288     sts_bat= inp_buff[29];
289     sts_pic_cnt= inp_buff[9];
290     sts_pic_rem= inp_buff[11];
291   }
292   else
293   {
294     sts_res= inp_buff[11];
295     sts_bat= inp_buff[29];
296     sts_pic_cnt= inp_buff[17] + inp_buff[19];
297     if (sts_res == RES_HIGH)
298       sts_pic_rem= inp_buff[21];
299     else
300       sts_pic_rem= inp_buff[23];
301   }
302 
303   return error;
304 }
305 
take_picture(void)306 int take_picture(void)
307 {
308   unsigned char rcv;
309   unsigned wait= 3;
310   int error= 0;
311 
312   if ((error= get_status())!=0)
313     return error;
314 
315   if (sts_pic_rem==0)
316     return ERR_IMPOSSIBLE;
317 
318   send_cmd(cmd_shot);
319 
320   for (;;)
321   {
322     rcv=crcv(&error);
323     if (error)
324       break;
325   }
326 
327   /* now photo is taken */
328 
329   wait= 10;
330   error= 0;
331   while ( ((rcv=crcv(&error)) != 0) && wait-- )
332     error= 0;
333 
334   if ( (rcv != 0) || error )
335   {
336     return ERR_NO_RESPONSE;
337   }
338 
339   /* camera is ready again */
340 
341   error= get_status();
342 
343   return error;
344 }
345 
erase_dc20_memory(void)346 int erase_dc20_memory(void)
347 {
348   char rcv;
349   unsigned wait= 30;
350   int error= 0;
351 
352   if ((error= get_status())!=0)
353     return error;
354 
355   if (sts_pic_cnt==0)
356     return ERR_IMPOSSIBLE;
357 
358   if ((error= send_cmd(cmd_erase))!=0)
359     return error;
360 
361   while ( ((rcv=crcv(&error)) != 0) && wait-- )
362     error= 0;
363 
364   if ( (rcv != 0) || error )
365   {
366     return ERR_NO_RESPONSE;
367   }
368 
369   if ((error= get_status())!=0)
370     return error;
371 
372   return error;
373 }
374 
toggle_resolution(void)375 int toggle_resolution(void)
376 {
377   int error= 0;
378 
379   if ((error= get_status())!=0)
380     return error;
381 
382   if (dc_type == 0x25)
383     return ERR_NO_DC25_SUPP;
384 
385   if (sts_pic_cnt)
386     return ERR_IMPOSSIBLE;
387 
388   if (sts_res == RES_LOW)
389   {
390     if ((error= send_cmd(cmd_hires))!=0)
391       return error;
392   }
393   else
394   {
395     if ((error= send_cmd(cmd_lores))!=0)
396       return error;
397   }
398 
399   error= 0;
400   for (;;)
401   {
402     crcv(&error);
403     if (error)
404       break;
405   }
406 
407   if ((error= get_status())!=0)
408     return error;
409 
410   return error;
411 }
412 
load_thumbnails(FILE * ofp)413 int load_thumbnails(FILE *ofp)
414 {
415   int i, blk, error= 0;
416 
417   if ((error= get_status())!=0)
418     return error;
419 
420   if (dc_type == 0x25)
421     return ERR_NO_DC25_SUPP;
422 
423   if (sts_pic_cnt==0)
424     return ERR_IMPOSSIBLE;
425 
426   for (i=1; i<= sts_pic_cnt; i++)
427   {
428     cmd_thumbn[4]= (char) i;
429 
430     if ((error= send_cmd(cmd_thumbn))!=0)
431       return error;
432 
433     for (blk= 0; blk< 5; blk++)
434     {
435       if (read_from_com( Kb+1) != Kb+1)
436         return ERR_PACKET_WRONG;
437 
438       if (fwrite(inp_buff, 1, Kb, ofp) != Kb)
439         return ERR_DATA_SAVE;
440 
441       if (blk%2 == 0)
442       {
443         printf(".");
444         fflush(stdout);
445       }
446 
447       cxmit(0xD2);
448     }
449     crcv(&error);
450   }
451 
452   return error;
453 }
454 
download_picture(int pic_no,FILE * ofp)455 int download_picture(int pic_no, FILE *ofp)
456 {
457   int blk, max_blk, error= 0;
458 
459   if ((error= get_status())!=0)
460     return error;
461 
462   if (sts_pic_cnt < pic_no)
463     return ERR_IMPOSSIBLE;
464 
465   cmd_ldpic2[4]= (char) pic_no;
466 
467   if ((error= send_cmd(cmd_ldpic2))!=0)
468     return error;
469 
470   if (read_from_com( Kb+1) != Kb+1)
471     return ERR_PACKET_WRONG;
472 
473   if (fwrite(inp_buff, 1, Kb, ofp) != Kb)
474     return ERR_DATA_SAVE;
475 
476   cxmit(0xD2);
477 
478   if (inp_buff[4] == RES_HIGH)
479     max_blk= 122;
480   else
481     max_blk= 61;
482 
483   for (blk= 1; blk< max_blk; blk++)
484   {
485     if (read_from_com( Kb+1) != Kb+1)
486       return ERR_PACKET_WRONG;
487 
488     if (fwrite(inp_buff, 1, Kb, ofp) != Kb)
489       return ERR_DATA_SAVE;
490 
491     if (blk%2 == 0)
492     {
493       printf(".");
494       fflush(stdout);
495     }
496 
497     cxmit(0xD2);
498   }
499 
500   crcv(&error);
501 
502   return error;
503 }
504 
505 
load_image_infos(int img_inf[MAX_PICT][5])506 int load_image_infos(int img_inf[MAX_PICT][5])
507 {
508   int i, error= 0;
509 
510   if ((error= get_status())!=0)
511     return error;
512 
513   for (i=1; i<= sts_pic_cnt; i++)
514   {
515     if (i > MAX_PICT)
516       break;
517 
518     cmd_ldpic1[4]= (char) i;
519 
520     if ((error= send_cmd(cmd_ldpic1))!=0)
521       return error;
522 
523     if (read_from_com( 257) != 257)
524       return ERR_PACKET_WRONG;
525 
526     img_inf[i][0]= inp_buff[16];
527     img_inf[i][1]= inp_buff[17];
528     img_inf[i][2]= inp_buff[34];
529     img_inf[i][3]= inp_buff[35];
530     img_inf[i][4]= inp_buff[4];
531 
532     cxmit(0xD2);
533 
534     crcv(&error);
535   }
536 
537   return error;
538 }
539