Page MenuHomeFreeBSD

D45256.diff
No OneTemporary

D45256.diff

diff --git a/lib/libmixer/mixer.3 b/lib/libmixer/mixer.3
--- a/lib/libmixer/mixer.3
+++ b/lib/libmixer/mixer.3
@@ -20,7 +20,7 @@
.\" THE SOFTWARE.
.\"
-.Dd January 19, 2023
+.Dd May 22, 2024
.Dt MIXER 3
.Os
.Sh NAME
@@ -395,7 +395,10 @@
.Pp
The
.Fn mixer_get_nmixers
-function returns the total number of mixer devices in the system.
+function returns the maximum mixer unit number.
+Although this might sound as incorrect behavior, given that one would expect
+"nmixers" to refer to the total number of active mixers, it is more intuitive
+for applications that want to loop through all mixer devices.
.Pp
The
.Fn MIX_ISDEV
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -2040,6 +2040,19 @@
return (NULL);
}
+static void
+dsp_oss_audioinfo_unavail(oss_audioinfo *ai, int unit)
+{
+ bzero(ai, sizeof(*ai));
+ ai->dev = unit;
+ snprintf(ai->name, sizeof(ai->name), "pcm%d (unavailable)", unit);
+ ai->pid = -1;
+ ai->card_number = unit;
+ ai->port_number = unit;
+ ai->mixer_dev = -1;
+ ai->legacy_device = unit;
+}
+
/**
* @brief Handler for SNDCTL_AUDIOINFO.
*
@@ -2084,8 +2097,14 @@
unit < devclass_get_maxunit(pcm_devclass); unit++) {
d = devclass_get_softc(pcm_devclass, unit);
if (!PCM_REGISTERED(d)) {
- d = NULL;
- continue;
+ if ((ai->dev == -1 && unit == snd_unit) ||
+ ai->dev == unit) {
+ dsp_oss_audioinfo_unavail(ai, unit);
+ return (0);
+ } else {
+ d = NULL;
+ continue;
+ }
}
PCM_UNLOCKASSERT(d);
diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
--- a/sys/dev/sound/pcm/mixer.h
+++ b/sys/dev/sound/pcm/mixer.h
@@ -69,8 +69,6 @@
void *mix_getdevinfo(struct snd_mixer *m);
struct mtx *mixer_get_lock(struct snd_mixer *m);
-extern int mixer_count;
-
#define MIXER_CMD_DIRECT 0 /* send command within driver */
#define MIXER_CMD_CDEV 1 /* send command from cdev/ioctl */
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -105,11 +105,6 @@
.d_name = "mixer",
};
-/**
- * Keeps a count of mixer devices; used only by OSSv4 SNDCTL_SYSINFO ioctl.
- */
-int mixer_count = 0;
-
static eventhandler_tag mixer_ehtag = NULL;
static struct cdev *
@@ -701,22 +696,13 @@
snd_mtxfree(m->lock);
kobj_delete((kobj_t)m, M_MIXER);
- --mixer_count;
-
return (0);
}
struct snd_mixer *
mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
{
- struct snd_mixer *m;
-
- m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc);
-
- if (m != NULL)
- ++mixer_count;
-
- return (m);
+ return (mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc));
}
int
@@ -769,8 +755,6 @@
pdev->si_drv1 = m;
snddev->mixer_dev = pdev;
- ++mixer_count;
-
if (bootverbose) {
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
if (!(m->devs & (1 << i)))
@@ -839,8 +823,6 @@
d->mixer_dev = NULL;
- --mixer_count;
-
return 0;
}
@@ -1411,6 +1393,17 @@
SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL);
SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL);
+static void
+mixer_oss_mixerinfo_unavail(oss_mixerinfo *mi, int unit)
+{
+ bzero(mi, sizeof(*mi));
+ mi->dev = unit;
+ snprintf(mi->id, sizeof(mi->id), "mixer%d (n/a)", unit);
+ snprintf(mi->name, sizeof(mi->name), "pcm%d:mixer (unavailable)", unit);
+ mi->card_number = unit;
+ mi->legacy_device = unit;
+}
+
/**
* @brief Handler for SNDCTL_MIXERINFO
*
@@ -1454,8 +1447,13 @@
for (i = 0; pcm_devclass != NULL &&
i < devclass_get_maxunit(pcm_devclass); i++) {
d = devclass_get_softc(pcm_devclass, i);
- if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
- continue;
+ if (!PCM_REGISTERED(d) || PCM_DETACHING(d)) {
+ if ((mi->dev == -1 && i == snd_unit) || mi->dev == i) {
+ mixer_oss_mixerinfo_unavail(mi, i);
+ return (0);
+ } else
+ continue;
+ }
/* XXX Need Giant magic entry */
@@ -1463,89 +1461,96 @@
PCM_UNLOCKASSERT(d);
PCM_LOCK(d);
- if (d->mixer_dev != NULL && d->mixer_dev->si_drv1 != NULL &&
- ((mi->dev == -1 && d->mixer_dev == i_dev) ||
+ if (!((d->mixer_dev == i_dev && mi->dev == -1) ||
mi->dev == i)) {
- m = d->mixer_dev->si_drv1;
- mtx_lock(m->lock);
-
- /*
- * At this point, the following synchronization stuff
- * has happened:
- * - a specific PCM device is locked.
- * - a specific mixer device has been locked, so be
- * sure to unlock when existing.
- */
- bzero((void *)mi, sizeof(*mi));
- mi->dev = i;
- snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
- strlcpy(mi->name, m->name, sizeof(mi->name));
- mi->modify_counter = m->modify_counter;
- mi->card_number = i;
- /*
- * Currently, FreeBSD assumes 1:1 relationship between
- * a pcm and mixer devices, so this is hardcoded to 0.
- */
- mi->port_number = 0;
-
- /**
- * @todo Fill in @sa oss_mixerinfo::mixerhandle.
- * @note From 4Front: "mixerhandle is an arbitrary
- * string that identifies the mixer better than
- * the device number (mixerinfo.dev). Device
- * numbers may change depending on the order the
- * drivers are loaded. However the handle should
- * remain the same provided that the sound card
- * is not moved to another PCI slot."
- */
-
- /**
- * @note
- * @sa oss_mixerinfo::magic is a reserved field.
- *
- * @par
- * From 4Front: "magic is usually 0. However some
- * devices may have dedicated setup utilities and the
- * magic field may contain an unique driver specific
- * value (managed by [4Front])."
- */
-
- mi->enabled = device_is_attached(m->dev) ? 1 : 0;
- /**
- * The only flag for @sa oss_mixerinfo::caps is
- * currently MIXER_CAP_VIRTUAL, which I'm not sure we
- * really worry about.
- */
- /**
- * Mixer extensions currently aren't supported, so
- * leave @sa oss_mixerinfo::nrext blank for now.
- */
-
- /**
- * @todo Fill in @sa oss_mixerinfo::priority (requires
- * touching drivers?)
- * @note The priority field is for mixer applets to
- * determine which mixer should be the default, with 0
- * being least preferred and 10 being most preferred.
- * From 4Front: "OSS drivers like ICH use higher
- * values (10) because such chips are known to be used
- * only on motherboards. Drivers for high end pro
- * devices use 0 because they will never be the
- * default mixer. Other devices use values 1 to 9
- * depending on the estimated probability of being the
- * default device.
- */
-
- snprintf(mi->devnode, sizeof(mi->devnode), "/dev/mixer%d", i);
- mi->legacy_device = i;
+ PCM_UNLOCK(d);
+ continue;
+ }
- mtx_unlock(m->lock);
+ if (d->mixer_dev->si_drv1 == NULL) {
+ mixer_oss_mixerinfo_unavail(mi, i);
+ PCM_UNLOCK(d);
+ return (0);
}
+ m = d->mixer_dev->si_drv1;
+ mtx_lock(m->lock);
+
+ /*
+ * At this point, the following synchronization stuff
+ * has happened:
+ * - a specific PCM device is locked.
+ * - a specific mixer device has been locked, so be
+ * sure to unlock when existing.
+ */
+ bzero((void *)mi, sizeof(*mi));
+ mi->dev = i;
+ snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
+ strlcpy(mi->name, m->name, sizeof(mi->name));
+ mi->modify_counter = m->modify_counter;
+ mi->card_number = i;
+ /*
+ * Currently, FreeBSD assumes 1:1 relationship between
+ * a pcm and mixer devices, so this is hardcoded to 0.
+ */
+ mi->port_number = 0;
+
+ /**
+ * @todo Fill in @sa oss_mixerinfo::mixerhandle.
+ * @note From 4Front: "mixerhandle is an arbitrary
+ * string that identifies the mixer better than
+ * the device number (mixerinfo.dev). Device
+ * numbers may change depending on the order the
+ * drivers are loaded. However the handle should
+ * remain the same provided that the sound card
+ * is not moved to another PCI slot."
+ */
+
+ /**
+ * @note
+ * @sa oss_mixerinfo::magic is a reserved field.
+ *
+ * @par
+ * From 4Front: "magic is usually 0. However some
+ * devices may have dedicated setup utilities and the
+ * magic field may contain an unique driver specific
+ * value (managed by [4Front])."
+ */
+
+ mi->enabled = device_is_attached(m->dev) ? 1 : 0;
+ /**
+ * The only flag for @sa oss_mixerinfo::caps is
+ * currently MIXER_CAP_VIRTUAL, which I'm not sure we
+ * really worry about.
+ */
+ /**
+ * Mixer extensions currently aren't supported, so
+ * leave @sa oss_mixerinfo::nrext blank for now.
+ */
+
+ /**
+ * @todo Fill in @sa oss_mixerinfo::priority (requires
+ * touching drivers?)
+ * @note The priority field is for mixer applets to
+ * determine which mixer should be the default, with 0
+ * being least preferred and 10 being most preferred.
+ * From 4Front: "OSS drivers like ICH use higher
+ * values (10) because such chips are known to be used
+ * only on motherboards. Drivers for high end pro
+ * devices use 0 because they will never be the
+ * default mixer. Other devices use values 1 to 9
+ * depending on the estimated probability of being the
+ * default device.
+ */
+
+ snprintf(mi->devnode, sizeof(mi->devnode), "/dev/mixer%d", i);
+ mi->legacy_device = i;
+
+ mtx_unlock(m->lock);
+
PCM_UNLOCK(d);
- if (m != NULL)
- return (0);
+ return (0);
}
return (EINVAL);
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -766,7 +766,12 @@
*/
si->nummidis = 0;
si->numtimers = 0;
- si->nummixers = mixer_count;
+ /*
+ * Set this to the maximum unit number so that applications will not
+ * break if they try to loop through all mixers and some of them are
+ * not available.
+ */
+ si->nummixers = devclass_get_maxunit(pcm_devclass);
si->numcards = devclass_get_maxunit(pcm_devclass);
si->numaudios = devclass_get_maxunit(pcm_devclass);
/* OSSv4 docs: Intended only for test apps; API doesn't
@@ -797,23 +802,29 @@
for (i = 0; pcm_devclass != NULL &&
i < devclass_get_maxunit(pcm_devclass); i++) {
d = devclass_get_softc(pcm_devclass, i);
- if (!PCM_REGISTERED(d))
- continue;
-
if (i != si->card)
continue;
- PCM_UNLOCKASSERT(d);
- PCM_LOCK(d);
-
- strlcpy(si->shortname, device_get_nameunit(d->dev),
- sizeof(si->shortname));
- strlcpy(si->longname, device_get_desc(d->dev),
- sizeof(si->longname));
- strlcpy(si->hw_info, d->status, sizeof(si->hw_info));
- si->intr_count = si->ack_count = 0;
-
- PCM_UNLOCK(d);
+ if (!PCM_REGISTERED(d)) {
+ snprintf(si->shortname, sizeof(si->shortname),
+ "pcm%d (n/a)", i);
+ strlcpy(si->longname, "Device unavailable",
+ sizeof(si->longname));
+ si->hw_info[0] = '\0';
+ si->intr_count = si->ack_count = 0;
+ } else {
+ PCM_UNLOCKASSERT(d);
+ PCM_LOCK(d);
+
+ strlcpy(si->shortname, device_get_nameunit(d->dev),
+ sizeof(si->shortname));
+ strlcpy(si->longname, device_get_desc(d->dev),
+ sizeof(si->longname));
+ strlcpy(si->hw_info, d->status, sizeof(si->hw_info));
+ si->intr_count = si->ack_count = 0;
+
+ PCM_UNLOCK(d);
+ }
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 11, 1:52 PM (20 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15754381
Default Alt Text
D45256.diff (11 KB)

Event Timeline