/**
 *	@file   liboasis-usb-att.c
 * 	@brief  Library file for the msatt driver
 * 	@author Tomasz Włostowski
 *	@date	October 17th 2018
 */


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include "liboasis-usb-att.h"
#include "liboasis-usb-att-i.h"
#include <ftdi.h>

static void eeprom_backup(unsigned char *eeprom_raw, int sz)
{
	static char fname[64];
	FILE *f;

	snprintf(fname, sizeof(fname),
		"/tmp/eeprom_dump-%d.bin", time());	/* FIXME: use timestamp/serial */
	if ((f = fopen(fname, "wb")) != NULL) {
		fwrite(eeprom_raw, sz, 1, f);
		fclose(f);
	}
}

int oau_factory_program_eeprom(unsigned int bus, unsigned int dev, char *serial)
{
	int i;
	int ret;
	int b, d;
	char devbus[16];
	static uint8_t eeprom_raw[128];
	static char ser[64];
	char *ptr;
	struct ftdi_context *ctx;
	long s;
	
	if ((ctx = ftdi_new()) == NULL) {
		fprintf(stderr, "cannot init libftdi, exiting\n");
		return -ENOMEM;
	}

	snprintf(devbus, sizeof(devbus), "d:%03d/%03d", bus, dev);
	ret = ftdi_usb_open_string(ctx, devbus);
	if (ret != 0) {
		fprintf(stderr, "cannot open usb device %s\n", devbus);
		return -EINVAL;
	}
	b = libusb_get_bus_number(ctx->usb_dev);
	d = libusb_get_port_number(ctx->usb_dev);

	ret = ftdi_read_eeprom(ctx);
	if (ret != 0) {
		fprintf(stderr, "could not read eeprom of %03x:%03x\n", b, d);
		return -ENOENT;
	}
	ret = ftdi_eeprom_decode(ctx, 1);
	if (ret != 0) {
		fprintf(stderr, "error %d decoding eeprom of %03x:%03x\n", b, d);
		return -ENOENT;
	}
	ret = ftdi_get_eeprom_buf(ctx, eeprom_raw, sizeof(eeprom_raw));
	if (ret != 0) {
		fprintf(stderr, "could not read raw eeprom of %03x:%03x\n", b, d);
		return -EINVAL;
	}
	eeprom_backup(eeprom_raw, sizeof(eeprom_raw));

	s = strtol(serial, &ptr, 10);
	if (*ptr != 0 || *serial == 0) {
		fprintf(stderr, "invalid serial %s\n", serial);
		return -EINVAL;
	}
	snprintf(ser, sizeof(ser), "HCCAIAD000-CR%06d", s);
	ftdi_eeprom_set_strings(ctx, OAU_MANUFACTURER, OAU_PRODUCT, ser);
	ftdi_set_eeprom_value(ctx, VENDOR_ID, OAU_VENDOR_ID);
	ftdi_set_eeprom_value(ctx, PRODUCT_ID, OAU_DEVICE_ID);
	ret = ftdi_eeprom_build(ctx);
	ret = ftdi_eeprom_decode(ctx, 1);
	printf("ftdi_eeprom_build returned %d\n", ret);
	if (1) {
	    ret = ftdi_write_eeprom(ctx);
	    printf("ftdi_write_eeprom returned %d\n", ret);
	    //ret = usbdev_reset(bus, dev);
	    ret = libusb_reset_device(ctx->usb_dev);
	}
	ftdi_free(ctx);

	return 0;
}

int main(int argc, char *argv[])
{
	int ret;
	unsigned int bus, dev;
	char serial[3] = { 'F', 'F', 0 };

	if (argc != 4) {
		fprintf(stderr, "usage: %s bus dev serialno\n", argv[0]);
		exit(1);
	}
	bus = strtol(argv[1], NULL, 0);
	dev = strtol(argv[2], NULL, 0);
	strncpy(serial, argv[3], sizeof(serial));

	ret = oau_factory_program_eeprom(bus, dev, serial);
	return ret;
}
