Merge branch 'master' into MCX

This commit is contained in:
hathach 2024-04-05 17:59:38 +07:00
commit 1c5abc835f
No known key found for this signature in database
GPG Key ID: 26FAB84F615C3C52
17 changed files with 251 additions and 137 deletions

View File

@ -28,29 +28,31 @@ jobs:
issueOrPrNumber = context.payload.pull_request.number;
}
// Check for Adafruit membership
const adafruitResponse = await github.rest.orgs.checkMembershipForUser({
org: 'adafruit',
username: username
});
if (adafruitResponse.status === 204) {
console.log('Adafruit Member');
label = 'Prio Urgent';
} else {
// Check if the user is a contributor
const collaboratorResponse = await github.rest.repos.checkCollaborator({
owner: context.repo.owner,
repo: context.repo.repo,
try {
// Check for Adafruit membership
const adafruitResponse = await github.rest.orgs.checkMembershipForUser({
org: 'adafruit',
username: username
});
if (collaboratorResponse.status === 204) {
console.log('Contributor');
label = 'Prio Higher';
if (adafruitResponse.status === 204) {
console.log('Adafruit Member');
label = 'Prio Urgent';
} else {
console.log('Not a contributor or Adafruit member');
// If not a Adafruit member, check if the user is a contributor
const collaboratorResponse = await github.rest.repos.checkCollaborator({
owner: context.repo.owner,
repo: context.repo.repo,
username: username
});
if (collaboratorResponse.status === 204) {
console.log('Contributor');
label = 'Prio Higher';
}
}
} catch (error) {
console.log(`Error processing user ${username}: ${error.message}`);
}
if (label !== '') {

View File

@ -113,6 +113,7 @@ CFLAGS += -DBOARD_$(BOARD_UPPER)
ifeq (${MAX3421_HOST},1)
SRC_C += src/portable/analog/max3421/hcd_max3421.c
CFLAGS += -DCFG_TUH_MAX3421=1
CMAKE_DEFSYM += -DMAX3421_HOST=1
endif
# Log level is mapped to TUSB DEBUG option

View File

@ -96,6 +96,7 @@ uint8_t current_resolution;
void led_blinking_task(void);
void audio_task(void);
void audio_control_task(void);
/*------------- MAIN -------------*/
int main(void)
@ -115,6 +116,7 @@ int main(void)
{
tud_task(); // TinyUSB device task
audio_task();
audio_control_task();
led_blinking_task();
}
}
@ -428,6 +430,45 @@ void audio_task(void)
}
}
void audio_control_task(void)
{
// Press on-board button to control volume
// Open host volume control, volume should switch between 10% and 100%
// Poll every 50ms
const uint32_t interval_ms = 50;
static uint32_t start_ms = 0;
static uint32_t btn_prev = 0;
if ( board_millis() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;
uint32_t btn = board_button_read();
if (!btn_prev && btn)
{
// Adjust volume between 0dB (100%) and -30dB (10%)
for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++)
{
volume[i] = volume[i] == 0 ? -VOLUME_CTRL_30_DB : 0;
}
// 6.1 Interrupt Data Message
const audio_interrupt_data_t data = {
.bInfo = 0, // Class-specific interrupt, originated from an interface
.bAttribute = AUDIO_CS_REQ_CUR, // Caused by current settings
.wValue_cn_or_mcn = 0, // CH0: master volume
.wValue_cs = AUDIO_FU_CTRL_VOLUME, // Volume change
.wIndex_ep_or_int = 0, // From the interface itself
.wIndex_entity_id = UAC2_ENTITY_SPK_FEATURE_UNIT, // From feature unit
};
tud_audio_int_write(&data);
}
btn_prev = btn;
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+

View File

@ -105,6 +105,9 @@ extern "C" {
// AUDIO CLASS DRIVER CONFIGURATION
//--------------------------------------------------------------------
// Allow volume controlled by on-baord button
#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 1
#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN
// How many formats are used, need to adjust USB descriptor if changed

View File

@ -82,27 +82,32 @@ uint8_t const * tud_descriptor_device_cb(void)
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
#define EPNUM_AUDIO_IN 0x03
#define EPNUM_AUDIO_OUT 0x03
#define EPNUM_AUDIO_INT 0x01
#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
// ISO endpoints for NRF5x are fixed to 0x08 (0x88)
#define EPNUM_AUDIO_IN 0x08
#define EPNUM_AUDIO_OUT 0x08
#define EPNUM_AUDIO_INT 0x01
#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_AUDIO_IN 0x01
#define EPNUM_AUDIO_OUT 0x02
#define EPNUM_AUDIO_INT 0x03
#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
// FT9XX doesn't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_AUDIO_IN 0x01
#define EPNUM_AUDIO_OUT 0x02
#define EPNUM_AUDIO_INT 0x03
#else
#define EPNUM_AUDIO_IN 0x01
#define EPNUM_AUDIO_OUT 0x01
#define EPNUM_AUDIO_INT 0x02
#endif
uint8_t const desc_configuration[] =
@ -111,7 +116,7 @@ uint8_t const desc_configuration[] =
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// Interface number, string index, EP Out & EP In address, EP size
TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80)
TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80)
};
// Invoked when received GET CONFIGURATION DESCRIPTOR

View File

@ -55,6 +55,7 @@ enum
+ TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
+ TUD_AUDIO_DESC_INPUT_TERM_LEN\
+ TUD_AUDIO_DESC_OUTPUT_TERM_LEN\
+ TUD_AUDIO_DESC_STD_AC_INT_EP_LEN\
/* Interface 1, Alternate 0 */\
+ TUD_AUDIO_DESC_STD_AS_INT_LEN\
/* Interface 1, Alternate 1 */\
@ -84,11 +85,11 @@ enum
+ TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\
+ TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \
#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \
/* Standard Interface Association Descriptor (IAD) */\
TUD_AUDIO_DESC_IAD(/*_firstitf*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\
/* Clock Source Descriptor(4.7.2.1) */\
@ -103,6 +104,8 @@ enum
TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\
/* Output Terminal Descriptor(4.7.2.5) */\
TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\
/* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */\
TUD_AUDIO_DESC_STD_AC_INT_EP(/*_ep*/ _epint, /*_interval*/ 0x01), \
/* Standard AS Interface Descriptor(4.9.1) */\
/* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\
TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\
@ -114,7 +117,7 @@ enum
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\
/* Interface 1, Alternate 2 - alternate interface for data streaming */\
@ -124,7 +127,7 @@ enum
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\
/* Standard AS Interface Descriptor(4.9.1) */\
@ -138,7 +141,7 @@ enum
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\
/* Interface 2, Alternate 2 - alternate interface for data streaming */\
@ -148,7 +151,7 @@ enum
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)

View File

@ -0,0 +1 @@
mcu:RP2040

View File

@ -79,17 +79,27 @@ set(WARNING_FLAGS_IAR "")
function(family_filter RESULT DIR)
get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
if (EXISTS "${DIR}/only.txt")
file(READ "${DIR}/only.txt" ONLYS)
# Replace newlines with semicolon so that it is treated as a list by CMake
string(REPLACE "\n" ";" ONLYS_LINES ${ONLYS})
if (EXISTS "${DIR}/skip.txt")
file(STRINGS "${DIR}/skip.txt" SKIPS_LINES)
foreach(MCU IN LISTS FAMILY_MCUS)
# For each line in only.txt
foreach(_line ${SKIPS_LINES})
# If mcu:xxx exists for this mcu then skip
if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}" OR ${_line} STREQUAL "family:${FAMILY}")
set(${RESULT} 0 PARENT_SCOPE)
return()
endif()
endforeach()
endforeach()
endif ()
# For each mcu
if (EXISTS "${DIR}/only.txt")
file(STRINGS "${DIR}/only.txt" ONLYS_LINES)
foreach(MCU IN LISTS FAMILY_MCUS)
# For each line in only.txt
foreach(_line ${ONLYS_LINES})
# If mcu:xxx exists for this mcu or board:xxx then include
if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}")
if (${_line} STREQUAL "mcu:${MCU}" OR ${_line} STREQUAL "board:${BOARD}" OR ${_line} STREQUAL "family:${FAMILY}")
set(${RESULT} 1 PARENT_SCOPE)
return()
endif()
@ -98,29 +108,8 @@ function(family_filter RESULT DIR)
# Didn't find it in only file so don't build
set(${RESULT} 0 PARENT_SCOPE)
elseif (EXISTS "${DIR}/skip.txt")
file(READ "${DIR}/skip.txt" SKIPS)
# Replace newlines with semicolon so that it is treated as a list by CMake
string(REPLACE "\n" ";" SKIPS_LINES ${SKIPS})
# For each mcu
foreach(MCU IN LISTS FAMILY_MCUS)
# For each line in only.txt
foreach(_line ${SKIPS_LINES})
# If mcu:xxx exists for this mcu then skip
if (${_line} STREQUAL "mcu:${MCU}")
set(${RESULT} 0 PARENT_SCOPE)
return()
endif()
endforeach()
endforeach()
# Didn't find in skip file so build
set(${RESULT} 1 PARENT_SCOPE)
else()
# Didn't find skip or only file so build
# only.txt not exist so build
set(${RESULT} 1 PARENT_SCOPE)
endif()
endfunction()

View File

@ -0,0 +1,4 @@
set(PICO_BOARD adafruit_feather_rp2040)
# Enable MAX3421E USB Host
set(MAX3421_HOST 1)

View File

@ -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

View File

@ -301,10 +301,12 @@ typedef struct
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
uint8_t ep_int_ctr; // Audio control interrupt EP.
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
uint8_t ep_int; // Audio control interrupt EP.
#endif
bool mounted; // Device opened
/*------------- From this point, data is not cleared by bus reset -------------*/
uint16_t desc_length; // Length of audio function descriptor
@ -358,8 +360,8 @@ typedef struct
#endif
// Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74)
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_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
@ -486,23 +488,7 @@ bool tud_audio_n_mounted(uint8_t func_id)
TU_VERIFY(func_id < CFG_TUD_AUDIO);
audiod_function_t* audio = &_audiod_fct[func_id];
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
if (audio->ep_out == 0) return false;
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_IN
if (audio->ep_in == 0) return false;
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
if (audio->ep_int_ctr == 0) return false;
#endif
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
if (audio->ep_fb == 0) return false;
#endif
return true;
return audio->mounted;
}
//--------------------------------------------------------------------+
@ -825,24 +811,30 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx)
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user
uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len)
#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
bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t * data)
{
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_ctr));
TU_VERIFY(usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int));
TU_VERIFY(tu_memcpy_s(_audiod_fct[func_id].ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_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_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len));
// Check length
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.
@ -1447,10 +1439,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_CTR_EPSIZE_IN > 0);
TU_ASSERT(CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP);
}
// Alternate setting MUST be zero - this check can be omitted
@ -1594,6 +1587,32 @@ 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
_audiod_fct[i].mounted = true;
break;
}
}
@ -2120,10 +2139,10 @@ 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_CTR_EPSIZE_IN
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
// Data transmission of control interrupt finished
if (audio->ep_int_ctr == ep_addr)
if (audio->ep_int == ep_addr)
{
// According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49)
// In case there is nothing to send we have to return a NAK - this is taken care of by PHY ???
@ -2132,7 +2151,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_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes));
if (tud_audio_int_done_cb) tud_audio_int_done_cb(rhport);
return true;
}
#endif

View File

@ -196,13 +196,9 @@
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1
#endif
// Audio interrupt control EP size - disabled if 0
#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74)
#endif
#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE
#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74)
// 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
// Use software encoding/decoding
@ -393,8 +389,8 @@ uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_i
tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx);
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len);
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
bool tud_audio_int_n_write (uint8_t func_id, const audio_interrupt_data_t * data);
#endif
@ -437,8 +433,8 @@ static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx);
// INT CTR API
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len);
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
static inline bool tud_audio_int_write (const audio_interrupt_data_t * data);
#endif
// Buffer control EP data and schedule a transmit
@ -537,8 +533,8 @@ 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_INT_CTR_EPSIZE_IN
TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied);
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport);
#endif
// Invoked when audio set interface request received
@ -669,10 +665,10 @@ static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx)
#endif
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len)
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
static inline bool tud_audio_int_write(const audio_interrupt_data_t * data)
{
return tud_audio_int_ctr_n_write(0, buffer, len);
return tud_audio_int_n_write(0, data);
}
#endif

View File

@ -1181,6 +1181,11 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t t
// TU_VERIFY(tud_ready());
TU_LOG_USBD(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
#if CFG_TUD_LOG_LEVEL >= 3
if(dir == TUSB_DIR_IN) {
TU_LOG_MEM(CFG_TUD_LOG_LEVEL, buffer, total_bytes, 2);
}
#endif
// Attempt to transfer on a busy endpoint, sound like an race condition !
TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);

View File

@ -393,6 +393,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
// For more channels, add definitions here
/* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */
#define TUD_AUDIO_DESC_STD_AC_INT_EP_LEN 7
#define TUD_AUDIO_DESC_STD_AC_INT_EP(_ep, _interval) \
TUD_AUDIO_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(6), _interval
/* Standard AS Interface Descriptor(4.9.1) */
#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9
#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \
@ -468,7 +473,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
@ -517,7 +522,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
@ -565,7 +570,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\

View File

@ -451,10 +451,10 @@ static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) {
// optional hcd configuration, called by tuh_configure()
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
(void) rhport;
TU_VERIFY(cfg_id == TUH_CFGID_MAX3421);
TU_VERIFY(cfg_id == TUH_CFGID_MAX3421 && cfg_param != NULL);
tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param;
_max_nak = cfg->max3421.max_nak;
_max_nak = tu_min8(cfg->max3421.max_nak, EP_STATE_ATTEMPT_MAX-EP_STATE_ATTEMPT_1);
return true;
}
@ -654,7 +654,7 @@ static void xact_generic(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool
// status
if (ep->buf == NULL || ep->total_len == 0) {
uint8_t const hxfr = HXFR_HS | (ep->hxfr_bm.is_out ? HXFR_OUT_NIN : 0);
uint8_t const hxfr = (uint8_t) (HXFR_HS | (ep->hxfr & HXFR_OUT_NIN));
peraddr_write(rhport, ep->daddr, in_isr);
hxfr_write(rhport, hxfr, in_isr);
return;
@ -676,19 +676,18 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf
max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir);
TU_VERIFY(ep);
// control transfer can switch direction
ep->hxfr_bm.is_out = ep_dir ? 0u : 1u;
if (ep_num == 0) {
// control transfer can switch direction
ep->hxfr_bm.is_out = ep_dir ? 0 : 1;
ep->hxfr_bm.is_setup = 0;
ep->data_toggle = 1;
}
ep->buf = buffer;
ep->total_len = buflen;
ep->xferred_len = 0;
ep->state = EP_STATE_ATTEMPT_1;
if (ep_num == 0) {
ep->hxfr_bm.is_setup = 0;
ep->data_toggle = 1;
}
// carry out transfer if not busy
if (!atomic_flag_test_and_set(&_hcd_data.busy)) {
xact_generic(rhport, ep, true, false);

View File

@ -102,17 +102,25 @@ static int _dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_
usbdev = dev;
usbdcd_driver.ep[0] = dev->ep0;
#ifdef EP_ALLOCREQ
// SDK v2
usbdcd_driver.req[0] = EP_ALLOCREQ(usbdcd_driver.ep[0]);
if (usbdcd_driver.req[0] != NULL)
{
if (usbdcd_driver.req[0] != NULL) {
usbdcd_driver.req[0]->len = 64;
usbdcd_driver.req[0]->buf = EP_ALLOCBUFFER(usbdcd_driver.ep[0], 64);
if (!usbdcd_driver.req[0]->buf)
{
if (!usbdcd_driver.req[0]->buf) {
EP_FREEREQ(usbdcd_driver.ep[0], usbdcd_driver.req[0]);
usbdcd_driver.req[0] = NULL;
return ENOMEM;
}
}
#else
// SDK v3
usbdcd_driver.req[0] = usbdev_allocreq(usbdcd_driver.ep[0], 64);
if (usbdcd_driver.req[0] == NULL) {
return ENOMEM;
}
#endif
usbdcd_driver.req[0]->callback = usbdcd_ep0incomplete;
@ -295,13 +303,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
}
usbdcd_driver.req[epnum] = NULL;
#ifdef EP_ALLOCREQ
// sdk v2
usbdcd_driver.req[epnum] = EP_ALLOCREQ(usbdcd_driver.ep[epnum]);
if (usbdcd_driver.req[epnum] != NULL)
{
if (usbdcd_driver.req[epnum] != NULL) {
usbdcd_driver.req[epnum]->len = ep_mps;
}
else
{
#else
// sdk v3
usbdcd_driver.req[epnum] = usbdev_allocreq(usbdcd_driver.ep[epnum], ep_mps);
#endif
if(usbdcd_driver.req[epnum] == NULL) {
return false;
}

View File

@ -64,18 +64,19 @@ def skip_example(example, board):
skip_file = ex_dir / "skip.txt"
only_file = ex_dir / "only.txt"
if skip_file.exists() and only_file.exists():
raise RuntimeError("Only have a skip or only file. Not both.")
elif skip_file.exists():
if skip_file.exists():
skips = skip_file.read_text().split()
return ("mcu:" + mcu in skips or
"board:" + board in skips or
"family:" + family in skips)
elif only_file.exists():
if ("mcu:" + mcu in skips or
"board:" + board in skips or
"family:" + family in skips):
return True
if only_file.exists():
onlys = only_file.read_text().split()
return not ("mcu:" + mcu in onlys or
"board:" + board in onlys or
"family:" + family in onlys)
if not ("mcu:" + mcu in onlys or
"board:" + board in onlys or
"family:" + family in onlys):
return True
return False