1841 lines
65 KiB
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
|