summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJerzy Kasenberg <[email protected]>2020-09-14 11:28:05 +0200
committerJerzy Kasenberg <[email protected]>2020-09-28 08:41:17 +0200
commit2ace98e943831784e6c9d81258babce2b7b3221c (patch)
tree4a0919fc7d514e1d45ae317c58010a910492668b /src
parent6b5233096978305f1d6a87ef83393ba50e8b0bd2 (diff)
audio_device: Update explicit feedback support
Feedback can be specified by the user code and will be sent at feedback endpoint specified interval.
Diffstat (limited to 'src')
-rw-r--r--src/class/audio/audio_device.c76
-rw-r--r--src/class/audio/audio_device.h5
-rw-r--r--src/device/usbd.h5
3 files changed, 68 insertions, 18 deletions
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index 181703f75..1b9cfe13a 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -121,10 +121,9 @@ typedef struct
#if CFG_TUD_AUDIO_EPSIZE_OUT
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_AUDIO_EPSIZE_OUT]; // Bigger makes no sense for isochronous EP's (but technically possible here)
- // TODO: required?
- //#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- // uint16_t fb_val; // Feedback value for asynchronous mode!
- //#endif
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+ uint32_t fb_val; // Feedback value for asynchronous mode (in 16.16 format).
+#endif
#endif
@@ -643,18 +642,51 @@ static bool audiod_tx_done_type_I_pcm_ff_cb(uint8_t rhport, audiod_interface_t*
// This function is called once a transmit of an feedback packet was successfully completed. Here, we get the next feedback value to be sent
#if CFG_TUD_AUDIO_EPSIZE_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
-static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio)
+static bool audio_fb_send(uint8_t rhport, audiod_interface_t *audio)
{
- (void) rhport;
- (void) audio;
+ uint8_t fb[4];
+ uint16_t len;
- // Here we need to return the feedback value
-#error RETURN YOUR FEEDBACK VALUE HERE!
+ if (audio->fb_val == 0)
+ {
+ len = 0;
+ return true;
+ }
+ else
+ {
+ len = 4;
+ // Here we need to return the feedback value
+ if (rhport == 0)
+ {
+ // For FS format is 10.14
+ fb[0] = (audio->fb_val >> 2) & 0xFF;
+ fb[1] = (audio->fb_val >> 10) & 0xFF;
+ fb[2] = (audio->fb_val >> 18) & 0xFF;
+ // 4th byte is needed to work correctly with MS Windows
+ fb[3] = 0;
+ }
+ else
+ {
+ // For HS format is 16.16
+ fb[0] = (audio->fb_val >> 0) & 0xFF;
+ fb[1] = (audio->fb_val >> 8) & 0xFF;
+ fb[2] = (audio->fb_val >> 16) & 0xFF;
+ fb[3] = (audio->fb_val >> 24) & 0xFF;
+ }
+ return usbd_edpt_xfer(rhport, audio->ep_fb, fb, len);
+ }
- if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
- return 0;
}
+//static uint16_t audio_fb_done_cb(uint8_t rhport, audiod_interface_t* audio)
+//{
+// (void) rhport;
+// (void) audio;
+//
+// if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
+// return 0;
+//}
+
#endif
// This function is called once a transmit of an interrupt control packet was successfully completed. Here, we get the remaining bytes to send
@@ -918,7 +950,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
}
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 0x10) // Check if usage is implicit data feedback
+ if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && ((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.usage == 1) // Check if usage is explicit data feedback
{
_audiod_itf[idxDriver].ep_fb = ep_addr;
@@ -1215,13 +1247,9 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
// Transmission of feedback EP finished
if (_audiod_itf[idxDriver].ep_fb == ep_addr)
{
- if (!audio_fb_done_cb(rhport, &_audiod_itf[idxDriver]))
- {
- // Load with ZLP
- return usbd_edpt_xfer(rhport, ep_addr, NULL, 0);
- }
+ if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
- return true;
+ return audio_fb_send(rhport, &_audiod_itf[idxDriver]);
}
#endif
#endif
@@ -1403,4 +1431,16 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *idxDriver)
return false;
}
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback)
+{
+ audiod_interface_t *audio = &_audiod_itf[0];
+
+ audio->fb_val = feedback;
+ TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_fb), true);
+
+ return audio_fb_send(rhport, audio);
+}
+#endif
+
#endif //TUSB_OPT_DEVICE_ENABLED && CFG_TUD_AUDIO
diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h
index 2f48955f2..f4029a84c 100644
--- a/src/class/audio/audio_device.h
+++ b/src/class/audio/audio_device.h
@@ -259,6 +259,11 @@ TU_ATTR_WEAK bool tud_audio_rx_done_cb(uint8_t rhport, uint8_t * buffer, uint16_
#if CFG_TUD_AUDIO_EPSIZE_OUT > 0 && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
TU_ATTR_WEAK bool tud_audio_fb_done_cb(uint8_t rhport);
+// User code should call this function with feedback value in 16.16 format for FS and HS.
+// Value will be corrected for FS to 10.14 format automatically.
+// (see Universal Serial Bus Specification Revision 2.0 5.12.4.2).
+// Feedback value will be sent at FB endpoint interval till it's changed.
+bool tud_audio_fb_set(uint8_t rhport, uint32_t feedback);
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
diff --git a/src/device/usbd.h b/src/device/usbd.h
index 43af25076..a450bca7c 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -377,6 +377,11 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \
TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay)
+/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */
+#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7
+#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \
+ TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval
+
// AUDIO simple descriptor (UAC2) for 1 microphone input
// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source