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_n_srs = 1;
3006 format.fmt_srs = (uint_t *)&(engine->fmt.sr);
3007 format.fmt_chns = (uchar_t)engine->fmt.ch;
3008 format.fmt_precision = (uchar_t)engine->fmt.prec;
3009 format.fmt_encoding = (uchar_t)engine->fmt.enc;
3010
3011 old_setup_teardown_count = streams_infop->acs_setup_teardown_count;
3012
3013 /* isoc pipe not open and playing is not in progress */
3014 if (old_setup_teardown_count) {
3015 streams_infop->acs_setup_teardown_count = 1;
3016
3017 mutex_exit(&uacp->usb_ac_mutex);
3018 usb_ac_release_access(uacp);
3019
3020 usb_ac_stop_play(uacp, engine);
3021 usb_ac_teardown(uacp, engine);
3022
3023 usb_ac_serialize_access(uacp);
3024 mutex_enter(&uacp->usb_ac_mutex);
3025 }
3026
3027 /*
3028 * Set format for the streaming interface with lower write queue
3029 * This boils down to set_alternate interface command in
3030 * usb_as and the reply mp contains the currently active
3031 * alternate number that is stored in the as_req structure
3032 */
3033 if (usb_ac_send_as_cmd(uacp, engine,
3034 USB_AUDIO_SET_FORMAT, &format) != USB_SUCCESS) {
3035 USB_DPRINTF_L2(PRINT_MASK_ALL,
3036 uacp->usb_ac_log_handle,
3037 "usb_ac_set_format: failed");
3038 goto fail;
3039
3040 }
3041 int sample = engine->fmt.sr;
3042
3043 /* Set the sample rate */
3044 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_SET_SAMPLE_FREQ,
3045 &sample) != USB_SUCCESS) {
3046 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3047 "usb_ac_set_format: setting format failed");
3048 goto fail;
3049
3050 }
3051
3052 mutex_exit(&uacp->usb_ac_mutex);
3053
3054 usb_ac_release_access(uacp);
3055
3056 /* This should block until successful */
3057 if (old_setup_teardown_count) {
3058 (void) usb_ac_setup(uacp, engine);
3059 }
3060
3061 mutex_enter(&uacp->usb_ac_mutex);
3062 streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3063 mutex_exit(&uacp->usb_ac_mutex);
3064
3065 return (USB_SUCCESS);
3066 fail:
3067 streams_infop->acs_setup_teardown_count = old_setup_teardown_count;
3068 mutex_exit(&uacp->usb_ac_mutex);
3069 usb_ac_release_access(uacp);
3070
3071 return (USB_FAILURE);
3072
3073 }
3074
3075 /*
3076 * usb_ac_start_play
3077 * Send a start_play command down to usb_as
3078 * Check power is done in usb_ac_send_as_cmd()
3079 */
3080 static int
usb_ac_start_play(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3081 usb_ac_start_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3082 {
3083 int samples;
3084 usb_audio_play_req_t play_req;
3085
3086
3087 mutex_enter(&uacp->usb_ac_mutex);
3088 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3089 mutex_exit(&uacp->usb_ac_mutex);
3090
3091 return (USB_FAILURE);
3092 }
3093 mutex_exit(&uacp->usb_ac_mutex);
3094
3095 usb_ac_serialize_access(uacp);
3096
3097 mutex_enter(&uacp->usb_ac_mutex);
3098
3099
3100
3101 /* Check for continuous sample rate done in usb_as */
3102 samples = engine->fmt.sr * engine->fmt.ch / engine->intrate;
3103 if (samples & engine->fmt.ch) {
3104 samples++;
3105 }
3106
3107 play_req.up_samples = samples;
3108 play_req.up_handle = uacp;
3109
3110 /* Send setup command to usb_as */
3111 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_PLAY,
3112 (void *)&play_req) != USB_SUCCESS) {
3113
3114 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3115 "usb_ac_start_play: failure");
3116
3117 mutex_exit(&uacp->usb_ac_mutex);
3118
3119 usb_ac_release_access(uacp);
3120
3121 return (USB_FAILURE);
3122 }
3123
3124 mutex_exit(&uacp->usb_ac_mutex);
3125
3126 usb_ac_release_access(uacp);
3127
3128 return (USB_SUCCESS);
3129 }
3130
3131
3132 /*
3133 * usb_ac_stop_play:
3134 * Stop the play engine
3135 * called from mixer framework.
3136 */
3137 void
usb_ac_stop_play(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3138 usb_ac_stop_play(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3139 {
3140
3141 if (engine == NULL) {
3142 engine = &(uacp->engines[0]);
3143 }
3144 mutex_enter(&uacp->usb_ac_mutex);
3145 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3146 mutex_exit(&uacp->usb_ac_mutex);
3147
3148 return;
3149 }
3150 mutex_exit(&uacp->usb_ac_mutex);
3151
3152 usb_ac_serialize_access(uacp);
3153 mutex_enter(&uacp->usb_ac_mutex);
3154
3155 /* Send setup command to usb_as */
3156 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_PAUSE_PLAY,
3157 (void *)NULL) != USB_SUCCESS) {
3158
3159 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3160 "usb_ac_do_pause_play: failure");
3161 }
3162
3163 mutex_exit(&uacp->usb_ac_mutex);
3164 usb_ac_release_access(uacp);
3165 }
3166
3167
3168 /*
3169 * usb_ac_start_record:
3170 * Sends a start record command down to usb_as.
3171 * Check power is done in usb_ac_send_as_cmd()
3172 */
3173 static int
usb_ac_start_record(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3174 usb_ac_start_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3175 {
3176
3177
3178 mutex_enter(&uacp->usb_ac_mutex);
3179 if (uacp->usb_ac_dev_state != USB_DEV_ONLINE) {
3180 mutex_exit(&uacp->usb_ac_mutex);
3181
3182 return (USB_FAILURE);
3183 }
3184 mutex_exit(&uacp->usb_ac_mutex);
3185
3186 usb_ac_serialize_access(uacp);
3187 mutex_enter(&uacp->usb_ac_mutex);
3188
3189
3190 /* Send setup command to usb_as */
3191 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_START_RECORD,
3192 (void *)uacp) != USB_SUCCESS) {
3193
3194 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3195 "usb_ac_start_record: failure");
3196
3197 mutex_exit(&uacp->usb_ac_mutex);
3198
3199 usb_ac_release_access(uacp);
3200
3201 return (USB_FAILURE);
3202 }
3203
3204 mutex_exit(&uacp->usb_ac_mutex);
3205 usb_ac_release_access(uacp);
3206
3207 return (USB_SUCCESS);
3208 }
3209
3210
3211 /*
3212 * usb_ac_stop_record:
3213 * Wrapper function for usb_ac_do_stop_record and is
3214 * called form mixer framework.
3215 */
3216 static void
usb_ac_stop_record(usb_ac_state_t * uacp,usb_audio_eng_t * engine)3217 usb_ac_stop_record(usb_ac_state_t *uacp, usb_audio_eng_t *engine)
3218 {
3219
3220 usb_ac_serialize_access(uacp);
3221 mutex_enter(&uacp->usb_ac_mutex);
3222
3223 /* Send setup command to usb_as */
3224 if (usb_ac_send_as_cmd(uacp, engine, USB_AUDIO_STOP_RECORD,
3225 NULL) != USB_SUCCESS) {
3226
3227 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3228 "usb_ac_do_stop_record: failure");
3229 }
3230
3231 mutex_exit(&uacp->usb_ac_mutex);
3232 usb_ac_release_access(uacp);
3233 }
3234
3235
3236 /*
3237 * Helper Functions for Mixer callbacks
3238 *
3239 * usb_ac_get_maxmin_volume:
3240 * Send USBA command down to get the maximum or minimum gain balance
3241 * Calculate min or max gain balance and return that. Return
3242 * USB_FAILURE for failure cases
3243 */
3244 /* ARGSUSED */
3245 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)3246 usb_ac_get_maxmin_volume(usb_ac_state_t *uacp, uint_t channel, int cmd,
3247 int dir, int feature_unitID, short *max_or_minp)
3248 {
3249 mblk_t *data = NULL;
3250 usb_cr_t cr;
3251 usb_cb_flags_t cb_flags;
3252
3253
3254 mutex_exit(&uacp->usb_ac_mutex);
3255
3256 if (usb_pipe_sync_ctrl_xfer(
3257 uacp->usb_ac_dip,
3258 uacp->usb_ac_default_ph,
3259 USB_DEV_REQ_DEV_TO_HOST |
3260 USB_DEV_REQ_TYPE_CLASS |
3261 USB_DEV_REQ_RCPT_IF, /* bmRequestType */
3262 cmd, /* bRequest */
3263 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3264 /* feature unit and id */
3265 (feature_unitID << 8)| uacp->usb_ac_ifno, /* wIndex */
3266 2, /* wLength */
3267 &data,
3268 USB_ATTRS_NONE,
3269 &cr, &cb_flags,
3270 USB_FLAGS_SLEEP) != USB_SUCCESS) {
3271 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3272 "usb_ac_get_maxmin_volume: failed, "
3273 "cr=%d, cb=0x%x cmd=%d, data=0x%p",
3274 cr, cb_flags, cmd, (void *)data);
3275
3276 freemsg(data);
3277 mutex_enter(&uacp->usb_ac_mutex);
3278
3279 return (USB_FAILURE);
3280 }
3281
3282 mutex_enter(&uacp->usb_ac_mutex);
3283 ASSERT(MBLKL(data) == 2);
3284
3285 *max_or_minp = (*(data->b_rptr+1) << 8) | *data->b_rptr;
3286
3287 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3288 "usb_ac_get_maxmin_volume: max_or_min=0x%x", *max_or_minp);
3289
3290 freemsg(data);
3291
3292 return (USB_SUCCESS);
3293 }
3294
3295
3296 /*
3297 * usb_ac_set_volume:
3298 * Send USBA command down to set the gain balance
3299 */
3300 /* ARGSUSED */
3301 static int
usb_ac_set_volume(usb_ac_state_t * uacp,uint_t channel,short gain,int dir,int feature_unitID)3302 usb_ac_set_volume(usb_ac_state_t *uacp, uint_t channel, short gain, int dir,
3303 int feature_unitID)
3304 {
3305 mblk_t *data = NULL;
3306 usb_cr_t cr;
3307 usb_cb_flags_t cb_flags;
3308 int rval = USB_FAILURE;
3309
3310
3311 mutex_exit(&uacp->usb_ac_mutex);
3312
3313 /* Construct the mblk_t from gain for sending to USBA */
3314 data = allocb(4, BPRI_HI);
3315 if (!data) {
3316 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3317 "usb_ac_set_volume: allocate data failed");
3318 mutex_enter(&uacp->usb_ac_mutex);
3319
3320 return (USB_FAILURE);
3321 }
3322
3323
3324
3325 *(data->b_wptr++) = (char)gain;
3326 *(data->b_wptr++) = (char)(gain >> 8);
3327
3328 if ((rval = usb_pipe_sync_ctrl_xfer(
3329 uacp->usb_ac_dip,
3330 uacp->usb_ac_default_ph,
3331 USB_DEV_REQ_HOST_TO_DEV |
3332 USB_DEV_REQ_TYPE_CLASS |
3333 USB_DEV_REQ_RCPT_IF, /* bmRequestType */
3334 USB_AUDIO_SET_CUR, /* bRequest */
3335 (USB_AUDIO_VOLUME_CONTROL << 8) | channel, /* wValue */
3336 /* feature unit and id */
3337 (feature_unitID << 8) | uacp->usb_ac_ifno, /* wIndex */
3338 2, /* wLength */
3339 &data, 0,
3340 &cr, &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
3341 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3342 "usb_ac_set_volume: failed, cr=%d cb=0x%x",
3343 cr, cb_flags);
3344 }
3345
3346 freemsg(data);
3347 mutex_enter(&uacp->usb_ac_mutex);
3348
3349 return (rval);
3350 }
3351
3352
3353 /*
3354 * usb_ac_set_mute is called for each unit that supports the
3355 * requested control from usb_ac_traverse_connections
3356 */
3357 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)3358 usb_ac_set_mute(usb_ac_state_t *uacp, uint_t featureID, uint_t dir,
3359 uint_t channel, uint_t control, uint_t muteval, uint_t *depth)
3360 {
3361 mblk_t *data;
3362 usb_cr_t cr;
3363 usb_cb_flags_t cb_flags;
3364 int rval = USB_FAILURE;
3365
3366
3367 if (usb_ac_feature_unit_check(uacp, featureID,
3368 dir, channel, control, 0, depth) != USB_SUCCESS) {
3369
3370 return (USB_FAILURE);
3371 }
3372 mutex_exit(&uacp->usb_ac_mutex);
3373
3374 /* Construct the mblk_t for sending to USBA */
3375 data = allocb(1, BPRI_HI);
3376
3377 if (!data) {
3378 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3379 "usb_ac_set_mute: allocate data failed");
3380 mutex_enter(&uacp->usb_ac_mutex);
3381
3382 return (USB_FAILURE);
3383 }
3384
3385
3386 *(data->b_wptr++) = (char)muteval;
3387
3388 if ((rval = usb_pipe_sync_ctrl_xfer(
3389 uacp->usb_ac_dip,
3390 uacp->usb_ac_default_ph,
3391 USB_DEV_REQ_HOST_TO_DEV |
3392 USB_DEV_REQ_TYPE_CLASS |
3393 USB_DEV_REQ_RCPT_IF, /* bmRequestType */
3394 USB_AUDIO_SET_CUR, /* bRequest */
3395 (USB_AUDIO_MUTE_CONTROL << 8) | channel, /* wValue */
3396 /* feature unit and id */
3397 (featureID << 8) | uacp->usb_ac_ifno, /* wIndex */
3398 1, /* wLength */
3399 &data,
3400 0, /* attributes */
3401 &cr, &cb_flags, 0)) != USB_SUCCESS) {
3402
3403 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3404 "usb_ac_set_mute: failed, cr=%d cb=0x%x", cr, cb_flags);
3405 }
3406 freemsg(data);
3407
3408 mutex_enter(&uacp->usb_ac_mutex);
3409
3410 return (rval);
3411 }
3412
3413
3414 /*
3415 * usb_ac_send_as_cmd:
3416 * Allocate message blk, send a command down to usb_as,
3417 * wait for the reply and free the message
3418 *
3419 * although not really needed to raise power if sending to as
3420 * it seems better to ensure that both interfaces are at full power
3421 */
3422 static int
usb_ac_send_as_cmd(usb_ac_state_t * uacp,usb_audio_eng_t * engine,int cmd,void * arg)3423 usb_ac_send_as_cmd(usb_ac_state_t *uacp, usb_audio_eng_t *engine,
3424 int cmd, void *arg)
3425 {
3426 usb_ac_streams_info_t *streams_infop;
3427 usb_ac_plumbed_t *plumb_infop;
3428 int rv;
3429 int rval;
3430 ldi_handle_t lh;
3431
3432 ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3433 streams_infop = engine->streams;
3434 plumb_infop = streams_infop->acs_plumbed;
3435
3436
3437 lh = plumb_infop->acp_lh;
3438
3439 rv = ldi_ioctl(lh, cmd, (intptr_t)arg, FKIOCTL, kcred, &rval);
3440 if (rv != 0) {
3441 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3442 "usb_ac_send_as_cmd: ldi_ioctl failed, error=%d", rv);
3443
3444 return (USB_FAILURE);
3445 }
3446
3447 return (USB_SUCCESS);
3448 }
3449
3450
3451 /*
3452 * usb_ac_serialize/release_access:
3453 */
3454 static void
usb_ac_serialize_access(usb_ac_state_t * uacp)3455 usb_ac_serialize_access(usb_ac_state_t *uacp)
3456 {
3457 (void) usb_serialize_access(uacp->usb_ac_ser_acc, USB_WAIT, 0);
3458 }
3459
3460 static void
usb_ac_release_access(usb_ac_state_t * uacp)3461 usb_ac_release_access(usb_ac_state_t *uacp)
3462 {
3463 usb_release_access(uacp->usb_ac_ser_acc);
3464 }
3465
3466
3467 static void
usb_ac_pm_busy_component(usb_ac_state_t * usb_ac_statep)3468 usb_ac_pm_busy_component(usb_ac_state_t *usb_ac_statep)
3469 {
3470 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3471
3472 if (usb_ac_statep->usb_ac_pm != NULL) {
3473 mutex_enter(&usb_ac_statep->usb_ac_mutex);
3474 usb_ac_statep->usb_ac_pm->acpm_pm_busy++;
3475
3476 USB_DPRINTF_L4(PRINT_MASK_PM,
3477 usb_ac_statep->usb_ac_log_handle,
3478 "usb_ac_pm_busy_component: %d",
3479 usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3480
3481 mutex_exit(&usb_ac_statep->usb_ac_mutex);
3482
3483 if (pm_busy_component(usb_ac_statep->usb_ac_dip, 0) !=
3484 DDI_SUCCESS) {
3485 mutex_enter(&usb_ac_statep->usb_ac_mutex);
3486 usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3487
3488 USB_DPRINTF_L2(PRINT_MASK_PM,
3489 usb_ac_statep->usb_ac_log_handle,
3490 "usb_ac_pm_busy_component failed: %d",
3491 usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3492
3493 mutex_exit(&usb_ac_statep->usb_ac_mutex);
3494 }
3495 }
3496 }
3497
3498
3499 static void
usb_ac_pm_idle_component(usb_ac_state_t * usb_ac_statep)3500 usb_ac_pm_idle_component(usb_ac_state_t *usb_ac_statep)
3501 {
3502 ASSERT(!mutex_owned(&usb_ac_statep->usb_ac_mutex));
3503
3504 if (usb_ac_statep->usb_ac_pm != NULL) {
3505 if (pm_idle_component(usb_ac_statep->usb_ac_dip, 0) ==
3506 DDI_SUCCESS) {
3507 mutex_enter(&usb_ac_statep->usb_ac_mutex);
3508 ASSERT(usb_ac_statep->usb_ac_pm->acpm_pm_busy > 0);
3509 usb_ac_statep->usb_ac_pm->acpm_pm_busy--;
3510
3511 USB_DPRINTF_L4(PRINT_MASK_PM,
3512 usb_ac_statep->usb_ac_log_handle,
3513 "usb_ac_pm_idle_component: %d",
3514 usb_ac_statep->usb_ac_pm->acpm_pm_busy);
3515
3516 mutex_exit(&usb_ac_statep->usb_ac_mutex);
3517 }
3518 }
3519 }
3520
3521
3522 /*
3523 * handle read from plumbed drivers
3524 */
3525 static void
usb_ac_reader(void * argp)3526 usb_ac_reader(void *argp)
3527 {
3528 usb_ac_plumbed_t *acp = (usb_ac_plumbed_t *)argp;
3529 usb_ac_state_t *uacp = acp->acp_uacp;
3530 ldi_handle_t lh;
3531 mblk_t *mp;
3532 int rv;
3533 timestruc_t tv = {0};
3534
3535 mutex_enter(&uacp->usb_ac_mutex);
3536 lh = acp->acp_lh;
3537 tv.tv_sec = usb_ac_wait_hid;
3538
3539 while (acp->acp_flags & ACP_ENABLED) {
3540 mp = NULL;
3541
3542 mutex_exit(&uacp->usb_ac_mutex);
3543
3544 rv = ldi_getmsg(lh, &mp, &tv);
3545
3546 mutex_enter(&uacp->usb_ac_mutex);
3547
3548 if (rv == ENODEV) {
3549 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3550 "Device is not availabe");
3551 break;
3552 }
3553
3554
3555 if ((acp->acp_flags & ACP_ENABLED) && mp != NULL && rv == 0)
3556 rv = usb_ac_read_msg(acp, mp);
3557
3558 }
3559 mutex_exit(&uacp->usb_ac_mutex);
3560 }
3561
3562
3563 /*
3564 * setup threads to read from the other usb modules that may send unsolicited
3565 * or asynchronous messages, which is only hid currently
3566 */
3567 static int
usb_ac_plumb(usb_ac_plumbed_t * acp)3568 usb_ac_plumb(usb_ac_plumbed_t *acp)
3569 {
3570 usb_ac_state_t *uacp = acp->acp_uacp;
3571 dev_info_t *dip;
3572 dev_info_t *acp_dip;
3573 int acp_inst;
3574 char *acp_name;
3575 char tq_nm[128];
3576 int rv = USB_FAILURE;
3577
3578 mutex_enter(&uacp->usb_ac_mutex);
3579
3580 dip = uacp->usb_ac_dip;
3581
3582 acp_dip = acp->acp_dip;
3583 acp_inst = ddi_get_instance(acp_dip);
3584 acp_name = (char *)ddi_driver_name(acp_dip);
3585
3586 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3587 "usb_ac_plumb:begin");
3588
3589 if (strcmp(acp_name, "hid") != 0) {
3590 rv = USB_SUCCESS;
3591 goto OUT;
3592 }
3593
3594 (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3595 ddi_driver_name(acp_dip), acp_inst);
3596
3597 acp->acp_tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3598 if (acp->acp_tqp == NULL)
3599 goto OUT;
3600
3601 if (ddi_taskq_dispatch(acp->acp_tqp, usb_ac_reader, (void *)acp,
3602 DDI_SLEEP) != DDI_SUCCESS)
3603 goto OUT;
3604
3605 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3606 "usb_ac_plumb: dispatched reader");
3607
3608 rv = USB_SUCCESS;
3609
3610 OUT:
3611 mutex_exit(&uacp->usb_ac_mutex);
3612
3613 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3614 "usb_ac_plumb: done, rv=%d", rv);
3615
3616 return (rv);
3617 }
3618
3619
3620 static void
usb_ac_mux_plumbing_tq(void * arg)3621 usb_ac_mux_plumbing_tq(void *arg)
3622 {
3623 usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3624
3625 if (usb_ac_mux_plumbing(uacp) != USB_SUCCESS)
3626 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3627 "usb_ac_mux_plumbing_tq:failed");
3628 }
3629
3630
3631 static int
usb_ac_do_plumbing(usb_ac_state_t * uacp)3632 usb_ac_do_plumbing(usb_ac_state_t *uacp)
3633 {
3634 dev_info_t *dip = uacp->usb_ac_dip;
3635 int inst = ddi_get_instance(dip);
3636 char tq_nm[128];
3637 int rv = USB_FAILURE;
3638
3639 (void) snprintf(tq_nm, sizeof (tq_nm), "%s_%d_tq",
3640 ddi_driver_name(dip), inst);
3641
3642 uacp->tqp = ddi_taskq_create(dip, tq_nm, 1, TASKQ_DEFAULTPRI, 0);
3643 if (uacp->tqp == NULL) {
3644 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3645 "usb_ac_do_plumbing: ddi_taskq_create failed");
3646 goto OUT;
3647 }
3648
3649 if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_plumbing_tq, (void *)uacp,
3650 DDI_SLEEP) != DDI_SUCCESS) {
3651 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3652 "usb_ac_do_plumbing: ddi_taskq_dispatch failed");
3653 goto OUT;
3654 }
3655
3656 rv = USB_SUCCESS;
3657
3658 OUT:
3659 return (rv);
3660 }
3661
3662
3663
3664 static void
usb_ac_mux_unplumbing_tq(void * arg)3665 usb_ac_mux_unplumbing_tq(void *arg)
3666 {
3667 usb_ac_state_t *uacp = (usb_ac_state_t *)arg;
3668
3669 if (usb_ac_mux_unplumbing(uacp) != USB_SUCCESS)
3670 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3671 "usb_ac_mux_unplumbing:failed");
3672 }
3673
3674
3675 static int
usb_ac_do_unplumbing(usb_ac_state_t * uacp)3676 usb_ac_do_unplumbing(usb_ac_state_t *uacp)
3677 {
3678 int rv = USB_FAILURE;
3679
3680 if (uacp->tqp == NULL)
3681 return (USB_SUCCESS);
3682
3683 if (ddi_taskq_dispatch(uacp->tqp, usb_ac_mux_unplumbing_tq,
3684 (void *)uacp, DDI_SLEEP) != DDI_SUCCESS) {
3685 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3686 "usb_ac_do_unplumbing: ddi_taskq_dispatch failed");
3687 goto OUT;
3688 }
3689
3690 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3691 "usb_ac_do_unplumbing: waiting for unplumb thread");
3692
3693 ddi_taskq_wait(uacp->tqp);
3694 rv = USB_SUCCESS;
3695
3696 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3697 "usb_ac_do_unplumbing: unplumb thread done");
3698
3699 OUT:
3700 if (uacp->tqp != NULL) {
3701 ddi_taskq_destroy(uacp->tqp);
3702 uacp->tqp = NULL;
3703 }
3704 return (rv);
3705 }
3706
3707
3708 /*
3709 * teardown threads to the other usb modules
3710 * and clear structures as part of unplumbing
3711 */
3712 static void
usb_ac_unplumb(usb_ac_plumbed_t * acp)3713 usb_ac_unplumb(usb_ac_plumbed_t *acp)
3714 {
3715 usb_ac_streams_info_t *streams_infop;
3716 usb_ac_state_t *uacp = acp->acp_uacp;
3717
3718
3719 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3720 "usb_ac_unplumb: begin");
3721
3722 if (acp->acp_tqp != NULL) {
3723 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3724 "usb_ac_unplumb: destroying taskq");
3725
3726 ddi_taskq_destroy(acp->acp_tqp);
3727 }
3728
3729 mutex_enter(&uacp->usb_ac_mutex);
3730
3731 if (acp->acp_driver == USB_AS_PLUMBED) {
3732 /*
3733 * we bzero the streams info and plumbed structure
3734 * since there is no guarantee that the next plumbing
3735 * will be identical
3736 */
3737 streams_infop = (usb_ac_streams_info_t *)acp->acp_data;
3738
3739 /* bzero the relevant plumbing structure */
3740 bzero(streams_infop, sizeof (usb_ac_streams_info_t));
3741 }
3742 bzero(acp, sizeof (usb_ac_plumbed_t));
3743
3744 mutex_exit(&uacp->usb_ac_mutex);
3745
3746 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3747 "usb_ac_unplumb: done");
3748 }
3749
3750
3751 /*ARGSUSED*/
3752 static int
usb_ac_mux_plumbing(usb_ac_state_t * uacp)3753 usb_ac_mux_plumbing(usb_ac_state_t *uacp)
3754 {
3755 dev_info_t *dip;
3756
3757 /* get the usb_ac dip */
3758 dip = uacp->usb_ac_dip;
3759
3760 /* Access to the global variables is synchronized */
3761 mutex_enter(&uacp->usb_ac_mutex);
3762
3763 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3764 "usb_ac_mux_plumbing:state = %d",
3765 uacp->usb_ac_plumbing_state);
3766
3767 if (uacp->usb_ac_plumbing_state >= USB_AC_STATE_PLUMBED) {
3768 mutex_exit(&uacp->usb_ac_mutex);
3769 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3770 "usb_ac_mux_plumbing: audio streams driver"
3771 " already plumbed");
3772
3773 return (USB_SUCCESS);
3774 }
3775
3776 /* usb_as and hid should be attached but double check */
3777 if (usb_ac_online_siblings(uacp) != USB_SUCCESS) {
3778 mutex_exit(&uacp->usb_ac_mutex);
3779 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3780 "usb_ac_mux_plumbing:no audio streams driver plumbed");
3781
3782 return (USB_FAILURE);
3783 }
3784
3785 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3786 "usb_ac_mux_plumbing: raising power");
3787 mutex_exit(&uacp->usb_ac_mutex);
3788
3789 /* bring the device to full power */
3790 usb_ac_pm_busy_component(uacp);
3791 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
3792
3793 /* avoid dips disappearing while we are plumbing */
3794 usb_ac_hold_siblings(uacp);
3795
3796 mutex_enter(&uacp->usb_ac_mutex);
3797
3798 /*
3799 * walk all siblings and create the usb_ac<->usb_as and
3800 * usb_ac<->hid streams. return of 0 indicates no or
3801 * partial/failed plumbing
3802 */
3803 if (usb_ac_mux_walk_siblings(uacp) == 0) {
3804 /* pretend that we are plumbed so we can unplumb */
3805 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3806
3807 mutex_exit(&uacp->usb_ac_mutex);
3808
3809 (void) usb_ac_mux_unplumbing(uacp);
3810
3811 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3812 "usb_ac_mux_plumbing: no audio streams driver plumbed");
3813
3814 usb_ac_rele_siblings(uacp);
3815
3816 usb_ac_pm_idle_component(uacp);
3817
3818 return (USB_FAILURE);
3819 }
3820 uacp->usb_ac_plumbing_state = USB_AC_STATE_PLUMBED;
3821
3822 /* restore state if we have already registered with the mixer */
3823 if (uacp->usb_ac_registered_with_mixer) {
3824 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3825 "usb_ac_mux_plumbing:already registered with mixer,"
3826 "restoring state");
3827
3828 (void) usb_ac_restore_audio_state(uacp, USB_FLAGS_SLEEP);
3829
3830 } else if (usb_ac_mixer_registration(uacp) != USB_SUCCESS) {
3831 mutex_exit(&uacp->usb_ac_mutex);
3832
3833 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3834 "usb_ac_mux_plumbing: mixer registration failed");
3835
3836 (void) usb_ac_mux_unplumbing(uacp);
3837
3838 usb_ac_rele_siblings(uacp);
3839
3840 usb_ac_pm_idle_component(uacp);
3841
3842 return (USB_FAILURE);
3843 }
3844
3845 mutex_exit(&uacp->usb_ac_mutex);
3846 usb_ac_rele_siblings(uacp);
3847
3848 usb_ac_pm_idle_component(uacp);
3849
3850 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3851 "usb_ac_mux_plumbing:done");
3852
3853 return (USB_SUCCESS);
3854 }
3855
3856
3857 static int
usb_ac_mux_unplumbing(usb_ac_state_t * uacp)3858 usb_ac_mux_unplumbing(usb_ac_state_t *uacp)
3859 {
3860 usb_ac_plumbed_t *acp;
3861 ldi_handle_t lh;
3862 dev_info_t *acp_dip;
3863 int inst;
3864 int i;
3865 dev_t devt;
3866 minor_t minor;
3867 int maxlinked = 0;
3868
3869 mutex_enter(&uacp->usb_ac_mutex);
3870
3871
3872 if (uacp->usb_ac_plumbing_state == USB_AC_STATE_UNPLUMBED) {
3873 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3874 "usb_ac_mux_unplumbing: already unplumbed!");
3875 mutex_exit(&uacp->usb_ac_mutex);
3876
3877 return (USB_SUCCESS);
3878 }
3879
3880 /* usb_ac might not have anything plumbed yet */
3881 if (uacp->usb_ac_current_plumbed_index == -1) {
3882 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3883 "usb_ac_mux_unplumbing: nothing plumbed");
3884 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3885 mutex_exit(&uacp->usb_ac_mutex);
3886
3887 return (USB_SUCCESS);
3888 }
3889
3890 /* do not allow detach if still busy */
3891 if (uacp->usb_ac_busy_count) {
3892 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3893 "usb_ac_mux_unplumbing: mux still busy (%d)",
3894 uacp->usb_ac_busy_count);
3895 mutex_exit(&uacp->usb_ac_mutex);
3896
3897 return (USB_FAILURE);
3898 }
3899
3900 uacp->usb_ac_plumbing_state = USB_AC_STATE_UNPLUMBED;
3901
3902 /* close ac-as and ac-hid streams */
3903 maxlinked = uacp->usb_ac_current_plumbed_index + 1;
3904 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3905 "usb_ac_mux_unplumbing: maxlinked = %d", maxlinked);
3906
3907 for (i = 0; i < maxlinked; i++) {
3908 /*
3909 * we must save members of usb_ac_plumbed[] before calling
3910 * usb_ac_unplumb() because it clears the structure
3911 */
3912 acp = &uacp->usb_ac_plumbed[i];
3913 lh = acp->acp_lh;
3914 acp_dip = acp->acp_dip;
3915 devt = acp->acp_devt;
3916
3917 if (acp_dip == NULL) {
3918 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3919 "usb_ac_mux_unplumbing: [%d] - skipping", i);
3920 continue;
3921 }
3922
3923 minor = getminor(devt);
3924 inst = ddi_get_instance(acp_dip);
3925
3926 uacp->usb_ac_current_plumbed_index = i;
3927
3928 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3929 "usb_ac_mux_unplumbing: [%d] - %s%d minor 0x%x", i,
3930 ddi_driver_name(acp_dip), inst, minor);
3931
3932 if (lh != NULL) {
3933
3934 acp->acp_flags &= ~ACP_ENABLED;
3935
3936 mutex_exit(&uacp->usb_ac_mutex);
3937
3938 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3939 "usb_ac_mux_unplumbing:[%d] - closing", i);
3940
3941 /*
3942 * ldi_close will cause panic if ldi_getmsg
3943 * is not finished. ddi_taskq_destroy will wait
3944 * for the thread to complete.
3945 */
3946 usb_ac_unplumb(acp);
3947 (void) ldi_close(lh, FREAD|FWRITE, kcred);
3948
3949
3950 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3951 "usb_ac_mux_unplumbing: [%d] - unplumbed", i);
3952
3953 mutex_enter(&uacp->usb_ac_mutex);
3954 }
3955 }
3956
3957 mutex_exit(&uacp->usb_ac_mutex);
3958
3959 /* Wait till all activity in the default pipe has drained */
3960 usb_ac_serialize_access(uacp);
3961 usb_ac_release_access(uacp);
3962
3963 mutex_enter(&uacp->usb_ac_mutex);
3964 uacp->usb_ac_current_plumbed_index = -1;
3965 mutex_exit(&uacp->usb_ac_mutex);
3966
3967 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
3968 "usb_ac_mux_unplumbing: done");
3969
3970 return (USB_SUCCESS);
3971 }
3972
3973
3974 /*
3975 * walk all siblings and create the ac<->as and ac<->hid streams
3976 */
3977 static int
usb_ac_mux_walk_siblings(usb_ac_state_t * uacp)3978 usb_ac_mux_walk_siblings(usb_ac_state_t *uacp)
3979 {
3980 dev_info_t *pdip;
3981 dev_info_t *child_dip;
3982 major_t drv_major;
3983 minor_t drv_minor;
3984 int drv_instance;
3985 char *drv_name;
3986 dev_t drv_devt;
3987 ldi_handle_t drv_lh;
3988 ldi_ident_t li;
3989 int error;
3990 int count = 0;
3991
3992 ASSERT(mutex_owned(&uacp->usb_ac_mutex));
3993
3994 pdip = ddi_get_parent(uacp->usb_ac_dip);
3995 child_dip = ddi_get_child(pdip);
3996
3997 while ((child_dip != NULL) && (count < USB_AC_MAX_PLUMBED)) {
3998 drv_instance = ddi_get_instance(child_dip);
3999 drv_name = (char *)ddi_driver_name(child_dip);
4000
4001 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4002 "usb_ac_mux_walk_siblings: plumbing %s%d count=%d",
4003 drv_name, drv_instance, count);
4004
4005 /* ignore own dip */
4006 if (child_dip == uacp->usb_ac_dip) {
4007 child_dip = ddi_get_next_sibling(child_dip);
4008 continue;
4009 }
4010 drv_instance = ddi_get_instance(child_dip);
4011
4012 /* ignore other dip other than usb_as and hid */
4013 if (strcmp(ddi_driver_name(child_dip), "usb_as") == 0) {
4014 uacp->usb_ac_plumbed[count].acp_driver = USB_AS_PLUMBED;
4015 drv_minor = USB_AS_CONSTRUCT_MINOR(drv_instance);
4016 } else if (strcmp(ddi_driver_name(child_dip), "hid") == 0) {
4017 uacp->usb_ac_plumbed[count].acp_driver = USB_AH_PLUMBED;
4018 drv_minor = HID_CONSTRUCT_EXTERNAL_MINOR(drv_instance);
4019 } else {
4020 drv_minor = drv_instance;
4021 uacp->usb_ac_plumbed[count].acp_driver =
4022 UNKNOWN_PLUMBED;
4023 child_dip = ddi_get_next_sibling(child_dip);
4024
4025 continue;
4026 }
4027
4028 if (!i_ddi_devi_attached(child_dip)) {
4029 child_dip = ddi_get_next_sibling(child_dip);
4030
4031 continue;
4032 }
4033
4034 if (DEVI_IS_DEVICE_REMOVED(child_dip)) {
4035 child_dip = ddi_get_next_sibling(child_dip);
4036
4037 continue;
4038 }
4039
4040 drv_major = ddi_driver_major(child_dip);
4041
4042 uacp->usb_ac_current_plumbed_index = count;
4043
4044 mutex_exit(&uacp->usb_ac_mutex);
4045
4046 drv_devt = makedevice(drv_major, drv_minor);
4047
4048 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4049 "usb_ac_mux_walk_siblings:: opening %s%d devt=(%d, 0x%x)",
4050 drv_name, drv_instance, drv_major, drv_minor);
4051
4052 error = ldi_ident_from_dip(uacp->usb_ac_dip, &li);
4053 if (error == 0) {
4054 mutex_enter(&uacp->usb_ac_mutex);
4055 uacp->usb_ac_plumbed[count].acp_flags |= ACP_ENABLED;
4056 mutex_exit(&uacp->usb_ac_mutex);
4057
4058 error = ldi_open_by_dev(&drv_devt, OTYP_CHR,
4059 FREAD|FWRITE, kcred, &drv_lh, li);
4060 ldi_ident_release(li);
4061 }
4062
4063 mutex_enter(&uacp->usb_ac_mutex);
4064 if (error) {
4065 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4066 "usb_ac_mux_walk_siblings: open of devt=(%d, 0x%x)"
4067 " failed error=%d", drv_major, drv_minor, error);
4068
4069 return (0);
4070 }
4071
4072 uacp->usb_ac_plumbed[count].acp_uacp = uacp;
4073 uacp->usb_ac_plumbed[count].acp_devt = drv_devt;
4074 uacp->usb_ac_plumbed[count].acp_lh = drv_lh;
4075 uacp->usb_ac_plumbed[count].acp_dip = child_dip;
4076 uacp->usb_ac_plumbed[count].acp_ifno =
4077 usb_get_if_number(child_dip);
4078
4079 if (uacp->usb_ac_plumbed[count].acp_driver == USB_AS_PLUMBED) {
4080 /* get registration data */
4081 if (usb_ac_get_reg_data(uacp, drv_lh, count) !=
4082 USB_SUCCESS) {
4083
4084 USB_DPRINTF_L3(PRINT_MASK_ALL,
4085 uacp->usb_ac_log_handle,
4086 "usb_ac_mux_walk_siblings:"
4087 "usb_ac_get_reg_data failed on %s%d",
4088 drv_name, drv_instance);
4089
4090 uacp->usb_ac_plumbed[count].acp_dip = NULL;
4091
4092 return (0);
4093 }
4094 } else if (uacp->usb_ac_plumbed[count].acp_driver ==
4095 USB_AH_PLUMBED) {
4096 int rval;
4097
4098 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4099 "usb_ac_mux_walk_siblings: pushing usb_ah on %s%d",
4100 drv_name, drv_instance);
4101
4102 mutex_exit(&uacp->usb_ac_mutex);
4103
4104 /* push usb_ah module on top of hid */
4105 error = ldi_ioctl(drv_lh, I_PUSH, (intptr_t)"usb_ah",
4106 FKIOCTL, kcred, &rval);
4107 mutex_enter(&uacp->usb_ac_mutex);
4108
4109 if (error) {
4110 USB_DPRINTF_L2(PRINT_MASK_ALL,
4111 uacp->usb_ac_log_handle,
4112 "usb_ac_mux_walk_siblings: ldi_ioctl"
4113 "I_PUSH failed on %s%d, error=%d",
4114 drv_name, drv_instance, error);
4115
4116 uacp->usb_ac_plumbed[count].acp_dip = NULL;
4117
4118 /* skip plumbing the hid driver */
4119 child_dip = ddi_get_next_sibling(child_dip);
4120 continue;
4121 }
4122 } else {
4123 /* should not be here */
4124 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4125 "usb_ac_mux_walk_siblings:- unknown module %s%d",
4126 drv_name, drv_instance);
4127 count--;
4128
4129 uacp->usb_ac_plumbed[count].acp_dip = NULL;
4130
4131 /* skip plumbing an unknown module */
4132 child_dip = ddi_get_next_sibling(child_dip);
4133 continue;
4134 }
4135
4136 mutex_exit(&uacp->usb_ac_mutex);
4137 error = usb_ac_plumb(&uacp->usb_ac_plumbed[count]);
4138 mutex_enter(&uacp->usb_ac_mutex);
4139
4140 if (error != USB_SUCCESS) {
4141 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4142 "usb_ac_mux_walk_siblings: usb_ac_plumb "
4143 "failed for %s%d", drv_name, drv_instance);
4144
4145 return (0);
4146 }
4147
4148 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4149 "usb_ac_mux_walk_siblings:plumbed %d, minor 0x%x",
4150 drv_instance, drv_minor);
4151
4152 child_dip = ddi_get_next_sibling(child_dip);
4153 count++;
4154 }
4155
4156 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4157 "usb_ac_mux_walk_siblings: %d drivers plumbed under usb_ac mux",
4158 count);
4159
4160 return (count);
4161 }
4162
4163
4164 /*
4165 * Register with mixer only after first plumbing.
4166 * Also do not register if earlier reg data
4167 * couldn't be received from at least one
4168 * streaming interface
4169 */
4170
4171 static int
usb_ac_mixer_registration(usb_ac_state_t * uacp)4172 usb_ac_mixer_registration(usb_ac_state_t *uacp)
4173 {
4174 usb_as_registration_t *asreg;
4175 int n;
4176
4177 if (uacp->usb_ac_registered_with_mixer) {
4178 return (USB_SUCCESS);
4179 }
4180
4181 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4182 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4183 break;
4184 }
4185 }
4186
4187 /* Haven't found a streaming interface; fail mixer registration */
4188 if (n > USB_AC_MAX_AS_PLUMBED) {
4189 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4190 "usb_ac_mixer_registration:- no streaming interface found");
4191
4192 return (USB_FAILURE);
4193 }
4194
4195 /*
4196 * Fill out streaming interface specific stuff
4197 * Note that we handle only one playing and one recording
4198 * streaming interface at the most
4199 */
4200 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4201 int ch, chs, id;
4202
4203 if (uacp->usb_ac_streams[n].acs_rcvd_reg_data == 0) {
4204 continue;
4205 }
4206
4207 asreg = &(uacp->usb_ac_streams[n].acs_streams_reg);
4208 if (asreg->reg_valid == 0) {
4209 continue;
4210 }
4211
4212
4213 chs = asreg->reg_formats[0].fmt_chns;
4214
4215 /* check if any channel supports vol. control for this fmt */
4216 for (ch = 0; ch <= chs; ch++) {
4217 if ((id = usb_ac_get_featureID(uacp,
4218 asreg->reg_mode, ch,
4219 USB_AUDIO_VOLUME_CONTROL)) != -1) {
4220 USB_DPRINTF_L3(PRINT_MASK_ALL,
4221 uacp->usb_ac_log_handle,
4222 "usb_ac_mixer_registration:n= [%d]"
4223 "- dir=%d featureID=%d",
4224 n, asreg->reg_mode, id);
4225
4226 break;
4227 }
4228 }
4229
4230 uacp->usb_ac_streams[n].acs_default_gain =
4231 (id == USB_AC_ID_NONE) ? (AF_MAX_GAIN): (AF_MAX_GAIN*3/4);
4232
4233 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4234 "usb_ac_mixer_registration:n= [%d] - mode=%d chs=%d"
4235 "default_gain=%d id=%d",
4236 n, asreg->reg_mode, chs,
4237 uacp->usb_ac_streams[n].acs_default_gain, id);
4238
4239 }
4240
4241 /* the rest */
4242
4243 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4244 "usb_ac_mixer_registration: calling usb_audio_register");
4245
4246 mutex_exit(&uacp->usb_ac_mutex);
4247
4248 if (usb_audio_register(uacp) != USB_SUCCESS) {
4249 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4250 "usb_ac_mixer_registration: usb_audio_register failed");
4251
4252 mutex_enter(&uacp->usb_ac_mutex);
4253
4254 return (USB_FAILURE);
4255 }
4256
4257 mutex_enter(&uacp->usb_ac_mutex);
4258
4259 uacp->usb_ac_registered_with_mixer = 1;
4260
4261 return (USB_SUCCESS);
4262 }
4263
4264
4265 /*
4266 * Get registriations data when driver attach
4267 */
4268 static int
usb_ac_get_reg_data(usb_ac_state_t * uacp,ldi_handle_t drv_lh,int index)4269 usb_ac_get_reg_data(usb_ac_state_t *uacp, ldi_handle_t drv_lh, int index)
4270 {
4271 int n, error, rval;
4272 usb_as_registration_t *streams_reg;
4273
4274
4275 ASSERT(uacp->usb_ac_registered_with_mixer == 0);
4276
4277 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
4278 /*
4279 * We haven't received registration data
4280 * from n-th streaming interface in the array
4281 */
4282 if (!uacp->usb_ac_streams[n].acs_rcvd_reg_data) {
4283 break;
4284 }
4285 }
4286
4287 if (n >= USB_AC_MAX_AS_PLUMBED) {
4288 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4289 "More than 2 streaming interfaces (play "
4290 "and/or record) currently not supported");
4291
4292 return (USB_FAILURE);
4293 }
4294
4295 /* take the stream reg struct with the same index */
4296 streams_reg = &uacp->usb_ac_streams[n].acs_streams_reg;
4297
4298 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4299 "usb_ac_get_reg_data:regdata from usb_as: streams_reg=0x%p, n=%d",
4300 (void *)streams_reg, n);
4301
4302 mutex_exit(&uacp->usb_ac_mutex);
4303
4304 if ((error = ldi_ioctl(drv_lh, USB_AUDIO_MIXER_REGISTRATION,
4305 (intptr_t)streams_reg, FKIOCTL, kcred, &rval)) != 0) {
4306 USB_DPRINTF_L2(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4307 "usb_ac_get_reg_data: ldi_ioctl failed for"
4308 "mixer registration error=%d", error);
4309
4310 mutex_enter(&uacp->usb_ac_mutex);
4311
4312 return (USB_FAILURE);
4313 } else {
4314 mutex_enter(&uacp->usb_ac_mutex);
4315
4316 rval = usb_ac_setup_plumbed(uacp, index, n);
4317
4318 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4319 "usb_ac_get_reg_data:usb_ac_streams[%d]: "
4320 "received_reg_data=%d type=%s", index,
4321 uacp->usb_ac_streams[n].acs_rcvd_reg_data,
4322 ((streams_reg->reg_mode == USB_AUDIO_PLAY) ?
4323 "play" : "record"));
4324
4325 usb_ac_print_reg_data(uacp, streams_reg);
4326
4327 return (rval);
4328 }
4329 }
4330
4331
4332 /*
4333 * setup plumbed and stream info structure
4334 */
4335 static int
usb_ac_setup_plumbed(usb_ac_state_t * uacp,int plb_idx,int str_idx)4336 usb_ac_setup_plumbed(usb_ac_state_t *uacp, int plb_idx, int str_idx)
4337 {
4338 uacp->usb_ac_plumbed[plb_idx].acp_data =
4339 &uacp->usb_ac_streams[str_idx];
4340 uacp->usb_ac_streams[str_idx].acs_plumbed =
4341 &uacp->usb_ac_plumbed[plb_idx];
4342 uacp->usb_ac_streams[str_idx].acs_rcvd_reg_data = 1;
4343
4344
4345 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4346 "usb_ac_setup_plumbed: done - plb_idx=%d str_idx=%d ",
4347 plb_idx, str_idx);
4348
4349 return (USB_SUCCESS);
4350 }
4351
4352
4353 /*
4354 * function to dump registration data
4355 */
4356 static void
usb_ac_print_reg_data(usb_ac_state_t * uacp,usb_as_registration_t * reg)4357 usb_ac_print_reg_data(usb_ac_state_t *uacp,
4358 usb_as_registration_t *reg)
4359 {
4360 int n;
4361
4362 for (n = 0; n < reg->reg_n_formats; n++) {
4363 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4364 "format%d: alt=%d chns=%d prec=%d enc=%d", n,
4365 reg->reg_formats[n].fmt_alt,
4366 reg->reg_formats[n].fmt_chns,
4367 reg->reg_formats[n].fmt_precision,
4368 reg->reg_formats[n].fmt_encoding);
4369 }
4370
4371 for (n = 0; n < USB_AS_N_FORMATS; n++) {
4372 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4373 "reg_formats[%d] ptr=0x%p", n,
4374 (void *)®->reg_formats[n]);
4375 }
4376
4377 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4378 "usb_ac_print_reg_data: End");
4379 }
4380
4381
4382 static int
usb_ac_online_siblings(usb_ac_state_t * uacp)4383 usb_ac_online_siblings(usb_ac_state_t *uacp)
4384 {
4385 dev_info_t *pdip, *child_dip;
4386 int rval = USB_SUCCESS;
4387
4388 ASSERT(mutex_owned(&uacp->usb_ac_mutex));
4389
4390 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4391 "usb_ac_online_siblings:start");
4392
4393 pdip = ddi_get_parent(uacp->usb_ac_dip);
4394
4395 child_dip = ddi_get_child(pdip);
4396 while (child_dip != NULL) {
4397
4398 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4399 "usb_ac_online_siblings: onlining %s%d ref=%d",
4400 ddi_driver_name(child_dip),
4401 ddi_get_instance(child_dip),
4402 DEVI(child_dip)->devi_ref);
4403
4404 /* Online the child_dip of usb_as and hid, if not already */
4405 if ((strcmp(ddi_driver_name(child_dip), "usb_as") == 0) ||
4406 (strcmp(ddi_driver_name(child_dip), "hid") == 0)) {
4407
4408 mutex_exit(&uacp->usb_ac_mutex);
4409 if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
4410 NDI_SUCCESS) {
4411 USB_DPRINTF_L3(PRINT_MASK_ALL,
4412 uacp->usb_ac_log_handle,
4413 "usb_ac_online_siblings:failed to online"
4414 "device %s%d", ddi_driver_name(child_dip),
4415 ddi_get_instance(child_dip));
4416
4417 /* only onlining usb_as is fatal */
4418 if (strcmp(ddi_driver_name(child_dip),
4419 "usb_as") == 0) {
4420 mutex_enter(&uacp->usb_ac_mutex);
4421 rval = USB_FAILURE;
4422 break;
4423 }
4424 }
4425 mutex_enter(&uacp->usb_ac_mutex);
4426 }
4427 child_dip = ddi_get_next_sibling(child_dip);
4428 }
4429
4430 return (rval);
4431 }
4432
4433
4434 /*
4435 * hold all audio children before or after plumbing
4436 * online usb_as and hid, if not already
4437 */
4438 static void
usb_ac_hold_siblings(usb_ac_state_t * uacp)4439 usb_ac_hold_siblings(usb_ac_state_t *uacp)
4440 {
4441 int circ;
4442 dev_info_t *pdip, *child_dip;
4443
4444 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4445 "usb_ac_hold_siblings:start");
4446
4447 /* hold all siblings and ourselves */
4448 pdip = ddi_get_parent(uacp->usb_ac_dip);
4449
4450 /* hold the children */
4451 ndi_devi_enter(pdip, &circ);
4452 child_dip = ddi_get_child(pdip);
4453 while (child_dip != NULL) {
4454 ndi_hold_devi(child_dip);
4455
4456 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4457 "usb_ac_hold_siblings: held %s%d ref=%d",
4458 ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4459 DEVI(child_dip)->devi_ref);
4460
4461 child_dip = ddi_get_next_sibling(child_dip);
4462 }
4463 ndi_devi_exit(pdip, circ);
4464 }
4465
4466
4467 /*
4468 * release all audio children before or after plumbing
4469 */
4470 static void
usb_ac_rele_siblings(usb_ac_state_t * uacp)4471 usb_ac_rele_siblings(usb_ac_state_t *uacp)
4472 {
4473 int circ;
4474 dev_info_t *pdip, *child_dip;
4475
4476 USB_DPRINTF_L4(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4477 "usb_ac_rele_siblings: start");
4478
4479 /* release all siblings and ourselves */
4480 pdip = ddi_get_parent(uacp->usb_ac_dip);
4481 ndi_devi_enter(pdip, &circ);
4482 child_dip = ddi_get_child(pdip);
4483 while (child_dip != NULL) {
4484 ndi_rele_devi(child_dip);
4485
4486 USB_DPRINTF_L3(PRINT_MASK_ALL, uacp->usb_ac_log_handle,
4487 "usb_ac_rele_siblings: released %s%d ref=%d",
4488 ddi_driver_name(child_dip), ddi_get_instance(child_dip),
4489 DEVI(child_dip)->devi_ref);
4490
4491 child_dip = ddi_get_next_sibling(child_dip);
4492 }
4493 ndi_devi_exit(pdip, circ);
4494 }
4495 static void
usb_restore_engine(usb_ac_state_t * statep)4496 usb_restore_engine(usb_ac_state_t *statep)
4497 {
4498 usb_audio_eng_t *engp;
4499 int i;
4500
4501 for (i = 0; i < USB_AC_ENG_MAX; i++) {
4502
4503 mutex_enter(&statep->usb_ac_mutex);
4504 engp = &statep->engines[i];
4505 mutex_exit(&statep->usb_ac_mutex);
4506
4507 if (engp->af_engp == NULL)
4508 continue;
4509 if (usb_ac_set_format(statep, engp) != USB_SUCCESS) {
4510 USB_DPRINTF_L2(PRINT_MASK_ATTA,
4511 statep->usb_ac_log_handle,
4512 "usb_restore_engine:set format fail, i=%d", i);
4513 return;
4514 }
4515 if (engp->started) {
4516 (void) usb_engine_start(engp);
4517 }
4518
4519 }
4520
4521 (void) usb_ac_ctrl_restore(statep);
4522 }
4523
4524
4525 /*
4526 * get the maximum format specification the device supports
4527 */
4528 static void
usb_ac_max_fmt(usb_as_registration_t * reg_data,usb_audio_format_t * fmtp)4529 usb_ac_max_fmt(usb_as_registration_t *reg_data,
4530 usb_audio_format_t *fmtp)
4531 {
4532
4533 uint_t ch = 0, sr = 0, prec = 0, enc = 0;
4534 int i;
4535
4536 usb_audio_formats_t *reg_formats = reg_data->reg_formats;
4537
4538 /* format priority: channels, sample rate, precision, encoding */
4539 for (i = 0; i < reg_data->reg_n_formats; i++) {
4540 uint_t val, fmt_sr;
4541 int n, keep;
4542
4543 val = reg_formats[i].fmt_chns;
4544 if (val < ch)
4545 continue;
4546 if (val > ch)
4547 keep = 1;
4548
4549 for (n = 0, fmt_sr = 0; n < reg_formats[i].fmt_n_srs; n++) {
4550 if (fmt_sr < reg_formats[i].fmt_srs[n]) {
4551 fmt_sr = reg_formats[i].fmt_srs[n];
4552 }
4553 }
4554 if (!keep && fmt_sr < sr)
4555 continue;
4556 if (fmt_sr > sr)
4557 keep = 1;
4558
4559 val = reg_formats[i].fmt_precision;
4560 if (!keep && (val < prec))
4561 continue;
4562 if (val > prec)
4563 keep = 1;
4564
4565 val = reg_formats[i].fmt_encoding;
4566 if (!keep && (val < enc))
4567 continue;
4568
4569 ch = reg_formats[i].fmt_chns;
4570 sr = fmt_sr;
4571 prec = reg_formats[i].fmt_precision;
4572 enc = reg_formats[i].fmt_encoding;
4573 }
4574
4575 fmtp->ch = ch;
4576 fmtp->sr = sr;
4577 fmtp->prec = prec;
4578 fmtp->enc = enc;
4579 }
4580
4581
4582 static void
usb_ac_rem_eng(usb_ac_state_t * statep,usb_audio_eng_t * engp)4583 usb_ac_rem_eng(usb_ac_state_t *statep, usb_audio_eng_t *engp)
4584 {
4585 if (statep->usb_ac_audio_dev == NULL || engp->af_engp == NULL)
4586 return;
4587
4588 audio_dev_remove_engine(statep->usb_ac_audio_dev, engp->af_engp);
4589 audio_engine_free(engp->af_engp);
4590
4591 mutex_enter(&engp->lock);
4592 engp->af_engp = NULL;
4593 engp->streams = NULL;
4594 mutex_exit(&engp->lock);
4595
4596 mutex_destroy(&engp->lock);
4597 cv_destroy(&engp->usb_audio_cv);
4598 }
4599
4600
4601 static int
usb_ac_add_eng(usb_ac_state_t * uacp,usb_ac_streams_info_t * asinfo)4602 usb_ac_add_eng(usb_ac_state_t *uacp, usb_ac_streams_info_t *asinfo)
4603 {
4604 audio_dev_t *af_devp = uacp->usb_ac_audio_dev;
4605 usb_audio_eng_t *engp;
4606 audio_engine_t *af_engp;
4607 int rv = USB_FAILURE;
4608 int dir = asinfo->acs_streams_reg.reg_mode;
4609 uint_t defgain;
4610
4611 if (asinfo->acs_rcvd_reg_data == 0) {
4612
4613 return (USB_SUCCESS);
4614 }
4615 if (dir == USB_AUDIO_PLAY) {
4616 engp = &(uacp->engines[0]);
4617 } else {
4618 engp = &(uacp->engines[1]);
4619 }
4620
4621 cv_init(&engp->usb_audio_cv, NULL, CV_DRIVER, NULL);
4622
4623 mutex_init(&engp->lock, NULL, MUTEX_DRIVER, NULL);
4624
4625 mutex_enter(&engp->lock);
4626
4627 engp->af_eflags =
4628 (dir == USB_AUDIO_PLAY)?ENGINE_OUTPUT_CAP:ENGINE_INPUT_CAP;
4629 engp->statep = uacp;
4630
4631 /* Set the format for the engine */
4632 usb_ac_max_fmt(&(asinfo->acs_streams_reg), &engp->fmt);
4633
4634 /* init the default gain */
4635 defgain = asinfo->acs_default_gain;
4636 if (engp->fmt.ch == 2) {
4637 engp->af_defgain = AUDIO_CTRL_STEREO_VAL(defgain, defgain);
4638 } else {
4639 engp->af_defgain = defgain;
4640 }
4641 engp->streams = asinfo;
4642
4643 mutex_exit(&engp->lock);
4644
4645 af_engp = audio_engine_alloc(&usb_engine_ops, engp->af_eflags);
4646 if (af_engp == NULL) {
4647
4648 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4649 "audio_engine_alloc failed");
4650 goto OUT;
4651 }
4652 ASSERT(engp->af_engp == 0);
4653
4654 mutex_enter(&engp->lock);
4655 engp->af_engp = af_engp;
4656 mutex_exit(&engp->lock);
4657
4658 audio_engine_set_private(af_engp, engp);
4659 audio_dev_add_engine(af_devp, af_engp);
4660
4661 /*
4662 * Set the format for this engine
4663 */
4664 if (usb_ac_set_format(uacp, engp) != USB_SUCCESS) {
4665 USB_DPRINTF_L2(PRINT_MASK_ATTA, uacp->usb_ac_log_handle,
4666 "set format failed, dir = %d", dir);
4667 goto OUT;
4668 }
4669 rv = USB_SUCCESS;
4670
4671 OUT:
4672 if (rv != USB_SUCCESS)
4673 usb_ac_rem_eng(uacp, engp);
4674
4675 return (rv);
4676 }
4677
4678
4679 static int
usb_ac_ctrl_set_defaults(usb_ac_state_t * statep)4680 usb_ac_ctrl_set_defaults(usb_ac_state_t *statep)
4681 {
4682 usb_audio_ctrl_t *ctrlp;
4683 int rv = USB_SUCCESS;
4684 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4685 "usb_ac_ctrl_set_defaults:begin");
4686
4687 for (int i = 0; i < CTL_NUM; i++) {
4688 ctrlp = statep->controls[i];
4689 if (!ctrlp) {
4690 continue;
4691 }
4692 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4693 USB_DPRINTF_L2(PRINT_MASK_ATTA,
4694 statep->usb_ac_log_handle,
4695 "usb_ac_ctrl_set_defaults:control write failed");
4696 rv = USB_FAILURE;
4697 }
4698
4699 }
4700 USB_DPRINTF_L4(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
4701 "usb_ac_ctrl_set_defaults:end");
4702 return (rv);
4703 }
4704
4705
4706 static int
usb_ac_ctrl_restore(usb_ac_state_t * statep)4707 usb_ac_ctrl_restore(usb_ac_state_t *statep)
4708 {
4709 usb_audio_ctrl_t *ctrlp;
4710 int rv = USB_SUCCESS;
4711
4712 for (int i = 0; i < CTL_NUM; i++) {
4713 ctrlp = statep->controls[i];
4714 if (ctrlp) {
4715 USB_DPRINTF_L3(PRINT_MASK_ATTA,
4716 statep->usb_ac_log_handle,
4717 "usb_ac_ctrl_restore:i = %d", i);
4718 if (audio_control_write(ctrlp->af_ctrlp, ctrlp->cval)) {
4719 rv = USB_FAILURE;
4720 }
4721 }
4722 }
4723 return (rv);
4724 }
4725
4726
4727
4728
4729 /*
4730 * moves data between driver buffer and framework/shim buffer
4731 */
4732 static void
usb_eng_bufio(usb_audio_eng_t * engp,void * buf,size_t sz)4733 usb_eng_bufio(usb_audio_eng_t *engp, void *buf, size_t sz)
4734 {
4735 size_t cpsz = sz;
4736 caddr_t *src, *dst;
4737
4738 if (engp->af_eflags & ENGINE_OUTPUT_CAP) {
4739 src = &engp->bufpos;
4740 dst = (caddr_t *)&buf;
4741 } else {
4742 src = (caddr_t *)&buf;
4743 dst = &engp->bufpos;
4744 }
4745
4746 /*
4747 * Wrap. If sz is exactly the remainder of the buffer
4748 * (bufpos + sz == bufendp) then the second cpsz should be 0 and so
4749 * the second memcpy() should have no effect, with bufpos updated
4750 * to the head of the buffer.
4751 */
4752 if (engp->bufpos + sz >= engp->bufendp) {
4753 cpsz = (size_t)engp->bufendp - (size_t)engp->bufpos;
4754 (void) memcpy(*dst, *src, cpsz);
4755
4756
4757 buf = (caddr_t)buf + cpsz;
4758 engp->bufpos = engp->bufp;
4759 cpsz = sz - cpsz;
4760 }
4761
4762 if (cpsz) {
4763 (void) memcpy(*dst, *src, cpsz);
4764
4765
4766 engp->bufpos += cpsz;
4767 }
4768 engp->bufio_count++;
4769 }
4770
4771
4772 /*
4773 * control read callback
4774 */
4775 static int
usb_audio_ctrl_read(void * arg,uint64_t * cvalp)4776 usb_audio_ctrl_read(void *arg, uint64_t *cvalp)
4777 {
4778 usb_audio_ctrl_t *ctrlp = arg;
4779
4780 mutex_enter(&ctrlp->ctrl_mutex);
4781 *cvalp = ctrlp->cval;
4782 mutex_exit(&ctrlp->ctrl_mutex);
4783
4784 return (0);
4785 }
4786
4787
4788 /*
4789 * stereo level control callback
4790 */
4791 static int
usb_audio_write_stero_rec(void * arg,uint64_t cval)4792 usb_audio_write_stero_rec(void *arg, uint64_t cval)
4793 {
4794 usb_audio_ctrl_t *ctrlp = arg;
4795 usb_ac_state_t *statep = ctrlp->statep;
4796 int rv = EIO;
4797 int left, right;
4798 uint_t count = 0;
4799
4800
4801 left = AUDIO_CTRL_STEREO_LEFT(cval);
4802 right = AUDIO_CTRL_STEREO_RIGHT(cval);
4803
4804 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4805 right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4806
4807 return (EINVAL);
4808 }
4809
4810 mutex_enter(&ctrlp->ctrl_mutex);
4811 ctrlp->cval = cval;
4812 mutex_exit(&ctrlp->ctrl_mutex);
4813
4814 mutex_enter(&statep->usb_ac_mutex);
4815 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4816 USB_AUDIO_FEATURE_UNIT, 1,
4817 USB_AUDIO_VOLUME_CONTROL,
4818 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4819
4820 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4821 USB_AUDIO_FEATURE_UNIT, 2,
4822 USB_AUDIO_VOLUME_CONTROL,
4823 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4824 rv = 0;
4825
4826 done:
4827 mutex_exit(&statep->usb_ac_mutex);
4828 return (rv);
4829 }
4830
4831 static int
usb_audio_write_ster_vol(void * arg,uint64_t cval)4832 usb_audio_write_ster_vol(void *arg, uint64_t cval)
4833 {
4834 usb_audio_ctrl_t *ctrlp = arg;
4835 usb_ac_state_t *statep = ctrlp->statep;
4836 int rv = EIO;
4837 int left, right;
4838 uint_t count = 0;
4839
4840 left = AUDIO_CTRL_STEREO_LEFT(cval);
4841 right = AUDIO_CTRL_STEREO_RIGHT(cval);
4842
4843 if (left < AF_MIN_GAIN || left > AF_MAX_GAIN ||
4844 right < AF_MIN_GAIN || right > AF_MAX_GAIN) {
4845 return (EINVAL);
4846 }
4847
4848 mutex_enter(&ctrlp->ctrl_mutex);
4849 ctrlp->cval = cval;
4850 mutex_exit(&ctrlp->ctrl_mutex);
4851
4852
4853 mutex_enter(&statep->usb_ac_mutex);
4854 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4855 USB_AUDIO_FEATURE_UNIT, 1,
4856 USB_AUDIO_VOLUME_CONTROL,
4857 USB_AC_FIND_ALL, &count, left, usb_ac_set_gain);
4858
4859 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4860 USB_AUDIO_FEATURE_UNIT, 2,
4861 USB_AUDIO_VOLUME_CONTROL,
4862 USB_AC_FIND_ALL, &count, right, usb_ac_set_gain);
4863 rv = 0;
4864
4865 OUT:
4866 mutex_exit(&statep->usb_ac_mutex);
4867 return (rv);
4868 }
4869
4870
4871 /*
4872 * mono level control callback
4873 */
4874 static int
usb_audio_write_mono_vol(void * arg,uint64_t cval)4875 usb_audio_write_mono_vol(void *arg, uint64_t cval)
4876 {
4877 usb_audio_ctrl_t *ctrlp = arg;
4878 usb_ac_state_t *statep = ctrlp->statep;
4879 int rv = EIO;
4880 int gain;
4881
4882 uint_t count = 0;
4883
4884 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4885 return (EINVAL);
4886 }
4887
4888 mutex_enter(&ctrlp->ctrl_mutex);
4889 ctrlp->cval = cval;
4890 mutex_exit(&ctrlp->ctrl_mutex);
4891
4892 gain = (int)(cval);
4893
4894 mutex_enter(&statep->usb_ac_mutex);
4895 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
4896 USB_AUDIO_FEATURE_UNIT, 1,
4897 USB_AUDIO_VOLUME_CONTROL,
4898 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4899
4900 rv = 0;
4901 OUT:
4902 mutex_exit(&statep->usb_ac_mutex);
4903
4904 return (rv);
4905 }
4906
4907
4908 /*
4909 * mono level control callback
4910 */
4911 static int
usb_audio_write_monitor_gain(void * arg,uint64_t cval)4912 usb_audio_write_monitor_gain(void *arg, uint64_t cval)
4913 {
4914 usb_audio_ctrl_t *ctrlp = arg;
4915 usb_ac_state_t *statep = ctrlp->statep;
4916 int rv = EIO;
4917 int gain;
4918 uint_t count = 0;
4919
4920 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4921
4922 return (EINVAL);
4923 }
4924
4925 mutex_enter(&ctrlp->ctrl_mutex);
4926 ctrlp->cval = cval;
4927 mutex_exit(&ctrlp->ctrl_mutex);
4928
4929 gain = (int)(cval);
4930
4931 mutex_enter(&statep->usb_ac_mutex);
4932 (void) usb_ac_set_monitor_gain_control(statep, USB_AUDIO_RECORD,
4933 USB_AUDIO_INPUT_TERMINAL, 1,
4934 USB_AUDIO_VOLUME_CONTROL,
4935 USB_AC_FIND_ALL, &count, gain,
4936 usb_ac_set_monitor_gain);
4937
4938 rv = 0;
4939 OUT:
4940 mutex_exit(&statep->usb_ac_mutex);
4941 return (rv);
4942 }
4943
4944 static int
usb_audio_write_mono_rec(void * arg,uint64_t cval)4945 usb_audio_write_mono_rec(void *arg, uint64_t cval)
4946 {
4947 usb_audio_ctrl_t *ctrlp = arg;
4948 usb_ac_state_t *statep = ctrlp->statep;
4949 int rv = EIO;
4950 int gain;
4951
4952 uint_t count = 0;
4953
4954 if (cval < (uint64_t)AF_MIN_GAIN || cval > (uint64_t)AF_MAX_GAIN) {
4955
4956 return (EINVAL);
4957 }
4958
4959 mutex_enter(&ctrlp->ctrl_mutex);
4960 ctrlp->cval = cval;
4961 mutex_exit(&ctrlp->ctrl_mutex);
4962
4963 gain = (int)(cval);
4964
4965 mutex_enter(&statep->usb_ac_mutex);
4966 (void) usb_ac_set_control(statep, USB_AUDIO_RECORD,
4967 USB_AUDIO_FEATURE_UNIT, 1,
4968 USB_AUDIO_VOLUME_CONTROL,
4969 USB_AC_FIND_ALL, &count, gain, usb_ac_set_gain);
4970
4971 rv = 0;
4972
4973 mutex_exit(&statep->usb_ac_mutex);
4974 return (rv);
4975 }
4976
4977 static int
usb_audio_write_mic_boost(void * arg,uint64_t cval)4978 usb_audio_write_mic_boost(void *arg, uint64_t cval)
4979 {
4980 usb_audio_ctrl_t *ctrlp = arg;
4981
4982 mutex_enter(&ctrlp->ctrl_mutex);
4983 ctrlp->cval = cval;
4984 mutex_exit(&ctrlp->ctrl_mutex);
4985 /* do nothing here */
4986 return (0);
4987 }
4988
4989 static int
usb_audio_write_rec_src(void * arg,uint64_t cval)4990 usb_audio_write_rec_src(void *arg, uint64_t cval)
4991 {
4992 usb_audio_ctrl_t *ctrlp = arg;
4993 usb_ac_state_t *statep = ctrlp->statep;
4994 int rv = 0;
4995
4996 if (cval & ~(statep->usb_ac_input_ports))
4997 return (EINVAL);
4998
4999 mutex_enter(&ctrlp->ctrl_mutex);
5000 ctrlp->cval = cval;
5001 mutex_exit(&ctrlp->ctrl_mutex);
5002
5003 mutex_enter(&statep->usb_ac_mutex);
5004 if (usb_ac_set_port(statep, USB_AUDIO_RECORD, cval) != USB_SUCCESS) {
5005
5006 USB_DPRINTF_L2(PRINT_MASK_ALL, statep->usb_ac_log_handle,
5007 "usb_audio_write_rec_src: failed");
5008 rv = EINVAL;
5009 }
5010 mutex_exit(&statep->usb_ac_mutex);
5011 rv = 0;
5012
5013 OUT:
5014 return (rv);
5015
5016 }
5017
5018
5019 int
usb_audio_set_mute(usb_ac_state_t * statep,uint64_t cval)5020 usb_audio_set_mute(usb_ac_state_t *statep, uint64_t cval)
5021 {
5022 short muteval;
5023 int rval;
5024
5025 uint_t count;
5026 muteval = (cval == 0) ? USB_AUDIO_MUTE_ON : USB_AUDIO_MUTE_OFF;
5027 count = 0;
5028 /* only support AUDIO_PLAY */
5029
5030 mutex_enter(&statep->usb_ac_mutex);
5031 (void) usb_ac_set_control(statep, USB_AUDIO_PLAY,
5032 USB_AUDIO_FEATURE_UNIT, 0,
5033 USB_AUDIO_MUTE_CONTROL,
5034 USB_AC_FIND_ALL, &count, muteval,
5035 usb_ac_set_mute);
5036 mutex_exit(&statep->usb_ac_mutex);
5037
5038 rval = (count == 0) ? USB_SUCCESS : USB_FAILURE;
5039
5040 return (rval);
5041 }
5042
5043
5044 /*
5045 * port selection control callback
5046 */
5047 /*
5048 * audio control registration related routines
5049 */
5050
5051 static usb_audio_ctrl_t *
usb_audio_ctrl_alloc(usb_ac_state_t * statep,uint32_t num,uint64_t val)5052 usb_audio_ctrl_alloc(usb_ac_state_t *statep, uint32_t num, uint64_t val)
5053 {
5054 audio_ctrl_desc_t desc;
5055 audio_ctrl_wr_t fn;
5056 usb_audio_ctrl_t *pc;
5057
5058 pc = kmem_zalloc(sizeof (usb_audio_ctrl_t), KM_SLEEP);
5059
5060 mutex_init(&pc->ctrl_mutex, NULL, MUTEX_DRIVER, NULL);
5061
5062 bzero(&desc, sizeof (desc));
5063
5064 switch (num) {
5065 case CTL_VOLUME_MONO:
5066 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5067 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5068 desc.acd_minvalue = 0;
5069 desc.acd_maxvalue = AF_MAX_GAIN;
5070 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5071 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5072 fn = usb_audio_write_mono_vol;
5073 break;
5074
5075 case CTL_VOLUME_STERO:
5076 desc.acd_name = AUDIO_CTRL_ID_VOLUME;
5077 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5078 desc.acd_minvalue = 0;
5079 desc.acd_maxvalue = AF_MAX_GAIN;
5080 desc.acd_flags = AUDIO_CTRL_FLAG_MAINVOL | AUDIO_CTRL_FLAG_RW
5081 | AUDIO_CTRL_FLAG_PLAY | AUDIO_CTRL_FLAG_POLL;
5082 fn = usb_audio_write_ster_vol;
5083
5084 break;
5085
5086 case CTL_REC_MONO:
5087 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5088 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5089 desc.acd_minvalue = 0;
5090 desc.acd_maxvalue = AF_MAX_GAIN;
5091 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5092 | AUDIO_CTRL_FLAG_RW;
5093 fn = usb_audio_write_mono_rec;
5094 break;
5095 case CTL_REC_STERO:
5096
5097 desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
5098 desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
5099 desc.acd_minvalue = 0;
5100 desc.acd_maxvalue = AF_MAX_GAIN;
5101 desc.acd_flags = AUDIO_CTRL_FLAG_RECVOL|AUDIO_CTRL_FLAG_REC
5102 | AUDIO_CTRL_FLAG_RW;
5103 fn = usb_audio_write_stero_rec;
5104 break;
5105
5106 case CTL_MONITOR_GAIN:
5107
5108 desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
5109 desc.acd_type = AUDIO_CTRL_TYPE_MONO;
5110 desc.acd_minvalue = 0;
5111 desc.acd_maxvalue = AF_MAX_GAIN;
5112 desc.acd_flags = AUDIO_CTRL_FLAG_MONVOL |AUDIO_CTRL_FLAG_MONITOR
5113 |AUDIO_CTRL_FLAG_RW;
5114 fn = usb_audio_write_monitor_gain;
5115 break;
5116
5117 case CTL_MIC_BOOST:
5118
5119 desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
5120 desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
5121 desc.acd_minvalue = 0;
5122 desc.acd_maxvalue = 1;
5123 desc.acd_flags = AUDIO_CTRL_FLAG_RW;
5124 fn = usb_audio_write_mic_boost;
5125 break;
5126 case CTL_REC_SRC:
5127
5128 desc.acd_name = AUDIO_CTRL_ID_RECSRC;
5129 desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
5130 desc.acd_minvalue = statep->usb_ac_input_ports;
5131 desc.acd_maxvalue = statep->usb_ac_input_ports;
5132 desc.acd_flags = AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC;
5133 for (int i = 0; usb_audio_dtypes[i]; i++) {
5134 desc.acd_enum[i] = usb_audio_dtypes[i];
5135 }
5136
5137 fn = usb_audio_write_rec_src;
5138 break;
5139
5140
5141
5142 default:
5143
5144 break;
5145 }
5146
5147 mutex_enter(&pc->ctrl_mutex);
5148
5149 pc->statep = statep;
5150 pc->cval = val;
5151 pc->af_ctrlp = audio_dev_add_control(statep->usb_ac_audio_dev, &desc,
5152 usb_audio_ctrl_read, fn, pc);
5153
5154 mutex_exit(&pc->ctrl_mutex);
5155
5156 mutex_enter(&statep->usb_ac_mutex);
5157 statep->controls[num] = pc;
5158 mutex_exit(&statep->usb_ac_mutex);
5159
5160
5161 return (pc);
5162 }
5163
5164
5165 static void
usb_audio_ctrl_free(usb_audio_ctrl_t * ctrlp)5166 usb_audio_ctrl_free(usb_audio_ctrl_t *ctrlp)
5167 {
5168 kmem_free(ctrlp, sizeof (usb_audio_ctrl_t));
5169 }
5170
5171 static void
usb_ac_rem_controls(usb_ac_state_t * statep)5172 usb_ac_rem_controls(usb_ac_state_t *statep)
5173 {
5174 usb_audio_ctrl_t *ctrlp;
5175
5176 for (int i = 0; i < CTL_NUM; i++) {
5177 ctrlp = statep->controls[i];
5178 if (ctrlp) {
5179 if (ctrlp->af_ctrlp != NULL)
5180 audio_dev_del_control(ctrlp->af_ctrlp);
5181
5182 usb_audio_ctrl_free(ctrlp);
5183 mutex_enter(&statep->usb_ac_mutex);
5184 statep->controls[i] = NULL;
5185 mutex_exit(&statep->usb_ac_mutex);
5186 }
5187 }
5188
5189 }
5190
5191
5192 static int
usb_ac_add_controls(usb_ac_state_t * statep)5193 usb_ac_add_controls(usb_ac_state_t *statep)
5194 {
5195 int rv = USB_FAILURE;
5196 usb_audio_format_t *format;
5197
5198
5199 if (statep->engines[0].af_engp) {
5200 /* Init controls for play format */
5201 format = &(statep->engines[0].fmt);
5202 if (format->ch == 2) {
5203 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_STERO,
5204 statep->engines[0].af_defgain);
5205 } else {
5206 (void) usb_audio_ctrl_alloc(statep, CTL_VOLUME_MONO,
5207 statep->engines[0].af_defgain);
5208 }
5209
5210 }
5211
5212 /* Init controls for rec format */
5213 if (statep->engines[1].af_engp) {
5214 format = &(statep->engines[1].fmt);
5215 if (format->ch == 2) {
5216 (void) usb_audio_ctrl_alloc(statep, CTL_REC_STERO,
5217 statep->engines[1].af_defgain);
5218 } else {
5219 (void) usb_audio_ctrl_alloc(statep, CTL_REC_MONO,
5220 statep->engines[1].af_defgain);
5221 }
5222
5223 /* Add monitor control */
5224 {
5225 (void) usb_audio_ctrl_alloc(statep,
5226 CTL_MONITOR_GAIN, 0);
5227 }
5228
5229 /* Add ports control */
5230 {
5231 (void) usb_audio_ctrl_alloc(statep, CTL_REC_SRC,
5232 statep->usb_ac_input_ports);
5233 }
5234
5235 }
5236
5237
5238 rv = USB_SUCCESS;
5239
5240 OUT:
5241 if (rv != USB_SUCCESS)
5242 usb_ac_rem_controls(statep);
5243 return (rv);
5244 }
5245
5246
5247
5248
5249
5250 /*ARGSUSED*/
5251 static int
usb_audio_unregister(usb_ac_state_t * statep)5252 usb_audio_unregister(usb_ac_state_t *statep)
5253 {
5254 int i;
5255
5256 if (statep == NULL)
5257 return (USB_SUCCESS);
5258
5259 if (statep->usb_ac_audio_dev == NULL)
5260 return (USB_SUCCESS);
5261
5262 if ((statep->flags & AF_REGISTERED) &&
5263 audio_dev_unregister(statep->usb_ac_audio_dev) != DDI_SUCCESS) {
5264 return (USB_FAILURE);
5265 }
5266 mutex_enter(&statep->usb_ac_mutex);
5267 statep->flags &= ~AF_REGISTERED;
5268 mutex_exit(&statep->usb_ac_mutex);
5269
5270 for (i = 0; i < USB_AC_ENG_MAX; i++)
5271 usb_ac_rem_eng(statep, &statep->engines[i]);
5272
5273 usb_ac_rem_controls(statep);
5274
5275 audio_dev_free(statep->usb_ac_audio_dev);
5276
5277 mutex_enter(&statep->usb_ac_mutex);
5278 statep->usb_ac_audio_dev = NULL;
5279 mutex_exit(&statep->usb_ac_mutex);
5280
5281 return (USB_SUCCESS);
5282 }
5283
5284
5285 static int
usb_audio_register(usb_ac_state_t * statep)5286 usb_audio_register(usb_ac_state_t *statep) {
5287 audio_dev_t *af_devp;
5288 int rv = USB_FAILURE;
5289 int n;
5290
5291 af_devp = audio_dev_alloc(statep->usb_ac_dip, 0);
5292 audio_dev_set_description(af_devp, "USB Audio");
5293 audio_dev_set_version(af_devp, "1.0");
5294
5295 mutex_enter(&statep->usb_ac_mutex);
5296 statep->usb_ac_audio_dev = af_devp;
5297 mutex_exit(&statep->usb_ac_mutex);
5298
5299
5300 for (n = 0; n < USB_AC_MAX_AS_PLUMBED; n++) {
5301 if (usb_ac_add_eng(statep, &(statep->usb_ac_streams[n]))
5302 != USB_SUCCESS) {
5303 USB_DPRINTF_L2(PRINT_MASK_ATTA,
5304 statep->usb_ac_log_handle,
5305 "usb_audio_register: add engine n =%d failed", n);
5306 goto OUT;
5307 }
5308 }
5309
5310
5311 if (usb_ac_add_controls(statep) != USB_SUCCESS) {
5312 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5313 "usb_audio_register: add controls failed");
5314 goto OUT;
5315 }
5316
5317 if (usb_ac_ctrl_set_defaults(statep) != USB_SUCCESS) {
5318 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5319 "usb_audio_register: set defaults failed");
5320 goto OUT;
5321 }
5322
5323 if (audio_dev_register(af_devp) != DDI_SUCCESS) {
5324 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5325 "audio_dev_register() failed");
5326 goto OUT;
5327 }
5328 mutex_enter(&statep->usb_ac_mutex);
5329 statep->flags |= AF_REGISTERED;
5330 mutex_exit(&statep->usb_ac_mutex);
5331
5332 rv = USB_SUCCESS;
5333
5334 OUT:
5335 if (rv != USB_SUCCESS) {
5336 (void) usb_audio_unregister(statep);
5337 }
5338 return (rv);
5339 }
5340
5341
5342 int
usb_ac_get_audio(void * handle,void * buf,int samples)5343 usb_ac_get_audio(void *handle, void *buf, int samples)
5344 {
5345 usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5346 usb_audio_eng_t *engp = &(statep->engines[0]);
5347 unsigned reqframes = samples >> engp->frsmshift;
5348 unsigned frames;
5349 unsigned i;
5350 size_t sz;
5351 caddr_t bp = buf;
5352
5353 mutex_enter(&engp->lock);
5354 if (!engp->started) {
5355 mutex_exit(&engp->lock);
5356
5357 return (0);
5358 }
5359 engp->busy = B_TRUE;
5360 mutex_exit(&engp->lock);
5361
5362 /* break requests from the driver into fragment sized chunks */
5363 for (i = 0; i < reqframes; i += frames) {
5364
5365 mutex_enter(&engp->lock);
5366 frames = reqframes - i;
5367 if (frames > engp->fragfr)
5368 frames = engp->fragfr;
5369
5370 sz = (frames << engp->frsmshift) << engp->smszshift;
5371
5372 /* must move data before updating framework */
5373 usb_eng_bufio(engp, bp, sz);
5374 engp->frames += frames;
5375 bp += sz;
5376
5377 mutex_exit(&engp->lock);
5378 }
5379
5380 mutex_enter(&engp->lock);
5381 engp->io_count++;
5382 engp->busy = B_FALSE;
5383 cv_signal(&engp->usb_audio_cv);
5384 mutex_exit(&engp->lock);
5385
5386 return (samples);
5387 }
5388
5389
5390
5391 void
usb_ac_send_audio(void * handle,void * buf,int samples)5392 usb_ac_send_audio(void *handle, void *buf, int samples)
5393 {
5394 usb_ac_state_t *statep = (usb_ac_state_t *)(handle);
5395 usb_audio_eng_t *engp = &(statep->engines[1]);
5396 unsigned reqframes = samples >> engp->frsmshift;
5397 unsigned frames;
5398 unsigned i;
5399 size_t sz;
5400 caddr_t bp = buf;
5401
5402 mutex_enter(&engp->lock);
5403
5404 if (!engp->started) {
5405
5406 mutex_exit(&engp->lock);
5407 return;
5408 }
5409 engp->busy = B_TRUE;
5410 mutex_exit(&engp->lock);
5411
5412 /* break requests from the driver into fragment sized chunks */
5413 for (i = 0; i < reqframes; i += frames) {
5414 mutex_enter(&engp->lock);
5415
5416 frames = reqframes - i;
5417 if (frames > engp->fragfr)
5418 frames = engp->fragfr;
5419
5420 sz = (frames << engp->frsmshift) << engp->smszshift;
5421
5422 /* must move data before updating framework */
5423 usb_eng_bufio(engp, bp, sz);
5424 engp->frames += frames;
5425 bp += sz;
5426
5427 mutex_exit(&engp->lock);
5428 }
5429
5430 mutex_enter(&engp->lock);
5431 engp->io_count++;
5432 engp->busy = B_FALSE;
5433 cv_signal(&engp->usb_audio_cv);
5434 mutex_exit(&engp->lock);
5435 }
5436
5437
5438 /*
5439 * **************************************************************************
5440 * audio framework engine callbacks
5441 */
5442 static int
usb_engine_open(void * arg,int flag,unsigned * nframesp,caddr_t * bufp)5443 usb_engine_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
5444 {
5445 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5446 usb_ac_state_t *statep = engp->statep;
5447 int rv = EIO;
5448
5449 _NOTE(ARGUNUSED(flag));
5450
5451 if (usb_ac_open(statep->usb_ac_dip) != USB_SUCCESS) {
5452
5453 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5454 "usb_ac_open() failed");
5455 return (EIO);
5456 }
5457
5458 mutex_enter(&engp->lock);
5459
5460 engp->intrate = 150;
5461 engp->sampsz = engp->fmt.prec / 8;
5462 engp->framesz = engp->sampsz * engp->fmt.ch;
5463
5464 engp->frsmshift = engp->fmt.ch / 2;
5465 engp->smszshift = engp->sampsz / 2;
5466
5467 /*
5468 * In order to match the requested number of samples per interrupt
5469 * from SADA drivers when computing the fragment size,
5470 * we need to first truncate the floating point result from
5471 * sample rate * channels / intr rate
5472 * then adjust up to an even number, before multiplying it
5473 * with the sample size
5474 */
5475 engp->fragsz = engp->fmt.sr * engp->fmt.ch / engp->intrate;
5476 if (engp->fragsz & 1)
5477 engp->fragsz++;
5478 engp->fragsz *= engp->sampsz;
5479 engp->fragfr = engp->fragsz / engp->framesz;
5480
5481 engp->nfrags = 10;
5482 engp->bufsz = engp->fragsz * engp->nfrags;
5483
5484 engp->bufp = kmem_zalloc(engp->bufsz, KM_SLEEP);
5485 engp->bufpos = engp->bufp;
5486 engp->bufendp = engp->bufp + engp->bufsz;
5487 engp->frames = 0;
5488 engp->io_count = 0;
5489 engp->bufio_count = 0;
5490 engp->started = B_FALSE;
5491 engp->busy = B_FALSE;
5492
5493 *nframesp = engp->nfrags * engp->fragfr;
5494 *bufp = engp->bufp;
5495
5496 mutex_exit(&engp->lock);
5497
5498 if (usb_ac_setup(statep, engp) != USB_SUCCESS) {
5499 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5500 "device setup failed");
5501 goto OUT;
5502 }
5503
5504
5505
5506 mutex_enter(&statep->usb_ac_mutex);
5507 statep->flags |= AD_SETUP;
5508 mutex_exit(&statep->usb_ac_mutex);
5509
5510 rv = 0;
5511
5512
5513 OUT:
5514 if (rv != 0)
5515 usb_engine_close(arg);
5516
5517 return (rv);
5518 }
5519
5520
5521 static void
usb_engine_close(void * arg)5522 usb_engine_close(void *arg)
5523 {
5524 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5525 usb_ac_state_t *statep = engp->statep;
5526
5527 mutex_enter(&engp->lock);
5528 while (engp->busy) {
5529 cv_wait(&engp->usb_audio_cv, &engp->lock);
5530 }
5531
5532 mutex_exit(&engp->lock);
5533
5534 if (statep->flags & AD_SETUP) {
5535 usb_ac_teardown(statep, engp);
5536 mutex_enter(&statep->usb_ac_mutex);
5537 statep->flags &= ~AD_SETUP;
5538 mutex_exit(&statep->usb_ac_mutex);
5539 }
5540 mutex_enter(&engp->lock);
5541
5542 if (engp->bufp != NULL) {
5543 kmem_free(engp->bufp, engp->bufsz);
5544 engp->bufp = NULL;
5545 engp->bufpos = NULL;
5546 engp->bufendp = NULL;
5547 }
5548
5549 mutex_exit(&engp->lock);
5550
5551 usb_ac_close(statep->usb_ac_dip);
5552 }
5553
5554
5555
5556 static int
usb_engine_start(void * arg)5557 usb_engine_start(void *arg)
5558 {
5559 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5560 int rv = 0;
5561 int (*start)(usb_ac_state_t *, usb_audio_eng_t *);
5562
5563 mutex_enter(&engp->lock);
5564 engp->started = B_TRUE;
5565 mutex_exit(&engp->lock);
5566
5567 usb_ac_state_t *statep = engp->statep;
5568
5569 start = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5570 usb_ac_start_play : usb_ac_start_record;
5571
5572 if ((*start)(statep, engp) != USB_SUCCESS) {
5573 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5574 "failed to start %d engine", engp->af_eflags);
5575 rv = EIO;
5576 }
5577
5578
5579 return (rv);
5580 }
5581
5582
5583 static void
usb_engine_stop(void * arg)5584 usb_engine_stop(void *arg)
5585 {
5586 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5587
5588 mutex_enter(&engp->lock);
5589 engp->started = B_FALSE;
5590 mutex_exit(&engp->lock);
5591
5592 usb_ac_state_t *statep = engp->statep;
5593 void (*stop)(usb_ac_state_t *, usb_audio_eng_t *);
5594
5595 stop = ((engp)->af_eflags & ENGINE_OUTPUT_CAP) ?
5596 usb_ac_stop_play : usb_ac_stop_record;
5597
5598 (*stop)(statep, engp);
5599 }
5600
5601
5602 static uint64_t
usb_engine_count(void * arg)5603 usb_engine_count(void *arg)
5604 {
5605 usb_audio_eng_t *engp = arg;
5606 uint64_t val;
5607
5608 mutex_enter(&engp->lock);
5609 val = engp->frames;
5610 mutex_exit(&engp->lock);
5611
5612 return (val);
5613 }
5614
5615
5616 static int
usb_engine_format(void * arg)5617 usb_engine_format(void *arg)
5618 {
5619 usb_audio_eng_t *engp = arg;
5620
5621 switch (engp->fmt.enc) {
5622 case USB_AUDIO_FORMAT_TYPE1_MULAW:
5623 return (AUDIO_FORMAT_ULAW);
5624 case USB_AUDIO_FORMAT_TYPE1_ALAW:
5625 return (AUDIO_FORMAT_ALAW);
5626 case USB_AUDIO_FORMAT_TYPE1_PCM8:
5627 return (AUDIO_FORMAT_U8);
5628
5629 case USB_AUDIO_FORMAT_TYPE1_PCM:
5630 break;
5631 default:
5632 return (AUDIO_FORMAT_NONE);
5633 }
5634
5635 switch (engp->fmt.prec) {
5636 case USB_AUDIO_PRECISION_8:
5637 return (AUDIO_FORMAT_S8);
5638 case USB_AUDIO_PRECISION_16:
5639 return (AUDIO_FORMAT_S16_LE);
5640 case USB_AUDIO_PRECISION_24:
5641 return (AUDIO_FORMAT_S24_LE);
5642 case USB_AUDIO_PRECISION_32:
5643 return (AUDIO_FORMAT_S32_LE);
5644 default:
5645 break;
5646 }
5647 return (AUDIO_FORMAT_NONE);
5648
5649
5650 }
5651
5652 static int
usb_engine_channels(void * arg)5653 usb_engine_channels(void *arg)
5654 {
5655 usb_audio_eng_t *engp = arg;
5656
5657 return (engp->fmt.ch);
5658 }
5659
5660
5661 static int
usb_engine_rate(void * arg)5662 usb_engine_rate(void *arg)
5663 {
5664 usb_audio_eng_t *engp = arg;
5665
5666 return (engp->fmt.sr);
5667 }
5668
5669
5670 /*ARGSUSED*/
5671 static void
usb_engine_sync(void * arg,unsigned nframes)5672 usb_engine_sync(void *arg, unsigned nframes)
5673 {
5674 /* Do nothing */
5675 }
5676
5677
5678 static unsigned
usb_engine_qlen(void * arg)5679 usb_engine_qlen(void *arg)
5680 {
5681 usb_audio_eng_t *engp = (usb_audio_eng_t *)arg;
5682
5683 return (engp->fragfr);
5684 }
5685
5686 /*
5687 * **************************************************************************
5688 * interfaces used by USB audio
5689 */
5690
5691 /*ARGSUSED*/
5692 static int
usb_change_phy_vol(usb_ac_state_t * statep,int value)5693 usb_change_phy_vol(usb_ac_state_t *statep, int value)
5694 {
5695 usb_audio_ctrl_t *ctrlp;
5696 uint64_t cval = 0;
5697 int64_t left, right, delta = 0;
5698
5699 ctrlp = statep->controls[CTL_VOLUME_STERO];
5700
5701 ASSERT(value != 0);
5702
5703 delta = (value < 0)?-1:1;
5704
5705 left = AUDIO_CTRL_STEREO_LEFT(ctrlp->cval) + delta;
5706 right = AUDIO_CTRL_STEREO_RIGHT(ctrlp->cval) + delta;
5707
5708 if (left > AF_MAX_GAIN)
5709 left = AF_MAX_GAIN;
5710 if (right > AF_MAX_GAIN)
5711 right = AF_MAX_GAIN;
5712
5713 if (left < AF_MIN_GAIN)
5714 left = AF_MIN_GAIN;
5715 if (right < AF_MIN_GAIN)
5716 right = AF_MIN_GAIN;
5717
5718 cval = AUDIO_CTRL_STEREO_VAL(left, right);
5719
5720 if (audio_control_write(ctrlp->af_ctrlp, cval)) {
5721 USB_DPRINTF_L2(PRINT_MASK_ATTA, statep->usb_ac_log_handle,
5722 "updateing control to value 0x%llx by driver failed",
5723 (long long unsigned)cval);
5724 return (USB_FAILURE);
5725 }
5726 return (USB_SUCCESS);
5727 }
5728