aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schiller <mschiller@tdt.de>2007-03-01 07:49:48 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-03-09 22:52:24 -0500
commitcf0cb1ae0273f0963a5d54c7ec4dde384863fac8 (patch)
tree6ee841b41ce4039266c47e2c819c18733502bd35
parent12bdbe03c8db7139de1de5c622cb0609d259cece (diff)
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.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 18816bf96a4d..310a8b5f5906 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -44,8 +44,43 @@ struct airprime_private {
44 int outstanding_urbs; 44 int outstanding_urbs;
45 int throttled; 45 int throttled;
46 struct urb *read_urbp[NUM_READ_URBS]; 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};
48 56
57static 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}
83
49static void airprime_read_bulk_callback(struct urb *urb) 84static void airprime_read_bulk_callback(struct urb *urb)
50{ 85{
51 struct usb_serial_port *port = urb->context; 86 struct usb_serial_port *port = urb->context;
@@ -118,6 +153,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
118 usb_set_serial_port_data(port, priv); 153 usb_set_serial_port_data(port, priv);
119 } 154 }
120 155
156 /* Set some sane defaults */
157 priv->rts_state = 1;
158 priv->dtr_state = 1;
159
121 for (i = 0; i < NUM_READ_URBS; ++i) { 160 for (i = 0; i < NUM_READ_URBS; ++i) {
122 buffer = kmalloc(buffer_size, GFP_KERNEL); 161 buffer = kmalloc(buffer_size, GFP_KERNEL);
123 if (!buffer) { 162 if (!buffer) {
@@ -151,6 +190,9 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
151 /* remember this urb so we can kill it when the port is closed */ 190 /* remember this urb so we can kill it when the port is closed */
152 priv->read_urbp[i] = urb; 191 priv->read_urbp[i] = urb;
153 } 192 }
193
194 airprime_send_setup(port);
195
154 goto out; 196 goto out;
155 197
156 errout: 198 errout:
@@ -176,6 +218,11 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
176 218
177 dbg("%s - port %d", __FUNCTION__, port->number); 219 dbg("%s - port %d", __FUNCTION__, port->number);
178 220
221 priv->rts_state = 0;
222 priv->dtr_state = 0;
223
224 airprime_send_setup(port);
225
179 for (i = 0; i < NUM_READ_URBS; ++i) { 226 for (i = 0; i < NUM_READ_URBS; ++i) {
180 usb_kill_urb (priv->read_urbp[i]); 227 usb_kill_urb (priv->read_urbp[i]);
181 kfree (priv->read_urbp[i]->transfer_buffer); 228 kfree (priv->read_urbp[i]->transfer_buffer);