Description
Problem Description
Currently UAC2 is missing feature unit support, necessary for basic functionality such as volume and mute. Most I2S codecs and amplifiers offer both mute and volume gain control through I2C, so it's quite important to implement these feature units.
Proposed Change (Summary)
The chance would expand uac2_ops with callbacks to handle CUR and RANGE requests.
the explicit feedback sample would be expanded to handle these requests for volume and mute.
A draft implementation is provided here https://github.com/Smartbox-Assistive-Technology/zephyr/pull/1/files
Proposed Change (Detailed)
Introduce the following new APIs:
/**
* @brief USB Audio 2 Feature Unit event handlers
*/
struct uac2_feature_unit_ops {
/**
* @brief Callback for host SET CUR requests on a Feature Unit.
* @param[in] buf Raw buffer from the host containing the new value.
* @param dev USB Audio 2 device
* @param entity_id Feature Unit ID
* @param control_selector Control selector (mute, volume, etc.)
* @param channel_num Channel number (0 = master, 1+ = individual channels)
* @param buf Buffer containing the new control value
* @param user_data Opaque user data pointer
* @return 0 on success, negative value on error
*/
int (*set_cur_cb)(const struct device *dev, uint8_t entity_id,
enum usb_audio_fucs control_selector, uint8_t channel_num,
const struct net_buf *buf, void *user_data);
/**
* @brief Callback for host GET CUR requests on a Feature Unit.
* @param dev USB Audio 2 device
* @param entity_id Feature Unit ID
* @param control_selector Control selector (mute, volume, etc.)
* @param channel_num Channel number (0 = master, 1+ = individual channels)
* @param[out] value Pointer to be filled with the current control value.
* @param user_data Opaque user data pointer
* @return 0 on success, negative value on error
*/
int (*get_cur_cb)(const struct device *dev, uint8_t entity_id,
enum usb_audio_fucs control_selector, uint8_t channel_num,
uint32_t *value, void *user_data);
/**
* @brief Callback for host GET RANGE requests on a Feature Unit.
* @param dev USB Audio 2 device
* @param entity_id Feature Unit ID
* @param control_selector Control selector (mute, volume, etc.)
* @param channel_num Channel number (0 = master, 1+ = individual channels)
* @param[out] range Pointer to the uac2_range struct to be filled.
* @param user_data Opaque user data pointer
* @return 0 on success, negative value on error
*/
int (*get_range_cb)(const struct device *dev, uint8_t entity_id,
enum usb_audio_fucs control_selector, uint8_t channel_num,
struct uac2_range *range, void *user_data);
};
Add a new enum, similar to what was present in usb_audio.h
* Refer Table A-23 from UAC2 specification
*/
enum usb_audio_fucs {
/* UAC1 and UAC2 controls */
USB_AUDIO_FU_CONTROL_UNDEFINED = 0x00,
USB_AUDIO_FU_MUTE_CONTROL = 0x01,
USB_AUDIO_FU_VOLUME_CONTROL = 0x02,
USB_AUDIO_FU_BASS_CONTROL = 0x03,
USB_AUDIO_FU_MID_CONTROL = 0x04,
USB_AUDIO_FU_TREBLE_CONTROL = 0x05,
USB_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL = 0x06,
USB_AUDIO_FU_AUTOMATIC_GAIN_CONTROL = 0x07,
USB_AUDIO_FU_DELAY_CONTROL = 0x08,
USB_AUDIO_FU_BASS_BOOST_CONTROL = 0x09,
USB_AUDIO_FU_LOUDNESS_CONTROL = 0x0A,
/* UAC2-only controls */
USB_AUDIO_FU_INPUT_GAIN_CONTROL = 0x0B,
USB_AUDIO_FU_INPUT_GAIN_PAD_CONTROL = 0x0C,
USB_AUDIO_FU_PHASE_INVERTER_CONTROL = 0x0D,
USB_AUDIO_FU_UNDERFLOW_CONTROL = 0x0E,
USB_AUDIO_FU_OVERFLOW_CONTROL = 0x0F,
USB_AUDIO_FU_LATENCY_CONTROL = 0x10
};
Add a new struc for the feature units, and expand uac2_ops
with feature_unit_ops
static const struct uac2_feature_unit_ops usb_audio_fu_ops = {
.set_cur_cb = app_set_feature_unit_cb,
.get_cur_cb = app_get_fu_cur_cb,
.get_range_cb = app_get_fu_range_cb,
};
static struct uac2_ops usb_audio_ops = {
.sof_cb = uac2_sof,
.terminal_update_cb = uac2_terminal_update_cb,
.get_recv_buf = uac2_get_recv_buf,
.data_recv_cb = uac2_data_recv_cb,
.buf_release_cb = uac2_buf_release_cb,
.feedback_cb = uac2_feedback_cb,
.feature_unit_ops = &usb_audio_fu_ops,
};
Update sample to include a sample implementation, and print some logs when the volume or mute status changes.
Dependencies
No response
Concerns and Unresolved Questions
No response
Alternatives Considered
I considered providing callbacks just for the volume and the mute, but that would introduce a bit too many callbacks for my taste, and also would need to be expanded extensively to handle all the other requests.
Metadata
Metadata
Assignees
Type
Projects
Status