/* testlibusb.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/times.h>
#include <sys/time.h>
#include <usb.h>
#include "tiffio.h"


#define BUFLEN		(256*1024)
#define FLASHSIZE	(2*1024*1024)
int main(int argc, char *argv[])
{
	char *pBuf;
	int ret, i, xfer_cnt, filesize, size;
	char string[256];
	double start, end;
	struct timeval t;
	FILE *pFile;
	TIFF *pTif;
	ttag_t config, photometric;
	uint16 nSamples, nBits;
	uint32 width, height;
	uint32* raster;

	typedef struct _scmd_t
	{
		unsigned sync;
		unsigned code;
		unsigned len;
	} cmd_t;

	cmd_t cmd_read = {0xC24755AA, 2, BUFLEN};
	cmd_t cmd_write = {0xC24755AA, 1, BUFLEN};
	cmd_t cmd_flash_read = {0xC24755AA, 3, FLASHSIZE};
	cmd_t cmd_flash_write = {0xC24755AA, 4, FLASHSIZE};

	libusb_context *pCtx;
   	libusb_device_handle *handle;
	size_t cnt;

	ret = libusb_init(&pCtx);
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}

	libusb_set_debug(pCtx, 3);

	handle = libusb_open_device_with_vid_pid (pCtx, 0x04B4, 0x7200);
	if (!handle)
	{
		printf("Error on opening device\n");
		return 1;
	}

	pBuf = (char*)malloc(BUFLEN);
	memset(pBuf, 0, BUFLEN);

	// ------------------------------------------------------
	printf("Send command\n");
	// ------------------------------------------------------
	ret = libusb_bulk_transfer (handle, 0x01, (char*)&cmd_write, sizeof(cmd_t), &xfer_cnt, 5000);
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}
	gettimeofday(&t, NULL);
	start = t.tv_sec + 1E-6*t.tv_usec;
	ret = libusb_bulk_transfer(handle, 0x01, (char*)pBuf, cmd_write.len, &xfer_cnt, 5000);
	size = xfer_cnt;
	gettimeofday(&t, NULL);
	end = t.tv_sec + 1E-6*t.tv_usec;
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}
	printf("Sent %d bytes\n", size);
	printf("Data rate: %.2f kbyte/s\n", (double)size/(1024*(end-start)));

	// ------------------------------------------------------
	printf("Read command\n");
	// ------------------------------------------------------
	ret = libusb_bulk_transfer(handle, 0x01, (char*)&cmd_read, sizeof(cmd_t), &xfer_cnt, 5000);
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}
	gettimeofday(&t, NULL);
	start = t.tv_sec + 1E-6*t.tv_usec;
	ret = libusb_bulk_transfer(handle, 0x82, (char*)pBuf, cmd_read.len, &xfer_cnt, 5000);
	size = xfer_cnt;
	gettimeofday(&t, NULL);
	end = t.tv_sec + 1E-6*t.tv_usec;
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}
	printf("Received %d bytes\n", size);
	printf("Data rate: %.2f kbyte/s\n", (double)size/(1024*(end-start)));
	free(pBuf);

	// ------------------------------------------------------
	printf("Read Flash\n");
	// ------------------------------------------------------
	pBuf = (char*)malloc(FLASHSIZE);
	memset(pBuf, 0, FLASHSIZE);
	ret = libusb_bulk_transfer(handle, 0x01, (char*)&cmd_flash_read, sizeof(cmd_t), &xfer_cnt, 5000);
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}

	gettimeofday(&t, NULL);
	start = t.tv_sec + 1E-6*t.tv_usec;
	ret = libusb_bulk_transfer(handle, 0x82, (char*)pBuf, cmd_flash_read.len, &xfer_cnt, 500000);
	size = xfer_cnt;
	gettimeofday(&t, NULL);
	end = t.tv_sec + 1E-6*t.tv_usec;
	if (ret != LIBUSB_SUCCESS)
	{
		printf("Error %08X\n", ret);
		return 1;
	}
	printf("Received %d bytes\n", size);
	printf("Data rate: %.2f kbyte/s\n", (double)size/(1024*(end-start)));

	pFile = fopen("./flash.bin", "wb");
	fwrite(pBuf, 1, size, pFile);
	fclose(pFile);
	free(pBuf);

	if (argc > 1)
	{
		// ------------------------------------------------------
		printf("Write Flash (File = %s)\n", argv[1]);
		// ------------------------------------------------------
		pTif = TIFFOpen(argv[1],"r");
		if (!pTif)
		{
			printf("Unable to open TIFF-file!\n");
			return 1;
		}
		ret = TIFFGetField(pTif, TIFFTAG_IMAGEWIDTH, &width);
		ret = TIFFGetField(pTif, TIFFTAG_IMAGELENGTH, &height);

		printf("TIFFTAG_IMAGEWIDTH      = %d\n", width);
		printf("TIFFTAG_IMAGELENGTH     = %d\n", height);

		filesize = width * height * sizeof (uint32);

		raster = (uint32*) _TIFFmalloc(filesize);
		if (raster != NULL)
		{
			ret = TIFFReadRGBAImageOriented(pTif, width, height, raster, ORIENTATION_TOPLEFT, 0);
			if (!ret)
			{
				printf("Unable to reading TIFF-file!\n");
				return 1;
			}
		}
		TIFFClose(pTif);

		printf ("File size = %d\n", filesize);
		if (filesize > FLASHSIZE)
		{
			printf("Cannot write flash: image to large!\n");
			return 1;
		}

		cmd_flash_write.len = filesize;
		ret = libusb_bulk_transfer(handle, 0x01, (char*)&cmd_flash_write, sizeof(cmd_t), &xfer_cnt, 5000);
		if (ret != LIBUSB_SUCCESS)
		{
			printf("Error %08X\n", ret);
			return 1;
		}

		gettimeofday(&t, NULL);
		start = t.tv_sec + 1E-6*t.tv_usec;
		size = 0;
		ret = libusb_bulk_transfer(handle, 0x01, (char*)raster, filesize, &xfer_cnt, 500000);
		if (ret != LIBUSB_SUCCESS)
		{
			printf("Error %08X\n", ret);
			return 1;
		}
		size += xfer_cnt;
		gettimeofday(&t, NULL);
		end = t.tv_sec + 1E-6*t.tv_usec;
		printf("Sent %d bytes\n", size);
		printf("Data rate: %.2f kbyte/s\n", (double)size/(1024*(end-start)));

		_TIFFfree(raster);

	}

	libusb_close(handle);
	libusb_exit(pCtx);
	return 0;

}
