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.

authored by Martin Schiller and committed by Greg Kroah-Hartman cf0cb1ae 12bdbe03

+47
+47
drivers/usb/serial/airprime.c
··· 44 44 int outstanding_urbs; 45 45 int throttled; 46 46 struct urb *read_urbp[NUM_READ_URBS]; 47 + 48 + /* Settings for the port */ 49 + int rts_state; /* Handshaking pins (outputs) */ 50 + int dtr_state; 51 + int cts_state; /* Handshaking pins (inputs) */ 52 + int dsr_state; 53 + int dcd_state; 54 + int ri_state; 47 55 }; 56 + 57 + static int airprime_send_setup(struct usb_serial_port *port) 58 + { 59 + struct usb_serial *serial = port->serial; 60 + struct airprime_private *priv; 61 + 62 + dbg("%s", __FUNCTION__); 63 + 64 + if (port->number != 0) 65 + return 0; 66 + 67 + priv = usb_get_serial_port_data(port); 68 + 69 + if (port->tty) { 70 + int val = 0; 71 + if (priv->dtr_state) 72 + val |= 0x01; 73 + if (priv->rts_state) 74 + val |= 0x02; 75 + 76 + return usb_control_msg(serial->dev, 77 + usb_rcvctrlpipe(serial->dev, 0), 78 + 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); 79 + } 80 + 81 + return 0; 82 + } 48 83 49 84 static void airprime_read_bulk_callback(struct urb *urb) 50 85 { ··· 153 118 usb_set_serial_port_data(port, priv); 154 119 } 155 120 121 + /* Set some sane defaults */ 122 + priv->rts_state = 1; 123 + priv->dtr_state = 1; 124 + 156 125 for (i = 0; i < NUM_READ_URBS; ++i) { 157 126 buffer = kmalloc(buffer_size, GFP_KERNEL); 158 127 if (!buffer) { ··· 190 151 /* remember this urb so we can kill it when the port is closed */ 191 152 priv->read_urbp[i] = urb; 192 153 } 154 + 155 + airprime_send_setup(port); 156 + 193 157 goto out; 194 158 195 159 errout: ··· 217 175 int i; 218 176 219 177 dbg("%s - port %d", __FUNCTION__, port->number); 178 + 179 + priv->rts_state = 0; 180 + priv->dtr_state = 0; 181 + 182 + airprime_send_setup(port); 220 183 221 184 for (i = 0; i < NUM_READ_URBS; ++i) { 222 185 usb_kill_urb (priv->read_urbp[i]);