xref: /freebsd/sys/dev/sound/pcm/mixer.c (revision 66df505066f51e6d8411b966765d828817f88971)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
5  * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
6  * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #ifdef HAVE_KERNEL_OPTION_HEADERS
32 #include "opt_snd.h"
33 #endif
34 
35 #include <dev/sound/pcm/sound.h>
36 
37 #include "feeder_if.h"
38 #include "mixer_if.h"
39 
40 SND_DECLARE_FILE("$FreeBSD$");
41 
42 static MALLOC_DEFINE(M_MIXER, "mixer", "mixer");
43 
44 static int mixer_bypass = 1;
45 SYSCTL_INT(_hw_snd, OID_AUTO, vpc_mixer_bypass, CTLFLAG_RWTUN,
46     &mixer_bypass, 0,
47     "control channel pcm/rec volume, bypassing real mixer device");
48 
49 #define MIXER_NAMELEN	16
50 struct snd_mixer {
51 	KOBJ_FIELDS;
52 	void *devinfo;
53 	int busy;
54 	int hwvol_mixer;
55 	int hwvol_step;
56 	int type;
57 	device_t dev;
58 	u_int32_t devs;
59 	u_int32_t mutedevs;
60 	u_int32_t recdevs;
61 	u_int32_t recsrc;
62 	u_int16_t level[32];
63 	u_int16_t level_muted[32];
64 	u_int8_t parent[32];
65 	u_int32_t child[32];
66 	u_int8_t realdev[32];
67 	char name[MIXER_NAMELEN];
68 	struct mtx *lock;
69 	oss_mixer_enuminfo enuminfo;
70 	/**
71 	 * Counter is incremented when applications change any of this
72 	 * mixer's controls.  A change in value indicates that persistent
73 	 * mixer applications should update their displays.
74 	 */
75 	int modify_counter;
76 };
77 
78 static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
79 	[SOUND_MIXER_VOLUME]	= 75,
80 	[SOUND_MIXER_BASS]	= 50,
81 	[SOUND_MIXER_TREBLE]	= 50,
82 	[SOUND_MIXER_SYNTH]	= 75,
83 	[SOUND_MIXER_PCM]	= 75,
84 	[SOUND_MIXER_SPEAKER]	= 75,
85 	[SOUND_MIXER_LINE]	= 75,
86 	[SOUND_MIXER_MIC] 	= 25,
87 	[SOUND_MIXER_CD]	= 75,
88 	[SOUND_MIXER_IGAIN]	= 0,
89 	[SOUND_MIXER_LINE1]	= 75,
90 	[SOUND_MIXER_VIDEO]	= 75,
91 	[SOUND_MIXER_RECLEV]	= 75,
92 	[SOUND_MIXER_OGAIN]	= 50,
93 	[SOUND_MIXER_MONITOR]	= 75,
94 };
95 
96 static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
97 
98 static d_open_t mixer_open;
99 static d_close_t mixer_close;
100 static d_ioctl_t mixer_ioctl;
101 
102 static struct cdevsw mixer_cdevsw = {
103 	.d_version =	D_VERSION,
104 	.d_open =	mixer_open,
105 	.d_close =	mixer_close,
106 	.d_ioctl =	mixer_ioctl,
107 	.d_name =	"mixer",
108 };
109 
110 /**
111  * Keeps a count of mixer devices; used only by OSSv4 SNDCTL_SYSINFO ioctl.
112  */
113 int mixer_count = 0;
114 
115 static eventhandler_tag mixer_ehtag = NULL;
116 
117 static struct cdev *
118 mixer_get_devt(device_t dev)
119 {
120 	struct snddev_info *snddev;
121 
122 	snddev = device_get_softc(dev);
123 
124 	return snddev->mixer_dev;
125 }
126 
127 static int
128 mixer_lookup(char *devname)
129 {
130 	int i;
131 
132 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
133 		if (strncmp(devname, snd_mixernames[i],
134 		    strlen(snd_mixernames[i])) == 0)
135 			return i;
136 	return -1;
137 }
138 
139 #define MIXER_SET_UNLOCK(x, y)		do {				\
140 	if ((y) != 0)							\
141 		snd_mtxunlock((x)->lock);				\
142 } while (0)
143 
144 #define MIXER_SET_LOCK(x, y)		do {				\
145 	if ((y) != 0)							\
146 		snd_mtxlock((x)->lock);					\
147 } while (0)
148 
149 static int
150 mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
151     u_int left, u_int right)
152 {
153 	struct pcm_channel *c;
154 	int dropmtx, acquiremtx;
155 
156 	if (PCM_DETACHING(d) || !PCM_REGISTERED(d))
157 		return (EINVAL);
158 
159 	if (mtx_owned(m->lock))
160 		dropmtx = 1;
161 	else
162 		dropmtx = 0;
163 
164 	if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
165 		acquiremtx = 0;
166 	else
167 		acquiremtx = 1;
168 
169 	/*
170 	 * Be careful here. If we're coming from cdev ioctl, it is OK to
171 	 * not doing locking AT ALL (except on individual channel) since
172 	 * we've been heavily guarded by pcm cv, or if we're still
173 	 * under Giant influence. Since we also have mix_* calls, we cannot
174 	 * assume such protection and just do the lock as usuall.
175 	 */
176 	MIXER_SET_UNLOCK(m, dropmtx);
177 	MIXER_SET_LOCK(d, acquiremtx);
178 
179 	CHN_FOREACH(c, d, channels.pcm.busy) {
180 		CHN_LOCK(c);
181 		if (c->direction == PCMDIR_PLAY &&
182 		    (c->feederflags & (1 << FEEDER_VOLUME)))
183 			chn_setvolume_multi(c, SND_VOL_C_MASTER, left, right,
184 			    (left + right) >> 1);
185 		CHN_UNLOCK(c);
186 	}
187 
188 	MIXER_SET_UNLOCK(d, acquiremtx);
189 	MIXER_SET_LOCK(m, dropmtx);
190 
191 	return (0);
192 }
193 
194 static int
195 mixer_set_eq(struct snd_mixer *m, struct snddev_info *d,
196     u_int dev, u_int level)
197 {
198 	struct pcm_channel *c;
199 	struct pcm_feeder *f;
200 	int tone, dropmtx, acquiremtx;
201 
202 	if (dev == SOUND_MIXER_TREBLE)
203 		tone = FEEDEQ_TREBLE;
204 	else if (dev == SOUND_MIXER_BASS)
205 		tone = FEEDEQ_BASS;
206 	else
207 		return (EINVAL);
208 
209 	if (PCM_DETACHING(d) || !PCM_REGISTERED(d))
210 		return (EINVAL);
211 
212 	if (mtx_owned(m->lock))
213 		dropmtx = 1;
214 	else
215 		dropmtx = 0;
216 
217 	if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
218 		acquiremtx = 0;
219 	else
220 		acquiremtx = 1;
221 
222 	/*
223 	 * Be careful here. If we're coming from cdev ioctl, it is OK to
224 	 * not doing locking AT ALL (except on individual channel) since
225 	 * we've been heavily guarded by pcm cv, or if we're still
226 	 * under Giant influence. Since we also have mix_* calls, we cannot
227 	 * assume such protection and just do the lock as usuall.
228 	 */
229 	MIXER_SET_UNLOCK(m, dropmtx);
230 	MIXER_SET_LOCK(d, acquiremtx);
231 
232 	CHN_FOREACH(c, d, channels.pcm.busy) {
233 		CHN_LOCK(c);
234 		f = chn_findfeeder(c, FEEDER_EQ);
235 		if (f != NULL)
236 			(void)FEEDER_SET(f, tone, level);
237 		CHN_UNLOCK(c);
238 	}
239 
240 	MIXER_SET_UNLOCK(d, acquiremtx);
241 	MIXER_SET_LOCK(m, dropmtx);
242 
243 	return (0);
244 }
245 
246 static int
247 mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
248 {
249 	struct snddev_info *d;
250 	u_int l, r, tl, tr;
251 	u_int32_t parent = SOUND_MIXER_NONE, child = 0;
252 	u_int32_t realdev;
253 	int i, dropmtx;
254 
255 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
256 	    (0 == (m->devs & (1 << dev))))
257 		return (-1);
258 
259 	l = min((lev & 0x00ff), 100);
260 	r = min(((lev & 0xff00) >> 8), 100);
261 	realdev = m->realdev[dev];
262 
263 	d = device_get_softc(m->dev);
264 	if (d == NULL)
265 		return (-1);
266 
267 	/* It is safe to drop this mutex due to Giant. */
268 	if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0)
269 		dropmtx = 1;
270 	else
271 		dropmtx = 0;
272 
273 	/* Allow the volume to be "changed" while muted. */
274 	if (muted & (1 << dev)) {
275 		m->level_muted[dev] = l | (r << 8);
276 		return (0);
277 	}
278 	MIXER_SET_UNLOCK(m, dropmtx);
279 
280 	/* TODO: recursive handling */
281 	parent = m->parent[dev];
282 	if (parent >= SOUND_MIXER_NRDEVICES)
283 		parent = SOUND_MIXER_NONE;
284 	if (parent == SOUND_MIXER_NONE)
285 		child = m->child[dev];
286 
287 	if (parent != SOUND_MIXER_NONE) {
288 		tl = (l * (m->level[parent] & 0x00ff)) / 100;
289 		tr = (r * ((m->level[parent] & 0xff00) >> 8)) / 100;
290 		if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
291 			(void)mixer_set_softpcmvol(m, d, tl, tr);
292 		else if (realdev != SOUND_MIXER_NONE &&
293 		    MIXER_SET(m, realdev, tl, tr) < 0) {
294 			MIXER_SET_LOCK(m, dropmtx);
295 			return (-1);
296 		}
297 	} else if (child != 0) {
298 		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
299 			if (!(child & (1 << i)) || m->parent[i] != dev)
300 				continue;
301 			realdev = m->realdev[i];
302 			tl = (l * (m->level[i] & 0x00ff)) / 100;
303 			tr = (r * ((m->level[i] & 0xff00) >> 8)) / 100;
304 			if (i == SOUND_MIXER_PCM &&
305 			    (d->flags & SD_F_SOFTPCMVOL))
306 				(void)mixer_set_softpcmvol(m, d, tl, tr);
307 			else if (realdev != SOUND_MIXER_NONE)
308 				MIXER_SET(m, realdev, tl, tr);
309 		}
310 		realdev = m->realdev[dev];
311 		if (realdev != SOUND_MIXER_NONE &&
312 		    MIXER_SET(m, realdev, l, r) < 0) {
313 			MIXER_SET_LOCK(m, dropmtx);
314 			return (-1);
315 		}
316 	} else {
317 		if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
318 			(void)mixer_set_softpcmvol(m, d, l, r);
319 		else if ((dev == SOUND_MIXER_TREBLE ||
320 		    dev == SOUND_MIXER_BASS) && (d->flags & SD_F_EQ))
321 			(void)mixer_set_eq(m, d, dev, (l + r) >> 1);
322 		else if (realdev != SOUND_MIXER_NONE &&
323 		    MIXER_SET(m, realdev, l, r) < 0) {
324 			MIXER_SET_LOCK(m, dropmtx);
325 			return (-1);
326 		}
327 	}
328 
329 	MIXER_SET_LOCK(m, dropmtx);
330 
331 	m->level[dev] = l | (r << 8);
332 	m->modify_counter++;
333 
334 	return (0);
335 }
336 
337 static int
338 mixer_get(struct snd_mixer *mixer, int dev)
339 {
340 	if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) {
341 		if (mixer->mutedevs & (1 << dev))
342 			return (mixer->level_muted[dev]);
343 		else
344 			return (mixer->level[dev]);
345 	} else {
346 		return (-1);
347 	}
348 }
349 
350 void
351 mix_setmutedevs(struct snd_mixer *mixer, u_int32_t mutedevs)
352 {
353 	u_int32_t delta;
354 
355 	/* Filter out invalid values. */
356 	mutedevs &= mixer->devs;
357 	delta = (mixer->mutedevs ^ mutedevs) & mixer->devs;
358 	mixer->mutedevs = mutedevs;
359 
360 	for (int i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
361 		if (!(delta & (1 << i)))
362 			continue;
363 		if (mutedevs & (1 << i)) {
364 			mixer->level_muted[i] = mixer->level[i];
365 			mixer_set(mixer, i, 0, 0);
366 		} else {
367 			mixer_set(mixer, i, 0, mixer->level_muted[i]);
368 		}
369 	}
370 }
371 
372 static int
373 mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
374 {
375 	struct snddev_info *d;
376 	u_int32_t recsrc;
377 	int dropmtx;
378 
379 	d = device_get_softc(mixer->dev);
380 	if (d == NULL)
381 		return -1;
382 	if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0)
383 		dropmtx = 1;
384 	else
385 		dropmtx = 0;
386 	src &= mixer->recdevs;
387 	if (src == 0)
388 		src = mixer->recdevs & SOUND_MASK_MIC;
389 	if (src == 0)
390 		src = mixer->recdevs & SOUND_MASK_MONITOR;
391 	if (src == 0)
392 		src = mixer->recdevs & SOUND_MASK_LINE;
393 	if (src == 0 && mixer->recdevs != 0)
394 		src = (1 << (ffs(mixer->recdevs) - 1));
395 	/* It is safe to drop this mutex due to Giant. */
396 	MIXER_SET_UNLOCK(mixer, dropmtx);
397 	recsrc = MIXER_SETRECSRC(mixer, src);
398 	MIXER_SET_LOCK(mixer, dropmtx);
399 
400 	mixer->recsrc = recsrc;
401 
402 	return 0;
403 }
404 
405 static int
406 mixer_getrecsrc(struct snd_mixer *mixer)
407 {
408 	return mixer->recsrc;
409 }
410 
411 /**
412  * @brief Retrieve the route number of the current recording device
413  *
414  * OSSv4 assigns routing numbers to recording devices, unlike the previous
415  * API which relied on a fixed table of device numbers and names.  This
416  * function returns the routing number of the device currently selected
417  * for recording.
418  *
419  * For now, this function is kind of a goofy compatibility stub atop the
420  * existing sound system.  (For example, in theory, the old sound system
421  * allows multiple recording devices to be specified via a bitmask.)
422  *
423  * @param m	mixer context container thing
424  *
425  * @retval 0		success
426  * @retval EIDRM	no recording device found (generally not possible)
427  * @todo Ask about error code
428  */
429 static int
430 mixer_get_recroute(struct snd_mixer *m, int *route)
431 {
432 	int i, cnt;
433 
434 	cnt = 0;
435 
436 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
437 		/** @todo can user set a multi-device mask? (== or &?) */
438 		if ((1 << i) == m->recsrc)
439 			break;
440 		if ((1 << i) & m->recdevs)
441 			++cnt;
442 	}
443 
444 	if (i == SOUND_MIXER_NRDEVICES)
445 		return EIDRM;
446 
447 	*route = cnt;
448 	return 0;
449 }
450 
451 /**
452  * @brief Select a device for recording
453  *
454  * This function sets a recording source based on a recording device's
455  * routing number.  Said number is translated to an old school recdev
456  * mask and passed over mixer_setrecsrc.
457  *
458  * @param m	mixer context container thing
459  *
460  * @retval 0		success(?)
461  * @retval EINVAL	User specified an invalid device number
462  * @retval otherwise	error from mixer_setrecsrc
463  */
464 static int
465 mixer_set_recroute(struct snd_mixer *m, int route)
466 {
467 	int i, cnt, ret;
468 
469 	ret = 0;
470 	cnt = 0;
471 
472 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
473 		if ((1 << i) & m->recdevs) {
474 			if (route == cnt)
475 				break;
476 			++cnt;
477 		}
478 	}
479 
480 	if (i == SOUND_MIXER_NRDEVICES)
481 		ret = EINVAL;
482 	else
483 		ret = mixer_setrecsrc(m, (1 << i));
484 
485 	return ret;
486 }
487 
488 void
489 mix_setdevs(struct snd_mixer *m, u_int32_t v)
490 {
491 	struct snddev_info *d;
492 	int i;
493 
494 	if (m == NULL)
495 		return;
496 
497 	d = device_get_softc(m->dev);
498 	if (d != NULL && (d->flags & SD_F_SOFTPCMVOL))
499 		v |= SOUND_MASK_PCM;
500 	if (d != NULL && (d->flags & SD_F_EQ))
501 		v |= SOUND_MASK_TREBLE | SOUND_MASK_BASS;
502 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
503 		if (m->parent[i] < SOUND_MIXER_NRDEVICES)
504 			v |= 1 << m->parent[i];
505 		v |= m->child[i];
506 	}
507 	m->devs = v;
508 }
509 
510 /**
511  * @brief Record mask of available recording devices
512  *
513  * Calling functions are responsible for defining the mask of available
514  * recording devices.  This function records that value in a structure
515  * used by the rest of the mixer code.
516  *
517  * This function also populates a structure used by the SNDCTL_DSP_*RECSRC*
518  * family of ioctls that are part of OSSV4.  All recording device labels
519  * are concatenated in ascending order corresponding to their routing
520  * numbers.  (Ex:  a system might have 0 => 'vol', 1 => 'cd', 2 => 'line',
521  * etc.)  For now, these labels are just the standard recording device
522  * names (cd, line1, etc.), but will eventually be fully dynamic and user
523  * controlled.
524  *
525  * @param m	mixer device context container thing
526  * @param v	mask of recording devices
527  */
528 void
529 mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
530 {
531 	oss_mixer_enuminfo *ei;
532 	char *loc;
533 	int i, nvalues, nwrote, nleft, ncopied;
534 
535 	ei = &m->enuminfo;
536 
537 	nvalues = 0;
538 	nwrote = 0;
539 	nleft = sizeof(ei->strings);
540 	loc = ei->strings;
541 
542 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
543 		if ((1 << i) & v) {
544 			ei->strindex[nvalues] = nwrote;
545 			ncopied = strlcpy(loc, snd_mixernames[i], nleft) + 1;
546 			    /* strlcpy retval doesn't include terminator */
547 
548 			nwrote += ncopied;
549 			nleft -= ncopied;
550 			nvalues++;
551 
552 			/*
553 			 * XXX I don't think this should ever be possible.
554 			 * Even with a move to dynamic device/channel names,
555 			 * each label is limited to ~16 characters, so that'd
556 			 * take a LOT to fill this buffer.
557 			 */
558 			if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) {
559 				device_printf(m->dev,
560 				    "mix_setrecdevs:  Not enough room to store device names--please file a bug report.\n");
561 				device_printf(m->dev,
562 				    "mix_setrecdevs:  Please include details about your sound hardware, OS version, etc.\n");
563 				break;
564 			}
565 
566 			loc = &ei->strings[nwrote];
567 		}
568 	}
569 
570 	/*
571 	 * NB:	The SNDCTL_DSP_GET_RECSRC_NAMES ioctl ignores the dev
572 	 * 	and ctrl fields.
573 	 */
574 	ei->nvalues = nvalues;
575 	m->recdevs = v;
576 }
577 
578 void
579 mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs)
580 {
581 	u_int32_t mask = 0;
582 	int i;
583 
584 	if (m == NULL || parent >= SOUND_MIXER_NRDEVICES)
585 		return;
586 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
587 		if (i == parent)
588 			continue;
589 		if (childs & (1 << i)) {
590 			mask |= 1 << i;
591 			if (m->parent[i] < SOUND_MIXER_NRDEVICES)
592 				m->child[m->parent[i]] &= ~(1 << i);
593 			m->parent[i] = parent;
594 			m->child[i] = 0;
595 		}
596 	}
597 	mask &= ~(1 << parent);
598 	m->child[parent] = mask;
599 }
600 
601 void
602 mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev)
603 {
604 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
605 	    !(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES))
606 		return;
607 	m->realdev[dev] = realdev;
608 }
609 
610 u_int32_t
611 mix_getparent(struct snd_mixer *m, u_int32_t dev)
612 {
613 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
614 		return SOUND_MIXER_NONE;
615 	return m->parent[dev];
616 }
617 
618 u_int32_t
619 mix_getchild(struct snd_mixer *m, u_int32_t dev)
620 {
621 	if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
622 		return 0;
623 	return m->child[dev];
624 }
625 
626 u_int32_t
627 mix_getdevs(struct snd_mixer *m)
628 {
629 	return m->devs;
630 }
631 
632 u_int32_t
633 mix_getmutedevs(struct snd_mixer *m)
634 {
635 	return m->mutedevs;
636 }
637 
638 u_int32_t
639 mix_getrecdevs(struct snd_mixer *m)
640 {
641 	return m->recdevs;
642 }
643 
644 void *
645 mix_getdevinfo(struct snd_mixer *m)
646 {
647 	return m->devinfo;
648 }
649 
650 static struct snd_mixer *
651 mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo,
652     int type, const char *desc)
653 {
654 	struct snd_mixer *m;
655 	int i;
656 
657 	KASSERT(dev != NULL && cls != NULL && devinfo != NULL,
658 	    ("%s(): NULL data dev=%p cls=%p devinfo=%p",
659 	    __func__, dev, cls, devinfo));
660 	KASSERT(type == MIXER_TYPE_PRIMARY || type == MIXER_TYPE_SECONDARY,
661 	    ("invalid mixer type=%d", type));
662 
663 	m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
664 	snprintf(m->name, sizeof(m->name), "%s:mixer",
665 	    device_get_nameunit(dev));
666 	if (desc != NULL) {
667 		strlcat(m->name, ":", sizeof(m->name));
668 		strlcat(m->name, desc, sizeof(m->name));
669 	}
670 	m->lock = snd_mtxcreate(m->name, (type == MIXER_TYPE_PRIMARY) ?
671 	    "primary pcm mixer" : "secondary pcm mixer");
672 	m->type = type;
673 	m->devinfo = devinfo;
674 	m->busy = 0;
675 	m->dev = dev;
676 	for (i = 0; i < (sizeof(m->parent) / sizeof(m->parent[0])); i++) {
677 		m->parent[i] = SOUND_MIXER_NONE;
678 		m->child[i] = 0;
679 		m->realdev[i] = i;
680 	}
681 
682 	if (MIXER_INIT(m)) {
683 		snd_mtxlock(m->lock);
684 		snd_mtxfree(m->lock);
685 		kobj_delete((kobj_t)m, M_MIXER);
686 		return (NULL);
687 	}
688 
689 	return (m);
690 }
691 
692 int
693 mixer_delete(struct snd_mixer *m)
694 {
695 	KASSERT(m != NULL, ("NULL snd_mixer"));
696 	KASSERT(m->type == MIXER_TYPE_SECONDARY,
697 	    ("%s(): illegal mixer type=%d", __func__, m->type));
698 
699 	/* mixer uninit can sleep --hps */
700 
701 	MIXER_UNINIT(m);
702 
703 	snd_mtxfree(m->lock);
704 	kobj_delete((kobj_t)m, M_MIXER);
705 
706 	--mixer_count;
707 
708 	return (0);
709 }
710 
711 struct snd_mixer *
712 mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
713 {
714 	struct snd_mixer *m;
715 
716 	m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc);
717 
718 	if (m != NULL)
719 		++mixer_count;
720 
721 	return (m);
722 }
723 
724 int
725 mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
726 {
727 	struct snddev_info *snddev;
728 	struct snd_mixer *m;
729 	u_int16_t v;
730 	struct cdev *pdev;
731 	int i, unit, devunit, val;
732 
733 	snddev = device_get_softc(dev);
734 	if (snddev == NULL)
735 		return (-1);
736 
737 	if (resource_int_value(device_get_name(dev),
738 	    device_get_unit(dev), "eq", &val) == 0 && val != 0) {
739 		snddev->flags |= SD_F_EQ;
740 		if ((val & SD_F_EQ_MASK) == val)
741 			snddev->flags |= val;
742 		else
743 			snddev->flags |= SD_F_EQ_DEFAULT;
744 		snddev->eqpreamp = 0;
745 	}
746 
747 	m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_PRIMARY, NULL);
748 	if (m == NULL)
749 		return (-1);
750 
751 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
752 		v = snd_mixerdefaults[i];
753 
754 		if (resource_int_value(device_get_name(dev),
755 		    device_get_unit(dev), snd_mixernames[i], &val) == 0) {
756 			if (val >= 0 && val <= 100) {
757 				v = (u_int16_t) val;
758 			}
759 		}
760 
761 		mixer_set(m, i, 0, v | (v << 8));
762 	}
763 
764 	mixer_setrecsrc(m, 0); /* Set default input. */
765 
766 	unit = device_get_unit(dev);
767 	devunit = snd_mkunit(unit, SND_DEV_CTL, 0);
768 	pdev = make_dev(&mixer_cdevsw, PCMMINOR(devunit),
769 		 UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit);
770 	pdev->si_drv1 = m;
771 	snddev->mixer_dev = pdev;
772 
773 	++mixer_count;
774 
775 	if (bootverbose) {
776 		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
777 			if (!(m->devs & (1 << i)))
778 				continue;
779 			if (m->realdev[i] != i) {
780 				device_printf(dev, "Mixer \"%s\" -> \"%s\":",
781 				    snd_mixernames[i],
782 				    (m->realdev[i] < SOUND_MIXER_NRDEVICES) ?
783 				    snd_mixernames[m->realdev[i]] : "none");
784 			} else {
785 				device_printf(dev, "Mixer \"%s\":",
786 				    snd_mixernames[i]);
787 			}
788 			if (m->parent[i] < SOUND_MIXER_NRDEVICES)
789 				printf(" parent=\"%s\"",
790 				    snd_mixernames[m->parent[i]]);
791 			if (m->child[i] != 0)
792 				printf(" child=0x%08x", m->child[i]);
793 			printf("\n");
794 		}
795 		if (snddev->flags & SD_F_SOFTPCMVOL)
796 			device_printf(dev, "Soft PCM mixer ENABLED\n");
797 		if (snddev->flags & SD_F_EQ)
798 			device_printf(dev, "EQ Treble/Bass ENABLED\n");
799 	}
800 
801 	return (0);
802 }
803 
804 int
805 mixer_uninit(device_t dev)
806 {
807 	int i;
808 	struct snddev_info *d;
809 	struct snd_mixer *m;
810 	struct cdev *pdev;
811 
812 	d = device_get_softc(dev);
813 	pdev = mixer_get_devt(dev);
814 	if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL)
815 		return EBADF;
816 
817 	m = pdev->si_drv1;
818 	KASSERT(m != NULL, ("NULL snd_mixer"));
819 	KASSERT(m->type == MIXER_TYPE_PRIMARY,
820 	    ("%s(): illegal mixer type=%d", __func__, m->type));
821 
822 	snd_mtxlock(m->lock);
823 
824 	if (m->busy) {
825 		snd_mtxunlock(m->lock);
826 		return EBUSY;
827 	}
828 
829 	/* destroy dev can sleep --hps */
830 
831 	snd_mtxunlock(m->lock);
832 
833 	pdev->si_drv1 = NULL;
834 	destroy_dev(pdev);
835 
836 	snd_mtxlock(m->lock);
837 
838 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
839 		mixer_set(m, i, 0, 0);
840 
841 	mixer_setrecsrc(m, SOUND_MASK_MIC);
842 
843 	snd_mtxunlock(m->lock);
844 
845 	/* mixer uninit can sleep --hps */
846 
847 	MIXER_UNINIT(m);
848 
849 	snd_mtxfree(m->lock);
850 	kobj_delete((kobj_t)m, M_MIXER);
851 
852 	d->mixer_dev = NULL;
853 
854 	--mixer_count;
855 
856 	return 0;
857 }
858 
859 int
860 mixer_reinit(device_t dev)
861 {
862 	struct snd_mixer *m;
863 	struct cdev *pdev;
864 	int i;
865 
866 	pdev = mixer_get_devt(dev);
867 	m = pdev->si_drv1;
868 	snd_mtxlock(m->lock);
869 
870 	i = MIXER_REINIT(m);
871 	if (i) {
872 		snd_mtxunlock(m->lock);
873 		return i;
874 	}
875 
876 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
877 		if (m->mutedevs & (1 << i))
878 			mixer_set(m, i, 0, 0);
879 		else
880 			mixer_set(m, i, 0, m->level[i]);
881 	}
882 
883 	mixer_setrecsrc(m, m->recsrc);
884 	snd_mtxunlock(m->lock);
885 
886 	return 0;
887 }
888 
889 static int
890 sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS)
891 {
892 	char devname[32];
893 	int error, dev;
894 	struct snd_mixer *m;
895 
896 	m = oidp->oid_arg1;
897 	snd_mtxlock(m->lock);
898 	strlcpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname));
899 	snd_mtxunlock(m->lock);
900 	error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req);
901 	snd_mtxlock(m->lock);
902 	if (error == 0 && req->newptr != NULL) {
903 		dev = mixer_lookup(devname);
904 		if (dev == -1) {
905 			snd_mtxunlock(m->lock);
906 			return EINVAL;
907 		} else {
908 			m->hwvol_mixer = dev;
909 		}
910 	}
911 	snd_mtxunlock(m->lock);
912 	return error;
913 }
914 
915 int
916 mixer_hwvol_init(device_t dev)
917 {
918 	struct snd_mixer *m;
919 	struct cdev *pdev;
920 
921 	pdev = mixer_get_devt(dev);
922 	m = pdev->si_drv1;
923 
924 	m->hwvol_mixer = SOUND_MIXER_VOLUME;
925 	m->hwvol_step = 5;
926 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
927 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
928             OID_AUTO, "hwvol_step", CTLFLAG_RWTUN, &m->hwvol_step, 0, "");
929 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
930 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
931 	    "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
932 	    m, 0, sysctl_hw_snd_hwvol_mixer, "A", "");
933 	return 0;
934 }
935 
936 void
937 mixer_hwvol_mute_locked(struct snd_mixer *m)
938 {
939 	mix_setmutedevs(m, m->mutedevs ^ (1 << m->hwvol_mixer));
940 }
941 
942 void
943 mixer_hwvol_mute(device_t dev)
944 {
945 	struct snd_mixer *m;
946 	struct cdev *pdev;
947 
948 	pdev = mixer_get_devt(dev);
949 	m = pdev->si_drv1;
950 	snd_mtxlock(m->lock);
951 	mixer_hwvol_mute_locked(m);
952 	snd_mtxunlock(m->lock);
953 }
954 
955 void
956 mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step)
957 {
958 	int level, left, right;
959 
960 	level = mixer_get(m, m->hwvol_mixer);
961 
962 	if (level != -1) {
963 		left = level & 0xff;
964 		right = (level >> 8) & 0xff;
965 		left += left_step * m->hwvol_step;
966 		if (left < 0)
967 			left = 0;
968 		else if (left > 100)
969 			left = 100;
970 		right += right_step * m->hwvol_step;
971 		if (right < 0)
972 			right = 0;
973 		else if (right > 100)
974 			right = 100;
975 
976 		mixer_set(m, m->hwvol_mixer, m->mutedevs, left | right << 8);
977 	}
978 }
979 
980 void
981 mixer_hwvol_step(device_t dev, int left_step, int right_step)
982 {
983 	struct snd_mixer *m;
984 	struct cdev *pdev;
985 
986 	pdev = mixer_get_devt(dev);
987 	m = pdev->si_drv1;
988 	snd_mtxlock(m->lock);
989 	mixer_hwvol_step_locked(m, left_step, right_step);
990 	snd_mtxunlock(m->lock);
991 }
992 
993 int
994 mixer_busy(struct snd_mixer *m)
995 {
996 	KASSERT(m != NULL, ("NULL snd_mixer"));
997 
998 	return (m->busy);
999 }
1000 
1001 int
1002 mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right)
1003 {
1004 	int ret;
1005 
1006 	KASSERT(m != NULL, ("NULL snd_mixer"));
1007 
1008 	snd_mtxlock(m->lock);
1009 	ret = mixer_set(m, dev, m->mutedevs, left | (right << 8));
1010 	snd_mtxunlock(m->lock);
1011 
1012 	return ((ret != 0) ? ENXIO : 0);
1013 }
1014 
1015 int
1016 mix_get(struct snd_mixer *m, u_int dev)
1017 {
1018 	int ret;
1019 
1020 	KASSERT(m != NULL, ("NULL snd_mixer"));
1021 
1022 	snd_mtxlock(m->lock);
1023 	ret = mixer_get(m, dev);
1024 	snd_mtxunlock(m->lock);
1025 
1026 	return (ret);
1027 }
1028 
1029 int
1030 mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1031 {
1032 	int ret;
1033 
1034 	KASSERT(m != NULL, ("NULL snd_mixer"));
1035 
1036 	snd_mtxlock(m->lock);
1037 	ret = mixer_setrecsrc(m, src);
1038 	snd_mtxunlock(m->lock);
1039 
1040 	return ((ret != 0) ? ENXIO : 0);
1041 }
1042 
1043 u_int32_t
1044 mix_getrecsrc(struct snd_mixer *m)
1045 {
1046 	u_int32_t ret;
1047 
1048 	KASSERT(m != NULL, ("NULL snd_mixer"));
1049 
1050 	snd_mtxlock(m->lock);
1051 	ret = mixer_getrecsrc(m);
1052 	snd_mtxunlock(m->lock);
1053 
1054 	return (ret);
1055 }
1056 
1057 int
1058 mix_get_type(struct snd_mixer *m)
1059 {
1060 	KASSERT(m != NULL, ("NULL snd_mixer"));
1061 
1062 	return (m->type);
1063 }
1064 
1065 device_t
1066 mix_get_dev(struct snd_mixer *m)
1067 {
1068 	KASSERT(m != NULL, ("NULL snd_mixer"));
1069 
1070 	return (m->dev);
1071 }
1072 
1073 /* ----------------------------------------------------------------------- */
1074 
1075 static int
1076 mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
1077 {
1078 	struct snddev_info *d;
1079 	struct snd_mixer *m;
1080 
1081 	if (i_dev == NULL || i_dev->si_drv1 == NULL)
1082 		return (EBADF);
1083 
1084 	m = i_dev->si_drv1;
1085 	d = device_get_softc(m->dev);
1086 	if (PCM_DETACHING(d) || !PCM_REGISTERED(d))
1087 		return (EBADF);
1088 
1089 	/* XXX Need Giant magic entry ??? */
1090 
1091 	snd_mtxlock(m->lock);
1092 	m->busy = 1;
1093 	snd_mtxunlock(m->lock);
1094 
1095 	return (0);
1096 }
1097 
1098 static int
1099 mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
1100 {
1101 	struct snddev_info *d;
1102 	struct snd_mixer *m;
1103 	int ret;
1104 
1105 	if (i_dev == NULL || i_dev->si_drv1 == NULL)
1106 		return (EBADF);
1107 
1108 	m = i_dev->si_drv1;
1109 	d = device_get_softc(m->dev);
1110 	if (!PCM_REGISTERED(d))
1111 		return (EBADF);
1112 
1113 	/* XXX Need Giant magic entry ??? */
1114 
1115 	snd_mtxlock(m->lock);
1116 	ret = (m->busy == 0) ? EBADF : 0;
1117 	m->busy = 0;
1118 	snd_mtxunlock(m->lock);
1119 
1120 	return (ret);
1121 }
1122 
1123 static int
1124 mixer_ioctl_channel(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
1125     struct thread *td, int from)
1126 {
1127 	struct snddev_info *d;
1128 	struct snd_mixer *m;
1129 	struct pcm_channel *c, *rdch, *wrch;
1130 	pid_t pid;
1131 	int j, ret;
1132 
1133 	if (td == NULL || td->td_proc == NULL)
1134 		return (-1);
1135 
1136 	m = dev->si_drv1;
1137 	d = device_get_softc(m->dev);
1138 	j = cmd & 0xff;
1139 
1140 	switch (j) {
1141 	case SOUND_MIXER_PCM:
1142 	case SOUND_MIXER_RECLEV:
1143 	case SOUND_MIXER_DEVMASK:
1144 	case SOUND_MIXER_CAPS:
1145 	case SOUND_MIXER_STEREODEVS:
1146 		break;
1147 	default:
1148 		return (-1);
1149 		break;
1150 	}
1151 
1152 	pid = td->td_proc->p_pid;
1153 	rdch = NULL;
1154 	wrch = NULL;
1155 	c = NULL;
1156 	ret = -1;
1157 
1158 	/*
1159 	 * This is unfair. Imagine single proc opening multiple
1160 	 * instances of same direction. What we do right now
1161 	 * is looking for the first matching proc/pid, and just
1162 	 * that. Nothing more. Consider it done.
1163 	 *
1164 	 * The better approach of controlling specific channel
1165 	 * pcm or rec volume is by doing mixer ioctl
1166 	 * (SNDCTL_DSP_[SET|GET][PLAY|REC]VOL / SOUND_MIXER_[PCM|RECLEV]
1167 	 * on its open fd, rather than cracky mixer bypassing here.
1168 	 */
1169 	CHN_FOREACH(c, d, channels.pcm.opened) {
1170 		CHN_LOCK(c);
1171 		if (c->pid != pid ||
1172 		    !(c->feederflags & (1 << FEEDER_VOLUME))) {
1173 			CHN_UNLOCK(c);
1174 			continue;
1175 		}
1176 		if (rdch == NULL && c->direction == PCMDIR_REC) {
1177 			rdch = c;
1178 			if (j == SOUND_MIXER_RECLEV)
1179 				goto mixer_ioctl_channel_proc;
1180 		} else if (wrch == NULL && c->direction == PCMDIR_PLAY) {
1181 			wrch = c;
1182 			if (j == SOUND_MIXER_PCM)
1183 				goto mixer_ioctl_channel_proc;
1184 		}
1185 		CHN_UNLOCK(c);
1186 		if (rdch != NULL && wrch != NULL)
1187 			break;
1188 	}
1189 
1190 	if (rdch == NULL && wrch == NULL)
1191 		return (-1);
1192 
1193 	if ((j == SOUND_MIXER_DEVMASK || j == SOUND_MIXER_CAPS ||
1194 	    j == SOUND_MIXER_STEREODEVS) &&
1195 	    (cmd & ~0xff) == MIXER_READ(0)) {
1196 		snd_mtxlock(m->lock);
1197 		*(int *)arg = mix_getdevs(m);
1198 		snd_mtxunlock(m->lock);
1199 		if (rdch != NULL)
1200 			*(int *)arg |= SOUND_MASK_RECLEV;
1201 		if (wrch != NULL)
1202 			*(int *)arg |= SOUND_MASK_PCM;
1203 		ret = 0;
1204 	}
1205 
1206 	return (ret);
1207 
1208 mixer_ioctl_channel_proc:
1209 
1210 	KASSERT(c != NULL, ("%s(): NULL channel", __func__));
1211 	CHN_LOCKASSERT(c);
1212 
1213 	if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1214 		int left, right, center;
1215 
1216 		left = *(int *)arg & 0x7f;
1217 		right = (*(int *)arg >> 8) & 0x7f;
1218 		center = (left + right) >> 1;
1219 		chn_setvolume_multi(c, SND_VOL_C_PCM, left, right, center);
1220 	} else if ((cmd & ~0xff) == MIXER_READ(0)) {
1221 		*(int *)arg = CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FL);
1222 		*(int *)arg |=
1223 		    CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FR) << 8;
1224 	}
1225 
1226 	CHN_UNLOCK(c);
1227 
1228 	return (0);
1229 }
1230 
1231 static int
1232 mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
1233     struct thread *td)
1234 {
1235 	struct snddev_info *d;
1236 	int ret;
1237 
1238 	if (i_dev == NULL || i_dev->si_drv1 == NULL)
1239 		return (EBADF);
1240 
1241 	d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
1242 	if (PCM_DETACHING(d) || !PCM_REGISTERED(d))
1243 		return (EBADF);
1244 
1245 	PCM_GIANT_ENTER(d);
1246 	PCM_ACQUIRE_QUICK(d);
1247 
1248 	ret = -1;
1249 
1250 	if (mixer_bypass != 0 && (d->flags & SD_F_VPC))
1251 		ret = mixer_ioctl_channel(i_dev, cmd, arg, mode, td,
1252 		    MIXER_CMD_CDEV);
1253 
1254 	if (ret == -1)
1255 		ret = mixer_ioctl_cmd(i_dev, cmd, arg, mode, td,
1256 		    MIXER_CMD_CDEV);
1257 
1258 	PCM_RELEASE_QUICK(d);
1259 	PCM_GIANT_LEAVE(d);
1260 
1261 	return (ret);
1262 }
1263 
1264 static void
1265 mixer_mixerinfo(struct snd_mixer *m, mixer_info *mi)
1266 {
1267 	bzero((void *)mi, sizeof(*mi));
1268 	strlcpy(mi->id, m->name, sizeof(mi->id));
1269 	strlcpy(mi->name, device_get_desc(m->dev), sizeof(mi->name));
1270 	mi->modify_counter = m->modify_counter;
1271 }
1272 
1273 /*
1274  * XXX Make sure you can guarantee concurrency safety before calling this
1275  *     function, be it through Giant, PCM_*, etc !
1276  */
1277 int
1278 mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
1279     struct thread *td, int from)
1280 {
1281 	struct snd_mixer *m;
1282 	int ret = EINVAL, *arg_i = (int *)arg;
1283 	int v = -1, j = cmd & 0xff;
1284 
1285 	/*
1286 	 * Certain ioctls may be made on any type of device (audio, mixer,
1287 	 * and MIDI).  Handle those special cases here.
1288 	 */
1289 	if (IOCGROUP(cmd) == 'X') {
1290 		switch (cmd) {
1291 		case SNDCTL_SYSINFO:
1292 			sound_oss_sysinfo((oss_sysinfo *)arg);
1293 			return (0);
1294 		case SNDCTL_CARDINFO:
1295 			return (sound_oss_card_info((oss_card_info *)arg));
1296 	    	case SNDCTL_AUDIOINFO:
1297 	    	case SNDCTL_AUDIOINFO_EX:
1298 	    	case SNDCTL_ENGINEINFO:
1299 			return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg));
1300 		case SNDCTL_MIXERINFO:
1301 			return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg));
1302 		}
1303 		return (EINVAL);
1304 	}
1305 
1306 	m = i_dev->si_drv1;
1307 
1308 	if (m == NULL)
1309 		return (EBADF);
1310 
1311 	snd_mtxlock(m->lock);
1312 	if (from == MIXER_CMD_CDEV && !m->busy) {
1313 		snd_mtxunlock(m->lock);
1314 		return (EBADF);
1315 	}
1316 	switch (cmd) {
1317 	case SNDCTL_DSP_GET_RECSRC_NAMES:
1318 		bcopy((void *)&m->enuminfo, arg, sizeof(oss_mixer_enuminfo));
1319 		ret = 0;
1320 		goto done;
1321 	case SNDCTL_DSP_GET_RECSRC:
1322 		ret = mixer_get_recroute(m, arg_i);
1323 		goto done;
1324 	case SNDCTL_DSP_SET_RECSRC:
1325 		ret = mixer_set_recroute(m, *arg_i);
1326 		goto done;
1327 	case OSS_GETVERSION:
1328 		*arg_i = SOUND_VERSION;
1329 		ret = 0;
1330 		goto done;
1331 	case SOUND_MIXER_INFO:
1332 		mixer_mixerinfo(m, (mixer_info *)arg);
1333 		ret = 0;
1334 		goto done;
1335 	}
1336 	if ((cmd & ~0xff) == MIXER_WRITE(0)) {
1337 		switch (j) {
1338 		case SOUND_MIXER_RECSRC:
1339 			ret = mixer_setrecsrc(m, *arg_i);
1340 			break;
1341 		case SOUND_MIXER_MUTE:
1342 			mix_setmutedevs(m, *arg_i);
1343 			ret = 0;
1344 			break;
1345 		default:
1346 			ret = mixer_set(m, j, m->mutedevs, *arg_i);
1347 			break;
1348 		}
1349 		snd_mtxunlock(m->lock);
1350 		return ((ret == 0) ? 0 : ENXIO);
1351 	}
1352 	if ((cmd & ~0xff) == MIXER_READ(0)) {
1353 		switch (j) {
1354 		case SOUND_MIXER_DEVMASK:
1355 		case SOUND_MIXER_CAPS:
1356 		case SOUND_MIXER_STEREODEVS:
1357 			v = mix_getdevs(m);
1358 			break;
1359 		case SOUND_MIXER_MUTE:
1360 			v = mix_getmutedevs(m);
1361 			break;
1362 		case SOUND_MIXER_RECMASK:
1363 			v = mix_getrecdevs(m);
1364 			break;
1365 		case SOUND_MIXER_RECSRC:
1366 			v = mixer_getrecsrc(m);
1367 			break;
1368 		default:
1369 			v = mixer_get(m, j);
1370 			break;
1371 		}
1372 		*arg_i = v;
1373 		snd_mtxunlock(m->lock);
1374 		return ((v != -1) ? 0 : ENXIO);
1375 	}
1376 done:
1377 	snd_mtxunlock(m->lock);
1378 	return (ret);
1379 }
1380 
1381 static void
1382 mixer_clone(void *arg,
1383     struct ucred *cred,
1384     char *name, int namelen, struct cdev **dev)
1385 {
1386 	struct snddev_info *d;
1387 
1388 	if (*dev != NULL)
1389 		return;
1390 	if (strcmp(name, "mixer") == 0) {
1391 		d = devclass_get_softc(pcm_devclass, snd_unit);
1392 		if (PCM_REGISTERED(d) && d->mixer_dev != NULL) {
1393 			*dev = d->mixer_dev;
1394 			dev_ref(*dev);
1395 		}
1396 	}
1397 }
1398 
1399 static void
1400 mixer_sysinit(void *p)
1401 {
1402 	if (mixer_ehtag != NULL)
1403 		return;
1404 	mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000);
1405 }
1406 
1407 static void
1408 mixer_sysuninit(void *p)
1409 {
1410 	if (mixer_ehtag == NULL)
1411 		return;
1412 	EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag);
1413 	mixer_ehtag = NULL;
1414 }
1415 
1416 SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL);
1417 SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL);
1418 
1419 /**
1420  * @brief Handler for SNDCTL_MIXERINFO
1421  *
1422  * This function searches for a mixer based on the numeric ID stored
1423  * in oss_miserinfo::dev.  If set to -1, then information about the
1424  * current mixer handling the request is provided.  Note, however, that
1425  * this ioctl may be made with any sound device (audio, mixer, midi).
1426  *
1427  * @note Caller must not hold any PCM device, channel, or mixer locks.
1428  *
1429  * See http://manuals.opensound.com/developer/SNDCTL_MIXERINFO.html for
1430  * more information.
1431  *
1432  * @param i_dev	character device on which the ioctl arrived
1433  * @param arg	user argument (oss_mixerinfo *)
1434  *
1435  * @retval EINVAL	oss_mixerinfo::dev specified a bad value
1436  * @retval 0		success
1437  */
1438 int
1439 mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
1440 {
1441 	struct snddev_info *d;
1442 	struct snd_mixer *m;
1443 	int nmix, i;
1444 
1445 	/*
1446 	 * If probing the device handling the ioctl, make sure it's a mixer
1447 	 * device.  (This ioctl is valid on audio, mixer, and midi devices.)
1448 	 */
1449 	if (mi->dev == -1 && i_dev->si_devsw != &mixer_cdevsw)
1450 		return (EINVAL);
1451 
1452 	d = NULL;
1453 	m = NULL;
1454 	nmix = 0;
1455 
1456 	/*
1457 	 * There's a 1:1 relationship between mixers and PCM devices, so
1458 	 * begin by iterating over PCM devices and search for our mixer.
1459 	 */
1460 	for (i = 0; pcm_devclass != NULL &&
1461 	    i < devclass_get_maxunit(pcm_devclass); i++) {
1462 		d = devclass_get_softc(pcm_devclass, i);
1463 		if (PCM_DETACHING(d) || !PCM_REGISTERED(d))
1464 			continue;
1465 
1466 		/* XXX Need Giant magic entry */
1467 
1468 		/* See the note in function docblock. */
1469 		PCM_UNLOCKASSERT(d);
1470 		PCM_LOCK(d);
1471 
1472 		if (d->mixer_dev != NULL && d->mixer_dev->si_drv1 != NULL &&
1473 		    ((mi->dev == -1 && d->mixer_dev == i_dev) ||
1474 		    mi->dev == nmix)) {
1475 			m = d->mixer_dev->si_drv1;
1476 			mtx_lock(m->lock);
1477 
1478 			/*
1479 			 * At this point, the following synchronization stuff
1480 			 * has happened:
1481 			 * - a specific PCM device is locked.
1482 			 * - a specific mixer device has been locked, so be
1483 			 *   sure to unlock when existing.
1484 			 */
1485 			bzero((void *)mi, sizeof(*mi));
1486 			mi->dev = nmix;
1487 			snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
1488 			strlcpy(mi->name, m->name, sizeof(mi->name));
1489 			mi->modify_counter = m->modify_counter;
1490 			mi->card_number = i;
1491 			/*
1492 			 * Currently, FreeBSD assumes 1:1 relationship between
1493 			 * a pcm and mixer devices, so this is hardcoded to 0.
1494 			 */
1495 			mi->port_number = 0;
1496 
1497 			/**
1498 			 * @todo Fill in @sa oss_mixerinfo::mixerhandle.
1499 			 * @note From 4Front:  "mixerhandle is an arbitrary
1500 			 *       string that identifies the mixer better than
1501 			 *       the device number (mixerinfo.dev).  Device
1502 			 *       numbers may change depending on the order the
1503 			 *       drivers are loaded. However the handle should
1504 			 *       remain the same provided that the sound card
1505 			 *       is not moved to another PCI slot."
1506 			 */
1507 
1508 			/**
1509 			 * @note
1510 			 * @sa oss_mixerinfo::magic is a reserved field.
1511 			 *
1512 			 * @par
1513 			 * From 4Front:  "magic is usually 0. However some
1514 			 * devices may have dedicated setup utilities and the
1515 			 * magic field may contain an unique driver specific
1516 			 * value (managed by [4Front])."
1517 			 */
1518 
1519 			mi->enabled = device_is_attached(m->dev) ? 1 : 0;
1520 			/**
1521 			 * The only flag for @sa oss_mixerinfo::caps is
1522 			 * currently MIXER_CAP_VIRTUAL, which I'm not sure we
1523 			 * really worry about.
1524 			 */
1525 			/**
1526 			 * Mixer extensions currently aren't supported, so
1527 			 * leave @sa oss_mixerinfo::nrext blank for now.
1528 			 */
1529 			/**
1530 			 * @todo Fill in @sa oss_mixerinfo::priority (requires
1531 			 *       touching drivers?)
1532 			 * @note The priority field is for mixer applets to
1533 			 * determine which mixer should be the default, with 0
1534 			 * being least preferred and 10 being most preferred.
1535 			 * From 4Front:  "OSS drivers like ICH use higher
1536 			 * values (10) because such chips are known to be used
1537 			 * only on motherboards.  Drivers for high end pro
1538 			 * devices use 0 because they will never be the
1539 			 * default mixer. Other devices use values 1 to 9
1540 			 * depending on the estimated probability of being the
1541 			 * default device.
1542 			 *
1543 			 * XXX Described by Hannu@4Front, but not found in
1544 			 *     soundcard.h.
1545 			strlcpy(mi->devnode, devtoname(d->mixer_dev),
1546 			sizeof(mi->devnode));
1547 			mi->legacy_device = i;
1548 			 */
1549 			mtx_unlock(m->lock);
1550 		} else
1551 			++nmix;
1552 
1553 		PCM_UNLOCK(d);
1554 
1555 		if (m != NULL)
1556 			return (0);
1557 	}
1558 
1559 	return (EINVAL);
1560 }
1561 
1562 /*
1563  * Allow the sound driver to use the mixer lock to protect its mixer
1564  * data:
1565  */
1566 struct mtx *
1567 mixer_get_lock(struct snd_mixer *m)
1568 {
1569 	if (m->lock == NULL) {
1570 		return (&Giant);
1571 	}
1572 	return (m->lock);
1573 }
1574 
1575 int
1576 mix_get_locked(struct snd_mixer *m, u_int dev, int *pleft, int *pright)
1577 {
1578 	int level;
1579 
1580 	level = mixer_get(m, dev);
1581 	if (level < 0) {
1582 		*pright = *pleft = -1;
1583 		return (-1);
1584 	}
1585 
1586 	*pleft = level & 0xFF;
1587 	*pright = (level >> 8) & 0xFF;
1588 
1589 	return (0);
1590 }
1591 
1592 int
1593 mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right)
1594 {
1595 	int level;
1596 
1597 	level = (left & 0xFF) | ((right & 0xFF) << 8);
1598 
1599 	return (mixer_set(m, dev, m->mutedevs, level));
1600 }
1601