From owner-dev-commits-src-branches@freebsd.org Wed Sep 22 13:02:35 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id F12B766A7AD; Wed, 22 Sep 2021 13:02:35 +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 4HDz3b1Npfz3DTn; Wed, 22 Sep 2021 13:02:35 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 9C70C17FB0; Wed, 22 Sep 2021 13:02:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 18MD2YXw013102; Wed, 22 Sep 2021 13:02:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 18MD2Ymq013101; Wed, 22 Sep 2021 13:02:34 GMT (envelope-from git) Date: Wed, 22 Sep 2021 13:02:34 GMT Message-Id: <202109221302.18MD2Ymq013101@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Hans Petter Selasky Subject: git: 66e91a9ee19f - stable/13 - Implement the SOUND_MIXER_WRITE_MUTE and SOUND_MIXER_READ_MUTE ioctl(9)s. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: hselasky X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 66e91a9ee19fe09125e5cf535c440c80faf77fa6 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Sep 2021 13:02:36 -0000 The branch stable/13 has been updated by hselasky: URL: https://cgit.FreeBSD.org/src/commit/?id=66e91a9ee19fe09125e5cf535c440c80faf77fa6 commit 66e91a9ee19fe09125e5cf535c440c80faf77fa6 Author: Hans Petter Selasky AuthorDate: 2021-07-20 17:02:41 +0000 Commit: Hans Petter Selasky CommitDate: 2021-09-22 12:59:31 +0000 Implement the SOUND_MIXER_WRITE_MUTE and SOUND_MIXER_READ_MUTE ioctl(9)s. These two ioctls are not part of the current version of OSS and were considered obsolete. However, their behaviour is not the same as their old one, so this implementation is specific to FreeBSD. Older OSS versions had the MUTE ioctls take and return an integer with a value of 0 or 1, which meant that the _whole_ mixer is unmuted or muted respectively. In my implementation, the ioctl takes and returns a bitmask that tells us which devices are muted. This allows us to mute and unmute only the devices we want, instead of the whole mixer. The bitmask works the same way as in DEVMASK, RECMASK and RECSRC. Integrated the hardware volume feature with the new mute system. Submitted by: Christos Margiolis Differential Revision: https://reviews.freebsd.org/D31130 MFC after: 1 week Sponsored by: NVIDIA Networking (cherry picked from commit 0f8dafb45859569aa36b63ca2bb4a1c35c970d1e) --- sys/dev/sound/pcm/mixer.c | 122 +++++++++++++++++++++++++++++++--------------- sys/dev/sound/pcm/mixer.h | 2 + 2 files changed, 84 insertions(+), 40 deletions(-) diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index 09b0bb8ab148..89e78b036e94 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -51,16 +51,16 @@ struct snd_mixer { KOBJ_FIELDS; void *devinfo; int busy; - int hwvol_muted; int hwvol_mixer; int hwvol_step; int type; device_t dev; - u_int32_t hwvol_mute_level; u_int32_t devs; + u_int32_t mutedevs; u_int32_t recdevs; u_int32_t recsrc; u_int16_t level[32]; + u_int16_t level_muted[32]; u_int8_t parent[32]; u_int32_t child[32]; u_int8_t realdev[32]; @@ -244,7 +244,7 @@ mixer_set_eq(struct snd_mixer *m, struct snddev_info *d, } static int -mixer_set(struct snd_mixer *m, u_int dev, u_int lev) +mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev) { struct snddev_info *d; u_int l, r, tl, tr; @@ -254,7 +254,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) if (m == NULL || dev >= SOUND_MIXER_NRDEVICES || (0 == (m->devs & (1 << dev)))) - return -1; + return (-1); l = min((lev & 0x00ff), 100); r = min(((lev & 0xff00) >> 8), 100); @@ -262,7 +262,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) d = device_get_softc(m->dev); if (d == NULL) - return -1; + return (-1); /* It is safe to drop this mutex due to Giant. */ if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0) @@ -270,6 +270,11 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) else dropmtx = 0; + /* Allow the volume to be "changed" while muted. */ + if (muted & (1 << dev)) { + m->level_muted[dev] = l | (r << 8); + return (0); + } MIXER_SET_UNLOCK(m, dropmtx); /* TODO: recursive handling */ @@ -287,7 +292,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) else if (realdev != SOUND_MIXER_NONE && MIXER_SET(m, realdev, tl, tr) < 0) { MIXER_SET_LOCK(m, dropmtx); - return -1; + return (-1); } } else if (child != 0) { for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { @@ -305,8 +310,8 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) realdev = m->realdev[dev]; if (realdev != SOUND_MIXER_NONE && MIXER_SET(m, realdev, l, r) < 0) { - MIXER_SET_LOCK(m, dropmtx); - return -1; + MIXER_SET_LOCK(m, dropmtx); + return (-1); } } else { if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL)) @@ -317,7 +322,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) else if (realdev != SOUND_MIXER_NONE && MIXER_SET(m, realdev, l, r) < 0) { MIXER_SET_LOCK(m, dropmtx); - return -1; + return (-1); } } @@ -326,16 +331,42 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) m->level[dev] = l | (r << 8); m->modify_counter++; - return 0; + return (0); } static int mixer_get(struct snd_mixer *mixer, int dev) { - if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) - return mixer->level[dev]; - else - return -1; + if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) { + if (mixer->mutedevs & (1 << dev)) + return (mixer->level_muted[dev]); + else + return (mixer->level[dev]); + } else { + return (-1); + } +} + +void +mix_setmutedevs(struct snd_mixer *mixer, u_int32_t mutedevs) +{ + u_int32_t delta; + + /* Filter out invalid values. */ + mutedevs &= mixer->devs; + delta = (mixer->mutedevs ^ mutedevs) & mixer->devs; + mixer->mutedevs = mutedevs; + + for (int i = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (!(delta & (1 << i))) + continue; + if (mutedevs & (1 << i)) { + mixer->level_muted[i] = mixer->level[i]; + mixer_set(mixer, i, 0, 0); + } else { + mixer_set(mixer, i, 0, mixer->level_muted[i]); + } + } } static int @@ -598,6 +629,12 @@ mix_getdevs(struct snd_mixer *m) return m->devs; } +u_int32_t +mix_getmutedevs(struct snd_mixer *m) +{ + return m->mutedevs; +} + u_int32_t mix_getrecdevs(struct snd_mixer *m) { @@ -721,7 +758,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) } } - mixer_set(m, i, v | (v << 8)); + mixer_set(m, i, 0, v | (v << 8)); } mixer_setrecsrc(m, 0); /* Set default input. */ @@ -799,7 +836,7 @@ mixer_uninit(device_t dev) snd_mtxlock(m->lock); for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - mixer_set(m, i, 0); + mixer_set(m, i, 0, 0); mixer_setrecsrc(m, SOUND_MASK_MIC); @@ -836,8 +873,12 @@ mixer_reinit(device_t dev) return i; } - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - mixer_set(m, i, m->level[i]); + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (m->mutedevs & (1 << i)) + mixer_set(m, i, 0, 0); + else + mixer_set(m, i, 0, m->level[i]); + } mixer_setrecsrc(m, m->recsrc); snd_mtxunlock(m->lock); @@ -863,10 +904,8 @@ sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) if (dev == -1) { snd_mtxunlock(m->lock); return EINVAL; - } - else if (dev != m->hwvol_mixer) { + } else { m->hwvol_mixer = dev; - m->hwvol_muted = 0; } } snd_mtxunlock(m->lock); @@ -897,14 +936,7 @@ mixer_hwvol_init(device_t dev) void mixer_hwvol_mute_locked(struct snd_mixer *m) { - if (m->hwvol_muted) { - m->hwvol_muted = 0; - mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level); - } else { - m->hwvol_muted++; - m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer); - mixer_set(m, m->hwvol_mixer, 0); - } + mix_setmutedevs(m, m->mutedevs ^ (1 << m->hwvol_mixer)); } void @@ -925,11 +957,8 @@ mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) { int level, left, right; - if (m->hwvol_muted) { - m->hwvol_muted = 0; - level = m->hwvol_mute_level; - } else - level = mixer_get(m, m->hwvol_mixer); + level = mixer_get(m, m->hwvol_mixer); + if (level != -1) { left = level & 0xff; right = (level >> 8) & 0xff; @@ -943,7 +972,8 @@ mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) right = 0; else if (right > 100) right = 100; - mixer_set(m, m->hwvol_mixer, left | right << 8); + + mixer_set(m, m->hwvol_mixer, m->mutedevs, left | right << 8); } } @@ -976,7 +1006,7 @@ mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right) KASSERT(m != NULL, ("NULL snd_mixer")); snd_mtxlock(m->lock); - ret = mixer_set(m, dev, left | (right << 8)); + ret = mixer_set(m, dev, m->mutedevs, left | (right << 8)); snd_mtxunlock(m->lock); return ((ret != 0) ? ENXIO : 0); @@ -1304,10 +1334,18 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, goto done; } if ((cmd & ~0xff) == MIXER_WRITE(0)) { - if (j == SOUND_MIXER_RECSRC) + switch (j) { + case SOUND_MIXER_RECSRC: ret = mixer_setrecsrc(m, *arg_i); - else - ret = mixer_set(m, j, *arg_i); + break; + case SOUND_MIXER_MUTE: + mix_setmutedevs(m, *arg_i); + ret = 0; + break; + default: + ret = mixer_set(m, j, m->mutedevs, *arg_i); + break; + } snd_mtxunlock(m->lock); return ((ret == 0) ? 0 : ENXIO); } @@ -1318,6 +1356,9 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, case SOUND_MIXER_STEREODEVS: v = mix_getdevs(m); break; + case SOUND_MIXER_MUTE: + v = mix_getmutedevs(m); + break; case SOUND_MIXER_RECMASK: v = mix_getrecdevs(m); break; @@ -1326,6 +1367,7 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, break; default: v = mixer_get(m, j); + break; } *arg_i = v; snd_mtxunlock(m->lock); @@ -1554,5 +1596,5 @@ mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right) level = (left & 0xFF) | ((right & 0xFF) << 8); - return (mixer_set(m, dev, level)); + return (mixer_set(m, dev, m->mutedevs, level)); } diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h index 8e11d553a3e4..7857609b2895 100644 --- a/sys/dev/sound/pcm/mixer.h +++ b/sys/dev/sound/pcm/mixer.h @@ -60,8 +60,10 @@ device_t mix_get_dev(struct snd_mixer *m); void mix_setdevs(struct snd_mixer *m, u_int32_t v); void mix_setrecdevs(struct snd_mixer *m, u_int32_t v); +void mix_setmutedevs(struct snd_mixer *m, u_int32_t v); u_int32_t mix_getdevs(struct snd_mixer *m); u_int32_t mix_getrecdevs(struct snd_mixer *m); +u_int32_t mix_getmutedevs(struct snd_mixer *m); void mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs); void mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev); u_int32_t mix_getparent(struct snd_mixer *m, u_int32_t dev);