From: ratchov Date: Wed, 3 Mar 2021 10:00:27 +0000 (+0000) Subject: sndiod: Move controls out of the device structure X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=9958002099ab280e77824dedb8f85e7144901bcf;p=openbsd sndiod: Move controls out of the device structure Moving to a global server-wide controls list is necessary to expose controls that are not associated to a particular device (ex. a device selector). The current hack to use the device-side sioctl_desc->addr variable as client-side key can't work anymore. So, we use a unique dynamically allocated ctl->addr key; this is much cleaner. A new "scope" enum (with two "void *" arguments) is used to determine what the control does control. This adds flexibility and allows to easily add new control types that are not associated to devices. No behavior change. --- diff --git a/usr.bin/sndiod/dev.c b/usr.bin/sndiod/dev.c index 7dc8bac2a0b..e47afb30314 100644 --- a/usr.bin/sndiod/dev.c +++ b/usr.bin/sndiod/dev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.c,v 1.91 2021/03/02 12:15:46 edd Exp $ */ +/* $OpenBSD: dev.c,v 1.92 2021/03/03 10:00:27 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov * @@ -106,6 +106,7 @@ struct slotops zomb_slotops = { zomb_exit }; +struct ctl *ctl_list = NULL; struct dev *dev_list = NULL; unsigned int dev_sndnum = 0; @@ -370,12 +371,14 @@ dev_midi_master(struct dev *d) master = d->master; else { master = 0; - for (c = d->ctl_list; c != NULL; c = c->next) { + for (c = ctl_list; c != NULL; c = c->next) { if (c->type != CTL_NUM || - strcmp(c->group, "") != 0 || + strcmp(c->group, d->name) != 0 || strcmp(c->node0.name, "output") != 0 || strcmp(c->func, "level") != 0) continue; + if (c->u.any.arg0 != d) + continue; v = (c->curval * 127 + c->maxval / 2) / c->maxval; if (master < v) master = v; @@ -465,7 +468,7 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) slot_array[chan].opt->dev != d) return; slot_setvol(slot_array + chan, msg[2]); - dev_onval(d, CTLADDR_SLOT_LEVEL(chan), msg[2]); + ctl_onval(CTL_SLOT_LEVEL, slot_array + chan, NULL, msg[2]); return; } x = (struct sysex *)msg; @@ -479,7 +482,7 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) if (len == SYSEX_SIZE(master)) { dev_master(d, x->u.master.coarse); if (d->master_enabled) { - dev_onval(d, CTLADDR_MASTER, + ctl_onval(CTL_DEV_MASTER, d, NULL, x->u.master.coarse); } } @@ -1005,14 +1008,16 @@ dev_master(struct dev *d, unsigned int master) if (d->mode & MODE_PLAY) dev_mix_adjvol(d); } else { - for (c = d->ctl_list; c != NULL; c = c->next) { + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope != CTL_HW || c->u.hw.dev != d) + continue; if (c->type != CTL_NUM || - strcmp(c->group, "") != 0 || + strcmp(c->group, d->name) != 0 || strcmp(c->node0.name, "output") != 0 || strcmp(c->func, "level") != 0) continue; v = (master * c->maxval + 64) / 127; - dev_setctl(d, c->addr, v); + ctl_setval(c, v); } } } @@ -1070,7 +1075,7 @@ dev_new(char *path, struct aparams *par, d->master = MIDI_MAXCTL; d->mtc.origin = 0; d->tstate = MMC_STOP; - d->ctl_list = NULL; + snprintf(d->name, CTL_NAMEMAX, "%u", d->num); d->next = dev_list; dev_list = d; return d; @@ -1216,10 +1221,8 @@ dev_allocbufs(struct dev *d) int dev_open(struct dev *d) { - int i; char name[CTL_NAMEMAX]; struct dev_alt *a; - struct slot *s; d->master_enabled = 0; d->mode = d->reqmode; @@ -1243,23 +1246,12 @@ dev_open(struct dev *d) if (!dev_allocbufs(d)) return 0; - for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) { - if (s->opt == NULL || s->opt->dev != d || s->name[0] == 0) - continue; - slot_ctlname(s, name, CTL_NAMEMAX); - dev_addctl(d, "app", CTL_NUM, - CTLADDR_SLOT_LEVEL(i), - name, -1, "level", - NULL, -1, 127, s->vol); - } - /* if there are multiple alt devs, add server.device knob */ if (d->alt_list->next != NULL) { for (a = d->alt_list; a != NULL; a = a->next) { snprintf(name, sizeof(name), "%d", a->idx); - dev_addctl(d, "", CTL_SEL, - CTLADDR_ALT_SEL + a->idx, - "server", -1, "device", + ctl_new(CTL_DEV_ALT, d, &a->idx, + CTL_SEL, d->name, "server", -1, "device", name, -1, 1, a->idx == d->alt_num); } } @@ -1334,17 +1326,19 @@ dev_freebufs(struct dev *d) void dev_close(struct dev *d) { - struct ctl *c; + struct dev_alt *a; + unsigned int idx; d->pstate = DEV_CFG; dev_sio_close(d); dev_freebufs(d); - /* there are no clients, just free remaining local controls */ - while ((c = d->ctl_list) != NULL) { - d->ctl_list = c->next; - xfree(c); + if (d->master_enabled) { + d->master_enabled = 0; + ctl_del(CTL_DEV_MASTER, d, NULL); } + for (idx = 0, a = d->alt_list; a != NULL; idx++, a = a->next) + ctl_del(CTL_DEV_ALT, d, &idx); } /* @@ -2325,8 +2319,11 @@ ctlslot_new(struct opt *o, struct ctlops *ops, void *arg) return NULL; s->ops = ops; s->arg = arg; - for (c = o->dev->ctl_list; c != NULL; c = c->next) + for (c = ctl_list; c != NULL; c = c->next) { + if (!ctlslot_visible(s, c)) + continue; c->refs_mask |= s->self; + } return s; } @@ -2338,7 +2335,7 @@ ctlslot_del(struct ctlslot *s) { struct ctl *c, **pc; - pc = &s->opt->dev->ctl_list; + pc = &ctl_list; while ((c = *pc) != NULL) { c->refs_mask &= ~s->self; if (c->refs_mask == 0) { @@ -2351,6 +2348,41 @@ ctlslot_del(struct ctlslot *s) dev_unref(s->opt->dev); } +int +ctlslot_visible(struct ctlslot *s, struct ctl *c) +{ + if (s->opt == NULL) + return 1; + switch (c->scope) { + case CTL_HW: + case CTL_DEV_MASTER: + case CTL_DEV_ALT: + return (s->opt->dev == c->u.any.arg0); + case CTL_SLOT_LEVEL: + return (s->opt->dev == c->u.slot_level.slot->opt->dev); + default: + return 0; + } +} + +struct ctl * +ctlslot_lookup(struct ctlslot *s, int addr) +{ + struct ctl *c; + + c = ctl_list; + while (1) { + if (c == NULL) + return NULL; + if (c->type != CTL_NONE && c->addr == addr) + break; + c = c->next; + } + if (!ctlslot_visible(s, c)) + return NULL; + return c; +} + void ctl_node_log(struct ctl_node *c) { @@ -2387,18 +2419,112 @@ ctl_log(struct ctl *c) } log_puts(" at "); log_putu(c->addr); + log_puts(" -> "); + switch (c->scope) { + case CTL_HW: + log_puts("hw:"); + log_puts(c->u.hw.dev->name); + log_puts("/"); + log_putu(c->u.hw.addr); + break; + case CTL_DEV_MASTER: + log_puts("dev_master:"); + log_puts(c->u.dev_master.dev->name); + break; + case CTL_DEV_ALT: + log_puts("dev_alt:"); + log_puts(c->u.dev_alt.dev->name); + log_putu(c->u.dev_alt.idx); + break; + case CTL_SLOT_LEVEL: + log_puts("slot_level:"); + log_puts(c->u.slot_level.slot->name); + log_putu(c->u.slot_level.slot->unit); + break; + default: + log_puts("unknown"); + } +} + +int +ctl_setval(struct ctl *c, int val) +{ + if (c->curval == val) { + if (log_level >= 3) { + ctl_log(c); + log_puts(": already set\n"); + } + return 1; + } + if (val < 0 || val > c->maxval) { + if (log_level >= 3) { + log_putu(val); + log_puts(": ctl val out of bounds\n"); + } + return 0; + } + + switch (c->scope) { + case CTL_HW: + if (log_level >= 3) { + ctl_log(c); + log_puts(": marked as dirty\n"); + } + c->curval = val; + c->dirty = 1; + return dev_ref(c->u.hw.dev); + case CTL_DEV_MASTER: + if (!c->u.dev_master.dev->master_enabled) + return 1; + dev_master(c->u.dev_master.dev, val); + dev_midi_master(c->u.dev_master.dev); + c->val_mask = ~0U; + c->curval = val; + return 1; + case CTL_DEV_ALT: + dev_setalt (c->u.dev_alt.dev, c->u.dev_alt.idx); + return 1; + case CTL_SLOT_LEVEL: + slot_setvol(c->u.slot_level.slot, val); + // XXX change dev_midi_vol() into slot_midi_vol() + dev_midi_vol(c->u.slot_level.slot->opt->dev, c->u.slot_level.slot); + c->val_mask = ~0U; + c->curval = val; + return 1; + default: + if (log_level >= 2) { + ctl_log(c); + log_puts(": not writable\n"); + } + return 1; + } } /* * add a ctl */ struct ctl * -dev_addctl(struct dev *d, char *gstr, int type, int addr, - char *str0, int unit0, char *func, char *str1, int unit1, int maxval, int val) +ctl_new(int scope, void *arg0, void *arg1, + int type, char *gstr, + char *str0, int unit0, char *func, + char *str1, int unit1, int maxval, int val) { struct ctl *c, **pc; + struct ctlslot *s; + int addr; int i; + /* + * find the smallest unused addr number and + * the last position in the list + */ + addr = 0; + for (pc = &ctl_list; (c = *pc) != NULL; pc = &c->next) { + if (c->addr > addr) + addr = c->addr; + } + addr++; + c = xmalloc(sizeof(struct ctl)); c->type = type; strlcpy(c->func, func, CTL_NAMEMAX); @@ -2410,65 +2536,138 @@ dev_addctl(struct dev *d, char *gstr, int type, int addr, c->node1.unit = unit1; } else memset(&c->node1, 0, sizeof(struct ctl_node)); + c->scope = scope; + c->u.any.arg0 = arg0; + switch (scope) { + case CTL_HW: + c->u.hw.addr = *(unsigned int *)arg1; + break; + case CTL_DEV_ALT: + c->u.dev_alt.idx = *(unsigned int *)arg1; + break; + default: + c->u.any.arg1 = NULL; + } c->addr = addr; c->maxval = maxval; c->val_mask = ~0; c->desc_mask = ~0; c->curval = val; c->dirty = 0; - c->refs_mask = 0; - for (i = 0; i < DEV_NCTLSLOT; i++) { - c->refs_mask |= CTL_DEVMASK; - if (ctlslot_array[i].ops != NULL) + c->refs_mask = CTL_DEVMASK; + for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) { + if (s->ops == NULL) + continue; + if (ctlslot_visible(s, c)) c->refs_mask |= 1 << i; } - for (pc = &d->ctl_list; *pc != NULL; pc = &(*pc)->next) - ; /* nothing */ - c->next = NULL; + c->next = *pc; *pc = c; #ifdef DEBUG - if (log_level >= 3) { - dev_log(d); - log_puts(": adding "); + if (log_level >= 2) { ctl_log(c); - log_puts("\n"); + log_puts(": added\n"); } #endif return c; } void -dev_rmctl(struct dev *d, int addr) +ctl_update(struct ctl *c) +{ + struct ctlslot *s; + unsigned int refs_mask; + int i; + + for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) { + if (s->ops == NULL) + continue; + refs_mask = ctlslot_visible(s, c) ? s->self : 0; + + /* nothing to do if no visibility change */ + if (((c->refs_mask & s->self) ^ refs_mask) == 0) + continue; + /* if control becomes visble */ + if (refs_mask) + c->refs_mask |= s->self; + /* if control is hidden */ + c->desc_mask |= s->self; + } +} + +int +ctl_match(struct ctl *c, int scope, void *arg0, void *arg1) +{ + if (c->type == CTL_NONE || c->scope != scope || c->u.any.arg0 != arg0) + return 0; + if (arg0 != NULL && c->u.any.arg0 != arg0) + return 0; + switch (scope) { + case CTL_HW: + if (arg1 != NULL && c->u.hw.addr != *(unsigned int *)arg1) + return 0; + break; + case CTL_DEV_ALT: + if (arg1 != NULL && c->u.dev_alt.idx != *(unsigned int *)arg1) + return 0; + break; + } + return 1; +} + +struct ctl * +ctl_find(int scope, void *arg0, void *arg1) +{ + struct ctl *c; + + for (c = ctl_list; c != NULL; c = c->next) { + if (ctl_match(c, scope, arg0, arg1)) + return c; + } + return NULL; +} + +int +ctl_onval(int scope, void *arg0, void *arg1, int val) +{ + struct ctl *c; + + c = ctl_find(scope, arg0, arg1); + if (c == NULL) + return 0; + c->curval = val; + c->val_mask = ~0U; + return 1; +} + +void +ctl_del(int scope, void *arg0, void *arg1) { struct ctl *c, **pc; - pc = &d->ctl_list; + pc = &ctl_list; for (;;) { c = *pc; if (c == NULL) return; - if (c->type != CTL_NONE && c->addr == addr) - break; - pc = &c->next; - } - c->type = CTL_NONE; + if (ctl_match(c, scope, arg0, arg1)) { #ifdef DEBUG - if (log_level >= 3) { - dev_log(d); - log_puts(": removing "); - ctl_log(c); - log_puts(", refs_mask = 0x"); - log_putx(c->refs_mask); - log_puts("\n"); - } + if (log_level >= 2) { + ctl_log(c); + log_puts(": removed\n"); + } #endif - c->refs_mask &= ~CTL_DEVMASK; - if (c->refs_mask == 0) { - *pc = c->next; - xfree(c); - return; + c->refs_mask &= ~CTL_DEVMASK; + if (c->refs_mask == 0) { + *pc = c->next; + xfree(c); + continue; + } + c->type = CTL_NONE; + c->desc_mask = ~0; + } + pc = &c->next; } - c->desc_mask = ~0; } void @@ -2479,10 +2678,11 @@ dev_ctlsync(struct dev *d) int found, i; found = 0; - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->addr != CTLADDR_MASTER && + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope == CTL_HW && + c->u.hw.dev == d && c->type == CTL_NUM && - strcmp(c->group, "") == 0 && + strcmp(c->group, d->name) == 0 && strcmp(c->node0.name, "output") == 0 && strcmp(c->func, "level") == 0) found = 1; @@ -2494,15 +2694,16 @@ dev_ctlsync(struct dev *d) log_puts(": software master level control disabled\n"); } d->master_enabled = 0; - dev_rmctl(d, CTLADDR_MASTER); + ctl_del(CTL_DEV_MASTER, d, NULL); } else if (!d->master_enabled && !found) { if (log_level >= 2) { dev_log(d); log_puts(": software master level control enabled\n"); } d->master_enabled = 1; - dev_addctl(d, "", CTL_NUM, CTLADDR_MASTER, - "output", -1, "level", NULL, -1, 127, d->master); + ctl_new(CTL_DEV_MASTER, d, NULL, + CTL_NUM, d->name, "output", -1, "level", + NULL, -1, 127, d->master); } for (s = ctlslot_array, i = DEV_NCTLSLOT; i > 0; i--, s++) { @@ -2511,95 +2712,6 @@ dev_ctlsync(struct dev *d) } } -int -dev_setctl(struct dev *d, int addr, int val) -{ - struct ctl *c; - struct slot *s; - int num; - - c = d->ctl_list; - for (;;) { - if (c == NULL) { - if (log_level >= 3) { - dev_log(d); - log_puts(": "); - log_putu(addr); - log_puts(": no such ctl address\n"); - } - return 0; - } - if (c->type != CTL_NONE && c->addr == addr) - break; - c = c->next; - } - if (c->curval == val) { - if (log_level >= 3) { - ctl_log(c); - log_puts(": already set\n"); - } - return 1; - } - if (val < 0 || val > c->maxval) { - if (log_level >= 3) { - dev_log(d); - log_puts(": "); - log_putu(val); - log_puts(": ctl val out of bounds\n"); - } - return 0; - } - if (addr >= CTLADDR_END) { - if (log_level >= 3) { - ctl_log(c); - log_puts(": marked as dirty\n"); - } - c->dirty = 1; - dev_ref(d); - } else { - if (addr >= CTLADDR_ALT_SEL) { - if (val) { - num = addr - CTLADDR_ALT_SEL; - dev_setalt(d, num); - } - return 1; - } else if (addr == CTLADDR_MASTER) { - if (d->master_enabled) { - dev_master(d, val); - dev_midi_master(d); - } - } else { - num = addr - CTLADDR_SLOT_LEVEL(0); - s = slot_array + num; - if (s->opt->dev != d) - return 1; - slot_setvol(s, val); - dev_midi_vol(d, s); - } - c->val_mask = ~0U; - } - c->curval = val; - return 1; -} - -int -dev_onval(struct dev *d, int addr, int val) -{ - struct ctl *c; - - c = d->ctl_list; - for (;;) { - if (c == NULL) - return 0; - if (c->type != CTL_NONE && c->addr == addr) - break; - c = c->next; - } - c->curval = val; - c->val_mask = ~0U; - return 1; -} - void dev_label(struct dev *d, int i) { @@ -2608,16 +2720,15 @@ dev_label(struct dev *d, int i) slot_ctlname(&slot_array[i], name, CTL_NAMEMAX); - c = d->ctl_list; + c = ctl_list; for (;;) { if (c == NULL) { - dev_addctl(d, "app", CTL_NUM, - CTLADDR_SLOT_LEVEL(i), - name, -1, "level", + ctl_new(CTL_SLOT_LEVEL, slot_array + i, NULL, + CTL_NUM, "app", name, -1, "level", NULL, -1, 127, slot_array[i].vol); return; } - if (c->addr == CTLADDR_SLOT_LEVEL(i)) + if (ctl_match(c, CTL_SLOT_LEVEL, slot_array + i, NULL)) break; c = c->next; } diff --git a/usr.bin/sndiod/dev.h b/usr.bin/sndiod/dev.h index 57ed8c88972..e1e6680e162 100644 --- a/usr.bin/sndiod/dev.h +++ b/usr.bin/sndiod/dev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dev.h,v 1.37 2021/01/29 11:38:23 ratchov Exp $ */ +/* $OpenBSD: dev.h,v 1.38 2021/03/03 10:00:27 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov * @@ -22,11 +22,6 @@ #include "siofile.h" #include "dev_sioctl.h" -#define CTLADDR_SLOT_LEVEL(n) (n) -#define CTLADDR_MASTER (DEV_NSLOT) -#define CTLADDR_ALT_SEL (CTLADDR_MASTER + 1) -#define CTLADDR_END (CTLADDR_ALT_SEL + DEV_NMAX) - /* * preallocated audio clients */ @@ -119,6 +114,7 @@ struct slot { struct ctl { struct ctl *next; + #define CTL_NONE 0 /* deleted */ #define CTL_NUM 2 /* number (aka integer value) */ #define CTL_SW 3 /* on/off switch, only bit 7 counts */ @@ -126,7 +122,34 @@ struct ctl { #define CTL_LIST 5 /* switch, element of a list */ #define CTL_SEL 6 /* element of a selector */ unsigned int type; /* one of above */ - unsigned int addr; /* control address */ + +#define CTL_HW 0 +#define CTL_DEV_MASTER 1 +#define CTL_DEV_ALT 2 +#define CTL_SLOT_LEVEL 3 + unsigned int scope; + union { + struct { + void *arg0; + void *arg1; + } any; + struct { + struct dev *dev; + unsigned int addr; + } hw; + struct { + struct dev *dev; + } dev_master; + struct { + struct dev *dev; + unsigned int idx; + } dev_alt; + struct { + struct slot *slot; + } slot_level; + } u; + + unsigned int addr; /* slot side control address */ #define CTL_NAMEMAX 16 /* max name lenght */ char func[CTL_NAMEMAX]; /* parameter function name */ char group[CTL_NAMEMAX]; /* group aka namespace */ @@ -160,6 +183,11 @@ struct dev { struct slot *slot_list; /* audio streams attached */ struct midi *midi; + /* + * name used for various controls + */ + char name[CTL_NAMEMAX]; + /* * audio device (while opened) */ @@ -243,15 +271,10 @@ struct dev { unsigned int master; /* software vol. knob */ unsigned int master_enabled; /* 1 if h/w has no vo. knob */ - - /* - * control - */ - - struct ctl *ctl_list; }; extern struct dev *dev_list; +extern struct ctl *ctl_list; extern struct slot slot_array[DEV_NSLOT]; extern struct ctlslot ctlslot_array[DEV_NCTLSLOT]; @@ -307,17 +330,22 @@ void slot_detach(struct slot *); /* * control related functions */ + +struct ctl *ctl_new(int, void *, void *, + int, char *, char *, int, char *, char *, int, int, int); +void ctl_del(int, void *, void *); void ctl_log(struct ctl *); +int ctl_setval(struct ctl *c, int val); +int ctl_match(struct ctl *, int, void *, void *); +struct ctl *ctl_find(int, void *, void *); +void ctl_update(struct ctl *); +int ctl_onval(int, void *, void *, int); + struct ctlslot *ctlslot_new(struct opt *, struct ctlops *, void *); void ctlslot_del(struct ctlslot *); -int dev_setctl(struct dev *, int, int); -int dev_onval(struct dev *, int, int); -int dev_nctl(struct dev *); +int ctlslot_visible(struct ctlslot *, struct ctl *); +struct ctl *ctlslot_lookup(struct ctlslot *, int); void dev_label(struct dev *, int); -struct ctl *dev_addctl(struct dev *, char *, int, int, - char *, int, char *, char *, int, int, int); -void dev_rmctl(struct dev *, int); -int dev_makeunit(struct dev *, char *); void dev_ctlsync(struct dev *); #endif /* !defined(DEV_H) */ diff --git a/usr.bin/sndiod/dev_sioctl.c b/usr.bin/sndiod/dev_sioctl.c index 3809542b6ac..45f6f5f641f 100644 --- a/usr.bin/sndiod/dev_sioctl.c +++ b/usr.bin/sndiod/dev_sioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dev_sioctl.c,v 1.6 2020/06/28 05:21:39 ratchov Exp $ */ +/* $OpenBSD: dev_sioctl.c,v 1.7 2021/03/03 10:00:27 ratchov Exp $ */ /* * Copyright (c) 2014-2020 Alexandre Ratchov * @@ -50,34 +50,27 @@ struct fileops dev_sioctl_ops = { void dev_sioctl_ondesc(void *arg, struct sioctl_desc *desc, int val) { -#define GROUP_PREFIX "hw" - char group_buf[CTL_NAMEMAX], *group; struct dev *d = arg; - int addr; + char *group, group_buf[CTL_NAMEMAX]; if (desc == NULL) { dev_ctlsync(d); return; } - addr = CTLADDR_END + desc->addr; - dev_rmctl(d, addr); + ctl_del(CTL_HW, d, &desc->addr); - /* - * prefix with "hw/" group names of controls we expose, to - * ensure that all controls have unique names when multiple - * sndiod's are chained - */ - if (strcmp(desc->group, "app") == 0 || (desc->group[0] == 0 && - strcmp(desc->node0.name, "server") == 0)) { - group = group_buf; - if (snprintf(group_buf, CTL_NAMEMAX, GROUP_PREFIX "/%s", - desc->group) >= CTL_NAMEMAX) + if (desc->group[0] == 0) + group = d->name; + else { + if (snprintf(group_buf, CTL_NAMEMAX, "%s/%s", + d->name, desc->group) >= CTL_NAMEMAX) return; - } else - group = desc->group; + group = group_buf; + } - dev_addctl(d, group, desc->type, addr, + ctl_new(CTL_HW, d, &desc->addr, + desc->type, group, desc->node0.name, desc->node0.unit, desc->func, desc->node1.name, desc->node1.unit, desc->maxval, val); } @@ -88,8 +81,6 @@ dev_sioctl_onval(void *arg, unsigned int addr, unsigned int val) struct dev *d = arg; struct ctl *c; - addr += CTLADDR_END; - dev_log(d); log_puts(": onctl: addr = "); log_putu(addr); @@ -97,8 +88,8 @@ dev_sioctl_onval(void *arg, unsigned int addr, unsigned int val) log_putu(val); log_puts("\n"); - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->addr != addr) + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope != CTL_HW || c->u.hw.addr != addr) continue; ctl_log(c); log_puts(": new value -> "); @@ -138,9 +129,9 @@ dev_sioctl_close(struct dev *d) struct ctl *c, **pc; /* remove controls */ - pc = &d->ctl_list; + pc = &ctl_list; while ((c = *pc) != NULL) { - if (c->addr >= CTLADDR_END) { + if (c->scope == CTL_HW && c->u.hw.dev == d) { c->refs_mask &= ~CTL_DEVMASK; if (c->refs_mask == 0) { *pc = c->next; @@ -162,8 +153,8 @@ dev_sioctl_pollfd(void *arg, struct pollfd *pfd) struct ctl *c; int events = 0; - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->dirty) + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope == CTL_HW && c->u.hw.dev == d && c->dirty) events |= POLLOUT; } return sioctl_pollfd(d->sioctl.hdl, pfd, events); @@ -195,11 +186,10 @@ dev_sioctl_out(void *arg) * we've finished iterating on it. */ cnt = 0; - for (c = d->ctl_list; c != NULL; c = c->next) { - if (!c->dirty) + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope != CTL_HW || c->u.hw.dev != d || !c->dirty) continue; - if (!sioctl_setval(d->sioctl.hdl, - c->addr - CTLADDR_END, c->curval)) { + if (!sioctl_setval(d->sioctl.hdl, c->u.hw.addr, c->curval)) { ctl_log(c); log_puts(": set failed\n"); break; diff --git a/usr.bin/sndiod/siofile.c b/usr.bin/sndiod/siofile.c index d620b1f36c1..3cc939427b2 100644 --- a/usr.bin/sndiod/siofile.c +++ b/usr.bin/sndiod/siofile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: siofile.c,v 1.23 2021/03/02 12:15:46 edd Exp $ */ +/* $OpenBSD: siofile.c,v 1.24 2021/03/03 10:00:27 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov * @@ -158,11 +158,10 @@ dev_sio_openlist(struct dev *d, log_puts("\n"); } d->alt_num = n->idx; - for (c = d->ctl_list; c != NULL; c = c->next) { - if (c->addr < CTLADDR_ALT_SEL || - c->addr >= CTLADDR_ALT_SEL + DEV_NMAX) + for (c = ctl_list; c != NULL; c = c->next) { + if (!ctl_match(c, CTL_DEV_ALT, d, NULL)) continue; - val = (c->addr - CTLADDR_ALT_SEL) == n->idx; + val = c->u.dev_alt.idx == n->idx; if (c->curval == val) continue; c->curval = val; diff --git a/usr.bin/sndiod/sock.c b/usr.bin/sndiod/sock.c index 83f8ad08bb2..4a425f32328 100644 --- a/usr.bin/sndiod/sock.c +++ b/usr.bin/sndiod/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.41 2021/01/29 11:38:23 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.42 2021/03/03 10:00:27 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov * @@ -1240,8 +1240,7 @@ sock_execmsg(struct sock *f) f->lastvol = ctl; /* dont trigger feedback message */ slot_setvol(s, ctl); dev_midi_vol(s->opt->dev, s); - dev_onval(s->opt->dev, - CTLADDR_SLOT_LEVEL(f->slot - slot_array), ctl); + ctl_onval(CTL_SLOT_LEVEL, s, NULL, ctl); break; case AMSG_CTLSUB: #ifdef DEBUG @@ -1267,9 +1266,10 @@ sock_execmsg(struct sock *f) if (m->u.ctlsub.desc) { if (!(f->ctlops & SOCK_CTLDESC)) { ctl = f->ctlslot->self; - c = f->ctlslot->opt->dev->ctl_list; + c = ctl_list; while (c != NULL) { - c->desc_mask |= ctl; + if (ctlslot_visible(f->ctlslot, c)) + c->desc_mask |= ctl; c = c->next; } f->ctlops |= SOCK_CTLDESC; @@ -1301,13 +1301,23 @@ sock_execmsg(struct sock *f) sock_close(f); return 0; } - if (!dev_setctl(f->ctlslot->opt->dev, - ntohs(m->u.ctlset.addr), - ntohs(m->u.ctlset.val))) { + + c = ctlslot_lookup(f->ctlslot, ntohs(m->u.ctlset.addr)); + if (c == NULL) { +#ifdef DEBUG + if (log_level >= 1) { + sock_log(f); + log_puts(": CTLSET, wrong addr\n"); + } +#endif + sock_close(f); + return 0; + } + if (!ctl_setval(c, ntohs(m->u.ctlset.val))) { #ifdef DEBUG if (log_level >= 1) { sock_log(f); - log_puts(": CTLSET, wrong addr/val\n"); + log_puts(": CTLSET, bad value\n"); } #endif sock_close(f); @@ -1403,7 +1413,7 @@ sock_execmsg(struct sock *f) int sock_buildmsg(struct sock *f) { - unsigned int size, mask; + unsigned int size, type, mask; struct amsg_ctl_desc *desc; struct ctl *c, **pc; @@ -1555,7 +1565,7 @@ sock_buildmsg(struct sock *f) desc = f->ctldesc; mask = f->ctlslot->self; size = 0; - pc = &f->ctlslot->opt->dev->ctl_list; + pc = &ctl_list; while ((c = *pc) != NULL) { if ((c->desc_mask & mask) == 0 || (c->refs_mask & mask) == 0) { @@ -1567,7 +1577,11 @@ sock_buildmsg(struct sock *f) break; c->desc_mask &= ~mask; c->val_mask &= ~mask; - strlcpy(desc->group, c->group, + type = ctlslot_visible(f->ctlslot, c) ? + c->type : CTL_NONE; + strlcpy(desc->group, (f->ctlslot->opt == NULL || + strcmp(c->group, f->ctlslot->opt->dev->name) != 0) ? + c->group : "", AMSG_CTL_NAMEMAX); strlcpy(desc->node0.name, c->node0.name, AMSG_CTL_NAMEMAX); @@ -1575,7 +1589,7 @@ sock_buildmsg(struct sock *f) strlcpy(desc->node1.name, c->node1.name, AMSG_CTL_NAMEMAX); desc->node1.unit = ntohs(c->node1.unit); - desc->type = c->type; + desc->type = type; strlcpy(desc->func, c->func, AMSG_CTL_NAMEMAX); desc->addr = htons(c->addr); desc->maxval = htons(c->maxval); @@ -1584,7 +1598,7 @@ sock_buildmsg(struct sock *f) desc++; /* if this is a deleted entry unref it */ - if (c->type == CTL_NONE) { + if (type == CTL_NONE) { c->refs_mask &= ~mask; if (c->refs_mask == 0) { *pc = c->next; @@ -1612,7 +1626,9 @@ sock_buildmsg(struct sock *f) } if (f->ctlslot && (f->ctlops & SOCK_CTLVAL)) { mask = f->ctlslot->self; - for (c = f->ctlslot->opt->dev->ctl_list; c != NULL; c = c->next) { + for (c = ctl_list; c != NULL; c = c->next) { + if (!ctlslot_visible(f->ctlslot, c)) + continue; if ((c->val_mask & mask) == 0) continue; c->val_mask &= ~mask;