Logo Search packages:      
Sourcecode: camediaplay version File versions  Download package

main.c

/*
 * Copyright(c) 1997, 1998 by Jun-ichiro Itoh. All rights reserved.
 * Freely redistributable unless otherwise noted.  Absolutely no warranty.
 *
 * author contact: Jun-ichiro itojun Itoh <itojun@mt.cs.keio.ac.jp>
 * $Id: main.c,v 1.8 2001/02/11 01:03:44 itojun Exp $
 */
#include "common.h"
#include "camedia.h"

#if HAVE_TERMIOS_H
# include <termios.h>
#else
/*# if HAVE_TERMIO_H*/
# if 0
#  include <termio.h>
# else
#  if HAVE_SYS_IOCTL_H
#   include <sys/ioctl.h>
#  endif
#  include <sgtty.h>
# endif
#endif
#include <setjmp.h>
#include <sys/stat.h>

/*
 * SETTIME functionality is disabled due to the handling of timezone.
 */
#define NO_SETTIME

/* serial lines */
static int baudrateflag = 19200;
static char *n0;
static int fd0;

static int dumpflag = 0;
static int dumpmaxlen = 20;
static int debugflag = 0;
static int openflag = O_WRONLY | O_TRUNC | O_CREAT;
static enum pictmode { FULLSIZE, THUMBNAIL, VOICE } pictmode = FULLSIZE;
static int verbose = 0;

static enum {
      SHOWNPICTS, GETPICTS, GETPICT1, GETSTATUS,
#ifndef NO_SETTIME
      SETTIME,
#endif
      SETID, SETSERIALNO, TAKEPICTURE,
} mode = SHOWNPICTS;

static int startpict = 0;
static int endpict = 0;
static int allpict = 0;

static char *idstring = "";
static char *serialnostring = "";

#define     SMALLWAIT   200*1000    /*usec*/

#define dprintf(x)                                    \
      { if (debugflag) {                              \
            fprintf(stderr, __FILE__ ":%d: ", __LINE__);    \
            fprintf x;                          \
        }                                       \
      }

/* uid */
static uid_t uid, euid;
static gid_t gid, egid;
static int uidswapped = 0;

/* uucp locking */
static int useuucplock = 1;
extern int uu_lock __P((char *));
extern int uu_unlock __P((char *));

/* error handling */
jmp_buf fatal;

void
daemonuid()
{
      if (uidswapped == 0)
            return;

#ifdef HAVE_SETREUID
      setreuid(uid, euid);
      setregid(gid, egid);
#else
      setuid(uid);
      seteuid(euid);
      setgid(gid);
      setegid(egid);
#endif
      uidswapped = 0;
}

void
useruid()
{
      if (uidswapped == 1)
            return;

#ifdef HAVE_SETREUID
      setregid(egid, gid);
      setreuid(euid, uid);
#else
      setgid(egid);
      setegid(gid);
      setuid(euid);
      seteuid(uid);
#endif
      uidswapped = 1;
}

static int
uucplock(name)
      char *name;
{
      int ret;

      if (useuucplock) {
            daemonuid();
            ret = uu_lock(rindex(name, '/') + 1);
            useruid();
      } else
            ret = 0;
      return ret;
}

static int
uucpunlock(name)
      char *name;
{
      int ret;

      if (useuucplock) {
            daemonuid();
            ret = uu_unlock(rindex(name, '/') + 1);
            useruid();
      } else
            ret = 0;
      return ret;
}

static char *
canondev(name)
      char *name;
{
      int fd;
      char *p;

      daemonuid();

      p = malloc(strlen(name) + 1);
      if (!p) {
            perror("malloc");
            goto back;
      }
      strcpy(p, name);
      fd = open(p, O_RDWR|O_NONBLOCK);
      if (0 <= fd) {
            close(fd);
            goto back;
      }

      p = realloc(p, strlen(name) + 6);
      if (!p) {
            perror("realloc");
            goto back;
      }
      strcpy(p, "/dev/");
      strcat(p, name);
      fd = open(p, O_RDWR|O_NONBLOCK);
      if (0 <= fd) {
            close(fd);
            goto back;
      }

      free(p);
      p = NULL;
back:
      useruid();
      return p;
}

speed_t
baudconv(int baud)
{
#define     BAUDCASE(x) case (x): { ret = B##x; break; }
      speed_t ret;

      ret = (speed_t) baud;
      switch (baud) {
      /* POSIX defined baudrates */
      BAUDCASE(0);      /*is it meaningful? */
      BAUDCASE(50);
      BAUDCASE(75);
      BAUDCASE(110);
      BAUDCASE(134);
      BAUDCASE(150);
      BAUDCASE(200);
      BAUDCASE(300);
      BAUDCASE(600);
      BAUDCASE(1200);
      BAUDCASE(1800);
      BAUDCASE(2400);
      BAUDCASE(4800);
      BAUDCASE(9600);
      BAUDCASE(19200);
      BAUDCASE(38400);

      /* non POSIX values */
#ifdef B7200
      BAUDCASE(7200);
#endif
#ifdef B14400
      BAUDCASE(14400);
#endif
#ifdef B28800
      BAUDCASE(28800);
#endif
#ifdef B57600
      BAUDCASE(57600);
#endif
#ifdef B115200
      BAUDCASE(115200);
#endif
#ifdef B230400
      BAUDCASE(230400);
#endif

      /* last resort */
      default:
            fprintf(stderr, "no defined value for baudrate %d found, "
                  "use the value without conversion\n", baud);
      }

      return ret;
#undef BAUDCASE
}

int
setbaud(fd, baud)
      int fd;
      int baud;
{
#if HAVE_TERMIOS_H
      /* termios */
      struct termios tio;

      if (tcgetattr(fd, &tio) < 0) {
            perror("tcgetattr");
            return 1;
      }
      tio.c_iflag = 0;
      tio.c_oflag = 0;
      tio.c_cflag = CS8 | CREAD | CLOCAL;
      tio.c_lflag = 0;
      tio.c_cc[VMIN] = 1;
      tio.c_cc[VTIME] = 5;
      cfsetispeed(&tio, baudconv(baud));
      cfsetospeed(&tio, baudconv(baud));
      if (tcsetattr(fd, TCSANOW, &tio) < 0) {
            perror("tcsetattr");
            return 1;
      }
#else
/*#if HAVE_TERMIO_H*/
# if 0
      /* termio */
# else
      /* sgtty */
      struct sgttyb ttyb;

      if (ioctl(fd, TIOCGETP, &ttyb) < 0) {
            perror("ioctl(TIOCGETP)");
            return 1;
      }
      ttyb.sg_ispeed = baud;
      ttyb.sg_ospeed = baud;
      ttyb.sg_flags = 0;
      if (ioctl(fd, TIOCSETP, &ttyb) < 0) {
            perror("ioctl(TIOCSETP)");
            return 1;
      }
# endif
#endif

      dprintf((stderr, "baudrate set to %d\n", baud));
      return 0;
}

void
dump_stream(dir, buf, len)
      int dir;
      u_char *buf;
      int len;
{
      size_t i;
      int truncate;

      if (!dumpflag)
            return;

      truncate = 0;
      if (dumpmaxlen < len) {
            len = dumpmaxlen;
            truncate = 1;
      }

      dir &= 0xff;
      if (dir == '>')
            fprintf(stderr, "camera>cpu: ");
      else
            fprintf(stderr, "cpu>camera: ");

      for (i = 0; i < len; i++)
            fprintf(stderr, "%02x ", buf[i] & 0xff);
      if (truncate)
            fprintf(stderr, "...");
      fprintf(stderr, "\n");
}

/*------------------------------------------------------------*/

u_char camedia_buf[1024 * 4];
size_t camedia_len;

void
camedia_init()
{
      /* initialize buffers */
      camedia_len = 0;
}

int
camedia_wait(rlen)
      int rlen;
{
      fd_set rdfd;
      int maxfd;
      int len;
      struct timeval t;

      while (camedia_len < rlen) {
            /* obtain chars from the camera */
            FD_ZERO(&rdfd);
            FD_SET(fd0, &rdfd);
            maxfd = fd0;
            /* timeout: 5sec */
            t.tv_sec = 5;
            t.tv_usec = 0;
            switch (select(maxfd + 1, &rdfd, NULL, NULL, &t)) {
            case -1:
                  if (errno == EINTR)
                        break;
                  perror("select");
                  exit(1);
            case 0:
                  dprintf((stderr, "read timeout.\n"));
                  return 1;
            default:
                  break;
            }

            if (FD_ISSET(fd0, &rdfd)) {
                  len = read(fd0, camedia_buf + camedia_len,
                        sizeof(camedia_buf) - camedia_len);
                  camedia_len += len;
            } else {
                  dprintf((stderr, "something wrong in camedia_get\n"));
                  return 1;
            }
      }
      dump_stream('>', camedia_buf, camedia_len);

      return 0;
}

int
camedia_get(buf, len)
      u_char *buf;
      int len;
{
      switch (camedia_wait(len)) {
      case 1:
            dprintf((stderr, "timeouted in camedia_get\n"));
            fprintf(stderr, "camera not ready.\n");
            longjmp(fatal, 1);
      case 0:
            break;
      }

      if (camedia_len < len)
            abort();

      memcpy(buf, camedia_buf, len);
      if (camedia_len - len)
            memmove(camedia_buf, camedia_buf + len, camedia_len - len);
      camedia_len -= len;

      return 0;
}

int
camedia_put(buf, len)
      u_char *buf;
      int len;
{
      int wlen;
      int i;

      /* Thanks goes to Thierry Bousch */
      for (i = 0; i < len; i++) {
            wlen = write(fd0, &buf[i], 1);
            if (wlen != 1) {
                  dprintf((stderr, "failed in camedia_put\n"));
                  return 1;
            }
            usleep(20*1000);
#if HAVE_TERMIOS_H
            /*termios*/
            tcdrain(fd0);
#else
/*#if HAVE_TERMIO_H*/
#if 0
            /*termio - yet to be done*/
#else
            /*sgtty*/
            ioctl(fd0, TCDRAIN, 0);
#endif
#endif
      }

      dump_stream('<', buf, len);
      return 0;
}

/*------------------------------------------------------------*/

int
camedia_attention()
{
      u_char buf[10];
      int timeout;

#define ATTN_WAIT 10

      camedia_put("\0", 1);
      timeout = 0;
      do {
            camedia_get(buf, 1);
            if (ATTN_WAIT <= timeout++) {
                  dprintf((stderr,
                        "timed out while waiting 0x15 "
                        "in camedia_attention"));
                  return 1;
            }
      } while (buf[0] != 0x00 && buf[0] != 0x15 && buf[0] != 0xff);

      switch (buf[0]) {
      case 0x00:  /*Agfa ePhoto307*/
      case 0x15:  /*others*/
            return 0;

      case 0xff:
            dprintf((stderr,
                  "got baudrate error reported in camedia_attention"));
            return 1;

      default:
            dprintf((stderr,
                  "unknown char 0x%02x arrived in camedia_attention",
                  buf[0]));
            return 1;
      }
}

int
camedia_getack()
{
      u_char buf[10];

      camedia_get(buf, 1);
      if (buf[0] != 0x06) {
            dprintf((stderr, "got 0x%02x while waiting ACK(0x06)\n",
                  buf[0] && 0xff));
            return 1;
      }
      return 0;
}

int
camedia_sendcmd(ch, buf, len)
      int ch;
      u_char *buf;
      int len;
{
      u_char tbuf[2];
      u_short sum;
      size_t i;
      int err;

      usleep(SMALLWAIT);      /*YYY*/

      /* generate checksum */
      sum = 0;
      for (i = 0; i < len; i++) {
            sum += (buf[i] & 0xff);
      }

      tbuf[0] = '\033';
      tbuf[1] = ch & 0xff;
      err = camedia_put(tbuf, 2);

      tbuf[0] = len & 0x00ff;
      tbuf[1] = (len & 0xff00) >> 8;
      err += camedia_put(tbuf, 2);

      err += camedia_put(buf, len);

      tbuf[0] = sum & 0x00ff;
      tbuf[1] = (sum & 0xff00) >> 8;
      err += camedia_put(tbuf, 2);

      return err ? 1 : 0;
}

int
camedia_getpacket(buf, plen, pfinal, ack, sector)
      u_char *buf;
      int *plen;
      int *pfinal;
      int *ack;
      int *sector;
{
      int err;
      u_char tbuf[2];
      u_short len;
      u_short cksum;
      size_t i;

      err = 0;

      /* init */
      *plen = 0;
      *pfinal = 1;
      *ack = 0;
      if (sector)
            *sector = -1;

      /* get the packet type. */
      if (camedia_get(tbuf, 1)) {
            dprintf((stderr, "err in camedia_getpacket: getting type\n"));
            err++;
      }
      if (tbuf[0] == 0x15) {
            dprintf((stderr, "got NAK\n"));
            return 1;
      } else if (tbuf[0] == 0xff) {
            dprintf((stderr, "got framing error\n"));
            return 1;
      } else if (tbuf[0] == 0x06) {
            dprintf((stderr, "got ACK\n"));
            *ack = 1;
            return 0;
      } else if (tbuf[0] != 0x02 && tbuf[0] != 0x03) {
            dprintf((stderr, "illegal packet received: 0x%02x\n", tbuf[0]));
            err++;
            goto back;
      }

      if (camedia_get(tbuf + 1, 1)) {
            dprintf((stderr, "err in camedia_getpacket: getting type\n"));
            err++;
      }

      if (sector)
            *sector = tbuf[1] & 0xff;
      switch (tbuf[0]) {
      case 0x02:
            *pfinal = 0;
            break;
      case 0x03:
            *pfinal = 1;
            break;
      default:
            dprintf((stderr, "err in camedia_getpacket: type = %02x%02x\n",
                  tbuf[1], tbuf[0]));
            err++;
      }

      /* get the packet len. */
      if (camedia_get(tbuf, 2)) {
            dprintf((stderr, "err in camedia_getpacket: getting len\n"));
            err++;
      }
      len = ((u_short)tbuf[1] << 8) + tbuf[0];

      /* get the packet content. */
      if (camedia_get(buf, len)) {
            dprintf((stderr, "err in camedia_getpacket: body\n"));
            err++;
      }

      /* check for checksum. */
      if (camedia_get(tbuf, 2)) {
            dprintf((stderr,
                  "err in camedia_getpacket: getting checksum\n"));
            err++;
      }

      cksum = 0;
      for (i = 0; i < len; i++) {
            cksum += (buf[i] & 0xff);
      }

      if (tbuf[0] != (cksum & 0x00ff) || tbuf[1] != (cksum & 0xff00) >> 8) {
            dprintf((stderr, "err in camedia_getpacket: cksum\n"));
#if 0
            err++;
#endif
      }

      /* XXX must check for retransmit */
#if 0
      if (!err)
            camedia_put("\006", 1); /*ACK*/
      else
            camedia_put("\025", 1); /*NAK*/
#else
      camedia_put("\006", 1); /*ACK*/
#endif

      if (!err)
            *plen = len;

back:
      return err ? 1 : 0;
}

int
camedia_getint(cmd, n)
      int cmd;
      int *n;
{
      u_char buf[1024];
      int len;
      int final;
      int ack;
      int err;

      err = 0;

      cmd &= 0xff;
      buf[0] = CAM_GETNUM;
      buf[1] = cmd;
      if (camedia_sendcmd('C', buf, 2)) {
            dprintf((stderr, "sendcmd err in camedia_getint(%02x %02x)\n",
                  CAM_GETNUM, cmd));
            err++;
            goto ng;
      }

      if (camedia_getpacket(buf, &len, &final, &ack, NULL)) {
            dprintf((stderr, "getpacket err in camedia_getint(%02x %02x)\n",
                  CAM_GETNUM, cmd));
            err++;
            goto ng;
      }
      if (!final || ack) {
            dprintf((stderr,
                  "getpacket err in camedia_getint(%02x %02x): %d/%d\n",
                  CAM_GETNUM, cmd, final, ack));
            err++;
            goto ng;
      }

      if (n) {
            *n = (buf[3] & 0xff);
            *n = (*n * 256) + (buf[2] & 0xff);
            *n = (*n * 256) + (buf[1] & 0xff);
            *n = (*n * 256) + (buf[0] & 0xff);
      }

ng:
      return err ? 1 : 0;
}

int
camedia_setint(cmd, n)
      int cmd;
      int n;
{
      u_char buf[1024];
      int len;
      int final;
      int ack;
      int err;

      err = 0;

      cmd &= 0xff;
      buf[0] = CAM_SETNUM;
      buf[1] = cmd;
      buf[2] = (n & 0x000000ff) >> 0;
      buf[3] = (n & 0x0000ff00) >> 8;
      buf[4] = (n & 0x00ff0000) >> 16;
      buf[5] = (n & 0xff000000) >> 24;
      if (camedia_sendcmd('C', buf, 6)) {
            dprintf((stderr, "sendcmd err in camedia_setint(%02x %02x)\n",
                  CAM_SETNUM, cmd));
            err++;
            goto ng;
      }
      if (camedia_getpacket(buf, &len, &final, &ack, NULL)) {
            dprintf((stderr, "getpacket err in camedia_setint(%02x %02x)\n",
                  CAM_SETNUM, cmd));
            err++;
            goto ng;
      }
      if (!ack) {
            dprintf((stderr,
                  "getpacket err in camedia_setint(%02x %02x): %d/%d\n",
                  CAM_SETNUM, cmd, final, ack));
            err++;
      }

ng:
      return err ? 1 : 0;
}

int
camedia_getstr(cmd, buf, plen)
      int cmd;
      u_char *buf;
      int *plen;
{
      u_char tbuf[10];
      int final;
      int ack;
      int err;

      err = 0;

      cmd &= 0xff;
      tbuf[0] = CAM_GETSTR;
      tbuf[1] = cmd;
      if (camedia_sendcmd('C', tbuf, 2)) {
            dprintf((stderr, "sendcmd err in camedia_getstr(%02x %02x)\n",
                  CAM_GETSTR, cmd));
            err++;
            goto ng;
      }

      if (camedia_getpacket(buf, plen, &final, &ack, NULL)) {
            dprintf((stderr, "getpacket err in camedia_getstr(%02x %02x)\n",
                  CAM_GETSTR, cmd));
            err++;
            goto ng;
      }
      if (!final || ack) {
            dprintf((stderr,
                  "getpacket err in camedia_getstr(%02x %02x): %d/%d\n",
                  CAM_GETSTR, cmd, final, ack));
            err++;
            goto ng;
      }

ng:
      return err ? 1 : 0;
}

int
camedia_setstr(cmd, src, srclen)
      int cmd;
      u_char *src;
      int srclen;
{
      u_char buf[1024];
      int len;
      int final;
      int ack;
      int err;

      err = 0;

      cmd &= 0xff;
      buf[0] = CAM_SETSTR;
      buf[1] = cmd;
      memcpy(&buf[2], src, srclen);
      if (camedia_sendcmd('C', buf, srclen + 2)) {
            dprintf((stderr, "sendcmd err in camedia_setstr(%02x %02x)\n",
                  CAM_SETSTR, cmd));
            err++;
            goto ng;
      }
      if (camedia_getpacket(buf, &len, &final, &ack, NULL)) {
            dprintf((stderr, "getpacket err in camedia_setstr(%02x %02x)\n",
                  CAM_SETSTR, cmd));
            err++;
            goto ng;
      }
      if (!ack) {
            dprintf((stderr,
                  "getpacket err in camedia_setstr(%02x %02x): %d/%d\n",
                  CAM_SETSTR, cmd, final, ack));
            err++;
      }

ng:
      return err ? 1 : 0;
}

int
camedia_control(cmd)
      int cmd;
{
      u_char buf[1024];
      int final;
      int ack;
      int err;
      int len;

      err = 0;

      cmd &= 0xff;
      buf[0] = CAM_CONTROL;
      buf[1] = cmd;
      if (camedia_sendcmd('C', buf, 2)) {
            dprintf((stderr, "sendcmd err in camedia_control(%02x %02x)\n",
                  CAM_CONTROL, cmd));
            err++;
            goto ng;
      }

      if (camedia_getpacket(buf, &len, &final, &ack, NULL)) {
            dprintf((stderr, "getpacket err in "
                  "camedia_control(%02x %02x)\n", CAM_CONTROL, cmd));
            err++;
            goto ng;
      }
      if (!final || ack) {
            dprintf((stderr,
                  "getpacket err in camedia_control(%02x %02x): %d/%d\n",
                  CAM_CONTROL, cmd, final, ack));
            err++;
            goto ng;
      }

ng:
      return err ? 1 : 0;
}


/*------------------------------------------------------------*/

int
camedia_setspeed(baud)
      int baud;
{
      u_char buf[10];
      int err;
      u_char value;

      err = 0;

      usleep(SMALLWAIT);

      while (camedia_attention()) {
            dprintf((stderr, "ATTN err in camedia_setspeed\n"));
            usleep(SMALLWAIT);
      }

      switch (baud) {
      case -1:
            value = '\000';
            break;
      case 9600:
            value = '\001';
            break;
      case 19200:
            value = '\002';
            break;
      case 38400:
            value = '\003';
            break;
      case 57600:
            value = '\004';
            break;
      case 115200:
            value = '\005';
            break;
      default:
            /* unsupported baud rate. */
            dprintf((stderr, "unsupported baudrate %d\n", baud));
            return 1;
      }

      /* set baudrate */
      memcpy(buf, "\0\021\0\0\0\0", 6);
      buf[2] = value;
      if (camedia_sendcmd('S', buf, 6)) {
            dprintf((stderr, "sendcmd err in camedia_setspeed\n"));
            err++;
      }

      if (camedia_getack()) {
            dprintf((stderr, "ACK err in camedia_setspeed\n"));
            err++;
      }

      usleep(20*1000);

      if (baud == -1)
            err += setbaud(fd0, 19200);
      else
            err += setbaud(fd0, baud);

      usleep(1000*1000);

      return err ? 1 : 0;
}

int
camedia_checkcamera()
{
      int err;

      err = 0;

      if (camedia_attention()) {
            dprintf((stderr, "ATTN err in camedia_checkcamera\n"));
            err++;
      }

      if (camedia_setspeed(-1)) {
            dprintf((stderr, "err in camedia_checkcamera\n"));
            err++;
      }

      if (camedia_setspeed(baudrateflag)) {
            dprintf((stderr, "err in camedia_checkcamera\n"));
            err++;
      }

      return err ? 1 : 0;
}

#ifndef NO_SETTIME
int
camedia_settime(t)
      time_t t;
{
      int err;

      err = 0;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_settime\n"));
            err++;
      }

      /* get picture # */
      if (camedia_setint(CAM_NUM_DATE, (int)t)) {
            dprintf((stderr, "setint err in camedia_settime\n"));
            err++;
      }

      return err ? 1 : 0;
}
#endif

int
camedia_setid(s)
      char *s;
{
      int err;

      err = 0;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_setid\n"));
            err++;
      }

      /* get picture # */
      if (camedia_setstr(CAM_STR_MODELID, s, strlen(s) + 1)) {
            dprintf((stderr, "setstr err in camedia_setid\n"));
            err++;
      }

      return err ? 1 : 0;
}

int
camedia_setserialno(s)
      char *s;
{
      int err;

      err = 0;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_setserialno\n"));
            err++;
      }

      /* get picture # */
      if (camedia_setstr(CAM_STR_SERIALNO, s, strlen(s) + 1)) {
            dprintf((stderr, "setstr err in camedia_setserialno\n"));
            err++;
      }

      return err ? 1 : 0;
}

int
camedia_takepicture()
{
      int err;

      err = 0;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_setserialno\n"));
            err++;
      }

      /* get picture # */
      if (camedia_control(CAM_CTL_SHUTTER)) {
            dprintf((stderr, "control err in camedia_takepicture\n"));
            err++;
      }

      return err ? 1 : 0;
}

int
camedia_getnpicts(n)
      int *n;
{
      int err;

      err = 0;

      *n = -1;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_getnpicts\n"));
            err++;
      }

      /* get picture # */
      if (camedia_getint(CAM_NUM_NPICTS, n)) {
            dprintf((stderr, "getint err in camedia_getnpicts\n"));
            err++;
      }

      return err ? 1 : 0;
}

int
camedia_getnpictremain(n)
      int *n;
{
      int err;

      err = 0;

      *n = -1;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_getnpicts\n"));
            err++;
      }

      /* get picture # */
      if (camedia_getint(CAM_NUM_NREMAIN, n)) {
            dprintf((stderr, "getint err in camedia_getnpicts\n"));
            err++;
      }

      return err ? 1 : 0;
}

int
camedia_getpict(n, pmode, fd)
      int n;
      enum pictmode pmode;
      int fd;
{
      u_char buf[1024 * 4];
      int len;
      int final;
      int ack;
      int sector;
      int err;
      int totallen;

      int cmd;

      err = 0;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, NULL)) {
            dprintf((stderr, "getint err in camedia_getnpicts\n"));
            err++;
      }

      /* specify the picture # */
      if (camedia_setint(CAM_NUM_PTR, n)) {
            dprintf((stderr, "setint err in camedia_getnpicts\n"));
            err++;
      }

      /* get the size */
      switch (pmode) {
      case FULLSIZE:
            cmd = CAM_NUM_PICTSIZE;
            break;
      case THUMBNAIL:
            cmd = CAM_NUM_THUMBSIZE;
            break;
      case VOICE:
            /* cannot esetimate size right now, protocol unknown */
            break;
      }
      if (pmode != VOICE) {
            if (camedia_getint(cmd, &totallen)) {
                  dprintf((stderr, "getint err in camedia_getnpicts\n"));
                  err++;
            } else
                  fprintf(stderr, "size will be %d\n", totallen);
      }

      /* start xfer */
      buf[0] = CAM_GETSTR;
      switch (pmode) {
      case FULLSIZE:
            buf[1] = CAM_STR_PICT;
            break;
      case THUMBNAIL:
            buf[1] = CAM_STR_THUMB;
            break;
      case VOICE:
            buf[1] = CAM_STR_VOICE;
            break;
      }

      if (camedia_sendcmd('C', buf, 2)) {
            dprintf((stderr, "sendcmd err in camedia_getpict\n"));
            err++;
      }

      /* get all sectors, and write them down into file */
      final = 0;
      totallen = 0;
      while (!final) {
            /*
             * XXX
             * must check for sector number skips/rewinds,
             * and checksum NAKs
             */
            if (camedia_getpacket(buf, &len, &final, &ack, &sector)) {
                  dprintf((stderr, "getpacket err in camedia_getpict\n"));
                  err++;
            } else if (ack) {
                  dprintf((stderr,
                        "getpacket err in camedia_getpict: %d/%d\n",
                        final, ack));
                  err++;

            } else {
                  if (verbose) {
                        fprintf(stderr,
                              "got sector %3d: %d bytes \r",
                                    sector, totallen);
                  }
                  write(fd, buf, len);

                  totallen += len;
            }
      }
      if (verbose) {
            fprintf(stderr,
                  "got sector %3d: %d bytes ...done%s\n",
                        sector, totallen, err ? " with err" : "");
      }

      return err ? 1 : 0;
}

int
camedia_getstatus()
{
      u_char buf[1024 * 4];
      int len;
      int err;
      int n;
      char *t;

      err = 0;

      /* get battery capacity - should check for battery shortage */
      if (camedia_getint(CAM_NUM_BATTERY, &n)) {
            dprintf((stderr, "getint err in camedia_getnpicts\n"));
            err++;
      } else
            fprintf(stderr, "battery capacity: %d%%\n", n);

      /* get camera id */
      if (camedia_getstr(CAM_STR_MODELID, buf, &len)) {
            dprintf((stderr, "can't get camera id\n"));
            err++;
      } else
            fprintf(stderr, "camera id: %s\n", buf);

      /* get camera type */
      if (camedia_getstr(CAM_STR_MODELTYPE, buf, &len)) {
            dprintf((stderr, "can't get camera type\n"));
            err++;
      } else
            fprintf(stderr, "camera type: %s\n", buf);

      /* get serial number */
      if (camedia_getstr(CAM_STR_SERIALNO, buf, &len)) {
            dprintf((stderr, "can't get serial number\n"));
            err++;
      } else
            fprintf(stderr, "serial number: %s\n", buf);

      /* get software version*/
      if (camedia_getstr(CAM_STR_VERSION, buf, &len)) {
            dprintf((stderr, "can't get software version\n"));
            err++;
      } else
            fprintf(stderr, "software version: %s\n", buf);

      /* get lens mode */
      if (camedia_getint(CAM_NUM_LENS, &n)) {
            dprintf((stderr, "can't get lens mode\n"));
            err++;
      } else {
            switch (n) {
            case 1:
                  t = "macro"; break;
            case 2:
                  t = "normal"; break;
            default:
                  t = "???"; break;
            }
            fprintf(stderr, "lens mode: %s\n", t);
      }

      /* get flash mode */
      if (camedia_getint(CAM_NUM_FLASH, &n)) {
            dprintf((stderr, "can't get flash mode\n"));
            err++;
      } else {
            switch (n) {
            case 0:
                  t = "auto"; break;
            case 1:
                  t = "force on"; break;
            case 2:
                  t = "force off"; break;
            case 3:
                  t = "on(redeye prevention)"; break;
            default:
                  t = "???"; break;
            }
            fprintf(stderr, "flash mode: %s\n", t);
      }

      /* get quality mode */
      if (camedia_getint(CAM_NUM_QUALITY, &n)) {
            dprintf((stderr, "can't get quality mode\n"));
            err++;
      } else {
            switch (n) {
            case 1:
                  t = "normal"; break;
            case 2:
                  t = "HQ"; break;
            default:
                  t = "???"; break;
            }

            if (verbose)
                  fprintf(stderr, "quality mode: %s(%d)\n", t, n);
            else
                  fprintf(stderr, "quality mode: %s\n", t);
      }

#ifndef NO_SETTIME
      /* get time setting */
      if (camedia_getint(CAM_NUM_DATE, &n)) {
            dprintf((stderr, "can't get time setting\n"));
            err++;
      } else {
            time_t t1;

            /*
             * XXX
             * we got seconds from epoch into n, but in local time!
             * how can we convert it into seconds from epoch in GMT,
             * in a portable manner?
             */
            t1 = n;
            fprintf(stderr, "date on camera: %s", ctime(&t1));
      }
#endif

      return err ? 1 : 0;
}

void
mainloop()
{
      int n;
      char fnamebuf[MAXPATHLEN];
      int i;
      int fd;

      switch (setjmp(fatal)) {
      case 0:
            break;
      default:
            goto fatalerr;
      }

      /*initial value*/
      if (setbaud(fd0, 19200)) {
            fprintf(stderr, "can't set baudrate\n");
            goto fatalerr;
      }

      camedia_init();

      camedia_setspeed(baudrateflag);

      usleep(SMALLWAIT);

      if (camedia_getnpicts(&n)) {
            fprintf(stderr, "error getting npicts\n");
            goto fatalerr;
      }

      if (!(mode == SHOWNPICTS || mode == GETPICTS || mode == GETPICT1))
            goto afterclarify;

      /*
       * parameter clarification
       */
      if (allpict) {
            startpict = 1;
            endpict = n;
      } else {
            /* default settings */
            if (startpict == 0)
                  startpict = 1;
            if (endpict == 0)
                  endpict = n;
      }
      if (startpict < 1 || n < startpict) {
            fprintf(stderr,
                  "illegal startpict %d (must be 1 to %d)\n",
                  startpict, n);
            goto fatalerr;
      }
      if (endpict < 1 || n < endpict) {
            fprintf(stderr,
                  "illegal endpict %d (must be 1 to %d)\n",
                  endpict, n);
            goto fatalerr;
      }
      if (endpict < startpict) {
            int tmp;
            tmp = startpict;
            startpict = endpict;
            endpict = tmp;
      }

afterclarify:;
      switch (mode) {
      case SHOWNPICTS:
            fprintf(stderr, "picts=%d/", n);
            if (camedia_getnpictremain(&n)) {
                  fprintf(stderr, "error getting npictremain\n");
                  goto fatalerr;
            }
            fprintf(stderr, "remain=%d\n", n);
            break;

      case GETPICTS:
            for (i = startpict; i <= endpict; i++) {
                  snprintf(fnamebuf, sizeof(fnamebuf), "pic%05d.jpg", i);
                  if (verbose) {
                        fprintf(stderr, "getting image %d to %s\n",
                              i, fnamebuf);
                  }
                  fd = open(fnamebuf, openflag, 0644);
                  if (fd < 0) {
                        perror("open");
                        goto fatalerr;
                  }
                  camedia_getpict(i, pictmode, fd);
                  close(fd);
            }
            break;

      case GETPICT1:
            if (startpict != endpict) {
                  fprintf(stderr, "more than 1 picts specified\n");
                  goto fatalerr;
            }
            if (verbose) {
                  fprintf(stderr,
                        "getting image %d to stdout\n", startpict);
            }
            camedia_getpict(startpict, pictmode, STDOUT_FILENO);
            break;

      case GETSTATUS:
            camedia_getstatus();
            break;

#ifndef NO_SETTIME
      case SETTIME:
            camedia_settime(time((time_t *)NULL));
            break;
#endif

      case SETID:
            camedia_setid(idstring);
            break;

      case SETSERIALNO:
            camedia_setserialno(serialnostring);
            break;

      case TAKEPICTURE:
            camedia_takepicture();
            break;

      default:
            dprintf((stderr, "internal error - case not matched\n"));
            break;
      }

      camedia_setspeed(-1);

      return;

fatalerr:
      /* cleanup() will be called automatically */
      exit(1);
}

void
usage()
{
      fprintf(stderr,
            "usage:\n"
            "\tcamediaplay [options] port\n"
            "\tcamediaplay [options] -o port > foo.jpg\n"
            "\tcamediaplay [options] -g port\n"
            "\tcamediaplay [options] -S port\n"
#ifndef NO_SETTIME
            "\tcamediaplay [options] -T port\n"
#endif
            "\tcamediaplay [options] -I ID port\n"
            "\tcamediaplay [options] -# SERIALNO port\n"
            "\tcamediaplay [options] -P port\n"
            );
}

void
cleanup()
{
      close(fd0);
      uucpunlock(n0);
}

void
main(argc, argv)
      int argc;
      char **argv;
{
      int opt;
      extern char *optarg;

      uid = getuid();
      euid = geteuid();
      gid = getgid();
      egid = getegid();
      useruid();

      useuucplock = 1;

#ifdef NO_SETTIME
# define ACCEPTOPT      "b:dDitVuve:s:n:agoSI:#:P"
#else
# define ACCEPTOPT      "b:dDitVuve:s:n:agoSTI:#:P"
#endif
      while ((opt = getopt(argc, argv, ACCEPTOPT)) != -1) {
#undef ACCEPTOPT
            switch (opt) {

            /* controls */
            case 'b':
                  baudrateflag = atoi(optarg);
                  break;
            case 'd':
                  dumpflag = 1;
                  break;
            case 'D':
                  debugflag = 1;
                  break;
            case 'i':
                  openflag = O_WRONLY | O_EXCL | O_CREAT;
                  break;
            case 't':
                  pictmode = THUMBNAIL;
                  break;
            case 'V':
                  pictmode = VOICE; /* specific to DSC-V1 */
                  break;
            case 'u':
                  useuucplock = 0;
                  break;
            case 'v':
                  verbose = 1;
                  break;

            /* picture range */
            case 'e':
                  endpict = atoi(optarg);
                  break;
            case 's':
                  startpict = atoi(optarg);
                  break;
            case 'n':
                  startpict = endpict = atoi(optarg);
                  break;
            case 'a':
                  allpict = 1;
                  break;

            /* mode */
            case 'g':
                  mode = GETPICTS;
                  break;
            case 'o':
                  mode = GETPICT1;
                  break;
            case 'S':
                  mode = GETSTATUS;
                  break;
#ifndef NO_SETTIME
            case 'T':
                  mode = SETTIME;
                  break;
#endif
            case 'I':
                  mode = SETID;
                  idstring = optarg;
                  break;
            case '#':
                  mode = SETSERIALNO;
                  serialnostring = optarg;
                  break;
            case 'P':
                  mode = TAKEPICTURE;
                  break;

            default:
                  usage();
                  exit(1);
            }
      }
      argc -= optind;
      argv += optind;

      if (1 < argc) {
            fprintf(stderr, "invalid argument\n");
            usage();
            exit(1);
      } else if (argc == 0) {
            fprintf(stderr, "no device specified\n");
            usage();
            exit(1);
      }

      n0 = canondev(argv[0]);
      if (!n0) {
            fprintf(stderr, "inappropriate device specified, "
                  "or device permission error\n");
            exit(1);
      }

      if (uucplock(n0) < 0) {
            fprintf(stderr, "device %s in use\n", n0);
            exit(1);
      }

      daemonuid();
      fd0 = open(n0, O_RDWR|O_NDELAY);
      if (fd0 < 0) {
            perror("open");
            exit(1);
      }
      useruid();

      atexit(cleanup);

      mainloop();

      exit(0);
}

Generated by  Doxygen 1.6.0   Back to index