Allow alternate devices to be switched with sndioctl

This commit is contained in:
Alexandre Ratchov 2020-06-18 06:27:36 +02:00
parent 2494f95430
commit 9a446c6b72
4 changed files with 62 additions and 3 deletions

View File

@ -68,6 +68,7 @@ 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 *);
void dev_sync_attach(struct dev *);
@ -1088,6 +1089,30 @@ dev_addname(struct dev *d, char *name)
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
*/
@ -1177,6 +1202,7 @@ dev_open(struct dev *d)
{
int i;
char name[CTL_NAMEMAX];
struct dev_alt *a;
d->master_enabled = 0;
d->mode = d->reqmode;
@ -1210,6 +1236,15 @@ dev_open(struct dev *d)
NULL, -1, 127, d->slot[i].vol);
}
for (a = d->alt_list; a != NULL; a = a->next) {
/* XXX: may already exist, move to hw/ group ? */
snprintf(name, sizeof(name), "%d", a->idx);
dev_addctl(d, "", CTL_SEL,
CTLADDR_ALT_SEL + a->idx,
"device", -1, "select",
name, -1, 1, a->idx == d->alt_num);
}
d->pstate = DEV_INIT;
return 1;
}
@ -2473,7 +2508,13 @@ dev_setctl(struct dev *d, int addr, int val)
c->dirty = 1;
dev_ref(d);
} else {
if (addr == CTLADDR_MASTER) {
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);

View File

@ -24,7 +24,8 @@
#define CTLADDR_SLOT_LEVEL(n) (n)
#define CTLADDR_MASTER (DEV_NSLOT)
#define CTLADDR_END (DEV_NSLOT + 1)
#define CTLADDR_ALT_SEL (CTLADDR_MASTER + 1)
#define CTLADDR_END (CTLADDR_ALT_SEL + DEV_NMAX)
/*
* audio stream state structure

View File

@ -95,7 +95,8 @@ dev_sio_openlist(struct dev *d, unsigned int mode, struct sioctl_hdl **rctlhdl)
struct dev_alt *n;
struct sio_hdl *hdl;
struct sioctl_hdl *ctlhdl;
int idx;
struct ctl *c;
int val;
for (n = d->alt_list; n != NULL; n = n->next) {
if (d->alt_num == n->idx)
@ -117,6 +118,17 @@ dev_sio_openlist(struct dev *d, unsigned int mode, struct sioctl_hdl **rctlhdl)
}
}
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)
continue;
val = (c->addr - CTLADDR_ALT_SEL) == n->idx;
if (c->curval == val)
continue;
c->curval = val;
if (val)
c->val_mask = ~0U;
}
*rctlhdl = ctlhdl;
return hdl;
}

View File

@ -196,6 +196,11 @@ PCI device allows
.Nm
to use the USB one preferably when it's connected
and to fall back to the PCI one when it's disconnected.
Alternate devices may be switched with the
.Va device.select
control of the
.Xr sndioctl 1
utility.
.It Fl f Ar device
Add this
.Xr sndio 7