Page MenuHomeFreeBSD

D45164.diff
No OneTemporary

D45164.diff

diff --git a/sys/dev/sound/pcm/dsp.h b/sys/dev/sound/pcm/dsp.h
--- a/sys/dev/sound/pcm/dsp.h
+++ b/sys/dev/sound/pcm/dsp.h
@@ -36,6 +36,7 @@
int dsp_make_dev(device_t);
void dsp_destroy_dev(device_t);
char *dsp_unit2name(char *, size_t, struct pcm_channel *);
-int dsp_oss_audioinfo(struct cdev *, oss_audioinfo *);
+int dsp_oss_audioinfo(struct cdev *, oss_audioinfo *, bool);
+int dsp_oss_engineinfo(struct cdev *, oss_audioinfo *);
#endif /* !_PCMDSP_H_ */
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
@@ -778,9 +778,15 @@
ret = sound_oss_card_info((oss_card_info *)arg);
break;
case SNDCTL_AUDIOINFO:
+ ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
+ false);
+ break;
case SNDCTL_AUDIOINFO_EX:
+ ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
+ true);
+ break;
case SNDCTL_ENGINEINFO:
- ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg);
+ ret = dsp_oss_engineinfo(i_dev, (oss_audioinfo *)arg);
break;
case SNDCTL_MIXERINFO:
ret = mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg);
@@ -2034,8 +2040,152 @@
return (NULL);
}
+/**
+ * @brief Handler for SNDCTL_AUDIOINFO.
+ *
+ * Gathers information about the audio device specified in ai->dev. If
+ * ai->dev == -1, then this function gathers information about the current
+ * device. If the call comes in on a non-audio device and ai->dev == -1,
+ * return EINVAL.
+ *
+ * This routine is supposed to go practically straight to the hardware,
+ * getting capabilities directly from the sound card driver, side-stepping
+ * the intermediate channel interface.
+ *
+ * @note
+ * Calling threads must not hold any snddev_info or pcm_channel locks.
+ *
+ * @param dev device on which the ioctl was issued
+ * @param ai ioctl request data container
+ * @param ex flag to distinguish between SNDCTL_AUDIOINFO from
+ * SNDCTL_AUDIOINFO_EX
+ *
+ * @retval 0 success
+ * @retval EINVAL ai->dev specifies an invalid device
+ */
+int
+dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai, bool ex)
+{
+ struct pcmchan_caps *caps;
+ struct pcm_channel *ch;
+ struct snddev_info *d;
+ uint32_t fmts;
+ int i, minch, maxch, unit;
+
+ /*
+ * If probing the device that received the ioctl, make sure it's a
+ * DSP device. (Users may use this ioctl with /dev/mixer and
+ * /dev/midi.)
+ */
+ if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw)
+ return (EINVAL);
+
+ for (unit = 0; pcm_devclass != NULL &&
+ unit < devclass_get_maxunit(pcm_devclass); unit++) {
+ d = devclass_get_softc(pcm_devclass, unit);
+ if (!PCM_REGISTERED(d)) {
+ d = NULL;
+ continue;
+ }
+
+ PCM_UNLOCKASSERT(d);
+ PCM_LOCK(d);
+ if ((ai->dev == -1 && d->dsp_dev == i_dev) ||
+ (ai->dev == unit)) {
+ PCM_UNLOCK(d);
+ break;
+ } else {
+ PCM_UNLOCK(d);
+ d = NULL;
+ }
+ }
+
+ /* Exhausted the search -- nothing is locked, so return. */
+ if (d == NULL)
+ return (EINVAL);
+
+ /* XXX Need Giant magic entry ??? */
+
+ PCM_UNLOCKASSERT(d);
+ PCM_LOCK(d);
+
+ bzero((void *)ai, sizeof(oss_audioinfo));
+ ai->dev = unit;
+ strlcpy(ai->name, device_get_desc(d->dev), sizeof(ai->name));
+ ai->pid = -1;
+ ai->card_number = -1;
+ ai->port_number = -1;
+ ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1;
+ ai->legacy_device = unit;
+ snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit);
+ ai->enabled = device_is_attached(d->dev) ? 1 : 0;
+ ai->next_play_engine = 0;
+ ai->next_rec_engine = 0;
+ ai->busy = 0;
+ ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER;
+ ai->iformats = 0;
+ ai->oformats = 0;
+ ai->min_rate = INT_MAX;
+ ai->max_rate = 0;
+ ai->min_channels = INT_MAX;
+ ai->max_channels = 0;
+
+ /* Gather global information about the device. */
+ CHN_FOREACH(ch, d, channels.pcm) {
+ CHN_UNLOCKASSERT(ch);
+ CHN_LOCK(ch);
+
+ /*
+ * Skip physical channels if we are servicing SNDCTL_AUDIOINFO,
+ * or VCHANs if we are servicing SNDCTL_AUDIOINFO_EX.
+ */
+ if ((ex && (ch->flags & CHN_F_VIRTUAL) != 0) ||
+ (!ex && (ch->flags & CHN_F_VIRTUAL) == 0)) {
+ CHN_UNLOCK(ch);
+ continue;
+ }
+
+ if ((ch->flags & CHN_F_BUSY) == 0) {
+ ai->busy |= (ch->direction == PCMDIR_PLAY) ?
+ OPEN_WRITE : OPEN_READ;
+ }
+
+ ai->caps |=
+ ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) |
+ ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT :
+ PCM_CAP_INPUT);
+
+ caps = chn_getcaps(ch);
+
+ minch = INT_MAX;
+ maxch = 0;
+ fmts = 0;
+ for (i = 0; caps->fmtlist[i]; i++) {
+ fmts |= AFMT_ENCODING(caps->fmtlist[i]);
+ minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch);
+ maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch);
+ }
+
+ if (ch->direction == PCMDIR_PLAY)
+ ai->oformats |= fmts;
+ else
+ ai->iformats |= fmts;
+
+ ai->min_rate = min(ai->min_rate, caps->minspeed);
+ ai->max_rate = max(ai->max_rate, caps->maxspeed);
+ ai->min_channels = min(ai->min_channels, minch);
+ ai->max_channels = max(ai->max_channels, maxch);
+
+ CHN_UNLOCK(ch);
+ }
+
+ PCM_UNLOCK(d);
+
+ return (0);
+}
+
static int
-dsp_oss_audioinfo_cb(void *data, void *arg)
+dsp_oss_engineinfo_cb(void *data, void *arg)
{
struct dsp_cdevpriv *priv = data;
struct pcm_channel *ch = arg;
@@ -2047,10 +2197,10 @@
}
/**
- * @brief Handler for SNDCTL_AUDIOINFO.
+ * @brief Handler for SNDCTL_ENGINEINFO
*
- * Gathers information about the audio device specified in ai->dev. If
- * ai->dev == -1, then this function gathers information about the current
+ * Gathers information about the audio device's engine specified in ai->dev.
+ * If ai->dev == -1, then this function gathers information about the current
* device. If the call comes in on a non-audio device and ai->dev == -1,
* return EINVAL.
*
@@ -2066,11 +2216,9 @@
*
* @retval 0 success
* @retval EINVAL ai->dev specifies an invalid device
- *
- * @todo Verify correctness of Doxygen tags. ;)
*/
int
-dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai)
+dsp_oss_engineinfo(struct cdev *i_dev, oss_audioinfo *ai)
{
struct pcmchan_caps *caps;
struct pcm_channel *ch;
@@ -2113,7 +2261,7 @@
CHN_LOCK(ch);
if (ai->dev == -1) {
if (devfs_foreach_cdevpriv(i_dev,
- dsp_oss_audioinfo_cb, ch) != 0) {
+ dsp_oss_engineinfo_cb, ch) != 0) {
devname = dsp_unit2name(buf,
sizeof(buf), ch);
}
@@ -2182,18 +2330,13 @@
* if any channel is mono, minch = 1;
* and if all channels are mono, maxch = 1.
*/
- minch = 0;
+ minch = INT_MAX;
maxch = 0;
fmts = 0;
for (i = 0; caps->fmtlist[i]; i++) {
- fmts |= caps->fmtlist[i];
- if (AFMT_CHANNEL(caps->fmtlist[i]) > 1) {
- minch = (minch == 0) ? 2 : minch;
- maxch = 2;
- } else {
- minch = 1;
- maxch = (maxch == 0) ? 1 : maxch;
- }
+ fmts |= AFMT_ENCODING(caps->fmtlist[i]);
+ minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch);
+ maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch);
}
if (ch->direction == PCMDIR_PLAY)
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
@@ -1282,9 +1282,13 @@
case SNDCTL_CARDINFO:
return (sound_oss_card_info((oss_card_info *)arg));
case SNDCTL_AUDIOINFO:
+ return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
+ false));
case SNDCTL_AUDIOINFO_EX:
- case SNDCTL_ENGINEINFO:
- return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg));
+ return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
+ true));
+ case SNDCTL_ENGINEINFO:
+ return (dsp_oss_engineinfo(i_dev, (oss_audioinfo *)arg));
case SNDCTL_MIXERINFO:
return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg));
}
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
@@ -718,9 +718,9 @@
/*
* Iterate over PCM devices and their channels, gathering up data
- * for the numaudios and openedaudio fields.
+ * for the numaudioengines and openedaudio fields.
*/
- si->numaudios = 0;
+ si->numaudioengines = 0;
bzero((void *)&si->openedaudio, sizeof(si->openedaudio));
j = 0;
@@ -737,7 +737,7 @@
PCM_UNLOCKASSERT(d);
PCM_LOCK(d);
- si->numaudios += PCM_CHANCOUNT(d);
+ si->numaudioengines += PCM_CHANCOUNT(d);
CHN_FOREACH(c, d, channels.pcm) {
CHN_UNLOCKASSERT(c);
@@ -751,7 +751,6 @@
PCM_UNLOCK(d);
}
- si->numaudioengines = si->numaudios;
si->numsynths = 0; /* OSSv4 docs: this field is obsolete */
/**
@@ -769,6 +768,7 @@
si->numtimers = 0;
si->nummixers = mixer_count;
si->numcards = devclass_get_maxunit(pcm_devclass);
+ si->numaudios = devclass_get_maxunit(pcm_devclass);
/* OSSv4 docs: Intended only for test apps; API doesn't
really have much of a concept of cards. Shouldn't be
used by applications. */

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 20, 5:14 AM (21 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14730918
Default Alt Text
D45164.diff (8 KB)

Event Timeline