union ftdi/pl2303/acm data to save memory.

This commit is contained in:
hathach
2025-06-19 18:14:24 +07:00
parent ce9140a150
commit 221b5288e4

View File

@@ -65,27 +65,30 @@ typedef struct {
uint8_t ep_notif; uint8_t ep_notif;
uint8_t serial_drid; // Serial Driver ID uint8_t serial_drid; // Serial Driver ID
bool mounted; // Enumeration is complete bool mounted; // Enumeration is complete
cdc_acm_capability_t acm_capability;
TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width struct {
TU_ATTR_ALIGNED(4) cdc_line_coding_t requested_line_coding; TU_ATTR_ALIGNED(4) cdc_line_coding_t coding; // Baudrate, stop bits, parity, data width
// 1 byte padding cdc_line_control_state_t control_state; // DTR, RTS
} line, requested_line;
cdc_line_control_state_t line_state; tuh_xfer_cb_t user_complete_cb; // required since we handle request internally first
cdc_line_control_state_t requested_line_state;
tuh_xfer_cb_t user_control_cb;
#if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X
tuh_xfer_cb_t requested_complete_cb; tuh_xfer_cb_t requested_complete_cb;
#endif #endif
#if CFG_TUH_CDC_FTDI union {
ftdi_private_t ftdi; struct {
#endif cdc_acm_capability_t capability;
} acm;
#if CFG_TUH_CDC_PL2303 #if CFG_TUH_CDC_FTDI
ftdi_private_t ftdi;
#endif
#if CFG_TUH_CDC_PL2303
pl2303_private_t pl2303; pl2303_private_t pl2303;
#endif #endif
};
struct { struct {
tu_edpt_stream_t tx; tu_edpt_stream_t tx;
@@ -376,8 +379,8 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons
p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber;
p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass;
p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol;
p_cdc->line_coding = (cdc_line_coding_t) { 0, 0, 0, 0 }; p_cdc->line.coding = (cdc_line_coding_t) { 0, 0, 0, 0 };
p_cdc->line_state.value = 0; p_cdc->line.control_state.value = 0;
return p_cdc; return p_cdc;
} }
} }
@@ -430,7 +433,7 @@ bool tuh_cdc_mounted(uint8_t idx) {
bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) { bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) {
cdch_interface_t * p_cdc = get_itf(idx); cdch_interface_t * p_cdc = get_itf(idx);
TU_VERIFY(p_cdc); TU_VERIFY(p_cdc);
*line_state = p_cdc->line_state.value; *line_state = p_cdc->line.control_state.value;
return true; return true;
} }
@@ -438,10 +441,10 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding)
cdch_interface_t * p_cdc = get_itf(idx); cdch_interface_t * p_cdc = get_itf(idx);
TU_VERIFY(p_cdc); TU_VERIFY(p_cdc);
*line_coding = p_cdc->line_coding; *line_coding = p_cdc->line.coding;
TU_LOG_P_CDC("get line coding %lu %u%c%s", TU_LOG_P_CDC("get line coding %lu %u%c%s",
p_cdc->line_coding.bit_rate, p_cdc->line_coding.data_bits, 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_PARITY_CHAR(p_cdc->line.coding.parity),
CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits));
return true; return true;
@@ -533,7 +536,7 @@ static bool set_line_coding_sequence(
// non-blocking // non-blocking
// stage 1 set baudrate // 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->requested_complete_cb = complete_cb; // store complete_cb to be used in set_line_coding_stage1_complete()
p_cdc->user_control_cb = 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_request(p_cdc, internal_control_complete, user_data);
} else { } else {
// blocking sequence // blocking sequence
@@ -549,7 +552,7 @@ static bool set_line_coding_sequence(
TU_VERIFY(result == XFER_RESULT_SUCCESS); TU_VERIFY(result == XFER_RESULT_SUCCESS);
// overtake baudrate after successful request // overtake baudrate after successful request
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate;
// stage 2 set data format // stage 2 set data format
result = XFER_RESULT_INVALID; result = XFER_RESULT_INVALID;
@@ -577,7 +580,7 @@ static void set_line_coding_stage1_complete(
if (xfer->result == XFER_RESULT_SUCCESS) { if (xfer->result == XFER_RESULT_SUCCESS) {
// stage 1 success, continue with stage 2 // stage 1 success, continue with stage 2
p_cdc->user_control_cb = p_cdc->requested_complete_cb; p_cdc->user_complete_cb = p_cdc->requested_complete_cb;
set_data_format_request(p_cdc, internal_control_complete, xfer->user_data); set_data_format_request(p_cdc, internal_control_complete, xfer->user_data);
} else { } else {
// stage 1 failed, notify user // stage 1 failed, notify user
@@ -614,13 +617,13 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c
TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT);
cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid];
p_cdc->requested_line_state.value = (uint8_t) line_state; 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_state.dtr, p_cdc->requested_line_state.rts); 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 = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data);
if (ret && !complete_cb) { if (ret && !complete_cb) {
p_cdc->line_state = p_cdc->requested_line_state; p_cdc->line.control_state = p_cdc->requested_line.control_state;
} }
return ret; return ret;
} }
@@ -631,12 +634,12 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete
TU_LOG_P_CDC("set baudrate %lu", baudrate); TU_LOG_P_CDC("set baudrate %lu", baudrate);
cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid];
p_cdc->requested_line_coding.bit_rate = baudrate; p_cdc->requested_line.coding.bit_rate = baudrate;
bool ret = set_function_call(p_cdc, driver->set_baudrate, complete_cb, user_data); bool ret = set_function_call(p_cdc, driver->set_baudrate, complete_cb, user_data);
if (ret && !complete_cb) { if (ret && !complete_cb) {
p_cdc->line_coding.bit_rate = baudrate; p_cdc->line.coding.bit_rate = baudrate;
} }
// TU_LOG_P_CDC_BOOL("set baudrate", ret); // TU_LOG_P_CDC_BOOL("set baudrate", ret);
@@ -652,16 +655,16 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin
CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits));
cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid];
p_cdc->requested_line_coding.stop_bits = stop_bits; p_cdc->requested_line.coding.stop_bits = stop_bits;
p_cdc->requested_line_coding.parity = parity; p_cdc->requested_line.coding.parity = parity;
p_cdc->requested_line_coding.data_bits = data_bits; p_cdc->requested_line.coding.data_bits = data_bits;
bool ret = set_function_call(p_cdc, driver->set_data_format, complete_cb, user_data); bool ret = set_function_call(p_cdc, driver->set_data_format, complete_cb, user_data);
if (ret && !complete_cb) { if (ret && !complete_cb) {
p_cdc->line_coding.stop_bits = stop_bits; p_cdc->line.coding.stop_bits = stop_bits;
p_cdc->line_coding.parity = parity; p_cdc->line.coding.parity = parity;
p_cdc->line_coding.data_bits = data_bits; p_cdc->line.coding.data_bits = data_bits;
} }
// TU_LOG_P_CDC_BOOL("set data format", ret); // TU_LOG_P_CDC_BOOL("set data format", ret);
@@ -678,12 +681,12 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding,
CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits));
cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid];
p_cdc->requested_line_coding = *line_coding; p_cdc->requested_line.coding = *line_coding;
bool ret = set_function_call(p_cdc, driver->set_line_coding, complete_cb, user_data); bool ret = set_function_call(p_cdc, driver->set_line_coding, complete_cb, user_data);
if (ret && !complete_cb) { if (ret && !complete_cb) {
p_cdc->line_coding = *line_coding; p_cdc->line.coding = *line_coding;
} }
// TU_LOG_P_CDC_BOOL("set line coding", ret); // TU_LOG_P_CDC_BOOL("set line coding", ret);
@@ -921,25 +924,25 @@ static void acm_internal_control_complete(tuh_xfer_t *xfer) {
if (success) { if (success) {
switch (xfer->setup->bRequest) { switch (xfer->setup->bRequest) {
case CDC_REQUEST_SET_CONTROL_LINE_STATE: case CDC_REQUEST_SET_CONTROL_LINE_STATE:
p_cdc->line_state = p_cdc->requested_line_state; p_cdc->line.control_state = p_cdc->requested_line.control_state;
break; break;
case CDC_REQUEST_SET_LINE_CODING: case CDC_REQUEST_SET_LINE_CODING:
p_cdc->line_coding = p_cdc->requested_line_coding; p_cdc->line.coding = p_cdc->requested_line.coding;
break; break;
default: break; default: break;
} }
} }
xfer->complete_cb = p_cdc->user_control_cb; xfer->complete_cb = p_cdc->user_complete_cb;
if (xfer->complete_cb) { if (xfer->complete_cb) {
xfer->complete_cb(xfer); xfer->complete_cb(xfer);
} }
} }
static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_VERIFY(p_cdc->acm_capability.support_line_request); TU_VERIFY(p_cdc->acm.capability.support_line_request);
tusb_control_request_t const request = { tusb_control_request_t const request = {
.bmRequestType_bit = { .bmRequestType_bit = {
@@ -948,12 +951,12 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co
.direction = TUSB_DIR_OUT .direction = TUSB_DIR_OUT
}, },
.bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
.wValue = tu_htole16((uint16_t) p_cdc->requested_line_state.value), .wValue = tu_htole16((uint16_t) p_cdc->requested_line.control_state.value),
.wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber),
.wLength = 0 .wLength = 0
}; };
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
tuh_xfer_t xfer = { tuh_xfer_t xfer = {
.daddr = p_cdc->daddr, .daddr = p_cdc->daddr,
@@ -970,9 +973,9 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co
} }
static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_VERIFY(p_cdc->acm_capability.support_line_request); TU_VERIFY(p_cdc->acm.capability.support_line_request);
TU_VERIFY((p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8) || TU_VERIFY((p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8) ||
p_cdc->requested_line_coding.data_bits == 16); p_cdc->requested_line.coding.data_bits == 16);
tusb_control_request_t const request = { tusb_control_request_t const request = {
.bmRequestType_bit = { .bmRequestType_bit = {
@@ -988,9 +991,9 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_
// use usbh enum buf to hold line coding since user line_coding variable does not live long enough // use usbh enum buf to hold line coding since user line_coding variable does not live long enough
uint8_t *enum_buf = usbh_get_enum_buf(); uint8_t *enum_buf = usbh_get_enum_buf();
memcpy(enum_buf, &p_cdc->requested_line_coding, sizeof(cdc_line_coding_t)); memcpy(enum_buf, &p_cdc->requested_line.coding, sizeof(cdc_line_coding_t));
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
tuh_xfer_t xfer = { tuh_xfer_t xfer = {
.daddr = p_cdc->daddr, .daddr = p_cdc->daddr,
@@ -1007,15 +1010,15 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_
} }
static bool acm_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool acm_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate;
return acm_set_line_coding(p_cdc, complete_cb, user_data); return acm_set_line_coding(p_cdc, complete_cb, user_data);
} }
static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; p_cdc->requested_line.coding.stop_bits = p_cdc->line.coding.stop_bits;
p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity;
p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits;
return acm_set_line_coding(p_cdc, complete_cb, user_data); return acm_set_line_coding(p_cdc, complete_cb, user_data);
} }
@@ -1042,7 +1045,7 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1
while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) {
if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) {
// save ACM bmCapabilities // save ACM bmCapabilities
p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; p_cdc->acm.capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities;
} }
p_desc = tu_desc_next(p_desc); p_desc = tu_desc_next(p_desc);
@@ -1082,8 +1085,8 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) {
switch (state) { switch (state) {
case CONFIG_ACM_SET_CONTROL_LINE_STATE: case CONFIG_ACM_SET_CONTROL_LINE_STATE:
#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
if (p_cdc->acm_capability.support_line_request) { if (p_cdc->acm.capability.support_line_request) {
p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM;
TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, CONFIG_ACM_SET_LINE_CODING)); TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, CONFIG_ACM_SET_LINE_CODING));
break; break;
} }
@@ -1092,8 +1095,8 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_ACM_SET_LINE_CODING: case CONFIG_ACM_SET_LINE_CODING:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
if (p_cdc->acm_capability.support_line_request) { if (p_cdc->acm.capability.support_line_request) {
p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM;
TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, CONFIG_ACM_COMPLETE)); TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, CONFIG_ACM_COMPLETE));
break; break;
} }
@@ -1175,10 +1178,10 @@ static bool ftdi_change_speed(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb
} }
static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 7 && p_cdc->requested_line_coding.data_bits <= 8, 0); TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 7 && p_cdc->requested_line.coding.data_bits <= 8, 0);
uint16_t value = (uint16_t) ((p_cdc->requested_line_coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 uint16_t value = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3
(p_cdc->requested_line_coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding (p_cdc->requested_line.coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding
(p_cdc->requested_line_coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding (p_cdc->requested_line.coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding
// not each FTDI supports 1.5 stop bits // not each FTDI supports 1.5 stop bits
return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE,
@@ -1186,8 +1189,8 @@ static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet
} }
static inline bool ftdi_update_mctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static inline bool ftdi_update_mctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t value = (uint16_t) ((p_cdc->requested_line_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | uint16_t value = (uint16_t) ((p_cdc->requested_line.control_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) |
(p_cdc->requested_line_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); (p_cdc->requested_line.control_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW));
return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
value, p_cdc->ftdi.channel, complete_cb, user_data); value, p_cdc->ftdi.channel, complete_cb, user_data);
@@ -1206,35 +1209,35 @@ static void ftdi_internal_control_complete(tuh_xfer_t *xfer) {
if (success) { if (success) {
if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST &&
xfer->setup->bmRequestType == FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ) { xfer->setup->bmRequestType == FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ) {
p_cdc->line_state = p_cdc->requested_line_state; p_cdc->line.control_state = p_cdc->requested_line.control_state;
} }
if (xfer->setup->bRequest == FTDI_SIO_SET_DATA_REQUEST && if (xfer->setup->bRequest == FTDI_SIO_SET_DATA_REQUEST &&
xfer->setup->bmRequestType == FTDI_SIO_SET_DATA_REQUEST_TYPE ) { xfer->setup->bmRequestType == FTDI_SIO_SET_DATA_REQUEST_TYPE ) {
p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits;
p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity;
p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits;
} }
if (xfer->setup->bRequest == FTDI_SIO_SET_BAUDRATE_REQUEST && if (xfer->setup->bRequest == FTDI_SIO_SET_BAUDRATE_REQUEST &&
xfer->setup->bmRequestType == FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ) { xfer->setup->bmRequestType == FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ) {
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate;
} }
} }
xfer->complete_cb = p_cdc->user_control_cb; xfer->complete_cb = p_cdc->user_complete_cb;
if (xfer->complete_cb) { if (xfer->complete_cb) {
xfer->complete_cb(xfer); xfer->complete_cb(xfer);
} }
} }
static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data));
return true; return true;
} }
static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data));
return true; return true;
@@ -1261,7 +1264,7 @@ static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet
} }
static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(ftdi_update_mctrl(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); TU_ASSERT(ftdi_update_mctrl(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data));
return true; return true;
@@ -1339,15 +1342,15 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) {
// from here sequence overtaken from Linux Kernel function ftdi_open() // from here sequence overtaken from Linux Kernel function ftdi_open()
case CONFIG_FTDI_SIO_RESET: case CONFIG_FTDI_SIO_RESET:
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, CONFIG_FTDI_SET_DATA)); TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, CONFIG_FTDI_SET_DATA));
break; break;
// from here sequence overtaken from Linux Kernel function ftdi_set_termios() // from here sequence overtaken from Linux Kernel function ftdi_set_termios()
case CONFIG_FTDI_SET_DATA: case CONFIG_FTDI_SET_DATA:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM;
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE));
break; break;
#else #else
@@ -1356,7 +1359,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) {
case CONFIG_FTDI_SET_BAUDRATE: case CONFIG_FTDI_SET_BAUDRATE:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL));
break; break;
#else #else
@@ -1371,8 +1374,8 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) {
case CONFIG_FTDI_MODEM_CTRL: case CONFIG_FTDI_MODEM_CTRL:
#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM;
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE));
break; break;
#else #else
@@ -1529,7 +1532,7 @@ static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) {
} }
static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) {
uint32_t baud = p_cdc->requested_line_coding.bit_rate; uint32_t baud = p_cdc->requested_line.coding.bit_rate;
uint32_t div_value = 0; uint32_t div_value = 0;
TU_VERIFY(baud); TU_VERIFY(baud);
@@ -1661,16 +1664,16 @@ static inline bool cp210x_ifc_enable(cdch_interface_t *p_cdc, uint16_t enabled,
static bool cp210x_set_baudrate_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool cp210x_set_baudrate_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support"
uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); uint32_t baud_le = tu_htole32(p_cdc->requested_line.coding.bit_rate);
return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data);
} }
static bool cp210x_set_line_ctl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool cp210x_set_line_ctl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8, 0);
uint16_t lcr = (uint16_t) ((p_cdc->requested_line_coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 uint16_t lcr = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11
(p_cdc->requested_line_coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding (p_cdc->requested_line.coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding
(p_cdc->requested_line_coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding (p_cdc->requested_line.coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding
return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data);
} }
@@ -1679,7 +1682,7 @@ static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet
// CP210x has the same bit coding // CP210x has the same bit coding
return cp210x_set_request(p_cdc, CP210X_SET_MHS, return cp210x_set_request(p_cdc, CP210X_SET_MHS,
(uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS |
p_cdc->requested_line_state.value), p_cdc->requested_line.control_state.value),
NULL, 0, complete_cb, user_data); NULL, 0, complete_cb, user_data);
} }
@@ -1697,38 +1700,38 @@ static void cp210x_internal_control_complete(tuh_xfer_t *xfer) {
if (success) { if (success) {
switch (xfer->setup->bRequest) { switch (xfer->setup->bRequest) {
case CP210X_SET_MHS: case CP210X_SET_MHS:
p_cdc->line_state = p_cdc->requested_line_state; p_cdc->line.control_state = p_cdc->requested_line.control_state;
break; break;
case CP210X_SET_LINE_CTL: case CP210X_SET_LINE_CTL:
p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits;
p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity;
p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits;
break; break;
case CP210X_SET_BAUDRATE: case CP210X_SET_BAUDRATE:
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate;
break; break;
default: break; default: break;
} }
} }
xfer->complete_cb = p_cdc->user_control_cb; xfer->complete_cb = p_cdc->user_complete_cb;
if (xfer->complete_cb) { if (xfer->complete_cb) {
xfer->complete_cb(xfer); xfer->complete_cb(xfer);
} }
} }
static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data));
return true; return true;
} }
static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data));
return true; return true;
@@ -1752,7 +1755,7 @@ static bool cp210x_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t comple
} }
static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data));
return true; return true;
@@ -1799,8 +1802,8 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_CP210X_SET_BAUDRATE_REQUEST: case CONFIG_CP210X_SET_BAUDRATE_REQUEST:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM;
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL)); TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL));
break; break;
#else #else
@@ -1809,7 +1812,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_CP210X_SET_LINE_CTL: case CONFIG_CP210X_SET_LINE_CTL:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS)); TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS));
break; break;
#else #else
@@ -1818,8 +1821,8 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_CP210X_SET_DTR_RTS: case CONFIG_CP210X_SET_DTR_RTS:
#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM;
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE));
break; break;
#else #else
@@ -1923,8 +1926,8 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t comp
static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// CH34x signals are inverted // CH34x signals are inverted
uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) | uint8_t control = ~((p_cdc->requested_line.control_state.rts ? CH34X_BIT_RTS : 0) |
(p_cdc->requested_line_state.dtr ? CH34X_BIT_DTR : 0)); (p_cdc->requested_line.control_state.dtr ? CH34X_BIT_DTR : 0));
return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data);
} }
@@ -1947,14 +1950,14 @@ static void ch34x_internal_control_complete(tuh_xfer_t *xfer) {
switch (tu_le16toh(xfer->setup->wValue)) { switch (tu_le16toh(xfer->setup->wValue)) {
case CH34X_REG16_DIVISOR_PRESCALER: case CH34X_REG16_DIVISOR_PRESCALER:
// baudrate // baudrate
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate;
break; break;
case CH32X_REG16_LCR2_LCR: case CH32X_REG16_LCR2_LCR:
// data format // data format
p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits;
p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity;
p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits;
break; break;
default: break; default: break;
@@ -1962,28 +1965,28 @@ static void ch34x_internal_control_complete(tuh_xfer_t *xfer) {
break; break;
case CH34X_REQ_MODEM_CTRL: case CH34X_REQ_MODEM_CTRL:
p_cdc->line_state = p_cdc->requested_line_state; p_cdc->line.control_state = p_cdc->requested_line.control_state;
break; break;
default: break; default: break;
} }
} }
xfer->complete_cb = p_cdc->user_control_cb; xfer->complete_cb = p_cdc->user_complete_cb;
if (xfer->complete_cb) { if (xfer->complete_cb) {
xfer->complete_cb(xfer); xfer->complete_cb(xfer);
} }
} }
static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data));
return true; return true;
} }
static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data));
return true; return true;
@@ -2008,7 +2011,7 @@ static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple
} }
static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data));
return true; return true;
@@ -2073,7 +2076,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) {
// see drivers from WCH vendor, Linux kernel and FreeBSD // see drivers from WCH vendor, Linux kernel and FreeBSD
if (version >= 0x30) { if (version >= 0x30) {
// init CH34x with line coding // init CH34x with line coding
p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X;
uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc);
uint8_t const lcr = ch34x_get_lcr(p_cdc); uint8_t const lcr = ch34x_get_lcr(p_cdc);
TU_ASSERT(div_ps != 0 && lcr != 0); TU_ASSERT(div_ps != 0 && lcr != 0);
@@ -2085,7 +2088,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_CH34X_SPECIAL_REG_WRITE: case CONFIG_CH34X_SPECIAL_REG_WRITE:
// overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver
p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; p_cdc->line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X;
TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007,
cdch_process_set_config, CONFIG_CH34X_FLOW_CONTROL)); cdch_process_set_config, CONFIG_CH34X_FLOW_CONTROL));
break; break;
@@ -2098,8 +2101,8 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_CH34X_MODEM_CONTROL: case CONFIG_CH34X_MODEM_CONTROL:
#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM;
p_cdc->user_control_cb = cdch_process_set_config; p_cdc->user_complete_cb = cdch_process_set_config;
TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE));
break; break;
#else #else
@@ -2121,7 +2124,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) {
// calculate divisor and prescaler for baudrate, return it as 16-bit combined value // calculate divisor and prescaler for baudrate, return it as 16-bit combined value
static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc) { static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc) {
uint32_t const baval = p_cdc->requested_line_coding.bit_rate; uint32_t const baval = p_cdc->requested_line.coding.bit_rate;
uint8_t a; uint8_t a;
uint8_t b; uint8_t b;
uint32_t c; uint32_t c;
@@ -2171,9 +2174,9 @@ static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc) {
// calculate lcr value from data coding // calculate lcr value from data coding
static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) {
uint8_t const stop_bits = p_cdc->requested_line_coding.stop_bits; uint8_t const stop_bits = p_cdc->requested_line.coding.stop_bits;
uint8_t const parity = p_cdc->requested_line_coding.parity; uint8_t const parity = p_cdc->requested_line.coding.parity;
uint8_t const data_bits = p_cdc->requested_line_coding.data_bits; uint8_t const data_bits = p_cdc->requested_line.coding.data_bits;
uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX;
TU_VERIFY(data_bits >= 5 && data_bits <= 8); TU_VERIFY(data_bits >= 5 && data_bits <= 8);
@@ -2276,7 +2279,7 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c
static inline bool pl2303_set_control_lines(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static inline bool pl2303_set_control_lines(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// PL2303 has the same bit coding // PL2303 has the same bit coding
return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE,
p_cdc->requested_line_state.value, 0, NULL, 0, complete_cb, user_data); p_cdc->requested_line.control_state.value, 0, NULL, 0, complete_cb, user_data);
} }
//static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) //static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE])
@@ -2292,14 +2295,14 @@ static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t compl
* even to the same values as before. Thus we actually need to filter * even to the same values as before. Thus we actually need to filter
* in this specific case. * in this specific case.
*/ */
TU_VERIFY(p_cdc->requested_line_coding.data_bits != p_cdc->line_coding.data_bits || TU_VERIFY(p_cdc->requested_line.coding.data_bits != p_cdc->line.coding.data_bits ||
p_cdc->requested_line_coding.stop_bits != p_cdc->line_coding.stop_bits || p_cdc->requested_line.coding.stop_bits != p_cdc->line.coding.stop_bits ||
p_cdc->requested_line_coding.parity != p_cdc->line_coding.parity || p_cdc->requested_line.coding.parity != p_cdc->line.coding.parity ||
p_cdc->requested_line_coding.bit_rate != p_cdc->line_coding.bit_rate ); p_cdc->requested_line.coding.bit_rate != p_cdc->line.coding.bit_rate );
/* For reference buf[6] data bits value */ /* For reference buf[6] data bits value */
TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8, 0);
buf[6] = p_cdc->requested_line_coding.data_bits; buf[6] = p_cdc->requested_line.coding.data_bits;
/* For reference buf[0]:buf[3] baud rate value */ /* For reference buf[0]:buf[3] baud rate value */
TU_VERIFY(pl2303_encode_baud_rate(p_cdc, &buf[0])); TU_VERIFY(pl2303_encode_baud_rate(p_cdc, &buf[0]));
@@ -2307,14 +2310,14 @@ static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t compl
/* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=0 is 1 stop bits */
/* For reference buf[4]=1 is 1.5 stop bits */ /* For reference buf[4]=1 is 1.5 stop bits */
/* For reference buf[4]=2 is 2 stop bits */ /* For reference buf[4]=2 is 2 stop bits */
buf[4] = p_cdc->requested_line_coding.stop_bits; // PL2303 has the same coding buf[4] = p_cdc->requested_line.coding.stop_bits; // PL2303 has the same coding
/* For reference buf[5]=0 is none parity */ /* For reference buf[5]=0 is none parity */
/* For reference buf[5]=1 is odd parity */ /* For reference buf[5]=1 is odd parity */
/* For reference buf[5]=2 is even parity */ /* For reference buf[5]=2 is even parity */
/* For reference buf[5]=3 is mark parity */ /* For reference buf[5]=3 is mark parity */
/* For reference buf[5]=4 is space parity */ /* For reference buf[5]=4 is space parity */
buf[5] = p_cdc->requested_line_coding.parity; // PL2303 has the same coding buf[5] = p_cdc->requested_line.coding.parity; // PL2303 has the same coding
return pl2303_set_request(p_cdc, PL2303_SET_LINE_REQUEST, PL2303_SET_LINE_REQUEST_TYPE, 0, 0, return pl2303_set_request(p_cdc, PL2303_SET_LINE_REQUEST, PL2303_SET_LINE_REQUEST_TYPE, 0, 0,
buf, PL2303_LINE_CODING_BUFSIZE, complete_cb, user_data); buf, PL2303_LINE_CODING_BUFSIZE, complete_cb, user_data);
@@ -2350,45 +2353,45 @@ static void pl2303_internal_control_complete(tuh_xfer_t *xfer) {
if (success) { if (success) {
if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST &&
xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) {
p_cdc->line_coding = p_cdc->requested_line_coding; p_cdc->line.coding = p_cdc->requested_line.coding;
} }
if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST &&
xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) {
p_cdc->line_state = p_cdc->requested_line_state; p_cdc->line.control_state = p_cdc->requested_line.control_state;
} }
} }
xfer->complete_cb = p_cdc->user_control_cb; xfer->complete_cb = p_cdc->user_complete_cb;
if (xfer->complete_cb) { if (xfer->complete_cb) {
xfer->complete_cb(xfer); xfer->complete_cb(xfer);
} }
} }
static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data));
return true; return true;
} }
static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate;
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data));
return true; return true;
} }
static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; p_cdc->requested_line.coding.stop_bits = p_cdc->line.coding.stop_bits;
p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity;
p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits;
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data));
return true; return true;
} }
static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// PL2303 has the same bit coding // PL2303 has the same bit coding
p_cdc->user_control_cb = complete_cb; p_cdc->user_complete_cb = complete_cb;
TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data));
return true; return true;
} }
@@ -2458,7 +2461,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) {
switch (state) { switch (state) {
// from here sequence overtaken from Linux Kernel function pl2303_startup() // from here sequence overtaken from Linux Kernel function pl2303_startup()
case CONFIG_PL2303_DETECT_TYPE: case CONFIG_PL2303_DETECT_TYPE:
p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config p_cdc->user_complete_cb = cdch_process_set_config;// set once for whole process config
// get type and quirks (step 1) // get type and quirks (step 1)
type = pl2303_detect_type(p_cdc, 1); type = pl2303_detect_type(p_cdc, 1);
TU_ASSERT(type != PL2303_TYPE_UNKNOWN); TU_ASSERT(type != PL2303_TYPE_UNKNOWN);
@@ -2606,7 +2609,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) {
// unnecessary pl2303_get_line_request() is skipped due to a stall // unnecessary pl2303_get_line_request() is skipped due to a stall
case CONFIG_PL2303_LINE_CODING: case CONFIG_PL2303_LINE_CODING:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM;
TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL));
break; break;
#else #else
@@ -2615,7 +2618,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) {
case CONFIG_PL2303_MODEM_CONTROL: case CONFIG_PL2303_MODEM_CONTROL:
#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM;
TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE));
break; break;
#else #else
@@ -2861,7 +2864,7 @@ static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODI
} }
static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) { static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) {
uint32_t baud = p_cdc->requested_line_coding.bit_rate; uint32_t baud = p_cdc->requested_line.coding.bit_rate;
uint32_t baud_sup; uint32_t baud_sup;
const pl2303_type_data_t* type_data = &pl2303_type_data[p_cdc->pl2303.type]; const pl2303_type_data_t* type_data = &pl2303_type_data[p_cdc->pl2303.type];