refactor audio device class

This commit is contained in:
sakimisu
2023-06-21 20:43:35 +08:00
parent 48efbfe521
commit 1c7110bd86
8 changed files with 433 additions and 474 deletions

View File

@@ -81,14 +81,6 @@
#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
#endif
#ifndef CONFIG_USBDEV_AUDIO_VERSION
#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
#endif
#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
#endif
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 128
#endif

View File

@@ -6,109 +6,71 @@
#include "usbd_core.h"
#include "usbd_audio.h"
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
struct usbd_audio_volume_info {
uint16_t vol_min;
uint16_t vol_max;
uint16_t vol_res;
uint16_t vol_current;
struct audio_entity_param {
uint32_t wCur;
uint32_t wMin;
uint32_t wMax;
uint32_t wRes;
};
struct usbd_audio_attribute_control {
struct usbd_audio_volume_info volume[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
uint8_t automatic_gain[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
};
#else
struct audio_v2_control_range2_param_block_default {
uint16_t wNumSubRanges;
struct
{
uint16_t wMin;
uint16_t wMax;
uint16_t wRes;
} subrange[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
} __PACKED;
struct usbd_audio_priv {
struct audio_entity_info *table;
uint8_t num;
uint16_t uac_version;
} g_usbd_audio;
struct usbd_audio_attribute_control {
uint32_t volume_bCUR;
uint32_t mute_bCUR;
struct audio_v2_control_range2_param_block_default volume;
uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
};
#endif
struct audio_entity_info {
usb_slist_t list;
uint8_t bDescriptorSubtype;
uint8_t bEntityId;
void *priv[2];
};
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
uint8_t control_selector;
uint32_t sampling_freq = 0;
uint8_t pitch_enable;
uint8_t ep;
if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
control_selector = HI_BYTE(setup->wValue);
ep = LO_BYTE(setup->wIndex);
control_selector = HI_BYTE(setup->wValue);
ep = LO_BYTE(setup->wIndex);
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
switch (control_selector) {
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
memcpy((uint8_t *)&sampling_freq, *data, *len);
USB_LOG_DBG("Set ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(0, ep, sampling_freq);
break;
case AUDIO_EP_CONTROL_PITCH:
pitch_enable = (*data)[0];
usbd_audio_set_pitch(ep, pitch_enable);
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
case AUDIO_REQUEST_GET_CUR:
sampling_freq = 16000;
memcpy(*data, &sampling_freq, 4);
*len = 4;
USB_LOG_DBG("Get ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
} else {
return -1;
switch (control_selector) {
case AUDIO_EP_CONTROL_SAMPLING_FEQ:
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy((uint8_t *)&sampling_freq, *data, *len);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(ep, sampling_freq);
break;
case AUDIO_REQUEST_GET_CUR:
case AUDIO_REQUEST_GET_MIN:
case AUDIO_REQUEST_GET_MAX:
case AUDIO_REQUEST_GET_RES:
sampling_freq = usbd_audio_get_sampling_freq(ep);
memcpy(*data, &sampling_freq, 3);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 3;
break;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
return 0;
}
#endif
static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
USB_LOG_DBG("AUDIO Class request: "
USB_LOG_DBG("Audio Class request: "
"bRequest 0x%02x\r\n",
setup->bRequest);
struct audio_entity_info *current_entity_info = NULL;
struct usbd_audio_attribute_control *current_feature_control = NULL;
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
uint32_t *sampling_freq;
#endif
usb_slist_t *i;
uint8_t entity_id;
uint8_t ep;
uint8_t subtype = 0x01;
uint8_t control_selector;
uint8_t ch;
uint8_t mute;
uint16_t volume;
int volume_db;
uint32_t sampling_freq = 0;
const char *mute_string[2] = { "off", "on" };
entity_id = HI_BYTE(setup->wIndex);
@@ -116,211 +78,189 @@ static int audio_class_interface_request_handler(struct usb_setup_packet *setup,
ch = LO_BYTE(setup->wValue);
ARG_UNUSED(mute_string);
if (ch > (CONFIG_USBDEV_AUDIO_MAX_CHANNEL - 1)) {
return -2;
}
usb_slist_for_each(i, &usbd_audio_entity_info_head)
{
struct audio_entity_info *tmp_entity_info = usb_slist_entry(i, struct audio_entity_info, list);
if (tmp_entity_info->bEntityId == entity_id) {
current_entity_info = tmp_entity_info;
for (uint8_t i = 0; i < g_usbd_audio.num; i++) {
if (g_usbd_audio.table[i].bEntityId == entity_id) {
subtype = g_usbd_audio.table[i].bDescriptorSubtype;
ep = g_usbd_audio.table[i].ep;
break;
}
}
if (current_entity_info == NULL) {
return -2;
}
current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
sampling_freq = (uint32_t *)current_entity_info->priv[1];
#endif
if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
float volume2db = 0.0;
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
current_feature_control->mute[ch] = mute;
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
usbd_audio_set_mute(entity_id, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = current_feature_control->mute[ch];
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
break;
case AUDIO_FU_CONTROL_VOLUME:
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
current_feature_control->volume[ch].vol_current = volume;
if (volume < 0x8000) {
volume2db = 0.00390625 * volume;
} else if (volume > 0x8000) {
volume2db = -0.00390625 * (0xffff - volume + 1);
}
USB_LOG_DBG("Set UnitId:%d ch[%d] %0.4f dB\r\n", entity_id, ch, volume2db);
usbd_audio_set_volume(entity_id, ch, volume2db);
break;
case AUDIO_REQUEST_GET_CUR:
memcpy(*data, &current_feature_control->volume[ch].vol_current, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
memcpy(*data, &current_feature_control->volume[ch].vol_min, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
memcpy(*data, &current_feature_control->volume[ch].vol_max, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
memcpy(*data, &current_feature_control->volume[ch].vol_res, 2);
*len = 2;
break;
case AUDIO_REQUEST_SET_RES:
memcpy(&current_feature_control->volume[ch].vol_res, *data, 2);
*len = 2;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
#else
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = current_feature_control->mute_bCUR;
*len = 1;
} else {
mute = (*data)[0];
current_feature_control->mute_bCUR = mute;
USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
usbd_audio_set_mute(entity_id, ch, mute);
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = current_feature_control->volume_bCUR & 0XFF;
(*data)[1] = (current_feature_control->volume_bCUR >> 8) & 0xff;
*len = 2;
} else {
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
current_feature_control->volume_bCUR = volume;
USB_LOG_DBG("Set UnitId:%d ch[%d] %d dB\r\n", entity_id, ch, volume);
usbd_audio_set_volume(entity_id, ch, volume);
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
case AUDIO_REQUEST_RANGE:
switch (control_selector) {
case AUDIO_FU_CONTROL_VOLUME:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = current_feature_control->volume.wNumSubRanges;
*((uint16_t *)(*data + 2)) = current_feature_control->volume.subrange[ch].wMin;
*((uint16_t *)(*data + 4)) = current_feature_control->volume.subrange[ch].wMax;
*((uint16_t *)(*data + 6)) = current_feature_control->volume.subrange[ch].wRes;
*len = 8;
} else {
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
#endif
}
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
else if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
memcpy(*data, &sampling_freq[ch], sizeof(uint32_t));
USB_LOG_DBG("Get ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
*len = 4;
} else {
memcpy(&sampling_freq[ch], *data, setup->wLength);
USB_LOG_DBG("Set ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
usbd_audio_set_sampling_freq(entity_id, ch, sampling_freq[ch]);
}
break;
case AUDIO_CS_CONTROL_CLOCK_VALID:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = 1;
*len = 1;
} else {
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
case AUDIO_REQUEST_RANGE:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(entity_id, &sampling_freq_table);
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
memcpy(*data, sampling_freq_table, (12 * num + 2));
*len = (12 * num + 2);
USB_LOG_DBG("Get sampling_freq_table entity_id:%d ch[%d] addr:%x\r\n", entity_id, ch, (uint32_t)sampling_freq_table);
} else {
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1;
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
return -1;
}
}
#endif
else {
if (subtype == 0x01) {
USB_LOG_ERR("Do not find subtype for 0x%02x\r\n", entity_id);
return -1;
}
USB_LOG_DBG("Audio entity_id:%02x, subtype:%02x, cs:%02x\r\n", entity_id, subtype, control_selector);
switch (subtype) {
case AUDIO_CONTROL_FEATURE_UNIT:
switch (control_selector) {
case AUDIO_FU_CONTROL_MUTE:
if (g_usbd_audio.uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
break;
case AUDIO_REQUEST_GET_CUR:
(*data)[0] = usbd_audio_get_mute(ep, ch);
*len = 1;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
} else {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = usbd_audio_get_mute(ep, ch);
*len = 1;
} else {
mute = (*data)[0];
usbd_audio_set_mute(ep, ch, mute);
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
}
break;
case AUDIO_FU_CONTROL_VOLUME:
if (g_usbd_audio.uac_version < 0x0200) {
switch (setup->bRequest) {
case AUDIO_REQUEST_SET_CUR:
memcpy(&volume, *data, *len);
if (volume < 0x8000) {
volume_db = volume / 256;
} else if (volume > 0x8000) {
volume_db = (0xffff - volume + 1) / -256;
}
volume_db += 128; /* 0 ~ 255 */
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
break;
case AUDIO_REQUEST_GET_CUR:
volume_db = usbd_audio_get_volume(ep, ch);
volume_db -= 128;
if (volume_db >= 0) {
volume = volume_db * 256;
} else {
volume = volume_db * 256 + 0xffff + 1;
}
memcpy(*data, &volume, 2);
*len = 2;
break;
case AUDIO_REQUEST_GET_MIN:
(*data)[0] = 0x00; /* -2560/256 dB */
(*data)[1] = 0xdb;
*len = 2;
break;
case AUDIO_REQUEST_GET_MAX:
(*data)[0] = 0x00; /* 0 dB */
(*data)[1] = 0x00;
*len = 2;
break;
case AUDIO_REQUEST_GET_RES:
(*data)[0] = 0x00; /* -256/256 dB */
(*data)[1] = 0x01;
*len = 2;
break;
default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
} else {
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
volume_db = usbd_audio_get_volume(ep, ch);
volume = volume_db;
memcpy(*data, &volume, 2);
*len = 2;
} else {
memcpy(&volume, *data, *len);
volume_db = volume;
USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume);
usbd_audio_set_volume(ep, ch, volume_db);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
*((uint16_t *)(*data + 0)) = 1;
*((uint16_t *)(*data + 2)) = 0;
*((uint16_t *)(*data + 4)) = 100;
*((uint16_t *)(*data + 6)) = 1;
*len = 8;
} else {
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
}
break;
default:
USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1;
}
break;
case AUDIO_CONTROL_CLOCK_SOURCE:
switch (control_selector) {
case AUDIO_CS_CONTROL_SAM_FREQ:
switch (setup->bRequest) {
case AUDIO_REQUEST_CUR:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
sampling_freq = usbd_audio_get_sampling_freq(ep);
memcpy(*data, &sampling_freq, 4);
USB_LOG_DBG("Get ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
*len = 4;
} else {
memcpy(&sampling_freq, *data, setup->wLength);
USB_LOG_DBG("Set ep:0x%02x %d Hz\r\n", ep, (int)sampling_freq);
usbd_audio_set_sampling_freq(ep, sampling_freq);
}
break;
case AUDIO_REQUEST_RANGE:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
uint8_t *sampling_freq_table = NULL;
uint16_t num;
usbd_audio_get_sampling_freq_table(ep, &sampling_freq_table);
num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
memcpy(*data, sampling_freq_table, (12 * num + 2));
*len = (12 * num + 2);
} else {
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1;
}
break;
case AUDIO_CS_CONTROL_CLOCK_VALID:
if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
(*data)[0] = 1;
*len = 1;
} else {
return -1;
}
break;
default:
//USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1;
}
break;
default:
break;
}
return 0;
}
@@ -333,7 +273,7 @@ static void audio_notify_handler(uint8_t event, void *arg)
case USBD_EVENT_SET_INTERFACE: {
struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
if (intf->bAlternateSetting == 1) {
if (intf->bAlternateSetting) {
usbd_audio_open(intf->bInterfaceNumber);
} else {
usbd_audio_close(intf->bInterfaceNumber);
@@ -347,86 +287,57 @@ static void audio_notify_handler(uint8_t event, void *arg)
}
}
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf)
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num)
{
intf->class_interface_handler = audio_class_interface_request_handler;
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
#else
intf->class_endpoint_handler = NULL;
#endif
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
if (uac_version < 0x0200) {
intf->class_interface_handler = audio_class_interface_request_handler;
intf->class_endpoint_handler = audio_class_endpoint_request_handler;
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
} else {
intf->class_interface_handler = audio_class_interface_request_handler;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = audio_notify_handler;
}
g_usbd_audio.uac_version = uac_version;
g_usbd_audio.table = table;
g_usbd_audio.num = num;
return intf;
}
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype)
{
struct audio_entity_info *entity_info = usb_malloc(sizeof(struct audio_entity_info));
memset(entity_info, 0, sizeof(struct audio_entity_info));
entity_info->bEntityId = entity_id;
entity_info->bDescriptorSubtype = bDescriptorSubtype;
if (bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
control->volume[ch].vol_min = 0xdb00;
control->volume[ch].vol_max = 0x0000;
control->volume[ch].vol_res = 0x0100;
control->volume[ch].vol_current = 0xf600;
control->mute[ch] = 0;
control->automatic_gain[ch] = 0;
}
#else
struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
memset(control, 0, sizeof(struct usbd_audio_attribute_control));
for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
control->volume.wNumSubRanges = 1;
control->volume.subrange[ch].wMin = 0;
control->volume.subrange[ch].wMax = 100;
control->volume.subrange[ch].wRes = 1;
control->mute[ch] = 0;
control->volume_bCUR = 0;
control->mute_bCUR = 0;
}
#endif
entity_info->priv[0] = control;
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
sampling_freq[ch] = 16000;
}
entity_info->priv[1] = sampling_freq;
#else
entity_info->priv[1] = NULL;
#endif
}
usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
}
__WEAK void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB)
__WEAK void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume)
{
}
__WEAK void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable)
__WEAK int usbd_audio_get_volume(uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute)
{
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
__WEAK bool usbd_audio_get_mute(uint8_t ep, uint8_t ch)
{
return 0;
}
__WEAK void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
{
}
#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
__WEAK uint32_t usbd_audio_get_sampling_freq(uint8_t ep)
{
return 0;
}
__WEAK void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
}
#endif
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
{
}

View File

@@ -12,17 +12,29 @@
extern "C" {
#endif
struct audio_entity_info {
uint8_t bDescriptorSubtype;
uint8_t bEntityId;
uint8_t ep;
};
/* Init audio interface driver */
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf);
struct usbd_interface *usbd_audio_init_intf(struct usbd_interface *intf,
uint16_t uac_version,
struct audio_entity_info *table,
uint8_t num);
void usbd_audio_open(uint8_t intf);
void usbd_audio_close(uint8_t intf);
void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype);
void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB);
void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable);
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq);
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table);
void usbd_audio_set_pitch(uint8_t ep, bool enable);
void usbd_audio_set_volume(uint8_t ep, uint8_t ch, int volume);
int usbd_audio_get_volume(uint8_t ep, uint8_t ch);
void usbd_audio_set_mute(uint8_t ep, uint8_t ch, bool mute);
bool usbd_audio_get_mute(uint8_t ep, uint8_t ch);
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq);
uint32_t usbd_audio_get_sampling_freq(uint8_t ep);
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table);
#ifdef __cplusplus
}

View File

@@ -14,6 +14,8 @@
#define AUDIO_IN_EP 0x81
#define AUDIO_IN_FU_ID 0x02
/* AUDIO Class Config */
#define AUDIO_FREQ 16000U
@@ -61,13 +63,13 @@
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v1_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, 0x00, 0x01),
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, INPUT_CTRL),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_IN_FU_ID, 0x01, 0x01, INPUT_CTRL),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, AUDIO_IN_FU_ID),
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
///////////////////////////////////////
/// string0 descriptor
@@ -176,14 +178,18 @@ static struct usbd_endpoint audio_in_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void audio_init()
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_endpoint(&audio_in_ep);
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
};
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
void audio_v1_init(uint8_t busid)
{
usbd_desc_register(audio_v1_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(&audio_in_ep);
usbd_initialize();
}

View File

@@ -15,6 +15,9 @@
#define AUDIO_IN_EP 0x81
#define AUDIO_OUT_EP 0x02
#define AUDIO_IN_FU_ID 0x02
#define AUDIO_OUT_FU_ID 0x05
/* AUDIO Class Config */
#define AUDIO_SPEAKER_FREQ 16000U
#define AUDIO_SPEAKER_FRAME_SIZE_BYTE 2u
@@ -49,7 +52,7 @@
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v1_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
@@ -59,9 +62,9 @@ const uint8_t audio_descriptor[] = {
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00, 0x00),
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,\
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_SPEAKER_FRAME_SIZE_BYTE, AUDIO_SPEAKER_RESOLUTION_BIT, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_SPEAKER_FREQ)),
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,\
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_MIC_FRAME_SIZE_BYTE, AUDIO_MIC_RESOLUTION_BIT, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET,
EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_MIC_FREQ)),
///////////////////////////////////////
/// string0 descriptor
@@ -137,8 +140,8 @@ const uint8_t audio_descriptor[] = {
0x00
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
@@ -148,7 +151,7 @@ void usbd_audio_open(uint8_t intf)
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
printf("OPEN1\r\n");
} else {
tx_flag = 1;
@@ -175,7 +178,7 @@ void usbd_configure_done_callback(void)
void usbd_audio_out_callback(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_in_callback(uint8_t ep, uint32_t nbytes)
@@ -198,32 +201,36 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void audio_init()
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
{ .bEntityId = AUDIO_OUT_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_OUT_EP },
};
void audio_v1_init(void)
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_interface(usbd_audio_init_intf(&intf2));
usbd_desc_register(audio_v1_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0100, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0100, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0100, audio_entity_table, 2));
usbd_add_endpoint(&audio_in_ep);
usbd_add_endpoint(&audio_out_ep);
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
usbd_audio_add_entity(0x05, AUDIO_CONTROL_FEATURE_UNIT);
usbd_initialize();
}
void audio_test()
void audio_v1_test(void)
{
while (1) {
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;
}
if (tx_flag) {
memset(write_buffer, 'a', AUDIO_IN_PACKET);
ep_tx_busy_flag = true;
usbd_ep_start_write(AUDIO_IN_EP, write_buffer, AUDIO_IN_PACKET);
while (ep_tx_busy_flag) {
if (tx_flag == false) {
break;
}
}
}

View File

@@ -14,6 +14,9 @@
#define AUDIO_IN_EP 0x81
#define AUDIO_IN_CLOCK_ID 0x01
#define AUDIO_IN_FU_ID 0x03
#define AUDIO_FREQ 48000
#define HALF_WORD_BYTES 2 //2 half word (one channel)
#define SAMPLE_BITS 16 //16 bit per channel
@@ -50,7 +53,6 @@
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
@@ -65,7 +67,7 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
@@ -168,9 +170,9 @@ void usbd_audio_close(uint8_t intf)
tx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
if (entity_id == 0x01) {
if (ep == AUDIO_IN_EP) {
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
}
}
@@ -192,23 +194,27 @@ static struct usbd_endpoint audio_in_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void audio_init()
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_endpoint(&audio_in_ep);
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_IN_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_IN_EP },
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
};
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
void audio_v2_init(void)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(&audio_in_ep);
usbd_initialize();
}
void audio_test()
void audio_v2_test(void)
{
while (1) {
if (tx_flag) {
}
if (tx_flag) {
}
}

View File

@@ -15,6 +15,11 @@
#define AUDIO_OUT_EP 0x02
#define AUDIO_IN_EP 0x81
#define AUDIO_OUT_CLOCK_ID 0x01
#define AUDIO_OUT_FU_ID 0x03
#define AUDIO_IN_CLOCK_ID 0x05
#define AUDIO_IN_FU_ID 0x07
#define AUDIO_FREQ 48000
#define HALF_WORD_BYTES 2 //2 half word (one channel)
#define SAMPLE_BITS 16 //16 bit per channel
@@ -49,36 +54,34 @@
#define INPUT_CH_ENABLE 0x000000ff
#endif
#define OUT_CHANNEL_NUM 2
#if OUT_CHANNEL_NUM == 1
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000000
#elif OUT_CHANNEL_NUM == 2
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000003
#elif OUT_CHANNEL_NUM == 3
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000007
#elif OUT_CHANNEL_NUM == 4
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000000f
#elif OUT_CHANNEL_NUM == 5
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000001f
#elif OUT_CHANNEL_NUM == 6
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000003F
#elif OUT_CHANNEL_NUM == 7
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000007f
#elif OUT_CHANNEL_NUM == 8
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x000000ff
#endif
/* AudioFreq * DataSize (2 bytes) * NumChannels */
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
@@ -106,7 +109,7 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
uint8_t audio_descriptor[] = {
uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
@@ -220,7 +223,8 @@ static const uint8_t mic_default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_4B(0x00)
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
@@ -230,7 +234,7 @@ void usbd_audio_open(uint8_t intf)
if (intf == 1) {
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN1\r\n");
} else {
tx_flag = 1;
@@ -248,27 +252,27 @@ void usbd_audio_close(uint8_t intf)
}
}
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
if (entity_id == 0x01) {
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)speaker_default_sampling_freq_table;
} else if (entity_id == 0x05) {
} else if (ep == AUDIO_IN_EP) {
*sampling_freq_table = (uint8_t *)mic_default_sampling_freq_table;
} else {
}
}
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
void usbd_audio_set_sampling_freq(uint8_t ep, uint32_t sampling_freq)
{
uint16_t packet_size = 0;
if (entity_id == 1) {
if (ep == AUDIO_OUT_EP) {
packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
} else if (entity_id == 5) {
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
} else if (ep == AUDIO_IN_EP) {
packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
audio_v2_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
}
}
@@ -278,6 +282,8 @@ void usbd_configure_done_callback(void)
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
void usbd_audio_iso_in_callback(uint8_t ep, uint32_t nbytes)
@@ -298,27 +304,37 @@ struct usbd_interface intf0;
struct usbd_interface intf1;
struct usbd_interface intf2;
void audio_init()
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_OUT_EP },
{ .bEntityId = AUDIO_OUT_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_OUT_EP },
{ .bEntityId = AUDIO_IN_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_IN_EP },
{ .bEntityId = AUDIO_IN_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_IN_EP },
};
void audio_v2_init(void)
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_interface(usbd_audio_init_intf(&intf2));
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 4));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 4));
usbd_add_interface(usbd_audio_init_intf(&intf2, 0x0200, audio_entity_table, 4));
usbd_add_endpoint(&audio_in_ep);
usbd_add_endpoint(&audio_out_ep);
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
usbd_audio_add_entity(0x05, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x07, AUDIO_CONTROL_FEATURE_UNIT);
usbd_initialize();
}
void audio_test()
void audio_v2_test(void)
{
while (1) {
if (tx_flag) {
}
if (tx_flag) {
}
if (rx_flag) {
}
}

View File

@@ -14,6 +14,9 @@
#define AUDIO_OUT_EP 0x01
#define AUDIO_OUT_CLOCK_ID 0x01
#define AUDIO_OUT_FU_ID 0x03
#define AUDIO_FREQ 48000
#define HALF_WORD_BYTES 2 //2 half word (one channel)
#define SAMPLE_BITS 16 //16 bit per channel
@@ -23,28 +26,28 @@
#define OUT_CHANNEL_NUM 2
#if OUT_CHANNEL_NUM == 1
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000000
#elif OUT_CHANNEL_NUM == 2
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000003
#elif OUT_CHANNEL_NUM == 3
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x00000007
#elif OUT_CHANNEL_NUM == 4
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000000f
#elif OUT_CHANNEL_NUM == 5
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000001f
#elif OUT_CHANNEL_NUM == 6
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000003F
#elif OUT_CHANNEL_NUM == 7
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x0000007f
#elif OUT_CHANNEL_NUM == 8
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
#define OUTPUT_CH_ENABLE 0x000000ff
#endif
@@ -64,13 +67,13 @@
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
const uint8_t audio_descriptor[] = {
const uint8_t audio_v2_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(AUDIO_OUT_CLOCK_ID, 0x03, 0x03),
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x02, OUTPUT_CTRL),
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, 0x09, AUDIO_OUT_PACKET, EP_INTERVAL),
///////////////////////////////////////
@@ -166,7 +169,7 @@ static const uint8_t default_sampling_freq_table[] = {
AUDIO_SAMPLE_FREQ_4B(0x00),
};
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t out_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
volatile bool rx_flag = 0;
@@ -174,7 +177,7 @@ void usbd_audio_open(uint8_t intf)
{
rx_flag = 1;
/* setup first out ep read transfer */
usbd_ep_start_read(AUDIO_OUT_EP, out_buffer, AUDIO_OUT_PACKET);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
USB_LOG_RAW("OPEN\r\n");
}
void usbd_audio_close(uint8_t intf)
@@ -183,9 +186,9 @@ void usbd_audio_close(uint8_t intf)
rx_flag = 0;
}
void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
void usbd_audio_get_sampling_freq_table(uint8_t ep, uint8_t **sampling_freq_table)
{
if (entity_id == 0x01) {
if (ep == AUDIO_OUT_EP) {
*sampling_freq_table = (uint8_t *)default_sampling_freq_table;
}
}
@@ -196,6 +199,8 @@ void usbd_configure_done_callback(void)
void usbd_audio_iso_out_callback(uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", nbytes);
usbd_ep_start_read(AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
}
static struct usbd_endpoint audio_out_ep = {
@@ -206,23 +211,27 @@ static struct usbd_endpoint audio_out_ep = {
struct usbd_interface intf0;
struct usbd_interface intf1;
void audio_init()
{
usbd_desc_register(audio_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0));
usbd_add_interface(usbd_audio_init_intf(&intf1));
usbd_add_endpoint(&audio_out_ep);
struct audio_entity_info audio_entity_table[] = {
{ .bEntityId = AUDIO_OUT_CLOCK_ID,
.bDescriptorSubtype = AUDIO_CONTROL_CLOCK_SOURCE,
.ep = AUDIO_OUT_EP },
{ .bEntityId = AUDIO_OUT_FU_ID,
.bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
.ep = AUDIO_OUT_EP },
};
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
void audio_v2_init(void)
{
usbd_desc_register(audio_v2_descriptor);
usbd_add_interface(usbd_audio_init_intf(&intf0, 0x0200, audio_entity_table, 2));
usbd_add_interface(usbd_audio_init_intf(&intf1, 0x0200, audio_entity_table, 2));
usbd_add_endpoint(&audio_out_ep);
usbd_initialize();
}
void audio_test()
void audio_v2_test(void)
{
while (1) {
if (rx_flag) {
}
if (rx_flag) {
}
}