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 */
81 uint_t usb_ac_errlevel = USB_LOG_L4;
82 uint_t usb_ac_errmask = (uint_t)-1;
83 uint_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 */
89 uint_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 */
95 static 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 };
108 enum {
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
121 static 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 */
162 static int usb_ac_attach(dev_info_t *, ddi_attach_cmd_t);
163 static int usb_ac_detach(dev_info_t *, ddi_detach_cmd_t);
164 static int usb_ac_power(dev_info_t *, int, int);
165
166 static uint_t usb_ac_get_featureID(usb_ac_state_t *, uchar_t, uint_t,
167 uint_t);
168
169 /* module entry points */
170 int usb_ac_open(dev_info_t *);
171 void usb_ac_close(dev_info_t *);
172
173 /* descriptor handling */
174 static int usb_ac_handle_descriptors(usb_ac_state_t *);
175 static void usb_ac_add_unit_descriptor(usb_ac_state_t *, uchar_t *, size_t);
176 static void usb_ac_alloc_unit(usb_ac_state_t *, uint_t);
177 static void usb_ac_free_all_units(usb_ac_state_t *);
178 static void usb_ac_setup_connections(usb_ac_state_t *);
179 static void usb_ac_map_termtype_to_port(usb_ac_state_t *, uint_t);
180
181 /* power management */
182 static int usb_ac_pwrlvl0(usb_ac_state_t *);
183 static int usb_ac_pwrlvl1(usb_ac_state_t *);
184 static int usb_ac_pwrlvl2(usb_ac_state_t *);
185 static int usb_ac_pwrlvl3(usb_ac_state_t *);
186 static void usb_ac_create_pm_components(dev_info_t *, usb_ac_state_t *);
187 static void usb_ac_pm_busy_component(usb_ac_state_t *);
188 static void usb_ac_pm_idle_component(usb_ac_state_t *);
189
190 /* event handling */
191 static int usb_ac_disconnect_event_cb(dev_info_t *);
192 static int usb_ac_reconnect_event_cb(dev_info_t *);
193 static int usb_ac_cpr_suspend(dev_info_t *);
194 static void usb_ac_cpr_resume(dev_info_t *);
195
196 static 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 */
203 static void usb_ac_restore_device_state(dev_info_t *, usb_ac_state_t *);
204 static int usb_ac_cleanup(dev_info_t *, usb_ac_state_t *);
205 static void usb_ac_serialize_access(usb_ac_state_t *);
206 static void usb_ac_release_access(usb_ac_state_t *);
207
208 static void usb_ac_push_unit_id(usb_ac_state_t *, uint_t);
209 static void usb_ac_pop_unit_id(usb_ac_state_t *, uint_t);
210 static void usb_ac_show_traverse_path(usb_ac_state_t *);
211 static int usb_ac_check_path(usb_ac_state_t *, uint_t);
212
213 static 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 *));
218 static uint_t usb_ac_set_port(usb_ac_state_t *, uint_t, uint_t);
219 static 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 *));
224 static 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 *));
229 static 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 *));
234 static int usb_ac_update_port(usb_ac_state_t *, uint_t,
235 uint_t, uint_t, uint_t, uint_t, uint_t *);
236 static int usb_ac_set_selector(usb_ac_state_t *, uint_t,
237 uint_t, uint_t, uint_t, uint_t, uint_t *);
238 static int usb_ac_feature_unit_check(usb_ac_state_t *, uint_t,
239 uint_t, uint_t, uint_t, uint_t, uint_t *);
240 static int usb_ac_set_gain(usb_ac_state_t *, uint_t,
241 uint_t, uint_t, uint_t, uint_t, uint_t *);
242 static int usb_ac_set_monitor_gain(usb_ac_state_t *, uint_t,
243 uint_t, uint_t, uint_t, uint_t, uint_t *);
244 static int usb_ac_set_volume(usb_ac_state_t *, uint_t, short, int dir,
245 int);
246 static int usb_ac_get_maxmin_volume(usb_ac_state_t *, uint_t, int, int,
247 int, short *);
248 static int usb_ac_send_as_cmd(usb_ac_state_t *, usb_audio_eng_t *,
249 int, void *);
250 static int usb_ac_set_format(usb_ac_state_t *, usb_audio_eng_t *);
251 static int usb_ac_do_setup(usb_ac_state_t *, usb_audio_eng_t *);
252
253 /* usb audio basic function entries */
254 static int usb_ac_setup(usb_ac_state_t *, usb_audio_eng_t *);
255 static void usb_ac_teardown(usb_ac_state_t *, usb_audio_eng_t *);
256 static int usb_ac_start_play(usb_ac_state_t *, usb_audio_eng_t *);
257 static int usb_ac_start_record(usb_ac_state_t *, usb_audio_eng_t *);
258 static void usb_ac_stop_record(usb_ac_state_t *, usb_audio_eng_t *);
259 static int usb_ac_restore_audio_state(usb_ac_state_t *, int);
260
261 static int usb_ac_ctrl_restore(usb_ac_state_t *);
262 /*
263 * Mux
264 */
265 static int usb_ac_mux_walk_siblings(usb_ac_state_t *);
266 static void usb_ac_print_reg_data(usb_ac_state_t *,
267 usb_as_registration_t *);
268 static int usb_ac_get_reg_data(usb_ac_state_t *, ldi_handle_t, int);
269 static int usb_ac_setup_plumbed(usb_ac_state_t *, int, int);
270 static int usb_ac_mixer_registration(usb_ac_state_t *);
271 static void usb_ac_hold_siblings(usb_ac_state_t *);
272 static int usb_ac_online_siblings(usb_ac_state_t *);
273 static void usb_ac_rele_siblings(usb_ac_state_t *);
274 static int usb_ac_mux_plumbing(usb_ac_state_t *);
275 static void usb_ac_mux_plumbing_tq(void *);
276 static int usb_ac_mux_unplumbing(usb_ac_state_t *);
277 static void usb_ac_mux_unplumbing_tq(void *);
278 static int usb_ac_plumb(usb_ac_plumbed_t *);
279 static void usb_ac_unplumb(usb_ac_plumbed_t *);
280 static void usb_ac_reader(void *);
281 static int usb_ac_read_msg(usb_ac_plumbed_t *, mblk_t *);
282 static int usb_ac_do_plumbing(usb_ac_state_t *);
283 static int usb_ac_do_unplumbing(usb_ac_state_t *);
284
285
286 static int usb_change_phy_vol(usb_ac_state_t *, int);
287 static void usb_restore_engine(usb_ac_state_t *);
288
289 /* anchor for soft state structures */
290 void *usb_ac_statep;
291
292 /*
293 * DDI Structures
294 */
295
296 /* Device operations structure */
297 static 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 */
313 static 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 */
320 static struct modlinkage usb_ac_modlinkage = {
321 MODREV_1, /* ml_rev */
322 { (void *)&usb_ac_modldrv, NULL } /* ml_linkage */
323 };
324
325 static int usb_audio_register(usb_ac_state_t *);
326 static int usb_audio_unregister(usb_ac_state_t *);
327
328 static int usb_engine_open(void *, int, unsigned *, caddr_t *);
329 static void usb_engine_close(void *);
330 static uint64_t usb_engine_count(void *);
331 static int usb_engine_start(void *);
332 static void usb_engine_stop(void *);
333 static int usb_engine_format(void *);
334 static int usb_engine_channels(void *);
335 static int usb_engine_rate(void *);
336 static void usb_engine_sync(void *, unsigned);
337 static unsigned usb_engine_qlen(void *);
338
339 /* engine buffer size in terms of fragments */
340
341 audio_engine_ops_t usb_engine_ops = {
342 AUDIO_ENGINE_VERSION,
343 usb_engine_open,
344 usb_engine_close,
345 usb_engine_start,
346 usb_engine_stop,
347 usb_engine_count,
348 usb_engine_format,
349 usb_engine_channels,
350 usb_engine_rate,
351 usb_engine_sync,
352 usb_engine_qlen,
353 };
354
355
356
357 _NOTE(SCHEME_PROTECTS_DATA("unique per call", mblk_t))
358
359 /* standard entry points */
360 int
361 _init(void)
362 {
363 int rval;
364
365 /* initialize the soft state */
366 if ((rval = ddi_soft_state_init(&usb_ac_statep,
367 sizeof (usb_ac_state_t), 1)) != DDI_SUCCESS) {
368 return (rval);
369 }
370
371 audio_init_ops(&usb_ac_dev_ops, "usb_ac");
372
373 if ((rval = mod_install(&usb_ac_modlinkage)) != 0) {
374 ddi_soft_state_fini(&usb_ac_statep);
375 audio_fini_ops(&usb_ac_dev_ops);
376 }
377
378 return (rval);
379 }
380
381 int
382 _fini(void)
383 {
384 int rval;
385
386 if ((rval = mod_remove(&usb_ac_modlinkage)) == 0) {
387 /* Free the soft state internal structures */
388 ddi_soft_state_fini(&usb_ac_statep);
389 audio_fini_ops(&usb_ac_dev_ops);
390 }
391
392 return (rval);
393 }
394
395 int
396 _info(struct modinfo *modinfop)
397 {
398 return (mod_info(&usb_ac_modlinkage, modinfop));
399 }
400
401 extern uint_t nproc;
402 #define INIT_PROCESS_CNT 3
403
404 static int
405 usb_ac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
406 {
407 usb_ac_state_t *uacp = NULL;
408 int instance = ddi_get_instance(dip);
409
410 switch (cmd) {
411 case DDI_ATTACH:
412 break;
413 case DDI_RESUME:
414 usb_ac_cpr_resume(dip);
415
416 return (DDI_SUCCESS);
417 default:
418 return (DDI_FAILURE);
419 }
420
421 /*
422 * wait until all processes are started from main.
423 * USB enumerates early in boot (ie. consconfig time).
424 * If the plumbing takes place early, the file descriptors
425 * are owned by the init process and can never be closed anymore
426 * Consequently, hot removal is not possible and the dips
427 * never go away. By waiting some time, e.g. INIT_PROCESS_CNT,
428 * the problem is avoided.
429 */
430 if (nproc < INIT_PROCESS_CNT) {
431 USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL,
432 "usb_ac%d attach too early", instance);
433
434 return (DDI_FAILURE);
435 }
436
437 /*
438 * Allocate soft state information.
439 */
440 if (ddi_soft_state_zalloc(usb_ac_statep, instance) != DDI_SUCCESS) {
441
442 goto fail;
443 }
444
445 /*
446 * get soft state space and initialize
447 */
448 uacp = (usb_ac_state_t *)ddi_get_soft_state(usb_ac_statep, instance);
449 if (uacp == NULL) {
450
451 goto fail;
452 }
453
454 /* get log handle */
455 uacp->usb_ac_log_handle = usb_alloc_log_hdl(dip, "ac",
456 &usb_ac_errlevel,
457 &usb_ac_errmask, &usb_ac_instance_debug,
458 0);
459
460 uacp->usb_ac_instance = instance;
461 uacp->usb_ac_dip = dip;
462
463 (void) snprintf(uacp->dstr, sizeof (uacp->dstr), "%s#%d",
464 ddi_driver_name(dip), instance);
465
466 if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
467 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
468 "usb_client_attach failed");
469
470 usb_free_log_hdl(uacp->usb_ac_log_handle);
471 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
472
473 return (DDI_FAILURE);
474 }
475
476 if (usb_get_dev_data(dip, &uacp->usb_ac_dev_data,
477 USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
478 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
479 "usb_get_dev_data failed");
480
481 usb_client_detach(dip, NULL);
482 usb_free_log_hdl(uacp->usb_ac_log_handle);
483 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
484
485 return (DDI_FAILURE);
486 }
487
488 /* initialize mutex & cv */
489 mutex_init(&uacp->usb_ac_mutex, NULL, MUTEX_DRIVER,
490 uacp->usb_ac_dev_data->dev_iblock_cookie);
491
492 uacp->usb_ac_default_ph = uacp->usb_ac_dev_data->dev_default_ph;
493
494 /* parse all class specific descriptors */
495 if (usb_ac_handle_descriptors(uacp) != USB_SUCCESS) {
496
497 goto fail;
498 }
499
500 /* we no longer need the descr tree */
501 usb_free_descr_tree(dip, uacp->usb_ac_dev_data);
502
503 uacp->usb_ac_ser_acc = usb_init_serialization(dip,
504 USB_INIT_SER_CHECK_SAME_THREAD);
505
506 mutex_enter(&uacp->usb_ac_mutex);
507
508 /* we are online */
509 uacp->usb_ac_dev_state = USB_DEV_ONLINE;
510
511 /*
512 * safe guard the postattach to be executed
513 * only two states arepossible: plumbed / unplumbed
514 */
515 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
516 uacp->usb_ac_current_plumbed_index = -1;
517
518 mutex_exit(&uacp->usb_ac_mutex);
519
520 /* create components to power manage this device */
521 usb_ac_create_pm_components(dip, uacp);
522
523 /* Register for events */
524 if (usb_register_event_cbs(dip, &usb_ac_events, 0) != USB_SUCCESS) {
525 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
526 "usb_ac_attach: couldn't register for events");
527
528 goto fail;
529 }
530
531 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
532 "usb_ac_attach: End");
533
534 /* report device */
535 ddi_report_dev(dip);
536
537 if (usb_ac_do_plumbing(uacp) != USB_SUCCESS)
538 goto fail;
539
540 return (DDI_SUCCESS);
541
542 fail:
543 if (uacp) {
544 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
545 "attach failed");
546
547 /* wait for plumbing thread to finish */
548 if (uacp->tqp != NULL) {
549 ddi_taskq_wait(uacp->tqp);
550 ddi_taskq_destroy(uacp->tqp);
551 uacp->tqp = NULL;
552 }
553 (void) usb_ac_cleanup(dip, uacp);
554 }
555
556 return (DDI_FAILURE);
557 }
558
559
560 static int
561 usb_ac_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
562 {
563 int instance = ddi_get_instance(dip);
564 usb_ac_state_t *uacp;
565 int rval = USB_FAILURE;
566
567 uacp = ddi_get_soft_state(usb_ac_statep, instance);
568
569 switch (cmd) {
570 case DDI_DETACH:
571 USB_DPRINTF_L4(PRINT_MASK_ATTA,
572 uacp->usb_ac_log_handle, "usb_ac_detach: detach");
573
574 /* wait for plumbing thread to finish */
575 if (uacp->tqp != NULL)
576 ddi_taskq_wait(uacp->tqp);
577
578 mutex_enter(&uacp->usb_ac_mutex);
579
580 /* do not allow detach if still busy */
581 if (uacp->usb_ac_busy_count) {
582 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
583 "usb_ac_detach:still busy, usb_ac_busy_count = %d",
584 uacp->usb_ac_busy_count);
585
586 mutex_exit(&uacp->usb_ac_mutex);
587 return (USB_FAILURE);
588 }
589 mutex_exit(&uacp->usb_ac_mutex);
590
591 (void) usb_audio_unregister(uacp);
592
593
594
595 /*
596 * unplumb to stop activity from other modules, then
597 * cleanup, which will also teardown audio framework state
598 */
599 if (usb_ac_do_unplumbing(uacp) == USB_SUCCESS)
600 rval = usb_ac_cleanup(dip, uacp);
601
602 if (rval != USB_SUCCESS) {
603 USB_DPRINTF_L2(PRINT_MASK_ATTA,
604 uacp->usb_ac_log_handle, "detach failed: %s%d",
605 ddi_driver_name(dip), instance);
606 }
607
608 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
609 case DDI_SUSPEND:
610 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
611 "usb_ac_detach: suspending");
612
613 rval = usb_ac_cpr_suspend(dip);
614
615 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
616 default:
617
618 return (DDI_FAILURE);
619 }
620 }
621
622
623 /*
624 * usb_ac_cleanup:
625 * cleanup on attach failure and detach
626 */
627 static int
628 usb_ac_cleanup(dev_info_t *dip, usb_ac_state_t *uacp)
629 {
630 usb_ac_power_t *uacpm;
631 int rval = USB_FAILURE;
632
633
634 mutex_enter(&uacp->usb_ac_mutex);
635 uacpm = uacp->usb_ac_pm;
636
637 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
638 "usb_ac_cleanup:begain");
639
640 ASSERT(uacp->usb_ac_busy_count == 0);
641
642 ASSERT(uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED);
643
644 mutex_exit(&uacp->usb_ac_mutex);
645
646 /*
647 * Disable the event callbacks, after this point, event
648 * callbacks will never get called. Note we shouldn't hold
649 * the mutex while unregistering events because there may be a
650 * competing event callback thread. Event callbacks are done
651 * with ndi mutex held and this can cause a potential deadlock.
652 */
653 usb_unregister_event_cbs(dip, &usb_ac_events);
654
655 mutex_enter(&uacp->usb_ac_mutex);
656
657 if (uacpm && (uacp->usb_ac_dev_state != USB_DEV_DISCONNECTED)) {
658 if (uacpm->acpm_wakeup_enabled) {
659 mutex_exit(&uacp->usb_ac_mutex);
660 usb_ac_pm_busy_component(uacp);
661 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
662
663 rval = usb_handle_remote_wakeup(dip,
664 USB_REMOTE_WAKEUP_DISABLE);
665 if (rval != USB_SUCCESS) {
666 USB_DPRINTF_L2(PRINT_MASK_PM,
667 uacp->usb_ac_log_handle,
668 "usb_ac_cleanup: disable remote "
669 "wakeup failed, rval=%d", rval);
670 }
671 usb_ac_pm_idle_component(uacp);
672 } else {
673 mutex_exit(&uacp->usb_ac_mutex);
674 }
675
676 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
677
678 mutex_enter(&uacp->usb_ac_mutex);
679 }
680
681 if (uacpm) {
682 kmem_free(uacpm, sizeof (usb_ac_power_t));
683 uacp->usb_ac_pm = NULL;
684 }
685
686 usb_client_detach(dip, uacp->usb_ac_dev_data);
687
688 /* free descriptors */
689 usb_ac_free_all_units(uacp);
690
691 mutex_exit(&uacp->usb_ac_mutex);
692
693 mutex_destroy(&uacp->usb_ac_mutex);
694
695 usb_fini_serialization(uacp->usb_ac_ser_acc);
696
697 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
698 "usb_ac_cleanup: Ending");
699
700 usb_free_log_hdl(uacp->usb_ac_log_handle);
701 kmem_free(uacp->usb_ac_connections, uacp->usb_ac_connections_len);
702 kmem_free(uacp->usb_ac_connections_a, uacp->usb_ac_connections_a_len);
703 kmem_free(uacp->usb_ac_unit_type, uacp->usb_ac_max_unit);
704 kmem_free(uacp->usb_ac_traverse_path, uacp->usb_ac_max_unit);
705
706 ddi_soft_state_free(usb_ac_statep, uacp->usb_ac_instance);
707
708 ddi_prop_remove_all(dip);
709
710 return (USB_SUCCESS);
711 }
712
713
714 int
715 usb_ac_open(dev_info_t *dip)
716 {
717 int inst = ddi_get_instance(dip);
718 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
719
720 mutex_enter(&uacp->usb_ac_mutex);
721
722 uacp->usb_ac_busy_count++;
723
724 mutex_exit(&uacp->usb_ac_mutex);
725
726 usb_ac_pm_busy_component(uacp);
727 (void) pm_raise_power(uacp->usb_ac_dip, 0, USB_DEV_OS_FULL_PWR);
728
729 return (0);
730 }
731
732
733 void
734 usb_ac_close(dev_info_t *dip)
735 {
736 int inst = ddi_get_instance(dip);
737 usb_ac_state_t *uacp = ddi_get_soft_state(usb_ac_statep, inst);
738
739 mutex_enter(&uacp->usb_ac_mutex);
740
741 if (uacp->usb_ac_busy_count > 0)
742 uacp->usb_ac_busy_count--;
743
744 mutex_exit(&uacp->usb_ac_mutex);
745
746 usb_ac_pm_idle_component(uacp);
747 }
748
749
750 /*
751 * usb_ac_read_msg:
752 * Handle asynchronous response from opened streams
753 */
754 static int
755 usb_ac_read_msg(usb_ac_plumbed_t *plumb_infop, mblk_t *mp)
756 {
757 usb_ac_state_t *uacp = plumb_infop->acp_uacp;
758 int error = DDI_SUCCESS;
759 int val;
760 char val1;
761 struct iocblk *iocp;
762
763
764 ASSERT(mutex_owned(&uacp->usb_ac_mutex));
765
766 /*
767 * typically an M_CTL is used between modules but in order to pass
768 * through the streamhead, an M_PROTO type must be used instead
769 */
770 switch (mp->b_datap->db_type) {
771 case M_PROTO:
772 case M_ERROR:
773 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
774 "M_CTL/M_ERROR");
775
776 switch (plumb_infop->acp_driver) {
777 case USB_AH_PLUMBED:
778 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
779 "message from hid, instance=%d",
780 ddi_get_instance(plumb_infop->acp_dip));
781
782 iocp = (struct iocblk *)(void *)mp->b_rptr;
783 ASSERT(mp->b_cont != NULL);
784
785 if (uacp->usb_ac_registered_with_mixer) {
786
787 val1 = *((char *)mp->b_cont->b_rptr);
788 val = (int)val1;
789
790 USB_DPRINTF_L4(PRINT_MASK_ALL,
791 uacp->usb_ac_log_handle, "val1=0x%x(%d),"
792 "val=0x%x(%d)", val1, val1, val, val);
793
794 switch (iocp->ioc_cmd) {
795 /* Handle relative volume change */
796 case USB_AUDIO_VOL_CHANGE:
797 /* prevent unplumbing */
798 uacp->usb_ac_busy_count++;
799 if (uacp->usb_ac_plumbing_state ==
800 USB_AC_STATE_PLUMBED) {
801 mutex_exit(&uacp->usb_ac_mutex);
802 (void) usb_change_phy_vol(
803 uacp, val);
804 mutex_enter(&uacp->
805 usb_ac_mutex);
806 }
807 uacp->usb_ac_busy_count--;
808 /* FALLTHRU */
809 case USB_AUDIO_MUTE:
810 default:
811 freemsg(mp);
812 break;
813 }
814 } else {
815 freemsg(mp);
816 }
817
818 break;
819 default:
820 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
821 "message from unknown module(%s)",
822 ddi_driver_name(plumb_infop->acp_dip));
823 freemsg(mp);
824 }
825
826 break;
827 default:
828 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
829 "Unknown type=%d", mp->b_datap->db_type);
830 freemsg(mp);
831 }
832
833
834 return (error);
835 }
836
837
838 /*
839 * Power Management
840 * usb_ac_power:
841 * power entry point
842 */
843 static int
844 usb_ac_power(dev_info_t *dip, int comp, int level)
845 {
846 _NOTE(ARGUNUSED(comp));
847 int instance = ddi_get_instance(dip);
848 usb_ac_state_t *uacp;
849 usb_ac_power_t *uacpm;
850 int rval = DDI_FAILURE;
851
852 uacp = ddi_get_soft_state(usb_ac_statep, instance);
853
854 mutex_enter(&uacp->usb_ac_mutex);
855 uacpm = uacp->usb_ac_pm;
856
857 if (USB_DEV_PWRSTATE_OK(uacpm->acpm_pwr_states, level)) {
858 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
859 "usb_ac_power: illegal level=%d pwr_states=%d",
860 level, uacpm->acpm_pwr_states);
861
862 goto done;
863 }
864
865 switch (level) {
866 case USB_DEV_OS_PWR_OFF:
867 rval = usb_ac_pwrlvl0(uacp);
868 break;
869 case USB_DEV_OS_PWR_1:
870 rval = usb_ac_pwrlvl1(uacp);
871 break;
872 case USB_DEV_OS_PWR_2:
873 rval = usb_ac_pwrlvl2(uacp);
874 break;
875 case USB_DEV_OS_FULL_PWR:
876 rval = usb_ac_pwrlvl3(uacp);
877 break;
878 }
879
880 done:
881 mutex_exit(&uacp->usb_ac_mutex);
882
883 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
884 }
885
886
887 /*
888 * functions to handle power transition for various levels
889 * These functions act as place holders to issue USB commands
890 * to the devices to change their power levels
891 * Level 0 = Device is powered off
892 * Level 3 = Device if full powered
893 * Level 1,2 = Intermediate power level of the device as implemented
894 * by the hardware.
895 * Note that Level 0 is OS power-off and Level 3 is OS full-power.
896 */
897 static int
898 usb_ac_pwrlvl0(usb_ac_state_t *uacp)
899 {
900 usb_ac_power_t *uacpm;
901 int rval;
902
903 uacpm = uacp->usb_ac_pm;
904
905 switch (uacp->usb_ac_dev_state) {
906 case USB_DEV_ONLINE:
907 /* Deny the powerdown request if the device is busy */
908 if (uacpm->acpm_pm_busy != 0) {
909
910 return (USB_FAILURE);
911 }
912
913 /* Issue USB D3 command to the device here */
914 rval = usb_set_device_pwrlvl3(uacp->usb_ac_dip);
915 ASSERT(rval == USB_SUCCESS);
916
917 uacp->usb_ac_dev_state = USB_DEV_PWRED_DOWN;
918 uacpm->acpm_current_power = USB_DEV_OS_PWR_OFF;
919
920 /* FALLTHRU */
921 case USB_DEV_DISCONNECTED:
922 case USB_DEV_SUSPENDED:
923 case USB_DEV_PWRED_DOWN:
924 default:
925 return (USB_SUCCESS);
926 }
927 }
928
929
930 /* ARGSUSED */
931 static int
932 usb_ac_pwrlvl1(usb_ac_state_t *uacp)
933 {
934 int rval;
935
936 /* Issue USB D2 command to the device here */
937 rval = usb_set_device_pwrlvl2(uacp->usb_ac_dip);
938 ASSERT(rval == USB_SUCCESS);
939
940 return (USB_FAILURE);
941 }
942
943
944 /* ARGSUSED */
945 static int
946 usb_ac_pwrlvl2(usb_ac_state_t *uacp)
947 {
948 int rval;
949
950 rval = usb_set_device_pwrlvl1(uacp->usb_ac_dip);
951 ASSERT(rval == USB_SUCCESS);
952
953 return (USB_FAILURE);
954 }
955
956
957 static int
958 usb_ac_pwrlvl3(usb_ac_state_t *uacp)
959 {
960 usb_ac_power_t *uacpm;
961 int rval;
962
963 uacpm = uacp->usb_ac_pm;
964
965 switch (uacp->usb_ac_dev_state) {
966 case USB_DEV_PWRED_DOWN:
967 /* Issue USB D0 command to the device here */
968 rval = usb_set_device_pwrlvl0(uacp->usb_ac_dip);
969 ASSERT(rval == USB_SUCCESS);
970
971 uacp->usb_ac_dev_state = USB_DEV_ONLINE;
972 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
973 /* FALLTHRU */
974 case USB_DEV_ONLINE:
975 /* we are already in full power */
976
977 /* FALLTHRU */
978 case USB_DEV_DISCONNECTED:
979 case USB_DEV_SUSPENDED:
980
981 return (USB_SUCCESS);
982 default:
983 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
984 "usb_ac_pwerlvl3: Illegal dev_state");
985
986 return (USB_FAILURE);
987 }
988 }
989
990
991 static void
992 usb_ac_create_pm_components(dev_info_t *dip, usb_ac_state_t *uacp)
993 {
994 usb_ac_power_t *uacpm;
995 uint_t pwr_states;
996
997 USB_DPRINTF_L4(PRINT_MASK_PM, uacp->usb_ac_log_handle,
998 "usb_ac_create_pm_components: begin");
999
1000 /* Allocate the state structure */
1001 uacpm = kmem_zalloc(sizeof (usb_ac_power_t), KM_SLEEP);
1002 uacp->usb_ac_pm = uacpm;
1003 uacpm->acpm_state = uacp;
1004 uacpm->acpm_capabilities = 0;
1005 uacpm->acpm_current_power = USB_DEV_OS_FULL_PWR;
1006
1007 if (usb_create_pm_components(dip, &pwr_states) ==
1008 USB_SUCCESS) {
1009 if (usb_handle_remote_wakeup(dip,
1010 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
1011 uacpm->acpm_wakeup_enabled = 1;
1012
1013 USB_DPRINTF_L4(PRINT_MASK_PM,
1014 uacp->usb_ac_log_handle,
1015 "remote Wakeup enabled");
1016 }
1017 uacpm->acpm_pwr_states = (uint8_t)pwr_states;
1018 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
1019 } else {
1020 if (uacpm) {
1021 kmem_free(uacpm, sizeof (usb_ac_power_t));
1022 uacp->usb_ac_pm = NULL;
1023 }
1024 USB_DPRINTF_L2(PRINT_MASK_PM, uacp->usb_ac_log_handle,
1025 "pm not enabled");
1026 }
1027
1028 }
1029
1030 /*
1031 * usb_ac_get_featureID:
1032 * find out if there is at least one feature unit that supports
1033 * the request controls.
1034 * Return featureID or USB_AC_ID_NONE.
1035 */
1036 static uint_t
1037 usb_ac_get_featureID(usb_ac_state_t *uacp, uchar_t dir,
1038 uint_t channel, uint_t control)
1039 {
1040 uint_t count = 0;
1041
1042 return (usb_ac_set_control(uacp, dir, USB_AUDIO_FEATURE_UNIT,
1043 channel, control, USB_AC_FIND_ONE, &count, 0,
1044 usb_ac_feature_unit_check));
1045 }
1046
1047
1048 /*
1049 * usb_ac_feature_unit_check:
1050 * check if a feature unit can support the required channel
1051 * and control combination. Return USB_SUCCESS or USB_FAILURE.
1052 * Called for each matching unit from usb_ac_traverse_connections.
1053 */
1054 /*ARGSUSED*/
1055 static int
1056 usb_ac_feature_unit_check(usb_ac_state_t *uacp, uint_t featureID,
1057 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1058 {
1059 usb_audio_feature_unit_descr1_t *feature_descrp;
1060 int n_channel_controls;
1061
1062
1063 ASSERT(featureID < uacp->usb_ac_max_unit);
1064
1065 /*
1066 * check if this control is supported on this channel
1067 */
1068 feature_descrp = (usb_audio_feature_unit_descr1_t *)
1069 uacp->usb_ac_units[featureID].acu_descriptor;
1070 ASSERT(feature_descrp->bUnitID == featureID);
1071
1072 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1073 "bControlSize=%d", feature_descrp->bControlSize);
1074
1075 if (feature_descrp->bControlSize == 0) {
1076 featureID = USB_AC_ID_NONE;
1077 } else {
1078 uint_t index;
1079
1080 n_channel_controls = (feature_descrp->bLength -
1081 offsetof(usb_audio_feature_unit_descr1_t,
1082 bmaControls))/feature_descrp->bControlSize;
1083
1084 USB_DPRINTF_L3(PRINT_MASK_ALL,
1085 uacp->usb_ac_log_handle,
1086 "#controls: %d index=%d", n_channel_controls,
1087 feature_descrp->bControlSize * channel);
1088
1089 if (channel > n_channel_controls) {
1090 featureID = USB_AC_ID_NONE;
1091 } else {
1092 /*
1093 * we only support MUTE and VOLUME
1094 * which are in the first byte
1095 */
1096 index = feature_descrp->bControlSize *
1097 channel;
1098
1099 USB_DPRINTF_L3(PRINT_MASK_ALL,
1100 uacp->usb_ac_log_handle,
1101 "control: 0x%x",
1102 feature_descrp->bmaControls[index]);
1103
1104 if ((feature_descrp->bmaControls[index] &
1105 control) == 0) {
1106 featureID = USB_AC_ID_NONE;
1107 }
1108 }
1109 }
1110
1111 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1112 "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
1113 dir, featureID);
1114
1115 return ((featureID != USB_AC_ID_NONE) ?
1116 USB_SUCCESS : USB_FAILURE);
1117 }
1118
1119
1120 /*
1121 * Descriptor Management
1122 *
1123 * usb_ac_handle_descriptors:
1124 * extract interesting descriptors from the config cloud
1125 */
1126 static int
1127 usb_ac_handle_descriptors(usb_ac_state_t *uacp)
1128 {
1129 int len, index;
1130 int rval = USB_FAILURE;
1131 usb_audio_cs_if_descr_t descr;
1132 usb_client_dev_data_t *dev_data = uacp->usb_ac_dev_data;
1133 usb_alt_if_data_t *altif_data;
1134 usb_cvs_data_t *cvs;
1135
1136
1137 altif_data = &dev_data->dev_curr_cfg->
1138 cfg_if[dev_data->dev_curr_if].if_alt[0];
1139
1140 uacp->usb_ac_ifno = dev_data->dev_curr_if;
1141 uacp->usb_ac_if_descr = altif_data->altif_descr;
1142
1143 /* find USB_AUDIO_CS_INTERFACE type descriptor */
1144 for (index = 0; index < altif_data->altif_n_cvs; index++) {
1145 cvs = &altif_data->altif_cvs[index];
1146 if (cvs->cvs_buf == NULL) {
1147 continue;
1148 }
1149 if (cvs->cvs_buf[1] == USB_AUDIO_CS_INTERFACE) {
1150 break;
1151 }
1152 }
1153
1154 if (index == altif_data->altif_n_cvs) {
1155 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1156 "usb_ac_handle_descriptors:cannot find descriptor type %d",
1157 USB_AUDIO_CS_INTERFACE);
1158
1159 return (rval);
1160 }
1161
1162 len = usb_parse_data(
1163 CS_AC_IF_HEADER_FORMAT,
1164 cvs->cvs_buf, cvs->cvs_buf_len,
1165 (void *)&descr, sizeof (usb_audio_cs_if_descr_t));
1166
1167 /* is this a sane header descriptor */
1168 if (!((len >= CS_AC_IF_HEADER_SIZE) &&
1169 (descr.bDescriptorType == USB_AUDIO_CS_INTERFACE) &&
1170 (descr.bDescriptorSubType == USB_AUDIO_HEADER))) {
1171 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1172 "invalid header");
1173
1174 return (rval);
1175 }
1176
1177 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1178 "index %d, header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t"
1179 "total=0x%x InCol=0x%x",
1180 index,
1181 descr.bDescriptorType,
1182 descr.bDescriptorSubType,
1183 descr.bcdADC,
1184 descr.wTotalLength,
1185 descr.blnCollection);
1186
1187 /*
1188 * we read descriptors by index and store them in ID array.
1189 * the actual parsing is done in usb_ac_add_unit_descriptor()
1190 */
1191 for (index++; index < altif_data->altif_n_cvs; index++) {
1192 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1193 "index=%d", index);
1194
1195 cvs = &altif_data->altif_cvs[index];
1196 if (cvs->cvs_buf == NULL) {
1197 continue;
1198 }
1199
1200 /* add to ID array */
1201 usb_ac_add_unit_descriptor(uacp, cvs->cvs_buf,
1202 cvs->cvs_buf_len);
1203 }
1204 rval = USB_SUCCESS;
1205
1206 usb_ac_setup_connections(uacp);
1207
1208 /* determine port types */
1209 usb_ac_map_termtype_to_port(uacp, USB_AUDIO_PLAY);
1210 usb_ac_map_termtype_to_port(uacp, USB_AUDIO_RECORD);
1211
1212
1213 return (rval);
1214 }
1215
1216
1217 /*
1218 * usb_ac_setup_connections:
1219 * build a matrix reflecting all connections
1220 */
1221 static void
1222 usb_ac_setup_connections(usb_ac_state_t *uacp)
1223 {
1224 usb_ac_unit_list_t *units = uacp->usb_ac_units;
1225 uchar_t *a, **p, i, unit;
1226 size_t a_len, p_len;
1227
1228 /* allocate array for unit types for quick reference */
1229 uacp->usb_ac_unit_type = kmem_zalloc(uacp->usb_ac_max_unit,
1230 KM_SLEEP);
1231 /* allocate array for traversal path */
1232 uacp->usb_ac_traverse_path = kmem_zalloc(uacp->usb_ac_max_unit,
1233 KM_SLEEP);
1234
1235
1236 /* allocate the connection matrix and set it up */
1237 a_len = uacp->usb_ac_max_unit * uacp->usb_ac_max_unit;
1238 p_len = uacp->usb_ac_max_unit * sizeof (uchar_t *);
1239
1240 /* trick to create a 2 dimensional array */
1241 a = kmem_zalloc(a_len, KM_SLEEP);
1242 p = kmem_zalloc(p_len, KM_SLEEP);
1243 for (i = 0; i < uacp->usb_ac_max_unit; i++) {
1244 p[i] = a + i * uacp->usb_ac_max_unit;
1245 }
1246 uacp->usb_ac_connections = p;
1247 uacp->usb_ac_connections_len = p_len;
1248 uacp->usb_ac_connections_a = a;
1249 uacp->usb_ac_connections_a_len = a_len;
1250
1251 /* traverse all units and set connections */
1252 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1253
1254 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1255 "--------traversing unit=0x%x type=0x%x--------",
1256 unit, units[unit].acu_type);
1257
1258 /* store type in the first unused column */
1259 uacp->usb_ac_unit_type[unit] = units[unit].acu_type;
1260
1261 /* save the Unit ID in the unit it points to */
1262 switch (units[unit].acu_type) {
1263 case USB_AUDIO_FEATURE_UNIT:
1264 {
1265 usb_audio_feature_unit_descr1_t *d =
1266 units[unit].acu_descriptor;
1267
1268 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1269 "USB_AUDIO_FEATURE_UNIT:sourceID=0x%x type=0x%x",
1270 d->bSourceID, units[d->bSourceID].acu_type);
1271
1272 if (d->bSourceID != 0) {
1273 ASSERT(p[unit][d->bSourceID] == B_FALSE);
1274 p[unit][d->bSourceID] = B_TRUE;
1275 }
1276
1277 break;
1278 }
1279 case USB_AUDIO_OUTPUT_TERMINAL:
1280 {
1281 usb_audio_output_term_descr_t *d =
1282 units[unit].acu_descriptor;
1283
1284 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1285 "USB_AUDIO_OUTPUT_TERMINAL:sourceID=0x%x type=0x%x",
1286 d->bSourceID, units[d->bSourceID].acu_type);
1287
1288 if (d->bSourceID != 0) {
1289 ASSERT(p[unit][d->bSourceID] == B_FALSE);
1290 p[unit][d->bSourceID] = B_TRUE;
1291 }
1292
1293 break;
1294 }
1295 case USB_AUDIO_MIXER_UNIT:
1296 {
1297 usb_audio_mixer_unit_descr1_t *d =
1298 units[unit].acu_descriptor;
1299 int n_sourceID = d->bNrInPins;
1300 int id;
1301
1302 for (id = 0; id < n_sourceID; id++) {
1303 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1304 uacp->usb_ac_log_handle,
1305 "USB_AUDIO_MIXER_UNIT:sourceID=0x%x"
1306 "type=0x%x c=%d",
1307 d->baSourceID[id],
1308 units[d->baSourceID[id]].acu_type,
1309 p[unit][d->baSourceID[id]]);
1310
1311 if (d->baSourceID[id] != 0) {
1312 ASSERT(p[unit][d->baSourceID[id]] ==
1313 B_FALSE);
1314 p[unit][d->baSourceID[id]] = B_TRUE;
1315 }
1316 }
1317
1318 break;
1319 }
1320 case USB_AUDIO_SELECTOR_UNIT:
1321 {
1322 usb_audio_selector_unit_descr1_t *d =
1323 units[unit].acu_descriptor;
1324 int n_sourceID = d->bNrInPins;
1325 int id;
1326
1327 for (id = 0; id < n_sourceID; id++) {
1328 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1329 uacp->usb_ac_log_handle,
1330 "USB_AUDIO_SELECTOR_UNIT:sourceID=0x%x"
1331 " type=0x%x", d->baSourceID[id],
1332 units[d->baSourceID[id]].acu_type);
1333
1334 if (d->baSourceID[id] != 0) {
1335 ASSERT(p[unit][d->baSourceID[id]] ==
1336 B_FALSE);
1337 p[unit][d->baSourceID[id]] = B_TRUE;
1338 }
1339 }
1340
1341 break;
1342 }
1343 case USB_AUDIO_PROCESSING_UNIT:
1344 {
1345 usb_audio_mixer_unit_descr1_t *d =
1346 units[unit].acu_descriptor;
1347 int n_sourceID = d->bNrInPins;
1348 int id;
1349
1350 for (id = 0; id < n_sourceID; id++) {
1351 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1352 uacp->usb_ac_log_handle,
1353 "USB_AUDIO_PROCESSING_UNIT:sourceID=0x%x"
1354 " type=0x%x", d->baSourceID[id],
1355 units[d->baSourceID[id]].acu_type);
1356
1357 if (d->baSourceID[id] != 0) {
1358 ASSERT(p[unit][d->baSourceID[id]] ==
1359 B_FALSE);
1360 p[unit][d->baSourceID[id]] = B_TRUE;
1361 }
1362 }
1363
1364 break;
1365 }
1366 case USB_AUDIO_EXTENSION_UNIT:
1367 {
1368 usb_audio_extension_unit_descr1_t *d =
1369 units[unit].acu_descriptor;
1370 int n_sourceID = d->bNrInPins;
1371 int id;
1372
1373 for (id = 0; id < n_sourceID; id++) {
1374 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1375 uacp->usb_ac_log_handle,
1376 "USB_AUDIO_EXTENSION_UNIT:sourceID=0x%x"
1377 "type=0x%x", d->baSourceID[id],
1378 units[d->baSourceID[id]].acu_type);
1379
1380 if (d->baSourceID[id] != 0) {
1381 ASSERT(p[unit][d->baSourceID[id]] ==
1382 B_TRUE);
1383 p[unit][d->baSourceID[id]] = B_FALSE;
1384 }
1385 }
1386
1387 break;
1388 }
1389 case USB_AUDIO_INPUT_TERMINAL:
1390
1391 break;
1392 default:
1393 /*
1394 * Ignore the rest because they are not support yet
1395 */
1396 break;
1397 }
1398 }
1399
1400 #ifdef DEBUG
1401 /* display topology in log buffer */
1402 {
1403 uint_t i, j, l;
1404 char *buf;
1405
1406 l = uacp->usb_ac_max_unit * 5;
1407
1408 buf = kmem_alloc(l, KM_SLEEP);
1409
1410 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1411 "unit types:");
1412
1413 /* two strings so they won't be replaced accidentily by tab */
1414 (void) sprintf(&buf[0], " "" ");
1415 for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1416 (void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1417 }
1418 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1419
1420 (void) sprintf(&buf[0], " +-------");
1421 for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1422 (void) sprintf(&buf[5+((i-1)*3)], "---");
1423 }
1424 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1425
1426 (void) sprintf(&buf[0], " "" ");
1427 for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1428 (void) sprintf(&buf[2 + (i*3)], "%02d ",
1429 uacp->usb_ac_unit_type[i]);
1430 }
1431 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1432 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, " ");
1433
1434 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
1435 "adjacency matrix:");
1436 (void) sprintf(&buf[0], " "" ");
1437 for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1438 (void) sprintf(&buf[2 + (i*3)], "%02d ", i);
1439 }
1440 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1441
1442 (void) sprintf(&buf[0], " +-------");
1443 for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1444 (void) sprintf(&buf[5+((i-1)*3)], "---");
1445 }
1446 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1447
1448 for (i = 1; i < uacp->usb_ac_max_unit; i++) {
1449 (void) sprintf(&buf[0], "%02d| "" ", i);
1450 for (j = 1; j < uacp->usb_ac_max_unit; j++) {
1451 (void) sprintf(&buf[1+(j * 3)], "%2d ", p[i][j]);
1452 }
1453 USB_DPRINTF_L3(PRINT_MASK_ATTA, uacp->usb_ac_log_handle, buf);
1454 }
1455 kmem_free(buf, l);
1456 }
1457 #endif
1458 }
1459
1460
1461 /*
1462 * usb_ac_add_unit_descriptor:
1463 * take the parsed descriptor in the buffer and store it in the ID unit
1464 * array. we grow the unit array if the ID exceeds the current max
1465 */
1466 static void
1467 usb_ac_add_unit_descriptor(usb_ac_state_t *uacp, uchar_t *buffer,
1468 size_t buflen)
1469 {
1470 void *descr;
1471 int len;
1472 char *format;
1473 size_t size;
1474
1475
1476 /* doubling the length should allow for padding */
1477 len = 2 * buffer[0];
1478 descr = kmem_zalloc(len, KM_SLEEP);
1479
1480 switch (buffer[2]) {
1481 case USB_AUDIO_INPUT_TERMINAL:
1482 format = CS_AC_INPUT_TERM_FORMAT;
1483 size = CS_AC_INPUT_TERM_SIZE;
1484
1485 break;
1486 case USB_AUDIO_OUTPUT_TERMINAL:
1487 format = CS_AC_OUTPUT_TERM_FORMAT;
1488 size = CS_AC_OUTPUT_TERM_SIZE;
1489
1490 break;
1491 case USB_AUDIO_MIXER_UNIT:
1492 format = CS_AC_MIXER_UNIT_DESCR1_FORMAT "255c";
1493 size = CS_AC_MIXER_UNIT_DESCR1_SIZE + buffer[4] - 1;
1494
1495 break;
1496 case USB_AUDIO_SELECTOR_UNIT:
1497 format = CS_AC_SELECTOR_UNIT_DESCR1_FORMAT "255c";
1498 size = CS_AC_SELECTOR_UNIT_DESCR1_SIZE + buffer[4] - 1;
1499
1500 break;
1501 case USB_AUDIO_FEATURE_UNIT:
1502 format = CS_AC_FEATURE_UNIT_FORMAT "255c";
1503 size = CS_AC_FEATURE_UNIT_SIZE;
1504
1505 break;
1506 case USB_AUDIO_PROCESSING_UNIT:
1507 format = CS_AC_PROCESSING_UNIT_DESCR1_FORMAT "255c";
1508 size = CS_AC_PROCESSING_UNIT_DESCR1_SIZE + buffer[6] - 1;
1509
1510 break;
1511 case USB_AUDIO_EXTENSION_UNIT:
1512 format = CS_AC_EXTENSION_UNIT_DESCR1_FORMAT "255c";
1513 size = CS_AC_EXTENSION_UNIT_DESCR1_SIZE + buffer[6] - 1;
1514
1515 break;
1516 default:
1517 USB_DPRINTF_L2(PRINT_MASK_ATTA,
1518 uacp->usb_ac_log_handle,
1519 "unsupported descriptor %d", buffer[2]);
1520
1521 /* ignore this descriptor */
1522 kmem_free(descr, len);
1523
1524 return;
1525 }
1526
1527 if (usb_parse_data(format, buffer, buflen, descr, len) < size) {
1528 /* ignore this descriptor */
1529 kmem_free(descr, len);
1530
1531 return;
1532 }
1533
1534 switch (buffer[2]) {
1535 case USB_AUDIO_INPUT_TERMINAL:
1536 {
1537 usb_audio_input_term_descr_t *d =
1538 (usb_audio_input_term_descr_t *)descr;
1539
1540 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1541 uacp->usb_ac_log_handle,
1542 "usb_ac_units[%d] ---input term: type=0x%x sub=0x%x"
1543 "termid=0x%x\n\t"
1544 "termtype=0x%x assoc=0x%x #ch=%d "
1545 "chconf=0x%x ich=0x%x iterm=0x%x",
1546 d->bTerminalID,
1547 d->bDescriptorType, d->bDescriptorSubType,
1548 d->bTerminalID, d->wTerminalType,
1549 d->bAssocTerminal, d->bNrChannels,
1550 d->wChannelConfig, d->iChannelNames,
1551 d->iTerminal);
1552
1553 usb_ac_alloc_unit(uacp, d->bTerminalID);
1554 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1555 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1556 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1557
1558 break;
1559 }
1560 case USB_AUDIO_OUTPUT_TERMINAL:
1561 {
1562 usb_audio_output_term_descr_t *d =
1563 (usb_audio_output_term_descr_t *)descr;
1564
1565 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1566 uacp->usb_ac_log_handle,
1567 "usb_ac_units[%d] ---output term: type=0x%x sub=0x%x"
1568 " termid=0x%x\n\t"
1569 "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
1570 d->bTerminalID,
1571 d->bDescriptorType, d->bDescriptorSubType,
1572 d->bTerminalID, d->wTerminalType,
1573 d->bAssocTerminal, d->bSourceID,
1574 d->iTerminal);
1575
1576 usb_ac_alloc_unit(uacp, d->bTerminalID);
1577 uacp->usb_ac_units[d->bTerminalID].acu_descriptor = descr;
1578 uacp->usb_ac_units[d->bTerminalID].acu_type = buffer[2];
1579 uacp->usb_ac_units[d->bTerminalID].acu_descr_length = len;
1580
1581 break;
1582 }
1583 case USB_AUDIO_MIXER_UNIT:
1584 {
1585 usb_audio_mixer_unit_descr1_t *d =
1586 (usb_audio_mixer_unit_descr1_t *)descr;
1587
1588 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1589 uacp->usb_ac_log_handle,
1590 "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1591 " unitid=0x%x\n\t"
1592 "#pins=0x%x sourceid[0]=0x%x",
1593 d->bUnitID,
1594 d->bDescriptorType, d->bDescriptorSubType,
1595 d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1596 usb_ac_alloc_unit(uacp, d->bUnitID);
1597 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1598 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1599 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1600
1601 break;
1602 }
1603 case USB_AUDIO_SELECTOR_UNIT:
1604 {
1605 usb_audio_selector_unit_descr1_t *d =
1606 (usb_audio_selector_unit_descr1_t *)descr;
1607
1608 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1609 uacp->usb_ac_log_handle,
1610 "usb_ac_units[%d] ---selector unit: type=0x%x sub=0x%x"
1611 " unitid=0x%x\n\t"
1612 "#pins=0x%x sourceid[0]=0x%x",
1613 d->bUnitID,
1614 d->bDescriptorType, d->bDescriptorSubType,
1615 d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1616 usb_ac_alloc_unit(uacp, d->bUnitID);
1617 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1618 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1619 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1620
1621 break;
1622 }
1623 case USB_AUDIO_FEATURE_UNIT:
1624 {
1625 usb_audio_feature_unit_descr1_t *d =
1626 (usb_audio_feature_unit_descr1_t *)descr;
1627
1628 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1629 uacp->usb_ac_log_handle,
1630 "usb_ac_units[%d] ---feature unit: type=0x%x sub=0x%x"
1631 " unitid=0x%x\n\t"
1632 "sourceid=0x%x size=0x%x",
1633 d->bUnitID,
1634 d->bDescriptorType, d->bDescriptorSubType,
1635 d->bUnitID, d->bSourceID, d->bControlSize);
1636
1637 usb_ac_alloc_unit(uacp, d->bUnitID);
1638 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1639 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1640 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1641
1642 break;
1643 }
1644 case USB_AUDIO_PROCESSING_UNIT:
1645 {
1646 usb_audio_processing_unit_descr1_t *d =
1647 (usb_audio_processing_unit_descr1_t *)descr;
1648
1649 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1650 uacp->usb_ac_log_handle,
1651 "usb_ac_units[%d] ---processing unit: type=0x%x sub=0x%x"
1652 " unitid=0x%x\n\t"
1653 "#pins=0x%x sourceid[0]=0x%x",
1654 d->bUnitID,
1655 d->bDescriptorType, d->bDescriptorSubType,
1656 d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1657 usb_ac_alloc_unit(uacp, d->bUnitID);
1658 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1659 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1660 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1661
1662 break;
1663 }
1664 case USB_AUDIO_EXTENSION_UNIT:
1665 {
1666 usb_audio_extension_unit_descr1_t *d =
1667 (usb_audio_extension_unit_descr1_t *)descr;
1668
1669 USB_DPRINTF_L3(PRINT_MASK_ATTA,
1670 uacp->usb_ac_log_handle,
1671 "usb_ac_units[%d] ---mixer unit: type=0x%x sub=0x%x"
1672 " unitid=0x%x\n\t"
1673 "#pins=0x%x sourceid[0]=0x%x",
1674 d->bUnitID,
1675 d->bDescriptorType, d->bDescriptorSubType,
1676 d->bUnitID, d->bNrInPins, d->baSourceID[0]);
1677 usb_ac_alloc_unit(uacp, d->bUnitID);
1678 uacp->usb_ac_units[d->bUnitID].acu_descriptor = descr;
1679 uacp->usb_ac_units[d->bUnitID].acu_type = buffer[2];
1680 uacp->usb_ac_units[d->bUnitID].acu_descr_length = len;
1681
1682 break;
1683 }
1684 default:
1685 break;
1686 }
1687 }
1688
1689
1690 /*
1691 * usb_ac_alloc_unit:
1692 * check if the unit ID is less than max_unit in which case no
1693 * extra entries are needed. If more entries are needed, copy over
1694 * the existing array into a new larger array
1695 */
1696 static void
1697 usb_ac_alloc_unit(usb_ac_state_t *uacp, uint_t unit)
1698 {
1699 usb_ac_unit_list_t *old = NULL;
1700 uint_t max_unit;
1701
1702
1703 if (uacp->usb_ac_units) {
1704 if (unit < uacp->usb_ac_max_unit) {
1705 /* existing array is big enough */
1706
1707 return;
1708 }
1709 old = uacp->usb_ac_units;
1710 max_unit = uacp->usb_ac_max_unit;
1711 }
1712
1713 /* allocate two extra ones */
1714 unit += 2;
1715 uacp->usb_ac_max_unit = unit;
1716 uacp->usb_ac_units = kmem_zalloc(unit *
1717 sizeof (usb_ac_unit_list_t), KM_SLEEP);
1718
1719 if (old) {
1720 size_t len = max_unit * sizeof (usb_ac_unit_list_t);
1721 bcopy(old, uacp->usb_ac_units, len);
1722
1723 kmem_free(old, len);
1724 }
1725 }
1726
1727
1728 /*
1729 * usb_ac_free_all_units:
1730 * free the entire unit list
1731 */
1732 static void
1733 usb_ac_free_all_units(usb_ac_state_t *uacp)
1734 {
1735 uint_t unit;
1736 usb_ac_unit_list_t *unitp;
1737
1738 if (uacp->usb_ac_units == NULL) {
1739
1740 return;
1741 }
1742
1743
1744 for (unit = 0; unit < uacp->usb_ac_max_unit; unit++) {
1745 unitp = &uacp->usb_ac_units[unit];
1746 if (unitp) {
1747 if (unitp->acu_descriptor) {
1748 kmem_free(unitp->acu_descriptor,
1749 unitp->acu_descr_length);
1750 }
1751 }
1752 }
1753
1754 kmem_free(uacp->usb_ac_units, uacp->usb_ac_max_unit *
1755 sizeof (usb_ac_unit_list_t));
1756 }
1757
1758
1759 /*
1760 * usb_ac_lookup_port_type:
1761 * map term type to port type
1762 * default just return LINE_IN + LINE_OUT
1763 */
1764 static int
1765 usb_ac_lookup_port_type(ushort_t termtype)
1766 {
1767 uint_t i;
1768
1769 /*
1770 * Looking for a input/ouput terminal type to match the port
1771 * type, it should not be common streaming type
1772 */
1773 ASSERT(termtype != USB_AUDIO_TERM_TYPE_STREAMING);
1774
1775 for (i = 0; ; i++) {
1776 if (usb_ac_term_type_map[i].term_type == 0) {
1777
1778 break;
1779 }
1780
1781 if (usb_ac_term_type_map[i].term_type == termtype) {
1782
1783 return (usb_ac_term_type_map[i].port_type);
1784 }
1785 }
1786
1787 return (USB_PORT_UNKNOWN);
1788 }
1789
1790
1791 /*
1792 * usb_ac_update_port:
1793 * called for each terminal
1794 */
1795 /*ARGSUSED*/
1796 static int
1797 usb_ac_update_port(usb_ac_state_t *uacp, uint_t id,
1798 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1799 {
1800 if (dir & USB_AUDIO_PLAY) {
1801 usb_audio_output_term_descr_t *d =
1802 (usb_audio_output_term_descr_t *)
1803 uacp->usb_ac_units[id].acu_descriptor;
1804 uint_t port_type =
1805 usb_ac_lookup_port_type(d->wTerminalType);
1806
1807 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1808 "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
1809 dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1810
1811 uacp->usb_ac_output_ports |= (1U << port_type);
1812 } else {
1813 usb_audio_input_term_descr_t *d =
1814 (usb_audio_input_term_descr_t *)
1815 uacp->usb_ac_units[id].acu_descriptor;
1816 uint_t port_type =
1817 usb_ac_lookup_port_type(d->wTerminalType);
1818
1819 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1820 "usb_ac_update_port: dir=%d wTerminalType=0x%x, name=%s",
1821 dir, d->wTerminalType, usb_audio_dtypes[port_type]);
1822
1823 uacp->usb_ac_input_ports |= (1U << port_type);
1824
1825 }
1826
1827 return (USB_SUCCESS);
1828 }
1829
1830
1831 /*
1832 * usb_ac_map_termtype_to_port:
1833 * starting from a streaming termtype find all
1834 * input or output terminals and OR into uacp->usb_ac_input_ports
1835 * or uacp->usb_ac_output_ports;
1836 */
1837 static void
1838 usb_ac_map_termtype_to_port(usb_ac_state_t *uacp, uint_t dir)
1839 {
1840 uint_t count = 0;
1841 uint_t depth = 0;
1842 uint_t search_type = (dir & USB_AUDIO_PLAY) ?
1843 USB_AUDIO_OUTPUT_TERMINAL : USB_AUDIO_INPUT_TERMINAL;
1844
1845
1846 (void) usb_ac_traverse_all_units(uacp, dir, search_type, 0,
1847 0, USB_AC_FIND_ALL, &count, 0, &depth, usb_ac_update_port);
1848
1849 ASSERT(depth == 0);
1850 }
1851
1852
1853 /*
1854 * usb_ac_set_port:
1855 * find a selector port (record side only) and set the
1856 * input to the matching pin
1857 */
1858 static uint_t
1859 usb_ac_set_port(usb_ac_state_t *uacp, uint_t dir, uint_t port)
1860 {
1861 uint_t count = 0;
1862 uint_t id;
1863 uint_t depth = 0;
1864
1865
1866 /* we only support the selector for the record side */
1867 if (dir & USB_AUDIO_RECORD) {
1868 id = usb_ac_traverse_all_units(uacp, dir,
1869 USB_AUDIO_SELECTOR_UNIT, 0,
1870 0, USB_AC_FIND_ONE, &count, port, &depth,
1871 usb_ac_set_selector);
1872
1873 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1874 "usb_ac_set_port: id=%d count=%d port=%d",
1875 id, count, port);
1876
1877 ASSERT(depth == 0);
1878 }
1879
1880 return (USB_SUCCESS);
1881 }
1882
1883
1884 /*
1885 * usb_ac_match_port:
1886 * given the requested port type, find a correspondig term type
1887 * Called from usb_ac_traverse_all_units()
1888 */
1889 /*ARGSUSED*/
1890 static int
1891 usb_ac_match_port(usb_ac_state_t *uacp, uint_t id,
1892 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1893 {
1894 uint_t port_type;
1895
1896
1897 if (dir & USB_AUDIO_PLAY) {
1898 usb_audio_output_term_descr_t *d =
1899 (usb_audio_output_term_descr_t *)
1900 uacp->usb_ac_units[id].acu_descriptor;
1901 port_type = usb_ac_lookup_port_type(d->wTerminalType);
1902
1903 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1904 "usb_ac_match_port: "
1905 "dir=%d type=0x%x port_type=%d port=%d",
1906 dir, d->wTerminalType, port_type, arg1);
1907 } else {
1908 usb_audio_output_term_descr_t *d =
1909 (usb_audio_output_term_descr_t *)
1910 uacp->usb_ac_units[id].acu_descriptor;
1911 port_type = usb_ac_lookup_port_type(d->wTerminalType);
1912
1913 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1914 "usb_ac_match_port: "
1915 "dir=%d type=0x%x port_type=%d port=%d",
1916 dir, d->wTerminalType, port_type, arg1);
1917 }
1918
1919 return (((1U << port_type) & arg1) ? USB_SUCCESS : USB_FAILURE);
1920 }
1921
1922
1923 /*
1924 * usb_ac_set_selector:
1925 * Called from usb_ac_traverse_all_units()
1926 * Find the correct pin and set selector to this pin
1927 */
1928 /*ARGSUSED*/
1929 static int
1930 usb_ac_set_selector(usb_ac_state_t *uacp, uint_t id,
1931 uint_t dir, uint_t channel, uint_t control, uint_t arg1, uint_t *depth)
1932 {
1933 uint_t count = 0;
1934 uint_t unit = USB_AC_ID_NONE;
1935 uint_t pin;
1936 uint_t search_target =
1937 (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
1938 USB_AUDIO_INPUT_TERMINAL;
1939 usb_audio_selector_unit_descr1_t *d =
1940 (usb_audio_selector_unit_descr1_t *)
1941 uacp->usb_ac_units[id].acu_descriptor;
1942 int n_sourceID = d->bNrInPins;
1943 int rval = USB_FAILURE;
1944
1945
1946 /*
1947 * for each pin, find a term type that matches the
1948 * requested port type
1949 */
1950 for (pin = 0; pin < n_sourceID; pin++) {
1951 if (d->baSourceID[pin] == 0) {
1952
1953 break;
1954 }
1955 unit = d->baSourceID[pin];
1956
1957 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1958 "usb_ac_set_selector: pin=%d unit=%d", pin, unit);
1959
1960 if (uacp->usb_ac_unit_type[unit] == search_target) {
1961 if (usb_ac_match_port(uacp, unit, dir, channel,
1962 control, arg1, depth) == USB_SUCCESS) {
1963
1964 break;
1965 } else {
1966 unit = USB_AC_ID_NONE;
1967
1968 continue;
1969 }
1970 }
1971
1972 /* find units connected to this unit */
1973 unit = usb_ac_traverse_connections(uacp, unit,
1974 dir, search_target, channel, control,
1975 USB_AC_FIND_ONE, &count, arg1, depth,
1976 usb_ac_match_port);
1977
1978 if (unit != USB_AC_ID_NONE) {
1979
1980 break;
1981 }
1982 }
1983
1984
1985 if (unit != USB_AC_ID_NONE) {
1986 mblk_t *data;
1987 usb_cr_t cr;
1988 usb_cb_flags_t cb_flags;
1989
1990 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1991 "usb_ac_set_selector: found id=%d at pin %d", unit, pin);
1992
1993 mutex_exit(&uacp->usb_ac_mutex);
1994
1995 data = allocb(1, BPRI_HI);
1996 if (!data) {
1997 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
1998 "usb_ac_set_selector: allocate data failed");
1999 mutex_enter(&uacp->usb_ac_mutex);
2000
2001 return (USB_FAILURE);
2002 }
2003
2004 /* pins are 1-based */
2005 *(data->b_rptr) = (char)++pin;
2006
2007 if (usb_pipe_sync_ctrl_xfer(
2008 uacp->usb_ac_dip,
2009 uacp->usb_ac_default_ph,
2010 USB_DEV_REQ_HOST_TO_DEV |
2011 USB_DEV_REQ_TYPE_CLASS |
2012 USB_DEV_REQ_RCPT_IF, /* bmRequestType */
2013 USB_AUDIO_SET_CUR, /* bRequest */
2014 0, /* wValue */
2015 /* feature unit and id */
2016 (id << 8)| uacp->usb_ac_ifno, /* wIndex */
2017 1, /* wLength */
2018 &data,
2019 USB_ATTRS_NONE,
2020 &cr, &cb_flags,
2021 USB_FLAGS_SLEEP) == USB_SUCCESS) {
2022 USB_DPRINTF_L3(PRINT_MASK_ALL,
2023 uacp->usb_ac_log_handle,
2024 "set current selection: %d", *data->b_rptr);
2025
2026 rval = USB_SUCCESS;
2027 } else {
2028 USB_DPRINTF_L2(PRINT_MASK_ALL,
2029 uacp->usb_ac_log_handle,
2030 "set current pin selection failed");
2031 }
2032 freemsg(data);
2033
2034 mutex_enter(&uacp->usb_ac_mutex);
2035 } else {
2036 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2037 "usb_ac_set_selector: nothing found");
2038 }
2039
2040 return (rval);
2041 }
2042
2043
2044 /*
2045 * usb_ac_set_control:
2046 * apply func to all units of search_target type for both the
2047 * requested channel and master channel
2048 */
2049 static uint_t
2050 usb_ac_set_control(usb_ac_state_t *uacp, uint_t dir, uint_t search_target,
2051 uint_t channel, uint_t control, uint_t all_or_one,
2052 uint_t *count, uint_t arg1,
2053 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2054 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2055 {
2056 uint_t id;
2057 uint_t depth = 0;
2058
2059 id = usb_ac_traverse_all_units(uacp, dir, search_target, channel,
2060 control, all_or_one, count, arg1, &depth, func);
2061
2062 if ((channel != 0) &&
2063 (((id == USB_AC_ID_NONE) && (all_or_one == USB_AC_FIND_ONE)) ||
2064 (all_or_one == USB_AC_FIND_ALL))) {
2065 /* try master channel */
2066 channel = 0;
2067 id = usb_ac_traverse_all_units(uacp, dir, search_target,
2068 channel, control, all_or_one, count, arg1,
2069 &depth, func);
2070 }
2071
2072 ASSERT(depth == 0);
2073
2074 return (id);
2075 }
2076
2077
2078 /*
2079 * usb_ac_traverse_all_units:
2080 * traverse all units starting with all IT or OT depending on direction.
2081 * If no unit is found for the particular channel, try master channel
2082 * If a matching unit is found, apply the function passed by
2083 * the caller
2084 */
2085 static uint_t
2086 usb_ac_traverse_all_units(usb_ac_state_t *uacp, uint_t dir,
2087 uint_t search_target, uint_t channel, uint_t control,
2088 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2089 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2090 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2091 {
2092 uint_t unit, start_type, id;
2093
2094 start_type = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_INPUT_TERMINAL :
2095 USB_AUDIO_OUTPUT_TERMINAL;
2096
2097 /* keep track of recursion */
2098 if ((*depth)++ > USB_AC_MAX_DEPTH) {
2099 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2100 "Unit topology too complex, giving up");
2101
2102 return (USB_AC_ID_NONE);
2103 }
2104
2105 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2106 /* is this an IT or OT? */
2107 if (uacp->usb_ac_unit_type[unit] != start_type) {
2108
2109 continue;
2110 }
2111
2112 /* start at streaming term types */
2113 if (dir & USB_AUDIO_PLAY) {
2114 usb_audio_input_term_descr_t *d =
2115 uacp->usb_ac_units[unit].acu_descriptor;
2116 if (d->wTerminalType !=
2117 USB_AUDIO_TERM_TYPE_STREAMING) {
2118
2119 continue;
2120 }
2121 } else {
2122 usb_audio_output_term_descr_t *d =
2123 uacp->usb_ac_units[unit].acu_descriptor;
2124 if (d->wTerminalType !=
2125 USB_AUDIO_TERM_TYPE_STREAMING) {
2126
2127 continue;
2128 }
2129 }
2130
2131 /* find units connected to this unit */
2132 id = usb_ac_traverse_connections(uacp, unit, dir,
2133 search_target, channel, control, all_or_one, count,
2134 arg1, depth, func);
2135
2136 if ((all_or_one == USB_AC_FIND_ONE) &&
2137 (id != USB_AC_ID_NONE)) {
2138 unit = id;
2139
2140 break;
2141 }
2142 }
2143
2144 (*depth)--;
2145
2146 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2147 }
2148
2149
2150 /*
2151 * usb_ac_set_monitor_gain_control:
2152 * search for a feature unit between output terminal (OT) and
2153 * input terminal. We are looking for a path between
2154 * for example a microphone and a speaker through a feature unit
2155 * and mixer
2156 */
2157 static uint_t
2158 usb_ac_set_monitor_gain_control(usb_ac_state_t *uacp, uint_t dir,
2159 uint_t search_target, uint_t channel, uint_t control,
2160 uint_t all_or_one, uint_t *count, uint_t arg1,
2161 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2162 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2163 {
2164 uint_t unit, id;
2165 uint_t depth = 0;
2166
2167
2168 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2169 usb_audio_output_term_descr_t *d =
2170 uacp->usb_ac_units[unit].acu_descriptor;
2171
2172 /* is this an OT and not stream type? */
2173 if ((uacp->usb_ac_unit_type[unit] ==
2174 USB_AUDIO_OUTPUT_TERMINAL) &&
2175 (d->wTerminalType != USB_AUDIO_TERM_TYPE_STREAMING)) {
2176
2177 /* find units connected to this unit */
2178 id = usb_ac_traverse_connections(uacp, unit, dir,
2179 search_target, channel, control, all_or_one, count,
2180 arg1, &depth, func);
2181
2182 if ((all_or_one == USB_AC_FIND_ONE) &&
2183 (id != USB_AC_ID_NONE)) {
2184
2185 break;
2186 }
2187 }
2188 }
2189
2190 ASSERT(depth == 0);
2191
2192 return (id);
2193 }
2194
2195
2196 /*
2197 * usb_ac_push/pop_unit
2198 * add/remove unit ID to the traverse path
2199 */
2200 static void
2201 usb_ac_push_unit_id(usb_ac_state_t *uacp, uint_t unit)
2202 {
2203 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index++] =
2204 (uchar_t)unit;
2205 ASSERT(uacp->usb_ac_traverse_path_index < uacp->usb_ac_max_unit);
2206 }
2207
2208
2209 /* ARGSUSED */
2210 static void
2211 usb_ac_pop_unit_id(usb_ac_state_t *uacp, uint_t unit)
2212 {
2213 uacp->usb_ac_traverse_path[uacp->usb_ac_traverse_path_index--] = 0;
2214 }
2215
2216
2217 /*
2218 * usb_ac_show_traverse_path:
2219 * display entire path, just for debugging
2220 */
2221 static void
2222 usb_ac_show_traverse_path(usb_ac_state_t *uacp)
2223 {
2224 int i;
2225
2226 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2227 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2228 "traverse path %d: unit=%d type=%d",
2229 i, uacp->usb_ac_traverse_path[i],
2230 uacp->usb_ac_unit_type[uacp->usb_ac_traverse_path[i]]);
2231 }
2232 }
2233
2234
2235 /*
2236 * usb_ac_check_path:
2237 * check for a specified type in the traverse path
2238 */
2239 static int
2240 usb_ac_check_path(usb_ac_state_t *uacp, uint_t type)
2241 {
2242 int i;
2243
2244 for (i = 0; i < uacp->usb_ac_traverse_path_index; i++) {
2245 uint_t unit = uacp->usb_ac_traverse_path[i];
2246
2247 if (uacp->usb_ac_unit_type[unit] == type) {
2248
2249 return (USB_SUCCESS);
2250 }
2251 }
2252
2253 return (USB_FAILURE);
2254 }
2255
2256
2257 /*
2258 * usb_ac_traverse_connections:
2259 * traverse all units and for each unit with the right type, call
2260 * func. If the func returns a success and search == USB_AC_FIND_ONE,
2261 * we are done. If all is set then we continue until we terminate
2262 * and input or output terminal.
2263 * For audio play, we traverse columns starting from an input terminal
2264 * to an output terminal while for record we traverse rows from output
2265 * terminal to input terminal.
2266 */
2267 static uint_t
2268 usb_ac_traverse_connections(usb_ac_state_t *uacp, uint_t start_unit, uint_t dir,
2269 uint_t search_target, uint_t channel, uint_t control,
2270 uint_t all_or_one, uint_t *count, uint_t arg1, uint_t *depth,
2271 int (*func)(usb_ac_state_t *uacp, uint_t unit, uint_t dir,
2272 uint_t channel, uint_t control, uint_t arg1, uint_t *depth))
2273 {
2274 uint_t unit, id;
2275 uint_t done = (dir & USB_AUDIO_PLAY) ? USB_AUDIO_OUTPUT_TERMINAL :
2276 USB_AUDIO_INPUT_TERMINAL;
2277
2278
2279 /* keep track of recursion depth */
2280 if ((*depth)++ > USB_AC_MAX_DEPTH) {
2281 USB_DPRINTF_L1(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2282 "Unit topology too complex, giving up");
2283
2284 return (USB_AC_ID_NONE);
2285 }
2286
2287 usb_ac_push_unit_id(uacp, start_unit);
2288
2289 for (unit = 1; unit < uacp->usb_ac_max_unit; unit++) {
2290 uint_t entry = (dir & USB_AUDIO_PLAY) ?
2291 uacp->usb_ac_connections[unit][start_unit] :
2292 uacp->usb_ac_connections[start_unit][unit];
2293
2294 if (entry) {
2295 USB_DPRINTF_L3(PRINT_MASK_ALL,
2296 uacp->usb_ac_log_handle,
2297 "start=%d unit=%d entry=%d type=%d "
2298 "done=%d found=%d",
2299 start_unit, unit, entry, search_target, done,
2300 uacp->usb_ac_unit_type[unit]);
2301
2302 /* did we find a matching type? */
2303 if (uacp->usb_ac_unit_type[unit] == search_target) {
2304 USB_DPRINTF_L3(PRINT_MASK_ALL,
2305 uacp->usb_ac_log_handle,
2306 "match: dir=%d unit=%d type=%d",
2307 dir, unit, search_target);
2308
2309 /* yes, no apply function to this unit */
2310 if (func(uacp, unit, dir, channel,
2311 control, arg1, depth) == USB_SUCCESS) {
2312 (*count)++;
2313
2314 USB_DPRINTF_L3(PRINT_MASK_ALL,
2315 uacp->usb_ac_log_handle,
2316 "func returned success, "
2317 "unit=%d all=%d", unit,
2318 all_or_one);
2319
2320 /* are we done? */
2321 if (all_or_one == USB_AC_FIND_ONE) {
2322
2323 break;
2324 }
2325 }
2326 }
2327
2328 /* did we find the terminating unit */
2329 if (uacp->usb_ac_unit_type[unit] == done) {
2330
2331 continue;
2332 }
2333 id = usb_ac_traverse_connections(uacp, unit, dir,
2334 search_target, channel, control,
2335 all_or_one, count, arg1, depth, func);
2336 if ((id != USB_AC_ID_NONE) &&
2337 (all_or_one == USB_AC_FIND_ONE)) {
2338 unit = id;
2339
2340 break;
2341 }
2342 }
2343 }
2344
2345 (*depth)--;
2346 usb_ac_pop_unit_id(uacp, start_unit);
2347
2348 return ((unit < uacp->usb_ac_max_unit) ? unit : USB_AC_ID_NONE);
2349 }
2350
2351
2352 /*
2353 * Event Management
2354 *
2355 * usb_ac_disconnect_event_cb:
2356 * The device has been disconnected. we either wait for
2357 * detach or a reconnect event.
2358 */
2359 static int
2360 usb_ac_disconnect_event_cb(dev_info_t *dip)
2361 {
2362 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2363 usb_ac_statep, ddi_get_instance(dip));
2364
2365 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2366 "usb_ac_disconnect_event_cb:start");
2367
2368 usb_ac_serialize_access(uacp);
2369 mutex_enter(&uacp->usb_ac_mutex);
2370
2371 /* setting to disconnect state will prevent replumbing */
2372 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2373
2374 if (uacp->usb_ac_busy_count) {
2375 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2376 "device was disconnected while busy. "
2377 "Data may have been lost");
2378 }
2379 mutex_exit(&uacp->usb_ac_mutex);
2380
2381 usb_ac_release_access(uacp);
2382 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2383 "usb_ac_disconnect_event_cb:done");
2384
2385
2386 return (USB_SUCCESS);
2387 }
2388
2389
2390 /*
2391 * usb_ac_cpr_suspend:
2392 */
2393 static int
2394 usb_ac_cpr_suspend(dev_info_t *dip)
2395 {
2396 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2397 usb_ac_statep, ddi_get_instance(dip));
2398
2399 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2400 "usb_ac_cpr_suspend: Begin");
2401
2402 mutex_enter(&uacp->usb_ac_mutex);
2403 uacp->usb_ac_dev_state = USB_DEV_SUSPENDED;
2404 mutex_exit(&uacp->usb_ac_mutex);
2405
2406 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2407 "usb_ac_cpr_suspend: End");
2408
2409 return (USB_SUCCESS);
2410 }
2411
2412
2413
2414 /*
2415 * usb_ac_reconnect_event_cb:
2416 * The device was disconnected but this instance not detached, probably
2417 * because the device was busy.
2418 * if the same device, continue with restoring state
2419 * We should either be in the unplumbed state or the plumbed open
2420 * state.
2421 */
2422 static int
2423 usb_ac_reconnect_event_cb(dev_info_t *dip)
2424 {
2425 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2426 usb_ac_statep, ddi_get_instance(dip));
2427
2428 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2429 "usb_ac_reconnect_event_cb:begain");
2430
2431 mutex_enter(&uacp->usb_ac_mutex);
2432 mutex_exit(&uacp->usb_ac_mutex);
2433
2434 usb_ac_serialize_access(uacp);
2435
2436 /* check the plumbing state */
2437 mutex_enter(&uacp->usb_ac_mutex);
2438 uacp->usb_ac_busy_count++;
2439 if (uacp->usb_ac_plumbing_state ==
2440 USB_AC_STATE_PLUMBED) {
2441 mutex_exit(&uacp->usb_ac_mutex);
2442 usb_ac_restore_device_state(dip, uacp);
2443 mutex_enter(&uacp->usb_ac_mutex);
2444 }
2445 uacp->usb_ac_busy_count--;
2446
2447 if (uacp->usb_ac_busy_count) {
2448 USB_DPRINTF_L0(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2449 "busy device has been reconnected");
2450 }
2451
2452 mutex_exit(&uacp->usb_ac_mutex);
2453
2454 usb_ac_release_access(uacp);
2455 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2456 "usb_ac_reconnect_event_cb:done");
2457
2458 return (USB_SUCCESS);
2459 }
2460
2461
2462 /*
2463 * usb_ac_cpr_resume:
2464 * Restore device state
2465 */
2466 static void
2467 usb_ac_cpr_resume(dev_info_t *dip)
2468 {
2469 usb_ac_state_t *uacp = (usb_ac_state_t *)ddi_get_soft_state(
2470 usb_ac_statep, ddi_get_instance(dip));
2471
2472 USB_DPRINTF_L4(PRINT_MASK_EVENTS, uacp->usb_ac_log_handle,
2473 "usb_ac_cpr_resume");
2474
2475 usb_ac_serialize_access(uacp);
2476
2477 usb_ac_restore_device_state(dip, uacp);
2478
2479 usb_ac_release_access(uacp);
2480 }
2481
2482
2483 /*
2484 * usb_ac_restore_device_state:
2485 * Set original configuration of the device
2486 * enable wrq - this starts new transactions on the control pipe
2487 */
2488 static void
2489 usb_ac_restore_device_state(dev_info_t *dip, usb_ac_state_t *uacp)
2490 {
2491 usb_ac_power_t *uacpm;
2492 int rval;
2493
2494 USB_DPRINTF_L4(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
2495 "usb_ac_restore_device_state:");
2496
2497 usb_ac_pm_busy_component(uacp);
2498 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2499
2500 /* Check if we are talking to the same device */
2501 if (usb_check_same_device(dip, uacp->usb_ac_log_handle,
2502 USB_LOG_L0, PRINT_MASK_ALL,
2503 USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) {
2504 usb_ac_pm_idle_component(uacp);
2505
2506 /* change the device state from suspended to disconnected */
2507 mutex_enter(&uacp->usb_ac_mutex);
2508 uacp->usb_ac_dev_state = USB_DEV_DISCONNECTED;
2509 mutex_exit(&uacp->usb_ac_mutex);
2510
2511 return;
2512 }
2513
2514 mutex_enter(&uacp->usb_ac_mutex);
2515 uacpm = uacp->usb_ac_pm;
2516 if (uacpm) {
2517 if (uacpm->acpm_wakeup_enabled) {
2518 mutex_exit(&uacp->usb_ac_mutex);
2519
2520 if ((rval = usb_handle_remote_wakeup(uacp->usb_ac_dip,
2521 USB_REMOTE_WAKEUP_ENABLE)) != USB_SUCCESS) {
2522
2523 USB_DPRINTF_L4(PRINT_MASK_ATTA,
2524 uacp->usb_ac_log_handle,
2525 "usb_ac_restore_device_state: "
2526 "remote wakeup "
2527 "enable failed, rval=%d", rval);
2528 }
2529
2530 mutex_enter(&uacp->usb_ac_mutex);
2531 }
2532 }
2533
2534 /* prevent unplumbing */
2535 uacp->usb_ac_busy_count++;
2536 uacp->usb_ac_dev_state = USB_DEV_ONLINE;
2537 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_PLUMBED) {
2538 (void) usb_ac_restore_audio_state(uacp, 0);
2539 }
2540 uacp->usb_ac_busy_count--;
2541 mutex_exit(&uacp->usb_ac_mutex);
2542 usb_ac_pm_idle_component(uacp);
2543 }
2544
2545
2546 /*
2547 * usb_ac_am_restore_state
2548 */
2549 static void
2550 usb_ac_am_restore_state(void *arg)
2551 {
2552 usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
2553
2554 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2555 "usb_ac_am_restore_state: Begin");
2556
2557 usb_ac_serialize_access(uacp);
2558
2559 mutex_enter(&uacp->usb_ac_mutex);
2560
2561 if (uacp->usb_ac_plumbing_state ==
2562 USB_AC_STATE_PLUMBED_RESTORING) {
2563 mutex_exit(&uacp->usb_ac_mutex);
2564
2565 /*
2566 * allow hid and usb_as to restore themselves
2567 * (some handshake would have been preferable though)
2568 */
2569 delay(USB_AC_RESTORE_DELAY);
2570
2571 usb_restore_engine(uacp);
2572
2573 mutex_enter(&uacp->usb_ac_mutex);
2574 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
2575 }
2576
2577 /* allow unplumbing */
2578 uacp->usb_ac_busy_count--;
2579 mutex_exit(&uacp->usb_ac_mutex);
2580
2581 usb_ac_release_access(uacp);
2582
2583 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2584 "usb_ac_am_restore_state: End");
2585 }
2586
2587
2588 /*
2589 * usb_ac_restore_audio_state:
2590 */
2591 static int
2592 usb_ac_restore_audio_state(usb_ac_state_t *uacp, int flag)
2593 {
2594 ASSERT(mutex_owned(&uacp->usb_ac_mutex));
2595
2596
2597 switch (uacp->usb_ac_plumbing_state) {
2598 case USB_AC_STATE_PLUMBED:
2599 uacp->usb_ac_plumbing_state =
2600 USB_AC_STATE_PLUMBED_RESTORING;
2601
2602 break;
2603 case USB_AC_STATE_UNPLUMBED:
2604
2605 return (USB_SUCCESS);
2606 case USB_AC_STATE_PLUMBED_RESTORING:
2607 default:
2608
2609 return (USB_FAILURE);
2610 }
2611
2612 /*
2613 * increment busy_count again, it will be decremented
2614 * in usb_ac_am_restore_state
2615 */
2616 uacp->usb_ac_busy_count++;
2617
2618 if (flag & USB_FLAGS_SLEEP) {
2619 mutex_exit(&uacp->usb_ac_mutex);
2620 usb_ac_am_restore_state((void *)uacp);
2621 mutex_enter(&uacp->usb_ac_mutex);
2622 } else {
2623 mutex_exit(&uacp->usb_ac_mutex);
2624 if (usb_async_req(uacp->usb_ac_dip,
2625 usb_ac_am_restore_state,
2626 (void *)uacp, USB_FLAGS_SLEEP) != USB_SUCCESS) {
2627
2628 mutex_enter(&uacp->usb_ac_mutex);
2629 uacp->usb_ac_busy_count--;
2630
2631 return (USB_FAILURE);
2632 }
2633 mutex_enter(&uacp->usb_ac_mutex);
2634 }
2635
2636 return (USB_SUCCESS);
2637 }
2638
2639
2640 /*
2641 * Mixer Callback Management
2642 * NOTE: all mixer callbacks are serialized. we cannot be closed while
2643 * we are in the middle of a callback. There needs to be a
2644 * teardown first. We cannot be unplumbed as long as we are
2645 * still open.
2646 *
2647 * usb_ac_setup:
2648 * Send setup to usb_as if the first setup
2649 * Check power is done in usb_ac_send_as_cmd()
2650 */
2651 static int
2652 usb_ac_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2653 {
2654 int rval = USB_SUCCESS;
2655
2656
2657 mutex_enter(&uacp->usb_ac_mutex);
2658
2659 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2660 mutex_exit(&uacp->usb_ac_mutex);
2661
2662 return (USB_FAILURE);
2663 }
2664 mutex_exit(&uacp->usb_ac_mutex);
2665
2666 usb_ac_serialize_access(uacp);
2667
2668
2669 rval = usb_ac_do_setup(uacp, engine);
2670
2671 usb_ac_release_access(uacp);
2672
2673 return (rval);
2674 }
2675
2676
2677 /*
2678 * usb_ac_do_setup:
2679 * Wrapper function for usb_ac_setup which can be called
2680 * either from audio framework for usb_ac_set_format
2681 */
2682 static int
2683 usb_ac_do_setup(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2684 {
2685 usb_ac_streams_info_t *streams_infop = NULL;
2686
2687
2688 mutex_enter(&uacp->usb_ac_mutex);
2689
2690
2691 streams_infop = (usb_ac_streams_info_t *)engine->streams;
2692
2693 /*
2694 * Handle multiple setup calls. Pass the setup call to usb_as only
2695 * the first time so isoc pipe will be opened only once
2696 */
2697 if (streams_infop->acs_setup_teardown_count++) {
2698 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2699 "usb_ac_do_setup: more than one setup, cnt=%d",
2700 streams_infop->acs_setup_teardown_count);
2701
2702 mutex_exit(&uacp->usb_ac_mutex);
2703
2704 return (USB_SUCCESS);
2705 }
2706
2707 /* Send setup command to usb_as */
2708 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SETUP, 0) !=
2709 USB_SUCCESS) {
2710 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2711 "usb_ac_do_setup: failure");
2712
2713 streams_infop->acs_setup_teardown_count--;
2714
2715 mutex_exit(&uacp->usb_ac_mutex);
2716
2717 return (USB_FAILURE);
2718 }
2719
2720 mutex_exit(&uacp->usb_ac_mutex);
2721
2722 return (USB_SUCCESS);
2723 }
2724
2725
2726 /*
2727 * usb_ac_teardown:
2728 * Send teardown to usb_as if the last teardown
2729 * Check power is done in usb_ac_send_as_cmd()
2730 * NOTE: allow teardown when disconnected
2731 */
2732 static void
2733 usb_ac_teardown(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2734 {
2735
2736 usb_ac_streams_info_t *streams_infop = NULL;
2737
2738 usb_ac_serialize_access(uacp);
2739
2740
2741 streams_infop = engine->streams;
2742
2743
2744 mutex_enter(&uacp->usb_ac_mutex);
2745
2746
2747
2748 /* There should be at least one matching setup call */
2749 ASSERT(streams_infop->acs_setup_teardown_count);
2750
2751 /*
2752 * Handle multiple setup/teardown calls. Pass the call to usb_as
2753 * only this is the last teardown so that isoc pipe is closed
2754 * only once
2755 */
2756 if (--(streams_infop->acs_setup_teardown_count)) {
2757 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2758 "usb_ac_teardown: more than one setup/teardown, "
2759 "cnt=%d",
2760 streams_infop->acs_setup_teardown_count);
2761
2762 goto done;
2763 }
2764
2765 /* Send teardown command to usb_as */
2766 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_TEARDOWN,
2767 (void *)NULL) != USB_SUCCESS) {
2768
2769 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2770 "usb_ac_teardown: failure");
2771
2772 streams_infop->acs_setup_teardown_count++;
2773
2774
2775 goto done;
2776 }
2777 done:
2778
2779 mutex_exit(&uacp->usb_ac_mutex);
2780
2781 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2782 "usb_ac_teardown: End");
2783 usb_ac_release_access(uacp);
2784 }
2785
2786
2787 /*
2788 * usb_ac_set_monitor_gain:
2789 * called for each output terminal which supports
2790 * from usb_ac_traverse_connections
2791 */
2792 static int
2793 usb_ac_set_monitor_gain(usb_ac_state_t *uacp, uint_t unit,
2794 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2795 {
2796 usb_audio_output_term_descr_t *d =
2797 uacp->usb_ac_units[unit].acu_descriptor;
2798
2799 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2800 "usb_ac_set_monitor_gain: ");
2801
2802 /* log how we got here */
2803 usb_ac_push_unit_id(uacp, unit);
2804 usb_ac_show_traverse_path(uacp);
2805 usb_ac_pop_unit_id(uacp, unit);
2806
2807 /* we only care about the ITs connected to real hw inputs */
2808 switch (d->wTerminalType) {
2809 case USB_AUDIO_TERM_TYPE_STREAMING:
2810
2811 return (USB_FAILURE);
2812
2813 case USB_AUDIO_TERM_TYPE_DT_MICROPHONE:
2814 case USB_AUDIO_TERM_TYPE_PERS_MICROPHONE:
2815 case USB_AUDIO_TERM_TYPE_OMNI_DIR_MICROPHONE:
2816 case USB_AUDIO_TERM_TYPE_MICROPHONE_ARRAY:
2817 case USB_AUDIO_TERM_TYPE_PROCESSING_MIC_ARRAY:
2818 default:
2819
2820 break;
2821 }
2822
2823 /*
2824 * we can only do this if the microphone is mixed into the
2825 * audio output so look for a mixer first
2826 */
2827 if (usb_ac_check_path(uacp, USB_AUDIO_MIXER_UNIT) ==
2828 USB_SUCCESS) {
2829 int i, id;
2830
2831 /* now look for a feature unit */
2832 for (i = uacp->usb_ac_traverse_path_index - 1; i >= 0;
2833 i--) {
2834 id = uacp->usb_ac_traverse_path[i];
2835
2836 switch (uacp->usb_ac_unit_type[id]) {
2837 case USB_AUDIO_MIXER_UNIT:
2838
2839 /* the FU should be before the mixer */
2840 return (USB_FAILURE);
2841
2842 case USB_AUDIO_FEATURE_UNIT:
2843 /*
2844 * now set the volume
2845 */
2846 if (usb_ac_set_gain(uacp, id, dir, channel,
2847 control, gain, depth) != USB_SUCCESS) {
2848
2849 /* try master channel */
2850 if (usb_ac_set_gain(uacp, id, dir,
2851 0, control, gain, depth) !=
2852 USB_SUCCESS) {
2853
2854 return (USB_FAILURE);
2855 }
2856 }
2857
2858 return (USB_SUCCESS);
2859
2860 default:
2861 continue;
2862 }
2863 }
2864 }
2865
2866 return (USB_FAILURE);
2867 }
2868
2869
2870 /*
2871 * usb_ac_set_gain is called for each feature unit which supports
2872 * the requested controls from usb_ac_traverse_connections
2873 * we still need to check whether this unit supports the requested
2874 * control.
2875 */
2876 static int
2877 usb_ac_set_gain(usb_ac_state_t *uacp, uint_t featureID,
2878 uint_t dir, uint_t channel, uint_t control, uint_t gain, uint_t *depth)
2879 {
2880 short max, min, current;
2881
2882 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2883 "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
2884 featureID, dir, channel, control, gain);
2885
2886 if (usb_ac_feature_unit_check(uacp, featureID,
2887 dir, channel, control, gain, depth) != USB_SUCCESS) {
2888
2889 return (USB_FAILURE);
2890 }
2891
2892 if (usb_ac_get_maxmin_volume(uacp, channel,
2893 USB_AUDIO_GET_MAX, dir, featureID, &max) != USB_SUCCESS) {
2894 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2895 "usb_ac_set_gain: getting max gain failed");
2896
2897 return (USB_FAILURE);
2898 }
2899
2900 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2901 "usb_ac_set_gain: channel %d, max=%d", channel, max);
2902
2903 if (usb_ac_get_maxmin_volume(uacp, channel,
2904 USB_AUDIO_GET_MIN, dir, featureID, &min) != USB_SUCCESS) {
2905 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2906 "usb_ac_set_gain: getting min gain failed");
2907
2908 return (USB_FAILURE);
2909 }
2910
2911 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2912 "usb_ac_set_gain: channel=%d, min=%d", channel, min);
2913
2914 if (usb_ac_get_maxmin_volume(uacp, channel,
2915 USB_AUDIO_GET_CUR, dir, featureID, ¤t) != USB_SUCCESS) {
2916 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2917 "usb_ac_set_gain: getting cur gain failed");
2918
2919 return (USB_FAILURE);
2920 }
2921
2922 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2923 "usb_ac_set_gain: channel=%d, cur=%d", channel, current);
2924
2925 /*
2926 * Set the gain for a channel. The audio mixer calculates the
2927 * impact, if any, on the channel's gain.
2928 *
2929 * 0 <= gain <= AUDIO_MAX_GAIN
2930 *
2931 * channel #, 0 == left, 1 == right
2932 */
2933
2934 if (gain == 0) {
2935 gain = USB_AUDIO_VOLUME_SILENCE;
2936 } else {
2937 gain = max - ((max - min) * (AF_MAX_GAIN - gain))/AF_MAX_GAIN;
2938 }
2939
2940 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2941 "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
2942 channel, dir, max, min, gain);
2943
2944 if (usb_ac_set_volume(uacp, channel, gain, dir,
2945 featureID) != USB_SUCCESS) {
2946 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2947 "usb_ac_set_gain: setting volume failed");
2948
2949 return (USB_FAILURE);
2950 }
2951
2952 /* just curious, read it back, device may round up/down */
2953 if (usb_ac_get_maxmin_volume(uacp, channel,
2954 USB_AUDIO_GET_CUR, dir, featureID, ¤t) != USB_SUCCESS) {
2955 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2956 "usb_ac_set_gain: getting cur gain failed");
2957 }
2958
2959 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
2960 "usb_ac_set_gain done: "
2961 "id=%d channel=%d, cur=%d gain=%d", featureID, channel,
2962 (ushort_t)current, (ushort_t)gain);
2963
2964 return (USB_SUCCESS);
2965 }
2966
2967
2968 /*
2969 * usb_ac_set_format
2970 * This mixer callback initiates a command to be sent to
2971 * usb_as to select an alternate with the passed characteristics
2972 * and also to set the sample frequency.
2973 * Note that this may be called when a playing is going on in
2974 * the streaming interface. To handle that, first stop
2975 * playing/recording, close the pipe by sending a teardown
2976 * command, send the set_format command down and then reopen
2977 * the pipe. Note : (1) audio framework will restart play/record
2978 * after a set_format command. (2) Check power is done in
2979 * usb_ac_send_as_cmd().
2980 */
2981 int
2982 usb_ac_set_format(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
2983 {
2984 usb_ac_streams_info_t *streams_infop = NULL;
2985 usb_audio_formats_t format;
2986 int old_setup_teardown_count = 0;
2987
2988 mutex_enter(&uacp->usb_ac_mutex);
2989 streams_infop = (usb_ac_streams_info_t *)engine->streams;
2990
2991 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
2992 mutex_exit(&uacp->usb_ac_mutex);
2993
2994 return (USB_FAILURE);
2995 }
2996 mutex_exit(&uacp->usb_ac_mutex);
2997
2998 usb_ac_serialize_access(uacp);
2999 mutex_enter(&uacp->usb_ac_mutex);
3000
3001 bzero(&format, sizeof (usb_audio_formats_t));
3002
3003 /* save format info */
3004 format.fmt_n_srs = 1;
3005 format.fmt_srs = (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);
3065 fail:
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 */
3079 static int
3080 usb_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 */
3136 void
3137 usb_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 */
3172 static int
3173 usb_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 */
3215 static void
3216 usb_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 */
3244 static int
3245 usb_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 */
3300 static int
3301 usb_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 */
3356 int
3357 usb_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 */
3421 static int
3422 usb_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 */
3453 static void
3454 usb_ac_serialize_access(usb_ac_state_t *uacp)
3455 {
3456 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3457 }
3458
3459 static void
3460 usb_ac_release_access(usb_ac_state_t *uacp)
3461 {
3462 usb_release_access(uacp->usb_ac_ser_acc);
3463 }
3464
3465
3466 static void
3467 usb_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
3498 static void
3499 usb_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 */
3524 static void
3525 usb_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 */
3566 static int
3567 usb_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
3609 OUT:
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
3619 static void
3620 usb_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
3630 static int
3631 usb_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
3657 OUT:
3658 return (rv);
3659 }
3660
3661
3662
3663 static void
3664 usb_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
3674 static int
3675 usb_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
3698 OUT:
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 */
3711 static void
3712 usb_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*/
3751 static int
3752 usb_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
3856 static int
3857 usb_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 */
3976 static int
3977 usb_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
4170 static int
4171 usb_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 */
4267 static int
4268 usb_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 */
4334 static int
4335 usb_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 */
4355 static void
4356 usb_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_formats[n]);
4374 }
4375
4376 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4377 "usb_ac_print_reg_data: End");
4378 }
4379
4380
4381 static int
4382 usb_ac_online_siblings(usb_ac_state_t *uacp)
4383 {
4384 dev_info_t *pdip, *child_dip;
4385 int rval = USB_SUCCESS;
4386
4387 ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4388
4389 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4390 "usb_ac_online_siblings:start");
4391
4392 pdip = ddi_get_parent(uacp->usb_ac_dip);
4393
4394 child_dip = ddi_get_child(pdip);
4395 while (child_dip != NULL) {
4396
4397 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4398 "usb_ac_online_siblings: onlining %s%d ref=%d",
4399 ddi_driver_name(child_dip),
4400 ddi_get_instance(child_dip),
4401 DEVI(child_dip)->devi_ref);
4402
4403 /* Online the child_dip of usb_as and hid, if not already */
4404 if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) ||
4405 (strcmp(ddi_driver_name(child_dip), "hid") == 0)) {
4406
4407 mutex_exit(&uacp->usb_ac_mutex);
4408 if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
4409 NDI_SUCCESS) {
4410 USB_DPRINTF_L3(PRINT_MASK_ALL,
4411 uacp->usb_ac_log_handle,
4412 "usb_ac_online_siblings:failed to online"
4413 "device %s%d", ddi_driver_name(child_dip),
4414 ddi_get_instance(child_dip));
4415
4416 /* only onlining usb_as is fatal */
4417 if (strcmp(ddi_driver_name(child_dip),
4418 "usb_as") == 0) {
4419 mutex_enter(&uacp->usb_ac_mutex);
4420 rval = USB_FAILURE;
4421 break;
4422 }
4423 }
4424 mutex_enter(&uacp->usb_ac_mutex);
4425 }
4426 child_dip = ddi_get_next_sibling(child_dip);
4427 }
4428
4429 return (rval);
4430 }
4431
4432
4433 /*
4434 * hold all audio children before or after plumbing
4435 * online usb_as and hid, if not already
4436 */
4437 static void
4438 usb_ac_hold_siblings(usb_ac_state_t *uacp)
4439 {
4440 int circ;
4441 dev_info_t *pdip, *child_dip;
4442
4443 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4444 "usb_ac_hold_siblings:start");
4445
4446 /* hold all siblings and ourselves */
4447 pdip = ddi_get_parent(uacp->usb_ac_dip);
4448
4449 /* hold the children */
4450 ndi_devi_enter(pdip, &circ);
4451 child_dip = ddi_get_child(pdip);
4452 while (child_dip != NULL) {
4453 ndi_hold_devi(child_dip);
4454
4455 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4456 "usb_ac_hold_siblings: held %s%d ref=%d",
4457 ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4458 DEVI(child_dip)->devi_ref);
4459
4460 child_dip = ddi_get_next_sibling(child_dip);
4461 }
4462 ndi_devi_exit(pdip, circ);
4463 }
4464
4465
4466 /*
4467 * release all audio children before or after plumbing
4468 */
4469 static void
4470 usb_ac_rele_siblings(usb_ac_state_t *uacp)
4471 {
4472 int circ;
4473 dev_info_t *pdip, *child_dip;
4474
4475 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4476 "usb_ac_rele_siblings: start");
4477
4478 /* release all siblings and ourselves */
4479 pdip = ddi_get_parent(uacp->usb_ac_dip);
4480 ndi_devi_enter(pdip, &circ);
4481 child_dip = ddi_get_child(pdip);
4482 while (child_dip != NULL) {
4483 ndi_rele_devi(child_dip);
4484
4485 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4486 "usb_ac_rele_siblings: released %s%d ref=%d",
4487 ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4488 DEVI(child_dip)->devi_ref);
4489
4490 child_dip = ddi_get_next_sibling(child_dip);
4491 }
4492 ndi_devi_exit(pdip, circ);
4493 }
4494 static void
4495 usb_restore_engine(usb_ac_state_t *statep)
4496 {
4497 usb_audio_eng_t *engp;
4498 int i;
4499
4500 for (i = 0; i < USB_AC_ENG_MAX; i++) {
4501
4502 mutex_enter(&statep->usb_ac_mutex);
4503 engp = &statep->engines[i];
4504 mutex_exit(&statep->usb_ac_mutex);
4505
4506 if (engp->af_engp == NULL)
4507 continue;
4508 if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
4509 USB_DPRINTF_L2(PRINT_MASK_ATTA,
4510 statep->usb_ac_log_handle,
4511 "usb_restore_engine:set format fail, i=%d", i);
4512 return;
4513 }
4514 if (engp->started) {
4515 (void) usb_engine_start(engp);
4516 }
4517
4518 }
4519
4520 (void) usb_ac_ctrl_restore(statep);
4521 }
4522
4523
4524 /*
4525 * get the maximum format specification the device supports
4526 */
4527 static void
4528 usb_ac_max_fmt(usb_as_registration_t *reg_data,
4529 usb_audio_format_t *fmtp)
4530 {
4531
4532 uint_t ch = 0, sr = 0, prec = 0, enc = 0;
4533 int i;
4534
4535 usb_audio_formats_t *reg_formats = reg_data->reg_formats;
4536
4537 /* format priority: channels, sample rate, precision, encoding */
4538 for (i = 0; i < reg_data->reg_n_formats; i++) {
4539 uint_t val, fmt_sr;
4540 int n, keep;
4541
4542 val = reg_formats[i].fmt_chns;
4543 if (val < ch)
4544 continue;
4545 if (val > ch)
4546 keep = 1;
4547
4548 for (n = 0, fmt_sr = 0; n < reg_formats[i].fmt_n_srs; n++) {
4549 if (fmt_sr < reg_formats[i].fmt_srs[n]) {
4550 fmt_sr = reg_formats[i].fmt_srs[n];
4551 }
4552 }
4553 if (!keep && fmt_sr < sr)
4554 continue;
4555 if (fmt_sr > sr)
4556 keep = 1;
4557
4558 val = reg_formats[i].fmt_precision;
4559 if (!keep && (val < prec))
4560 continue;
4561 if (val > prec)
4562 keep = 1;
4563
4564 val = reg_formats[i].fmt_encoding;
4565 if (!keep && (val < enc))
4566 continue;
4567
4568 ch = reg_formats[i].fmt_chns;
4569 sr = fmt_sr;
4570 prec = reg_formats[i].fmt_precision;
4571 enc = reg_formats[i].fmt_encoding;
4572 }
4573
4574 fmtp->ch = ch;
4575 fmtp->sr = sr;
4576 fmtp->prec = prec;
4577 fmtp->enc = enc;
4578 }
4579
4580
4581 static void
4582 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
4583 {
4584 if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
4585 return;
4586
4587 audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
4588 audio_engine_free(engp->af_engp);
4589
4590 mutex_enter(&engp->lock);
4591 engp->af_engp = NULL;
4592 engp->streams = NULL;
4593 mutex_exit(&engp->lock);
4594
4595 mutex_destroy(&engp->lock);
4596 cv_destroy(&engp->usb_audio_cv);
4597 }
4598
4599
4600 static int
4601 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t *asinfo)
4602 {
4603 audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
4604 usb_audio_eng_t *engp;
4605 audio_engine_t *af_engp;
4606 int rv = USB_FAILURE;
4607 int dir = asinfo->acs_streams_reg.reg_mode;
4608 uint_t defgain;
4609
4610 if (asinfo->acs_rcvd_reg_data == 0) {
4611
4612 return (USB_SUCCESS);
4613 }
4614 if (dir == USB_AUDIO_PLAY) {
4615 engp = &(uacp->engines[0]);
4616 } else {
4617 engp = &(uacp->engines[1]);
4618 }
4619
4620 cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL);
4621
4622 mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
4623
4624 mutex_enter(&engp->lock);
4625
4626 engp->af_eflags =
4627 (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
4628 engp->statep = uacp;
4629
4630 /* Set the format for the engine */
4631 usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
4632
4633 /* init the default gain */
4634 defgain = asinfo->acs_default_gain;
4635 if (engp->fmt.ch == 2) {
4636 engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
4637 } else {
4638 engp->af_defgain = defgain;
4639 }
4640 engp->streams = asinfo;
4641
4642 mutex_exit(&engp->lock);
4643
4644 af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
4645 if (af_engp == NULL) {
4646
4647 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4648 "audio_engine_alloc failed");
4649 goto OUT;
4650 }
4651 ASSERT(engp->af_engp == 0);
4652
4653 mutex_enter(&engp->lock);
4654 engp->af_engp = af_engp;
4655 mutex_exit(&engp->lock);
4656
4657 audio_engine_set_private(af_engp, engp);
4658 audio_dev_add_engine(af_devp, af_engp);
4659
4660 /*
4661 * Set the format for this engine
4662 */
4663 if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
4664 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4665 "set format failed, dir = %d", dir);
4666 goto OUT;
4667 }
4668 rv = USB_SUCCESS;
4669
4670 OUT:
4671 if (rv != USB_SUCCESS)
4672 usb_ac_rem_eng(uacp, engp);
4673
4674 return (rv);
4675 }
4676
4677
4678 static int
4679 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
4680 {
4681 usb_audio_ctrl_t *ctrlp;
4682 int rv = USB_SUCCESS;
4683 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4684 "usb_ac_ctrl_set_defaults:begin");
4685
4686 for (int i = 0; i < CTL_NUM; i++) {
4687 ctrlp = statep->controls[i];
4688 if (!ctrlp) {
4689 continue;
4690 }
4691 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4692 USB_DPRINTF_L2(PRINT_MASK_ATTA,
4693 statep->usb_ac_log_handle,
4694 "usb_ac_ctrl_set_defaults:control write failed");
4695 rv = USB_FAILURE;
4696 }
4697
4698 }
4699 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4700 "usb_ac_ctrl_set_defaults:end");
4701 return (rv);
4702 }
4703
4704
4705 static int
4706 usb_ac_ctrl_restore(usb_ac_state_t *statep)
4707 {
4708 usb_audio_ctrl_t *ctrlp;
4709 int rv = USB_SUCCESS;
4710
4711 for (int i = 0; i < CTL_NUM; i++) {
4712 ctrlp = statep->controls[i];
4713 if (ctrlp) {
4714 USB_DPRINTF_L3(PRINT_MASK_ATTA,
4715 statep->usb_ac_log_handle,
4716 "usb_ac_ctrl_restore:i = %d", i);
4717 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4718 rv = USB_FAILURE;
4719 }
4720 }
4721 }
4722 return (rv);
4723 }
4724
4725
4726
4727
4728 /*
4729 * moves data between driver buffer and framework/shim buffer
4730 */
4731 static void
4732 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
4733 {
4734 size_t cpsz = sz;
4735 caddr_t *src, *dst;
4736
4737 if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
4738 src = &engp->bufpos;
4739 dst = (caddr_t *)&buf;
4740 } else {
4741 src = (caddr_t *)&buf;
4742 dst = &engp->bufpos;
4743 }
4744
4745 /*
4746 * Wrap. If sz is exactly the remainder of the buffer
4747 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
4748 * the second memcpy() should have no effect, with bufpos updated
4749 * to the head of the buffer.
4750 */
4751 if (engp->bufpos + sz >= engp->bufendp) {
4752 cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
4753 (void) memcpy(*dst, *src, cpsz);
4754
4755
4756 buf = (caddr_t)buf + cpsz;
4757 engp->bufpos = engp->bufp;
4758 cpsz = sz - cpsz;
4759 }
4760
4761 if (cpsz) {
4762 (void) memcpy(*dst, *src, cpsz);
4763
4764
4765 engp->bufpos += cpsz;
4766 }
4767 engp->bufio_count++;
4768 }
4769
4770
4771 /*
4772 * control read callback
4773 */
4774 static int
4775 usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
4776 {
4777 usb_audio_ctrl_t *ctrlp = arg;
4778
4779 mutex_enter(&ctrlp->ctrl_mutex);
4780 *cvalp = ctrlp->cval;
4781 mutex_exit(&ctrlp->ctrl_mutex);
4782
4783 return (0);
4784 }
4785
4786
4787 /*
4788 * stereo level control callback
4789 */
4790 static int
4791 usb_audio_write_stero_rec(void *arg, uint64_t cval)
4792 {
4793 usb_audio_ctrl_t *ctrlp = arg;
4794 usb_ac_state_t *statep = ctrlp->statep;
4795 int rv = EIO;
4796 int left, right;
4797 uint_t count = 0;
4798
4799
4800 left = AUDIO_CTRL_STEREO_LEFT(cval);
4801 right = AUDIO_CTRL_STEREO_RIGHT(cval);
4802
4803 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4804 right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4805
4806 return (EINVAL);
4807 }
4808
4809 mutex_enter(&ctrlp->ctrl_mutex);
4810 ctrlp->cval = cval;
4811 mutex_exit(&ctrlp->ctrl_mutex);
4812
4813 mutex_enter(&statep->usb_ac_mutex);
4814 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4815 USB_AUDIO_FEATURE_UNIT, 1,
4816 USB_AUDIO_VOLUME_CONTROL,
4817 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4818
4819 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4820 USB_AUDIO_FEATURE_UNIT, 2,
4821 USB_AUDIO_VOLUME_CONTROL,
4822 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4823 rv = 0;
4824
4825 done:
4826 mutex_exit(&statep->usb_ac_mutex);
4827 return (rv);
4828 }
4829
4830 static int
4831 usb_audio_write_ster_vol(void *arg, uint64_t cval)
4832 {
4833 usb_audio_ctrl_t *ctrlp = arg;
4834 usb_ac_state_t *statep = ctrlp->statep;
4835 int rv = EIO;
4836 int left, right;
4837 uint_t count = 0;
4838
4839 left = AUDIO_CTRL_STEREO_LEFT(cval);
4840 right = AUDIO_CTRL_STEREO_RIGHT(cval);
4841
4842 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4843 right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4844 return (EINVAL);
4845 }
4846
4847 mutex_enter(&ctrlp->ctrl_mutex);
4848 ctrlp->cval = cval;
4849 mutex_exit(&ctrlp->ctrl_mutex);
4850
4851
4852 mutex_enter(&statep->usb_ac_mutex);
4853 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4854 USB_AUDIO_FEATURE_UNIT, 1,
4855 USB_AUDIO_VOLUME_CONTROL,
4856 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4857
4858 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4859 USB_AUDIO_FEATURE_UNIT, 2,
4860 USB_AUDIO_VOLUME_CONTROL,
4861 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4862 rv = 0;
4863
4864 OUT:
4865 mutex_exit(&statep->usb_ac_mutex);
4866 return (rv);
4867 }
4868
4869
4870 /*
4871 * mono level control callback
4872 */
4873 static int
4874 usb_audio_write_mono_vol(void *arg, uint64_t cval)
4875 {
4876 usb_audio_ctrl_t *ctrlp = arg;
4877 usb_ac_state_t *statep = ctrlp->statep;
4878 int rv = EIO;
4879 int gain;
4880
4881 uint_t count = 0;
4882
4883 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4884 return (EINVAL);
4885 }
4886
4887 mutex_enter(&ctrlp->ctrl_mutex);
4888 ctrlp->cval = cval;
4889 mutex_exit(&ctrlp->ctrl_mutex);
4890
4891 gain = (int)(cval);
4892
4893 mutex_enter(&statep->usb_ac_mutex);
4894 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4895 USB_AUDIO_FEATURE_UNIT, 1,
4896 USB_AUDIO_VOLUME_CONTROL,
4897 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4898
4899 rv = 0;
4900 OUT:
4901 mutex_exit(&statep->usb_ac_mutex);
4902
4903 return (rv);
4904 }
4905
4906
4907 /*
4908 * mono level control callback
4909 */
4910 static int
4911 usb_audio_write_monitor_gain(void *arg, uint64_t cval)
4912 {
4913 usb_audio_ctrl_t *ctrlp = arg;
4914 usb_ac_state_t *statep = ctrlp->statep;
4915 int rv = EIO;
4916 int gain;
4917 uint_t count = 0;
4918
4919 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4920
4921 return (EINVAL);
4922 }
4923
4924 mutex_enter(&ctrlp->ctrl_mutex);
4925 ctrlp->cval = cval;
4926 mutex_exit(&ctrlp->ctrl_mutex);
4927
4928 gain = (int)(cval);
4929
4930 mutex_enter(&statep->usb_ac_mutex);
4931 (void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
4932 USB_AUDIO_INPUT_TERMINAL, 1,
4933 USB_AUDIO_VOLUME_CONTROL,
4934 USB_AC_FIND_ALL, &count, gain,
4935 usb_ac_set_monitor_gain);
4936
4937 rv = 0;
4938 OUT:
4939 mutex_exit(&statep->usb_ac_mutex);
4940 return (rv);
4941 }
4942
4943 static int
4944 usb_audio_write_mono_rec(void *arg, uint64_t cval)
4945 {
4946 usb_audio_ctrl_t *ctrlp = arg;
4947 usb_ac_state_t *statep = ctrlp->statep;
4948 int rv = EIO;
4949 int gain;
4950
4951 uint_t count = 0;
4952
4953 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4954
4955 return (EINVAL);
4956 }
4957
4958 mutex_enter(&ctrlp->ctrl_mutex);
4959 ctrlp->cval = cval;
4960 mutex_exit(&ctrlp->ctrl_mutex);
4961
4962 gain = (int)(cval);
4963
4964 mutex_enter(&statep->usb_ac_mutex);
4965 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4966 USB_AUDIO_FEATURE_UNIT, 1,
4967 USB_AUDIO_VOLUME_CONTROL,
4968 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4969
4970 rv = 0;
4971
4972 mutex_exit(&statep->usb_ac_mutex);
4973 return (rv);
4974 }
4975
4976 static int
4977 usb_audio_write_mic_boost(void *arg, uint64_t cval)
4978 {
4979 usb_audio_ctrl_t *ctrlp = arg;
4980
4981 mutex_enter(&ctrlp->ctrl_mutex);
4982 ctrlp->cval = cval;
4983 mutex_exit(&ctrlp->ctrl_mutex);
4984 /* do nothing here */
4985 return (0);
4986 }
4987
4988 static int
4989 usb_audio_write_rec_src(void *arg, uint64_t cval)
4990 {
4991 usb_audio_ctrl_t *ctrlp = arg;
4992 usb_ac_state_t *statep = ctrlp->statep;
4993 int rv = 0;
4994
4995 if (cval & ~(statep->usb_ac_input_ports))
4996 return (EINVAL);
4997
4998 mutex_enter(&ctrlp->ctrl_mutex);
4999 ctrlp->cval = cval;
5000 mutex_exit(&ctrlp->ctrl_mutex);
5001
5002 mutex_enter(&statep->usb_ac_mutex);
5003 if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
5004
5005 USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
5006 "usb_audio_write_rec_src: failed");
5007 rv = EINVAL;
5008 }
5009 mutex_exit(&statep->usb_ac_mutex);
5010 rv = 0;
5011
5012 OUT:
5013 return (rv);
5014
5015 }
5016
5017
5018 int
5019 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
5020 {
5021 short muteval;
5022 int rval;
5023
5024 uint_t count;
5025 muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
5026 count = 0;
5027 /* only support AUDIO_PLAY */
5028
5029 mutex_enter(&statep->usb_ac_mutex);
5030 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
5031 USB_AUDIO_FEATURE_UNIT, 0,
5032 USB_AUDIO_MUTE_CONTROL,
5033 USB_AC_FIND_ALL, &count, muteval,
5034 usb_ac_set_mute);
5035 mutex_exit(&statep->usb_ac_mutex);
5036
5037 rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
5038
5039 return (rval);
5040 }
5041
5042
5043 /*
5044 * port selection control callback
5045 */
5046 /*
5047 * audio control registration related routines
5048 */
5049
5050 static usb_audio_ctrl_t *
5051 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
5052 {
5053 audio_ctrl_desc_t desc;
5054 audio_ctrl_wr_t fn;
5055 usb_audio_ctrl_t *pc;
5056
5057 pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
5058
5059 mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
5060
5061 bzero(&desc, sizeof (desc));
5062
5063 switch (num) {
5064 case CTL_VOLUME_MONO:
5065 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5066 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5067 desc.acd_minvalue = 0;
5068 desc.acd_maxvalue = AF_MAX_GAIN;
5069 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5070 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5071 fn = usb_audio_write_mono_vol;
5072 break;
5073
5074 case CTL_VOLUME_STERO:
5075 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5076 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5077 desc.acd_minvalue = 0;
5078 desc.acd_maxvalue = AF_MAX_GAIN;
5079 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5080 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5081 fn = usb_audio_write_ster_vol;
5082
5083 break;
5084
5085 case CTL_REC_MONO:
5086 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5087 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5088 desc.acd_minvalue = 0;
5089 desc.acd_maxvalue = AF_MAX_GAIN;
5090 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5091 | AUDIO_CTRL_FLAG_RW;
5092 fn = usb_audio_write_mono_rec;
5093 break;
5094 case CTL_REC_STERO:
5095
5096 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5097 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5098 desc.acd_minvalue = 0;
5099 desc.acd_maxvalue = AF_MAX_GAIN;
5100 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5101 | AUDIO_CTRL_FLAG_RW;
5102 fn = usb_audio_write_stero_rec;
5103 break;
5104
5105 case CTL_MONITOR_GAIN:
5106
5107 desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
5108 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5109 desc.acd_minvalue = 0;
5110 desc.acd_maxvalue = AF_MAX_GAIN;
5111 desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
5112 |AUDIO_CTRL_FLAG_RW;
5113 fn = usb_audio_write_monitor_gain;
5114 break;
5115
5116 case CTL_MIC_BOOST:
5117
5118 desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
5119 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
5120 desc.acd_minvalue = 0;
5121 desc.acd_maxvalue = 1;
5122 desc.acd_flags = AUDIO_CTRL_FLAG_RW;
5123 fn = usb_audio_write_mic_boost;
5124 break;
5125 case CTL_REC_SRC:
5126
5127 desc.acd_name = AUDIO_CTRL_ID_RECSRC;
5128 desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
5129 desc.acd_minvalue = statep->usb_ac_input_ports;
5130 desc.acd_maxvalue = statep->usb_ac_input_ports;
5131 desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
5132 for (int i = 0; usb_audio_dtypes[i]; i++) {
5133 desc.acd_enum[i] = usb_audio_dtypes[i];
5134 }
5135
5136 fn = usb_audio_write_rec_src;
5137 break;
5138
5139
5140
5141 default:
5142
5143 break;
5144 }
5145
5146 mutex_enter(&pc->ctrl_mutex);
5147
5148 pc->statep = statep;
5149 pc->cval = val;
5150 pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
5151 usb_audio_ctrl_read, fn, pc);
5152
5153 mutex_exit(&pc->ctrl_mutex);
5154
5155 mutex_enter(&statep->usb_ac_mutex);
5156 statep->controls[num] = pc;
5157 mutex_exit(&statep->usb_ac_mutex);
5158
5159
5160 return (pc);
5161 }
5162
5163
5164 static void
5165 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
5166 {
5167 kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
5168 }
5169
5170 static void
5171 usb_ac_rem_controls(usb_ac_state_t *statep)
5172 {
5173 usb_audio_ctrl_t *ctrlp;
5174
5175 for (int i = 0; i < CTL_NUM; i++) {
5176 ctrlp = statep->controls[i];
5177 if (ctrlp) {
5178 if (ctrlp->af_ctrlp != NULL)
5179 audio_dev_del_control(ctrlp->af_ctrlp);
5180
5181 usb_audio_ctrl_free(ctrlp);
5182 mutex_enter(&statep->usb_ac_mutex);
5183 statep->controls[i] = NULL;
5184 mutex_exit(&statep->usb_ac_mutex);
5185 }
5186 }
5187
5188 }
5189
5190
5191 static int
5192 usb_ac_add_controls(usb_ac_state_t *statep)
5193 {
5194 int rv = USB_FAILURE;
5195 usb_audio_format_t *format;
5196
5197
5198 if (statep->engines[0].af_engp) {
5199 /* Init controls for play format */
5200 format = &(statep->engines[0].fmt);
5201 if (format->ch == 2) {
5202 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
5203 statep->engines[0].af_defgain);
5204 } else {
5205 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
5206 statep->engines[0].af_defgain);
5207 }
5208
5209 }
5210
5211 /* Init controls for rec format */
5212 if (statep->engines[1].af_engp) {
5213 format = &(statep->engines[1].fmt);
5214 if (format->ch == 2) {
5215 (void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
5216 statep->engines[1].af_defgain);
5217 } else {
5218 (void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
5219 statep->engines[1].af_defgain);
5220 }
5221
5222 /* Add monitor control */
5223 {
5224 (void) usb_audio_ctrl_alloc(statep,
5225 CTL_MONITOR_GAIN, 0);
5226 }
5227
5228 /* Add ports control */
5229 {
5230 (void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
5231 statep->usb_ac_input_ports);
5232 }
5233
5234 }
5235
5236
5237 rv = USB_SUCCESS;
5238
5239 OUT:
5240 if (rv != USB_SUCCESS)
5241 usb_ac_rem_controls(statep);
5242 return (rv);
5243 }
5244
5245
5246
5247
5248
5249 /*ARGSUSED*/
5250 static int
5251 usb_audio_unregister(usb_ac_state_t *statep)
5252 {
5253 int i;
5254
5255 if (statep == NULL)
5256 return (USB_SUCCESS);
5257
5258 if (statep->usb_ac_audio_dev == NULL)
5259 return (USB_SUCCESS);
5260
5261 if ((statep->flags & AF_REGISTERED) &&
5262 audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
5263 return (USB_FAILURE);
5264 }
5265 mutex_enter(&statep->usb_ac_mutex);
5266 statep->flags &= ~AF_REGISTERED;
5267 mutex_exit(&statep->usb_ac_mutex);
5268
5269 for (i = 0; i < USB_AC_ENG_MAX; i++)
5270 usb_ac_rem_eng(statep, &statep->engines[i]);
5271
5272 usb_ac_rem_controls(statep);
5273
5274 audio_dev_free(statep->usb_ac_audio_dev);
5275
5276 mutex_enter(&statep->usb_ac_mutex);
5277 statep->usb_ac_audio_dev = NULL;
5278 mutex_exit(&statep->usb_ac_mutex);
5279
5280 return (USB_SUCCESS);
5281 }
5282
5283
5284 static int
5285 usb_audio_register(usb_ac_state_t *statep) {
5286 audio_dev_t *af_devp;
5287 int rv = USB_FAILURE;
5288 int n;
5289
5290 af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
5291 audio_dev_set_description(af_devp, "USB Audio");
5292 audio_dev_set_version(af_devp, "1.0");
5293
5294 mutex_enter(&statep->usb_ac_mutex);
5295 statep->usb_ac_audio_dev = af_devp;
5296 mutex_exit(&statep->usb_ac_mutex);
5297
5298
5299 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
5300 if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
5301 != USB_SUCCESS) {
5302 USB_DPRINTF_L2(PRINT_MASK_ATTA,
5303 statep->usb_ac_log_handle,
5304 "usb_audio_register: add engine n =%d failed", n);
5305 goto OUT;
5306 }
5307 }
5308
5309
5310 if (usb_ac_add_controls(statep) != USB_SUCCESS) {
5311 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5312 "usb_audio_register: add controls failed");
5313 goto OUT;
5314 }
5315
5316 if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
5317 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5318 "usb_audio_register: set defaults failed");
5319 goto OUT;
5320 }
5321
5322 if (audio_dev_register(af_devp) != DDI_SUCCESS) {
5323 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5324 "audio_dev_register() failed");
5325 goto OUT;
5326 }
5327 mutex_enter(&statep->usb_ac_mutex);
5328 statep->flags |= AF_REGISTERED;
5329 mutex_exit(&statep->usb_ac_mutex);
5330
5331 rv = USB_SUCCESS;
5332
5333 OUT:
5334 if (rv != USB_SUCCESS) {
5335 (void) usb_audio_unregister(statep);
5336 }
5337 return (rv);
5338 }
5339
5340
5341 int
5342 usb_ac_get_audio(void *handle, void *buf, int samples)
5343 {
5344 usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5345 usb_audio_eng_t *engp = &(statep->engines[0]);
5346 unsigned reqframes = samples >> engp->frsmshift;
5347 unsigned frames;
5348 unsigned i;
5349 size_t sz;
5350 caddr_t bp = buf;
5351
5352 mutex_enter(&engp->lock);
5353 if (!engp->started) {
5354 mutex_exit(&engp->lock);
5355
5356 return (0);
5357 }
5358 engp->busy = B_TRUE;
5359 mutex_exit(&engp->lock);
5360
5361 /* break requests from the driver into fragment sized chunks */
5362 for (i = 0; i < reqframes; i += frames) {
5363
5364 mutex_enter(&engp->lock);
5365 frames = reqframes - i;
5366 if (frames > engp->fragfr)
5367 frames = engp->fragfr;
5368
5369 sz = (frames << engp->frsmshift) << engp->smszshift;
5370
5371 /* must move data before updating framework */
5372 usb_eng_bufio(engp, bp, sz);
5373 engp->frames += frames;
5374 bp += sz;
5375
5376 mutex_exit(&engp->lock);
5377 }
5378
5379 mutex_enter(&engp->lock);
5380 engp->io_count++;
5381 engp->busy = B_FALSE;
5382 cv_signal(&engp->usb_audio_cv);
5383 mutex_exit(&engp->lock);
5384
5385 return (samples);
5386 }
5387
5388
5389
5390 void
5391 usb_ac_send_audio(void *handle, void *buf, int samples)
5392 {
5393 usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5394 usb_audio_eng_t *engp = &(statep->engines[1]);
5395 unsigned reqframes = samples >> engp->frsmshift;
5396 unsigned frames;
5397 unsigned i;
5398 size_t sz;
5399 caddr_t bp = buf;
5400
5401 mutex_enter(&engp->lock);
5402
5403 if (!engp->started) {
5404
5405 mutex_exit(&engp->lock);
5406 return;
5407 }
5408 engp->busy = B_TRUE;
5409 mutex_exit(&engp->lock);
5410
5411 /* break requests from the driver into fragment sized chunks */
5412 for (i = 0; i < reqframes; i += frames) {
5413 mutex_enter(&engp->lock);
5414
5415 frames = reqframes - i;
5416 if (frames > engp->fragfr)
5417 frames = engp->fragfr;
5418
5419 sz = (frames << engp->frsmshift) << engp->smszshift;
5420
5421 /* must move data before updating framework */
5422 usb_eng_bufio(engp, bp, sz);
5423 engp->frames += frames;
5424 bp += sz;
5425
5426 mutex_exit(&engp->lock);
5427 }
5428
5429 mutex_enter(&engp->lock);
5430 engp->io_count++;
5431 engp->busy = B_FALSE;
5432 cv_signal(&engp->usb_audio_cv);
5433 mutex_exit(&engp->lock);
5434 }
5435
5436
5437 /*
5438 * **************************************************************************
5439 * audio framework engine callbacks
5440 */
5441 static int
5442 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
5443 {
5444 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5445 usb_ac_state_t *statep = engp->statep;
5446 int rv = EIO;
5447
5448 _NOTE(ARGUNUSED(flag));
5449
5450 if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
5451
5452 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5453 "usb_ac_open() failed");
5454 return (EIO);
5455 }
5456
5457 mutex_enter(&engp->lock);
5458
5459 engp->intrate = 150;
5460 engp->sampsz = engp->fmt.prec / 8;
5461 engp->framesz = engp->sampsz * engp->fmt.ch;
5462
5463 engp->frsmshift = engp->fmt.ch / 2;
5464 engp->smszshift = engp->sampsz / 2;
5465
5466 /*
5467 * In order to match the requested number of samples per interrupt
5468 * from SADA drivers when computing the fragment size,
5469 * we need to first truncate the floating point result from
5470 * sample rate * channels / intr rate
5471 * then adjust up to an even number, before multiplying it
5472 * with the sample size
5473 */
5474 engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
5475 if (engp->fragsz & 1)
5476 engp->fragsz++;
5477 engp->fragsz *= engp->sampsz;
5478 engp->fragfr = engp->fragsz / engp->framesz;
5479
5480 engp->nfrags = 10;
5481 engp->bufsz = engp->fragsz * engp->nfrags;
5482
5483 engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
5484 engp->bufpos = engp->bufp;
5485 engp->bufendp = engp->bufp + engp->bufsz;
5486 engp->frames = 0;
5487 engp->io_count = 0;
5488 engp->bufio_count = 0;
5489 engp->started = B_FALSE;
5490 engp->busy = B_FALSE;
5491
5492 *nframesp = engp->nfrags * engp->fragfr;
5493 *bufp = engp->bufp;
5494
5495 mutex_exit(&engp->lock);
5496
5497 if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
5498 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5499 "device setup failed");
5500 goto OUT;
5501 }
5502
5503
5504
5505 mutex_enter(&statep->usb_ac_mutex);
5506 statep->flags |= AD_SETUP;
5507 mutex_exit(&statep->usb_ac_mutex);
5508
5509 rv = 0;
5510
5511
5512 OUT:
5513 if (rv != 0)
5514 usb_engine_close(arg);
5515
5516 return (rv);
5517 }
5518
5519
5520 static void
5521 usb_engine_close(void *arg)
5522 {
5523 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5524 usb_ac_state_t *statep = engp->statep;
5525
5526 mutex_enter(&engp->lock);
5527 while (engp->busy) {
5528 cv_wait(&engp->usb_audio_cv, &engp->lock);
5529 }
5530
5531 mutex_exit(&engp->lock);
5532
5533 if (statep->flags & AD_SETUP) {
5534 usb_ac_teardown(statep, engp);
5535 mutex_enter(&statep->usb_ac_mutex);
5536 statep->flags &= ~AD_SETUP;
5537 mutex_exit(&statep->usb_ac_mutex);
5538 }
5539 mutex_enter(&engp->lock);
5540
5541 if (engp->bufp != NULL) {
5542 kmem_free(engp->bufp, engp->bufsz);
5543 engp->bufp = NULL;
5544 engp->bufpos = NULL;
5545 engp->bufendp = NULL;
5546 }
5547
5548 mutex_exit(&engp->lock);
5549
5550 usb_ac_close(statep->usb_ac_dip);
5551 }
5552
5553
5554
5555 static int
5556 usb_engine_start(void *arg)
5557 {
5558 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5559 int rv = 0;
5560 int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
5561
5562 mutex_enter(&engp->lock);
5563 engp->started = B_TRUE;
5564 mutex_exit(&engp->lock);
5565
5566 usb_ac_state_t *statep = engp->statep;
5567
5568 start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5569 usb_ac_start_play : usb_ac_start_record;
5570
5571 if ((*start)(statep, engp) != USB_SUCCESS) {
5572 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5573 "failed to start %d engine", engp->af_eflags);
5574 rv = EIO;
5575 }
5576
5577
5578 return (rv);
5579 }
5580
5581
5582 static void
5583 usb_engine_stop(void *arg)
5584 {
5585 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5586
5587 mutex_enter(&engp->lock);
5588 engp->started = B_FALSE;
5589 mutex_exit(&engp->lock);
5590
5591 usb_ac_state_t *statep = engp->statep;
5592 void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
5593
5594 stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5595 usb_ac_stop_play : usb_ac_stop_record;
5596
5597 (*stop)(statep, engp);
5598 }
5599
5600
5601 static uint64_t
5602 usb_engine_count(void *arg)
5603 {
5604 usb_audio_eng_t *engp = arg;
5605 uint64_t val;
5606
5607 mutex_enter(&engp->lock);
5608 val = engp->frames;
5609 mutex_exit(&engp->lock);
5610
5611 return (val);
5612 }
5613
5614
5615 static int
5616 usb_engine_format(void *arg)
5617 {
5618 usb_audio_eng_t *engp = arg;
5619
5620 switch (engp->fmt.enc) {
5621 case USB_AUDIO_FORMAT_TYPE1_MULAW:
5622 return (AUDIO_FORMAT_ULAW);
5623 case USB_AUDIO_FORMAT_TYPE1_ALAW:
5624 return (AUDIO_FORMAT_ALAW);
5625 case USB_AUDIO_FORMAT_TYPE1_PCM8:
5626 return (AUDIO_FORMAT_U8);
5627
5628 case USB_AUDIO_FORMAT_TYPE1_PCM:
5629 break;
5630 default:
5631 return (AUDIO_FORMAT_NONE);
5632 }
5633
5634 switch (engp->fmt.prec) {
5635 case USB_AUDIO_PRECISION_8:
5636 return (AUDIO_FORMAT_S8);
5637 case USB_AUDIO_PRECISION_16:
5638 return (AUDIO_FORMAT_S16_LE);
5639 case USB_AUDIO_PRECISION_24:
5640 return (AUDIO_FORMAT_S24_LE);
5641 case USB_AUDIO_PRECISION_32:
5642 return (AUDIO_FORMAT_S32_LE);
5643 default:
5644 break;
5645 }
5646 return (AUDIO_FORMAT_NONE);
5647
5648
5649 }
5650
5651 static int
5652 usb_engine_channels(void *arg)
5653 {
5654 usb_audio_eng_t *engp = arg;
5655
5656 return (engp->fmt.ch);
5657 }
5658
5659
5660 static int
5661 usb_engine_rate(void *arg)
5662 {
5663 usb_audio_eng_t *engp = arg;
5664
5665 return (engp->fmt.sr);
5666 }
5667
5668
5669 /*ARGSUSED*/
5670 static void
5671 usb_engine_sync(void *arg, unsigned nframes)
5672 {
5673 /* Do nothing */
5674 }
5675
5676
5677 static unsigned
5678 usb_engine_qlen(void *arg)
5679 {
5680 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5681
5682 return (engp->fragfr);
5683 }
5684
5685 /*
5686 * **************************************************************************
5687 * interfaces used by USB audio
5688 */
5689
5690 /*ARGSUSED*/
5691 static int
5692 usb_change_phy_vol(usb_ac_state_t *statep, int value)
5693 {
5694 usb_audio_ctrl_t *ctrlp;
5695 uint64_t cval = 0;
5696 int64_t left, right, delta = 0;
5697
5698 ctrlp = statep->controls[CTL_VOLUME_STERO];
5699
5700 ASSERT(value != 0);
5701
5702 delta = (value < 0)?-1:1;
5703
5704 left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
5705 right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
5706
5707 if (left > AF_MAX_GAIN)
5708 left = AF_MAX_GAIN;
5709 if (right > AF_MAX_GAIN)
5710 right = AF_MAX_GAIN;
5711
5712 if (left < AF_MIN_GAIN)
5713 left = AF_MIN_GAIN;
5714 if (right < AF_MIN_GAIN)
5715 right = AF_MIN_GAIN;
5716
5717 cval = AUDIO_CTRL_STEREO_VAL(left, right);
5718
5719 if (audio_control_write(ctrlp->af_ctrlp, cval)) {
5720 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5721 "updateing control to value 0x%llx by driver failed",
5722 (long long unsigned)cval);
5723 return (USB_FAILURE);
5724 }
5725 return (USB_SUCCESS);
5726 }