diff options
Diffstat (limited to 'drivers/usb/serial/airprime.c')
-rw-r--r-- | drivers/usb/serial/airprime.c | 87 |
1 files changed, 55 insertions, 32 deletions
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 0af42e32fa0a..39a498362594 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
@@ -18,11 +18,6 @@ | |||
18 | 18 | ||
19 | static struct usb_device_id id_table [] = { | 19 | static struct usb_device_id id_table [] = { |
20 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ | 20 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ |
21 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ | ||
22 | { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */ | ||
23 | { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */ | ||
24 | { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ | ||
25 | { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ | ||
26 | { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */ | 21 | { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */ |
27 | { }, | 22 | { }, |
28 | }; | 23 | }; |
@@ -44,8 +39,43 @@ struct airprime_private { | |||
44 | int outstanding_urbs; | 39 | int outstanding_urbs; |
45 | int throttled; | 40 | int throttled; |
46 | struct urb *read_urbp[NUM_READ_URBS]; | 41 | struct urb *read_urbp[NUM_READ_URBS]; |
42 | |||
43 | /* Settings for the port */ | ||
44 | int rts_state; /* Handshaking pins (outputs) */ | ||
45 | int dtr_state; | ||
46 | int cts_state; /* Handshaking pins (inputs) */ | ||
47 | int dsr_state; | ||
48 | int dcd_state; | ||
49 | int ri_state; | ||
47 | }; | 50 | }; |
48 | 51 | ||
52 | static int airprime_send_setup(struct usb_serial_port *port) | ||
53 | { | ||
54 | struct usb_serial *serial = port->serial; | ||
55 | struct airprime_private *priv; | ||
56 | |||
57 | dbg("%s", __FUNCTION__); | ||
58 | |||
59 | if (port->number != 0) | ||
60 | return 0; | ||
61 | |||
62 | priv = usb_get_serial_port_data(port); | ||
63 | |||
64 | if (port->tty) { | ||
65 | int val = 0; | ||
66 | if (priv->dtr_state) | ||
67 | val |= 0x01; | ||
68 | if (priv->rts_state) | ||
69 | val |= 0x02; | ||
70 | |||
71 | return usb_control_msg(serial->dev, | ||
72 | usb_rcvctrlpipe(serial->dev, 0), | ||
73 | 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
49 | static void airprime_read_bulk_callback(struct urb *urb) | 79 | static void airprime_read_bulk_callback(struct urb *urb) |
50 | { | 80 | { |
51 | struct usb_serial_port *port = urb->context; | 81 | struct usb_serial_port *port = urb->context; |
@@ -58,11 +88,6 @@ static void airprime_read_bulk_callback(struct urb *urb) | |||
58 | if (urb->status) { | 88 | if (urb->status) { |
59 | dbg("%s - nonzero read bulk status received: %d", | 89 | dbg("%s - nonzero read bulk status received: %d", |
60 | __FUNCTION__, urb->status); | 90 | __FUNCTION__, urb->status); |
61 | /* something happened, so free up the memory for this urb */ | ||
62 | if (urb->transfer_buffer) { | ||
63 | kfree (urb->transfer_buffer); | ||
64 | urb->transfer_buffer = NULL; | ||
65 | } | ||
66 | return; | 91 | return; |
67 | } | 92 | } |
68 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 93 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
@@ -123,6 +148,10 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
123 | usb_set_serial_port_data(port, priv); | 148 | usb_set_serial_port_data(port, priv); |
124 | } | 149 | } |
125 | 150 | ||
151 | /* Set some sane defaults */ | ||
152 | priv->rts_state = 1; | ||
153 | priv->dtr_state = 1; | ||
154 | |||
126 | for (i = 0; i < NUM_READ_URBS; ++i) { | 155 | for (i = 0; i < NUM_READ_URBS; ++i) { |
127 | buffer = kmalloc(buffer_size, GFP_KERNEL); | 156 | buffer = kmalloc(buffer_size, GFP_KERNEL); |
128 | if (!buffer) { | 157 | if (!buffer) { |
@@ -146,6 +175,8 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
146 | airprime_read_bulk_callback, port); | 175 | airprime_read_bulk_callback, port); |
147 | result = usb_submit_urb(urb, GFP_KERNEL); | 176 | result = usb_submit_urb(urb, GFP_KERNEL); |
148 | if (result) { | 177 | if (result) { |
178 | usb_free_urb(urb); | ||
179 | kfree(buffer); | ||
149 | dev_err(&port->dev, | 180 | dev_err(&port->dev, |
150 | "%s - failed submitting read urb %d for port %d, error %d\n", | 181 | "%s - failed submitting read urb %d for port %d, error %d\n", |
151 | __FUNCTION__, i, port->number, result); | 182 | __FUNCTION__, i, port->number, result); |
@@ -154,33 +185,21 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) | |||
154 | /* remember this urb so we can kill it when the port is closed */ | 185 | /* remember this urb so we can kill it when the port is closed */ |
155 | priv->read_urbp[i] = urb; | 186 | priv->read_urbp[i] = urb; |
156 | } | 187 | } |
188 | |||
189 | airprime_send_setup(port); | ||
190 | |||
157 | goto out; | 191 | goto out; |
158 | 192 | ||
159 | errout: | 193 | errout: |
160 | /* some error happened, cancel any submitted urbs and clean up anything that | 194 | /* some error happened, cancel any submitted urbs and clean up anything that |
161 | got allocated successfully */ | 195 | got allocated successfully */ |
162 | 196 | ||
163 | for ( ; i >= 0; --i) { | 197 | while (i-- != 0) { |
164 | urb = priv->read_urbp[i]; | 198 | urb = priv->read_urbp[i]; |
165 | if (urb) { | 199 | buffer = urb->transfer_buffer; |
166 | /* This urb was submitted successfully. So we have to | 200 | usb_kill_urb (urb); |
167 | cancel it. | 201 | usb_free_urb (urb); |
168 | Unlinking the urb will invoke read_bulk_callback() | 202 | kfree (buffer); |
169 | with an error status, so its transfer buffer will | ||
170 | be freed there */ | ||
171 | if (usb_unlink_urb (urb) != -EINPROGRESS) { | ||
172 | /* comments in drivers/usb/core/urb.c say this | ||
173 | can only happen if the urb was never submitted, | ||
174 | or has completed already. | ||
175 | Either way we may have to free the transfer | ||
176 | buffer here. */ | ||
177 | if (urb->transfer_buffer) { | ||
178 | kfree (urb->transfer_buffer); | ||
179 | urb->transfer_buffer = NULL; | ||
180 | } | ||
181 | } | ||
182 | usb_free_urb (urb); | ||
183 | } | ||
184 | } | 203 | } |
185 | 204 | ||
186 | out: | 205 | out: |
@@ -194,10 +213,14 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp) | |||
194 | 213 | ||
195 | dbg("%s - port %d", __FUNCTION__, port->number); | 214 | dbg("%s - port %d", __FUNCTION__, port->number); |
196 | 215 | ||
197 | /* killing the urb will invoke read_bulk_callback() with an error status, | 216 | priv->rts_state = 0; |
198 | so the transfer buffer will be freed there */ | 217 | priv->dtr_state = 0; |
218 | |||
219 | airprime_send_setup(port); | ||
220 | |||
199 | for (i = 0; i < NUM_READ_URBS; ++i) { | 221 | for (i = 0; i < NUM_READ_URBS; ++i) { |
200 | usb_kill_urb (priv->read_urbp[i]); | 222 | usb_kill_urb (priv->read_urbp[i]); |
223 | kfree (priv->read_urbp[i]->transfer_buffer); | ||
201 | usb_free_urb (priv->read_urbp[i]); | 224 | usb_free_urb (priv->read_urbp[i]); |
202 | } | 225 | } |
203 | 226 | ||