|
63 | 63 | #define CH341_REG_DIVISOR 0x13
|
64 | 64 | #define CH341_REG_LCR 0x18
|
65 | 65 | #define CH341_REG_LCR2 0x25
|
| 66 | +#define CH341_REG_FLOW_CTL 0x27 |
66 | 67 |
|
67 | 68 | #define CH341_NBREAK_BITS 0x01
|
68 | 69 |
|
|
77 | 78 | #define CH341_LCR_CS6 0x01
|
78 | 79 | #define CH341_LCR_CS5 0x00
|
79 | 80 |
|
| 81 | +#define CH341_FLOW_CTL_NONE 0x00 |
| 82 | +#define CH341_FLOW_CTL_RTSCTS 0x01 |
| 83 | + |
80 | 84 | #define CH341_QUIRK_LIMITED_PRESCALER BIT(0)
|
81 | 85 | #define CH341_QUIRK_SIMULATE_BREAK BIT(1)
|
82 | 86 |
|
@@ -478,6 +482,28 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
|
478 | 482 | return r;
|
479 | 483 | }
|
480 | 484 |
|
| 485 | +static void ch341_set_flow_control(struct tty_struct *tty, |
| 486 | + struct usb_serial_port *port, |
| 487 | + const struct ktermios *old_termios) |
| 488 | +{ |
| 489 | + u16 flow_ctl; |
| 490 | + int r; |
| 491 | + |
| 492 | + if (C_CRTSCTS(tty)) |
| 493 | + flow_ctl = CH341_FLOW_CTL_RTSCTS; |
| 494 | + else |
| 495 | + flow_ctl = CH341_FLOW_CTL_NONE; |
| 496 | + |
| 497 | + r = ch341_control_out(port->serial->dev, |
| 498 | + CH341_REQ_WRITE_REG, |
| 499 | + (CH341_REG_FLOW_CTL << 8) | CH341_REG_FLOW_CTL, |
| 500 | + (flow_ctl << 8) | flow_ctl); |
| 501 | + if (r < 0 && old_termios) { |
| 502 | + tty->termios.c_cflag &= ~CRTSCTS; |
| 503 | + tty->termios.c_cflag |= (old_termios->c_cflag & CRTSCTS); |
| 504 | + } |
| 505 | +} |
| 506 | + |
481 | 507 | /* Old_termios contains the original termios settings and
|
482 | 508 | * tty->termios contains the new setting to be used.
|
483 | 509 | */
|
@@ -546,6 +572,8 @@ static void ch341_set_termios(struct tty_struct *tty,
|
546 | 572 | spin_unlock_irqrestore(&priv->lock, flags);
|
547 | 573 |
|
548 | 574 | ch341_set_handshake(port->serial->dev, priv->mcr);
|
| 575 | + |
| 576 | + ch341_set_flow_control(tty, port, old_termios); |
549 | 577 | }
|
550 | 578 |
|
551 | 579 | /*
|
@@ -632,13 +660,12 @@ static int ch341_simulate_break(struct tty_struct *tty, int break_state)
|
632 | 660 |
|
633 | 661 | static int ch341_break_ctl(struct tty_struct *tty, int break_state)
|
634 | 662 | {
|
635 |
| - const uint16_t ch341_break_reg = |
636 |
| - ((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK; |
| 663 | + const u16 ch341_break_reg = (CH341_REG_LCR << 8) | CH341_REG_BREAK; |
637 | 664 | struct usb_serial_port *port = tty->driver_data;
|
638 | 665 | struct ch341_private *priv = usb_get_serial_port_data(port);
|
| 666 | + u16 reg_contents; |
| 667 | + u8 break_reg[2]; |
639 | 668 | int r;
|
640 |
| - uint16_t reg_contents; |
641 |
| - uint8_t break_reg[2]; |
642 | 669 |
|
643 | 670 | if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK)
|
644 | 671 | return ch341_simulate_break(tty, break_state);
|
|
0 commit comments