On Mon, Mar 31, 2014 at 11:38:43PM +0000, Karl Palsson wrote:
> Based on wireshark packet traces from a windows machine.
> 
> ch340 and ch341 both seem to support all parity modes, but only the ch341
> appears to support variable data bits and variable stop bits, so those are 
> left
> unimplemented, as before.
> 
> Tested on a generic usb-rs485 dongle with the chip label scratched off, and
> some Modbus/RTU devices that required various parity settings.
> 
> Signed-off-by: Karl Palsson <ka...@tweak.net.au>
> ---
>  drivers/usb/serial/ch341.c | 27 ++++++++++++++++++++++++++-
>  1 file changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
> index 82371f6..afd2ec4 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,
>       struct ch341_private *priv = usb_get_serial_port_data(port);
>       unsigned baud_rate;
>       unsigned long flags;
> +     unsigned int par_flags;
>  
>       baud_rate = tty_get_baud_rate(tty);
>  
> @@ -366,9 +367,33 @@ static void ch341_set_termios(struct tty_struct *tty,
>  
>       /* Unimplemented:
>        * (cflag & CSIZE) : data bits [5, 8]
> -      * (cflag & PARENB) : parity {NONE, EVEN, ODD}
>        * (cflag & CSTOPB) : stop bits [1, 2]
>        */
> +     /* CH340 doesn't appear to support variable stop bits or data bits */
> +     if (C_PARENB(tty)) {
> +             if (C_PARODD(tty)) {
> +                     if (tty->termios.c_cflag & CMSPAR) {

The kernel recently gained a C_CMSPAR(tty) macro. Could you use that for
consistency?

> +                             dev_dbg(&port->dev, "parity = mark\n");
> +                             par_flags = 0xeb;
> +                     } else {
> +                             dev_dbg(&port->dev, "parity = odd\n");
> +                             par_flags = 0xcb;
> +                     }
> +             } else {
> +                     if (tty->termios.c_cflag & CMSPAR) {
> +                             dev_dbg(&port->dev, "parity = space\n");
> +                             par_flags = 0xfb;
> +                     } else {
> +                             dev_dbg(&port->dev, "parity = even\n");
> +                             par_flags = 0xdb;
> +                     }
> +             }
> +     } else {
> +             dev_dbg(&port->dev, "parity = none\n");
> +             par_flags = 0xc3;
> +     }
> +     ch341_control_out(port->serial->dev, 0x9a, 0x2518, par_flags);

I noticed that 0x2518 is the same register that is being read from and
written to in ch341_configure(). Does the value written there (0x50)
make any sense to you?

Also, a patch adding break control introduced 

#define CH341_REQ_WRITE_REG    0x9A
#define CH341_REQ_READ_REG     0x95

Perhaps we should start using those?

> +

There's a stray new line here.

>  }
>  
>  static void ch341_break_ctl(struct tty_struct *tty, int break_state)

Thanks,
Johan
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to