/**********************************************************************
*
* Copyright (c) 2005 Endace Technology Ltd, Hamilton, New Zealand.
* All rights reserved.
*
* This source code is proprietary to Endace Technology Limited and no part
* of it may be redistributed, published or disclosed except as outlined in
* the written contract supplied with this product.
*
* $Id: dagswid.c 12679 2010-03-30 23:03:38Z wilson.zhu $
*
**********************************************************************/

/* Endace headers. */
#include "dagapi.h"
#include "dagutil.h"
#include "dagclarg.h"
#include "dagema.h"
#include "d37t_i2c.h"
#include "dag37t_api.h"
#include "dagswid.h"


#ifndef _WIN32
#define DEFAULT_DEVICE "/dev/dag0"     /* default device */
#else /* _WIN32 */
#define DEFAULT_DEVICE "dag0"  /* default device */
#endif /* _WIN32 */

static const char *const kCvsHeader __attribute__ ((unused)) = "$Id: dagswid.c 12679 2010-03-30 23:03:38Z wilson.zhu $";
static const char *const kRevisionString = "$Revision: 12679 $";

/* Command line configuration */
typedef struct
{
    int argc;
    char **argv;
    char *device;      /* Dag device */
    uint32_t key;      /* Write enable key */
    char *software_id; /* String to write to software ID */
    int start_xscale;  /* Reset and start xscale */
    int use_drb_comm;  /* dag3.7t communication mode: drb or socket */
} t_config;

t_config config;                /* Command line configuration */
int verbose = 0;                /* verbose output */

enum
{
	CLA_HELP,
	CLA_VERBOSE,
	CLA_VERSION,
	CLA_DEVICE,
	CLA_RESET,
	CLA_STRING,
	CLA_KEY
};

#define BUFSIZE 256
static char dagname_buf[DAGNAME_BUFSIZE] = "dag0";
static char dagname[DAGNAME_BUFSIZE] = "dag0";
static char string_buf[BUFSIZE];
static int dagstream;

/* Implementation of internal routines. */
static void
print_version(void)
{
	printf("dagswid(DAG %s) %s\n", kDagReleaseVersion, kRevisionString);
}

static void
print_usage(ClArgPtr clarg)
{
	print_version();
	printf("dagswid - Endace DAG3.7T Software ID and LM63 Temperature Sensor demo\n");
	printf("(c) 2005 Endace Technology Ltd.\n\n");
	printf("Usage: dagswid [options] \n");
	dagclarg_display_usage(clarg, stdout);
}


/**********************************************************************
* FUNCTION:     hg_scanInputs(config, argc, argv)
* DESCRIPTION:  Read the command line options and fill in the config info.
* INPUTS:       config - pointer to the configuration info to fill in
*               argc   - number of command line tokens
*               argv   - command line token array
* OUTPUTS:      config populated with command line options
* RETURNS:      none
**********************************************************************/
void hg_scanInputs (t_config * config, int argc, char **argv)
{
	ClArgPtr clarg = NULL;
	int argindex;
	int clarg_result;
	FILE *errorfile = NULL;
	int code;
	
	config->argc = argc;
	config->argv = argv;
	config->device = DEFAULT_DEVICE;
	config->key = 0;
	config->software_id = NULL;
	config->start_xscale = 0;
	config->use_drb_comm = 0;

	/* Set up the command line options. */
	clarg = dagclarg_init(argc, (const char * const *)argv);

	dagclarg_add(clarg, "display help (this page).", "--help", 'h', CLA_HELP);
	dagclarg_add_long_option(clarg, CLA_HELP, "--usage");
	dagclarg_add_short_option(clarg, CLA_HELP, '?');
	dagclarg_add(clarg, "display version information.", "--version", 'V', CLA_VERSION);
	dagclarg_add(clarg, "increase verbosity.", "--verbose", 'v', CLA_VERBOSE);
	dagclarg_add_string(clarg, "DAG device to use.", "--device", 'd', "device", dagname_buf, DAGNAME_BUFSIZE, CLA_DEVICE);
	dagclarg_add(clarg, "reset and start the xscale.", "--rst", 'x', CLA_RESET);
	dagclarg_add_string(clarg, "write the string to the software ID", "--write", 'w', "string", string_buf, BUFSIZE, CLA_STRING);
	dagclarg_add_uint(clarg, "hex key to enable write access to software ID", "--key", 'k', "key", &config->key, CLA_KEY);
		
	/* Parse the command line options. */
	clarg_result = dagclarg_parse(clarg, errorfile, &argindex, &code);
	while (1 == clarg_result)
	{
		switch (code)
		{

			case CLA_HELP:
				print_usage(clarg);
				exit(EXIT_SUCCESS);
				break;

			case CLA_VERBOSE:
				dagutil_inc_verbosity();
				errorfile = stderr;
				break;

			case CLA_VERSION:
				print_version();
				exit(EXIT_SUCCESS);
				break;

			case CLA_DEVICE:
				if (-1 == dag_parse_name(dagname_buf, dagname, DAGNAME_BUFSIZE, &dagstream))
				{
					dagutil_panic("dag_parse_name(%s): %s\n", dagname_buf, strerror(errno));
				}
				config->device = dagname;
				break;

			case CLA_RESET:
				config->start_xscale = 1;
				break;

			case CLA_STRING:
				config->software_id = string_buf;
				break;

			case CLA_KEY:
				break;

			default:
					/* Unknown option. */
					dagutil_error("unknown option %s\n", argv[argindex]); 
					print_usage(clarg);
					exit(EXIT_FAILURE);
				break;
		}
		clarg_result = dagclarg_parse(clarg, errorfile, &argindex, &code);
	}

	if (-1 == clarg_result)
	{
		if (argindex < argc)
		{
			dagutil_error("while processing option %s\n", argv[argindex]);
		}
		dagclarg_display_usage(clarg, stderr);
		exit(EXIT_FAILURE);
	}

}

char soft_id[D37T_SOFTWARE_ID_SIZE+1];

int
dagswid_main(int argc, char **argv)
{
	int res, addr;
	int temperature;
	
	int dagfd;

	dagutil_set_progname("dagswid");
		
	memset (&config, 0, sizeof (config));
	hg_scanInputs (&config, argc, argv);
	
	dagfd = dag_open(config.device);
	if (dagfd < 0)
	{
		fprintf (stderr, "dag_open %s: %s\n", config.device, strerror (errno));
		return EXIT_FAILURE;
	}
	
	
	if (config.start_xscale)
	{
		printf("Restarting xScale ... please wait this may take up to 60 seconds.\n");
		res = dagema_reset_processor(dagfd, 0);
		if (res < 0)
		{
			fprintf (stderr, "failed to restart xScale (errorcode:%d)\n", dagema_get_last_error());
			return EXIT_FAILURE;
		}
	}

	/* Set board debug flags */
	d37t_set_debug(dagfd, 0);
	
	if (config.software_id != NULL)
	{
		printf("Writing Software ID \"%s\" to %s\n",
		config.software_id, config.device);
	
		memset(soft_id, 0, D37T_SOFTWARE_ID_SIZE);
		strncpy(soft_id, config.software_id, D37T_SOFTWARE_ID_SIZE-1);
		
		/* Write all 128 bytes */
		res = d37t_write_software_id(dagfd, D37T_SOFTWARE_ID_SIZE, (uint8_t*) soft_id, config.key);
		if (res)
		{
			printf("Failed to write software ID, res=%d\n\n", res);
		}
		else
		{
			printf("Software ID update completed\n\n");
		}
	}
	
	res = d37t_read_software_id(dagfd, D37T_SOFTWARE_ID_SIZE, (uint8_t*) soft_id);
	if (res)
	{
		printf("d37t_read_software_id() failed res=%d\n", res);
	}
	else
	{
		/* Replace any non-printable characters with spaces for this demo */
		for (addr = 0; addr < D37T_SOFTWARE_ID_SIZE; addr++)
		{
			if (soft_id[addr])
			{
				if (!isgraph(soft_id[addr]))
					soft_id[addr] = ' ';
			}
		}
		
		/* Null terminate it just in case */
		soft_id[D37T_SOFTWARE_ID_SIZE] = 0;
		
		printf("Software ID: \"%s\"\n", soft_id);
	}
	
	res = d37t_read_temperature(dagfd, 0, &temperature);
	if (res)
	{
		printf("d37t_read_temperature() failed, res=%d\n", res);
	}
	else
	{
		printf("Temperature: %d Degrees Celcius\n", temperature);
	}
	
	dag_close(dagfd);
	
	return EXIT_SUCCESS;
}


#ifndef ENDACE_UNIT_TEST
int
main(int argc, const char* const * argv)
{
	return dagswid_main(argc, (char**) argv);
}
#endif /* ENDACE_UNIT_TEST */
