/* $Id: maskset.c,v 1.7 2002/06/28 11:27:53 indoh Exp $ */
/* command/maskset.c */

/************************************************************
 *
 * COPYRIGHT (C) HITACHI,LTD. 2002 ALL RIGHTS RESERVED.
 * WRITTEN BY HITACHI SYSTEMS DEVELOPMENT LABORATORY,
 *            HITACHI CENTRAL RESEARCH LABORATORY.
 *
 * Created by K.Hatasaki <keisukeh@crl.hitachi.co.jp>
 *
 ************************************************************/

#include "command.h"

#define LKST_ETYPE_DEF_MNEMONICS
#include <linux/lkst_events.h>

inline void maskset_list(void)
{
	int retval;
	int fd;
	int i;

	lkst_maskset_id id;
	struct lkst_maskset_listparam lp;
	struct lkst_maskset_listent listent[LKST_MASKSET_TBL_MAX];

	fd = open_dev();

	lp.listent_size = LKST_MASKSET_LISTENT_SIZE(LKST_MASKSET_TBL_MAX);
	lp.listent = listent;

	retval = ioctl(fd, LKST_IOC_MASKSET_LIST, &lp);	/* maskset list */

	if (retval) {
		fprintf(stderr, "ioctl() error: %s\n", strerror(errno));
		exit(1);
	}

	printf("maskset_id\tlength\t\tname\n");
	for (i = 0; i < LKST_MASKSET_TBL_MAX; i++) {
		id = lp.listent[i].id;
		if (id != LKST_MASKSET_ID_VOID) {
				printf(" %3d", id);
			if (id == lp.current_id) 
				printf("*");
			printf("\t\t %4d\t\t%s\n",
			       lp.listent[i].len,
			       lp.listent[i].name);
		}
	}

	close(fd);
}

inline void maskset_read_disp(struct lkst_maskset_param *param,
			      int all, int disp)
{
	struct lkst_maskset_body *maskset;
	int	event_type;
	char	*event_type_name;
	int i;

	maskset = param->maskset;

	printf("# ID=%d\n", param->id);
	printf("# maskset name=%s\n# length=%d\n",
	       maskset->name, maskset->len);

	if (disp) {
		printf("# event_type	event_handler_ID\n");
		for (i = 0; i < maskset->len; i++) {
			printf(" 0x%03x		 0x%03x\n",
			       maskset->entry[i].event_type,
			       maskset->entry[i].id);
		}
	} else {
		printf("# event_type\tevent_name\t\tevent_handler_ID\n");
		for (i = 0; i < maskset->len; i++) {
			event_type = maskset->entry[i].event_type,
				event_type_name = lkst_event_type_mnemonics[event_type];
			if (event_type_name || all)
				printf(" 0x%03x\t\t%-24s\t0x%03x\n",
				       event_type,
				       event_type_name,
				       maskset->entry[i].id);
		}
	}
}


inline void maskset_read(lkst_maskset_id id, int all, int disp)
{
	int retval;
	int fd;
	int i;
	struct lkst_maskset_param param;
	struct lkst_maskset_body maskset;

	fd = open_dev();

	param.id = id;
	param.maskset_size = LKST_MASKSET_SIZE(LKST_MASKSET_TABLE_LEN_MAX);
	param.maskset = &maskset;


	retval = ioctl(fd, LKST_IOC_MASKSET_READ, &param); /* maskset read */

	if (retval) {
		fprintf(stderr, "ioctl() error: %s\n", strerror(errno));
		exit(1);
	}

	maskset_read_disp(&param, all, disp);

	close(fd);
}

inline void maskset_read_all(int all, int disp)
{
	int retval;
	int fd;
	int i;
	struct lkst_maskset_param param;
	struct lkst_maskset_body maskset;
	struct lkst_maskset_listparam lp;
	struct lkst_maskset_listent listent[LKST_MASKSET_TBL_MAX];

	fd = open_dev();

	lp.listent_size = LKST_MASKSET_LISTENT_SIZE(LKST_MASKSET_TBL_MAX);
	lp.listent = listent;

	retval = ioctl(fd, LKST_IOC_MASKSET_LIST, &lp);	/* maskset list */

	if (retval) {
		fprintf(stderr, "ioctl() error: %s\n", strerror(errno));
		exit(1);
	}

	for (i = 0; i < LKST_MASKSET_TBL_MAX; i++) {
		if (lp.listent[i].id != LKST_MASKSET_ID_VOID) {

			param.id = lp.listent[i].id;
			param.maskset_size = 
				LKST_MASKSET_SIZE(LKST_MASKSET_TABLE_LEN_MAX);
			param.maskset = &maskset;

			retval = ioctl(fd, LKST_IOC_MASKSET_READ, &param);

			if (retval) {
				fprintf(stderr, "ioctl() error: %s\n",
					strerror(errno));
				exit(1);
			}
			maskset_read_disp(&param, all, disp);
		}
	}

	close(fd);
}

inline void maskset_set(lkst_maskset_id id)
{
	int retval;
	lkst_maskset_id maskset_id;
	int fd;

	fd = open_dev();

	maskset_id = id;

	retval = ioctl(fd, LKST_IOC_MASKSET_SET, maskset_id); /* maskset set */

	if (retval) {
		fprintf(stderr, "ioctl() error: %s\n", strerror(errno));
		exit(1);
	}

	printf("Currently selected maskset was changed to id=%d\n", maskset_id);

	close(fd);
}

inline void maskset_xchg(lkst_maskset_id id)
{
	fprintf(stderr, "error: %s\n", strerror(ENOSYS));
	printf("Please use `lkstm set`.\n");
	exit(1);
}

inline void maskset_write(lkst_maskset_id *id, char *file_name, char *maskset_name)
{
	int retval;
	int fd;
	FILE *fp_i;

	char line[255], *buf[10], value[6];
	struct lkst_maskset_param param;
	int	iEntries, i;
	int	event_type;
	int lcnt = 0;
	lkst_evhandler_id	evhandler_id;

	struct lkst_maskset_body body = {
		name:"",
		len:0,
		entry:{
			{LKST_ETYPE_MAX, 0}
		}
	};

	strncpy(body.name, maskset_name, 255);

	if (0 == strncmp("-", file_name, 2)) {
		fp_i = stdin;
		printf("event_type	event_handler_ID\n");
	} else if ((fp_i = fopen(file_name, "r")) == NULL) {
		perror("input");
		exit(1);
	}

				/* read maskset body from an input file */
	while (NULL != fgets (line, 255, fp_i)) {

		lcnt++;

		if( line[0] == '#' )
			continue;
		if ((buf[0] = (char *) strtok(line, "\t \n")) == NULL)
			continue;

		for(i=1; (buf[i] = (char *)strtok(NULL,"\t \n")) != NULL; i++);

		if (buf[1] == NULL) {
			fprintf(stderr, "Error: Invalid data at line %d\n",
				lcnt - 1);
			exit(1);
		}

		event_type = strtol(strncpy(value, buf[0], 5), NULL, 16);

		evhandler_id = (lkst_evhandler_id) 
			strtol(strncpy(value, buf[i-1], 5), NULL, 16);

		body.entry[body.len].event_type = event_type;
		body.entry[body.len].id = evhandler_id;
		body.len++;
	}

	fd = open_dev();
	
	/* content of new maskset */
	param.id = *id;
	param.maskset_size = LKST_MASKSET_SIZE(body.len);
	param.maskset = &body;

	retval = ioctl(fd, LKST_IOC_MASKSET_WRITE, &param); /* maskset write */

	if (retval) {
		fprintf(stderr, "ioctl() error: %s\n", strerror(errno));
		exit(1);
	}

	*id = param.id;

	printf("New maskset id=%d was written.\n", param.id);

	close(fd);
}

inline void maskset_delete(lkst_maskset_id id)
{
	int retval;
	int fd;

	fd = open_dev();

	retval = ioctl(fd, LKST_IOC_MASKSET_DELETE, id); /* maskset_delete */

	if (retval) {
		fprintf(stderr, "ioctl() error: %s\n", strerror(errno));
		exit(1);
	}

	printf("Maskset id=%d was deleted.\n", id);

	close(fd);
}
