/* 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