summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2024-01-19 15:58:05 +0700
committerhathach <[email protected]>2024-01-19 15:58:05 +0700
commit98781bb903d94190d57ad4b9436a85a31d67404c (patch)
tree2aa4c7c8cd1f24122c2d6a53aea9e53c7cf73ff2
parent23c2d929a1bae39578b195c7c7b068fb718212bd (diff)
- add ch34x_set_data_format()
- add ch34x_set_line_coding()
-rw-r--r--examples/host/cdc_msc_hid/src/cdc_app.c68
-rw-r--r--src/class/cdc/cdc_host.c100
-rw-r--r--src/class/cdc/serial/ch34x.h3
3 files changed, 102 insertions, 69 deletions
diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c
index a1b26e49c..81052047c 100644
--- a/examples/host/cdc_msc_hid/src/cdc_app.c
+++ b/examples/host/cdc_msc_hid/src/cdc_app.c
@@ -27,20 +27,11 @@
#include "tusb.h"
#include "bsp/board_api.h"
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM DECLARATION
-//--------------------------------------------------------------------+
-
-
-//------------- IMPLEMENTATION -------------//
-
-size_t get_console_inputs(uint8_t* buf, size_t bufsize)
-{
+size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
size_t count = 0;
- while (count < bufsize)
- {
+ while (count < bufsize) {
int ch = board_getchar();
- if ( ch <= 0 ) break;
+ if (ch <= 0) break;
buf[count] = (uint8_t) ch;
count++;
@@ -49,22 +40,18 @@ size_t get_console_inputs(uint8_t* buf, size_t bufsize)
return count;
}
-void cdc_app_task(void)
-{
- uint8_t buf[64+1]; // +1 for extra null character
- uint32_t const bufsize = sizeof(buf)-1;
+void cdc_app_task(void) {
+ uint8_t buf[64 + 1]; // +1 for extra null character
+ uint32_t const bufsize = sizeof(buf) - 1;
uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0;
// loop over all mounted interfaces
- for(uint8_t idx=0; idx<CFG_TUH_CDC; idx++)
- {
- if ( tuh_cdc_mounted(idx) )
- {
+ for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
+ if (tuh_cdc_mounted(idx)) {
// console --> cdc interfaces
- if (count)
- {
+ if (count) {
tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx);
}
@@ -72,11 +59,14 @@ void cdc_app_task(void)
}
}
+//--------------------------------------------------------------------+
+// TinyUSB callbacks
+//--------------------------------------------------------------------+
+
// Invoked when received new data
-void tuh_cdc_rx_cb(uint8_t idx)
-{
- uint8_t buf[64+1]; // +1 for extra null character
- uint32_t const bufsize = sizeof(buf)-1;
+void tuh_cdc_rx_cb(uint8_t idx) {
+ uint8_t buf[64 + 1]; // +1 for extra null character
+ uint32_t const bufsize = sizeof(buf) - 1;
// forward cdc interfaces -> console
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
@@ -85,29 +75,31 @@ void tuh_cdc_rx_cb(uint8_t idx)
printf((char*) buf);
}
-void tuh_cdc_mount_cb(uint8_t idx)
-{
- tuh_itf_info_t itf_info = { 0 };
+// Invoked when a device with CDC interface is mounted
+// idx is index of cdc interface in the internal pool.
+void tuh_cdc_mount_cb(uint8_t idx) {
+ tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info);
- printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
+ printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
+ itf_info.desc.bInterfaceNumber);
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
// CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration
// otherwise you need to call tuh_cdc_set_line_coding() first
- cdc_line_coding_t line_coding = { 0 };
- if ( tuh_cdc_get_local_line_coding(idx, &line_coding) )
- {
+ cdc_line_coding_t line_coding = {0};
+ if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
printf(" Baudrate: %lu, 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);
+ printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
}
#endif
}
-void tuh_cdc_umount_cb(uint8_t idx)
-{
- tuh_itf_info_t itf_info = { 0 };
+// Invoked when a device with CDC interface is unmounted
+void tuh_cdc_umount_cb(uint8_t idx) {
+ tuh_itf_info_t itf_info = {0};
tuh_cdc_itf_get_info(idx, &itf_info);
- printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber);
+ printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr,
+ itf_info.desc.bInterfaceNumber);
}
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index bfaa64a77..37fa30982 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -1327,48 +1327,88 @@ static void ch34x_control_complete(tuh_xfer_t* xfer) {
process_internal_control_complete(p_cdc, 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) {
-// uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits);
-// 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;
-//
-// TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr,
-// complete_cb ? ch34x_control_complete : NULL, user_data));
-// return false;
-//}
+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;
-static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits);
+ TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr,
+ complete_cb ? ch34x_control_complete : NULL, user_data));
+ return true;
+}
+
+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);
TU_VERIFY(div_ps != 0);
+ TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps,
+ complete_cb, 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;
p_cdc->user_control_cb = complete_cb;
- TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps,
- complete_cb ? ch34x_control_complete : NULL, user_data));
-
+ TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate,
+ complete_cb ? ch34x_control_complete : NULL, user_data));
return true;
}
-//static void ch34x_set_line_coding_stage1(tuh_xfer_t* xfer) {
-//
-//}
+static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) {
+ uint8_t const itf_num = 0;
+ uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
+ cdch_interface_t* p_cdc = get_itf(idx);
+ TU_ASSERT(p_cdc, );
+ 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_control_complete, xfer->user_data), );
+ } else {
+ // stage 1 failed, notify user
+ xfer->complete_cb = p_cdc->user_control_cb;
+ if (xfer->complete_cb) {
+ xfer->complete_cb(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->baudrate_requested = line_coding->bit_rate;
-// p_cdc->user_control_cb = complete_cb;
-// uint8_t factor, divisor, lcr;
-// TU_ASSERT (ch34x_get_factor_divisor(line_coding->bit_rate, &factor, &divisor));
-// TU_ASSERT (ch34x_get_lcr(line_coding, &lcr));
-// TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, (uint16_t) (lcr << 8 | 0x9c), (uint16_t) (factor << 8 | 0x80 | divisor),
-// complete_cb ? ch34x_control_complete : NULL, user_data));
- (void) p_cdc;
- (void) line_coding;
- (void) complete_cb;
- (void) user_data;
+ p_cdc->requested_line_coding = *line_coding;
+ 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));
+ } 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_VERIFY(result == XFER_RESULT_SUCCESS);
+ p_cdc->line_coding.bit_rate = 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_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) {
+ user_data = result;
+ }
+ }
return true;
}
diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h
index 3f78a3007..5def8d212 100644
--- a/src/class/cdc/serial/ch34x.h
+++ b/src/class/cdc/serial/ch34x.h
@@ -63,7 +63,8 @@
#define CH341_REG_0x2C 0x2C // undocumented register
#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts)
-#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER)
+#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER)
+#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR)
// modem control bits
#define CH34X_BIT_RTS ( 1 << 6 )