xref: /freebsd/share/man/man4/sndstat.4 (revision c96151d33509655efb7fb26768cb56a041c176f1)
1*c96151d3SKa Ho Ng.\"
2*c96151d3SKa Ho Ng.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*c96151d3SKa Ho Ng.\"
4*c96151d3SKa Ho Ng.\" This software was developed by Ka Ho Ng
5*c96151d3SKa Ho Ng.\" under sponsorship from the FreeBSD Foundation.
6*c96151d3SKa Ho Ng.\"
7*c96151d3SKa Ho Ng.\" Copyright (c) 2020 The FreeBSD Foundation
8*c96151d3SKa Ho Ng.\"
9*c96151d3SKa Ho Ng.\" Redistribution and use in source and binary forms, with or without
10*c96151d3SKa Ho Ng.\" modification, are permitted provided that the following conditions
11*c96151d3SKa Ho Ng.\" are met:
12*c96151d3SKa Ho Ng.\" 1. Redistributions of source code must retain the above copyright
13*c96151d3SKa Ho Ng.\"    notice, this list of conditions and the following disclaimer.
14*c96151d3SKa Ho Ng.\" 2. Redistributions in binary form must reproduce the above copyright
15*c96151d3SKa Ho Ng.\"    notice, this list of conditions and the following disclaimer in the
16*c96151d3SKa Ho Ng.\"    documentation and/or other materials provided with the distribution.
17*c96151d3SKa Ho Ng.\"
18*c96151d3SKa Ho Ng.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*c96151d3SKa Ho Ng.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*c96151d3SKa Ho Ng.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*c96151d3SKa Ho Ng.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*c96151d3SKa Ho Ng.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*c96151d3SKa Ho Ng.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*c96151d3SKa Ho Ng.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*c96151d3SKa Ho Ng.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*c96151d3SKa Ho Ng.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*c96151d3SKa Ho Ng.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*c96151d3SKa Ho Ng.\" SUCH DAMAGE.
29*c96151d3SKa Ho Ng.\"
30*c96151d3SKa Ho Ng.\" $FreeBSD$
31*c96151d3SKa Ho Ng.\"
32*c96151d3SKa Ho Ng.\" Note: The date here should be updated whenever a non-trivial
33*c96151d3SKa Ho Ng.\" change is made to the manual page.
34*c96151d3SKa Ho Ng.Dd December 7, 2020
35*c96151d3SKa Ho Ng.Dt SNDSTAT 4
36*c96151d3SKa Ho Ng.Os
37*c96151d3SKa Ho Ng.Sh NAME
38*c96151d3SKa Ho Ng.Nm sndstat
39*c96151d3SKa Ho Ng.Nd "nvlist-based PCM audio device enumeration interface"
40*c96151d3SKa Ho Ng.Sh SYNOPSIS
41*c96151d3SKa Ho NgTo compile the driver into the kernel,
42*c96151d3SKa Ho Ngplace the following lines in the
43*c96151d3SKa Ho Ngkernel configuration file:
44*c96151d3SKa Ho Ng.Bd -ragged -offset indent
45*c96151d3SKa Ho Ng.Cd "device sound"
46*c96151d3SKa Ho Ng.Ed
47*c96151d3SKa Ho Ng.Sh DESCRIPTION
48*c96151d3SKa Ho NgThe ioctl interface provided by
49*c96151d3SKa Ho Ng.Pa /dev/sndstat
50*c96151d3SKa Ho Ngdevice allows callers to enumeration PCM audio devices available for use.
51*c96151d3SKa Ho Ng.Sh IOCTLS
52*c96151d3SKa Ho NgFor all ioctls requiring data exchange between the subsystem and callers,
53*c96151d3SKa Ho Ngthe following structures are used to describe a serialized nvlist:
54*c96151d3SKa Ho Ng.Bd -literal -offset indent
55*c96151d3SKa Ho Ngstruct sndstat_nvlbuf_arg {
56*c96151d3SKa Ho Ng	size_t nbytes;
57*c96151d3SKa Ho Ng	void *buf;
58*c96151d3SKa Ho Ng};
59*c96151d3SKa Ho Ng.Ed
60*c96151d3SKa Ho Ng.Pp
61*c96151d3SKa Ho NgHere is an example of an nvlist, with explanations of the common fields:
62*c96151d3SKa Ho Ng.Bd -literal -offset indent
63*c96151d3SKa Ho Ngdsps (NVLIST ARRAY): 1
64*c96151d3SKa Ho Ng    from_user (BOOL): FALSE
65*c96151d3SKa Ho Ng    nameunit (STRING): [pcm0]
66*c96151d3SKa Ho Ng    devnode (STRING): [dsp0]
67*c96151d3SKa Ho Ng    desc (STRING): [Generic (0x8086) (Analog Line-out)]
68*c96151d3SKa Ho Ng    pchan (NUMBER): 1 (1) (0x1)
69*c96151d3SKa Ho Ng    rchan (NUMBER): 0 (0) (0x0)
70*c96151d3SKa Ho Ng    pminrate (NUMBER): 48000 (48000) (0xbb80)
71*c96151d3SKa Ho Ng    pmaxrate (NUMBER): 48000 (48000) (0xbb80)
72*c96151d3SKa Ho Ng    pfmts (NUMBER): 2097168 (2097168) (0x200010)
73*c96151d3SKa Ho Ng    provider_info (NVLIST):
74*c96151d3SKa Ho Ng        unit (NUMBER): 0 (0) (0x0)
75*c96151d3SKa Ho Ng        bitperfect (BOOL): FALSE
76*c96151d3SKa Ho Ng        pvchan (NUMBER): 1 (1) (0x1)
77*c96151d3SKa Ho Ng        rvchan (NUMBER): 0 (0) (0x0)
78*c96151d3SKa Ho Ng    provider (STRING): [sound(4)]
79*c96151d3SKa Ho Ng    ,
80*c96151d3SKa Ho Ng.Ed
81*c96151d3SKa Ho Ng.Bl -tag -width ".Dv provider_info"
82*c96151d3SKa Ho Ng.It Dv from_user
83*c96151d3SKa Ho NgWhether the PCM audio device node is created by in-kernel audio subsystem or
84*c96151d3SKa Ho Nguserspace providers.
85*c96151d3SKa Ho Ng.It Dv nameunit
86*c96151d3SKa Ho NgThe device identification in the form of subsystem plus a unit number.
87*c96151d3SKa Ho Ng.It Dv devnode
88*c96151d3SKa Ho NgThe PCM audio device node relative path in devfs.
89*c96151d3SKa Ho Ng.It Dv desc
90*c96151d3SKa Ho NgThe descripton of the PCM audio device.
91*c96151d3SKa Ho Ng.It Dv pchan
92*c96151d3SKa Ho NgThe number of playback channels supported by hardware.
93*c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support playback at all.
94*c96151d3SKa Ho Ng.It Dv rchan
95*c96151d3SKa Ho NgThe number of recording channels supported by hardware.
96*c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support recording at all.
97*c96151d3SKa Ho Ng.It Dv pminrate
98*c96151d3SKa Ho NgThe minimum supported playback direction sampling rate.
99*c96151d3SKa Ho NgOnly exists if pchan is greater than 0.
100*c96151d3SKa Ho Ng.It Dv pmaxrate
101*c96151d3SKa Ho NgThe maximum supported playback direction sampling rate.
102*c96151d3SKa Ho NgOnly exists if pchan is greater than 0.
103*c96151d3SKa Ho Ng.It Dv pfmts
104*c96151d3SKa Ho NgThe supported playback direction sample format.
105*c96151d3SKa Ho NgOnly exists if pchan is greater than 0.
106*c96151d3SKa Ho Ng.It Dv rminrate
107*c96151d3SKa Ho NgThe minimum supported recording direction sampling rate.
108*c96151d3SKa Ho NgOnly exists if rchan is greater than 0.
109*c96151d3SKa Ho Ng.It Dv rmaxrate
110*c96151d3SKa Ho NgThe maximum supported recording direction sampling rate.
111*c96151d3SKa Ho NgOnly exists if rchan is greater than 0.
112*c96151d3SKa Ho Ng.It Dv rfmts
113*c96151d3SKa Ho NgThe supported playback recording sample format.
114*c96151d3SKa Ho NgOnly exists if rchan is greater than 0.
115*c96151d3SKa Ho Ng.It Dv provider_info
116*c96151d3SKa Ho NgProvider-specific fields.
117*c96151d3SKa Ho NgThis field may not exist if the PCM audio device is not provided by in-kernel
118*c96151d3SKa Ho Nginterface.
119*c96151d3SKa Ho NgThis field will not exist if the provider field is an empty string.
120*c96151d3SKa Ho Ng.It Dv provider
121*c96151d3SKa Ho NgA string specifying the provider of the PCm audio device.
122*c96151d3SKa Ho Ng.El
123*c96151d3SKa Ho Ng.Pp
124*c96151d3SKa Ho NgThe following ioctls are providede for use:
125*c96151d3SKa Ho Ng.Bl -tag -width ".Dv SNDSTAT_FLUSH_USER_DEVS"
126*c96151d3SKa Ho Ng.It Dv SNDSTAT_REFRESH_DEVS
127*c96151d3SKa Ho NgDrop any previously fetched PCM audio devices list snapshots.
128*c96151d3SKa Ho NgThis ioctl takes no arguments.
129*c96151d3SKa Ho Ng.It Dv SNDSTAT_GET_DEVS
130*c96151d3SKa Ho NgGenerate and/or return PCM audio devices list snapshots to callers.
131*c96151d3SKa Ho NgThis ioctl takes a pointer to
132*c96151d3SKa Ho Ng.Fa struct sndstat_nvlbuf_arg
133*c96151d3SKa Ho Ngas the first and the only argument.
134*c96151d3SKa Ho NgCallers need to provide a sufficiently large buffer to hold a serialized
135*c96151d3SKa Ho Ngnvlist.
136*c96151d3SKa Ho NgIf there is no existing PCM audio device list snapshot available in the
137*c96151d3SKa Ho Nginternal structure of the opened sndstat.
138*c96151d3SKa Ho Ng.Fa fd ,
139*c96151d3SKa Ho Nga new PCM audio device list snapshot will be automatically generated.
140*c96151d3SKa Ho NgCallers have to set
141*c96151d3SKa Ho Ng.Fa nbytes
142*c96151d3SKa Ho Ngto either 0 or the size of buffer provided.
143*c96151d3SKa Ho NgIn case
144*c96151d3SKa Ho Ng.Fa nbytes
145*c96151d3SKa Ho Ngis 0, the buffer size required to hold a serialized nvlist
146*c96151d3SKa Ho Ngstream of current snapshot will be returned in
147*c96151d3SKa Ho Ng.Fa nbytes ,
148*c96151d3SKa Ho Ngand
149*c96151d3SKa Ho Ng.Fa buf
150*c96151d3SKa Ho Ngwill be ignored.
151*c96151d3SKa Ho NgOtherwise, if the buffer is not sufficiently large,
152*c96151d3SKa Ho Ngthe ioctl returns success, and
153*c96151d3SKa Ho Ng.Fa nbytes
154*c96151d3SKa Ho Ngwill be set to 0.
155*c96151d3SKa Ho NgIf the buffer provided is sufficiently large,
156*c96151d3SKa Ho Ng.Fa nbytes
157*c96151d3SKa Ho Ngwill be set to the size of the serialized nvlist written to the provided buffer.
158*c96151d3SKa Ho NgOnce a PCM audio device list snapshot is returned to user-space successfully,
159*c96151d3SKa Ho Ngthe snapshot stored in the subsystem's internal structure of the given
160*c96151d3SKa Ho Ng.Fa fd
161*c96151d3SKa Ho Ngwill be freed.
162*c96151d3SKa Ho Ng.It Dv SNDSTAT_ADD_USER_DEVS
163*c96151d3SKa Ho NgAdd a list of PCM audio devices provided by callers to
164*c96151d3SKa Ho Ng.Pa /dev/sndstat
165*c96151d3SKa Ho Ngdevice.
166*c96151d3SKa Ho NgThis ioctl takes a pointer to
167*c96151d3SKa Ho Ng.Fa struct sndstat_nvlbuf_arg
168*c96151d3SKa Ho Ngas the first and the only argument.
169*c96151d3SKa Ho NgCallers have to provide a buffer holding a serialized nvlist.
170*c96151d3SKa Ho Ng.Fa nbytes
171*c96151d3SKa Ho Ngshould be set to the length in bytes of the serialized nvlist.
172*c96151d3SKa Ho Ng.Fa buf
173*c96151d3SKa Ho Ngshould be pointed to a buffer storing the serialized nvlist.
174*c96151d3SKa Ho NgUserspace-backed PCM audio device nodes should be listed inside the serialized
175*c96151d3SKa Ho Ngnvlist.
176*c96151d3SKa Ho Ng.It Dv SNDSTAT_FLUSH_USER_DEVS
177*c96151d3SKa Ho NgFlush any PCM audio devices previously added by callers.
178*c96151d3SKa Ho NgThis ioctl takes no arguments.
179*c96151d3SKa Ho Ng.El
180*c96151d3SKa Ho Ng.Sh FILES
181*c96151d3SKa Ho Ng.Bl -tag -width ".Pa /dev/sndstat" -compact
182*c96151d3SKa Ho Ng.It Pa /dev/sndstat
183*c96151d3SKa Ho Ng.El
184*c96151d3SKa Ho Ng.Sh EXAMPLES
185*c96151d3SKa Ho NgThe following code enumerates all available PCM audio devices:
186*c96151d3SKa Ho Ng.Bd -literal -offset indent
187*c96151d3SKa Ho Ng#include <sys/types.h>
188*c96151d3SKa Ho Ng#include <err.h>
189*c96151d3SKa Ho Ng#include <fcntl.h>
190*c96151d3SKa Ho Ng#include <stdio.h>
191*c96151d3SKa Ho Ng#include <stdlib.h>
192*c96151d3SKa Ho Ng#include <sys/nv.h>
193*c96151d3SKa Ho Ng#include <sys/sndstat.h>
194*c96151d3SKa Ho Ng#include <sysexits.h>
195*c96151d3SKa Ho Ng#include <unistd.h>
196*c96151d3SKa Ho Ng
197*c96151d3SKa Ho Ngint
198*c96151d3SKa Ho Ngmain()
199*c96151d3SKa Ho Ng{
200*c96151d3SKa Ho Ng	int fd;
201*c96151d3SKa Ho Ng	struct sndstat_nvlbuf_arg arg;
202*c96151d3SKa Ho Ng	const nvlist_t * const *di;
203*c96151d3SKa Ho Ng	size_t i, nitems;
204*c96151d3SKa Ho Ng	nvlist_t *nvl;
205*c96151d3SKa Ho Ng
206*c96151d3SKa Ho Ng	/* Open sndstat node in read-only first */
207*c96151d3SKa Ho Ng	fd = open("/dev/sndstat", O_RDONLY);
208*c96151d3SKa Ho Ng
209*c96151d3SKa Ho Ng	if (ioctl(fd, SNDSTAT_REFRESH_DEVS, NULL))
210*c96151d3SKa Ho Ng		err(1, "ioctl(fd, SNDSTAT_REFRESH_DEVS, NULL)");
211*c96151d3SKa Ho Ng
212*c96151d3SKa Ho Ng	/* Get the size of snapshot, when nbytes = 0 */
213*c96151d3SKa Ho Ng	arg.nbytes = 0;
214*c96151d3SKa Ho Ng	arg.buf = NULL;
215*c96151d3SKa Ho Ng	if (ioctl(fd, SNDSTAT_GET_DEVS, &arg))
216*c96151d3SKa Ho Ng		err(1, "ioctl(fd, SNDSTAT_GET_DEVS, &arg)");
217*c96151d3SKa Ho Ng
218*c96151d3SKa Ho Ng	/* Get snapshot data */
219*c96151d3SKa Ho Ng	arg.buf = malloc(arg.nbytes);
220*c96151d3SKa Ho Ng	if (arg.buf == NULL)
221*c96151d3SKa Ho Ng		err(EX_OSERR, "malloc");
222*c96151d3SKa Ho Ng	if (ioctl(fd, SNDSTAT_GET_DEVS, &arg))
223*c96151d3SKa Ho Ng		err(1, "ioctl(fd, SNDSTAT_GET_DEVS, &arg)");
224*c96151d3SKa Ho Ng
225*c96151d3SKa Ho Ng	/* Deserialize the nvlist stream */
226*c96151d3SKa Ho Ng	nvl = nvlist_unpack(arg.buf, arg.nbytes, 0);
227*c96151d3SKa Ho Ng	free(arg.buf);
228*c96151d3SKa Ho Ng
229*c96151d3SKa Ho Ng	/* Get DSPs array */
230*c96151d3SKa Ho Ng	di = nvlist_get_nvlist_array(nvl, SNDSTAT_LABEL_DSPS, &nitems);
231*c96151d3SKa Ho Ng	for (i = 0; i < nitems; i++) {
232*c96151d3SKa Ho Ng		const char *nameunit, *devnode, *desc;
233*c96151d3SKa Ho Ng
234*c96151d3SKa Ho Ng		/*
235*c96151d3SKa Ho Ng		 * Examine each device nvlist item
236*c96151d3SKa Ho Ng		 */
237*c96151d3SKa Ho Ng
238*c96151d3SKa Ho Ng		nameunit = nvlist_get_string(di[i], SNDSTAT_LABEL_NAMEUNIT);
239*c96151d3SKa Ho Ng		devnode = nvlist_get_string(di[i], SNDSTAT_LABEL_DEVNODE);
240*c96151d3SKa Ho Ng		desc = nvlist_get_string(di[i], SNDSTAT_LABEL_DESC);
241*c96151d3SKa Ho Ng		printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n",
242*c96151d3SKa Ho Ng		    nameunit, devnode, desc);
243*c96151d3SKa Ho Ng	}
244*c96151d3SKa Ho Ng
245*c96151d3SKa Ho Ng	nvlist_destroy(nvl);
246*c96151d3SKa Ho Ng	return (0);
247*c96151d3SKa Ho Ng}
248*c96151d3SKa Ho Ng.Ed
249*c96151d3SKa Ho Ng.Sh SEE ALSO
250*c96151d3SKa Ho Ng.Xr sound 4 ,
251*c96151d3SKa Ho Ng.Xr nv 9
252*c96151d3SKa Ho Ng.Sh HISTORY
253*c96151d3SKa Ho NgThe nvlist-based ioctls support for
254*c96151d3SKa Ho Ng.Nm
255*c96151d3SKa Ho Ngdevice first appeared in
256*c96151d3SKa Ho Ng.Fx 13.0 .
257*c96151d3SKa Ho Ng.Sh AUTHORS
258*c96151d3SKa Ho NgThis manual page was written by
259*c96151d3SKa Ho Ng.An Ka Ho Ng Aq Mt khng@FreeBSD.org .
260