apply TUD_EPBUF_DEF for device: bth, dfu, hid, msc

This commit is contained in:
hathach
2024-11-22 12:25:37 +07:00
parent f148670753
commit 090964cd1b
6 changed files with 266 additions and 301 deletions

View File

@@ -67,28 +67,27 @@ typedef struct {
OSAL_MUTEX_DEF(rx_ff_mutex);
OSAL_MUTEX_DEF(tx_ff_mutex);
// Endpoint Transfer buffer
union {
CFG_TUD_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE];
TUD_DCACHE_PADDING;
};
union {
CFG_TUD_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE];
TUD_DCACHE_PADDING;
};
} cdcd_interface_t;
#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
typedef struct {
TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE);
TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE);
} cdcd_epbuf_t;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
static tud_cdc_configure_fifo_t _cdcd_fifo_cfg;
static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
uint8_t const rhport = 0;
static bool _prep_out_transaction(uint8_t itf) {
const uint8_t rhport = 0;
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Skip if usb is not ready yet
TU_VERIFY(tud_ready() && p_cdc->ep_out);
@@ -99,7 +98,7 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// 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 >= sizeof(p_cdc->epout_buf));
TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE);
// claim endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out));
@@ -107,9 +106,9 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&p_cdc->rx_ff);
if ( available >= sizeof(p_cdc->epout_buf) ) {
return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
}else {
if (available >= CFG_TUD_CDC_EP_BUFSIZE) {
return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE);
} else {
// Release endpoint since we don't make any transfer
usbd_edpt_release(rhport, p_cdc->ep_out);
return false;
@@ -120,7 +119,7 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// APPLICATION API
//--------------------------------------------------------------------+
bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg) {
bool tud_cdc_configure_fifo(const tud_cdc_configure_fifo_t* cfg) {
TU_VERIFY(cfg);
_cdcd_fifo_cfg = (*cfg);
return true;
@@ -157,7 +156,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) {
uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
_prep_out_transaction(p_cdc);
_prep_out_transaction(itf);
return num_read;
}
@@ -168,13 +167,13 @@ bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) {
void tud_cdc_n_read_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
tu_fifo_clear(&p_cdc->rx_ff);
_prep_out_transaction(p_cdc);
_prep_out_transaction(itf);
}
//--------------------------------------------------------------------+
// WRITE API
//--------------------------------------------------------------------+
uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
@@ -192,23 +191,26 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
uint32_t tud_cdc_n_write_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Skip if usb is not ready yet
TU_VERIFY(tud_ready(), 0);
// No data to send
if (!tu_fifo_count(&p_cdc->tx_ff)) return 0;
if (!tu_fifo_count(&p_cdc->tx_ff)) {
return 0;
}
uint8_t const rhport = 0;
const uint8_t rhport = 0;
// Claim the endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 0);
// Pull data from FIFO
uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE);
if (count) {
TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0);
TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_epbuf->epin, count), 0);
return count;
} else {
// Release endpoint since we don't make any transfer
@@ -292,32 +294,37 @@ void cdcd_reset(uint8_t rhport) {
cdcd_interface_t* p_cdc = &_cdcd_itf[i];
tu_memclr(p_cdc, ITF_MEM_RESET_SIZE);
if (!_cdcd_fifo_cfg.rx_persistent) tu_fifo_clear(&p_cdc->rx_ff);
if (!_cdcd_fifo_cfg.tx_persistent) tu_fifo_clear(&p_cdc->tx_ff);
if (!_cdcd_fifo_cfg.rx_persistent) {
tu_fifo_clear(&p_cdc->rx_ff);
}
if (!_cdcd_fifo_cfg.tx_persistent) {
tu_fifo_clear(&p_cdc->tx_ff);
}
tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
}
}
uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) {
// Only support ACM subclass
TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
// Find available interface
cdcd_interface_t* p_cdc = NULL;
for (uint8_t cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) {
if (_cdcd_itf[cdc_id].ep_in == 0) {
p_cdc = &_cdcd_itf[cdc_id];
cdcd_interface_t* p_cdc;
uint8_t cdc_id;
for (cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) {
p_cdc = &_cdcd_itf[cdc_id];
if (p_cdc->ep_in == 0) {
break;
}
}
TU_ASSERT(p_cdc, 0);
TU_ASSERT(cdc_id < CFG_TUD_CDC, 0);
//------------- Control Interface -------------//
p_cdc->itf_num = itf_desc->bInterfaceNumber;
uint16_t drv_len = sizeof(tusb_desc_interface_t);
uint8_t const* p_desc = tu_desc_next(itf_desc);
const uint8_t* p_desc = tu_desc_next(itf_desc);
// Communication Functional Descriptors
while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) {
@@ -327,7 +334,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
// notification endpoint
tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc;
const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc;
TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
p_cdc->ep_notif = desc_ep->bEndpointAddress;
@@ -338,7 +345,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
//------------- Data Interface (if any) -------------//
if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) {
(TUSB_CLASS_CDC_DATA == ((const tusb_desc_interface_t*) p_desc)->bInterfaceClass)) {
// next to endpoint descriptor
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
@@ -350,7 +357,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
}
// Prepare for incoming data
_prep_out_transaction(p_cdc);
_prep_out_transaction(cdc_id);
return drv_len;
}
@@ -358,19 +365,21 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
uint8_t itf = 0;
cdcd_interface_t* p_cdc = _cdcd_itf;
uint8_t itf;
cdcd_interface_t* p_cdc;
// Identify which interface to use
for (;; itf++, p_cdc++) {
if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
if (p_cdc->itf_num == request->wIndex) break;
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
p_cdc = &_cdcd_itf[itf];
if (p_cdc->itf_num == request->wIndex) {
break;
}
}
TU_VERIFY(itf < CFG_TUD_CDC);
switch (request->bRequest) {
case CDC_REQUEST_SET_LINE_CODING:
@@ -378,7 +387,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
TU_LOG_DRV(" Set Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
} else if (stage == CONTROL_STAGE_ACK) {
if (tud_cdc_line_coding_cb) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
if (tud_cdc_line_coding_cb) {
tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
}
}
break;
@@ -409,7 +420,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
// Invoke callback
if (tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts);
if (tud_cdc_line_state_cb) {
tud_cdc_line_state_cb(itf, dtr, rts);
}
}
break;
@@ -418,7 +431,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
tud_control_status(rhport, request);
} else if (stage == CONTROL_STAGE_ACK) {
TU_LOG_DRV(" Send Break\r\n");
if (tud_cdc_send_break_cb) tud_cdc_send_break_cb(itf, request->wValue);
if (tud_cdc_send_break_cb) {
tud_cdc_send_break_cb(itf, request->wValue);
}
}
break;
@@ -438,28 +453,33 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Identify which interface to use
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
p_cdc = &_cdcd_itf[itf];
if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) break;
if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) {
break;
}
}
TU_ASSERT(itf < CFG_TUD_CDC);
cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// 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_epbuf->epout, (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)) {
for (uint32_t i = 0; i < xferred_bytes; i++) {
if ((p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
if ((p_cdc->wanted_char == p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
}
}
}
// invoke receive callback (if there is still data)
if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf);
if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) {
tud_cdc_rx_cb(itf);
}
// prepare for OUT transaction
_prep_out_transaction(p_cdc);
_prep_out_transaction(itf);
}
// Data sent to host, we continue to fetch from tx fifo to send.
@@ -467,7 +487,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Though maybe the baudrate is not really important !!!
if (ep_addr == p_cdc->ep_in) {
// invoke transmit callback to possibly refill tx fifo
if (tud_cdc_tx_complete_cb) tud_cdc_tx_complete_cb(itf);
if (tud_cdc_tx_complete_cb) {
tud_cdc_tx_complete_cb(itf);
}
if (0 == tud_cdc_n_write_flush(itf)) {
// If there is no data left, a ZLP should be sent if