KT24-1110_65E-HA-651B/apps/common/usb/device/uac1.c
2024-11-10 18:44:17 +08:00

1348 lines
48 KiB
C

/* Copyright(C) JieLi Technology
* usb audio 1.0
* All right reserved
*
*/
#include "system/includes.h"
#include "usb_config.h"
#include "usb/device/usb_stack.h"
#include "usb/device/uac_audio.h"
#include "app_config.h"
#if TCFG_USB_SLAVE_AUDIO_ENABLE
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
static u32 mic_samplingfrequency;
/*********************************************************/
/*
Audio Class
*/
/*********************************************************/
///Standard Interface Association Descriptor
static const u8 uac_audio_interface_association[] = {
USB_DT_INTERFACE_ASSOCIATION_SIZE, //Size of this descriptor in bytes: 8
USB_DT_INTERFACE_ASSOCIATION,//INTERFACE ASSOCIATION Descriptor
0,//Interface number of the first interface that is associated with this function
0,//Number of contiguous interfaces that are associated with this function.
USB_CLASS_AUDIO,//AUDIO_FUNCTION Function Class code
USB_SUBCLASS_AUDIOSTREAMING,//FUNCTION_SUBCLASS_UNDEFINED
PC_PROTOCOL_UNDEFINED,//AF_VERSION_02_00 Function Protocol code.
SPEAKER_STR_INDEX,//Index of a string descriptor that describes this interface.
};
static const u8 uac_ac_standard_interface_desc[] = {
///standard interface AC descriptor(Interface 0, Alternate Setting 0)
USB_DT_INTERFACE_SIZE, //Length
USB_DT_INTERFACE, //DescriptorType:Inerface
0x00, //InterfaceNum
0x00, //AlternateSetting
0x00, //NumEndpoint
USB_CLASS_AUDIO, //InterfaceClass:audio
USB_SUBCLASS_AUDIOCONTROL, //InterfaceSubClass:audio ctl
PC_PROTOCOL_UNDEFINED, //InterfaceProtocol
SPEAKER_STR_INDEX, //Interface String
};
static const u8 uac_spk_ac_interface[] = {
///class-specific AC interface descriptor
0x09, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_HEADER, //DescriptorSubType:audio control header
0x00, 0x01, //bcdADC:audio Device Class v1.00
0x28, 0x00, //TotalLength of class-specific AC interface descriptors
0x01, //InCollection:1 AudioStreaming interface
0x02, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface
/* 0x03, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface */
};
static const u8 uac_audio_ac_interface[] = {
///class-specific AC interface descriptor
0x0a, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_HEADER, //DescriptorSubType:audio control header
0x00, 0x01, //bcdADC:audio Device Class v1.00
0x47, 0x00, //TotalLength of class-specific AC interface descriptors
0x02, //InCollection:1 AudioStreaming interface
0x01, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface
0x02, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface
};
static const u8 uac_spk_input_terminal_desc[] = {
///USB USB Streaming IT(Speaker)
0x0c, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_INPUT_TERMINAL, //DescriptorSubType:Input Terminal
SPK_INPUT_TERMINAL_ID, //TerminalID
LOBYTE(UAC_TERMINAL_STREAMING), HIBYTE(UAC_TERMINAL_STREAMING), //TerminalType:USB Streaming
0x00, //AssocTerminal
SPK_CHANNEL, //NrChannels:2 channel
#if SPK_CHANNEL == 1
0x04, 0x00, //Mono center front channel
#else
0x03, 0x00, //ChannelConfig:Left Front,Right Front,
#endif
0x00, //ChannelName String
0x00, //Terminal String
};
///Audio Feature Unit Descriptor(Speaker)
static const u8 uac_spk_feature_desc[] = {
0x07 + (SPK_CHANNEL + 1) * 1, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_FEATURE_UNIT, //DescriptorSubType:Audio Feature Unit
SPK_FEATURE_UNIT_ID, //UnitID
SPK_INPUT_TERMINAL_ID, //SourceID:1 #USB Streaming IT
0x01, //ControlSize:1 byte
0x01, //Controls:BIT[0……7]:Mute,Volume Bass Mid Treble......
0x02, //left ch
#if SPK_CHANNEL == 2
0x02, //right ch
#endif
0x00, //Feature String
};
static const u8 uac_spk_output_terminal_desc[] = {
///USB Speaker OT
0x09, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_OUTPUT_TERMINAL, //DescriptorSubTYpe:Output Terminal
SPK_OUTPUT_TERMINAL_ID, //TerminalID
LOBYTE(UAC_OUTPUT_TERMINAL_SPEAKER), HIBYTE(UAC_OUTPUT_TERMINAL_SPEAKER), //TerminalType:Speaker
0, //AssocTerminal:
SPK_FEATURE_UNIT_ID, //SourceID: Feature UNIT
0x00, //Terminal String
};
static const u8 uac_spk_as_interface_desc[] = {
//-------------------Speaker interface---------------------//
///standard interface AS descriptor(Interface 1, Alternate Setting 0)
USB_DT_INTERFACE_SIZE, //Length
USB_DT_INTERFACE, //DescriptorType:Interface
0x00, //InterfaceNum:2
0x00, //AlternateSetting:0
0x00, //NumEndpoint:0
USB_CLASS_AUDIO, //InterfaceClass:audio
USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming
PC_PROTOCOL_UNDEFINED, //InterfaceProtocol
0x00, //Interface String
///standard interface AS descriptor(Interface 2, Alternate Setting 1)
USB_DT_INTERFACE_SIZE, //Length
USB_DT_INTERFACE, //DescriptorType:Interface
0x00, //InterfaceNum
0x01, //AlternateSetting
0x01, //NumEndpoint
USB_CLASS_AUDIO, //InterfaceClass:audio
USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming
PC_PROTOCOL_UNDEFINED, //InterfaceProtocol
0x00, //Interface String
///Audio Streaming Interface Descriptor:AS_GENERAL(0x01),
0x07, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_AS_GENERAL, //DescriptorSubType:AS_GENERAL
SPK_INPUT_TERMINAL_ID, //TerminalLink:#1 USB Streaming IT
0x01, //Delay:1
(SPK_AUDIO_TYPE & 0xFF), (SPK_AUDIO_TYPE >> 8), //FormatTag:PCM
///Type 1 Format type descriptor
0x0b, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_FORMAT_TYPE, //DescriptorSubType:Format_type
UAC_FORMAT_TYPE_I, //FormatType:Format type 1
SPK_CHANNEL, //NumberOfChannel
0x02, //SubframeSize:2byte
SPK_AUDIO_RES, //BitsResolution:16bit
0x01, //SampleFreqType:One sampling frequency.
DW1BYTE(SPK_AUDIO_RATE), DW2BYTE(SPK_AUDIO_RATE), DW3BYTE(SPK_AUDIO_RATE),
//Isochronous,Synchronization Type(Asynchronous)
0x09, //Length
USB_DT_ENDPOINT, //DescriptorType:endpoint descriptor
USB_DIR_OUT | SPK_ISO_EP_OUT, //EndpointAddress:Output endpoint 1
USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE, //0x09,
LOBYTE(SPK_FRAME_LEN), HIBYTE(SPK_FRAME_LEN), //MaxPacketSize
UAC_ISO_INTERVAL,//one packet per frame 0x00, //Interval //Asynchronous
0x00,//unused
0x00,//unused
//Audio Endpoint descriptor,General
0x07, //Length
USB_DT_CS_ENDPOINT, //DescriptorType:audio endpoint descriptor
UAC_AS_GENERAL, //DescriptorSubType:audio endpiont general
// 0x01, // bmAttributes (Sampling Freq Control)
0x00, //Attributes
0x00, //LockDelayUnits
0x00, 0x00, //LockDelay
};
const u8 speakerStringDescriptor[20] = {
20, //该描述符的长度为20字节
0x03, //字符串描述符的类型编码为0x03
'U', 0x00, //U
'S', 0x00, //S
'B', 0x00, //B
' ', 0x00, //
'A', 0x00, //A
'u', 0x00, //u
'd', 0x00, //d
'i', 0x00, //i
'o', 0x00, //o
};
/*********************************************************/
/*
Microphone Class
*/
/*********************************************************/
///Standard Interface Association Descriptor
static const u8 uac_mic_interface_association[] = {
USB_DT_INTERFACE_ASSOCIATION_SIZE,//Size of this descriptor in bytes
USB_DT_INTERFACE_ASSOCIATION,//INTERFACE ASSOCIATION Descriptor
2,//Interface number of the first interface that is associated with this function ****
1,//Number of contiguous interfaces that are associated with this function.
USB_CLASS_AUDIO,//AUDIO_FUNCTION Function Class code
USB_SUBCLASS_AUDIOSTREAMING,//FUNCTION_SUBCLASS_UNDEFINED
PC_PROTOCOL_UNDEFINED,//AF_VERSION_02_00 Function Protocol code.
MIC_STR_INDEX,//Index of a string descriptor that describes this interface
};
static const u8 uac_mic_ac_interface[] = {
///class-specific AC interface descriptor
0x09, //Length
USB_DT_CS_INTERFACE, //DescriptorType
UAC_HEADER, //DescriptorSubType
0x00, 0x01, //bcdADC
0x27, 0x00, /*TotalLength of class-specific AC interface descriptors */
/* Includes the combined length */
/* of this descriptor header and all Unit and */
/* Terminal descriptors. */
0x01, //InCollection:1 AudioStreaming interface
0x01, //InterfaceNr(1) ****
};
///USB USB Streaming IT(Microphone)
static const u8 uac_mic_input_terminal_desc[] = {
0x0c, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_INPUT_TERMINAL, //DescriptorSubType:Input Terminal
MIC_INPUT_TERMINAL_ID, //TerminalID
LOBYTE(UAC_INPUT_TERMINAL_MICROPHONE), HIBYTE(UAC_INPUT_TERMINAL_MICROPHONE), //TerminalType:Microphone
0, //AssocTerminal
MIC_CHANNEL, //NrChannels
#if MIC_CHANNEL == 2
0x03, 0x00, //wChannelConfig:Left Front right Front
#else
0x00, 0x00, //wChannelConfig:
#endif
0x00, //ChannelName String
0x00, //Terminal String
};
//SELECTOR_UNIT
static const u8 uac_mic_selector_uint_desc[] = {
0x7, // bLength 7
USB_DT_CS_INTERFACE,// bDescriptorType CS_INTERFACE (0x24)
UAC_SELECTOR_UNIT,// bDescriptorSubtype SELECTOR_UNIT (0x05)
MIC_SELECTOR_UNIT_ID,//bUnitID 33
1,//bNrInPins 1
MIC_FEATURE_UNIT_ID, //baSourceID(1) 50
0,//iSelector None (0)
};
///Audio Feature Unit Descriptor(Microphone)
static const u8 uac_mic_feature_desc[] = {
7 + (MIC_CHANNEL + 1) * 1, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_FEATURE_UNIT, //DescriptorSubType:Audio Feature Unit
MIC_FEATURE_UNIT_ID, //UnitID
MIC_INPUT_TERMINAL_ID, //SourceID: #Microphone
0x01, //ControlSize:1 byte
0x43, 0x00, // bmaControls[0] (Mute,Volume,Automatic)
#if MIC_CHANNEL == 2
0x00,
#endif
0x00, //Feature String
};
///USB Microphone OT
static const u8 uac_mic_output_terminal_desc[] = {
0x09, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_OUTPUT_TERMINAL, //DescriptorSubTYpe:Output Terminal
MIC_OUTPUT_TERMINAL_ID, //TerminalID
LOBYTE(UAC_TERMINAL_STREAMING), HIBYTE(UAC_TERMINAL_STREAMING), //TerminalType:USB Sreaming
2, //AssocTerminal:
MIC_SELECTOR_UNIT_ID, //SourceID:A #Feature UNIT
0x00, //Terminal String
};
///standard interface AS descriptor(Interface 1, Alternate Setting 0)
static const u8 uac_mic_as_interface_desc[] = {
USB_DT_INTERFACE_SIZE, //Length
USB_DT_INTERFACE, //DescriptorType:Interface
0x03, //InterfaceNum ****
0x00, //AlternateSetting
0x00, //NumEndpoint
USB_CLASS_AUDIO, //InterfaceClass:audio
USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming
0x00, //InterfaceProtocol
0x00, //Interface String
///standard interface AS descriptor(Interface 2, Alternate Setting 1)
USB_DT_INTERFACE_SIZE, //Length
USB_DT_INTERFACE, //DescriptorType:Interface
0x02, //InterfaceNum ****
0x01, //AlternateSetting
0x01, //NumEndpoint
USB_CLASS_AUDIO, //InterfaceClass:audio
USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming
0x00, //InterfaceProtocol
0x00, //Interface String
///Audio Streaming Interface Descriptor:AS_GENERAL
0x07, //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_AS_GENERAL, //DescriptorSubType:AS_GENERAL
MIC_OUTPUT_TERMINAL_ID, //TerminalLink:#1 USB Streaming OT
0x01, //Delay:1
(MIC_AUDIO_TYPE & 0xFF), (MIC_AUDIO_TYPE >> 8), //FormatTag:PCM
///Type 1 Format type descriptor
0x08 + 3 * (MIC_SamplingFrequency), //Length
USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor
UAC_FORMAT_TYPE, //DescriptorSubType:Format_type
UAC_FORMAT_TYPE_I_PCM, //FormatType:Format type 1
MIC_CHANNEL, //NumberOfChannel:1
MIC_AUDIO_RES / 8, //SubframeSize:2byte
MIC_AUDIO_RES, //BitsResolution:16bit
#if MIC_SamplingFrequency > 1
MIC_SamplingFrequency,
DW1BYTE(MIC_AUDIO_RATE_1), DW2BYTE(MIC_AUDIO_RATE_1), DW3BYTE(MIC_AUDIO_RATE_1),
DW1BYTE(MIC_AUDIO_RATE_2), DW2BYTE(MIC_AUDIO_RATE_2), DW3BYTE(MIC_AUDIO_RATE_2),
DW1BYTE(MIC_AUDIO_RATE), DW2BYTE(MIC_AUDIO_RATE), DW3BYTE(MIC_AUDIO_RATE),
DW1BYTE(MIC_AUDIO_RATE_4), DW2BYTE(MIC_AUDIO_RATE_4), DW3BYTE(MIC_AUDIO_RATE_4),
#else
0x01, //SampleFreqType:One sampling frequency.
DW1BYTE(MIC_AUDIO_RATE), DW2BYTE(MIC_AUDIO_RATE), DW3BYTE(MIC_AUDIO_RATE),
#endif
///Endpoint 1 - Standard Descriptor:Output Endpoint1
//Isochronous,Synchronization Type(Asynchronous)
USB_DT_ENDPOINT_AUDIO_SIZE, //Length
USB_DT_ENDPOINT, //DescriptorType:endpoint descriptor
USB_DIR_IN | MIC_ISO_EP_IN, //EndpointAddress:Output endpoint
USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
LOBYTE(MIC_FRAME_LEN), HIBYTE(MIC_FRAME_LEN), //MaxPacketSize
UAC_ISO_INTERVAL,//one packet per frame //Interval
0x00,//unused
0x00,//unused
///Endpoint - Audio Streaming Descriptor
//Audio Endpoint descriptor,General
0x07, //Length
USB_DT_CS_ENDPOINT, //DescriptorType:audio endpoint descriptor
UAC_AS_GENERAL, //DescriptorSubType:audio endpiont general
#if MIC_SamplingFrequency > 1
0x01, // bmAttributes (Sampling Freq Control)
#else
0x00, //Attributes
#endif
0x00, //LockDelayUnits
0x00, 0x00, //LockDelay
};
static const u8 micStringDescriptor[30] = {
30, //该描述符的长度为30字节
0x03, //字符串描述符的类型编码为0x03
'U', 0x00, //U
'S', 0x00, //S
'B', 0x00, //B
' ', 0x00, //
'M', 0x00, //M
'i', 0x00, //i
'c', 0x00, //c
'r', 0x00, //r
'o', 0x00, //o
'p', 0x00, //p
'h', 0x00, //h
'o', 0x00, //o
'n', 0x00, //n
'e', 0x00, //e
};
const u8 *uac_get_string(u32 id)
{
if (id == SPEAKER_STR_INDEX) {
return speakerStringDescriptor;
} else if (id == MIC_STR_INDEX) {
return micStringDescriptor;
}
return NULL;
}
struct uac_info_t {
u16 spk_left_vol;
u16 spk_right_vol;
u16 spk_max_vol;
u16 spk_min_vol;
u16 spk_def_vol;
u16 spk_vol_res;
u8 *spk_dma_buffer;
u16 mic_max_vol;
u16 mic_min_vol;
u16 mic_def_vol;
u16 mic_vol_res;
u16 mic_vol;
u8 *mic_dma_buffer;
u8 spk_mute: 1;
u8 mic_mute: 1;
u8 bAGC: 1;
u8 res: 5;
};
struct uac_info_t *uac_info;
#if USB_MALLOC_ENABLE
#else
struct uac_info_t _uac_info SEC(.uac_var);
#endif
static u32 vol_convert(u16 v)
{
const u16 vol_table[] = {
0xe3a0, 0xe461, 0xe519, 0xe5c8, 0xe670, 0xe711, 0xe7ac, 0xe840, 0xe8cf, 0xe959,
0xe9df, 0xea60, 0xeadc, 0xeb55, 0xebca, 0xec3c, 0xecab, 0xed16, 0xed7f, 0xede5,
0xee48, 0xeea9, 0xef08, 0xef64, 0xefbe, 0xf016, 0xf06c, 0xf0c0, 0xf113, 0xf164,
0xf1b3, 0xf200, 0xf24c, 0xf297, 0xf2e0, 0xf328, 0xf36e, 0xf3b4, 0xf3f8, 0xf43a,
0xf47c, 0xf4bd, 0xf4fc, 0xf53b, 0xf579, 0xf5b5, 0xf5f1, 0xf62c, 0xf666, 0xf69f,
0xf6d7, 0xf70e, 0xf745, 0xf77b, 0xf7b0, 0xf7e5, 0xf818, 0xf84b, 0xf87e, 0xf8b0,
0xf8e1, 0xf911, 0xf941, 0xf970, 0xf99f, 0xf9cd, 0xf9fb, 0xfa28, 0xfa55, 0xfa81,
0xfaad, 0xfad8, 0xfb03, 0xfb2d, 0xfb56, 0xfb80, 0xfba9, 0xfbd1, 0xfbf9, 0xfc21,
0xfc48, 0xfc6f, 0xfc95, 0xfcbb, 0xfce1, 0xfd06, 0xfd2b, 0xfd50, 0xfd74, 0xfd98,
0xfdbc, 0xfddf, 0xfe02, 0xfe25, 0xfe47, 0xfe69, 0xfe8b, 0xfead, 0xfece, 0xfeef,
0xff0f,
};
if (v <= 100) {
return vol_table[v];
}
for (int i = 0; i < sizeof(vol_table) / 2; i++) {
if (v <= vol_table[i]) {
return i;
}
}
return 0;
}
void uac_get_cur_vol(const usb_dev usb_id, u16 *l_vol, u16 *r_vol)
{
if (l_vol) {
*l_vol = 0;
}
if (r_vol) {
*r_vol = 0;
}
if (uac_info) {
if (!uac_info->spk_mute) {
if (l_vol) {
*l_vol = vol_convert(uac_info->spk_left_vol);
}
if (r_vol) {
*r_vol = vol_convert(uac_info->spk_right_vol);
}
}
}
}
u16 uac_get_mic_vol(const usb_dev usb_id)
{
if (uac_info) {
if (!uac_info->mic_mute) {
return vol_convert(uac_info->mic_vol);
}
}
return 0;
}
u16 uac_get_mic_sameplerate(void *priv)
{
u16 sample_rate = (u16)mic_samplingfrequency;
return sample_rate;
}
static u32 uac_vol_handler(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 ret = 0;
u8 read_ep[8];
u8 mute;
u16 volume = 0;
usb_read_ep0(usb_id, read_ep, setup->wLength);
ret = USB_EP0_STAGE_SETUP;
switch (HIBYTE(setup->wValue)) {
case UAC_FU_MUTE:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
memcpy((u8 *)&mute, read_ep, 1);
if (mute) {
uac_mute_volume(SPK_FEATURE_UNIT_ID, 0, 0);
uac_info->spk_mute = 1;
} else {
uac_mute_volume(SPK_FEATURE_UNIT_ID,
vol_convert(uac_info->spk_left_vol),
vol_convert(uac_info->spk_right_vol));
uac_info->spk_mute = 0;
}
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
memcpy((u8 *)&mute, read_ep, 1);
if (mute) {
uac_mute_volume(MIC_FEATURE_UNIT_ID, 0, 0);
uac_info->mic_mute = 1;
} else {
uac_mute_volume(MIC_FEATURE_UNIT_ID, vol_convert(uac_info->mic_vol), 0);
uac_info->mic_mute = 0;
}
}
break;
case UAC_FU_VOLUME:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
memcpy((u8 *)&volume, read_ep, setup->wLength);
if (LOBYTE(setup->wValue) == 1) {
uac_info->spk_left_vol = volume;
} else if (LOBYTE(setup->wValue) == 2) {
uac_info->spk_right_vol = volume;
/* printf("%x %d",volume,vol_convert(volume)); */
}
if (!uac_info->spk_mute) {
uac_mute_volume(SPK_FEATURE_UNIT_ID,
vol_convert(uac_info->spk_left_vol),
vol_convert(uac_info->spk_right_vol));
}
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
memcpy((u8 *)&uac_info->mic_vol, read_ep, sizeof(uac_info->mic_vol));
/* if (uac_info->mic_vol == 0x8000) { */
/* uac_info->mic_vol = 0; */
/* } else if (uac_info->mic_vol >= 100) { */
/* uac_info->mic_vol = 99; */
/* } */
if (!uac_info->mic_mute) {
uac_mute_volume(MIC_FEATURE_UNIT_ID, vol_convert(uac_info->mic_vol), 0);
}
}
break;
case UAC_FU_AUTOMATIC_GAIN:
if (read_ep[0]) {
uac_info->bAGC = 1;
} else {
uac_info->bAGC = 0;
}
break;
default :
ret = USB_EP0_SET_STALL;
break;
}
return ret;
}
#if USB_ROOT2
static u8 SetInterface_0_Lock;
#endif
static u32 uac_endpoint_recv(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 ret = 0;
u8 read_ep[8];
usb_read_ep0(usb_id, read_ep, setup->wLength);
ret = USB_EP0_STAGE_SETUP;
u32 ep = LOBYTE(setup->wIndex);
switch (ep) {
case MIC_ISO_EP_IN|USB_DIR_IN:
memcpy(&mic_samplingfrequency, read_ep, 3);
break;
case SPK_ISO_EP_OUT|USB_DIR_OUT:
/* memcpy(&spk_samplingfrequency,read_ep,3); */
break;
}
return ret;
}
u32 uac_setup_endpoint(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
{
u32 ret = 0;
const usb_dev usb_id = usb_device2id(usb_device);
u8 type = req->bRequestType & USB_TYPE_MASK;
if (type != USB_TYPE_CLASS) {
return ret;
}
if (req->bRequest != 0x01) {
return ret;
}
if (req->wValue != 0x0100) {
return ret;
}
usb_set_setup_recv(usb_device, uac_endpoint_recv);
return 1;
}
static u32 audio_ac_itf_handler(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
{
u8 mute;
const usb_dev usb_id = usb_device2id(usb_device);
u32 tx_len;
u8 *tx_payload = usb_get_setup_buffer(usb_device);
u32 bRequestType = setup->bRequestType & USB_TYPE_MASK;
u32 ret = 0;
switch (setup->bRequest) {
case USB_REQ_SET_INTERFACE:
#if USB_ROOT2
SetInterface_0_Lock = 1;
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);//no alt setting
}
#else
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);//no alt setting
#endif
break;
case USB_REQ_GET_INTERFACE:
#if USB_ROOT2
if (usb_root2_testing()) {
SetInterface_0_Lock = 0;
}
#endif
if (setup->wLength) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
tx_len = 1;
tx_payload[0] = 0x00;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
}
break;
case UAC_SET_CUR:
/* USB_DEBUG_PRINTF("set vol && mute"); */
usb_set_setup_recv(usb_device, uac_vol_handler);
break;
case UAC_GET_CUR:
switch (HIBYTE(setup->wValue)) {
case UAC_FU_MUTE:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
mute = uac_info->spk_mute ;
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
mute = uac_info->mic_mute ;
}
tx_payload = &mute;
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
case UAC_FU_VOLUME:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
if (LOBYTE(setup->wValue) == 1) {
tx_payload = (u8 *)&uac_info->spk_left_vol;
} else if (LOBYTE(setup->wValue) == 2) {
tx_payload = (u8 *)&uac_info->spk_right_vol;
}
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->mic_vol;
}
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
case UAC_FU_AUTOMATIC_GAIN:
if (uac_info->bAGC) {
tx_payload[0] = 0x01;
} else {
tx_payload[0] = 0x00;
}
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
}
break;
case UAC_GET_DEF:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->spk_def_vol;
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->mic_def_vol;
}
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
case UAC_GET_MAX:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->spk_max_vol;
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->mic_max_vol;
}
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
case UAC_GET_MIN:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->spk_min_vol;
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->mic_min_vol;
}
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
case UAC_GET_RES:
if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->spk_vol_res;
} else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) {
tx_payload = (u8 *)&uac_info->mic_vol_res;
}
tx_len = setup->wLength;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
break;
case UAC_GET_LEN:
break;
case UAC_GET_INFO:
break;
case USB_REQ_GET_STATUS:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
break;
default:
ret = 1 ;
break;
}
return ret;
}
#define UAC_PLC_EN 0
#if UAC_PLC_EN
typedef struct _USBAUDIO_PLC_API {
unsigned int (*need_buf)();
void (*open)(unsigned char *ptr, int sr, int nch);
int (*run)(unsigned char *ptr, short *inbuf, short *oubuf, short len, short err_flag);
} USBAUDIO_PLC_API;
extern USBAUDIO_PLC_API *get_USBplc_api();
static USBAUDIO_PLC_API *uac_plc_api = 0;
static u8 *uac_plc_buffer;
void usb_audio_plc_open()
{
uac_plc_api = get_USBplc_api();
u32 bufsize = uac_plc_api->need_buf();
uac_plc_buffer = malloc(bufsize);
uac_plc_api->open(uac_plc_buffer, SPK_AUDIO_RATE, SPK_CHANNEL);
}
void usb_audio_plc_close()
{
if (uac_plc_api) {
uac_plc_api = NULL;
}
if (uac_plc_buffer) {
free(uac_plc_buffer);
uac_plc_buffer = NULL;
}
}
#endif
static void spk_transfer(struct usb_device_t *usb_device, u32 ep)
{
const usb_dev usb_id = usb_device2id(usb_device);
u8 *ep_buffer = uac_info->spk_dma_buffer;
u32 spk_frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000;
spk_frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0);
u32 rx_len = usb_g_iso_read(usb_id, SPK_ISO_EP_OUT, NULL, spk_frame_len, 0);
#if UAC_PLC_EN
if (rx_len) {
uac_plc_api->run(uac_plc_buffer, ep_buffer, ep_buffer, rx_len, 0);
} else {
uac_plc_api->run(uac_plc_buffer, ep_buffer, ep_buffer, rx_len, 1);
}
#endif
uac_speaker_stream_write(ep_buffer, rx_len);
}
static void open_spk(struct usb_device_t *usb_device)
{
log_info("%s", __func__);
const usb_dev usb_id = usb_device2id(usb_device);
u32 spk_frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000;
spk_frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0);
u8 *ep_buffer = uac_info->spk_dma_buffer;
uac_speaker_stream_open(SPK_AUDIO_RATE, SPK_CHANNEL);
#if UAC_PLC_EN
usb_audio_plc_open();
#endif
usb_g_set_intr_hander(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, spk_transfer);
usb_g_ep_config(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, spk_frame_len);
}
static void close_spk(struct usb_device_t *usb_device)
{
log_info("%s", __func__);
const usb_dev usb_id = usb_device2id(usb_device);
usb_clr_intr_rxe(usb_id, SPK_ISO_EP_OUT);
usb_g_set_intr_hander(usb_id, SPK_ISO_EP_OUT, NULL);
#if UAC_PLC_EN
usb_audio_plc_close();
#endif
uac_speaker_stream_close();
}
static u32 spk_as_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
{
const usb_dev usb_id = usb_device2id(usb_device);
u32 tx_len;
u8 *tx_payload = usb_get_setup_buffer(usb_device);
u32 bRequestType = setup->bRequestType & USB_TYPE_MASK;
u32 ret = 0;
switch (setup->bRequest) {
case USB_REQ_SET_INTERFACE:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
#if USB_ROOT2
if (!usb_root2_testing()) {
SetInterface_0_Lock = 1;
}
if (SetInterface_0_Lock == 0) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
if (setup->wValue == 1) { //alt 1
open_spk(usb_device);
} else if (setup->wValue == 0) { //alt 0
close_spk(usb_device);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
}
#else
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
if (setup->wValue == 1) { //alt 1
open_spk(usb_device);
} else if (setup->wValue == 0) { //alt 0
close_spk(usb_device);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
#endif
}
break;
case USB_REQ_GET_INTERFACE:
if (usb_root2_testing()) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
if (setup->wLength) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
tx_len = 1;
tx_payload[0] = 0x00;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
}
}
break;
case USB_REQ_GET_STATUS:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
break;
default:
break;
}
return ret;
}
static u8 mic_no_data;
static void mic_transfer(struct usb_device_t *usb_device, u32 ep)
{
const usb_dev usb_id = usb_device2id(usb_device);
u8 *ep_buffer = uac_info->mic_dma_buffer;
if (mic_samplingfrequency == 0) {
mic_samplingfrequency = MIC_AUDIO_RATE;
}
u32 mic_frame_len = ((mic_samplingfrequency * MIC_AUDIO_RES / 8 * MIC_CHANNEL) / 1000);
mic_frame_len += (mic_samplingfrequency % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0);
int len = uac_mic_stream_read(ep_buffer, mic_frame_len);
if (len) {
mic_no_data = 0;
} else if (mic_no_data) {
len = mic_frame_len;
memset(ep_buffer, 0, len);
}
usb_g_iso_write(usb_id, MIC_ISO_EP_IN, NULL, len);
}
static void open_mic(struct usb_device_t *usb_device)
{
log_info("%s", __func__);
mic_no_data = 1;
const usb_dev usb_id = usb_device2id(usb_device);
usb_enable_ep(usb_id, MIC_ISO_EP_IN);
u8 *ep_buffer = uac_info->mic_dma_buffer;
usb_g_set_intr_hander(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, mic_transfer);
if (mic_samplingfrequency == 0) {
mic_samplingfrequency = MIC_AUDIO_RATE;
}
u32 mic_frame_len = ((mic_samplingfrequency * MIC_AUDIO_RES / 8 * MIC_CHANNEL) / 1000);
mic_frame_len += (mic_samplingfrequency % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0);
uac_mic_stream_open(mic_samplingfrequency, mic_frame_len, MIC_CHANNEL);
usb_g_ep_config(usb_id,
MIC_ISO_EP_IN | USB_DIR_IN,
USB_ENDPOINT_XFER_ISOC,
1, ep_buffer, mic_frame_len);
mic_transfer(usb_device, MIC_ISO_EP_IN);
}
static void close_mic(struct usb_device_t *usb_device)
{
log_info("%s", __func__);
const usb_dev usb_id = usb_device2id(usb_device);
usb_clr_intr_txe(usb_id, MIC_ISO_EP_IN);
usb_g_set_intr_hander(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, NULL);
uac_mic_stream_close();
}
static u32 mic_as_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
{
const usb_dev usb_id = usb_device2id(usb_device);
u8 *tx_payload = usb_get_setup_buffer(usb_device);
u32 tx_len;
u32 bRequestType = setup->bRequestType & USB_TYPE_MASK;
u32 ret = 0;
switch (setup->bRequest) {
case USB_REQ_SET_INTERFACE:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
#if USB_ROOT2
if (!usb_root2_testing()) {
SetInterface_0_Lock = 1;
}
if (SetInterface_0_Lock == 0) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
if (setup->wValue == 1) {//alt 1
open_mic(usb_device);
} else if (setup->wValue == 0) { //alt 0
close_mic(usb_device);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
}
#else
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
if (setup->wValue == 1) {//alt 1
open_mic(usb_device);
} else if (setup->wValue == 0) { //alt 0
close_mic(usb_device);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
#endif
}
break;
case USB_REQ_GET_INTERFACE:
if (usb_root2_testing()) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
if (setup->wLength) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
tx_len = 1;
tx_payload[0] = 0x00;
usb_set_data_payload(usb_device, setup, tx_payload, tx_len);
}
}
break;
case USB_REQ_GET_STATUS:
if (usb_device->bDeviceStates == USB_DEFAULT) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
} else {
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
}
break;
default:
break;
}
return ret;
}
void spk_reset(struct usb_device_t *usb_device, u32 ift_num)
{
const usb_dev usb_id = usb_device2id(usb_device);
log_debug("%s", __func__);
u8 *ep_buffer = uac_info->spk_dma_buffer;
usb_g_ep_config(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, SPK_FRAME_LEN);
}
u32 uac_spk_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num)
{
int i = 0;
u8 *tptr = ptr;
u32 offset;
u32 frame_len;
log_debug("spkdc:%d\n", *cur_itf_num);
memcpy(tptr, (u8 *)uac_ac_standard_interface_desc, sizeof(uac_ac_standard_interface_desc));
tptr[2] = *cur_itf_num;
tptr += sizeof(uac_ac_standard_interface_desc);//0x09
memcpy(tptr, (u8 *)uac_spk_ac_interface, sizeof(uac_spk_ac_interface));
#if SPK_CHANNEL == 1
tptr[5]--;
#endif
tptr[8] = *cur_itf_num + 1;
tptr += sizeof(uac_spk_ac_interface);//0x09
memcpy(tptr, (u8 *)uac_spk_input_terminal_desc, sizeof(uac_spk_input_terminal_desc));
tptr += sizeof(uac_spk_input_terminal_desc);//0x0c
memcpy(tptr, (u8 *)uac_spk_feature_desc, sizeof(uac_spk_feature_desc));
tptr += sizeof(uac_spk_feature_desc);//0x0a
memcpy(tptr, (u8 *)uac_spk_output_terminal_desc, sizeof(uac_spk_output_terminal_desc));
tptr += sizeof(uac_spk_output_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_spk_as_interface_desc, sizeof(uac_spk_as_interface_desc));
tptr[2] = *cur_itf_num + 1;
tptr[9 + 2] = *cur_itf_num + 1;
frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000;
frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0);
offset = 9 + 9 + 7 + 11 + 4;
//MaxPacketSize of spk iso out
tptr[offset] = LOBYTE(frame_len);
tptr[offset + 1] = HIBYTE(frame_len);
tptr += sizeof(uac_spk_as_interface_desc);//0x09+0x09+0x07+0x0b+0x09+0x07
if (usb_set_interface_hander(usb_id, *cur_itf_num, audio_ac_itf_handler) != *cur_itf_num) {
ASSERT(0, "uac spk set interface_hander fail");
}
if (usb_set_reset_hander(usb_id, *cur_itf_num, spk_reset) != *cur_itf_num) {
}
(*cur_itf_num) ++;
if (usb_set_interface_hander(usb_id, *cur_itf_num, spk_as_itf_hander) != *cur_itf_num) {
ASSERT(0, "uac spk set interface_hander fail");
}
(*cur_itf_num) ++;
i = tptr - ptr;
return i;
}
void mic_reset(struct usb_device_t *usb_device, u32 ift_num)
{
const usb_dev usb_id = usb_device2id(usb_device);
log_error("%s", __func__);
#if USB_ROOT2
usb_disable_ep(usb_id, SPK_ISO_EP_OUT);
/* uac_release(usb_id); */
#else
u8 *ep_buffer = uac_info->mic_dma_buffer;
usb_g_ep_config(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, MIC_FRAME_LEN);
#endif
}
u32 uac_mic_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num)
{
int i = 0;
u8 *tptr = ptr;
u32 offset;
u32 frame_len;
log_debug("micdc:%d\n", *cur_itf_num);
memcpy(tptr, (u8 *)uac_ac_standard_interface_desc, sizeof(uac_ac_standard_interface_desc));
tptr[2] = *cur_itf_num;
tptr[8] = MIC_STR_INDEX;
tptr += sizeof(uac_ac_standard_interface_desc);//0x09
memcpy(tptr, uac_mic_ac_interface, sizeof(uac_mic_ac_interface));
#if MIC_CHANNEL == 2
tptr[5]++;
#endif
tptr[8] = *cur_itf_num + 1;
tptr += sizeof(uac_mic_ac_interface);
memcpy(tptr, (u8 *)uac_mic_input_terminal_desc, sizeof(uac_mic_input_terminal_desc));
tptr += sizeof(uac_mic_input_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_output_terminal_desc, sizeof(uac_mic_output_terminal_desc));
tptr += sizeof(uac_mic_output_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_selector_uint_desc, sizeof(uac_mic_selector_uint_desc));
tptr += sizeof(uac_mic_selector_uint_desc);
memcpy(tptr, (u8 *)uac_mic_feature_desc, sizeof(uac_mic_feature_desc));
tptr += sizeof(uac_mic_feature_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_as_interface_desc, sizeof(uac_mic_as_interface_desc));
tptr[2] = *cur_itf_num + 1;
tptr[9 + 2] = *cur_itf_num + 1;
#if MIC_SamplingFrequency > 1
u32 sr = 0;
//find the max sample rate
if (sr < MIC_AUDIO_RATE_1) {
sr = MIC_AUDIO_RATE_1;
}
if (sr < MIC_AUDIO_RATE_2) {
sr = MIC_AUDIO_RATE_2;
}
if (sr < MIC_AUDIO_RATE) {
sr = MIC_AUDIO_RATE;
}
if (sr < MIC_AUDIO_RATE_4) {
sr = MIC_AUDIO_RATE_4;
}
frame_len = sr * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000;
frame_len += (sr % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0);
#else
frame_len = MIC_AUDIO_RATE * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000;
frame_len += (MIC_AUDIO_RATE % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0);
#endif
offset = 9 + 9 + 7 + (8 + 3 * MIC_SamplingFrequency) + 4;
//MaxPacketSize of mic iso in
tptr[offset] = LOBYTE(frame_len);
tptr[offset + 1] = HIBYTE(frame_len);
tptr += sizeof(uac_mic_as_interface_desc);//0x09
if (usb_set_interface_hander(usb_id, *cur_itf_num, audio_ac_itf_handler) != *cur_itf_num) {
ASSERT(0, "uac mic set interface_hander fail");
}
if (usb_set_reset_hander(usb_id, *cur_itf_num, mic_reset) != *cur_itf_num) {
}
(*cur_itf_num) ++;
if (usb_set_interface_hander(usb_id, *cur_itf_num, mic_as_itf_hander) != *cur_itf_num) {
ASSERT(0, "uac mic set interface_hander fail");
}
(*cur_itf_num) ++;
i = tptr - ptr;
return i;
}
void audio_reset(struct usb_device_t *usb_device, u32 ift_num)
{
const usb_dev usb_id = usb_device2id(usb_device);
log_debug("%s", __func__);
#if USB_ROOT2
usb_disable_ep(usb_id, SPK_ISO_EP_OUT);
/* uac_release(usb_id); */
#else
u8 *ep_buffer;
ep_buffer = uac_info->spk_dma_buffer;
usb_g_ep_config(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, SPK_FRAME_LEN);
ep_buffer = uac_info->mic_dma_buffer;
usb_g_ep_config(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, MIC_FRAME_LEN);
#endif
}
u32 uac_audio_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num)
{
int i = 0;
u8 *tptr = ptr;
u32 offset;
u32 frame_len;
memcpy(tptr, (u8 *)uac_audio_interface_association, sizeof(uac_audio_interface_association));
tptr[2] = *cur_itf_num;
tptr[3] = 3;
tptr += sizeof(uac_audio_interface_association);//0x09
memcpy(tptr, (u8 *)uac_ac_standard_interface_desc, sizeof(uac_ac_standard_interface_desc));
tptr[2] = *cur_itf_num;
tptr += sizeof(uac_ac_standard_interface_desc);//0x09
memcpy(tptr, (u8 *)uac_audio_ac_interface, sizeof(uac_audio_ac_interface));
#if SPK_CHANNEL == 1
tptr[5]--;
#endif
#if MIC_CHANNEL == 2
tptr[5]++;
#endif
tptr[8] = *cur_itf_num + 1;
tptr[9] = *cur_itf_num + 2;
tptr += sizeof(uac_audio_ac_interface);//0x09
memcpy(tptr, (u8 *)uac_spk_input_terminal_desc, sizeof(uac_spk_input_terminal_desc));
tptr += sizeof(uac_spk_input_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_input_terminal_desc, sizeof(uac_mic_input_terminal_desc));
tptr += sizeof(uac_mic_input_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_spk_output_terminal_desc, sizeof(uac_spk_output_terminal_desc));
tptr += sizeof(uac_spk_output_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_output_terminal_desc, sizeof(uac_mic_output_terminal_desc));
tptr += sizeof(uac_mic_output_terminal_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_selector_uint_desc, sizeof(uac_mic_selector_uint_desc));
tptr += sizeof(uac_mic_selector_uint_desc);
memcpy(tptr, (u8 *)uac_spk_feature_desc, sizeof(uac_spk_feature_desc));
tptr += sizeof(uac_spk_feature_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_feature_desc, sizeof(uac_mic_feature_desc));
tptr += sizeof(uac_mic_feature_desc);//0x09
memcpy(tptr, (u8 *)uac_spk_as_interface_desc, sizeof(uac_spk_as_interface_desc));
tptr[2] = *cur_itf_num + 1;
tptr[9 + 2] = *cur_itf_num + 1;
frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000;
frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0);
offset = 9 + 9 + 7 + 11 + 4;
//MaxPacketSize of spk iso out
tptr[offset] = LOBYTE(frame_len);
tptr[offset + 1] = HIBYTE(frame_len);
tptr += sizeof(uac_spk_as_interface_desc);//0x09
memcpy(tptr, (u8 *)uac_mic_as_interface_desc, sizeof(uac_mic_as_interface_desc));
tptr[2] = *cur_itf_num + 2;
tptr[9 + 2] = *cur_itf_num + 2;
#if MIC_SamplingFrequency > 1
u32 sr = 0;
//find the max sample rate
if (sr < MIC_AUDIO_RATE_1) {
sr = MIC_AUDIO_RATE_1;
}
if (sr < MIC_AUDIO_RATE_2) {
sr = MIC_AUDIO_RATE_2;
}
if (sr < MIC_AUDIO_RATE) {
sr = MIC_AUDIO_RATE;
}
if (sr < MIC_AUDIO_RATE_4) {
sr = MIC_AUDIO_RATE_4;
}
frame_len = sr * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000;
frame_len += (sr % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0);
#else
frame_len = MIC_AUDIO_RATE * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000;
frame_len += (MIC_AUDIO_RATE % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0);
#endif
offset = 9 + 9 + 7 + (8 + 3 * MIC_SamplingFrequency) + 4;
//MaxPacketSize of mic iso in
tptr[offset] = LOBYTE(frame_len);
tptr[offset + 1] = HIBYTE(frame_len);
tptr += sizeof(uac_mic_as_interface_desc);//0x09
log_debug("audio control interface num:%d\n", *cur_itf_num);
if (usb_set_interface_hander(usb_id, *cur_itf_num, audio_ac_itf_handler) != *cur_itf_num) {
ASSERT(0, "uac spk set interface_hander fail");
}
if (usb_set_reset_hander(usb_id, *cur_itf_num, audio_reset) != *cur_itf_num) {
}
(*cur_itf_num) ++;
log_debug("speaker stream interface num:%d\n", *cur_itf_num);
if (usb_set_interface_hander(usb_id, *cur_itf_num, spk_as_itf_hander) != *cur_itf_num) {
ASSERT(0, "uac spk set interface_hander fail");
}
(*cur_itf_num) ++;
log_debug("mic stream interface num:%d\n", *cur_itf_num);
if (usb_set_interface_hander(usb_id, *cur_itf_num, mic_as_itf_hander) != *cur_itf_num) {
ASSERT(0, "uac mic set interface_hander fail");
}
(*cur_itf_num) ++;
i = tptr - ptr;
return i;
}
u32 uac_register(const usb_dev usb_id)
{
if (uac_info == NULL) {
#if USB_MALLOC_ENABLE
uac_info = (struct uac_info_t *)malloc(sizeof(struct uac_info_t));
if (uac_info == NULL) {
printf("uac_register err\n");
return -1;
}
#else
memset(&_uac_info, 0, sizeof(struct uac_info_t));
uac_info = &_uac_info;
#endif
uac_info->spk_dma_buffer = usb_alloc_ep_dmabuffer(usb_id, SPK_ISO_EP_OUT, SPK_FRAME_LEN);
uac_info->mic_dma_buffer = usb_alloc_ep_dmabuffer(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, MIC_FRAME_LEN);
}
uac_info->spk_def_vol = vol_convert(uac_get_spk_vol());
uac_info->spk_left_vol = uac_info->spk_def_vol;
uac_info->spk_right_vol = uac_info->spk_def_vol;
uac_info->spk_max_vol = vol_convert(100);
uac_info->spk_min_vol = vol_convert(0);
uac_info->spk_vol_res = 0x30;
uac_info->spk_mute = 0;
uac_info->mic_max_vol = vol_convert(100);
uac_info->mic_min_vol = vol_convert(0);
uac_info->mic_vol_res = 0x30;
uac_info->mic_def_vol = vol_convert(13 / 14.0 * 100);
uac_info->mic_vol = uac_info->mic_def_vol;
uac_info->mic_mute = 0;
return 0;
}
void uac_release(const usb_dev usb_id)
{
struct usb_device_t *usb_device = usb_id2device(usb_id);
if (uac_info) {
close_spk(usb_device);
close_mic(usb_device);
#if USB_MALLOC_ENABLE
free(uac_info);
#endif
uac_info = NULL;
}
}
#endif