diff options
author | cg <cg@FreeBSD.org> | 2001-06-16 21:25:10 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2001-06-16 21:25:10 +0000 |
commit | 4a0664e88e403e97d641f7ad4fd6dab71095bd0b (patch) | |
tree | b90a72aa9539fc95aa3dfcae3c1ed22290a8bec2 /sys/dev/sound/pcm/mixer.c | |
parent | b81ba90a5fa7778120861346194bdd1912baa63b (diff) | |
download | FreeBSD-src-4a0664e88e403e97d641f7ad4fd6dab71095bd0b.zip FreeBSD-src-4a0664e88e403e97d641f7ad4fd6dab71095bd0b.tar.gz |
use a global devclass for all drivers - i'm not entirely sure why this
worked before.
mixer, dsp and sndstat are seperate devices - give them their own cdevsws
instead of demuxing requests sent to a single cdevsw.
use the si_drv1/si_drv2 fields in dev_t structures for holding information
specific to an open instance of mixer/dsp.
nuke /dev/{dsp,dspW,audio}[0-9]* links - this functionality is now provided
using cloning.
various locking fixes.
Diffstat (limited to 'sys/dev/sound/pcm/mixer.c')
-rw-r--r-- | sys/dev/sound/pcm/mixer.c | 251 |
1 files changed, 172 insertions, 79 deletions
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index 5b1f7a3..a71e127 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -68,6 +68,39 @@ static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = { static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; +static d_open_t mixer_open; +static d_close_t mixer_close; + +static struct cdevsw mixer_cdevsw = { + /* open */ mixer_open, + /* close */ mixer_close, + /* read */ noread, + /* write */ nowrite, + /* ioctl */ mixer_ioctl, + /* poll */ nopoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "mixer", + /* maj */ SND_CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, +}; + +static eventhandler_tag mixer_ehtag; + +static dev_t +mixer_get_devt(device_t dev) +{ + dev_t pdev; + int unit; + + unit = device_get_unit(dev); + pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); + + return pdev; +} + #ifdef SND_DYNSYSCTL static int mixer_lookup(char *devname) @@ -157,31 +190,19 @@ mix_getdevinfo(struct snd_mixer *m) } int -mixer_busy(struct snd_mixer *m, int busy) -{ - m->busy = busy; - return 0; -} - -int -mixer_isbusy(struct snd_mixer *m) -{ - return m->busy; -} - -int mixer_init(device_t dev, kobj_class_t cls, void *devinfo) { - struct snddev_info *d; struct snd_mixer *m; u_int16_t v; - int i; + dev_t pdev; + int i, unit; m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO); snprintf(m->name, MIXER_NAMELEN, "%s:mixer", device_get_nameunit(dev)); m->lock = snd_mtxcreate(m->name); m->type = cls->name; m->devinfo = devinfo; + m->busy = 0; if (MIXER_INIT(m)) goto bad; @@ -193,8 +214,10 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) mixer_setrecsrc(m, SOUND_MASK_MIC); - d = device_get_softc(dev); - d->mixer = m; + unit = device_get_unit(dev); + pdev = make_dev(&mixer_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, 0), + UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit); + pdev->si_drv1 = m; return 0; @@ -209,13 +232,21 @@ int mixer_uninit(device_t dev) { int i; - struct snddev_info *d; struct snd_mixer *m; + dev_t pdev; - d = device_get_softc(dev); - m = d->mixer; + pdev = mixer_get_devt(dev); + m = pdev->si_drv1; snd_mtxlock(m->lock); + if (m->busy) { + snd_mtxunlock(m->lock); + return EBUSY; + } + + pdev->si_drv1 = NULL; + destroy_dev(pdev); + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) mixer_set(m, i, 0); @@ -225,7 +256,6 @@ mixer_uninit(device_t dev) snd_mtxfree(m->lock); kobj_delete((kobj_t)m, M_MIXER); - d->mixer = NULL; return 0; } @@ -233,12 +263,12 @@ mixer_uninit(device_t dev) int mixer_reinit(device_t dev) { - int i; - struct snddev_info *d; struct snd_mixer *m; + dev_t pdev; + int i; - d = device_get_softc(dev); - m = d->mixer; + pdev = mixer_get_devt(dev); + m = pdev->si_drv1; snd_mtxlock(m->lock); i = MIXER_REINIT(m); @@ -256,52 +286,6 @@ mixer_reinit(device_t dev) return 0; } -int -mixer_ioctl(struct snddev_info *d, u_long cmd, caddr_t arg) -{ - int ret, *arg_i = (int *)arg; - int v = -1, j = cmd & 0xff; - struct snd_mixer *m; - - m = d->mixer; - - snd_mtxlock(m->lock); - if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { - if (j == SOUND_MIXER_RECSRC) - ret = mixer_setrecsrc(m, *arg_i); - else - ret = mixer_set(m, j, *arg_i); - snd_mtxunlock(m->lock); - return (ret == 0)? 0 : ENXIO; - } - - if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) { - switch (j) { - case SOUND_MIXER_DEVMASK: - case SOUND_MIXER_CAPS: - case SOUND_MIXER_STEREODEVS: - v = mix_getdevs(m); - break; - - case SOUND_MIXER_RECMASK: - v = mix_getrecdevs(m); - break; - - case SOUND_MIXER_RECSRC: - v = mixer_getrecsrc(m); - break; - - default: - v = mixer_get(m, j); - } - *arg_i = v; - snd_mtxunlock(m->lock); - return (v != -1)? 0 : ENXIO; - } - snd_mtxunlock(m->lock); - return ENXIO; -} - #ifdef SND_DYNSYSCTL static int sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) @@ -333,12 +317,15 @@ sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) int mixer_hwvol_init(device_t dev) { - struct snddev_info *d; + struct snddev_info *d; struct snd_mixer *m; + dev_t pdev; d = device_get_softc(dev); - m = d->mixer; + pdev = mixer_get_devt(dev); + m = pdev->si_drv1; snd_mtxlock(m->lock); + m->hwvol_mixer = SOUND_MIXER_VOLUME; m->hwvol_step = 5; #ifdef SND_DYNSYSCTL @@ -355,11 +342,11 @@ mixer_hwvol_init(device_t dev) void mixer_hwvol_mute(device_t dev) { - struct snddev_info *d; struct snd_mixer *m; + dev_t pdev; - d = device_get_softc(dev); - m = d->mixer; + pdev = mixer_get_devt(dev); + m = pdev->si_drv1; snd_mtxlock(m->lock); if (m->hwvol_muted) { m->hwvol_muted = 0; @@ -375,12 +362,12 @@ mixer_hwvol_mute(device_t dev) void mixer_hwvol_step(device_t dev, int left_step, int right_step) { - struct snddev_info *d; struct snd_mixer *m; int level, left, right; + dev_t pdev; - d = device_get_softc(dev); - m = d->mixer; + pdev = mixer_get_devt(dev); + m = pdev->si_drv1; snd_mtxlock(m->lock); if (m->hwvol_muted) { m->hwvol_muted = 0; @@ -401,4 +388,110 @@ mixer_hwvol_step(device_t dev, int left_step, int right_step) snd_mtxunlock(m->lock); } +/* ----------------------------------------------------------------------- */ + +static int +mixer_open(dev_t i_dev, int flags, int mode, struct proc *p) +{ + struct snd_mixer *m; + + m = i_dev->si_drv1; + if (m->busy) + return EBUSY; + m->busy = 1; + + return 0; +} + +static int +mixer_close(dev_t i_dev, int flags, int mode, struct proc *p) +{ + struct snd_mixer *m; + + m = i_dev->si_drv1; + if (!m->busy) + return EBADF; + m->busy = 0; + + return 0; +} + +int +mixer_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p) +{ + int ret, *arg_i = (int *)arg; + int v = -1, j = cmd & 0xff; + struct snd_mixer *m; + + m = i_dev->si_drv1; + if (!m->busy) + return EBADF; + + snd_mtxlock(m->lock); + if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { + if (j == SOUND_MIXER_RECSRC) + ret = mixer_setrecsrc(m, *arg_i); + else + ret = mixer_set(m, j, *arg_i); + snd_mtxunlock(m->lock); + return (ret == 0)? 0 : ENXIO; + } + + if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) { + switch (j) { + case SOUND_MIXER_DEVMASK: + case SOUND_MIXER_CAPS: + case SOUND_MIXER_STEREODEVS: + v = mix_getdevs(m); + break; + + case SOUND_MIXER_RECMASK: + v = mix_getrecdevs(m); + break; + + case SOUND_MIXER_RECSRC: + v = mixer_getrecsrc(m); + break; + + default: + v = mixer_get(m, j); + } + *arg_i = v; + snd_mtxunlock(m->lock); + return (v != -1)? 0 : ENXIO; + } + snd_mtxunlock(m->lock); + return ENXIO; +} + +static void +mixer_clone(void *arg, char *name, int namelen, dev_t *dev) +{ + dev_t pdev; + + if (*dev != NODEV) + return; + if (strcmp(name, "mixer") == 0) { + pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(snd_unit, SND_DEV_CTL, 0)); + if (pdev->si_flags & SI_NAMED) + *dev = pdev; + } +} + +static void +mixer_sysinit(void *p) +{ + mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000); +} + +static void +mixer_sysuninit(void *p) +{ + if (mixer_ehtag != NULL) + EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag); +} + +SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL); +SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL); + |