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

Annotation of src/usr.bin/sndiod/dev_sioctl.c, Revision 1.1

1.1     ! ratchov     1: /*     $OpenBSD$       */
        !             2: /*
        !             3:  * Copyright (c) 2014-2020 Alexandre Ratchov <alex@caoua.org>
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: #include <sys/time.h>
        !            18: #include <sys/types.h>
        !            19:
        !            20: #include <poll.h>
        !            21: #include <sndio.h>
        !            22: #include <stdio.h>
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: #include "abuf.h"
        !            26: #include "defs.h"
        !            27: #include "dev.h"
        !            28: #include "dsp.h"
        !            29: #include "file.h"
        !            30: #include "dev_sioctl.h"
        !            31: #include "utils.h"
        !            32:
        !            33: void dev_sioctl_ondesc(void *, struct sioctl_desc *, int);
        !            34: void dev_sioctl_onval(void *, unsigned int, unsigned int);
        !            35: int dev_sioctl_pollfd(void *, struct pollfd *);
        !            36: int dev_sioctl_revents(void *, struct pollfd *);
        !            37: void dev_sioctl_in(void *);
        !            38: void dev_sioctl_out(void *);
        !            39: void dev_sioctl_hup(void *);
        !            40:
        !            41: struct fileops dev_sioctl_ops = {
        !            42:        "sioctl",
        !            43:        dev_sioctl_pollfd,
        !            44:        dev_sioctl_revents,
        !            45:        dev_sioctl_in,
        !            46:        dev_sioctl_out,
        !            47:        dev_sioctl_hup
        !            48: };
        !            49:
        !            50: void
        !            51: dev_sioctl_ondesc(void *arg, struct sioctl_desc *desc, int val)
        !            52: {
        !            53: #define GROUP_PREFIX           "hw"
        !            54:        char group_buf[CTL_NAMEMAX], *group;
        !            55:        struct dev *d = arg;
        !            56:        int addr;
        !            57:
        !            58:        if (desc == NULL)
        !            59:                return;
        !            60:        addr = CTLADDR_END + desc->addr;
        !            61:        dev_rmctl(d, addr);
        !            62:
        !            63:        /*
        !            64:         * prefix group names we use (top-level and "app") with "hw."
        !            65:         * to ensure that all controls have unique names when multiple
        !            66:         * sndiod's are chained
        !            67:         */
        !            68:        if (desc->group[0] == 0)
        !            69:                group = GROUP_PREFIX;
        !            70:        else {
        !            71:                group = group_buf;
        !            72:                if (snprintf(group_buf, CTL_NAMEMAX, GROUP_PREFIX "/%s",
        !            73:                    desc->group) >= CTL_NAMEMAX)
        !            74:                        return;
        !            75:        }
        !            76:
        !            77:        dev_addctl(d, group, desc->type, addr,
        !            78:            desc->node0.name, desc->node0.unit, desc->func,
        !            79:            desc->node1.name, desc->node1.unit, desc->maxval, val);
        !            80: }
        !            81:
        !            82: void
        !            83: dev_sioctl_onval(void *arg, unsigned int addr, unsigned int val)
        !            84: {
        !            85:        struct dev *d = arg;
        !            86:        struct ctl *c;
        !            87:
        !            88:        addr += CTLADDR_END;
        !            89:
        !            90:        dev_log(d);
        !            91:        log_puts(": onctl: addr = ");
        !            92:        log_putu(addr);
        !            93:        log_puts(", val = ");
        !            94:        log_putu(val);
        !            95:        log_puts("\n");
        !            96:
        !            97:        for (c = d->ctl_list; c != NULL; c = c->next) {
        !            98:                if (c->addr != addr)
        !            99:                        continue;
        !           100:                ctl_log(c);
        !           101:                log_puts(": new value -> ");
        !           102:                log_putu(val);
        !           103:                log_puts("\n");
        !           104:                c->val_mask = ~0U;
        !           105:                c->curval = val;
        !           106:        }
        !           107: }
        !           108:
        !           109: /*
        !           110:  * open the control device.
        !           111:  */
        !           112: void
        !           113: dev_sioctl_open(struct dev *d)
        !           114: {
        !           115:        if (d->sioctl.hdl == NULL)
        !           116:                return;
        !           117:        sioctl_ondesc(d->sioctl.hdl, dev_sioctl_ondesc, d);
        !           118:        sioctl_onval(d->sioctl.hdl, dev_sioctl_onval, d);
        !           119:        d->sioctl.file = file_new(&dev_sioctl_ops, d, "mix",
        !           120:            sioctl_nfds(d->sioctl.hdl));
        !           121: }
        !           122:
        !           123: /*
        !           124:  * close the control device.
        !           125:  */
        !           126: void
        !           127: dev_sioctl_close(struct dev *d)
        !           128: {
        !           129:        if (d->sioctl.hdl == NULL)
        !           130:                return;
        !           131:        file_del(d->sioctl.file);
        !           132: }
        !           133:
        !           134: int
        !           135: dev_sioctl_pollfd(void *arg, struct pollfd *pfd)
        !           136: {
        !           137:        struct dev *d = arg;
        !           138:        struct ctl *c;
        !           139:        int events = 0;
        !           140:
        !           141:        for (c = d->ctl_list; c != NULL; c = c->next) {
        !           142:                if (c->dirty)
        !           143:                        events |= POLLOUT;
        !           144:        }
        !           145:        return sioctl_pollfd(d->sioctl.hdl, pfd, events);
        !           146: }
        !           147:
        !           148: int
        !           149: dev_sioctl_revents(void *arg, struct pollfd *pfd)
        !           150: {
        !           151:        struct dev *d = arg;
        !           152:
        !           153:        return sioctl_revents(d->sioctl.hdl, pfd);
        !           154: }
        !           155:
        !           156: void
        !           157: dev_sioctl_in(void *arg)
        !           158: {
        !           159: }
        !           160:
        !           161: void
        !           162: dev_sioctl_out(void *arg)
        !           163: {
        !           164:        struct dev *d = arg;
        !           165:        struct ctl *c;
        !           166:        int cnt;
        !           167:
        !           168:        /*
        !           169:         * for each dirty ctl, call sioctl_setval() and dev_unref(). As
        !           170:         * dev_unref() may destroy the ctl_list, we must call it after
        !           171:         * we've finished iterating on it.
        !           172:         */
        !           173:        cnt = 0;
        !           174:        for (c = d->ctl_list; c != NULL; c = c->next) {
        !           175:                if (!c->dirty)
        !           176:                        continue;
        !           177:                if (!sioctl_setval(d->sioctl.hdl,
        !           178:                        c->addr - CTLADDR_END, c->curval)) {
        !           179:                        ctl_log(c);
        !           180:                        log_puts(": set failed\n");
        !           181:                        break;
        !           182:                }
        !           183:                if (log_level >= 2) {
        !           184:                        ctl_log(c);
        !           185:                        log_puts(": changed\n");
        !           186:                }
        !           187:                c->dirty = 0;
        !           188:                cnt++;
        !           189:        }
        !           190:        while (cnt-- > 0)
        !           191:                dev_unref(d);
        !           192: }
        !           193:
        !           194: void
        !           195: dev_sioctl_hup(void *arg)
        !           196: {
        !           197:        struct dev *d = arg;
        !           198:
        !           199:        dev_sioctl_close(d);
        !           200: }