usb_ac.c revision 11936:54dc8a89ba0d
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * AUDIO CONTROL Driver:
28 *
29 * usb_ac is a multiplexor that sits on top of usb_as and hid and is
30 * responsible for (1) providing the entry points to audio mixer framework,
31 * (2) passing control commands to and from usb_as and hid and (3) processing
32 * control messages from hid/usb_ah that it can handle.
33 *
34 * 1. Mixer entry points are: usb_ac_setup(), usb_ac_teardown(),
35 *	usb_ac_set_config(), usb_ac_set_format(), usb_ac_start_play(),
36 *	usb_ac_pause_play(), usb_ac_stop_play, usb_ac_start_record(),
37 *	usb_ac_stop_record().
38 * 2. usb_ac is a streams driver that passes streams messages down to
39 *	usb_as that selects the correct alternate with passed format
40 *	parameters, sets sample frequency, starts play/record, stops
41 *	play/record, pause play/record, open/close isoc pipe.
42 * 3. usb_ac handles the set_config command through the default pipe
43 *	of sound control interface of the audio device in a synchronous
44 *	manner.
45 *
46 * Serialization: A competing thread can't be allowed to interfere with
47 * (1) pipe, (2) streams state.
48 * So we need some kind of serialization among the asynchronous
49 * threads that can run in the driver. The serialization is mostly
50 * needed to avoid races among open/close/events/power entry points
51 * etc. Once a routine takes control, it checks if the resource (pipe or
52 * stream or dev state) is still accessible. If so, it proceeds with
53 * its job and until it completes, no other thread requiring the same
54 * resource can run.
55 *
56 * PM model in usb_ac: Raise power during attach. If a device is not at full
57 * power, raise power in the entry points. After the command is over,
58 * pm_idle_component() is called. The power is lowered in detach().
59 */
60#include <sys/usb/usba/usbai_version.h>
61#include <sys/usb/usba.h>
62#include <sys/sunndi.h>
63#include <sys/strsubr.h>
64#include <sys/strsun.h>
65#include <sys/ddi.h>
66#include <sys/sunddi.h>
67#include <sys/sunldi.h>
68
69#include <sys/audio/audio_driver.h>
70
71#include <sys/usb/clients/audio/usb_audio.h>
72#include <sys/usb/clients/audio/usb_mixer.h>
73#include <sys/usb/clients/audio/usb_ac/usb_ac.h>
74
75/* for getting the minor node info from hid */
76#include <sys/usb/clients/hid/hidminor.h>
77#include <sys/usb/clients/audio/usb_as/usb_as.h>
78
79
80/* debug support */
81uint_t	usb_ac_errlevel 	= USB_LOG_L4;
82uint_t	usb_ac_errmask		= (uint_t)-1;
83uint_t	usb_ac_instance_debug	= (uint_t)-1;
84
85/*
86 * wait period in seconds for the HID message processing thread
87 * used primarily to check when the stream has closed
88 */
89uint_t usb_ac_wait_hid = 1;
90
91/*
92 * table for converting term types of input and output terminals
93 * to OSS port types (pretty rough mapping)
94 */
95static const char *usb_audio_dtypes[] = {
96	AUDIO_PORT_LINEIN,
97	AUDIO_PORT_LINEOUT,
98	AUDIO_PORT_SPEAKER,
99	AUDIO_PORT_HEADPHONES,
100	AUDIO_PORT_HANDSET,
101	AUDIO_PORT_CD,
102	AUDIO_PORT_MIC,
103	AUDIO_PORT_PHONE,
104	AUDIO_PORT_SPDIFIN,
105	AUDIO_PORT_OTHER,
106	NULL,
107};
108enum {
109	USB_PORT_LINEIN = 0,
110	USB_PORT_LINEOUT,
111	USB_PORT_SPEAKER,
112	USB_PORT_HEADPHONES,
113	USB_PORT_HANDSET,
114	USB_PORT_CD,
115	USB_PORT_MIC,
116	USB_PORT_PHONE,
117	USB_PORT_SPDIFIN,
118	USB_PORT_UNKNOWN
119};
120
121static struct {
122	ushort_t	term_type;
123	uint_t	port_type;
124} usb_ac_term_type_map[] = {
125
126	/* Input Terminal Types */
127{ USB_AUDIO_TERM_TYPE_MICROPHONE,		USB_PORT_MIC },
128{ USB_AUDIO_TERM_TYPE_DT_MICROPHONE,		USB_PORT_MIC },
129{ USB_AUDIO_TERM_TYPE_PERS_MICROPHONE,		USB_PORT_MIC },
130{ USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE,	USB_PORT_MIC },
131{ USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY,		USB_PORT_MIC },
132{ USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY,	USB_PORT_MIC },
133
134	/* Output Terminal Types */
135{ USB_AUDIO_TERM_TYPE_SPEAKER,			USB_PORT_SPEAKER },
136{ USB_AUDIO_TERM_TYPE_HEADPHONES,		USB_PORT_HEADPHONES },
137{ USB_AUDIO_TERM_TYPE_DISPLAY_AUDIO,		USB_PORT_LINEOUT },
138{ USB_AUDIO_TERM_TYPE_DT_SPEAKER,		USB_PORT_SPEAKER },
139{ USB_AUDIO_TERM_TYPE_ROOM_SPEAKER,		USB_PORT_SPEAKER },
140{ USB_AUDIO_TERM_TYPE_COMM_SPEAKER,		USB_PORT_SPEAKER },
141{ USB_AUDIO_TERM_TYPE_LF_EFFECTS_SPEAKER,	USB_PORT_SPEAKER },
142
143	/* Bi-directional Terminal Types */
144{ USB_AUDIO_TERM_TYPE_HANDSET,		USB_PORT_HANDSET },
145
146	/* Telephony Terminal Types */
147{ USB_AUDIO_TERM_TYPE_PHONE_LINE,	USB_PORT_PHONE},
148{ USB_AUDIO_TERM_TYPE_TELEPHONE,	USB_PORT_PHONE},
149{ USB_AUDIO_TERM_TYPE_DOWN_LINE_PHONE,	USB_PORT_PHONE },
150
151	/* External Terminal Types */
152{ USB_AUDIO_TERM_TYPE_SPDIF_IF,		USB_PORT_SPDIFIN },
153	/* Embedded Function Terminal Types */
154{ USB_AUDIO_TERM_TYPE_CD_PLAYER,	USB_PORT_CD },
155{ 0, 0 }
156};
157
158
159/*
160 * Module linkage routines for the kernel
161 */
162static int	usb_ac_attach(dev_info_t *, ddi_attach_cmd_t);
163static int	usb_ac_detach(dev_info_t *, ddi_detach_cmd_t);
164static int	usb_ac_power(dev_info_t *, int, int);
165
166static uint_t	usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
167				uint_t);
168
169/* module entry points */
170int		usb_ac_open(dev_info_t *);
171void		usb_ac_close(dev_info_t *);
172
173/* descriptor handling */
174static int	usb_ac_handle_descriptors(usb_ac_state_t *);
175static void	usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t);
176static void	usb_ac_alloc_unit(usb_ac_state_t *, uint_t);
177static void	usb_ac_free_all_units(usb_ac_state_t *);
178static void	usb_ac_setup_connections(usb_ac_state_t *);
179static void	usb_ac_map_termtype_to_port(usb_ac_state_t *, uint_t);
180
181/* power management */
182static int	usb_ac_pwrlvl0(usb_ac_state_t *);
183static int	usb_ac_pwrlvl1(usb_ac_state_t *);
184static int	usb_ac_pwrlvl2(usb_ac_state_t *);
185static int	usb_ac_pwrlvl3(usb_ac_state_t *);
186static void	usb_ac_create_pm_components(dev_info_t *, usb_ac_state_t *);
187static void	usb_ac_pm_busy_component(usb_ac_state_t *);
188static void	usb_ac_pm_idle_component(usb_ac_state_t *);
189
190/* event handling */
191static int	usb_ac_disconnect_event_cb(dev_info_t *);
192static int	usb_ac_reconnect_event_cb(dev_info_t *);
193static int	usb_ac_cpr_suspend(dev_info_t *);
194static void	usb_ac_cpr_resume(dev_info_t *);
195
196static usb_event_t usb_ac_events = {
197	usb_ac_disconnect_event_cb,
198	usb_ac_reconnect_event_cb,
199	NULL, NULL
200};
201
202/* misc. support */
203static void	usb_ac_restore_device_state(dev_info_t *, usb_ac_state_t *);
204static int	usb_ac_cleanup(dev_info_t *, usb_ac_state_t *);
205static void	usb_ac_serialize_access(usb_ac_state_t *);
206static void	usb_ac_release_access(usb_ac_state_t *);
207
208static void	usb_ac_push_unit_id(usb_ac_state_t *, uint_t);
209static void	usb_ac_pop_unit_id(usb_ac_state_t *, uint_t);
210static void	usb_ac_show_traverse_path(usb_ac_state_t *);
211static int	usb_ac_check_path(usb_ac_state_t *, uint_t);
212
213static uint_t	usb_ac_traverse_connections(usb_ac_state_t *, uint_t, uint_t,
214				uint_t, uint_t, uint_t, uint_t,
215				uint_t *, uint_t, uint_t *,
216				int (*func)(usb_ac_state_t *, uint_t, uint_t,
217				uint_t, uint_t, uint_t, uint_t *));
218static uint_t	usb_ac_set_port(usb_ac_state_t *, uint_t, uint_t);
219static uint_t	usb_ac_set_control(usb_ac_state_t *, uint_t, uint_t,
220				uint_t, uint_t, uint_t,
221				uint_t *, uint_t,
222				int (*func)(usb_ac_state_t *, uint_t, uint_t,
223				uint_t, uint_t, uint_t, uint_t *));
224static uint_t	usb_ac_set_monitor_gain_control(usb_ac_state_t *, uint_t,
225				uint_t, uint_t, uint_t, uint_t,
226				uint_t *, uint_t,
227				int (*func)(usb_ac_state_t *, uint_t, uint_t,
228				uint_t, uint_t, uint_t, uint_t *));
229static uint_t	usb_ac_traverse_all_units(usb_ac_state_t *, uint_t, uint_t,
230				uint_t, uint_t, uint_t, uint_t *,
231				uint_t, uint_t *,
232				int (*func)(usb_ac_state_t *, uint_t, uint_t,
233				uint_t, uint_t, uint_t, uint_t *));
234static int	usb_ac_update_port(usb_ac_state_t *, uint_t,
235				uint_t, uint_t, uint_t, uint_t, uint_t *);
236static int	usb_ac_set_selector(usb_ac_state_t *, uint_t,
237				uint_t, uint_t, uint_t, uint_t, uint_t *);
238static int	usb_ac_feature_unit_check(usb_ac_state_t *, uint_t,
239				uint_t, uint_t, uint_t, uint_t, uint_t *);
240static int	usb_ac_set_gain(usb_ac_state_t *, uint_t,
241				uint_t, uint_t, uint_t, uint_t, uint_t *);
242static int	usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t,
243				uint_t, uint_t, uint_t, uint_t, uint_t *);
244static int	usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir,
245				int);
246static int	usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int,
247				int, short *);
248static int	usb_ac_send_as_cmd(usb_ac_state_t *, usb_audio_eng_t *,
249				int, void *);
250static int	usb_ac_set_format(usb_ac_state_t *, usb_audio_eng_t *);
251static int	usb_ac_do_setup(usb_ac_state_t *, usb_audio_eng_t *);
252
253/*  usb audio basic function entries */
254static int	usb_ac_setup(usb_ac_state_t *, usb_audio_eng_t *);
255static void	usb_ac_teardown(usb_ac_state_t *, usb_audio_eng_t *);
256static int	usb_ac_start_play(usb_ac_state_t *, usb_audio_eng_t *);
257static int	usb_ac_start_record(usb_ac_state_t *, usb_audio_eng_t *);
258static void	usb_ac_stop_record(usb_ac_state_t *, usb_audio_eng_t *);
259static int	usb_ac_restore_audio_state(usb_ac_state_t *, int);
260
261static int	usb_ac_ctrl_restore(usb_ac_state_t *);
262/*
263 * Mux
264 */
265static int	usb_ac_mux_walk_siblings(usb_ac_state_t *);
266static void	usb_ac_print_reg_data(usb_ac_state_t *,
267				usb_as_registration_t *);
268static int	usb_ac_get_reg_data(usb_ac_state_t *, ldi_handle_t, int);
269static int	usb_ac_setup_plumbed(usb_ac_state_t *, int, int);
270static int	usb_ac_mixer_registration(usb_ac_state_t *);
271static void	usb_ac_hold_siblings(usb_ac_state_t *);
272static int	usb_ac_online_siblings(usb_ac_state_t *);
273static void	usb_ac_rele_siblings(usb_ac_state_t *);
274static int	usb_ac_mux_plumbing(usb_ac_state_t *);
275static void	usb_ac_mux_plumbing_tq(void *);
276static int	usb_ac_mux_unplumbing(usb_ac_state_t *);
277static void	usb_ac_mux_unplumbing_tq(void *);
278static int	usb_ac_plumb(usb_ac_plumbed_t *);
279static void	usb_ac_unplumb(usb_ac_plumbed_t *);
280static void	usb_ac_reader(void *);
281static int	usb_ac_read_msg(usb_ac_plumbed_t *, mblk_t *);
282static int	usb_ac_do_plumbing(usb_ac_state_t *);
283static int	usb_ac_do_unplumbing(usb_ac_state_t *);
284
285
286static int usb_change_phy_vol(usb_ac_state_t *, int);
287static void usb_restore_engine(usb_ac_state_t *);
288
289/* anchor for soft state structures */
290void	*usb_ac_statep;
291
292/*
293 * DDI Structures
294 */
295
296/* Device operations structure */
297static struct dev_ops usb_ac_dev_ops = {
298	DEVO_REV,		/* devo_rev */
299	0,			/* devo_refcnt */
300	NULL,			/* devo_getinfo */
301	nulldev,		/* devo_identify - obsolete */
302	nulldev,		/* devo_probe - not needed */
303	usb_ac_attach,		/* devo_attach */
304	usb_ac_detach,		/* devo_detach */
305	nodev,			/* devo_reset */
306	NULL,			/* devi_cb_ops */
307	NULL,			/* devo_busb_ac_ops */
308	usb_ac_power,		/* devo_power */
309	ddi_quiesce_not_needed,	/* devo_quiesce */
310};
311
312/* Linkage structure for loadable drivers */
313static struct modldrv usb_ac_modldrv = {
314	&mod_driverops,				/* drv_modops */
315	"USB Audio Control Driver",		/* drv_linkinfo */
316	&usb_ac_dev_ops				/* drv_dev_ops */
317};
318
319/* Module linkage structure */
320static struct modlinkage usb_ac_modlinkage = {
321	MODREV_1,			/* ml_rev */
322	(void *)&usb_ac_modldrv,	/* ml_linkage */
323	NULL				/* NULL terminates the list */
324};
325
326static int usb_audio_register(usb_ac_state_t *);
327static int usb_audio_unregister(usb_ac_state_t *);
328
329static int usb_engine_open(void *, int, unsigned *, caddr_t *);
330static void usb_engine_close(void *);
331static uint64_t usb_engine_count(void *);
332static int usb_engine_start(void *);
333static void usb_engine_stop(void *);
334static int usb_engine_format(void *);
335static int usb_engine_channels(void *);
336static int usb_engine_rate(void *);
337static void usb_engine_sync(void *, unsigned);
338static unsigned usb_engine_qlen(void *);
339
340/* engine buffer size in terms of fragments */
341
342audio_engine_ops_t usb_engine_ops = {
343	AUDIO_ENGINE_VERSION,
344	usb_engine_open,
345	usb_engine_close,
346	usb_engine_start,
347	usb_engine_stop,
348	usb_engine_count,
349	usb_engine_format,
350	usb_engine_channels,
351	usb_engine_rate,
352	usb_engine_sync,
353	usb_engine_qlen,
354};
355
356
357
358_NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
359
360/* standard entry points */
361int
362_init(void)
363{
364	int rval;
365
366	/* initialize the soft state */
367	if ((rval = ddi_soft_state_init(&usb_ac_statep,
368	    sizeof (usb_ac_state_t), 1)) != DDI_SUCCESS) {
369		return (rval);
370	}
371
372	audio_init_ops(&usb_ac_dev_ops, "usb_ac");
373
374	if ((rval = mod_install(&usb_ac_modlinkage)) != 0) {
375		ddi_soft_state_fini(&usb_ac_statep);
376		audio_fini_ops(&usb_ac_dev_ops);
377	}
378
379	return (rval);
380}
381
382int
383_fini(void)
384{
385	int rval;
386
387	if ((rval = mod_remove(&usb_ac_modlinkage)) == 0) {
388		/* Free the soft state internal structures */
389		ddi_soft_state_fini(&usb_ac_statep);
390		audio_fini_ops(&usb_ac_dev_ops);
391	}
392
393	return (rval);
394}
395
396int
397_info(struct modinfo *modinfop)
398{
399	return (mod_info(&usb_ac_modlinkage, modinfop));
400}
401
402extern	uint_t		nproc;
403#define	INIT_PROCESS_CNT 3
404
405static int
406usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
407{
408	usb_ac_state_t		*uacp = NULL;
409	int			instance = ddi_get_instance(dip);
410
411	switch (cmd) {
412		case DDI_ATTACH:
413			break;
414		case DDI_RESUME:
415			usb_ac_cpr_resume(dip);
416
417			return (DDI_SUCCESS);
418		default:
419			return (DDI_FAILURE);
420	}
421
422	/*
423	 * wait  until all processes are started from main.
424	 * USB enumerates early in boot (ie. consconfig time).
425	 * If the plumbing takes place early, the file descriptors
426	 * are owned by the init process and can never be closed anymore
427	 * Consequently, hot removal is not possible and the dips
428	 * never go away. By waiting some time, e.g. INIT_PROCESS_CNT,
429	 * the problem is avoided.
430	 */
431	if (nproc < INIT_PROCESS_CNT) {
432		USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL,
433		    "usb_ac%d attach too early", instance);
434
435		return (DDI_FAILURE);
436	}
437
438	/*
439	 * Allocate soft state information.
440	 */
441	if (ddi_soft_state_zalloc(usb_ac_statep, instance) != DDI_SUCCESS) {
442
443		goto fail;
444	}
445
446	/*
447	 * get soft state space and initialize
448	 */
449	uacp = (usb_ac_state_t *)ddi_get_soft_state(usb_ac_statep, instance);
450	if (uacp == NULL) {
451
452		goto fail;
453	}
454
455	/* get log handle */
456	uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac",
457	    &usb_ac_errlevel,
458	    &usb_ac_errmask, &usb_ac_instance_debug,
459	    0);
460
461	uacp->usb_ac_instance = instance;
462	uacp->usb_ac_dip = dip;
463
464	(void) snprintf(uacp->dstr, sizeof (uacp->dstr), "%s#%d",
465	    ddi_driver_name(dip), instance);
466
467	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
468		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
469		    "usb_client_attach failed");
470
471		usb_free_log_hdl(uacp->usb_ac_log_handle);
472		ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
473
474		return (DDI_FAILURE);
475	}
476
477	if (usb_get_dev_data(dip, &uacp->usb_ac_dev_data,
478	    USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
479		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
480		    "usb_get_dev_data failed");
481
482		usb_client_detach(dip, NULL);
483		usb_free_log_hdl(uacp->usb_ac_log_handle);
484		ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
485
486		return (DDI_FAILURE);
487	}
488
489	/* initialize mutex & cv */
490	mutex_init(&uacp->usb_ac_mutex, NULL, MUTEX_DRIVER,
491	    uacp->usb_ac_dev_data->dev_iblock_cookie);
492
493	uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph;
494
495	/* parse all class specific descriptors */
496	if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) {
497
498		goto fail;
499	}
500
501	/* we no longer need the descr tree */
502	usb_free_descr_tree(dip, uacp->usb_ac_dev_data);
503
504	uacp->usb_ac_ser_acc = usb_init_serialization(dip,
505	    USB_INIT_SER_CHECK_SAME_THREAD);
506
507	mutex_enter(&uacp->usb_ac_mutex);
508
509	/* we are online */
510	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
511
512	/*
513	 * safe guard the postattach to be executed
514	 * only two states arepossible: plumbed / unplumbed
515	 */
516	uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
517	uacp->usb_ac_current_plumbed_index = -1;
518
519	mutex_exit(&uacp->usb_ac_mutex);
520
521	/* create components to power manage this device */
522	usb_ac_create_pm_components(dip, uacp);
523
524	/* Register for events */
525	if (usb_register_event_cbs(dip, &usb_ac_events, 0) != USB_SUCCESS) {
526		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
527		    "usb_ac_attach: couldn't register for events");
528
529		goto fail;
530	}
531
532	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
533	    "usb_ac_attach: End");
534
535	/* report device */
536	ddi_report_dev(dip);
537
538	if (usb_ac_do_plumbing(uacp) != USB_SUCCESS)
539		goto fail;
540
541	return (DDI_SUCCESS);
542
543fail:
544	if (uacp) {
545		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
546		    "attach failed");
547
548		/* wait for plumbing thread to finish */
549		if (uacp->tqp != NULL) {
550			ddi_taskq_wait(uacp->tqp);
551			ddi_taskq_destroy(uacp->tqp);
552			uacp->tqp = NULL;
553		}
554		(void) usb_ac_cleanup(dip, uacp);
555	}
556
557	return (DDI_FAILURE);
558}
559
560
561static int
562usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
563{
564	int instance = ddi_get_instance(dip);
565	usb_ac_state_t	*uacp;
566	int rval = USB_FAILURE;
567
568	uacp = ddi_get_soft_state(usb_ac_statep, instance);
569
570	switch (cmd) {
571	case DDI_DETACH:
572		USB_DPRINTF_L4(PRINT_MASK_ATTA,
573		    uacp->usb_ac_log_handle, "usb_ac_detach: detach");
574
575		/* wait for plumbing thread to finish */
576		if (uacp->tqp != NULL)
577			ddi_taskq_wait(uacp->tqp);
578
579		mutex_enter(&uacp->usb_ac_mutex);
580
581		/* do not allow detach if still busy */
582		if (uacp->usb_ac_busy_count) {
583			USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
584			    "usb_ac_detach:still busy, usb_ac_busy_count = %d",
585			    uacp->usb_ac_busy_count);
586
587			mutex_exit(&uacp->usb_ac_mutex);
588			return (USB_FAILURE);
589		}
590		mutex_exit(&uacp->usb_ac_mutex);
591
592		(void) usb_audio_unregister(uacp);
593
594
595
596		/*
597		 * unplumb to stop activity from other modules, then
598		 * cleanup, which will also teardown audio framework state
599		 */
600		if (usb_ac_do_unplumbing(uacp) == USB_SUCCESS)
601			rval = usb_ac_cleanup(dip, uacp);
602
603		if (rval != USB_SUCCESS) {
604			USB_DPRINTF_L2(PRINT_MASK_ATTA,
605			    uacp->usb_ac_log_handle, "detach failed: %s%d",
606			    ddi_driver_name(dip), instance);
607		}
608
609		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
610	case DDI_SUSPEND:
611		USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
612		    "usb_ac_detach: suspending");
613
614		rval = usb_ac_cpr_suspend(dip);
615
616		return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
617	default:
618
619		return (DDI_FAILURE);
620	}
621}
622
623
624/*
625 * usb_ac_cleanup:
626 *	cleanup on attach failure and detach
627 */
628static int
629usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
630{
631	usb_ac_power_t	*uacpm;
632	int	rval = USB_FAILURE;
633
634
635	mutex_enter(&uacp->usb_ac_mutex);
636	uacpm = uacp->usb_ac_pm;
637
638	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
639	    "usb_ac_cleanup:begain");
640
641	ASSERT(uacp->usb_ac_busy_count == 0);
642
643	ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED);
644
645	mutex_exit(&uacp->usb_ac_mutex);
646
647	/*
648	 * Disable the event callbacks, after this point, event
649	 * callbacks will never get called. Note we shouldn't hold
650	 * the mutex while unregistering events because there may be a
651	 * competing event callback thread. Event callbacks are done
652	 * with ndi mutex held and this can cause a potential deadlock.
653	 */
654	usb_unregister_event_cbs(dip, &usb_ac_events);
655
656	mutex_enter(&uacp->usb_ac_mutex);
657
658	if (uacpm && (uacp->usb_ac_dev_state != USB_DEV_DISCONNECTED)) {
659		if (uacpm->acpm_wakeup_enabled) {
660			mutex_exit(&uacp->usb_ac_mutex);
661			usb_ac_pm_busy_component(uacp);
662			(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
663
664			rval = usb_handle_remote_wakeup(dip,
665			    USB_REMOTE_WAKEUP_DISABLE);
666			if (rval != USB_SUCCESS) {
667				USB_DPRINTF_L2(PRINT_MASK_PM,
668				    uacp->usb_ac_log_handle,
669				    "usb_ac_cleanup: disable remote "
670				    "wakeup failed, rval=%d", rval);
671			}
672			usb_ac_pm_idle_component(uacp);
673		} else {
674			mutex_exit(&uacp->usb_ac_mutex);
675		}
676
677		(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
678
679		mutex_enter(&uacp->usb_ac_mutex);
680	}
681
682	if (uacpm) {
683		kmem_free(uacpm,  sizeof (usb_ac_power_t));
684		uacp->usb_ac_pm = NULL;
685	}
686
687	usb_client_detach(dip, uacp->usb_ac_dev_data);
688
689	/* free descriptors */
690	usb_ac_free_all_units(uacp);
691
692	mutex_exit(&uacp->usb_ac_mutex);
693
694	mutex_destroy(&uacp->usb_ac_mutex);
695
696	usb_fini_serialization(uacp->usb_ac_ser_acc);
697
698	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
699	    "usb_ac_cleanup: Ending");
700
701	usb_free_log_hdl(uacp->usb_ac_log_handle);
702	kmem_free(uacp->usb_ac_connections, uacp->usb_ac_connections_len);
703	kmem_free(uacp->usb_ac_connections_a, uacp->usb_ac_connections_a_len);
704	kmem_free(uacp->usb_ac_unit_type, uacp->usb_ac_max_unit);
705	kmem_free(uacp->usb_ac_traverse_path, uacp->usb_ac_max_unit);
706
707	ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
708
709	ddi_prop_remove_all(dip);
710
711	return (USB_SUCCESS);
712}
713
714
715int
716usb_ac_open(dev_info_t *dip)
717{
718	int inst = ddi_get_instance(dip);
719	usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
720
721	mutex_enter(&uacp->usb_ac_mutex);
722
723	uacp->usb_ac_busy_count++;
724
725	mutex_exit(&uacp->usb_ac_mutex);
726
727	usb_ac_pm_busy_component(uacp);
728	(void) pm_raise_power(uacp->usb_ac_dip, 0, USB_DEV_OS_FULL_PWR);
729
730	return (0);
731}
732
733
734void
735usb_ac_close(dev_info_t *dip)
736{
737	int inst = ddi_get_instance(dip);
738	usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
739
740	mutex_enter(&uacp->usb_ac_mutex);
741
742	if (uacp->usb_ac_busy_count > 0)
743		uacp->usb_ac_busy_count--;
744
745	mutex_exit(&uacp->usb_ac_mutex);
746
747	usb_ac_pm_idle_component(uacp);
748}
749
750
751/*
752 * usb_ac_read_msg:
753 *	Handle asynchronous response from opened streams
754 */
755static int
756usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
757{
758	usb_ac_state_t	*uacp = plumb_infop->acp_uacp;
759	int error = DDI_SUCCESS;
760	int	val;
761	char	val1;
762	struct iocblk *iocp;
763
764
765	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
766
767	/*
768	 * typically an M_CTL is used between modules but in order to pass
769	 * through the streamhead, an M_PROTO type must be used instead
770	 */
771	switch (mp->b_datap->db_type) {
772	case M_PROTO:
773	case M_ERROR:
774		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
775		    "M_CTL/M_ERROR");
776
777		switch (plumb_infop->acp_driver) {
778		case USB_AH_PLUMBED:
779			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
780			    "message from hid, instance=%d",
781			    ddi_get_instance(plumb_infop->acp_dip));
782
783			iocp = (struct iocblk *)(void *)mp->b_rptr;
784			ASSERT(mp->b_cont != NULL);
785
786			if (uacp->usb_ac_registered_with_mixer) {
787
788				val1 = *((char *)mp->b_cont->b_rptr);
789				val = (int)val1;
790
791				USB_DPRINTF_L4(PRINT_MASK_ALL,
792				    uacp->usb_ac_log_handle, "val1=0x%x(%d),"
793				    "val=0x%x(%d)", val1, val1, val, val);
794
795				switch (iocp->ioc_cmd) {
796				/* Handle relative volume change */
797				case USB_AUDIO_VOL_CHANGE:
798					/* prevent unplumbing */
799					uacp->usb_ac_busy_count++;
800					if (uacp->usb_ac_plumbing_state ==
801					    USB_AC_STATE_PLUMBED) {
802						mutex_exit(&uacp->usb_ac_mutex);
803						(void) usb_change_phy_vol(
804						    uacp, val);
805						mutex_enter(&uacp->
806						    usb_ac_mutex);
807					}
808					uacp->usb_ac_busy_count--;
809					/* FALLTHRU */
810				case USB_AUDIO_MUTE:
811				default:
812					freemsg(mp);
813					break;
814				}
815			} else {
816				freemsg(mp);
817			}
818
819			break;
820		default:
821			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
822			    "message from unknown module(%s)",
823			    ddi_driver_name(plumb_infop->acp_dip));
824			freemsg(mp);
825		}
826
827		break;
828	default:
829		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
830		    "Unknown type=%d", mp->b_datap->db_type);
831		freemsg(mp);
832	}
833
834
835	return (error);
836}
837
838
839/*
840 * Power Management
841 * usb_ac_power:
842 *	power entry point
843 */
844static int
845usb_ac_power(dev_info_t *dip, int comp, int level)
846{
847	_NOTE(ARGUNUSED(comp));
848	int		instance = ddi_get_instance(dip);
849	usb_ac_state_t	*uacp;
850	usb_ac_power_t	*uacpm;
851	int		rval = DDI_FAILURE;
852
853	uacp = ddi_get_soft_state(usb_ac_statep, instance);
854
855	mutex_enter(&uacp->usb_ac_mutex);
856	uacpm = uacp->usb_ac_pm;
857
858	if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) {
859		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
860		    "usb_ac_power: illegal level=%d pwr_states=%d",
861		    level, uacpm->acpm_pwr_states);
862
863		goto done;
864	}
865
866	switch (level) {
867	case USB_DEV_OS_PWR_OFF:
868		rval = usb_ac_pwrlvl0(uacp);
869		break;
870	case USB_DEV_OS_PWR_1:
871		rval = usb_ac_pwrlvl1(uacp);
872		break;
873	case USB_DEV_OS_PWR_2:
874		rval = usb_ac_pwrlvl2(uacp);
875		break;
876	case USB_DEV_OS_FULL_PWR:
877		rval = usb_ac_pwrlvl3(uacp);
878		break;
879	}
880
881done:
882	mutex_exit(&uacp->usb_ac_mutex);
883
884	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
885}
886
887
888/*
889 * functions to handle power transition for various levels
890 * These functions act as place holders to issue USB commands
891 * to the devices to change their power levels
892 * Level 0 = Device is powered off
893 * Level 3 = Device if full powered
894 * Level 1,2 = Intermediate power level of the device as implemented
895 *	by the hardware.
896 * Note that Level 0 is OS power-off and Level 3 is OS full-power.
897 */
898static int
899usb_ac_pwrlvl0(usb_ac_state_t *uacp)
900{
901	usb_ac_power_t	*uacpm;
902	int		rval;
903
904	uacpm = uacp->usb_ac_pm;
905
906	switch (uacp->usb_ac_dev_state) {
907	case USB_DEV_ONLINE:
908		/* Deny the powerdown request if the device is busy */
909		if (uacpm->acpm_pm_busy != 0) {
910
911			return (USB_FAILURE);
912		}
913
914		/* Issue USB D3 command to the device here */
915		rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip);
916		ASSERT(rval == USB_SUCCESS);
917
918		uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN;
919		uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF;
920
921		/* FALLTHRU */
922	case USB_DEV_DISCONNECTED:
923	case USB_DEV_SUSPENDED:
924	case USB_DEV_PWRED_DOWN:
925	default:
926		return (USB_SUCCESS);
927	}
928}
929
930
931/* ARGSUSED */
932static int
933usb_ac_pwrlvl1(usb_ac_state_t *uacp)
934{
935	int		rval;
936
937	/* Issue USB D2 command to the device here */
938	rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip);
939	ASSERT(rval == USB_SUCCESS);
940
941	return (USB_FAILURE);
942}
943
944
945/* ARGSUSED */
946static int
947usb_ac_pwrlvl2(usb_ac_state_t *uacp)
948{
949	int		rval;
950
951	rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip);
952	ASSERT(rval == USB_SUCCESS);
953
954	return (USB_FAILURE);
955}
956
957
958static int
959usb_ac_pwrlvl3(usb_ac_state_t *uacp)
960{
961	usb_ac_power_t	*uacpm;
962	int		rval;
963
964	uacpm = uacp->usb_ac_pm;
965
966	switch (uacp->usb_ac_dev_state) {
967	case USB_DEV_PWRED_DOWN:
968		/* Issue USB D0 command to the device here */
969		rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip);
970		ASSERT(rval == USB_SUCCESS);
971
972		uacp->usb_ac_dev_state = USB_DEV_ONLINE;
973		uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
974		/* FALLTHRU */
975	case USB_DEV_ONLINE:
976		/* we are already in full power */
977
978		/* FALLTHRU */
979	case USB_DEV_DISCONNECTED:
980	case USB_DEV_SUSPENDED:
981
982		return (USB_SUCCESS);
983	default:
984		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
985		    "usb_ac_pwerlvl3: Illegal dev_state");
986
987		return (USB_FAILURE);
988	}
989}
990
991
992static void
993usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
994{
995	usb_ac_power_t	*uacpm;
996	uint_t		pwr_states;
997
998	USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
999	    "usb_ac_create_pm_components: begin");
1000
1001	/* Allocate the state structure */
1002	uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP);
1003	uacp->usb_ac_pm = uacpm;
1004	uacpm->acpm_state = uacp;
1005	uacpm->acpm_capabilities = 0;
1006	uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1007
1008	if (usb_create_pm_components(dip, &pwr_states) ==
1009	    USB_SUCCESS) {
1010		if (usb_handle_remote_wakeup(dip,
1011		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1012			uacpm->acpm_wakeup_enabled = 1;
1013
1014			USB_DPRINTF_L4(PRINT_MASK_PM,
1015			    uacp->usb_ac_log_handle,
1016			    "remote Wakeup enabled");
1017		}
1018		uacpm->acpm_pwr_states = (uint8_t)pwr_states;
1019		(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1020	} else {
1021		if (uacpm) {
1022			kmem_free(uacpm,  sizeof (usb_ac_power_t));
1023			uacp->usb_ac_pm = NULL;
1024		}
1025		USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1026		    "pm not enabled");
1027	}
1028
1029}
1030
1031/*
1032 * usb_ac_get_featureID:
1033 *	find out if there is at least one feature unit that supports
1034 *	the request controls.
1035 *	Return featureID or USB_AC_ID_NONE.
1036 */
1037static uint_t
1038usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir,
1039    uint_t channel, uint_t control)
1040{
1041	uint_t count = 0;
1042
1043	return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT,
1044	    channel, control, USB_AC_FIND_ONE, &count, 0,
1045	    usb_ac_feature_unit_check));
1046}
1047
1048
1049/*
1050 * usb_ac_feature_unit_check:
1051 *	check if a feature unit can support the required channel
1052 *	and control combination. Return USB_SUCCESS or USB_FAILURE.
1053 *	Called for each matching unit from usb_ac_traverse_connections.
1054 */
1055/*ARGSUSED*/
1056static int
1057usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
1058    uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1059{
1060	usb_audio_feature_unit_descr1_t *feature_descrp;
1061	int				n_channel_controls;
1062
1063
1064	ASSERT(featureID < uacp->usb_ac_max_unit);
1065
1066	/*
1067	 * check if this control is supported on this channel
1068	 */
1069	feature_descrp = (usb_audio_feature_unit_descr1_t *)
1070	    uacp->usb_ac_units[featureID].acu_descriptor;
1071	ASSERT(feature_descrp->bUnitID == featureID);
1072
1073	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1074	    "bControlSize=%d", feature_descrp->bControlSize);
1075
1076	if (feature_descrp->bControlSize == 0) {
1077		featureID = USB_AC_ID_NONE;
1078	} else {
1079		uint_t index;
1080
1081		n_channel_controls = (feature_descrp->bLength -
1082		    offsetof(usb_audio_feature_unit_descr1_t,
1083		    bmaControls))/feature_descrp->bControlSize;
1084
1085		USB_DPRINTF_L3(PRINT_MASK_ALL,
1086		    uacp->usb_ac_log_handle,
1087		    "#controls: %d index=%d", n_channel_controls,
1088		    feature_descrp->bControlSize * channel);
1089
1090		if (channel > n_channel_controls) {
1091			featureID = USB_AC_ID_NONE;
1092		} else {
1093			/*
1094			 * we only support MUTE and VOLUME
1095			 * which are in the first byte
1096			 */
1097			index = feature_descrp->bControlSize *
1098			    channel;
1099
1100			USB_DPRINTF_L3(PRINT_MASK_ALL,
1101			    uacp->usb_ac_log_handle,
1102			    "control: 0x%x",
1103			    feature_descrp->bmaControls[index]);
1104
1105			if ((feature_descrp->bmaControls[index] &
1106			    control) == 0) {
1107				featureID = USB_AC_ID_NONE;
1108			}
1109		}
1110	}
1111
1112	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1113	    "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
1114	    dir, featureID);
1115
1116	return ((featureID != USB_AC_ID_NONE) ?
1117	    USB_SUCCESS : USB_FAILURE);
1118}
1119
1120
1121/*
1122 * Descriptor Management
1123 *
1124 * usb_ac_handle_descriptors:
1125 *	extract interesting descriptors from the config cloud
1126 */
1127static int
1128usb_ac_handle_descriptors(usb_ac_state_t *uacp)
1129{
1130	int			len, index;
1131	int			rval = USB_FAILURE;
1132	usb_audio_cs_if_descr_t descr;
1133	usb_client_dev_data_t	*dev_data = uacp->usb_ac_dev_data;
1134	usb_alt_if_data_t	*altif_data;
1135	usb_cvs_data_t		*cvs;
1136
1137
1138	altif_data = &dev_data->dev_curr_cfg->
1139	    cfg_if[dev_data->dev_curr_if].if_alt[0];
1140
1141	uacp->usb_ac_ifno	= dev_data->dev_curr_if;
1142	uacp->usb_ac_if_descr	= altif_data->altif_descr;
1143
1144	/* find USB_AUDIO_CS_INTERFACE type descriptor */
1145	for (index = 0; index < altif_data->altif_n_cvs; index++) {
1146		cvs = &altif_data->altif_cvs[index];
1147		if (cvs->cvs_buf == NULL) {
1148			continue;
1149		}
1150		if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) {
1151			break;
1152		}
1153	}
1154
1155	if (index == altif_data->altif_n_cvs) {
1156		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1157		    "usb_ac_handle_descriptors:cannot find descriptor type %d",
1158		    USB_AUDIO_CS_INTERFACE);
1159
1160		return (rval);
1161	}
1162
1163	len = usb_parse_data(
1164	    CS_AC_IF_HEADER_FORMAT,
1165	    cvs->cvs_buf, cvs->cvs_buf_len,
1166	    (void *)&descr, sizeof (usb_audio_cs_if_descr_t));
1167
1168	/* is this a sane header descriptor */
1169	if (!((len >= CS_AC_IF_HEADER_SIZE) &&
1170	    (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
1171	    (descr.bDescriptorSubType == USB_AUDIO_HEADER))) {
1172		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1173		    "invalid header");
1174
1175		return (rval);
1176	}
1177
1178	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1179	    "index %d, header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
1180	    "total=0x%x InCol=0x%x",
1181	    index,
1182	    descr.bDescriptorType,
1183	    descr.bDescriptorSubType,
1184	    descr.bcdADC,
1185	    descr.wTotalLength,
1186	    descr.blnCollection);
1187
1188	/*
1189	 * we read descriptors by index and store them in ID array.
1190	 * the actual parsing is done in usb_ac_add_unit_descriptor()
1191	 */
1192	for (index++; index < altif_data->altif_n_cvs; index++) {
1193		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1194		    "index=%d", index);
1195
1196		cvs = &altif_data->altif_cvs[index];
1197		if (cvs->cvs_buf == NULL) {
1198			continue;
1199		}
1200
1201		/* add to ID array */
1202		usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf,
1203		    cvs->cvs_buf_len);
1204	}
1205	rval = USB_SUCCESS;
1206
1207	usb_ac_setup_connections(uacp);
1208
1209	/* determine port types */
1210	usb_ac_map_termtype_to_port(uacp, USB_AUDIO_PLAY);
1211	usb_ac_map_termtype_to_port(uacp, USB_AUDIO_RECORD);
1212
1213
1214	return (rval);
1215}
1216
1217
1218/*
1219 * usb_ac_setup_connections:
1220 *	build a matrix reflecting all connections
1221 */
1222static void
1223usb_ac_setup_connections(usb_ac_state_t *uacp)
1224{
1225	usb_ac_unit_list_t	*units = uacp->usb_ac_units;
1226	uchar_t			*a, **p, i, unit;
1227	size_t			a_len, p_len;
1228
1229	/* allocate array for unit types for quick reference */
1230	uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit,
1231	    KM_SLEEP);
1232	/* allocate array for traversal path */
1233	uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit,
1234	    KM_SLEEP);
1235
1236
1237	/* allocate the connection matrix and set it up */
1238	a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit;
1239	p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *);
1240
1241	/* trick to create a 2 dimensional array */
1242	a = kmem_zalloc(a_len, KM_SLEEP);
1243	p = kmem_zalloc(p_len, KM_SLEEP);
1244	for (i = 0; i < uacp->usb_ac_max_unit; i++) {
1245		p[i] = a + i * uacp->usb_ac_max_unit;
1246	}
1247	uacp->usb_ac_connections = p;
1248	uacp->usb_ac_connections_len = p_len;
1249	uacp->usb_ac_connections_a = a;
1250	uacp->usb_ac_connections_a_len = a_len;
1251
1252	/* traverse all units and set connections */
1253	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1254
1255		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1256		    "--------traversing unit=0x%x type=0x%x--------",
1257		    unit, units[unit].acu_type);
1258
1259		/* store type in the first unused column */
1260		uacp->usb_ac_unit_type[unit] = units[unit].acu_type;
1261
1262		/* save the Unit ID in the unit it points to */
1263		switch (units[unit].acu_type) {
1264		case USB_AUDIO_FEATURE_UNIT:
1265		{
1266			usb_audio_feature_unit_descr1_t *d =
1267			    units[unit].acu_descriptor;
1268
1269			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1270			    "USB_AUDIO_FEATURE_UNIT:sourceID=0x%x type=0x%x",
1271			    d->bSourceID, units[d->bSourceID].acu_type);
1272
1273			if (d->bSourceID != 0) {
1274				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1275				p[unit][d->bSourceID] = B_TRUE;
1276			}
1277
1278			break;
1279		}
1280		case USB_AUDIO_OUTPUT_TERMINAL:
1281		{
1282			usb_audio_output_term_descr_t *d =
1283			    units[unit].acu_descriptor;
1284
1285			USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1286			    "USB_AUDIO_OUTPUT_TERMINAL:sourceID=0x%x type=0x%x",
1287			    d->bSourceID, units[d->bSourceID].acu_type);
1288
1289			if (d->bSourceID != 0) {
1290				ASSERT(p[unit][d->bSourceID] == B_FALSE);
1291				p[unit][d->bSourceID] = B_TRUE;
1292			}
1293
1294			break;
1295		}
1296		case USB_AUDIO_MIXER_UNIT:
1297		{
1298			usb_audio_mixer_unit_descr1_t *d =
1299			    units[unit].acu_descriptor;
1300			int n_sourceID = d->bNrInPins;
1301			int id;
1302
1303			for (id = 0; id < n_sourceID; id++) {
1304				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1305				    uacp->usb_ac_log_handle,
1306				    "USB_AUDIO_MIXER_UNIT:sourceID=0x%x"
1307				    "type=0x%x c=%d",
1308				    d->baSourceID[id],
1309				    units[d->baSourceID[id]].acu_type,
1310				    p[unit][d->baSourceID[id]]);
1311
1312				if (d->baSourceID[id] != 0) {
1313					ASSERT(p[unit][d->baSourceID[id]] ==
1314					    B_FALSE);
1315					p[unit][d->baSourceID[id]] = B_TRUE;
1316				}
1317			}
1318
1319			break;
1320		}
1321		case USB_AUDIO_SELECTOR_UNIT:
1322		{
1323			usb_audio_selector_unit_descr1_t *d =
1324			    units[unit].acu_descriptor;
1325			int n_sourceID = d->bNrInPins;
1326			int id;
1327
1328			for (id = 0; id < n_sourceID; id++) {
1329				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1330				    uacp->usb_ac_log_handle,
1331				    "USB_AUDIO_SELECTOR_UNIT:sourceID=0x%x"
1332				    " type=0x%x", d->baSourceID[id],
1333				    units[d->baSourceID[id]].acu_type);
1334
1335				if (d->baSourceID[id] != 0) {
1336					ASSERT(p[unit][d->baSourceID[id]] ==
1337					    B_FALSE);
1338					p[unit][d->baSourceID[id]] = B_TRUE;
1339				}
1340			}
1341
1342			break;
1343		}
1344		case USB_AUDIO_PROCESSING_UNIT:
1345		{
1346			usb_audio_mixer_unit_descr1_t *d =
1347			    units[unit].acu_descriptor;
1348			int n_sourceID = d->bNrInPins;
1349			int id;
1350
1351			for (id = 0; id < n_sourceID; id++) {
1352				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1353				    uacp->usb_ac_log_handle,
1354				    "USB_AUDIO_PROCESSING_UNIT:sourceID=0x%x"
1355				    " type=0x%x", d->baSourceID[id],
1356				    units[d->baSourceID[id]].acu_type);
1357
1358				if (d->baSourceID[id] != 0) {
1359					ASSERT(p[unit][d->baSourceID[id]] ==
1360					    B_FALSE);
1361					p[unit][d->baSourceID[id]] = B_TRUE;
1362				}
1363			}
1364
1365			break;
1366		}
1367		case USB_AUDIO_EXTENSION_UNIT:
1368		{
1369			usb_audio_extension_unit_descr1_t *d =
1370			    units[unit].acu_descriptor;
1371			int n_sourceID = d->bNrInPins;
1372			int id;
1373
1374			for (id = 0; id < n_sourceID; id++) {
1375				USB_DPRINTF_L3(PRINT_MASK_ATTA,
1376				    uacp->usb_ac_log_handle,
1377				    "USB_AUDIO_EXTENSION_UNIT:sourceID=0x%x"
1378				    "type=0x%x", d->baSourceID[id],
1379				    units[d->baSourceID[id]].acu_type);
1380
1381				if (d->baSourceID[id] != 0) {
1382					ASSERT(p[unit][d->baSourceID[id]] ==
1383					    B_TRUE);
1384					p[unit][d->baSourceID[id]] = B_FALSE;
1385				}
1386			}
1387
1388			break;
1389		}
1390		case USB_AUDIO_INPUT_TERMINAL:
1391
1392			break;
1393		default:
1394			/*
1395			 * Ignore the rest because they are not support yet
1396			 */
1397			break;
1398		}
1399	}
1400
1401#ifdef DEBUG
1402	/* display topology in log buffer */
1403{
1404	uint_t i, j, l;
1405	char *buf;
1406
1407	l = uacp->usb_ac_max_unit * 5;
1408
1409	buf = kmem_alloc(l, KM_SLEEP);
1410
1411	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1412	    "unit types:");
1413
1414	/* two	strings so they won't be replaced accidentily by tab */
1415	(void) sprintf(&buf[0], "    ""    ");
1416	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1417		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1418	}
1419	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1420
1421	(void) sprintf(&buf[0], "  +-------");
1422	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1423		(void) sprintf(&buf[5+((i-1)*3)], "---");
1424	}
1425	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1426
1427	(void) sprintf(&buf[0], "    ""    ");
1428	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1429		(void) sprintf(&buf[2 + (i*3)], "%02d ",
1430		    uacp->usb_ac_unit_type[i]);
1431	}
1432	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1433	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " ");
1434
1435	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1436	    "adjacency matrix:");
1437	(void) sprintf(&buf[0], "    ""    ");
1438	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1439		(void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1440	}
1441	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1442
1443	(void) sprintf(&buf[0], "  +-------");
1444	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1445		(void) sprintf(&buf[5+((i-1)*3)], "---");
1446	}
1447	USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1448
1449	for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1450		(void) sprintf(&buf[0], "%02d| "" ", i);
1451		for (j = 1; j < uacp->usb_ac_max_unit; j++) {
1452			(void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]);
1453		}
1454		USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1455	}
1456	kmem_free(buf, l);
1457}
1458#endif
1459}
1460
1461
1462/*
1463 * usb_ac_add_unit_descriptor:
1464 *	take the parsed descriptor in the buffer and store it in the ID unit
1465 *	array. we grow the unit array if the ID exceeds the current max
1466 */
1467static void
1468usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
1469	size_t buflen)
1470{
1471	void	*descr;
1472	int	len;
1473	char	*format;
1474	size_t	size;
1475
1476
1477	/* doubling the length should allow for padding */
1478	len = 2 * buffer[0];
1479	descr = kmem_zalloc(len, KM_SLEEP);
1480
1481	switch (buffer[2]) {
1482	case USB_AUDIO_INPUT_TERMINAL:
1483		format = CS_AC_INPUT_TERM_FORMAT;
1484		size = CS_AC_INPUT_TERM_SIZE;
1485
1486		break;
1487	case USB_AUDIO_OUTPUT_TERMINAL:
1488		format = CS_AC_OUTPUT_TERM_FORMAT;
1489		size = CS_AC_OUTPUT_TERM_SIZE;
1490
1491		break;
1492	case USB_AUDIO_MIXER_UNIT:
1493		format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c";
1494		size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1;
1495
1496		break;
1497	case USB_AUDIO_SELECTOR_UNIT:
1498		format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c";
1499		size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1;
1500
1501		break;
1502	case USB_AUDIO_FEATURE_UNIT:
1503		format = CS_AC_FEATURE_UNIT_FORMAT "255c";
1504		size = CS_AC_FEATURE_UNIT_SIZE;
1505
1506		break;
1507	case USB_AUDIO_PROCESSING_UNIT:
1508		format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c";
1509		size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1;
1510
1511		break;
1512	case USB_AUDIO_EXTENSION_UNIT:
1513		format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c";
1514		size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1;
1515
1516		break;
1517	default:
1518		USB_DPRINTF_L2(PRINT_MASK_ATTA,
1519		    uacp->usb_ac_log_handle,
1520		    "unsupported descriptor %d", buffer[2]);
1521
1522		/* ignore this descriptor */
1523		kmem_free(descr, len);
1524
1525		return;
1526	}
1527
1528	if (usb_parse_data(format, buffer, buflen, descr, len) < size) {
1529		/* ignore this descriptor */
1530		kmem_free(descr, len);
1531
1532		return;
1533	}
1534
1535	switch (buffer[2]) {
1536	case USB_AUDIO_INPUT_TERMINAL:
1537	{
1538		usb_audio_input_term_descr_t *d =
1539		    (usb_audio_input_term_descr_t *)descr;
1540
1541		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1542		    uacp->usb_ac_log_handle,
1543		    "usb_ac_units[%d] ---input term: type=0x%x sub=0x%x"
1544		    "termid=0x%x\n\t"
1545		    "termtype=0x%x assoc=0x%x #ch=%d "
1546		    "chconf=0x%x ich=0x%x iterm=0x%x",
1547		    d->bTerminalID,
1548		    d->bDescriptorType, d->bDescriptorSubType,
1549		    d->bTerminalID, d->wTerminalType,
1550		    d->bAssocTerminal, d->bNrChannels,
1551		    d->wChannelConfig, d->iChannelNames,
1552		    d->iTerminal);
1553
1554		usb_ac_alloc_unit(uacp, d->bTerminalID);
1555		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1556		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1557		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1558
1559		break;
1560	}
1561	case USB_AUDIO_OUTPUT_TERMINAL:
1562	{
1563		usb_audio_output_term_descr_t *d =
1564		    (usb_audio_output_term_descr_t *)descr;
1565
1566		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1567		    uacp->usb_ac_log_handle,
1568		    "usb_ac_units[%d] ---output term: type=0x%x sub=0x%x"
1569		    " termid=0x%x\n\t"
1570		    "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
1571		    d->bTerminalID,
1572		    d->bDescriptorType, d->bDescriptorSubType,
1573		    d->bTerminalID, d->wTerminalType,
1574		    d->bAssocTerminal, d->bSourceID,
1575		    d->iTerminal);
1576
1577		usb_ac_alloc_unit(uacp, d->bTerminalID);
1578		uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1579		uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1580		uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1581
1582		break;
1583	}
1584	case USB_AUDIO_MIXER_UNIT:
1585	{
1586		usb_audio_mixer_unit_descr1_t *d =
1587		    (usb_audio_mixer_unit_descr1_t *)descr;
1588
1589		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1590		    uacp->usb_ac_log_handle,
1591		    "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1592		    " unitid=0x%x\n\t"
1593		    "#pins=0x%x sourceid[0]=0x%x",
1594		    d->bUnitID,
1595		    d->bDescriptorType, d->bDescriptorSubType,
1596		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1597		usb_ac_alloc_unit(uacp, d->bUnitID);
1598		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1599		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1600		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1601
1602		break;
1603	}
1604	case USB_AUDIO_SELECTOR_UNIT:
1605	{
1606		usb_audio_selector_unit_descr1_t *d =
1607		    (usb_audio_selector_unit_descr1_t *)descr;
1608
1609		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1610		    uacp->usb_ac_log_handle,
1611		    "usb_ac_units[%d] ---selector unit: type=0x%x sub=0x%x"
1612		    " unitid=0x%x\n\t"
1613		    "#pins=0x%x sourceid[0]=0x%x",
1614		    d->bUnitID,
1615		    d->bDescriptorType, d->bDescriptorSubType,
1616		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1617		usb_ac_alloc_unit(uacp, d->bUnitID);
1618		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1619		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1620		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1621
1622		break;
1623	}
1624	case USB_AUDIO_FEATURE_UNIT:
1625	{
1626		usb_audio_feature_unit_descr1_t *d =
1627		    (usb_audio_feature_unit_descr1_t *)descr;
1628
1629		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1630		    uacp->usb_ac_log_handle,
1631		    "usb_ac_units[%d] ---feature unit: type=0x%x sub=0x%x"
1632		    " unitid=0x%x\n\t"
1633		    "sourceid=0x%x size=0x%x",
1634		    d->bUnitID,
1635		    d->bDescriptorType, d->bDescriptorSubType,
1636		    d->bUnitID, d->bSourceID, d->bControlSize);
1637
1638		usb_ac_alloc_unit(uacp, d->bUnitID);
1639		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1640		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1641		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1642
1643		break;
1644	}
1645	case USB_AUDIO_PROCESSING_UNIT:
1646	{
1647		usb_audio_processing_unit_descr1_t *d =
1648		    (usb_audio_processing_unit_descr1_t *)descr;
1649
1650		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1651		    uacp->usb_ac_log_handle,
1652		    "usb_ac_units[%d] ---processing unit: type=0x%x sub=0x%x"
1653		    " unitid=0x%x\n\t"
1654		    "#pins=0x%x sourceid[0]=0x%x",
1655		    d->bUnitID,
1656		    d->bDescriptorType, d->bDescriptorSubType,
1657		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1658		usb_ac_alloc_unit(uacp, d->bUnitID);
1659		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1660		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1661		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1662
1663		break;
1664	}
1665	case USB_AUDIO_EXTENSION_UNIT:
1666	{
1667		usb_audio_extension_unit_descr1_t *d =
1668		    (usb_audio_extension_unit_descr1_t *)descr;
1669
1670		USB_DPRINTF_L3(PRINT_MASK_ATTA,
1671		    uacp->usb_ac_log_handle,
1672		    "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1673		    " unitid=0x%x\n\t"
1674		    "#pins=0x%x sourceid[0]=0x%x",
1675		    d->bUnitID,
1676		    d->bDescriptorType, d->bDescriptorSubType,
1677		    d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1678		usb_ac_alloc_unit(uacp, d->bUnitID);
1679		uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1680		uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1681		uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1682
1683		break;
1684	}
1685	default:
1686		break;
1687	}
1688}
1689
1690
1691/*
1692 * usb_ac_alloc_unit:
1693 *	check if the unit ID is less than max_unit in which case no
1694 *	extra entries are needed. If more entries are needed, copy over
1695 *	the existing array into a new larger array
1696 */
1697static void
1698usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
1699{
1700	usb_ac_unit_list_t *old = NULL;
1701	uint_t	max_unit;
1702
1703
1704	if (uacp->usb_ac_units) {
1705		if (unit < uacp->usb_ac_max_unit) {
1706			/* existing array is big enough */
1707
1708			return;
1709		}
1710		old = uacp->usb_ac_units;
1711		max_unit = uacp->usb_ac_max_unit;
1712	}
1713
1714	/* allocate two extra ones */
1715	unit += 2;
1716	uacp->usb_ac_max_unit = unit;
1717	uacp->usb_ac_units = kmem_zalloc(unit *
1718	    sizeof (usb_ac_unit_list_t), KM_SLEEP);
1719
1720	if (old) {
1721		size_t len = max_unit * sizeof (usb_ac_unit_list_t);
1722		bcopy(old, uacp->usb_ac_units, len);
1723
1724		kmem_free(old, len);
1725	}
1726}
1727
1728
1729/*
1730 * usb_ac_free_all_units:
1731 *	free the entire unit list
1732 */
1733static void
1734usb_ac_free_all_units(usb_ac_state_t *uacp)
1735{
1736	uint_t	unit;
1737	usb_ac_unit_list_t *unitp;
1738
1739	if (uacp->usb_ac_units == NULL) {
1740
1741		return;
1742	}
1743
1744
1745	for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1746		unitp = &uacp->usb_ac_units[unit];
1747		if (unitp) {
1748			if (unitp->acu_descriptor) {
1749				kmem_free(unitp->acu_descriptor,
1750				    unitp->acu_descr_length);
1751			}
1752		}
1753	}
1754
1755	kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit *
1756	    sizeof (usb_ac_unit_list_t));
1757}
1758
1759
1760/*
1761 * usb_ac_lookup_port_type:
1762 *	map term type to port type
1763 *	default just return LINE_IN + LINE_OUT
1764 */
1765static int
1766usb_ac_lookup_port_type(ushort_t termtype)
1767{
1768	uint_t i;
1769
1770	/*
1771	 * Looking for a input/ouput terminal type to match the port
1772	 * type, it should not be common streaming type
1773	 */
1774	ASSERT(termtype != USB_AUDIO_TERM_TYPE_STREAMING);
1775
1776	for (i = 0; ; i++) {
1777		if (usb_ac_term_type_map[i].term_type == 0) {
1778
1779			break;
1780		}
1781
1782		if (usb_ac_term_type_map[i].term_type == termtype) {
1783
1784			return (usb_ac_term_type_map[i].port_type);
1785		}
1786	}
1787
1788	return (USB_PORT_UNKNOWN);
1789}
1790
1791
1792/*
1793 * usb_ac_update_port:
1794 *	called for each terminal
1795 */
1796/*ARGSUSED*/
1797static int
1798usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
1799    uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1800{
1801	if (dir & USB_AUDIO_PLAY) {
1802		usb_audio_output_term_descr_t *d =
1803		    (usb_audio_output_term_descr_t *)
1804		    uacp->usb_ac_units[id].acu_descriptor;
1805		uint_t port_type =
1806		    usb_ac_lookup_port_type(d->wTerminalType);
1807
1808		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1809		    "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
1810		    dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1811
1812		uacp->usb_ac_output_ports |= (1U << port_type);
1813	} else {
1814		usb_audio_input_term_descr_t *d =
1815		    (usb_audio_input_term_descr_t *)
1816		    uacp->usb_ac_units[id].acu_descriptor;
1817		uint_t port_type =
1818		    usb_ac_lookup_port_type(d->wTerminalType);
1819
1820		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1821		    "usb_ac_update_port: dir=%d wTerminalType=0x%x,  name=%s",
1822		    dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1823
1824		uacp->usb_ac_input_ports |= (1U << port_type);
1825
1826	}
1827
1828	return (USB_SUCCESS);
1829}
1830
1831
1832/*
1833 * usb_ac_map_termtype_to_port:
1834 *	starting from a streaming termtype find all
1835 *	input or output terminals and OR into uacp->usb_ac_input_ports
1836 *	or uacp->usb_ac_output_ports;
1837 */
1838static void
1839usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
1840{
1841	uint_t count = 0;
1842	uint_t depth = 0;
1843	uint_t search_type = (dir & USB_AUDIO_PLAY) ?
1844	    USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
1845
1846
1847	(void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
1848	    0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
1849
1850	ASSERT(depth == 0);
1851}
1852
1853
1854/*
1855 * usb_ac_set_port:
1856 *	find a selector port (record side only) and set the
1857 *	input to the matching pin
1858 */
1859static uint_t
1860usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
1861{
1862	uint_t count = 0;
1863	uint_t id;
1864	uint_t depth = 0;
1865
1866
1867	/* we only support the selector for the record side */
1868	if (dir & USB_AUDIO_RECORD) {
1869		id = usb_ac_traverse_all_units(uacp, dir,
1870		    USB_AUDIO_SELECTOR_UNIT, 0,
1871		    0, USB_AC_FIND_ONE, &count, port, &depth,
1872		    usb_ac_set_selector);
1873
1874		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1875		    "usb_ac_set_port: id=%d count=%d port=%d",
1876		    id, count, port);
1877
1878		ASSERT(depth == 0);
1879	}
1880
1881	return (USB_SUCCESS);
1882}
1883
1884
1885/*
1886 * usb_ac_match_port:
1887 *	given the requested port type, find a correspondig term type
1888 *	Called from usb_ac_traverse_all_units()
1889 */
1890/*ARGSUSED*/
1891static int
1892usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
1893    uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1894{
1895	uint_t port_type;
1896
1897
1898	if (dir & USB_AUDIO_PLAY) {
1899		usb_audio_output_term_descr_t *d =
1900		    (usb_audio_output_term_descr_t *)
1901		    uacp->usb_ac_units[id].acu_descriptor;
1902		port_type = usb_ac_lookup_port_type(d->wTerminalType);
1903
1904		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1905		    "usb_ac_match_port: "
1906		    "dir=%d type=0x%x port_type=%d port=%d",
1907		    dir, d->wTerminalType, port_type, arg1);
1908	} else {
1909		usb_audio_output_term_descr_t *d =
1910		    (usb_audio_output_term_descr_t *)
1911		    uacp->usb_ac_units[id].acu_descriptor;
1912		port_type = usb_ac_lookup_port_type(d->wTerminalType);
1913
1914		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1915		    "usb_ac_match_port: "
1916		    "dir=%d type=0x%x port_type=%d port=%d",
1917		    dir, d->wTerminalType, port_type, arg1);
1918	}
1919
1920	return (((1U << port_type) & arg1) ? USB_SUCCESS : USB_FAILURE);
1921}
1922
1923
1924/*
1925 * usb_ac_set_selector:
1926 *	Called from usb_ac_traverse_all_units()
1927 *	Find the correct pin and set selector to this pin
1928 */
1929/*ARGSUSED*/
1930static int
1931usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
1932    uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1933{
1934	uint_t count = 0;
1935	uint_t unit = USB_AC_ID_NONE;
1936	uint_t pin;
1937	uint_t search_target =
1938	    (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
1939	    USB_AUDIO_INPUT_TERMINAL;
1940	usb_audio_selector_unit_descr1_t *d =
1941	    (usb_audio_selector_unit_descr1_t *)
1942	    uacp->usb_ac_units[id].acu_descriptor;
1943	int n_sourceID = d->bNrInPins;
1944	int rval = USB_FAILURE;
1945
1946
1947	/*
1948	 * for each pin, find a term type that matches the
1949	 * requested port type
1950	 */
1951	for (pin = 0; pin < n_sourceID; pin++) {
1952		if (d->baSourceID[pin] == 0) {
1953
1954			break;
1955		}
1956		unit = d->baSourceID[pin];
1957
1958		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1959		    "usb_ac_set_selector: pin=%d unit=%d", pin, unit);
1960
1961		if (uacp->usb_ac_unit_type[unit] == search_target) {
1962			if (usb_ac_match_port(uacp, unit, dir, channel,
1963			    control, arg1, depth) == USB_SUCCESS) {
1964
1965				break;
1966			} else {
1967				unit = USB_AC_ID_NONE;
1968
1969				continue;
1970			}
1971		}
1972
1973		/* find units connected to this unit */
1974		unit = usb_ac_traverse_connections(uacp, unit,
1975		    dir, search_target, channel, control,
1976		    USB_AC_FIND_ONE, &count, arg1, depth,
1977		    usb_ac_match_port);
1978
1979		if (unit != USB_AC_ID_NONE) {
1980
1981			break;
1982		}
1983	}
1984
1985
1986	if (unit != USB_AC_ID_NONE) {
1987		mblk_t		*data;
1988		usb_cr_t	cr;
1989		usb_cb_flags_t	cb_flags;
1990
1991		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1992		    "usb_ac_set_selector: found id=%d at pin %d", unit, pin);
1993
1994		mutex_exit(&uacp->usb_ac_mutex);
1995
1996		data = allocb(1, BPRI_HI);
1997		if (!data) {
1998			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1999			    "usb_ac_set_selector: allocate data failed");
2000			mutex_enter(&uacp->usb_ac_mutex);
2001
2002			return (USB_FAILURE);
2003		}
2004
2005		/* pins are 1-based */
2006		*(data->b_rptr) = (char)++pin;
2007
2008		if (usb_pipe_sync_ctrl_xfer(
2009		    uacp->usb_ac_dip,
2010		    uacp->usb_ac_default_ph,
2011		    USB_DEV_REQ_HOST_TO_DEV |
2012		    USB_DEV_REQ_TYPE_CLASS |
2013		    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
2014		    USB_AUDIO_SET_CUR,		/* bRequest */
2015		    0,				/* wValue */
2016						/* feature unit and id */
2017		    (id << 8)| uacp->usb_ac_ifno, /* wIndex */
2018		    1,				/* wLength */
2019		    &data,
2020		    USB_ATTRS_NONE,
2021		    &cr, &cb_flags,
2022		    USB_FLAGS_SLEEP) == USB_SUCCESS) {
2023			USB_DPRINTF_L3(PRINT_MASK_ALL,
2024			    uacp->usb_ac_log_handle,
2025			    "set current selection: %d", *data->b_rptr);
2026
2027			rval = USB_SUCCESS;
2028		} else {
2029			USB_DPRINTF_L2(PRINT_MASK_ALL,
2030			    uacp->usb_ac_log_handle,
2031			    "set current pin selection failed");
2032		}
2033		freemsg(data);
2034
2035		mutex_enter(&uacp->usb_ac_mutex);
2036	} else {
2037		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2038		    "usb_ac_set_selector: nothing found");
2039	}
2040
2041	return (rval);
2042}
2043
2044
2045/*
2046 * usb_ac_set_control:
2047 *	apply func to all units of search_target type for both the
2048 *	requested channel and master channel
2049 */
2050static uint_t
2051usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
2052	uint_t channel, uint_t control, uint_t all_or_one,
2053	uint_t *count, uint_t arg1,
2054	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2055		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2056{
2057	uint_t id;
2058	uint_t depth = 0;
2059
2060	id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
2061	    control, all_or_one, count, arg1, &depth, func);
2062
2063	if ((channel != 0) &&
2064	    (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) ||
2065	    (all_or_one == USB_AC_FIND_ALL)))  {
2066		/* try master channel */
2067		channel = 0;
2068		id = usb_ac_traverse_all_units(uacp, dir, search_target,
2069		    channel, control, all_or_one, count, arg1,
2070		    &depth, func);
2071	}
2072
2073	ASSERT(depth == 0);
2074
2075	return (id);
2076}
2077
2078
2079/*
2080 * usb_ac_traverse_all_units:
2081 *	traverse all units starting with all IT or OT depending on direction.
2082 *	If no unit is found for the particular channel, try master channel
2083 *	If a matching unit is found, apply the function passed by
2084 *	the caller
2085 */
2086static uint_t
2087usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
2088	uint_t search_target, uint_t channel, uint_t control,
2089	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2090	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2091		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2092{
2093	uint_t unit, start_type, id;
2094
2095	start_type = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
2096	    USB_AUDIO_OUTPUT_TERMINAL;
2097
2098	/* keep track of recursion */
2099	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2100		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2101		    "Unit topology too complex, giving up");
2102
2103		return (USB_AC_ID_NONE);
2104	}
2105
2106	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2107		/* is this an IT or OT? */
2108		if (uacp->usb_ac_unit_type[unit] != start_type) {
2109
2110			continue;
2111		}
2112
2113		/* start at streaming term types */
2114		if (dir & USB_AUDIO_PLAY) {
2115			usb_audio_input_term_descr_t *d =
2116			    uacp->usb_ac_units[unit].acu_descriptor;
2117			if (d->wTerminalType !=
2118			    USB_AUDIO_TERM_TYPE_STREAMING) {
2119
2120				continue;
2121			}
2122		} else {
2123			usb_audio_output_term_descr_t *d =
2124			    uacp->usb_ac_units[unit].acu_descriptor;
2125			if (d->wTerminalType !=
2126			    USB_AUDIO_TERM_TYPE_STREAMING) {
2127
2128				continue;
2129			}
2130		}
2131
2132		/* find units connected to this unit */
2133		id = usb_ac_traverse_connections(uacp, unit, dir,
2134		    search_target, channel, control, all_or_one, count,
2135		    arg1, depth, func);
2136
2137		if ((all_or_one == USB_AC_FIND_ONE) &&
2138		    (id != USB_AC_ID_NONE)) {
2139			unit = id;
2140
2141			break;
2142		}
2143	}
2144
2145	(*depth)--;
2146
2147	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2148}
2149
2150
2151/*
2152 * usb_ac_set_monitor_gain_control:
2153 *	search for a feature unit between output terminal (OT) and
2154 *	input terminal. We are looking for a path between
2155 *	for example a microphone and a speaker through a feature unit
2156 *	and mixer
2157 */
2158static uint_t
2159usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
2160	uint_t search_target, uint_t channel, uint_t control,
2161	uint_t all_or_one, uint_t *count, uint_t arg1,
2162	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2163		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2164{
2165	uint_t unit, id;
2166	uint_t depth = 0;
2167
2168
2169	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2170		usb_audio_output_term_descr_t *d =
2171		    uacp->usb_ac_units[unit].acu_descriptor;
2172
2173		/* is this an OT and not stream type? */
2174		if ((uacp->usb_ac_unit_type[unit] ==
2175		    USB_AUDIO_OUTPUT_TERMINAL) &&
2176		    (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) {
2177
2178			/* find units connected to this unit */
2179			id = usb_ac_traverse_connections(uacp, unit, dir,
2180			    search_target, channel, control, all_or_one, count,
2181			    arg1, &depth, func);
2182
2183			if ((all_or_one == USB_AC_FIND_ONE) &&
2184			    (id != USB_AC_ID_NONE)) {
2185
2186				break;
2187			}
2188		}
2189	}
2190
2191	ASSERT(depth == 0);
2192
2193	return (id);
2194}
2195
2196
2197/*
2198 * usb_ac_push/pop_unit
2199 *	add/remove unit ID to the traverse path
2200 */
2201static void
2202usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
2203{
2204	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] =
2205	    (uchar_t)unit;
2206	ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
2207}
2208
2209
2210/* ARGSUSED */
2211static void
2212usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
2213{
2214	uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
2215}
2216
2217
2218/*
2219 * usb_ac_show_traverse_path:
2220 *	display entire path, just for debugging
2221 */
2222static void
2223usb_ac_show_traverse_path(usb_ac_state_t *uacp)
2224{
2225	int i;
2226
2227	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2228		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2229		    "traverse path %d: unit=%d type=%d",
2230		    i, uacp->usb_ac_traverse_path[i],
2231		    uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]);
2232	}
2233}
2234
2235
2236/*
2237 * usb_ac_check_path:
2238 *	check for a specified type in the traverse path
2239 */
2240static int
2241usb_ac_check_path(usb_ac_state_t *uacp, uint_t type)
2242{
2243	int i;
2244
2245	for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2246		uint_t unit = uacp->usb_ac_traverse_path[i];
2247
2248		if (uacp->usb_ac_unit_type[unit] == type) {
2249
2250			return (USB_SUCCESS);
2251		}
2252	}
2253
2254	return (USB_FAILURE);
2255}
2256
2257
2258/*
2259 * usb_ac_traverse_connections:
2260 *	traverse all units and for each unit with the right type, call
2261 *	func. If the func returns a success and search == USB_AC_FIND_ONE,
2262 *	we are done. If all is set then we continue until we terminate
2263 *	and input or output terminal.
2264 *	For audio play, we traverse columns starting from an input terminal
2265 *	to an output terminal while for record we traverse rows from output
2266 *	terminal to input terminal.
2267 */
2268static uint_t
2269usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
2270	uint_t search_target, uint_t channel, uint_t control,
2271	uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2272	int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2273		uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2274{
2275	uint_t unit, id;
2276	uint_t done = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2277	    USB_AUDIO_INPUT_TERMINAL;
2278
2279
2280	/* keep track of recursion depth */
2281	if ((*depth)++ > USB_AC_MAX_DEPTH) {
2282		USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2283		    "Unit topology too complex, giving up");
2284
2285		return (USB_AC_ID_NONE);
2286	}
2287
2288	usb_ac_push_unit_id(uacp, start_unit);
2289
2290	for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2291		uint_t entry = (dir & USB_AUDIO_PLAY) ?
2292		    uacp->usb_ac_connections[unit][start_unit] :
2293		    uacp->usb_ac_connections[start_unit][unit];
2294
2295		if (entry) {
2296			USB_DPRINTF_L3(PRINT_MASK_ALL,
2297			    uacp->usb_ac_log_handle,
2298			    "start=%d unit=%d entry=%d type=%d "
2299			    "done=%d found=%d",
2300			    start_unit, unit, entry, search_target, done,
2301			    uacp->usb_ac_unit_type[unit]);
2302
2303			/* did we find a matching type? */
2304			if (uacp->usb_ac_unit_type[unit] == search_target) {
2305				USB_DPRINTF_L3(PRINT_MASK_ALL,
2306				    uacp->usb_ac_log_handle,
2307				    "match: dir=%d unit=%d type=%d",
2308				    dir, unit, search_target);
2309
2310				/* yes, no apply function to this unit */
2311				if (func(uacp, unit, dir, channel,
2312				    control, arg1, depth) == USB_SUCCESS) {
2313					(*count)++;
2314
2315					USB_DPRINTF_L3(PRINT_MASK_ALL,
2316					    uacp->usb_ac_log_handle,
2317					    "func returned success, "
2318					    "unit=%d all=%d", unit,
2319					    all_or_one);
2320
2321					/* are we done? */
2322					if (all_or_one == USB_AC_FIND_ONE) {
2323
2324						break;
2325					}
2326				}
2327			}
2328
2329			/* did we find the terminating unit */
2330			if (uacp->usb_ac_unit_type[unit] == done) {
2331
2332				continue;
2333			}
2334			id = usb_ac_traverse_connections(uacp, unit, dir,
2335			    search_target, channel, control,
2336			    all_or_one, count, arg1, depth, func);
2337			if ((id != USB_AC_ID_NONE) &&
2338			    (all_or_one == USB_AC_FIND_ONE)) {
2339				unit = id;
2340
2341				break;
2342			}
2343		}
2344	}
2345
2346	(*depth)--;
2347	usb_ac_pop_unit_id(uacp, start_unit);
2348
2349	return	((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2350}
2351
2352
2353/*
2354 * Event Management
2355 *
2356 * usb_ac_disconnect_event_cb:
2357 *	The device has been disconnected. we either wait for
2358 *	detach or a reconnect event.
2359 */
2360static int
2361usb_ac_disconnect_event_cb(dev_info_t *dip)
2362{
2363	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2364	    usb_ac_statep, ddi_get_instance(dip));
2365
2366	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2367	    "usb_ac_disconnect_event_cb:start");
2368
2369	usb_ac_serialize_access(uacp);
2370	mutex_enter(&uacp->usb_ac_mutex);
2371
2372	/* setting to disconnect state will prevent replumbing */
2373	uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2374
2375	if (uacp->usb_ac_busy_count) {
2376		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2377		    "device was disconnected while busy. "
2378		    "Data may have been lost");
2379	}
2380	mutex_exit(&uacp->usb_ac_mutex);
2381
2382	usb_ac_release_access(uacp);
2383	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2384	    "usb_ac_disconnect_event_cb:done");
2385
2386
2387	return (USB_SUCCESS);
2388}
2389
2390
2391/*
2392 * usb_ac_cpr_suspend:
2393 */
2394static int
2395usb_ac_cpr_suspend(dev_info_t *dip)
2396{
2397	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2398	    usb_ac_statep, ddi_get_instance(dip));
2399
2400	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2401	    "usb_ac_cpr_suspend: Begin");
2402
2403	mutex_enter(&uacp->usb_ac_mutex);
2404	uacp->usb_ac_dev_state = USB_DEV_SUSPENDED;
2405	mutex_exit(&uacp->usb_ac_mutex);
2406
2407	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2408	    "usb_ac_cpr_suspend: End");
2409
2410	return (USB_SUCCESS);
2411}
2412
2413
2414
2415/*
2416 * usb_ac_reconnect_event_cb:
2417 *	The device was disconnected but this instance not detached, probably
2418 *	because the device was busy.
2419 *	if the same device, continue with restoring state
2420 *	We should either be in the unplumbed state or the plumbed open
2421 *	state.
2422 */
2423static int
2424usb_ac_reconnect_event_cb(dev_info_t *dip)
2425{
2426	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2427	    usb_ac_statep, ddi_get_instance(dip));
2428
2429	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2430	    "usb_ac_reconnect_event_cb:begain");
2431
2432	mutex_enter(&uacp->usb_ac_mutex);
2433	mutex_exit(&uacp->usb_ac_mutex);
2434
2435	usb_ac_serialize_access(uacp);
2436
2437	/* check the plumbing state */
2438	mutex_enter(&uacp->usb_ac_mutex);
2439	uacp->usb_ac_busy_count++;
2440	if (uacp->usb_ac_plumbing_state ==
2441	    USB_AC_STATE_PLUMBED) {
2442		mutex_exit(&uacp->usb_ac_mutex);
2443		usb_ac_restore_device_state(dip, uacp);
2444		mutex_enter(&uacp->usb_ac_mutex);
2445	}
2446	uacp->usb_ac_busy_count--;
2447
2448	if (uacp->usb_ac_busy_count) {
2449		USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2450		    "busy device has been reconnected");
2451	}
2452
2453	mutex_exit(&uacp->usb_ac_mutex);
2454
2455	usb_ac_release_access(uacp);
2456	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2457	    "usb_ac_reconnect_event_cb:done");
2458
2459	return (USB_SUCCESS);
2460}
2461
2462
2463/*
2464 * usb_ac_cpr_resume:
2465 *	Restore device state
2466 */
2467static void
2468usb_ac_cpr_resume(dev_info_t *dip)
2469{
2470	usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2471	    usb_ac_statep, ddi_get_instance(dip));
2472
2473	USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2474	    "usb_ac_cpr_resume");
2475
2476	usb_ac_serialize_access(uacp);
2477
2478	usb_ac_restore_device_state(dip, uacp);
2479
2480	usb_ac_release_access(uacp);
2481}
2482
2483
2484/*
2485 * usb_ac_restore_device_state:
2486 *	Set original configuration of the device
2487 *	enable wrq - this starts new transactions on the control pipe
2488 */
2489static void
2490usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp)
2491{
2492	usb_ac_power_t	*uacpm;
2493	int	rval;
2494
2495	USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2496	    "usb_ac_restore_device_state:");
2497
2498	usb_ac_pm_busy_component(uacp);
2499	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2500
2501	/* Check if we are talking to the same device */
2502	if (usb_check_same_device(dip, uacp->usb_ac_log_handle,
2503	    USB_LOG_L0, PRINT_MASK_ALL,
2504	    USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
2505		usb_ac_pm_idle_component(uacp);
2506
2507		/* change the device state from suspended to disconnected */
2508		mutex_enter(&uacp->usb_ac_mutex);
2509		uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2510		mutex_exit(&uacp->usb_ac_mutex);
2511
2512		return;
2513	}
2514
2515	mutex_enter(&uacp->usb_ac_mutex);
2516	uacpm = uacp->usb_ac_pm;
2517	if (uacpm) {
2518		if (uacpm->acpm_wakeup_enabled) {
2519			mutex_exit(&uacp->usb_ac_mutex);
2520
2521			if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip,
2522			    USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
2523
2524				USB_DPRINTF_L4(PRINT_MASK_ATTA,
2525				    uacp->usb_ac_log_handle,
2526				    "usb_ac_restore_device_state: "
2527				    "remote wakeup "
2528				    "enable failed, rval=%d", rval);
2529			}
2530
2531			mutex_enter(&uacp->usb_ac_mutex);
2532		}
2533	}
2534
2535	/* prevent unplumbing */
2536	uacp->usb_ac_busy_count++;
2537	uacp->usb_ac_dev_state = USB_DEV_ONLINE;
2538	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) {
2539		(void) usb_ac_restore_audio_state(uacp, 0);
2540	}
2541	uacp->usb_ac_busy_count--;
2542	mutex_exit(&uacp->usb_ac_mutex);
2543	usb_ac_pm_idle_component(uacp);
2544}
2545
2546
2547/*
2548 * usb_ac_am_restore_state
2549 */
2550static void
2551usb_ac_am_restore_state(void *arg)
2552{
2553	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
2554
2555	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2556	    "usb_ac_am_restore_state: Begin");
2557
2558	usb_ac_serialize_access(uacp);
2559
2560	mutex_enter(&uacp->usb_ac_mutex);
2561
2562	if (uacp->usb_ac_plumbing_state ==
2563	    USB_AC_STATE_PLUMBED_RESTORING) {
2564		mutex_exit(&uacp->usb_ac_mutex);
2565
2566		/*
2567		 * allow hid and usb_as to restore themselves
2568		 * (some handshake would have been preferable though)
2569		 */
2570		delay(USB_AC_RESTORE_DELAY);
2571
2572		usb_restore_engine(uacp);
2573
2574		mutex_enter(&uacp->usb_ac_mutex);
2575		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
2576	}
2577
2578	/* allow unplumbing */
2579	uacp->usb_ac_busy_count--;
2580	mutex_exit(&uacp->usb_ac_mutex);
2581
2582	usb_ac_release_access(uacp);
2583
2584	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2585	    "usb_ac_am_restore_state: End");
2586}
2587
2588
2589/*
2590 * usb_ac_restore_audio_state:
2591 */
2592static int
2593usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
2594{
2595	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
2596
2597
2598	switch (uacp->usb_ac_plumbing_state) {
2599	case USB_AC_STATE_PLUMBED:
2600		uacp->usb_ac_plumbing_state =
2601		    USB_AC_STATE_PLUMBED_RESTORING;
2602
2603		break;
2604	case USB_AC_STATE_UNPLUMBED:
2605
2606		return (USB_SUCCESS);
2607	case USB_AC_STATE_PLUMBED_RESTORING:
2608	default:
2609
2610		return (USB_FAILURE);
2611	}
2612
2613	/*
2614	 * increment busy_count again, it will be decremented
2615	 * in usb_ac_am_restore_state
2616	 */
2617	uacp->usb_ac_busy_count++;
2618
2619	if (flag & USB_FLAGS_SLEEP) {
2620		mutex_exit(&uacp->usb_ac_mutex);
2621		usb_ac_am_restore_state((void *)uacp);
2622		mutex_enter(&uacp->usb_ac_mutex);
2623	} else {
2624		mutex_exit(&uacp->usb_ac_mutex);
2625		if (usb_async_req(uacp->usb_ac_dip,
2626		    usb_ac_am_restore_state,
2627		    (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) {
2628
2629			mutex_enter(&uacp->usb_ac_mutex);
2630			uacp->usb_ac_busy_count--;
2631
2632			return (USB_FAILURE);
2633		}
2634		mutex_enter(&uacp->usb_ac_mutex);
2635	}
2636
2637	return (USB_SUCCESS);
2638}
2639
2640
2641/*
2642 * Mixer Callback Management
2643 * NOTE: all mixer callbacks are serialized. we cannot be closed while
2644 *	we are in the middle of a callback. There needs to be a
2645 *	teardown first. We cannot be unplumbed as long as we are
2646 *	still open.
2647 *
2648 * usb_ac_setup:
2649 *	Send setup to usb_as if the first setup
2650 *	Check power is done in usb_ac_send_as_cmd()
2651 */
2652static int
2653usb_ac_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2654{
2655	int	rval = USB_SUCCESS;
2656
2657
2658	mutex_enter(&uacp->usb_ac_mutex);
2659
2660	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2661		mutex_exit(&uacp->usb_ac_mutex);
2662
2663		return (USB_FAILURE);
2664	}
2665	mutex_exit(&uacp->usb_ac_mutex);
2666
2667	usb_ac_serialize_access(uacp);
2668
2669
2670	rval = usb_ac_do_setup(uacp, engine);
2671
2672	usb_ac_release_access(uacp);
2673
2674	return (rval);
2675}
2676
2677
2678/*
2679 * usb_ac_do_setup:
2680 *	Wrapper function for usb_ac_setup which can be called
2681 *	either from audio framework for usb_ac_set_format
2682 */
2683static int
2684usb_ac_do_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2685{
2686	usb_ac_streams_info_t	*streams_infop = NULL;
2687
2688
2689	mutex_enter(&uacp->usb_ac_mutex);
2690
2691
2692	streams_infop = (usb_ac_streams_info_t *)engine->streams;
2693
2694	/*
2695	 * Handle multiple setup calls. Pass the setup call to usb_as only
2696	 * the first time so isoc pipe will be opened only once
2697	 */
2698	if (streams_infop->acs_setup_teardown_count++) {
2699		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2700		    "usb_ac_do_setup: more than one setup, cnt=%d",
2701		    streams_infop->acs_setup_teardown_count);
2702
2703		mutex_exit(&uacp->usb_ac_mutex);
2704
2705		return (USB_SUCCESS);
2706	}
2707
2708	/* Send setup command to usb_as */
2709	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SETUP, 0) !=
2710	    USB_SUCCESS) {
2711		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2712		    "usb_ac_do_setup: failure");
2713
2714		streams_infop->acs_setup_teardown_count--;
2715
2716		mutex_exit(&uacp->usb_ac_mutex);
2717
2718		return (USB_FAILURE);
2719	}
2720
2721	mutex_exit(&uacp->usb_ac_mutex);
2722
2723	return (USB_SUCCESS);
2724}
2725
2726
2727/*
2728 * usb_ac_teardown:
2729 *	Send teardown to usb_as if the last teardown
2730 *	Check power is done in usb_ac_send_as_cmd()
2731 *	NOTE: allow teardown when disconnected
2732 */
2733static void
2734usb_ac_teardown(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2735{
2736
2737	usb_ac_streams_info_t	*streams_infop = NULL;
2738
2739	usb_ac_serialize_access(uacp);
2740
2741
2742	streams_infop = engine->streams;
2743
2744
2745	mutex_enter(&uacp->usb_ac_mutex);
2746
2747
2748
2749	/* There should be at least one matching setup call */
2750	ASSERT(streams_infop->acs_setup_teardown_count);
2751
2752	/*
2753	 * Handle multiple setup/teardown calls. Pass the call to usb_as
2754	 * only this is the last teardown so that isoc pipe is closed
2755	 * only once
2756	 */
2757	if (--(streams_infop->acs_setup_teardown_count)) {
2758		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2759		    "usb_ac_teardown: more than one setup/teardown, "
2760		    "cnt=%d",
2761		    streams_infop->acs_setup_teardown_count);
2762
2763		goto done;
2764	}
2765
2766	/* Send teardown command to usb_as */
2767	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_TEARDOWN,
2768	    (void *)NULL) != USB_SUCCESS) {
2769
2770		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2771		    "usb_ac_teardown: failure");
2772
2773		streams_infop->acs_setup_teardown_count++;
2774
2775
2776		goto done;
2777	}
2778done:
2779
2780	mutex_exit(&uacp->usb_ac_mutex);
2781
2782	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2783	    "usb_ac_teardown: End");
2784	usb_ac_release_access(uacp);
2785}
2786
2787
2788/*
2789 * usb_ac_set_monitor_gain:
2790 *	called for each output terminal which supports
2791 *	from usb_ac_traverse_connections
2792 */
2793static int
2794usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
2795    uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2796{
2797	usb_audio_output_term_descr_t *d =
2798	    uacp->usb_ac_units[unit].acu_descriptor;
2799
2800	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2801	    "usb_ac_set_monitor_gain: ");
2802
2803	/* log how we got here */
2804	usb_ac_push_unit_id(uacp, unit);
2805	usb_ac_show_traverse_path(uacp);
2806	usb_ac_pop_unit_id(uacp, unit);
2807
2808	/* we only care about the ITs connected to real hw inputs */
2809	switch (d->wTerminalType) {
2810	case USB_AUDIO_TERM_TYPE_STREAMING:
2811
2812		return (USB_FAILURE);
2813
2814	case USB_AUDIO_TERM_TYPE_DT_MICROPHONE:
2815	case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE:
2816	case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE:
2817	case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY:
2818	case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY:
2819	default:
2820
2821		break;
2822	}
2823
2824	/*
2825	 * we can only do this if the microphone is mixed into the
2826	 * audio output so look for a mixer first
2827	 */
2828	if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) ==
2829	    USB_SUCCESS) {
2830		int i, id;
2831
2832		/* now look for a feature unit */
2833		for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0;
2834		    i--) {
2835			id = uacp->usb_ac_traverse_path[i];
2836
2837			switch (uacp->usb_ac_unit_type[id]) {
2838			case USB_AUDIO_MIXER_UNIT:
2839
2840				/* the FU should be before the mixer */
2841				return (USB_FAILURE);
2842
2843			case USB_AUDIO_FEATURE_UNIT:
2844				/*
2845				 * now set the volume
2846				 */
2847				if (usb_ac_set_gain(uacp, id, dir, channel,
2848				    control, gain, depth) != USB_SUCCESS) {
2849
2850					/* try master channel */
2851					if (usb_ac_set_gain(uacp, id, dir,
2852					    0, control, gain, depth) !=
2853					    USB_SUCCESS) {
2854
2855						return (USB_FAILURE);
2856					}
2857				}
2858
2859				return (USB_SUCCESS);
2860
2861			default:
2862				continue;
2863			}
2864		}
2865	}
2866
2867	return (USB_FAILURE);
2868}
2869
2870
2871/*
2872 * usb_ac_set_gain is called for each feature unit which supports
2873 * the requested controls from usb_ac_traverse_connections
2874 * we still need to check whether this unit supports the requested
2875 * control.
2876 */
2877static int
2878usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
2879    uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2880{
2881	short max, min, current;
2882
2883	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2884	    "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
2885	    featureID, dir, channel, control, gain);
2886
2887	if (usb_ac_feature_unit_check(uacp, featureID,
2888	    dir, channel, control, gain, depth) != USB_SUCCESS) {
2889
2890		return (USB_FAILURE);
2891	}
2892
2893	if (usb_ac_get_maxmin_volume(uacp, channel,
2894	    USB_AUDIO_GET_MAX, dir, featureID, &max) != USB_SUCCESS) {
2895		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2896		    "usb_ac_set_gain: getting max gain failed");
2897
2898		return (USB_FAILURE);
2899	}
2900
2901	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2902	    "usb_ac_set_gain: channel %d, max=%d", channel, max);
2903
2904	if (usb_ac_get_maxmin_volume(uacp, channel,
2905	    USB_AUDIO_GET_MIN, dir, featureID, &min) != USB_SUCCESS) {
2906		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2907		    "usb_ac_set_gain: getting min gain failed");
2908
2909		return (USB_FAILURE);
2910	}
2911
2912	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2913	    "usb_ac_set_gain: channel=%d, min=%d", channel, min);
2914
2915	if (usb_ac_get_maxmin_volume(uacp, channel,
2916	    USB_AUDIO_GET_CUR, dir, featureID, &current) != USB_SUCCESS) {
2917		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2918		    "usb_ac_set_gain: getting cur gain failed");
2919
2920		return (USB_FAILURE);
2921	}
2922
2923	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2924	    "usb_ac_set_gain: channel=%d, cur=%d", channel, current);
2925
2926	/*
2927	 * Set the gain for a channel. The audio mixer calculates the
2928	 * impact, if any, on the channel's gain.
2929	 *
2930	 *	0 <= gain <= AUDIO_MAX_GAIN
2931	 *
2932	 *	channel #, 0 == left, 1 == right
2933	 */
2934
2935	if (gain == 0) {
2936		gain = USB_AUDIO_VOLUME_SILENCE;
2937	} else {
2938		gain = max - ((max - min) * (AF_MAX_GAIN - gain))/AF_MAX_GAIN;
2939	}
2940
2941	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2942	    "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
2943	    channel, dir, max, min, gain);
2944
2945	if (usb_ac_set_volume(uacp, channel, gain, dir,
2946	    featureID) != USB_SUCCESS) {
2947		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2948		    "usb_ac_set_gain: setting volume failed");
2949
2950		return (USB_FAILURE);
2951	}
2952
2953	/* just curious, read it back, device may round up/down */
2954	if (usb_ac_get_maxmin_volume(uacp, channel,
2955	    USB_AUDIO_GET_CUR, dir, featureID, &current) != USB_SUCCESS) {
2956		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2957		    "usb_ac_set_gain: getting cur gain failed");
2958	}
2959
2960	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2961	    "usb_ac_set_gain done: "
2962	    "id=%d channel=%d, cur=%d gain=%d", featureID, channel,
2963	    (ushort_t)current, (ushort_t)gain);
2964
2965	return (USB_SUCCESS);
2966}
2967
2968
2969/*
2970 * usb_ac_set_format
2971 *	This mixer callback initiates a command to be sent to
2972 *	usb_as to select an alternate with the passed characteristics
2973 *	and also to set the sample frequency.
2974 *	Note that this may be called when a playing is going on in
2975 *	the streaming interface. To handle that, first stop
2976 *	playing/recording, close the pipe by sending a teardown
2977 *	command, send the set_format command down and then reopen
2978 *	the pipe. Note : (1) audio framework will restart play/record
2979 *	after a set_format command. (2) Check power is done in
2980 *	usb_ac_send_as_cmd().
2981 */
2982int
2983usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2984{
2985	usb_ac_streams_info_t	*streams_infop = NULL;
2986	usb_audio_formats_t	format;
2987	int old_setup_teardown_count = 0;
2988
2989	mutex_enter(&uacp->usb_ac_mutex);
2990	streams_infop = (usb_ac_streams_info_t *)engine->streams;
2991
2992	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2993		mutex_exit(&uacp->usb_ac_mutex);
2994
2995		return (USB_FAILURE);
2996	}
2997	mutex_exit(&uacp->usb_ac_mutex);
2998
2999	usb_ac_serialize_access(uacp);
3000	mutex_enter(&uacp->usb_ac_mutex);
3001
3002	bzero(&format, sizeof (usb_audio_formats_t));
3003
3004	/* save format info */
3005	format.fmt_sr		= (uint_t)engine->fmt.sr;
3006	format.fmt_chns	= (uchar_t)engine->fmt.ch;
3007	format.fmt_precision	= (uchar_t)engine->fmt.prec;
3008	format.fmt_encoding	= (uchar_t)engine->fmt.enc;
3009
3010	old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3011
3012	/* isoc pipe not open and playing is not in progress */
3013	if (old_setup_teardown_count) {
3014		streams_infop->acs_setup_teardown_count = 1;
3015
3016		mutex_exit(&uacp->usb_ac_mutex);
3017		usb_ac_release_access(uacp);
3018
3019		usb_ac_stop_play(uacp, engine);
3020		usb_ac_teardown(uacp, engine);
3021
3022		usb_ac_serialize_access(uacp);
3023		mutex_enter(&uacp->usb_ac_mutex);
3024	}
3025
3026	/*
3027	 * Set format for the streaming interface with lower write queue
3028	 * This boils down to set_alternate  interface command in
3029	 * usb_as and the reply mp contains the currently active
3030	 * alternate number that is stored in the as_req structure
3031	 */
3032	if (usb_ac_send_as_cmd(uacp, engine,
3033	    USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
3034		USB_DPRINTF_L2(PRINT_MASK_ALL,
3035		    uacp->usb_ac_log_handle,
3036		    "usb_ac_set_format: failed");
3037		goto fail;
3038
3039	}
3040	int sample =  engine->fmt.sr;
3041
3042	/* Set the sample rate */
3043	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
3044	    &sample) != USB_SUCCESS) {
3045		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3046		    "usb_ac_set_format: setting format failed");
3047		goto fail;
3048
3049	}
3050
3051	mutex_exit(&uacp->usb_ac_mutex);
3052
3053	usb_ac_release_access(uacp);
3054
3055	/* This should block until successful */
3056	if (old_setup_teardown_count) {
3057		(void) usb_ac_setup(uacp, engine);
3058	}
3059
3060	mutex_enter(&uacp->usb_ac_mutex);
3061	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3062	mutex_exit(&uacp->usb_ac_mutex);
3063
3064	return (USB_SUCCESS);
3065fail:
3066	streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3067	mutex_exit(&uacp->usb_ac_mutex);
3068	usb_ac_release_access(uacp);
3069
3070	return (USB_FAILURE);
3071
3072}
3073
3074/*
3075 * usb_ac_start_play
3076 *	Send a start_play command down to usb_as
3077 *	Check power is done in usb_ac_send_as_cmd()
3078 */
3079static int
3080usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3081{
3082	int			samples;
3083	usb_audio_play_req_t	play_req;
3084
3085
3086	mutex_enter(&uacp->usb_ac_mutex);
3087	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3088		mutex_exit(&uacp->usb_ac_mutex);
3089
3090		return (USB_FAILURE);
3091	}
3092	mutex_exit(&uacp->usb_ac_mutex);
3093
3094	usb_ac_serialize_access(uacp);
3095
3096	mutex_enter(&uacp->usb_ac_mutex);
3097
3098
3099
3100	/* Check for continuous sample rate done in usb_as */
3101	samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
3102	if (samples & engine->fmt.ch) {
3103		samples++;
3104	}
3105
3106	play_req.up_samples = samples;
3107	play_req.up_handle = uacp;
3108
3109	/* Send setup command to usb_as */
3110	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
3111	    (void *)&play_req) != USB_SUCCESS) {
3112
3113		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3114		    "usb_ac_start_play: failure");
3115
3116		mutex_exit(&uacp->usb_ac_mutex);
3117
3118		usb_ac_release_access(uacp);
3119
3120		return (USB_FAILURE);
3121	}
3122
3123	mutex_exit(&uacp->usb_ac_mutex);
3124
3125	usb_ac_release_access(uacp);
3126
3127	return (USB_SUCCESS);
3128}
3129
3130
3131/*
3132 * usb_ac_stop_play:
3133 *	Stop the play engine
3134 *	called from mixer framework.
3135 */
3136void
3137usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3138{
3139
3140	if (engine == NULL) {
3141		engine = &(uacp->engines[0]);
3142	}
3143	mutex_enter(&uacp->usb_ac_mutex);
3144	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3145		mutex_exit(&uacp->usb_ac_mutex);
3146
3147		return;
3148	}
3149	mutex_exit(&uacp->usb_ac_mutex);
3150
3151	usb_ac_serialize_access(uacp);
3152	mutex_enter(&uacp->usb_ac_mutex);
3153
3154	/* Send setup command to usb_as */
3155	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
3156	    (void *)NULL) != USB_SUCCESS) {
3157
3158		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3159		    "usb_ac_do_pause_play: failure");
3160	}
3161
3162	mutex_exit(&uacp->usb_ac_mutex);
3163	usb_ac_release_access(uacp);
3164}
3165
3166
3167/*
3168 * usb_ac_start_record:
3169 *	Sends a start record command down to usb_as.
3170 *	Check power is done in usb_ac_send_as_cmd()
3171 */
3172static int
3173usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3174{
3175
3176
3177	mutex_enter(&uacp->usb_ac_mutex);
3178	if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3179		mutex_exit(&uacp->usb_ac_mutex);
3180
3181		return (USB_FAILURE);
3182	}
3183	mutex_exit(&uacp->usb_ac_mutex);
3184
3185	usb_ac_serialize_access(uacp);
3186	mutex_enter(&uacp->usb_ac_mutex);
3187
3188
3189	/* Send setup command to usb_as */
3190	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
3191	    (void *)uacp) != USB_SUCCESS) {
3192
3193		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3194		    "usb_ac_start_record: failure");
3195
3196		mutex_exit(&uacp->usb_ac_mutex);
3197
3198		usb_ac_release_access(uacp);
3199
3200		return (USB_FAILURE);
3201	}
3202
3203	mutex_exit(&uacp->usb_ac_mutex);
3204	usb_ac_release_access(uacp);
3205
3206	return (USB_SUCCESS);
3207}
3208
3209
3210/*
3211 * usb_ac_stop_record:
3212 *	Wrapper function for usb_ac_do_stop_record and is
3213 *	called form mixer framework.
3214 */
3215static void
3216usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3217{
3218
3219	usb_ac_serialize_access(uacp);
3220	mutex_enter(&uacp->usb_ac_mutex);
3221
3222	/* Send setup command to usb_as */
3223	if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
3224	    NULL) != USB_SUCCESS) {
3225
3226		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3227		    "usb_ac_do_stop_record: failure");
3228	}
3229
3230	mutex_exit(&uacp->usb_ac_mutex);
3231	usb_ac_release_access(uacp);
3232}
3233
3234
3235/*
3236 * Helper Functions for Mixer callbacks
3237 *
3238 * usb_ac_get_maxmin_volume:
3239 *	Send USBA command down to get the maximum or minimum gain balance
3240 *	Calculate min or max gain balance and return that. Return
3241 *	USB_FAILURE for failure cases
3242 */
3243/* ARGSUSED */
3244static int
3245usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
3246    int dir, int feature_unitID, short *max_or_minp)
3247{
3248	mblk_t		*data = NULL;
3249	usb_cr_t	cr;
3250	usb_cb_flags_t	cb_flags;
3251
3252
3253	mutex_exit(&uacp->usb_ac_mutex);
3254
3255	if (usb_pipe_sync_ctrl_xfer(
3256	    uacp->usb_ac_dip,
3257	    uacp->usb_ac_default_ph,
3258	    USB_DEV_REQ_DEV_TO_HOST |
3259	    USB_DEV_REQ_TYPE_CLASS |
3260	    USB_DEV_REQ_RCPT_IF,	/* bmRequestType */
3261	    cmd,			/* bRequest */
3262	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3263					/* feature unit and id */
3264	    (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
3265	    2,				/* wLength */
3266	    &data,
3267	    USB_ATTRS_NONE,
3268	    &cr, &cb_flags,
3269	    USB_FLAGS_SLEEP) != USB_SUCCESS) {
3270		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3271		    "usb_ac_get_maxmin_volume: failed, "
3272		    "cr=%d, cb=0x%x cmd=%d, data=0x%p",
3273		    cr, cb_flags, cmd, (void *)data);
3274
3275		freemsg(data);
3276		mutex_enter(&uacp->usb_ac_mutex);
3277
3278		return (USB_FAILURE);
3279	}
3280
3281	mutex_enter(&uacp->usb_ac_mutex);
3282	ASSERT(MBLKL(data) == 2);
3283
3284	*max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr;
3285
3286	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3287	    "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp);
3288
3289	freemsg(data);
3290
3291	return (USB_SUCCESS);
3292}
3293
3294
3295/*
3296 * usb_ac_set_volume:
3297 *	Send USBA command down to set the gain balance
3298 */
3299/* ARGSUSED */
3300static int
3301usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
3302    int feature_unitID)
3303{
3304	mblk_t		*data = NULL;
3305	usb_cr_t	cr;
3306	usb_cb_flags_t	cb_flags;
3307	int		rval = USB_FAILURE;
3308
3309
3310	mutex_exit(&uacp->usb_ac_mutex);
3311
3312	/* Construct the mblk_t from gain for sending to USBA */
3313	data = allocb(4, BPRI_HI);
3314	if (!data) {
3315		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3316		    "usb_ac_set_volume: allocate data failed");
3317		mutex_enter(&uacp->usb_ac_mutex);
3318
3319		return (USB_FAILURE);
3320	}
3321
3322
3323
3324	*(data->b_wptr++) = (char)gain;
3325	*(data->b_wptr++) = (char)(gain >> 8);
3326
3327	if ((rval = usb_pipe_sync_ctrl_xfer(
3328	    uacp->usb_ac_dip,
3329	    uacp->usb_ac_default_ph,
3330	    USB_DEV_REQ_HOST_TO_DEV |
3331	    USB_DEV_REQ_TYPE_CLASS |
3332	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3333	    USB_AUDIO_SET_CUR,			/* bRequest */
3334	    (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3335						/* feature unit and id */
3336	    (feature_unitID << 8) | uacp->usb_ac_ifno,	/* wIndex */
3337	    2,					/* wLength */
3338	    &data, 0,
3339	    &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
3340		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3341		    "usb_ac_set_volume: failed, cr=%d cb=0x%x",
3342		    cr, cb_flags);
3343	}
3344
3345	freemsg(data);
3346	mutex_enter(&uacp->usb_ac_mutex);
3347
3348	return (rval);
3349}
3350
3351
3352/*
3353 * usb_ac_set_mute is called for each unit that supports the
3354 * requested control from usb_ac_traverse_connections
3355 */
3356int
3357usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
3358    uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
3359{
3360	mblk_t		*data;
3361	usb_cr_t	cr;
3362	usb_cb_flags_t	cb_flags;
3363	int		rval = USB_FAILURE;
3364
3365
3366	if (usb_ac_feature_unit_check(uacp, featureID,
3367	    dir, channel, control, 0, depth) != USB_SUCCESS) {
3368
3369		return (USB_FAILURE);
3370	}
3371	mutex_exit(&uacp->usb_ac_mutex);
3372
3373	/* Construct the mblk_t for sending to USBA */
3374	data = allocb(1, BPRI_HI);
3375
3376	if (!data) {
3377		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3378		    "usb_ac_set_mute: allocate data failed");
3379		mutex_enter(&uacp->usb_ac_mutex);
3380
3381		return (USB_FAILURE);
3382	}
3383
3384
3385	*(data->b_wptr++) = (char)muteval;
3386
3387	if ((rval = usb_pipe_sync_ctrl_xfer(
3388	    uacp->usb_ac_dip,
3389	    uacp->usb_ac_default_ph,
3390	    USB_DEV_REQ_HOST_TO_DEV |
3391	    USB_DEV_REQ_TYPE_CLASS |
3392	    USB_DEV_REQ_RCPT_IF,		/* bmRequestType */
3393	    USB_AUDIO_SET_CUR,			/* bRequest */
3394	    (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
3395						/* feature unit and id */
3396	    (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
3397	    1,					/* wLength */
3398	    &data,
3399	    0,					/* attributes */
3400	    &cr, &cb_flags, 0)) != USB_SUCCESS) {
3401
3402		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3403		    "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
3404	}
3405	freemsg(data);
3406
3407	mutex_enter(&uacp->usb_ac_mutex);
3408
3409	return (rval);
3410}
3411
3412
3413/*
3414 * usb_ac_send_as_cmd:
3415 *	Allocate message blk, send a command down to usb_as,
3416 *	wait for the reply and free the message
3417 *
3418 *	although not really needed to raise power if sending to as
3419 *	it seems better to ensure that both interfaces are at full power
3420 */
3421static int
3422usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
3423    int cmd, void *arg)
3424{
3425	usb_ac_streams_info_t *streams_infop;
3426	usb_ac_plumbed_t *plumb_infop;
3427	int		rv;
3428	int		rval;
3429	ldi_handle_t	lh;
3430
3431	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3432	streams_infop = engine->streams;
3433	plumb_infop = streams_infop->acs_plumbed;
3434
3435
3436	lh = plumb_infop->acp_lh;
3437
3438	rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval);
3439	if (rv != 0) {
3440		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3441		    "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv);
3442
3443		return (USB_FAILURE);
3444	}
3445
3446	return (USB_SUCCESS);
3447}
3448
3449
3450/*
3451 * usb_ac_serialize/release_access:
3452 */
3453static void
3454usb_ac_serialize_access(usb_ac_state_t	*uacp)
3455{
3456	(void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3457}
3458
3459static void
3460usb_ac_release_access(usb_ac_state_t *uacp)
3461{
3462	usb_release_access(uacp->usb_ac_ser_acc);
3463}
3464
3465
3466static void
3467usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
3468{
3469	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3470
3471	if (usb_ac_statep->usb_ac_pm != NULL) {
3472		mutex_enter(&usb_ac_statep->usb_ac_mutex);
3473		usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
3474
3475		USB_DPRINTF_L4(PRINT_MASK_PM,
3476		    usb_ac_statep->usb_ac_log_handle,
3477		    "usb_ac_pm_busy_component: %d",
3478		    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3479
3480		mutex_exit(&usb_ac_statep->usb_ac_mutex);
3481
3482		if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
3483		    DDI_SUCCESS) {
3484			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3485			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3486
3487			USB_DPRINTF_L2(PRINT_MASK_PM,
3488			    usb_ac_statep->usb_ac_log_handle,
3489			    "usb_ac_pm_busy_component failed: %d",
3490			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3491
3492			mutex_exit(&usb_ac_statep->usb_ac_mutex);
3493		}
3494	}
3495}
3496
3497
3498static void
3499usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
3500{
3501	ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3502
3503	if (usb_ac_statep->usb_ac_pm != NULL) {
3504		if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
3505		    DDI_SUCCESS) {
3506			mutex_enter(&usb_ac_statep->usb_ac_mutex);
3507			ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
3508			usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3509
3510			USB_DPRINTF_L4(PRINT_MASK_PM,
3511			    usb_ac_statep->usb_ac_log_handle,
3512			    "usb_ac_pm_idle_component: %d",
3513			    usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3514
3515			mutex_exit(&usb_ac_statep->usb_ac_mutex);
3516		}
3517	}
3518}
3519
3520
3521/*
3522 * handle read from plumbed drivers
3523 */
3524static void
3525usb_ac_reader(void *argp)
3526{
3527	usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp;
3528	usb_ac_state_t *uacp = acp->acp_uacp;
3529	ldi_handle_t lh;
3530	mblk_t *mp;
3531	int rv;
3532	timestruc_t tv = {0};
3533
3534	mutex_enter(&uacp->usb_ac_mutex);
3535	lh = acp->acp_lh;
3536	tv.tv_sec = usb_ac_wait_hid;
3537
3538	while (acp->acp_flags & ACP_ENABLED) {
3539		mp = NULL;
3540
3541		mutex_exit(&uacp->usb_ac_mutex);
3542
3543		rv = ldi_getmsg(lh, &mp, &tv);
3544
3545		mutex_enter(&uacp->usb_ac_mutex);
3546
3547		if (rv == ENODEV) {
3548			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3549			    "Device is not availabe");
3550			break;
3551		}
3552
3553
3554		if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0)
3555			rv = usb_ac_read_msg(acp, mp);
3556
3557	}
3558	mutex_exit(&uacp->usb_ac_mutex);
3559}
3560
3561
3562/*
3563 * setup threads to read from the other usb modules that may send unsolicited
3564 * or asynchronous messages, which is only hid currently
3565 */
3566static int
3567usb_ac_plumb(usb_ac_plumbed_t *acp)
3568{
3569	usb_ac_state_t	*uacp = acp->acp_uacp;
3570	dev_info_t	*dip;
3571	dev_info_t	*acp_dip;
3572	int		acp_inst;
3573	char		*acp_name;
3574	char		tq_nm[128];
3575	int		rv = USB_FAILURE;
3576
3577	mutex_enter(&uacp->usb_ac_mutex);
3578
3579	dip = uacp->usb_ac_dip;
3580
3581	acp_dip = acp->acp_dip;
3582	acp_inst = ddi_get_instance(acp_dip);
3583	acp_name = (char *)ddi_driver_name(acp_dip);
3584
3585	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3586	    "usb_ac_plumb:begin");
3587
3588	if (strcmp(acp_name, "hid") != 0) {
3589		rv = USB_SUCCESS;
3590		goto OUT;
3591	}
3592
3593	(void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3594	    ddi_driver_name(acp_dip), acp_inst);
3595
3596	acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3597	if (acp->acp_tqp == NULL)
3598		goto OUT;
3599
3600	if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp,
3601	    DDI_SLEEP) != DDI_SUCCESS)
3602		goto OUT;
3603
3604	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3605	    "usb_ac_plumb: dispatched reader");
3606
3607	rv = USB_SUCCESS;
3608
3609OUT:
3610	mutex_exit(&uacp->usb_ac_mutex);
3611
3612	USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3613	    "usb_ac_plumb: done, rv=%d", rv);
3614
3615	return (rv);
3616}
3617
3618
3619static void
3620usb_ac_mux_plumbing_tq(void *arg)
3621{
3622	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3623
3624	if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS)
3625		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3626		    "usb_ac_mux_plumbing_tq:failed");
3627}
3628
3629
3630static int
3631usb_ac_do_plumbing(usb_ac_state_t *uacp)
3632{
3633	dev_info_t *dip = uacp->usb_ac_dip;
3634	int inst = ddi_get_instance(dip);
3635	char tq_nm[128];
3636	int rv = USB_FAILURE;
3637
3638	(void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3639	    ddi_driver_name(dip), inst);
3640
3641	uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3642	if (uacp->tqp == NULL) {
3643		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3644		    "usb_ac_do_plumbing: ddi_taskq_create failed");
3645		goto OUT;
3646	}
3647
3648	if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp,
3649	    DDI_SLEEP) != DDI_SUCCESS) {
3650		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3651		    "usb_ac_do_plumbing: ddi_taskq_dispatch failed");
3652		goto OUT;
3653	}
3654
3655	rv = USB_SUCCESS;
3656
3657OUT:
3658	return (rv);
3659}
3660
3661
3662
3663static void
3664usb_ac_mux_unplumbing_tq(void *arg)
3665{
3666	usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3667
3668	if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS)
3669		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3670		    "usb_ac_mux_unplumbing:failed");
3671}
3672
3673
3674static int
3675usb_ac_do_unplumbing(usb_ac_state_t *uacp)
3676{
3677	int rv = USB_FAILURE;
3678
3679	if (uacp->tqp == NULL)
3680		return (USB_SUCCESS);
3681
3682	if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq,
3683	    (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) {
3684		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3685		    "usb_ac_do_unplumbing: ddi_taskq_dispatch failed");
3686		goto OUT;
3687	}
3688
3689	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3690	    "usb_ac_do_unplumbing: waiting for unplumb thread");
3691
3692	ddi_taskq_wait(uacp->tqp);
3693	rv = USB_SUCCESS;
3694
3695	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3696	    "usb_ac_do_unplumbing: unplumb thread done");
3697
3698OUT:
3699	if (uacp->tqp != NULL) {
3700		ddi_taskq_destroy(uacp->tqp);
3701		uacp->tqp = NULL;
3702	}
3703	return (rv);
3704}
3705
3706
3707/*
3708 * teardown threads to the other usb modules
3709 * and clear structures as part of unplumbing
3710 */
3711static void
3712usb_ac_unplumb(usb_ac_plumbed_t *acp)
3713{
3714	usb_ac_streams_info_t *streams_infop;
3715	usb_ac_state_t	*uacp = acp->acp_uacp;
3716
3717
3718	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3719	    "usb_ac_unplumb: begin");
3720
3721	if (acp->acp_tqp != NULL) {
3722		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3723		    "usb_ac_unplumb: destroying taskq");
3724
3725		ddi_taskq_destroy(acp->acp_tqp);
3726	}
3727
3728	mutex_enter(&uacp->usb_ac_mutex);
3729
3730	if (acp->acp_driver == USB_AS_PLUMBED) {
3731		/*
3732		 * we bzero the streams info and plumbed structure
3733		 * since there is no guarantee that the next plumbing
3734		 * will be identical
3735		 */
3736		streams_infop = (usb_ac_streams_info_t *)acp->acp_data;
3737
3738		/* bzero the relevant plumbing structure */
3739		bzero(streams_infop, sizeof (usb_ac_streams_info_t));
3740	}
3741	bzero(acp, sizeof (usb_ac_plumbed_t));
3742
3743	mutex_exit(&uacp->usb_ac_mutex);
3744
3745	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3746	    "usb_ac_unplumb: done");
3747}
3748
3749
3750/*ARGSUSED*/
3751static int
3752usb_ac_mux_plumbing(usb_ac_state_t *uacp)
3753{
3754	dev_info_t		*dip;
3755
3756	/* get the usb_ac dip */
3757	dip = uacp->usb_ac_dip;
3758
3759	/* Access to the global variables is synchronized */
3760	mutex_enter(&uacp->usb_ac_mutex);
3761
3762	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3763	    "usb_ac_mux_plumbing:state = %d",
3764	    uacp->usb_ac_plumbing_state);
3765
3766	if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) {
3767		mutex_exit(&uacp->usb_ac_mutex);
3768		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3769		    "usb_ac_mux_plumbing: audio streams driver"
3770		    " already plumbed");
3771
3772		return (USB_SUCCESS);
3773	}
3774
3775	/* usb_as and hid should be attached but double check */
3776	if (usb_ac_online_siblings(uacp) != USB_SUCCESS) {
3777		mutex_exit(&uacp->usb_ac_mutex);
3778		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3779		"usb_ac_mux_plumbing:no audio streams driver plumbed");
3780
3781		return (USB_FAILURE);
3782	}
3783
3784	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3785	    "usb_ac_mux_plumbing: raising power");
3786	mutex_exit(&uacp->usb_ac_mutex);
3787
3788	/* bring the device to full power */
3789	usb_ac_pm_busy_component(uacp);
3790	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3791
3792	/* avoid dips disappearing while we are plumbing */
3793	usb_ac_hold_siblings(uacp);
3794
3795	mutex_enter(&uacp->usb_ac_mutex);
3796
3797	/*
3798	 * walk all siblings and create the usb_ac<->usb_as and
3799	 * usb_ac<->hid streams. return of 0 indicates no or
3800	 * partial/failed plumbing
3801	 */
3802	if (usb_ac_mux_walk_siblings(uacp) == 0) {
3803		/* pretend that we are plumbed so we can unplumb */
3804		uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3805
3806		mutex_exit(&uacp->usb_ac_mutex);
3807
3808		(void) usb_ac_mux_unplumbing(uacp);
3809
3810		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3811		    "usb_ac_mux_plumbing: no audio streams driver plumbed");
3812
3813		usb_ac_rele_siblings(uacp);
3814
3815		usb_ac_pm_idle_component(uacp);
3816
3817		return (USB_FAILURE);
3818	}
3819	uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3820
3821	/* restore state if we have already registered with the mixer */
3822	if (uacp->usb_ac_registered_with_mixer) {
3823		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3824		    "usb_ac_mux_plumbing:already registered with mixer,"
3825		    "restoring state");
3826
3827		(void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP);
3828
3829	} else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) {
3830		mutex_exit(&uacp->usb_ac_mutex);
3831
3832		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3833		    "usb_ac_mux_plumbing: mixer registration failed");
3834
3835		(void) usb_ac_mux_unplumbing(uacp);
3836
3837		usb_ac_rele_siblings(uacp);
3838
3839		usb_ac_pm_idle_component(uacp);
3840
3841		return (USB_FAILURE);
3842	}
3843
3844	mutex_exit(&uacp->usb_ac_mutex);
3845	usb_ac_rele_siblings(uacp);
3846
3847	usb_ac_pm_idle_component(uacp);
3848
3849	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3850	    "usb_ac_mux_plumbing:done");
3851
3852	return (USB_SUCCESS);
3853}
3854
3855
3856static int
3857usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
3858{
3859	usb_ac_plumbed_t	*acp;
3860	ldi_handle_t		lh;
3861	dev_info_t		*acp_dip;
3862	int			inst;
3863	int			i;
3864	dev_t			devt;
3865	minor_t			minor;
3866	int			maxlinked = 0;
3867
3868	mutex_enter(&uacp->usb_ac_mutex);
3869
3870
3871	if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) {
3872		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3873		    "usb_ac_mux_unplumbing: already unplumbed!");
3874		mutex_exit(&uacp->usb_ac_mutex);
3875
3876		return (USB_SUCCESS);
3877	}
3878
3879	/* usb_ac might not have anything plumbed yet */
3880	if (uacp->usb_ac_current_plumbed_index == -1) {
3881		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3882		    "usb_ac_mux_unplumbing: nothing plumbed");
3883		uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3884		mutex_exit(&uacp->usb_ac_mutex);
3885
3886		return (USB_SUCCESS);
3887	}
3888
3889	/* do not allow detach if still busy */
3890	if (uacp->usb_ac_busy_count) {
3891		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3892		    "usb_ac_mux_unplumbing: mux still busy (%d)",
3893		    uacp->usb_ac_busy_count);
3894		mutex_exit(&uacp->usb_ac_mutex);
3895
3896		return (USB_FAILURE);
3897	}
3898
3899	uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3900
3901	/* close ac-as and ac-hid streams */
3902	maxlinked = uacp->usb_ac_current_plumbed_index + 1;
3903	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3904	    "usb_ac_mux_unplumbing: maxlinked = %d",  maxlinked);
3905
3906	for (i = 0; i < maxlinked; i++) {
3907		/*
3908		 * we must save members of usb_ac_plumbed[] before calling
3909		 * usb_ac_unplumb() because it clears the structure
3910		 */
3911		acp = &uacp->usb_ac_plumbed[i];
3912		lh = acp->acp_lh;
3913		acp_dip = acp->acp_dip;
3914		devt = acp->acp_devt;
3915
3916		if (acp_dip == NULL) {
3917			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3918			    "usb_ac_mux_unplumbing: [%d] - skipping",  i);
3919			continue;
3920		}
3921
3922		minor = getminor(devt);
3923		inst = ddi_get_instance(acp_dip);
3924
3925		uacp->usb_ac_current_plumbed_index = i;
3926
3927		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3928		    "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x",  i,
3929		    ddi_driver_name(acp_dip), inst, minor);
3930
3931		if (lh != NULL) {
3932
3933			acp->acp_flags &= ~ACP_ENABLED;
3934
3935			mutex_exit(&uacp->usb_ac_mutex);
3936
3937			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3938			    "usb_ac_mux_unplumbing:[%d] - closing", i);
3939
3940			/*
3941			 * ldi_close will cause panic if ldi_getmsg
3942			 * is not finished. ddi_taskq_destroy will wait
3943			 * for the thread to complete.
3944			 */
3945			usb_ac_unplumb(acp);
3946			(void) ldi_close(lh, FREAD|FWRITE, kcred);
3947
3948
3949			USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3950			    "usb_ac_mux_unplumbing: [%d] - unplumbed", i);
3951
3952			mutex_enter(&uacp->usb_ac_mutex);
3953		}
3954	}
3955
3956	mutex_exit(&uacp->usb_ac_mutex);
3957
3958	/* Wait till all activity in the default pipe has drained */
3959	usb_ac_serialize_access(uacp);
3960	usb_ac_release_access(uacp);
3961
3962	mutex_enter(&uacp->usb_ac_mutex);
3963	uacp->usb_ac_current_plumbed_index = -1;
3964	mutex_exit(&uacp->usb_ac_mutex);
3965
3966	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3967	    "usb_ac_mux_unplumbing: done");
3968
3969	return (USB_SUCCESS);
3970}
3971
3972
3973/*
3974 * walk all siblings and create the ac<->as and ac<->hid streams
3975 */
3976static int
3977usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
3978{
3979	dev_info_t	*pdip;
3980	dev_info_t	*child_dip;
3981	major_t		drv_major;
3982	minor_t		drv_minor;
3983	int		drv_instance;
3984	char		*drv_name;
3985	dev_t		drv_devt;
3986	ldi_handle_t	drv_lh;
3987	ldi_ident_t	li;
3988	int		error;
3989	int		count = 0;
3990
3991	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3992
3993	pdip = ddi_get_parent(uacp->usb_ac_dip);
3994	child_dip = ddi_get_child(pdip);
3995
3996	while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) {
3997		drv_instance = ddi_get_instance(child_dip);
3998		drv_name = (char *)ddi_driver_name(child_dip);
3999
4000		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4001		    "usb_ac_mux_walk_siblings: plumbing %s%d count=%d",
4002		    drv_name, drv_instance, count);
4003
4004		/* ignore own dip */
4005		if (child_dip == uacp->usb_ac_dip) {
4006			child_dip = ddi_get_next_sibling(child_dip);
4007			continue;
4008		}
4009		drv_instance = ddi_get_instance(child_dip);
4010
4011		/* ignore other dip other than usb_as and hid */
4012		if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) {
4013			uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED;
4014			drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance);
4015		} else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) {
4016			uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED;
4017			drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance);
4018		} else {
4019			drv_minor = drv_instance;
4020			uacp->usb_ac_plumbed[count].acp_driver =
4021			    UNKNOWN_PLUMBED;
4022			child_dip = ddi_get_next_sibling(child_dip);
4023
4024			continue;
4025		}
4026
4027		if (!i_ddi_devi_attached(child_dip)) {
4028			child_dip = ddi_get_next_sibling(child_dip);
4029
4030			continue;
4031		}
4032
4033		if (DEVI_IS_DEVICE_REMOVED(child_dip)) {
4034			child_dip = ddi_get_next_sibling(child_dip);
4035
4036			continue;
4037		}
4038
4039		drv_major = ddi_driver_major(child_dip);
4040
4041		uacp->usb_ac_current_plumbed_index = count;
4042
4043		mutex_exit(&uacp->usb_ac_mutex);
4044
4045		drv_devt = makedevice(drv_major, drv_minor);
4046
4047		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4048		    "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)",
4049		    drv_name, drv_instance, drv_major, drv_minor);
4050
4051		error = ldi_ident_from_dip(uacp->usb_ac_dip, &li);
4052		if (error == 0) {
4053			mutex_enter(&uacp->usb_ac_mutex);
4054			uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED;
4055			mutex_exit(&uacp->usb_ac_mutex);
4056
4057			error = ldi_open_by_dev(&drv_devt, OTYP_CHR,
4058			    FREAD|FWRITE, kcred, &drv_lh, li);
4059			ldi_ident_release(li);
4060		}
4061
4062		mutex_enter(&uacp->usb_ac_mutex);
4063		if (error) {
4064			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4065			    "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)"
4066			    " failed error=%d", drv_major, drv_minor, error);
4067
4068			return (0);
4069		}
4070
4071		uacp->usb_ac_plumbed[count].acp_uacp = uacp;
4072		uacp->usb_ac_plumbed[count].acp_devt = drv_devt;
4073		uacp->usb_ac_plumbed[count].acp_lh = drv_lh;
4074		uacp->usb_ac_plumbed[count].acp_dip = child_dip;
4075		uacp->usb_ac_plumbed[count].acp_ifno =
4076		    usb_get_if_number(child_dip);
4077
4078		if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) {
4079			/* get registration data */
4080			if (usb_ac_get_reg_data(uacp, drv_lh, count) !=
4081			    USB_SUCCESS) {
4082
4083				USB_DPRINTF_L3(PRINT_MASK_ALL,
4084				    uacp->usb_ac_log_handle,
4085				    "usb_ac_mux_walk_siblings:"
4086				    "usb_ac_get_reg_data failed on %s%d",
4087				    drv_name, drv_instance);
4088
4089				uacp->usb_ac_plumbed[count].acp_dip = NULL;
4090
4091				return (0);
4092			}
4093		} else if (uacp->usb_ac_plumbed[count].acp_driver ==
4094		    USB_AH_PLUMBED) {
4095			int rval;
4096
4097			USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4098			    "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d",
4099			    drv_name, drv_instance);
4100
4101			mutex_exit(&uacp->usb_ac_mutex);
4102
4103			/* push usb_ah module on top of hid */
4104			error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah",
4105			    FKIOCTL, kcred, &rval);
4106			mutex_enter(&uacp->usb_ac_mutex);
4107
4108			if (error) {
4109				USB_DPRINTF_L2(PRINT_MASK_ALL,
4110				    uacp->usb_ac_log_handle,
4111				    "usb_ac_mux_walk_siblings: ldi_ioctl"
4112				    "I_PUSH failed on %s%d, error=%d",
4113				    drv_name, drv_instance, error);
4114
4115				uacp->usb_ac_plumbed[count].acp_dip = NULL;
4116
4117				/* skip plumbing the hid driver */
4118				child_dip = ddi_get_next_sibling(child_dip);
4119				continue;
4120			}
4121		} else {
4122			/* should not be here */
4123			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4124			    "usb_ac_mux_walk_siblings:- unknown module %s%d",
4125			    drv_name, drv_instance);
4126			count--;
4127
4128			uacp->usb_ac_plumbed[count].acp_dip = NULL;
4129
4130			/* skip plumbing an unknown module */
4131			child_dip = ddi_get_next_sibling(child_dip);
4132			continue;
4133		}
4134
4135		mutex_exit(&uacp->usb_ac_mutex);
4136		error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]);
4137		mutex_enter(&uacp->usb_ac_mutex);
4138
4139		if (error != USB_SUCCESS) {
4140			USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4141			    "usb_ac_mux_walk_siblings: usb_ac_plumb "
4142			    "failed for %s%d", drv_name, drv_instance);
4143
4144			return (0);
4145		}
4146
4147		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4148		    "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x",
4149		    drv_instance, drv_minor);
4150
4151		child_dip = ddi_get_next_sibling(child_dip);
4152		count++;
4153	}
4154
4155	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4156	    "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux",
4157	    count);
4158
4159	return (count);
4160}
4161
4162
4163/*
4164 * Register with mixer only after first plumbing.
4165 * Also do not register if earlier reg data
4166 * couldn't be received from at least one
4167 * streaming interface
4168 */
4169
4170static int
4171usb_ac_mixer_registration(usb_ac_state_t *uacp)
4172{
4173	usb_as_registration_t *asreg;
4174	int		n;
4175
4176	if (uacp->usb_ac_registered_with_mixer) {
4177		return (USB_SUCCESS);
4178	}
4179
4180	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4181		if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4182			break;
4183		}
4184	}
4185
4186	/* Haven't found a streaming interface; fail mixer registration */
4187	if (n > USB_AC_MAX_AS_PLUMBED) {
4188		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4189		"usb_ac_mixer_registration:- no streaming interface found");
4190
4191		return (USB_FAILURE);
4192	}
4193
4194	/*
4195	 * Fill out streaming interface specific stuff
4196	 * Note that we handle only one playing and one recording
4197	 * streaming interface at the most
4198	 */
4199	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4200		int ch, chs, id;
4201
4202		if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) {
4203			continue;
4204		}
4205
4206		asreg = &(uacp->usb_ac_streams[n].acs_streams_reg);
4207		if (asreg->reg_valid == 0) {
4208			continue;
4209		}
4210
4211
4212		chs = asreg->reg_formats[0].fmt_chns;
4213
4214		/* check if any channel supports vol. control for this fmt */
4215		for (ch = 0; ch <= chs; ch++) {
4216			if ((id = usb_ac_get_featureID(uacp,
4217			    asreg->reg_mode, ch,
4218			    USB_AUDIO_VOLUME_CONTROL)) != -1) {
4219				USB_DPRINTF_L3(PRINT_MASK_ALL,
4220				    uacp->usb_ac_log_handle,
4221				    "usb_ac_mixer_registration:n= [%d]"
4222				    "- dir=%d featureID=%d",
4223				    n, asreg->reg_mode, id);
4224
4225				break;
4226			}
4227		}
4228
4229		uacp->usb_ac_streams[n].acs_default_gain =
4230		    (id == USB_AC_ID_NONE) ?  (AF_MAX_GAIN): (AF_MAX_GAIN*3/4);
4231
4232		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4233		    "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d"
4234		    "default_gain=%d id=%d",
4235		    n, asreg->reg_mode, chs,
4236		    uacp->usb_ac_streams[n].acs_default_gain, id);
4237
4238	}
4239
4240	/* the rest */
4241
4242	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4243	    "usb_ac_mixer_registration: calling usb_audio_register");
4244
4245	mutex_exit(&uacp->usb_ac_mutex);
4246
4247	if (usb_audio_register(uacp) != USB_SUCCESS) {
4248		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4249		    "usb_ac_mixer_registration: usb_audio_register failed");
4250
4251		mutex_enter(&uacp->usb_ac_mutex);
4252
4253		return (USB_FAILURE);
4254	}
4255
4256	mutex_enter(&uacp->usb_ac_mutex);
4257
4258	uacp->usb_ac_registered_with_mixer = 1;
4259
4260	return (USB_SUCCESS);
4261}
4262
4263
4264/*
4265 * Get registriations data when driver attach
4266 */
4267static int
4268usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
4269{
4270	int n, error, rval;
4271	usb_as_registration_t *streams_reg;
4272
4273
4274	ASSERT(uacp->usb_ac_registered_with_mixer == 0);
4275
4276	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4277		/*
4278		 * We haven't received registration data
4279		 * from n-th streaming interface in the array
4280		 */
4281		if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4282			break;
4283		}
4284	}
4285
4286	if (n >= USB_AC_MAX_AS_PLUMBED) {
4287		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4288		"More than 2 streaming interfaces (play "
4289		"and/or record) currently not supported");
4290
4291		return (USB_FAILURE);
4292	}
4293
4294	/* take the stream reg struct with the same index */
4295	streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg;
4296
4297	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4298	"usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d",
4299	    (void *)streams_reg, n);
4300
4301	mutex_exit(&uacp->usb_ac_mutex);
4302
4303	if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION,
4304	    (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) {
4305		USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4306		    "usb_ac_get_reg_data: ldi_ioctl failed for"
4307		    "mixer registration error=%d", error);
4308
4309		mutex_enter(&uacp->usb_ac_mutex);
4310
4311		return (USB_FAILURE);
4312	} else {
4313		mutex_enter(&uacp->usb_ac_mutex);
4314
4315		rval = usb_ac_setup_plumbed(uacp, index, n);
4316
4317		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4318		"usb_ac_get_reg_data:usb_ac_streams[%d]: "
4319		    "received_reg_data=%d type=%s",  index,
4320		    uacp->usb_ac_streams[n].acs_rcvd_reg_data,
4321		    ((streams_reg->reg_mode == USB_AUDIO_PLAY) ?
4322		    "play" : "record"));
4323
4324		usb_ac_print_reg_data(uacp, streams_reg);
4325
4326		return (rval);
4327	}
4328}
4329
4330
4331/*
4332 * setup plumbed and stream info structure
4333 */
4334static int
4335usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx)
4336{
4337	uacp->usb_ac_plumbed[plb_idx].acp_data =
4338	    &uacp->usb_ac_streams[str_idx];
4339	uacp->usb_ac_streams[str_idx].acs_plumbed =
4340	    &uacp->usb_ac_plumbed[plb_idx];
4341	uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1;
4342
4343
4344	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4345	    "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ",
4346	    plb_idx, str_idx);
4347
4348	return (USB_SUCCESS);
4349}
4350
4351
4352/*
4353 * function to dump registration data
4354 */
4355static void
4356usb_ac_print_reg_data(usb_ac_state_t *uacp,
4357    usb_as_registration_t *reg)
4358{
4359	int n;
4360
4361	for (n = 0; n < reg->reg_n_formats; n++) {
4362		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4363		    "format%d: alt=%d chns=%d prec=%d enc=%d", n,
4364		    reg->reg_formats[n].fmt_alt,
4365		    reg->reg_formats[n].fmt_chns,
4366		    reg->reg_formats[n].fmt_precision,
4367		    reg->reg_formats[n].fmt_encoding);
4368	}
4369
4370	for (n = 0; n < USB_AS_N_FORMATS; n++) {
4371		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4372		    "reg_formats[%d] ptr=0x%p", n,
4373		    (void *)&reg->reg_formats[n]);
4374	}
4375
4376	for (n = 0; n < USB_AS_N_CHANNELS; n++) {
4377		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4378		    "reg_channels[%d]=%d", n, reg->reg_channels[n]);
4379	}
4380
4381	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4382	    "usb_ac_print_reg_data: End");
4383}
4384
4385
4386static int
4387usb_ac_online_siblings(usb_ac_state_t *uacp)
4388{
4389	dev_info_t	*pdip, *child_dip;
4390	int		rval = USB_SUCCESS;
4391
4392	ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4393
4394	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4395	    "usb_ac_online_siblings:start");
4396
4397	pdip = ddi_get_parent(uacp->usb_ac_dip);
4398
4399	child_dip = ddi_get_child(pdip);
4400	while (child_dip != NULL) {
4401
4402		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4403		    "usb_ac_online_siblings: onlining %s%d ref=%d",
4404		    ddi_driver_name(child_dip),
4405		    ddi_get_instance(child_dip),
4406		    DEVI(child_dip)->devi_ref);
4407
4408		/* Online the child_dip of usb_as and hid,  if not already */
4409		if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) ||
4410		    (strcmp(ddi_driver_name(child_dip), "hid") == 0)) {
4411
4412			mutex_exit(&uacp->usb_ac_mutex);
4413			if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
4414			    NDI_SUCCESS) {
4415				USB_DPRINTF_L3(PRINT_MASK_ALL,
4416				    uacp->usb_ac_log_handle,
4417				    "usb_ac_online_siblings:failed to online"
4418				    "device %s%d", ddi_driver_name(child_dip),
4419				    ddi_get_instance(child_dip));
4420
4421				/* only onlining usb_as is fatal */
4422				if (strcmp(ddi_driver_name(child_dip),
4423				    "usb_as") == 0) {
4424					mutex_enter(&uacp->usb_ac_mutex);
4425					rval = USB_FAILURE;
4426					break;
4427				}
4428			}
4429			mutex_enter(&uacp->usb_ac_mutex);
4430		}
4431		child_dip = ddi_get_next_sibling(child_dip);
4432	}
4433
4434	return (rval);
4435}
4436
4437
4438/*
4439 * hold all audio children before or after plumbing
4440 * online usb_as and hid, if not already
4441 */
4442static void
4443usb_ac_hold_siblings(usb_ac_state_t *uacp)
4444{
4445	int		circ;
4446	dev_info_t	*pdip, *child_dip;
4447
4448	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4449	    "usb_ac_hold_siblings:start");
4450
4451	/* hold all siblings and ourselves */
4452	pdip = ddi_get_parent(uacp->usb_ac_dip);
4453
4454	/* hold the children */
4455	ndi_devi_enter(pdip, &circ);
4456	child_dip = ddi_get_child(pdip);
4457	while (child_dip != NULL) {
4458		ndi_hold_devi(child_dip);
4459
4460		USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4461		    "usb_ac_hold_siblings: held %s%d ref=%d",
4462		    ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4463		    DEVI(child_dip)->devi_ref);
4464
4465		child_dip = ddi_get_next_sibling(child_dip);
4466	}
4467	ndi_devi_exit(pdip, circ);
4468}
4469
4470
4471/*
4472 * release all audio children before or after plumbing
4473 */
4474static void
4475usb_ac_rele_siblings(usb_ac_state_t *uacp)
4476{
4477	int		circ;
4478	dev_info_t	*pdip, *child_dip;
4479
4480	USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4481	    "usb_ac_rele_siblings: start");
4482
4483	/* release all siblings and ourselves */
4484	pdip = ddi_get_parent(uacp->usb_ac_dip);
4485	ndi_devi_enter(pdip, &circ);
4486	child_dip = ddi_get_child(pdip);
4487	while (child_dip != NULL) {
4488		ndi_rele_devi(child_dip);
4489
4490		USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4491		    "usb_ac_rele_siblings: released %s%d ref=%d",
4492		    ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4493		    DEVI(child_dip)->devi_ref);
4494
4495		child_dip = ddi_get_next_sibling(child_dip);
4496	}
4497	ndi_devi_exit(pdip, circ);
4498}
4499static void
4500usb_restore_engine(usb_ac_state_t *statep)
4501{
4502	usb_audio_eng_t *engp;
4503	int i;
4504
4505	for (i = 0; i < USB_AC_ENG_MAX; i++) {
4506
4507		mutex_enter(&statep->usb_ac_mutex);
4508		engp = &statep->engines[i];
4509		mutex_exit(&statep->usb_ac_mutex);
4510
4511		if (engp->af_engp == NULL)
4512			continue;
4513		if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
4514			USB_DPRINTF_L2(PRINT_MASK_ATTA,
4515			    statep->usb_ac_log_handle,
4516			    "usb_restore_engine:set format fail, i=%d", i);
4517			return;
4518		}
4519		if (engp->started) {
4520			(void) usb_engine_start(engp);
4521		}
4522
4523	}
4524
4525	(void) usb_ac_ctrl_restore(statep);
4526}
4527
4528
4529/*
4530 * get the maximum format specification the device supports
4531 */
4532static void
4533usb_ac_max_fmt(usb_as_registration_t *reg_data,
4534    usb_audio_format_t *fmtp)
4535{
4536
4537	uint_t *srs, *chs;
4538	uint_t sr, ch, prec, enc, val;
4539	int i;
4540
4541	usb_audio_formats_t *reg_formats = reg_data->reg_formats;
4542	srs = reg_data->reg_srs;
4543	chs = reg_data->reg_channels;
4544
4545	for (i = 0, sr = 0; srs[i]; i++) {
4546		val = srs[i];
4547		if (val > sr)
4548			sr = val;
4549	}
4550
4551	for (i = 0, ch = 0; chs[i]; i++) {
4552		val = chs[i];
4553		if (val > ch)
4554			ch = val;
4555	}
4556
4557	for (i = 0, prec = 0, enc = 0; i < reg_data->reg_n_formats; i++) {
4558		val = reg_formats[i].fmt_precision;
4559		if (val > prec)
4560			prec = val;
4561
4562		val = reg_formats[i].fmt_encoding;
4563		if (val > enc)
4564			enc = val;
4565	}
4566
4567	fmtp->sr = sr;
4568	fmtp->ch =  ch;
4569	fmtp->prec = prec;
4570	fmtp->enc =  enc;
4571}
4572
4573
4574static void
4575usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
4576{
4577	if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
4578		return;
4579
4580	audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
4581	audio_engine_free(engp->af_engp);
4582
4583	mutex_enter(&engp->lock);
4584	engp->af_engp = NULL;
4585	engp->streams = NULL;
4586	mutex_exit(&engp->lock);
4587
4588	mutex_destroy(&engp->lock);
4589	cv_destroy(&engp->usb_audio_cv);
4590}
4591
4592
4593static int
4594usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t  *asinfo)
4595{
4596	audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
4597	usb_audio_eng_t *engp;
4598	audio_engine_t *af_engp;
4599	int rv = USB_FAILURE;
4600	int dir = asinfo->acs_streams_reg.reg_mode;
4601	uint_t defgain;
4602
4603	if (asinfo->acs_rcvd_reg_data == 0) {
4604
4605		return (USB_SUCCESS);
4606	}
4607	if (dir == USB_AUDIO_PLAY) {
4608		engp = &(uacp->engines[0]);
4609	} else {
4610		engp = &(uacp->engines[1]);
4611	}
4612
4613	cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL);
4614
4615	mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
4616
4617	mutex_enter(&engp->lock);
4618
4619	engp->af_eflags =
4620	    (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
4621	engp->statep = uacp;
4622
4623	/* Set the format for the engine */
4624	usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
4625
4626	/* init the default gain */
4627	defgain = asinfo->acs_default_gain;
4628	if (engp->fmt.ch == 2) {
4629		engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
4630	} else {
4631		engp->af_defgain = defgain;
4632	}
4633	engp->streams = asinfo;
4634
4635	mutex_exit(&engp->lock);
4636
4637	af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
4638	if (af_engp == NULL) {
4639
4640		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4641		    "audio_engine_alloc failed");
4642		goto OUT;
4643	}
4644	ASSERT(engp->af_engp == 0);
4645
4646	mutex_enter(&engp->lock);
4647	engp->af_engp = af_engp;
4648	mutex_exit(&engp->lock);
4649
4650	audio_engine_set_private(af_engp, engp);
4651	audio_dev_add_engine(af_devp, af_engp);
4652
4653	/*
4654	 * Set the format for this engine
4655	 */
4656	if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
4657		USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4658		    "set format failed, dir = %d", dir);
4659		goto OUT;
4660	}
4661	rv = USB_SUCCESS;
4662
4663OUT:
4664	if (rv != USB_SUCCESS)
4665		usb_ac_rem_eng(uacp, engp);
4666
4667	return (rv);
4668}
4669
4670
4671static int
4672usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
4673{
4674	usb_audio_ctrl_t *ctrlp;
4675	int rv = USB_SUCCESS;
4676	USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4677	    "usb_ac_ctrl_set_defaults:begin");
4678
4679	for (int i = 0; i < CTL_NUM; i++) {
4680		ctrlp = statep->controls[i];
4681		if (!ctrlp) {
4682			continue;
4683		}
4684		if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4685			USB_DPRINTF_L2(PRINT_MASK_ATTA,
4686			    statep->usb_ac_log_handle,
4687			    "usb_ac_ctrl_set_defaults:control write failed");
4688			rv = USB_FAILURE;
4689		}
4690
4691	}
4692	USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4693	    "usb_ac_ctrl_set_defaults:end");
4694	return (rv);
4695}
4696
4697
4698static int
4699usb_ac_ctrl_restore(usb_ac_state_t *statep)
4700{
4701	usb_audio_ctrl_t *ctrlp;
4702	int rv = USB_SUCCESS;
4703
4704	for (int i = 0; i < CTL_NUM; i++) {
4705		ctrlp = statep->controls[i];
4706		if (ctrlp) {
4707			USB_DPRINTF_L3(PRINT_MASK_ATTA,
4708			    statep->usb_ac_log_handle,
4709			    "usb_ac_ctrl_restore:i = %d", i);
4710			if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4711				rv = USB_FAILURE;
4712			}
4713		}
4714	}
4715	return (rv);
4716}
4717
4718
4719
4720
4721/*
4722 * moves data between driver buffer and framework/shim buffer
4723 */
4724static void
4725usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
4726{
4727	size_t cpsz = sz;
4728	caddr_t *src, *dst;
4729
4730	if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
4731		src = &engp->bufpos;
4732		dst = (caddr_t *)&buf;
4733	} else {
4734		src = (caddr_t *)&buf;
4735		dst = &engp->bufpos;
4736	}
4737
4738	/*
4739	 * Wrap.  If sz is exactly the remainder of the buffer
4740	 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
4741	 * the second memcpy() should have no effect, with bufpos updated
4742	 * to the head of the buffer.
4743	 */
4744	if (engp->bufpos + sz >= engp->bufendp) {
4745		cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
4746		(void) memcpy(*dst, *src, cpsz);
4747
4748
4749		buf = (caddr_t)buf + cpsz;
4750		engp->bufpos = engp->bufp;
4751		cpsz = sz - cpsz;
4752	}
4753
4754	if (cpsz) {
4755		(void) memcpy(*dst, *src, cpsz);
4756
4757
4758		engp->bufpos += cpsz;
4759	}
4760	engp->bufio_count++;
4761}
4762
4763
4764/*
4765 * control read callback
4766 */
4767static int
4768usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
4769{
4770	usb_audio_ctrl_t *ctrlp = arg;
4771
4772	mutex_enter(&ctrlp->ctrl_mutex);
4773	*cvalp = ctrlp->cval;
4774	mutex_exit(&ctrlp->ctrl_mutex);
4775
4776	return (0);
4777}
4778
4779
4780/*
4781 * stereo level control callback
4782 */
4783static int
4784usb_audio_write_stero_rec(void *arg, uint64_t cval)
4785{
4786	usb_audio_ctrl_t *ctrlp = arg;
4787	usb_ac_state_t *statep = ctrlp->statep;
4788	int rv = EIO;
4789	int left, right;
4790	uint_t count = 0;
4791
4792
4793	left = AUDIO_CTRL_STEREO_LEFT(cval);
4794	right = AUDIO_CTRL_STEREO_RIGHT(cval);
4795
4796	if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4797	    right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4798
4799		return (EINVAL);
4800	}
4801
4802	mutex_enter(&ctrlp->ctrl_mutex);
4803	ctrlp->cval = cval;
4804	mutex_exit(&ctrlp->ctrl_mutex);
4805
4806	mutex_enter(&statep->usb_ac_mutex);
4807	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4808	    USB_AUDIO_FEATURE_UNIT, 1,
4809	    USB_AUDIO_VOLUME_CONTROL,
4810	    USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4811
4812	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4813	    USB_AUDIO_FEATURE_UNIT, 2,
4814	    USB_AUDIO_VOLUME_CONTROL,
4815	    USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4816	rv = 0;
4817
4818done:
4819	mutex_exit(&statep->usb_ac_mutex);
4820	return (rv);
4821}
4822
4823static int
4824usb_audio_write_ster_vol(void *arg, uint64_t cval)
4825{
4826	usb_audio_ctrl_t *ctrlp = arg;
4827	usb_ac_state_t *statep = ctrlp->statep;
4828	int rv = EIO;
4829	int left, right;
4830	uint_t count = 0;
4831
4832	left = AUDIO_CTRL_STEREO_LEFT(cval);
4833	right = AUDIO_CTRL_STEREO_RIGHT(cval);
4834
4835	if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4836	    right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4837		return (EINVAL);
4838	}
4839
4840	mutex_enter(&ctrlp->ctrl_mutex);
4841	ctrlp->cval = cval;
4842	mutex_exit(&ctrlp->ctrl_mutex);
4843
4844
4845	mutex_enter(&statep->usb_ac_mutex);
4846	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4847	    USB_AUDIO_FEATURE_UNIT, 1,
4848	    USB_AUDIO_VOLUME_CONTROL,
4849	    USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4850
4851	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4852	    USB_AUDIO_FEATURE_UNIT, 2,
4853	    USB_AUDIO_VOLUME_CONTROL,
4854	    USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4855	rv = 0;
4856
4857OUT:
4858	mutex_exit(&statep->usb_ac_mutex);
4859	return (rv);
4860}
4861
4862
4863/*
4864 * mono level control callback
4865 */
4866static int
4867usb_audio_write_mono_vol(void *arg, uint64_t cval)
4868{
4869	usb_audio_ctrl_t *ctrlp = arg;
4870	usb_ac_state_t *statep = ctrlp->statep;
4871	int rv = EIO;
4872	int gain;
4873
4874	uint_t count = 0;
4875
4876	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4877		return (EINVAL);
4878	}
4879
4880	mutex_enter(&ctrlp->ctrl_mutex);
4881	ctrlp->cval = cval;
4882	mutex_exit(&ctrlp->ctrl_mutex);
4883
4884	gain = (int)(cval);
4885
4886	mutex_enter(&statep->usb_ac_mutex);
4887	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4888	    USB_AUDIO_FEATURE_UNIT, 1,
4889	    USB_AUDIO_VOLUME_CONTROL,
4890	    USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4891
4892	rv = 0;
4893OUT:
4894	mutex_exit(&statep->usb_ac_mutex);
4895
4896	return (rv);
4897}
4898
4899
4900/*
4901 * mono level control callback
4902 */
4903static int
4904usb_audio_write_monitor_gain(void *arg, uint64_t cval)
4905{
4906	usb_audio_ctrl_t *ctrlp = arg;
4907	usb_ac_state_t *statep = ctrlp->statep;
4908	int rv = EIO;
4909	int gain;
4910	uint_t count = 0;
4911
4912	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4913
4914		return (EINVAL);
4915	}
4916
4917	mutex_enter(&ctrlp->ctrl_mutex);
4918	ctrlp->cval = cval;
4919	mutex_exit(&ctrlp->ctrl_mutex);
4920
4921	gain = (int)(cval);
4922
4923	mutex_enter(&statep->usb_ac_mutex);
4924	(void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
4925	    USB_AUDIO_INPUT_TERMINAL, 1,
4926	    USB_AUDIO_VOLUME_CONTROL,
4927	    USB_AC_FIND_ALL, &count, gain,
4928	    usb_ac_set_monitor_gain);
4929
4930	rv = 0;
4931OUT:
4932	mutex_exit(&statep->usb_ac_mutex);
4933	return (rv);
4934}
4935
4936static int
4937usb_audio_write_mono_rec(void *arg, uint64_t cval)
4938{
4939	usb_audio_ctrl_t *ctrlp = arg;
4940	usb_ac_state_t *statep = ctrlp->statep;
4941	int rv = EIO;
4942	int gain;
4943
4944	uint_t count = 0;
4945
4946	if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4947
4948		return (EINVAL);
4949	}
4950
4951	mutex_enter(&ctrlp->ctrl_mutex);
4952	ctrlp->cval = cval;
4953	mutex_exit(&ctrlp->ctrl_mutex);
4954
4955	gain = (int)(cval);
4956
4957	mutex_enter(&statep->usb_ac_mutex);
4958	(void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4959	    USB_AUDIO_FEATURE_UNIT, 1,
4960	    USB_AUDIO_VOLUME_CONTROL,
4961	    USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4962
4963	rv = 0;
4964
4965	mutex_exit(&statep->usb_ac_mutex);
4966	return (rv);
4967}
4968
4969static int
4970usb_audio_write_mic_boost(void *arg, uint64_t cval)
4971{
4972	usb_audio_ctrl_t *ctrlp = arg;
4973
4974	mutex_enter(&ctrlp->ctrl_mutex);
4975	ctrlp->cval = cval;
4976	mutex_exit(&ctrlp->ctrl_mutex);
4977	/* do nothing here */
4978	return (0);
4979}
4980
4981static int
4982usb_audio_write_rec_src(void *arg, uint64_t cval)
4983{
4984	usb_audio_ctrl_t *ctrlp = arg;
4985	usb_ac_state_t *statep = ctrlp->statep;
4986	int rv = 0;
4987
4988	if (cval & ~(statep->usb_ac_input_ports))
4989		return (EINVAL);
4990
4991	mutex_enter(&ctrlp->ctrl_mutex);
4992	ctrlp->cval = cval;
4993	mutex_exit(&ctrlp->ctrl_mutex);
4994
4995	mutex_enter(&statep->usb_ac_mutex);
4996	if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
4997
4998		USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
4999		    "usb_audio_write_rec_src: failed");
5000		rv = EINVAL;
5001	}
5002	mutex_exit(&statep->usb_ac_mutex);
5003	rv = 0;
5004
5005OUT:
5006	return (rv);
5007
5008}
5009
5010
5011int
5012usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
5013{
5014	short	muteval;
5015	int	rval;
5016
5017	uint_t count;
5018	muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
5019	count = 0;
5020	/* only support AUDIO_PLAY */
5021
5022	mutex_enter(&statep->usb_ac_mutex);
5023	(void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
5024	    USB_AUDIO_FEATURE_UNIT, 0,
5025	    USB_AUDIO_MUTE_CONTROL,
5026	    USB_AC_FIND_ALL, &count, muteval,
5027	    usb_ac_set_mute);
5028	mutex_exit(&statep->usb_ac_mutex);
5029
5030	rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
5031
5032	return (rval);
5033}
5034
5035
5036/*
5037 * port selection control callback
5038 */
5039/*
5040 * audio control registration related routines
5041 */
5042
5043static usb_audio_ctrl_t *
5044usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
5045{
5046	audio_ctrl_desc_t	desc;
5047	audio_ctrl_wr_t		fn;
5048	usb_audio_ctrl_t	*pc;
5049
5050	pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
5051
5052	mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
5053
5054	bzero(&desc, sizeof (desc));
5055
5056	switch (num) {
5057	case CTL_VOLUME_MONO:
5058		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5059		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5060		desc.acd_minvalue = 0;
5061		desc.acd_maxvalue = AF_MAX_GAIN;
5062		desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5063		    | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5064		fn = usb_audio_write_mono_vol;
5065		break;
5066
5067	case CTL_VOLUME_STERO:
5068		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5069		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5070		desc.acd_minvalue = 0;
5071		desc.acd_maxvalue = AF_MAX_GAIN;
5072		desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5073		    | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5074		fn = usb_audio_write_ster_vol;
5075
5076		break;
5077
5078	case CTL_REC_MONO:
5079		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5080		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5081		desc.acd_minvalue = 0;
5082		desc.acd_maxvalue = AF_MAX_GAIN;
5083		desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5084		    | AUDIO_CTRL_FLAG_RW;
5085		fn = usb_audio_write_mono_rec;
5086		break;
5087	case CTL_REC_STERO:
5088
5089		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5090		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5091		desc.acd_minvalue = 0;
5092		desc.acd_maxvalue = AF_MAX_GAIN;
5093		desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5094		    | AUDIO_CTRL_FLAG_RW;
5095		fn = usb_audio_write_stero_rec;
5096		break;
5097
5098	case CTL_MONITOR_GAIN:
5099
5100		desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
5101		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5102		desc.acd_minvalue = 0;
5103		desc.acd_maxvalue = AF_MAX_GAIN;
5104		desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
5105		    |AUDIO_CTRL_FLAG_RW;
5106		fn = usb_audio_write_monitor_gain;
5107		break;
5108
5109	case CTL_MIC_BOOST:
5110
5111		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
5112		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
5113		desc.acd_minvalue = 0;
5114		desc.acd_maxvalue = 1;
5115		desc.acd_flags = AUDIO_CTRL_FLAG_RW;
5116		fn = usb_audio_write_mic_boost;
5117		break;
5118	case CTL_REC_SRC:
5119
5120		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
5121		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
5122		desc.acd_minvalue = statep->usb_ac_input_ports;
5123		desc.acd_maxvalue = statep->usb_ac_input_ports;
5124		desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
5125		for (int i = 0; usb_audio_dtypes[i]; i++) {
5126			desc.acd_enum[i] = usb_audio_dtypes[i];
5127		}
5128
5129		fn = usb_audio_write_rec_src;
5130		break;
5131
5132
5133
5134	default:
5135
5136		break;
5137	}
5138
5139	mutex_enter(&pc->ctrl_mutex);
5140
5141	pc->statep = statep;
5142	pc->cval = val;
5143	pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
5144	    usb_audio_ctrl_read, fn, pc);
5145
5146	mutex_exit(&pc->ctrl_mutex);
5147
5148	mutex_enter(&statep->usb_ac_mutex);
5149	statep->controls[num] = pc;
5150	mutex_exit(&statep->usb_ac_mutex);
5151
5152
5153	return (pc);
5154}
5155
5156
5157static void
5158usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
5159{
5160	kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
5161}
5162
5163static void
5164usb_ac_rem_controls(usb_ac_state_t *statep)
5165{
5166	usb_audio_ctrl_t *ctrlp;
5167
5168	for (int i = 0; i < CTL_NUM; i++) {
5169		ctrlp = statep->controls[i];
5170		if (ctrlp) {
5171			if (ctrlp->af_ctrlp != NULL)
5172				audio_dev_del_control(ctrlp->af_ctrlp);
5173
5174			usb_audio_ctrl_free(ctrlp);
5175			mutex_enter(&statep->usb_ac_mutex);
5176			statep->controls[i] = NULL;
5177			mutex_exit(&statep->usb_ac_mutex);
5178		}
5179	}
5180
5181}
5182
5183
5184static int
5185usb_ac_add_controls(usb_ac_state_t *statep)
5186{
5187	int rv = USB_FAILURE;
5188	usb_audio_format_t *format;
5189
5190
5191	if (statep->engines[0].af_engp) {
5192		/* Init controls for play format */
5193		format = &(statep->engines[0].fmt);
5194		if (format->ch == 2) {
5195			(void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
5196			    statep->engines[0].af_defgain);
5197		} else {
5198			(void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
5199			    statep->engines[0].af_defgain);
5200		}
5201
5202	}
5203
5204	/* Init controls for rec format */
5205	if (statep->engines[1].af_engp) {
5206		format = &(statep->engines[1].fmt);
5207		if (format->ch == 2) {
5208			(void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
5209			    statep->engines[1].af_defgain);
5210		} else {
5211			(void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
5212			    statep->engines[1].af_defgain);
5213		}
5214
5215		/* Add monitor control */
5216		{
5217			(void) usb_audio_ctrl_alloc(statep,
5218			    CTL_MONITOR_GAIN, 0);
5219		}
5220
5221		/* Add ports control */
5222		{
5223			(void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
5224			    statep->usb_ac_input_ports);
5225		}
5226
5227	}
5228
5229
5230	rv = USB_SUCCESS;
5231
5232OUT:
5233	if (rv != USB_SUCCESS)
5234		usb_ac_rem_controls(statep);
5235	return (rv);
5236}
5237
5238
5239
5240
5241
5242/*ARGSUSED*/
5243static int
5244usb_audio_unregister(usb_ac_state_t *statep)
5245{
5246	int i;
5247
5248	if (statep == NULL)
5249		return (USB_SUCCESS);
5250
5251	if (statep->usb_ac_audio_dev == NULL)
5252		return (USB_SUCCESS);
5253
5254	if ((statep->flags & AF_REGISTERED) &&
5255	    audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
5256		return (USB_FAILURE);
5257	}
5258	mutex_enter(&statep->usb_ac_mutex);
5259	statep->flags &= ~AF_REGISTERED;
5260	mutex_exit(&statep->usb_ac_mutex);
5261
5262	for (i = 0; i < USB_AC_ENG_MAX; i++)
5263		usb_ac_rem_eng(statep, &statep->engines[i]);
5264
5265	usb_ac_rem_controls(statep);
5266
5267	audio_dev_free(statep->usb_ac_audio_dev);
5268
5269	mutex_enter(&statep->usb_ac_mutex);
5270	statep->usb_ac_audio_dev = NULL;
5271	mutex_exit(&statep->usb_ac_mutex);
5272
5273	return (USB_SUCCESS);
5274}
5275
5276
5277static int
5278usb_audio_register(usb_ac_state_t *statep) {
5279	audio_dev_t *af_devp;
5280	int rv = USB_FAILURE;
5281	int n;
5282
5283	af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
5284	audio_dev_set_description(af_devp,  "USB Audio");
5285	audio_dev_set_version(af_devp, "1.0");
5286
5287	mutex_enter(&statep->usb_ac_mutex);
5288	statep->usb_ac_audio_dev = af_devp;
5289	mutex_exit(&statep->usb_ac_mutex);
5290
5291
5292	for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
5293		if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
5294		    != USB_SUCCESS) {
5295			USB_DPRINTF_L2(PRINT_MASK_ATTA,
5296			    statep->usb_ac_log_handle,
5297			    "usb_audio_register: add engine n =%d failed", n);
5298			goto OUT;
5299		}
5300	}
5301
5302
5303	if (usb_ac_add_controls(statep) != USB_SUCCESS) {
5304		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5305		    "usb_audio_register: add controls failed");
5306		goto OUT;
5307	}
5308
5309	if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
5310		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5311		    "usb_audio_register: set defaults failed");
5312		goto OUT;
5313	}
5314
5315	if (audio_dev_register(af_devp) != DDI_SUCCESS) {
5316		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5317		    "audio_dev_register() failed");
5318		goto OUT;
5319	}
5320	mutex_enter(&statep->usb_ac_mutex);
5321	statep->flags |= AF_REGISTERED;
5322	mutex_exit(&statep->usb_ac_mutex);
5323
5324	rv = USB_SUCCESS;
5325
5326OUT:
5327	if (rv != USB_SUCCESS) {
5328		(void) usb_audio_unregister(statep);
5329	}
5330	return (rv);
5331}
5332
5333
5334int
5335usb_ac_get_audio(void *handle, void *buf, int samples)
5336{
5337	usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5338	usb_audio_eng_t *engp = &(statep->engines[0]);
5339	unsigned reqframes = samples >> engp->frsmshift;
5340	unsigned frames;
5341	unsigned i;
5342	size_t sz;
5343	caddr_t bp = buf;
5344
5345	mutex_enter(&engp->lock);
5346	if (!engp->started) {
5347		mutex_exit(&engp->lock);
5348
5349		return (0);
5350	}
5351	engp->busy = B_TRUE;
5352	mutex_exit(&engp->lock);
5353
5354	/* break requests from the driver into fragment sized chunks */
5355	for (i = 0; i < reqframes; i += frames) {
5356
5357		mutex_enter(&engp->lock);
5358		frames = reqframes - i;
5359		if (frames > engp->fragfr)
5360			frames = engp->fragfr;
5361
5362		sz = (frames << engp->frsmshift) << engp->smszshift;
5363
5364		/* must move data before updating framework */
5365		usb_eng_bufio(engp, bp, sz);
5366		engp->frames += frames;
5367		bp += sz;
5368
5369		mutex_exit(&engp->lock);
5370	}
5371
5372	mutex_enter(&engp->lock);
5373	engp->io_count++;
5374	engp->busy = B_FALSE;
5375	cv_signal(&engp->usb_audio_cv);
5376	mutex_exit(&engp->lock);
5377
5378	return (samples);
5379}
5380
5381
5382
5383void
5384usb_ac_send_audio(void *handle, void *buf, int samples)
5385{
5386	usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5387	usb_audio_eng_t *engp = &(statep->engines[1]);
5388	unsigned reqframes = samples >> engp->frsmshift;
5389	unsigned frames;
5390	unsigned i;
5391	size_t sz;
5392	caddr_t bp = buf;
5393
5394	mutex_enter(&engp->lock);
5395
5396	if (!engp->started) {
5397
5398		mutex_exit(&engp->lock);
5399		return;
5400	}
5401	engp->busy = B_TRUE;
5402	mutex_exit(&engp->lock);
5403
5404	/* break requests from the driver into fragment sized chunks */
5405	for (i = 0; i < reqframes; i += frames) {
5406		mutex_enter(&engp->lock);
5407
5408		frames = reqframes - i;
5409		if (frames > engp->fragfr)
5410			frames = engp->fragfr;
5411
5412		sz = (frames << engp->frsmshift) << engp->smszshift;
5413
5414		/* must move data before updating framework */
5415		usb_eng_bufio(engp, bp, sz);
5416		engp->frames += frames;
5417		bp += sz;
5418
5419		mutex_exit(&engp->lock);
5420	}
5421
5422	mutex_enter(&engp->lock);
5423	engp->io_count++;
5424	engp->busy = B_FALSE;
5425	cv_signal(&engp->usb_audio_cv);
5426	mutex_exit(&engp->lock);
5427}
5428
5429
5430/*
5431 * **************************************************************************
5432 * audio framework engine callbacks
5433 */
5434static int
5435usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
5436{
5437	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5438	usb_ac_state_t *statep = engp->statep;
5439	int rv = EIO;
5440
5441	_NOTE(ARGUNUSED(flag));
5442
5443	if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
5444
5445		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5446		    "usb_ac_open() failed");
5447		return (EIO);
5448	}
5449
5450	mutex_enter(&engp->lock);
5451
5452	engp->intrate =  150;
5453	engp->sampsz = engp->fmt.prec / 8;
5454	engp->framesz = engp->sampsz * engp->fmt.ch;
5455
5456	if (engp->fmt.ch > 2) {
5457		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5458		    "unsupported channel count: %u", engp->fmt.ch);
5459		mutex_exit(&engp->lock);
5460		goto OUT;
5461	}
5462	if (engp->fmt.prec > 16) {
5463		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5464		    "unsupported precision: %u", engp->fmt.prec);
5465		mutex_exit(&engp->lock);
5466		goto OUT;
5467	}
5468
5469	engp->frsmshift = engp->fmt.ch / 2;
5470	engp->smszshift = engp->sampsz / 2;
5471
5472	/*
5473	 * In order to match the requested number of samples per interrupt
5474	 * from SADA drivers when computing the fragment size,
5475	 * we need to first truncate the floating point result from
5476	 *	sample rate * channels / intr rate
5477	 * then adjust up to an even number, before multiplying it
5478	 * with the sample size
5479	 */
5480	engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
5481	if (engp->fragsz & 1)
5482		engp->fragsz++;
5483	engp->fragsz *= engp->sampsz;
5484	engp->fragfr = engp->fragsz / engp->framesz;
5485
5486	engp->nfrags = 10;
5487	engp->bufsz = engp->fragsz * engp->nfrags;
5488
5489	engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
5490	engp->bufpos = engp->bufp;
5491	engp->bufendp = engp->bufp + engp->bufsz;
5492	engp->frames = 0;
5493	engp->io_count = 0;
5494	engp->bufio_count = 0;
5495	engp->started = B_FALSE;
5496	engp->busy = B_FALSE;
5497
5498	*nframesp = engp->nfrags * engp->fragfr;
5499	*bufp = engp->bufp;
5500
5501	mutex_exit(&engp->lock);
5502
5503	if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
5504		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5505		    "device setup failed");
5506		goto OUT;
5507	}
5508
5509
5510
5511	mutex_enter(&statep->usb_ac_mutex);
5512	statep->flags |= AD_SETUP;
5513	mutex_exit(&statep->usb_ac_mutex);
5514
5515	rv = 0;
5516
5517
5518OUT:
5519	if (rv != 0)
5520		usb_engine_close(arg);
5521
5522	return (rv);
5523}
5524
5525
5526static void
5527usb_engine_close(void *arg)
5528{
5529	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5530	usb_ac_state_t *statep = engp->statep;
5531
5532	mutex_enter(&engp->lock);
5533	while (engp->busy) {
5534		cv_wait(&engp->usb_audio_cv, &engp->lock);
5535	}
5536
5537	mutex_exit(&engp->lock);
5538
5539	if (statep->flags & AD_SETUP) {
5540		usb_ac_teardown(statep, engp);
5541		mutex_enter(&statep->usb_ac_mutex);
5542		statep->flags &= ~AD_SETUP;
5543		mutex_exit(&statep->usb_ac_mutex);
5544	}
5545	mutex_enter(&engp->lock);
5546
5547	if (engp->bufp != NULL) {
5548		kmem_free(engp->bufp, engp->bufsz);
5549		engp->bufp = NULL;
5550		engp->bufpos = NULL;
5551		engp->bufendp = NULL;
5552	}
5553
5554	mutex_exit(&engp->lock);
5555
5556	usb_ac_close(statep->usb_ac_dip);
5557}
5558
5559
5560
5561static int
5562usb_engine_start(void *arg)
5563{
5564	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5565	int rv = 0;
5566	int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
5567
5568	mutex_enter(&engp->lock);
5569	engp->started = B_TRUE;
5570	mutex_exit(&engp->lock);
5571
5572	usb_ac_state_t *statep = engp->statep;
5573
5574	start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5575	    usb_ac_start_play : usb_ac_start_record;
5576
5577	if ((*start)(statep, engp) != USB_SUCCESS) {
5578		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5579		    "failed to start %d engine", engp->af_eflags);
5580		rv = EIO;
5581	}
5582
5583
5584	return (rv);
5585}
5586
5587
5588static void
5589usb_engine_stop(void *arg)
5590{
5591	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5592
5593	mutex_enter(&engp->lock);
5594	engp->started = B_FALSE;
5595	mutex_exit(&engp->lock);
5596
5597	usb_ac_state_t *statep = engp->statep;
5598	void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
5599
5600	stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5601	    usb_ac_stop_play : usb_ac_stop_record;
5602
5603	(*stop)(statep, engp);
5604}
5605
5606
5607static uint64_t
5608usb_engine_count(void *arg)
5609{
5610	usb_audio_eng_t	*engp = arg;
5611	uint64_t	val;
5612
5613	mutex_enter(&engp->lock);
5614	val = engp->frames;
5615	mutex_exit(&engp->lock);
5616
5617	return (val);
5618}
5619
5620
5621static int
5622usb_engine_format(void *arg)
5623{
5624	usb_audio_eng_t *engp = arg;
5625
5626	switch (engp->fmt.enc) {
5627		case USB_AUDIO_FORMAT_TYPE1_MULAW:
5628			return (AUDIO_FORMAT_ULAW);
5629		case USB_AUDIO_FORMAT_TYPE1_ALAW:
5630			return (AUDIO_FORMAT_ALAW);
5631		case USB_AUDIO_FORMAT_TYPE1_PCM8:
5632			return (AUDIO_FORMAT_U8);
5633
5634		case USB_AUDIO_FORMAT_TYPE1_PCM:
5635			break;
5636		default:
5637			return (AUDIO_FORMAT_NONE);
5638	}
5639
5640	switch (engp->fmt.prec) {
5641		case 8:
5642			return (AUDIO_FORMAT_S8);
5643		case 16:
5644			return (AUDIO_FORMAT_S16_LE);
5645		case 24:
5646			return (AUDIO_FORMAT_S24_LE);
5647		case 32:
5648			return (AUDIO_FORMAT_S32_LE);
5649		default:
5650			break;
5651	}
5652	return (AUDIO_FORMAT_NONE);
5653
5654
5655}
5656
5657static int
5658usb_engine_channels(void *arg)
5659{
5660	usb_audio_eng_t *engp = arg;
5661
5662	return (engp->fmt.ch);
5663}
5664
5665
5666static int
5667usb_engine_rate(void *arg)
5668{
5669	usb_audio_eng_t *engp = arg;
5670
5671	return (engp->fmt.sr);
5672}
5673
5674
5675/*ARGSUSED*/
5676static void
5677usb_engine_sync(void *arg, unsigned nframes)
5678{
5679	/* Do nothing */
5680}
5681
5682
5683static unsigned
5684usb_engine_qlen(void *arg)
5685{
5686	usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5687
5688	return (engp->fragfr);
5689}
5690
5691/*
5692 * **************************************************************************
5693 * interfaces used by USB audio
5694 */
5695
5696/*ARGSUSED*/
5697static int
5698usb_change_phy_vol(usb_ac_state_t *statep, int value)
5699{
5700	usb_audio_ctrl_t *ctrlp;
5701	uint64_t cval = 0;
5702	int64_t left, right, delta = 0;
5703
5704	ctrlp = statep->controls[CTL_VOLUME_STERO];
5705
5706	ASSERT(value != 0);
5707
5708	delta = (value < 0)?-1:1;
5709
5710	left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
5711	right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
5712
5713	if (left > AF_MAX_GAIN)
5714		left = AF_MAX_GAIN;
5715	if (right > AF_MAX_GAIN)
5716		right = AF_MAX_GAIN;
5717
5718	if (left < AF_MIN_GAIN)
5719		left = AF_MIN_GAIN;
5720	if (right < AF_MIN_GAIN)
5721		right = AF_MIN_GAIN;
5722
5723	cval = AUDIO_CTRL_STEREO_VAL(left, right);
5724
5725	if (audio_control_write(ctrlp->af_ctrlp, cval)) {
5726		USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5727		    "updateing control  to value 0x%llx by driver failed",
5728		    (long long unsigned)cval);
5729		return (USB_FAILURE);
5730	}
5731	return (USB_SUCCESS);
5732}
5733