Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1370015 > unrolled thread

Major improvements to the ch341 driver

Started byGrigori Goronzy <greg@chown.ath.cx>
First post2016-04-02 19:20 +0200
Last post2016-04-06 14:10 +0200
Articles 10 — 4 participants

Back to article view | Back to linux.kernel


Contents

  Major improvements to the ch341 driver Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:20 +0200
    [PATCH v2 04/14] USB: ch341: add definitions for modem control Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:30 +0200
    [PATCH v2 13/14] USB: ch341: get rid of default configuration Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:30 +0200
    [PATCH v2 09/14] USB: ch341: add support for RTS/CTS flow control Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:30 +0200
    [PATCH v2 05/14] USB: ch341: fix USB buffer allocations Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:30 +0200
      Re: [PATCH v2 05/14] USB: ch341: fix USB buffer allocations Oliver Neukum <oneukum@suse.com> - 2016-04-04 09:20 +0200
    [PATCH v2 03/14] USB: ch341: add LCR register definitions Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:30 +0200
    [PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits Grigori Goronzy <greg@chown.ath.cx> - 2016-04-02 19:30 +0200
      Re: [PATCH v2 07/14] USB: ch341: add support for parity, frame length,  stop bits Karl Palsson <karlp@tweak.net.au> - 2016-04-03 18:00 +0200
      Re: [PATCH v2 07/14] USB: ch341: add support for parity, frame  length, stop bits One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> - 2016-04-06 14:10 +0200

#1370015 — Major improvements to the ch341 driver

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:20 +0200
SubjectMajor improvements to the ch341 driver
Message-ID<rjxnk-74U-3@gated-at.bofh.it>
Hi,

this patchset consists of several improvements and cleanups to the
ch341 driver, which has been mostly unmaintained for the last few
years, despite major shortcomings.  For instance, there is no support
at all for parity, which is an often used feature.  Other settings
are missing too, as is hardware flow control.

Here's a summary of changes:

- Restructured initialization and configuration, which makes CH341A hardware
  work for the first time and is the basis for some following additions.
- Support for the different parity modes, including mark/space
- Support for two stop bits
- Support for 5, 6 and 7 bit transfers
- Support for RTS/CTS hardware flow control
- Improved handling of B0 and DTR/RTS lines
- Added tx_empty callback
- Extracted magic numbers into definitions
- Cleaned up code style and debug/error messages

This has been tested on several different CH340G dongles and a
CH341A adapter which is designed for EEPROM programming (but still
supports UART).  Functionality of the different configurations has
been verified with a logic analyzer. In addition I did some quick
interoperability tests with a CP2102 UART.  My original motivation
for this work was parity support which I needed for stcgal [1],
and it works fine with that software too, of course.

Please review.  I would also appreciate to get some more testing
done.  In particular, I would like to make the sure the restructured
initialization does not break anything.

If you wonder, this is v2 because I initially sent it to the wrong list.

Best regards
Grigori

[1] https://github.com/grigorig/stcgal

[toc] | [next] | [standalone]


#1370016 — [PATCH v2 04/14] USB: ch341: add definitions for modem control

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:30 +0200
Subject[PATCH v2 04/14] USB: ch341: add definitions for modem control
Message-ID<rjxx0-78K-3@gated-at.bofh.it>
In reply to#1370015
Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
---
 drivers/usb/serial/ch341.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 788c75a..25c5d8d 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -62,6 +62,7 @@
  * the Net/FreeBSD uchcom.c driver by Takanori Watanabe.  Domo arigato.
  */
 
+#define CH341_MODEM_CTRL       0xA4
 #define CH341_REQ_WRITE_REG    0x9A
 #define CH341_REQ_READ_REG     0x95
 #define CH341_REG_BREAK1       0x05
@@ -163,7 +164,7 @@ static int ch341_set_baudrate(struct usb_device *dev,
 
 static int ch341_set_handshake(struct usb_device *dev, u8 control)
 {
-	return ch341_control_out(dev, 0xa4, ~control, 0);
+	return ch341_control_out(dev, CH341_MODEM_CTRL, ~control, 0);
 }
 
 static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1370017 — [PATCH v2 13/14] USB: ch341: get rid of default configuration

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:30 +0200
Subject[PATCH v2 13/14] USB: ch341: get rid of default configuration
Message-ID<rjxx0-78K-5@gated-at.bofh.it>
In reply to#1370015
If the serial port hasn't been opened yet, no baud rate should be
set and RTS/DTR need to be deasserted.

Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
---
 drivers/usb/serial/ch341.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 3b9a43d..6981e2ad 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -25,7 +25,6 @@
 #include <linux/serial.h>
 #include <asm/unaligned.h>
 
-#define DEFAULT_BAUD_RATE 9600
 #define DEFAULT_TIMEOUT   1000
 
 /* flags for IO-Bits */
@@ -235,10 +234,6 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
 	if (r < 0)
 		goto out;
 
-	r = ch341_init_set_baudrate(dev, priv, 0);
-	if (r < 0)
-		goto out;
-
 	r = ch341_set_handshake(dev, priv->line_control);
 	if (r < 0)
 		goto out;
@@ -261,8 +256,6 @@ static int ch341_port_probe(struct usb_serial_port *port)
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	priv->baud_rate = DEFAULT_BAUD_RATE;
-	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
 	r = ch341_configure(port->serial->dev, priv);
 	if (r < 0)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1370018 — [PATCH v2 09/14] USB: ch341: add support for RTS/CTS flow control

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:30 +0200
Subject[PATCH v2 09/14] USB: ch341: add support for RTS/CTS flow control
Message-ID<rjxx0-78K-7@gated-at.bofh.it>
In reply to#1370015
v2: use correct flag variable

Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
---
 drivers/usb/serial/ch341.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 58309d1..d956f75 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -69,6 +69,7 @@
 #define CH341_REQ_READ_REG     0x95
 #define CH341_REG_BREAK1       0x05
 #define CH341_REG_LCR          0x18
+#define CH341_REG_RTSCTS       0x27
 #define CH341_NBREAK_BITS_REG1 0x01
 
 #define CH341_LCR_ENABLE_RX    0x80
@@ -403,6 +404,16 @@ static void ch341_set_termios(struct tty_struct *tty,
 
 	ch341_set_handshake(port->serial->dev, priv->line_control);
 
+	if (cflag & CRTSCTS) {
+		r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG,
+				CH341_REG_RTSCTS | ((uint16_t)CH341_REG_RTSCTS << 8),
+				0x0101);
+		if (r < 0) {
+			dev_err(&port->dev, "%s - USB control write error (%d)\n",
+					__func__, r);
+			tty->termios.c_cflag &= ~CRTSCTS;
+		}
+	}
 }
 
 static void ch341_break_ctl(struct tty_struct *tty, int break_state)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1370019 — [PATCH v2 05/14] USB: ch341: fix USB buffer allocations

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:30 +0200
Subject[PATCH v2 05/14] USB: ch341: fix USB buffer allocations
Message-ID<rjxx0-78K-13@gated-at.bofh.it>
In reply to#1370015
Use the correct types and sizes.

Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
---
 drivers/usb/serial/ch341.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 25c5d8d..6781911 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -116,7 +116,7 @@ static int ch341_control_out(struct usb_device *dev, u8 request,
 
 static int ch341_control_in(struct usb_device *dev,
 			    u8 request, u16 value, u16 index,
-			    char *buf, unsigned bufsize)
+			    unsigned char *buf, unsigned bufsize)
 {
 	int r;
 
@@ -169,9 +169,9 @@ static int ch341_set_handshake(struct usb_device *dev, u8 control)
 
 static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
 {
-	char *buffer;
+	unsigned char *buffer;
 	int r;
-	const unsigned size = 8;
+	const unsigned size = 2;
 	unsigned long flags;
 
 	buffer = kmalloc(size, GFP_KERNEL);
@@ -199,9 +199,9 @@ out:	kfree(buffer);
 
 static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
 {
-	char *buffer;
+	unsigned char *buffer;
 	int r;
-	const unsigned size = 8;
+	const unsigned size = 2;
 
 	buffer = kmalloc(size, GFP_KERNEL);
 	if (!buffer)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1370406 — Re: [PATCH v2 05/14] USB: ch341: fix USB buffer allocations

FromOliver Neukum <oneukum@suse.com>
Date2016-04-04 09:20 +0200
SubjectRe: [PATCH v2 05/14] USB: ch341: fix USB buffer allocations
Message-ID<rk6XM-82e-7@gated-at.bofh.it>
In reply to#1370019
On Sat, 2016-04-02 at 19:07 +0200, Grigori Goronzy wrote:
> Use the correct types and sizes.
> 
> Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
> ---
>  drivers/usb/serial/ch341.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
> index 25c5d8d..6781911 100644
> --- a/drivers/usb/serial/ch341.c
> +++ b/drivers/usb/serial/ch341.c
> @@ -116,7 +116,7 @@ static int ch341_control_out(struct usb_device *dev, u8 request,
>  
>  static int ch341_control_in(struct usb_device *dev,
>  			    u8 request, u16 value, u16 index,
> -			    char *buf, unsigned bufsize)
> +			    unsigned char *buf, unsigned bufsize)

If you do that, you can just use u8 *

>  {
>  	int r;
>  
> @@ -169,9 +169,9 @@ static int ch341_set_handshake(struct usb_device *dev, u8 control)
>  
>  static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
>  {
> -	char *buffer;
> +	unsigned char *buffer;
>  	int r;
> -	const unsigned size = 8;
> +	const unsigned size = 2;
>  	unsigned long flags;
>  
>  	buffer = kmalloc(size, GFP_KERNEL);
> @@ -199,9 +199,9 @@ out:	kfree(buffer);
>  
>  static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
>  {
> -	char *buffer;
> +	unsigned char *buffer;
>  	int r;
> -	const unsigned size = 8;
> +	const unsigned size = 2;

Are you sure only 2 are used?
For the amount of space needed it makes no difference.

	Regards
		Oliver

[toc] | [prev] | [next] | [standalone]


#1370020 — [PATCH v2 03/14] USB: ch341: add LCR register definitions

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:30 +0200
Subject[PATCH v2 03/14] USB: ch341: add LCR register definitions
Message-ID<rjxx0-78K-9@gated-at.bofh.it>
In reply to#1370015
BREAK2 seems to be a misnomer, the register configures various aspects
of the UART configuration.

Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
---
 drivers/usb/serial/ch341.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 9fb9089..788c75a 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -65,10 +65,19 @@
 #define CH341_REQ_WRITE_REG    0x9A
 #define CH341_REQ_READ_REG     0x95
 #define CH341_REG_BREAK1       0x05
-#define CH341_REG_BREAK2       0x18
+#define CH341_REG_LCR          0x18
 #define CH341_NBREAK_BITS_REG1 0x01
-#define CH341_NBREAK_BITS_REG2 0x40
 
+#define CH341_LCR_ENABLE_RX    0x80
+#define CH341_LCR_ENABLE_TX    0x40
+#define CH341_LCR_MARK_SPACE   0x20
+#define CH341_LCR_PAR_EVEN     0x10
+#define CH341_LCR_ENABLE_PAR   0x08
+#define CH341_LCR_STOP_BITS_2  0x04
+#define CH341_LCR_CS8          0x03
+#define CH341_LCR_CS7          0x02
+#define CH341_LCR_CS6          0x01
+#define CH341_LCR_CS5          0x00
 
 static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x4348, 0x5523) },
@@ -371,7 +380,7 @@ static void ch341_set_termios(struct tty_struct *tty,
 static void ch341_break_ctl(struct tty_struct *tty, int break_state)
 {
 	const uint16_t ch341_break_reg =
-		CH341_REG_BREAK1 | ((uint16_t) CH341_REG_BREAK2 << 8);
+		CH341_REG_BREAK1 | ((uint16_t) CH341_REG_LCR << 8);
 	struct usb_serial_port *port = tty->driver_data;
 	int r;
 	uint16_t reg_contents;
@@ -393,11 +402,11 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state)
 	if (break_state != 0) {
 		dev_dbg(&port->dev, "%s - Enter break state requested\n", __func__);
 		break_reg[0] &= ~CH341_NBREAK_BITS_REG1;
-		break_reg[1] &= ~CH341_NBREAK_BITS_REG2;
+		break_reg[1] &= ~CH341_LCR_ENABLE_TX;
 	} else {
 		dev_dbg(&port->dev, "%s - Leave break state requested\n", __func__);
 		break_reg[0] |= CH341_NBREAK_BITS_REG1;
-		break_reg[1] |= CH341_NBREAK_BITS_REG2;
+		break_reg[1] |= CH341_LCR_ENABLE_TX;
 	}
 	dev_dbg(&port->dev, "%s - New ch341 break register contents - reg1: %x, reg2: %x\n",
 		__func__, break_reg[0], break_reg[1]);
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1370021 — [PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits

FromGrigori Goronzy <greg@chown.ath.cx>
Date2016-04-02 19:30 +0200
Subject[PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits
Message-ID<rjxx1-78K-17@gated-at.bofh.it>
In reply to#1370015
With the new reinitialization method, configuring parity, different
frame lengths and different stop bit settings work as expected on
both CH340G and CH341A.  This has been extensively tested with a
logic analyzer.

Tested-by: Ryan Barber <rfb@skyscraper.nu>
Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
---
 drivers/usb/serial/ch341.c | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index c001773..4d66f0f 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -346,6 +346,7 @@ static void ch341_set_termios(struct tty_struct *tty,
 	unsigned baud_rate;
 	unsigned long flags;
 	unsigned char ctrl;
+	unsigned cflag = tty->termios.c_cflag;
 	int r;
 
 	/* redundant changes may cause the chip to lose bytes */
@@ -356,7 +357,35 @@ static void ch341_set_termios(struct tty_struct *tty,
 
 	priv->baud_rate = baud_rate;
 
-	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8;
+	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
+
+	switch (cflag & CSIZE) {
+	case CS5:
+		ctrl |= CH341_LCR_CS5;
+		break;
+	case CS6:
+		ctrl |= CH341_LCR_CS6;
+		break;
+	case CS7:
+		ctrl |= CH341_LCR_CS7;
+		break;
+	case CS8:
+	default:
+		ctrl |= CH341_LCR_CS8;
+		break;
+	}
+
+	if (cflag & PARENB) {
+		ctrl |= CH341_LCR_ENABLE_PAR;
+		if ((cflag & PARODD) == 0)
+			ctrl |= CH341_LCR_PAR_EVEN;
+	}
+
+	if (cflag & CMSPAR)
+		ctrl |= CH341_LCR_MARK_SPACE;
+
+	if (cflag & CSTOPB)
+		ctrl |= CH341_LCR_STOP_BITS_2;
 
 	if (baud_rate) {
 		spin_lock_irqsave(&priv->lock, flags);
@@ -373,11 +402,6 @@ static void ch341_set_termios(struct tty_struct *tty,
 
 	ch341_set_handshake(port->serial->dev, priv->line_control);
 
-	/* Unimplemented:
-	 * (cflag & CSIZE) : data bits [5, 8]
-	 * (cflag & PARENB) : parity {NONE, EVEN, ODD}
-	 * (cflag & CSTOPB) : stop bits [1, 2]
-	 */
 }
 
 static void ch341_break_ctl(struct tty_struct *tty, int break_state)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1370247 — Re: [PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits

FromKarl Palsson <karlp@tweak.net.au>
Date2016-04-03 18:00 +0200
SubjectRe: [PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits
Message-ID<rjSBs-5EU-27@gated-at.bofh.it>
In reply to#1370021

[Multipart message — attachments visible in raw view] — view raw

Grigori Goronzy <greg@chown.ath.cx> wrote:
> With the new reinitialization method, configuring parity,
> different frame lengths and different stop bit settings work as
> expected on both CH340G and CH341A. This has been extensively
> tested with a logic analyzer.
> 
> Tested-by: Ryan Barber <rfb@skyscraper.nu>
> Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
> ---
>  drivers/usb/serial/ch341.c | 36 ++++++++++++++++++++++++++++++------
>  1 file changed, 30 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/serial/ch341.c
> b/drivers/usb/serial/ch341.c index c001773..4d66f0f 100644
> --- a/drivers/usb/serial/ch341.c
> +++ b/drivers/usb/serial/ch341.c
> @@ -346,6 +346,7 @@ static void ch341_set_termios(struct tty_struct *tty,
>  	unsigned baud_rate;
>  	unsigned long flags;
>  	unsigned char ctrl;
> +	unsigned cflag = tty->termios.c_cflag;
>  	int r;
>  
>  	/* redundant changes may cause the chip to lose bytes */
> @@ -356,7 +357,35 @@ static void ch341_set_termios(struct tty_struct *tty,
>  
>  	priv->baud_rate = baud_rate;
>  
> -	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8;
> +	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
> +
> +	switch (cflag & CSIZE) {
> +	case CS5:
> +		ctrl |= CH341_LCR_CS5;
> +		break;
> +	case CS6:
> +		ctrl |= CH341_LCR_CS6;
> +		break;
> +	case CS7:
> +		ctrl |= CH341_LCR_CS7;
> +		break;
> +	case CS8:
> +	default:
> +		ctrl |= CH341_LCR_CS8;
> +		break;
> +	}
> +
> +	if (cflag & PARENB) {
> +		ctrl |= CH341_LCR_ENABLE_PAR;
> +		if ((cflag & PARODD) == 0)
> +			ctrl |= CH341_LCR_PAR_EVEN;
> +	}
> +
> +	if (cflag & CMSPAR)
> +		ctrl |= CH341_LCR_MARK_SPACE;
> +
> +	if (cflag & CSTOPB)
> +		ctrl |= CH341_LCR_STOP_BITS_2;
>  

I think this should be moved up to the PARENB check, at least,
when I was working on this. Also there's macros for some of the
flag checks: (From some code I was working on, but you can see
the mark/space is differently handled, this matched the windows
driver I was reversing usb captures from.)

if (C_PARENB(tty)) {
		*lcr |= CH341_LCR_PARITY;
		if (C_CMSPAR(tty)) {
			*lcr |= CH341_LCR_SPAR;
			if (C_PARODD(tty)) {
				dev_dbg(&port->dev, "parity = mark\n");
				*lcr &= ~CH341_LCR_EPAR;
			} else {
				dev_dbg(&port->dev, "parity = space\n");
				*lcr |= CH341_LCR_EPAR;
			}
		} else {
			*lcr &= ~CH341_LCR_SPAR;
			if (C_PARODD(tty)) {
				dev_dbg(&port->dev, "parity = odd\n");
				*lcr &= ~CH341_LCR_EPAR;
			} else {
				dev_dbg(&port->dev, "parity = even\n");
				*lcr |= CH341_LCR_EPAR;
			}
		}
	} else {
		*lcr &= ~(CH341_LCR_PARITY | CH341_LCR_SPAR | CH341_LCR_EPAR);
		dev_dbg(&port->dev, "parity = none\n");
	}



>  	if (baud_rate) {
>  		spin_lock_irqsave(&priv->lock, flags);
> @@ -373,11 +402,6 @@ static void ch341_set_termios(struct tty_struct *tty,
>  
>  	ch341_set_handshake(port->serial->dev, priv->line_control);
>  
> -	/* Unimplemented:
> -	 * (cflag & CSIZE) : data bits [5, 8]
> -	 * (cflag & PARENB) : parity {NONE, EVEN, ODD}
> -	 * (cflag & CSTOPB) : stop bits [1, 2]
> -	 */
>  }
>  
>  static void ch341_break_ctl(struct tty_struct *tty, int break_state)
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-usb" in the body of a message to
> majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html

[toc] | [prev] | [next] | [standalone]


#1372465 — Re: [PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits

FromOne Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Date2016-04-06 14:10 +0200
SubjectRe: [PATCH v2 07/14] USB: ch341: add support for parity, frame length, stop bits
Message-ID<rkUrx-3zX-15@gated-at.bofh.it>
In reply to#1370021
On Sat,  2 Apr 2016 19:07:16 +0200
Grigori Goronzy <greg@chown.ath.cx> wrote:

> With the new reinitialization method, configuring parity, different
> frame lengths and different stop bit settings work as expected on
> both CH340G and CH341A.  This has been extensively tested with a
> logic analyzer.
> 
> Tested-by: Ryan Barber <rfb@skyscraper.nu>
> Signed-off-by: Grigori Goronzy <greg@chown.ath.cx>
> ---
>  drivers/usb/serial/ch341.c | 36 ++++++++++++++++++++++++++++++------
>  1 file changed, 30 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
> index c001773..4d66f0f 100644
> --- a/drivers/usb/serial/ch341.c
> +++ b/drivers/usb/serial/ch341.c
> @@ -346,6 +346,7 @@ static void ch341_set_termios(struct tty_struct *tty,
>  	unsigned baud_rate;
>  	unsigned long flags;
>  	unsigned char ctrl;
> +	unsigned cflag = tty->termios.c_cflag;
>  	int r;
>  
>  	/* redundant changes may cause the chip to lose bytes */
> @@ -356,7 +357,35 @@ static void ch341_set_termios(struct tty_struct *tty,
>  
>  	priv->baud_rate = baud_rate;
>  
> -	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8;
> +	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
> +
> +	switch (cflag & CSIZE) {
> +	case CS5:
> +		ctrl |= CH341_LCR_CS5;
> +		break;
> +	case CS6:
> +		ctrl |= CH341_LCR_CS6;
> +		break;
> +	case CS7:
> +		ctrl |= CH341_LCR_CS7;
> +		break;
> +	case CS8:
> +	default:
> +		ctrl |= CH341_LCR_CS8;

In the default case tty-.termios.c_cflag should also be updated to show
CS8

Alan

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web