lkml.org 
[lkml]   [2007]   [Aug]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectDTR/DSR Patch
    Hello,

    I make driver for Point of Sale Printer, a wide range of Printer use
    only a DTR/DSR hardware-handshaking. When I use a handshaking in the
    userspace, the Printr has a overrun problem and our customer has a
    problem with the tax office.

    my Patch relaize a simple DTR/DSR handhake with a small change of the
    code. The change auf the userspace is very simple. e.g.


    cflags |= CDTRDSR;

    The change of the stty tool at 2 lines.

    Michael


    diff -Nur linux-2.6/drivers/serial/8250.c linux-2.6.dsr_test/drivers/serial/8250.c
    --- linux-2.6/drivers/serial/8250.c 2007-08-28 11:31:48.000000000 +0200
    +++ linux-2.6.dsr_test/drivers/serial/8250.c 2007-08-31 13:20:57.000000000 +0200
    @@ -1400,12 +1400,15 @@
    up->port.info != NULL) {
    if (status & UART_MSR_TERI)
    up->port.icount.rng++;
    - if (status & UART_MSR_DDSR)
    - up->port.icount.dsr++;
    if (status & UART_MSR_DDCD)
    uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
    - if (status & UART_MSR_DCTS)
    - uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
    + if (status & (UART_MSR_DCTS|UART_MSR_DDSR)) {
    + if (status & UART_MSR_DDSR)
    + up->port.icount.dsr++;
    + else
    + up->port.icount.cts++;
    + uart_handle_dsr_cts_change(&up->port, status & UART_MSR_CTS, status & UART_MSR_DSR);
    + }

    wake_up_interruptible(&up->port.info->delta_msr_wait);
    }
    diff -Nur linux-2.6/drivers/serial/serial_core.c linux-2.6.dsr_test/drivers/serial/serial_core.c
    --- linux-2.6/drivers/serial/serial_core.c 2007-08-28 11:31:48.000000000 +0200
    +++ linux-2.6.dsr_test/drivers/serial/serial_core.c 2007-08-31 13:29:22.000000000 +0200
    @@ -191,6 +191,13 @@
    info->tty->hw_stopped = 1;
    spin_unlock_irq(&port->lock);
    }
    +
    + if (info->flags & UIF_DSR_FLOW) {
    + spin_lock_irq(&port->lock);
    + if (!(port->ops->get_mctrl(port) & TIOCM_DSR))
    + info->tty->hw_stopped = 1;
    + spin_unlock_irq(&port->lock);
    + }

    info->flags |= UIF_INITIALIZED;

    @@ -437,6 +444,11 @@
    else
    state->info->flags &= ~UIF_CTS_FLOW;

    + if (termios->c_cflag & CDTRDSR)
    + state->info->flags |= UIF_DSR_FLOW;
    + else
    + state->info->flags &= ~UIF_DSR_FLOW;
    +
    if (termios->c_cflag & CLOCAL)
    state->info->flags &= ~UIF_CHECK_CD;
    else
    --- linux-2.6/include/asm-i386/termbits.h 2007-05-21 10:37:10.000000000 +0200
    +++ linux-2.6.dsr_test/include/asm-i386/termbits.h 2007-08-28 11:58:43.000000000 +0200
    @@ -157,6 +157,7 @@
    #define B3500000 0010016
    #define B4000000 0010017
    #define CIBAUD 002003600000
    +#define CDTRDSR 004000000000 /* dtrdsr flow control */
    #define CMSPAR 010000000000 /* mark or space (stick) parity */
    #define CRTSCTS 020000000000 /* flow control */

    diff -Nur linux-2.6/include/linux/serial_core.h linux-2.6.dsr_test/include/linux/serial_core.h
    --- linux-2.6/include/linux/serial_core.h 2007-08-16 10:30:59.000000000 +0200
    +++ linux-2.6.dsr_test/include/linux/serial_core.h 2007-08-30 16:09:55.000000000 +0200
    @@ -334,6 +334,7 @@
    * Definitions for info->flags. These are _private_ to serial_core, and
    * are specific to this structure. They may be queried by low level drivers.
    */
    +#define UIF_DSR_FLOW ((__force uif_t) (1 << 22))
    #define UIF_CHECK_CD ((__force uif_t) (1 << 25))
    #define UIF_CTS_FLOW ((__force uif_t) (1 << 26))
    #define UIF_NORMAL_ACTIVE ((__force uif_t) (1 << 29))
    @@ -493,26 +494,27 @@

    /**
    * uart_handle_cts_change - handle a change of clear-to-send state
    + * when set DTR/DSR and RTS/CTS send only when both lines ok
    * @port: uart_port structure for the open port
    * @status: new clear to send status, nonzero if active
    */
    static inline void
    -uart_handle_cts_change(struct uart_port *port, unsigned int status)
    +uart_handle_dsr_cts_change(struct uart_port *port, unsigned int status_cts, unsigned int status_dsr)
    {
    struct uart_info *info = port->info;
    struct tty_struct *tty = info->tty;
    + int cts_stop = (info->flags & UIF_CTS_FLOW) && !status_cts;
    + int dsr_stop = (info->flags & UIF_DSR_FLOW) && !status_dsr;

    - port->icount.cts++;
    -
    - if (info->flags & UIF_CTS_FLOW) {
    + if ((info->flags & UIF_CTS_FLOW) || (info->flags & UIF_DSR_FLOW)) {
    if (tty->hw_stopped) {
    - if (status) {
    + if (!(cts_stop||dsr_stop)) {
    tty->hw_stopped = 0;
    port->ops->start_tx(port);
    uart_write_wakeup(port);
    }
    } else {
    - if (!status) {
    + if (cts_stop||dsr_stop) {
    tty->hw_stopped = 1;
    port->ops->stop_tx(port);
    }
    @@ -543,7 +545,7 @@
    * UART_ENABLE_MS - determine if port should enable modem status irqs
    */
    #define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
    - (cflag) & CRTSCTS || \
    + (cflag) & (CRTSCTS|CDTRDSR) || \
    !((cflag) & CLOCAL))

    #endif
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-08-31 15:45    [W:0.048 / U:390.468 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site