File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / butz.c
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Wed Jun 28 15:19:32 2017 UTC (7 years ago) by misho
Branches: MAIN
CVS tags: tools3_0, tools2_9, tools2_8, TOOLS2_9, TOOLS2_8, TOOLS2_7, HEAD
ver 2.7

    1: /*************************************************************************
    2:  * (C) 2014 AITNET - Sofia/Bulgaria - <office@aitbg.com>
    3:  *  by Michael Pounov <misho@aitbg.com>
    4:  *
    5:  * $Author: misho $
    6:  * $Id: butz.c,v 1.3 2017/06/28 15:19:32 misho Exp $
    7:  *
    8:  *************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004 - 2017
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: 
   48: 
   49: cfg_root_t cfg;
   50: sched_root_task_t *root;
   51: volatile intptr_t Kill;
   52: int gpio, flg, maxpins, defact, resbut, led = -1;
   53: extern char compiled[], compiledby[], compilehost[];
   54: char szCfgName[PATH_MAX] = BUTZ_CFG;
   55: char szDevName[PATH_MAX] = _PATH_DEVGPIOC"0";
   56: 
   57: static void
   58: Usage()
   59: {
   60: 	printf(	" -= Butz =- Service for board buttons management\n"
   61: 		"=== %s === %s@%s ===\n\n"
   62: 		"  Syntax: butz [options] [set_value]\n"
   63: 		"\n"
   64: 		"\t-c <cfgfile>\tConfig file [default: /etc/butz.conf]\n"
   65: 		"\t-d <devname>\tGPIO control device [default: /dev/gpioc]\n"
   66: 		"\n", compiled, compiledby, compilehost);
   67: }
   68: 
   69: static int
   70: prepareGPIO()
   71: {
   72: 	const char *str;
   73: 	struct gpio_pin pin;
   74: 	struct gpio_req req;
   75: 
   76: 	str = cfg_getAttribute(&cfg, "reset", "default_after");
   77: 	if (str)
   78: 		defact = strtol(str, NULL, 0);
   79: 	str = cfg_getAttribute(&cfg, "reset", "gpio_led_ping");
   80: 	if (str)
   81: 		led = strtol(str, NULL, 0);
   82: 	str = cfg_getAttribute(&cfg, "reset", "gpio_pin");
   83: 	if (!str || maxpins < (resbut = strtol(str, NULL, 0))) {
   84: 		EERROR(EINVAL, "Reset button pin not defined or wrong number!");
   85: 		return -1;
   86: 	}
   87: 
   88: 	/* switch button pin into input state */
   89: 	pin.gp_pin = resbut;
   90: 	pin.gp_flags = GPIO_PIN_INPUT;
   91: 	if (ioctl(gpio, GPIOSETCONFIG, &pin) == -1)
   92: 		return -1;
   93: 	/* toggle led pin */
   94: 	if (led != -1) {
   95: 		req.gp_pin = led;
   96: 		if (ioctl(gpio, GPIOTOGGLE, &req) == -1) {
   97: 			ESYSERR(0);
   98: 			return -1;
   99: 		}
  100: 	}
  101: 
  102: 	return 0;
  103: }
  104: 
  105: static void *
  106: sigHandler(sched_task_t *task)
  107: {
  108: 	switch (TASK_VAL(task)) {
  109: 		case SIGHUP:
  110: 			cfgUnloadConfig(&cfg);
  111: 			if (cfgLoadConfig(szCfgName, &cfg)) {
  112: 				ELIBERR(cfg);
  113: 				Kill++;
  114: 			}
  115: 			if (prepareGPIO())
  116: 				Kill++;
  117: 			break;
  118: 		case SIGTERM:
  119: 			Kill++;
  120: 			break;
  121: 		default:
  122: 			EERROR(EINVAL, "Undefined signal %lu!", TASK_VAL(task));
  123: 			break;
  124: 	}
  125: 
  126: 	schedSignalSelf(task);
  127: 	taskExit(task, NULL);
  128: }
  129: 
  130: static void *
  131: execReset(sched_task_t *task)
  132: {
  133: 	pid_t pid;
  134: 	const char *str;
  135: 
  136: 	str = cfg_getAttribute(&cfg, "reset", "click");
  137: 	if (!str)
  138: 		taskExit(task, NULL);
  139: 
  140: 	if ((pid = fork()) == -1)
  141: 		ESYSERR(0);
  142: 	else if (!pid) {
  143: 		execl(str, str, "click", NULL);
  144: 		ESYSERR(0);
  145: 		_exit(127);
  146: 	}
  147: 
  148: 	flg ^= flg;
  149: 	taskExit(task, NULL);
  150: }
  151: 
  152: static void *
  153: execDefault(sched_task_t *task)
  154: {
  155: 	pid_t pid;
  156: 	const char *str;
  157: 
  158: 	str = cfg_getAttribute(&cfg, "reset", "default");
  159: 	if (!str)
  160: 		taskExit(task, NULL);
  161: 
  162: 	if ((pid = fork()) == -1)
  163: 		ESYSERR(0);
  164: 	else if (!pid) {
  165: 		execl(str, str, "default", NULL);
  166: 		ESYSERR(0);
  167: 		_exit(127);
  168: 	}
  169: 
  170: 	flg ^= flg;
  171: 	taskExit(task, NULL);
  172: }
  173: 
  174: static void *
  175: butReset(sched_task_t *task)
  176: {
  177: 	struct timespec ts = { 1, 0 };
  178: 	struct gpio_req req;
  179: 
  180: 	/* check reset button */
  181: 	req.gp_pin = resbut;
  182: 	if (ioctl(gpio, GPIOGET, &req) == -1) {
  183: 		ESYSERR(0);
  184: 		goto end;
  185: 	}
  186: 	/* switch on */
  187: 	if (flg != -1 && !req.gp_value)
  188: 		if (++flg == 1)
  189: 			schedSuspend(TASK_ROOT(task), execReset, NULL, flg, NULL, 0);
  190: 	if (defact && flg >= defact) {
  191: 		schedCancelby(TASK_ROOT(task), taskSUSPEND, CRITERIA_CALL, execReset, NULL);
  192: 		schedEvent(TASK_ROOT(task), execDefault, NULL, flg, NULL, 0);
  193: 		flg = -1;
  194: 		goto end;
  195: 	}
  196: 	if (flg > 0 && req.gp_value)
  197: 		schedResumeby(TASK_ROOT(task), CRITERIA_ID, (void*) 1);
  198: 
  199: 	/* toggle led pin */
  200: 	if (flg != -1 && led != -1) {
  201: 		req.gp_pin = led;
  202: 		if (ioctl(gpio, GPIOTOGGLE, &req) == -1)
  203: 			ESYSERR(0);
  204: 	}
  205: end:
  206: 	schedTimer(TASK_ROOT(task), TASK_FUNC(task), TASK_ARG(task), 
  207: 			ts, TASK_DATA(task), TASK_DATLEN(task));
  208: 	taskExit(task, NULL);
  209: }
  210: 
  211: 
  212: int
  213: main(int argc, char **argv)
  214: {
  215: 	char ch;
  216: 	pid_t pid;
  217: 	struct timespec ts = { 1, 0 };
  218: 
  219: 	while ((ch = getopt(argc, argv, "hc:d:")) != -1)
  220: 		switch (ch) {
  221: 			case 'd':
  222: 				strlcpy(szDevName, optarg, sizeof szDevName);
  223: 				break;
  224: 			case 'c':
  225: 				strlcpy(szCfgName, optarg, sizeof szCfgName);
  226: 				break;
  227: 			case 'h':
  228: 			default:
  229: 				Usage();
  230: 				return 1;
  231: 		}
  232: 	argc -= optind;
  233: 	argv += optind;
  234: 
  235: 	switch ((pid = fork())) {
  236: 		case -1:
  237: 			printf("Error:: failed fork() #%d - %s\n", errno, strerror(errno));
  238: 			return 1;
  239: 		case 0:
  240: 			setsid();
  241: 			chdir("/");
  242: 
  243: 			gpio = open(_PATH_DEVNULL, O_RDWR);
  244: 			if (gpio > 2) {
  245: 				dup2(gpio, STDIN_FILENO);
  246: 				dup2(gpio, STDOUT_FILENO);
  247: 				dup2(gpio, STDERR_FILENO);
  248: 				close(gpio);
  249: 			}
  250: 			break;
  251: 		default:
  252: 			return 0;
  253: 	}
  254: 
  255: 	openlog("butz", LOG_PID | LOG_CONS, LOG_DAEMON);
  256: 	gpio = open(szDevName, O_RDONLY);
  257: 	if (gpio == -1) {
  258: 		ESYSERR(0);
  259: 		return 1;
  260: 	}
  261: 	if (ioctl(gpio, GPIOMAXPIN, &maxpins) == -1) {
  262: 		ESYSERR(0);
  263: 		return 1;
  264: 	}
  265: 
  266: 	if (cfgLoadConfig(szCfgName, &cfg)) {
  267: 		ELIBERR(cfg);
  268: 		close(gpio);
  269: 		return 1;
  270: 	}
  271: 	if (prepareGPIO()) {
  272: 		close(gpio);
  273: 		return 1;
  274: 	}
  275: 	root = schedBegin();
  276: 	if (!root) {
  277: 		ELIBERR(sched);
  278: 		close(gpio);
  279: 		return 1;
  280: 	}
  281: 
  282: 	schedSignal(root, sigHandler, NULL, SIGHUP, NULL, 0);
  283: 	schedSignal(root, sigHandler, NULL, SIGTERM, NULL, 0);
  284: 	schedTimer(root, butReset, NULL, ts, NULL, 0);
  285: 
  286: 	schedRun(root, &Kill);
  287: 	schedEnd(&root);
  288: 	cfgUnloadConfig(&cfg);
  289: 	close(gpio);
  290: 	closelog();
  291: 	return 0;
  292: }

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