diff options
author | Martin Schiller <mschiller@tdt.de> | 2007-03-01 07:49:48 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-03-09 22:52:24 -0500 |
commit | cf0cb1ae0273f0963a5d54c7ec4dde384863fac8 (patch) | |
tree | 6ee841b41ce4039266c47e2c819c18733502bd35 | |
parent | 12bdbe03c8db7139de1de5c622cb0609d259cece (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.c | 47 |
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 | ||
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 | } | ||
83 | |||
49 | static void airprime_read_bulk_callback(struct urb *urb) | 84 | static 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); |