usb_ac.c revision 77e515715b61e28fcf0c3f30936492888cecfd8b
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * AUDIO CONTROL Driver: usb_ac is a streams multiplexor that sits 2N/A * on top of usb_as and hid and is responsible for 2N/A * (1) providing the entry points to audio mixer framework, (2) passing 2N/A * streams messages to and from usb_as and hid and (3) processing 2N/A * control messages that it can handle. 2N/A * 1. Mixer entry points are: usb_ac_setup(), usb_ac_teardown(), 2N/A * usb_ac_set_config(), usb_ac_set_format(), usb_ac_start_play(), 2N/A * usb_ac_pause_play(), usb_ac_stop_play, usb_ac_start_record(), 2N/A * usb_ac_stop_record(). 2N/A * 2. usb_ac is a streams driver that passes streams messages down to 2N/A * usb_as that selects the correct alternate with passed format 2N/A * 3. usb_ac handles the set_config command through the default pipe 2N/A * of sound control interface of the audio device in a synchronous 2N/A * Serialization: usb_ac being a streams driver and having the requirement 2N/A * of making non-blockings calls (USBA or streams or mixer) needs to drop 2N/A * mutexes over such calls. But at the same time, a competing thread 2N/A * can't be allowed to interfere with (1) pipe, (2) streams state. 2N/A * So we need some kind of serialization among the asynchronous 2N/A * threads that can run in the driver. The serialization is mostly 2N/A * etc. Once a routine takes control, it checks if the resource (pipe or 2N/A * stream or dev state) is still accessible. If so, it proceeds with 2N/A * its job and until it completes, no other thread requiring the same 2N/A * PM model in usb_ac: Raise power during attach. If a device is not at full 2N/A * power, raise power in the entry points. After the command is over, 2N/A * pm_idle_component() is called. The power is lowered in detach(). 2N/A * locking: Warlock is not aware of the automatic locking mechanisms for 2N/A * tunable timeout for usb_as response, allow at least 10 secs for control 2N/A * table for converting term types of input and output terminals 2N/A * to SADA port types (pretty rough mapping) 2N/A * Module linkage routines for the kernel 2N/A * STREAMS module entry points 2N/A/* descriptor handling */ 2N/A/* power management */ 2N/A/* Mixer entry points */ 2N/A * External functions 2N/A * mixer registration data 2N/A/* anchor for soft state structures */ 2N/A/* for passing soft state etc. to usb_ac_dacf module */ 2N/A/* STREAMS driver id and limit value structure */ 2N/A 0xffff,
/* module ID number */ 2N/A "usb_ac",
/* module name */ 2N/A/* STREAMS queue processing procedures structures */ 2N/A/* upper read queue */ 2N/A/* upper write queue */ 2N/A/* lower read queue */ 2N/A/* lower write queue */ 2N/A/* STREAMS entity declaration structure */ 2N/A * Entry points structure 2N/A/* Device operations structure */ 2N/A 0,
/* devo_refcnt */ 2N/A/* Linkage structure for loadable drivers */ 2N/A "USB Audio Control Driver",
/* drv_linkinfo */ 2N/A/* Module linkage structure */ 2N/A NULL /* NULL terminates the list */ 2N/A/* warlock directives */ 2N/A/* standard entry points */ 2N/A /* initialize the soft state */ 2N/A /* Free the soft state internal structures */ 2N/A * wait until all processes are started from main. 2N/A * USB enumerates early in boot (ie. consconfig time). 2N/A * If the plumbing takes place early, the file descriptors 2N/A * are owned by the init process and can never be closed anymore 2N/A * Consequently, hot removal is not possible and the dips 2N/A * never go away. By waiting some time, e.g. INIT_PROCESS_CNT, 2N/A * the problem is avoided. 2N/A * Allocate soft state information. 2N/A * get soft state space and initialize 2N/A /* get log handle */ 2N/A "usb_client_attach failed");
2N/A "usb_get_dev_data failed");
2N/A /* initialize mutex & cv */ 2N/A /* register with audiosup */ 2N/A * we register with pathname, the mgf, product, and serial number 2N/A * strings, vid.pid, and driver name which should be pretty unique 2N/A "registering with key: %s",
key);
2N/A "audio_sup_register failed");
2N/A /* save softstate pointer in audio handle */ 2N/A /* parse all class specific descriptors */ 2N/A /* we no longer need the descr tree */ 2N/A /* read .conf file properties */ 2N/A /* create minor node */ 2N/A "usb_ac_attach: couldn't create minor node mux");
2N/A * safe guard the postattach to be executed 2N/A * only two states arepossible: plumbed / unplumbed 2N/A /* create components to power manage this device */ 2N/A /* Register for events */ 2N/A "usb_ac_attach: couldn't register for events");
2N/A "usb_ac_attach: End");
2N/A * cleanup on attach failure and detach 2N/A "usb_ac_cleanup: uacpm=0x%p", (
void *)
uacpm);
2N/A * deregister with audio framework, if it fails we are hosed 2N/A * and we probably don't want to plumb again 2N/A * Disable the event callbacks, after this point, event 2N/A * callbacks will never get called. Note we shouldn't hold 2N/A * the mutex while unregistering events because there may be a 2N/A * competing event callback thread. Event callbacks are done 2N/A * with ndi mutex held and this can cause a potential deadlock. 2N/A "usb_ac_cleanup: disable remote " 2N/A /* free descriptors */ 2N/A "usb_ac_cleanup: Ending");
2N/A * Open entry point. Called on the plumbing minor node or 2N/A * audio or audioctl minor nodes which we pass to audio_sup_open() 2N/A * We do not raise power here and wait for the setup callback 2N/A "usb_ac_open: Begin q=0x%p, minor=0x%x instance=%d " 2N/A "usb_ac_open: clone open not supported");
2N/A "usb_ac_open: opening mux");
2N/A * This is the plumbing open, initiated during attach/ 2N/A /* Save the dev_t value of pluming q to use for lower q's */ 2N/A /* Initialize the queue pointers */ 2N/A /* release mutex while making streams framework call */ 2N/A /* pass the open to audio_sup_open so SADA can do its work */ 2N/A "usb_ac_open: calling audio_sup_open, q=0x%p, open_cnt=%d",
2N/A "usb_ac_open: End q=0x%p, open cnt=%d",
2N/A "usb_ac_close: Begin q=0x%p, opencount=%d",
2N/A /* closing the mux? */ 2N/A "usb_ac_close: closing mux plumbing stream");
2N/A /* Wait till all activity in the default pipe has drained */ 2N/A /* normal streams closing */ 2N/A "usb_ac_close: End rval=%d q=0x%p, opencount=%d",
2N/A * are processed here. All other ioctls are passed to audio_sup routines 2N/A * for further processing. 2N/A "usb_ac_uwput: q=0x%p, mp=0x%p", (
void *)q, (
void *)
mp);
2N/A /* ioctl from plumbing thread (namely P_LINK) */ 2N/A /* Pass to audio_sup routine */ 2N/A * read put entry point for the lower mux. Get the response from the 2N/A * lower module, signal usb_ac_send_as_cmd(), the thread that is waiting 2N/A * for a response to a message sent earlier anbd pass the response 2N/A "usb_ac_lrput: q=0x%p, mp=0x%p, instance=%d",
2N/A "reply from usb_as, lrq=0x%p", (
void *)q);
2N/A "M_CTL from hid, lrq=0x%p", (
void *)q);
2N/A /* Handle relative volume change */ 2N/A /* prevent unplumbing */ 2N/A "M_CTL from unknown module(%s)",
2N/A * Nobody is waiting; nothing to send up. 2N/A "usb_ac_lrput: done");
2N/A "usb_ac_power: illegal level=%d pwr_states=%d",
2N/A * functions to handle power transition for various levels 2N/A * These functions act as place holders to issue USB commands 2N/A * to the devices to change their power levels 2N/A * Level 0 = Device is powered off 2N/A * Level 3 = Device if full powered 2N/A * Level 1,2 = Intermediate power level of the device as implemented 2N/A * Note that Level 0 is OS power-off and Level 3 is OS full-power. 2N/A /* Deny the powerdown request if the device is busy */ 2N/A /* Issue USB D3 command to the device here */ 2N/A /* Issue USB D2 command to the device here */ 2N/A /* Issue USB D0 command to the device here */ 2N/A /* we are already in full power */ 2N/A "usb_ac_pwerlvl3: Illegal dev_state");
2N/A "usb_ac_create_pm_components: begin");
2N/A /* Allocate the state structure */ 2N/A "remote Wakeup enabled");
2N/A "usb_ac_create_pm_components: end");
2N/A * usb_ac_plumb_ioctl: 2N/A * caused by ldi_ioctl). Maybe we will need to use this function 2N/A * to issue other IOCTLS to children in future from plumbing thread 2N/A "usb_ac_plumb_ioctl, q=0x%p mp=0x%p instance=%d",
2N/A "LINK ioctl, index=%d linkblk ptr=0x%p", n, (
void *)
linkp);
2N/A * We keep track of the module that is being 2N/A * currently plumbed through usb_ac_current_plumbed_index 2N/A * to the plumb structure array. We set the lwq field 2N/A * of the plumb structure here. 2N/A "UNLINK ioctl, linkblk ptr=0x%p", (
void *)
linkp);
2N/A * we bzero the streams info and plumbed structure 2N/A * since there is no guarantee that the next plumbing 2N/A /* bzero the relevant plumbing structure */ 2N/A * Common exit path for calls that return a positive 2N/A * acknowledgment with a return value of 0. 2N/A "usb_ac_plumb_ioctl: End (ACK)");
2N/A "usb_ac_plumb_ioctl: End: (NAK)");
2N/A * usb_ac_get_plumb_info: 2N/A * Get plumb_info pointer that matches module "name" 2N/A * If name = "usb_as", match the direction also (record or play) 2N/A /* Match direction */ 2N/A * usb_ac_get_pinfo_from_lrq: 2N/A * Get plumb_info pointer that matches the lrq passed 2N/A * usb_ac_get_featureID: 2N/A * find out if there is at least one feature unit that supports 2N/A * the request controls. 2N/A * Return featureID or USB_AC_ID_NONE. 2N/A * usb_ac_feature_unit_check: 2N/A * check if a feature unit can support the required channel 2N/A * and control combination. Return USB_SUCCESS or USB_FAILURE. 2N/A * Called for each matching unit from usb_ac_traverse_connections. 2N/A "usb_ac_feature_unit_check: ID=%d ch=%d cntrl=%d",
2N/A * check if this control is supported on this channel 2N/A * we only support MUTE and VOLUME 2N/A * which are in the first byte 2N/A "usb_ac_feature_unit_check: dir=%d featureID=0x%x",
2N/A * Descriptor Management 2N/A * usb_ac_handle_descriptors: 2N/A * extract interesting descriptors from the config cloud 2N/A "config=%ld, interface=%d",
2N/A /* find USB_AUDIO_CS_INTERFACE type descriptor */ 2N/A /* is this a sane header descriptor */ 2N/A "header: type=0x%x subtype=0x%x bcdADC=0x%x\n\t" 2N/A "total=0x%x InCol=0x%x",
2N/A * we read descriptors by index and store them in ID array. 2N/A * the actual parsing is done in usb_ac_add_unit_descriptor() 2N/A /* add to ID array */ 2N/A /* determine port types */ 2N/A "input port types=0x%x output port types =0x%x",
2N/A * usb_ac_setup_connections: 2N/A * build a matrix reflecting all connections 2N/A /* allocate array for unit types for quick reference */ 2N/A /* allocate array for traversal path */ 2N/A /* allocate the connection matrix and set it up */ 2N/A /* trick to create a 2 dimensional array */ 2N/A /* traverse all units and set connections */ 2N/A "traversing unit=0x%x type=0x%x",
2N/A /* store type in the first unused column */ 2N/A /* save the Unit ID in the unit it points to */ 2N/A "sourceID=0x%x type=0x%x c=%d",
2N/A "sourceID=0x%x type=0x%x",
2N/A "sourceID=0x%x type=0x%x",
2N/A "sourceID=0x%x type=0x%x",
2N/A * Ignore the rest because they are not support yet 2N/A /* display topology in log buffer */ 2N/A /* two strings so they won't be replaced accidentily by tab */ 2N/A "adjacency matrix:");
2N/A * usb_ac_add_unit_descriptor: 2N/A * take the parsed descriptor in the buffer and store it in the ID unit 2N/A * array. we grow the unit array if the ID exceeds the current max 2N/A "usb_ac_add_unit_descriptor: 0x%x 0x%x 0x%x",
2N/A /* doubling the length should allow for padding */ 2N/A /* ignore this descriptor */ 2N/A /* ignore this descriptor */ 2N/A "input term: type=0x%x sub=0x%x termid=0x%x\n\t" 2N/A "termtype=0x%x assoc=0x%x #ch=%d " 2N/A "chconf=0x%x ich=0x%x iterm=0x%x",
2N/A "output term: type=0x%x sub=0x%x termid=0x%x\n\t" 2N/A "termtype=0x%x assoc=0x%x sourceID=0x%x iterm=0x%x",
2N/A "mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2N/A "#pins=0x%x sourceid[0]=0x%x",
2N/A "selector unit: type=0x%x sub=0x%x unitid=0x%x\n\t" 2N/A "#pins=0x%x sourceid[0]=0x%x",
"feature unit: type=0x%x sub=0x%x unitid=0x%x\n\t" "sourceid=0x%x size=0x%x",
"processing unit: type=0x%x sub=0x%x unitid=0x%x\n\t" "#pins=0x%x sourceid[0]=0x%x",
"mixer unit: type=0x%x sub=0x%x unitid=0x%x\n\t" "#pins=0x%x sourceid[0]=0x%x",
* check if the unit ID is less than max_unit in which case no * extra entries are needed. If more entries are needed, copy over * the existing array into a new larger array "usb_ac_alloc_unit: unit=%d",
unit);
/* existing array is big enough */ /* allocate two extra ones */ * free the entire unit list * usb_ac_lookup_port_type: * map term type to port type * default just return LINE_IN + LINE_OUT * called for each terminal "usb_ac_update_port: dir=%d type=0x%x port type=%d",
"usb_ac_update_port: dir=%d type=0x%x port type=%d",
* usb_ac_map_termtype_to_port: * starting from a streaming termtype find all * input or output terminals and OR into uacp->usb_ac_input_ports * or uacp->usb_ac_output_ports; "usb_ac_map_term_to_port: dir=%d",
dir);
* find a selector port (record side only) and set the * input to the matching pin "usb_ac_set_port: dir=%d port=%d",
dir,
port);
/* we only support the selector for the record side */ "usb_ac_set_port: id=%d count=%d port=%d",
* given the requested port type, find a correspondig term type * Called from usb_ac_traverse_all_units() "usb_ac_match_port: id=%d dir=%d port=%d",
"dir=%d type=0x%x port_type=%d port=%d",
"dir=%d type=0x%x port_type=%d port=%d",
* Called from usb_ac_traverse_all_units() * Find the correct pin and set selector to this pin "usb_ac_set_selector: id=%d dir=%d port=%d",
* for each pin, find a term type that matches the "usb_ac_set_selector: pin=%d unit=%d",
pin,
unit);
/* find units connected to this unit */ "usb_ac_set_selector: found id=%d at pin %d",
unit,
pin);
/* feature unit and id */ "set current pin selection failed");
"usb_ac_set_selector: nothing found");
* apply func to all units of search_target type for both the * requested channel and master channel "usb_ac_set_control: dir=%d type=%d ch=%d cntl=%d",
* usb_ac_traverse_all_units: * traverse all units starting with all IT or OT depending on direction. * If no unit is found for the particular channel, try master channel * If a matching unit is found, apply the function passed by "usb_ac_traverse_all_units: " "dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
/* keep track of recursion */ "Unit topology too complex, giving up");
/* is this an IT or OT? */ /* start at streaming term types */ /* find units connected to this unit */ * usb_ac_set_monitor_gain_control: * search for a feature unit between output terminal (OT) and * input terminal. We are looking for a path between * for example a microphone and a speaker through a feature unit "usb_ac_set_monitor_gain_control: dir=%d type=%d ch=%d cntl=%d",
/* is this an OT and not stream type? */ /* find units connected to this unit */ "usb_ac_push_unit_id: pushing %d at %d",
unit,
"usb_ac_push_unit_id: popping %d at %d",
unit,
* usb_ac_show_traverse_path: * display entire path, just for debugging "traverse path %d: unit=%d type=%d",
* check for a specified type in the traverse path * usb_ac_traverse_connections: * traverse all units and for each unit with the right type, call * func. If the func returns a success and search == USB_AC_FIND_ONE, * we are done. If all is set then we continue until we terminate * and input or output terminal. * For audio play, we traverse columns starting from an input terminal * to an output terminal while for record we traverse rows from output * terminal to input terminal. "usb_ac_traverse_connections: " "start=%d dir=%d type=%d ch=%d cntl=%d all=%d depth=%d",
/* keep track of recursion depth */ "Unit topology too complex, giving up");
"start=%d unit=%d entry=%d type=%d " /* did we find a matching type? */ "match: dir=%d unit=%d type=%d",
/* yes, no apply function to this unit */ "func returned success, " /* did we find the terminating unit */ * usb_ac_disconnect_event_cb: * The device has been disconnected. we either wait for * detach or a reconnect event. "usb_ac_disconnect_event_cb: dip=0x%p", (
void *)
dip);
/* setting to disconnect state will prevent replumbing */ "device was disconnected while busy. " "Data may have been lost");
"usb_ac_disconnect_event_cb: done");
"usb_ac_cpr_suspend: Begin");
"usb_ac_cpr_suspend: End");
* usb_ac_reconnect_event_cb: * The device was disconnected but this instance not detached, probably * because the device was busy. * if the same device, continue with restoring state * We should either be in the unplumbed state or the plumbed open "usb_ac_reconnect_event_cb: dip=0x%p", (
void *)
dip);
/* check the plumbing state */ "busy device has been reconnected");
* usb_ac_restore_device_state: * Set original configuration of the device * enable wrq - this starts new transactions on the control pipe "usb_ac_restore_device_state:");
/* Check if we are talking to the same device */ /* change the device state from suspended to disconnected */ "usb_ac_restore_device_state: " "enable failed, rval=%d",
rval);
* usb_ac_am_restore_state "usb_ac_am_restore_state: Begin");
* allow hid and usb_as to restore themselves * (some handshake would have been preferable though) "usb_ac_am_restore_state: End");
* usb_ac_restore_audio_state: "usb_ac_restore_audio_state: flag=%d",
flag);
* increment busy_count again, it will be decremented * in usb_ac_am_restore_state * Mixer Callback Management * NOTE: all mixer callbacks are serialized. we cannot be closed while * we are in the middle of a callback. There needs to be a * teardown first. We cannot be unplumbed as long as we are * Send setup to usb_as if the first setup * Check power is done in usb_ac_send_as_cmd() "usb_ac_setup: Begin ahdl=0x%p, stream=%d, flag=%d",
"usb_ac_setup: rval=%d",
rval);
* Wrapper function for usb_ac_setup which can be called * either from audio framework for usb_ac_set_format "usb_ac_do_setup: Begin ahdl=0x%p, stream=%d, flag=%d",
* Handle multiple setup calls. Pass the setup call to usb_as only * the first time so isoc pipe will be opened only once "usb_ac_do_setup: more than one setup, cnt=%d",
/* Send setup command to usb_as */ "usb_ac_do_setup: failure");
* Send teardown to usb_as if the last teardown * Check power is done in usb_ac_send_as_cmd() * NOTE: allow teardown when disconnected "usb_ac_teardown: Begin ahdl=0x%p, stream=%d",
* Check power is done in usb_ac_send_as_cmd() "usb_ac_do_teardown: Begin ahdl=0x%p, stream=%d",
/* There should be at least one matching setup call */ * only this is the last teardown so that isoc pipe is closed /* Send teardown command to usb_as */ "usb_ac_do_teardown: failure");
"usb_ac_do_teardown: End");
* This routine will send control commands to get the max * and min gain balance, calculate the gain to be set from the * arguments and send another control command to set it. * Check power is done here since we will access the default pipe "usb_ac_set_config: Begin ahdl=0x%p\n\t" "stream=%d, cmd=%d, flag=%d, arg1=%d, arg2=%d",
* Set the gain for a channel. The audio mixer calculates the * impact, if any, on the channel's gain. * 0 <= gain <= AUDIO_MAX_GAIN * arg2 --> channel #, 0 == left, 1 == right * We service the set_config command when the device is "usb_ac_set_config: channel(%d) passed is " * If feature unit id could not be found, it probably means * volume/gain control is not available for this device. * and we just return success if we haven't completed * the registration with the mixer yet "mixer=%d, no featureID, arg1=%d",
* We service the set_config command when the device is "usb_ac_set_config: channel(%d) passed is " * always return success since we told the mixer * we always support this and sdtaudiocontrol displays * monitor gain regardless. /* Now it's safe to release access to other routines */ "usb_ac_set_config: %s done, rval=%d",
what,
rval);
* usb_ac_set_monitor_gain: * called for each output terminal which supports * from usb_ac_traverse_connections "usb_ac_set_monitor_gain: ");
"id=%d dir=%d ch=%d cntl=%d gain=%d type=%d term type=0x%x",
/* log how we got here */ /* we only care about the ITs connected to real hw inputs */ * we can only do this if the microphone is mixed into the * audio output so look for a mixer first /* now look for a feature unit */ /* the FU should be before the mixer */ * usb_ac_set_gain is called for each feature unit which supports * the requested controls from usb_ac_traverse_connections * we still need to check whether this unit supports the requested "usb_ac_set_gain: id=%d dir=%d ch=%d cntl=%d gain=%d",
"usb_ac_set_gain: getting max gain failed");
"usb_ac_set_gain: channel %d, max=%d",
channel,
max);
"usb_ac_set_gain: getting min gain failed");
"usb_ac_set_gain: channel=%d, min=%d",
channel,
min);
"usb_ac_set_gain: getting cur gain failed");
* Set the gain for a channel. The audio mixer calculates the * impact, if any, on the channel's gain. * 0 <= gain <= AUDIO_MAX_GAIN * channel #, 0 == left, 1 == right "usb_ac_set_gain: ch=%d dir=%d max=%d min=%d gain=%d",
"usb_ac_set_gain: setting volume failed");
/* just curious, read it back, device may round up/down */ "usb_ac_set_gain: getting cur gain failed");
* This mixer callback initiates a command to be sent to * usb_as to select an alternate with the passed characteristics * and also to set the sample frequency. * Note that this may be called when a playing is going on in * the streaming interface. To handle that, first stop * command, send the set_format command down and then reopen * the pipe. Note : (1) audio framework will restart play/record * after a set_format command. (2) Check power is done in "usb_ac_set_format: Begin ahdl=0x%p, stream=%d, flag=%d, " "usb_ac_set_format: no plumb info");
/* isoc pipe not open and playing is not in progress */ /* isoc pipe is open and playing might be in progress */ /* Keep a copy of the old format */ /* This blocks until the current isoc xfer is over */ * Setting new alternate has failed, try restoring * If there is a bandwidth failure, hang around * till bandwidth is available. Also we know that * there is a matching alternate, so that can't fail. /* We closed the pipe; reopen it */ /* This should block until successful */ "usb_ac_set_format: End");
* usb_ac_get_curr_n_channels: * Return no. of channels from the current format table * Get format for the current alternate "usb_ac_get_curr_format: no plumb info");
* Sets format and get alternate setting that matches with * the format from the usb_as playing or recording interface * Send the set sample freq command down to usb_as. "usb_ac_send_format_cmd: Begin ahdl=0x%p, stream=%d, dir=%d, " "usb_ac_send_format_cmd: plumb_infop=0x%p, streams_infop=0x%p",
* Set format for the streaming interface with lower write queue * This boils down to set_alternate interface command in * usb_as and the reply mp contains the currently active * alternate number that is stored in the as_req structure "usb_ac_send_format_cmd: failed");
/* alternate number stored and reply mp freed */ /* Set the sample rate */ "usb_ac_send_format_cmd: setting format failed");
"usb_ac_send_format_cmd: End");
* Send a start_play command down to usb_as * Check power is done in usb_ac_send_as_cmd() "usb_ac_start_play: Begin ahdl=0x%p, stream=%d",
"usb_ac_start_play: plumb_infop=0x%p, streams_infop=0x%p",
/* Check for continuous sample rate done in usb_as */ /* Send setup command to usb_as */ "usb_ac_start_play: failure");
"usb_ac_start_play: End");
* Wrapper function for usb_ac_do_pause_play and gets * called from mixer framework. "usb_ac_pause_play: Begin ahdl=0x%p, stream=%d",
"usb_ac_pause_play: End");
* Send a pause_play command to usb_as. * Check power is done in usb_ac_send_as_cmd() "usb_ac_do_pause_play: Begin ahdl=0x%p, stream=%d",
/* Send setup command to usb_as */ "usb_ac_do_pause_play: failure");
"usb_ac_do_pause_play: End");
* Wrapper function for usb_ac_pause_play and gets * called from mixer framework. "usb_ac_stop_play: Begin ahdl=0x%p, stream=%d",
"usb_ac_stop_play: End");
* Sends a start record command down to usb_as. * Check power is done in usb_ac_send_as_cmd() "usb_ac_start_record: Begin ahdl=0x%p, stream=%d",
/* Send setup command to usb_as */ "usb_ac_start_record: failure");
"usb_ac_start_record: End");
* Wrapper function for usb_ac_do_stop_record and is * called form mixer framework. "usb_ac_stop_record: Begin ahdl=0x%p, stream=%d",
"usb_ac_stop_record: End");
* Sends a stop_record command down. * Check power is done in usb_ac_send_as_cmd() "usb_ac_do_stop_record: Begin ahdl=0x%p, stream=%d",
/* Send setup command to usb_as */ "usb_ac_do_stop_record: failure");
"usb_ac_do_stop_record: End");
* Helper Functions for Mixer callbacks * usb_ac_get_maxmin_volume: * Send USBA command down to get the maximum or minimum gain balance * Calculate min or max gain balance and return that. Return * USB_FAILURE for failure cases "usb_ac_get_maxmin_volume: channel=%d, cmd=%d dir=%d",
/* feature unit and id */ "usb_ac_get_maxmin_volume: failed, " "cr=%d, cb=0x%x cmd=%d, data=0x%p",
"usb_ac_get_maxmin_volume: max_or_min=0x%x",
max_or_min);
* Send USBA command down to set the gain balance "usb_ac_set_volume: channel=%d gain=%d dir=%d FU=%d",
/* Construct the mblk_t from gain for sending to USBA */ /* feature unit and id */ "usb_ac_set_volume: failed, cr=%d cb=0x%x",
* usb_ac_set_mute is called for each unit that supports the * requested control from usb_ac_traverse_connections "usb_ac_set_mute: muteval=0x%x, dir=%d",
muteval,
dir);
/* Construct the mblk_t for sending to USBA */ /* feature unit and id */ "usb_ac_set_mute: failed, cr=%d cb=0x%x",
cr,
cb_flags);
* Allocate message blk, send a command down to usb_as, * wait for the reply and free the message * although not really needed to raise power if sending to as * it seems better to ensure that both interfaces are at full power "usb_ac_send_as_cmd: Begin lwq=0x%p, cmd=0x%x, arg=0x%p",
"usb_ac_send_as_cmd: canputnext failed");
* Allocate mblk for a particular command "usb_ac_send_as_cmd: unknown cmd=%d",
cmd);
"usb_ac_send_as_cmd: can't get mblk to send cmd down");
* Set wait flag and send message down; we have made sure * before that canputnext succeeds. Note mp will be freed down * Wait for the response; reply will arrive through rput() * M_CTL and the cv_wait will be signaled there and wait flag " timeout happen before cmd complete.");
" not signaled by USB_AS_PLUMBED.");
/* Wait is over, get the reply data */ "usb_ac_send_as_cmd: db_type=0x%x cmd=0x%x",
* This command sets mixer format data * and returns alternate setting that matches * usb_ac_allocate_req_mblk: * Allocate a message block with the specified M_CTL cmd, * The 2nd mblk contains the data for the command with a length len "usb_ac_allocate_req_mblk: cmd=0x%x, buf=0x%p, len=%d",
"usb_ac_allocate_req_mblk: mp=0x%p", (
void *)
mp);
"usb_ac_pm_busy_component: %d",
"usb_ac_pm_busy_component failed: %d",
"usb_ac_pm_idle_component: %d",