changed to use of p_cdc->requested_line_coding

This commit is contained in:
IngHK
2024-02-22 14:59:16 +01:00
parent 829ea52873
commit 2f50f5a426

View File

@@ -63,12 +63,10 @@ typedef struct {
cdc_acm_capability_t acm_capability;
TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width
uint8_t line_state; // DTR (bit0), RTS (bit1)
#if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X
cdc_line_coding_t requested_line_coding;
TU_ATTR_ALIGNED(4) cdc_line_coding_t requested_line_coding;
// 1 byte padding
#endif
uint8_t line_state; // DTR (bit0), RTS (bit1)
tuh_xfer_cb_t user_control_cb;
@@ -95,9 +93,9 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC];
static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
static void acm_process_config(tuh_xfer_t* xfer);
static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, 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);
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_line_coding(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, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
//------------- FTDI prototypes -------------//
@@ -109,9 +107,9 @@ static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST};
static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len);
static void ftdi_process_config(tuh_xfer_t* xfer);
static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool ftdi_sio_set_baudrate(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);
static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
#endif
@@ -124,9 +122,9 @@ static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIS
static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
static void cp210x_process_config(tuh_xfer_t* xfer);
static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, 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);
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_line_coding(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, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
#endif
@@ -139,9 +137,9 @@ static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}
static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len);
static void ch34x_process_config(tuh_xfer_t* xfer);
static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, 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);
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_line_coding(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, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
#endif
@@ -170,9 +168,9 @@ typedef struct {
bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len);
void (*const process_set_config)(tuh_xfer_t* xfer);
bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
bool (*const set_data_format)(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
bool (*const set_line_coding)(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, 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);
#if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL
uint8_t const * name;
#endif
@@ -276,6 +274,7 @@ static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const
p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber;
p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass;
p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol;
p_cdc->line_coding = (cdc_line_coding_t) { 0, 0, 0, 0 };
p_cdc->line_state = 0;
return p_cdc;
}
@@ -451,12 +450,14 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete
TU_LOG_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;
if (complete_cb) {
return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data);
return driver->set_baudrate(p_cdc, complete_cb, user_data);
} else {
// blocking
xfer_result_t result = XFER_RESULT_INVALID;
bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result);
bool ret = driver->set_baudrate(p_cdc, complete_cb, (uintptr_t) &result);
if (user_data) {
// user_data is not NULL, return result via user_data
@@ -477,12 +478,16 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin
data_bits, parity, stop_bits);
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.parity = parity;
p_cdc->requested_line_coding.data_bits = data_bits;
if (complete_cb) {
return driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, user_data);
return driver->set_data_format(p_cdc, complete_cb, user_data);
} else {
// blocking
xfer_result_t result = XFER_RESULT_INVALID;
bool ret = driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, (uintptr_t) &result);
bool ret = driver->set_data_format(p_cdc, complete_cb, (uintptr_t) &result);
if (user_data) {
// user_data is not NULL, return result via user_data
@@ -491,7 +496,7 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin
TU_VERIFY(ret && result == XFER_RESULT_SUCCESS);
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;
return true;
}
@@ -504,12 +509,14 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding,
line_coding->bit_rate, line_coding->data_bits, line_coding->parity, line_coding->stop_bits);
cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid];
p_cdc->requested_line_coding = *line_coding;
if ( complete_cb ) {
return driver->set_line_coding(p_cdc, line_coding, complete_cb, user_data);
return driver->set_line_coding(p_cdc, complete_cb, user_data);
} else {
// blocking
xfer_result_t result = XFER_RESULT_INVALID;
bool ret = driver->set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result);
bool ret = driver->set_line_coding(p_cdc, complete_cb, (uintptr_t) &result);
if (user_data) {
// user_data is not NULL, return result via user_data
@@ -714,8 +721,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) {
break;
case CDC_REQUEST_SET_LINE_CODING:
uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength));
memcpy(&p_cdc->line_coding, xfer->buffer, len);
p_cdc->line_coding = p_cdc->requested_line_coding;
break;
default: break;
@@ -758,7 +764,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st
return true;
}
static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, 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) {
tusb_control_request_t const request = {
.bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_INTERFACE,
@@ -773,7 +779,7 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const
// 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();
memcpy(enum_buf, 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;
tuh_xfer_t xfer = {
@@ -789,23 +795,19 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const
return true;
}
static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
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;
cdc_line_coding_t line_coding;
line_coding.bit_rate = p_cdc->line_coding.bit_rate;
line_coding.stop_bits = stop_bits;
line_coding.parity = parity;
line_coding.data_bits = data_bits;
return acm_set_line_coding(p_cdc, &line_coding, 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, uint32_t baudrate, 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.parity = p_cdc->line_coding.parity;
p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits;
TU_VERIFY(p_cdc->acm_capability.support_line_request);
cdc_line_coding_t line_coding = p_cdc->line_coding;
line_coding.bit_rate = baudrate;
return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data);
return acm_set_line_coding(p_cdc, complete_cb, user_data);
}
//------------- Enumeration -------------//
@@ -879,11 +881,11 @@ static void acm_process_config(tuh_xfer_t* xfer) {
case CONFIG_ACM_SET_LINE_CODING:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
if (p_cdc->acm_capability.support_line_request) {
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE),);
break;
}
if (p_cdc->acm_capability.support_line_request) {
p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM;
TU_ASSERT(acm_set_line_coding(p_cdc, acm_process_config, CONFIG_ACM_COMPLETE),);
break;
}
#endif
TU_ATTR_FALLTHROUGH;
@@ -902,7 +904,7 @@ static void acm_process_config(tuh_xfer_t* xfer) {
//--------------------------------------------------------------------+
#if CFG_TUH_CDC_FTDI
static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud);
static uint32_t ftdi_232bm_baud_to_divisor(cdch_interface_t* p_cdc);
//------------- Control Request -------------//
@@ -967,32 +969,26 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) {
}
}
static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate);
static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(p_cdc);
p_cdc->user_control_cb = complete_cb;
p_cdc->requested_line_coding.bit_rate = baudrate;
TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor,
complete_cb ? ftdi_internal_control_complete : NULL, user_data));
return true;
}
static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
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) {
(void) p_cdc;
(void) stop_bits;
(void) parity;
(void) data_bits;
(void) complete_cb;
(void) user_data;
// TODO not implemented yet
return false;
}
static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
(void) p_cdc;
(void) line_coding;
(void) complete_cb;
(void) user_data;
// TODO not implemented yet
@@ -1056,11 +1052,11 @@ static void ftdi_process_config(tuh_xfer_t* xfer) {
case CONFIG_FTDI_SET_BAUDRATE: {
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, ftdi_process_config, CONFIG_FTDI_SET_DATA),);
break;
p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate;
TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA),);
break;
#else
TU_ATTR_FALLTHROUGH;
TU_ATTR_FALLTHROUGH;
#endif
}
@@ -1107,8 +1103,8 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) {
return divisor;
}
static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) {
return ftdi_232bm_baud_base_to_divisor(baud, 48000000u);
static uint32_t ftdi_232bm_baud_to_divisor(cdch_interface_t* p_cdc) {
return ftdi_232bm_baud_base_to_divisor(p_cdc->requested_line_coding.bit_rate, 48000000u);
}
#endif
@@ -1175,9 +1171,7 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) {
break;
case CP210X_SET_BAUDRATE:
uint32_t baudrate;
memcpy(&baudrate, xfer->buffer, sizeof(uint32_t));
p_cdc->line_coding.bit_rate = tu_le32toh(baudrate);
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
break;
default: break;
@@ -1190,29 +1184,24 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) {
}
}
static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint32_t baud_le = tu_htole32(baudrate);
static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate);
p_cdc->user_control_cb = complete_cb;
return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4,
complete_cb ? cp210x_internal_control_complete : NULL, user_data);
}
static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
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) {
(void) p_cdc;
(void) stop_bits;
(void) parity;
(void) data_bits;
(void) complete_cb;
(void) user_data;
// TODO not implemented yet
return false;
}
static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// TODO implement later
(void) p_cdc;
(void) line_coding;
(void) complete_cb;
(void) user_data;
return false;
@@ -1265,11 +1254,11 @@ static void cp210x_process_config(tuh_xfer_t* xfer) {
case CONFIG_CP210X_SET_BAUDRATE: {
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),);
break;
p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate;
TU_ASSERT(cp210x_set_baudrate(p_cdc, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),);
break;
#else
TU_ATTR_FALLTHROUGH;
TU_ATTR_FALLTHROUGH;
#endif
}
@@ -1306,8 +1295,8 @@ static void cp210x_process_config(tuh_xfer_t* xfer) {
#if CFG_TUH_CDC_CH34X
static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits);
static uint16_t ch34x_get_divisor_prescaler(uint32_t baval);
static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc);
static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc);
//------------- Control Request -------------//
@@ -1368,9 +1357,8 @@ static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16
// return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data );
//}
static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate);
static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc);
TU_VERIFY(div_ps);
TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps,
complete_cb, user_data));
@@ -1436,25 +1424,17 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) {
}
}
static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.stop_bits = stop_bits;
p_cdc->requested_line_coding.parity = parity;
p_cdc->requested_line_coding.data_bits = data_bits;
uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits);
static bool ch34x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint8_t const lcr = ch34x_get_lcr(p_cdc);
TU_VERIFY(lcr);
TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr,
complete_cb ? ch34x_internal_control_complete : NULL, user_data));
return true;
}
static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding.bit_rate = baudrate;
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;
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate,
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;
}
@@ -1468,8 +1448,7 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) {
if (xfer->result == XFER_RESULT_SUCCESS) {
// stage 1 success, continue to stage 2
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity,
p_cdc->requested_line_coding.data_bits, ch34x_internal_control_complete, xfer->user_data), );
TU_ASSERT(ch34x_set_data_format(p_cdc, ch34x_internal_control_complete, xfer->user_data), );
} else {
// stage 1 failed, notify user
xfer->complete_cb = p_cdc->user_control_cb;
@@ -1480,31 +1459,24 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) {
}
// 2 stages: set baudrate (stage1) + set data format (stage2)
static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding,
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
p_cdc->requested_line_coding = *line_coding;
static bool ch34x_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;
if (complete_cb) {
// stage 1 set baudrate
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate,
ch34x_set_line_coding_stage1_complete, user_data));
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, ch34x_set_line_coding_stage1_complete, user_data));
} else {
// sync call
xfer_result_t result;
// stage 1 set baudrate
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result));
TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, NULL, (uintptr_t) &result));
TU_VERIFY(result == XFER_RESULT_SUCCESS);
p_cdc->line_coding.bit_rate = line_coding->bit_rate;
p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
// stage 2 set data format
TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits,
NULL, (uintptr_t) &result));
TU_ASSERT(ch34x_set_data_format(p_cdc, NULL, (uintptr_t) &result));
TU_VERIFY(result == XFER_RESULT_SUCCESS);
p_cdc->line_coding.stop_bits = line_coding->stop_bits;
p_cdc->line_coding.parity = line_coding->parity;
p_cdc->line_coding.data_bits = line_coding->data_bits;
// update transfer result, user_data is expected to point to xfer_result_t
if (user_data) {
@@ -1592,10 +1564,10 @@ static void ch34x_process_config(tuh_xfer_t* xfer) {
// only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD
TU_ASSERT (version >= 0x30,);
// init CH34x with line coding
cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X;
uint16_t const div_ps = ch34x_get_divisor_prescaler(line_coding.bit_rate);
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);
TU_ASSERT(div_ps, );
uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits);
uint8_t const lcr = ch34x_get_lcr(p_cdc);
TU_ASSERT(lcr, );
TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps,
ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),);
@@ -1604,7 +1576,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) {
case CONFIG_CH34X_SPECIAL_REG_WRITE:
// 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, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),);
break;
@@ -1631,7 +1603,8 @@ static void ch34x_process_config(tuh_xfer_t* xfer) {
//------------- Helper -------------//
// calculate divisor and prescaler for baudrate, return it as 16-bit combined value
static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) {
static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc) {
uint32_t const baval = p_cdc->requested_line_coding.bit_rate;
uint8_t a;
uint8_t b;
uint32_t c;
@@ -1680,7 +1653,11 @@ static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) {
}
// calculate lcr value from data coding
static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits) {
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 parity = p_cdc->requested_line_coding.parity;
uint8_t const data_bits = p_cdc->requested_line_coding.data_bits;
uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX;
TU_VERIFY(data_bits >= 5 && data_bits <= 8, 0);
lcr |= (uint8_t) (data_bits - 5);