DTR/DSR Patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux