doubao_chat/apps/common/usb/host/audio.c

1841 lines
65 KiB
C

#include "app_config.h"
#include "system/timer.h"
#include "device/ioctl_cmds.h"
#include "generic/includes.h"
#include "system/init.h"
#if TCFG_HOST_AUDIO_ENABLE
#include "usb/host/usb_host.h"
#include "usb_ctrl_transfer.h"
#include "usb_bulk_transfer.h"
#include "audio.h"
#include "usb_config.h"
#include "event/device_event.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[AUDIO]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define retval_check(ret, out) \
if ((int)(ret) < 0) { \
log_error("ret %d", (ret)); \
if ((out)) { \
goto __exit_fail; \
} \
}
#define my_abs(a) ((a) > 0 ? (a) : (-(a)))
/* #define USB_AUDIO_PLAY_TEST */
struct usb_audio_mic {
u32 sample_rate;
u8 *send_buf;
u8 *usb_audio_mic_buf;
u8 *usb_audio_mic_buf2;
cbuffer_t usb_audio_record_cbuf;
u32 usb_audio_remain_len;
OS_SEM sem;
int (*get_buf)(const usb_dev usb_id, void *ptr, u32 len, u8 channel, u32 sample_rate);
u16 vol_cur;
u16 vol_min;
u16 vol_max;
u16 vol_res;
u16 vol_l_cur;
u16 vol_l_min;
u16 vol_l_max;
u16 vol_l_res;
u16 vol_r_cur;
u16 vol_r_min;
u16 vol_r_max;
u16 vol_r_res;
u16 mute_en : 1;
u16 vol_en : 1;
u16 mute_l_en : 1;
u16 vol_l_en : 1;
u16 mute_r_en : 1;
u16 vol_r_en : 1;
u16 mute : 1;
u16 mute_l : 1;
u16 mute_r : 1;
u16 sr_ctrl_en : 1;
u16 reserve : 6;
u8 i_t_id; //input terminal index
u8 f_u_id; //feature unit index
u8 o_t_id; //output terminal index
u8 Cur_AlternateSetting;
u8 src_channel;
u8 mic_state;
};
struct usb_audio_play {
u32 sample_rate;
u8 *usb_audio_spk_buf;
u8 *usb_audio_spk_buf2;
u8 *buffer;
cbuffer_t usb_audio_spk_cbuf;
int (*put_buf)(const usb_dev usb_id, void *ptr, u32 len, u8 channel, u32 sample_rate);
u16 vol_cur;
u16 vol_min;
u16 vol_max;
u16 vol_res;
u16 vol_l_cur;
u16 vol_l_min;
u16 vol_l_max;
u16 vol_l_res;
u16 vol_r_cur;
u16 vol_r_min;
u16 vol_r_max;
u16 vol_r_res;
u16 mute_en : 1;
u16 vol_en : 1;
u16 agc_en : 1;
u16 mute_l_en : 1;
u16 vol_l_en : 1;
u16 agc_l_en : 1;
u16 mute_r_en : 1;
u16 vol_r_en : 1;
u16 agc_r_en : 1;
u16 mute : 1;
u16 mute_l : 1;
u16 mute_r : 1;
u16 agc : 1;
u16 agc_l : 1;
u16 agc_r : 1;
u16 sr_ctrl_en : 1;
u8 i_t_id; //input terminal index
u8 f_u_id; //feature unit index
u8 o_t_id; //output terminal index
u8 Cur_AlternateSetting;
u8 spk_state;
u8 src_channel;
};
struct usb_audio_info {
struct usb_audio_mic host_mic;
struct usb_audio_play host_spk;
OS_SEM *wait_sem;
};
enum {
AUDIO_MIC_IDLE = 0,
AUDIO_MIC_START,
AUDIO_MIC_STOP,
AUDIO_MIC_PAUSE,
};
enum {
AUDIO_SPK_IDLE = 0,
AUDIO_SPK_START,
AUDIO_SPK_STOP,
AUDIO_SPK_PAUSE,
};
struct usb_audio_info _usb_audio_info[USB_MAX_HW_NUM] = {0};
#define __this (&_usb_audio_info[usb_id])
struct audio_device_t audio_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE];
static u8 *ep_in_dma_buf[USB_MAX_HW_NUM];
static u8 *ep_out_dma_buf[USB_MAX_HW_NUM];
static int set_power(struct usb_host_device *host_dev, u32 value)
{
const usb_dev usb_id = host_device2id(host_dev);
return 0;
}
static int get_power(struct usb_host_device *host_dev, u32 value)
{
return 0;
}
static const struct interface_ctrl uac_ctrl = {
.interface_class = USB_CLASS_AUDIO,
.set_power = set_power,
.get_power = get_power,
.ioctl = NULL,
};
static const struct usb_interface_info _uac_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = {
{
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][0],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][1],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][2],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][3],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][4],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][5],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][6],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[0][7],
},
},
#if USB_MAX_HW_NUM > 1
{
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][0],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][1],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][2],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][3],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][4],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][5],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][6],
},
{
.ctrl = (struct interface_ctrl *) &uac_ctrl,
.dev.audio = &audio_device[1][7],
},
}
#endif
};
static void reset_usb_host_audio_control_info(const usb_dev usb_id)
{
__this->host_spk.vol_cur = 0;
__this->host_spk.vol_min = 0;
__this->host_spk.vol_max = 0;
__this->host_spk.vol_res = 0;
__this->host_spk.vol_l_cur = 0;
__this->host_spk.vol_l_min = 0;
__this->host_spk.vol_l_max = 0;
__this->host_spk.vol_l_res = 0;
__this->host_spk.vol_r_cur = 0;
__this->host_spk.vol_r_min = 0;
__this->host_spk.vol_r_max = 0;
__this->host_spk.vol_r_res = 0;
__this->host_spk.mute_en = 0;
__this->host_spk.vol_en = 0;
__this->host_spk.agc_en = 0;
__this->host_spk.mute_l_en = 0;
__this->host_spk.vol_l_en = 0;
__this->host_spk.agc_l_en = 0;
__this->host_spk.mute_r_en = 0;
__this->host_spk.vol_r_en = 0;
__this->host_spk.agc_r_en = 0;
__this->host_spk.mute = 0;
__this->host_spk.mute_l = 0;
__this->host_spk.mute_r = 0;
__this->host_spk.agc = 0;
__this->host_spk.agc_l = 0;
__this->host_spk.agc_r = 0;
__this->host_spk.sr_ctrl_en = 0;
__this->host_spk.i_t_id = 0;
__this->host_spk.f_u_id = 0;
__this->host_spk.o_t_id = 0;
__this->host_mic.vol_cur = 0;
__this->host_mic.vol_min = 0;
__this->host_mic.vol_max = 0;
__this->host_mic.vol_res = 0;
__this->host_mic.vol_l_cur = 0;
__this->host_mic.vol_l_min = 0;
__this->host_mic.vol_l_max = 0;
__this->host_mic.vol_l_res = 0;
__this->host_mic.vol_r_cur = 0;
__this->host_mic.vol_r_min = 0;
__this->host_mic.vol_r_max = 0;
__this->host_mic.vol_r_res = 0;
__this->host_mic.mute_en = 0;
__this->host_mic.vol_en = 0;
__this->host_mic.mute_l_en = 0;
__this->host_mic.vol_l_en = 0;
__this->host_mic.mute_r_en = 0;
__this->host_mic.vol_r_en = 0;
__this->host_mic.mute = 0;
__this->host_mic.mute_l = 0;
__this->host_mic.mute_r = 0;
__this->host_mic.sr_ctrl_en = 0;
__this->host_mic.reserve = 0;
__this->host_mic.i_t_id = 0;
__this->host_mic.f_u_id = 0;
__this->host_mic.o_t_id = 0;
}
int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
{
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
const usb_dev usb_id = host_device2id(host_dev);
const struct usb_interface_info *usb_if = &_uac_if[usb_id][interface_num];
struct audio_streaming_t *as_t = NULL;
memset(usb_if->dev.p, 0, sizeof(struct audio_device_t));
host_dev->interface_info[interface_num] = usb_if;
usb_if->dev.audio->parent = host_dev;
if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOCONTROL) {
log_info("audio control interface : %d\n", interface_num);
pBuf += sizeof(struct usb_interface_descriptor);
usb_if->dev.audio->subclass = interface->bInterfaceSubClass;
usb_if->dev.audio->interface_num = interface_num;
reset_usb_host_audio_control_info(usb_id);
int len = 0;
int cur_len;
int cur_type;
int cur_sub_type;
int bControlSize = 0;
u16 wTotalLength = 0;
u8 i_t_id = -1;
u8 f_u_id = -1;
u8 o_t_id = -1;
const u8 *feature_desc = NULL;
while (1) {
cur_len = pBuf[len];
cur_type = pBuf[len + 1];
cur_sub_type = pBuf[len + 2];
if (!cur_len || cur_type != USB_DT_CS_INTERFACE) {
break;
}
if (wTotalLength > 0 && len >= wTotalLength) {
break;
}
if (cur_sub_type == UAC_HEADER) {
wTotalLength = pBuf[len + 6] << 8 | pBuf[len + 5];
log_debug("UAC_HEADER: version %04x, TotalLength %d",
pBuf[len + 4] << 8 | pBuf[len + 3],
wTotalLength);
} else if (cur_sub_type == UAC_INPUT_TERMINAL) {
u16 terminal_type = pBuf[len + 5] << 8 | pBuf[len + 4];
u16 ch = pBuf[len + 7];
i_t_id = pBuf[len + 3];
switch (terminal_type) {
case UAC_INPUT_TERMINAL_MICROPHONE:
case UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE:
case UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE:
case 0x0402:
__this->host_spk.i_t_id = i_t_id;
break;
default:
break;
}
log_debug("INPUT_TERMINAL: %d 0x%x %d", i_t_id, terminal_type, ch);
} else if (cur_sub_type == UAC_FEATURE_UNIT) {
f_u_id = pBuf[len + 3];
u8 src_id = pBuf[len + 4];
bControlSize = pBuf[len + 5];
feature_desc = pBuf + len;
if (__this->host_spk.i_t_id == i_t_id && src_id == i_t_id) {
__this->host_spk.f_u_id = f_u_id;
__this->host_spk.mute_en = !!(feature_desc[6] & 0x1);
__this->host_spk.vol_en = !!(feature_desc[6] & 0x2);
__this->host_spk.agc_en = !!(feature_desc[6] & 0x40);
if (cur_len == (7 + (2 + 1) * bControlSize)) {
__this->host_spk.mute_l_en = !!(feature_desc[6 + bControlSize * 1] & 0x1);
__this->host_spk.vol_l_en = !!(feature_desc[6 + bControlSize * 1] & 0x2);
__this->host_spk.agc_l_en = !!(feature_desc[6 + bControlSize * 1] & 0x40);
__this->host_spk.mute_r_en = !!(feature_desc[6 + bControlSize * 2] & 0x1);
__this->host_spk.vol_r_en = !!(feature_desc[6 + bControlSize * 2] & 0x2);
__this->host_spk.agc_r_en = !!(feature_desc[6 + bControlSize * 2] & 0x40);
}
}
log_debug("FEATURE_UNIT: %d %d %d", f_u_id, src_id, bControlSize);
} else if (cur_sub_type == UAC_OUTPUT_TERMINAL) {
o_t_id = pBuf[len + 3];
u8 src_id = pBuf[len + 7];
u16 terminal_type = pBuf[len + 5] << 8 | pBuf[len + 4];
if (__this->host_spk.i_t_id == i_t_id) {
__this->host_spk.o_t_id = o_t_id;
}
switch (terminal_type) {
case UAC_OUTPUT_TERMINAL_SPEAKER:
case UAC_OUTPUT_TERMINAL_HEADPHONES:
case UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER:
case UAC_OUTPUT_TERMINAL_ROOM_SPEAKER:
case UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER:
case UAC_OUTPUT_TERMINAL_HEADSET:
__this->host_mic.i_t_id = i_t_id;
__this->host_mic.f_u_id = f_u_id;
__this->host_mic.o_t_id = o_t_id;
if (feature_desc && (feature_desc[4] == i_t_id)) {
__this->host_mic.mute_en = !!(feature_desc[6] & 0x01);
__this->host_mic.vol_en = !!(feature_desc[6] & 0x02);
__this->host_mic.mute_l_en = !!(feature_desc[6 + bControlSize * 1] & 0x01);
__this->host_mic.vol_l_en = !!(feature_desc[6 + bControlSize * 1] & 0x02);
if (feature_desc[0] == (7 + (2 + 1) * bControlSize)) {
__this->host_mic.mute_r_en = !!(feature_desc[6 + bControlSize * 2] & 0x01);
__this->host_mic.vol_r_en = !!(feature_desc[6 + bControlSize * 2] & 0x02);
}
}
break;
default:
break;
}
log_debug("OUTPUT_TERMINAL: %d %d %x", o_t_id, src_id, terminal_type);
}
len += cur_len;
}
return sizeof(struct usb_interface_descriptor);
}
if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING) {
usb_if->dev.audio->subclass = interface->bInterfaceSubClass;
usb_if->dev.audio->interface_num = interface_num;
if (interface->bNumEndpoints == 0) {
pBuf += sizeof(struct usb_interface_descriptor);
do {
struct usb_interface_descriptor *as_interface = (struct usb_interface_descriptor *)pBuf;
if (as_interface->bNumEndpoints == 0 || as_interface->bInterfaceClass != USB_CLASS_AUDIO) {
break;
}
log_info("audio streaming interface : %d ep_num:%d Altersetting:%d", interface_num, as_interface->bNumEndpoints, as_interface->bAlternateSetting);
as_t = &usb_if->dev.audio->as[as_interface->bAlternateSetting - 1];
as_t->bNumEndpoints = as_interface->bNumEndpoints;
pBuf += (USB_DT_INTERFACE_SIZE + UAC_DT_AS_HEADER_SIZE);
//解析format
struct uac_format_type_i_discrete_descriptor *uac_format_desc = (struct uac_format_type_i_discrete_descriptor *)pBuf;
if (uac_format_desc->bDescriptorSubtype == UAC_FORMAT_TYPE) {
as_t->bFormatType = uac_format_desc->bFormatType;
as_t->bNrChannels = uac_format_desc->bNrChannels;
as_t->bSubframeSize = uac_format_desc->bSubframeSize;
as_t->bBitResolution = uac_format_desc->bBitResolution;
as_t->bSamFreqType = uac_format_desc->bSamFreqType;
for (u8 i = 0; i < as_t->bSamFreqType; i++) {
memcpy(&as_t->tSamFreq[i], &uac_format_desc->tSamFreq[i], 3);
log_info("as bNrChannels:%d bBitResolution:%d tSamFreq : %d", as_t->bNrChannels, as_t->bBitResolution, as_t->tSamFreq[i]);
}
//Endpointdescriptor
pBuf += uac_format_desc->bLength;
/* for (int i = 0; i < as_t->bNumEndpoints; i++) { */
struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf;
if (endpoint->bDescriptorType == USB_DT_ENDPOINT) {
as_t->ep_Interval = endpoint->bInterval;
as_t->ep_max_packet_size = endpoint->wMaxPacketSize;
if (endpoint->bEndpointAddress & USB_DIR_IN) {
as_t->ep = endpoint->bEndpointAddress & 0xf;
log_info("ep in : %x\n", as_t->ep);
usb_if->dev.audio->support = MICROPHONE_SUPPORTED;
} else {
as_t->ep = endpoint->bEndpointAddress;
log_info("ep out : %x\n", as_t->ep);
usb_if->dev.audio->support = HEADPHONE_SUPPORTED;
}
pBuf += USB_DT_ENDPOINT_AUDIO_SIZE;
pBuf += UAC_ISO_ENDPOINT_DESC_SIZE;
}
#if 0
struct uac_iso_endpoint_descriptor *iso_endpoint = (struct uac_iso_endpoint_descriptor *)pBuf;
if (iso_endpoint->bDescriptorType == USB_DT_CS_ENDPOINT) {
as_t->sr_ctrl_dis = !(iso_endpoint->bmAttributes & BIT(0));
pBuf += UAC_ISO_ENDPOINT_DESC_SIZE;
} else {
as_t->sr_ctrl_dis = 0;
}
#endif
/* } */
} else {
log_error("uac_format_desc->bDescriptorSubtype err!!\n");
goto __exit;
}
} while (1);
/* log_info("lennnn:%d\n",pBuf - (u8 *)interface); */
return pBuf - (u8 *)interface;
} else {
log_info("audio streaming interface : %d ep_num:%d Altersetting:%d\n", interface_num, interface->bNumEndpoints, interface->bAlternateSetting);
}
}
__exit:
return USB_DT_INTERFACE_SIZE;
}
static struct audio_device_t *__find_microphone_interface(const struct usb_host_device *host_dev)
{
struct audio_device_t *audio = NULL;
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
if (usb_if &&
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
audio = usb_if->dev.audio;
if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING &&
audio->support == MICROPHONE_SUPPORTED) {
// find host_spk
return audio;
}
}
}
return NULL;
}
static struct audio_device_t *__find_headphone_interface(const struct usb_host_device *host_dev)
{
struct audio_device_t *audio = NULL;
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
if (usb_if &&
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
audio = usb_if->dev.audio;
if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING &&
audio->support == HEADPHONE_SUPPORTED) {
// find headphone
return audio;
}
}
}
return NULL;
}
static struct audio_device_t *__find_control_interface(const struct usb_host_device *host_dev)
{
struct audio_device_t *audio = NULL;
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
if (usb_if &&
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
audio = usb_if->dev.audio;
if (audio->subclass == USB_SUBCLASS_AUDIOCONTROL) {
return audio;
}
}
}
return NULL;
}
/*******************************************************************************************************/
static u16 host_mic_vol_convert(u16 v, u16 min, u16 max, u8 dir)
{
u16 retval = 0;
s16 reg1;
s16 reg2;
if (dir == 0) {
if (v > 100) {
v = 100;
}
reg1 = my_abs((s16)max - (s16)min);
retval = (s16)min + (s16)(reg1 * v / 100);
} else {
if ((s16)v > (s16)max) {
v = max;
}
if ((s16)v < (s16)min) {
v = min;
}
reg1 = my_abs((s16)max - (s16)min);
reg2 = my_abs((s16)v - (s16)min);
retval = reg2 * 100 / reg1;
}
return retval;
}
static s32 __usb_host_mic_get_mute(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret;
u8 mute = 0;
if (__this->host_mic.mute_en) {
mute = 0;
ret = usb_audio_mute_control_get_cur(host_dev, __this->host_mic.f_u_id, 0, &mute, audio->interface_num);
retval_check(ret, 0);
if (mute) {
__this->host_mic.mute = 1;
log_debug("host mic mic is mute");
} else {
__this->host_mic.mute = 0;
log_debug("host mic mic is unmute");
}
}
if (__this->host_mic.mute_l_en) {
mute = 0;
ret = usb_audio_mute_control_get_cur(host_dev, __this->host_mic.f_u_id, 1, &mute, audio->interface_num);
retval_check(ret, 0);
if (mute) {
__this->host_mic.mute_l = 1;
log_debug("host mic mic_l is mute");
} else {
__this->host_mic.mute_l = 0;
log_debug("host mic mic_l is unmute");
}
}
if (__this->host_mic.mute_r_en) {
mute = 0;
ret = usb_audio_mute_control_get_cur(host_dev, __this->host_mic.f_u_id, 2, &mute, audio->interface_num);
retval_check(ret, 0);
if (mute) {
__this->host_mic.mute_r = 1;
log_debug("host mic mic_r is mute");
} else {
__this->host_mic.mute_r = 0;
log_debug("host mic mic_r is unmute");
}
}
__exit_fail:
return ret;
}
static s32 __usb_host_mic_set_mute(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
u8 mute = 0;
if (__this->host_mic.mute_en) {
mute = __this->host_mic.mute;
ret = usb_audio_mute_control_set_cur(host_dev, __this->host_mic.f_u_id, 0, mute, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic set mute to %d", mute);
}
if (__this->host_mic.mute_l_en) {
mute = __this->host_mic.mute_l;
ret = usb_audio_mute_control_set_cur(host_dev, __this->host_mic.f_u_id, 1, mute, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic set mute_l to %d", mute);
}
if (__this->host_mic.mute_r_en) {
mute = __this->host_mic.mute_r;
ret = usb_audio_mute_control_set_cur(host_dev, __this->host_mic.f_u_id, 2, mute, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic set mute_r to %d", mute);
}
__exit_fail:
return ret;
}
static s32 __usb_host_mic_get_all_volume(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
if (__this->host_mic.vol_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_mic.f_u_id, 0, &__this->host_mic.vol_cur, audio->interface_num);
retval_check(ret, 0);
//GET MIN
ret = usb_audio_volume_control_get_min(host_dev, __this->host_mic.f_u_id, 0, &__this->host_mic.vol_min, audio->interface_num);
retval_check(ret, 0);
//GET MAX
ret = usb_audio_volume_control_get_max(host_dev, __this->host_mic.f_u_id, 0, &__this->host_mic.vol_max, audio->interface_num);
retval_check(ret, 0);
//GET RES
ret = usb_audio_volume_control_get_res(host_dev, __this->host_mic.f_u_id, 0, &__this->host_mic.vol_res, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic vol min %04x, vol max %04x, vol res %04x, vol cur %04x",
__this->host_mic.vol_min,
__this->host_mic.vol_max,
__this->host_mic.vol_res,
__this->host_mic.vol_cur);
}
if (__this->host_mic.vol_l_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_mic.f_u_id, 1, &__this->host_mic.vol_l_cur, audio->interface_num);
retval_check(ret, 0);
//GET MIN
ret = usb_audio_volume_control_get_min(host_dev, __this->host_mic.f_u_id, 1, &__this->host_mic.vol_l_min, audio->interface_num);
retval_check(ret, 0);
//GET MAX
ret = usb_audio_volume_control_get_max(host_dev, __this->host_mic.f_u_id, 1, &__this->host_mic.vol_l_max, audio->interface_num);
retval_check(ret, 0);
//GET RES
ret = usb_audio_volume_control_get_res(host_dev, __this->host_mic.f_u_id, 1, &__this->host_mic.vol_l_res, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic vol min %04x, vol max %04x, vol res %04x, vol cur %04x",
__this->host_mic.vol_l_min,
__this->host_mic.vol_l_max,
__this->host_mic.vol_l_res,
__this->host_mic.vol_l_cur);
}
if (__this->host_mic.vol_r_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_mic.f_u_id, 2, &__this->host_mic.vol_r_cur, audio->interface_num);
retval_check(ret, 0);
//GET MIN
ret = usb_audio_volume_control_get_min(host_dev, __this->host_mic.f_u_id, 2, &__this->host_mic.vol_r_min, audio->interface_num);
retval_check(ret, 0);
//GET MAX
ret = usb_audio_volume_control_get_max(host_dev, __this->host_mic.f_u_id, 2, &__this->host_mic.vol_r_max, audio->interface_num);
retval_check(ret, 0);
//GET RES
ret = usb_audio_volume_control_get_res(host_dev, __this->host_mic.f_u_id, 2, &__this->host_mic.vol_r_res, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic vol min %04x, vol max %04x, vol res %04x, vol cur %04x",
__this->host_mic.vol_r_min,
__this->host_mic.vol_r_max,
__this->host_mic.vol_r_res,
__this->host_mic.vol_r_cur);
}
__exit_fail:
return ret;
}
static s32 __usb_host_mic_get_cur_volume(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
if (__this->host_mic.vol_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_mic.f_u_id, 0, &__this->host_mic.vol_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic get vol cur %04x", __this->host_mic.vol_cur);
}
if (__this->host_mic.vol_l_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_mic.f_u_id, 1, &__this->host_mic.vol_l_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic get vol_l cur %04x", __this->host_mic.vol_l_cur);
}
if (__this->host_mic.vol_r_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_mic.f_u_id, 2, &__this->host_mic.vol_r_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic get vol_r cur %04x", __this->host_mic.vol_r_cur);
}
__exit_fail:
return ret;
}
static s32 __usb_host_mic_set_cur_volume(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
if (__this->host_mic.vol_en) {
//SET CUR
ret = usb_audio_volume_control_set_cur(host_dev, __this->host_mic.f_u_id, 0, __this->host_mic.vol_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic set vol to 0x%04x", __this->host_mic.vol_cur);
}
if (__this->host_mic.vol_l_en) {
//SET CUR
ret = usb_audio_volume_control_set_cur(host_dev, __this->host_mic.f_u_id, 1, __this->host_mic.vol_l_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic set vol_l to 0x%04x", __this->host_mic.vol_l_cur);
}
if (__this->host_mic.vol_r_en) {
//SET CUR
ret = usb_audio_volume_control_set_cur(host_dev, __this->host_mic.f_u_id, 2, __this->host_mic.vol_r_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host mic set vol_r to 0x%04x", __this->host_mic.vol_r_cur);
}
__exit_fail:
return ret;
}
int usb_host_mic_set_volume(const usb_dev usb_id, u16 vol_l, u16 vol_r)
{
u32 vol = 0;
if (__this->host_mic.vol_en) {
vol = (vol_l + vol_r) / 2;
__this->host_mic.vol_cur = host_mic_vol_convert(vol, __this->host_mic.vol_min, __this->host_mic.vol_max, 0);
}
if (__this->host_mic.vol_l_en) {
__this->host_mic.vol_l_cur = host_mic_vol_convert(vol_l, __this->host_mic.vol_l_min, __this->host_mic.vol_l_max, 0);
}
if (__this->host_mic.vol_r_en) {
__this->host_mic.vol_r_cur = host_mic_vol_convert(vol_r, __this->host_mic.vol_r_min, __this->host_mic.vol_r_max, 0);
}
return __usb_host_mic_set_cur_volume(usb_id);
}
int usb_host_mic_set_mute(const usb_dev usb_id, u8 mute)
{
mute = !!mute;
log_debug("host mic set mute %d", mute);
if (__this->host_mic.mute_en) {
__this->host_mic.mute = mute;
}
if (__this->host_mic.mute_l_en) {
__this->host_mic.mute_l = mute;
}
if (__this->host_mic.mute_r_en) {
__this->host_mic.mute_r = mute;
}
return __usb_host_mic_set_mute(usb_id);
}
#ifdef USB_AUDIO_PLAY_TEST
static const s16 sin_48k[] = {
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
};
#endif
static u32 usb_audio_tx_len[USB_MAX_HW_NUM] = {0};
static void usb_audio_tx_isr(struct usb_host_device *host_dev, u32 ep)
{
const usb_dev usb_id = host_device2id(host_dev);
struct audio_device_t *audio = NULL;
struct audio_streaming_t *as_t = NULL;
u16 ep_max_packet_size = 0;
u8 channel = 0;
u32 rlen = 0;
if (__this->host_mic.mic_state != AUDIO_MIC_START) {
return;
}
audio = __find_headphone_interface(host_dev);
if (!audio) {
log_error("no find headphone interface!");
return;
}
as_t = &audio->as[__this->host_mic.Cur_AlternateSetting - 1];
ep_max_packet_size = as_t->ep_max_packet_size;
channel = as_t->bNrChannels;
//iso send
#ifdef USB_AUDIO_PLAY_TEST
//For Test
int tx_len = 0;
#if 1 // 单声道双声道输出
s16 buf[240 / 2];
for (u8 i = 0, j = 0; i < 240 / 2; i += 2) {
buf[i] = sin_48k[j];
buf[i + 1] = sin_48k[j];
j++;
if (j >= sizeof(sin_48k) / sizeof(sin_48k[0])) {
j = 0;
}
}
#else
//单声道直接输出
u8 buf[248];
do {
memcpy(&buf[tx_len], sin_48k, sizeof(sin_48k));
tx_len += sizeof(sin_48k);
} while (tx_len < ep_max_packet_size);
#endif
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
#else
if (__this->host_mic.usb_audio_remain_len == 0) {
cbuf_read_alloc(&__this->host_mic.usb_audio_record_cbuf, &__this->host_mic.usb_audio_remain_len);
usb_audio_tx_len[usb_id] = 0;
}
if (__this->host_mic.usb_audio_remain_len) {
if (usb_audio_tx_len[usb_id] == 0) {
rlen = cbuf_read(&__this->host_mic.usb_audio_record_cbuf, __this->host_mic.usb_audio_mic_buf2, __this->host_mic.usb_audio_remain_len);
if (!rlen) {
__this->host_mic.usb_audio_remain_len = 0;
usb_audio_tx_len[usb_id] = 0;
putchar('c');
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1);
os_sem_set(&__this->host_mic.sem, 0);
os_sem_post(&__this->host_mic.sem);
return;
}
os_sem_set(&__this->host_mic.sem, 0);
os_sem_post(&__this->host_mic.sem);
}
u8 *send_buf = __this->host_mic.send_buf;
u8 *play_buf = __this->host_mic.usb_audio_mic_buf2;
if (channel == 2) {
if (__this->host_mic.src_channel == 1) {
//源数据是单声道数据,转双声道输出
int j = 0;
for (u32 i = 0; i < ep_max_packet_size; i += 4) {
//left
*(send_buf + i) = *(play_buf + (usb_audio_tx_len[usb_id] + j));
*(send_buf + i + 1) = *(play_buf + (usb_audio_tx_len[usb_id] + j + 1));
//right
*(send_buf + i + 2) = *(play_buf + (usb_audio_tx_len[usb_id] + j));
*(send_buf + i + 3) = *(play_buf + (usb_audio_tx_len[usb_id] + j + 1));
j += 2;
}
usb_audio_tx_len[usb_id] += j;
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, send_buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
} else if (__this->host_mic.src_channel == 2) {
//源数据是双声道数据,直接双声道输出
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, play_buf + usb_audio_tx_len[usb_id], ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
usb_audio_tx_len[usb_id] += ep_max_packet_size;
}
} else if (channel == 1) {
if (__this->host_mic.src_channel == 1) {
//源数据是单声道数据,直接单声道输出
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, play_buf + usb_audio_tx_len[usb_id], ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
usb_audio_tx_len[usb_id] += ep_max_packet_size;
} else if (__this->host_mic.src_channel == 2) {
//源数据是双声道数据,转单声道输出
int j = 0;
for (u32 i = 0; i < ep_max_packet_size; i += 2) {
//left
*(send_buf + i) = *(play_buf + (usb_audio_tx_len[usb_id] + j));
*(send_buf + i + 1) = *(play_buf + (usb_audio_tx_len[usb_id] + j + 1));
j += 4;
}
usb_audio_tx_len[usb_id] += j;
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, send_buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
}
}
if (usb_audio_tx_len[usb_id] >= __this->host_mic.usb_audio_remain_len) {
__this->host_mic.usb_audio_remain_len = 0;
usb_audio_tx_len[usb_id] = 0;
}
} else {
//audio buf null ,send null packet
os_sem_set(&__this->host_mic.sem, 0);
os_sem_post(&__this->host_mic.sem);
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1);
putchar('d');
}
#endif
}
static void audio_recorder_task(void *p)
{
log_info(">>> Enter usb audio record task");
struct usb_host_device *host_dev = (struct usb_host_device *)p;
const usb_dev usb_id = host_device2id(host_dev);
u8 *ptr = NULL;
u32 wlen = 0;
u32 ret = 0;
struct audio_device_t *audio = __find_headphone_interface(host_dev);
struct audio_streaming_t *as_t = &audio->as[__this->host_mic.Cur_AlternateSetting - 1];
u32 ep_max_packet_size = as_t->ep_max_packet_size;
u32 usb_audio_buf_size = ep_max_packet_size * 10; //预留10个包的缓存
log_info("audio play ep max packet : %d\n", ep_max_packet_size);
if (__this->host_mic.src_channel != as_t->bNrChannels && __this->host_mic.src_channel == 1) {
usb_audio_buf_size >>= 1;
}
os_sem_create(&__this->host_mic.sem, 0);
//分配双缓存
// 一个缓存保存读卡的数据,一个用于usb发送
if (!__this->host_mic.usb_audio_mic_buf2) {
__this->host_mic.usb_audio_mic_buf2 = zalloc(usb_audio_buf_size);
}
if (!__this->host_mic.send_buf) {
__this->host_mic.send_buf = zalloc(ep_max_packet_size);
}
if (!__this->host_mic.usb_audio_mic_buf) {
__this->host_mic.usb_audio_mic_buf = zalloc(usb_audio_buf_size);
cbuf_init(&__this->host_mic.usb_audio_record_cbuf, __this->host_mic.usb_audio_mic_buf, usb_audio_buf_size);
}
if (!__this->host_mic.send_buf || !__this->host_mic.usb_audio_mic_buf || !__this->host_mic.usb_audio_mic_buf2) {
os_sem_pend(&__this->host_mic.sem, 0);
}
__this->host_mic.mic_state = AUDIO_MIC_START;
usb_h_ep_write_async(usb_id, as_t->host_ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //启动iso传输
os_sem_post(__this->wait_sem);
while (1) {
if (__this->host_mic.Cur_AlternateSetting == 0 || __this->host_mic.mic_state != AUDIO_MIC_START) {
os_time_dly(50);
continue;
}
ptr = cbuf_write_alloc(&__this->host_mic.usb_audio_record_cbuf, &wlen);
if (wlen) {
/* putchar('a'); */
if (__this->host_mic.get_buf) {
ret = __this->host_mic.get_buf(usb_id, ptr, wlen, __this->host_mic.src_channel, __this->host_mic.sample_rate);
if (ret != wlen) {
goto __task_exit;
}
}
cbuf_write_updata(&__this->host_mic.usb_audio_record_cbuf, wlen);
} else {
log_w("usb audio record buf not enough!\n");
}
__task_exit:
os_sem_pend(&__this->host_mic.sem, 0);
}
}
void usb_audio_start_recorder(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = NULL;
struct audio_streaming_t *as_t = NULL;
u8 find_alternatesetting = 0;
audio = __find_headphone_interface(host_dev);
if (!audio) {
log_error("no find headphone interface!");
return;
}
for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) {
as_t = &audio->as[i];
if (as_t->bBitResolution == bit_reso) {
for (u8 j = 0; j < as_t->bSamFreqType; j++) {
if (sample_rate == 0 && as_t->tSamFreq[as_t->bSamFreqType - j - 1] && as_t->tSamFreq[as_t->bSamFreqType - j - 1] <= 48000) {
sample_rate = as_t->tSamFreq[as_t->bSamFreqType - j - 1];
find_alternatesetting = i + 1;
break;
}
if (as_t->tSamFreq[as_t->bSamFreqType - j - 1] == sample_rate) {
find_alternatesetting = i + 1;
break;
}
}
}
}
if (!find_alternatesetting) {
log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n");
return;
}
as_t = &audio->as[find_alternatesetting - 1];
u32 ep_max_packet_size = sample_rate * 2 * as_t->bNrChannels / 1000;
if (ep_max_packet_size > as_t->ep_max_packet_size) {
ep_max_packet_size = as_t->ep_max_packet_size;
} else {
as_t->ep_max_packet_size = ep_max_packet_size;
}
//端点分配
u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC);
ASSERT(host_ep != -1, "ep not enough");
ep_out_dma_buf[usb_id] = usb_h_alloc_ep_buffer(usb_id, host_ep, as_t->ep_max_packet_size + 64); //预留64个字节防止硬件越界访问
ASSERT(ep_out_dma_buf[usb_id] != NULL);
as_t->host_ep = host_ep;
if (channel == 0) {
channel = as_t->bNrChannels;
}
__this->host_mic.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting
__this->host_mic.sample_rate = sample_rate; //选择采样率
__this->host_mic.src_channel = channel;
usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface Alternatesetting
if (!as_t->sr_ctrl_dis) {
usb_audio_sampling_frequency_control(host_dev, as_t->ep, sample_rate);//设置采样率
}
log_info("H2D ep: %x --> %x interval: %d", host_ep, as_t->ep, as_t->ep_Interval);
usb_write_txfuncaddr(usb_id, host_ep, host_dev->private_data.devnum);
usb_h_set_ep_isr(host_dev, host_ep, usb_audio_tx_isr, host_dev);
usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, as_t->ep_Interval, ep_out_dma_buf[usb_id], as_t->ep_max_packet_size);
__usb_host_mic_get_all_volume(usb_id);
usb_host_mic_set_mute(usb_id, 0);
usb_host_mic_set_volume(usb_id, HOST_MIC_VOLUME, HOST_MIC_VOLUME);
OS_SEM sem;
os_sem_create(&sem, 0);
__this->wait_sem = &sem;
if (usb_id == 0) {
task_create(audio_recorder_task, host_dev, "uac_record0");
} else {
task_create(audio_recorder_task, host_dev, "uac_record1");
}
os_sem_pend(&sem, 0);
__this->wait_sem = NULL;
}
void usb_audio_stop_recorder(const usb_dev usb_id)
{
__this->host_mic.mic_state = AUDIO_MIC_STOP;
usb_h_set_ep_isr(NULL, 0, NULL, NULL);
if (__this->host_mic.get_buf) {
__this->host_mic.get_buf(usb_id, NULL, 0, 0, 0);
}
__this->host_mic.Cur_AlternateSetting = 0;
if (usb_id == 0) {
task_kill("uac_record0");
} else {
task_kill("uac_record1");
}
__this->host_mic.sample_rate = 0;
__this->host_mic.src_channel = 0;
if (__this->host_mic.usb_audio_mic_buf) {
free(__this->host_mic.usb_audio_mic_buf);
__this->host_mic.usb_audio_mic_buf = NULL;
}
if (__this->host_mic.usb_audio_mic_buf2) {
free(__this->host_mic.usb_audio_mic_buf2);
__this->host_mic.usb_audio_mic_buf2 = NULL;
}
if (__this->host_mic.send_buf) {
free(__this->host_mic.send_buf);
__this->host_mic.send_buf = NULL;
}
if (ep_out_dma_buf[usb_id]) {
usb_h_free_ep_buffer(usb_id, ep_out_dma_buf[usb_id]);
ep_out_dma_buf[usb_id] = NULL;
}
}
void usb_audio_pause_recorder(const usb_dev usb_id)
{
__this->host_mic.mic_state = AUDIO_MIC_PAUSE;
}
void usb_audio_resume_recorder(const usb_dev usb_id)
{
const struct usb_host_device *host_dev = host_id2device(usb_id);
struct audio_device_t *audio = __find_headphone_interface(host_dev);
struct audio_streaming_t *as_t = &audio->as[__this->host_mic.Cur_AlternateSetting - 1];
if (__this->host_mic.usb_audio_mic_buf) {
__this->host_mic.usb_audio_remain_len = 0;
usb_audio_tx_len[usb_id] = 0;
cbuf_clear(&__this->host_mic.usb_audio_record_cbuf);
__this->host_mic.mic_state = AUDIO_MIC_START;
usb_h_ep_write_async(usb_id, as_t->host_ep, as_t->ep_max_packet_size, as_t->ep, NULL, as_t->ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //重新启动传输
}
}
/******************************************************************************************************/
static u16 host_speaker_vol_convert(u16 v, u16 min, u16 max, u8 dir)
{
u16 retval = 0;
s16 reg1;
s16 reg2;
if (dir == 0) {
if (v > 100) {
v = 100;
}
reg1 = my_abs((s16)max - (s16)min);
retval = (s16)min + (s16)(reg1 * v / 100);
} else {
if ((s16)v > (s16)max) {
v = max;
}
if ((s16)v < (s16)min) {
v = min;
}
reg1 = my_abs((s16)max - (s16)min);
reg2 = my_abs((s16)v - (s16)min);
retval = reg2 * 100 / reg1;
}
return retval;
}
static s32 __usb_host_speaker_get_mute(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
u8 mute = 0;
if (__this->host_spk.mute_en) {
mute = 0;
ret = usb_audio_mute_control_get_cur(host_dev, __this->host_spk.f_u_id, 0, &mute, audio->interface_num);
retval_check(ret, 0);
if (mute) {
__this->host_spk.mute = 1;
log_debug("host spk spk is mute");
} else {
__this->host_spk.mute = 0;
log_debug("host spk spk is unmute");
}
}
if (__this->host_spk.mute_l_en) {
mute = 0;
ret = usb_audio_mute_control_get_cur(host_dev, __this->host_spk.f_u_id, 1, &mute, audio->interface_num);
retval_check(ret, 0);
if (mute) {
__this->host_spk.mute_l = 1;
log_debug("host spk spk_l is mute");
} else {
__this->host_spk.mute_l = 0;
log_debug("host spk spk_l is unmute");
}
}
if (__this->host_spk.mute_r_en) {
mute = 0;
ret = usb_audio_mute_control_get_cur(host_dev, __this->host_spk.f_u_id, 2, &mute, audio->interface_num);
retval_check(ret, 0);
if (mute) {
__this->host_spk.mute_r = 1;
log_debug("host spk spk_r is mute");
} else {
__this->host_spk.mute_r = 0;
log_debug("host spk spk_r is unmute");
}
}
__exit_fail:
return ret;
}
static s32 __usb_host_speaker_set_mute(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
u8 mute = 0;
if (__this->host_spk.mute_en) {
mute = __this->host_spk.mute;
ret = usb_audio_mute_control_set_cur(host_dev, __this->host_spk.f_u_id, 0, mute, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk set mute to %d", mute);
}
if (__this->host_spk.mute_l_en) {
mute = __this->host_spk.mute_l;
ret = usb_audio_mute_control_set_cur(host_dev, __this->host_spk.f_u_id, 1, mute, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk set mute_l to %d", mute);
}
if (__this->host_spk.mute_r_en) {
mute = __this->host_spk.mute_r;
ret = usb_audio_mute_control_set_cur(host_dev, __this->host_spk.f_u_id, 2, mute, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk set mute_r to %d", mute);
}
__exit_fail:
return ret;
}
static s32 __usb_host_speaker_get_all_volume(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
if (__this->host_spk.vol_en) {
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 0, &__this->host_spk.vol_cur, audio->interface_num);
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 0, &__this->host_spk.vol_cur, audio->interface_num);
retval_check(ret, 0);
//GET MIN
ret = usb_audio_volume_control_get_min(host_dev, __this->host_spk.f_u_id, 0, &__this->host_spk.vol_min, audio->interface_num);
retval_check(ret, 0);
//GET MAX
ret = usb_audio_volume_control_get_max(host_dev, __this->host_spk.f_u_id, 0, &__this->host_spk.vol_max, audio->interface_num);
retval_check(ret, 0);
//GET RES
ret = usb_audio_volume_control_get_res(host_dev, __this->host_spk.f_u_id, 0, &__this->host_spk.vol_res, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk vol min %04x, vol max %04x, vol res %04x, vol cur %04x",
__this->host_spk.vol_min,
__this->host_spk.vol_max,
__this->host_spk.vol_res,
__this->host_spk.vol_cur);
}
if (__this->host_spk.vol_l_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 1, &__this->host_spk.vol_l_cur, audio->interface_num);
retval_check(ret, 0);
//GET MIN
ret = usb_audio_volume_control_get_min(host_dev, __this->host_spk.f_u_id, 1, &__this->host_spk.vol_l_min, audio->interface_num);
retval_check(ret, 0);
//GET MAX
ret = usb_audio_volume_control_get_max(host_dev, __this->host_spk.f_u_id, 1, &__this->host_spk.vol_l_max, audio->interface_num);
retval_check(ret, 0);
//GET RES
ret = usb_audio_volume_control_get_res(host_dev, __this->host_spk.f_u_id, 1, &__this->host_spk.vol_l_res, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk voll min %04x, voll max %04x, voll res %04x, voll cur %04x",
__this->host_spk.vol_l_min,
__this->host_spk.vol_l_max,
__this->host_spk.vol_l_res,
__this->host_spk.vol_l_cur);
}
if (__this->host_spk.vol_r_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 2, &__this->host_spk.vol_r_cur, audio->interface_num);
retval_check(ret, 0);
//GET MIN
ret = usb_audio_volume_control_get_min(host_dev, __this->host_spk.f_u_id, 2, &__this->host_spk.vol_r_min, audio->interface_num);
retval_check(ret, 0);
//GET MAX
ret = usb_audio_volume_control_get_max(host_dev, __this->host_spk.f_u_id, 2, &__this->host_spk.vol_r_max, audio->interface_num);
retval_check(ret, 0);
//GET RES
ret = usb_audio_volume_control_get_res(host_dev, __this->host_spk.f_u_id, 2, &__this->host_spk.vol_r_res, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk volr min %04x, volr max %04x, volr res %04x, volr cur %04x",
__this->host_spk.vol_r_min,
__this->host_spk.vol_r_max,
__this->host_spk.vol_r_res,
__this->host_spk.vol_r_cur);
}
__exit_fail:
return ret;
}
static s32 __usb_host_speaker_get_cur_volume(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
if (__this->host_spk.vol_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 0, &__this->host_spk.vol_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk get vol_cur %04x", __this->host_spk.vol_cur);
}
if (__this->host_spk.vol_l_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 1, &__this->host_spk.vol_l_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk get vol_l_cur %04x", __this->host_spk.vol_l_cur);
}
if (__this->host_spk.vol_r_en) {
//GET CUR
ret = usb_audio_volume_control_get_cur(host_dev, __this->host_spk.f_u_id, 2, &__this->host_spk.vol_r_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk get vol_r_cur %04x", __this->host_spk.vol_r_cur);
}
__exit_fail:
return ret;
}
static s32 __usb_host_speaker_set_cur_volume(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
s32 ret = 0;
if (__this->host_spk.vol_en) {
//SET CUR
ret = usb_audio_volume_control_set_cur(host_dev, __this->host_spk.f_u_id, 0, __this->host_spk.vol_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk set vol to 0x%04x", __this->host_spk.vol_cur);
}
if (__this->host_spk.vol_l_en) {
//SET CUR
ret = usb_audio_volume_control_set_cur(host_dev, __this->host_spk.f_u_id, 1, __this->host_spk.vol_l_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk set vol_l to 0x%04x", __this->host_spk.vol_l_cur);
}
if (__this->host_spk.vol_r_en) {
//SET CUR
ret = usb_audio_volume_control_set_cur(host_dev, __this->host_spk.f_u_id, 2, __this->host_spk.vol_r_cur, audio->interface_num);
retval_check(ret, 0);
log_debug("host spk set vol_r to 0x%04x", __this->host_spk.vol_r_cur);
}
__exit_fail:
return ret;
}
int usb_host_speaker_set_volume(const usb_dev usb_id, u16 vol)
{
if (__this->host_spk.vol_en) {
__this->host_spk.vol_cur = host_speaker_vol_convert(vol, __this->host_spk.vol_min, __this->host_spk.vol_max, 0);
}
if (__this->host_spk.vol_l_en) {
__this->host_spk.vol_l_cur = host_speaker_vol_convert(vol, __this->host_spk.vol_l_min, __this->host_spk.vol_l_max, 0);
}
if (__this->host_spk.vol_r_en) {
__this->host_spk.vol_r_cur = host_speaker_vol_convert(vol, __this->host_spk.vol_r_min, __this->host_spk.vol_r_max, 0);
}
return __usb_host_speaker_set_cur_volume(usb_id);
}
int usb_host_speaker_set_mute(const usb_dev usb_id, u8 mute)
{
mute = !!mute;
log_debug("host spk set mute %d", mute);
if (__this->host_spk.mute_en) {
__this->host_spk.mute = mute;
}
if (__this->host_spk.mute_l_en) {
__this->host_spk.mute_l = mute;
}
if (__this->host_spk.mute_r_en) {
__this->host_spk.mute_r = mute;
}
return __usb_host_speaker_set_mute(usb_id);
}
static s32 __usb_slave_mic_get_agc(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
int ret = 0;
u8 agc;
if (__this->host_spk.agc_en) {
ret = usb_audio_agc_control_get_cur(host_dev, __this->host_spk.f_u_id, 0, &agc, audio->interface_num);
retval_check(ret, 0);
__this->host_spk.agc = agc;
}
if (__this->host_spk.agc_l_en) {
ret = usb_audio_agc_control_get_cur(host_dev, __this->host_spk.f_u_id, 1, &agc, audio->interface_num);
retval_check(ret, 0);
__this->host_spk.agc_l = agc;
}
if (__this->host_spk.agc_r_en) {
ret = usb_audio_agc_control_get_cur(host_dev, __this->host_spk.f_u_id, 2, &agc, audio->interface_num);
retval_check(ret, 0);
__this->host_spk.agc_r = agc;
}
__exit_fail:
return ret;
}
static s32 __usb_slave_mic_set_agc(const usb_dev usb_id)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = __find_control_interface(host_dev);
if (!audio) {
log_error("no find control interface!");
return -1;
}
int ret = 0;
u8 agc;
if (__this->host_spk.agc_en) {
agc = __this->host_spk.agc;
ret = usb_audio_agc_control_set_cur(host_dev, __this->host_spk.f_u_id, 0, agc, audio->interface_num);
retval_check(ret, 0);
}
if (__this->host_spk.agc_l_en) {
agc = __this->host_spk.agc_l;
ret = usb_audio_agc_control_set_cur(host_dev, __this->host_spk.f_u_id, 1, agc, audio->interface_num);
retval_check(ret, 0);
}
if (__this->host_spk.agc_r_en) {
agc = __this->host_spk.agc_r;
ret = usb_audio_agc_control_set_cur(host_dev, __this->host_spk.f_u_id, 2, agc, audio->interface_num);
retval_check(ret, 0);
}
__exit_fail:
return ret;
}
static u32 write_file_len[USB_MAX_HW_NUM];
static void usb_audio_rx_isr(struct usb_host_device *host_dev, u32 ep)
{
u8 *ptr = NULL;
u32 rlen, wlen = 0;
usb_dev usb_id = host_device2id(host_dev);
struct audio_device_t *audio = NULL;
struct audio_streaming_t *as_t = NULL;
if (__this->host_spk.spk_state != AUDIO_SPK_START) {
return;
}
audio = __find_microphone_interface(host_dev);
if (!audio) {
log_error("no find microphone interface!");
return;
}
as_t = &audio->as[__this->host_spk.Cur_AlternateSetting - 1];
int rx_len = usb_h_ep_read_async(usb_id, ep, as_t->ep, __this->host_spk.buffer, as_t->ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
/* printf("rx len : %d %d\n", rx_len, ep); */
if (rx_len > 0) {
cbuf_write(&__this->host_spk.usb_audio_spk_cbuf, __this->host_spk.buffer, rx_len);
}
cbuf_write_alloc(&__this->host_spk.usb_audio_spk_cbuf, &wlen);
if (wlen == 0) {
if (write_file_len[usb_id]) {
putchar('e');
}
/* [> printf("R:%d W:%d\n", rx_len,wlen); <] */
cbuf_read_alloc(&__this->host_spk.usb_audio_spk_cbuf, &rlen);
cbuf_read(&__this->host_spk.usb_audio_spk_cbuf, __this->host_spk.usb_audio_spk_buf2, rlen);
write_file_len[usb_id] = rlen;
if (usb_id == 0) {
os_taskq_post_msg("uac_play0", 2, 0x01, rlen);
} else {
os_taskq_post_msg("uac_play1", 2, 0x01, rlen);
}
}
usb_h_ep_read_async(usb_id, ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //触发下一个接收中断
}
static void audio_player_task(void *p)
{
log_info(">>> Enter usb audio player task");
struct usb_host_device *host_dev = (struct usb_host_device *)p;
const usb_dev usb_id = host_device2id(host_dev);
u8 *ptr = NULL;
u32 rlen = 0;
u32 ret = 0;
int msg[4];
struct audio_device_t *audio = __find_microphone_interface(host_dev);
struct audio_streaming_t *as_t = &audio->as[__this->host_spk.Cur_AlternateSetting - 1];
u32 ep_max_packet_size = as_t->ep_max_packet_size;
u32 usb_audio_buf_size = ep_max_packet_size * 10;
log_info("ep max packet : %d\n", ep_max_packet_size);
//分配双缓存
// 一个缓存写卡的数据,一个用于usb接收
if (!__this->host_spk.usb_audio_spk_buf) {
__this->host_spk.usb_audio_spk_buf = zalloc(usb_audio_buf_size);
cbuf_init(&__this->host_spk.usb_audio_spk_cbuf, __this->host_spk.usb_audio_spk_buf, usb_audio_buf_size);
}
if (!__this->host_spk.usb_audio_spk_buf2) {
__this->host_spk.usb_audio_spk_buf2 = zalloc(usb_audio_buf_size);
}
if (!__this->host_spk.buffer) {
__this->host_spk.buffer = malloc(as_t->ep_max_packet_size);
}
if (!__this->host_spk.usb_audio_spk_buf || !__this->host_spk.usb_audio_spk_buf2) {
os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
}
__this->host_spk.spk_state = AUDIO_SPK_START;
__this->host_spk.put_buf(usb_id, NULL, 0, __this->host_spk.src_channel == as_t->bNrChannels ? __this->host_spk.src_channel : __this->host_spk.src_channel | BIT(7), __this->host_spk.sample_rate);
usb_h_ep_read_async(usb_id, as_t->host_ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //启动iso
os_sem_post(__this->wait_sem);
while (1) {
ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
if (ret == OS_TASKQ) {
switch (msg[1]) {
case 0x01:
ptr = __this->host_spk.usb_audio_spk_buf2;
rlen = msg[2];
/* putchar('b'); */
if (__this->host_spk.put_buf) {
__this->host_spk.put_buf(usb_id, ptr, rlen, __this->host_spk.src_channel, __this->host_spk.sample_rate);
}
write_file_len[usb_id] = 0;
break;
}
}
}
}
void usb_audio_start_player(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate)
{
struct usb_host_device *host_dev = (struct usb_host_device *)host_id2device(usb_id);
struct audio_device_t *audio = NULL;
struct audio_streaming_t *as_t = NULL;
u8 find_alternatesetting = 0;
audio = __find_microphone_interface(host_dev);
if (!audio) {
log_error("no find host_spk interface!");
return;
}
for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) {
as_t = &audio->as[i];
if (as_t->bBitResolution == bit_reso) {
for (u8 j = 0; j < as_t->bSamFreqType; j++) {
if (sample_rate == 0 && as_t->tSamFreq[as_t->bSamFreqType - j - 1] && as_t->tSamFreq[as_t->bSamFreqType - j - 1] <= 48000) {
sample_rate = as_t->tSamFreq[as_t->bSamFreqType - j - 1];
find_alternatesetting = i + 1;
break;
}
if (as_t->tSamFreq[as_t->bSamFreqType - j - 1] == sample_rate) {
find_alternatesetting = i + 1;
break;
}
}
}
}
if (!find_alternatesetting) {
log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n");
return;
}
as_t = &audio->as[find_alternatesetting - 1];
u32 ep_max_packet_size = sample_rate * 2 * as_t->bNrChannels / 1000;
if (ep_max_packet_size > as_t->ep_max_packet_size) {
ep_max_packet_size = as_t->ep_max_packet_size;
} else {
as_t->ep_max_packet_size = ep_max_packet_size;
}
//端点分配
u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_ISOC);
ASSERT(host_ep != -1, "ep not enough");
host_ep = host_ep | USB_DIR_IN;
ep_in_dma_buf[usb_id] = usb_h_alloc_ep_buffer(usb_id, host_ep, as_t->ep_max_packet_size + 64); //预留64个字节防止硬件越界访问
ASSERT(ep_in_dma_buf[usb_id] != NULL);
as_t->host_ep = host_ep & 0x0f;
if (channel == 0) {
channel = as_t->bNrChannels;
}
__this->host_spk.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting
__this->host_spk.sample_rate = sample_rate; //选择采样率
__this->host_spk.src_channel = channel;
usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface 1 Alternatesetting 1
if (!as_t->sr_ctrl_dis) {
usb_audio_sampling_frequency_control(host_dev, as_t->ep | USB_DIR_IN, sample_rate);//设置采样率
}
log_info("D2H ep: %x --> %x interval: %d", as_t->ep, host_ep, as_t->ep_Interval);
usb_write_rxfuncaddr(usb_id, as_t->host_ep, host_dev->private_data.devnum);
usb_h_set_ep_isr(host_dev, host_ep, usb_audio_rx_isr, host_dev);
usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, as_t->ep_Interval, ep_in_dma_buf[usb_id], as_t->ep_max_packet_size);
__usb_host_speaker_get_all_volume(usb_id);
usb_host_speaker_set_mute(usb_id, 0);
usb_host_speaker_set_volume(usb_id, HOST_SPK_VOLUME);
/* user_host_speaker_control(host_dev); */ //与AC53通信开启dac
OS_SEM sem;
os_sem_create(&sem, 0);
__this->wait_sem = &sem;
if (usb_id == 0) {
task_create(audio_player_task, host_dev, "uac_play0");
} else {
task_create(audio_player_task, host_dev, "uac_play1");
}
os_sem_pend(&sem, 0);
__this->wait_sem = NULL;
}
void usb_audio_stop_player(const usb_dev usb_id)
{
__this->host_spk.spk_state = AUDIO_SPK_STOP;
usb_h_set_ep_isr(NULL, 0, NULL, NULL);
if (usb_id == 0) {
task_kill("uac_play0");
} else {
task_kill("uac_play1");
}
if (__this->host_spk.put_buf) {
__this->host_spk.put_buf(usb_id, NULL, 0, 0, 0);
}
__this->host_spk.Cur_AlternateSetting = 0;
__this->host_spk.sample_rate = 0;
if (__this->host_spk.usb_audio_spk_buf) {
free(__this->host_spk.usb_audio_spk_buf);
__this->host_spk.usb_audio_spk_buf = NULL;
}
if (__this->host_spk.usb_audio_spk_buf2) {
free(__this->host_spk.usb_audio_spk_buf2);
__this->host_spk.usb_audio_spk_buf2 = NULL;
}
if (__this->host_spk.buffer) {
free(__this->host_spk.buffer);
__this->host_spk.buffer = NULL;
}
if (ep_in_dma_buf[usb_id]) {
usb_h_free_ep_buffer(usb_id, ep_in_dma_buf[usb_id]);
ep_in_dma_buf[usb_id] = NULL;
}
}
void usb_audio_pause_player(const usb_dev usb_id)
{
__this->host_spk.spk_state = AUDIO_SPK_PAUSE;
}
void usb_audio_resume_player(const usb_dev usb_id)
{
const struct usb_host_device *host_dev = host_id2device(usb_id);
struct audio_device_t *audio = __find_microphone_interface(host_dev);
struct audio_streaming_t *as_t = &audio->as[__this->host_spk.Cur_AlternateSetting - 1];
if (__this->host_spk.usb_audio_spk_buf) {
cbuf_clear(&__this->host_spk.usb_audio_spk_cbuf);
write_file_len[usb_id] = 0;
__this->host_spk.spk_state = AUDIO_SPK_START;
usb_h_ep_read_async(usb_id, as_t->host_ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //重新启动接收
}
}
void usb_audio_start_process(const usb_dev usb_id)
{
usb_audio_start_recorder(usb_id, HOST_MIC_CHANNEL, HOST_MIC_AUDIO_RES, HOST_MIC_AUDIO_RATE); //开启主机的host_spk
usb_audio_start_player(usb_id, HOST_SPK_CHANNEL, HOST_SPK_AUDIO_RES, HOST_SPK_AUDIO_RATE); //开启主机的speaker
}
void usb_audio_stop_process(const usb_dev usb_id)
{
usb_audio_stop_recorder(usb_id);
usb_audio_stop_player(usb_id);
}
void usb_host_audio_init(const usb_dev usb_id, int (*put_buf)(const usb_dev usb_id, void *ptr, u32 len, u8 channel, u32 sample_rate), int (*get_buf)(const usb_dev usb_id, void *ptr, u32 len, u8 channel, u32 sample_rate))
{
memset(__this, 0, sizeof(struct usb_audio_info));
__this->host_mic.get_buf = get_buf;
__this->host_spk.put_buf = put_buf;
}
void usb_host_audio_exit(const usb_dev usb_id)
{
__this->host_mic.get_buf = NULL;
__this->host_spk.put_buf = NULL;
}
#endif