Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F169300720
D5191.id13006.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D5191.id13006.diff
View Options
Index: sys/dev/sound/pcm/sndstat.c
===================================================================
--- sys/dev/sound/pcm/sndstat.c
+++ sys/dev/sound/pcm/sndstat.c
@@ -44,14 +44,15 @@
#define SS_TYPE_LAST 3
static d_open_t sndstat_open;
-static d_close_t sndstat_close;
+static void sndstat_close(void *);
static d_read_t sndstat_read;
+static d_write_t sndstat_write;
static struct cdevsw sndstat_cdevsw = {
.d_version = D_VERSION,
.d_open = sndstat_open,
- .d_close = sndstat_close,
.d_read = sndstat_read,
+ .d_write = sndstat_write,
.d_name = "sndstat",
.d_flags = D_TRACKCLOSE,
};
@@ -64,50 +65,27 @@
int type, unit;
};
+struct sndstat_file {
+ TAILQ_ENTRY(sndstat_file) entry;
+ struct sbuf sbuf;
+ int out_offset;
+ int in_offset;
+};
+
static struct sx sndstat_lock;
-static struct sbuf sndstat_sbuf;
-static struct cdev *sndstat_dev = NULL;
-static int sndstat_bufptr = -1;
+static struct cdev *sndstat_dev;
static int sndstat_maxunit = -1;
-static int sndstat_files = 0;
+static int sndstat_files;
-#define SNDSTAT_PID(x) ((pid_t)((intptr_t)((x)->si_drv1)))
-#define SNDSTAT_PID_SET(x, y) (x)->si_drv1 = (void *)((intptr_t)(y))
-#define SNDSTAT_FLUSH() do { \
- if (sndstat_bufptr != -1) { \
- sbuf_delete(&sndstat_sbuf); \
- sndstat_bufptr = -1; \
- } \
-} while (0)
+#define SNDSTAT_LOCK() sx_xlock(&sndstat_lock)
+#define SNDSTAT_UNLOCK() sx_xunlock(&sndstat_lock)
static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(sndstat_devlist);
+static TAILQ_HEAD(, sndstat_file) sndstat_filelist = TAILQ_HEAD_INITIALIZER(sndstat_filelist);
int snd_verbose = 0;
-#ifdef SND_DEBUG
-static int
-sysctl_hw_snd_sndstat_pid(SYSCTL_HANDLER_ARGS)
-{
- int err, val;
-
- if (sndstat_dev == NULL)
- return (EINVAL);
-
- sx_xlock(&sndstat_lock);
- val = (int)SNDSTAT_PID(sndstat_dev);
- err = sysctl_handle_int(oidp, &val, 0, req);
- if (err == 0 && req->newptr != NULL && val == 0) {
- SNDSTAT_FLUSH();
- SNDSTAT_PID_SET(sndstat_dev, 0);
- }
- sx_unlock(&sndstat_lock);
- return (err);
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, sndstat_pid, CTLTYPE_INT | CTLFLAG_RWTUN,
- 0, sizeof(int), sysctl_hw_snd_sndstat_pid, "I", "sndstat busy pid");
-#endif
-
-static int sndstat_prepare(struct sbuf *s);
+static int sndstat_prepare(struct sndstat_file *);
static int
sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
@@ -122,7 +100,7 @@
else
snd_verbose = verbose;
}
- return error;
+ return (error);
}
SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RWTUN,
0, sizeof(int), sysctl_hw_sndverbose, "I", "verbosity level");
@@ -130,75 +108,123 @@
static int
sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
{
- if (sndstat_dev == NULL || i_dev != sndstat_dev)
- return EBADF;
-
- sx_xlock(&sndstat_lock);
- if (SNDSTAT_PID(i_dev) != 0) {
- sx_unlock(&sndstat_lock);
- return EBUSY;
- }
- SNDSTAT_PID_SET(i_dev, td->td_proc->p_pid);
- if (sbuf_new(&sndstat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
- SNDSTAT_PID_SET(i_dev, 0);
- sx_unlock(&sndstat_lock);
- return ENXIO;
- }
- sndstat_bufptr = 0;
- sx_unlock(&sndstat_lock);
- return 0;
-}
+ struct sndstat_file *pf;
-static int
-sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
-{
- if (sndstat_dev == NULL || i_dev != sndstat_dev)
- return EBADF;
+ pf = malloc(sizeof(*pf), M_DEVBUF, M_WAITOK | M_ZERO);
- sx_xlock(&sndstat_lock);
- if (SNDSTAT_PID(i_dev) == 0) {
- sx_unlock(&sndstat_lock);
- return EBADF;
+ SNDSTAT_LOCK();
+ if (sbuf_new(&pf->sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
+ SNDSTAT_UNLOCK();
+ free(pf, M_DEVBUF);
+ return (ENOMEM);
}
+ TAILQ_INSERT_TAIL(&sndstat_filelist, pf, entry);
+ SNDSTAT_UNLOCK();
+
+ devfs_set_cdevpriv(pf, &sndstat_close);
- SNDSTAT_FLUSH();
- SNDSTAT_PID_SET(i_dev, 0);
+ return (0);
+}
+
+static void
+sndstat_close(void *sndstat_file)
+{
+ struct sndstat_file *pf = (struct sndstat_file *)sndstat_file;
- sx_unlock(&sndstat_lock);
+ SNDSTAT_LOCK();
+ sbuf_delete(&pf->sbuf);
+ TAILQ_REMOVE(&sndstat_filelist, pf, entry);
+ SNDSTAT_UNLOCK();
- return 0;
+ free(pf, M_DEVBUF);
}
static int
sndstat_read(struct cdev *i_dev, struct uio *buf, int flag)
{
- int l, err;
-
- if (sndstat_dev == NULL || i_dev != sndstat_dev)
- return EBADF;
-
- sx_xlock(&sndstat_lock);
- if (SNDSTAT_PID(i_dev) != buf->uio_td->td_proc->p_pid ||
- sndstat_bufptr == -1) {
- sx_unlock(&sndstat_lock);
- return EBADF;
- }
-
- if (sndstat_bufptr == 0) {
- err = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM;
- if (err) {
- SNDSTAT_FLUSH();
- sx_unlock(&sndstat_lock);
- return err;
+ struct sndstat_file *pf;
+ int err;
+ int len;
+
+ err = devfs_get_cdevpriv((void **)&pf);
+ if (err != 0)
+ return (err);
+
+ /* skip zero-length reads */
+ if (buf->uio_resid == 0)
+ return (0);
+
+ SNDSTAT_LOCK();
+ if (pf->out_offset != 0) {
+ /* don't allow both reading and writing */
+ err = EINVAL;
+ goto done;
+ } else if (pf->in_offset == 0) {
+ err = sndstat_prepare(pf);
+ if (err <= 0) {
+ err = ENOMEM;
+ goto done;
}
}
+ len = sbuf_len(&pf->sbuf) - pf->in_offset;
+ if (len > buf->uio_resid)
+ len = buf->uio_resid;
+ if (len > 0)
+ err = uiomove(sbuf_data(&pf->sbuf) + pf->in_offset, len, buf);
+ pf->in_offset += len;
+done:
+ SNDSTAT_UNLOCK();
+ return (err);
+}
- l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr);
- err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
- sndstat_bufptr += l;
- sx_unlock(&sndstat_lock);
-
- return err;
+static int
+sndstat_write(struct cdev *i_dev, struct uio *buf, int flag)
+{
+ struct sndstat_file *pf;
+ uint8_t temp[64];
+ int err;
+ int len;
+
+ err = devfs_get_cdevpriv((void **)&pf);
+ if (err != 0)
+ return (err);
+
+ /* skip zero-length writes */
+ if (buf->uio_resid == 0)
+ return (0);
+
+ /* don't allow writing more than 64Kbytes */
+ if (buf->uio_resid > 65536)
+ return (ENOMEM);
+
+ SNDSTAT_LOCK();
+ if (pf->in_offset != 0 || pf->out_offset != 0) {
+ /* don't allow both reading and writing */
+ err = EINVAL;
+ } else {
+ while (1) {
+ len = sizeof(temp);
+ if (len > buf->uio_resid)
+ len = buf->uio_resid;
+ if (len > 0) {
+ err = uiomove(temp, len, buf);
+ if (err)
+ break;
+ } else {
+ break;
+ }
+ if (sbuf_bcat(&pf->sbuf, temp, len) < 0) {
+ err = ENOMEM;
+ break;
+ }
+ }
+ if (err == 0) {
+ sbuf_finish(&pf->sbuf);
+ pf->out_offset = sbuf_len(&pf->sbuf);
+ }
+ }
+ SNDSTAT_UNLOCK();
+ return (err);
}
/************************************************************************/
@@ -210,42 +236,26 @@
SLIST_FOREACH(ent, &sndstat_devlist, link) {
if (ent->type == type && ent->unit == unit)
- return ent;
+ return (ent);
}
- return NULL;
+ return (NULL);
}
int
sndstat_acquire(struct thread *td)
{
- if (sndstat_dev == NULL)
- return EBADF;
-
- sx_xlock(&sndstat_lock);
- if (SNDSTAT_PID(sndstat_dev) != 0) {
- sx_unlock(&sndstat_lock);
- return EBUSY;
- }
- SNDSTAT_PID_SET(sndstat_dev, td->td_proc->p_pid);
- sx_unlock(&sndstat_lock);
- return 0;
+ SNDSTAT_LOCK();
+ SNDSTAT_UNLOCK();
+ return (0);
}
int
sndstat_release(struct thread *td)
{
- if (sndstat_dev == NULL)
- return EBADF;
-
- sx_xlock(&sndstat_lock);
- if (SNDSTAT_PID(sndstat_dev) != td->td_proc->p_pid) {
- sx_unlock(&sndstat_lock);
- return EBADF;
- }
- SNDSTAT_PID_SET(sndstat_dev, 0);
- sx_unlock(&sndstat_lock);
- return 0;
+ SNDSTAT_LOCK();
+ SNDSTAT_UNLOCK();
+ return (0);
}
int
@@ -265,7 +275,7 @@
else if (!strcmp(devtype, "sequencer"))
type = SS_TYPE_SEQUENCER;
else
- return EINVAL;
+ return (EINVAL);
} else {
type = SS_TYPE_MODULE;
unit = -1;
@@ -278,20 +288,20 @@
ent->unit = unit;
ent->handler = handler;
- sx_xlock(&sndstat_lock);
+ SNDSTAT_LOCK();
SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
if (type == SS_TYPE_MODULE)
sndstat_files++;
sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
- sx_unlock(&sndstat_lock);
+ SNDSTAT_UNLOCK();
- return 0;
+ return (0);
}
int
sndstat_registerfile(char *str)
{
- return sndstat_register(NULL, str, NULL);
+ return (sndstat_register(NULL, str, NULL));
}
int
@@ -299,19 +309,19 @@
{
struct sndstat_entry *ent;
- sx_xlock(&sndstat_lock);
+ SNDSTAT_LOCK();
SLIST_FOREACH(ent, &sndstat_devlist, link) {
if (ent->dev == dev) {
SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
- sx_unlock(&sndstat_lock);
+ SNDSTAT_UNLOCK();
free(ent, M_DEVBUF);
- return 0;
+ return (0);
}
}
- sx_unlock(&sndstat_lock);
+ SNDSTAT_UNLOCK();
- return ENXIO;
+ return (ENXIO);
}
int
@@ -319,29 +329,31 @@
{
struct sndstat_entry *ent;
- sx_xlock(&sndstat_lock);
+ SNDSTAT_LOCK();
SLIST_FOREACH(ent, &sndstat_devlist, link) {
if (ent->dev == NULL && ent->str == str) {
SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
sndstat_files--;
- sx_unlock(&sndstat_lock);
+ SNDSTAT_UNLOCK();
free(ent, M_DEVBUF);
- return 0;
+ return (0);
}
}
- sx_unlock(&sndstat_lock);
+ SNDSTAT_UNLOCK();
- return ENXIO;
+ return (ENXIO);
}
/************************************************************************/
static int
-sndstat_prepare(struct sbuf *s)
+sndstat_prepare(struct sndstat_file *pf_self)
{
+ struct sbuf *s = &pf_self->sbuf;
struct sndstat_entry *ent;
struct snddev_info *d;
+ struct sndstat_file *pf;
int i, j;
if (snd_verbose > 0) {
@@ -350,12 +362,6 @@
MACHINE_ARCH);
}
- if (SLIST_EMPTY(&sndstat_devlist)) {
- sbuf_printf(s, "No devices installed.\n");
- sbuf_finish(s);
- return sbuf_len(s);
- }
-
sbuf_printf(s, "Installed devices:\n");
for (i = 0; i <= sndstat_maxunit; i++) {
@@ -379,6 +385,18 @@
}
}
+ sbuf_printf(s, "Installed devices from userspace:\n");
+
+ /* append any input from userspace */
+ TAILQ_FOREACH(pf, &sndstat_filelist, entry) {
+ if (pf == pf_self)
+ continue;
+ if (pf->out_offset != 0) {
+ sbuf_bcat(s, sbuf_data(&pf->sbuf),
+ sbuf_len(&pf->sbuf));
+ }
+ }
+
if (snd_verbose >= 3 && sndstat_files > 0) {
sbuf_printf(s, "\nFile Versions:\n");
@@ -389,57 +407,25 @@
}
sbuf_finish(s);
- return sbuf_len(s);
-}
-
-static int
-sndstat_init(void)
-{
- if (sndstat_dev != NULL)
- return EINVAL;
- sx_init(&sndstat_lock, "sndstat lock");
- sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS,
- UID_ROOT, GID_WHEEL, 0444, "sndstat");
- return 0;
-}
-
-static int
-sndstat_uninit(void)
-{
- if (sndstat_dev == NULL)
- return EINVAL;
-
- sx_xlock(&sndstat_lock);
- if (SNDSTAT_PID(sndstat_dev) != curthread->td_proc->p_pid) {
- sx_unlock(&sndstat_lock);
- return EBUSY;
- }
-
- /* XXXPHO: use destroy_dev_sched() */
- destroy_dev(sndstat_dev);
- sndstat_dev = NULL;
-
- SNDSTAT_FLUSH();
-
- sx_unlock(&sndstat_lock);
- sx_destroy(&sndstat_lock);
- return 0;
+ return (sbuf_len(s));
}
static void
sndstat_sysinit(void *p)
{
- sndstat_init();
+ sx_init(&sndstat_lock, "sndstat lock");
+ sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS,
+ UID_ROOT, GID_WHEEL, 0664, "sndstat");
}
+SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
static void
sndstat_sysuninit(void *p)
{
- int error;
-
- error = sndstat_uninit();
- KASSERT(error == 0, ("%s: error = %d", __func__, error));
+ if (sndstat_dev != NULL) {
+ /* destroy_dev() will wait for all references to go away */
+ destroy_dev(sndstat_dev);
+ }
+ sx_destroy(&sndstat_lock);
}
-
-SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysuninit, NULL);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Sep 2, 3:57 AM (1 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37898479
Default Alt Text
D5191.id13006.diff (11 KB)
Attached To
Mode
D5191: Make /dev/sndstat writeable
Attached
Detach File
Event Timeline
Log In to Comment