[BACK]Return to usbhidaction.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / usbhidaction

Annotation of src/usr.bin/usbhidaction/usbhidaction.c, Revision 1.1

1.1     ! nate        1: /*     $OpenBSD$ */
        !             2: /*      $NetBSD: usbhidaction.c,v 1.7 2002/01/18 14:38:59 augustss Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Lennart Augustsson <lennart@augustsson.net>.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: #include <stdio.h>
        !            41: #include <stdlib.h>
        !            42: #include <string.h>
        !            43: #include <ctype.h>
        !            44: #include <err.h>
        !            45: #include <fcntl.h>
        !            46: #include <limits.h>
        !            47: #include <unistd.h>
        !            48: #include <sys/types.h>
        !            49: #include <sys/ioctl.h>
        !            50: #include <dev/usb/usb.h>
        !            51: #include <dev/usb/usbhid.h>
        !            52: #include <usbhid.h>
        !            53: #include <util.h>
        !            54: #include <syslog.h>
        !            55: #include <signal.h>
        !            56:
        !            57: int verbose = 0;
        !            58: int isdemon = 0;
        !            59: int reparse = 1;
        !            60:
        !            61: struct command {
        !            62:        struct command *next;
        !            63:        int line;
        !            64:
        !            65:        struct hid_item item;
        !            66:        int value;
        !            67:        char anyvalue;
        !            68:        char *name;
        !            69:        char *action;
        !            70: };
        !            71: struct command *commands;
        !            72:
        !            73: #define SIZE 4000
        !            74:
        !            75: void usage(void);
        !            76: struct command *parse_conf(const char *, report_desc_t, int, int);
        !            77: void docmd(struct command *, int, const char *, int, char **);
        !            78: void freecommands(struct command *);
        !            79:
        !            80: static void
        !            81: sighup(int sig)
        !            82: {
        !            83:        reparse = 1;
        !            84: }
        !            85:
        !            86: int
        !            87: main(int argc, char **argv)
        !            88: {
        !            89:        const char *conf = NULL;
        !            90:        const char *dev = NULL;
        !            91:        int fd, ch, sz, n, val, i;
        !            92:        int demon, ignore;
        !            93:        report_desc_t repd;
        !            94:        char buf[100];
        !            95:        char devnamebuf[PATH_MAX];
        !            96:        struct command *cmd;
        !            97:        int reportid;
        !            98:
        !            99:        demon = 1;
        !           100:        ignore = 0;
        !           101:        while ((ch = getopt(argc, argv, "c:df:iv")) != -1) {
        !           102:                switch(ch) {
        !           103:                case 'c':
        !           104:                        conf = optarg;
        !           105:                        break;
        !           106:                case 'd':
        !           107:                        demon ^= 1;
        !           108:                        break;
        !           109:                case 'i':
        !           110:                        ignore++;
        !           111:                        break;
        !           112:                case 'f':
        !           113:                        dev = optarg;
        !           114:                        break;
        !           115:                case 'v':
        !           116:                        demon = 0;
        !           117:                        verbose++;
        !           118:                        break;
        !           119:                case '?':
        !           120:                default:
        !           121:                        usage();
        !           122:                }
        !           123:        }
        !           124:        argc -= optind;
        !           125:        argv += optind;
        !           126:
        !           127:        if (conf == NULL || dev == NULL)
        !           128:                usage();
        !           129:
        !           130:        hid_init(NULL);
        !           131:
        !           132:        if (dev[0] != '/') {
        !           133:                snprintf(devnamebuf, sizeof(devnamebuf), "/dev/%s%s",
        !           134:                         isdigit(dev[0]) ? "uhid" : "", dev);
        !           135:                dev = devnamebuf;
        !           136:        }
        !           137:
        !           138:        fd = open(dev, O_RDWR);
        !           139:        if (fd < 0)
        !           140:                err(1, "%s", dev);
        !           141:        if (ioctl(fd, USB_GET_REPORT_ID, &reportid) < 0)
        !           142:                reportid = -1;
        !           143:        repd = hid_get_report_desc(fd);
        !           144:        if (repd == NULL)
        !           145:                err(1, "hid_get_report_desc() failed\n");
        !           146:
        !           147:        commands = parse_conf(conf, repd, reportid, ignore);
        !           148:
        !           149:        sz = hid_report_size(repd, hid_input, reportid);
        !           150:
        !           151:        if (verbose)
        !           152:                printf("report size %d\n", sz);
        !           153:        if (sz > sizeof buf)
        !           154:                errx(1, "report too large");
        !           155:
        !           156:        (void)signal(SIGHUP, sighup);
        !           157:
        !           158:        if (demon) {
        !           159:                if (daemon(0, 0) < 0)
        !           160:                        err(1, "daemon()");
        !           161:                pidfile(NULL);
        !           162:                isdemon = 1;
        !           163:        }
        !           164:
        !           165:        for(;;) {
        !           166:                n = read(fd, buf, sz);
        !           167:                if (verbose > 2) {
        !           168:                        printf("read %d bytes:", n);
        !           169:                        for (i = 0; i < n; i++)
        !           170:                                printf(" %02x", buf[i]);
        !           171:                        printf("\n");
        !           172:                }
        !           173:                if (n < 0) {
        !           174:                        if (verbose)
        !           175:                                err(1, "read");
        !           176:                        else
        !           177:                                exit(1);
        !           178:                }
        !           179: #if 0
        !           180:                if (n != sz) {
        !           181:                        err(2, "read size");
        !           182:                }
        !           183: #endif
        !           184:                for (cmd = commands; cmd; cmd = cmd->next) {
        !           185:                        val = hid_get_data(buf, &cmd->item);
        !           186:                        if (cmd->value == val || cmd->anyvalue)
        !           187:                                docmd(cmd, val, dev, argc, argv);
        !           188:                }
        !           189:                if (reparse) {
        !           190:                        struct command *cmds =
        !           191:                            parse_conf(conf, repd, reportid, ignore);
        !           192:                        if (cmds) {
        !           193:                                freecommands(commands);
        !           194:                                commands = cmds;
        !           195:                        }
        !           196:                        reparse = 0;
        !           197:                }
        !           198:        }
        !           199:
        !           200:        exit(0);
        !           201: }
        !           202:
        !           203: void
        !           204: usage(void)
        !           205: {
        !           206:        extern char *__progname;
        !           207:
        !           208:        fprintf(stderr, "Usage: %s -c config_file [-d] -f hid_dev "
        !           209:                "[-i] [-v]\n", __progname);
        !           210:        exit(1);
        !           211: }
        !           212:
        !           213: static int
        !           214: peek(FILE *f)
        !           215: {
        !           216:        int c;
        !           217:
        !           218:        c = getc(f);
        !           219:        if (c != EOF)
        !           220:                ungetc(c, f);
        !           221:        return c;
        !           222: }
        !           223:
        !           224: struct command *
        !           225: parse_conf(const char *conf, report_desc_t repd, int reportid, int ignore)
        !           226: {
        !           227:        FILE *f;
        !           228:        char *p;
        !           229:        int line;
        !           230:        char buf[SIZE], name[SIZE], value[SIZE], action[SIZE];
        !           231:        char usage[SIZE], coll[SIZE];
        !           232:        struct command *cmd, *cmds;
        !           233:        struct hid_data *d;
        !           234:        struct hid_item h;
        !           235:        int u, lo, hi, range;
        !           236:
        !           237:
        !           238:        f = fopen(conf, "r");
        !           239:        if (f == NULL)
        !           240:                err(1, "%s", conf);
        !           241:
        !           242:        cmds = NULL;
        !           243:        for (line = 1; ; line++) {
        !           244:                if (fgets(buf, sizeof buf, f) == NULL)
        !           245:                        break;
        !           246:                if (buf[0] == '#' || buf[0] == '\n')
        !           247:                        continue;
        !           248:                p = strchr(buf, '\n');
        !           249:                while (p && isspace(peek(f))) {
        !           250:                        if (fgets(p, sizeof buf - strlen(buf), f) == NULL)
        !           251:                                break;
        !           252:                        p = strchr(buf, '\n');
        !           253:                }
        !           254:                if (p)
        !           255:                        *p = 0;
        !           256:                if (sscanf(buf, "%s %s %[^\n]", name, value, action) != 3) {
        !           257:                        if (isdemon) {
        !           258:                                syslog(LOG_WARNING, "config file `%s', line %d"
        !           259:                                       ", syntax error: %s", conf, line, buf);
        !           260:                                freecommands(cmds);
        !           261:                                return (NULL);
        !           262:                        } else {
        !           263:                                errx(1, "config file `%s', line %d,"
        !           264:                                     ", syntax error: %s", conf, line, buf);
        !           265:                        }
        !           266:                }
        !           267:
        !           268:                cmd = malloc(sizeof *cmd);
        !           269:                if (cmd == NULL)
        !           270:                        err(1, "malloc failed");
        !           271:                cmd->next = cmds;
        !           272:                cmds = cmd;
        !           273:                cmd->line = line;
        !           274:
        !           275:                if (strcmp(value, "*") == 0) {
        !           276:                        cmd->anyvalue = 1;
        !           277:                } else {
        !           278:                        cmd->anyvalue = 0;
        !           279:                        if (sscanf(value, "%d", &cmd->value) != 1) {
        !           280:                                if (isdemon) {
        !           281:                                        syslog(LOG_WARNING,
        !           282:                                               "config file `%s', line %d, "
        !           283:                                               "bad value: %s\n",
        !           284:                                               conf, line, value);
        !           285:                                        freecommands(cmds);
        !           286:                                        return (NULL);
        !           287:                                } else {
        !           288:                                        errx(1, "config file `%s', line %d, "
        !           289:                                             "bad value: %s\n",
        !           290:                                             conf, line, value);
        !           291:                                }
        !           292:                        }
        !           293:                }
        !           294:
        !           295:                coll[0] = 0;
        !           296:                for (d = hid_start_parse(repd, 1 << hid_input, reportid);
        !           297:                     hid_get_item(d, &h); ) {
        !           298:                        if (verbose > 2)
        !           299:                                printf("kind=%d usage=%x\n", h.kind, h.usage);
        !           300:                        if (h.flags & HIO_CONST)
        !           301:                                continue;
        !           302:                        switch (h.kind) {
        !           303:                        case hid_input:
        !           304:                                if (h.usage_minimum != 0 ||
        !           305:                                    h.usage_maximum != 0) {
        !           306:                                        lo = h.usage_minimum;
        !           307:                                        hi = h.usage_maximum;
        !           308:                                        range = 1;
        !           309:                                } else {
        !           310:                                        lo = h.usage;
        !           311:                                        hi = h.usage;
        !           312:                                        range = 0;
        !           313:                                }
        !           314:                                for (u = lo; u <= hi; u++) {
        !           315:                                        snprintf(usage, sizeof usage,  "%s:%s",
        !           316:                                                 hid_usage_page(HID_PAGE(u)),
        !           317:                                                 hid_usage_in_page(u));
        !           318:                                        if (verbose > 2)
        !           319:                                                printf("usage %s\n", usage);
        !           320:                                        if (!strcasecmp(usage, name))
        !           321:                                                goto foundhid;
        !           322:                                        if (coll[0]) {
        !           323:                                                snprintf(usage, sizeof usage,
        !           324:                                                  "%s.%s:%s", coll+1,
        !           325:                                                  hid_usage_page(HID_PAGE(u)),
        !           326:                                                  hid_usage_in_page(u));
        !           327:                                                if (verbose > 2)
        !           328:                                                        printf("usage %s\n",
        !           329:                                                               usage);
        !           330:                                                if (!strcasecmp(usage, name))
        !           331:                                                        goto foundhid;
        !           332:                                        }
        !           333:                                }
        !           334:                                break;
        !           335:                        case hid_collection:
        !           336:                                snprintf(coll + strlen(coll),
        !           337:                                    sizeof coll - strlen(coll),  ".%s:%s",
        !           338:                                    hid_usage_page(HID_PAGE(h.usage)),
        !           339:                                    hid_usage_in_page(h.usage));
        !           340:                                break;
        !           341:                        case hid_endcollection:
        !           342:                                if (coll[0])
        !           343:                                        *strrchr(coll, '.') = 0;
        !           344:                                break;
        !           345:                        default:
        !           346:                                break;
        !           347:                        }
        !           348:                }
        !           349:                if (ignore) {
        !           350:                        if (verbose)
        !           351:                                warnx("ignore item '%s'\n", name);
        !           352:                        continue;
        !           353:                }
        !           354:                if (isdemon) {
        !           355:                        syslog(LOG_WARNING, "config file `%s', line %d, HID "
        !           356:                               "item not found: `%s'\n", conf, line, name);
        !           357:                        freecommands(cmds);
        !           358:                        return (NULL);
        !           359:                } else {
        !           360:                        errx(1, "config file `%s', line %d, HID item "
        !           361:                             "not found: `%s'\n", conf, line, name);
        !           362:                }
        !           363:
        !           364:        foundhid:
        !           365:                hid_end_parse(d);
        !           366:                cmd->item = h;
        !           367:                cmd->name = strdup(name);
        !           368:                cmd->action = strdup(action);
        !           369:                if (range) {
        !           370:                        if (cmd->value == 1)
        !           371:                                cmd->value = u - lo;
        !           372:                        else
        !           373:                                cmd->value = -1;
        !           374:                }
        !           375:
        !           376:                if (verbose)
        !           377:                        printf("PARSE:%d %s, %d, '%s'\n", cmd->line, name,
        !           378:                               cmd->value, cmd->action);
        !           379:        }
        !           380:        fclose(f);
        !           381:        return (cmds);
        !           382: }
        !           383:
        !           384: void
        !           385: docmd(struct command *cmd, int value, const char *hid, int argc, char **argv)
        !           386: {
        !           387:        char cmdbuf[SIZE], *p, *q;
        !           388:        size_t len;
        !           389:        int n, r;
        !           390:
        !           391:        for (p = cmd->action, q = cmdbuf; *p && q < &cmdbuf[SIZE-1]; ) {
        !           392:                if (*p == '$') {
        !           393:                        p++;
        !           394:                        len = &cmdbuf[SIZE-1] - q;
        !           395:                        if (isdigit(*p)) {
        !           396:                                n = strtol(p, &p, 10) - 1;
        !           397:                                if (n >= 0 && n < argc) {
        !           398:                                        strncpy(q, argv[n], len);
        !           399:                                        q += strlen(q);
        !           400:                                }
        !           401:                        } else if (*p == 'V') {
        !           402:                                p++;
        !           403:                                snprintf(q, len, "%d", value);
        !           404:                                q += strlen(q);
        !           405:                        } else if (*p == 'N') {
        !           406:                                p++;
        !           407:                                strncpy(q, cmd->name, len);
        !           408:                                q += strlen(q);
        !           409:                        } else if (*p == 'H') {
        !           410:                                p++;
        !           411:                                strncpy(q, hid, len);
        !           412:                                q += strlen(q);
        !           413:                        } else if (*p) {
        !           414:                                *q++ = *p++;
        !           415:                        }
        !           416:                } else {
        !           417:                        *q++ = *p++;
        !           418:                }
        !           419:        }
        !           420:        *q = 0;
        !           421:
        !           422:        if (verbose)
        !           423:                printf("system '%s'\n", cmdbuf);
        !           424:        r = system(cmdbuf);
        !           425:        if (verbose > 1 && r)
        !           426:                printf("return code = 0x%x\n", r);
        !           427: }
        !           428:
        !           429: void
        !           430: freecommands(struct command *cmd)
        !           431: {
        !           432:        struct command *next;
        !           433:
        !           434:        while (cmd) {
        !           435:                next = cmd->next;
        !           436:                free(cmd);
        !           437:                cmd = next;
        !           438:        }
        !           439: }