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.
This commit is contained in:
parent
12bdbe03c8
commit
cf0cb1ae02
|
@ -44,8 +44,43 @@ struct airprime_private {
|
||||||
int outstanding_urbs;
|
int outstanding_urbs;
|
||||||
int throttled;
|
int throttled;
|
||||||
struct urb *read_urbp[NUM_READ_URBS];
|
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)
|
static void airprime_read_bulk_callback(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = urb->context;
|
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);
|
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) {
|
for (i = 0; i < NUM_READ_URBS; ++i) {
|
||||||
buffer = kmalloc(buffer_size, GFP_KERNEL);
|
buffer = kmalloc(buffer_size, GFP_KERNEL);
|
||||||
if (!buffer) {
|
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 */
|
/* remember this urb so we can kill it when the port is closed */
|
||||||
priv->read_urbp[i] = urb;
|
priv->read_urbp[i] = urb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
airprime_send_setup(port);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
@ -176,6 +218,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
|
||||||
|
|
||||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
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) {
|
for (i = 0; i < NUM_READ_URBS; ++i) {
|
||||||
usb_kill_urb (priv->read_urbp[i]);
|
usb_kill_urb (priv->read_urbp[i]);
|
||||||
kfree (priv->read_urbp[i]->transfer_buffer);
|
kfree (priv->read_urbp[i]->transfer_buffer);
|
||||||
|
|
Loading…
Reference in New Issue