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