From nobody Sat May 25 19:31:34 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4VmsTy4CzNz5LSxC; Sat, 25 May 2024 19:31:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4VmsTy1KH5z4jf7; Sat, 25 May 2024 19:31:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1716665494; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=SUqwIrxeG4TBdhFk3zDHk4ag5/2Lc/ZQ8RyqG8W/W/w=; b=FMXvrE7kgPyNvRWW3bJJ85JVUZJnYeFKrNlZnLVDOOM772/6WFeKVxnSHak8RpuokDtnCE tSYVPP+QYzlRKeFyUDyuni9QtOEq6+AbGJE32AKeS3iG5YSdqhNueyv4OUS6zcytWkqNgP FaSB+Z9okxJKM16hr+IfcsCpwdkIoBjBk+poDIlqSfu300AU0A9rC8MfrP987y0dozDj3+ tuXMh6X9xbZN7L1xPQBAoyr0W4l4yDmuytav0cnnQfYPFzfIOP+6oDvF3ba5MLI8hlJ3hh MkpNw+VdyiKSHb0cg4iXflv5gNVBbhy3MsaCNApeKq25V0iSVN0W7JgSRa6Jwg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1716665494; a=rsa-sha256; cv=none; b=Mh4bd6K1RcQzGcvpJx+VNOGt/9ytzfaH9XUDstx3bjkwcZgD8A53gPDO0H4LkNXf6xpMft sqOFvE9HBbZX8U9jxZu299jgH6nNyYvzevnw1jyM0af8DrSKwZ5VSYxiXR5ShF7kokHIyN lHYt4klnZb4qrhHTM1VKwCW3Azz/L2fdDAiYLhGEZ43S5/mN/6XYWG9IDmPBKWXsl4HvsQ X4IRuZC5oiLFJH9R4n7pfGXuPCxRgvnMxNb4COApsgXsJZalvJh4YZwosH7d+AuUFhPaR3 8Vdj5nMpQTe6rYW0+YhUOiwgNoezygDPHjVkBdHxQtKti78PAZst3n3KRkfioA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1716665494; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=SUqwIrxeG4TBdhFk3zDHk4ag5/2Lc/ZQ8RyqG8W/W/w=; b=Vn9fyydUkcWKPJ4Wpb1Ga0ay3Vr/xtXVB7kigci0paukwCX9Bzp1mlk84/vPEBZvBQbwR5 eohsDjhLuUVOTZWw5R8qQTOME3vAfAuXzMqc6ZAEF1uVe/YZ1cw7RDAXFiyzSH08mREiW7 ihWqkHR+NZz1ZtKYLeWNEx0KDA4ivycKC1uQEjsZkPzP7LsXm5rT310+kZ0w1+TU0VX71d ViAV7L/ZdN960MTYIQevg7uIhv2luUjQQpq/w1yaocAM7nUE0fwUaMZDGjtbGWKF23h4Ri W+/NMhrOZPjCMDdRo2j0yoeTVJgpjVm1fGewvb/tRYT0U0mNx7HvxAacXGoBUQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4VmsTy0xMWzTLT; Sat, 25 May 2024 19:31:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 44PJVYRW043336; Sat, 25 May 2024 19:31:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 44PJVYr9043333; Sat, 25 May 2024 19:31:34 GMT (envelope-from git) Date: Sat, 25 May 2024 19:31:34 GMT Message-Id: <202405251931.44PJVYr9043333@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Christos Margiolis Subject: git: e8a80b4e50e8 - stable/14 - sound: Separate implementations for SNDCTL_AUDIOINFO[_EX] and SNDCTL_ENGINEINFO List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: christos X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: e8a80b4e50e8d992fe46a95509b37fc457288f93 Auto-Submitted: auto-generated The branch stable/14 has been updated by christos: URL: https://cgit.FreeBSD.org/src/commit/?id=e8a80b4e50e8d992fe46a95509b37fc457288f93 commit e8a80b4e50e8d992fe46a95509b37fc457288f93 Author: Christos Margiolis AuthorDate: 2024-05-23 00:57:04 +0000 Commit: Christos Margiolis CommitDate: 2024-05-25 19:30:26 +0000 sound: Separate implementations for SNDCTL_AUDIOINFO[_EX] and SNDCTL_ENGINEINFO FreeBSD's implementation of SNDCTL_AUDIOINFO[_EX] and SNDCTL_ENGINEINFO does not exactly work as intended. The problem is essentially that both IOCTLs return the same information, while in fact the information returned currently by dsp_oss_audioinfo() is what _only_ SNDCTL_ENGINEINFO is meant to return. This behavior is also noted in the OSS manual [1] (see bold paragraph in "Audio engines and device files" section), but since e8c0d15a64fa ("sound: Get rid of snd_clone and use DEVFS_CDEVPRIV(9)") we can actually fix this, because we now expose only a single device for each soundcard, and create the engines (channels) internally. SNDCTL_ENGINEINFO will now report info about all channels in a given device, and SNDCTL_AUDIOINFO[_EX] will only report information about /dev/dspX. To make this work, we also have to modify the SNDCTL_SYSINFO IOCTL to report the number of audio devices and audio engines correctly. While here, modernize the minimum and maximum channel counting in both SNDCTL_AUDIOINFO[_EX] and SNDCTL_ENGINEINFO. Currently these IOCTLs will report only up to 2 channels, which is no longer the case. [1] http://manuals.opensound.com/developer/SNDCTL_AUDIOINFO.html PR: 246231, 252761 Sponsored by: The FreeBSD Foundation MFC after: 1 day Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D45164 (cherry picked from commit e07f9178502b7cbc0769fc10e99ad0d013f437fd) --- sys/dev/sound/pcm/dsp.c | 179 +++++++++++++++++++++++++++++++++++++++++----- sys/dev/sound/pcm/dsp.h | 3 +- sys/dev/sound/pcm/mixer.c | 8 ++- sys/dev/sound/pcm/sound.c | 8 +-- 4 files changed, 173 insertions(+), 25 deletions(-) diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 6e5fad048d40..4ee5d7c6738c 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -778,9 +778,15 @@ dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 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 @@ dsp_unit2name(char *buf, size_t len, struct pcm_channel *ch) 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 @@ dsp_oss_audioinfo_cb(void *data, void *arg) } /** - * @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 @@ dsp_oss_audioinfo_cb(void *data, void *arg) * * @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 @@ dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai) 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 @@ dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai) * 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/dsp.h b/sys/dev/sound/pcm/dsp.h index b81e60dc19b5..7559e855d4e1 100644 --- a/sys/dev/sound/pcm/dsp.h +++ b/sys/dev/sound/pcm/dsp.h @@ -36,6 +36,7 @@ extern struct cdevsw dsp_cdevsw; 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/mixer.c b/sys/dev/sound/pcm/mixer.c index 9811496853c8..130333c7c442 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -1282,9 +1282,13 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 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 index e66462af2a71..072d42c4e989 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -718,9 +718,9 @@ sound_oss_sysinfo(oss_sysinfo *si) /* * 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 @@ sound_oss_sysinfo(oss_sysinfo *si) 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 @@ sound_oss_sysinfo(oss_sysinfo *si) PCM_UNLOCK(d); } - si->numaudioengines = si->numaudios; si->numsynths = 0; /* OSSv4 docs: this field is obsolete */ /** @@ -769,6 +768,7 @@ sound_oss_sysinfo(oss_sysinfo *si) 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. */