/* * file: dc320.c # description: download program for Polaroid DC320 POS camera * author: Peter Desnoyers, pjd@fred.cambridge.ma.us */ #include #include #include #include #include #include #include #include #include int verbose = 0; #define E6_4 0xe6, 0xe6, 0xe6, 0xe6 #define E6_8 E6_4, E6_4 /* function: printhex description: print data in hex with an optional prefix at the beginning of each line */ void printhex(int n, unsigned char *buf, char *prefix) { int i; if (!prefix) prefix = ""; printf("%s", prefix); for (i = 0; i < n; i++) { if (i > 0 && (i%16) == 0) printf("\n%s", prefix); printf(" %02X", buf[i]); } printf("\n"); } /* function: read_data returns: number of data bytes read (>= 1), exits otherwise description: read some bytes with a 1-second timeout, exit if none. */ int read_data(int fd, char *buf, int bufsiz) { fd_set fds; struct timeval to = {1,0}; int n; FD_ZERO(&fds); FD_SET(fd, &fds); n = select(fd+1, &fds, NULL, NULL, &to); if (n < 0) perror("internal select error"), exit(1); if (n == 0) fprintf(stderr, "Timeout waiting for camera\n"), exit(1); if (!FD_ISSET(fd, &fds)) fprintf(stderr, "Internal error - weird\n"), exit(1); n = read(fd, buf, bufsiz); if (verbose) printhex(n, buf, "RPL> "); return n; } /* function: send_data description: write data to fd, print if verbose */ void send_data(int fd, char *buf, int len) { if (verbose) printhex(len, buf, "CMD> "); write(fd, buf, len); } /* function: open_tty returns: valid file descriptor, or prints an error message and exits description: open the device, set non-blocking mode, set raw TTY modes and 115kb speed. */ int open_tty(char *tty) { int fd; struct termios ti; if ((fd = open(tty, O_RDWR | O_NDELAY)) < 0) perror("can't open port for read/write"), exit(1); if (tcgetattr(fd, &ti) < 0) perror("can't get TTY attributes"), exit(1); cfmakeraw(&ti); cfsetospeed(&ti, B115200); cfsetispeed(&ti, B115200); if (tcsetattr(fd, TCSANOW, &ti) < 0) perror("can't set TTY attributes"), exit(1); return fd; } /* function: hdr description: negotiate start-up stuff with the camera */ void hdr(int fd) { char cmd1[] = {E6_8, 0, 0xff, 0xff}; char cmd2[] = {E6_4, 1, 0xfe, 0xff}; char cmd3[] = {E6_4, 2, 0xfd, 0xff}; char cmd4[] = {E6_4, 0xa, 0xf5, 0xff}; unsigned char buf[32]; int n; send_data(fd, cmd1, sizeof(cmd1)); n = read_data(fd, buf, sizeof(buf)); send_data(fd, cmd2, sizeof(cmd2)); n = read_data(fd, buf, sizeof(buf)); send_data(fd, cmd3, sizeof(cmd3)); n = read_data(fd, buf, sizeof(buf)); send_data(fd, cmd4, sizeof(cmd4)); n = read_data(fd, buf, sizeof(buf)); } /* function: npics description: retrieve picture count from camera. Exits on read error/timeout */ int npics(int fd) { char cmd1[] = {E6_4, 3, 0xfc, 0xff}; unsigned char buf[32]; int n; send_data(fd, cmd1, sizeof(cmd1)); n = read_data(fd, buf, sizeof(buf)); return buf[1]; } /* function: picsiz description: get the size in bytes of the i-th picture (numbered 1..N) */ int picsiz(int fd, int i) { char cmd1[] = {E6_4, 4, 1, 0xfb, 0xfe}; unsigned char buf[32]; int n, len; cmd1[5] += (i-1); /* gak - adjust checksum by hand */ cmd1[7] -= (i-1); send_data(fd, cmd1, sizeof(cmd1)); n = read_data(fd, buf, sizeof(buf)); len = (buf[1] << 24) + (buf[2] << 16) + (buf[3] << 8) + buf[4]; return len; } /* packet checksum: 1s complement sum of bytes, then subtract from 255 (like IP checksum, but 8 bits) so 1s complement sum of all bytes=0. The last byte is FF for 1-byte commands, FE for 2-byte, etc. for up to at least 3 bytes :-) */ /* function: getxxx description: get that funky per-image data that seems to encode luminance or brightness or something like that. */ void getxxx(int fd, int i, char *name) { char cmd[] = {E6_4, 0x0c, 01, 0xf3, 0xfe}; unsigned char buf[32]; int n; FILE *fp; cmd[5] += (i-1); cmd[7] -= (i-1); send_data(fd, cmd, sizeof(cmd)); n = read_data(fd, buf, sizeof(buf)); /* not that useful writing in binary - I ought to just write it in hex instead... */ if (!(fp = fopen(name, "w"))) perror("can't create output file"), exit(1); fwrite(buf, n, 1, fp); fclose(fp); } /* function: getpic description: read an actual picture from the camera, into a named file */ void getpic(int fd, int i, int len, char *name) { char cmd1[] = {E6_4, 5, 1, 0xfa, 0xfe}; unsigned char buf[2048], *p; int n, j, cksum, f1, f2; FILE *fp; printf("reading picture %d (%s)\n", i, name); fp = fopen(name, "w"); cmd1[5] += (i-1); cmd1[7] -= (i-1); send_data(fd, cmd1, sizeof(cmd1)); while (len > 0) { j = (len>2000) ? 2000 : len; usleep(10000); n = read_data(fd, buf, 5); f1 = (buf[1]<<8) + buf[2]; f2 = (buf[3]<<8) + buf[4]; printf("frame %d (%d)\n", f1, f2); for (p = buf; n > 0 && j > 0; p += n, j -= n) { usleep(1000); n = read_data(fd, p, j); } fwrite(buf, p-buf, 1, fp); len -= (p-buf); n = read_data(fd, buf, 2); cksum = (buf[0]<<8) + buf[1]; } fclose(fp); } /* function: delpics description: send DELETE command to camera - deletes all pictures */ void delpics(int fd) { char cmd[] = {E6_4, 7, 0xf8, 0xff}; unsigned char buf[32]; int n; send_data(fd, cmd, sizeof(cmd)); n = read_data(fd, buf, sizeof(buf)); } /* usage: dc320 [-port /dev/xyz] [-verbose] [-get|-delete|-stuff] description: initializes communication with DC320 and gets image count. Additional flags: -verbose - print lots of cruft -port - use another TTY. (or setenv DC320_PORT) -get - gets pictures into files named pic.%d.dat. -delete - deletes all pictures -stuff - get global luminance? bytes into pic.%d.etc */ int main(int argc, char **argv) { int fd; int n, size, i; int getpics=0, delete=0, stuff=0; char nbuf[32]; char *tty = "/dev/tts/1"; if (getenv("DC320_PORT")) tty = getenv("DC320_PORT"); for (argc--, argv++; argc > 0; argc--, argv++) { if (!strcmp(*argv, "-get")) getpics++; if (!strcmp(*argv, "-delete")) delete++; if (!strcmp(*argv, "-stuff")) stuff++; if (!strcmp(*argv, "-verbose")) verbose++; if (!strcmp(*argv, "-port")) { tty = *++argv; argc--; } } fd = open_tty(tty); /* exits if error */ printf("searching for camera... %s", verbose?"\n":""); hdr(fd); printf("found.\n"); if (delete) { delpics(fd); } else { printf("counting pictures... %s", verbose?"\n":""); n = npics(fd); printf("%d pictures\n", n); for (i = 1; i <= n; i++) { size = picsiz(fd, i); printf(" picture %d: %d bytes\n", i, size); if (getpics) { sprintf(nbuf, "pic.%d.dat", i); printf(" fetching picture...%s", verbose?"\n":""); getpic(fd, i, size, nbuf); printf("done.\n"); } if (stuff) { sprintf(nbuf, "pic.%d.etc", i); printf(" fetching weird data...%s", verbose?"\n":""); getxxx(fd, i, nbuf); printf("done.\n"); } } } close(fd); return 0; }