/******************************************************************************
 * $Id: read.c,v 1.4 2010/06/22 22:06:54 tw Exp $
 * read - Basic data read functions
 *
 * Copyright (C) 2008 Thomas Weidenfeller
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

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

#include <sys/select.h>
// #include <sys/time.h>
// #include <sys/types.h>
// #include <unistd.h>



#include "read.h"
#include "error.h"

int read_timeout = 2;	// can be changed via command line option

/*
 * Get the next byte under timeout supervision.
 * TODO: Use a buffer instead of reading data one by one.
 */
uint8_t
next(void) {
	uint8_t c;
	int r;

	struct timeval timeout = { read_timeout, 0 };
	fd_set readfds;
	FD_ZERO(&readfds);
	FD_SET(STDIN_FILENO, &readfds);

	r = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &timeout);
	if(r == -1) {
		die("Read error.");
	} else if(r) {
		// TODO: Read more than one byte into a buffer instead.
		r = read(STDIN_FILENO, &c, 1);
		if(r != 1) {
			die("Not enough input data (read error)");
		}
	} else {
		die("Not enough input data (timeout)");
	}

	return c;
}


/**
 * Read and evaluate the data header.
 */
int
read_header() {
	int	c;		// input byte
	int	i;		// loop counter
	int	size;		// size of data
	int 	size_size;	// size of size field in input

	//
	// Check for "magic" character: #
	//
	if((c = next()) != '#') {
		 die("Format error. Expected '#', got 0x%02X", c);
	}

	//
	// Get length of length field (an ASCII digit)
	//
	c = next();

	// 
	// The GDS-1000A will go up to a length-length of 7
	// so checking for 9 leaves some room 
	//
	if(c < '1' || c > '9') {
		 die("Format error. Expected length '1' ... '9', got 0x%02X", c);
	}
	size_size = c - '0';

	//
	// Get data length (an ASCII number)
	//
	size = 0;
	for(i = 0; i < size_size; i++) {
		c = next();
		if(c < '0' || c > '9') {
			 die("Format error. Expected digit '0' ... '9', got 0x%02X", c);
		}
		size = (size * 10) + c - '0';
	}
	
	return size;
}
