summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/sndiod/dev.c423
-rw-r--r--usr.bin/sndiod/dev.h37
-rw-r--r--usr.bin/sndiod/fdpass.c62
-rw-r--r--usr.bin/sndiod/fdpass.h8
-rw-r--r--usr.bin/sndiod/midi.c129
-rw-r--r--usr.bin/sndiod/midi.h9
-rw-r--r--usr.bin/sndiod/miofile.c71
-rw-r--r--usr.bin/sndiod/miofile.h3
-rw-r--r--usr.bin/sndiod/opt.c241
-rw-r--r--usr.bin/sndiod/opt.h13
-rw-r--r--usr.bin/sndiod/siofile.c216
-rw-r--r--usr.bin/sndiod/siofile.h3
-rw-r--r--usr.bin/sndiod/sndiod.c98
-rw-r--r--usr.bin/sndiod/sock.c100
-rw-r--r--usr.bin/sndiod/utils.c46
-rw-r--r--usr.bin/sndiod/utils.h6
16 files changed, 829 insertions, 636 deletions
diff --git a/usr.bin/sndiod/dev.c b/usr.bin/sndiod/dev.c
index b68b60413ec..b63af2248b1 100644
--- a/usr.bin/sndiod/dev.c
+++ b/usr.bin/sndiod/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.102 2021/05/03 04:29:50 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.103 2021/11/01 14:43:24 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -45,16 +45,13 @@ struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int);
void dev_adjpar(struct dev *, int, int, int);
int dev_allocbufs(struct dev *);
-int dev_open(struct dev *);
void dev_freebufs(struct dev *);
-void dev_close(struct dev *);
int dev_ref(struct dev *);
void dev_unref(struct dev *);
int dev_init(struct dev *);
void dev_done(struct dev *);
struct dev *dev_bynum(int);
void dev_del(struct dev *);
-void dev_setalt(struct dev *, unsigned int);
unsigned int dev_roundof(struct dev *, unsigned int);
void dev_wakeup(struct dev *);
@@ -930,10 +927,8 @@ dev_new(char *path, struct aparams *par,
return NULL;
}
d = xmalloc(sizeof(struct dev));
- d->alt_list = NULL;
- dev_addname(d,path);
+ d->path = path;
d->num = dev_sndnum++;
- d->alt_num = -1;
d->reqpar = *par;
d->reqmode = mode;
@@ -948,6 +943,7 @@ dev_new(char *path, struct aparams *par,
d->slot_list = NULL;
d->master = MIDI_MAXCTL;
d->master_enabled = 0;
+ d->alt_next = d;
snprintf(d->name, CTL_NAMEMAX, "%u", d->num);
for (pd = &dev_list; *pd != NULL; pd = &(*pd)->next)
;
@@ -957,51 +953,6 @@ dev_new(char *path, struct aparams *par,
}
/*
- * add a alternate name
- */
-int
-dev_addname(struct dev *d, char *name)
-{
- struct dev_alt *a;
-
- if (d->alt_list != NULL && d->alt_list->idx == DEV_NMAX - 1) {
- log_puts(name);
- log_puts(": too many alternate names\n");
- return 0;
- }
- a = xmalloc(sizeof(struct dev_alt));
- a->name = name;
- a->idx = (d->alt_list == NULL) ? 0 : d->alt_list->idx + 1;
- a->next = d->alt_list;
- d->alt_list = a;
- return 1;
-}
-
-/*
- * set prefered alt device name
- */
-void
-dev_setalt(struct dev *d, unsigned int idx)
-{
- struct dev_alt **pa, *a;
-
- /* find alt with given index */
- for (pa = &d->alt_list; (a = *pa)->idx != idx; pa = &a->next)
- ;
-
- /* detach from list */
- *pa = a->next;
-
- /* attach at head */
- a->next = d->alt_list;
- d->alt_list = a;
-
- /* reopen device with the new alt */
- if (idx != d->alt_num)
- dev_reopen(d);
-}
-
-/*
* adjust device parameters and mode
*/
void
@@ -1099,9 +1050,6 @@ dev_allocbufs(struct dev *d)
int
dev_open(struct dev *d)
{
- char name[CTL_NAMEMAX];
- struct dev_alt *a;
-
d->mode = d->reqmode;
d->round = d->reqround;
d->bufsz = d->reqbufsz;
@@ -1123,16 +1071,6 @@ dev_open(struct dev *d)
if (!dev_allocbufs(d))
return 0;
- /* 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);
- ctl_new(CTL_DEV_ALT, d, &a->idx,
- CTL_SEL, d->name, "server", -1, "device",
- name, -1, 1, a->idx == d->alt_num);
- }
- }
-
d->pstate = DEV_INIT;
return 1;
}
@@ -1158,18 +1096,18 @@ dev_abort(struct dev *d)
}
d->slot_list = NULL;
- for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, c++) {
- if (c->ops == NULL)
- continue;
- if (c->opt->dev != d)
- continue;
- c->ops->exit(c->arg);
- c->ops = NULL;
- }
-
for (o = opt_list; o != NULL; o = o->next) {
if (o->dev != d)
continue;
+ for (c = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, c++) {
+ if (c->ops == NULL)
+ continue;
+ if (c->opt == o) {
+ c->ops->exit(s->arg);
+ c->ops = NULL;
+ }
+ }
+
midi_abort(o->midi);
}
@@ -1208,9 +1146,6 @@ dev_freebufs(struct dev *d)
void
dev_close(struct dev *d)
{
- struct dev_alt *a;
- unsigned int idx;
-
d->pstate = DEV_CFG;
dev_sio_close(d);
dev_freebufs(d);
@@ -1219,82 +1154,6 @@ dev_close(struct dev *d)
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);
-}
-
-/*
- * Close the device, but attempt to migrate everything to a new sndio
- * device.
- */
-int
-dev_reopen(struct dev *d)
-{
- struct mtc *mtc;
- struct slot *s;
- long long pos;
- unsigned int pstate;
- int delta;
-
- /* not opened */
- if (d->pstate == DEV_CFG)
- return 1;
-
- /* save state */
- delta = d->delta;
- pstate = d->pstate;
-
- if (!dev_sio_reopen(d))
- return 0;
-
- /* reopen returns a stopped device */
- d->pstate = DEV_INIT;
-
- /* reallocate new buffers, with new parameters */
- dev_freebufs(d);
- dev_allocbufs(d);
-
- /*
- * adjust time positions, make anything go back delta ticks, so
- * that the new device can start at zero
- */
- for (s = d->slot_list; s != NULL; s = s->next) {
- pos = (long long)s->delta * d->round + s->delta_rem;
- pos -= (long long)delta * s->round;
- s->delta_rem = pos % (int)d->round;
- s->delta = pos / (int)d->round;
- if (log_level >= 3) {
- slot_log(s);
- log_puts(": adjusted: delta -> ");
- log_puti(s->delta);
- log_puts(", delta_rem -> ");
- log_puti(s->delta_rem);
- log_puts("\n");
- }
-
- /* reinitilize the format conversion chain */
- slot_initconv(s);
- }
- mtc = &mtc_array[0];
- if (mtc->dev == d && mtc->tstate == MTC_RUN) {
- mtc->delta -= delta * MTC_SEC;
- if (log_level >= 2) {
- dev_log(mtc->dev);
- log_puts(": adjusted mtc: delta ->");
- log_puti(mtc->delta);
- log_puts("\n");
- }
- }
-
- /* remove old controls and add new ones */
- dev_sioctl_close(d);
- dev_sioctl_open(d);
-
- /* start the device if needed */
- if (pstate == DEV_RUN)
- dev_wakeup(d);
-
- return 1;
}
int
@@ -1381,7 +1240,6 @@ void
dev_del(struct dev *d)
{
struct dev **p;
- struct dev_alt *a;
#ifdef DEBUG
if (log_level >= 3) {
@@ -1401,10 +1259,6 @@ dev_del(struct dev *d)
#endif
}
*p = d->next;
- while ((a = d->alt_list) != NULL) {
- d->alt_list = a->next;
- xfree(a);
- }
xfree(d);
}
@@ -1444,6 +1298,103 @@ dev_wakeup(struct dev *d)
}
/*
+ * Return true if both of the given devices can run the same
+ * clients
+ */
+int
+dev_iscompat(struct dev *o, struct dev *n)
+{
+ if (((long long)o->round * n->rate != (long long)n->round * o->rate) ||
+ ((long long)o->bufsz * n->rate != (long long)n->bufsz * o->rate)) {
+ if (log_level >= 1) {
+ log_puts(n->name);
+ log_puts(": not compatible with ");
+ log_puts(o->name);
+ log_puts("\n");
+ }
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Close the device, but attempt to migrate everything to a new sndio
+ * device.
+ */
+struct dev *
+dev_migrate(struct dev *odev)
+{
+ struct dev *ndev;
+ struct opt *o;
+ struct slot *s;
+ int i;
+
+ /* not opened */
+ if (odev->pstate == DEV_CFG)
+ return odev;
+
+ ndev = odev;
+ while (1) {
+ /* try next one, circulating through the list */
+ ndev = ndev->alt_next;
+ if (ndev == odev) {
+ if (log_level >= 1) {
+ dev_log(odev);
+ log_puts(": no fall-back device found\n");
+ }
+ return NULL;
+ }
+
+
+ if (!dev_ref(ndev))
+ continue;
+
+ /* check if new parameters are compatible with old ones */
+ if (!dev_iscompat(odev, ndev)) {
+ dev_unref(ndev);
+ continue;
+ }
+
+ /* found it!*/
+ break;
+ }
+
+ if (log_level >= 1) {
+ dev_log(odev);
+ log_puts(": switching to ");
+ dev_log(ndev);
+ log_puts("\n");
+ }
+
+ if (mtc_array[0].dev == odev)
+ mtc_setdev(&mtc_array[0], ndev);
+
+ /* move opts to new device (also moves clients using the opts) */
+ for (o = opt_list; o != NULL; o = o->next) {
+ if (o->dev != odev)
+ continue;
+ if (strcmp(o->name, o->dev->name) == 0)
+ continue;
+ opt_setdev(o, ndev);
+ }
+
+ /* terminate remaining clients */
+ for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
+ if (s->opt == NULL || s->opt->dev != odev)
+ continue;
+ if (s->ops != NULL) {
+ s->ops->exit(s);
+ s->ops = NULL;
+ }
+ }
+
+ /* slots and/or MMC hold refs, drop ours */
+ dev_unref(ndev);
+
+ return ndev;
+}
+
+/*
* check that all clients controlled by MMC are ready to start, if so,
* attach them all at the same position
*/
@@ -1552,6 +1503,43 @@ mtc_loc(struct mtc *mtc, unsigned int origin)
}
/*
+ * set MMC device
+ */
+void
+mtc_setdev(struct mtc *mtc, struct dev *d)
+{
+ struct opt *o;
+
+ if (mtc->dev == d)
+ return;
+
+ if (log_level >= 2) {
+ dev_log(d);
+ log_puts(": set to be MIDI clock source\n");
+ }
+
+ /* adjust clock and ref counter, if needed */
+ if (mtc->tstate == MTC_RUN) {
+ mtc->delta -= mtc->dev->delta;
+ dev_unref(mtc->dev);
+ }
+
+ mtc->dev = d;
+
+ if (mtc->tstate == MTC_RUN) {
+ mtc->delta += mtc->dev->delta;
+ dev_ref(mtc->dev);
+ dev_wakeup(mtc->dev);
+ }
+
+ /* move in once anything using MMC */
+ for (o = opt_list; o != NULL; o = o->next) {
+ if (o->mtc == mtc)
+ opt_setdev(o, mtc->dev);
+ }
+}
+
+/*
* allocate buffers & conversion chain
*/
void
@@ -1787,7 +1775,8 @@ slot_new(struct opt *opt, unsigned int id, char *who,
NULL, -1, 127, s->vol);
found:
- if (!dev_ref(opt->dev))
+ /* open device, this may change opt's device */
+ if (!opt_ref(s->opt))
return NULL;
s->opt = opt;
s->ops = ops;
@@ -1809,8 +1798,6 @@ found:
if (log_level >= 3) {
slot_log(s);
log_puts(": using ");
- dev_log(s->opt->dev);
- log_puts(".");
log_puts(s->opt->name);
log_puts(", mode = ");
log_putx(mode);
@@ -1839,7 +1826,7 @@ slot_del(struct slot *s)
slot_stop(s, 0);
break;
}
- dev_unref(s->opt->dev);
+ opt_unref(s->opt);
}
/*
@@ -1861,6 +1848,62 @@ slot_setvol(struct slot *s, unsigned int vol)
}
/*
+ * set device for this slot
+ */
+void
+slot_setopt(struct slot *s, struct opt *o)
+{
+ struct opt *t;
+ struct dev *odev, *ndev;
+ struct ctl *c;
+
+ if (s->opt == NULL || s->opt == o)
+ return;
+
+ if (log_level >= 2) {
+ slot_log(s);
+ log_puts(": moving to opt ");
+ log_puts(o->name);
+ log_puts("\n");
+ }
+
+ odev = s->opt->dev;
+ if (s->ops != NULL) {
+ ndev = opt_ref(o);
+ if (ndev == NULL)
+ return;
+
+ if (!dev_iscompat(odev, ndev)) {
+ opt_unref(o);
+ return;
+ }
+ }
+
+ if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
+ slot_detach(s);
+
+ t = s->opt;
+ s->opt = o;
+
+ c = ctl_find(CTL_SLOT_LEVEL, s, NULL);
+ ctl_update(c);
+
+ if (o->dev != t->dev) {
+ dev_midi_slotdesc(odev, s);
+ dev_midi_slotdesc(ndev, s);
+ dev_midi_vol(ndev, s);
+ }
+
+ if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
+ slot_attach(s);
+
+ if (s->ops != NULL) {
+ opt_unref(t);
+ return;
+ }
+}
+
+/*
* attach the slot to the device (ie start playing & recording
*/
void
@@ -2202,7 +2245,7 @@ ctlslot_new(struct opt *o, struct ctlops *ops, void *arg)
}
s->opt = o;
s->self = 1 << i;
- if (!dev_ref(o->dev))
+ if (!opt_ref(o))
return NULL;
s->ops = ops;
s->arg = arg;
@@ -2232,7 +2275,7 @@ ctlslot_del(struct ctlslot *s)
pc = &c->next;
}
s->ops = NULL;
- dev_unref(s->opt->dev);
+ opt_unref(s->opt);
}
int
@@ -2243,8 +2286,9 @@ ctlslot_visible(struct ctlslot *s, struct ctl *c)
switch (c->scope) {
case CTL_HW:
case CTL_DEV_MASTER:
- case CTL_DEV_ALT:
return (s->opt->dev == c->u.any.arg0);
+ case CTL_OPT_DEV:
+ return (s->opt == c->u.any.arg0);
case CTL_SLOT_LEVEL:
return (s->opt->dev == c->u.slot_level.slot->opt->dev);
default:
@@ -2271,6 +2315,28 @@ ctlslot_lookup(struct ctlslot *s, int addr)
}
void
+ctlslot_update(struct ctlslot *s)
+{
+ struct ctl *c;
+ unsigned int refs_mask;
+
+ for (c = ctl_list; c != NULL; c = c->next) {
+ if (c->type == CTL_NONE)
+ 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;
+ }
+}
+
+void
ctl_node_log(struct ctl_node *c)
{
log_puts(c->name);
@@ -2318,16 +2384,17 @@ ctl_log(struct ctl *c)
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;
+ case CTL_OPT_DEV:
+ log_puts("opt_dev:");
+ log_puts(c->u.opt_dev.opt->name);
+ log_puts("/");
+ log_puts(c->u.opt_dev.dev->name);
+ break;
default:
log_puts("unknown");
}
@@ -2368,9 +2435,6 @@ ctl_setval(struct ctl *c, int val)
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()
@@ -2378,6 +2442,10 @@ ctl_setval(struct ctl *c, int val)
c->val_mask = ~0U;
c->curval = val;
return 1;
+ case CTL_OPT_DEV:
+ c->u.opt_dev.opt->alt_first = c->u.opt_dev.dev;
+ opt_setdev(c->u.opt_dev.opt, c->u.opt_dev.dev);
+ return 1;
default:
if (log_level >= 2) {
ctl_log(c);
@@ -2429,8 +2497,8 @@ ctl_new(int scope, void *arg0, void *arg1,
case CTL_HW:
c->u.hw.addr = *(unsigned int *)arg1;
break;
- case CTL_DEV_ALT:
- c->u.dev_alt.idx = *(unsigned int *)arg1;
+ case CTL_OPT_DEV:
+ c->u.any.arg1 = arg1;
break;
default:
c->u.any.arg1 = NULL;
@@ -2494,8 +2562,8 @@ ctl_match(struct ctl *c, int scope, void *arg0, void *arg1)
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)
+ case CTL_OPT_DEV:
+ if (arg1 != NULL && c->u.any.arg1 != arg1)
return 0;
break;
}
@@ -2600,4 +2668,3 @@ dev_ctlsync(struct dev *d)
s->ops->sync(s->arg);
}
}
-
diff --git a/usr.bin/sndiod/dev.h b/usr.bin/sndiod/dev.h
index 1e778e5bd0d..45ae71f47b9 100644
--- a/usr.bin/sndiod/dev.h
+++ b/usr.bin/sndiod/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.40 2021/03/03 10:19:06 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.41 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -126,7 +126,7 @@ struct ctl {
#define CTL_HW 0
#define CTL_DEV_MASTER 1
-#define CTL_DEV_ALT 2
+#define CTL_OPT_DEV 2
#define CTL_SLOT_LEVEL 3
unsigned int scope;
union {
@@ -142,12 +142,16 @@ struct ctl {
struct dev *dev;
} dev_master;
struct {
- struct dev *dev;
- unsigned int idx;
- } dev_alt;
- struct {
struct slot *slot;
} slot_level;
+ struct {
+ struct slot *slot;
+ struct opt *opt;
+ } slot_opt;
+ struct {
+ struct opt *opt;
+ struct dev *dev;
+ } opt_dev;
} u;
unsigned int addr; /* slot side control address */
@@ -217,6 +221,11 @@ struct dev {
char name[CTL_NAMEMAX];
/*
+ * next to try if this fails
+ */
+ struct dev *alt_next;
+
+ /*
* audio device (while opened)
*/
struct dev_sio sio;
@@ -256,12 +265,7 @@ struct dev {
#define DEV_INIT 1 /* stopped */
#define DEV_RUN 2 /* playin & recording */
unsigned int pstate; /* one of above */
- struct dev_alt {
- struct dev_alt *next;
- char *name;
- unsigned int idx;
- } *alt_list;
- int alt_num;
+ char *path;
/*
* actual parameters and runtime state (i.e. once opened)
@@ -283,12 +287,13 @@ extern struct mtc mtc_array[1];
void slot_array_init(void);
void dev_log(struct dev *);
+int dev_open(struct dev *);
+void dev_close(struct dev *);
void dev_abort(struct dev *);
-int dev_reopen(struct dev *);
+struct dev *dev_migrate(struct dev *);
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int);
struct dev *dev_bynum(int);
-int dev_addname(struct dev *, char *);
void dev_del(struct dev *);
void dev_adjpar(struct dev *, int, int, int);
int dev_init(struct dev *);
@@ -297,6 +302,7 @@ int dev_ref(struct dev *);
void dev_unref(struct dev *);
int dev_getpos(struct dev *);
unsigned int dev_roundof(struct dev *, unsigned int);
+int dev_iscompat(struct dev *, struct dev *);
/*
* interface to hardware device
@@ -330,6 +336,7 @@ struct slot *slot_new(struct opt *, unsigned int, char *,
struct slotops *, void *, int);
void slot_del(struct slot *);
void slot_setvol(struct slot *, unsigned int);
+void slot_setopt(struct slot *, struct opt *);
void slot_start(struct slot *);
void slot_stop(struct slot *, int);
void slot_read(struct slot *);
@@ -356,6 +363,8 @@ struct ctlslot *ctlslot_new(struct opt *, struct ctlops *, void *);
void ctlslot_del(struct ctlslot *);
int ctlslot_visible(struct ctlslot *, struct ctl *);
struct ctl *ctlslot_lookup(struct ctlslot *, int);
+void ctlslot_update(struct ctlslot *);
+
void dev_label(struct dev *, int);
void dev_ctlsync(struct dev *);
diff --git a/usr.bin/sndiod/fdpass.c b/usr.bin/sndiod/fdpass.c
index 9f97f35b7e1..d5f7617a282 100644
--- a/usr.bin/sndiod/fdpass.c
+++ b/usr.bin/sndiod/fdpass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdpass.c,v 1.10 2020/06/18 05:11:13 ratchov Exp $ */
+/* $OpenBSD: fdpass.c,v 1.11 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
*
@@ -36,7 +36,6 @@ struct fdpass_msg {
#define FDPASS_RETURN 3 /* return after above commands */
unsigned int cmd; /* one of above */
unsigned int num; /* audio device or midi port number */
- unsigned int idx; /* index in the path list */
unsigned int mode; /* SIO_PLAY, SIO_REC, MIO_IN, ... */
};
@@ -77,7 +76,7 @@ fdpass_log(struct fdpass *f)
}
static int
-fdpass_send(struct fdpass *f, int cmd, int num, int idx, int mode, int fd)
+fdpass_send(struct fdpass *f, int cmd, int num, int mode, int fd)
{
struct fdpass_msg data;
struct msghdr msg;
@@ -91,7 +90,6 @@ fdpass_send(struct fdpass *f, int cmd, int num, int idx, int mode, int fd)
data.cmd = cmd;
data.num = num;
- data.idx = idx;
data.mode = mode;
iov.iov_base = &data;
iov.iov_len = sizeof(struct fdpass_msg);
@@ -131,8 +129,6 @@ fdpass_send(struct fdpass *f, int cmd, int num, int idx, int mode, int fd)
log_puti(cmd);
log_puts(", num = ");
log_puti(num);
- log_puts(", idx = ");
- log_puti(idx);
log_puts(", mode = ");
log_puti(mode);
log_puts(", fd = ");
@@ -146,7 +142,7 @@ fdpass_send(struct fdpass *f, int cmd, int num, int idx, int mode, int fd)
}
static int
-fdpass_recv(struct fdpass *f, int *cmd, int *num, int *idx, int *mode, int *fd)
+fdpass_recv(struct fdpass *f, int *cmd, int *num, int *mode, int *fd)
{
struct fdpass_msg data;
struct msghdr msg;
@@ -217,7 +213,6 @@ fdpass_recv(struct fdpass *f, int *cmd, int *num, int *idx, int *mode, int *fd)
}
*cmd = data.cmd;
*num = data.num;
- *idx = data.idx;
*mode = data.mode;
#ifdef DEBUG
if (log_level >= 3) {
@@ -226,8 +221,6 @@ fdpass_recv(struct fdpass *f, int *cmd, int *num, int *idx, int *mode, int *fd)
log_puti(*cmd);
log_puts(", num = ");
log_puti(*num);
- log_puts(", idx = ");
- log_puti(*idx);
log_puts(", mode = ");
log_puti(*mode);
log_puts(", fd = ");
@@ -243,7 +236,7 @@ fdpass_waitret(struct fdpass *f, int *retfd)
{
int cmd, unused;
- if (!fdpass_recv(fdpass_peer, &cmd, &unused, &unused, &unused, retfd))
+ if (!fdpass_recv(fdpass_peer, &cmd, &unused, &unused, retfd))
return 0;
if (cmd != FDPASS_RETURN) {
if (log_level >= 1) {
@@ -257,13 +250,13 @@ fdpass_waitret(struct fdpass *f, int *retfd)
}
struct sio_hdl *
-fdpass_sio_open(int num, int idx, unsigned int mode)
+fdpass_sio_open(int num, unsigned int mode)
{
int fd;
if (fdpass_peer == NULL)
return NULL;
- if (!fdpass_send(fdpass_peer, FDPASS_OPEN_SND, num, idx, mode, -1))
+ if (!fdpass_send(fdpass_peer, FDPASS_OPEN_SND, num, mode, -1))
return NULL;
if (!fdpass_waitret(fdpass_peer, &fd))
return NULL;
@@ -273,13 +266,13 @@ fdpass_sio_open(int num, int idx, unsigned int mode)
}
struct mio_hdl *
-fdpass_mio_open(int num, int idx, unsigned int mode)
+fdpass_mio_open(int num, unsigned int mode)
{
int fd;
if (fdpass_peer == NULL)
return NULL;
- if (!fdpass_send(fdpass_peer, FDPASS_OPEN_MIDI, num, idx, mode, -1))
+ if (!fdpass_send(fdpass_peer, FDPASS_OPEN_MIDI, num, mode, -1))
return NULL;
if (!fdpass_waitret(fdpass_peer, &fd))
return NULL;
@@ -289,13 +282,13 @@ fdpass_mio_open(int num, int idx, unsigned int mode)
}
struct sioctl_hdl *
-fdpass_sioctl_open(int num, int idx, unsigned int mode)
+fdpass_sioctl_open(int num, unsigned int mode)
{
int fd;
if (fdpass_peer == NULL)
return NULL;
- if (!fdpass_send(fdpass_peer, FDPASS_OPEN_CTL, num, idx, mode, -1))
+ if (!fdpass_send(fdpass_peer, FDPASS_OPEN_CTL, num, mode, -1))
return NULL;
if (!fdpass_waitret(fdpass_peer, &fd))
return NULL;
@@ -320,14 +313,12 @@ fdpass_in_worker(void *arg)
void
fdpass_in_helper(void *arg)
{
- int cmd, num, idx, mode, fd;
+ int cmd, num, mode, fd;
struct fdpass *f = arg;
struct dev *d;
- struct dev_alt *da;
struct port *p;
- char *path;
- if (!fdpass_recv(f, &cmd, &num, &idx, &mode, &fd))
+ if (!fdpass_recv(f, &cmd, &num, &mode, &fd))
return;
switch (cmd) {
case FDPASS_OPEN_SND:
@@ -340,15 +331,7 @@ fdpass_in_helper(void *arg)
fdpass_close(f);
return;
}
- for (da = d->alt_list; ; da = da->next) {
- if (da == NULL) {
- fdpass_close(f);
- return;
- }
- if (da->idx == idx)
- break;
- }
- fd = sio_sun_getfd(da->name, mode, 1);
+ fd = sio_sun_getfd(d->path, mode, 1);
break;
case FDPASS_OPEN_MIDI:
p = port_bynum(num);
@@ -360,12 +343,7 @@ fdpass_in_helper(void *arg)
fdpass_close(f);
return;
}
- path = namelist_byindex(&p->path_list, idx);
- if (path == NULL) {
- fdpass_close(f);
- return;
- }
- fd = mio_rmidi_getfd(path, mode, 1);
+ fd = mio_rmidi_getfd(p->path, mode, 1);
break;
case FDPASS_OPEN_CTL:
d = dev_bynum(num);
@@ -377,21 +355,13 @@ fdpass_in_helper(void *arg)
fdpass_close(f);
return;
}
- for (da = d->alt_list; ; da = da->next) {
- if (da == NULL) {
- fdpass_close(f);
- return;
- }
- if (da->idx == idx)
- break;
- }
- fd = sioctl_sun_getfd(da->name, mode, 1);
+ fd = sioctl_sun_getfd(d->path, mode, 1);
break;
default:
fdpass_close(f);
return;
}
- fdpass_send(f, FDPASS_RETURN, 0, 0, 0, fd);
+ fdpass_send(f, FDPASS_RETURN, 0, 0, fd);
}
void
diff --git a/usr.bin/sndiod/fdpass.h b/usr.bin/sndiod/fdpass.h
index e11926e26b0..fec1a23813b 100644
--- a/usr.bin/sndiod/fdpass.h
+++ b/usr.bin/sndiod/fdpass.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdpass.h,v 1.3 2020/02/26 13:53:58 ratchov Exp $ */
+/* $OpenBSD: fdpass.h,v 1.4 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
*
@@ -25,8 +25,8 @@ void fdpass_close(struct fdpass *f);
extern struct fileops worker_fileops, helper_fileops;
extern struct fdpass *fdpass_peer;
-struct sio_hdl *fdpass_sio_open(int, int, unsigned int);
-struct mio_hdl *fdpass_mio_open(int, int, unsigned int);
-struct sioctl_hdl *fdpass_sioctl_open(int, int, unsigned int);
+struct sio_hdl *fdpass_sio_open(int, unsigned int);
+struct mio_hdl *fdpass_mio_open(int, unsigned int);
+struct sioctl_hdl *fdpass_sioctl_open(int, unsigned int);
#endif /* !defined(FDPASS_H) */
diff --git a/usr.bin/sndiod/midi.c b/usr.bin/sndiod/midi.c
index fea9441b2e2..371a830908f 100644
--- a/usr.bin/sndiod/midi.c
+++ b/usr.bin/sndiod/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.28 2021/03/08 09:42:50 ratchov Exp $ */
+/* $OpenBSD: midi.c,v 1.29 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -433,6 +433,45 @@ midi_abort(struct midi *p)
}
}
+/*
+ * connect to "nep" all endpoints currently connected to "oep"
+ */
+void
+midi_migrate(struct midi *oep, struct midi *nep)
+{
+ struct midithru *t;
+ struct midi *ep;
+ int i;
+
+ for (i = 0; i < MIDITHRU_NMAX; i++) {
+ t = midithru + i;
+ if (t->txmask & oep->self) {
+ t->txmask &= ~oep->self;
+ t->txmask |= nep->self;
+ }
+ if (t->rxmask & oep->self) {
+ t->rxmask &= ~oep->self;
+ t->rxmask |= nep->self;
+ }
+ }
+
+ for (i = 0; i < MIDI_NEP; i++) {
+ ep = midi_ep + i;
+ if (ep->txmask & oep->self) {
+ ep->txmask &= ~oep->self;
+ ep->txmask |= nep->self;
+ }
+ }
+
+ for (i = 0; i < MIDI_NEP; i++) {
+ ep = midi_ep + i;
+ if (oep->txmask & ep->self) {
+ oep->txmask &= ~ep->self;
+ nep->txmask |= ep->self;
+ }
+ }
+}
+
void
port_log(struct port *p)
{
@@ -482,19 +521,17 @@ port_exit(void *arg)
struct port *
port_new(char *path, unsigned int mode, int hold)
{
- struct port *c, **pc;
+ struct port *c;
c = xmalloc(sizeof(struct port));
- c->path_list = NULL;
- namelist_add(&c->path_list, path);
+ c->path = path;
c->state = PORT_CFG;
c->hold = hold;
c->midi = midi_new(&port_midiops, c, mode);
c->num = midi_portnum++;
- for (pc = &port_list; *pc != NULL; pc = &(*pc)->next)
- ;
- c->next = *pc;
- *pc = c;
+ c->alt_next = c;
+ c->next = port_list;
+ port_list = c;
return c;
}
@@ -518,7 +555,6 @@ port_del(struct port *c)
#endif
}
*p = c->next;
- namelist_clear(&c->path_list);
xfree(c);
}
@@ -555,6 +591,67 @@ port_unref(struct port *c)
}
struct port *
+port_alt_ref(int num)
+{
+ struct port *a, *p;
+
+ a = port_bynum(num);
+ if (a == NULL)
+ return NULL;
+
+ /* circulate to first alt port */
+ while (a->alt_next->num > a->num)
+ a = a->alt_next;
+
+ p = a;
+ while (1) {
+ if (port_ref(p))
+ break;
+ p = p->alt_next;
+ if (p == a)
+ return NULL;
+ }
+
+ return p;
+}
+
+struct port *
+port_migrate(struct port *op)
+{
+ struct port *np;
+
+ /* not opened */
+ if (op->state == PORT_CFG)
+ return op;
+
+ np = op;
+ while (1) {
+ /* try next one, circulating through the list */
+ np = np->alt_next;
+ if (np == op) {
+ if (log_level >= 2) {
+ port_log(op);
+ log_puts(": no fall-back port found\n");
+ }
+ return op;
+ }
+
+ if (port_ref(np))
+ break;
+ }
+
+ if (log_level >= 2) {
+ port_log(op);
+ log_puts(": switching to ");
+ port_log(np);
+ log_puts("\n");
+ }
+
+ midi_migrate(op->midi, np->midi);
+ return np;
+}
+
+struct port *
port_bynum(int num)
{
struct port *p;
@@ -590,6 +687,8 @@ port_close(struct port *c)
panic();
}
#endif
+ port_log(c);
+ log_puts(": closed\n");
c->state = PORT_CFG;
port_mio_close(c);
return 1;
@@ -627,15 +726,3 @@ port_done(struct port *c)
if (c->state == PORT_INIT)
port_drain(c);
}
-
-int
-port_reopen(struct port *p)
-{
- if (p->state == PORT_CFG)
- return 1;
-
- if (!port_mio_reopen(p))
- return 0;
-
- return 1;
-}
diff --git a/usr.bin/sndiod/midi.h b/usr.bin/sndiod/midi.h
index c8b7d1ed627..cd398de4ca5 100644
--- a/usr.bin/sndiod/midi.h
+++ b/usr.bin/sndiod/midi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.h,v 1.14 2021/01/28 11:17:58 ratchov Exp $ */
+/* $OpenBSD: midi.h,v 1.15 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -89,7 +89,8 @@ struct port {
#define PORT_DRAIN 2
unsigned int state;
unsigned int num; /* port serial number */
- struct name *path_list;
+ char *path;
+ struct port *alt_next;
int hold; /* hold the port open ? */
struct midi *midi;
};
@@ -113,6 +114,7 @@ void midi_tag(struct midi *, unsigned int);
unsigned int midi_tags(struct midi *);
void midi_link(struct midi *, struct midi *);
void midi_abort(struct midi *);
+void midi_migrate(struct midi *, struct midi *);
void port_log(struct port *);
struct port *port_new(char *, unsigned int, int);
@@ -124,6 +126,7 @@ int port_init(struct port *);
void port_done(struct port *);
void port_drain(struct port *);
int port_close(struct port *);
-int port_reopen(struct port *);
+struct port *port_alt_ref(int);
+struct port *port_migrate(struct port *);
#endif /* !defined(MIDI_H) */
diff --git a/usr.bin/sndiod/miofile.c b/usr.bin/sndiod/miofile.c
index dbfacc4ab1b..f9818745935 100644
--- a/usr.bin/sndiod/miofile.c
+++ b/usr.bin/sndiod/miofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: miofile.c,v 1.8 2021/01/28 11:17:58 ratchov Exp $ */
+/* $OpenBSD: miofile.c,v 1.9 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -45,74 +45,16 @@ struct fileops port_mio_ops = {
port_mio_hup
};
-/*
- * open the port using one of the provided paths
- */
-static struct mio_hdl *
-port_mio_openlist(struct port *c, unsigned int mode)
-{
- struct mio_hdl *hdl;
- struct name *n;
- int idx;
-
- idx = 0;
- n = c->path_list;
- while (1) {
- if (n == NULL)
- break;
- hdl = fdpass_mio_open(c->num, idx, mode);
- if (hdl != NULL) {
- if (log_level >= 2) {
- port_log(c);
- log_puts(": using ");
- log_puts(n->str);
- log_puts("\n");
- }
- return hdl;
- }
- n = n->next;
- idx++;
- }
- return NULL;
-}
-
int
port_mio_open(struct port *p)
{
- p->mio.hdl = port_mio_openlist(p, p->midi->mode);
+ p->mio.hdl = fdpass_mio_open(p->num, p->midi->mode);
if (p->mio.hdl == NULL)
return 0;
p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(p->mio.hdl));
return 1;
}
-/*
- * Open an alternate port. Upon success, close the old port
- * and continue using the new one.
- */
-int
-port_mio_reopen(struct port *p)
-{
- struct mio_hdl *hdl;
-
- hdl = port_mio_openlist(p, p->midi->mode);
- if (hdl == NULL) {
- if (log_level >= 1) {
- port_log(p);
- log_puts(": couldn't open an alternate port\n");
- }
- return 0;
- }
-
- /* close unused device */
- file_del(p->mio.file);
- mio_close(p->mio.hdl);
-
- p->mio.hdl = hdl;
- p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(hdl));
- return 1;
-}
-
void
port_mio_close(struct port *p)
{
@@ -187,9 +129,8 @@ port_mio_hup(void *arg)
{
struct port *p = arg;
- if (!port_reopen(p)) {
- midi_abort(p->midi);
- if (p->state != PORT_CFG)
- port_close(p);
- }
+ port_migrate(p);
+ midi_abort(p->midi);
+ if (p->state != PORT_CFG)
+ port_close(p);
}
diff --git a/usr.bin/sndiod/miofile.h b/usr.bin/sndiod/miofile.h
index 703caa023d5..fd307dc1307 100644
--- a/usr.bin/sndiod/miofile.h
+++ b/usr.bin/sndiod/miofile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: miofile.h,v 1.2 2019/09/21 04:42:46 ratchov Exp $ */
+/* $OpenBSD: miofile.h,v 1.3 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -25,7 +25,6 @@ struct port_mio {
};
int port_mio_open(struct port *);
-int port_mio_reopen(struct port *);
void port_mio_close(struct port *);
#endif /* !defined(MIOFILE_H) */
diff --git a/usr.bin/sndiod/opt.c b/usr.bin/sndiod/opt.c
index 99621d738d1..0dfd8baa33f 100644
--- a/usr.bin/sndiod/opt.c
+++ b/usr.bin/sndiod/opt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: opt.c,v 1.8 2021/03/03 10:19:06 ratchov Exp $ */
+/* $OpenBSD: opt.c,v 1.9 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2011 Alexandre Ratchov <alex@caoua.org>
*
@@ -59,8 +59,7 @@ opt_midi_omsg(void *arg, unsigned char *msg, int len)
chan = msg[0] & MIDI_CHANMASK;
if (chan >= DEV_NSLOT)
return;
- if (slot_array[chan].opt == NULL ||
- slot_array[chan].opt->dev != o->dev)
+ if (slot_array[chan].opt != o)
return;
slot_setvol(slot_array + chan, msg[2]);
ctl_onval(CTL_SLOT_LEVEL, slot_array + chan, NULL, msg[2]);
@@ -91,6 +90,7 @@ opt_midi_omsg(void *arg, unsigned char *msg, int len)
return;
if (o->mtc == NULL)
return;
+ mtc_setdev(o->mtc, o->dev);
if (log_level >= 2) {
log_puts(o->name);
log_puts(": mmc stop\n");
@@ -102,6 +102,7 @@ opt_midi_omsg(void *arg, unsigned char *msg, int len)
return;
if (o->mtc == NULL)
return;
+ mtc_setdev(o->mtc, o->dev);
if (log_level >= 2) {
log_puts(o->name);
log_puts(": mmc start\n");
@@ -115,6 +116,7 @@ opt_midi_omsg(void *arg, unsigned char *msg, int len)
return;
if (o->mtc == NULL)
return;
+ mtc_setdev(o->mtc, o->dev);
switch (x->u.loc.hr >> 5) {
case MTC_FPS_24:
fps = 24;
@@ -173,22 +175,28 @@ opt_new(struct dev *d, char *name,
int pmin, int pmax, int rmin, int rmax,
int maxweight, int mmc, int dup, unsigned int mode)
{
+ struct dev *a;
struct opt *o, **po;
unsigned int len, num;
char c;
- for (len = 0; name[len] != '\0'; len++) {
- if (len == OPT_NAMEMAX) {
- log_puts(name);
- log_puts(": too long\n");
- return NULL;
- }
- c = name[len];
- if ((c < 'a' || c > 'z') &&
- (c < 'A' || c > 'Z')) {
- log_puts(name);
- log_puts(": only alphabetic chars allowed\n");
- return NULL;
+ if (name == NULL) {
+ name = d->name;
+ len = strlen(name);
+ } else {
+ for (len = 0; name[len] != '\0'; len++) {
+ if (len == OPT_NAMEMAX) {
+ log_puts(name);
+ log_puts(": too long\n");
+ return NULL;
+ }
+ c = name[len];
+ if ((c < 'a' || c > 'z') &&
+ (c < 'A' || c > 'Z')) {
+ log_puts(name);
+ log_puts(": only alphabetic chars allowed\n");
+ return NULL;
+ }
}
}
num = 0;
@@ -199,9 +207,8 @@ opt_new(struct dev *d, char *name,
log_puts(": too many opts\n");
return NULL;
}
- if (opt_byname(d, name)) {
- dev_log(d);
- log_puts(".");
+
+ if (opt_byname(name)) {
log_puts(name);
log_puts(": already defined\n");
return NULL;
@@ -220,9 +227,18 @@ opt_new(struct dev *d, char *name,
}
}
+ if (strcmp(d->name, name) == 0)
+ a = d;
+ else {
+ /* circulate to the first "alternate" device (greatest num) */
+ for (a = d; a->alt_next->num > a->num; a = a->alt_next)
+ ;
+ }
+
o = xmalloc(sizeof(struct opt));
o->num = num;
- o->dev = d;
+ o->alt_first = o->dev = a;
+ o->refcnt = 0;
/*
* XXX: below, we allocate a midi input buffer, since we don't
@@ -286,19 +302,29 @@ opt_new(struct dev *d, char *name,
}
struct opt *
-opt_byname(struct dev *d, char *name)
+opt_byname(char *name)
{
struct opt *o;
for (o = opt_list; o != NULL; o = o->next) {
- if (d != NULL && o->dev != d)
- continue;
if (strcmp(name, o->name) == 0)
return o;
}
return NULL;
}
+struct opt *
+opt_bynum(int num)
+{
+ struct opt *o;
+
+ for (o = opt_list; o != NULL; o = o->next) {
+ if (o->num == num)
+ return o;
+ }
+ return NULL;
+}
+
void
opt_del(struct opt *o)
{
@@ -316,3 +342,174 @@ opt_del(struct opt *o)
*po = o->next;
xfree(o);
}
+
+void
+opt_init(struct opt *o)
+{
+ struct dev *d;
+
+ if (strcmp(o->name, o->dev->name) != 0) {
+ for (d = dev_list; d != NULL; d = d->next) {
+ ctl_new(CTL_OPT_DEV, o, d,
+ CTL_SEL, o->name, "server", -1, "device",
+ d->name, -1, 1, o->dev == d);
+ }
+ }
+}
+
+void
+opt_done(struct opt *o)
+{
+ struct dev *d;
+
+ if (o->refcnt != 0) {
+ // XXX: all clients are already kicked, so this never happens
+ log_puts(o->name);
+ log_puts(": still has refs\n");
+ }
+ for (d = dev_list; d != NULL; d = d->next)
+ ctl_del(CTL_OPT_DEV, o, d);
+}
+
+/*
+ * Set opt's device, and (if necessary) move clients to
+ * to the new device
+ */
+void
+opt_setdev(struct opt *o, struct dev *ndev)
+{
+ struct dev *odev;
+ struct ctl *c;
+ struct ctlslot *p;
+ struct slot *s;
+ int i;
+
+ if (!dev_ref(ndev))
+ return;
+
+ odev = o->dev;
+ if (odev == ndev) {
+ dev_unref(ndev);
+ return;
+ }
+
+ /* check if clients can use new device */
+ for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
+ if (s->opt != o)
+ continue;
+ if (s->ops != NULL && !dev_iscompat(odev, ndev)) {
+ dev_unref(ndev);
+ return;
+ }
+ }
+
+ /*
+ * if we're using MMC, move all opts to the new device, mtc_setdev()
+ * will call us back
+ */
+ if (o->mtc != NULL && o->mtc->dev != ndev) {
+ mtc_setdev(o->mtc, ndev);
+ dev_unref(ndev);
+ return;
+ }
+
+ c = ctl_find(CTL_OPT_DEV, o, o->dev);
+ if (c != NULL)
+ c->curval = 0;
+
+ /* detach clients from old device */
+ for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
+ if (s->opt != o)
+ continue;
+
+ if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP)
+ slot_detach(s);
+ }
+
+ o->dev = ndev;
+
+ if (o->refcnt > 0) {
+ dev_unref(odev);
+ dev_ref(o->dev);
+ }
+
+ c = ctl_find(CTL_OPT_DEV, o, o->dev);
+ if (c != NULL) {
+ c->curval = 1;
+ c->val_mask = ~0;
+ }
+
+ /* attach clients to new device */
+ for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
+ if (s->opt != o)
+ continue;
+
+ if (ndev != odev) {
+ dev_midi_slotdesc(odev, s);
+ dev_midi_slotdesc(ndev, s);
+ dev_midi_vol(ndev, s);
+ }
+
+ c = ctl_find(CTL_SLOT_LEVEL, s, NULL);
+ ctl_update(c);
+
+ if (s->pstate == SLOT_RUN || s->pstate == SLOT_STOP) {
+ slot_initconv(s);
+ slot_attach(s);
+ }
+ }
+
+ /* move controlling clients to new device */
+ for (p = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, p++) {
+ if (p->ops == NULL)
+ continue;
+ if (p->opt == o)
+ ctlslot_update(p);
+ }
+
+ dev_unref(ndev);
+}
+
+/*
+ * Get a reference to opt's device
+ */
+struct dev *
+opt_ref(struct opt *o)
+{
+ struct dev *d;
+
+ if (o->refcnt == 0) {
+ if (strcmp(o->name, o->dev->name) == 0) {
+ if (!dev_ref(o->dev))
+ return NULL;
+ } else {
+ /* find first working one */
+ d = o->alt_first;
+ while (1) {
+ if (dev_ref(d))
+ break;
+ d = d->alt_next;
+ if (d == o->alt_first)
+ return NULL;
+ }
+
+ /* if device changed, move everything to the new one */
+ if (d != o->dev)
+ opt_setdev(o, d);
+ }
+ }
+
+ o->refcnt++;
+ return o->dev;
+}
+
+/*
+ * Release opt's device
+ */
+void
+opt_unref(struct opt *o)
+{
+ o->refcnt--;
+ if (o->refcnt == 0)
+ dev_unref(o->dev);
+}
diff --git a/usr.bin/sndiod/opt.h b/usr.bin/sndiod/opt.h
index bb56f445100..7dd9e2f7c71 100644
--- a/usr.bin/sndiod/opt.h
+++ b/usr.bin/sndiod/opt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: opt.h,v 1.6 2021/03/03 10:19:06 ratchov Exp $ */
+/* $OpenBSD: opt.h,v 1.7 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -23,7 +23,7 @@ struct dev;
struct opt {
struct opt *next;
- struct dev *dev;
+ struct dev *dev, *alt_first;
struct midi *midi;
struct mtc *mtc; /* if set, MMC-controlled MTC source */
@@ -35,6 +35,7 @@ struct opt {
int rmin, rmax; /* recording channels */
int dup; /* true if join/expand enabled */
int mode; /* bitmap of MODE_XXX */
+ int refcnt;
};
extern struct opt *opt_list;
@@ -42,6 +43,12 @@ extern struct opt *opt_list;
struct opt *opt_new(struct dev *, char *, int, int, int, int,
int, int, int, unsigned int);
void opt_del(struct opt *);
-struct opt *opt_byname(struct dev *, char *);
+struct opt *opt_byname(char *);
+struct opt *opt_bynum(int);
+void opt_init(struct opt *);
+void opt_done(struct opt *);
+void opt_setdev(struct opt *, struct dev *);
+struct dev *opt_ref(struct opt *);
+void opt_unref(struct opt *);
#endif /* !defined(OPT_H) */
diff --git a/usr.bin/sndiod/siofile.c b/usr.bin/sndiod/siofile.c
index 3cc939427b2..48bf8623c25 100644
--- a/usr.bin/sndiod/siofile.c
+++ b/usr.bin/sndiod/siofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siofile.c,v 1.24 2021/03/03 10:00:27 ratchov Exp $ */
+/* $OpenBSD: siofile.c,v 1.25 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -87,24 +87,25 @@ dev_sio_timeout(void *arg)
dev_abort(d);
}
-static int
-dev_sio_openalt(struct dev *d, struct dev_alt *n,
- struct sio_hdl **rhdl, struct sioctl_hdl **rctlhdl, unsigned int *rmode)
+/*
+ * open the device.
+ */
+int
+dev_sio_open(struct dev *d)
{
- struct sio_hdl *hdl;
- struct sioctl_hdl *ctlhdl;
- unsigned int mode = d->reqmode & (MODE_PLAY | MODE_REC);
+ struct sio_par par;
+ unsigned int rate, mode = d->reqmode & (SIO_PLAY | SIO_REC);
- hdl = fdpass_sio_open(d->num, n->idx, mode);
- if (hdl == NULL) {
+ d->sio.hdl = fdpass_sio_open(d->num, mode);
+ if (d->sio.hdl == NULL) {
if (mode != (SIO_PLAY | SIO_REC))
return 0;
- hdl = fdpass_sio_open(d->num, n->idx, SIO_PLAY);
- if (hdl != NULL)
+ d->sio.hdl = fdpass_sio_open(d->num, SIO_PLAY);
+ if (d->sio.hdl != NULL)
mode = SIO_PLAY;
else {
- hdl = fdpass_sio_open(d->num, n->idx, SIO_REC);
- if (hdl != NULL)
+ d->sio.hdl = fdpass_sio_open(d->num, SIO_REC);
+ if (d->sio.hdl != NULL)
mode = SIO_REC;
else
return 0;
@@ -115,76 +116,16 @@ dev_sio_openalt(struct dev *d, struct dev_alt *n,
log_puts(" mode\n");
}
}
+ d->mode = mode;
- ctlhdl = fdpass_sioctl_open(d->num, n->idx, SIOCTL_READ | SIOCTL_WRITE);
- if (ctlhdl == NULL) {
+ d->sioctl.hdl = fdpass_sioctl_open(d->num, SIOCTL_READ | SIOCTL_WRITE);
+ if (d->sioctl.hdl == NULL) {
if (log_level >= 1) {
dev_log(d);
log_puts(": no control device\n");
}
}
- *rhdl = hdl;
- *rctlhdl = ctlhdl;
- *rmode = mode;
- return 1;
-}
-
-/*
- * open the device using one of the provided paths
- */
-static int
-dev_sio_openlist(struct dev *d,
- struct sio_hdl **rhdl, struct sioctl_hdl **rctlhdl, unsigned int *rmode)
-{
- struct dev_alt *n;
- struct ctl *c;
- int val;
-
- for (n = d->alt_list; n != NULL; n = n->next) {
- if (d->alt_num == n->idx)
- continue;
- if (log_level >= 2) {
- dev_log(d);
- log_puts(": trying ");
- log_puts(n->name);
- log_puts("\n");
- }
- if (dev_sio_openalt(d, n, rhdl, rctlhdl, rmode)) {
- if (log_level >= 2) {
- dev_log(d);
- log_puts(": using ");
- log_puts(n->name);
- log_puts("\n");
- }
- d->alt_num = n->idx;
- for (c = ctl_list; c != NULL; c = c->next) {
- if (!ctl_match(c, CTL_DEV_ALT, d, NULL))
- continue;
- val = c->u.dev_alt.idx == n->idx;
- if (c->curval == val)
- continue;
- c->curval = val;
- if (val)
- c->val_mask = ~0U;
- }
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * open the device.
- */
-int
-dev_sio_open(struct dev *d)
-{
- struct sio_par par;
-
- if (!dev_sio_openlist(d, &d->sio.hdl, &d->sioctl.hdl, &d->mode))
- return 0;
-
sio_initpar(&par);
par.bits = d->par.bits;
par.bps = d->par.bps;
@@ -195,17 +136,40 @@ dev_sio_open(struct dev *d)
par.pchan = d->pchan;
if (d->mode & SIO_REC)
par.rchan = d->rchan;
- if (d->bufsz)
- par.appbufsz = d->bufsz;
- if (d->round)
- par.round = d->round;
- if (d->rate)
- par.rate = d->rate;
+ par.appbufsz = d->bufsz;
+ par.round = d->round;
+ par.rate = d->rate;
if (!sio_setpar(d->sio.hdl, &par))
goto bad_close;
if (!sio_getpar(d->sio.hdl, &par))
goto bad_close;
+ /*
+ * If the requested rate is not supported by the device,
+ * use the new one, but retry using a block size that would
+ * match the requested one
+ */
+ rate = par.rate;
+ if (rate != d->rate) {
+ sio_initpar(&par);
+ par.bits = d->par.bits;
+ par.bps = d->par.bps;
+ par.sig = d->par.sig;
+ par.le = d->par.le;
+ par.msb = d->par.msb;
+ if (mode & SIO_PLAY)
+ par.pchan = d->reqpchan;
+ if (mode & SIO_REC)
+ par.rchan = d->reqrchan;
+ par.appbufsz = d->bufsz * rate / d->rate;
+ par.round = d->round * rate / d->rate;
+ par.rate = rate;
+ if (!sio_setpar(d->sio.hdl, &par))
+ goto bad_close;
+ if (!sio_getpar(d->sio.hdl, &par))
+ goto bad_close;
+ }
+
#ifdef DEBUG
/*
* We support any parameter combination exposed by the kernel,
@@ -266,7 +230,6 @@ dev_sio_open(struct dev *d)
goto bad_close;
}
#endif
-
d->par.bits = par.bits;
d->par.bps = par.bps;
d->par.sig = par.sig;
@@ -299,88 +262,6 @@ dev_sio_open(struct dev *d)
return 0;
}
-/*
- * Open an alternate device. Upon success and if the new device is
- * compatible with the old one, close the old device and continue
- * using the new one. The new device is not started.
- */
-int
-dev_sio_reopen(struct dev *d)
-{
- struct sio_par par;
- struct sio_hdl *hdl;
- struct sioctl_hdl *ctlhdl;
- unsigned int mode;
-
- if (!dev_sio_openlist(d, &hdl, &ctlhdl, &mode))
- return 0;
-
- sio_initpar(&par);
- par.bits = d->par.bits;
- par.bps = d->par.bps;
- par.sig = d->par.sig;
- par.le = d->par.le;
- par.msb = d->par.msb;
- if (mode & SIO_PLAY)
- par.pchan = d->reqpchan;
- if (mode & SIO_REC)
- par.rchan = d->reqrchan;
- par.appbufsz = d->bufsz;
- par.round = d->round;
- par.rate = d->rate;
- if (!sio_setpar(hdl, &par))
- goto bad_close;
- if (!sio_getpar(hdl, &par))
- goto bad_close;
-
- /* check if new parameters are compatible with old ones */
- if (par.round != d->round || par.bufsz != d->bufsz ||
- par.rate != d->rate) {
- if (log_level >= 1) {
- dev_log(d);
- log_puts(": alternate device not compatible\n");
- }
- goto bad_close;
- }
-
- /* close unused device */
- timo_del(&d->sio.watchdog);
- file_del(d->sio.file);
- sio_close(d->sio.hdl);
- if (d->sioctl.hdl) {
- file_del(d->sioctl.file);
- sioctl_close(d->sioctl.hdl);
- d->sioctl.hdl = NULL;
- }
-
- /* update parameters */
- d->mode = mode;
- d->par.bits = par.bits;
- d->par.bps = par.bps;
- d->par.sig = par.sig;
- d->par.le = par.le;
- d->par.msb = par.msb;
- if (d->mode & SIO_PLAY)
- d->pchan = par.pchan;
- if (d->mode & SIO_REC)
- d->rchan = par.rchan;
-
- d->sio.hdl = hdl;
- d->sioctl.hdl = ctlhdl;
- d->sio.file = file_new(&dev_sio_ops, d, "dev", sio_nfds(hdl));
- if (d->sioctl.hdl) {
- d->sioctl.file = file_new(&dev_sioctl_ops, d, "mix",
- sioctl_nfds(ctlhdl));
- }
- sio_onmove(hdl, dev_sio_onmove, d);
- return 1;
-bad_close:
- sio_close(hdl);
- if (ctlhdl)
- sioctl_close(ctlhdl);
- return 0;
-}
-
void
dev_sio_close(struct dev *d)
{
@@ -399,7 +280,6 @@ dev_sio_close(struct dev *d)
sioctl_close(d->sioctl.hdl);
d->sioctl.hdl = NULL;
}
- d->alt_num = -1;
}
void
@@ -662,6 +542,6 @@ dev_sio_hup(void *arg)
log_puts(": disconnected\n");
}
#endif
- if (!dev_reopen(d))
- dev_abort(d);
+ dev_migrate(d);
+ dev_abort(d);
}
diff --git a/usr.bin/sndiod/siofile.h b/usr.bin/sndiod/siofile.h
index 4cebf879730..c34f922d523 100644
--- a/usr.bin/sndiod/siofile.h
+++ b/usr.bin/sndiod/siofile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: siofile.h,v 1.4 2019/09/21 04:42:46 ratchov Exp $ */
+/* $OpenBSD: siofile.h,v 1.5 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -38,7 +38,6 @@ struct dev_sio {
};
int dev_sio_open(struct dev *);
-int dev_sio_reopen(struct dev *);
void dev_sio_close(struct dev *);
void dev_sio_log(struct dev *);
void dev_sio_start(struct dev *);
diff --git a/usr.bin/sndiod/sndiod.c b/usr.bin/sndiod/sndiod.c
index ad6a2cce7c3..96088e33c04 100644
--- a/usr.bin/sndiod/sndiod.c
+++ b/usr.bin/sndiod/sndiod.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sndiod.c,v 1.46 2021/07/12 15:09:20 beck Exp $ */
+/* $OpenBSD: sndiod.c,v 1.47 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -318,8 +318,7 @@ mkdev(char *path, struct aparams *par,
struct dev *d;
for (d = dev_list; d != NULL; d = d->next) {
- if (d->alt_list->next == NULL &&
- strcmp(d->alt_list->name, path) == 0)
+ if (strcmp(d->path, path) == 0)
return d;
}
if (!bufsz && !round) {
@@ -341,8 +340,7 @@ mkport(char *path, int hold)
struct port *c;
for (c = port_list; c != NULL; c = c->next) {
- if (c->path_list->next == NULL &&
- strcmp(c->path_list->str, path) == 0)
+ if (strcmp(c->path, path) == 0)
return c;
}
c = port_new(path, MODE_MIDIMASK, hold);
@@ -385,10 +383,8 @@ static int
start_helper(int background)
{
struct dev *d;
- struct dev_alt *da;
struct port *p;
struct passwd *pw;
- struct name *n;
int s[2];
pid_t pid;
@@ -424,14 +420,11 @@ start_helper(int background)
err(1, "cannot drop privileges");
}
for (d = dev_list; d != NULL; d = d->next) {
- for (da = d->alt_list; da != NULL; da = da->next) {
- dounveil(da->name, "rsnd/", "/dev/audio");
- dounveil(da->name, "rsnd/", "/dev/audioctl");
- }
+ dounveil(d->path, "rsnd/", "/dev/audio");
+ dounveil(d->path, "rsnd/", "/dev/audioctl");
}
for (p = port_list; p != NULL; p = p->next) {
- for (n = p->path_list; n != NULL; n = n->next)
- dounveil(n->str, "rmidi/", "/dev/rmidi");
+ dounveil(p->path, "rmidi/", "/dev/rmidi");
}
if (pledge("stdio sendfd rpath wpath", NULL) == -1)
err(1, "pledge");
@@ -461,10 +454,12 @@ main(int argc, char **argv)
char base[SOCKPATH_MAX], path[SOCKPATH_MAX];
unsigned int mode, dup, mmc, vol;
unsigned int hold, autovol, bufsz, round, rate;
+ unsigned int reopen_list;
const char *str;
struct aparams par;
- struct dev *d;
- struct port *p;
+ struct opt *o;
+ struct dev *d, *dev_first, *dev_next;
+ struct port *p, *port_first, *port_next;
struct listen *l;
struct passwd *pw;
struct tcpaddr {
@@ -493,6 +488,8 @@ main(int argc, char **argv)
rmax = 1;
aparams_init(&par);
mode = MODE_PLAY | MODE_REC;
+ dev_first = dev_next = NULL;
+ port_first = port_next = NULL;
tcpaddr_list = NULL;
d = NULL;
p = NULL;
@@ -559,11 +556,17 @@ main(int argc, char **argv)
break;
case 'q':
p = mkport(optarg, hold);
+ /* create new circulate list */
+ port_first = port_next = p;
break;
case 'Q':
if (p == NULL)
errx(1, "-Q %s: no ports defined", optarg);
- namelist_add(&p->path_list, optarg);
+ p = mkport(optarg, hold);
+ /* add to circulate list */
+ p->alt_next = port_next;
+ port_first->alt_next = p;
+ port_next = p;
break;
case 'a':
hold = opt_onoff();
@@ -584,12 +587,18 @@ main(int argc, char **argv)
case 'f':
d = mkdev(optarg, &par, 0, bufsz, round,
rate, hold, autovol);
+ /* create new circulate list */
+ dev_first = dev_next = d;
break;
case 'F':
if (d == NULL)
errx(1, "-F %s: no devices defined", optarg);
- if (!dev_addname(d, optarg))
- exit(1);
+ d = mkdev(optarg, &par, 0, bufsz, round,
+ rate, hold, autovol);
+ /* add to circulate list */
+ d->alt_next = dev_next;
+ dev_first->alt_next = d;
+ dev_next = d;
break;
default:
fputs(usagestr, stderr);
@@ -612,12 +621,27 @@ main(int argc, char **argv)
bufsz, round, rate, 0, autovol);
}
}
+
+ /*
+ * Add default sub-device (if none) backed by the last device
+ */
+ o = opt_byname("default");
+ if (o == NULL) {
+ o = mkopt("default", dev_list, pmin, pmax, rmin, rmax,
+ mode, vol, 0, dup);
+ if (o == NULL)
+ return 1;
+ }
+
+ /*
+ * For each device create an anonymous sub-device using
+ * the "default" sub-device as template
+ */
for (d = dev_list; d != NULL; d = d->next) {
- if (opt_byname(d, "default"))
- continue;
- if (mkopt("default", d, pmin, pmax, rmin, rmax,
- mode, vol, mmc, dup) == NULL)
+ if (opt_new(d, NULL, o->pmin, o->pmax, o->rmin, o->rmax,
+ o->maxweight, o->mtc != NULL, o->dup, o->mode) == NULL)
return 1;
+ dev_adjpar(d, o->mode, o->pmax, o->rmax);
}
setsig();
@@ -652,6 +676,8 @@ main(int argc, char **argv)
if (!dev_init(d))
return 1;
}
+ for (o = opt_list; o != NULL; o = o->next)
+ opt_init(o);
if (background) {
log_flush();
log_level = 0;
@@ -680,10 +706,28 @@ main(int argc, char **argv)
break;
if (reopen_flag) {
reopen_flag = 0;
- for (d = dev_list; d != NULL; d = d->next)
- dev_reopen(d);
- for (p = port_list; p != NULL; p = p->next)
- port_reopen(p);
+
+ reopen_list = 0;
+ for (d = dev_list; d != NULL; d = d->next) {
+ if (d->pstate != DEV_CFG)
+ reopen_list |= (1 << d->num);
+ }
+ for (d = dev_list; d != NULL; d = d->next) {
+ if (reopen_list & (1 << d->num))
+ dev_migrate(d);
+ }
+
+ reopen_list = 0;
+ for (p = port_list; p != NULL; p = p->next) {
+ if (p->state != PORT_CFG)
+ reopen_list |= (1 << p->num);
+ }
+ for (p = port_list; p != NULL; p = p->next) {
+ if (reopen_list & (1 << p->num)) {
+ if (port_migrate(p) != p)
+ port_close(p);
+ }
+ }
}
if (!fdpass_peer)
break;
@@ -695,6 +739,8 @@ main(int argc, char **argv)
listen_close(listen_list);
while (sock_list != NULL)
sock_close(sock_list);
+ for (o = opt_list; o != NULL; o = o->next)
+ opt_done(o);
for (d = dev_list; d != NULL; d = d->next)
dev_done(d);
for (p = port_list; p != NULL; p = p->next)
diff --git a/usr.bin/sndiod/sock.c b/usr.bin/sndiod/sock.c
index c29ea58b621..fcf97cf09fc 100644
--- a/usr.bin/sndiod/sock.c
+++ b/usr.bin/sndiod/sock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sock.c,v 1.44 2021/03/03 10:19:06 ratchov Exp $ */
+/* $OpenBSD: sock.c,v 1.45 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -101,6 +101,48 @@ struct sock *sock_list = NULL;
unsigned int sock_sesrefs = 0; /* connections to the session */
uint8_t sock_sescookie[AMSG_COOKIELEN]; /* owner of the session */
+/*
+ * Old clients used to send dev number and opt name. This routine
+ * finds proper opt pointer for the given device.
+ */
+static struct opt *
+legacy_opt(int devnum, char *optname)
+{
+ struct dev *d;
+ struct opt *o;
+
+ d = dev_bynum(devnum);
+ if (d == NULL)
+ return NULL;
+ if (strcmp(optname, "default") == 0) {
+ for (o = opt_list; o != NULL; o = o->next) {
+ if (strcmp(o->name, d->name) == 0)
+ return o;
+ }
+ return NULL;
+ } else {
+ o = opt_byname(optname);
+ return (o != NULL && o->dev == d) ? o : NULL;
+ }
+}
+
+/*
+ * If control slot is associated to a particular opt, then
+ * remove the unused group part of the control name to make mixer
+ * look nicer
+ */
+static char *
+ctlgroup(struct sock *f, struct ctl *c)
+{
+ if (f->ctlslot->opt == NULL)
+ return c->group;
+ if (strcmp(c->group, f->ctlslot->opt->name) == 0)
+ return "";
+ if (strcmp(c->group, f->ctlslot->opt->dev->name) == 0)
+ return "";
+ return c->group;
+}
+
void
sock_log(struct sock *f)
{
@@ -130,7 +172,7 @@ sock_log(struct sock *f)
void
sock_close(struct sock *f)
{
- struct dev *d;
+ struct opt *o;
struct sock **pf;
unsigned int tags, i;
@@ -159,8 +201,8 @@ sock_close(struct sock *f)
if (f->midi) {
tags = midi_tags(f->midi);
for (i = 0; i < DEV_NMAX; i++) {
- if ((tags & (1 << i)) && (d = dev_bynum(i)) != NULL)
- dev_unref(d);
+ if ((tags & (1 << i)) && (o = opt_bynum(i)) != NULL)
+ opt_unref(o);
}
midi_del(f->midi);
f->midi = NULL;
@@ -818,7 +860,6 @@ sock_hello(struct sock *f)
{
struct amsg_hello *p = &f->rmsg.u.hello;
struct port *c;
- struct dev *d;
struct opt *opt;
unsigned int mode;
unsigned int id;
@@ -876,21 +917,25 @@ sock_hello(struct sock *f)
if (f->midi == NULL)
return 0;
/* XXX: add 'devtype' to libsndio */
- if (p->devnum < 16) {
- d = dev_bynum(p->devnum);
- if (d == NULL)
+ if (p->devnum == AMSG_NODEV) {
+ opt = opt_byname(p->opt);
+ if (opt == NULL)
+ return 0;
+ if (!opt_ref(opt))
return 0;
- opt = opt_byname(d, p->opt);
+ midi_tag(f->midi, opt->num);
+ } else if (p->devnum < 16) {
+ opt = legacy_opt(p->devnum, p->opt);
if (opt == NULL)
return 0;
- if (!dev_ref(d))
+ if (!opt_ref(opt))
return 0;
midi_tag(f->midi, opt->num);
} else if (p->devnum < 32) {
midi_tag(f->midi, p->devnum);
} else if (p->devnum < 48) {
- c = port_bynum(p->devnum - 32);
- if (c == NULL || !port_ref(c))
+ c = port_alt_ref(p->devnum - 32);
+ if (c == NULL)
return 0;
f->port = c;
midi_link(f->midi, c->midi);
@@ -899,19 +944,15 @@ sock_hello(struct sock *f)
return 1;
}
if (mode & MODE_CTLMASK) {
- d = dev_bynum(p->devnum);
- if (d == NULL) {
- if (log_level >= 2) {
- sock_log(f);
- log_puts(": ");
- log_putu(p->devnum);
- log_puts(": no such device\n");
- }
- return 0;
+ if (p->devnum == AMSG_NODEV) {
+ opt = opt_byname(p->opt);
+ if (opt == NULL)
+ return 0;
+ } else {
+ opt = legacy_opt(p->devnum, p->opt);
+ if (opt == NULL)
+ return 0;
}
- opt = opt_byname(d, p->opt);
- if (opt == NULL)
- return 0;
f->ctlslot = ctlslot_new(opt, &sock_ctlops, f);
if (f->ctlslot == NULL) {
if (log_level >= 2) {
@@ -926,10 +967,8 @@ sock_hello(struct sock *f)
f->ctlsyncpending = 0;
return 1;
}
- d = dev_bynum(p->devnum);
- if (d == NULL)
- return 0;
- opt = opt_byname(d, p->opt);
+ opt = (p->devnum == AMSG_NODEV) ?
+ opt_byname(p->opt) : legacy_opt(p->devnum, p->opt);
if (opt == NULL)
return 0;
f->slot = slot_new(opt, id, p->who, &sock_slotops, f, mode);
@@ -1582,10 +1621,7 @@ sock_buildmsg(struct sock *f)
c->val_mask &= ~mask;
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->group, ctlgroup(f, c), AMSG_CTL_NAMEMAX);
strlcpy(desc->node0.name, c->node0.name,
AMSG_CTL_NAMEMAX);
desc->node0.unit = ntohs(c->node0.unit);
diff --git a/usr.bin/sndiod/utils.c b/usr.bin/sndiod/utils.c
index 118f2366b84..228c57001a5 100644
--- a/usr.bin/sndiod/utils.c
+++ b/usr.bin/sndiod/utils.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: utils.c,v 1.7 2020/01/23 05:40:09 ratchov Exp $ */
+/* $OpenBSD: utils.c,v 1.8 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2003-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -188,47 +188,3 @@ xstrdup(char *s)
memcpy(p, s, size);
return p;
}
-
-/*
- * copy and append the given string to the name list
- */
-void
-namelist_add(struct name **list, char *str)
-{
- struct name *n;
- size_t size;
-
- size = strlen(str) + 1;
- n = xmalloc(sizeof(struct name) + size);
- memcpy(n->str, str, size);
- n->next = *list;
- *list = n;
-}
-
-void
-namelist_clear(struct name **list)
-{
- struct name *n;
-
- while ((n = *list) != NULL) {
- *list = n->next;
- xfree(n);
- }
-}
-
-char *
-namelist_byindex(struct name **list, unsigned int idx)
-{
- struct name *n;
-
- n = *list;
- while (1) {
- if (n == NULL)
- return NULL;
- if (idx == 0)
- break;
- n = n->next;
- idx--;
- }
- return n->str;
-}
diff --git a/usr.bin/sndiod/utils.h b/usr.bin/sndiod/utils.h
index ef589f673b7..a3ba936e243 100644
--- a/usr.bin/sndiod/utils.h
+++ b/usr.bin/sndiod/utils.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: utils.h,v 1.5 2020/01/23 05:40:09 ratchov Exp $ */
+/* $OpenBSD: utils.h,v 1.6 2021/11/01 14:43:25 ratchov Exp $ */
/*
* Copyright (c) 2003-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -36,10 +36,6 @@ void *xmalloc(size_t);
char *xstrdup(char *);
void xfree(void *);
-void namelist_add(struct name **, char *);
-void namelist_clear(struct name **);
-char *namelist_byindex(struct name **, unsigned int);
-
/*
* Log levels:
*