diff options
| author | Zixun LI <[email protected]> | 2025-11-27 12:01:33 +0100 |
|---|---|---|
| committer | Zixun LI <[email protected]> | 2025-11-27 12:01:33 +0100 |
| commit | 2e8d193c732bb211ebff8badff16a84775db42ff (patch) | |
| tree | 9a3410e65711df25559524b760447ff68fdd316a /src/class | |
| parent | b997ec725812d2f6a573610ba0dd817f271eddea (diff) | |
| parent | 5ef55bfa30d6f8cf175b3d327f621c76aae7b138 (diff) | |
Merge remote-tracking branch 'tinyusb/master' into hcd_fsdev
Signed-off-by: Zixun LI <[email protected]>
Diffstat (limited to 'src/class')
| -rw-r--r-- | src/class/cdc/cdc_device.c | 91 | ||||
| -rw-r--r-- | src/class/cdc/cdc_device.h | 38 | ||||
| -rw-r--r-- | src/class/midi/midi_device.c | 26 | ||||
| -rw-r--r-- | src/class/vendor/vendor_device.c | 47 |
4 files changed, 124 insertions, 78 deletions
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 9e62c6509..7ef8aa738 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -66,6 +66,8 @@ typedef struct { #define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, line_coding) +// Skip local EP buffer if dedicated hw FIFO is supported + #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 typedef struct { TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE); TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE); @@ -75,6 +77,9 @@ typedef struct { #endif } cdcd_epbuf_t; +CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; +#endif + //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ @@ -115,7 +120,6 @@ TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ 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_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); TU_ATTR_ALWAYS_INLINE static inline uint8_t find_cdc_itf(uint8_t ep_addr) { @@ -166,40 +170,22 @@ void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t *coding) { } #if CFG_TUD_CDC_NOTIFY -bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *state) { +bool tud_cdc_n_notify_msg(uint8_t itf, cdc_notify_msg_t *msg) { TU_VERIFY(itf < CFG_TUD_CDC); - cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf]; + const cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); - cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify; - notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF; - notify_msg->request.bRequest = CDC_NOTIF_SERIAL_STATE; - notify_msg->request.wValue = 0; - notify_msg->request.wIndex = p_cdc->itf_num; - notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t); - notify_msg->serial_state = *state; - - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t), false); -} - -bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) { - TU_VERIFY(itf < CFG_TUD_CDC); - cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf]; - TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); + #if CFG_TUD_EDPT_DEDICATED_HWFIFO + cdc_notify_msg_t *msg_epbuf = msg; + #else + cdc_notify_msg_t *msg_epbuf = &_cdcd_epbuf[itf].epnotify; + *msg_epbuf = *msg; + #endif - cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify; - notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF; - notify_msg->request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE; - notify_msg->request.wValue = 0; - notify_msg->request.wIndex = p_cdc->itf_num; - notify_msg->request.wLength = sizeof(cdc_notify_conn_speed_change_t); - notify_msg->conn_speed_change = *conn_speed_change; + msg_epbuf->request.wIndex = p_cdc->itf_num; - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t), false); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)msg_epbuf, 8 + msg_epbuf->request.wLength, false); } #endif @@ -268,8 +254,6 @@ void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t *p_cdc = &_cdcd_itf[i]; - cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; - p_cdc->wanted_char = (char) -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 @@ -278,14 +262,23 @@ void cdcd_init(void) { p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; + #if CFG_TUD_EDPT_DEDICATED_HWFIFO + uint8_t *epout_buf = NULL; + uint8_t *epin_buf = NULL; + #else + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; + uint8_t *epout_buf = p_epbuf->epout; + uint8_t *epin_buf = p_epbuf->epin; + #endif + tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, - p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); + epout_buf, CFG_TUD_CDC_EP_BUFSIZE); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable tu_edpt_stream_init(&p_cdc->stream.tx, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, - p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); + p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE); } } @@ -481,11 +474,35 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == stream_rx->ep_addr) { tu_edpt_stream_read_xfer_complete(stream_rx, xferred_bytes); - // Check for wanted char and invoke wanted callback (multiple times if multiple wanted received) + // Check for wanted char and invoke wanted callback if (((signed char)p_cdc->wanted_char) != -1) { - for (uint32_t i = 0; i < xferred_bytes; i++) { - if ((p_cdc->wanted_char == (char)stream_rx->ep_buf[i]) && !tu_edpt_stream_empty(stream_rx)) { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + tu_fifo_buffer_info_t buf_info; + tu_fifo_get_read_info(&stream_rx->ff, &buf_info); + + // find backward + uint8_t *ptr; + if (buf_info.wrapped.len > 0) { + ptr = buf_info.wrapped.ptr + buf_info.wrapped.len - 1; // last byte of wrap buffer + } else if (buf_info.linear.len > 0) { + ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer + } else { + ptr = NULL; // no data + } + + if (ptr != NULL) { + for (uint32_t i = 0; i < xferred_bytes; i++) { + if (p_cdc->wanted_char == (char)*ptr) { + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + break; // only invoke once per transfer, even if multiple wanted chars are present + } + + if (ptr == buf_info.wrapped.ptr) { + ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer + } else if (ptr == buf_info.linear.ptr) { + break; // reached the beginning + } else { + ptr--; + } } } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 6f21af4f3..0809b578f 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -36,6 +36,14 @@ #define CFG_TUD_CDC_NOTIFY 0 #endif +#ifndef CFG_TUD_CDC_TX_BUFSIZE + #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#endif + +#ifndef CFG_TUD_CDC_RX_BUFSIZE + #define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#endif + #if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE @@ -133,11 +141,37 @@ bool tud_cdc_n_write_clear(uint8_t itf); #if CFG_TUD_CDC_NOTIFY +bool tud_cdc_n_notify_msg(uint8_t itf, cdc_notify_msg_t *msg); + // Send UART status notification: DCD, DSR etc .. -bool tud_cdc_n_notify_uart_state(uint8_t itf, const cdc_notify_uart_state_t *state); +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_n_notify_uart_state(uint8_t itf, + const cdc_notify_uart_state_t *state) { + cdc_notify_msg_t notify_msg; + notify_msg.request.bmRequestType = CDC_REQ_TYPE_NOTIF; + notify_msg.request.bRequest = CDC_NOTIF_SERIAL_STATE; + notify_msg.request.wValue = 0; + notify_msg.request.wIndex = 0; // filled later + notify_msg.request.wLength = sizeof(cdc_notify_uart_state_t); + notify_msg.serial_state = *state; + return tud_cdc_n_notify_msg(itf, ¬ify_msg); +} // Send connection speed change notification -bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change); +TU_ATTR_ALWAYS_INLINE static inline bool +tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t *conn_speed_change) { + cdc_notify_msg_t notify_msg; + notify_msg.request.bmRequestType = CDC_REQ_TYPE_NOTIF; + notify_msg.request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE; + notify_msg.request.wValue = 0; + notify_msg.request.wIndex = 0; // filled later + notify_msg.request.wLength = sizeof(cdc_notify_conn_speed_change_t); + notify_msg.conn_speed_change = *conn_speed_change; + return tud_cdc_n_notify_msg(itf, ¬ify_msg); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_msg(cdc_notify_msg_t *msg) { + return tud_cdc_n_notify_msg(0, msg); +} TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_uart_state(const cdc_notify_uart_state_t* state) { return tud_cdc_n_notify_uart_state(0, state); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index b20903d68..8d1dc7d4a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (CFG_TUD_ENABLED && CFG_TUD_MIDI) +#if CFG_TUD_ENABLED && CFG_TUD_MIDI //--------------------------------------------------------------------+ // INCLUDE @@ -71,20 +71,21 @@ typedef struct { static midid_interface_t _midid_itf[CFG_TUD_MIDI]; -// Endpoint Transfer buffer + #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 +// Endpoint Transfer buffer: not used if dedicated hw FIFO is available typedef struct { TUD_EPBUF_DEF(epin, CFG_TUD_MIDI_EP_BUFSIZE); TUD_EPBUF_DEF(epout, CFG_TUD_MIDI_EP_BUFSIZE); } midid_epbuf_t; CFG_TUD_MEM_SECTION static midid_epbuf_t _midid_epbuf[CFG_TUD_MIDI]; + #endif //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ bool tud_midi_n_mounted (uint8_t itf) { midid_interface_t *p_midi = &_midid_itf[itf]; - const bool tx_opened = tu_edpt_stream_is_opened(&p_midi->ep_stream.tx); const bool rx_opened = tu_edpt_stream_is_opened(&p_midi->ep_stream.rx); return tx_opened && rx_opened; @@ -313,18 +314,23 @@ uint32_t tud_midi_n_packet_write_n(uint8_t itf, const uint8_t packets[], uint32_ //--------------------------------------------------------------------+ void midid_init(void) { tu_memclr(_midid_itf, sizeof(_midid_itf)); - for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { midid_interface_t *p_midi = &_midid_itf[i]; + + #if CFG_TUD_EDPT_DEDICATED_HWFIFO + uint8_t *epout_buf = NULL; + uint8_t *epin_buf = NULL; + #else midid_epbuf_t *p_epbuf = &_midid_epbuf[i]; + uint8_t *epout_buf = p_epbuf->epout; + uint8_t *epin_buf = p_epbuf->epin; + #endif - tu_edpt_stream_init( - &p_midi->ep_stream.rx, false, false, false, p_midi->ep_stream.rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, - p_epbuf->epout, CFG_TUD_MIDI_EP_BUFSIZE); + tu_edpt_stream_init(&p_midi->ep_stream.rx, false, false, false, p_midi->ep_stream.rx_ff_buf, + CFG_TUD_MIDI_RX_BUFSIZE, epout_buf, CFG_TUD_MIDI_EP_BUFSIZE); - tu_edpt_stream_init( - &p_midi->ep_stream.tx, false, true, false, p_midi->ep_stream.tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, p_epbuf->epin, - CFG_TUD_MIDI_EP_BUFSIZE); + tu_edpt_stream_init(&p_midi->ep_stream.tx, false, true, false, p_midi->ep_stream.tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, + epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); } } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 7da4d2239..c7903375d 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -37,6 +37,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { + uint8_t rhport; uint8_t itf_num; /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -97,32 +98,26 @@ bool tud_vendor_n_mounted(uint8_t itf) { uint32_t tud_vendor_n_available(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - return tu_edpt_stream_read_available(&p_itf->rx.stream); } bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) { TU_VERIFY(itf < CFG_TUD_VENDOR); vendord_interface_t* p_itf = &_vendord_itf[itf]; - return tu_edpt_stream_peek(&p_itf->rx.stream, u8); } uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_read(rhport, &p_itf->rx.stream, buffer, bufsize); + return tu_edpt_stream_read(p_itf->rhport, &p_itf->rx.stream, buffer, bufsize); } void tud_vendor_n_read_flush (uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, ); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - tu_edpt_stream_clear(&p_itf->rx.stream); - tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream); + tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->rx.stream); } //--------------------------------------------------------------------+ @@ -131,25 +126,19 @@ void tud_vendor_n_read_flush (uint8_t itf) { uint32_t tud_vendor_n_write (uint8_t itf, const void* buffer, uint32_t bufsize) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_write(rhport, &p_itf->tx.stream, buffer, (uint16_t) bufsize); + return tu_edpt_stream_write(p_itf->rhport, &p_itf->tx.stream, buffer, (uint16_t)bufsize); } uint32_t tud_vendor_n_write_flush (uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream); + return tu_edpt_stream_write_xfer(p_itf->rhport, &p_itf->tx.stream); } uint32_t tud_vendor_n_write_available (uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_write_available(rhport, &p_itf->tx.stream); + return tu_edpt_stream_write_available(p_itf->rhport, &p_itf->tx.stream); } //--------------------------------------------------------------------+ @@ -162,23 +151,21 @@ void vendord_init(void) { vendord_interface_t* p_itf = &_vendord_itf[i]; vendord_epbuf_t* p_epbuf = &_vendord_epbuf[i]; - uint8_t* rx_ff_buf = - #if CFG_TUD_VENDOR_RX_BUFSIZE > 0 - p_itf->rx.ff_buf; - #else - NULL; - #endif + #if CFG_TUD_VENDOR_RX_BUFSIZE > 0 + uint8_t *rx_ff_buf = p_itf->rx.ff_buf; + #else + uint8_t *rx_ff_buf = NULL; + #endif tu_edpt_stream_init(&p_itf->rx.stream, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, p_epbuf->epout, CFG_TUD_VENDOR_EPSIZE); - uint8_t* tx_ff_buf = - #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 - p_itf->tx.ff_buf; - #else - NULL; - #endif + #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 + uint8_t *tx_ff_buf = p_itf->tx.ff_buf; + #else + uint8_t* tx_ff_buf = NULL; + #endif tu_edpt_stream_init(&p_itf->tx.stream, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, @@ -225,7 +212,9 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin } TU_VERIFY(p_vendor, 0); + p_vendor->rhport = rhport; p_vendor->itf_num = desc_itf->bInterfaceNumber; + while (tu_desc_in_bounds(p_desc, desc_end)) { const uint8_t desc_type = tu_desc_type(p_desc); if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) { |
