// -*-c++-*-
/**********************************************************************
 *     EPSCAN, an EPSON ES-1200 scanner driver     
 *     Adam P. Jenkins <ajenkins@cs.umass.edu>
 *     
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License
 *     as published by the Free Software Foundation; either version 2
 *     of the License, or (at your option) any later version.
 *     
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *     
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **********************************************************************/

// -*-c++-*-
// Adam P. Jenkins <ajenkins@cs.umass.edu>
// 
// This is a virtual class, meant to be the interface by which a
// scanner driver reads from and writes to the scanner.  The EPSON
// scanners have both a parallel and a SCSI interface, so this is
// intended to be a front end to either interface.
//
// The functions initialize, send, sendf, and receive, must be defined
// by the derived class.  The constructor, and setBufSize
// are the only non-virtual functions.  This class provides buffers
// for reading and writing data as protected members, and provides the
// member function setBufSize to set the read buffersize.

#ifndef _IODEVICE_H_
#define _IODEVICE_H_

#include <sys/types.h>		// for u_char
#include <stdlib.h>
#include <stdio.h>

#include "debug.h"

class IODevice {
 public:
   IODevice(void);
   virtual ~IODevice(void);

   // Initialize the device
   virtual int open(const char *device)=0;
   // close the device
   virtual int close(void)=0;
   // initialize device
   virtual int initialize(void)=0;
   
   // send len bytes in src to device
   virtual int send(const u_char *src, const int len)=0;
   // printf style version of send
   virtual int sendf(const char *format, ...)=0;
   // read len bytes of data from device
   virtual int receive(const int len)=0;
   // read len bytes of data from device, and store in buf
   virtual int receive(const int len, u_char *buf)=0;
   // return pointer to receiveBuf
   virtual const u_char *getRbuf(void)=0;
   
   // pre-set receive buffersize to n bytes. This can be called even
   // if buffer is already set; it calls realloc on it. 
   int setBufSize(const int n);
   
   virtual const char *strError(void) const=0;

 protected:
   u_char *receiveBuf;		// Buffer used for receiving data

 private:
   int receiveBufSize;		// current size of receiveBuf
};

inline
IODevice::IODevice(void)
{
   dprintf("Constructed\n");
   receiveBuf = NULL;
   receiveBufSize = 0;
}

inline
IODevice::~IODevice(void)
{
   dprintf("destroyed!!\n");
   if (receiveBuf)
     free(receiveBuf);
}

// Function: IODevice::setBufSize
// Parameters: 
//   const int n - Size to expand buffer to
//   
// Description: Sets the read-buffer's size to n bytes.  If the
// buffer's size is already greater than n, the size won't be reduced,
// but if it is smaller than n, it will be increased to n with realloc().
// 
// Return value: Returns 0 on succes, -1 on failure.
inline int
IODevice::setBufSize(const int n)
{
   dprintf("called with n = %d\n", n);
   if (n > receiveBufSize)
   {
      u_char *tmp = (u_char *) realloc(receiveBuf, n);
      if (!tmp)
      {
	 perror(__PRETTY_FUNCTION__);
	 return -1;
      }
      else
      {
	 receiveBuf = tmp;
	 receiveBufSize = n;
	 return 0;
      }
   }
   else
     return 0;
}

#endif // _IODEVICE_H_
