summaryrefslogtreecommitdiff
path: root/class/audio
diff options
context:
space:
mode:
Diffstat (limited to 'class/audio')
-rw-r--r--class/audio/usb_audio.h40
-rw-r--r--class/audio/usbh_audio.c12
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;