diff options
Diffstat (limited to 'src/class')
| -rw-r--r-- | src/class/audio/audio.h | 29 | ||||
| -rw-r--r-- | src/class/audio/audio_device.c | 392 | ||||
| -rw-r--r-- | src/class/cdc/cdc_device.c | 10 | ||||
| -rw-r--r-- | src/class/cdc/cdc_host.c | 62 | ||||
| -rw-r--r-- | src/class/cdc/cdc_host.h | 10 | ||||
| -rw-r--r-- | src/class/dfu/dfu_device.c | 4 | ||||
| -rw-r--r-- | src/class/hid/hid_device.c | 28 | ||||
| -rw-r--r-- | src/class/hid/hid_host.c | 75 | ||||
| -rw-r--r-- | src/class/hid/hid_host.h | 17 | ||||
| -rw-r--r-- | src/class/midi/midi_device.c | 36 | ||||
| -rw-r--r-- | src/class/msc/msc_device.c | 20 | ||||
| -rw-r--r-- | src/class/msc/msc_host.c | 13 | ||||
| -rw-r--r-- | src/class/msc/msc_host.h | 20 |
13 files changed, 393 insertions, 323 deletions
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 936f09104..f99061eae 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000, + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification @@ -823,6 +823,33 @@ typedef struct TU_ATTR_PACKED uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. } audio_desc_cs_as_iso_data_ep_t; +// 5.2.2 Control Request Layout +typedef struct TU_ATTR_PACKED +{ + union + { + struct TU_ATTR_PACKED + { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + + uint8_t bmRequestType; + }; + + uint8_t bRequest; ///< Request type audio_cs_req_t + uint8_t bChannelNumber; + uint8_t bControlSelector; + union + { + uint8_t bInterface; + uint8_t bEndpoint; + }; + uint8_t bEntityID; + uint16_t wLength; +} audio_control_request_t; + //// 5.2.3 Control Request Parameter Block Layout // 5.2.3.1 1-byte Control CUR Parameter Block diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8e4420ed0..404d28817 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -102,19 +102,19 @@ // EP IN software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO #endif @@ -126,32 +126,32 @@ osal_mutex_def_t ep_in_ff_mutex_wr_3; // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // EP OUT software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO #endif @@ -163,52 +163,52 @@ osal_mutex_def_t ep_out_ff_mutex_rd_3; // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 -CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; #if CFG_TUD_AUDIO > 1 -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; #endif #if CFG_TUD_AUDIO > 2 -CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO @@ -218,21 +218,21 @@ osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 -CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO @@ -294,7 +294,7 @@ typedef struct // 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]; + CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE]; #endif // Decoding parameters - parameters are set when alternate AS interface is set by host @@ -393,12 +393,12 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio); #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf); -#endif static inline uint8_t tu_desc_subtype(void const* desc) { return ((uint8_t const*) desc)[2]; } +#endif bool tud_audio_n_mounted(uint8_t func_id) { @@ -643,7 +643,6 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u // Determine amount of samples uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx; uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; uint8_t cnt_ff; @@ -662,14 +661,14 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used); + src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used); + audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); } tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } @@ -885,7 +884,7 @@ range [-1, +1) * */ // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) { // Optimize for fast half word copies typedef struct{ @@ -900,15 +899,15 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const switch (nBytesToCopy) { case 1: - while((uint8_t *)src < src_end) + while(src < src_end) { - *dst = *(uint8_t *)src++; + *dst = *src++; dst += n_ff_used; } break; case 2: - while((uint8_t *)src < src_end) + while(src < src_end) { *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; src += 2; @@ -917,23 +916,23 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const break; case 3: - while((uint8_t *)src < src_end) + while(src < src_end) { // memcpy(dst, src, 3); // src = (uint8_t *)src + 3; // dst += 3 * n_ff_used; // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *(uint8_t *)src++; - *dst++ = *(uint8_t *)src++; - *dst++ = *(uint8_t *)src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; dst += 3 * (n_ff_used - 1); } break; case 4: - while((uint8_t *)src < src_end) + while(src < src_end) { *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; src += 4; @@ -993,8 +992,8 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi if (info.len_lin != 0) { info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length - src_end = info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used); + src_end = (uint8_t *)info.ptr_lin + info.len_lin; + dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); // Limit up to desired length info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); @@ -1002,8 +1001,8 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // Handle wrapped part of FIFO if (info.len_wrap != 0) { - src_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used); + src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; + audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); } tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); @@ -1481,18 +1480,20 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * audio->ep_in_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_in); - // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); - - audio->ep_in = 0; // Necessary? - - // Clear support FIFOs if used -#if CFG_TUD_AUDIO_ENABLE_ENCODING + // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_clear(&audio->ep_in_ff); +#else for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { tu_fifo_clear(&audio->tx_supp_ff[cnt]); } #endif + + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + + audio->ep_in = 0; // Necessary? } #endif @@ -1502,16 +1503,22 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_out_as_intf_num = 0; usbd_edpt_close(rhport, audio->ep_out); - audio->ep_out = 0; // Necessary? - // Clear support FIFOs if used -#if CFG_TUD_AUDIO_ENABLE_DECODING + // Clear FIFOs, since data is no longer valid +#if !CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_clear(&audio->ep_out_ff); +#else for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { tu_fifo_clear(&audio->rx_supp_ff[cnt]); } #endif + // Invoke callback - can be used to stop data sampling + if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + + audio->ep_out = 0; // Necessary? + // Close corresponding feedback EP #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP usbd_edpt_close(rhport, audio->ep_fb); @@ -1605,9 +1612,17 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff ); #endif #endif + +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // In case of asynchronous EP, call Cb after ep_fb is set + if (!(((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync == 0x01 && audio->ep_fb == 0)) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } +#else // Invoke callback if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); - +#endif // Prepare for incoming data #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); @@ -1621,8 +1636,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_fb = ep_addr; - // Invoke callback - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + // Invoke callback after ep_out is set + if (audio->ep_out != 0) + { + if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + } } #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1658,64 +1676,65 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t itf = TU_U16_LOW(p_request->wIndex); - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - if (tud_audio_set_req_entity_cb) + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + if (entityID != 0) { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + if (tud_audio_set_req_entity_cb) + { + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } else { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + if (tud_audio_set_req_itf_cb) + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + } + else + { + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it + } } } - else + break; + + case TUSB_REQ_RCPT_ENDPOINT: { - if (tud_audio_set_req_itf_cb) + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + if (tud_audio_set_req_ep_cb) { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it } } - break; - - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } - // Unknown/Unsupported recipient default: TU_BREAKPOINT(); return false; } @@ -1754,73 +1773,75 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) + case TUSB_REQ_RCPT_INTERFACE: { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) + // Verify if entity is present + if (entityID != 0) { - if (tud_audio_get_req_entity_cb) + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - return tud_audio_get_req_entity_cb(rhport, p_request); + if (tud_audio_get_req_entity_cb) + { + return tud_audio_get_req_entity_cb(rhport, p_request); + } + else + { + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall + } } - else + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + + // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests + if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall + if (tud_audio_get_req_itf_cb) + { + return tud_audio_get_req_itf_cb(rhport, p_request); + } + else + { + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall + } } } } - else + break; + + case TUSB_REQ_RCPT_ENDPOINT: { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_itf_cb) + if (tud_audio_get_req_ep_cb) { - return tud_audio_get_req_itf_cb(rhport, p_request); + return tud_audio_get_req_ep_cb(rhport, p_request); } else { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall } } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - - // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests - if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) - { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } - } - break; - // Unknown/Unsupported recipient default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false; } @@ -1913,8 +1934,12 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 { if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport)); - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, &_audiod_fct[func_id]); + // Schedule a transmit with the new value if EP is not busy + if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb)) + { + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + return audiod_fb_send(rhport, &_audiod_fct[func_id]); + } } #endif #endif @@ -1935,29 +1960,31 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req // Conduct checks which depend on the recipient switch (p_request->bmRequestType_bit.recipient) { - case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label - - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - - // Verify if entity is present - if (entityID != 0) - { - // Find index of audio driver structure and verify entity really exists - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - } - else + case TUSB_REQ_RCPT_INTERFACE: { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Verify if entity is present + if (entityID != 0) + { + // Find index of audio driver structure and verify entity really exists + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + } + else + { + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + } } break; - case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label - - uint8_t ep = TU_U16_LOW(p_request->wIndex); + case TUSB_REQ_RCPT_ENDPOINT: + { + uint8_t ep = TU_U16_LOW(p_request->wIndex); - // Find index of audio driver structure and verify EP really exists - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + // Find index of audio driver structure and verify EP really exists + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + } break; // Unknown/Unsupported recipient @@ -1992,15 +2019,17 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio while (p_desc < p_desc_end) { // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) { - *idxItf = tmp; - *pp_desc_int = p_desc; - return true; + if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf) + { + *idxItf = tmp; + *pp_desc_int = p_desc; + return true; + } + // Increase index, bytes read, and pointer + tmp++; } - - // Increase index, bytes read, and pointer - tmp++; p_desc = tu_desc_next(p_desc); } } @@ -2137,10 +2166,10 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * if (as_itf == audio->ep_in_as_intf_num) { audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels; - audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType; + audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType); #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats; + audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats); #endif } #endif @@ -2202,22 +2231,19 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); // Format the feedback value - if (_audiod_fct[func_id].rhport == 0) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; +#if !TUD_OPT_HIGH_SPEED + uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val; - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - } - else - { - // For HS format is 16.16 as originally demanded - _audiod_fct[func_id].fb_val = feedback; - } + // For FS format is 10.14 + *(fb++) = (feedback >> 2) & 0xFF; + *(fb++) = (feedback >> 10) & 0xFF; + *(fb++) = (feedback >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; +#else + // For HS format is 16.16 as originally demanded + _audiod_fct[func_id].fb_val = feedback; +#endif // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index a926081cc..68080c61d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -273,9 +273,6 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); - // Note: 0xFF can be used with RNDIS - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0); - // Find available interface cdcd_interface_t * p_cdc = NULL; for(uint8_t cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++) @@ -303,10 +300,11 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { - // notification endpoint if any - TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 ); + // notification endpoint + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; + TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 33f1a8ad3..fc7100e81 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,29 +149,27 @@ void cdch_init(void) tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) +uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // Only support ACM - TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass); + (void) max_len; - // Only support AT commands, no protocol and vendor specific commands. - TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || - 0xff == itf_desc->bInterfaceProtocol); + // Only support ACM subclass + // Protocol 0xFF can be RNDIS device for windows XP + TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass && + 0xFF != itf_desc->bInterfaceProtocol, 0); - uint8_t const * p_desc; - cdch_data_t * p_cdc; - - p_desc = tu_desc_next(itf_desc); - p_cdc = get_itf(dev_addr); + cdch_data_t * p_cdc = get_itf(dev_addr); - p_cdc->itf_num = itf_desc->bInterfaceNumber; - p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com + p_cdc->itf_num = itf_desc->bInterfaceNumber; + p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; //------------- Communication Interface -------------// - (*p_length) = sizeof(tusb_desc_interface_t); + uint16_t drv_len = tu_desc_len(itf_desc); + uint8_t const * p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors - while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] ) + while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) { @@ -179,52 +177,52 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) { // notification endpoint - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) ); - p_cdc->ep_notif = ep_desc->bEndpointAddress; + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); + p_cdc->ep_notif = desc_ep->bEndpointAddress; - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { - (*p_length) += p_desc[DESC_OFFSET_LEN]; + // next to endpoint descriptor + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs for(uint32_t i=0; i<2; i++) { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); - TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0); - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) + if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { - p_cdc->ep_in = ep_desc->bEndpointAddress; + p_cdc->ep_in = desc_ep->bEndpointAddress; }else { - p_cdc->ep_out = ep_desc->bEndpointAddress; + p_cdc->ep_out = desc_ep->bEndpointAddress; } - (*p_length) += p_desc[DESC_OFFSET_LEN]; + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next( p_desc ); } } - return true; + return drv_len; } bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 6ff392709..edcd258a8 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void cdch_init(void); -bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length); -bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close(uint8_t dev_addr); +void cdch_init (void); +uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 81045ff7b..c696d70a2 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -247,7 +247,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength) { - TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE); + TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, 0); uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength); tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval); return retval; @@ -276,6 +276,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * // if they wish, there still will be the internal control buffer copy to this buffer // but this mode would provide zero copy from the class driver to the application + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); // setup for data phase tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength); } @@ -283,6 +284,7 @@ static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request) { (void) rhport; + TU_VERIFY( request->wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE, ); tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength); _dfu_state_ctx.blk_transfer_in_proc = false; } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index e44f282c4..a10e3a5e3 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -280,7 +280,21 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength); + uint8_t* report_buf = p_hid->epin_buf; + uint16_t req_len = request->wLength; + + uint16_t xferlen = 0; + + // If host request a specific Report ID, add ID to as 1 byte of response + if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) ) + { + *report_buf++ = report_id; + req_len--; + + xferlen++; + } + + xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); TU_ASSERT( xferlen > 0 ); tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen); @@ -298,7 +312,17 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t uint8_t const report_type = tu_u16_high(request->wValue); uint8_t const report_id = tu_u16_low(request->wValue); - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength); + uint8_t const* report_buf = p_hid->epout_buf; + uint16_t report_len = request->wLength; + + // If host request a specific Report ID, extract report ID in buffer before invoking callback + if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) ) + { + report_buf++; + report_len--; + } + + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); } break; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index cde5e23a5..40b6f5631 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -37,16 +37,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -/* - "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard - "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse - "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control - "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control - "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen - "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad - "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF - */ typedef struct { uint8_t itf_num; @@ -108,7 +98,7 @@ uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance) return hid_itf->itf_protocol; } -bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance) { hidh_interface_t* hid_itf = get_instance(dev_addr, instance); return hid_itf->protocol_mode; @@ -253,33 +243,37 @@ void hidh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ -static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); +static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + (void) max_len; + + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = (uint8_t const *) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); + TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0); // not enough interface, try to increase CFG_TUH_HID // TODO multiple devices hidh_device_t* hid_dev = get_dev(dev_addr); - TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID); + TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0); //------------- Endpoint Descriptor -------------// + drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); // TODO also open endpoint OUT - TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 ); hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count); hid_dev->inst_count++; @@ -292,12 +286,13 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de hid_itf->report_desc_type = desc_hid->bReportType; hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); - hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode + // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol; - *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) @@ -324,43 +319,49 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num) .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) ); + TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) ); return true; } -static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) +// Force device to work in BOOT protocol +static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result + // Stall is a valid response for SET_IDLE, therefore we could ignore its result (void) result; uint8_t const itf_num = (uint8_t) request->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); hidh_interface_t* hid_itf = get_instance(dev_addr, instance); - TU_LOG2("HID Get Protocol\r\n"); + TU_LOG2("HID Set Protocol\r\n"); + hid_itf->protocol_mode = HID_PROTOCOL_BOOT; tusb_control_request_t const new_request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN + .direction = TUSB_DIR_OUT }, - .bRequest = HID_REQ_CONTROL_GET_PROTOCOL, - .wValue = 0, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = HID_PROTOCOL_BOOT, .wIndex = hid_itf->itf_num, - .wLength = 1 + .wLength = 0 }; - TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) ); - return false; + TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) ); + return true; } static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result) { - // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result - (void) result; + // We can be here after SET_IDLE or SET_PROTOCOL (boot device) + // Trigger assert if result is not successful with set protocol + if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE ) + { + TU_ASSERT(result == XFER_RESULT_SUCCESS); + } uint8_t const itf_num = (uint8_t) request->wIndex; uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num); @@ -368,7 +369,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons // Get Report Descriptor // using usbh enumeration buffer since report descriptor can be very long - TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE ); + TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE ); TU_LOG2("HID Get Report Descriptor\r\n"); tusb_control_request_t const new_request = @@ -452,9 +453,9 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t const data8 = desc_report[0]; - TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; i<size; i++) TU_LOG2("%02X ", desc_report[i]); - TU_LOG2("\r\n"); + TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); + for(uint32_t i=0; i<size; i++) TU_LOG(3, "%02X ", desc_report[i]); + TU_LOG(3, "\r\n"); switch(type) { diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 2e4cce600..ef203123d 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -66,9 +66,10 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance); // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance); -// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -// Note: as HID spec, device will be initialized in Report mode -bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); +// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) +// Note: Device will be initialized in Boot protocol for simplicity. +// Application can use set_protocol() to switch back to Report protocol. +uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance); // Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) // This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE) @@ -118,11 +119,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void hidh_init(void); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close(uint8_t dev_addr); +void hidh_init (void); +uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close (uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 953ca26e6..c39e03976 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -197,9 +197,11 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { - midid_interface_t* p_midi = &_midid_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); - _prep_out_transaction(p_midi); + midid_interface_t* midi = &_midid_itf[itf]; + TU_VERIFY(midi->ep_out); + + uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); + _prep_out_transaction(midi); return (num_read == 4); } @@ -234,19 +236,19 @@ static uint32_t write_flush(midid_interface_t* midi) uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->itf_num, 0); + TU_VERIFY(midi->ep_in, 0); midid_stream_t* stream = &midi->stream_write; - uint32_t total_written = 0; uint32_t i = 0; - while ( i < bufsize ) + while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) { uint8_t const data = buffer[i]; + i++; if ( stream->index == 0 ) { - // new event packet + //------------- New event packet -------------// uint8_t const msg = data >> 4; @@ -308,9 +310,9 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* } else { - // On-going (buffering) packet + //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, total_written); + TU_ASSERT(stream->index < 4, i); stream->buffer[stream->index] = data; stream->index++; @@ -333,27 +335,20 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* // complete current event packet, reset stream stream->index = stream->total = 0; - // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing - if ( count != 4 ) break; - - // updated written if succeeded - total_written = i; + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, i); } - - i++; } write_flush(midi); - return total_written; + return i; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) { midid_interface_t* midi = &_midid_itf[itf]; - if (midi->itf_num == 0) { - return 0; - } + TU_VERIFY(midi->ep_in); if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; @@ -435,6 +430,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint } p_midi->itf_num = desc_midi->bInterfaceNumber; + (void) p_midi->itf_num; // next descriptor drv_len += tu_desc_len(p_desc); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 7f13b4891..014e8b69e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -37,6 +37,10 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + +// Can be selectively disabled to reduce logging when troubleshooting other driver +#define MSC_DEBUG 2 + enum { MSC_STAGE_CMD = 0, @@ -99,7 +103,7 @@ static inline uint16_t rdwr10_get_blockcount(uint8_t const command[]) //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 2 -static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = +TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { { .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" }, { .key = SCSI_CMD_INQUIRY , .data = "Inquiry" }, @@ -114,7 +118,7 @@ static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { .key = SCSI_CMD_WRITE_10 , .data = "Write10" } }; -static tu_lookup_table_t const _msc_scsi_cmd_table = +TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table = { .count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup), .items = _msc_scsi_cmd_lookup @@ -232,8 +236,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT( event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE ); - TU_LOG2(" SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - // TU_LOG2_MEM(p_cbw, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); + // TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; p_csw->tag = p_cbw->tag; @@ -305,8 +309,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_DATA: - TU_LOG2(" SCSI Data\r\n"); - //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Data\r\n"); + //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2); // OUT transfer, invoke callback if needed if ( !tu_bit_test(p_cbw->dir, 7) ) @@ -402,8 +406,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) ) { - TU_LOG2(" SCSI Status: %u\r\n", p_csw->status); - // TU_LOG2_MEM(p_csw, xferred_bytes, 2); + TU_LOG(MSC_DEBUG, " SCSI Status: %u\r\n", p_csw->status); + // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); // Invoke complete callback if defined // Note: There is racing issue with samd51 + qspi flash testing with arduino diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7f98ef9b1..2c027deff 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -360,18 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length) +uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + // msc driver length is fixed + uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); + msch_interface_t* p_msc = get_itf(dev_addr); tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); for(uint32_t i=0; i<2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { @@ -385,9 +389,8 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de } p_msc->itf_num = desc_itf->bInterfaceNumber; - (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t); - return true; + return drv_len; } bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index ce4fe64dc..9e4217ba5 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -41,13 +41,6 @@ #define CFG_TUH_MSC_MAXLUN 4 #endif - -/** \addtogroup ClassDriver_MSC - * @{ - * \defgroup MSC_Host Host - * The interface API includes status checking function, data transferring function and callback functions - * @{ */ - typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw); //--------------------------------------------------------------------+ @@ -113,17 +106,14 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -void msch_init(void); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length); -bool msch_set_config(uint8_t dev_addr, uint8_t itf_num); -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void msch_close(uint8_t dev_addr); +void msch_init (void); +uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool msch_set_config (uint8_t dev_addr, uint8_t itf_num); +bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void msch_close (uint8_t dev_addr); #ifdef __cplusplus } #endif #endif /* _TUSB_MSC_HOST_H_ */ - -/// @} -/// @} |
