summaryrefslogtreecommitdiff
path: root/src/class
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2024-04-01 19:48:45 +0200
committerHiFiPhile <[email protected]>2024-04-01 20:02:35 +0200
commit05f9cab1916195ceb55d73efa56d226b2451f5d1 (patch)
tree7d438c933c16e4052a9d38f6843e17d8c9587dce /src/class
parenta1f01fcbe0fecb8d1783a105d7f22cba032dfced (diff)
UAC2: refactor interrupt endpoint support.
Diffstat (limited to 'src/class')
-rw-r--r--src/class/audio/audio.h25
-rw-r--r--src/class/audio/audio_device.c114
-rw-r--r--src/class/audio/audio_device.h51
3 files changed, 80 insertions, 110 deletions
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h
index 70d431282..d6f3e22e2 100644
--- a/src/class/audio/audio.h
+++ b/src/class/audio/audio.h
@@ -924,6 +924,31 @@ typedef struct TU_ATTR_PACKED {
} subrange[numSubRanges]; \
}
+// 6.1 Interrupt Data Message Format
+typedef struct TU_ATTR_PACKED
+{
+ uint8_t bInfo;
+ uint8_t bAttribute;
+ union
+ {
+ uint16_t wValue;
+ struct
+ {
+ uint8_t wValue_cn_or_mcn;
+ uint8_t wValue_cs;
+ };
+ };
+ union
+ {
+ uint16_t wIndex;
+ struct
+ {
+ uint8_t wIndex_ep_or_int;
+ uint8_t wIndex_entity_id;
+ };
+ };
+} audio_interrupt_data_t;
+
/** @} */
#ifdef __cplusplus
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index f4e7de0c8..93e995c56 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -301,8 +301,8 @@ typedef struct
#endif
-#if CFG_TUD_AUDIO_INT_EPSIZE_IN
- uint8_t ep_int; // Audio control interrupt EP.
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ uint8_t ep_int; // Audio control interrupt EP.
#endif
/*------------- From this point, data is not cleared by bus reset -------------*/
@@ -358,8 +358,8 @@ typedef struct
#endif
// Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74)
-#if CFG_TUD_AUDIO_INT_EPSIZE_IN
- CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[CFG_TUD_AUDIO_INT_EP_IN_SW_BUFFER_SIZE];
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6];
#endif
// Decoding parameters - parameters are set when alternate AS interface is set by host
@@ -826,26 +826,29 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx)
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-
// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_done_cb() is called in inform user
-uint16_t tud_audio_int_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len)
+bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t * data)
{
- TU_VERIFY(_audiod_fct[func_id].ep_int != 0);
-
TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL);
+ TU_VERIFY(_audiod_fct[func_id].ep_int != 0);
+
// We write directly into the EP's buffer - abort if previous transfer not complete
- TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int));
+ TU_VERIFY(usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int));
// Check length
- TU_VERIFY(tu_memcpy_s(_audiod_fct[func_id].ep_int_buf, CFG_TUD_AUDIO_INT_EP_IN_SW_BUFFER_SIZE, buffer, len)==0);
-
- // Schedule transmit
- TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, _audiod_fct[func_id].ep_int_buf, len));
+ if (tu_memcpy_s(_audiod_fct[func_id].ep_int_buf, sizeof(_audiod_fct[func_id].ep_int_buf), data, sizeof(audio_interrupt_data_t)) == 0)
+ {
+ // Schedule transmit
+ TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, _audiod_fct[func_id].ep_int_buf, sizeof(_audiod_fct[func_id].ep_int_buf)), 0);
+ } else
+ {
+ // Release endpoint since we don't make any transfer
+ usbd_edpt_release(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int);
+ }
return true;
}
-
#endif
// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission.
@@ -1091,48 +1094,6 @@ static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio)
}
#endif
-#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-static bool set_int_number(audiod_function_t *audio)
-{
-
- uint8_t const *p_desc = audio->p_desc;
- // Get pointer at end
- uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
-
-
- bool found = false;
- while (!found && p_desc < p_desc_end)
- {
- // For each interface/alternate
- if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE)
- {
- uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints;
- while (!found && foundEPs < nEps && p_desc < p_desc_end)
- {
- // For each endpoint
- if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
- {
- tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc;
- uint8_t const ep_addr = desc_ep->bEndpointAddress;
- // If endpoint is input-direction and interrupt-type
- if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.xfer == 0x03) // Check if usage is interrupt EP
- {
- // Store endpoint number and open endpoint
- audio->ep_int = ep_addr;
- TU_ASSERT(usbd_edpt_open(audio->rhport, desc_ep));
- found = true;
- }
- foundEPs += 1;
- }
- p_desc = tu_desc_next(p_desc);
- }
- }
- p_desc = tu_desc_next(p_desc);
- }
- return found;
-}
-#endif
-
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
@@ -1492,10 +1453,11 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
// Verify version is correct - this check can be omitted
TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2);
- // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted
- if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed
+ // Verify interrupt control EP is enabled if demanded by descriptor
+ TU_ASSERT(itf_desc->bNumEndpoints <= 1); // 0 or 1 EPs are allowed
+ if (itf_desc->bNumEndpoints == 1)
{
- TU_VERIFY(CFG_TUD_AUDIO_INT_EPSIZE_IN > 0);
+ TU_ASSERT(CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP);
}
// Alternate setting MUST be zero - this check can be omitted
@@ -1639,6 +1601,31 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
}
#endif // CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ {
+ uint8_t const *p_desc = _audiod_fct[i].p_desc;
+ uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
+ {
+ // For each endpoint
+ if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
+ {
+ tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ uint8_t const ep_addr = desc_ep->bEndpointAddress;
+ // If endpoint is input-direction and interrupt-type
+ if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
+ {
+ // Store endpoint number and open endpoint
+ _audiod_fct[i].ep_int = ep_addr;
+ TU_ASSERT(usbd_edpt_open(_audiod_fct[i].rhport, desc_ep));
+ }
+ }
+ p_desc = tu_desc_next(p_desc);
+ }
+ }
+#endif
+
break;
}
}
@@ -1649,10 +1636,6 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
// This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification)
uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; // - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor
-#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
- TU_ASSERT(set_int_number(&_audiod_fct[i]));
-#endif
-
return drv_len;
}
@@ -2169,7 +2152,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
{
audiod_function_t* audio = &_audiod_fct[func_id];
-#if CFG_TUD_AUDIO_INT_EPSIZE_IN
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
// Data transmission of control interrupt finished
if (audio->ep_int == ep_addr)
@@ -2181,7 +2164,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
// I assume here, that things above are handled by PHY
// All transmission is done - what remains to do is to inform job was completed
- if (tud_audio_int_done_cb) TU_VERIFY(tud_audio_int_done_cb(rhport, (uint16_t) xferred_bytes));
+ if (tud_audio_int_done_cb) tud_audio_int_done_cb(rhport);
+ return true;
}
#endif
diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h
index 70bbd7ff6..040a760d6 100644
--- a/src/class/audio/audio_device.h
+++ b/src/class/audio/audio_device.h
@@ -198,21 +198,7 @@
// Enable/disable interrupt EP (required for notifying host of control changes)
#ifndef CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0 // Feedback - 0 or 1
-#endif
-
-// Audio interrupt control EP size - disabled if 0
-#ifndef CFG_TUD_AUDIO_INT_EPSIZE_IN
-// Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74)
-#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-#define CFG_TUD_AUDIO_INT_EPSIZE_IN 6
-#else
-#define CFG_TUD_AUDIO_INT_EPSIZE_IN 0
-#endif
-#endif
-
-#ifndef CFG_TUD_AUDIO_INT_EP_IN_SW_BUFFER_SIZE
-#define CFG_TUD_AUDIO_INT_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74)
+#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0 // Feedback - 0 or 1
#endif
// Use software encoding/decoding
@@ -404,7 +390,7 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_i
#endif
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-uint16_t tud_audio_int_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len);
+bool tud_audio_int_n_write (uint8_t func_id, const audio_interrupt_data_t * data);
#endif
@@ -448,7 +434,7 @@ static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx);
// INT CTR API
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-static inline uint16_t tud_audio_int_write (uint8_t const* buffer, uint16_t len);
+static inline bool tud_audio_int_write (const audio_interrupt_data_t * data);
#endif
// Buffer control EP data and schedule a transmit
@@ -548,32 +534,7 @@ TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-// UAC2 ยง6.1 "interrupt data message"
-typedef struct TU_ATTR_PACKED
-{
- uint8_t bInfo;
- uint8_t bAttribute;
- union TU_ATTR_PACKED
- {
- uint16_t wValue;
- struct TU_ATTR_PACKED
- {
- uint8_t wValue_cn_or_mcn;
- uint8_t wValue_cs;
- };
- };
- union TU_ATTR_PACKED
- {
- uint16_t wIndex;
- struct TU_ATTR_PACKED
- {
- uint8_t wIndex_ep_or_int;
- uint8_t wIndex_entity_id;
- };
- };
-} audio_status_update_t;
-
-TU_ATTR_WEAK bool tud_audio_int_done_cb(uint8_t rhport, uint16_t n_bytes_copied);
+TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport);
#endif
// Invoked when audio set interface request received
@@ -705,9 +666,9 @@ static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx)
#endif
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
-static inline uint16_t tud_audio_int_write(uint8_t const* buffer, uint16_t len)
+static inline bool tud_audio_int_write(const audio_interrupt_data_t * data)
{
- return tud_audio_int_n_write(0, buffer, len);
+ return tud_audio_int_n_write(0, data);
}
#endif