Date: Sat, 21 Aug 1999 22:12:32 +0300 From: Harri Haanpaa --Boundary_(ID_08bJruDOqhtrOSQL2n60ag) Content-type: text/plain; charset=us-ascii On Tue, Aug 17, 1999 at 02:20:05PM +0200, J.A. Bezemer wrote: > [Been on vacation, so please excuse the delay ;-] I was on a conference trip and ill for a few days, so excuse the delay :) > About the error detection: it should be easy to just check the checksums of > the received packets, flag an error if needed, but just continue with the > actions. Then after the current actions are completed, just repeat them if > there was an error. And a 1-second timeout in case a packet was received > incorrectly by the camera. Should be very robust, but a little slow with a > noisy line. That sounds reasonable, but at the moment I don't think I'll find time for that. (The picture attached is probably worth more than a thousand words on that.) At 57600, the program hasn't had any trouble transfering the pictures; of course, a data error might have gone undetected. The program is included as an attachment. You may need to change the tty hard-wired into the code. Usage: run my version (57600 bps) of your ps350init, and then run this program in the directory where you want the pictures. The program logs all data sent/received from the serial port to stdout and stderr, so you may want to run the program either as /haha >debug1 2>debug2 or /haha >/dev/null 2>/dev/null Here it takes about 15 minutes to download the pictures from the 2M card that came with the camera. In most of the subroutines, a char[] constant is initialized and then relevant entries in the array are changed to represent the parameters. Then the array is sent to the camera as a command. The program basically proceeds according to the protocol as you described, except that it doesn't try the nonexistent disk and starts with DC97 and it doesn't shut the camera off after downloading. There are very few comments. If you need comments I'd be glad to comment the code a little. Just ask. Oh, BTW, does the copyright comment at the beginning of the file look OK to you? What do you think it should look like? Harri ---------------------------------------------------------------------- Later mail: I notice that in the usage instructions the user is asked to first run my version of the ps350init script, which is not included. My version simply sets the speed to 57600 instead of 115200. You'll find J.A.Bezemer's original script at http://panic.et.tudelft.nl/~costar/ps350doc.tgz To use a lower speed, find the line cat compu3e-4 > "$tty" in the script. compu3e-4 contains one character, the ascii code 4, ^D. In my version of the script, I've created the file compu3e-3 which contains ascii code 3, ^C, and changed the speed from 115200 to 57600 - it didn't work for me with the higher speed, but with the lower speed the transmission seemed reliable, even though my dirty hack doesn't even attempt to recover from any errors. If this doesn't work, you could try ^B and 38400, ^A and 19200 or perhaps even ^@ and 9600. You probably need to run my program within seconds of the ps350init finishing. ---------------------------------------------------------------------- --Boundary_(ID_08bJruDOqhtrOSQL2n60ag) Content-type: text/x-csrc; NAME=haha.c Content-disposition: attachment; filename=haha.c Content-transfer-encoding: 8bit /* Canon PowerShot 350 Picture Downloader Copyright (C) 1999 H.Haanpää CRC routine and picture file naming (C) 1999 J.A.Bezemer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ void do_download(char *sector, int filelen); #include #include #include #include #include unsigned char raw_data[300]; unsigned char tmp[300]; unsigned char dirent[30000]; unsigned char dirent2[30000]; unsigned char bigbuf[30000]; unsigned char count; char *port="/dev/ttyS1"; FILE *camera; int crc(char *data) { long datalen = 296; /* number of data bytes. Always 296. */ char bits[] = {1, 2, 4, 8, 16, 32, 64, 128}; long chksum = 0; long i, j; int inputbit, lastbit, xorbit; /* calculate checksum */ for (i = 0; i < datalen; i++) for (j = 0; j <= 7; j++) { lastbit = chksum & 0x0001; /* remember if last bit was 1 */ chksum >>= 1; /* shift 1 place */ inputbit = data[i] & bits[j] ? 1 : 0; /* the In bit */ xorbit = inputbit ^ lastbit; /* output of upper XOR gate */ if (xorbit) /* XOR if needed */ chksum ^= 0x8408; } /* display checksum */ return chksum; } void send(char *packet, int len) { int i; int chksum; for (i=0; i<300; i++) raw_data[i]=0; for (i=0; i0) do_download(sector,filelen); send_forgetf(sector); fread(raw_data, 1, 300, camera);fwrite(raw_data, 1, 300, stdout);fflush(stdout); /* get response packet */ fread(raw_data, 1, 300, camera);fwrite(raw_data, 1, 300, stdout);fflush(stdout); /* get response packet */ send_ack(); } } } void do_download(char *sector, int filelen) { static char fdl_str[]="\000\020\030\000\000\000\000\000\022\000\001\140\030\000\000\000!\000\000\000xxxxyyyy"; time_t time; struct tm *temptm; char timestring[200]; char tempstring[300]; char newname[300]; int newnamecounter; struct stat statbuf2; FILE *jpgfile; fdl_str[16]=++count; fdl_str[20]=sector[0]; fdl_str[21]=sector[1]; fdl_str[22]=sector[2]; fdl_str[23]=sector[3]; if (filelen>=0x245C) { fdl_str[24]=0x5C; fdl_str[25]=0x24; fdl_str[26]=0x00; fdl_str[27]=0x00; } else { fdl_str[24]=filelen & 0xFF; fdl_str[25]=(filelen >> 8) & 0xFF; fdl_str[26]=(filelen >>16) & 0xFF; fdl_str[27]=(filelen >>24) & 0xFF; } send(fdl_str, 28); fread(raw_data, 1, 300, camera);fwrite(raw_data, 1, 300, stdout);fflush(stdout); /* get response packet */ time= (((time_t) raw_data[91]) ) | (((time_t) raw_data[92]) << 8 ) | (((time_t) raw_data[93]) << 16 ) | (((time_t) raw_data[94]) << 24 ); temptm=gmtime(&time); strftime(timestring, 200, "%Y%m%d-%H%M%S", temptm); if (raw_data[14] < 20) /* thumbnail */ snprintf(tempstring, 200, "thm_%s", timestring); else /* other jpg */ snprintf(tempstring, 200, "aut_%s", timestring); snprintf(newname, 200, "%s.jpg", tempstring); newnamecounter=1; /* check if file exists. Will hang if all names are used... */ while (stat(newname, &statbuf2)==0) { newnamecounter++; snprintf(newname, 200, "%s-%d.jpg", tempstring, newnamecounter); } jpgfile=fopen(newname, "w"); fwrite(raw_data+41, 1, raw_data[3]+256*(raw_data[4]&0x7F)-36, jpgfile); for(;;) { fread(raw_data, 1, 300, camera);fwrite(raw_data, 1, 300, stdout);fflush(stdout); /* get response packet */ while(raw_data[2]!=3) { /* until we get an EOT */ fwrite(raw_data+5, 1, raw_data[3]+256*(raw_data[4]&0x7F), jpgfile); fread(raw_data, 1, 300, camera);fwrite(raw_data, 1, 300, stdout);fflush(stdout); /* get response packet */ } send_ack(); filelen-=0x245C; if(filelen<=0) break; if (filelen<0x245C) { fdl_str[24]=filelen & 0xFF; fdl_str[25]=(filelen >> 8) & 0xFF; fdl_str[26]=(filelen >>16) & 0xFF; fdl_str[27]=(filelen >>24) & 0xFF; } send(fdl_str, 28); fread(raw_data, 1, 300, camera);fwrite(raw_data, 1, 300, stdout);fflush(stdout); /* get response packet */ fwrite(raw_data+41, 1, raw_data[3]+256*(raw_data[4]&0x7F)-36, jpgfile); } fclose(jpgfile); }