2. 音频控制接口初始化
任务说明
本案例完成USB音频设备类中音频控制接口(AudioControl Interface)的初始化逻辑,为后续处理音量(Volume)、静音(Mute)等类特定控制请求建立默认状态。初始化完成后,设备应能对主机发来的控制请求返回当前默认值,并支持后续通过请求处理函数修改这些值。
核心实现
// audio_control.h
#ifndef AUDIO_CONTROL_H
#define AUDIO_CONTROL_H
#include <stdint.h>
// 音频控制接口的通道数量(立体声:左/右)
#define AC_NUM_CHANNELS 2
// 控制请求选择子(USB Audio Class 1.0)
#define AC_FEATURE_UNIT_CONTROL 0x03
#define AC_MUTE_CONTROL 0x01
#define AC_VOLUME_CONTROL 0x02
// 音量范围(-60dB ~ 0dB,分辨率0.5dB,以0.5dB为单位)
#define VOLUME_MIN (-120) // -60dB
#define VOLUME_MAX 0 // 0dB
#define VOLUME_RES 1 // 0.5dB步进
typedef struct {
uint16_t mute; // 0=非静音, 1=静音
int16_t volume[AC_NUM_CHANNELS]; // 当前音量值
} ac_feature_state_t;
// 初始化音频控制接口状态
void ac_init(ac_feature_state_t *state);
// 获取当前控制值(供请求处理回调调用)
uint16_t ac_get_mute(const ac_feature_state_t *state);
int16_t ac_get_volume(const ac_feature_state_t *state, uint8_t channel);
// 设置控制值(供请求处理回调调用)
void ac_set_mute(ac_feature_state_t *state, uint16_t mute);
void ac_set_volume(ac_feature_state_t *state, uint8_t channel, int16_t volume);
#endif // AUDIO_CONTROL_H
// audio_control.c
#include "audio_control.h"
void ac_init(ac_feature_state_t *state) {
if (!state) return;
state->mute = 0; // 默认非静音
for (int i = 0; i < AC_NUM_CHANNELS; i++) {
state->volume[i] = VOLUME_MAX; // 默认0dB
}
}
uint16_t ac_get_mute(const ac_feature_state_t *state) {
return state ? state->mute : 0;
}
int16_t ac_get_volume(const ac_feature_state_t *state, uint8_t channel) {
if (!state || channel >= AC_NUM_CHANNELS) return 0;
return state->volume[channel];
}
void ac_set_mute(ac_feature_state_t *state, uint16_t mute) {
if (state) state->mute = mute ? 1 : 0;
}
void ac_set_volume(ac_feature_state_t *state, uint8_t channel, int16_t volume) {
if (!state || channel >= AC_NUM_CHANNELS) return;
// 限制在有效范围内
if (volume < VOLUME_MIN) volume = VOLUME_MIN;
if (volume > VOLUME_MAX) volume = VOLUME_MAX;
state->volume[channel] = volume;
}
// 使用示例(main.c 或请求处理回调中)
#include "audio_control.h"
ac_feature_state_t ac_state;
void usb_audio_control_init(void) {
ac_init(&ac_state);
}
// 处理主机发来的 GET_CUR 请求时调用
uint16_t handle_get_cur(uint8_t control_selector, uint8_t channel) {
switch (control_selector) {
case AC_MUTE_CONTROL:
return ac_get_mute(&ac_state);
case AC_VOLUME_CONTROL:
return (uint16_t)ac_get_volume(&ac_state, channel);
default:
return 0;
}
}
// 处理主机发来的 SET_CUR 请求时调用
void handle_set_cur(uint8_t control_selector, uint8_t channel, uint16_t value) {
switch (control_selector) {
case AC_MUTE_CONTROL:
ac_set_mute(&ac_state, value);
break;
case AC_VOLUME_CONTROL:
ac_set_volume(&ac_state, channel, (int16_t)value);
break;
default:
break;
}
}
编译与验证
将上述三个文件加入工程编译(或直接编译audio_control.c与包含main的测试文件)。验证路径如下:
- 调用
ac_init()后,断言ac_get_mute()返回0,ac_get_volume(ch0)与ac_get_volume(ch1)均返回0(即0dB)。 - 调用
ac_set_volume(0, -60),再读取ac_get_volume(0),应返回-60。 - 调用
ac_set_volume(1, 100)(超出上限),读取应被钳位到0。 - 调用
ac_set_mute(1)后,ac_get_mute()返回1。
通过条件:以上断言全部成立,且handle_get_cur/handle_set_cur能正确映射到状态读写。该初始化逻辑为USB音频类控制请求处理提供了确定的默认状态与访问接口,可直接接入UDC(USB Device Controller)的EP0回调中。