/**
 * This app note demonstrates how to implement a configuration and/or
 * firmware update via wired upload.
 *
 * @attention error handling is oversimplified in this code by exiting on
 * failure without releasing resources. This is not recommended in production
 * software!
 */


#include <stdio.h>
#include <stdint.h>
#include <baltech_sdk.h>


/**
 * If condition is TRUE, the process is stopped immediately and an error is
 * displayed.
 *
 * @attention For simplicity and readabilty this app note relies on the OS
 * to release resources when exit_if() stops due to failure.
 * In production code this is bad practice and should be done explicitly
 * instead!
 */
static void exit_if(bool condition, char *errormessage)
{
	if (condition)
	{
		fprintf(stderr, "\n%s\n", errormessage);
		exit(EXIT_FAILURE);
	}
}


/**
 * Check if an error has occurred. If yes, stop process immediately and show
 * an error message.
 *
 * @attention For simplicity and readabilty this app note relies on the OS
 * to release resources when exit_if() stops due to failure.
 * In production code this is bad practice and should be done explicitly
 * instead!
 */
static void exit_on_error(brp_errcode errcode, char *errormessage)
{
	if (errcode != BRP_OK)
	{
		char * errname = brp_map_errcode(errcode);
		if (errname == NULL)
			fprintf(stderr, "\n%s [brp_errcode:%08X]\n", errormessage, errcode);
		else
			fprintf(stderr, "\n%s [%s]\n", errormessage, errname);
		exit(EXIT_FAILURE);
	}
}


static void show_progress(
	unsigned transferred_bytes,
	unsigned estimated_total,
	unsigned progress_percent,
	unsigned estimated_time_overhead,
	bool reconnecting)
{
	(void)estimated_time_overhead;
	(void)reconnecting;
	printf("Transferred %u Bytes (%u%%)\r", transferred_bytes, progress_percent);
}


void show_reader_info(brp_protocol dev)
{
	char * fws, *cfgid, *cfgname;
	brp_errcode errcode;

	errcode = brp_Sys_GetInfo((brp_Sys_GetInfo_t){dev, .Info=&fws});
	exit_on_error(errcode, "Failed to retrieve firmwarestring");
	printf("FIRMWARE: %s\n", fws);
}


int main(int argc, char *argv[])
{
	brp_errcode errcode;

	exit_if(argc < 2,
			"filename of BEC2/BF3 file needs to be passed via command line");

	brp_protocol dev = brp_create();
	brp_set_io(dev, brp_create_usb_hid(0));
	errcode = brp_open(dev);
	exit_on_error(errcode, "failed to connect to USB/HID reader");

	errcode = brp_update_reader(dev, argv[1], show_progress);
	exit_on_error(errcode, "Failed to update reader");
	printf("\n");

	show_reader_info(dev);

	brp_destroy(dev);

	return EXIT_SUCCESS;
}
