Annotation of embedtools/src/butz.c, revision 1.3

1.3     ! misho       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.2.2.2 2017/01/22 20:40:10 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: */
1.2       misho      46: #include "global.h"
                     47: 
                     48: 
                     49: cfg_root_t cfg;
                     50: sched_root_task_t *root;
1.3     ! misho      51: volatile intptr_t Kill;
        !            52: int gpio, flg, maxpins, defact, resbut, led = -1;
1.2       misho      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:        }
1.3     ! misho     125: 
        !           126:        schedSignalSelf(task);
1.2       misho     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>