diff options
Diffstat (limited to 'class/audio')
| -rw-r--r-- | class/audio/usb_audio.h | 40 | ||||
| -rw-r--r-- | class/audio/usbh_audio.c | 12 |
2 files changed, 32 insertions, 20 deletions
diff --git a/class/audio/usb_audio.h b/class/audio/usb_audio.h index 95609765..efb758ae 100644 --- a/class/audio/usb_audio.h +++ b/class/audio/usb_audio.h @@ -687,6 +687,10 @@ struct audio_cs_if_as_general_descriptor { #define AUDIO_SIZEOF_AS_GENERAL_DESC (7) +#ifndef CONFIG_USBHOST_AUDIO_MAX_SAMPLE_FREQ_NUM +#define CONFIG_USBHOST_AUDIO_MAX_SAMPLE_FREQ_NUM 8 +#endif + struct audio_cs_if_as_format_type_descriptor { uint8_t bLength; uint8_t bDescriptorType; @@ -696,7 +700,7 @@ struct audio_cs_if_as_format_type_descriptor { uint8_t bSubframeSize; uint8_t bBitResolution; uint8_t bSamFreqType; - uint8_t tSamFreq[3]; + uint8_t tSamFreq[3 * CONFIG_USBHOST_AUDIO_MAX_SAMPLE_FREQ_NUM]; } __PACKED; #define AUDIO_SIZEOF_FORMAT_TYPE_DESC(bSamFreqType) (8 + 3 * (bSamFreqType)) @@ -1344,19 +1348,27 @@ struct audio_v2_control_range3_param_block { #define AUDIO_SAMPLE_FREQ_4B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), \ (uint8_t)((frq >> 16)), (uint8_t)((frq >> 24)) -/* format 10.14 */ -#define AUDIO_FREQ_TO_FEEDBACK_FS(freq) ((freq << 10) / 1000) -#define AUDIO_FEEDBACK_TO_BUF_FS(buf, feedback) \ - buf[0] = ((feedback << 4) & 0xFFU); \ - buf[1] = (((feedback << 4) >> 8U) & 0xFFU); \ - buf[2] = (((feedback << 4) >> 16U) & 0xFFU) +/* FS feedback uses 10.14 samples per audio data service interval. */ +#define AUDIO_FREQ_TO_FEEDBACK_FS(freq) ((uint32_t)(((uint64_t)(freq) << 10U) / 1000U)) +#define AUDIO_FEEDBACK_TO_FREQ_FS(feedback) ((uint32_t)(((uint64_t)(feedback) * 1000U) >> 10U)) +#define AUDIO_FEEDBACK_TO_BUF_FS_INTERVAL(buf, feedback, interval) do { \ + uint32_t audio_feedback_value = (uint32_t)((uint64_t)(feedback) << ((interval) + 3U)); \ + (buf)[0] = (uint8_t)(audio_feedback_value); \ + (buf)[1] = (uint8_t)(audio_feedback_value >> 8U); \ + (buf)[2] = (uint8_t)(audio_feedback_value >> 16U); \ +} while (0) +#define AUDIO_FEEDBACK_TO_BUF_FS(buf, feedback) AUDIO_FEEDBACK_TO_BUF_FS_INTERVAL(buf, feedback, 1U) -/* format 16.16 */ -#define AUDIO_FREQ_TO_FEEDBACK_HS(freq) ((freq << 13) / 1000) -#define AUDIO_FEEDBACK_TO_BUF_HS(buf, feedback) \ - buf[0] = (((feedback & 0x00001FFFu) << 3) & 0xFFu); \ - buf[1] = ((((feedback & 0x00001FFFu) << 3) >> 8) & 0xFFu); \ - buf[2] = (((feedback & 0x01FFE000u) >> 13) & 0xFFu); \ - buf[3] = (((feedback & 0x01FFE000u) >> 21) & 0xFFu) +/* Keep HS feedback in 16.16 samples per microframe, then scale it by the audio data endpoint interval when serialized. */ +#define AUDIO_FREQ_TO_FEEDBACK_HS(freq) ((uint32_t)(((uint64_t)(freq) << 16U) / 8000U)) +#define AUDIO_FEEDBACK_TO_FREQ_HS(feedback) ((uint32_t)(((uint64_t)(feedback) * 8000U) >> 16U)) +#define AUDIO_FEEDBACK_TO_BUF_HS_INTERVAL(buf, feedback, interval) do { \ + uint32_t audio_feedback_value = (uint32_t)((uint64_t)(feedback) << ((interval) - 1U)); \ + (buf)[0] = (uint8_t)(audio_feedback_value); \ + (buf)[1] = (uint8_t)(audio_feedback_value >> 8U); \ + (buf)[2] = (uint8_t)(audio_feedback_value >> 16U); \ + (buf)[3] = (uint8_t)(audio_feedback_value >> 24U); \ +} while (0) +#define AUDIO_FEEDBACK_TO_BUF_HS(buf, feedback) AUDIO_FEEDBACK_TO_BUF_HS_INTERVAL(buf, feedback, 4U) #endif /* USB_AUDIO_H */ diff --git a/class/audio/usbh_audio.c b/class/audio/usbh_audio.c index ee0a3349..c401e83e 100644 --- a/class/audio/usbh_audio.c +++ b/class/audio/usbh_audio.c @@ -385,7 +385,7 @@ feature_found: setup->wLength = 2; ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); - if (ret < 0) { + if (ret < 2) { return ret; } @@ -400,7 +400,7 @@ feature_found: setup->wLength = 2; ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); - if (ret < 0) { + if (ret < 2) { return ret; } @@ -415,7 +415,7 @@ feature_found: setup->wLength = 2; ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); - if (ret < 0) { + if (ret < 2) { return ret; } memcpy(volume_max, g_audio_buf, 2); @@ -429,7 +429,7 @@ feature_found: setup->wLength = 2; ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); - if (ret < 0) { + if (ret < 2) { return ret; } memcpy(volume_res, g_audio_buf, 2); @@ -694,12 +694,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) case AUDIO_STREAMING_FORMAT_TYPE: { struct audio_cs_if_as_format_type_descriptor *desc = (struct audio_cs_if_as_format_type_descriptor *)p; - USB_ASSERT(desc->bSamFreqType == 1); + USB_ASSERT(desc->bSamFreqType <= CONFIG_USBHOST_AUDIO_MAX_SAMPLE_FREQ_NUM && desc->bSamFreqType > 0); USB_ASSERT(desc->bNrChannels <= CONFIG_USBHOST_AUDIO_MAX_CHANNELS); USB_ASSERT(cur_alt_setting < CONFIG_USBHOST_MAX_INTF_ALTSETTINGS); audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].bNrChannels = desc->bNrChannels; - memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_format[cur_alt_setting], desc, AUDIO_SIZEOF_FORMAT_TYPE_DESC(1)); + memcpy(&audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].as_format[cur_alt_setting], desc, AUDIO_SIZEOF_FORMAT_TYPE_DESC(desc->bSamFreqType)); } break; default: break; |
