// 31.12.98 - beim abschluss wird die Schnittstelle wieder auf 19200 gesetzt
// 01.01.99 - function camediaSetDateToFile
// 07.11.99 - delete image funktionen

//#define CAM_DEBUG 1 
//#define CAM_VERBOSE 1
//#define CAM_SIMULATE 1


#include <termios.h>
#include <sys/types.h>
#if HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/fcntl.h>
#include <sys/param.h>
#include <curses.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <utime.h>

#include "camreal.h"
#include "camera_def.h"
#include "jpeg_datei.h"


#define	CAM_SETNUM	0x00
#define	CAM_GETNUM	0x01
#define	CAM_NUM_QUALITY		0x01
#define	CAM_NUM_DATE		0x02
#define	CAM_NUM_SHUTSPEED	0x03
#define	CAM_NUM_PTR		0x04
#define	CAM_NUM_FLASH		0x07
#define	CAM_NUM_NPICTS		0x0a
#define	CAM_NUM_NREMAIN		0x0b
#define	CAM_NUM_PICTSIZE	0x0c
#define	CAM_NUM_THUMBSIZE	0x0d
#define	CAM_NUM_BATTERY		0x10
#define	CAM_NUM_POWEROFF1	0x17
#define	CAM_NUM_POWEROFF2	0x18
#define	CAM_NUM_MEMORY		0x1c
#define	CAM_NUM_LENS		0x21
#define	CAM_NUM_POWEROFF3	0x26
#define	CAM_NUM_BRIGHT		0x29
#define	CAM_CONTROL	        0x02
#define	CAM_CTL_SHUTTER		0x02
#define CAM_SETSTR	        0x03
#define	CAM_GETSTR	        0x04
#define	CAM_STR_PICT		0x0e
#define	CAM_STR_THUMB		0x0f
#define	CAM_STR_MODELID		0x16
#define	CAM_STR_SERIALNO	0x19
#define	CAM_STR_VERSION		0x1a
#define	CAM_STR_MODELTYPE	0x1b

#define	SMALLWAIT	200*1000	/*usec*/
#define	LARGEWAIT	1000*1000	/* 1 sekunde*/



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



//==========================================================================

speed_t CameraRealClass::baudconv(int baud)
{
   speed_t returnSpeed;

   returnSpeed = (speed_t) baud;
   switch (baud) 
   {
       case 9600:
          returnSpeed=B9600;
          break;
       case 19200:
          returnSpeed=B19200;
          break;
       case 38400:
          returnSpeed=B38400;
          break;
          

	/* non POSIX values */
#ifdef B57600
       case 57600:
          returnSpeed=B57600;
          break;
#endif
#ifdef B115200
       case 115200:
          returnSpeed=B115200;
          break;
#endif
#ifdef B230400
       case 230400:
          returnSpeed=B230400;
          break;
#endif

	default:
          // 19200 ist der default 
          returnSpeed=B19200;
          break;
   }
#ifdef CAM_VERBOSE
   fprintf(stderr,"Baudconv %d = %d\n",baud,returnSpeed);
#endif
   return returnSpeed;
} // CameraRealClass::baudconv


//==========================================================================


int CameraRealClass::setbaud(int fd, int baud)
{
   /* termios */
   struct termios tio;

   if (tcgetattr(fd, &tio) < 0)
   {
      return RC_BAUD_SET;
   }
   
   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) 
   {
      return RC_BAUD_SET;
   }
#ifdef CAM_VERBOSE
   fprintf(stderr,"set baud to %d\n",baud);
#endif

   return RC_OK;
} // CameraRealClass::setbaud


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


void CameraRealClass::dump_stream(int dir, char *buf, int len)
{
   int i;
   int truncate;

   if(verbose==0)
      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");
}



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


int CameraRealClass::camedia_init()
{
   // buffer auf 0 setzen
   camedia_len = 0;
   return RC_OK;
}


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

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

   while (camedia_len < rlen) 
   {
      // zeichen von der camera lesen
      
      // den descriptor set loeschen
      FD_ZERO(&rdfd);
      
      // den device descriptor von serial eintragen
      FD_SET(fd0, &rdfd);
      
      maxfd = fd0;
      // timeout: 2sec 
      t.tv_sec = 2;
      t.tv_usec = 0;
      switch (select(maxfd + 1, &rdfd, NULL, NULL, &t)) 
      {
         case -1:
            if (errno == EINTR)
               break;
            return RC_SELECT;
         case 0:
            dprintf((stderr, "read timeout.\n"));
            return RC_TIMEOUT;
         default:
            break;
      }

      // wenn von meinem descriptor was da ist
      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 RC_CAMERA_GET;
      }
   }
   dump_stream('>', camedia_buf, camedia_len);

   return RC_OK;
}


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

int CameraRealClass::camedia_get(char *buf, int len)
{
   int rc;

   rc = camedia_wait(len);
   if(rc != RC_OK)
   {
      dprintf((stderr, "timeouted in camedia_get\n"));
      return rc; 
   }

   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 RC_OK;
}


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

int CameraRealClass::camedia_put(char * buf, int len)
{
   int wlen;
   int i;

   for (i = 0; i < len; i++) 
   {
      wlen = write(fd0, &buf[i], 1);
      if (wlen != 1) 
      {
         dprintf((stderr, "failed in camedia_put\n"));
         return RC_CAMERA_PUT;
      }
      usleep(20*1000);
      tcdrain(fd0);
   }

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

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

int CameraRealClass::camedia_attention()
{
   char buf[10];
   int  timeout;

   camedia_put("\0", 1);
   timeout = 0;
   do 
   {
      camedia_get(buf, 1);
   } while (   buf[0] != 0x15 
            && timeout++ < 4);
   if (timeout)
      return RC_TIMEOUT;

   return RC_OK;
}



//==========================================================================


int CameraRealClass::camedia_getack()
{
   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 RC_GETACK;
   }
   return RC_OK;
}

//==========================================================================


int CameraRealClass::camedia_getDone()
{
   char buf[10];

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



//==========================================================================


int CameraRealClass::camedia_checkDevice()
{
   char empfangBuffer[10];
   int  returnCode;
   int  timeout;

   returnCode = camedia_put("\0", 1);
   if(returnCode != RC_OK)
      return returnCode;

   // warten auf antwort von der camedia

   timeout =0;
   do 
   {
      usleep(100*1000);
      returnCode= camedia_get(empfangBuffer, 1);
   } while (   returnCode != RC_OK 
            && timeout++ < 4);

   if(returnCode == RC_TIMEOUT)
      return RC_TIMEOUT;

   if(empfangBuffer[0] != 0x15 )
      return RC_WRONG_ID;

   return RC_OK;
}

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

int CameraRealClass::camedia_sendcmd(int ch, char *buf, int len)
{
   u_short sum;
   char    tbuf[2];
   int     i;
   int     error = RC_OK;

   usleep(SMALLWAIT);	

   // fuer checksumme
   sum = 0;
   for (i = 0; i < len; i++) 
   {
      sum += (buf[i] & 0xff);
   }

   tbuf[0] = '\033';
   tbuf[1] = ch & 0xff;
   error = camedia_put(tbuf, 2);
   if(error != RC_OK)
      return error;

   tbuf[0] = len & 0x00ff;
   tbuf[1] = (len & 0xff00) >> 8;
   error += camedia_put(tbuf, 2);
   if(error != RC_OK)
      return error;

   error += camedia_put(buf, len);
   if(error != RC_OK)
      return error;

   tbuf[0] = sum & 0x00ff;
   tbuf[1] = (sum & 0xff00) >> 8;
   error += camedia_put(tbuf, 2);
   if(error != RC_OK)
      return error;

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getpacket(char *buf, 
                                       int *plen, 
                                       int *pfinal, 
                                       int *ack, 
                                       int *sector)
{
   u_short len;
   u_short cksum;
   u_char  tbuf[2];
   size_t  i;
   int     error=RC_OK;


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

   /* get the packet type. */
   error= camedia_get((char *)tbuf, 1);
   if(error != RC_OK)
   {
      dprintf((stderr, "err in camedia_getpacket: getting type\n"));
      return error;
   }

   if (tbuf[0] == 0x06) 
   {
      dprintf((stderr, "got ACK\n"));
      *ack = 1;
      return RC_OK;
   } 
   else if (tbuf[0] != 0x02 && tbuf[0] != 0x03) 
   {
      dprintf((stderr, "illegal packet received\n"));
      return RC_ILLEGAL_PACKET;
   }

   error=camedia_get((char *)tbuf + 1, 1);
   if (error != RC_OK) 
   {
     dprintf((stderr, "err in camedia_getpacket: getting type\n"));
     return error;
   }

   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]));
         return RC_CAMERA_GETPACKET;
   } // switch 

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

   // get the packet content.
   if (camedia_get(buf, len) != RC_OK) 
   {
      dprintf((stderr, "err in camedia_getpacket: body\n"));
      return RC_PACKET_BODY;
   }

   /* check for checksum. */
   if (camedia_get((char *)tbuf, 2) != RC_OK) 
   {
      dprintf((stderr,
			"err in camedia_getpacket: getting checksum\n"));
      return RC_CHECKSUM;
   }

   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"));
   }

   /* XXX must check for retransmit */
   camedia_put("\006", 1);	/*ACK*/

   *plen = len;

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getint(int cmd, int *n)
{
   char buf[1024];
   int  len;
   int  final;
   int  ack;
   int  error=0;

   cmd    &= 0xff;
   buf[0]  = CAM_GETNUM;
   buf[1]  = cmd;

   error = camedia_sendcmd('C', buf, 2);
   if ( error != RC_OK) 
   {
      dprintf((stderr, "sendcmd err in camedia_getint(%02x %02x)\n",
			CAM_GETNUM, cmd));
      return error;
   }

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

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

//========================================================================

int CameraRealClass::camedia_setint(int cmd, int n)
{
   char buf[1024];
   int  len;
   int  final;
   int  ack;
   int  error = 0;


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

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getstr(int cmd, char *buf, int *plen)
{
   char tbuf[10];
   int  final;
   int  ack;
   int  error = 0;


   cmd &= 0xff;
   tbuf[0] = CAM_GETSTR;
   tbuf[1] = cmd;

   error = camedia_sendcmd('C', tbuf, 2);
   
   if (error != RC_OK) 
   {
      dprintf((stderr, "sendcmd err in camedia_getstr(%02x %02x)\n",
			CAM_GETSTR, cmd));
      return error;
   }

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

   return RC_OK;
}


//==========================================================================


int CameraRealClass::camedia_setspeed(int baud)
{
   char buf[10];
   char value;
   int  error = 0;
   int  returnValue,maxTry;


   usleep(SMALLWAIT);

   maxTry =3;
   returnValue = camedia_attention();
   while (   returnValue != RC_OK
          && maxTry >= 0        ) 
   {
      dprintf((stderr, "ATTN err in camedia_setspeed\n"));
      usleep(SMALLWAIT);
      maxTry -= 1;
      returnValue = camedia_attention();
   }

   if(returnValue != RC_OK)
      return returnValue;

   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 RC_UNSUPPORTED_BAUD;
   }

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

   error = camedia_getack();
   if (error != RC_OK) 
   {
      dprintf((stderr, "ACK err in camedia_setspeed\n"));
      return error;
   }

   usleep(20*1000);


   if (baud == -1)
      error = setbaud(fd0, 19200);
   else
      error = setbaud(fd0, baud);
   if(error != RC_OK)
      return error;

   usleep(1000*1000);

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_checkcamera()
{
   int error =0;

   error = camedia_attention();
   if (error != RC_OK) 
   {
      dprintf((stderr, "ATTN err in camedia_checkcamera\n"));
      return error;
   }

   error = camedia_setspeed(-1);
   if (error != RC_OK) 
   {
      dprintf((stderr, "err in camedia_checkcamera\n"));
      return error;
   }

   error = camedia_setspeed(baudrateflag);
   if (error != RC_OK) 
   {
      dprintf((stderr, "err in camedia_checkcamera\n"));
      return error;
   }

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getnpicts(int *n)
{
   int error =0;

   *n = -1;

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

   /* get picture # */
   error = camedia_getint(CAM_NUM_NPICTS, n);
   if (error != RC_OK) 
   {
      dprintf((stderr, "getint err in camedia_getnpicts\n"));
      return error;
   }
   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getnpictremain(int *n)
{
   int error = RC_OK;

   *n = -1;

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

   /* get picture # */
   error = camedia_getint(CAM_NUM_NREMAIN, n);
   if (error != RC_OK) 
   {
      dprintf((stderr, "getint err in camedia_getnpicts\n"));
      return RC_GETNPICTS;
   }

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getpict(int n, int thumbnail, int fd)
{
   char buf[1024 * 4];
   bool abbruch = FALSE;
   int  len;
   int  final;
   int  ack;
   int  sector;
   int  error=0;
   int  totallen;
   int  theFinalLength;
   int  cmd;
   


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

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

   /* get the size */
   if (!thumbnail)
      cmd = CAM_NUM_PICTSIZE;
   else
      cmd = CAM_NUM_THUMBSIZE;

   error =camedia_getint(cmd, &totallen);
   if (error != RC_OK) 
   {
      dprintf((stderr, "getint err in camedia_getnpicts\n"));
      return error;
   }
   else
   {
      if(verbose)
         fprintf(stderr, "size will be %d\n", totallen);
   }

   theFinalLength = totallen;
   
   //   start transfer
   if(!thumbnail)
      memcpy(buf, "\004\016", 2);
   else
      memcpy(buf, "\004\017", 2);

   error = camedia_sendcmd('C', buf, 2);
   if (error != RC_OK) 
   {
      dprintf((stderr, "sendcmd err in camedia_getpict\n"));
      return error;
   }

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

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

         totallen += len;
         if(ProgressCB != NULL)
         {
             abbruch= (ProgressCB)(ProgressData,
                                   ((float)totallen)/((float)theFinalLength));
         }
         else
         {
            abbruch = FALSE;
         }
      }
   }
   if(abbruch)
      return RC_ABORT;
   if (verbose) 
   {
      fprintf(stderr,
               "got sector %3d: %d bytes ...done%s\n",
               sector, totallen, error ? " with error" : "");
   }

   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getstatus()
{
   char buf[1024 * 4];
   char *t;
   int  len;
   int  error=0;
   int  n;


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

   /* get camera id */
   error=camedia_getstr(CAM_STR_MODELID, buf, &len);
   if (error!= RC_OK) 
   {
      dprintf((stderr, "can't get camera id\n"));
      return RC_GET_ID;
   } 
   else
   {
      if(verbose)
         fprintf(stderr, "camera id: %s\n", buf);
   }

   /* get camera type */
   error = camedia_getstr(CAM_STR_MODELTYPE, buf, &len);
   if (error != RC_OK) 
   {
      dprintf((stderr, "can't get camera type\n"));
      return RC_GET_MODEL;
   } 
   else
   {
      if(verbose)
         fprintf(stderr, "camera type: %s\n", buf);
   }

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

   /* get flash mode */
   error = camedia_getint(CAM_NUM_FLASH, &n);
   if (error != RC_OK ) 
   {
      dprintf((stderr, "can't get flash mode\n"));
      return RC_GET_FLASH;
      
   } 
   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;
      }
      if(verbose)
         fprintf(stderr, "flash mode: %s\n", t);
   }

   // get quality mode 
   error = camedia_getint(CAM_NUM_QUALITY, &n);
   if (error != RC_OK) 
   {
      dprintf((stderr, "can't get quality mode\n"));
      return RC_GET_QUALITY;
   } 
   else 
   {
      switch (n) 
      {
         case 1:
            t = "normal"; 
            break;
         case 2:
            t = "HQ"; 
            break;
         default:
            t = "???"; 
            break;
      } // switch
   if(verbose)
      fprintf(stderr, "quality mode: %s\n", t);
   }


   return RC_OK;
}

//========================================================================

int CameraRealClass::camedia_getoptions(int OptionMask,
                                        CameraRealOptionGetClass &Optionen)
{
   int error=0;
   int laenge;

#ifdef ALT

   int i,wert;
   char string[255];
   error=camedia_getstr(22, string, &laenge);
   fprintf(stderr,"%d <%s>\n",22,string);   
   error=camedia_getstr(25, string, &laenge);
   fprintf(stderr,"%d <%s>\n",25,string);   
   error=camedia_getstr(26, string, &laenge);
   fprintf(stderr,"%d <%s>\n",26,string);   
   error=camedia_getstr(27, string, &laenge);
   fprintf(stderr,"%d <%s>\n",27,string);   
   error=camedia_getstr(48, string, &laenge);
   fprintf(stderr,"%d <%s>\n",48,string);   
   for(i=23;i<42;i++)
   {
      /* get battery capacity - should check for battery shortage */
      error = camedia_getint(i, &wert);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "error in %d\n",i));
      }
      else
      {
         if(verbose)
            fprintf(stderr, "%d: %d\n",i,wert );
         
      }
   }
return RC_OK;
#endif


   if(OptionMask & CameraOptionID)
   {
      error=camedia_getstr(CAM_STR_MODELID, Optionen.ID, &laenge);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get camera id\n"));
         return RC_GET_ID;
      } 
      else
      {
         Optionen.ID[laenge] = '\0';
         if(verbose)
            fprintf(stderr, "camera id: %s\n",Optionen.ID);
      }
    }

   if(OptionMask & CameraOptionType)
   {
      error=camedia_getstr(CAM_STR_MODELTYPE, Optionen.Type, &laenge);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get camera type\n"));
         return RC_GET_MODEL;
      } 
      else
      {
         Optionen.Type[laenge] = '\0';
         if(verbose)
            fprintf(stderr, "camera type: %s\n", Optionen.Type);
      }
    }
   if(OptionMask & CameraOptionSerial)
   {
      /* get battery capacity - should check for battery shortage */
      error = camedia_getstr(CAM_STR_SERIALNO, Optionen.Serial,&laenge);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get serial number\n"));
         return  RC_GETSERIAL;
      }
      else
      {
         Optionen.Serial[laenge] = '\0';
         if(verbose)
            fprintf(stderr, "serial: %s\n",Optionen.Serial );
         
      }
   }

   if(OptionMask & CameraOptionBattery)
   {
      /* get battery capacity - should check for battery shortage */
      error = camedia_getint(CAM_NUM_BATTERY, &Optionen.Battery);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get battery charge\n"));
         return  RC_GETBATTERY;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "battery: %d\n",Optionen.Battery );
         
      }
   }
   if(OptionMask & CameraOptionMemory)
   {
      /* get battery capacity - should check for battery shortage */
      error = camedia_getint(CAM_NUM_MEMORY, &Optionen.Memory);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get memory\n"));
         return  RC_GETMEMORY;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "memory: %d\n",Optionen.Memory );
         
      }
   }

   if(OptionMask & CameraOptionClock)
   {
      /* get date */
      int wert;
      error = camedia_getint(CAM_NUM_DATE, &wert);
      Optionen.Clock = (time_t) wert;
      if (error != RC_OK) 
      {
         dprintf((stderr, "can't get date\n"));
         return RC_GET_DATE;
      }
      else
      { 
         if(verbose)
            fprintf(stderr,"the date number is %x\n",wert);
      }
   }

   if(OptionMask & CameraOptionShutdownComputer)
   {
      /* get power off 1 */
      error = camedia_getint(CAM_NUM_POWEROFF1, &Optionen.ShutdownComputer);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get poweroff 1\n"));
         return  RC_GETPOWEROFF;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "shutdown compi: %d\n",Optionen.ShutdownComputer );
         
      }
   }

   if(OptionMask & CameraOptionShutdownLCD)
   {
      /* get power off 3 */
      error = camedia_getint(CAM_NUM_POWEROFF3, &Optionen.ShutdownLCD);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get poweroff 3\n"));
         return  RC_GETPOWEROFF;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "shutdown LCD: %d\n",Optionen.ShutdownLCD );
         
      }
   }

   if(OptionMask & CameraOptionShutdownCamera)
   {
      /* get power off 2 */
      error = camedia_getint(CAM_NUM_POWEROFF2, &Optionen.ShutdownCamera);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get poweroff 2\n"));
         return  RC_GETPOWEROFF;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "shutdown camera: %d\n",Optionen.ShutdownCamera );
         
      }
   }

   if(OptionMask & CameraOptionBrightness)
   {
      /* get power off 2 */
      error = camedia_getint(CAM_NUM_BRIGHT, &Optionen.Brightness);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get brightness\n"));
         return  RC_GETBRIGHTNESS;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "brightness: %d\n",Optionen.Brightness );
         
      }
   }

   if(OptionMask & CameraOptionQuality)
   {
      /* get quality settings */
      error = camedia_getint(CAM_NUM_QUALITY, &Optionen.Quality);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get quality\n"));
         return  RC_GET_QUALITY;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "quality mode: %d\n",Optionen.Quality );
         
      }
   }

   if(OptionMask & CameraOptionLens)
   {
      /* get lens settings */
      error = camedia_getint(CAM_NUM_LENS, &Optionen.Lens);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get lens mode\n"));
         return  RC_GET_LENS;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "lens mode: %d\n",Optionen.Lens );
         
      }
   }

   if(OptionMask & CameraOptionFlash)
   {
      /* get lens settings */
      error = camedia_getint(CAM_NUM_FLASH, &Optionen.Flash);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't get flash mode\n"));
         return  RC_GET_FLASH;
      }
      else
      {
         if(verbose)
            fprintf(stderr, "flash mode: %d\n",Optionen.Flash );
         
      }
   }
   

   return RC_OK;
} // CameraRealClass::camedia_getoptions

//========================================================================

int CameraRealClass::camedia_setoptions(int OptionMask,
                                        CameraRealOptionGetClass &Optionen)
{
   int error=0;

   if(OptionMask & CameraOptionShutdownComputer)
   {
      /* set power off 1 */
      error = camedia_setint(CAM_NUM_POWEROFF1, Optionen.ShutdownComputer);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set poweroff 1\n"));
         return  RC_SETPOWEROFF;
      }
   }

   if(OptionMask & CameraOptionShutdownLCD)
   {
      /* set power off 3 */
      error = camedia_setint(CAM_NUM_POWEROFF3, Optionen.ShutdownLCD);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set poweroff 3\n"));
         return  RC_SETPOWEROFF;
      }
   }

   if(OptionMask & CameraOptionShutdownCamera)
   {
      /* set power off 2 */
      error = camedia_setint(CAM_NUM_POWEROFF2, Optionen.ShutdownCamera);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set poweroff 2\n"));
         return  RC_SETPOWEROFF;
      }
   }

   if(OptionMask & CameraOptionBrightness)
   {
      /* set brightness */
      error = camedia_setint(CAM_NUM_BRIGHT, Optionen.Brightness);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set brightness\n"));
         return  RC_SETBRIGHTNESS;
      }
   }

   if(OptionMask & CameraOptionQuality)
   {
      /* set quality  */
      error = camedia_setint(CAM_NUM_QUALITY, Optionen.Quality);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set quality\n"));
         return  RC_SET_QUALITY;
      }
   }

   if(OptionMask & CameraOptionLens)
   {
      /* set lens  */
      error = camedia_setint(CAM_NUM_LENS, Optionen.Lens);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set lens mode\n"));
         return  RC_SET_LENS;
      }
   }
   if(OptionMask & CameraOptionFlash)
   {
      /* set flash */
      error = camedia_setint(CAM_NUM_FLASH, Optionen.Flash);
      if (error!= RC_OK) 
      {
         dprintf((stderr, "can't set flash mode\n"));
         return  RC_SET_FLASH;
      }
   }
   

   return RC_OK;

} // camedia_setoptions

//==========================================================================


int CameraRealClass::camediaGetDate(time_t *camediaZeit,bool set)
{
   int number;
   int error;
   
   if(camediaZeit ==NULL)
      return RC_GET_DATE;
   if(set ==TRUE)
   {
      number = (int) *camediaZeit;
      error = camedia_setint(CAM_NUM_DATE, number);
      if (error != RC_OK) 
      {
         dprintf((stderr, "can't set date\n"));
         return RC_SET_DATE;
      } 
   }

   *camediaZeit =0;
   
   /* get date */
   error = camedia_getint(CAM_NUM_DATE, &number);
   if (error != RC_OK) 
   {
      dprintf((stderr, "can't get date\n"));
      return RC_GET_DATE;
   } 
   *camediaZeit = (time_t) number;

   return RC_OK;
}

//==========================================================================

int CameraRealClass::camedia_setAutoTime()
{
   time_t aktuelleZeit;
   int    number;
   int    error;
   
   if(AutoSetTime ==FALSE)
      return RC_OK;
   
   aktuelleZeit = time(&aktuelleZeit);
   number =(int) aktuelleZeit;
   error = camedia_setint(CAM_NUM_DATE, number);
   if (error != RC_OK) 
   {
      dprintf((stderr, "can't set date\n"));
      return RC_SET_DATE;
   }

   AutoSetTime =FALSE;
   return RC_OK;
} // camedia_setAutoTime

//==========================================================================
int CameraRealClass::camedia_deleteAllImages()
{
   char buf[1024];
   int  error=0;

   buf[0] = 0x02;
   buf[1] = 0x01;
   buf[2] = 0x00;

   error = camedia_sendcmd('C', buf, 3);
   if ( error != RC_OK) 
   {
      dprintf((stderr, "sendcmd err in camedia_deleteAllImages\n"));
      return error;
   }
   error = camedia_getack();
   if (error != RC_OK) 
   {
      dprintf((stderr, "getpacket err in camedia_deleteAllImages\n"));
      return error;
   }
   usleep(SMALLWAIT);
   error = camedia_getDone();
   if (error != RC_OK) 
   {
      dprintf((stderr, "getdone err in camedia_deleteAllImages\n"));
      return error;
   }

   return RC_OK;
}

//==========================================================================

int CameraRealClass::camedia_deleteSingleImage(int imageNumber)
{
   char buf[1024];
   int  error=0;


   /* specify the picture # */
   error = camedia_setint(CAM_NUM_PTR, imageNumber);
   if (error != RC_OK) 
   {
      dprintf((stderr, "setint err in camedia_deleteSingleImage\n"));
      return error;
   }

   buf[0] = 0x02;
   buf[1] = 0x07;
   buf[2] = 0x00;

   error = camedia_sendcmd('C', buf, 3);
   if ( error != RC_OK) 
   {
      dprintf((stderr, "sendcmd err in camedia_deleteSingleImage\n"));
      return error;
   }
   error = camedia_getack();
   if (error != RC_OK) 
   {
      dprintf((stderr, "getpacket err in camedia_deleteSingleImage\n"));
      return error;
   }
   usleep(SMALLWAIT);
   error = camedia_getDone();
   if (error != RC_OK) 
   {
      dprintf((stderr, "getdone err in camedia_deleteSingleImage\n"));
      return error;
   }
   return RC_OK;
}

//==========================================================================

int CameraRealClass::camedia_pushShutter()
{
   char buf[1024];
   int  error=0;
   int  timeout =0;

   buf[0] = 0x02;
   buf[1] = 0x02;
   buf[2] = 0x00;

   error = camedia_sendcmd('C', buf, 3);
   if ( error != RC_OK) 
   {
      dprintf((stderr, "sendcmd err in camedia_pushShutter\n"));
      return error;
   }
   error = camedia_getack();
   if (error != RC_OK) 
   {
      dprintf((stderr, "ack err in camedia_pushShutter\n"));
      return error;
   }

   // now wait for the picture to be done
   timeout =0;
   do
   {
      usleep(LARGEWAIT);
      error = camedia_getDone();
      timeout ++;
   } while(timeout<15 && error != RC_OK);
   
   if (error != RC_OK) 
   {
      dprintf((stderr, "getdone err in camedia_pushShutter\n"));
      return error;
   }
   return RC_OK;
}  


//==========================================================================

int CameraRealClass::camediaSetDateToFile(char *filename)
{
   size_t gelesen;
   time_t number;
   size_t i;
   struct tm *lokalzeit;
   struct utimbuf timebuffer;
   char   readbuffer[10000];
   FILE   *infile;
#ifdef CAM_VERBOSE
   char  *zeitchar;
#endif

   infile = fopen(filename,"rb");
   
   if(infile ==NULL)
      return RC_DATEFILE;
   
   gelesen = fread(readbuffer,1,10000,infile);
   fclose(infile);      

   if(gelesen < 2000 )
      return RC_DATEFILE;

   for(i=0;i<(gelesen -50);i++)
   {
      if(readbuffer[i] != 'T')
         continue;
      if(strncmp(&readbuffer[i],"TimeDate=",9)==0)
      {
          int position ;
          position = i+9;
#ifdef CAM_VERBOSE
          fprintf(stderr,"Position =%d\n",position);
#endif
          number =0;
          sscanf( &readbuffer[position],"%ld",&number);     
          break;
      }
   }
   if(i >= (gelesen-50))
      return RC_DATEFILE;
#ifdef CAM_VERBOSE
   fprintf(stderr,"number = %ld\n",number);
   zeitchar = ctime( (time_t *)  (&number));
   fprintf(stderr,"datum = %s",zeitchar);
#endif
   /* einfacher check auf gültiges datum */
   lokalzeit =localtime(&number);
   if(lokalzeit->tm_year <96)
      return RC_DATEFILE;


   timebuffer.actime= (time_t) number;
   timebuffer.modtime= (time_t) number;
   utime(filename,&timebuffer); 
   return RC_OK;    
} // CameraRealClass::camediaSetDateToFile



//==========================================================================


int CameraRealClass::camediaOpenDevice(char *deviceName,int speed,int *fd)
{

   if(verbose)
      fprintf(stderr,"opening device %s\n",deviceName);

   *fd = open(deviceName, O_RDWR|O_NDELAY);

   if(*fd <0)
      return RC_ERROR;
     
   setbaud(*fd, 19200); // zuerst mal auf die default-baud setzen

   return RC_OK;
} // camediaOpenDevice


//==========================================================================

int CameraRealClass::camediaCloseDevice(int fd)
{

   camedia_setspeed(19200); // return to default speed
   close(fd);
     
   return RC_OK;
}

//==========================================================================


CameraRealClass::CameraRealClass(CameraApplicationClass * application)
{
   cameraApplication = application;

   baudrateflag = 19200;
   dumpmaxlen   = 20;
   openflag     = O_WRONLY | O_TRUNC | O_CREAT;
   
   verbose = 0;

   this->ProgressCB   = NULL;
   this->ProgressData = NULL;
   this->AutoSetTime  = FALSE;


#if defined( CAM_DEBUG) || defined(CAM_VERBOSE)
   verbose= 1;
#endif   
}

//==========================================================================



int CameraRealClass::GetNumberOfImages(int *numberOfImages)
{
   int returnCode;
#ifdef CAM_DEBUG
   *numberOfImages =15;
   return RC_OK;
#endif      
   *numberOfImages = 0;
   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }
   fd0 = deviceHandle;

   camedia_init();

   camedia_setspeed(cameraApplication->Geschwindigkeit);

   usleep(SMALLWAIT);
   camedia_setAutoTime();

   returnCode = camedia_getnpicts(numberOfImages);
   if(verbose)
   {
      fprintf(stderr,"returncode of camedia_getnpicts =%d\n",
           returnCode);
      fprintf(stderr,"numberOfImages of camedia_getnpicts =%d\n",
           *numberOfImages);
   }

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;
      
   return returnCode;
} // GetNumberOfImages
   


//==========================================================================


int CameraRealClass::LoadAllImages()
{
   return 0;
}


//==========================================================================


int CameraRealClass::LoadImage(int index,char *filename)
{

   int returnCode=RC_OK;
   int outfile;

   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }

   fd0 = deviceHandle;

   returnCode = camedia_init();
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   returnCode =camedia_setspeed(cameraApplication->Geschwindigkeit);
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   usleep(SMALLWAIT);
   camedia_setAutoTime();


   outfile = open(filename, openflag, 0644);
   if (outfile < 0) 
   {
      camediaCloseDevice(deviceHandle);
      return RC_NO_FILE;
   }
   
   // camera is base 1, so add 1 to the index 
   returnCode = camedia_getpict(index+1, 0, outfile);
   close(outfile);

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;

   // jetzt noch das datum des bildes setzen
   camediaSetDateToFile(filename);

   return returnCode;

} //CameraRealClass::LoadImage



//==========================================================================

//==========================================================================

int CameraRealClass::LoadThumbNail(int index, buffer2d ** image)
{
   JpegInfoType *jpegDatei;
  
   buffer2d     *bild;
   char         tempFileName[]="/tmp/MotifCamedia.jpg";
   int          breite=40,hoehe=50;
   int          x,y;
   int          returnCode;
   int          outfile;


   *image =NULL;
#ifdef CAM_DEBUG
   breite = 80;
   hoehe = 60;
      
   bild = new buffer2d(breite,hoehe);
   for(y=0;y<hoehe;y++)
   {
      for(x=0;x<breite;x++)
      {
         unsigned char r,g,b;
         r = x*3;
         g = y*3;
         b = 111;
         bild->set(x,y,r,g,b);
      }
   }
   *image=bild;
   return
#endif

   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return 0;
   }



   fd0 = deviceHandle;

   camedia_init();

   camedia_setspeed(cameraApplication->Geschwindigkeit);

   usleep(SMALLWAIT);
   camedia_setAutoTime();



   outfile = open(tempFileName, openflag, 0644);
   if (outfile < 0) 
   {
      camediaCloseDevice(deviceHandle);
      return RC_NO_FILE;
   }
   
   // camera is base 1, so add 1 to the index 
   camedia_getpict(index+1, 1, outfile);
   close(outfile);

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;

   // now read the image into an buffer
   
   jpegDatei = new JpegInfoType();
   
   jpegDatei-> JpegSetFilename(tempFileName);
   breite = jpegDatei->JpegGetBildBreite();
   hoehe = jpegDatei->JpegGetBildHoehe();
   bild = new buffer2d(breite,hoehe);
   for(y=0;y<hoehe;y++)
   {
      unsigned char *leseZeile;
      leseZeile = jpegDatei->JpegReadLine();
      for(x=0;x<breite;x++)
      {
         unsigned char r,g,b;
         r = (unsigned char) *leseZeile++;
         g = (unsigned char) *leseZeile++;
         b = (unsigned char) *leseZeile++;
         bild->set(x,y,r,g,b);
      }
   }
   delete jpegDatei;

   // delete the image
   
   remove( tempFileName);   
   *image=bild;
   return 0;

   
} // CameraRealClass::LoadThumbNail

   
//=============================================================================
// public function

int CameraRealClass::IsCameraDevice(char *deviceName)
{
   int returnCode;

#ifdef CAM_DEBUG
   fprintf(stderr,"opening device %s\n",deviceName);
#endif
   camedia_init();
   fd0 = open(deviceName, O_RDWR|O_NDELAY);


   if(fd0 <0)
   {
#ifdef CAM_DEBUG
      fprintf(stderr,"device nicht geoeffnet, errno = %d\n",errno);
#endif
      return RC_ILLEGAL_DEVICE;
   }
   else
   {
#ifdef CAM_DEBUG
      fprintf(stderr,"fd=%d geoeffnet\n",fd0);
#endif
      // device auf die default baudrate schalten
      setbaud(fd0, 19200); 

      deviceHandle =fd0;

      returnCode = camedia_checkDevice();
#ifdef CAM_DEBUG
      fprintf(stderr,"checkDevice = %d\n",returnCode);
#endif
      
      close(fd0);
   } // for i 

   return returnCode;

} // IsCameraDevice

//=============================================================================
// public function

void CameraRealClass::SetProgressCallback(CameraRealProgressCB ProgressCB,
                            void * ProgressData)
{
   this->ProgressCB   = ProgressCB;
   this->ProgressData = ProgressData;
}                            

//=============================================================================
// public function

int  CameraRealClass::GetOptions(int OptionMask,CameraRealOptionGetClass &Optionen)
{
   int returnCode;

#if CAM_SIMULATE
   strcpy(Optionen.ID,"Simulated Camera ID");
   strcpy(Optionen.Type,"Simulated Type");
   Optionen.Battery=65;
   Optionen.Memory=123456;
   Optionen.Clock=4455661;
   Optionen.ShutdownCamera=30;
   Optionen.ShutdownLCD=60;
   Optionen.ShutdownComputer=90;
   Optionen.Brightness=4;
   Optionen.Quality=2;
   Optionen.Lens=2;
   Optionen.Flash=0;
   return RC_OK;
#endif


   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }
   fd0 = deviceHandle;

   camedia_init();

   camedia_setspeed(cameraApplication->Geschwindigkeit);

   usleep(SMALLWAIT);
   camedia_setAutoTime();


   returnCode = camedia_getoptions(OptionMask,Optionen);
   if(verbose)
   {
      fprintf(stderr,"returncode of camedia_getoptions =%d\n",
           returnCode);
   }

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;
      
   return returnCode;
} // ::GetOptions

//=============================================================================
// public function

int  CameraRealClass::SetOptions(int OptionMask,CameraRealOptionGetClass &Optionen)
{
   int returnCode;

#if CAM_SIMULATE
   return RC_OK;
#endif


   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }
   fd0 = deviceHandle;

   camedia_init();

   camedia_setspeed(cameraApplication->Geschwindigkeit);

   usleep(SMALLWAIT);
   camedia_setAutoTime();


   returnCode = camedia_setoptions(OptionMask,Optionen);
   if(verbose)
   {
      fprintf(stderr,"returncode of camedia_setoptions =%d\n",
           returnCode);
   }

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;
      
   return returnCode;
} // ::SetOptions

//=============================================================================
// public function

int  CameraRealClass::GetTime(time_t *camediaZeit,bool Set)
{
   int returnCode;

#if CAM_SIMULATE
   *camediaZeit = (time_t) 1234567;
   return RC_OK;
#endif


   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }
   fd0 = deviceHandle;

   camedia_init();

   camedia_setspeed(cameraApplication->Geschwindigkeit);

   usleep(SMALLWAIT);


   returnCode = camediaGetDate(camediaZeit,Set);
   if(verbose)
   {
      fprintf(stderr,"returncode of camediaGetDate =%d\n",
           returnCode);
   }

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;
      
   return returnCode;
} // GetTime

//==========================================================================


int CameraRealClass::DeleteAllImages()
{

   int returnCode=RC_OK;

   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }

   fd0 = deviceHandle;

   returnCode = camedia_init();
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   returnCode =camedia_setspeed(cameraApplication->Geschwindigkeit);
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   // nun die bilder loeschen
   returnCode = camedia_deleteAllImages();
    

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;

   return returnCode;

} //CameraRealClass::LoadImage


//==========================================================================


int CameraRealClass::DeleteSingleImage(int images[], int anzahl)
{

   int returnCode=RC_OK;
   int i;

   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }

   fd0 = deviceHandle;

   returnCode = camedia_init();
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   returnCode =camedia_setspeed(cameraApplication->Geschwindigkeit);
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }


   // nun die bilder loeschen
   // dabei rückwaerts vorgehen
   for(i=anzahl-1; i>=0; i--)
   {
      if(verbose)
         fprintf(stderr,"loesche bild %d\n",images[i]);
   
     // camera is base 1, so add 1 to the index 
      returnCode = camedia_deleteSingleImage(images[i]+1);
      if(returnCode != RC_OK)
         break;
   }

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;

   return returnCode;

} //CameraRealClass::DeleteSingleImage



//==========================================================================


int CameraRealClass::MakeImage(char * filename)
{

   int returnCode=RC_OK;
   int numberOfImages,lastImage;
   int outfile;
   
   returnCode = camediaOpenDevice(cameraApplication->deviceName,
   		cameraApplication->Geschwindigkeit,
   		&deviceHandle);
  
   if(returnCode != RC_OK)
   {
      if(verbose)
         fprintf(stderr,"cmediaOpenDevice fehlgeschlagen!\n");
      // hier noch einen fehler setzen
      return returnCode;
   }

   fd0 = deviceHandle;

   returnCode = camedia_init();
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   returnCode =camedia_setspeed(cameraApplication->Geschwindigkeit);
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }
   // anzahl der bilder ermitteln
   // dann eine machen
   // erneute anzahl ermitteln
   // das letzte laden
   // das letzte wieder loeschen

   returnCode = camedia_getnpicts(&numberOfImages);
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;

   }
   returnCode = camedia_pushShutter();
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }

   returnCode = camedia_getnpicts(&lastImage);
   if(returnCode != RC_OK)
   {
      camediaCloseDevice(deviceHandle);
      return returnCode;
   }
   if(lastImage != (numberOfImages+1) )
   {
      camediaCloseDevice(deviceHandle);
      return RC_NO_IMAGE_TAKEN;
   }

   outfile = open(filename, openflag, 0644);
   if (outfile < 0) 
   {
      camediaCloseDevice(deviceHandle);
      return RC_NO_FILE;
   }
   
   // camera is base 1, so add 1 to the index 
   returnCode = camedia_getpict(lastImage, 0, outfile);
   close(outfile);


   returnCode = camedia_deleteSingleImage(lastImage);

   camediaCloseDevice(deviceHandle);
   deviceHandle = -1;

   return returnCode;

} //CameraRealClass::MakeImage



