Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147911132
D29770.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
27 KB
Referenced Files
None
Subscribers
None
D29770.diff
View Options
diff --git a/share/man/man4/sndstat.4 b/share/man/man4/sndstat.4
--- a/share/man/man4/sndstat.4
+++ b/share/man/man4/sndstat.4
@@ -31,7 +31,7 @@
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
-.Dd December 7, 2020
+.Dd April 15, 2021
.Dt SNDSTAT 4
.Os
.Sh NAME
@@ -52,7 +52,7 @@
For all ioctls requiring data exchange between the subsystem and callers,
the following structures are used to describe a serialized nvlist:
.Bd -literal -offset indent
-struct sndstat_nvlbuf_arg {
+struct sndstioc_nv_arg {
size_t nbytes;
void *buf;
};
@@ -67,9 +67,12 @@
desc (STRING): [Generic (0x8086) (Analog Line-out)]
pchan (NUMBER): 1 (1) (0x1)
rchan (NUMBER): 0 (0) (0x0)
- pminrate (NUMBER): 48000 (48000) (0xbb80)
- pmaxrate (NUMBER): 48000 (48000) (0xbb80)
- pfmts (NUMBER): 2097168 (2097168) (0x200010)
+ info_play (NVLIST):
+ min_rate (NUMBER): 48000 (48000) (0xbb80)
+ max_rate (NUMBER): 48000 (48000) (0xbb80)
+ formats (NUMBER): 16 (16) (0x10)
+ min_chn (NUMBER): 2 (2) (0x2)
+ max_chn (NUMBER): 2 (2) (0x2)
provider_info (NVLIST):
unit (NUMBER): 0 (0) (0x0)
bitperfect (BOOL): FALSE
@@ -94,24 +97,38 @@
.It Dv rchan
The number of recording channels supported by hardware.
This can be 0 if this PCM audio device does not support recording at all.
-.It Dv pminrate
-The minimum supported playback direction sampling rate.
-Only exists if pchan is greater than 0.
-.It Dv pmaxrate
-The maximum supported playback direction sampling rate.
-Only exists if pchan is greater than 0.
-.It Dv pfmts
-The supported playback direction sample format.
-Only exists if pchan is greater than 0.
-.It Dv rminrate
-The minimum supported recording direction sampling rate.
-Only exists if rchan is greater than 0.
-.It Dv rmaxrate
-The maximum supported recording direction sampling rate.
-Only exists if rchan is greater than 0.
-.It Dv rfmts
-The supported playback recording sample format.
-Only exists if rchan is greater than 0.
+.It Dv info_play
+Supported configurations in playback direction.
+This exists only if this PCM audio device supports playback.
+There are a number of name/value pairs inside this field:
+.Bl -tag -width ".Dv min_rate"
+.It Dv min_rate
+Minimum supported sampling rate.
+.It Dv max_rate
+Maximum supported sampling rate.
+.It Dv formats
+Supported sample formats.
+.It Dv min_chn
+Minimum supported number of channels in channel layout
+.It Dv max_chn
+Maximum supported number of channels in channel layout
+.El
+.It Dv info_rec
+Supported configurations in recording direction.
+This exists only if this PCM audio device supports recording.
+There are a number of name/value pairs inside this field:
+.Bl -tag -width ".Dv min_rate"
+.It Dv min_rate
+Minimum supported sampling rate.
+.It Dv max_rate
+Maximum supported sampling rate.
+.It Dv formats
+Supported sample formats.
+.It Dv min_chn
+Minimum supported number of channels in channel layout
+.It Dv max_chn
+Maximum supported number of channels in channel layout
+.El
.It Dv provider_info
Provider-specific fields.
This field may not exist if the PCM audio device is not provided by in-kernel
@@ -121,15 +138,15 @@
A string specifying the provider of the PCm audio device.
.El
.Pp
-The following ioctls are providede for use:
-.Bl -tag -width ".Dv SNDSTAT_FLUSH_USER_DEVS"
-.It Dv SNDSTAT_REFRESH_DEVS
+The following ioctls are provided for use:
+.Bl -tag -width ".Dv SNDSTIOC_FLUSH_USER_DEVS"
+.It Dv SNDSTIOC_REFRESH_DEVS
Drop any previously fetched PCM audio devices list snapshots.
This ioctl takes no arguments.
-.It Dv SNDSTAT_GET_DEVS
+.It Dv SNDSTIOC_GET_DEVS
Generate and/or return PCM audio devices list snapshots to callers.
This ioctl takes a pointer to
-.Fa struct sndstat_nvlbuf_arg
+.Fa struct sndstioc_nv_arg
as the first and the only argument.
Callers need to provide a sufficiently large buffer to hold a serialized
nvlist.
@@ -159,12 +176,12 @@
the snapshot stored in the subsystem's internal structure of the given
.Fa fd
will be freed.
-.It Dv SNDSTAT_ADD_USER_DEVS
+.It Dv SNDSTIOC_ADD_USER_DEVS
Add a list of PCM audio devices provided by callers to
.Pa /dev/sndstat
device.
This ioctl takes a pointer to
-.Fa struct sndstat_nvlbuf_arg
+.Fa struct sndstioc_nv_arg
as the first and the only argument.
Callers have to provide a buffer holding a serialized nvlist.
.Fa nbytes
@@ -173,7 +190,7 @@
should be pointed to a buffer storing the serialized nvlist.
Userspace-backed PCM audio device nodes should be listed inside the serialized
nvlist.
-.It Dv SNDSTAT_FLUSH_USER_DEVS
+.It Dv SNDSTIOC_FLUSH_USER_DEVS
Flush any PCM audio devices previously added by callers.
This ioctl takes no arguments.
.El
@@ -198,7 +215,7 @@
main()
{
int fd;
- struct sndstat_nvlbuf_arg arg;
+ struct sndstioc_nv_arg arg;
const nvlist_t * const *di;
size_t i, nitems;
nvlist_t *nvl;
@@ -206,28 +223,28 @@
/* Open sndstat node in read-only first */
fd = open("/dev/sndstat", O_RDONLY);
- if (ioctl(fd, SNDSTAT_REFRESH_DEVS, NULL))
- err(1, "ioctl(fd, SNDSTAT_REFRESH_DEVS, NULL)");
+ if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL))
+ err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)");
/* Get the size of snapshot, when nbytes = 0 */
arg.nbytes = 0;
arg.buf = NULL;
- if (ioctl(fd, SNDSTAT_GET_DEVS, &arg))
- err(1, "ioctl(fd, SNDSTAT_GET_DEVS, &arg)");
+ if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg))
+ err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)");
/* Get snapshot data */
arg.buf = malloc(arg.nbytes);
if (arg.buf == NULL)
err(EX_OSERR, "malloc");
- if (ioctl(fd, SNDSTAT_GET_DEVS, &arg))
- err(1, "ioctl(fd, SNDSTAT_GET_DEVS, &arg)");
+ if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg))
+ err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)");
/* Deserialize the nvlist stream */
nvl = nvlist_unpack(arg.buf, arg.nbytes, 0);
free(arg.buf);
/* Get DSPs array */
- di = nvlist_get_nvlist_array(nvl, SNDSTAT_LABEL_DSPS, &nitems);
+ di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems);
for (i = 0; i < nitems; i++) {
const char *nameunit, *devnode, *desc;
@@ -235,9 +252,9 @@
* Examine each device nvlist item
*/
- nameunit = nvlist_get_string(di[i], SNDSTAT_LABEL_NAMEUNIT);
- devnode = nvlist_get_string(di[i], SNDSTAT_LABEL_DEVNODE);
- desc = nvlist_get_string(di[i], SNDSTAT_LABEL_DESC);
+ nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT);
+ devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE);
+ desc = nvlist_get_string(di[i], SNDST_DSPS_DESC);
printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n",
nameunit, devnode, desc);
}
diff --git a/sys/dev/sound/pcm/sndstat.c b/sys/dev/sound/pcm/sndstat.c
--- a/sys/dev/sound/pcm/sndstat.c
+++ b/sys/dev/sound/pcm/sndstat.c
@@ -89,12 +89,13 @@
char *desc;
unsigned int pchan;
unsigned int rchan;
- uint32_t pminrate;
- uint32_t pmaxrate;
- uint32_t rminrate;
- uint32_t rmaxrate;
- uint32_t pfmts;
- uint32_t rfmts;
+ struct {
+ uint32_t min_rate;
+ uint32_t max_rate;
+ uint32_t formats;
+ uint32_t min_chn;
+ uint32_t max_chn;
+ } info_play, info_rec;
nvlist_t *provider_nvl;
};
@@ -326,46 +327,77 @@
static void
sndstat_get_caps(struct snddev_info *d, bool play, uint32_t *min_rate,
- uint32_t *max_rate, uint32_t *fmts)
+ uint32_t *max_rate, uint32_t *fmts, uint32_t *minchn, uint32_t *maxchn)
{
struct pcm_channel *c;
+ unsigned int encoding;
int dir;
dir = play ? PCMDIR_PLAY : PCMDIR_REC;
- *min_rate = 0;
- *max_rate = 0;
- *fmts = 0;
if (play && d->pvchancount > 0) {
*min_rate = *max_rate = d->pvchanrate;
- *fmts = d->pvchanformat;
+ *fmts = AFMT_ENCODING(d->pvchanformat);
+ *minchn = *maxchn = AFMT_CHANNEL(d->pvchanformat);
return;
} else if (!play && d->rvchancount > 0) {
*min_rate = *max_rate = d->rvchanrate;
- *fmts = d->rvchanformat;
+ *fmts = AFMT_ENCODING(d->rvchanformat);
+ *minchn = *maxchn = AFMT_CHANNEL(d->rvchanformat);
return;
}
+ *min_rate = UINT32_MAX;
+ *max_rate = 0;
+ *minchn = UINT32_MAX;
+ *maxchn = 0;
+ encoding = 0;
CHN_FOREACH(c, d, channels.pcm) {
struct pcmchan_caps *caps;
+ int i;
if (c->direction != dir || (c->flags & CHN_F_VIRTUAL) != 0)
continue;
CHN_LOCK(c);
caps = chn_getcaps(c);
- *min_rate = caps->minspeed;
- *max_rate = caps->maxspeed;
- *fmts = chn_getformats(c);
+ *min_rate = min(caps->minspeed, *min_rate);
+ *max_rate = max(caps->maxspeed, *max_rate);
+ for (i = 0; caps->fmtlist[i]; i++) {
+ encoding |= AFMT_ENCODING(caps->fmtlist[i]);
+ *minchn = min(AFMT_CHANNEL(encoding), *minchn);
+ *maxchn = max(AFMT_CHANNEL(encoding), *maxchn);
+ }
CHN_UNLOCK(c);
}
+ if (*min_rate == UINT32_MAX)
+ *min_rate = 0;
+ if (*minchn == UINT32_MAX)
+ *minchn = 0;
+}
+
+static nvlist_t *
+sndstat_create_diinfo_nv(uint32_t min_rate, uint32_t max_rate, uint32_t formats,
+ uint32_t min_chn, uint32_t max_chn)
+{
+ nvlist_t *nv;
+
+ nv = nvlist_create(0);
+ if (nv == NULL)
+ return (NULL);
+ nvlist_add_number(nv, SNDST_DSPS_INFO_MIN_RATE, min_rate);
+ nvlist_add_number(nv, SNDST_DSPS_INFO_MAX_RATE, max_rate);
+ nvlist_add_number(nv, SNDST_DSPS_INFO_FORMATS, formats);
+ nvlist_add_number(nv, SNDST_DSPS_INFO_MIN_CHN, min_chn);
+ nvlist_add_number(nv, SNDST_DSPS_INFO_MAX_CHN, max_chn);
+ return (nv);
}
static int
sndstat_build_sound4_nvlist(struct snddev_info *d, nvlist_t **dip)
{
- uint32_t maxrate, minrate, fmts;
- nvlist_t *di = NULL, *sound4di = NULL;
+ uint32_t maxrate, minrate, fmts, minchn, maxchn;
+ nvlist_t *di = NULL, *sound4di = NULL, *diinfo = NULL;
int err;
di = nvlist_create(0);
@@ -379,40 +411,54 @@
goto done;
}
- nvlist_add_bool(di, SNDSTAT_LABEL_FROM_USER, false);
- nvlist_add_stringf(di, SNDSTAT_LABEL_NAMEUNIT, "%s",
+ nvlist_add_bool(di, SNDST_DSPS_FROM_USER, false);
+ nvlist_add_stringf(di, SNDST_DSPS_NAMEUNIT, "%s",
device_get_nameunit(d->dev));
- nvlist_add_stringf(di, SNDSTAT_LABEL_DEVNODE, "dsp%d",
+ nvlist_add_stringf(di, SNDST_DSPS_DEVNODE, "dsp%d",
device_get_unit(d->dev));
nvlist_add_string(
- di, SNDSTAT_LABEL_DESC, device_get_desc(d->dev));
+ di, SNDST_DSPS_DESC, device_get_desc(d->dev));
PCM_ACQUIRE_QUICK(d);
- nvlist_add_number(di, SNDSTAT_LABEL_PCHAN, d->playcount);
- nvlist_add_number(di, SNDSTAT_LABEL_RCHAN, d->reccount);
+ nvlist_add_number(di, SNDST_DSPS_PCHAN, d->playcount);
+ nvlist_add_number(di, SNDST_DSPS_RCHAN, d->reccount);
if (d->playcount > 0) {
- sndstat_get_caps(d, true, &minrate, &maxrate, &fmts);
- nvlist_add_number(di, SNDSTAT_LABEL_PMINRATE, minrate);
- nvlist_add_number(di, SNDSTAT_LABEL_PMAXRATE, maxrate);
- nvlist_add_number(di, SNDSTAT_LABEL_PFMTS, fmts);
+ sndstat_get_caps(d, true, &minrate, &maxrate, &fmts, &minchn,
+ &maxchn);
+ nvlist_add_number(di, "pminrate", minrate);
+ nvlist_add_number(di, "pmaxrate", maxrate);
+ nvlist_add_number(di, "pfmts", fmts);
+ diinfo = sndstat_create_diinfo_nv(minrate, maxrate, fmts,
+ minchn, maxchn);
+ if (diinfo == NULL)
+ nvlist_set_error(di, ENOMEM);
+ else
+ nvlist_move_nvlist(di, SNDST_DSPS_INFO_PLAY, diinfo);
}
if (d->reccount > 0) {
- sndstat_get_caps(d, false, &minrate, &maxrate, &fmts);
- nvlist_add_number(di, SNDSTAT_LABEL_RMINRATE, minrate);
- nvlist_add_number(di, SNDSTAT_LABEL_RMAXRATE, maxrate);
- nvlist_add_number(di, SNDSTAT_LABEL_RFMTS, fmts);
+ sndstat_get_caps(d, false, &minrate, &maxrate, &fmts, &minchn,
+ &maxchn);
+ nvlist_add_number(di, "rminrate", minrate);
+ nvlist_add_number(di, "rmaxrate", maxrate);
+ nvlist_add_number(di, "rfmts", fmts);
+ diinfo = sndstat_create_diinfo_nv(minrate, maxrate, fmts,
+ minchn, maxchn);
+ if (diinfo == NULL)
+ nvlist_set_error(di, ENOMEM);
+ else
+ nvlist_move_nvlist(di, SNDST_DSPS_INFO_REC, diinfo);
}
- nvlist_add_number(sound4di, SNDSTAT_LABEL_SOUND4_UNIT,
+ nvlist_add_number(sound4di, SNDST_DSPS_SOUND4_UNIT,
device_get_unit(d->dev)); // XXX: I want signed integer here
nvlist_add_bool(
- sound4di, SNDSTAT_LABEL_SOUND4_BITPERFECT, d->flags & SD_F_BITPERFECT);
- nvlist_add_number(sound4di, SNDSTAT_LABEL_SOUND4_PVCHAN, d->pvchancount);
- nvlist_add_number(sound4di, SNDSTAT_LABEL_SOUND4_RVCHAN, d->rvchancount);
- nvlist_move_nvlist(di, SNDSTAT_LABEL_PROVIDER_INFO, sound4di);
+ sound4di, SNDST_DSPS_SOUND4_BITPERFECT, d->flags & SD_F_BITPERFECT);
+ nvlist_add_number(sound4di, SNDST_DSPS_SOUND4_PVCHAN, d->pvchancount);
+ nvlist_add_number(sound4di, SNDST_DSPS_SOUND4_RVCHAN, d->rvchancount);
+ nvlist_move_nvlist(di, SNDST_DSPS_PROVIDER_INFO, sound4di);
sound4di = NULL;
PCM_RELEASE_QUICK(d);
- nvlist_add_string(di, SNDSTAT_LABEL_PROVIDER, SNDSTAT_LABEL_SOUND4_PROVIDER);
+ nvlist_add_string(di, SNDST_DSPS_PROVIDER, SNDST_DSPS_SOUND4_PROVIDER);
err = nvlist_error(di);
if (err)
@@ -431,7 +477,7 @@
static int
sndstat_build_userland_nvlist(struct sndstat_userdev *ud, nvlist_t **dip)
{
- nvlist_t *di;
+ nvlist_t *di, *diinfo;
int err;
di = nvlist_create(0);
@@ -440,34 +486,48 @@
goto done;
}
- nvlist_add_bool(di, SNDSTAT_LABEL_FROM_USER, true);
- nvlist_add_number(di, SNDSTAT_LABEL_PCHAN, ud->pchan);
- nvlist_add_number(di, SNDSTAT_LABEL_RCHAN, ud->rchan);
- nvlist_add_string(di, SNDSTAT_LABEL_NAMEUNIT, ud->nameunit);
+ nvlist_add_bool(di, SNDST_DSPS_FROM_USER, true);
+ nvlist_add_number(di, SNDST_DSPS_PCHAN, ud->pchan);
+ nvlist_add_number(di, SNDST_DSPS_RCHAN, ud->rchan);
+ nvlist_add_string(di, SNDST_DSPS_NAMEUNIT, ud->nameunit);
nvlist_add_string(
- di, SNDSTAT_LABEL_DEVNODE, ud->devnode);
- nvlist_add_string(di, SNDSTAT_LABEL_DESC, ud->desc);
+ di, SNDST_DSPS_DEVNODE, ud->devnode);
+ nvlist_add_string(di, SNDST_DSPS_DESC, ud->desc);
if (ud->pchan != 0) {
- nvlist_add_number(
- di, SNDSTAT_LABEL_PMINRATE, ud->pminrate);
- nvlist_add_number(
- di, SNDSTAT_LABEL_PMAXRATE, ud->pmaxrate);
- nvlist_add_number(
- di, SNDSTAT_LABEL_PFMTS, ud->pfmts);
+ nvlist_add_number(di, "pminrate",
+ ud->info_play.min_rate);
+ nvlist_add_number(di, "pmaxrate",
+ ud->info_play.max_rate);
+ nvlist_add_number(di, "pfmts",
+ ud->info_play.formats);
+ diinfo = sndstat_create_diinfo_nv(ud->info_play.min_rate,
+ ud->info_play.max_rate, ud->info_play.formats,
+ ud->info_play.min_chn, ud->info_play.max_chn);
+ if (diinfo == NULL)
+ nvlist_set_error(di, ENOMEM);
+ else
+ nvlist_move_nvlist(di, SNDST_DSPS_INFO_PLAY, diinfo);
}
if (ud->rchan != 0) {
- nvlist_add_number(
- di, SNDSTAT_LABEL_RMINRATE, ud->rminrate);
- nvlist_add_number(
- di, SNDSTAT_LABEL_RMAXRATE, ud->rmaxrate);
- nvlist_add_number(
- di, SNDSTAT_LABEL_RFMTS, ud->rfmts);
+ nvlist_add_number(di, "rminrate",
+ ud->info_rec.min_rate);
+ nvlist_add_number(di, "rmaxrate",
+ ud->info_rec.max_rate);
+ nvlist_add_number(di, "rfmts",
+ ud->info_rec.formats);
+ diinfo = sndstat_create_diinfo_nv(ud->info_rec.min_rate,
+ ud->info_rec.max_rate, ud->info_rec.formats,
+ ud->info_rec.min_chn, ud->info_rec.max_chn);
+ if (diinfo == NULL)
+ nvlist_set_error(di, ENOMEM);
+ else
+ nvlist_move_nvlist(di, SNDST_DSPS_INFO_REC, diinfo);
}
- nvlist_add_string(di, SNDSTAT_LABEL_PROVIDER,
+ nvlist_add_string(di, SNDST_DSPS_PROVIDER,
(ud->provider != NULL) ? ud->provider : "");
if (ud->provider_nvl != NULL)
nvlist_add_nvlist(
- di, SNDSTAT_LABEL_PROVIDER_INFO, ud->provider_nvl);
+ di, SNDST_DSPS_PROVIDER_INFO, ud->provider_nvl);
err = nvlist_error(di);
if (err)
@@ -511,7 +571,7 @@
if (err)
goto done;
- nvlist_append_nvlist_array(nvl, SNDSTAT_LABEL_DSPS, di);
+ nvlist_append_nvlist_array(nvl, SNDST_DSPS, di);
nvlist_destroy(di);
err = nvlist_error(nvl);
if (err)
@@ -531,7 +591,7 @@
sx_xunlock(&pf->lock);
goto done;
}
- nvlist_append_nvlist_array(nvl, SNDSTAT_LABEL_DSPS, di);
+ nvlist_append_nvlist_array(nvl, SNDST_DSPS, di);
nvlist_destroy(di);
err = nvlist_error(nvl);
@@ -568,7 +628,7 @@
sndstat_get_devs(struct sndstat_file *pf, caddr_t data)
{
int err;
- struct sndstat_nvlbuf_arg *arg = (struct sndstat_nvlbuf_arg *)data;
+ struct sndstioc_nv_arg *arg = (struct sndstioc_nv_arg *)data;
SNDSTAT_LOCK();
sx_xlock(&pf->lock);
@@ -654,31 +714,65 @@
return (0);
}
+static bool
+sndstat_diinfo_is_sane(const nvlist_t *diinfo)
+{
+ if (!(nvlist_exists_number(diinfo, SNDST_DSPS_INFO_MIN_RATE) &&
+ nvlist_exists_number(diinfo, SNDST_DSPS_INFO_MAX_RATE) &&
+ nvlist_exists_number(diinfo, SNDST_DSPS_INFO_FORMATS) &&
+ nvlist_exists_number(diinfo, SNDST_DSPS_INFO_MIN_CHN) &&
+ nvlist_exists_number(diinfo, SNDST_DSPS_INFO_MAX_CHN)))
+ return (false);
+ return (true);
+}
+
static bool
sndstat_dsp_nvlist_is_sane(const nvlist_t *nvlist)
{
- if (!(nvlist_exists_string(nvlist, SNDSTAT_LABEL_DEVNODE) &&
- nvlist_exists_string(nvlist, SNDSTAT_LABEL_DESC) &&
- nvlist_exists_number(nvlist, SNDSTAT_LABEL_PCHAN) &&
- nvlist_exists_number(nvlist, SNDSTAT_LABEL_RCHAN)))
+ if (!(nvlist_exists_string(nvlist, SNDST_DSPS_DEVNODE) &&
+ nvlist_exists_string(nvlist, SNDST_DSPS_DESC) &&
+ nvlist_exists_number(nvlist, SNDST_DSPS_PCHAN) &&
+ nvlist_exists_number(nvlist, SNDST_DSPS_RCHAN)))
return (false);
- if (nvlist_get_number(nvlist, SNDSTAT_LABEL_PCHAN) > 0)
- if (!(nvlist_exists_number(nvlist, SNDSTAT_LABEL_PMINRATE) &&
- nvlist_exists_number(nvlist, SNDSTAT_LABEL_PMAXRATE) &&
- nvlist_exists_number(nvlist, SNDSTAT_LABEL_PFMTS)))
+ if (nvlist_get_number(nvlist, SNDST_DSPS_PCHAN) > 0) {
+ if (nvlist_exists_nvlist(nvlist, SNDST_DSPS_INFO_PLAY)) {
+ if (!sndstat_diinfo_is_sane(nvlist_get_nvlist(nvlist,
+ SNDST_DSPS_INFO_PLAY)))
+ return (false);
+ } else if (!(nvlist_exists_number(nvlist, "pminrate") &&
+ nvlist_exists_number(nvlist, "pmaxrate") &&
+ nvlist_exists_number(nvlist, "pfmts")))
return (false);
+ }
- if (nvlist_get_number(nvlist, SNDSTAT_LABEL_RCHAN) > 0)
- if (!(nvlist_exists_number(nvlist, SNDSTAT_LABEL_RMINRATE) &&
- nvlist_exists_number(nvlist, SNDSTAT_LABEL_RMAXRATE) &&
- nvlist_exists_number(nvlist, SNDSTAT_LABEL_RFMTS)))
+ if (nvlist_get_number(nvlist, SNDST_DSPS_RCHAN) > 0) {
+ if (nvlist_exists_nvlist(nvlist, SNDST_DSPS_INFO_REC)) {
+ if (!sndstat_diinfo_is_sane(nvlist_get_nvlist(nvlist,
+ SNDST_DSPS_INFO_REC)))
+ return (false);
+ } else if (!(nvlist_exists_number(nvlist, "rminrate") &&
+ nvlist_exists_number(nvlist, "rmaxrate") &&
+ nvlist_exists_number(nvlist, "rfmts")))
return (false);
+ }
return (true);
}
+static void
+sndstat_get_diinfo_nv(const nvlist_t *nv, uint32_t *min_rate,
+ uint32_t *max_rate, uint32_t *formats, uint32_t *min_chn,
+ uint32_t *max_chn)
+{
+ *min_rate = nvlist_get_number(nv, SNDST_DSPS_INFO_MIN_RATE);
+ *max_rate = nvlist_get_number(nv, SNDST_DSPS_INFO_MAX_RATE);
+ *formats = nvlist_get_number(nv, SNDST_DSPS_INFO_FORMATS);
+ *min_chn = nvlist_get_number(nv, SNDST_DSPS_INFO_MIN_CHN);
+ *max_chn = nvlist_get_number(nv, SNDST_DSPS_INFO_MAX_CHN);
+}
+
static int
sndstat_dsp_unpack_nvlist(const nvlist_t *nvlist, struct sndstat_userdev *ud)
{
@@ -687,36 +781,53 @@
uint32_t pminrate = 0, pmaxrate = 0;
uint32_t rminrate = 0, rmaxrate = 0;
uint32_t pfmts = 0, rfmts = 0;
+ uint32_t pminchn = 0, pmaxchn = 0;
+ uint32_t rminchn = 0, rmaxchn = 0;
nvlist_t *provider_nvl = NULL;
+ const nvlist_t *diinfo;
const char *provider;
- devnode = nvlist_get_string(nvlist, SNDSTAT_LABEL_DEVNODE);
- if (nvlist_exists_string(nvlist, SNDSTAT_LABEL_NAMEUNIT))
- nameunit = nvlist_get_string(nvlist, SNDSTAT_LABEL_NAMEUNIT);
+ devnode = nvlist_get_string(nvlist, SNDST_DSPS_DEVNODE);
+ if (nvlist_exists_string(nvlist, SNDST_DSPS_NAMEUNIT))
+ nameunit = nvlist_get_string(nvlist, SNDST_DSPS_NAMEUNIT);
else
nameunit = devnode;
- desc = nvlist_get_string(nvlist, SNDSTAT_LABEL_DESC);
- pchan = nvlist_get_number(nvlist, SNDSTAT_LABEL_PCHAN);
- rchan = nvlist_get_number(nvlist, SNDSTAT_LABEL_RCHAN);
+ desc = nvlist_get_string(nvlist, SNDST_DSPS_DESC);
+ pchan = nvlist_get_number(nvlist, SNDST_DSPS_PCHAN);
+ rchan = nvlist_get_number(nvlist, SNDST_DSPS_RCHAN);
if (pchan != 0) {
- pminrate = nvlist_get_number(nvlist, SNDSTAT_LABEL_PMINRATE);
- pmaxrate = nvlist_get_number(nvlist, SNDSTAT_LABEL_PMAXRATE);
- pfmts = nvlist_get_number(nvlist, SNDSTAT_LABEL_PFMTS);
+ if (nvlist_exists_nvlist(nvlist, SNDST_DSPS_INFO_PLAY)) {
+ diinfo = nvlist_get_nvlist(nvlist,
+ SNDST_DSPS_INFO_PLAY);
+ sndstat_get_diinfo_nv(diinfo, &pminrate, &pmaxrate,
+ &pfmts, &pminchn, &pmaxchn);
+ } else {
+ pminrate = nvlist_get_number(nvlist, "pminrate");
+ pmaxrate = nvlist_get_number(nvlist, "pmaxrate");
+ pfmts = nvlist_get_number(nvlist, "pfmts");
+ }
}
if (rchan != 0) {
- rminrate = nvlist_get_number(nvlist, SNDSTAT_LABEL_RMINRATE);
- rmaxrate = nvlist_get_number(nvlist, SNDSTAT_LABEL_RMAXRATE);
- rfmts = nvlist_get_number(nvlist, SNDSTAT_LABEL_RFMTS);
+ if (nvlist_exists_nvlist(nvlist, SNDST_DSPS_INFO_REC)) {
+ diinfo = nvlist_get_nvlist(nvlist,
+ SNDST_DSPS_INFO_REC);
+ sndstat_get_diinfo_nv(diinfo, &rminrate, &rmaxrate,
+ &rfmts, &rminchn, &rmaxchn);
+ } else {
+ rminrate = nvlist_get_number(nvlist, "rminrate");
+ rmaxrate = nvlist_get_number(nvlist, "rmaxrate");
+ rfmts = nvlist_get_number(nvlist, "rfmts");
+ }
}
- provider = dnvlist_get_string(nvlist, SNDSTAT_LABEL_PROVIDER, "");
+ provider = dnvlist_get_string(nvlist, SNDST_DSPS_PROVIDER, "");
if (provider[0] == '\0')
provider = NULL;
if (provider != NULL &&
- nvlist_exists_nvlist(nvlist, SNDSTAT_LABEL_PROVIDER_INFO)) {
+ nvlist_exists_nvlist(nvlist, SNDST_DSPS_PROVIDER_INFO)) {
provider_nvl = nvlist_clone(
- nvlist_get_nvlist(nvlist, SNDSTAT_LABEL_PROVIDER_INFO));
+ nvlist_get_nvlist(nvlist, SNDST_DSPS_PROVIDER_INFO));
if (provider_nvl == NULL)
return (ENOMEM);
}
@@ -727,12 +838,16 @@
ud->desc = strdup(desc, M_DEVBUF);
ud->pchan = pchan;
ud->rchan = rchan;
- ud->pminrate = pminrate;
- ud->pmaxrate = pmaxrate;
- ud->rminrate = rminrate;
- ud->rmaxrate = rmaxrate;
- ud->pfmts = pfmts;
- ud->rfmts = rfmts;
+ ud->info_play.min_rate = pminrate;
+ ud->info_play.max_rate = pmaxrate;
+ ud->info_play.formats = pfmts;
+ ud->info_play.min_chn = pminchn;
+ ud->info_play.max_chn = pmaxchn;
+ ud->info_rec.min_rate = rminrate;
+ ud->info_rec.max_rate = rmaxrate;
+ ud->info_rec.formats = rfmts;
+ ud->info_rec.min_chn = rminchn;
+ ud->info_rec.max_chn = rmaxchn;
ud->provider_nvl = provider_nvl;
return (0);
}
@@ -744,7 +859,7 @@
nvlist_t *nvl = NULL;
const nvlist_t * const *dsps;
size_t i, ndsps;
- struct sndstat_nvlbuf_arg *arg = (struct sndstat_nvlbuf_arg *)data;
+ struct sndstioc_nv_arg *arg = (struct sndstioc_nv_arg *)data;
if ((pf->fflags & FWRITE) == 0) {
err = EPERM;
@@ -755,11 +870,11 @@
if (err != 0)
goto done;
- if (!nvlist_exists_nvlist_array(nvl, SNDSTAT_LABEL_DSPS)) {
+ if (!nvlist_exists_nvlist_array(nvl, SNDST_DSPS)) {
err = EINVAL;
goto done;
}
- dsps = nvlist_get_nvlist_array(nvl, SNDSTAT_LABEL_DSPS, &ndsps);
+ dsps = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &ndsps);
for (i = 0; i < ndsps; i++) {
if (!sndstat_dsp_nvlist_is_sane(dsps[i])) {
err = EINVAL;
@@ -801,8 +916,8 @@
static int
compat_sndstat_get_devs32(struct sndstat_file *pf, caddr_t data)
{
- struct sndstat_nvlbuf_arg32 *arg32 = (struct sndstat_nvlbuf_arg32 *)data;
- struct sndstat_nvlbuf_arg arg;
+ struct sndstioc_nv_arg32 *arg32 = (struct sndstioc_nv_arg32 *)data;
+ struct sndstioc_nv_arg arg;
int err;
arg.buf = (void *)(uintptr_t)arg32->buf;
@@ -820,8 +935,8 @@
static int
compat_sndstat_add_user_devs32(struct sndstat_file *pf, caddr_t data)
{
- struct sndstat_nvlbuf_arg32 *arg32 = (struct sndstat_nvlbuf_arg32 *)data;
- struct sndstat_nvlbuf_arg arg;
+ struct sndstioc_nv_arg32 *arg32 = (struct sndstioc_nv_arg32 *)data;
+ struct sndstioc_nv_arg arg;
int err;
arg.buf = (void *)(uintptr_t)arg32->buf;
@@ -849,11 +964,11 @@
return (err);
switch (cmd) {
- case SNDSTAT_GET_DEVS:
+ case SNDSTIOC_GET_DEVS:
err = sndstat_get_devs(pf, data);
break;
#ifdef COMPAT_FREEBSD32
- case SNDSTAT_GET_DEVS32:
+ case SNDSTIOC_GET_DEVS32:
if (!SV_CURPROC_FLAG(SV_ILP32)) {
err = ENODEV;
break;
@@ -861,11 +976,11 @@
err = compat_sndstat_get_devs32(pf, data);
break;
#endif
- case SNDSTAT_ADD_USER_DEVS:
+ case SNDSTIOC_ADD_USER_DEVS:
err = sndstat_add_user_devs(pf, data);
break;
#ifdef COMPAT_FREEBSD32
- case SNDSTAT_ADD_USER_DEVS32:
+ case SNDSTIOC_ADD_USER_DEVS32:
if (!SV_CURPROC_FLAG(SV_ILP32)) {
err = ENODEV;
break;
@@ -873,10 +988,10 @@
err = compat_sndstat_add_user_devs32(pf, data);
break;
#endif
- case SNDSTAT_REFRESH_DEVS:
+ case SNDSTIOC_REFRESH_DEVS:
err = sndstat_refresh_devs(pf);
break;
- case SNDSTAT_FLUSH_USER_DEVS:
+ case SNDSTIOC_FLUSH_USER_DEVS:
err = sndstat_flush_user_devs(pf);
break;
default:
diff --git a/sys/sys/sndstat.h b/sys/sys/sndstat.h
--- a/sys/sys/sndstat.h
+++ b/sys/sys/sndstat.h
@@ -38,56 +38,65 @@
#include <sys/ioccom.h>
#endif /* !_IOWR */
-struct sndstat_nvlbuf_arg {
+struct sndstioc_nv_arg {
size_t nbytes; /* [IN/OUT] buffer size/number of bytes filled */
void *buf; /* [OUT] buffer holding a packed nvlist */
};
/*
- * Common labels
+ * Common name/value pair names
*/
-#define SNDSTAT_LABEL_DSPS "dsps"
-#define SNDSTAT_LABEL_FROM_USER "from_user"
-#define SNDSTAT_LABEL_PCHAN "pchan"
-#define SNDSTAT_LABEL_RCHAN "rchan"
-#define SNDSTAT_LABEL_PMINRATE "pminrate"
-#define SNDSTAT_LABEL_PMAXRATE "pmaxrate"
-#define SNDSTAT_LABEL_RMINRATE "rminrate"
-#define SNDSTAT_LABEL_RMAXRATE "rmaxrate"
-#define SNDSTAT_LABEL_PFMTS "pfmts"
-#define SNDSTAT_LABEL_RFMTS "rfmts"
-#define SNDSTAT_LABEL_NAMEUNIT "nameunit"
-#define SNDSTAT_LABEL_DEVNODE "devnode"
-#define SNDSTAT_LABEL_DESC "desc"
-#define SNDSTAT_LABEL_PROVIDER "provider"
-#define SNDSTAT_LABEL_PROVIDER_INFO "provider_info"
+#define SNDST_DSPS "dsps"
+#define SNDST_DSPS_FROM_USER "from_user"
+#define SNDST_DSPS_PCHAN "pchan"
+#define SNDST_DSPS_RCHAN "rchan"
+#define SNDST_DSPS_NAMEUNIT "nameunit"
+#define SNDST_DSPS_DEVNODE "devnode"
+#define SNDST_DSPS_DESC "desc"
+#define SNDST_DSPS_PROVIDER "provider"
+#define SNDST_DSPS_PROVIDER_INFO "provider_info"
/*
- * sound(4)-specific labels
+ * Common name/value pair names for play/rec info
*/
-#define SNDSTAT_LABEL_SOUND4_PROVIDER "sound(4)"
-#define SNDSTAT_LABEL_SOUND4_UNIT "unit"
-#define SNDSTAT_LABEL_SOUND4_BITPERFECT "bitperfect"
-#define SNDSTAT_LABEL_SOUND4_PVCHAN "pvchan"
-#define SNDSTAT_LABEL_SOUND4_RVCHAN "rvchan"
+#define SNDST_DSPS_INFO_PLAY "info_play"
+#define SNDST_DSPS_INFO_REC "info_rec"
+#define SNDST_DSPS_INFO_MIN_RATE "min_rate"
+#define SNDST_DSPS_INFO_MAX_RATE "max_rate"
+#define SNDST_DSPS_INFO_FORMATS "formats"
+#define SNDST_DSPS_INFO_MIN_CHN "min_chn"
+#define SNDST_DSPS_INFO_MAX_CHN "max_chn"
-#define SNDSTAT_REFRESH_DEVS _IO('D', 100)
-#define SNDSTAT_GET_DEVS _IOWR('D', 101, struct sndstat_nvlbuf_arg)
-#define SNDSTAT_ADD_USER_DEVS _IOWR('D', 102, struct sndstat_nvlbuf_arg)
-#define SNDSTAT_FLUSH_USER_DEVS _IO('D', 103)
+/*
+ * sound(4)-specific name/value pair names
+ */
+#define SNDST_DSPS_SOUND4_PROVIDER "sound(4)"
+#define SNDST_DSPS_SOUND4_UNIT "unit"
+#define SNDST_DSPS_SOUND4_BITPERFECT "bitperfect"
+#define SNDST_DSPS_SOUND4_PVCHAN "pvchan"
+#define SNDST_DSPS_SOUND4_RVCHAN "rvchan"
+
+#define SNDSTIOC_REFRESH_DEVS \
+ _IO('D', 100)
+#define SNDSTIOC_GET_DEVS \
+ _IOWR('D', 101, struct sndstioc_nv_arg)
+#define SNDSTIOC_ADD_USER_DEVS \
+ _IOWR('D', 102, struct sndstioc_nv_arg)
+#define SNDSTIOC_FLUSH_USER_DEVS \
+ _IO('D', 103)
#ifdef _KERNEL
#ifdef COMPAT_FREEBSD32
-struct sndstat_nvlbuf_arg32 {
+struct sndstioc_nv_arg32 {
uint32_t nbytes;
uint32_t buf;
};
-#define SNDSTAT_GET_DEVS32 \
- _IOC_NEWTYPE(SNDSTAT_GET_DEVS, struct sndstat_nvlbuf_arg32)
-#define SNDSTAT_ADD_USER_DEVS32 \
- _IOC_NEWTYPE(SNDSTAT_ADD_USER_DEVS, struct sndstat_nvlbuf_arg32)
+#define SNDSTIOC_GET_DEVS32 \
+ _IOC_NEWTYPE(SNDSTIOC_GET_DEVS, struct sndstioc_nv_arg32)
+#define SNDSTIOC_ADD_USER_DEVS32 \
+ _IOC_NEWTYPE(SNDSTIOC_ADD_USER_DEVS, struct sndstioc_nv_arg32)
#endif
#endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 15, 2:51 PM (2 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29720175
Default Alt Text
D29770.diff (27 KB)
Attached To
Mode
D29770: sndstat: nvlist schema and API definition changes
Attached
Detach File
Event Timeline
Log In to Comment