[PATCH 15/23] USB: RTS/DTR signal patch for airprime driver

Greg Kroah-Hartman <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
From: Martin Schiller <[email protected]>

I encountered some problems with the airprime driver in use with a Novatel
Merlin XU870:

Closing an open Connection to e.g. /dev/ttyUSB0 doesn't reset the
RTS/DTR lines of the Modem.  Consequently, when I use minicom to
establish a connection by "ATD*99#" the modem doesn't hang up even if i
exit minicom and so I cannot reuse the modem unless I remove it and plug
it in again.

With the attached patch, the RTS/DTR lines are resetted on a close.  The
code was mainly taken from the option.c driver.
---
 drivers/usb/serial/airprime.c |   47 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 18816bf..310a8b5 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -44,8 +44,43 @@ struct airprime_private {
 	int outstanding_urbs;
 	int throttled;
 	struct urb *read_urbp[NUM_READ_URBS];
+
+	/* Settings for the port */
+	int rts_state;	/* Handshaking pins (outputs) */
+	int dtr_state;
+	int cts_state;	/* Handshaking pins (inputs) */
+	int dsr_state;
+	int dcd_state;
+	int ri_state;
 };
 
+static int airprime_send_setup(struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	struct airprime_private *priv;
+
+	dbg("%s", __FUNCTION__);
+
+	if (port->number != 0)
+		return 0;
+
+	priv = usb_get_serial_port_data(port);
+
+	if (port->tty) {
+		int val = 0;
+		if (priv->dtr_state)
+			val |= 0x01;
+		if (priv->rts_state)
+			val |= 0x02;
+
+		return usb_control_msg(serial->dev,
+				usb_rcvctrlpipe(serial->dev, 0),
+				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+	}
+
+	return 0;
+}
+
 static void airprime_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
@@ -118,6 +153,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
 		usb_set_serial_port_data(port, priv);
 	}
 
+	/* Set some sane defaults */
+	priv->rts_state = 1;
+	priv->dtr_state = 1;
+
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
@@ -151,6 +190,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
 		/* remember this urb so we can kill it when the port is closed */
 		priv->read_urbp[i] = urb;
 	}
+
+	airprime_send_setup(port);
+
 	goto out;
 
  errout:
@@ -176,6 +218,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	priv->rts_state = 0;
+	priv->dtr_state = 0;
+
+	airprime_send_setup(port);
+
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		usb_kill_urb (priv->read_urbp[i]);
 		kfree (priv->read_urbp[i]->transfer_buffer);
-- 
1.5.0.2


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.