-/* $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 <alex@caoua.org>
*
zomb_exit
};
+struct ctl *ctl_list = NULL;
struct dev *dev_list = NULL;
unsigned int dev_sndnum = 0;
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;
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;
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);
}
}
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);
}
}
}
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;
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;
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);
}
}
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);
}
/*
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;
}
{
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) {
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)
{
}
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);
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
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;
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++) {
}
}
-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)
{
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;
}
-/* $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 <alex@caoua.org>
*
#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
*/
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 */
#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 */
struct slot *slot_list; /* audio streams attached */
struct midi *midi;
+ /*
+ * name used for various controls
+ */
+ char name[CTL_NAMEMAX];
+
/*
* audio device (while opened)
*/
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];
/*
* 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) */
-/* $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 <alex@caoua.org>
*
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);
}
struct dev *d = arg;
struct ctl *c;
- addr += CTLADDR_END;
-
dev_log(d);
log_puts(": onctl: addr = ");
log_putu(addr);
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 -> ");
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;
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);
* 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;
-/* $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 <alex@caoua.org>
*
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
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;
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);
int
sock_buildmsg(struct sock *f)
{
- unsigned int size, mask;
+ unsigned int size, type, mask;
struct amsg_ctl_desc *desc;
struct ctl *c, **pc;
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) {
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);
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);
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;
}
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;