#include <stdio.h>
#include <unistd.h>

#include "orcd.h"
#include "orcutils.h"
#include "ioutils.h"

/** returns packet length, or <0 on error. **/
int readPacket(orcd_t *orcd, int fd, void *bufin)
{
  unsigned char* buf=(unsigned char*) bufin;

  orcd=orcd; // silence warning.

 reset:             // try to read a new packet
  int len=0;

  while(true)
    {
      unsigned char cin;
      int res, c;

      // XXX HACK XXX YUCK. if it's the serialfd, use a timeout.
      if (orcd->serialfd == fd)
	res=readtimeout(fd, &cin, 1, 5000);
      else
	res=read(fd, &cin, 1);

      c=cin;

      if (res!=1)
	{
	  //	  perror("read !=1 char");
	  return -1;
	}

      if (c==EOF)
	return -1;

      // wait for synchronization byte (packet header)
      if (len==0 && c!=237)
	{
	  if (c!=238) // don't complain about event character
	    {
	      if (orcd->opt->getOptionBool("debug"))
		{
		  printf("(%02X)",c);
		  fflush(NULL);
		}
	    }
	  continue;
	}

      // add this byte to the buffer.
      buf[len++]=c;

      if (len<2)   // if we don't have the length byte yet, we can't do anything else.
	continue;

      if (len>ORC_MAX_PACKETSIZE) // is this packet ridiculously long?
	goto reset;

      if (len<buf[1]) // have we read in the whole packet?
	continue;

      unsigned char chk=checksum(buf, buf[1]-1);

      // check the checksum
      if (chk!=buf[len-1])
	{
	  if (orcd->opt->getOptionBool("debug"))
	  {
	    for (int i=0;i<len;i++)
	      printf("%02X ",buf[i]);
	    
	    printf("\nbad packet; len=%02X: checksum %02X!=%02X\n",len, chk,buf[len-1]);
	  }
	  goto reset;
	}
      buf[len-1]=chk;

      //      printf("[%i]",len);
      return len;
    }

  return 0;
}
