Module Name:    src
Committed By:   nat
Date:           Sat Jul  1 23:31:19 UTC 2017

Modified Files:
        src/sys/dev/pad: pad.c padvar.h
        src/sys/sys: file.h

Log Message:
Pad is now clones its device, attaching upon open and detaching upon close.
This means that only one pad device is required in /dev.

The code contains a compile time limit of 128 units.

Ok christos@.


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/sys/dev/pad/pad.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/pad/padvar.h
cvs rdiff -u -r1.81 -r1.82 src/sys/sys/file.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pad/pad.c
diff -u src/sys/dev/pad/pad.c:1.38 src/sys/dev/pad/pad.c:1.39
--- src/sys/dev/pad/pad.c:1.38	Sat Jul  1 05:50:10 2017
+++ src/sys/dev/pad/pad.c	Sat Jul  1 23:31:19 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: pad.c,v 1.38 2017/07/01 05:50:10 nat Exp $ */
+/* $NetBSD: pad.c,v 1.39 2017/07/01 23:31:19 nat Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,18 +27,23 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.38 2017/07/01 05:50:10 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.39 2017/07/01 23:31:19 nat Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/buf.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/vnode.h>
+#include <sys/kauth.h>
 #include <sys/kmem.h>
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/proc.h>
 #include <sys/condvar.h>
 #include <sys/select.h>
+#include <sys/stat.h>
 #include <sys/audioio.h>
 #include <sys/vnode.h>
 #include <sys/module.h>
@@ -52,6 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.38
 
 #include <dev/pad/padvar.h>
 
+#define MAXDEVS		128
 #define PADUNIT(x)	minor(x)
 
 #define PADFREQ		44100
@@ -104,7 +110,15 @@ static stream_filter_t *pad_swvol_filter
     const audio_params_t *, const audio_params_t *);
 static void	pad_swvol_dtor(stream_filter_t *);
 
-static bool	pad_is_attached;	/* Do we have an audio* child? */
+static int pad_close(struct file *);
+static int pad_read(struct file *, off_t *, struct uio *, kauth_cred_t, int);
+static int pad_write(struct file *, off_t *, struct uio *, kauth_cred_t, int);
+static int pad_ioctl(struct file *, u_long, void *);
+static int pad_kqfilter(struct file *, struct knote *);
+static int pad_poll(struct file *, int);
+static int pad_stat(struct file *, struct stat *);
+static int pad_mmap(struct file *, off_t *, size_t, int, int *, int *,
+			   struct uvm_object **, int *);
 
 static const struct audio_hw_if pad_hw_if = {
 	.open = pad_audio_open,
@@ -135,13 +149,11 @@ static int	pad_add_block(pad_softc_t *, 
 static int	pad_get_block(pad_softc_t *, pad_block_t *, int);
 
 dev_type_open(pad_open);
-dev_type_close(pad_close);
-dev_type_read(pad_read);
 
 const struct cdevsw pad_cdevsw = {
 	.d_open = pad_open,
-	.d_close = pad_close,
-	.d_read = pad_read,
+	.d_close = noclose,
+	.d_read = noread,
 	.d_write = nowrite,
 	.d_ioctl = noioctl,
 	.d_stop = nostop,
@@ -153,35 +165,35 @@ const struct cdevsw pad_cdevsw = {
 	.d_flag = D_OTHER | D_MPSAFE,
 };
 
+const struct fileops pad_fileops = {
+	.fo_read = pad_read,
+	.fo_write = pad_write,
+	.fo_ioctl = pad_ioctl,
+	.fo_fcntl = fnullop_fcntl,
+	.fo_stat = pad_stat,
+	.fo_poll = pad_poll,
+	.fo_close = pad_close,
+	.fo_mmap = pad_mmap,
+	.fo_kqfilter = pad_kqfilter,
+	.fo_restart = fnullop_restart
+};
+
 CFATTACH_DECL2_NEW(pad, sizeof(pad_softc_t), pad_match, pad_attach, pad_detach,
     NULL, NULL, pad_childdet);
 
 void
 padattach(int n)
 {
-	int i, err;
-	cfdata_t cf;
-
-	aprint_debug("pad: requested %d units\n", n);
+	int error;
 
-	err = config_cfattach_attach(pad_cd.cd_name, &pad_ca);
-	if (err) {
+	error = config_cfattach_attach(pad_cd.cd_name, &pad_ca);
+	if (error) {
 		aprint_error("%s: couldn't register cfattach: %d\n",
-		    pad_cd.cd_name, err);
+		    pad_cd.cd_name, error);
 		config_cfdriver_detach(&pad_cd);
 		return;
 	}
 
-	for (i = 0; i < n; i++) {
-		cf = kmem_alloc(sizeof(struct cfdata), KM_SLEEP);
-		cf->cf_name = pad_cd.cd_name;
-		cf->cf_atname = pad_cd.cd_name;
-		cf->cf_unit = i;
-		cf->cf_fstate = FSTATE_STAR;
-
-		(void)config_attach_pseudo(cf);
-	}
-
 	return;
 }
 
@@ -258,51 +270,37 @@ pad_childdet(device_t self, device_t chi
 static void
 pad_attach(device_t parent, device_t self, void *opaque)
 {
-	pad_softc_t *sc = device_private(self);
-
 	aprint_normal_dev(self, "outputs: 44100Hz, 16-bit, stereo\n");
 
-	sc->sc_dev = self;
-	sc->sc_open = 0;
-	if (auconv_create_encodings(pad_formats, PAD_NFORMATS,
-	    &sc->sc_encodings) != 0) {
-		aprint_error_dev(self, "couldn't create encodings\n");
-		return;
-	}
-
-	cv_init(&sc->sc_condvar, device_xname(self));
-	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
-
-	sc->sc_swvol = 255;
-	sc->sc_buflen = 0;
-	sc->sc_rpos = sc->sc_wpos = 0;
-	sc->sc_audiodev = audio_attach_mi(&pad_hw_if, sc, sc->sc_dev);
-
-	if (!pmf_device_register(self, NULL, NULL))
-		aprint_error_dev(self, "couldn't establish power handler\n");
-
-	pad_is_attached = true;
 	return;
 }
 
 static int
 pad_detach(device_t self, int flags)
 {
-	pad_softc_t *sc = device_private(self);
+	pad_softc_t *sc;
 	int cmaj, mn, rc;
 
-	if (!pad_is_attached)
-		return ENXIO;
+	sc = device_private(self);
+	config_deactivate(sc->sc_audiodev);
+	
+	/* Start draining existing accessors of the device. */
+	if ((rc = config_detach_children(self, flags)) != 0)
+		return rc;
+
+	mutex_enter(&sc->sc_lock);
+	sc->sc_dying = true;
+	cv_broadcast(&sc->sc_condvar);
+	mutex_exit(&sc->sc_lock);
+
+	KASSERT(sc->sc_open > 0);
+	sc->sc_open = 0;
 
 	cmaj = cdevsw_lookup_major(&pad_cdevsw);
-	mn = device_unit(self);
+	mn = device_unit(sc->sc_dev);
 	vdevgone(cmaj, mn, mn, VCHR);
 
-	if ((rc = config_detach_children(self, flags)) != 0)
-		return rc;
-
-	pmf_device_deregister(self);
+	pmf_device_deregister(sc->sc_dev);
 
 	mutex_destroy(&sc->sc_lock);
 	mutex_destroy(&sc->sc_intr_lock);
@@ -310,46 +308,149 @@ pad_detach(device_t self, int flags)
 
 	auconv_delete_encodings(sc->sc_encodings);
 
-	pad_is_attached = false;
-	return 0;
+	return rc;
 }
 
 int
 pad_open(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	pad_softc_t *sc;
+	struct file *fp;
+	device_t paddev;
+	cfdata_t cf;
+	int error, fd, i;
 
-	sc = device_lookup_private(&pad_cd, PADUNIT(dev));
-	if (sc == NULL)
+	for (i = 0; i < MAXDEVS; i++) {
+		if (device_lookup(&pad_cd, i) == NULL)
+			break;
+	}
+	if (i == MAXDEVS)
 		return ENXIO;
 
-	if (atomic_swap_uint(&sc->sc_open, 1) != 0)
+	cf = kmem_alloc(sizeof(struct cfdata), KM_SLEEP);
+	cf->cf_name = pad_cd.cd_name;
+	cf->cf_atname = pad_cd.cd_name;
+	cf->cf_unit = i;
+	cf->cf_fstate = FSTATE_STAR;
+
+	paddev = config_attach_pseudo(cf);
+	sc = device_private(paddev);
+	sc->sc_dev = paddev;
+	sc->sc_dying = false;
+
+	if (sc->sc_open == 1)
 		return EBUSY;
+
+	error = fd_allocfile(&fp, &fd);
+	if (error) {
+		config_detach(sc->sc_dev, 0);
+		return error;
+	}
+
+	if (auconv_create_encodings(pad_formats, PAD_NFORMATS,
+	    &sc->sc_encodings) != 0) {
+		aprint_error_dev(sc->sc_dev, "couldn't create encodings\n");
+		config_detach(sc->sc_dev, 0);
+		return EINVAL;
+	}
+
+	cv_init(&sc->sc_condvar, device_xname(sc->sc_dev));
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
+
+	sc->sc_swvol = 255;
+	sc->sc_buflen = 0;
+	sc->sc_rpos = sc->sc_wpos = 0;
+	sc->sc_audiodev = audio_attach_mi(&pad_hw_if, sc, sc->sc_dev);
+
+	if (!pmf_device_register(sc->sc_dev, NULL, NULL))
+		aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
+
+	error = fd_clone(fp, fd, flags, &pad_fileops, sc);
+	KASSERT(error == EMOVEFD);
 	
-	return 0;
+	sc->sc_open = 1;
+
+	return error;
 }
 
-int
-pad_close(dev_t dev, int flags, int fmt, struct lwp *l)
+static int
+pad_close(struct file *fp)
 {
 	pad_softc_t *sc;
 
-	sc = device_lookup_private(&pad_cd, PADUNIT(dev));
+	sc = fp->f_pad;
 	if (sc == NULL)
 		return ENXIO;
 
-	KASSERT(sc->sc_open > 0);
-	sc->sc_open = 0;
+	config_detach(sc->sc_dev, DETACH_FORCE);
+
+	fp->f_pad = NULL;
+
+	return 0;
+}
+
+static int
+pad_poll(struct file *fp, int events)
+{
+	return ENODEV;
+}
+
+static int
+pad_kqfilter(struct file *fp, struct knote *kn)
+{
+	struct pad_softc *sc;
+	dev_t dev;
+	
+	sc = fp->f_pad;
+	if (sc == NULL)
+		return EIO;
+
+	dev = makedev(cdevsw_lookup_major(&pad_cdevsw), device_unit(sc->sc_dev));
+
+	return seltrue_kqfilter(dev, kn);
+}
+
+static int
+pad_ioctl(struct file *fp, u_long cmd, void *data)
+{
+	return ENODEV;
+}
+
+static int
+pad_stat(struct file *fp, struct stat *st)
+{
+	struct pad_softc *sc;
+	
+	sc = fp->f_pad;
+	if (sc == NULL)
+		return EIO;
+
+	memset(st, 0, sizeof(*st));
+
+	st->st_dev = makedev(cdevsw_lookup_major(&pad_cdevsw), device_unit(sc->sc_dev));
+
+	st->st_uid = kauth_cred_geteuid(fp->f_cred);
+	st->st_gid = kauth_cred_getegid(fp->f_cred);
+	st->st_mode = S_IFCHR;
 
 	return 0;
 }
 
+static int
+pad_mmap(struct file *fp, off_t *offp, size_t len, int prot, int *flagsp,
+	     int *advicep, struct uvm_object **uobjp, int *maxprotp)
+{
+	return 1;
+}
+
 #define PAD_BYTES_PER_SEC   (PADFREQ * PADPREC / NBBY * PADCHAN)
 #define BYTESTOSLEEP	    (int64_t)(PAD_BLKSIZE)
 #define TIMENEXTREAD	    (int64_t)(BYTESTOSLEEP * 1000000 / PAD_BYTES_PER_SEC)
 
-int
-pad_read(dev_t dev, struct uio *uio, int flags)
+static int
+pad_read(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
+	  int ioflag)
 {
 	struct timeval now;
 	uint64_t nowusec, lastusec;
@@ -359,7 +460,7 @@ pad_read(dev_t dev, struct uio *uio, int
 	void *intrarg;
 	int err, wait_ticks;
 
-	sc = device_lookup_private(&pad_cd, PADUNIT(dev));
+	sc = fp->f_pad;
 	if (sc == NULL)
 		return ENXIO;
 
@@ -367,6 +468,10 @@ pad_read(dev_t dev, struct uio *uio, int
 
 	while (uio->uio_resid > 0 && !err) {
 		mutex_enter(&sc->sc_lock);
+		if (sc->sc_dying == true) {
+			mutex_exit(&sc->sc_lock);
+			return EIO;
+		}
 		intr = sc->sc_intr;
 		intrarg = sc->sc_intrarg;
 
@@ -425,6 +530,13 @@ pad_read(dev_t dev, struct uio *uio, int
 }
 
 static int
+pad_write(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
+	  int ioflag)
+{
+	return EOPNOTSUPP;
+}
+
+static int
 pad_audio_open(void *opaque, int flags)
 {
 	pad_softc_t *sc;

Index: src/sys/dev/pad/padvar.h
diff -u src/sys/dev/pad/padvar.h:1.10 src/sys/dev/pad/padvar.h:1.11
--- src/sys/dev/pad/padvar.h:1.10	Sat Jul  1 05:50:10 2017
+++ src/sys/dev/pad/padvar.h	Sat Jul  1 23:31:19 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: padvar.h,v 1.10 2017/07/01 05:50:10 nat Exp $ */
+/* $NetBSD: padvar.h,v 1.11 2017/07/01 23:31:19 nat Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca>
@@ -40,6 +40,7 @@ typedef struct pad_softc {
 	kcondvar_t	sc_condvar;
 	kmutex_t	sc_lock;
 	kmutex_t	sc_intr_lock;
+	bool		sc_dying;
 
 	device_t	sc_audiodev;
 	int		sc_blksize;

Index: src/sys/sys/file.h
diff -u src/sys/sys/file.h:1.81 src/sys/sys/file.h:1.82
--- src/sys/sys/file.h:1.81	Fri Feb 10 19:31:42 2017
+++ src/sys/sys/file.h	Sat Jul  1 23:31:19 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: file.h,v 1.81 2017/02/10 19:31:42 nat Exp $	*/
+/*	$NetBSD: file.h,v 1.82 2017/07/01 23:31:19 nat Exp $	*/
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -104,6 +104,7 @@ union file_data {
 	void *fd_data;			// DTYPE_MISC
 	struct rnd_ctx *fd_rndctx;	// DTYPE_MISC (rnd)
 	struct audio_chan *fd_audioctx;	// DTYPE_MISC (audio)
+	struct pad_softc *fd_pad;	// DTYPE_MISC (pad)
 	int fd_devunit;			// DTYPE_MISC (tap)
 	struct bpf_d *fd_bpf;		// DTYPE_MISC (bpf)
 	struct fcrypt *fd_fcrypt;	// DTYPE_CRYPTO is not used
@@ -146,6 +147,7 @@ struct file {
 
 #define f_rndctx	f_undata.fd_rndctx
 #define f_audioctx	f_undata.fd_audioctx
+#define f_pad		f_undata.fd_pad
 #define f_devunit	f_undata.fd_devunit
 #define f_bpf		f_undata.fd_bpf
 #define f_fcrypt	f_undata.fd_fcrypt

Reply via email to