diff options
author | Martin Schiller <mschiller@tdt.de> | 2007-03-01 12:49:48 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-03-10 03:52:24 (GMT) |
commit | cf0cb1ae0273f0963a5d54c7ec4dde384863fac8 (patch) | |
tree | 6ee841b41ce4039266c47e2c819c18733502bd35 | |
parent | 12bdbe03c8db7139de1de5c622cb0609d259cece (diff) | |
download | linux-cf0cb1ae0273f0963a5d54c7ec4dde384863fac8.tar.xz |
USB: RTS/DTR signal patch for airprime driver
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.
-rw-r--r-- | 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); |