Skip to content

Commit

Permalink
USB: RTS/DTR signal patch for airprime driver
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Martin Schiller authored and Greg Kroah-Hartman committed Mar 10, 2007
1 parent 12bdbe0 commit cf0cb1a
Showing 1 changed file with 47 additions and 0 deletions.
47 changes: 47 additions & 0 deletions drivers/usb/serial/airprime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand Down

0 comments on commit cf0cb1a

Please sign in to comment.