mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-23 22:43:49 +00:00
Merge branch 'master' into fix-fifo-memory-overflow
This commit is contained in:
commit
b42d298b81
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@ -38,6 +38,8 @@ jobs:
|
||||
|
||||
- name: Build Fuzzer
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
fuzz_harness=$(ls -d test/fuzz/device/*/)
|
||||
for h in $fuzz_harness
|
||||
do
|
||||
|
@ -14,6 +14,7 @@ add_executable(${PROJECT})
|
||||
|
||||
# Example source
|
||||
target_sources(${PROJECT} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c
|
||||
|
@ -7,7 +7,8 @@ INC += \
|
||||
|
||||
# Example source
|
||||
EXAMPLE_SOURCE = \
|
||||
src/hid_app.c \
|
||||
src/cdc_app.c \
|
||||
src/hid_app.c \
|
||||
src/main.c \
|
||||
src/msc_app.c \
|
||||
|
||||
|
113
examples/host/cdc_msc_hid/src/cdc_app.c
Normal file
113
examples/host/cdc_msc_hid/src/cdc_app.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2022, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#include "tusb.h"
|
||||
#include "bsp/board.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
|
||||
//------------- IMPLEMENTATION -------------//
|
||||
|
||||
size_t get_console_inputs(uint8_t* buf, size_t bufsize)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (count < bufsize)
|
||||
{
|
||||
int ch = board_getchar();
|
||||
if ( ch <= 0 ) break;
|
||||
|
||||
buf[count] = (uint8_t) ch;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void cdc_app_task(void)
|
||||
{
|
||||
uint8_t buf[64+1]; // +1 for extra null character
|
||||
uint32_t const bufsize = sizeof(buf)-1;
|
||||
|
||||
uint32_t count = get_console_inputs(buf, bufsize);
|
||||
buf[count] = 0;
|
||||
|
||||
// loop over all mounted interfaces
|
||||
for(uint8_t idx=0; idx<CFG_TUH_CDC; idx++)
|
||||
{
|
||||
if ( tuh_cdc_mounted(idx) )
|
||||
{
|
||||
// console --> cdc interfaces
|
||||
if (count)
|
||||
{
|
||||
tuh_cdc_write(idx, buf, count);
|
||||
tuh_cdc_write_flush(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when received new data
|
||||
void tuh_cdc_rx_cb(uint8_t idx)
|
||||
{
|
||||
uint8_t buf[64+1]; // +1 for extra null character
|
||||
uint32_t const bufsize = sizeof(buf)-1;
|
||||
|
||||
// forward cdc interfaces -> console
|
||||
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
|
||||
buf[count] = 0;
|
||||
|
||||
printf((char*) buf);
|
||||
}
|
||||
|
||||
void tuh_cdc_mount_cb(uint8_t idx)
|
||||
{
|
||||
tuh_cdc_itf_info_t itf_info = { 0 };
|
||||
tuh_cdc_itf_get_info(idx, &itf_info);
|
||||
|
||||
printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.bInterfaceNumber);
|
||||
|
||||
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
// CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
|
||||
// otherwise you need to call tuh_cdc_set_line_coding() first
|
||||
cdc_line_coding_t line_coding = { 0 };
|
||||
if ( tuh_cdc_get_local_line_coding(idx, &line_coding) )
|
||||
{
|
||||
printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
|
||||
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity , line_coding.data_bits);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tuh_cdc_umount_cb(uint8_t idx)
|
||||
{
|
||||
tuh_cdc_itf_info_t itf_info = { 0 };
|
||||
tuh_cdc_itf_get_info(idx, &itf_info);
|
||||
|
||||
printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.bInterfaceNumber);
|
||||
}
|
@ -35,7 +35,7 @@
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void);
|
||||
|
||||
extern void cdc_task(void);
|
||||
extern void cdc_app_task(void);
|
||||
extern void hid_app_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
@ -52,38 +52,15 @@ int main(void)
|
||||
{
|
||||
// tinyusb host task
|
||||
tuh_task();
|
||||
led_blinking_task();
|
||||
|
||||
cdc_task();
|
||||
led_blinking_task();
|
||||
cdc_app_task();
|
||||
hid_app_task();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB CDC
|
||||
//--------------------------------------------------------------------+
|
||||
CFG_TUSB_MEM_SECTION static char serial_in_buffer[64] = { 0 };
|
||||
|
||||
// invoked ISR context
|
||||
void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
|
||||
{
|
||||
(void) event;
|
||||
(void) pipe_id;
|
||||
(void) xferred_bytes;
|
||||
|
||||
printf(serial_in_buffer);
|
||||
tu_memclr(serial_in_buffer, sizeof(serial_in_buffer));
|
||||
|
||||
tuh_cdc_receive(dev_addr, serial_in_buffer, sizeof(serial_in_buffer), true); // waiting for next data
|
||||
}
|
||||
|
||||
void cdc_task(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -108,6 +108,17 @@
|
||||
#define CFG_TUH_HID_EPIN_BUFSIZE 64
|
||||
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
|
||||
|
||||
//------------- CDC -------------//
|
||||
|
||||
// Set Line Control state on enumeration/mounted:
|
||||
// DTR ( bit 0), RTS (bit 1)
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
|
||||
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -721,11 +721,13 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t bLength ; ///< Size of this descriptor, in bytes: 17.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL.
|
||||
uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this terminal.
|
||||
uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types.
|
||||
uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated.
|
||||
uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected.
|
||||
uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster.
|
||||
uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t.
|
||||
uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first logical channel.
|
||||
uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t.
|
||||
uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal.
|
||||
} audio_desc_input_terminal_t;
|
||||
|
@ -41,16 +41,6 @@
|
||||
/** \defgroup ClassDriver_CDC_Common Common Definitions
|
||||
* @{ */
|
||||
|
||||
// TODO remove
|
||||
/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In)
|
||||
typedef enum
|
||||
{
|
||||
CDC_PIPE_NOTIFICATION , ///< Notification pipe
|
||||
CDC_PIPE_DATA_IN , ///< Data in pipe
|
||||
CDC_PIPE_DATA_OUT , ///< Data out pipe
|
||||
CDC_PIPE_ERROR , ///< Invalid Pipe ID
|
||||
}cdc_pipeid_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CDC Communication Interface Class
|
||||
//--------------------------------------------------------------------+
|
||||
@ -192,6 +182,28 @@ typedef enum
|
||||
CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60,
|
||||
}cdc_management_request_t;
|
||||
|
||||
enum
|
||||
{
|
||||
CDC_CONTROL_LINE_STATE_DTR = 0x01,
|
||||
CDC_CONTROL_LINE_STATE_RTS = 0x02,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CDC_LINE_CONDING_STOP_BITS_1 = 0, // 1 bit
|
||||
CDC_LINE_CONDING_STOP_BITS_1_5 = 1, // 1.5 bits
|
||||
CDC_LINE_CONDING_STOP_BITS_2 = 2, // 2 bits
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CDC_LINE_CODING_PARITY_NONE = 0,
|
||||
CDC_LINE_CODING_PARITY_ODD = 1,
|
||||
CDC_LINE_CODING_PARITY_EVEN = 2,
|
||||
CDC_LINE_CODING_PARITY_MARK = 3,
|
||||
CDC_LINE_CODING_PARITY_SPACE = 4,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Management Element Notification (Notification Endpoint)
|
||||
//--------------------------------------------------------------------+
|
||||
@ -390,8 +402,8 @@ TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct");
|
||||
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint16_t dte_is_present : 1; ///< Indicates to DCE if DTE is presentor not. This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR.
|
||||
uint16_t half_duplex_carrier_control : 1;
|
||||
uint16_t dtr : 1;
|
||||
uint16_t rts : 1;
|
||||
uint16_t : 14;
|
||||
} cdc_line_control_state_t;
|
||||
|
||||
|
@ -62,10 +62,8 @@ typedef struct
|
||||
uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE];
|
||||
uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE];
|
||||
|
||||
#if CFG_FIFO_MUTEX
|
||||
osal_mutex_def_t rx_ff_mutex;
|
||||
osal_mutex_def_t tx_ff_mutex;
|
||||
#endif
|
||||
OSAL_MUTEX_DEF(rx_ff_mutex);
|
||||
OSAL_MUTEX_DEF(tx_ff_mutex);
|
||||
|
||||
// Endpoint Transfer buffer
|
||||
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE];
|
||||
@ -248,10 +246,8 @@ void cdcd_init(void)
|
||||
// In this way, the most current data is prioritized.
|
||||
tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true);
|
||||
|
||||
#if CFG_FIFO_MUTEX
|
||||
tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex));
|
||||
tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +432,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
// Received new data
|
||||
if ( ep_addr == p_cdc->ep_out )
|
||||
{
|
||||
tu_fifo_write_n(&p_cdc->rx_ff, &p_cdc->epout_buf, (uint16_t) xferred_bytes);
|
||||
tu_fifo_write_n(&p_cdc->rx_ff, p_cdc->epout_buf, (uint16_t) xferred_bytes);
|
||||
|
||||
// Check for wanted char and invoke callback if needed
|
||||
if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) )
|
||||
|
@ -27,7 +27,6 @@
|
||||
#ifndef _TUSB_CDC_DEVICE_H_
|
||||
#define _TUSB_CDC_DEVICE_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "cdc.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -81,7 +80,7 @@ int32_t tud_cdc_n_read_char (uint8_t itf);
|
||||
// Clear the received FIFO
|
||||
void tud_cdc_n_read_flush (uint8_t itf);
|
||||
|
||||
// Get a byte from FIFO at the specified position without removing it
|
||||
// Get a byte from FIFO without removing it
|
||||
bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8);
|
||||
|
||||
// Write bytes to TX FIFO, data may remain in the FIFO for a while
|
||||
@ -135,7 +134,7 @@ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf);
|
||||
// Invoked when received `wanted_char`
|
||||
TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
|
||||
|
||||
// Invoked when space becomes available in TX buffer
|
||||
// Invoked when a TX is complete and therefore space becomes available in TX buffer
|
||||
TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf);
|
||||
|
||||
// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
|
||||
|
@ -33,96 +33,260 @@
|
||||
|
||||
#include "cdc_host.h"
|
||||
|
||||
|
||||
// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
|
||||
#define CDCH_DEBUG 2
|
||||
|
||||
#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct {
|
||||
uint8_t itf_num;
|
||||
uint8_t itf_protocol;
|
||||
|
||||
uint8_t ep_notif;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
typedef struct {
|
||||
uint8_t daddr;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
|
||||
cdc_acm_capability_t acm_capability;
|
||||
uint8_t ep_notif;
|
||||
|
||||
} cdch_data_t;
|
||||
cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width
|
||||
uint8_t line_state; // DTR (bit0), RTS (bit1)
|
||||
|
||||
tuh_xfer_cb_t user_control_cb;
|
||||
|
||||
struct {
|
||||
tu_edpt_stream_t tx;
|
||||
tu_edpt_stream_t rx;
|
||||
|
||||
uint8_t tx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE];
|
||||
CFG_TUSB_MEM_ALIGN uint8_t tx_ep_buf[CFG_TUH_CDC_TX_EPSIZE];
|
||||
|
||||
uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE];
|
||||
CFG_TUSB_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE];
|
||||
} stream;
|
||||
|
||||
} cdch_interface_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
static cdch_data_t cdch_data[CFG_TUH_DEVICE_MAX];
|
||||
|
||||
static inline cdch_data_t* get_itf(uint8_t dev_addr)
|
||||
CFG_TUSB_MEM_SECTION
|
||||
static cdch_interface_t cdch_data[CFG_TUH_CDC];
|
||||
|
||||
static inline cdch_interface_t* get_itf(uint8_t idx)
|
||||
{
|
||||
return &cdch_data[dev_addr-1];
|
||||
TU_ASSERT(idx < CFG_TUH_CDC, NULL);
|
||||
cdch_interface_t* p_cdc = &cdch_data[idx];
|
||||
|
||||
return (p_cdc->daddr != 0) ? p_cdc : NULL;
|
||||
}
|
||||
|
||||
bool tuh_cdc_mounted(uint8_t dev_addr)
|
||||
static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr)
|
||||
{
|
||||
cdch_data_t* cdc = get_itf(dev_addr);
|
||||
return cdc->ep_in && cdc->ep_out;
|
||||
}
|
||||
|
||||
bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid)
|
||||
{
|
||||
if ( !tuh_cdc_mounted(dev_addr) ) return false;
|
||||
|
||||
cdch_data_t const * p_cdc = get_itf(dev_addr);
|
||||
|
||||
switch (pipeid)
|
||||
for(uint8_t i=0; i<CFG_TUH_CDC; i++)
|
||||
{
|
||||
case CDC_PIPE_NOTIFICATION:
|
||||
return usbh_edpt_busy(dev_addr, p_cdc->ep_notif );
|
||||
|
||||
case CDC_PIPE_DATA_IN:
|
||||
return usbh_edpt_busy(dev_addr, p_cdc->ep_in );
|
||||
|
||||
case CDC_PIPE_DATA_OUT:
|
||||
return usbh_edpt_busy(dev_addr, p_cdc->ep_out );
|
||||
|
||||
default:
|
||||
return false;
|
||||
cdch_interface_t* p_cdc = &cdch_data[i];
|
||||
if ( (p_cdc->daddr == daddr) &&
|
||||
(ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return TUSB_INDEX_INVALID;
|
||||
}
|
||||
|
||||
|
||||
static cdch_interface_t* find_new_itf(void)
|
||||
{
|
||||
for(uint8_t i=0; i<CFG_TUH_CDC; i++)
|
||||
{
|
||||
if (cdch_data[i].daddr == 0) return &cdch_data[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API (parameter validation needed)
|
||||
// APPLICATION API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tuh_cdc_serial_is_mounted(uint8_t dev_addr)
|
||||
|
||||
uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num)
|
||||
{
|
||||
// TODO consider all AT Command as serial candidate
|
||||
return tuh_cdc_mounted(dev_addr) &&
|
||||
(cdch_data[dev_addr-1].itf_protocol <= CDC_COMM_PROTOCOL_ATCOMMAND_CDMA);
|
||||
for(uint8_t i=0; i<CFG_TUH_CDC; i++)
|
||||
{
|
||||
const cdch_interface_t* p_cdc = &cdch_data[i];
|
||||
|
||||
if (p_cdc->daddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i;
|
||||
}
|
||||
|
||||
return TUSB_INDEX_INVALID;
|
||||
}
|
||||
|
||||
bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify)
|
||||
bool tuh_cdc_itf_get_info(uint8_t idx, tuh_cdc_itf_info_t* info)
|
||||
{
|
||||
(void) is_notify;
|
||||
TU_VERIFY( tuh_cdc_mounted(dev_addr) );
|
||||
TU_VERIFY( p_data != NULL && length);
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc && info);
|
||||
|
||||
uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
|
||||
if ( usbh_edpt_busy(dev_addr, ep_out) ) return false;
|
||||
info->daddr = p_cdc->daddr;
|
||||
info->bInterfaceNumber = p_cdc->bInterfaceNumber;
|
||||
info->bInterfaceSubClass = p_cdc->bInterfaceSubClass;
|
||||
info->bInterfaceProtocol = p_cdc->bInterfaceProtocol;
|
||||
|
||||
return usbh_edpt_xfer(dev_addr, ep_out, (void*)(uintptr_t) p_data, (uint16_t) length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify)
|
||||
bool tuh_cdc_mounted(uint8_t idx)
|
||||
{
|
||||
(void) is_notify;
|
||||
TU_VERIFY( tuh_cdc_mounted(dev_addr) );
|
||||
TU_VERIFY( p_buffer != NULL && length );
|
||||
|
||||
uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
|
||||
if ( usbh_edpt_busy(dev_addr, ep_in) ) return false;
|
||||
|
||||
return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, (uint16_t) length);
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
return p_cdc != NULL;
|
||||
}
|
||||
|
||||
bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb)
|
||||
bool tuh_cdc_get_dtr(uint8_t idx)
|
||||
{
|
||||
cdch_data_t const * p_cdc = get_itf(dev_addr);
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false;
|
||||
}
|
||||
|
||||
bool tuh_cdc_get_rts(uint8_t idx)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false;
|
||||
}
|
||||
|
||||
bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
*line_coding = p_cdc->line_coding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Write
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize);
|
||||
}
|
||||
|
||||
uint32_t tuh_cdc_write_flush(uint8_t idx)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_write_xfer(&p_cdc->stream.tx);
|
||||
}
|
||||
|
||||
bool tuh_cdc_write_clear(uint8_t idx)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_clear(&p_cdc->stream.tx);
|
||||
}
|
||||
|
||||
uint32_t tuh_cdc_write_available(uint8_t idx)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_write_available(&p_cdc->stream.tx);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Read
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize);
|
||||
}
|
||||
|
||||
uint32_t tuh_cdc_read_available(uint8_t idx)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_read_available(&p_cdc->stream.rx);
|
||||
}
|
||||
|
||||
bool tuh_cdc_peek(uint8_t idx, uint8_t* ch)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
return tu_edpt_stream_peek(&p_cdc->stream.rx, ch);
|
||||
}
|
||||
|
||||
bool tuh_cdc_read_clear (uint8_t idx)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx);
|
||||
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Control Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// internal control complete to update state such as line state, encoding
|
||||
static void cdch_internal_control_complete(tuh_xfer_t* xfer)
|
||||
{
|
||||
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
|
||||
uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_ASSERT(p_cdc, );
|
||||
|
||||
if (xfer->result == XFER_RESULT_SUCCESS)
|
||||
{
|
||||
switch(xfer->setup->bRequest)
|
||||
{
|
||||
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||||
p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue);
|
||||
break;
|
||||
|
||||
case CDC_REQUEST_SET_LINE_CODING:
|
||||
{
|
||||
uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength));
|
||||
memcpy(&p_cdc->line_coding, xfer->buffer, len);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
xfer->complete_cb = p_cdc->user_control_cb;
|
||||
xfer->complete_cb(xfer);
|
||||
}
|
||||
|
||||
bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc && p_cdc->acm_capability.support_line_request);
|
||||
|
||||
TU_LOG_CDCH("CDC Set Control Line State\r\n");
|
||||
|
||||
tusb_control_request_t const request =
|
||||
{
|
||||
@ -133,36 +297,154 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xf
|
||||
.direction = TUSB_DIR_OUT
|
||||
},
|
||||
.bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
|
||||
.wValue = tu_htole16((uint16_t) ((dtr ? 1u : 0u) | (rts ? 2u : 0u))),
|
||||
.wIndex = tu_htole16(p_cdc->itf_num),
|
||||
.wValue = tu_htole16(line_state),
|
||||
.wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber),
|
||||
.wLength = 0
|
||||
};
|
||||
|
||||
p_cdc->user_control_cb = complete_cb;
|
||||
tuh_xfer_t xfer =
|
||||
{
|
||||
.daddr = dev_addr,
|
||||
.daddr = p_cdc->daddr,
|
||||
.ep_addr = 0,
|
||||
.setup = &request,
|
||||
.buffer = NULL,
|
||||
.complete_cb = complete_cb,
|
||||
.user_data = 0
|
||||
.complete_cb = cdch_internal_control_complete,
|
||||
.user_data = user_data
|
||||
};
|
||||
|
||||
return tuh_control_xfer(&xfer);
|
||||
}
|
||||
|
||||
bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
|
||||
{
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
TU_VERIFY(p_cdc && p_cdc->acm_capability.support_line_request);
|
||||
|
||||
TU_LOG_CDCH("CDC Set Line Conding\r\n");
|
||||
|
||||
tusb_control_request_t const request =
|
||||
{
|
||||
.bmRequestType_bit =
|
||||
{
|
||||
.recipient = TUSB_REQ_RCPT_INTERFACE,
|
||||
.type = TUSB_REQ_TYPE_CLASS,
|
||||
.direction = TUSB_DIR_OUT
|
||||
},
|
||||
.bRequest = CDC_REQUEST_SET_LINE_CODING,
|
||||
.wValue = 0,
|
||||
.wIndex = tu_htole16(p_cdc->bInterfaceNumber),
|
||||
.wLength = tu_htole16(sizeof(cdc_line_coding_t))
|
||||
};
|
||||
|
||||
// use usbh enum buf to hold line coding since user line_coding variable may not live long enough
|
||||
// for the transfer to complete
|
||||
uint8_t* enum_buf = usbh_get_enum_buf();
|
||||
memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t));
|
||||
|
||||
p_cdc->user_control_cb = complete_cb;
|
||||
tuh_xfer_t xfer =
|
||||
{
|
||||
.daddr = p_cdc->daddr,
|
||||
.ep_addr = 0,
|
||||
.setup = &request,
|
||||
.buffer = enum_buf,
|
||||
.complete_cb = cdch_internal_control_complete,
|
||||
.user_data = user_data
|
||||
};
|
||||
|
||||
return tuh_control_xfer(&xfer);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH-CLASS DRIVER API
|
||||
// CLASS-USBH API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void cdch_init(void)
|
||||
{
|
||||
tu_memclr(cdch_data, sizeof(cdch_data));
|
||||
|
||||
for(size_t i=0; i<CFG_TUH_CDC; i++)
|
||||
{
|
||||
cdch_interface_t* p_cdc = &cdch_data[i];
|
||||
|
||||
tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false,
|
||||
p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE,
|
||||
p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE);
|
||||
|
||||
tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false,
|
||||
p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE,
|
||||
p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
|
||||
void cdch_close(uint8_t daddr)
|
||||
{
|
||||
for(uint8_t idx=0; idx<CFG_TUH_CDC; idx++)
|
||||
{
|
||||
cdch_interface_t* p_cdc = &cdch_data[idx];
|
||||
if (p_cdc->daddr == daddr)
|
||||
{
|
||||
// Invoke application callback
|
||||
if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx);
|
||||
|
||||
//tu_memclr(p_cdc, sizeof(cdch_interface_t));
|
||||
p_cdc->daddr = 0;
|
||||
p_cdc->bInterfaceNumber = 0;
|
||||
tu_edpt_stream_close(&p_cdc->stream.tx);
|
||||
tu_edpt_stream_close(&p_cdc->stream.rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
|
||||
{
|
||||
// TODO handle stall response, retry failed transfer ...
|
||||
TU_ASSERT(event == XFER_RESULT_SUCCESS);
|
||||
|
||||
uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr);
|
||||
cdch_interface_t * p_cdc = get_itf(idx);
|
||||
TU_ASSERT(p_cdc);
|
||||
|
||||
if ( ep_addr == p_cdc->stream.tx.ep_addr )
|
||||
{
|
||||
// invoke tx complete callback to possibly refill tx fifo
|
||||
if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx);
|
||||
|
||||
if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) )
|
||||
{
|
||||
// If there is no data left, a ZLP should be sent if:
|
||||
// - xferred_bytes is multiple of EP Packet size and not zero
|
||||
tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes);
|
||||
}
|
||||
}
|
||||
else if ( ep_addr == p_cdc->stream.rx.ep_addr )
|
||||
{
|
||||
tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes);
|
||||
|
||||
// invoke receive callback
|
||||
if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx);
|
||||
|
||||
// prepare for next transfer if needed
|
||||
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
|
||||
}else if ( ep_addr == p_cdc->ep_notif )
|
||||
{
|
||||
// TODO handle notification endpoint
|
||||
}else
|
||||
{
|
||||
TU_ASSERT(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Enumeration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
|
||||
{
|
||||
(void) rhport;
|
||||
(void) max_len;
|
||||
|
||||
// Only support ACM subclass
|
||||
// Protocol 0xFF can be RNDIS device for windows XP
|
||||
@ -170,17 +452,22 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
|
||||
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass &&
|
||||
0xFF != itf_desc->bInterfaceProtocol);
|
||||
|
||||
cdch_data_t * p_cdc = get_itf(dev_addr);
|
||||
uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len;
|
||||
|
||||
p_cdc->itf_num = itf_desc->bInterfaceNumber;
|
||||
p_cdc->itf_protocol = itf_desc->bInterfaceProtocol;
|
||||
cdch_interface_t * p_cdc = find_new_itf();
|
||||
TU_VERIFY(p_cdc);
|
||||
|
||||
//------------- Communication Interface -------------//
|
||||
uint16_t drv_len = tu_desc_len(itf_desc);
|
||||
p_cdc->daddr = daddr;
|
||||
p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber;
|
||||
p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass;
|
||||
p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol;
|
||||
p_cdc->line_state = 0;
|
||||
|
||||
//------------- Control Interface -------------//
|
||||
uint8_t const * p_desc = tu_desc_next(itf_desc);
|
||||
|
||||
// Communication Functional Descriptors
|
||||
while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
|
||||
while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) )
|
||||
{
|
||||
if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
|
||||
{
|
||||
@ -188,19 +475,18 @@ 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;
|
||||
}
|
||||
|
||||
drv_len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
|
||||
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
|
||||
// Open notification endpoint of control interface if any
|
||||
if (itf_desc->bNumEndpoints == 1)
|
||||
{
|
||||
// notification endpoint
|
||||
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc));
|
||||
tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
|
||||
|
||||
TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) );
|
||||
TU_ASSERT( tuh_edpt_open(daddr, desc_ep) );
|
||||
p_cdc->ep_notif = desc_ep->bEndpointAddress;
|
||||
|
||||
drv_len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
|
||||
@ -209,52 +495,96 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
|
||||
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
|
||||
{
|
||||
// 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 *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
|
||||
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer);
|
||||
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType &&
|
||||
TUSB_XFER_BULK == desc_ep->bmAttributes.xfer);
|
||||
|
||||
TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep));
|
||||
TU_ASSERT(tuh_edpt_open(daddr, desc_ep));
|
||||
|
||||
if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
|
||||
{
|
||||
p_cdc->ep_in = desc_ep->bEndpointAddress;
|
||||
tu_edpt_stream_open(&p_cdc->stream.rx, daddr, desc_ep);
|
||||
}else
|
||||
{
|
||||
p_cdc->ep_out = desc_ep->bEndpointAddress;
|
||||
tu_edpt_stream_open(&p_cdc->stream.tx, daddr, desc_ep);
|
||||
}
|
||||
|
||||
drv_len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next( p_desc );
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
||||
enum
|
||||
{
|
||||
(void) dev_addr; (void) itf_num;
|
||||
return true;
|
||||
CONFIG_SET_CONTROL_LINE_STATE,
|
||||
CONFIG_SET_LINE_CODING,
|
||||
CONFIG_COMPLETE
|
||||
};
|
||||
|
||||
static void process_cdc_config(tuh_xfer_t* xfer)
|
||||
{
|
||||
uintptr_t const state = xfer->user_data;
|
||||
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
|
||||
uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
|
||||
TU_ASSERT(idx != TUSB_INDEX_INVALID, );
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case CONFIG_SET_CONTROL_LINE_STATE:
|
||||
#if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
|
||||
TU_ASSERT( tuh_cdc_set_control_line_state(idx, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_cdc_config, CONFIG_SET_LINE_CODING), );
|
||||
break;
|
||||
#endif
|
||||
TU_ATTR_FALLTHROUGH;
|
||||
|
||||
case CONFIG_SET_LINE_CODING:
|
||||
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
{
|
||||
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
|
||||
TU_ASSERT( tuh_cdc_set_line_coding(idx, &line_coding, process_cdc_config, CONFIG_COMPLETE), );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
TU_ATTR_FALLTHROUGH;
|
||||
|
||||
case CONFIG_COMPLETE:
|
||||
if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx);
|
||||
|
||||
// Prepare for incoming data
|
||||
cdch_interface_t* p_cdc = get_itf(idx);
|
||||
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
|
||||
|
||||
// notify usbh that driver enumeration is complete
|
||||
// itf_num+1 to account for data interface as well
|
||||
usbh_driver_set_config_complete(xfer->daddr, itf_num+1);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
|
||||
bool cdch_set_config(uint8_t daddr, uint8_t itf_num)
|
||||
{
|
||||
(void) ep_addr;
|
||||
tuh_cdc_xfer_isr( dev_addr, event, 0, xferred_bytes );
|
||||
// fake transfer to kick-off process
|
||||
tusb_control_request_t request;
|
||||
request.wIndex = tu_htole16((uint16_t) itf_num);
|
||||
|
||||
tuh_xfer_t xfer;
|
||||
xfer.daddr = daddr;
|
||||
xfer.result = XFER_RESULT_SUCCESS;
|
||||
xfer.setup = &request;
|
||||
xfer.user_data = CONFIG_SET_CONTROL_LINE_STATE;
|
||||
|
||||
process_cdc_config(&xfer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cdch_close(uint8_t dev_addr)
|
||||
{
|
||||
TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, );
|
||||
|
||||
cdch_data_t * p_cdc = get_itf(dev_addr);
|
||||
tu_memclr(p_cdc, sizeof(cdch_data_t));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -34,89 +34,156 @@
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CDC APPLICATION PUBLIC API
|
||||
// Class Driver Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
/** \ingroup ClassDriver_CDC Communication Device Class (CDC)
|
||||
* \addtogroup CDC_Serial Serial
|
||||
* @{
|
||||
* \defgroup CDC_Serial_Host Host
|
||||
* @{ */
|
||||
|
||||
bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb);
|
||||
// Set Line Control state on enumeration/mounted: DTR ( bit 0), RTS (bit 1)
|
||||
#ifndef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0
|
||||
#endif
|
||||
|
||||
static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_xfer_cb_t complete_cb)
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
//#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
//#endif
|
||||
|
||||
// RX FIFO size
|
||||
#ifndef CFG_TUH_CDC_RX_BUFSIZE
|
||||
#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX
|
||||
#endif
|
||||
|
||||
// RX Endpoint size
|
||||
#ifndef CFG_TUH_CDC_RX_EPSIZE
|
||||
#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX
|
||||
#endif
|
||||
|
||||
// TX FIFO size
|
||||
#ifndef CFG_TUH_CDC_TX_BUFSIZE
|
||||
#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX
|
||||
#endif
|
||||
|
||||
// TX Endpoint size
|
||||
#ifndef CFG_TUH_CDC_TX_EPSIZE
|
||||
#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
typedef struct
|
||||
{
|
||||
return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb);
|
||||
uint8_t daddr;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
} tuh_cdc_itf_info_t;
|
||||
|
||||
// Get Interface index from device address + interface number
|
||||
// return TUSB_INDEX_INVALID (0xFF) if not found
|
||||
uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num);
|
||||
|
||||
// Get Interface information
|
||||
// return true if index is correct and interface is currently mounted
|
||||
bool tuh_cdc_itf_get_info(uint8_t idx, tuh_cdc_itf_info_t* info);
|
||||
|
||||
// Check if a interface is mounted
|
||||
bool tuh_cdc_mounted(uint8_t idx);
|
||||
|
||||
// Get current DTR status
|
||||
bool tuh_cdc_get_dtr(uint8_t idx);
|
||||
|
||||
// Get current RTS status
|
||||
bool tuh_cdc_get_rts(uint8_t idx);
|
||||
|
||||
// Check if interface is connected (DTR active)
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx)
|
||||
{
|
||||
return tuh_cdc_get_dtr(idx);
|
||||
}
|
||||
|
||||
static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_xfer_cb_t complete_cb)
|
||||
// Get local (saved/cached) version of line coding.
|
||||
// This function should return correct values if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding()
|
||||
// are invoked previously or CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined.
|
||||
// NOTE: This function does not make any USB transfer request to device.
|
||||
bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Write API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Get the number of bytes available for writing
|
||||
uint32_t tuh_cdc_write_available(uint8_t idx);
|
||||
|
||||
// Write to cdc interface
|
||||
uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize);
|
||||
|
||||
// Force sending data if possible, return number of forced bytes
|
||||
uint32_t tuh_cdc_write_flush(uint8_t idx);
|
||||
|
||||
// Clear the transmit FIFO
|
||||
bool tuh_cdc_write_clear(uint8_t idx);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Read API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Get the number of bytes available for reading
|
||||
uint32_t tuh_cdc_read_available(uint8_t idx);
|
||||
|
||||
// Read from cdc interface
|
||||
uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize);
|
||||
|
||||
// Get a byte from RX FIFO without removing it
|
||||
bool tuh_cdc_peek(uint8_t idx, uint8_t* ch);
|
||||
|
||||
// Clear the received FIFO
|
||||
bool tuh_cdc_read_clear (uint8_t idx);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Control Endpoint (Request) API
|
||||
// Each Function will make a USB transfer request to/from device
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Request to Set Control Line State: DTR (bit 0), RTS (bit 1)
|
||||
bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
|
||||
|
||||
// Request to Set Line Coding
|
||||
bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
|
||||
|
||||
// Request to Get Line Coding
|
||||
// Should only use if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() never got invoked and
|
||||
// CFG_TUH_CDC_LINE_CODING_ON_ENUM is not defined
|
||||
// bool tuh_cdc_get_line_coding(uint8_t idx, cdc_line_coding_t* coding);
|
||||
|
||||
// Connect by set both DTR, RTS
|
||||
static inline bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
|
||||
{
|
||||
return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb);
|
||||
return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data);
|
||||
}
|
||||
|
||||
/** \brief Check if device support CDC Serial interface or not
|
||||
* \param[in] dev_addr device address
|
||||
* \retval true if device supports
|
||||
* \retval false if device does not support or is not mounted
|
||||
*/
|
||||
bool tuh_cdc_serial_is_mounted(uint8_t dev_addr);
|
||||
|
||||
/** \brief Check if the interface is currently busy or not
|
||||
* \param[in] dev_addr device address
|
||||
* \param[in] pipeid value from \ref cdc_pipeid_t to indicate target pipe.
|
||||
* \retval true if the interface is busy, meaning the stack is still transferring/waiting data from/to device
|
||||
* \retval false if the interface is not busy, meaning the stack successfully transferred data from/to device
|
||||
* \note This function is used to check if previous transfer is complete (success or error), so that the next transfer
|
||||
* can be scheduled. User needs to make sure the corresponding interface is mounted
|
||||
* (by \ref tuh_cdc_serial_is_mounted) before calling this function.
|
||||
*/
|
||||
bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid);
|
||||
|
||||
/** \brief Perform USB OUT transfer to device
|
||||
* \param[in] dev_addr device address
|
||||
* \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
|
||||
* \param[in] length Number of bytes to be transferred via USB bus
|
||||
* \retval TUSB_ERROR_NONE on success
|
||||
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
|
||||
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
|
||||
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
|
||||
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
|
||||
* interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
|
||||
*/
|
||||
bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify);
|
||||
|
||||
/** \brief Perform USB IN transfer to get data from device
|
||||
* \param[in] dev_addr device address
|
||||
* \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
|
||||
* \param[in] length Number of bytes to be transferred via USB bus
|
||||
* \retval TUSB_ERROR_NONE on success
|
||||
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
|
||||
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
|
||||
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
|
||||
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
|
||||
* interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
|
||||
*/
|
||||
bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify);
|
||||
// Disconnect by clear both DTR, RTS
|
||||
static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
|
||||
{
|
||||
return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CDC APPLICATION CALLBACKS
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/** \brief Callback function that is invoked when an transferring event occurred
|
||||
* \param[in] dev_addr Address of device
|
||||
* \param[in] event an value from \ref xfer_result_t
|
||||
* \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe
|
||||
* \param[in] xferred_bytes Number of bytes transferred via USB bus
|
||||
* \note event can be one of following
|
||||
* - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
|
||||
* - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
|
||||
* - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
|
||||
* \note
|
||||
*/
|
||||
void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
|
||||
// Invoked when a device with CDC interface is mounted
|
||||
// idx is index of cdc interface in the internal pool.
|
||||
TU_ATTR_WEAK extern void tuh_cdc_mount_cb(uint8_t idx);
|
||||
|
||||
/// @} // group CDC_Serial_Host
|
||||
/// @}
|
||||
// Invoked when a device with CDC interface is unmounted
|
||||
TU_ATTR_WEAK extern void tuh_cdc_umount_cb(uint8_t idx);
|
||||
|
||||
// Invoked when received new data
|
||||
TU_ATTR_WEAK extern void tuh_cdc_rx_cb(uint8_t idx);
|
||||
|
||||
// Invoked when a TX is complete and therefore space becomes available in TX buffer
|
||||
TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
|
@ -62,6 +62,7 @@ typedef struct
|
||||
hidh_interface_t instances[CFG_TUH_HID];
|
||||
} hidh_device_t;
|
||||
|
||||
CFG_TUSB_MEM_SECTION
|
||||
static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX];
|
||||
|
||||
//------------- Internal prototypes -------------//
|
||||
@ -258,7 +259,7 @@ bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance)
|
||||
|
||||
if ( !usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size) )
|
||||
{
|
||||
usbh_edpt_claim(dev_addr, hid_itf->ep_in);
|
||||
usbh_edpt_release(dev_addr, hid_itf->ep_in);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,11 @@
|
||||
|
||||
#include "msc_host.h"
|
||||
|
||||
// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
|
||||
#define MSCH_DEBUG 2
|
||||
|
||||
#define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF
|
||||
//--------------------------------------------------------------------+
|
||||
@ -417,7 +422,7 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
||||
p_msc->configured = true;
|
||||
|
||||
//------------- Get Max Lun -------------//
|
||||
TU_LOG2("MSC Get Max Lun\r\n");
|
||||
TU_LOG_MSCH("MSC Get Max Lun\r\n");
|
||||
tusb_control_request_t const request =
|
||||
{
|
||||
.bmRequestType_bit =
|
||||
@ -456,7 +461,7 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer)
|
||||
p_msc->max_lun++; // MAX LUN is minus 1 by specs
|
||||
|
||||
// TODO multiple LUN support
|
||||
TU_LOG2("SCSI Test Unit Ready\r\n");
|
||||
TU_LOG_MSCH("SCSI Test Unit Ready\r\n");
|
||||
uint8_t const lun = 0;
|
||||
tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0);
|
||||
}
|
||||
@ -469,14 +474,14 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_d
|
||||
if (csw->status == 0)
|
||||
{
|
||||
// Unit is ready, read its capacity
|
||||
TU_LOG2("SCSI Read Capacity\r\n");
|
||||
TU_LOG_MSCH("SCSI Read Capacity\r\n");
|
||||
tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0);
|
||||
}else
|
||||
{
|
||||
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
|
||||
// with Request Sense to start working !!
|
||||
// TODO limit number of retries
|
||||
TU_LOG2("SCSI Request Sense\r\n");
|
||||
TU_LOG_MSCH("SCSI Request Sense\r\n");
|
||||
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete, 0));
|
||||
}
|
||||
|
||||
|
@ -392,7 +392,7 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
|
||||
|
||||
if (NCM_GET_NTB_PARAMETERS == request->bRequest)
|
||||
{
|
||||
tud_control_xfer(rhport, request, (void*)&ntb_parameters, sizeof(ntb_parameters));
|
||||
tud_control_xfer(rhport, request, (void*)(uintptr_t) &ntb_parameters, sizeof(ntb_parameters));
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -157,12 +157,14 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack
|
||||
static uint8_t termChar;
|
||||
static uint8_t termCharRequested = false;
|
||||
|
||||
osal_mutex_def_t usbtmcLockBuffer;
|
||||
static osal_mutex_t usbtmcLock;
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
static OSAL_MUTEX_DEF(usbtmcLockBuffer);
|
||||
#endif
|
||||
osal_mutex_t usbtmcLock;
|
||||
|
||||
// Our own private lock, mostly for the state variable.
|
||||
#define criticalEnter() do {osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0)
|
||||
#define criticalLeave() do {osal_mutex_unlock(usbtmcLock); } while (0)
|
||||
#define criticalEnter() do { (void) osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0)
|
||||
#define criticalLeave() do { (void) osal_mutex_unlock(usbtmcLock); } while (0)
|
||||
|
||||
bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState)
|
||||
{
|
||||
@ -362,9 +364,9 @@ bool tud_usbtmc_start_bus_read()
|
||||
case STATE_RCV:
|
||||
break;
|
||||
default:
|
||||
TU_VERIFY(false);
|
||||
return false;
|
||||
}
|
||||
TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, 64));
|
||||
TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_state.ep_bulk_out_buf, (uint16_t)usbtmc_state.ep_bulk_out_wMaxPacketSize));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -464,53 +466,52 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
||||
switch(usbtmc_state.state)
|
||||
{
|
||||
case STATE_IDLE:
|
||||
TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t));
|
||||
msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf);
|
||||
uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse);
|
||||
TU_VERIFY(msg->header.bTag == invInvTag);
|
||||
TU_VERIFY(msg->header.bTag != 0x00);
|
||||
{
|
||||
TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t));
|
||||
msg = (usbtmc_msg_generic_t*)(usbtmc_state.ep_bulk_out_buf);
|
||||
uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse);
|
||||
TU_VERIFY(msg->header.bTag == invInvTag);
|
||||
TU_VERIFY(msg->header.bTag != 0x00);
|
||||
|
||||
switch(msg->header.MsgID) {
|
||||
case USBTMC_MSGID_DEV_DEP_MSG_OUT:
|
||||
if(!handle_devMsgOutStart(rhport, msg, xferred_bytes))
|
||||
{
|
||||
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
|
||||
TU_VERIFY(false);
|
||||
}
|
||||
break;
|
||||
switch(msg->header.MsgID) {
|
||||
case USBTMC_MSGID_DEV_DEP_MSG_OUT:
|
||||
if(!handle_devMsgOutStart(rhport, msg, xferred_bytes))
|
||||
{
|
||||
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case USBTMC_MSGID_DEV_DEP_MSG_IN:
|
||||
TU_VERIFY(handle_devMsgIn(msg, xferred_bytes));
|
||||
break;
|
||||
case USBTMC_MSGID_DEV_DEP_MSG_IN:
|
||||
TU_VERIFY(handle_devMsgIn(msg, xferred_bytes));
|
||||
break;
|
||||
|
||||
#if (CFG_TUD_USBTMC_ENABLE_488)
|
||||
case USBTMC_MSGID_USB488_TRIGGER:
|
||||
// Spec says we halt the EP if we didn't declare we support it.
|
||||
TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger);
|
||||
TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg));
|
||||
case USBTMC_MSGID_USB488_TRIGGER:
|
||||
// Spec says we halt the EP if we didn't declare we support it.
|
||||
TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger);
|
||||
TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg));
|
||||
|
||||
break;
|
||||
break;
|
||||
#endif
|
||||
case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT:
|
||||
case USBTMC_MSGID_VENDOR_SPECIFIC_IN:
|
||||
default:
|
||||
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
|
||||
TU_VERIFY(false);
|
||||
return false;
|
||||
case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT:
|
||||
case USBTMC_MSGID_VENDOR_SPECIFIC_IN:
|
||||
default:
|
||||
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
case STATE_RCV:
|
||||
if(!handle_devMsgOut(rhport, usbtmc_state.ep_bulk_out_buf, xferred_bytes, xferred_bytes))
|
||||
{
|
||||
usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out);
|
||||
TU_VERIFY(false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case STATE_ABORTING_BULK_OUT:
|
||||
TU_VERIFY(false);
|
||||
return false; // Should be stalled by now, shouldn't have received a packet.
|
||||
return false;
|
||||
|
||||
case STATE_TX_REQUESTED:
|
||||
case STATE_TX_INITIATED:
|
||||
@ -518,7 +519,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
||||
case STATE_ABORTING_BULK_IN_SHORTED:
|
||||
case STATE_ABORTING_BULK_IN_ABORTED:
|
||||
default:
|
||||
TU_VERIFY(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(ep_addr == usbtmc_state.ep_bulk_in)
|
||||
@ -567,7 +568,6 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
|
||||
|
||||
default:
|
||||
TU_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (ep_addr == usbtmc_state.ep_int_in) {
|
||||
@ -871,16 +871,13 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
|
||||
case USB488_bREQUEST_LOCAL_LOCKOUT:
|
||||
{
|
||||
TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface
|
||||
TU_VERIFY(false);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
TU_VERIFY(false);
|
||||
return false;
|
||||
}
|
||||
TU_VERIFY(false);
|
||||
}
|
||||
|
||||
#endif /* CFG_TUD_TSMC */
|
||||
|
@ -66,7 +66,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
|
||||
#define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__)
|
||||
#define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__)
|
||||
#define TU_LOG_ARR(n, ...) TU_XSTRCAT3(TU_LOG, n, _ARR)(__VA_ARGS__)
|
||||
#define TU_LOG_VAR(n, ...) TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__)
|
||||
#define TU_LOG_PTR(n, ...) TU_XSTRCAT3(TU_LOG, n, _PTR)(__VA_ARGS__)
|
||||
#define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__)
|
||||
#define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__)
|
||||
#define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
|
||||
@ -76,7 +76,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
|
||||
#define TU_LOG1 tu_printf
|
||||
#define TU_LOG1_MEM tu_print_mem
|
||||
#define TU_LOG1_ARR(_x, _n) tu_print_arr((uint8_t const*)(_x), _n)
|
||||
#define TU_LOG1_VAR(_x) tu_print_arr((uint8_t const*)(_x), sizeof(*(_x)))
|
||||
#define TU_LOG1_PTR(_x) tu_print_arr((uint8_t const*)(_x), sizeof(*(_x)))
|
||||
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) )
|
||||
#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) )
|
||||
|
||||
@ -85,7 +85,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
|
||||
#define TU_LOG2 TU_LOG1
|
||||
#define TU_LOG2_MEM TU_LOG1_MEM
|
||||
#define TU_LOG2_ARR TU_LOG1_ARR
|
||||
#define TU_LOG2_VAR TU_LOG1_VAR
|
||||
#define TU_LOG2_PTR TU_LOG1_PTR
|
||||
#define TU_LOG2_INT TU_LOG1_INT
|
||||
#define TU_LOG2_HEX TU_LOG1_HEX
|
||||
#endif
|
||||
@ -95,7 +95,7 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
|
||||
#define TU_LOG3 TU_LOG1
|
||||
#define TU_LOG3_MEM TU_LOG1_MEM
|
||||
#define TU_LOG3_ARR TU_LOG1_ARR
|
||||
#define TU_LOG3_VAR TU_LOG1_VAR
|
||||
#define TU_LOG3_PTR TU_LOG1_PTR
|
||||
#define TU_LOG3_INT TU_LOG1_INT
|
||||
#define TU_LOG3_HEX TU_LOG1_HEX
|
||||
#endif
|
||||
@ -132,7 +132,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
|
||||
#ifndef TU_LOG
|
||||
#define TU_LOG(n, ...)
|
||||
#define TU_LOG_MEM(n, ...)
|
||||
#define TU_LOG_VAR(n, ...)
|
||||
#define TU_LOG_PTR(n, ...)
|
||||
#define TU_LOG_INT(n, ...)
|
||||
#define TU_LOG_HEX(n, ...)
|
||||
#define TU_LOG_LOCATION()
|
||||
@ -143,14 +143,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
|
||||
|
||||
#define TU_LOG0(...)
|
||||
#define TU_LOG0_MEM(...)
|
||||
#define TU_LOG0_VAR(...)
|
||||
#define TU_LOG0_PTR(...)
|
||||
#define TU_LOG0_INT(...)
|
||||
#define TU_LOG0_HEX(...)
|
||||
|
||||
#ifndef TU_LOG1
|
||||
#define TU_LOG1(...)
|
||||
#define TU_LOG1_MEM(...)
|
||||
#define TU_LOG1_VAR(...)
|
||||
#define TU_LOG1_PTR(...)
|
||||
#define TU_LOG1_INT(...)
|
||||
#define TU_LOG1_HEX(...)
|
||||
#endif
|
||||
@ -158,7 +158,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
|
||||
#ifndef TU_LOG2
|
||||
#define TU_LOG2(...)
|
||||
#define TU_LOG2_MEM(...)
|
||||
#define TU_LOG2_VAR(...)
|
||||
#define TU_LOG2_PTR(...)
|
||||
#define TU_LOG2_INT(...)
|
||||
#define TU_LOG2_HEX(...)
|
||||
#endif
|
||||
@ -166,7 +166,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
|
||||
#ifndef TU_LOG3
|
||||
#define TU_LOG3(...)
|
||||
#define TU_LOG3_MEM(...)
|
||||
#define TU_LOG3_VAR(...)
|
||||
#define TU_LOG3_PTR(...)
|
||||
#define TU_LOG3_INT(...)
|
||||
#define TU_LOG3_HEX(...)
|
||||
#endif
|
||||
|
@ -734,8 +734,6 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1
|
||||
|
||||
@param[in] f
|
||||
Pointer to the FIFO buffer to manipulate
|
||||
@param[in] offset
|
||||
Position to read from in the FIFO buffer with respect to read pointer
|
||||
@param[in] p_buffer
|
||||
Pointer to the place holder for data read from the buffer
|
||||
|
||||
|
@ -42,15 +42,13 @@ extern "C" {
|
||||
// within a certain number (see tu_fifo_overflow()).
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "osal/osal.h"
|
||||
|
||||
#define tu_fifo_mutex_t osal_mutex_t
|
||||
|
||||
// mutex is only needed for RTOS
|
||||
// for OS None, we don't get preempted
|
||||
#define CFG_FIFO_MUTEX (CFG_TUSB_OS != OPT_OS_NONE)
|
||||
|
||||
#if CFG_FIFO_MUTEX
|
||||
#include "osal/osal.h"
|
||||
#define tu_fifo_mutex_t osal_mutex_t
|
||||
#endif
|
||||
#define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED
|
||||
|
||||
/* Write/Read index is always in the range of:
|
||||
* 0 .. 2*depth-1
|
||||
@ -122,7 +120,7 @@ typedef struct
|
||||
volatile uint16_t wr_idx ; ///< write index
|
||||
volatile uint16_t rd_idx ; ///< read index
|
||||
|
||||
#if CFG_FIFO_MUTEX
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
tu_fifo_mutex_t mutex_wr;
|
||||
tu_fifo_mutex_t mutex_rd;
|
||||
#endif
|
||||
@ -155,13 +153,18 @@ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
|
||||
bool tu_fifo_clear(tu_fifo_t *f);
|
||||
bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);
|
||||
|
||||
#if CFG_FIFO_MUTEX
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tu_fifo_config_mutex(tu_fifo_t *f, tu_fifo_mutex_t wr_mutex, tu_fifo_mutex_t rd_mutex)
|
||||
{
|
||||
f->mutex_wr = wr_mutex;
|
||||
f->mutex_rd = rd_mutex;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex)
|
||||
|
||||
#endif
|
||||
|
||||
bool tu_fifo_write (tu_fifo_t* f, void const * p_data);
|
||||
|
@ -281,6 +281,10 @@
|
||||
// Default Values
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef TUP_MCU_MULTIPLE_CORE
|
||||
#define TUP_MCU_MULTIPLE_CORE 0
|
||||
#endif
|
||||
|
||||
#ifndef TUP_DCD_ENDPOINT_MAX
|
||||
#warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8"
|
||||
#define TUP_DCD_ENDPOINT_MAX 8
|
||||
|
@ -28,6 +28,8 @@
|
||||
#ifndef _TUSB_PRIVATE_H_
|
||||
#define _TUSB_PRIVATE_H_
|
||||
|
||||
// Internal Helper used by Host and Device Stack
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -39,8 +41,31 @@ typedef struct TU_ATTR_PACKED
|
||||
volatile uint8_t claimed : 1;
|
||||
}tu_edpt_state_t;
|
||||
|
||||
typedef struct {
|
||||
bool is_host; // host or device most
|
||||
union {
|
||||
uint8_t daddr;
|
||||
uint8_t rhport;
|
||||
uint8_t hwid;
|
||||
};
|
||||
uint8_t ep_addr;
|
||||
uint8_t ep_speed;
|
||||
|
||||
uint16_t ep_packetsize;
|
||||
uint16_t ep_bufsize;
|
||||
|
||||
// TODO xfer_fifo can skip this buffer
|
||||
uint8_t* ep_buf;
|
||||
|
||||
tu_fifo_t ff;
|
||||
|
||||
// mutex: read if ep rx, write if e tx
|
||||
OSAL_MUTEX_DEF(ff_mutex);
|
||||
|
||||
}tu_edpt_stream_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Helper used by Host and Device Stack
|
||||
// Endpoint
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Check if endpoint descriptor is valid per USB specs
|
||||
@ -58,6 +83,89 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
|
||||
// Release an endpoint with provided mutex
|
||||
bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint Stream
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Init an stream, should only be called once
|
||||
bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable,
|
||||
void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize);
|
||||
|
||||
// Open an stream for an endpoint
|
||||
// hwid is either device address (host mode) or rhport (device mode)
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep)
|
||||
{
|
||||
tu_fifo_clear(&s->ff);
|
||||
s->hwid = hwid;
|
||||
s->ep_addr = desc_ep->bEndpointAddress;
|
||||
s->ep_packetsize = tu_edpt_packet_size(desc_ep);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tu_edpt_stream_close(tu_edpt_stream_t* s)
|
||||
{
|
||||
s->hwid = 0;
|
||||
s->ep_addr = 0;
|
||||
}
|
||||
|
||||
// Clear fifo
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool tu_edpt_stream_clear(tu_edpt_stream_t* s)
|
||||
{
|
||||
return tu_fifo_clear(&s->ff);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Stream Write
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Write to stream
|
||||
uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize);
|
||||
|
||||
// Start an usb transfer if endpoint is not busy
|
||||
uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s);
|
||||
|
||||
// Start an zero-length packet if needed
|
||||
bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes);
|
||||
|
||||
// Get the number of bytes available for writing
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s)
|
||||
{
|
||||
return (uint32_t) tu_fifo_remaining(&s->ff);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Stream Read
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Read from stream
|
||||
uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize);
|
||||
|
||||
// Start an usb transfer if endpoint is not busy
|
||||
uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s);
|
||||
|
||||
// Must be called in the transfer complete callback
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes)
|
||||
{
|
||||
tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes);
|
||||
}
|
||||
|
||||
// Get the number of bytes available for reading
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s)
|
||||
{
|
||||
return (uint32_t) tu_fifo_count(&s->ff);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch)
|
||||
{
|
||||
return tu_fifo_peek(&s->ff, ch);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -69,6 +69,15 @@ typedef enum
|
||||
TUSB_DIR_IN_MASK = 0x80
|
||||
}tusb_dir_t;
|
||||
|
||||
enum
|
||||
{
|
||||
TUSB_EPSIZE_BULK_FS = 64,
|
||||
TUSB_EPSIZE_BULK_HS= 512,
|
||||
|
||||
TUSB_EPSIZE_ISO_FS_MAX = 1023,
|
||||
TUSB_EPSIZE_ISO_HS_MAX = 1024,
|
||||
};
|
||||
|
||||
/// Isochronous End Point Attributes
|
||||
typedef enum
|
||||
{
|
||||
@ -243,7 +252,6 @@ enum
|
||||
INTERFACE_INVALID_NUMBER = 0xff
|
||||
};
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00,
|
||||
@ -265,6 +273,11 @@ enum
|
||||
CONTROL_STAGE_ACK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TUSB_INDEX_INVALID = 0xff
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -39,13 +39,13 @@
|
||||
// USBD Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Debug level of USBD
|
||||
#define USBD_DBG 2
|
||||
|
||||
#ifndef CFG_TUD_TASK_QUEUE_SZ
|
||||
#define CFG_TUD_TASK_QUEUE_SZ 16
|
||||
#endif
|
||||
|
||||
// Debug level of USBD
|
||||
#define USBD_DBG 2
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Data
|
||||
//--------------------------------------------------------------------+
|
||||
@ -272,10 +272,12 @@ static uint8_t _usbd_rhport = RHPORT_INVALID;
|
||||
OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t);
|
||||
static osal_queue_t _usbd_q;
|
||||
|
||||
// Mutex for claiming endpoint, only needed when using with preempted RTOS
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
static osal_mutex_def_t _ubsd_mutexdef;
|
||||
static osal_mutex_t _usbd_mutex;
|
||||
// Mutex for claiming endpoint
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
static osal_mutex_def_t _ubsd_mutexdef;
|
||||
static osal_mutex_t _usbd_mutex;
|
||||
#else
|
||||
#define _usbd_mutex NULL
|
||||
#endif
|
||||
|
||||
|
||||
@ -389,7 +391,7 @@ bool tud_init (uint8_t rhport)
|
||||
|
||||
tu_varclr(&_usbd_dev);
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
// Init device mutex
|
||||
_usbd_mutex = osal_mutex_create(&_ubsd_mutexdef);
|
||||
TU_ASSERT(_usbd_mutex);
|
||||
@ -504,7 +506,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr)
|
||||
break;
|
||||
|
||||
case DCD_EVENT_SETUP_RECEIVED:
|
||||
TU_LOG_VAR(USBD_DBG, &event.setup_received);
|
||||
TU_LOG_PTR(USBD_DBG, &event.setup_received);
|
||||
TU_LOG(USBD_DBG, "\r\n");
|
||||
|
||||
// Mark as connected after receiving 1st setup packet.
|
||||
@ -1209,11 +1211,7 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr)
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir];
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
return tu_edpt_claim(ep_state, _usbd_mutex);
|
||||
#else
|
||||
return tu_edpt_claim(ep_state, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr)
|
||||
@ -1224,11 +1222,7 @@ bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr)
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir];
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
return tu_edpt_release(ep_state, _usbd_mutex);
|
||||
#else
|
||||
return tu_edpt_release(ep_state, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
|
@ -293,7 +293,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
|
||||
/* MIDI Streaming (MS) Interface */\
|
||||
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\
|
||||
/* MS Header */\
|
||||
7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN)
|
||||
7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN + 2 * TUD_MIDI_DESC_EP_LEN(_numcables))
|
||||
|
||||
#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \
|
||||
(uint8_t)(((_cablenum) - 1) * 4 + 1)
|
||||
@ -317,6 +317,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
|
||||
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, _stridx,\
|
||||
/* MS Out Jack (External), connected to In Jack Embedded */\
|
||||
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, _stridx
|
||||
|
||||
#define TUD_MIDI_DESC_JACK(_cablenum) TUD_MIDI_DESC_JACK_DESC(_cablenum, 0)
|
||||
|
||||
#define TUD_MIDI_DESC_EP_LEN(_numcables) (9 + 4 + (_numcables))
|
||||
@ -603,7 +604,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
|
||||
/* optional interrupt endpoint */ \
|
||||
// _int_pollingInterval : for LS/FS, expressed in frames (1ms each). 16 may be a good number?
|
||||
#define TUD_USBTMC_INT_DESCRIPTOR(_ep_interrupt, _ep_interrupt_size, _int_pollingInterval ) \
|
||||
7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), 0x16
|
||||
7, TUSB_DESC_ENDPOINT, _ep_interrupt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_interrupt_size), _int_pollingInterval
|
||||
|
||||
#define TUD_USBTMC_INT_DESCRIPTOR_LEN (7u)
|
||||
|
||||
|
151
src/host/usbh.c
151
src/host/usbh.c
@ -30,7 +30,6 @@
|
||||
|
||||
#include "host/hcd.h"
|
||||
#include "tusb.h"
|
||||
#include "common/tusb_private.h"
|
||||
#include "host/usbh_classdriver.h"
|
||||
#include "hub.h"
|
||||
|
||||
@ -46,8 +45,10 @@
|
||||
#define CFG_TUH_INTERFACE_MAX 8
|
||||
#endif
|
||||
|
||||
// Debug level of USBD
|
||||
#define USBH_DBG_LVL 2
|
||||
// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
|
||||
#define USBH_DEBUG 2
|
||||
|
||||
#define TU_LOG_USBH(...) TU_LOG(USBH_DEBUG, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH-HCD common data structure
|
||||
@ -212,28 +213,12 @@ static usbh_dev0_t _dev0;
|
||||
// TODO: hub can has its own simpler struct to save memory
|
||||
CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[TOTAL_DEVICES];
|
||||
|
||||
// Mutex for claiming endpoint, only needed when using with preempted RTOS
|
||||
#if TUSB_OPT_MUTEX
|
||||
static osal_mutex_def_t _usbh_mutexdef;
|
||||
static osal_mutex_t _usbh_mutex;
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void usbh_lock(void)
|
||||
{
|
||||
osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void usbh_unlock(void)
|
||||
{
|
||||
osal_mutex_unlock(_usbh_mutex);
|
||||
}
|
||||
|
||||
// Mutex for claiming endpoint
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
static osal_mutex_def_t _usbh_mutexdef;
|
||||
static osal_mutex_t _usbh_mutex;
|
||||
#else
|
||||
|
||||
#define _usbh_mutex NULL
|
||||
|
||||
#define usbh_lock()
|
||||
#define usbh_unlock()
|
||||
|
||||
#define _usbh_mutex NULL
|
||||
#endif
|
||||
|
||||
// Event queue
|
||||
@ -244,10 +229,10 @@ static osal_queue_t _usbh_q;
|
||||
CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
|
||||
static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
|
||||
|
||||
// Control transfer: since most controller does not support multiple control transfer
|
||||
// on multiple devices concurrently. And control transfer is not used much except enumeration
|
||||
// We will only execute control transfer one at a time.
|
||||
struct
|
||||
// Control transfers: since most controllers do not support multiple control transfers
|
||||
// on multiple devices concurrently and control transfers are not used much except for
|
||||
// enumeration, we will only execute control transfers one at a time.
|
||||
CFG_TUSB_MEM_SECTION struct
|
||||
{
|
||||
tusb_control_request_t request TU_ATTR_ALIGNED(4);
|
||||
uint8_t* buffer;
|
||||
@ -277,8 +262,6 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t
|
||||
// TODO rework time-related function later
|
||||
void osal_task_delay(uint32_t msec)
|
||||
{
|
||||
(void) msec;
|
||||
|
||||
const uint32_t start = hcd_frame_number(_usbh_controller);
|
||||
while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {}
|
||||
}
|
||||
@ -342,18 +325,20 @@ bool tuh_init(uint8_t controller_id)
|
||||
// skip if already initialized
|
||||
if ( tuh_inited() ) return true;
|
||||
|
||||
TU_LOG2("USBH init on controller %u\r\n", controller_id);
|
||||
TU_LOG2_INT(sizeof(usbh_device_t));
|
||||
TU_LOG2_INT(sizeof(hcd_event_t));
|
||||
TU_LOG2_INT(sizeof(_ctrl_xfer));
|
||||
TU_LOG2_INT(sizeof(tuh_xfer_t));
|
||||
TU_LOG_USBH("USBH init on controller %u\r\n", controller_id);
|
||||
TU_LOG_INT(USBH_DEBUG, sizeof(usbh_device_t));
|
||||
TU_LOG_INT(USBH_DEBUG, sizeof(hcd_event_t));
|
||||
TU_LOG_INT(USBH_DEBUG, sizeof(_ctrl_xfer));
|
||||
TU_LOG_INT(USBH_DEBUG, sizeof(tuh_xfer_t));
|
||||
TU_LOG_INT(USBH_DEBUG, sizeof(tu_fifo_t));
|
||||
TU_LOG_INT(USBH_DEBUG, sizeof(tu_edpt_stream_t));
|
||||
|
||||
// Event queue
|
||||
_usbh_q = osal_queue_create( &_usbh_qdef );
|
||||
TU_ASSERT(_usbh_q != NULL);
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
// Mutex
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
// Init mutex
|
||||
_usbh_mutex = osal_mutex_create(&_usbh_mutexdef);
|
||||
TU_ASSERT(_usbh_mutex);
|
||||
#endif
|
||||
@ -371,7 +356,7 @@ bool tuh_init(uint8_t controller_id)
|
||||
// Class drivers
|
||||
for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
|
||||
{
|
||||
TU_LOG2("%s init\r\n", usbh_class_drivers[drv_id].name);
|
||||
TU_LOG_USBH("%s init\r\n", usbh_class_drivers[drv_id].name);
|
||||
usbh_class_drivers[drv_id].init();
|
||||
}
|
||||
|
||||
@ -419,12 +404,12 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
||||
case HCD_EVENT_DEVICE_ATTACH:
|
||||
// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating
|
||||
// one device before enumerating another one.
|
||||
TU_LOG2("[%u:] USBH DEVICE ATTACH\r\n", event.rhport);
|
||||
TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport);
|
||||
enum_new_device(&event);
|
||||
break;
|
||||
|
||||
case HCD_EVENT_DEVICE_REMOVE:
|
||||
TU_LOG2("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port);
|
||||
TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port);
|
||||
process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port);
|
||||
|
||||
#if CFG_TUH_HUB
|
||||
@ -443,7 +428,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const ep_dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
|
||||
TU_LOG_USBH("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
|
||||
|
||||
if (event.dev_addr == 0)
|
||||
{
|
||||
@ -467,7 +452,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
||||
uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
|
||||
if(drv_id < USBH_CLASS_DRIVER_COUNT)
|
||||
{
|
||||
TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
|
||||
TU_LOG_USBH("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
|
||||
usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
|
||||
}
|
||||
else
|
||||
@ -537,8 +522,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
|
||||
|
||||
uint8_t const daddr = xfer->daddr;
|
||||
|
||||
// TODO probably better to use semaphore as resource management than mutex
|
||||
usbh_lock();
|
||||
(void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
|
||||
bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
|
||||
if (is_idle)
|
||||
@ -553,14 +537,16 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
|
||||
_ctrl_xfer.user_data = xfer->user_data;
|
||||
}
|
||||
|
||||
usbh_unlock();
|
||||
(void) osal_mutex_unlock(_usbh_mutex);
|
||||
|
||||
TU_VERIFY(is_idle);
|
||||
const uint8_t rhport = usbh_get_rhport(daddr);
|
||||
|
||||
TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->setup->bRequest] : "Unknown Request");
|
||||
TU_LOG2_VAR(xfer->setup);
|
||||
TU_LOG2("\r\n");
|
||||
TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr,
|
||||
(xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ?
|
||||
tu_str_std_request[xfer->setup->bRequest] : "Class Request");
|
||||
TU_LOG_PTR(USBH_DEBUG, xfer->setup);
|
||||
TU_LOG_USBH("\r\n");
|
||||
|
||||
if (xfer->complete_cb)
|
||||
{
|
||||
@ -597,14 +583,14 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage)
|
||||
{
|
||||
usbh_lock();
|
||||
(void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
_ctrl_xfer.stage = stage;
|
||||
usbh_unlock();
|
||||
(void) osal_mutex_unlock(_usbh_mutex);
|
||||
}
|
||||
|
||||
static void _xfer_complete(uint8_t daddr, xfer_result_t result)
|
||||
{
|
||||
TU_LOG2("\r\n");
|
||||
TU_LOG_USBH("\r\n");
|
||||
|
||||
// duplicate xfer since user can execute control transfer within callback
|
||||
tusb_control_request_t const request = _ctrl_xfer.request;
|
||||
@ -637,7 +623,11 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
|
||||
|
||||
if (XFER_RESULT_SUCCESS != result)
|
||||
{
|
||||
TU_LOG1("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED");
|
||||
TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes);
|
||||
#if CFG_TUSB_DEBUG == 1
|
||||
TU_LOG1_PTR(request);
|
||||
TU_LOG1("\r\n");
|
||||
#endif
|
||||
|
||||
// terminate transfer if any stage failed
|
||||
_xfer_complete(dev_addr, result);
|
||||
@ -658,8 +648,8 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
|
||||
case CONTROL_STAGE_DATA:
|
||||
if (request->wLength)
|
||||
{
|
||||
TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr);
|
||||
TU_LOG2_MEM(_ctrl_xfer.buffer, xferred_bytes, 2);
|
||||
TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr);
|
||||
TU_LOG_MEM(USBH_DEBUG, _ctrl_xfer.buffer, xferred_bytes, 2);
|
||||
}
|
||||
|
||||
_ctrl_xfer.actual_len = (uint16_t) xferred_bytes;
|
||||
@ -775,7 +765,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir];
|
||||
|
||||
TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
|
||||
TU_LOG_USBH(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
|
||||
|
||||
// Attempt to transfer on a busy endpoint, sound like an race condition !
|
||||
TU_ASSERT(ep_state->busy == 0);
|
||||
@ -791,7 +781,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
|
||||
|
||||
if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
|
||||
{
|
||||
TU_LOG2("OK\r\n");
|
||||
TU_LOG_USBH("OK\r\n");
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
@ -806,7 +796,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
|
||||
|
||||
static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
|
||||
{
|
||||
TU_LOG2("[%u:%u] Open EP0 with Size = %u\r\n", usbh_get_rhport(dev_addr), dev_addr, max_packet_size);
|
||||
TU_LOG_USBH("[%u:%u] Open EP0 with Size = %u\r\n", usbh_get_rhport(dev_addr), dev_addr, max_packet_size);
|
||||
|
||||
tusb_desc_endpoint_t ep0_desc =
|
||||
{
|
||||
@ -975,7 +965,7 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void*
|
||||
bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data)
|
||||
{
|
||||
TU_LOG2("HID Get Report Descriptor\r\n");
|
||||
TU_LOG_USBH("HID Get Report Descriptor\r\n");
|
||||
tusb_control_request_t const request =
|
||||
{
|
||||
.bmRequestType_bit =
|
||||
@ -1014,7 +1004,7 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_
|
||||
bool tuh_configuration_set(uint8_t daddr, uint8_t config_num,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data)
|
||||
{
|
||||
TU_LOG2("Set Configuration = %d\r\n", config_num);
|
||||
TU_LOG_USBH("Set Configuration = %d\r\n", config_num);
|
||||
|
||||
tusb_control_request_t const request =
|
||||
{
|
||||
@ -1118,11 +1108,11 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h
|
||||
(hub_port == 0 || dev->hub_port == hub_port) && // hub_port = 0 means all devices of downstream hub
|
||||
dev->connected)
|
||||
{
|
||||
TU_LOG2(" Address = %u\r\n", dev_addr);
|
||||
TU_LOG_USBH(" Address = %u\r\n", dev_addr);
|
||||
|
||||
if (is_hub_addr(dev_addr))
|
||||
{
|
||||
TU_LOG(USBH_DBG_LVL, "HUB address = %u is unmounted\r\n", dev_addr);
|
||||
TU_LOG(USBH_DEBUG, "HUB address = %u is unmounted\r\n", dev_addr);
|
||||
// If the device itself is a usb hub, unplug downstream devices.
|
||||
// FIXME un-roll recursive calls to prevent potential stack overflow
|
||||
process_device_unplugged(rhport, dev_addr, 0);
|
||||
@ -1135,7 +1125,7 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h
|
||||
// Close class driver
|
||||
for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
|
||||
{
|
||||
TU_LOG2("%s close\r\n", usbh_class_drivers[drv_id].name);
|
||||
TU_LOG_USBH("%s close\r\n", usbh_class_drivers[drv_id].name);
|
||||
usbh_class_drivers[drv_id].close(dev_addr);
|
||||
}
|
||||
|
||||
@ -1260,7 +1250,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
TU_ASSERT( usbh_edpt_control_open(addr0, 8), );
|
||||
|
||||
// Get first 8 bytes of device descriptor for Control Endpoint size
|
||||
TU_LOG2("Get 8 byte of Device Descriptor\r\n");
|
||||
TU_LOG_USBH("Get 8 byte of Device Descriptor\r\n");
|
||||
TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR), );
|
||||
}
|
||||
break;
|
||||
@ -1269,7 +1259,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
case ENUM_RESET_2:
|
||||
// TODO not used by now, but may be needed for some devices !?
|
||||
// Reset device again before Set Address
|
||||
TU_LOG2("Port reset2 \r\n");
|
||||
TU_LOG_USBH("Port reset2 \r\n");
|
||||
if (_dev0.hub_addr == 0)
|
||||
{
|
||||
// connected directly to roothub
|
||||
@ -1287,7 +1277,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
__attribute__((fallthrough));
|
||||
TU_ATTR_FALLTHROUGH;
|
||||
#endif
|
||||
|
||||
case ENUM_SET_ADDR:
|
||||
@ -1309,7 +1299,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size), );
|
||||
|
||||
// Get full device descriptor
|
||||
TU_LOG2("Get Device Descriptor\r\n");
|
||||
TU_LOG_USBH("Get Device Descriptor\r\n");
|
||||
TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC), );
|
||||
}
|
||||
break;
|
||||
@ -1330,7 +1320,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
|
||||
// Get 9-byte for total length
|
||||
uint8_t const config_idx = CONFIG_NUM - 1;
|
||||
TU_LOG2("Get Configuration[0] Descriptor (9 bytes)\r\n");
|
||||
TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n");
|
||||
TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), );
|
||||
}
|
||||
break;
|
||||
@ -1347,7 +1337,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
|
||||
// Get full configuration descriptor
|
||||
uint8_t const config_idx = CONFIG_NUM - 1;
|
||||
TU_LOG2("Get Configuration[0] Descriptor\r\n");
|
||||
TU_LOG_USBH("Get Configuration[0] Descriptor\r\n");
|
||||
TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), );
|
||||
}
|
||||
break;
|
||||
@ -1362,7 +1352,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
||||
|
||||
case ENUM_CONFIG_DRIVER:
|
||||
{
|
||||
TU_LOG2("Device configured\r\n");
|
||||
TU_LOG_USBH("Device configured\r\n");
|
||||
usbh_device_t* dev = get_device(daddr);
|
||||
TU_ASSERT(dev, );
|
||||
|
||||
@ -1402,7 +1392,7 @@ static bool enum_new_device(hcd_event_t* event)
|
||||
if ( !hcd_port_connect_status(_dev0.rhport) ) return true;
|
||||
|
||||
_dev0.speed = hcd_port_speed_get(_dev0.rhport );
|
||||
TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]);
|
||||
TU_LOG_USBH("%s Speed\r\n", tu_str_speed[_dev0.speed]);
|
||||
|
||||
// fake transfer to kick-off the enumeration process
|
||||
tuh_xfer_t xfer;
|
||||
@ -1459,7 +1449,7 @@ static bool enum_request_set_addr(void)
|
||||
uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
|
||||
TU_ASSERT(new_addr != 0);
|
||||
|
||||
TU_LOG2("Set Address = %d\r\n", new_addr);
|
||||
TU_LOG_USBH("Set Address = %d\r\n", new_addr);
|
||||
|
||||
usbh_device_t* new_dev = get_device(new_addr);
|
||||
|
||||
@ -1503,9 +1493,12 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
|
||||
{
|
||||
usbh_device_t* dev = get_device(dev_addr);
|
||||
|
||||
uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
|
||||
uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength);
|
||||
uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + total_len;
|
||||
uint8_t const* p_desc = tu_desc_next(desc_cfg);
|
||||
|
||||
TU_LOG_USBH("Parsing Configuration descriptor (wTotalLength = %u)\r\n", total_len);
|
||||
|
||||
// parse each interfaces
|
||||
while( p_desc < desc_end )
|
||||
{
|
||||
@ -1543,15 +1536,14 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
|
||||
TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t));
|
||||
|
||||
// Find driver for this interface
|
||||
uint8_t drv_id;
|
||||
for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
|
||||
for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
|
||||
{
|
||||
usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
|
||||
|
||||
if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) )
|
||||
{
|
||||
// open successfully
|
||||
TU_LOG2(" %s opened\r\n", driver->name);
|
||||
TU_LOG_USBH(" %s opened\r\n", driver->name);
|
||||
|
||||
// bind (associated) interfaces to found driver
|
||||
for(uint8_t i=0; i<assoc_itf_count; i++)
|
||||
@ -1571,7 +1563,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
|
||||
|
||||
if( drv_id >= USBH_CLASS_DRIVER_COUNT )
|
||||
{
|
||||
TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
|
||||
TU_LOG(USBH_DEBUG, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
|
||||
desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol);
|
||||
}
|
||||
}
|
||||
@ -1590,12 +1582,13 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
|
||||
for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++)
|
||||
{
|
||||
// continue with next valid interface
|
||||
// TODO skip IAD binding interface such as CDCs
|
||||
// IAD binding interface such as CDCs should return itf_num + 1 when complete
|
||||
// with usbh_driver_set_config_complete()
|
||||
uint8_t const drv_id = dev->itf2drv[itf_num];
|
||||
if (drv_id != DRVID_INVALID)
|
||||
{
|
||||
usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
|
||||
TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num);
|
||||
TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num);
|
||||
driver->set_config(dev_addr, itf_num);
|
||||
break;
|
||||
}
|
||||
@ -1608,7 +1601,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
|
||||
|
||||
if (is_hub_addr(dev_addr))
|
||||
{
|
||||
TU_LOG(USBH_DBG_LVL, "HUB address = %u is mounted\r\n", dev_addr);
|
||||
TU_LOG(USBH_DEBUG, "HUB address = %u is mounted\r\n", dev_addr);
|
||||
}else
|
||||
{
|
||||
// Invoke callback if available
|
||||
|
@ -29,11 +29,16 @@
|
||||
|
||||
#include "osal/osal.h"
|
||||
#include "common/tusb_fifo.h"
|
||||
#include "common/tusb_private.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS)
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -33,17 +33,24 @@
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
|
||||
// Return immediately
|
||||
#define OSAL_TIMEOUT_NOTIMEOUT (0)
|
||||
// Default timeout
|
||||
#define OSAL_TIMEOUT_NORMAL (10)
|
||||
// Wait forever
|
||||
#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX)
|
||||
|
||||
#define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER
|
||||
|
||||
typedef void (*osal_task_func_t)( void * );
|
||||
|
||||
// Timeout
|
||||
#define OSAL_TIMEOUT_NOTIMEOUT (0) // Return immediately
|
||||
#define OSAL_TIMEOUT_NORMAL (10) // Default timeout
|
||||
#define OSAL_TIMEOUT_WAIT_FOREVER (UINT32_MAX) // Wait forever
|
||||
#define OSAL_TIMEOUT_CONTROL_XFER OSAL_TIMEOUT_WAIT_FOREVER
|
||||
|
||||
// Mutex is required when using a preempted RTOS or MCU has multiple cores
|
||||
#if (CFG_TUSB_OS == OPT_OS_NONE) && !TUP_MCU_MULTIPLE_CORE
|
||||
#define OSAL_MUTEX_REQUIRED 0
|
||||
#define OSAL_MUTEX_DEF(_name) uint8_t :0
|
||||
#else
|
||||
#define OSAL_MUTEX_REQUIRED 1
|
||||
#define OSAL_MUTEX_DEF(_name) osal_mutex_def_t _name
|
||||
#endif
|
||||
|
||||
// OS thin implementation
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
#include "osal_none.h"
|
||||
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
|
@ -115,7 +115,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t se
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken);
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
|
||||
@ -189,7 +189,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken);
|
||||
|
||||
#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
|
||||
|
@ -82,6 +82,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s
|
||||
typedef osal_semaphore_def_t osal_mutex_def_t;
|
||||
typedef osal_semaphore_t osal_mutex_t;
|
||||
|
||||
#if OSAL_MUTEX_REQUIRED
|
||||
// Note: multiple cores MCUs usually do provide IPC API for mutex
|
||||
// or we can use std atomic function
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
|
||||
{
|
||||
mdef->count = 1;
|
||||
@ -98,6 +102,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
|
||||
return osal_semaphore_post(mutex_hdl, false);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define osal_mutex_create(_mdef) (NULL)
|
||||
#define osal_mutex_lock(_mutex_hdl, _ms) (true)
|
||||
#define osal_mutex_unlock(_mutex_hdl) (true)
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// QUEUE API
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -63,7 +63,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t se
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) {
|
||||
// TODO: implement
|
||||
rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -188,7 +188,7 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
|
||||
static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr)
|
||||
{
|
||||
for(ehci_link_t* prev = list_head;
|
||||
!prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head);
|
||||
!prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head) && prev != NULL;
|
||||
prev = list_next(prev) )
|
||||
{
|
||||
// TODO check type for ISO iTD and siTD
|
||||
|
208
src/tusb.c
208
src/tusb.c
@ -31,11 +31,18 @@
|
||||
#include "tusb.h"
|
||||
#include "common/tusb_private.h"
|
||||
|
||||
// TODO clean up
|
||||
#if CFG_TUD_ENABLED
|
||||
#include "device/usbd_pvt.h"
|
||||
#endif
|
||||
|
||||
#if CFG_TUH_ENABLED
|
||||
#include "host/usbh_classdriver.h"
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Public API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tusb_init(void)
|
||||
{
|
||||
#if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
|
||||
@ -67,18 +74,16 @@ bool tusb_inited(void)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Helper for both Host and Device stack
|
||||
// Endpoint Helper for both Host and Device stack
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
|
||||
{
|
||||
(void) mutex;
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
// pre-check to help reducing mutex lock
|
||||
TU_VERIFY((ep_state->busy == 0) && (ep_state->claimed == 0));
|
||||
osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
(void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
|
||||
// can only claim the endpoint if it is not busy and not claimed yet.
|
||||
bool const available = (ep_state->busy == 0) && (ep_state->claimed == 0);
|
||||
@ -87,9 +92,7 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
|
||||
ep_state->claimed = 1;
|
||||
}
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
osal_mutex_unlock(mutex);
|
||||
#endif
|
||||
(void) osal_mutex_unlock(mutex);
|
||||
|
||||
return available;
|
||||
}
|
||||
@ -98,9 +101,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
|
||||
{
|
||||
(void) mutex;
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
(void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
|
||||
// can only release the endpoint if it is claimed and not busy
|
||||
bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0);
|
||||
@ -109,9 +110,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
|
||||
ep_state->claimed = 0;
|
||||
}
|
||||
|
||||
#if TUSB_OPT_MUTEX
|
||||
osal_mutex_unlock(mutex);
|
||||
#endif
|
||||
(void) osal_mutex_unlock(mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -204,9 +203,184 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf,
|
||||
return len;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Debug
|
||||
*------------------------------------------------------------------*/
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint Stream Helper for both Host and Device stack
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable,
|
||||
void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize)
|
||||
{
|
||||
osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex);
|
||||
(void) new_mutex;
|
||||
(void) is_tx;
|
||||
|
||||
s->is_host = is_host;
|
||||
tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable);
|
||||
tu_fifo_config_mutex(&s->ff, is_tx ? new_mutex : NULL, is_tx ? NULL : new_mutex);
|
||||
|
||||
s->ep_buf = ep_buf;
|
||||
s->ep_bufsize = ep_bufsize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool stream_claim(tu_edpt_stream_t* s)
|
||||
{
|
||||
if (s->is_host)
|
||||
{
|
||||
#if CFG_TUH_ENABLED
|
||||
return usbh_edpt_claim(s->daddr, s->ep_addr);
|
||||
#endif
|
||||
}else
|
||||
{
|
||||
#if CFG_TUD_ENABLED
|
||||
return usbd_edpt_claim(s->rhport, s->ep_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool stream_xfer(tu_edpt_stream_t* s, uint16_t count)
|
||||
{
|
||||
if (s->is_host)
|
||||
{
|
||||
#if CFG_TUH_ENABLED
|
||||
return usbh_edpt_xfer(s->daddr, s->ep_addr, count ? s->ep_buf : NULL, count);
|
||||
#endif
|
||||
}else
|
||||
{
|
||||
#if CFG_TUD_ENABLED
|
||||
return usbd_edpt_xfer(s->rhport, s->ep_addr, count ? s->ep_buf : NULL, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool stream_release(tu_edpt_stream_t* s)
|
||||
{
|
||||
if (s->is_host)
|
||||
{
|
||||
#if CFG_TUH_ENABLED
|
||||
return usbh_edpt_release(s->daddr, s->ep_addr);
|
||||
#endif
|
||||
}else
|
||||
{
|
||||
#if CFG_TUD_ENABLED
|
||||
return usbd_edpt_release(s->rhport, s->ep_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Stream Write
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes)
|
||||
{
|
||||
// ZLP condition: no pending data, last transferred bytes is multiple of packet size
|
||||
TU_VERIFY( !tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize-1))) );
|
||||
|
||||
TU_VERIFY( stream_claim(s) );
|
||||
TU_ASSERT( stream_xfer(s, 0) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s)
|
||||
{
|
||||
// skip if no data
|
||||
TU_VERIFY( tu_fifo_count(&s->ff), 0 );
|
||||
|
||||
// Claim the endpoint
|
||||
TU_VERIFY( stream_claim(s), 0 );
|
||||
|
||||
// Pull data from FIFO -> EP buf
|
||||
uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize);
|
||||
|
||||
if ( count )
|
||||
{
|
||||
TU_ASSERT( stream_xfer(s, count), 0 );
|
||||
return count;
|
||||
}else
|
||||
{
|
||||
// Release endpoint since we don't make any transfer
|
||||
// Note: data is dropped if terminal is not connected
|
||||
stream_release(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize)
|
||||
{
|
||||
TU_VERIFY(bufsize); // TODO support ZLP
|
||||
|
||||
uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize);
|
||||
|
||||
// flush if fifo has more than packet size or
|
||||
// in rare case: fifo depth is configured too small (which never reach packet size)
|
||||
if ( (tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize) )
|
||||
{
|
||||
tu_edpt_stream_write_xfer(s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Stream Read
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s)
|
||||
{
|
||||
uint16_t available = tu_fifo_remaining(&s->ff);
|
||||
|
||||
// Prepare for incoming data but only allow what we can store in the ring buffer.
|
||||
// TODO Actually we can still carry out the transfer, keeping count of received bytes
|
||||
// and slowly move it to the FIFO when read().
|
||||
// This pre-check reduces endpoint claiming
|
||||
TU_VERIFY(available >= s->ep_packetsize);
|
||||
|
||||
// claim endpoint
|
||||
TU_VERIFY(stream_claim(s), 0);
|
||||
|
||||
// get available again since fifo can be changed before endpoint is claimed
|
||||
available = tu_fifo_remaining(&s->ff);
|
||||
|
||||
if ( available >= s->ep_packetsize )
|
||||
{
|
||||
// multiple of packet size limit by ep bufsize
|
||||
uint16_t count = (uint16_t) (available & ~(s->ep_packetsize -1));
|
||||
count = tu_min16(count, s->ep_bufsize);
|
||||
|
||||
TU_ASSERT( stream_xfer(s, count), 0 );
|
||||
|
||||
return count;
|
||||
}else
|
||||
{
|
||||
// Release endpoint since we don't make any transfer
|
||||
stream_release(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize);
|
||||
tu_edpt_stream_read_xfer(s);
|
||||
return num_read;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Debug
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#if CFG_TUSB_DEBUG
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -256,6 +256,10 @@ typedef int make_iso_compilers_happy;
|
||||
// For backward compatible
|
||||
#define TUSB_OPT_HOST_ENABLED CFG_TUH_ENABLED
|
||||
|
||||
// highspeed support indicator
|
||||
#define TUH_OPT_HIGH_SPEED (CFG_TUH_MAX_SPEED ? (CFG_TUH_MAX_SPEED & OPT_MODE_HIGH_SPEED) : TUP_RHPORT_HIGHSPEED)
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TODO move later
|
||||
//--------------------------------------------------------------------+
|
||||
@ -299,9 +303,6 @@ typedef int make_iso_compilers_happy;
|
||||
#define CFG_TUSB_OS_INC_PATH
|
||||
#endif
|
||||
|
||||
// mutex is only needed for RTOS TODO also required with multiple core MCUs
|
||||
#define TUSB_OPT_MUTEX (CFG_TUSB_OS != OPT_OS_NONE)
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Device Options (Default)
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -16,9 +16,9 @@ __check_defined = \
|
||||
|
||||
#-------------- Fuzz harness compiler ------------
|
||||
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
GDB = gdb
|
||||
CC ?= clang
|
||||
CXX ?= clang++
|
||||
GDB ?= gdb
|
||||
OBJCOPY = objcopy
|
||||
SIZE = size
|
||||
MKDIR = mkdir
|
||||
@ -34,6 +34,13 @@ else
|
||||
PYTHON = python3
|
||||
endif
|
||||
|
||||
#-------------- Fuzz harness flags ------------
|
||||
COVERAGE_FLAGS ?= -fsanitize-coverage=trace-pc-guard
|
||||
SANITIZER_FLAGS ?= -fsanitize=fuzzer \
|
||||
-fsanitize=address
|
||||
|
||||
CFLAGS += $(COVERAGE_FLAGS) $(SANITIZER_FLAGS)
|
||||
|
||||
#-------------- Source files and compiler flags --------------
|
||||
|
||||
|
||||
@ -42,9 +49,6 @@ INC += $(TOP)/test
|
||||
# Compiler Flags
|
||||
CFLAGS += \
|
||||
-ggdb \
|
||||
-fsanitize=fuzzer \
|
||||
-fsanitize=address \
|
||||
-fsanitize=undefined \
|
||||
-fdata-sections \
|
||||
-ffunction-sections \
|
||||
-fno-strict-aliasing \
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "unity.h"
|
||||
|
||||
// Files to test
|
||||
#include "osal/osal.h"
|
||||
#include "tusb_fifo.h"
|
||||
#include "tusb.h"
|
||||
#include "usbd.h"
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "unity.h"
|
||||
|
||||
// Files to test
|
||||
#include "osal/osal.h"
|
||||
#include "tusb_fifo.h"
|
||||
#include "tusb.h"
|
||||
#include "usbd.h"
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
|
||||
#include "osal/osal.h"
|
||||
#include "tusb_fifo.h"
|
||||
|
||||
#define FIFO_SIZE 64
|
||||
|
Loading…
x
Reference in New Issue
Block a user