From db511fb2f3df190f538d84d08b6be83746adae0e Mon Sep 17 00:00:00 2001 From: IngHK Date: Mon, 19 Feb 2024 08:05:16 +0100 Subject: fixed CFG_TUH_CDC_LINE_CONTROL_ON_ENUM handling. only set if defined. value 0 is also valid --- src/class/cdc/cdc_host.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src/class/cdc/cdc_host.h') diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index d512a23a5..ca6567453 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -37,16 +37,6 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -// 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 - -// 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_CODING_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 -- cgit v1.3.1 From a9cc07fc83599fab4d9576e6f5b793bc1bf2bf35 Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 10 Mar 2024 08:20:12 +0100 Subject: added line control function using cdc_line_control_state_t --- src/class/cdc/cdc_host.c | 35 ++++++++++++++++++++++++++++++----- src/class/cdc/cdc_host.h | 10 ++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) (limited to 'src/class/cdc/cdc_host.h') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a3407a5f9..86b874b1e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -50,8 +50,9 @@ DADDR, ITF_NUM, NAME, ##__VA_ARGS__) #define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) -#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %s", VAL ? "true" : "false" ) +#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %d", VAL) +// assert and set config complete #define TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) \ do { \ if (!(_cond)) { _MESS_FAILED(); TU_BREAKPOINT(); set_config_complete(idx, _itf_offset, false); } \ @@ -586,24 +587,48 @@ static bool set_function_call ( } } -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // uses cdc_line_control_state_t union for line_state cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set control line state line_state = %u", line_state); + TU_LOG_P_CDC("set control line state dtr = %u rts = %u", line_state.dtr, line_state.rts ); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_state.all = (uint8_t) line_state; + p_cdc->requested_line_state = line_state; bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_state.all = (uint8_t) line_state; + p_cdc->line_state = line_state; } // TU_LOG_P_CDC_BOOL("set control line state", ret); return ret; } +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // uses uint16_t for line_state => DTR (bit 0), RTS (bit 1) + + return tuh_cdc_set_control_line_state_u(idx, (cdc_line_control_state_t) { .all = (uint8_t) line_state }, + complete_cb, user_data); +} + +bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_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->serial_drid < SERIAL_DRIVER_COUNT); + cdc_line_control_state_t const line_state = { .dtr = dtr_state, .rts = p_cdc->line_state.rts }; + + return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); +} + +bool tuh_cdc_set_rts(uint8_t idx, bool rts_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->serial_drid < SERIAL_DRIVER_COUNT); + cdc_line_control_state_t const line_state = { .rts = rts_state, .dtr = p_cdc->line_state.dtr }; + + return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); +} + bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index ca6567453..77081d3b0 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -132,8 +132,14 @@ bool tuh_cdc_read_clear (uint8_t idx); // - The function will return true if transfer is successful, false otherwise. //--------------------------------------------------------------------+ -// 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 Control Line State +bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, // uses cdc_line_control_state_t union for line_state + tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, // uses uint16_t for line_state (legacy function) + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // DTR (bit 0), RTS (bit 1) + +bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set DTR +bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set RTS // Request to set baudrate bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -- cgit v1.3.1 From d132044b7587f7e846bbec6e7b897d0842a21d13 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Feb 2025 15:40:48 +0700 Subject: add tuh_midi_mount_cb_t struct for tuh_midi_mount_cb() change tuh_midi_rx/tx_cb() to have xferred_bytes rename tuh_midi_get_num_rx/tx_cables() to tuh_midi_get_rx/tx_cable_count() use default empty callback instead of weak null to be compatible with keil compiler --- examples/host/cdc_msc_hid/src/main.c | 4 +- examples/host/midi_rx/src/main.c | 13 +++--- src/class/cdc/cdc_host.h | 8 ++-- src/class/midi/midi_device.c | 5 --- src/class/midi/midi_host.c | 81 ++++++++++++++++-------------------- src/class/midi/midi_host.h | 34 +++++++++------ src/host/usbh_pvt.h | 4 -- 7 files changed, 70 insertions(+), 79 deletions(-) (limited to 'src/class/cdc/cdc_host.h') diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 71257c0fe..2d5df23f9 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -82,12 +82,12 @@ int main(void) { void tuh_mount_cb(uint8_t dev_addr) { // application set-up - printf("A device with address %d is mounted\r\n", dev_addr); + printf("A device with address %u is mounted\r\n", dev_addr); } void tuh_umount_cb(uint8_t dev_addr) { // application tear-down - printf("A device with address %d is unmounted \r\n", dev_addr); + printf("A device with address %u is unmounted \r\n", dev_addr); } diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 6db329ab5..d26321e5d 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -91,9 +91,9 @@ void midi_host_rx_task(void) { //--------------------------------------------------------------------+ // Invoked when device with MIDI interface is mounted. -void tuh_midi_mount_cb(uint8_t idx, uint8_t num_cables_rx, uint16_t num_cables_tx) { - printf("MIDI Interface Index = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", - idx, num_cables_rx, num_cables_tx); +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { + printf("MIDI Interface Index = %u, Address = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", + idx, mount_cb_data->daddr, mount_cb_data->rx_cable_count, mount_cb_data->tx_cable_count); } // Invoked when device with hid interface is un-mounted @@ -101,8 +101,8 @@ void tuh_midi_umount_cb(uint8_t idx) { printf("MIDI Interface Index = %u is unmounted\r\n", idx); } -void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets) { - if (num_packets == 0) { +void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { + if (xferred_bytes == 0) { return; } @@ -117,6 +117,7 @@ void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets) { printf("\r\n"); } -void tuh_midi_tx_cb(uint8_t idx) { +void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; + (void) xferred_bytes; } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index df975b2f0..8c5399534 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -49,22 +49,22 @@ // RX FIFO size #ifndef CFG_TUH_CDC_RX_BUFSIZE -#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // RX Endpoint size #ifndef CFG_TUH_CDC_RX_EPSIZE -#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS #endif // TX FIFO size #ifndef CFG_TUH_CDC_TX_BUFSIZE -#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // TX Endpoint size #ifndef CFG_TUH_CDC_TX_EPSIZE -#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS #endif //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 7b6705640..0bbb3caf4 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -39,9 +39,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ - - - typedef struct { uint8_t itf_num; uint8_t ep_in; @@ -440,8 +437,6 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint1 drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - } else { - TU_LOG2("Warning: MIDI Device has no Audio Control Interface"); } // 2nd Interface is MIDI Streaming diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 770a39a8d..a4b1ebd2e 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -40,6 +40,15 @@ #define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_LOG_LEVEL, __VA_ARGS__) +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data) { (void) idx; (void) desc_cb_data; } +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { (void) idx; (void) mount_cb_data; } +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx) { (void) idx; } +TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } +TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -52,8 +61,8 @@ typedef struct { uint8_t ep_in; // IN endpoint address uint8_t ep_out; // OUT endpoint address - uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value - uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value + uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value + uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value #if CFG_TUH_MIDI_STREAM_API // For Stream read()/write() API @@ -135,16 +144,13 @@ void midih_close(uint8_t daddr) { midih_interface_t* p_midi = &_midi_host[idx]; if (p_midi->daddr == daddr) { TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); - - if (tuh_midi_umount_cb) { - tuh_midi_umount_cb(idx); - } + tuh_midi_umount_cb(idx); p_midi->ep_in = 0; p_midi->ep_out = 0; p_midi->bInterfaceNumber = 0; - p_midi->num_cables_rx = 0; - p_midi->num_cables_tx = 0; + p_midi->rx_cable_count = 0; + p_midi->tx_cable_count = 0; p_midi->daddr = 0; p_midi->mounted = false; tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); @@ -163,33 +169,16 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint midih_interface_t *p_midi_host = &_midi_host[idx]; if (ep_addr == p_midi_host->ep_stream.rx.ep_addr) { - // receive new data if available + // receive new data, put it into FIFO and invoke callback if available if (xferred_bytes) { - // put in the RX FIFO only non-zero MIDI IN 4-byte packets - uint32_t packets_queued = 0; - uint8_t *buf = _midi_epbuf->rx; - const uint32_t npackets = xferred_bytes / 4; - for (uint32_t p = 0; p < npackets; p++) { - // some devices send back all zero packets even if there is no data ready - const uint32_t packet = tu_unaligned_read32(buf); - if (packet != 0) { - tu_edpt_stream_read_xfer_complete_with_buf(&p_midi_host->ep_stream.rx, buf, 4); - ++packets_queued; - TU_LOG3("MIDI RX=%08x\r\n", packet); - } - buf += 4; - } - - if (tuh_midi_rx_cb) { - tuh_midi_rx_cb(idx, packets_queued); - } + tu_edpt_stream_read_xfer_complete(&p_midi_host->ep_stream.rx, xferred_bytes); + tuh_midi_rx_cb(idx, xferred_bytes); } tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for next transfer } else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) { - if (tuh_midi_tx_cb) { - tuh_midi_tx_cb(idx); - } + tuh_midi_tx_cb(idx, xferred_bytes); + if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi_host->ep_stream.tx)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero @@ -207,7 +196,6 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d (void) rhport; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); - // const uint8_t* p_start = ((uint8_t const*) desc_itf); const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len; const uint8_t *p_desc = (const uint8_t *) desc_itf; @@ -286,14 +274,14 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { p_midi->ep_out = p_ep->bEndpointAddress; - p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack; + p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; desc_cb.desc_epout = p_ep; TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep); } else { p_midi->ep_in = p_ep->bEndpointAddress; - p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack; + p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; desc_cb.desc_epin = p_ep; TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); @@ -309,10 +297,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d desc_cb.desc_midi_total_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); p_midi->daddr = dev_addr; - - if (tuh_midi_descriptor_cb) { - tuh_midi_descriptor_cb(idx, &desc_cb); - } + tuh_midi_descriptor_cb(idx, &desc_cb); return true; } @@ -323,9 +308,13 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { midih_interface_t *p_midi = &_midi_host[idx]; p_midi->mounted = true; - if (tuh_midi_mount_cb) { - tuh_midi_mount_cb(idx, p_midi->num_cables_rx, p_midi->num_cables_tx); - } + const tuh_midi_mount_cb_t mount_cb_data = { + .daddr = dev_addr, + .bInterfaceNumber = itf_num, + .rx_cable_count = p_midi->rx_cable_count, + .tx_cable_count = p_midi->tx_cable_count, + }; + tuh_midi_mount_cb(idx, &mount_cb_data); tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for incoming data @@ -355,18 +344,18 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { return TUSB_INDEX_INVALID_8; } -uint8_t tuh_midi_get_num_tx_cables (uint8_t idx) { +uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; TU_VERIFY(p_midi->ep_stream.tx.ep_addr != 0, 0); - return p_midi->num_cables_tx; + return p_midi->tx_cable_count; } -uint8_t tuh_midi_get_num_rx_cables (uint8_t idx) { +uint8_t tuh_midi_get_rx_cable_count (uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; TU_VERIFY(p_midi->ep_stream.rx.ep_addr != 0, 0); - return p_midi->num_cables_rx; + return p_midi->rx_cable_count; } uint32_t tuh_midi_read_available(uint8_t idx) { @@ -410,7 +399,7 @@ uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bu uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0); midih_interface_t *p_midi = &_midi_host[idx]; - TU_VERIFY(cable_num < p_midi->num_cables_tx); + TU_VERIFY(cable_num < p_midi->tx_cable_count); midi_driver_stream_t *stream = &p_midi->stream_write; uint32_t byte_count = 0; @@ -520,7 +509,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff while (nread == 4 && bytes_buffered < bufsize) { *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f; uint8_t bytes_to_add_to_stream = 0; - if (*p_cable_num < p_midi->num_cables_rx) { + if (*p_cable_num < p_midi->rx_cable_count) { // ignore the CIN field; too many devices out there encode this wrong uint8_t status = p_midi->stream_read.buffer[1]; uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 717e6ba67..b06bb43d7 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -37,10 +37,6 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_MAX_CABLES -#define CFG_TUH_MAX_CABLES 16 -#endif - #ifndef CFG_TUH_MIDI_RX_BUFSIZE #define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif @@ -60,7 +56,7 @@ #endif //--------------------------------------------------------------------+ -// Application API +// Application Types //--------------------------------------------------------------------+ typedef struct { const tusb_desc_interface_t* desc_audio_control; @@ -76,6 +72,17 @@ typedef struct { const uint8_t* desc_jack[16]; // list of jack descriptors (embedded + external) } tuh_midi_descriptor_cb_t; +typedef struct { + uint8_t daddr; + uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t rx_cable_count; + uint8_t tx_cable_count; +} tuh_midi_mount_cb_t; + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + // Check if MIDI interface is mounted bool tuh_midi_mounted(uint8_t idx); @@ -84,10 +91,10 @@ bool tuh_midi_mounted(uint8_t idx); uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); // return the number of virtual midi cables on the device's IN endpoint -uint8_t tuh_midi_get_num_rx_cables(uint8_t idx); +uint8_t tuh_midi_get_rx_cable_count(uint8_t idx); // return the number of virtual midi cables on the device's OUT endpoint -uint8_t tuh_midi_get_num_tx_cables(uint8_t idx); +uint8_t tuh_midi_get_tx_cable_count(uint8_t idx); // return the raw number of bytes available. // Note: this is related but not the same as number of stream bytes available. @@ -151,16 +158,19 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff // Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. // Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. -TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb); +void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data); // Invoked when device with MIDI interface is mounted. -TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, uint8_t num_cables_rx, uint16_t num_cables_tx); +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data); // Invoked when device with MIDI interface is un-mounted -TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx); +void tuh_midi_umount_cb(uint8_t idx); + +// Invoked when received new data +void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes); -TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets); -TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx); +// Invoked when a TX is complete and therefore space becomes available in TX buffer +void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index d27c4baa2..bfa1fb2ba 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -41,10 +41,6 @@ #define TU_LOG_INT_USBH(...) TU_LOG_INT(CFG_TUH_LOG_LEVEL, __VA_ARGS__) #define TU_LOG_HEX_USBH(...) TU_LOG_HEX(CFG_TUH_LOG_LEVEL, __VA_ARGS__) -enum { - USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) -}; - //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ -- cgit v1.3.1 From ce9140a150f685ae228362c5fcd0b85a7900e67a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Jun 2025 17:57:21 +0700 Subject: rename tuh_cdc_get_local_line_coding to tuh_cdc_get_line_coding_local add tuh_cdc_get_control_line_state_local() implement tuh_cdc_get/set_dtr/rts() as inline --- src/class/cdc/cdc_host.c | 55 ++++++++---------------------------------------- src/class/cdc/cdc_host.h | 45 +++++++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 57 deletions(-) (limited to 'src/class/cdc/cdc_host.h') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 7259e819f..80b01f928 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -427,27 +427,14 @@ bool tuh_cdc_mounted(uint8_t idx) { return p_cdc->mounted; } -bool tuh_cdc_get_dtr(uint8_t idx) { +bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - - bool ret = p_cdc->line_state.dtr; -// TU_LOG_P_CDC_BOOL("get DTR", ret); - - return ret; -} - -bool tuh_cdc_get_rts(uint8_t idx) { - cdch_interface_t * p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - bool ret = p_cdc->line_state.rts; -// TU_LOG_P_CDC_BOOL("get RTS", ret); - - return ret; + *line_state = p_cdc->line_state.value; + return true; } -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t * line_coding) { +bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -622,46 +609,22 @@ static bool set_function_call ( } } -bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // uses cdc_line_control_state_t union for line_state +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->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set control line state dtr = %u rts = %u", line_state.dtr, line_state.rts); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_state = line_state; + p_cdc->requested_line_state.value = (uint8_t) line_state; + TU_LOG_P_CDC("set control line state dtr = %u rts = %u", p_cdc->requested_line_state.dtr, p_cdc->requested_line_state.rts); - bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); + const bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_state = line_state; + p_cdc->line_state = p_cdc->requested_line_state; } return ret; } -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // uses uint16_t for line_state => DTR (bit 0), RTS (bit 1) - - return tuh_cdc_set_control_line_state_u(idx, (cdc_line_control_state_t) { .value = (uint8_t) line_state }, - complete_cb, user_data); -} - -bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_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->serial_drid < SERIAL_DRIVER_COUNT); - cdc_line_control_state_t const line_state = { .dtr = dtr_state, .rts = p_cdc->line_state.rts }; - - return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); -} - -bool tuh_cdc_set_rts(uint8_t idx, bool rts_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->serial_drid < SERIAL_DRIVER_COUNT); - cdc_line_control_state_t const line_state = {.rts = rts_state, .dtr = p_cdc->line_state.dtr}; - - return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); -} - bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 63eb1fc0f..688164cb2 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -69,14 +69,27 @@ uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num); // return true if index is correct and interface is currently mounted bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info); -// Check if a interface is mounted +// Check if an interface is mounted bool tuh_cdc_mounted(uint8_t idx); +// Get local (cached) line state +// This function should return correct values if tuh_cdc_set_control_line_state() / tuh_cdc_get_control_line_state() +// are invoked previously or CFG_TUH_CDC_LINE_STATE_ON_ENUM is defined. +bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state); + // Get current DTR status -bool tuh_cdc_get_dtr(uint8_t idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_dtr(uint8_t idx) { + uint16_t line_state; + TU_VERIFY(tuh_cdc_get_control_line_state_local(idx, &line_state)); + return (line_state & CDC_CONTROL_LINE_STATE_DTR) != 0; +} // Get current RTS status -bool tuh_cdc_get_rts(uint8_t idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_rts(uint8_t idx) { + uint16_t line_state; + TU_VERIFY(tuh_cdc_get_control_line_state_local(idx, &line_state)); + return (line_state & CDC_CONTROL_LINE_STATE_RTS) != 0; +} // Check if interface is connected (DTR active) TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) { @@ -87,7 +100,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) { // 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); +bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t* line_coding); + +#define tuh_cdc_get_local_line_coding tuh_cdc_get_line_coding_local // backward compatibility //--------------------------------------------------------------------+ // Write API @@ -131,14 +146,22 @@ bool tuh_cdc_read_clear (uint8_t idx); // - The function will return true if transfer is successful, false otherwise. //--------------------------------------------------------------------+ -// Request to Set Control Line State -bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, // uses cdc_line_control_state_t union for line_state - tuh_xfer_cb_t complete_cb, uintptr_t user_data); -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, // uses uint16_t for line_state (legacy function) - tuh_xfer_cb_t complete_cb, uintptr_t user_data); // DTR (bit 0), RTS (bit 1) +// 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); -bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set DTR -bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set RTS +// Request to Set DTR +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdc_line_control_state_t line_state = { .dtr = dtr_state }; + line_state.rts = tuh_cdc_get_rts(idx); + return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); +} + +// Request to Set RTS +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdc_line_control_state_t line_state = { .rts = rts_state }; + line_state.dtr = tuh_cdc_get_dtr(idx); + return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); +} // Request to set baudrate bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -- cgit v1.3.1 From adf6cbfe03523cd8f7e23cb7f2edbb4304a6cd89 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Jun 2025 12:52:34 +0700 Subject: cdch clean up and refactor, add explicit sync() API --- examples/host/cdc_msc_hid/src/cdc_app.c | 2 +- src/class/cdc/cdc_host.c | 172 +++++++++++++------------------- src/class/cdc/cdc_host.h | 48 +++++++-- src/class/cdc/serial/pl2303.h | 33 +++--- 4 files changed, 127 insertions(+), 128 deletions(-) (limited to 'src/class/cdc/cdc_host.h') diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 6f4433f22..2fa9a8560 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -89,7 +89,7 @@ void tuh_cdc_mount_cb(uint8_t idx) { // If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack // while eneumerating new cdc device cdc_line_coding_t line_coding = {0}; - if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { + if (tuh_cdc_get_line_coding_local(idx, &line_coding)) { printf(" Baudrate: %" PRIu32 ", 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); } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2fe2c85bc..50d0a020d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -42,15 +42,15 @@ // Level where CFG_TUSB_DEBUG must be at least for this driver is logged #ifndef CFG_TUH_CDC_LOG_LEVEL - #define CFG_TUH_CDC_LOG_LEVEL CFG_TUH_LOG_LEVEL + #define CFG_TUH_CDC_LOG_LEVEL 1 #endif -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_CDC(TXT,DADDR,ITF_NUM,NAME,...) TU_LOG_DRV("[:%u:%u] CDCh %s " TXT "\r\n", \ - DADDR, ITF_NUM, NAME, ##__VA_ARGS__) -#define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ - serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) -#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %d", VAL) +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_CDC(_cdc, _format, ...) TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ + serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) + +// Driver that need to set line coding in two stages: baudrate then data format. +#define DRIVER_2STAGE_SET_LINE_CODING (CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X) //--------------------------------------------------------------------+ // Host CDC Interface @@ -72,7 +72,8 @@ typedef struct { } line, requested_line; tuh_xfer_cb_t user_complete_cb; // required since we handle request internally first - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X + + #if DRIVER_2STAGE_SET_LINE_CODING tuh_xfer_cb_t requested_complete_cb; #endif @@ -197,49 +198,57 @@ enum { SERIAL_DRIVER_COUNT }; +typedef bool (*serial_driver_func_t)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + typedef struct { uint16_t const (*vid_pid_list)[2]; uint16_t const vid_pid_count; + bool is_2stage_line_coding; // true if driver requires to set baudrate then data format separately + bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); bool (*const process_set_config)(tuh_xfer_t * xfer); - bool (*const set_control_line_state)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_baudrate)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_data_format)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_line_coding)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + const serial_driver_func_t set_control_line_state; + const serial_driver_func_t set_baudrate; + const serial_driver_func_t set_data_format; + const serial_driver_func_t set_line_coding; #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - uint8_t const * name; + const char * name; #endif } cdch_serial_driver_t; +#if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + #define DRIVER_NAME_DECLARE(_str) .name = _str +#else + #define DRIVER_NAME_DECLARE(_str) +#endif + // Note driver list must be in the same order as SERIAL_DRIVER enum static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = NULL, .vid_pid_count = 0, + .is_2stage_line_coding = false, .open = acm_open, .process_set_config = acm_process_set_config, .set_control_line_state = acm_set_control_line_state, .set_baudrate = acm_set_baudrate, .set_data_format = acm_set_data_format, .set_line_coding = acm_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "ACM" - #endif + DRIVER_NAME_DECLARE("ACM") }, #if CFG_TUH_CDC_FTDI { .vid_pid_list = ftdi_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), + .is_2stage_line_coding = true, .open = ftdi_open, .process_set_config = ftdi_proccess_set_config, .set_control_line_state = ftdi_set_modem_ctrl, .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, .set_line_coding = ftdi_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "FTDI" - #endif + DRIVER_NAME_DECLARE("FTDI") }, #endif @@ -247,15 +256,14 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = cp210x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), + .is_2stage_line_coding = true, .open = cp210x_open, .process_set_config = cp210x_process_set_config, .set_control_line_state = cp210x_set_modem_ctrl, .set_baudrate = cp210x_set_baudrate, .set_data_format = cp210x_set_data_format, .set_line_coding = cp210x_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "CP210x" - #endif + DRIVER_NAME_DECLARE("CP210x") }, #endif @@ -263,15 +271,14 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = ch34x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), + .is_2stage_line_coding = true, .open = ch34x_open, .process_set_config = ch34x_process_set_config, .set_control_line_state = ch34x_set_modem_ctrl, .set_baudrate = ch34x_set_baudrate, .set_data_format = ch34x_set_data_format, .set_line_coding = ch34x_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "CH34x" - #endif + DRIVER_NAME_DECLARE("CH34x") }, #endif @@ -279,15 +286,14 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = pl2303_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), + .is_2stage_line_coding = false, .open = pl2303_open, .process_set_config = pl2303_process_set_config, .set_control_line_state = pl2303_set_modem_ctrl, .set_baudrate = pl2303_set_baudrate, .set_data_format = pl2303_set_data_format, .set_line_coding = pl2303_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "PL2303" - #endif + DRIVER_NAME_DECLARE("PL2303") } #endif }; @@ -440,13 +446,7 @@ bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) { bool tuh_cdc_get_line_coding_local(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; - TU_LOG_P_CDC("get line coding %lu %u%c%s", - p_cdc->line.coding.bit_rate, p_cdc->line.coding.data_bits, - CDC_LINE_CODING_PARITY_CHAR(p_cdc->line.coding.parity), - CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); - return true; } @@ -520,29 +520,27 @@ bool tuh_cdc_read_clear (uint8_t idx) { // Control Endpoint API //--------------------------------------------------------------------+ +#if DRIVER_2STAGE_SET_LINE_CODING + // set line coding using sequence with 2 stages: set baudrate (stage1) + set data format (stage2) static bool set_line_coding_sequence( cdch_interface_t * p_cdc, - // control request function to set baudrate - bool (*set_baudrate_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - // control request function to set data format - bool (*set_data_format_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - // function to be called after stage 1 completed - void (*set_line_coding_stage1_complete)(tuh_xfer_t * xfer), - // control complete function to be called after request - void (*internal_control_complete)(tuh_xfer_t * xfer), + serial_driver_func_t set_baudrate, + serial_driver_func_t set_data_format, + tuh_xfer_cb_t set_line_coding_stage1_complete, // function to be called after stage 1 completed + tuh_xfer_cb_t internal_control_complete, // control complete function to be called after request tuh_xfer_cb_t complete_cb, uintptr_t user_data) { if (complete_cb) { // non-blocking // stage 1 set baudrate p_cdc->requested_complete_cb = complete_cb; // store complete_cb to be used in set_line_coding_stage1_complete() p_cdc->user_complete_cb = set_line_coding_stage1_complete; - return set_baudrate_request(p_cdc, internal_control_complete, user_data); + return set_baudrate(p_cdc, internal_control_complete, user_data); } else { // blocking sequence // stage 1 set baudrate xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL - bool ret = set_baudrate_request(p_cdc, NULL, (uintptr_t) &result); + bool ret = set_baudrate(p_cdc, NULL, (uintptr_t) &result); if (user_data) { *((xfer_result_t *) user_data) = result; @@ -556,7 +554,7 @@ static bool set_line_coding_sequence( // stage 2 set data format result = XFER_RESULT_INVALID; - ret = set_data_format_request(p_cdc, NULL, (uintptr_t) &result); + ret = set_data_format(p_cdc, NULL, (uintptr_t) &result); if (user_data) { *((xfer_result_t *) user_data) = result; @@ -590,58 +588,35 @@ static void set_line_coding_stage1_complete( } } } - -// call of (non-)blocking set-functions (to set line state, baudrate, ...) -static bool set_function_call ( - cdch_interface_t * p_cdc, - bool (*set_function)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - if (complete_cb) { - // non-blocking with call back - return set_function(p_cdc, complete_cb, user_data); - } else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL - bool ret = set_function(p_cdc, NULL, (uintptr_t) &result); - - if (user_data) { - *((xfer_result_t *) user_data) = result; - } - - return (ret && result == XFER_RESULT_SUCCESS); - } -} +#endif 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->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_CDC(p_cdc, "set control line state dtr = %u rts = %u", p_cdc->requested_line.control_state.dtr, p_cdc->requested_line.control_state.rts); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line.control_state.value = (uint8_t) line_state; - TU_LOG_P_CDC("set control line state dtr = %u rts = %u", p_cdc->requested_line.control_state.dtr, p_cdc->requested_line.control_state.rts); - - const bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); - + const bool ret = driver->set_control_line_state(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line.control_state = p_cdc->requested_line.control_state; + // blocking, update line state if request was successful + p_cdc->line.control_state.value = (uint8_t) line_state; } + return ret; } bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set baudrate %lu", baudrate); + TU_LOG_CDC(p_cdc, "set baudrate %lu", baudrate); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line.coding.bit_rate = baudrate; - - bool ret = set_function_call(p_cdc, driver->set_baudrate, complete_cb, user_data); - + const bool ret = driver->set_baudrate(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { p_cdc->line.coding.bit_rate = baudrate; } -// TU_LOG_P_CDC_BOOL("set baudrate", ret); return ret; } @@ -650,7 +625,7 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set data format %u%c%s", + TU_LOG_CDC(p_cdc, "set data format %u%c%s", data_bits, CDC_LINE_CODING_PARITY_CHAR(parity), CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; @@ -659,15 +634,13 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin p_cdc->requested_line.coding.parity = parity; p_cdc->requested_line.coding.data_bits = data_bits; - bool ret = set_function_call(p_cdc, driver->set_data_format, complete_cb, user_data); + const bool ret = driver->set_data_format(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { p_cdc->line.coding.stop_bits = stop_bits; p_cdc->line.coding.parity = parity; p_cdc->line.coding.data_bits = data_bits; } -// TU_LOG_P_CDC_BOOL("set data format", ret); - return ret; } @@ -675,7 +648,7 @@ 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->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set line coding %lu %u%c%s", + TU_LOG_CDC(p_cdc, "set line coding %lu %u%c%s", line_coding->bit_rate, line_coding->data_bits, CDC_LINE_CODING_PARITY_CHAR(line_coding->parity), CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); @@ -683,12 +656,11 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, p_cdc->requested_line.coding = *line_coding; - bool ret = set_function_call(p_cdc, driver->set_line_coding, complete_cb, user_data); + const bool ret = driver->set_line_coding(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { p_cdc->line.coding = *line_coding; } -// TU_LOG_P_CDC_BOOL("set line coding", ret); return ret; } @@ -728,7 +700,7 @@ 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) { - TU_LOG_P_CDC("close"); + TU_LOG_CDC(p_cdc, "close"); // Invoke application callback if (tuh_cdc_umount_cb) { @@ -847,9 +819,8 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } if (driver_detected) { - TU_LOG_CDC("open", daddr, itf_desc->bInterfaceNumber, driver_detected->name); - bool ret = driver_detected->open(daddr, itf_desc, max_len); - // TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); + const bool ret = driver_detected->open(daddr, itf_desc, max_len); + TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "OK" : "FAILED"); return ret; } @@ -859,7 +830,6 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); - TU_LOG_P_CDC_BOOL("set config complete", success); if (success) { p_cdc->mounted = true; @@ -883,6 +853,8 @@ static void cdch_process_set_config(tuh_xfer_t *xfer) { TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); const uint8_t idx = get_idx_by_ptr(p_cdc); + TU_LOG_DRV(" state = %u\r\n", xfer->user_data); + if (!serial_drivers[p_cdc->serial_drid].process_set_config(xfer)) { const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; set_config_complete(idx, itf_offset, false); @@ -895,7 +867,7 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set config"); + TU_LOG_CDC(p_cdc, "set config"); // fake transfer to kick-off process_set_config() tuh_xfer_t xfer; @@ -919,7 +891,6 @@ static void acm_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1204,7 +1175,6 @@ static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && @@ -1232,14 +1202,12 @@ static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); - return true; } static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); - return true; } @@ -1271,7 +1239,6 @@ static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ } //------------- Enumeration -------------// - enum { CONFIG_FTDI_DETERMINE_TYPE = 0, CONFIG_FTDI_WRITE_LATENCY, @@ -1448,7 +1415,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL const char * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; - TU_LOG_P_CDC("%s detected (bcdDevice = 0x%04x)", + TU_LOG_CDC(p_cdc, "%s detected (bcdDevice = 0x%04x)", ftdi_chip_name[p_cdc->ftdi.chip_type], version); #endif @@ -1595,7 +1562,7 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { break; } - TU_LOG_P_CDC("Baudrate divisor = 0x%lu", div_value); + TU_LOG_CDC(p_cdc, "Baudrate divisor = 0x%lu", div_value); return div_value; } @@ -1695,7 +1662,6 @@ static void cp210x_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1795,7 +1761,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - switch (state) { + switch (state) { case CONFIG_CP210X_IFC_ENABLE: TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, CONFIG_CP210X_SET_BAUDRATE_REQUEST)); break; @@ -1941,7 +1907,6 @@ static void ch34x_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -2059,7 +2024,6 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); uint8_t buffer[2];// TODO remove - TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { @@ -2071,7 +2035,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) uint8_t const version = xfer->buffer[0]; - TU_LOG_P_CDC("Chip Version = 0x%02x", version); + TU_LOG_CDC(p_cdc, "Chip Version = 0x%02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming // see drivers from WCH vendor, Linux kernel and FreeBSD if (version >= 0x30) { @@ -2348,7 +2312,6 @@ static void pl2303_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && @@ -2458,6 +2421,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { pl2303_type_t type; TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1)); + switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_DETECT_TYPE: @@ -2741,7 +2705,7 @@ static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { default: break; } - TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); + TU_LOG_CDC(p_cdc, "unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); return PL2303_TYPE_UNKNOWN; } @@ -2886,7 +2850,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); } - TU_LOG_P_CDC("real baudrate %lu", baud); + TU_LOG_CDC(p_cdc, "real baudrate %lu", baud); return true; } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 688164cb2..37bfca270 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -137,13 +137,12 @@ bool tuh_cdc_peek(uint8_t idx, uint8_t* ch); bool tuh_cdc_read_clear (uint8_t idx); //--------------------------------------------------------------------+ -// Control Endpoint (Request) API +// Control Request API // Each Function will make a USB control transfer request to/from device // - If complete_cb is provided, the function will return immediately and invoke // the callback when request is complete. // - If complete_cb is NULL, the function will block until request is complete. -// - In this case, user_data should be pointed to xfer_result_t to hold the transfer result. -// - The function will return true if transfer is successful, false otherwise. +// In this case, user_data should be usb_xfer_result_t* to hold the transfer result. //--------------------------------------------------------------------+ // Request to Set Control Line State: DTR (bit 0), RTS (bit 1) @@ -179,17 +178,52 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // bool tuh_cdc_get_line_coding(uint8_t idx, cdc_line_coding_t* coding); // Connect by set both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE 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(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); } // Disconnect by clear both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE 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); } +//--------------------------------------------------------------------+ +// Control Request Sync API +// Each Function will make a USB control transfer request to/from device the function will block until request is +// complete. The function will return the transfer request result +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_control_line_state_sync(uint8_t idx, uint16_t line_state) { + TU_API_SYNC(tuh_cdc_set_control_line_state, idx, line_state); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_dtr_sync(uint8_t idx, bool dtr_state) { + TU_API_SYNC(tuh_cdc_set_dtr, idx, dtr_state); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_rts_sync(uint8_t idx, bool rts_state) { + TU_API_SYNC(tuh_cdc_set_rts, idx, rts_state); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_baudrate_sync(uint8_t idx, uint32_t baudrate) { + TU_API_SYNC(tuh_cdc_set_baudrate, idx, baudrate); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_data_format_sync(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { + TU_API_SYNC(tuh_cdc_set_data_format, idx, stop_bits, parity, data_bits); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_line_coding_sync(uint8_t idx, cdc_line_coding_t const* line_coding) { + TU_API_SYNC(tuh_cdc_set_line_coding, idx, line_coding); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_connect_sync(uint8_t idx) { + TU_API_SYNC(tuh_cdc_connect, idx); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_disconnect_sync(uint8_t idx) { + TU_API_SYNC(tuh_cdc_disconnect, idx); +} + //--------------------------------------------------------------------+ // CDC APPLICATION CALLBACKS //--------------------------------------------------------------------+ diff --git a/src/class/cdc/serial/pl2303.h b/src/class/cdc/serial/pl2303.h index c01dac0e1..63910c7bb 100644 --- a/src/class/cdc/serial/pl2303.h +++ b/src/class/cdc/serial/pl2303.h @@ -109,36 +109,37 @@ typedef enum pl2303_type { } pl2303_type_t; typedef struct pl2303_type_data { - uint32_t const max_baud_rate; - uint8_t const quirks; - uint8_t const no_autoxonxoff : 1; - uint8_t const no_divisors : 1; - uint8_t const alt_divisors : 1; + uint32_t max_baud_rate; + uint8_t quirks; + uint8_t no_autoxonxoff : 1; + uint8_t no_divisors : 1; + uint8_t alt_divisors : 1; } pl2303_type_data_t; #define PL2303_TYPE_DATA \ [PL2303_TYPE_H] = { \ - .max_baud_rate = 1228800, \ - .quirks = PL2303_QUIRK_LEGACY, \ - .no_autoxonxoff = true, \ + .max_baud_rate = 1228800, .quirks = PL2303_QUIRK_LEGACY, \ + .no_autoxonxoff = 1, .no_divisors = 0, .alt_divisors = 0 \ }, \ [PL2303_TYPE_HX] = { \ - .max_baud_rate = 6000000, \ + .max_baud_rate = 6000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 0 \ }, \ [PL2303_TYPE_TA] = { \ - .max_baud_rate = 6000000, \ - .alt_divisors = true, \ + .max_baud_rate = 6000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 1 \ }, \ [PL2303_TYPE_TB] = { \ - .max_baud_rate = 12000000, \ - .alt_divisors = true, \ + .max_baud_rate = 12000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 1 \ }, \ [PL2303_TYPE_HXD] = { \ - .max_baud_rate = 12000000, \ + .max_baud_rate = 12000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 0 \ }, \ [PL2303_TYPE_HXN] = { \ - .max_baud_rate = 12000000, \ - .no_divisors = true, \ + .max_baud_rate = 12000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 1, .alt_divisors = 0 \ } typedef struct TU_ATTR_PACKED { -- cgit v1.3.1