File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / butz.c
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Sat Feb 8 20:57:16 2014 UTC (10 years, 4 months ago) by misho
Branches: MAIN
CVS tags: tools2_7, TOOLS2_6, HEAD
version 2.6

    1: #include "global.h"
    2: 
    3: 
    4: cfg_root_t cfg;
    5: sched_root_task_t *root;
    6: int Kill, gpio, flg, maxpins, defact, resbut, led = -1;
    7: extern char compiled[], compiledby[], compilehost[];
    8: char szCfgName[PATH_MAX] = BUTZ_CFG;
    9: char szDevName[PATH_MAX] = _PATH_DEVGPIOC"0";
   10: 
   11: static void
   12: Usage()
   13: {
   14: 	printf(	" -= Butz =- Service for board buttons management\n"
   15: 		"=== %s === %s@%s ===\n\n"
   16: 		"  Syntax: butz [options] [set_value]\n"
   17: 		"\n"
   18: 		"\t-c <cfgfile>\tConfig file [default: /etc/butz.conf]\n"
   19: 		"\t-d <devname>\tGPIO control device [default: /dev/gpioc]\n"
   20: 		"\n", compiled, compiledby, compilehost);
   21: }
   22: 
   23: static int
   24: prepareGPIO()
   25: {
   26: 	const char *str;
   27: 	struct gpio_pin pin;
   28: 	struct gpio_req req;
   29: 
   30: 	str = cfg_getAttribute(&cfg, "reset", "default_after");
   31: 	if (str)
   32: 		defact = strtol(str, NULL, 0);
   33: 	str = cfg_getAttribute(&cfg, "reset", "gpio_led_ping");
   34: 	if (str)
   35: 		led = strtol(str, NULL, 0);
   36: 	str = cfg_getAttribute(&cfg, "reset", "gpio_pin");
   37: 	if (!str || maxpins < (resbut = strtol(str, NULL, 0))) {
   38: 		EERROR(EINVAL, "Reset button pin not defined or wrong number!");
   39: 		return -1;
   40: 	}
   41: 
   42: 	/* switch button pin into input state */
   43: 	pin.gp_pin = resbut;
   44: 	pin.gp_flags = GPIO_PIN_INPUT;
   45: 	if (ioctl(gpio, GPIOSETCONFIG, &pin) == -1)
   46: 		return -1;
   47: 	/* toggle led pin */
   48: 	if (led != -1) {
   49: 		req.gp_pin = led;
   50: 		if (ioctl(gpio, GPIOTOGGLE, &req) == -1) {
   51: 			ESYSERR(0);
   52: 			return -1;
   53: 		}
   54: 	}
   55: 
   56: 	return 0;
   57: }
   58: 
   59: static void *
   60: sigHandler(sched_task_t *task)
   61: {
   62: 	switch (TASK_VAL(task)) {
   63: 		case SIGHUP:
   64: 			cfgUnloadConfig(&cfg);
   65: 			if (cfgLoadConfig(szCfgName, &cfg)) {
   66: 				ELIBERR(cfg);
   67: 				Kill++;
   68: 			}
   69: 			if (prepareGPIO())
   70: 				Kill++;
   71: 			break;
   72: 		case SIGTERM:
   73: 			Kill++;
   74: 			break;
   75: 		default:
   76: 			EERROR(EINVAL, "Undefined signal %lu!", TASK_VAL(task));
   77: 			break;
   78: 	}
   79: 	taskExit(task, NULL);
   80: }
   81: 
   82: static void *
   83: execReset(sched_task_t *task)
   84: {
   85: 	pid_t pid;
   86: 	const char *str;
   87: 
   88: 	str = cfg_getAttribute(&cfg, "reset", "click");
   89: 	if (!str)
   90: 		taskExit(task, NULL);
   91: 
   92: 	if ((pid = fork()) == -1)
   93: 		ESYSERR(0);
   94: 	else if (!pid) {
   95: 		execl(str, str, "click", NULL);
   96: 		ESYSERR(0);
   97: 		_exit(127);
   98: 	}
   99: 
  100: 	flg ^= flg;
  101: 	taskExit(task, NULL);
  102: }
  103: 
  104: static void *
  105: execDefault(sched_task_t *task)
  106: {
  107: 	pid_t pid;
  108: 	const char *str;
  109: 
  110: 	str = cfg_getAttribute(&cfg, "reset", "default");
  111: 	if (!str)
  112: 		taskExit(task, NULL);
  113: 
  114: 	if ((pid = fork()) == -1)
  115: 		ESYSERR(0);
  116: 	else if (!pid) {
  117: 		execl(str, str, "default", NULL);
  118: 		ESYSERR(0);
  119: 		_exit(127);
  120: 	}
  121: 
  122: 	flg ^= flg;
  123: 	taskExit(task, NULL);
  124: }
  125: 
  126: static void *
  127: butReset(sched_task_t *task)
  128: {
  129: 	struct timespec ts = { 1, 0 };
  130: 	struct gpio_req req;
  131: 
  132: 	/* check reset button */
  133: 	req.gp_pin = resbut;
  134: 	if (ioctl(gpio, GPIOGET, &req) == -1) {
  135: 		ESYSERR(0);
  136: 		goto end;
  137: 	}
  138: 	/* switch on */
  139: 	if (flg != -1 && !req.gp_value)
  140: 		if (++flg == 1)
  141: 			schedSuspend(TASK_ROOT(task), execReset, NULL, flg, NULL, 0);
  142: 	if (defact && flg >= defact) {
  143: 		schedCancelby(TASK_ROOT(task), taskSUSPEND, CRITERIA_CALL, execReset, NULL);
  144: 		schedEvent(TASK_ROOT(task), execDefault, NULL, flg, NULL, 0);
  145: 		flg = -1;
  146: 		goto end;
  147: 	}
  148: 	if (flg > 0 && req.gp_value)
  149: 		schedResumeby(TASK_ROOT(task), CRITERIA_ID, (void*) 1);
  150: 
  151: 	/* toggle led pin */
  152: 	if (flg != -1 && led != -1) {
  153: 		req.gp_pin = led;
  154: 		if (ioctl(gpio, GPIOTOGGLE, &req) == -1)
  155: 			ESYSERR(0);
  156: 	}
  157: end:
  158: 	schedTimer(TASK_ROOT(task), TASK_FUNC(task), TASK_ARG(task), 
  159: 			ts, TASK_DATA(task), TASK_DATLEN(task));
  160: 	taskExit(task, NULL);
  161: }
  162: 
  163: 
  164: int
  165: main(int argc, char **argv)
  166: {
  167: 	char ch;
  168: 	pid_t pid;
  169: 	struct timespec ts = { 1, 0 };
  170: 
  171: 	while ((ch = getopt(argc, argv, "hc:d:")) != -1)
  172: 		switch (ch) {
  173: 			case 'd':
  174: 				strlcpy(szDevName, optarg, sizeof szDevName);
  175: 				break;
  176: 			case 'c':
  177: 				strlcpy(szCfgName, optarg, sizeof szCfgName);
  178: 				break;
  179: 			case 'h':
  180: 			default:
  181: 				Usage();
  182: 				return 1;
  183: 		}
  184: 	argc -= optind;
  185: 	argv += optind;
  186: 
  187: 	switch ((pid = fork())) {
  188: 		case -1:
  189: 			printf("Error:: failed fork() #%d - %s\n", errno, strerror(errno));
  190: 			return 1;
  191: 		case 0:
  192: 			setsid();
  193: 			chdir("/");
  194: 
  195: 			gpio = open(_PATH_DEVNULL, O_RDWR);
  196: 			if (gpio > 2) {
  197: 				dup2(gpio, STDIN_FILENO);
  198: 				dup2(gpio, STDOUT_FILENO);
  199: 				dup2(gpio, STDERR_FILENO);
  200: 				close(gpio);
  201: 			}
  202: 			break;
  203: 		default:
  204: 			return 0;
  205: 	}
  206: 
  207: 	openlog("butz", LOG_PID | LOG_CONS, LOG_DAEMON);
  208: 	gpio = open(szDevName, O_RDONLY);
  209: 	if (gpio == -1) {
  210: 		ESYSERR(0);
  211: 		return 1;
  212: 	}
  213: 	if (ioctl(gpio, GPIOMAXPIN, &maxpins) == -1) {
  214: 		ESYSERR(0);
  215: 		return 1;
  216: 	}
  217: 
  218: 	if (cfgLoadConfig(szCfgName, &cfg)) {
  219: 		ELIBERR(cfg);
  220: 		close(gpio);
  221: 		return 1;
  222: 	}
  223: 	if (prepareGPIO()) {
  224: 		close(gpio);
  225: 		return 1;
  226: 	}
  227: 	root = schedBegin();
  228: 	if (!root) {
  229: 		ELIBERR(sched);
  230: 		close(gpio);
  231: 		return 1;
  232: 	}
  233: 
  234: 	schedSignal(root, sigHandler, NULL, SIGHUP, NULL, 0);
  235: 	schedSignal(root, sigHandler, NULL, SIGTERM, NULL, 0);
  236: 	schedTimer(root, butReset, NULL, ts, NULL, 0);
  237: 
  238: 	schedRun(root, &Kill);
  239: 	schedEnd(&root);
  240: 	cfgUnloadConfig(&cfg);
  241: 	close(gpio);
  242: 	closelog();
  243: 	return 0;
  244: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>