Merge branch 'dcd_notif' into testing

This commit is contained in:
HiFiPhile
2025-06-22 17:22:45 +02:00
5 changed files with 80 additions and 10 deletions

View File

@@ -98,7 +98,6 @@ void tud_umount_cb(void) {
blink_interval_ms = BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
// USB CDC
//--------------------------------------------------------------------+
@@ -119,6 +118,16 @@ static void cdc_task(void) {
echo_serial_port(0, buf, count);
echo_serial_port(1, buf, count);
}
// Press on-board button to send Uart status notification
static uint32_t btn_prev = 0;
static cdc_uart_state_t state = {0};
uint32_t btn = board_button_read();
if (!btn_prev && btn) {
state.bTxCarrier ^= 1;
tud_cdc_send_uart_state(state);
}
btn_prev = btn;
}
}
}

View File

@@ -136,10 +136,10 @@ uint8_t const desc_fs_configuration[] =
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 10, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 10, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
};
#if TUD_OPT_HIGH_SPEED
@@ -151,10 +151,10 @@ uint8_t const desc_hs_configuration[] =
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 10, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512),
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512),
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 10, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512),
};
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed

View File

@@ -412,6 +412,35 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct");
//--------------------------------------------------------------------+
// Notifications
//--------------------------------------------------------------------+
typedef struct TU_ATTR_PACKED
{
uint16_t bRxCarrier : 1;
uint16_t bTxCarrier : 1;
uint16_t bBreak : 1;
uint16_t bRingSignal : 1;
uint16_t bFraming : 1;
uint16_t bParity : 1;
uint16_t bOverRun : 1;
uint16_t : 9;
} cdc_uart_state_t;
typedef struct TU_ATTR_PACKED
{
uint8_t bmRequestType;
uint8_t bNotification;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
cdc_uart_state_t bmUartState;
} cdc_notif_serial_state_t;
TU_VERIFY_STATIC(sizeof(cdc_notif_serial_state_t) == 10, "size is not correct");
#define CDC_REQ_TYPE_NOTIF 0xA1 ///< Direction IN; Type Class; Recipient Interface
TU_ATTR_PACKED_END // End of all packed definitions
TU_ATTR_BIT_FIELD_ORDER_END

View File

@@ -46,6 +46,7 @@
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
typedef struct {
uint8_t rhport;
uint8_t itf_num;
uint8_t ep_notif;
uint8_t ep_in;
@@ -74,6 +75,7 @@ typedef struct {
typedef struct {
TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE);
TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE);
TUD_EPBUF_TYPE_DEF(cdc_notif_serial_state_t, epnotif);
} cdcd_epbuf_t;
//--------------------------------------------------------------------+
@@ -101,7 +103,7 @@ static bool _prep_out_transaction(uint8_t itf) {
TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE);
// claim endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out));
TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_out));
// fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&p_cdc->rx_ff);
@@ -110,7 +112,7 @@ static bool _prep_out_transaction(uint8_t itf) {
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);
usbd_edpt_release(p_cdc->rhport, p_cdc->ep_out);
return false;
}
}
@@ -142,6 +144,27 @@ void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) {
(*coding) = _cdcd_itf[itf].line_coding;
}
bool tud_cdc_n_send_uart_state (uint8_t itf, cdc_uart_state_t state) {
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);
// claim endpoint
TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notif));
p_epbuf->epnotif.bmRequestType = CDC_REQ_TYPE_NOTIF;
p_epbuf->epnotif.bNotification = CDC_NOTIF_SERIAL_STATE;
p_epbuf->epnotif.wValue = 0;
p_epbuf->epnotif.wIndex = p_cdc->itf_num;
p_epbuf->epnotif.wLength = 2;
p_epbuf->epnotif.bmUartState = state;
// transfer
return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notif, (uint8_t *)&p_epbuf->epnotif, sizeof(cdc_notif_serial_state_t));
}
void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) {
_cdcd_itf[itf].wanted_char = wanted;
}
@@ -204,7 +227,7 @@ uint32_t tud_cdc_n_write_flush(uint8_t itf) {
const uint8_t rhport = 0;
// Claim the endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 0);
TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0);
// Pull data from FIFO
const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE);
@@ -215,7 +238,7 @@ uint32_t tud_cdc_n_write_flush(uint8_t itf) {
} else {
// Release endpoint since we don't make any transfer
// Note: data is dropped if terminal is not connected
usbd_edpt_release(rhport, p_cdc->ep_in);
usbd_edpt_release(p_cdc->rhport, p_cdc->ep_in);
return 0;
}
}
@@ -319,6 +342,7 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16
TU_ASSERT(cdc_id < CFG_TUD_CDC, 0);
//------------- Control Interface -------------//
p_cdc->rhport = rhport;
p_cdc->itf_num = itf_desc->bInterfaceNumber;
uint16_t drv_len = sizeof(tusb_desc_interface_t);
@@ -455,7 +479,7 @@ 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)) {
if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notif)) {
break;
}
}

View File

@@ -83,6 +83,9 @@ uint8_t tud_cdc_n_get_line_state(uint8_t itf);
// Get current line encoding: bit rate, stop bits parity etc ..
void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding);
// Send UART status notification: DCD, DSR etc ..
bool tud_cdc_n_send_uart_state(uint8_t itf, cdc_uart_state_t state);
// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving
void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted);
@@ -146,6 +149,11 @@ TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_get_line_coding(cdc_line_coding
tud_cdc_n_get_line_coding(0, coding);
}
TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_send_uart_state(cdc_uart_state_t state) {
return tud_cdc_n_send_uart_state(0, state);
}
TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_set_wanted_char(char wanted) {
tud_cdc_n_set_wanted_char(0, wanted);
}