aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/airprime.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/airprime.c')
-rw-r--r--drivers/usb/serial/airprime.c87
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
19static struct usb_device_id id_table [] = { 19static 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
52static 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
49static void airprime_read_bulk_callback(struct urb *urb) 79static 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