Commit 6fb6b8846458afb7b5689f86cf35705c40eb70e5
Committed by
Greg Kroah-Hartman
1 parent
3a42610812
Exists in
master
and in
7 other branches
USB: cdc-acm: remove unused drain-delay code
The drain-delay code is no longer used, so remove it. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 2 changed files with 0 additions and 7 deletions Inline Diff
drivers/usb/class/cdc-acm.c
1 | /* | 1 | /* |
2 | * cdc-acm.c | 2 | * cdc-acm.c |
3 | * | 3 | * |
4 | * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de> | 4 | * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de> |
5 | * Copyright (c) 1999 Pavel Machek <pavel@ucw.cz> | 5 | * Copyright (c) 1999 Pavel Machek <pavel@ucw.cz> |
6 | * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com> | 6 | * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com> |
7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> |
8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> | 8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> |
9 | * Copyright (c) 2005 David Kubicek <dave@awk.cz> | 9 | * Copyright (c) 2005 David Kubicek <dave@awk.cz> |
10 | * | 10 | * |
11 | * USB Abstract Control Model driver for USB modems and ISDN adapters | 11 | * USB Abstract Control Model driver for USB modems and ISDN adapters |
12 | * | 12 | * |
13 | * Sponsored by SuSE | 13 | * Sponsored by SuSE |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
16 | * it under the terms of the GNU General Public License as published by | 16 | * it under the terms of the GNU General Public License as published by |
17 | * the Free Software Foundation; either version 2 of the License, or | 17 | * the Free Software Foundation; either version 2 of the License, or |
18 | * (at your option) any later version. | 18 | * (at your option) any later version. |
19 | * | 19 | * |
20 | * This program is distributed in the hope that it will be useful, | 20 | * This program is distributed in the hope that it will be useful, |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | * GNU General Public License for more details. | 23 | * GNU General Public License for more details. |
24 | * | 24 | * |
25 | * You should have received a copy of the GNU General Public License | 25 | * You should have received a copy of the GNU General Public License |
26 | * along with this program; if not, write to the Free Software | 26 | * along with this program; if not, write to the Free Software |
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #undef DEBUG | 30 | #undef DEBUG |
31 | #undef VERBOSE_DEBUG | 31 | #undef VERBOSE_DEBUG |
32 | 32 | ||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/tty.h> | 37 | #include <linux/tty.h> |
38 | #include <linux/serial.h> | 38 | #include <linux/serial.h> |
39 | #include <linux/tty_driver.h> | 39 | #include <linux/tty_driver.h> |
40 | #include <linux/tty_flip.h> | 40 | #include <linux/tty_flip.h> |
41 | #include <linux/module.h> | 41 | #include <linux/module.h> |
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/uaccess.h> | 43 | #include <linux/uaccess.h> |
44 | #include <linux/usb.h> | 44 | #include <linux/usb.h> |
45 | #include <linux/usb/cdc.h> | 45 | #include <linux/usb/cdc.h> |
46 | #include <asm/byteorder.h> | 46 | #include <asm/byteorder.h> |
47 | #include <asm/unaligned.h> | 47 | #include <asm/unaligned.h> |
48 | #include <linux/list.h> | 48 | #include <linux/list.h> |
49 | 49 | ||
50 | #include "cdc-acm.h" | 50 | #include "cdc-acm.h" |
51 | 51 | ||
52 | 52 | ||
53 | #define ACM_CLOSE_TIMEOUT 15 /* seconds to let writes drain */ | ||
54 | |||
55 | |||
56 | #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" | 53 | #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" |
57 | #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" | 54 | #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" |
58 | 55 | ||
59 | static struct usb_driver acm_driver; | 56 | static struct usb_driver acm_driver; |
60 | static struct tty_driver *acm_tty_driver; | 57 | static struct tty_driver *acm_tty_driver; |
61 | static struct acm *acm_table[ACM_TTY_MINORS]; | 58 | static struct acm *acm_table[ACM_TTY_MINORS]; |
62 | 59 | ||
63 | static DEFINE_MUTEX(open_mutex); | 60 | static DEFINE_MUTEX(open_mutex); |
64 | 61 | ||
65 | #define ACM_READY(acm) (acm && acm->dev && acm->port.count) | 62 | #define ACM_READY(acm) (acm && acm->dev && acm->port.count) |
66 | 63 | ||
67 | static const struct tty_port_operations acm_port_ops = { | 64 | static const struct tty_port_operations acm_port_ops = { |
68 | }; | 65 | }; |
69 | 66 | ||
70 | /* | 67 | /* |
71 | * Functions for ACM control messages. | 68 | * Functions for ACM control messages. |
72 | */ | 69 | */ |
73 | 70 | ||
74 | static int acm_ctrl_msg(struct acm *acm, int request, int value, | 71 | static int acm_ctrl_msg(struct acm *acm, int request, int value, |
75 | void *buf, int len) | 72 | void *buf, int len) |
76 | { | 73 | { |
77 | int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), | 74 | int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), |
78 | request, USB_RT_ACM, value, | 75 | request, USB_RT_ACM, value, |
79 | acm->control->altsetting[0].desc.bInterfaceNumber, | 76 | acm->control->altsetting[0].desc.bInterfaceNumber, |
80 | buf, len, 5000); | 77 | buf, len, 5000); |
81 | dev_dbg(&acm->control->dev, | 78 | dev_dbg(&acm->control->dev, |
82 | "%s - rq 0x%02x, val %#x, len %#x, result %d\n", | 79 | "%s - rq 0x%02x, val %#x, len %#x, result %d\n", |
83 | __func__, request, value, len, retval); | 80 | __func__, request, value, len, retval); |
84 | return retval < 0 ? retval : 0; | 81 | return retval < 0 ? retval : 0; |
85 | } | 82 | } |
86 | 83 | ||
87 | /* devices aren't required to support these requests. | 84 | /* devices aren't required to support these requests. |
88 | * the cdc acm descriptor tells whether they do... | 85 | * the cdc acm descriptor tells whether they do... |
89 | */ | 86 | */ |
90 | #define acm_set_control(acm, control) \ | 87 | #define acm_set_control(acm, control) \ |
91 | acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0) | 88 | acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0) |
92 | #define acm_set_line(acm, line) \ | 89 | #define acm_set_line(acm, line) \ |
93 | acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line)) | 90 | acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line)) |
94 | #define acm_send_break(acm, ms) \ | 91 | #define acm_send_break(acm, ms) \ |
95 | acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) | 92 | acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) |
96 | 93 | ||
97 | /* | 94 | /* |
98 | * Write buffer management. | 95 | * Write buffer management. |
99 | * All of these assume proper locks taken by the caller. | 96 | * All of these assume proper locks taken by the caller. |
100 | */ | 97 | */ |
101 | 98 | ||
102 | static int acm_wb_alloc(struct acm *acm) | 99 | static int acm_wb_alloc(struct acm *acm) |
103 | { | 100 | { |
104 | int i, wbn; | 101 | int i, wbn; |
105 | struct acm_wb *wb; | 102 | struct acm_wb *wb; |
106 | 103 | ||
107 | wbn = 0; | 104 | wbn = 0; |
108 | i = 0; | 105 | i = 0; |
109 | for (;;) { | 106 | for (;;) { |
110 | wb = &acm->wb[wbn]; | 107 | wb = &acm->wb[wbn]; |
111 | if (!wb->use) { | 108 | if (!wb->use) { |
112 | wb->use = 1; | 109 | wb->use = 1; |
113 | return wbn; | 110 | return wbn; |
114 | } | 111 | } |
115 | wbn = (wbn + 1) % ACM_NW; | 112 | wbn = (wbn + 1) % ACM_NW; |
116 | if (++i >= ACM_NW) | 113 | if (++i >= ACM_NW) |
117 | return -1; | 114 | return -1; |
118 | } | 115 | } |
119 | } | 116 | } |
120 | 117 | ||
121 | static int acm_wb_is_avail(struct acm *acm) | 118 | static int acm_wb_is_avail(struct acm *acm) |
122 | { | 119 | { |
123 | int i, n; | 120 | int i, n; |
124 | unsigned long flags; | 121 | unsigned long flags; |
125 | 122 | ||
126 | n = ACM_NW; | 123 | n = ACM_NW; |
127 | spin_lock_irqsave(&acm->write_lock, flags); | 124 | spin_lock_irqsave(&acm->write_lock, flags); |
128 | for (i = 0; i < ACM_NW; i++) | 125 | for (i = 0; i < ACM_NW; i++) |
129 | n -= acm->wb[i].use; | 126 | n -= acm->wb[i].use; |
130 | spin_unlock_irqrestore(&acm->write_lock, flags); | 127 | spin_unlock_irqrestore(&acm->write_lock, flags); |
131 | return n; | 128 | return n; |
132 | } | 129 | } |
133 | 130 | ||
134 | /* | 131 | /* |
135 | * Finish write. Caller must hold acm->write_lock | 132 | * Finish write. Caller must hold acm->write_lock |
136 | */ | 133 | */ |
137 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) | 134 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) |
138 | { | 135 | { |
139 | wb->use = 0; | 136 | wb->use = 0; |
140 | acm->transmitting--; | 137 | acm->transmitting--; |
141 | usb_autopm_put_interface_async(acm->control); | 138 | usb_autopm_put_interface_async(acm->control); |
142 | } | 139 | } |
143 | 140 | ||
144 | /* | 141 | /* |
145 | * Poke write. | 142 | * Poke write. |
146 | * | 143 | * |
147 | * the caller is responsible for locking | 144 | * the caller is responsible for locking |
148 | */ | 145 | */ |
149 | 146 | ||
150 | static int acm_start_wb(struct acm *acm, struct acm_wb *wb) | 147 | static int acm_start_wb(struct acm *acm, struct acm_wb *wb) |
151 | { | 148 | { |
152 | int rc; | 149 | int rc; |
153 | 150 | ||
154 | acm->transmitting++; | 151 | acm->transmitting++; |
155 | 152 | ||
156 | wb->urb->transfer_buffer = wb->buf; | 153 | wb->urb->transfer_buffer = wb->buf; |
157 | wb->urb->transfer_dma = wb->dmah; | 154 | wb->urb->transfer_dma = wb->dmah; |
158 | wb->urb->transfer_buffer_length = wb->len; | 155 | wb->urb->transfer_buffer_length = wb->len; |
159 | wb->urb->dev = acm->dev; | 156 | wb->urb->dev = acm->dev; |
160 | 157 | ||
161 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); | 158 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); |
162 | if (rc < 0) { | 159 | if (rc < 0) { |
163 | dev_err(&acm->data->dev, | 160 | dev_err(&acm->data->dev, |
164 | "%s - usb_submit_urb(write bulk) failed: %d\n", | 161 | "%s - usb_submit_urb(write bulk) failed: %d\n", |
165 | __func__, rc); | 162 | __func__, rc); |
166 | acm_write_done(acm, wb); | 163 | acm_write_done(acm, wb); |
167 | } | 164 | } |
168 | return rc; | 165 | return rc; |
169 | } | 166 | } |
170 | 167 | ||
171 | static int acm_write_start(struct acm *acm, int wbn) | 168 | static int acm_write_start(struct acm *acm, int wbn) |
172 | { | 169 | { |
173 | unsigned long flags; | 170 | unsigned long flags; |
174 | struct acm_wb *wb = &acm->wb[wbn]; | 171 | struct acm_wb *wb = &acm->wb[wbn]; |
175 | int rc; | 172 | int rc; |
176 | 173 | ||
177 | spin_lock_irqsave(&acm->write_lock, flags); | 174 | spin_lock_irqsave(&acm->write_lock, flags); |
178 | if (!acm->dev) { | 175 | if (!acm->dev) { |
179 | wb->use = 0; | 176 | wb->use = 0; |
180 | spin_unlock_irqrestore(&acm->write_lock, flags); | 177 | spin_unlock_irqrestore(&acm->write_lock, flags); |
181 | return -ENODEV; | 178 | return -ENODEV; |
182 | } | 179 | } |
183 | 180 | ||
184 | dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__, | 181 | dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__, |
185 | acm->susp_count); | 182 | acm->susp_count); |
186 | usb_autopm_get_interface_async(acm->control); | 183 | usb_autopm_get_interface_async(acm->control); |
187 | if (acm->susp_count) { | 184 | if (acm->susp_count) { |
188 | if (!acm->delayed_wb) | 185 | if (!acm->delayed_wb) |
189 | acm->delayed_wb = wb; | 186 | acm->delayed_wb = wb; |
190 | else | 187 | else |
191 | usb_autopm_put_interface_async(acm->control); | 188 | usb_autopm_put_interface_async(acm->control); |
192 | spin_unlock_irqrestore(&acm->write_lock, flags); | 189 | spin_unlock_irqrestore(&acm->write_lock, flags); |
193 | return 0; /* A white lie */ | 190 | return 0; /* A white lie */ |
194 | } | 191 | } |
195 | usb_mark_last_busy(acm->dev); | 192 | usb_mark_last_busy(acm->dev); |
196 | 193 | ||
197 | rc = acm_start_wb(acm, wb); | 194 | rc = acm_start_wb(acm, wb); |
198 | spin_unlock_irqrestore(&acm->write_lock, flags); | 195 | spin_unlock_irqrestore(&acm->write_lock, flags); |
199 | 196 | ||
200 | return rc; | 197 | return rc; |
201 | 198 | ||
202 | } | 199 | } |
203 | /* | 200 | /* |
204 | * attributes exported through sysfs | 201 | * attributes exported through sysfs |
205 | */ | 202 | */ |
206 | static ssize_t show_caps | 203 | static ssize_t show_caps |
207 | (struct device *dev, struct device_attribute *attr, char *buf) | 204 | (struct device *dev, struct device_attribute *attr, char *buf) |
208 | { | 205 | { |
209 | struct usb_interface *intf = to_usb_interface(dev); | 206 | struct usb_interface *intf = to_usb_interface(dev); |
210 | struct acm *acm = usb_get_intfdata(intf); | 207 | struct acm *acm = usb_get_intfdata(intf); |
211 | 208 | ||
212 | return sprintf(buf, "%d", acm->ctrl_caps); | 209 | return sprintf(buf, "%d", acm->ctrl_caps); |
213 | } | 210 | } |
214 | static DEVICE_ATTR(bmCapabilities, S_IRUGO, show_caps, NULL); | 211 | static DEVICE_ATTR(bmCapabilities, S_IRUGO, show_caps, NULL); |
215 | 212 | ||
216 | static ssize_t show_country_codes | 213 | static ssize_t show_country_codes |
217 | (struct device *dev, struct device_attribute *attr, char *buf) | 214 | (struct device *dev, struct device_attribute *attr, char *buf) |
218 | { | 215 | { |
219 | struct usb_interface *intf = to_usb_interface(dev); | 216 | struct usb_interface *intf = to_usb_interface(dev); |
220 | struct acm *acm = usb_get_intfdata(intf); | 217 | struct acm *acm = usb_get_intfdata(intf); |
221 | 218 | ||
222 | memcpy(buf, acm->country_codes, acm->country_code_size); | 219 | memcpy(buf, acm->country_codes, acm->country_code_size); |
223 | return acm->country_code_size; | 220 | return acm->country_code_size; |
224 | } | 221 | } |
225 | 222 | ||
226 | static DEVICE_ATTR(wCountryCodes, S_IRUGO, show_country_codes, NULL); | 223 | static DEVICE_ATTR(wCountryCodes, S_IRUGO, show_country_codes, NULL); |
227 | 224 | ||
228 | static ssize_t show_country_rel_date | 225 | static ssize_t show_country_rel_date |
229 | (struct device *dev, struct device_attribute *attr, char *buf) | 226 | (struct device *dev, struct device_attribute *attr, char *buf) |
230 | { | 227 | { |
231 | struct usb_interface *intf = to_usb_interface(dev); | 228 | struct usb_interface *intf = to_usb_interface(dev); |
232 | struct acm *acm = usb_get_intfdata(intf); | 229 | struct acm *acm = usb_get_intfdata(intf); |
233 | 230 | ||
234 | return sprintf(buf, "%d", acm->country_rel_date); | 231 | return sprintf(buf, "%d", acm->country_rel_date); |
235 | } | 232 | } |
236 | 233 | ||
237 | static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL); | 234 | static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL); |
238 | /* | 235 | /* |
239 | * Interrupt handlers for various ACM device responses | 236 | * Interrupt handlers for various ACM device responses |
240 | */ | 237 | */ |
241 | 238 | ||
242 | /* control interface reports status changes with "interrupt" transfers */ | 239 | /* control interface reports status changes with "interrupt" transfers */ |
243 | static void acm_ctrl_irq(struct urb *urb) | 240 | static void acm_ctrl_irq(struct urb *urb) |
244 | { | 241 | { |
245 | struct acm *acm = urb->context; | 242 | struct acm *acm = urb->context; |
246 | struct usb_cdc_notification *dr = urb->transfer_buffer; | 243 | struct usb_cdc_notification *dr = urb->transfer_buffer; |
247 | struct tty_struct *tty; | 244 | struct tty_struct *tty; |
248 | unsigned char *data; | 245 | unsigned char *data; |
249 | int newctrl; | 246 | int newctrl; |
250 | int retval; | 247 | int retval; |
251 | int status = urb->status; | 248 | int status = urb->status; |
252 | 249 | ||
253 | switch (status) { | 250 | switch (status) { |
254 | case 0: | 251 | case 0: |
255 | /* success */ | 252 | /* success */ |
256 | break; | 253 | break; |
257 | case -ECONNRESET: | 254 | case -ECONNRESET: |
258 | case -ENOENT: | 255 | case -ENOENT: |
259 | case -ESHUTDOWN: | 256 | case -ESHUTDOWN: |
260 | /* this urb is terminated, clean up */ | 257 | /* this urb is terminated, clean up */ |
261 | dev_dbg(&acm->control->dev, | 258 | dev_dbg(&acm->control->dev, |
262 | "%s - urb shutting down with status: %d\n", | 259 | "%s - urb shutting down with status: %d\n", |
263 | __func__, status); | 260 | __func__, status); |
264 | return; | 261 | return; |
265 | default: | 262 | default: |
266 | dev_dbg(&acm->control->dev, | 263 | dev_dbg(&acm->control->dev, |
267 | "%s - nonzero urb status received: %d\n", | 264 | "%s - nonzero urb status received: %d\n", |
268 | __func__, status); | 265 | __func__, status); |
269 | goto exit; | 266 | goto exit; |
270 | } | 267 | } |
271 | 268 | ||
272 | if (!ACM_READY(acm)) | 269 | if (!ACM_READY(acm)) |
273 | goto exit; | 270 | goto exit; |
274 | 271 | ||
275 | usb_mark_last_busy(acm->dev); | 272 | usb_mark_last_busy(acm->dev); |
276 | 273 | ||
277 | data = (unsigned char *)(dr + 1); | 274 | data = (unsigned char *)(dr + 1); |
278 | switch (dr->bNotificationType) { | 275 | switch (dr->bNotificationType) { |
279 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | 276 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: |
280 | dev_dbg(&acm->control->dev, "%s - network connection: %d\n", | 277 | dev_dbg(&acm->control->dev, "%s - network connection: %d\n", |
281 | __func__, dr->wValue); | 278 | __func__, dr->wValue); |
282 | break; | 279 | break; |
283 | 280 | ||
284 | case USB_CDC_NOTIFY_SERIAL_STATE: | 281 | case USB_CDC_NOTIFY_SERIAL_STATE: |
285 | tty = tty_port_tty_get(&acm->port); | 282 | tty = tty_port_tty_get(&acm->port); |
286 | newctrl = get_unaligned_le16(data); | 283 | newctrl = get_unaligned_le16(data); |
287 | 284 | ||
288 | if (tty) { | 285 | if (tty) { |
289 | if (!acm->clocal && | 286 | if (!acm->clocal && |
290 | (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { | 287 | (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { |
291 | dev_dbg(&acm->control->dev, | 288 | dev_dbg(&acm->control->dev, |
292 | "%s - calling hangup\n", __func__); | 289 | "%s - calling hangup\n", __func__); |
293 | tty_hangup(tty); | 290 | tty_hangup(tty); |
294 | } | 291 | } |
295 | tty_kref_put(tty); | 292 | tty_kref_put(tty); |
296 | } | 293 | } |
297 | 294 | ||
298 | acm->ctrlin = newctrl; | 295 | acm->ctrlin = newctrl; |
299 | 296 | ||
300 | dev_dbg(&acm->control->dev, | 297 | dev_dbg(&acm->control->dev, |
301 | "%s - input control lines: dcd%c dsr%c break%c " | 298 | "%s - input control lines: dcd%c dsr%c break%c " |
302 | "ring%c framing%c parity%c overrun%c\n", | 299 | "ring%c framing%c parity%c overrun%c\n", |
303 | __func__, | 300 | __func__, |
304 | acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', | 301 | acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', |
305 | acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', | 302 | acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', |
306 | acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', | 303 | acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', |
307 | acm->ctrlin & ACM_CTRL_RI ? '+' : '-', | 304 | acm->ctrlin & ACM_CTRL_RI ? '+' : '-', |
308 | acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', | 305 | acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', |
309 | acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', | 306 | acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', |
310 | acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); | 307 | acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); |
311 | break; | 308 | break; |
312 | 309 | ||
313 | default: | 310 | default: |
314 | dev_dbg(&acm->control->dev, | 311 | dev_dbg(&acm->control->dev, |
315 | "%s - unknown notification %d received: index %d " | 312 | "%s - unknown notification %d received: index %d " |
316 | "len %d data0 %d data1 %d\n", | 313 | "len %d data0 %d data1 %d\n", |
317 | __func__, | 314 | __func__, |
318 | dr->bNotificationType, dr->wIndex, | 315 | dr->bNotificationType, dr->wIndex, |
319 | dr->wLength, data[0], data[1]); | 316 | dr->wLength, data[0], data[1]); |
320 | break; | 317 | break; |
321 | } | 318 | } |
322 | exit: | 319 | exit: |
323 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 320 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
324 | if (retval) | 321 | if (retval) |
325 | dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n", | 322 | dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n", |
326 | __func__, retval); | 323 | __func__, retval); |
327 | } | 324 | } |
328 | 325 | ||
329 | /* data interface returns incoming bytes, or we got unthrottled */ | 326 | /* data interface returns incoming bytes, or we got unthrottled */ |
330 | static void acm_read_bulk(struct urb *urb) | 327 | static void acm_read_bulk(struct urb *urb) |
331 | { | 328 | { |
332 | struct acm_rb *buf; | 329 | struct acm_rb *buf; |
333 | struct acm_ru *rcv = urb->context; | 330 | struct acm_ru *rcv = urb->context; |
334 | struct acm *acm = rcv->instance; | 331 | struct acm *acm = rcv->instance; |
335 | int status = urb->status; | 332 | int status = urb->status; |
336 | 333 | ||
337 | dev_vdbg(&acm->data->dev, "%s - status %d\n", __func__, status); | 334 | dev_vdbg(&acm->data->dev, "%s - status %d\n", __func__, status); |
338 | 335 | ||
339 | if (!ACM_READY(acm)) { | 336 | if (!ACM_READY(acm)) { |
340 | dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); | 337 | dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); |
341 | return; | 338 | return; |
342 | } | 339 | } |
343 | usb_mark_last_busy(acm->dev); | 340 | usb_mark_last_busy(acm->dev); |
344 | 341 | ||
345 | if (status) | 342 | if (status) |
346 | dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", | 343 | dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", |
347 | __func__, status); | 344 | __func__, status); |
348 | 345 | ||
349 | buf = rcv->buffer; | 346 | buf = rcv->buffer; |
350 | buf->size = urb->actual_length; | 347 | buf->size = urb->actual_length; |
351 | 348 | ||
352 | if (likely(status == 0)) { | 349 | if (likely(status == 0)) { |
353 | spin_lock(&acm->read_lock); | 350 | spin_lock(&acm->read_lock); |
354 | acm->processing++; | 351 | acm->processing++; |
355 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | 352 | list_add_tail(&rcv->list, &acm->spare_read_urbs); |
356 | list_add_tail(&buf->list, &acm->filled_read_bufs); | 353 | list_add_tail(&buf->list, &acm->filled_read_bufs); |
357 | spin_unlock(&acm->read_lock); | 354 | spin_unlock(&acm->read_lock); |
358 | } else { | 355 | } else { |
359 | /* we drop the buffer due to an error */ | 356 | /* we drop the buffer due to an error */ |
360 | spin_lock(&acm->read_lock); | 357 | spin_lock(&acm->read_lock); |
361 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | 358 | list_add_tail(&rcv->list, &acm->spare_read_urbs); |
362 | list_add(&buf->list, &acm->spare_read_bufs); | 359 | list_add(&buf->list, &acm->spare_read_bufs); |
363 | spin_unlock(&acm->read_lock); | 360 | spin_unlock(&acm->read_lock); |
364 | /* nevertheless the tasklet must be kicked unconditionally | 361 | /* nevertheless the tasklet must be kicked unconditionally |
365 | so the queue cannot dry up */ | 362 | so the queue cannot dry up */ |
366 | } | 363 | } |
367 | if (likely(!acm->susp_count)) | 364 | if (likely(!acm->susp_count)) |
368 | tasklet_schedule(&acm->urb_task); | 365 | tasklet_schedule(&acm->urb_task); |
369 | } | 366 | } |
370 | 367 | ||
371 | static void acm_rx_tasklet(unsigned long _acm) | 368 | static void acm_rx_tasklet(unsigned long _acm) |
372 | { | 369 | { |
373 | struct acm *acm = (void *)_acm; | 370 | struct acm *acm = (void *)_acm; |
374 | struct acm_rb *buf; | 371 | struct acm_rb *buf; |
375 | struct tty_struct *tty; | 372 | struct tty_struct *tty; |
376 | struct acm_ru *rcv; | 373 | struct acm_ru *rcv; |
377 | unsigned long flags; | 374 | unsigned long flags; |
378 | unsigned char throttled; | 375 | unsigned char throttled; |
379 | 376 | ||
380 | dev_vdbg(&acm->data->dev, "%s\n", __func__); | 377 | dev_vdbg(&acm->data->dev, "%s\n", __func__); |
381 | 378 | ||
382 | if (!ACM_READY(acm)) { | 379 | if (!ACM_READY(acm)) { |
383 | dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); | 380 | dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); |
384 | return; | 381 | return; |
385 | } | 382 | } |
386 | 383 | ||
387 | spin_lock_irqsave(&acm->throttle_lock, flags); | 384 | spin_lock_irqsave(&acm->throttle_lock, flags); |
388 | throttled = acm->throttle; | 385 | throttled = acm->throttle; |
389 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | 386 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
390 | if (throttled) { | 387 | if (throttled) { |
391 | dev_dbg(&acm->data->dev, "%s - throttled\n", __func__); | 388 | dev_dbg(&acm->data->dev, "%s - throttled\n", __func__); |
392 | return; | 389 | return; |
393 | } | 390 | } |
394 | 391 | ||
395 | tty = tty_port_tty_get(&acm->port); | 392 | tty = tty_port_tty_get(&acm->port); |
396 | 393 | ||
397 | next_buffer: | 394 | next_buffer: |
398 | spin_lock_irqsave(&acm->read_lock, flags); | 395 | spin_lock_irqsave(&acm->read_lock, flags); |
399 | if (list_empty(&acm->filled_read_bufs)) { | 396 | if (list_empty(&acm->filled_read_bufs)) { |
400 | spin_unlock_irqrestore(&acm->read_lock, flags); | 397 | spin_unlock_irqrestore(&acm->read_lock, flags); |
401 | goto urbs; | 398 | goto urbs; |
402 | } | 399 | } |
403 | buf = list_entry(acm->filled_read_bufs.next, | 400 | buf = list_entry(acm->filled_read_bufs.next, |
404 | struct acm_rb, list); | 401 | struct acm_rb, list); |
405 | list_del(&buf->list); | 402 | list_del(&buf->list); |
406 | spin_unlock_irqrestore(&acm->read_lock, flags); | 403 | spin_unlock_irqrestore(&acm->read_lock, flags); |
407 | 404 | ||
408 | dev_vdbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", | 405 | dev_vdbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", |
409 | __func__, buf, buf->size); | 406 | __func__, buf, buf->size); |
410 | if (tty) { | 407 | if (tty) { |
411 | spin_lock_irqsave(&acm->throttle_lock, flags); | 408 | spin_lock_irqsave(&acm->throttle_lock, flags); |
412 | throttled = acm->throttle; | 409 | throttled = acm->throttle; |
413 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | 410 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
414 | if (!throttled) { | 411 | if (!throttled) { |
415 | tty_insert_flip_string(tty, buf->base, buf->size); | 412 | tty_insert_flip_string(tty, buf->base, buf->size); |
416 | tty_flip_buffer_push(tty); | 413 | tty_flip_buffer_push(tty); |
417 | } else { | 414 | } else { |
418 | tty_kref_put(tty); | 415 | tty_kref_put(tty); |
419 | dev_dbg(&acm->data->dev, "%s - throttling noticed\n", | 416 | dev_dbg(&acm->data->dev, "%s - throttling noticed\n", |
420 | __func__); | 417 | __func__); |
421 | spin_lock_irqsave(&acm->read_lock, flags); | 418 | spin_lock_irqsave(&acm->read_lock, flags); |
422 | list_add(&buf->list, &acm->filled_read_bufs); | 419 | list_add(&buf->list, &acm->filled_read_bufs); |
423 | spin_unlock_irqrestore(&acm->read_lock, flags); | 420 | spin_unlock_irqrestore(&acm->read_lock, flags); |
424 | return; | 421 | return; |
425 | } | 422 | } |
426 | } | 423 | } |
427 | 424 | ||
428 | spin_lock_irqsave(&acm->read_lock, flags); | 425 | spin_lock_irqsave(&acm->read_lock, flags); |
429 | list_add(&buf->list, &acm->spare_read_bufs); | 426 | list_add(&buf->list, &acm->spare_read_bufs); |
430 | spin_unlock_irqrestore(&acm->read_lock, flags); | 427 | spin_unlock_irqrestore(&acm->read_lock, flags); |
431 | goto next_buffer; | 428 | goto next_buffer; |
432 | 429 | ||
433 | urbs: | 430 | urbs: |
434 | tty_kref_put(tty); | 431 | tty_kref_put(tty); |
435 | 432 | ||
436 | while (!list_empty(&acm->spare_read_bufs)) { | 433 | while (!list_empty(&acm->spare_read_bufs)) { |
437 | spin_lock_irqsave(&acm->read_lock, flags); | 434 | spin_lock_irqsave(&acm->read_lock, flags); |
438 | if (list_empty(&acm->spare_read_urbs)) { | 435 | if (list_empty(&acm->spare_read_urbs)) { |
439 | acm->processing = 0; | 436 | acm->processing = 0; |
440 | spin_unlock_irqrestore(&acm->read_lock, flags); | 437 | spin_unlock_irqrestore(&acm->read_lock, flags); |
441 | return; | 438 | return; |
442 | } | 439 | } |
443 | rcv = list_entry(acm->spare_read_urbs.next, | 440 | rcv = list_entry(acm->spare_read_urbs.next, |
444 | struct acm_ru, list); | 441 | struct acm_ru, list); |
445 | list_del(&rcv->list); | 442 | list_del(&rcv->list); |
446 | spin_unlock_irqrestore(&acm->read_lock, flags); | 443 | spin_unlock_irqrestore(&acm->read_lock, flags); |
447 | 444 | ||
448 | buf = list_entry(acm->spare_read_bufs.next, | 445 | buf = list_entry(acm->spare_read_bufs.next, |
449 | struct acm_rb, list); | 446 | struct acm_rb, list); |
450 | list_del(&buf->list); | 447 | list_del(&buf->list); |
451 | 448 | ||
452 | rcv->buffer = buf; | 449 | rcv->buffer = buf; |
453 | 450 | ||
454 | if (acm->is_int_ep) | 451 | if (acm->is_int_ep) |
455 | usb_fill_int_urb(rcv->urb, acm->dev, | 452 | usb_fill_int_urb(rcv->urb, acm->dev, |
456 | acm->rx_endpoint, | 453 | acm->rx_endpoint, |
457 | buf->base, | 454 | buf->base, |
458 | acm->readsize, | 455 | acm->readsize, |
459 | acm_read_bulk, rcv, acm->bInterval); | 456 | acm_read_bulk, rcv, acm->bInterval); |
460 | else | 457 | else |
461 | usb_fill_bulk_urb(rcv->urb, acm->dev, | 458 | usb_fill_bulk_urb(rcv->urb, acm->dev, |
462 | acm->rx_endpoint, | 459 | acm->rx_endpoint, |
463 | buf->base, | 460 | buf->base, |
464 | acm->readsize, | 461 | acm->readsize, |
465 | acm_read_bulk, rcv); | 462 | acm_read_bulk, rcv); |
466 | rcv->urb->transfer_dma = buf->dma; | 463 | rcv->urb->transfer_dma = buf->dma; |
467 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 464 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
468 | 465 | ||
469 | /* This shouldn't kill the driver as unsuccessful URBs are | 466 | /* This shouldn't kill the driver as unsuccessful URBs are |
470 | returned to the free-urbs-pool and resubmited ASAP */ | 467 | returned to the free-urbs-pool and resubmited ASAP */ |
471 | spin_lock_irqsave(&acm->read_lock, flags); | 468 | spin_lock_irqsave(&acm->read_lock, flags); |
472 | if (acm->susp_count || | 469 | if (acm->susp_count || |
473 | usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { | 470 | usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { |
474 | list_add(&buf->list, &acm->spare_read_bufs); | 471 | list_add(&buf->list, &acm->spare_read_bufs); |
475 | list_add(&rcv->list, &acm->spare_read_urbs); | 472 | list_add(&rcv->list, &acm->spare_read_urbs); |
476 | acm->processing = 0; | 473 | acm->processing = 0; |
477 | spin_unlock_irqrestore(&acm->read_lock, flags); | 474 | spin_unlock_irqrestore(&acm->read_lock, flags); |
478 | return; | 475 | return; |
479 | } else { | 476 | } else { |
480 | spin_unlock_irqrestore(&acm->read_lock, flags); | 477 | spin_unlock_irqrestore(&acm->read_lock, flags); |
481 | dev_vdbg(&acm->data->dev, | 478 | dev_vdbg(&acm->data->dev, |
482 | "%s - sending urb 0x%p, rcv 0x%p, buf 0x%p\n", | 479 | "%s - sending urb 0x%p, rcv 0x%p, buf 0x%p\n", |
483 | __func__, rcv->urb, rcv, buf); | 480 | __func__, rcv->urb, rcv, buf); |
484 | } | 481 | } |
485 | } | 482 | } |
486 | spin_lock_irqsave(&acm->read_lock, flags); | 483 | spin_lock_irqsave(&acm->read_lock, flags); |
487 | acm->processing = 0; | 484 | acm->processing = 0; |
488 | spin_unlock_irqrestore(&acm->read_lock, flags); | 485 | spin_unlock_irqrestore(&acm->read_lock, flags); |
489 | } | 486 | } |
490 | 487 | ||
491 | /* data interface wrote those outgoing bytes */ | 488 | /* data interface wrote those outgoing bytes */ |
492 | static void acm_write_bulk(struct urb *urb) | 489 | static void acm_write_bulk(struct urb *urb) |
493 | { | 490 | { |
494 | struct acm_wb *wb = urb->context; | 491 | struct acm_wb *wb = urb->context; |
495 | struct acm *acm = wb->instance; | 492 | struct acm *acm = wb->instance; |
496 | unsigned long flags; | 493 | unsigned long flags; |
497 | 494 | ||
498 | if (urb->status || (urb->actual_length != urb->transfer_buffer_length)) | 495 | if (urb->status || (urb->actual_length != urb->transfer_buffer_length)) |
499 | dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n", | 496 | dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n", |
500 | __func__, | 497 | __func__, |
501 | urb->actual_length, | 498 | urb->actual_length, |
502 | urb->transfer_buffer_length, | 499 | urb->transfer_buffer_length, |
503 | urb->status); | 500 | urb->status); |
504 | 501 | ||
505 | spin_lock_irqsave(&acm->write_lock, flags); | 502 | spin_lock_irqsave(&acm->write_lock, flags); |
506 | acm_write_done(acm, wb); | 503 | acm_write_done(acm, wb); |
507 | spin_unlock_irqrestore(&acm->write_lock, flags); | 504 | spin_unlock_irqrestore(&acm->write_lock, flags); |
508 | if (ACM_READY(acm)) | 505 | if (ACM_READY(acm)) |
509 | schedule_work(&acm->work); | 506 | schedule_work(&acm->work); |
510 | else | ||
511 | wake_up_interruptible(&acm->drain_wait); | ||
512 | } | 507 | } |
513 | 508 | ||
514 | static void acm_softint(struct work_struct *work) | 509 | static void acm_softint(struct work_struct *work) |
515 | { | 510 | { |
516 | struct acm *acm = container_of(work, struct acm, work); | 511 | struct acm *acm = container_of(work, struct acm, work); |
517 | struct tty_struct *tty; | 512 | struct tty_struct *tty; |
518 | 513 | ||
519 | dev_vdbg(&acm->data->dev, "%s\n", __func__); | 514 | dev_vdbg(&acm->data->dev, "%s\n", __func__); |
520 | 515 | ||
521 | if (!ACM_READY(acm)) | 516 | if (!ACM_READY(acm)) |
522 | return; | 517 | return; |
523 | tty = tty_port_tty_get(&acm->port); | 518 | tty = tty_port_tty_get(&acm->port); |
524 | if (!tty) | 519 | if (!tty) |
525 | return; | 520 | return; |
526 | tty_wakeup(tty); | 521 | tty_wakeup(tty); |
527 | tty_kref_put(tty); | 522 | tty_kref_put(tty); |
528 | } | 523 | } |
529 | 524 | ||
530 | /* | 525 | /* |
531 | * TTY handlers | 526 | * TTY handlers |
532 | */ | 527 | */ |
533 | 528 | ||
534 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) | 529 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) |
535 | { | 530 | { |
536 | struct acm *acm; | 531 | struct acm *acm; |
537 | int rv = -ENODEV; | 532 | int rv = -ENODEV; |
538 | int i; | 533 | int i; |
539 | 534 | ||
540 | mutex_lock(&open_mutex); | 535 | mutex_lock(&open_mutex); |
541 | 536 | ||
542 | acm = acm_table[tty->index]; | 537 | acm = acm_table[tty->index]; |
543 | if (!acm || !acm->dev) | 538 | if (!acm || !acm->dev) |
544 | goto out; | 539 | goto out; |
545 | else | 540 | else |
546 | rv = 0; | 541 | rv = 0; |
547 | 542 | ||
548 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 543 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
549 | 544 | ||
550 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); | 545 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); |
551 | 546 | ||
552 | tty->driver_data = acm; | 547 | tty->driver_data = acm; |
553 | tty_port_tty_set(&acm->port, tty); | 548 | tty_port_tty_set(&acm->port, tty); |
554 | 549 | ||
555 | if (usb_autopm_get_interface(acm->control) < 0) | 550 | if (usb_autopm_get_interface(acm->control) < 0) |
556 | goto early_bail; | 551 | goto early_bail; |
557 | else | 552 | else |
558 | acm->control->needs_remote_wakeup = 1; | 553 | acm->control->needs_remote_wakeup = 1; |
559 | 554 | ||
560 | mutex_lock(&acm->mutex); | 555 | mutex_lock(&acm->mutex); |
561 | if (acm->port.count++) { | 556 | if (acm->port.count++) { |
562 | mutex_unlock(&acm->mutex); | 557 | mutex_unlock(&acm->mutex); |
563 | usb_autopm_put_interface(acm->control); | 558 | usb_autopm_put_interface(acm->control); |
564 | goto out; | 559 | goto out; |
565 | } | 560 | } |
566 | 561 | ||
567 | acm->ctrlurb->dev = acm->dev; | 562 | acm->ctrlurb->dev = acm->dev; |
568 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { | 563 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { |
569 | dev_err(&acm->control->dev, | 564 | dev_err(&acm->control->dev, |
570 | "%s - usb_submit_urb(ctrl irq) failed\n", __func__); | 565 | "%s - usb_submit_urb(ctrl irq) failed\n", __func__); |
571 | goto bail_out; | 566 | goto bail_out; |
572 | } | 567 | } |
573 | 568 | ||
574 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && | 569 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && |
575 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) | 570 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) |
576 | goto full_bailout; | 571 | goto full_bailout; |
577 | 572 | ||
578 | usb_autopm_put_interface(acm->control); | 573 | usb_autopm_put_interface(acm->control); |
579 | 574 | ||
580 | INIT_LIST_HEAD(&acm->spare_read_urbs); | 575 | INIT_LIST_HEAD(&acm->spare_read_urbs); |
581 | INIT_LIST_HEAD(&acm->spare_read_bufs); | 576 | INIT_LIST_HEAD(&acm->spare_read_bufs); |
582 | INIT_LIST_HEAD(&acm->filled_read_bufs); | 577 | INIT_LIST_HEAD(&acm->filled_read_bufs); |
583 | 578 | ||
584 | for (i = 0; i < acm->rx_buflimit; i++) | 579 | for (i = 0; i < acm->rx_buflimit; i++) |
585 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); | 580 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); |
586 | for (i = 0; i < acm->rx_buflimit; i++) | 581 | for (i = 0; i < acm->rx_buflimit; i++) |
587 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); | 582 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); |
588 | 583 | ||
589 | acm->throttle = 0; | 584 | acm->throttle = 0; |
590 | 585 | ||
591 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); | 586 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); |
592 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | 587 | rv = tty_port_block_til_ready(&acm->port, tty, filp); |
593 | tasklet_schedule(&acm->urb_task); | 588 | tasklet_schedule(&acm->urb_task); |
594 | 589 | ||
595 | mutex_unlock(&acm->mutex); | 590 | mutex_unlock(&acm->mutex); |
596 | out: | 591 | out: |
597 | mutex_unlock(&open_mutex); | 592 | mutex_unlock(&open_mutex); |
598 | return rv; | 593 | return rv; |
599 | 594 | ||
600 | full_bailout: | 595 | full_bailout: |
601 | usb_kill_urb(acm->ctrlurb); | 596 | usb_kill_urb(acm->ctrlurb); |
602 | bail_out: | 597 | bail_out: |
603 | acm->port.count--; | 598 | acm->port.count--; |
604 | mutex_unlock(&acm->mutex); | 599 | mutex_unlock(&acm->mutex); |
605 | usb_autopm_put_interface(acm->control); | 600 | usb_autopm_put_interface(acm->control); |
606 | early_bail: | 601 | early_bail: |
607 | mutex_unlock(&open_mutex); | 602 | mutex_unlock(&open_mutex); |
608 | tty_port_tty_set(&acm->port, NULL); | 603 | tty_port_tty_set(&acm->port, NULL); |
609 | return -EIO; | 604 | return -EIO; |
610 | } | 605 | } |
611 | 606 | ||
612 | static void acm_tty_unregister(struct acm *acm) | 607 | static void acm_tty_unregister(struct acm *acm) |
613 | { | 608 | { |
614 | int i, nr; | 609 | int i, nr; |
615 | 610 | ||
616 | nr = acm->rx_buflimit; | 611 | nr = acm->rx_buflimit; |
617 | tty_unregister_device(acm_tty_driver, acm->minor); | 612 | tty_unregister_device(acm_tty_driver, acm->minor); |
618 | usb_put_intf(acm->control); | 613 | usb_put_intf(acm->control); |
619 | acm_table[acm->minor] = NULL; | 614 | acm_table[acm->minor] = NULL; |
620 | usb_free_urb(acm->ctrlurb); | 615 | usb_free_urb(acm->ctrlurb); |
621 | for (i = 0; i < ACM_NW; i++) | 616 | for (i = 0; i < ACM_NW; i++) |
622 | usb_free_urb(acm->wb[i].urb); | 617 | usb_free_urb(acm->wb[i].urb); |
623 | for (i = 0; i < nr; i++) | 618 | for (i = 0; i < nr; i++) |
624 | usb_free_urb(acm->ru[i].urb); | 619 | usb_free_urb(acm->ru[i].urb); |
625 | kfree(acm->country_codes); | 620 | kfree(acm->country_codes); |
626 | kfree(acm); | 621 | kfree(acm); |
627 | } | 622 | } |
628 | 623 | ||
629 | static void acm_port_down(struct acm *acm) | 624 | static void acm_port_down(struct acm *acm) |
630 | { | 625 | { |
631 | int i, nr = acm->rx_buflimit; | 626 | int i, nr = acm->rx_buflimit; |
632 | mutex_lock(&open_mutex); | 627 | mutex_lock(&open_mutex); |
633 | if (acm->dev) { | 628 | if (acm->dev) { |
634 | usb_autopm_get_interface(acm->control); | 629 | usb_autopm_get_interface(acm->control); |
635 | acm_set_control(acm, acm->ctrlout = 0); | 630 | acm_set_control(acm, acm->ctrlout = 0); |
636 | usb_kill_urb(acm->ctrlurb); | 631 | usb_kill_urb(acm->ctrlurb); |
637 | for (i = 0; i < ACM_NW; i++) | 632 | for (i = 0; i < ACM_NW; i++) |
638 | usb_kill_urb(acm->wb[i].urb); | 633 | usb_kill_urb(acm->wb[i].urb); |
639 | tasklet_disable(&acm->urb_task); | 634 | tasklet_disable(&acm->urb_task); |
640 | for (i = 0; i < nr; i++) | 635 | for (i = 0; i < nr; i++) |
641 | usb_kill_urb(acm->ru[i].urb); | 636 | usb_kill_urb(acm->ru[i].urb); |
642 | tasklet_enable(&acm->urb_task); | 637 | tasklet_enable(&acm->urb_task); |
643 | acm->control->needs_remote_wakeup = 0; | 638 | acm->control->needs_remote_wakeup = 0; |
644 | usb_autopm_put_interface(acm->control); | 639 | usb_autopm_put_interface(acm->control); |
645 | } | 640 | } |
646 | mutex_unlock(&open_mutex); | 641 | mutex_unlock(&open_mutex); |
647 | } | 642 | } |
648 | 643 | ||
649 | static void acm_tty_hangup(struct tty_struct *tty) | 644 | static void acm_tty_hangup(struct tty_struct *tty) |
650 | { | 645 | { |
651 | struct acm *acm = tty->driver_data; | 646 | struct acm *acm = tty->driver_data; |
652 | tty_port_hangup(&acm->port); | 647 | tty_port_hangup(&acm->port); |
653 | acm_port_down(acm); | 648 | acm_port_down(acm); |
654 | } | 649 | } |
655 | 650 | ||
656 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 651 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
657 | { | 652 | { |
658 | struct acm *acm = tty->driver_data; | 653 | struct acm *acm = tty->driver_data; |
659 | 654 | ||
660 | /* Perform the closing process and see if we need to do the hardware | 655 | /* Perform the closing process and see if we need to do the hardware |
661 | shutdown */ | 656 | shutdown */ |
662 | if (!acm) | 657 | if (!acm) |
663 | return; | 658 | return; |
664 | if (tty_port_close_start(&acm->port, tty, filp) == 0) { | 659 | if (tty_port_close_start(&acm->port, tty, filp) == 0) { |
665 | mutex_lock(&open_mutex); | 660 | mutex_lock(&open_mutex); |
666 | if (!acm->dev) { | 661 | if (!acm->dev) { |
667 | tty_port_tty_set(&acm->port, NULL); | 662 | tty_port_tty_set(&acm->port, NULL); |
668 | acm_tty_unregister(acm); | 663 | acm_tty_unregister(acm); |
669 | tty->driver_data = NULL; | 664 | tty->driver_data = NULL; |
670 | } | 665 | } |
671 | mutex_unlock(&open_mutex); | 666 | mutex_unlock(&open_mutex); |
672 | return; | 667 | return; |
673 | } | 668 | } |
674 | acm_port_down(acm); | 669 | acm_port_down(acm); |
675 | tty_port_close_end(&acm->port, tty); | 670 | tty_port_close_end(&acm->port, tty); |
676 | tty_port_tty_set(&acm->port, NULL); | 671 | tty_port_tty_set(&acm->port, NULL); |
677 | } | 672 | } |
678 | 673 | ||
679 | static int acm_tty_write(struct tty_struct *tty, | 674 | static int acm_tty_write(struct tty_struct *tty, |
680 | const unsigned char *buf, int count) | 675 | const unsigned char *buf, int count) |
681 | { | 676 | { |
682 | struct acm *acm = tty->driver_data; | 677 | struct acm *acm = tty->driver_data; |
683 | int stat; | 678 | int stat; |
684 | unsigned long flags; | 679 | unsigned long flags; |
685 | int wbn; | 680 | int wbn; |
686 | struct acm_wb *wb; | 681 | struct acm_wb *wb; |
687 | 682 | ||
688 | if (!ACM_READY(acm)) | 683 | if (!ACM_READY(acm)) |
689 | return -EINVAL; | 684 | return -EINVAL; |
690 | if (!count) | 685 | if (!count) |
691 | return 0; | 686 | return 0; |
692 | 687 | ||
693 | dev_vdbg(&acm->data->dev, "%s - count %d\n", __func__, count); | 688 | dev_vdbg(&acm->data->dev, "%s - count %d\n", __func__, count); |
694 | 689 | ||
695 | spin_lock_irqsave(&acm->write_lock, flags); | 690 | spin_lock_irqsave(&acm->write_lock, flags); |
696 | wbn = acm_wb_alloc(acm); | 691 | wbn = acm_wb_alloc(acm); |
697 | if (wbn < 0) { | 692 | if (wbn < 0) { |
698 | spin_unlock_irqrestore(&acm->write_lock, flags); | 693 | spin_unlock_irqrestore(&acm->write_lock, flags); |
699 | return 0; | 694 | return 0; |
700 | } | 695 | } |
701 | wb = &acm->wb[wbn]; | 696 | wb = &acm->wb[wbn]; |
702 | 697 | ||
703 | count = (count > acm->writesize) ? acm->writesize : count; | 698 | count = (count > acm->writesize) ? acm->writesize : count; |
704 | dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); | 699 | dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); |
705 | memcpy(wb->buf, buf, count); | 700 | memcpy(wb->buf, buf, count); |
706 | wb->len = count; | 701 | wb->len = count; |
707 | spin_unlock_irqrestore(&acm->write_lock, flags); | 702 | spin_unlock_irqrestore(&acm->write_lock, flags); |
708 | 703 | ||
709 | stat = acm_write_start(acm, wbn); | 704 | stat = acm_write_start(acm, wbn); |
710 | if (stat < 0) | 705 | if (stat < 0) |
711 | return stat; | 706 | return stat; |
712 | return count; | 707 | return count; |
713 | } | 708 | } |
714 | 709 | ||
715 | static int acm_tty_write_room(struct tty_struct *tty) | 710 | static int acm_tty_write_room(struct tty_struct *tty) |
716 | { | 711 | { |
717 | struct acm *acm = tty->driver_data; | 712 | struct acm *acm = tty->driver_data; |
718 | if (!ACM_READY(acm)) | 713 | if (!ACM_READY(acm)) |
719 | return -EINVAL; | 714 | return -EINVAL; |
720 | /* | 715 | /* |
721 | * Do not let the line discipline to know that we have a reserve, | 716 | * Do not let the line discipline to know that we have a reserve, |
722 | * or it might get too enthusiastic. | 717 | * or it might get too enthusiastic. |
723 | */ | 718 | */ |
724 | return acm_wb_is_avail(acm) ? acm->writesize : 0; | 719 | return acm_wb_is_avail(acm) ? acm->writesize : 0; |
725 | } | 720 | } |
726 | 721 | ||
727 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) | 722 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) |
728 | { | 723 | { |
729 | struct acm *acm = tty->driver_data; | 724 | struct acm *acm = tty->driver_data; |
730 | if (!ACM_READY(acm)) | 725 | if (!ACM_READY(acm)) |
731 | return 0; | 726 | return 0; |
732 | /* | 727 | /* |
733 | * This is inaccurate (overcounts), but it works. | 728 | * This is inaccurate (overcounts), but it works. |
734 | */ | 729 | */ |
735 | return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize; | 730 | return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize; |
736 | } | 731 | } |
737 | 732 | ||
738 | static void acm_tty_throttle(struct tty_struct *tty) | 733 | static void acm_tty_throttle(struct tty_struct *tty) |
739 | { | 734 | { |
740 | struct acm *acm = tty->driver_data; | 735 | struct acm *acm = tty->driver_data; |
741 | if (!ACM_READY(acm)) | 736 | if (!ACM_READY(acm)) |
742 | return; | 737 | return; |
743 | spin_lock_bh(&acm->throttle_lock); | 738 | spin_lock_bh(&acm->throttle_lock); |
744 | acm->throttle = 1; | 739 | acm->throttle = 1; |
745 | spin_unlock_bh(&acm->throttle_lock); | 740 | spin_unlock_bh(&acm->throttle_lock); |
746 | } | 741 | } |
747 | 742 | ||
748 | static void acm_tty_unthrottle(struct tty_struct *tty) | 743 | static void acm_tty_unthrottle(struct tty_struct *tty) |
749 | { | 744 | { |
750 | struct acm *acm = tty->driver_data; | 745 | struct acm *acm = tty->driver_data; |
751 | if (!ACM_READY(acm)) | 746 | if (!ACM_READY(acm)) |
752 | return; | 747 | return; |
753 | spin_lock_bh(&acm->throttle_lock); | 748 | spin_lock_bh(&acm->throttle_lock); |
754 | acm->throttle = 0; | 749 | acm->throttle = 0; |
755 | spin_unlock_bh(&acm->throttle_lock); | 750 | spin_unlock_bh(&acm->throttle_lock); |
756 | tasklet_schedule(&acm->urb_task); | 751 | tasklet_schedule(&acm->urb_task); |
757 | } | 752 | } |
758 | 753 | ||
759 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) | 754 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) |
760 | { | 755 | { |
761 | struct acm *acm = tty->driver_data; | 756 | struct acm *acm = tty->driver_data; |
762 | int retval; | 757 | int retval; |
763 | if (!ACM_READY(acm)) | 758 | if (!ACM_READY(acm)) |
764 | return -EINVAL; | 759 | return -EINVAL; |
765 | retval = acm_send_break(acm, state ? 0xffff : 0); | 760 | retval = acm_send_break(acm, state ? 0xffff : 0); |
766 | if (retval < 0) | 761 | if (retval < 0) |
767 | dev_dbg(&acm->control->dev, "%s - send break failed\n", | 762 | dev_dbg(&acm->control->dev, "%s - send break failed\n", |
768 | __func__); | 763 | __func__); |
769 | return retval; | 764 | return retval; |
770 | } | 765 | } |
771 | 766 | ||
772 | static int acm_tty_tiocmget(struct tty_struct *tty) | 767 | static int acm_tty_tiocmget(struct tty_struct *tty) |
773 | { | 768 | { |
774 | struct acm *acm = tty->driver_data; | 769 | struct acm *acm = tty->driver_data; |
775 | 770 | ||
776 | if (!ACM_READY(acm)) | 771 | if (!ACM_READY(acm)) |
777 | return -EINVAL; | 772 | return -EINVAL; |
778 | 773 | ||
779 | return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | | 774 | return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | |
780 | (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | | 775 | (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | |
781 | (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | | 776 | (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | |
782 | (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) | | 777 | (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) | |
783 | (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) | | 778 | (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) | |
784 | TIOCM_CTS; | 779 | TIOCM_CTS; |
785 | } | 780 | } |
786 | 781 | ||
787 | static int acm_tty_tiocmset(struct tty_struct *tty, | 782 | static int acm_tty_tiocmset(struct tty_struct *tty, |
788 | unsigned int set, unsigned int clear) | 783 | unsigned int set, unsigned int clear) |
789 | { | 784 | { |
790 | struct acm *acm = tty->driver_data; | 785 | struct acm *acm = tty->driver_data; |
791 | unsigned int newctrl; | 786 | unsigned int newctrl; |
792 | 787 | ||
793 | if (!ACM_READY(acm)) | 788 | if (!ACM_READY(acm)) |
794 | return -EINVAL; | 789 | return -EINVAL; |
795 | 790 | ||
796 | newctrl = acm->ctrlout; | 791 | newctrl = acm->ctrlout; |
797 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | | 792 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | |
798 | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); | 793 | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); |
799 | clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | | 794 | clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | |
800 | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); | 795 | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); |
801 | 796 | ||
802 | newctrl = (newctrl & ~clear) | set; | 797 | newctrl = (newctrl & ~clear) | set; |
803 | 798 | ||
804 | if (acm->ctrlout == newctrl) | 799 | if (acm->ctrlout == newctrl) |
805 | return 0; | 800 | return 0; |
806 | return acm_set_control(acm, acm->ctrlout = newctrl); | 801 | return acm_set_control(acm, acm->ctrlout = newctrl); |
807 | } | 802 | } |
808 | 803 | ||
809 | static int acm_tty_ioctl(struct tty_struct *tty, | 804 | static int acm_tty_ioctl(struct tty_struct *tty, |
810 | unsigned int cmd, unsigned long arg) | 805 | unsigned int cmd, unsigned long arg) |
811 | { | 806 | { |
812 | struct acm *acm = tty->driver_data; | 807 | struct acm *acm = tty->driver_data; |
813 | 808 | ||
814 | if (!ACM_READY(acm)) | 809 | if (!ACM_READY(acm)) |
815 | return -EINVAL; | 810 | return -EINVAL; |
816 | 811 | ||
817 | return -ENOIOCTLCMD; | 812 | return -ENOIOCTLCMD; |
818 | } | 813 | } |
819 | 814 | ||
820 | static const __u32 acm_tty_speed[] = { | 815 | static const __u32 acm_tty_speed[] = { |
821 | 0, 50, 75, 110, 134, 150, 200, 300, 600, | 816 | 0, 50, 75, 110, 134, 150, 200, 300, 600, |
822 | 1200, 1800, 2400, 4800, 9600, 19200, 38400, | 817 | 1200, 1800, 2400, 4800, 9600, 19200, 38400, |
823 | 57600, 115200, 230400, 460800, 500000, 576000, | 818 | 57600, 115200, 230400, 460800, 500000, 576000, |
824 | 921600, 1000000, 1152000, 1500000, 2000000, | 819 | 921600, 1000000, 1152000, 1500000, 2000000, |
825 | 2500000, 3000000, 3500000, 4000000 | 820 | 2500000, 3000000, 3500000, 4000000 |
826 | }; | 821 | }; |
827 | 822 | ||
828 | static const __u8 acm_tty_size[] = { | 823 | static const __u8 acm_tty_size[] = { |
829 | 5, 6, 7, 8 | 824 | 5, 6, 7, 8 |
830 | }; | 825 | }; |
831 | 826 | ||
832 | static void acm_tty_set_termios(struct tty_struct *tty, | 827 | static void acm_tty_set_termios(struct tty_struct *tty, |
833 | struct ktermios *termios_old) | 828 | struct ktermios *termios_old) |
834 | { | 829 | { |
835 | struct acm *acm = tty->driver_data; | 830 | struct acm *acm = tty->driver_data; |
836 | struct ktermios *termios = tty->termios; | 831 | struct ktermios *termios = tty->termios; |
837 | struct usb_cdc_line_coding newline; | 832 | struct usb_cdc_line_coding newline; |
838 | int newctrl = acm->ctrlout; | 833 | int newctrl = acm->ctrlout; |
839 | 834 | ||
840 | if (!ACM_READY(acm)) | 835 | if (!ACM_READY(acm)) |
841 | return; | 836 | return; |
842 | 837 | ||
843 | newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); | 838 | newline.dwDTERate = cpu_to_le32(tty_get_baud_rate(tty)); |
844 | newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; | 839 | newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; |
845 | newline.bParityType = termios->c_cflag & PARENB ? | 840 | newline.bParityType = termios->c_cflag & PARENB ? |
846 | (termios->c_cflag & PARODD ? 1 : 2) + | 841 | (termios->c_cflag & PARODD ? 1 : 2) + |
847 | (termios->c_cflag & CMSPAR ? 2 : 0) : 0; | 842 | (termios->c_cflag & CMSPAR ? 2 : 0) : 0; |
848 | newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; | 843 | newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; |
849 | /* FIXME: Needs to clear unsupported bits in the termios */ | 844 | /* FIXME: Needs to clear unsupported bits in the termios */ |
850 | acm->clocal = ((termios->c_cflag & CLOCAL) != 0); | 845 | acm->clocal = ((termios->c_cflag & CLOCAL) != 0); |
851 | 846 | ||
852 | if (!newline.dwDTERate) { | 847 | if (!newline.dwDTERate) { |
853 | newline.dwDTERate = acm->line.dwDTERate; | 848 | newline.dwDTERate = acm->line.dwDTERate; |
854 | newctrl &= ~ACM_CTRL_DTR; | 849 | newctrl &= ~ACM_CTRL_DTR; |
855 | } else | 850 | } else |
856 | newctrl |= ACM_CTRL_DTR; | 851 | newctrl |= ACM_CTRL_DTR; |
857 | 852 | ||
858 | if (newctrl != acm->ctrlout) | 853 | if (newctrl != acm->ctrlout) |
859 | acm_set_control(acm, acm->ctrlout = newctrl); | 854 | acm_set_control(acm, acm->ctrlout = newctrl); |
860 | 855 | ||
861 | if (memcmp(&acm->line, &newline, sizeof newline)) { | 856 | if (memcmp(&acm->line, &newline, sizeof newline)) { |
862 | memcpy(&acm->line, &newline, sizeof newline); | 857 | memcpy(&acm->line, &newline, sizeof newline); |
863 | dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n", | 858 | dev_dbg(&acm->control->dev, "%s - set line: %d %d %d %d\n", |
864 | __func__, | 859 | __func__, |
865 | le32_to_cpu(newline.dwDTERate), | 860 | le32_to_cpu(newline.dwDTERate), |
866 | newline.bCharFormat, newline.bParityType, | 861 | newline.bCharFormat, newline.bParityType, |
867 | newline.bDataBits); | 862 | newline.bDataBits); |
868 | acm_set_line(acm, &acm->line); | 863 | acm_set_line(acm, &acm->line); |
869 | } | 864 | } |
870 | } | 865 | } |
871 | 866 | ||
872 | /* | 867 | /* |
873 | * USB probe and disconnect routines. | 868 | * USB probe and disconnect routines. |
874 | */ | 869 | */ |
875 | 870 | ||
876 | /* Little helpers: write/read buffers free */ | 871 | /* Little helpers: write/read buffers free */ |
877 | static void acm_write_buffers_free(struct acm *acm) | 872 | static void acm_write_buffers_free(struct acm *acm) |
878 | { | 873 | { |
879 | int i; | 874 | int i; |
880 | struct acm_wb *wb; | 875 | struct acm_wb *wb; |
881 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); | 876 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); |
882 | 877 | ||
883 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) | 878 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) |
884 | usb_free_coherent(usb_dev, acm->writesize, wb->buf, wb->dmah); | 879 | usb_free_coherent(usb_dev, acm->writesize, wb->buf, wb->dmah); |
885 | } | 880 | } |
886 | 881 | ||
887 | static void acm_read_buffers_free(struct acm *acm) | 882 | static void acm_read_buffers_free(struct acm *acm) |
888 | { | 883 | { |
889 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); | 884 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); |
890 | int i, n = acm->rx_buflimit; | 885 | int i, n = acm->rx_buflimit; |
891 | 886 | ||
892 | for (i = 0; i < n; i++) | 887 | for (i = 0; i < n; i++) |
893 | usb_free_coherent(usb_dev, acm->readsize, | 888 | usb_free_coherent(usb_dev, acm->readsize, |
894 | acm->rb[i].base, acm->rb[i].dma); | 889 | acm->rb[i].base, acm->rb[i].dma); |
895 | } | 890 | } |
896 | 891 | ||
897 | /* Little helper: write buffers allocate */ | 892 | /* Little helper: write buffers allocate */ |
898 | static int acm_write_buffers_alloc(struct acm *acm) | 893 | static int acm_write_buffers_alloc(struct acm *acm) |
899 | { | 894 | { |
900 | int i; | 895 | int i; |
901 | struct acm_wb *wb; | 896 | struct acm_wb *wb; |
902 | 897 | ||
903 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { | 898 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { |
904 | wb->buf = usb_alloc_coherent(acm->dev, acm->writesize, GFP_KERNEL, | 899 | wb->buf = usb_alloc_coherent(acm->dev, acm->writesize, GFP_KERNEL, |
905 | &wb->dmah); | 900 | &wb->dmah); |
906 | if (!wb->buf) { | 901 | if (!wb->buf) { |
907 | while (i != 0) { | 902 | while (i != 0) { |
908 | --i; | 903 | --i; |
909 | --wb; | 904 | --wb; |
910 | usb_free_coherent(acm->dev, acm->writesize, | 905 | usb_free_coherent(acm->dev, acm->writesize, |
911 | wb->buf, wb->dmah); | 906 | wb->buf, wb->dmah); |
912 | } | 907 | } |
913 | return -ENOMEM; | 908 | return -ENOMEM; |
914 | } | 909 | } |
915 | } | 910 | } |
916 | return 0; | 911 | return 0; |
917 | } | 912 | } |
918 | 913 | ||
919 | static int acm_probe(struct usb_interface *intf, | 914 | static int acm_probe(struct usb_interface *intf, |
920 | const struct usb_device_id *id) | 915 | const struct usb_device_id *id) |
921 | { | 916 | { |
922 | struct usb_cdc_union_desc *union_header = NULL; | 917 | struct usb_cdc_union_desc *union_header = NULL; |
923 | struct usb_cdc_country_functional_desc *cfd = NULL; | 918 | struct usb_cdc_country_functional_desc *cfd = NULL; |
924 | unsigned char *buffer = intf->altsetting->extra; | 919 | unsigned char *buffer = intf->altsetting->extra; |
925 | int buflen = intf->altsetting->extralen; | 920 | int buflen = intf->altsetting->extralen; |
926 | struct usb_interface *control_interface; | 921 | struct usb_interface *control_interface; |
927 | struct usb_interface *data_interface; | 922 | struct usb_interface *data_interface; |
928 | struct usb_endpoint_descriptor *epctrl = NULL; | 923 | struct usb_endpoint_descriptor *epctrl = NULL; |
929 | struct usb_endpoint_descriptor *epread = NULL; | 924 | struct usb_endpoint_descriptor *epread = NULL; |
930 | struct usb_endpoint_descriptor *epwrite = NULL; | 925 | struct usb_endpoint_descriptor *epwrite = NULL; |
931 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 926 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
932 | struct acm *acm; | 927 | struct acm *acm; |
933 | int minor; | 928 | int minor; |
934 | int ctrlsize, readsize; | 929 | int ctrlsize, readsize; |
935 | u8 *buf; | 930 | u8 *buf; |
936 | u8 ac_management_function = 0; | 931 | u8 ac_management_function = 0; |
937 | u8 call_management_function = 0; | 932 | u8 call_management_function = 0; |
938 | int call_interface_num = -1; | 933 | int call_interface_num = -1; |
939 | int data_interface_num; | 934 | int data_interface_num; |
940 | unsigned long quirks; | 935 | unsigned long quirks; |
941 | int num_rx_buf; | 936 | int num_rx_buf; |
942 | int i; | 937 | int i; |
943 | int combined_interfaces = 0; | 938 | int combined_interfaces = 0; |
944 | 939 | ||
945 | /* normal quirks */ | 940 | /* normal quirks */ |
946 | quirks = (unsigned long)id->driver_info; | 941 | quirks = (unsigned long)id->driver_info; |
947 | num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; | 942 | num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; |
948 | 943 | ||
949 | /* handle quirks deadly to normal probing*/ | 944 | /* handle quirks deadly to normal probing*/ |
950 | if (quirks == NO_UNION_NORMAL) { | 945 | if (quirks == NO_UNION_NORMAL) { |
951 | data_interface = usb_ifnum_to_if(usb_dev, 1); | 946 | data_interface = usb_ifnum_to_if(usb_dev, 1); |
952 | control_interface = usb_ifnum_to_if(usb_dev, 0); | 947 | control_interface = usb_ifnum_to_if(usb_dev, 0); |
953 | goto skip_normal_probe; | 948 | goto skip_normal_probe; |
954 | } | 949 | } |
955 | 950 | ||
956 | /* normal probing*/ | 951 | /* normal probing*/ |
957 | if (!buffer) { | 952 | if (!buffer) { |
958 | dev_err(&intf->dev, "Weird descriptor references\n"); | 953 | dev_err(&intf->dev, "Weird descriptor references\n"); |
959 | return -EINVAL; | 954 | return -EINVAL; |
960 | } | 955 | } |
961 | 956 | ||
962 | if (!buflen) { | 957 | if (!buflen) { |
963 | if (intf->cur_altsetting->endpoint && | 958 | if (intf->cur_altsetting->endpoint && |
964 | intf->cur_altsetting->endpoint->extralen && | 959 | intf->cur_altsetting->endpoint->extralen && |
965 | intf->cur_altsetting->endpoint->extra) { | 960 | intf->cur_altsetting->endpoint->extra) { |
966 | dev_dbg(&intf->dev, | 961 | dev_dbg(&intf->dev, |
967 | "Seeking extra descriptors on endpoint\n"); | 962 | "Seeking extra descriptors on endpoint\n"); |
968 | buflen = intf->cur_altsetting->endpoint->extralen; | 963 | buflen = intf->cur_altsetting->endpoint->extralen; |
969 | buffer = intf->cur_altsetting->endpoint->extra; | 964 | buffer = intf->cur_altsetting->endpoint->extra; |
970 | } else { | 965 | } else { |
971 | dev_err(&intf->dev, | 966 | dev_err(&intf->dev, |
972 | "Zero length descriptor references\n"); | 967 | "Zero length descriptor references\n"); |
973 | return -EINVAL; | 968 | return -EINVAL; |
974 | } | 969 | } |
975 | } | 970 | } |
976 | 971 | ||
977 | while (buflen > 0) { | 972 | while (buflen > 0) { |
978 | if (buffer[1] != USB_DT_CS_INTERFACE) { | 973 | if (buffer[1] != USB_DT_CS_INTERFACE) { |
979 | dev_err(&intf->dev, "skipping garbage\n"); | 974 | dev_err(&intf->dev, "skipping garbage\n"); |
980 | goto next_desc; | 975 | goto next_desc; |
981 | } | 976 | } |
982 | 977 | ||
983 | switch (buffer[2]) { | 978 | switch (buffer[2]) { |
984 | case USB_CDC_UNION_TYPE: /* we've found it */ | 979 | case USB_CDC_UNION_TYPE: /* we've found it */ |
985 | if (union_header) { | 980 | if (union_header) { |
986 | dev_err(&intf->dev, "More than one " | 981 | dev_err(&intf->dev, "More than one " |
987 | "union descriptor, skipping ...\n"); | 982 | "union descriptor, skipping ...\n"); |
988 | goto next_desc; | 983 | goto next_desc; |
989 | } | 984 | } |
990 | union_header = (struct usb_cdc_union_desc *)buffer; | 985 | union_header = (struct usb_cdc_union_desc *)buffer; |
991 | break; | 986 | break; |
992 | case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/ | 987 | case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/ |
993 | cfd = (struct usb_cdc_country_functional_desc *)buffer; | 988 | cfd = (struct usb_cdc_country_functional_desc *)buffer; |
994 | break; | 989 | break; |
995 | case USB_CDC_HEADER_TYPE: /* maybe check version */ | 990 | case USB_CDC_HEADER_TYPE: /* maybe check version */ |
996 | break; /* for now we ignore it */ | 991 | break; /* for now we ignore it */ |
997 | case USB_CDC_ACM_TYPE: | 992 | case USB_CDC_ACM_TYPE: |
998 | ac_management_function = buffer[3]; | 993 | ac_management_function = buffer[3]; |
999 | break; | 994 | break; |
1000 | case USB_CDC_CALL_MANAGEMENT_TYPE: | 995 | case USB_CDC_CALL_MANAGEMENT_TYPE: |
1001 | call_management_function = buffer[3]; | 996 | call_management_function = buffer[3]; |
1002 | call_interface_num = buffer[4]; | 997 | call_interface_num = buffer[4]; |
1003 | if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) | 998 | if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) |
1004 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); | 999 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); |
1005 | break; | 1000 | break; |
1006 | default: | 1001 | default: |
1007 | /* there are LOTS more CDC descriptors that | 1002 | /* there are LOTS more CDC descriptors that |
1008 | * could legitimately be found here. | 1003 | * could legitimately be found here. |
1009 | */ | 1004 | */ |
1010 | dev_dbg(&intf->dev, "Ignoring descriptor: " | 1005 | dev_dbg(&intf->dev, "Ignoring descriptor: " |
1011 | "type %02x, length %d\n", | 1006 | "type %02x, length %d\n", |
1012 | buffer[2], buffer[0]); | 1007 | buffer[2], buffer[0]); |
1013 | break; | 1008 | break; |
1014 | } | 1009 | } |
1015 | next_desc: | 1010 | next_desc: |
1016 | buflen -= buffer[0]; | 1011 | buflen -= buffer[0]; |
1017 | buffer += buffer[0]; | 1012 | buffer += buffer[0]; |
1018 | } | 1013 | } |
1019 | 1014 | ||
1020 | if (!union_header) { | 1015 | if (!union_header) { |
1021 | if (call_interface_num > 0) { | 1016 | if (call_interface_num > 0) { |
1022 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); | 1017 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); |
1023 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); | 1018 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); |
1024 | control_interface = intf; | 1019 | control_interface = intf; |
1025 | } else { | 1020 | } else { |
1026 | if (intf->cur_altsetting->desc.bNumEndpoints != 3) { | 1021 | if (intf->cur_altsetting->desc.bNumEndpoints != 3) { |
1027 | dev_dbg(&intf->dev,"No union descriptor, giving up\n"); | 1022 | dev_dbg(&intf->dev,"No union descriptor, giving up\n"); |
1028 | return -ENODEV; | 1023 | return -ENODEV; |
1029 | } else { | 1024 | } else { |
1030 | dev_warn(&intf->dev,"No union descriptor, testing for castrated device\n"); | 1025 | dev_warn(&intf->dev,"No union descriptor, testing for castrated device\n"); |
1031 | combined_interfaces = 1; | 1026 | combined_interfaces = 1; |
1032 | control_interface = data_interface = intf; | 1027 | control_interface = data_interface = intf; |
1033 | goto look_for_collapsed_interface; | 1028 | goto look_for_collapsed_interface; |
1034 | } | 1029 | } |
1035 | } | 1030 | } |
1036 | } else { | 1031 | } else { |
1037 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); | 1032 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); |
1038 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); | 1033 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); |
1039 | if (!control_interface || !data_interface) { | 1034 | if (!control_interface || !data_interface) { |
1040 | dev_dbg(&intf->dev, "no interfaces\n"); | 1035 | dev_dbg(&intf->dev, "no interfaces\n"); |
1041 | return -ENODEV; | 1036 | return -ENODEV; |
1042 | } | 1037 | } |
1043 | } | 1038 | } |
1044 | 1039 | ||
1045 | if (data_interface_num != call_interface_num) | 1040 | if (data_interface_num != call_interface_num) |
1046 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); | 1041 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); |
1047 | 1042 | ||
1048 | if (control_interface == data_interface) { | 1043 | if (control_interface == data_interface) { |
1049 | /* some broken devices designed for windows work this way */ | 1044 | /* some broken devices designed for windows work this way */ |
1050 | dev_warn(&intf->dev,"Control and data interfaces are not separated!\n"); | 1045 | dev_warn(&intf->dev,"Control and data interfaces are not separated!\n"); |
1051 | combined_interfaces = 1; | 1046 | combined_interfaces = 1; |
1052 | /* a popular other OS doesn't use it */ | 1047 | /* a popular other OS doesn't use it */ |
1053 | quirks |= NO_CAP_LINE; | 1048 | quirks |= NO_CAP_LINE; |
1054 | if (data_interface->cur_altsetting->desc.bNumEndpoints != 3) { | 1049 | if (data_interface->cur_altsetting->desc.bNumEndpoints != 3) { |
1055 | dev_err(&intf->dev, "This needs exactly 3 endpoints\n"); | 1050 | dev_err(&intf->dev, "This needs exactly 3 endpoints\n"); |
1056 | return -EINVAL; | 1051 | return -EINVAL; |
1057 | } | 1052 | } |
1058 | look_for_collapsed_interface: | 1053 | look_for_collapsed_interface: |
1059 | for (i = 0; i < 3; i++) { | 1054 | for (i = 0; i < 3; i++) { |
1060 | struct usb_endpoint_descriptor *ep; | 1055 | struct usb_endpoint_descriptor *ep; |
1061 | ep = &data_interface->cur_altsetting->endpoint[i].desc; | 1056 | ep = &data_interface->cur_altsetting->endpoint[i].desc; |
1062 | 1057 | ||
1063 | if (usb_endpoint_is_int_in(ep)) | 1058 | if (usb_endpoint_is_int_in(ep)) |
1064 | epctrl = ep; | 1059 | epctrl = ep; |
1065 | else if (usb_endpoint_is_bulk_out(ep)) | 1060 | else if (usb_endpoint_is_bulk_out(ep)) |
1066 | epwrite = ep; | 1061 | epwrite = ep; |
1067 | else if (usb_endpoint_is_bulk_in(ep)) | 1062 | else if (usb_endpoint_is_bulk_in(ep)) |
1068 | epread = ep; | 1063 | epread = ep; |
1069 | else | 1064 | else |
1070 | return -EINVAL; | 1065 | return -EINVAL; |
1071 | } | 1066 | } |
1072 | if (!epctrl || !epread || !epwrite) | 1067 | if (!epctrl || !epread || !epwrite) |
1073 | return -ENODEV; | 1068 | return -ENODEV; |
1074 | else | 1069 | else |
1075 | goto made_compressed_probe; | 1070 | goto made_compressed_probe; |
1076 | } | 1071 | } |
1077 | 1072 | ||
1078 | skip_normal_probe: | 1073 | skip_normal_probe: |
1079 | 1074 | ||
1080 | /*workaround for switched interfaces */ | 1075 | /*workaround for switched interfaces */ |
1081 | if (data_interface->cur_altsetting->desc.bInterfaceClass | 1076 | if (data_interface->cur_altsetting->desc.bInterfaceClass |
1082 | != CDC_DATA_INTERFACE_TYPE) { | 1077 | != CDC_DATA_INTERFACE_TYPE) { |
1083 | if (control_interface->cur_altsetting->desc.bInterfaceClass | 1078 | if (control_interface->cur_altsetting->desc.bInterfaceClass |
1084 | == CDC_DATA_INTERFACE_TYPE) { | 1079 | == CDC_DATA_INTERFACE_TYPE) { |
1085 | struct usb_interface *t; | 1080 | struct usb_interface *t; |
1086 | dev_dbg(&intf->dev, | 1081 | dev_dbg(&intf->dev, |
1087 | "Your device has switched interfaces.\n"); | 1082 | "Your device has switched interfaces.\n"); |
1088 | t = control_interface; | 1083 | t = control_interface; |
1089 | control_interface = data_interface; | 1084 | control_interface = data_interface; |
1090 | data_interface = t; | 1085 | data_interface = t; |
1091 | } else { | 1086 | } else { |
1092 | return -EINVAL; | 1087 | return -EINVAL; |
1093 | } | 1088 | } |
1094 | } | 1089 | } |
1095 | 1090 | ||
1096 | /* Accept probe requests only for the control interface */ | 1091 | /* Accept probe requests only for the control interface */ |
1097 | if (!combined_interfaces && intf != control_interface) | 1092 | if (!combined_interfaces && intf != control_interface) |
1098 | return -ENODEV; | 1093 | return -ENODEV; |
1099 | 1094 | ||
1100 | if (!combined_interfaces && usb_interface_claimed(data_interface)) { | 1095 | if (!combined_interfaces && usb_interface_claimed(data_interface)) { |
1101 | /* valid in this context */ | 1096 | /* valid in this context */ |
1102 | dev_dbg(&intf->dev, "The data interface isn't available\n"); | 1097 | dev_dbg(&intf->dev, "The data interface isn't available\n"); |
1103 | return -EBUSY; | 1098 | return -EBUSY; |
1104 | } | 1099 | } |
1105 | 1100 | ||
1106 | 1101 | ||
1107 | if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) | 1102 | if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) |
1108 | return -EINVAL; | 1103 | return -EINVAL; |
1109 | 1104 | ||
1110 | epctrl = &control_interface->cur_altsetting->endpoint[0].desc; | 1105 | epctrl = &control_interface->cur_altsetting->endpoint[0].desc; |
1111 | epread = &data_interface->cur_altsetting->endpoint[0].desc; | 1106 | epread = &data_interface->cur_altsetting->endpoint[0].desc; |
1112 | epwrite = &data_interface->cur_altsetting->endpoint[1].desc; | 1107 | epwrite = &data_interface->cur_altsetting->endpoint[1].desc; |
1113 | 1108 | ||
1114 | 1109 | ||
1115 | /* workaround for switched endpoints */ | 1110 | /* workaround for switched endpoints */ |
1116 | if (!usb_endpoint_dir_in(epread)) { | 1111 | if (!usb_endpoint_dir_in(epread)) { |
1117 | /* descriptors are swapped */ | 1112 | /* descriptors are swapped */ |
1118 | struct usb_endpoint_descriptor *t; | 1113 | struct usb_endpoint_descriptor *t; |
1119 | dev_dbg(&intf->dev, | 1114 | dev_dbg(&intf->dev, |
1120 | "The data interface has switched endpoints\n"); | 1115 | "The data interface has switched endpoints\n"); |
1121 | t = epread; | 1116 | t = epread; |
1122 | epread = epwrite; | 1117 | epread = epwrite; |
1123 | epwrite = t; | 1118 | epwrite = t; |
1124 | } | 1119 | } |
1125 | made_compressed_probe: | 1120 | made_compressed_probe: |
1126 | dev_dbg(&intf->dev, "interfaces are valid\n"); | 1121 | dev_dbg(&intf->dev, "interfaces are valid\n"); |
1127 | for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); | 1122 | for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); |
1128 | 1123 | ||
1129 | if (minor == ACM_TTY_MINORS) { | 1124 | if (minor == ACM_TTY_MINORS) { |
1130 | dev_err(&intf->dev, "no more free acm devices\n"); | 1125 | dev_err(&intf->dev, "no more free acm devices\n"); |
1131 | return -ENODEV; | 1126 | return -ENODEV; |
1132 | } | 1127 | } |
1133 | 1128 | ||
1134 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); | 1129 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); |
1135 | if (acm == NULL) { | 1130 | if (acm == NULL) { |
1136 | dev_err(&intf->dev, "out of memory (acm kzalloc)\n"); | 1131 | dev_err(&intf->dev, "out of memory (acm kzalloc)\n"); |
1137 | goto alloc_fail; | 1132 | goto alloc_fail; |
1138 | } | 1133 | } |
1139 | 1134 | ||
1140 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); | 1135 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); |
1141 | readsize = le16_to_cpu(epread->wMaxPacketSize) * | 1136 | readsize = le16_to_cpu(epread->wMaxPacketSize) * |
1142 | (quirks == SINGLE_RX_URB ? 1 : 2); | 1137 | (quirks == SINGLE_RX_URB ? 1 : 2); |
1143 | acm->combined_interfaces = combined_interfaces; | 1138 | acm->combined_interfaces = combined_interfaces; |
1144 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; | 1139 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; |
1145 | acm->control = control_interface; | 1140 | acm->control = control_interface; |
1146 | acm->data = data_interface; | 1141 | acm->data = data_interface; |
1147 | acm->minor = minor; | 1142 | acm->minor = minor; |
1148 | acm->dev = usb_dev; | 1143 | acm->dev = usb_dev; |
1149 | acm->ctrl_caps = ac_management_function; | 1144 | acm->ctrl_caps = ac_management_function; |
1150 | if (quirks & NO_CAP_LINE) | 1145 | if (quirks & NO_CAP_LINE) |
1151 | acm->ctrl_caps &= ~USB_CDC_CAP_LINE; | 1146 | acm->ctrl_caps &= ~USB_CDC_CAP_LINE; |
1152 | acm->ctrlsize = ctrlsize; | 1147 | acm->ctrlsize = ctrlsize; |
1153 | acm->readsize = readsize; | 1148 | acm->readsize = readsize; |
1154 | acm->rx_buflimit = num_rx_buf; | 1149 | acm->rx_buflimit = num_rx_buf; |
1155 | acm->urb_task.func = acm_rx_tasklet; | 1150 | acm->urb_task.func = acm_rx_tasklet; |
1156 | acm->urb_task.data = (unsigned long) acm; | 1151 | acm->urb_task.data = (unsigned long) acm; |
1157 | INIT_WORK(&acm->work, acm_softint); | 1152 | INIT_WORK(&acm->work, acm_softint); |
1158 | init_waitqueue_head(&acm->drain_wait); | ||
1159 | spin_lock_init(&acm->throttle_lock); | 1153 | spin_lock_init(&acm->throttle_lock); |
1160 | spin_lock_init(&acm->write_lock); | 1154 | spin_lock_init(&acm->write_lock); |
1161 | spin_lock_init(&acm->read_lock); | 1155 | spin_lock_init(&acm->read_lock); |
1162 | mutex_init(&acm->mutex); | 1156 | mutex_init(&acm->mutex); |
1163 | acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); | 1157 | acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); |
1164 | acm->is_int_ep = usb_endpoint_xfer_int(epread); | 1158 | acm->is_int_ep = usb_endpoint_xfer_int(epread); |
1165 | if (acm->is_int_ep) | 1159 | if (acm->is_int_ep) |
1166 | acm->bInterval = epread->bInterval; | 1160 | acm->bInterval = epread->bInterval; |
1167 | tty_port_init(&acm->port); | 1161 | tty_port_init(&acm->port); |
1168 | acm->port.ops = &acm_port_ops; | 1162 | acm->port.ops = &acm_port_ops; |
1169 | 1163 | ||
1170 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 1164 | buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
1171 | if (!buf) { | 1165 | if (!buf) { |
1172 | dev_err(&intf->dev, "out of memory (ctrl buffer alloc)\n"); | 1166 | dev_err(&intf->dev, "out of memory (ctrl buffer alloc)\n"); |
1173 | goto alloc_fail2; | 1167 | goto alloc_fail2; |
1174 | } | 1168 | } |
1175 | acm->ctrl_buffer = buf; | 1169 | acm->ctrl_buffer = buf; |
1176 | 1170 | ||
1177 | if (acm_write_buffers_alloc(acm) < 0) { | 1171 | if (acm_write_buffers_alloc(acm) < 0) { |
1178 | dev_err(&intf->dev, "out of memory (write buffer alloc)\n"); | 1172 | dev_err(&intf->dev, "out of memory (write buffer alloc)\n"); |
1179 | goto alloc_fail4; | 1173 | goto alloc_fail4; |
1180 | } | 1174 | } |
1181 | 1175 | ||
1182 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); | 1176 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); |
1183 | if (!acm->ctrlurb) { | 1177 | if (!acm->ctrlurb) { |
1184 | dev_err(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); | 1178 | dev_err(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); |
1185 | goto alloc_fail5; | 1179 | goto alloc_fail5; |
1186 | } | 1180 | } |
1187 | for (i = 0; i < num_rx_buf; i++) { | 1181 | for (i = 0; i < num_rx_buf; i++) { |
1188 | struct acm_ru *rcv = &(acm->ru[i]); | 1182 | struct acm_ru *rcv = &(acm->ru[i]); |
1189 | 1183 | ||
1190 | rcv->urb = usb_alloc_urb(0, GFP_KERNEL); | 1184 | rcv->urb = usb_alloc_urb(0, GFP_KERNEL); |
1191 | if (rcv->urb == NULL) { | 1185 | if (rcv->urb == NULL) { |
1192 | dev_err(&intf->dev, | 1186 | dev_err(&intf->dev, |
1193 | "out of memory (read urbs usb_alloc_urb)\n"); | 1187 | "out of memory (read urbs usb_alloc_urb)\n"); |
1194 | goto alloc_fail6; | 1188 | goto alloc_fail6; |
1195 | } | 1189 | } |
1196 | 1190 | ||
1197 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1191 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
1198 | rcv->instance = acm; | 1192 | rcv->instance = acm; |
1199 | } | 1193 | } |
1200 | for (i = 0; i < num_rx_buf; i++) { | 1194 | for (i = 0; i < num_rx_buf; i++) { |
1201 | struct acm_rb *rb = &(acm->rb[i]); | 1195 | struct acm_rb *rb = &(acm->rb[i]); |
1202 | 1196 | ||
1203 | rb->base = usb_alloc_coherent(acm->dev, readsize, | 1197 | rb->base = usb_alloc_coherent(acm->dev, readsize, |
1204 | GFP_KERNEL, &rb->dma); | 1198 | GFP_KERNEL, &rb->dma); |
1205 | if (!rb->base) { | 1199 | if (!rb->base) { |
1206 | dev_err(&intf->dev, | 1200 | dev_err(&intf->dev, |
1207 | "out of memory (read bufs usb_alloc_coherent)\n"); | 1201 | "out of memory (read bufs usb_alloc_coherent)\n"); |
1208 | goto alloc_fail7; | 1202 | goto alloc_fail7; |
1209 | } | 1203 | } |
1210 | } | 1204 | } |
1211 | for (i = 0; i < ACM_NW; i++) { | 1205 | for (i = 0; i < ACM_NW; i++) { |
1212 | struct acm_wb *snd = &(acm->wb[i]); | 1206 | struct acm_wb *snd = &(acm->wb[i]); |
1213 | 1207 | ||
1214 | snd->urb = usb_alloc_urb(0, GFP_KERNEL); | 1208 | snd->urb = usb_alloc_urb(0, GFP_KERNEL); |
1215 | if (snd->urb == NULL) { | 1209 | if (snd->urb == NULL) { |
1216 | dev_err(&intf->dev, | 1210 | dev_err(&intf->dev, |
1217 | "out of memory (write urbs usb_alloc_urb)\n"); | 1211 | "out of memory (write urbs usb_alloc_urb)\n"); |
1218 | goto alloc_fail8; | 1212 | goto alloc_fail8; |
1219 | } | 1213 | } |
1220 | 1214 | ||
1221 | if (usb_endpoint_xfer_int(epwrite)) | 1215 | if (usb_endpoint_xfer_int(epwrite)) |
1222 | usb_fill_int_urb(snd->urb, usb_dev, | 1216 | usb_fill_int_urb(snd->urb, usb_dev, |
1223 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 1217 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
1224 | NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); | 1218 | NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); |
1225 | else | 1219 | else |
1226 | usb_fill_bulk_urb(snd->urb, usb_dev, | 1220 | usb_fill_bulk_urb(snd->urb, usb_dev, |
1227 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 1221 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
1228 | NULL, acm->writesize, acm_write_bulk, snd); | 1222 | NULL, acm->writesize, acm_write_bulk, snd); |
1229 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1223 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
1230 | snd->instance = acm; | 1224 | snd->instance = acm; |
1231 | } | 1225 | } |
1232 | 1226 | ||
1233 | usb_set_intfdata(intf, acm); | 1227 | usb_set_intfdata(intf, acm); |
1234 | 1228 | ||
1235 | i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); | 1229 | i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); |
1236 | if (i < 0) | 1230 | if (i < 0) |
1237 | goto alloc_fail8; | 1231 | goto alloc_fail8; |
1238 | 1232 | ||
1239 | if (cfd) { /* export the country data */ | 1233 | if (cfd) { /* export the country data */ |
1240 | acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); | 1234 | acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL); |
1241 | if (!acm->country_codes) | 1235 | if (!acm->country_codes) |
1242 | goto skip_countries; | 1236 | goto skip_countries; |
1243 | acm->country_code_size = cfd->bLength - 4; | 1237 | acm->country_code_size = cfd->bLength - 4; |
1244 | memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, | 1238 | memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, |
1245 | cfd->bLength - 4); | 1239 | cfd->bLength - 4); |
1246 | acm->country_rel_date = cfd->iCountryCodeRelDate; | 1240 | acm->country_rel_date = cfd->iCountryCodeRelDate; |
1247 | 1241 | ||
1248 | i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); | 1242 | i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); |
1249 | if (i < 0) { | 1243 | if (i < 0) { |
1250 | kfree(acm->country_codes); | 1244 | kfree(acm->country_codes); |
1251 | goto skip_countries; | 1245 | goto skip_countries; |
1252 | } | 1246 | } |
1253 | 1247 | ||
1254 | i = device_create_file(&intf->dev, | 1248 | i = device_create_file(&intf->dev, |
1255 | &dev_attr_iCountryCodeRelDate); | 1249 | &dev_attr_iCountryCodeRelDate); |
1256 | if (i < 0) { | 1250 | if (i < 0) { |
1257 | device_remove_file(&intf->dev, &dev_attr_wCountryCodes); | 1251 | device_remove_file(&intf->dev, &dev_attr_wCountryCodes); |
1258 | kfree(acm->country_codes); | 1252 | kfree(acm->country_codes); |
1259 | goto skip_countries; | 1253 | goto skip_countries; |
1260 | } | 1254 | } |
1261 | } | 1255 | } |
1262 | 1256 | ||
1263 | skip_countries: | 1257 | skip_countries: |
1264 | usb_fill_int_urb(acm->ctrlurb, usb_dev, | 1258 | usb_fill_int_urb(acm->ctrlurb, usb_dev, |
1265 | usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), | 1259 | usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), |
1266 | acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, | 1260 | acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, |
1267 | /* works around buggy devices */ | 1261 | /* works around buggy devices */ |
1268 | epctrl->bInterval ? epctrl->bInterval : 0xff); | 1262 | epctrl->bInterval ? epctrl->bInterval : 0xff); |
1269 | acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1263 | acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
1270 | acm->ctrlurb->transfer_dma = acm->ctrl_dma; | 1264 | acm->ctrlurb->transfer_dma = acm->ctrl_dma; |
1271 | 1265 | ||
1272 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); | 1266 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); |
1273 | 1267 | ||
1274 | acm_set_control(acm, acm->ctrlout); | 1268 | acm_set_control(acm, acm->ctrlout); |
1275 | 1269 | ||
1276 | acm->line.dwDTERate = cpu_to_le32(9600); | 1270 | acm->line.dwDTERate = cpu_to_le32(9600); |
1277 | acm->line.bDataBits = 8; | 1271 | acm->line.bDataBits = 8; |
1278 | acm_set_line(acm, &acm->line); | 1272 | acm_set_line(acm, &acm->line); |
1279 | 1273 | ||
1280 | usb_driver_claim_interface(&acm_driver, data_interface, acm); | 1274 | usb_driver_claim_interface(&acm_driver, data_interface, acm); |
1281 | usb_set_intfdata(data_interface, acm); | 1275 | usb_set_intfdata(data_interface, acm); |
1282 | 1276 | ||
1283 | usb_get_intf(control_interface); | 1277 | usb_get_intf(control_interface); |
1284 | tty_register_device(acm_tty_driver, minor, &control_interface->dev); | 1278 | tty_register_device(acm_tty_driver, minor, &control_interface->dev); |
1285 | 1279 | ||
1286 | acm_table[minor] = acm; | 1280 | acm_table[minor] = acm; |
1287 | 1281 | ||
1288 | return 0; | 1282 | return 0; |
1289 | alloc_fail8: | 1283 | alloc_fail8: |
1290 | for (i = 0; i < ACM_NW; i++) | 1284 | for (i = 0; i < ACM_NW; i++) |
1291 | usb_free_urb(acm->wb[i].urb); | 1285 | usb_free_urb(acm->wb[i].urb); |
1292 | alloc_fail7: | 1286 | alloc_fail7: |
1293 | acm_read_buffers_free(acm); | 1287 | acm_read_buffers_free(acm); |
1294 | alloc_fail6: | 1288 | alloc_fail6: |
1295 | for (i = 0; i < num_rx_buf; i++) | 1289 | for (i = 0; i < num_rx_buf; i++) |
1296 | usb_free_urb(acm->ru[i].urb); | 1290 | usb_free_urb(acm->ru[i].urb); |
1297 | usb_free_urb(acm->ctrlurb); | 1291 | usb_free_urb(acm->ctrlurb); |
1298 | alloc_fail5: | 1292 | alloc_fail5: |
1299 | acm_write_buffers_free(acm); | 1293 | acm_write_buffers_free(acm); |
1300 | alloc_fail4: | 1294 | alloc_fail4: |
1301 | usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1295 | usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
1302 | alloc_fail2: | 1296 | alloc_fail2: |
1303 | kfree(acm); | 1297 | kfree(acm); |
1304 | alloc_fail: | 1298 | alloc_fail: |
1305 | return -ENOMEM; | 1299 | return -ENOMEM; |
1306 | } | 1300 | } |
1307 | 1301 | ||
1308 | static void stop_data_traffic(struct acm *acm) | 1302 | static void stop_data_traffic(struct acm *acm) |
1309 | { | 1303 | { |
1310 | int i; | 1304 | int i; |
1311 | 1305 | ||
1312 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 1306 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
1313 | 1307 | ||
1314 | tasklet_disable(&acm->urb_task); | 1308 | tasklet_disable(&acm->urb_task); |
1315 | 1309 | ||
1316 | usb_kill_urb(acm->ctrlurb); | 1310 | usb_kill_urb(acm->ctrlurb); |
1317 | for (i = 0; i < ACM_NW; i++) | 1311 | for (i = 0; i < ACM_NW; i++) |
1318 | usb_kill_urb(acm->wb[i].urb); | 1312 | usb_kill_urb(acm->wb[i].urb); |
1319 | for (i = 0; i < acm->rx_buflimit; i++) | 1313 | for (i = 0; i < acm->rx_buflimit; i++) |
1320 | usb_kill_urb(acm->ru[i].urb); | 1314 | usb_kill_urb(acm->ru[i].urb); |
1321 | 1315 | ||
1322 | tasklet_enable(&acm->urb_task); | 1316 | tasklet_enable(&acm->urb_task); |
1323 | 1317 | ||
1324 | cancel_work_sync(&acm->work); | 1318 | cancel_work_sync(&acm->work); |
1325 | } | 1319 | } |
1326 | 1320 | ||
1327 | static void acm_disconnect(struct usb_interface *intf) | 1321 | static void acm_disconnect(struct usb_interface *intf) |
1328 | { | 1322 | { |
1329 | struct acm *acm = usb_get_intfdata(intf); | 1323 | struct acm *acm = usb_get_intfdata(intf); |
1330 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 1324 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
1331 | struct tty_struct *tty; | 1325 | struct tty_struct *tty; |
1332 | 1326 | ||
1333 | /* sibling interface is already cleaning up */ | 1327 | /* sibling interface is already cleaning up */ |
1334 | if (!acm) | 1328 | if (!acm) |
1335 | return; | 1329 | return; |
1336 | 1330 | ||
1337 | mutex_lock(&open_mutex); | 1331 | mutex_lock(&open_mutex); |
1338 | if (acm->country_codes) { | 1332 | if (acm->country_codes) { |
1339 | device_remove_file(&acm->control->dev, | 1333 | device_remove_file(&acm->control->dev, |
1340 | &dev_attr_wCountryCodes); | 1334 | &dev_attr_wCountryCodes); |
1341 | device_remove_file(&acm->control->dev, | 1335 | device_remove_file(&acm->control->dev, |
1342 | &dev_attr_iCountryCodeRelDate); | 1336 | &dev_attr_iCountryCodeRelDate); |
1343 | } | 1337 | } |
1344 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); | 1338 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); |
1345 | acm->dev = NULL; | 1339 | acm->dev = NULL; |
1346 | usb_set_intfdata(acm->control, NULL); | 1340 | usb_set_intfdata(acm->control, NULL); |
1347 | usb_set_intfdata(acm->data, NULL); | 1341 | usb_set_intfdata(acm->data, NULL); |
1348 | 1342 | ||
1349 | stop_data_traffic(acm); | 1343 | stop_data_traffic(acm); |
1350 | 1344 | ||
1351 | acm_write_buffers_free(acm); | 1345 | acm_write_buffers_free(acm); |
1352 | usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, | 1346 | usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, |
1353 | acm->ctrl_dma); | 1347 | acm->ctrl_dma); |
1354 | acm_read_buffers_free(acm); | 1348 | acm_read_buffers_free(acm); |
1355 | 1349 | ||
1356 | if (!acm->combined_interfaces) | 1350 | if (!acm->combined_interfaces) |
1357 | usb_driver_release_interface(&acm_driver, intf == acm->control ? | 1351 | usb_driver_release_interface(&acm_driver, intf == acm->control ? |
1358 | acm->data : acm->control); | 1352 | acm->data : acm->control); |
1359 | 1353 | ||
1360 | if (acm->port.count == 0) { | 1354 | if (acm->port.count == 0) { |
1361 | acm_tty_unregister(acm); | 1355 | acm_tty_unregister(acm); |
1362 | mutex_unlock(&open_mutex); | 1356 | mutex_unlock(&open_mutex); |
1363 | return; | 1357 | return; |
1364 | } | 1358 | } |
1365 | 1359 | ||
1366 | mutex_unlock(&open_mutex); | 1360 | mutex_unlock(&open_mutex); |
1367 | tty = tty_port_tty_get(&acm->port); | 1361 | tty = tty_port_tty_get(&acm->port); |
1368 | if (tty) { | 1362 | if (tty) { |
1369 | tty_hangup(tty); | 1363 | tty_hangup(tty); |
1370 | tty_kref_put(tty); | 1364 | tty_kref_put(tty); |
1371 | } | 1365 | } |
1372 | } | 1366 | } |
1373 | 1367 | ||
1374 | #ifdef CONFIG_PM | 1368 | #ifdef CONFIG_PM |
1375 | static int acm_suspend(struct usb_interface *intf, pm_message_t message) | 1369 | static int acm_suspend(struct usb_interface *intf, pm_message_t message) |
1376 | { | 1370 | { |
1377 | struct acm *acm = usb_get_intfdata(intf); | 1371 | struct acm *acm = usb_get_intfdata(intf); |
1378 | int cnt; | 1372 | int cnt; |
1379 | 1373 | ||
1380 | if (message.event & PM_EVENT_AUTO) { | 1374 | if (message.event & PM_EVENT_AUTO) { |
1381 | int b; | 1375 | int b; |
1382 | 1376 | ||
1383 | spin_lock_irq(&acm->read_lock); | 1377 | spin_lock_irq(&acm->read_lock); |
1384 | spin_lock(&acm->write_lock); | 1378 | spin_lock(&acm->write_lock); |
1385 | b = acm->processing + acm->transmitting; | 1379 | b = acm->processing + acm->transmitting; |
1386 | spin_unlock(&acm->write_lock); | 1380 | spin_unlock(&acm->write_lock); |
1387 | spin_unlock_irq(&acm->read_lock); | 1381 | spin_unlock_irq(&acm->read_lock); |
1388 | if (b) | 1382 | if (b) |
1389 | return -EBUSY; | 1383 | return -EBUSY; |
1390 | } | 1384 | } |
1391 | 1385 | ||
1392 | spin_lock_irq(&acm->read_lock); | 1386 | spin_lock_irq(&acm->read_lock); |
1393 | spin_lock(&acm->write_lock); | 1387 | spin_lock(&acm->write_lock); |
1394 | cnt = acm->susp_count++; | 1388 | cnt = acm->susp_count++; |
1395 | spin_unlock(&acm->write_lock); | 1389 | spin_unlock(&acm->write_lock); |
1396 | spin_unlock_irq(&acm->read_lock); | 1390 | spin_unlock_irq(&acm->read_lock); |
1397 | 1391 | ||
1398 | if (cnt) | 1392 | if (cnt) |
1399 | return 0; | 1393 | return 0; |
1400 | /* | 1394 | /* |
1401 | we treat opened interfaces differently, | 1395 | we treat opened interfaces differently, |
1402 | we must guard against open | 1396 | we must guard against open |
1403 | */ | 1397 | */ |
1404 | mutex_lock(&acm->mutex); | 1398 | mutex_lock(&acm->mutex); |
1405 | 1399 | ||
1406 | if (acm->port.count) | 1400 | if (acm->port.count) |
1407 | stop_data_traffic(acm); | 1401 | stop_data_traffic(acm); |
1408 | 1402 | ||
1409 | mutex_unlock(&acm->mutex); | 1403 | mutex_unlock(&acm->mutex); |
1410 | return 0; | 1404 | return 0; |
1411 | } | 1405 | } |
1412 | 1406 | ||
1413 | static int acm_resume(struct usb_interface *intf) | 1407 | static int acm_resume(struct usb_interface *intf) |
1414 | { | 1408 | { |
1415 | struct acm *acm = usb_get_intfdata(intf); | 1409 | struct acm *acm = usb_get_intfdata(intf); |
1416 | struct acm_wb *wb; | 1410 | struct acm_wb *wb; |
1417 | int rv = 0; | 1411 | int rv = 0; |
1418 | int cnt; | 1412 | int cnt; |
1419 | 1413 | ||
1420 | spin_lock_irq(&acm->read_lock); | 1414 | spin_lock_irq(&acm->read_lock); |
1421 | acm->susp_count -= 1; | 1415 | acm->susp_count -= 1; |
1422 | cnt = acm->susp_count; | 1416 | cnt = acm->susp_count; |
1423 | spin_unlock_irq(&acm->read_lock); | 1417 | spin_unlock_irq(&acm->read_lock); |
1424 | 1418 | ||
1425 | if (cnt) | 1419 | if (cnt) |
1426 | return 0; | 1420 | return 0; |
1427 | 1421 | ||
1428 | mutex_lock(&acm->mutex); | 1422 | mutex_lock(&acm->mutex); |
1429 | if (acm->port.count) { | 1423 | if (acm->port.count) { |
1430 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); | 1424 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); |
1431 | 1425 | ||
1432 | spin_lock_irq(&acm->write_lock); | 1426 | spin_lock_irq(&acm->write_lock); |
1433 | if (acm->delayed_wb) { | 1427 | if (acm->delayed_wb) { |
1434 | wb = acm->delayed_wb; | 1428 | wb = acm->delayed_wb; |
1435 | acm->delayed_wb = NULL; | 1429 | acm->delayed_wb = NULL; |
1436 | spin_unlock_irq(&acm->write_lock); | 1430 | spin_unlock_irq(&acm->write_lock); |
1437 | acm_start_wb(acm, wb); | 1431 | acm_start_wb(acm, wb); |
1438 | } else { | 1432 | } else { |
1439 | spin_unlock_irq(&acm->write_lock); | 1433 | spin_unlock_irq(&acm->write_lock); |
1440 | } | 1434 | } |
1441 | 1435 | ||
1442 | /* | 1436 | /* |
1443 | * delayed error checking because we must | 1437 | * delayed error checking because we must |
1444 | * do the write path at all cost | 1438 | * do the write path at all cost |
1445 | */ | 1439 | */ |
1446 | if (rv < 0) | 1440 | if (rv < 0) |
1447 | goto err_out; | 1441 | goto err_out; |
1448 | 1442 | ||
1449 | tasklet_schedule(&acm->urb_task); | 1443 | tasklet_schedule(&acm->urb_task); |
1450 | } | 1444 | } |
1451 | 1445 | ||
1452 | err_out: | 1446 | err_out: |
1453 | mutex_unlock(&acm->mutex); | 1447 | mutex_unlock(&acm->mutex); |
1454 | return rv; | 1448 | return rv; |
1455 | } | 1449 | } |
1456 | 1450 | ||
1457 | static int acm_reset_resume(struct usb_interface *intf) | 1451 | static int acm_reset_resume(struct usb_interface *intf) |
1458 | { | 1452 | { |
1459 | struct acm *acm = usb_get_intfdata(intf); | 1453 | struct acm *acm = usb_get_intfdata(intf); |
1460 | struct tty_struct *tty; | 1454 | struct tty_struct *tty; |
1461 | 1455 | ||
1462 | mutex_lock(&acm->mutex); | 1456 | mutex_lock(&acm->mutex); |
1463 | if (acm->port.count) { | 1457 | if (acm->port.count) { |
1464 | tty = tty_port_tty_get(&acm->port); | 1458 | tty = tty_port_tty_get(&acm->port); |
1465 | if (tty) { | 1459 | if (tty) { |
1466 | tty_hangup(tty); | 1460 | tty_hangup(tty); |
1467 | tty_kref_put(tty); | 1461 | tty_kref_put(tty); |
1468 | } | 1462 | } |
1469 | } | 1463 | } |
1470 | mutex_unlock(&acm->mutex); | 1464 | mutex_unlock(&acm->mutex); |
1471 | return acm_resume(intf); | 1465 | return acm_resume(intf); |
1472 | } | 1466 | } |
1473 | 1467 | ||
1474 | #endif /* CONFIG_PM */ | 1468 | #endif /* CONFIG_PM */ |
1475 | 1469 | ||
1476 | #define NOKIA_PCSUITE_ACM_INFO(x) \ | 1470 | #define NOKIA_PCSUITE_ACM_INFO(x) \ |
1477 | USB_DEVICE_AND_INTERFACE_INFO(0x0421, x, \ | 1471 | USB_DEVICE_AND_INTERFACE_INFO(0x0421, x, \ |
1478 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ | 1472 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ |
1479 | USB_CDC_ACM_PROTO_VENDOR) | 1473 | USB_CDC_ACM_PROTO_VENDOR) |
1480 | 1474 | ||
1481 | #define SAMSUNG_PCSUITE_ACM_INFO(x) \ | 1475 | #define SAMSUNG_PCSUITE_ACM_INFO(x) \ |
1482 | USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \ | 1476 | USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \ |
1483 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ | 1477 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ |
1484 | USB_CDC_ACM_PROTO_VENDOR) | 1478 | USB_CDC_ACM_PROTO_VENDOR) |
1485 | 1479 | ||
1486 | /* | 1480 | /* |
1487 | * USB driver structure. | 1481 | * USB driver structure. |
1488 | */ | 1482 | */ |
1489 | 1483 | ||
1490 | static const struct usb_device_id acm_ids[] = { | 1484 | static const struct usb_device_id acm_ids[] = { |
1491 | /* quirky and broken devices */ | 1485 | /* quirky and broken devices */ |
1492 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ | 1486 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
1493 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1487 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1494 | }, | 1488 | }, |
1495 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ | 1489 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ |
1496 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1490 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1497 | }, | 1491 | }, |
1498 | { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */ | 1492 | { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */ |
1499 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1493 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1500 | }, | 1494 | }, |
1501 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ | 1495 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ |
1502 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1496 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1503 | }, | 1497 | }, |
1504 | { USB_DEVICE(0x079b, 0x000f), /* BT On-Air USB MODEM */ | 1498 | { USB_DEVICE(0x079b, 0x000f), /* BT On-Air USB MODEM */ |
1505 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1499 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1506 | }, | 1500 | }, |
1507 | { USB_DEVICE(0x0ace, 0x1602), /* ZyDAS 56K USB MODEM */ | 1501 | { USB_DEVICE(0x0ace, 0x1602), /* ZyDAS 56K USB MODEM */ |
1508 | .driver_info = SINGLE_RX_URB, | 1502 | .driver_info = SINGLE_RX_URB, |
1509 | }, | 1503 | }, |
1510 | { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */ | 1504 | { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */ |
1511 | .driver_info = SINGLE_RX_URB, /* firmware bug */ | 1505 | .driver_info = SINGLE_RX_URB, /* firmware bug */ |
1512 | }, | 1506 | }, |
1513 | { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */ | 1507 | { USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */ |
1514 | .driver_info = SINGLE_RX_URB, /* firmware bug */ | 1508 | .driver_info = SINGLE_RX_URB, /* firmware bug */ |
1515 | }, | 1509 | }, |
1516 | { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ | 1510 | { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ |
1517 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1511 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1518 | }, | 1512 | }, |
1519 | { USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */ | 1513 | { USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */ |
1520 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1514 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1521 | }, | 1515 | }, |
1522 | { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ | 1516 | { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ |
1523 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1517 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1524 | }, | 1518 | }, |
1525 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ | 1519 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ |
1526 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1520 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1527 | }, | 1521 | }, |
1528 | { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */ | 1522 | { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */ |
1529 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1523 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1530 | }, | 1524 | }, |
1531 | { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ | 1525 | { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ |
1532 | }, | 1526 | }, |
1533 | { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ | 1527 | { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ |
1534 | .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on | 1528 | .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on |
1535 | data interface instead of | 1529 | data interface instead of |
1536 | communications interface. | 1530 | communications interface. |
1537 | Maybe we should define a new | 1531 | Maybe we should define a new |
1538 | quirk for this. */ | 1532 | quirk for this. */ |
1539 | }, | 1533 | }, |
1540 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ | 1534 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ |
1541 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1535 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1542 | }, | 1536 | }, |
1543 | { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ | 1537 | { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ |
1544 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1538 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1545 | }, | 1539 | }, |
1546 | 1540 | ||
1547 | /* Nokia S60 phones expose two ACM channels. The first is | 1541 | /* Nokia S60 phones expose two ACM channels. The first is |
1548 | * a modem and is picked up by the standard AT-command | 1542 | * a modem and is picked up by the standard AT-command |
1549 | * information below. The second is 'vendor-specific' but | 1543 | * information below. The second is 'vendor-specific' but |
1550 | * is treated as a serial device at the S60 end, so we want | 1544 | * is treated as a serial device at the S60 end, so we want |
1551 | * to expose it on Linux too. */ | 1545 | * to expose it on Linux too. */ |
1552 | { NOKIA_PCSUITE_ACM_INFO(0x042D), }, /* Nokia 3250 */ | 1546 | { NOKIA_PCSUITE_ACM_INFO(0x042D), }, /* Nokia 3250 */ |
1553 | { NOKIA_PCSUITE_ACM_INFO(0x04D8), }, /* Nokia 5500 Sport */ | 1547 | { NOKIA_PCSUITE_ACM_INFO(0x04D8), }, /* Nokia 5500 Sport */ |
1554 | { NOKIA_PCSUITE_ACM_INFO(0x04C9), }, /* Nokia E50 */ | 1548 | { NOKIA_PCSUITE_ACM_INFO(0x04C9), }, /* Nokia E50 */ |
1555 | { NOKIA_PCSUITE_ACM_INFO(0x0419), }, /* Nokia E60 */ | 1549 | { NOKIA_PCSUITE_ACM_INFO(0x0419), }, /* Nokia E60 */ |
1556 | { NOKIA_PCSUITE_ACM_INFO(0x044D), }, /* Nokia E61 */ | 1550 | { NOKIA_PCSUITE_ACM_INFO(0x044D), }, /* Nokia E61 */ |
1557 | { NOKIA_PCSUITE_ACM_INFO(0x0001), }, /* Nokia E61i */ | 1551 | { NOKIA_PCSUITE_ACM_INFO(0x0001), }, /* Nokia E61i */ |
1558 | { NOKIA_PCSUITE_ACM_INFO(0x0475), }, /* Nokia E62 */ | 1552 | { NOKIA_PCSUITE_ACM_INFO(0x0475), }, /* Nokia E62 */ |
1559 | { NOKIA_PCSUITE_ACM_INFO(0x0508), }, /* Nokia E65 */ | 1553 | { NOKIA_PCSUITE_ACM_INFO(0x0508), }, /* Nokia E65 */ |
1560 | { NOKIA_PCSUITE_ACM_INFO(0x0418), }, /* Nokia E70 */ | 1554 | { NOKIA_PCSUITE_ACM_INFO(0x0418), }, /* Nokia E70 */ |
1561 | { NOKIA_PCSUITE_ACM_INFO(0x0425), }, /* Nokia N71 */ | 1555 | { NOKIA_PCSUITE_ACM_INFO(0x0425), }, /* Nokia N71 */ |
1562 | { NOKIA_PCSUITE_ACM_INFO(0x0486), }, /* Nokia N73 */ | 1556 | { NOKIA_PCSUITE_ACM_INFO(0x0486), }, /* Nokia N73 */ |
1563 | { NOKIA_PCSUITE_ACM_INFO(0x04DF), }, /* Nokia N75 */ | 1557 | { NOKIA_PCSUITE_ACM_INFO(0x04DF), }, /* Nokia N75 */ |
1564 | { NOKIA_PCSUITE_ACM_INFO(0x000e), }, /* Nokia N77 */ | 1558 | { NOKIA_PCSUITE_ACM_INFO(0x000e), }, /* Nokia N77 */ |
1565 | { NOKIA_PCSUITE_ACM_INFO(0x0445), }, /* Nokia N80 */ | 1559 | { NOKIA_PCSUITE_ACM_INFO(0x0445), }, /* Nokia N80 */ |
1566 | { NOKIA_PCSUITE_ACM_INFO(0x042F), }, /* Nokia N91 & N91 8GB */ | 1560 | { NOKIA_PCSUITE_ACM_INFO(0x042F), }, /* Nokia N91 & N91 8GB */ |
1567 | { NOKIA_PCSUITE_ACM_INFO(0x048E), }, /* Nokia N92 */ | 1561 | { NOKIA_PCSUITE_ACM_INFO(0x048E), }, /* Nokia N92 */ |
1568 | { NOKIA_PCSUITE_ACM_INFO(0x0420), }, /* Nokia N93 */ | 1562 | { NOKIA_PCSUITE_ACM_INFO(0x0420), }, /* Nokia N93 */ |
1569 | { NOKIA_PCSUITE_ACM_INFO(0x04E6), }, /* Nokia N93i */ | 1563 | { NOKIA_PCSUITE_ACM_INFO(0x04E6), }, /* Nokia N93i */ |
1570 | { NOKIA_PCSUITE_ACM_INFO(0x04B2), }, /* Nokia 5700 XpressMusic */ | 1564 | { NOKIA_PCSUITE_ACM_INFO(0x04B2), }, /* Nokia 5700 XpressMusic */ |
1571 | { NOKIA_PCSUITE_ACM_INFO(0x0134), }, /* Nokia 6110 Navigator (China) */ | 1565 | { NOKIA_PCSUITE_ACM_INFO(0x0134), }, /* Nokia 6110 Navigator (China) */ |
1572 | { NOKIA_PCSUITE_ACM_INFO(0x046E), }, /* Nokia 6110 Navigator */ | 1566 | { NOKIA_PCSUITE_ACM_INFO(0x046E), }, /* Nokia 6110 Navigator */ |
1573 | { NOKIA_PCSUITE_ACM_INFO(0x002f), }, /* Nokia 6120 classic & */ | 1567 | { NOKIA_PCSUITE_ACM_INFO(0x002f), }, /* Nokia 6120 classic & */ |
1574 | { NOKIA_PCSUITE_ACM_INFO(0x0088), }, /* Nokia 6121 classic */ | 1568 | { NOKIA_PCSUITE_ACM_INFO(0x0088), }, /* Nokia 6121 classic */ |
1575 | { NOKIA_PCSUITE_ACM_INFO(0x00fc), }, /* Nokia 6124 classic */ | 1569 | { NOKIA_PCSUITE_ACM_INFO(0x00fc), }, /* Nokia 6124 classic */ |
1576 | { NOKIA_PCSUITE_ACM_INFO(0x0042), }, /* Nokia E51 */ | 1570 | { NOKIA_PCSUITE_ACM_INFO(0x0042), }, /* Nokia E51 */ |
1577 | { NOKIA_PCSUITE_ACM_INFO(0x00b0), }, /* Nokia E66 */ | 1571 | { NOKIA_PCSUITE_ACM_INFO(0x00b0), }, /* Nokia E66 */ |
1578 | { NOKIA_PCSUITE_ACM_INFO(0x00ab), }, /* Nokia E71 */ | 1572 | { NOKIA_PCSUITE_ACM_INFO(0x00ab), }, /* Nokia E71 */ |
1579 | { NOKIA_PCSUITE_ACM_INFO(0x0481), }, /* Nokia N76 */ | 1573 | { NOKIA_PCSUITE_ACM_INFO(0x0481), }, /* Nokia N76 */ |
1580 | { NOKIA_PCSUITE_ACM_INFO(0x0007), }, /* Nokia N81 & N81 8GB */ | 1574 | { NOKIA_PCSUITE_ACM_INFO(0x0007), }, /* Nokia N81 & N81 8GB */ |
1581 | { NOKIA_PCSUITE_ACM_INFO(0x0071), }, /* Nokia N82 */ | 1575 | { NOKIA_PCSUITE_ACM_INFO(0x0071), }, /* Nokia N82 */ |
1582 | { NOKIA_PCSUITE_ACM_INFO(0x04F0), }, /* Nokia N95 & N95-3 NAM */ | 1576 | { NOKIA_PCSUITE_ACM_INFO(0x04F0), }, /* Nokia N95 & N95-3 NAM */ |
1583 | { NOKIA_PCSUITE_ACM_INFO(0x0070), }, /* Nokia N95 8GB */ | 1577 | { NOKIA_PCSUITE_ACM_INFO(0x0070), }, /* Nokia N95 8GB */ |
1584 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ | 1578 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ |
1585 | { NOKIA_PCSUITE_ACM_INFO(0x0099), }, /* Nokia 6210 Navigator, RM-367 */ | 1579 | { NOKIA_PCSUITE_ACM_INFO(0x0099), }, /* Nokia 6210 Navigator, RM-367 */ |
1586 | { NOKIA_PCSUITE_ACM_INFO(0x0128), }, /* Nokia 6210 Navigator, RM-419 */ | 1580 | { NOKIA_PCSUITE_ACM_INFO(0x0128), }, /* Nokia 6210 Navigator, RM-419 */ |
1587 | { NOKIA_PCSUITE_ACM_INFO(0x008f), }, /* Nokia 6220 Classic */ | 1581 | { NOKIA_PCSUITE_ACM_INFO(0x008f), }, /* Nokia 6220 Classic */ |
1588 | { NOKIA_PCSUITE_ACM_INFO(0x00a0), }, /* Nokia 6650 */ | 1582 | { NOKIA_PCSUITE_ACM_INFO(0x00a0), }, /* Nokia 6650 */ |
1589 | { NOKIA_PCSUITE_ACM_INFO(0x007b), }, /* Nokia N78 */ | 1583 | { NOKIA_PCSUITE_ACM_INFO(0x007b), }, /* Nokia N78 */ |
1590 | { NOKIA_PCSUITE_ACM_INFO(0x0094), }, /* Nokia N85 */ | 1584 | { NOKIA_PCSUITE_ACM_INFO(0x0094), }, /* Nokia N85 */ |
1591 | { NOKIA_PCSUITE_ACM_INFO(0x003a), }, /* Nokia N96 & N96-3 */ | 1585 | { NOKIA_PCSUITE_ACM_INFO(0x003a), }, /* Nokia N96 & N96-3 */ |
1592 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ | 1586 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ |
1593 | { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ | 1587 | { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ |
1594 | { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ | 1588 | { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ |
1595 | { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */ | 1589 | { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */ |
1596 | { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */ | 1590 | { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */ |
1597 | { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */ | 1591 | { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */ |
1598 | { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */ | 1592 | { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */ |
1599 | { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */ | 1593 | { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */ |
1600 | { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */ | 1594 | { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */ |
1601 | { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */ | 1595 | { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */ |
1602 | { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */ | 1596 | { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */ |
1603 | { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ | 1597 | { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ |
1604 | { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ | 1598 | { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ |
1605 | { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ | 1599 | { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ |
1606 | { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */ | 1600 | { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */ |
1607 | { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ | 1601 | { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ |
1608 | 1602 | ||
1609 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ | 1603 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ |
1610 | 1604 | ||
1611 | /* Support Lego NXT using pbLua firmware */ | 1605 | /* Support Lego NXT using pbLua firmware */ |
1612 | { USB_DEVICE(0x0694, 0xff00), | 1606 | { USB_DEVICE(0x0694, 0xff00), |
1613 | .driver_info = NOT_A_MODEM, | 1607 | .driver_info = NOT_A_MODEM, |
1614 | }, | 1608 | }, |
1615 | 1609 | ||
1616 | /* control interfaces without any protocol set */ | 1610 | /* control interfaces without any protocol set */ |
1617 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1611 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1618 | USB_CDC_PROTO_NONE) }, | 1612 | USB_CDC_PROTO_NONE) }, |
1619 | 1613 | ||
1620 | /* control interfaces with various AT-command sets */ | 1614 | /* control interfaces with various AT-command sets */ |
1621 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1615 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1622 | USB_CDC_ACM_PROTO_AT_V25TER) }, | 1616 | USB_CDC_ACM_PROTO_AT_V25TER) }, |
1623 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1617 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1624 | USB_CDC_ACM_PROTO_AT_PCCA101) }, | 1618 | USB_CDC_ACM_PROTO_AT_PCCA101) }, |
1625 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1619 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1626 | USB_CDC_ACM_PROTO_AT_PCCA101_WAKE) }, | 1620 | USB_CDC_ACM_PROTO_AT_PCCA101_WAKE) }, |
1627 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1621 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1628 | USB_CDC_ACM_PROTO_AT_GSM) }, | 1622 | USB_CDC_ACM_PROTO_AT_GSM) }, |
1629 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1623 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1630 | USB_CDC_ACM_PROTO_AT_3G) }, | 1624 | USB_CDC_ACM_PROTO_AT_3G) }, |
1631 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1625 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1632 | USB_CDC_ACM_PROTO_AT_CDMA) }, | 1626 | USB_CDC_ACM_PROTO_AT_CDMA) }, |
1633 | 1627 | ||
1634 | { } | 1628 | { } |
1635 | }; | 1629 | }; |
1636 | 1630 | ||
1637 | MODULE_DEVICE_TABLE(usb, acm_ids); | 1631 | MODULE_DEVICE_TABLE(usb, acm_ids); |
1638 | 1632 | ||
1639 | static struct usb_driver acm_driver = { | 1633 | static struct usb_driver acm_driver = { |
1640 | .name = "cdc_acm", | 1634 | .name = "cdc_acm", |
1641 | .probe = acm_probe, | 1635 | .probe = acm_probe, |
1642 | .disconnect = acm_disconnect, | 1636 | .disconnect = acm_disconnect, |
1643 | #ifdef CONFIG_PM | 1637 | #ifdef CONFIG_PM |
1644 | .suspend = acm_suspend, | 1638 | .suspend = acm_suspend, |
1645 | .resume = acm_resume, | 1639 | .resume = acm_resume, |
1646 | .reset_resume = acm_reset_resume, | 1640 | .reset_resume = acm_reset_resume, |
1647 | #endif | 1641 | #endif |
1648 | .id_table = acm_ids, | 1642 | .id_table = acm_ids, |
1649 | #ifdef CONFIG_PM | 1643 | #ifdef CONFIG_PM |
1650 | .supports_autosuspend = 1, | 1644 | .supports_autosuspend = 1, |
1651 | #endif | 1645 | #endif |
1652 | }; | 1646 | }; |
1653 | 1647 | ||
1654 | /* | 1648 | /* |
1655 | * TTY driver structures. | 1649 | * TTY driver structures. |
1656 | */ | 1650 | */ |
1657 | 1651 | ||
1658 | static const struct tty_operations acm_ops = { | 1652 | static const struct tty_operations acm_ops = { |
1659 | .open = acm_tty_open, | 1653 | .open = acm_tty_open, |
1660 | .close = acm_tty_close, | 1654 | .close = acm_tty_close, |
1661 | .hangup = acm_tty_hangup, | 1655 | .hangup = acm_tty_hangup, |
1662 | .write = acm_tty_write, | 1656 | .write = acm_tty_write, |
1663 | .write_room = acm_tty_write_room, | 1657 | .write_room = acm_tty_write_room, |
1664 | .ioctl = acm_tty_ioctl, | 1658 | .ioctl = acm_tty_ioctl, |
1665 | .throttle = acm_tty_throttle, | 1659 | .throttle = acm_tty_throttle, |
1666 | .unthrottle = acm_tty_unthrottle, | 1660 | .unthrottle = acm_tty_unthrottle, |
1667 | .chars_in_buffer = acm_tty_chars_in_buffer, | 1661 | .chars_in_buffer = acm_tty_chars_in_buffer, |
1668 | .break_ctl = acm_tty_break_ctl, | 1662 | .break_ctl = acm_tty_break_ctl, |
1669 | .set_termios = acm_tty_set_termios, | 1663 | .set_termios = acm_tty_set_termios, |
1670 | .tiocmget = acm_tty_tiocmget, | 1664 | .tiocmget = acm_tty_tiocmget, |
1671 | .tiocmset = acm_tty_tiocmset, | 1665 | .tiocmset = acm_tty_tiocmset, |
1672 | }; | 1666 | }; |
1673 | 1667 | ||
1674 | /* | 1668 | /* |
1675 | * Init / exit. | 1669 | * Init / exit. |
1676 | */ | 1670 | */ |
1677 | 1671 | ||
1678 | static int __init acm_init(void) | 1672 | static int __init acm_init(void) |
1679 | { | 1673 | { |
1680 | int retval; | 1674 | int retval; |
1681 | acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS); | 1675 | acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS); |
1682 | if (!acm_tty_driver) | 1676 | if (!acm_tty_driver) |
1683 | return -ENOMEM; | 1677 | return -ENOMEM; |
1684 | acm_tty_driver->owner = THIS_MODULE, | 1678 | acm_tty_driver->owner = THIS_MODULE, |
1685 | acm_tty_driver->driver_name = "acm", | 1679 | acm_tty_driver->driver_name = "acm", |
1686 | acm_tty_driver->name = "ttyACM", | 1680 | acm_tty_driver->name = "ttyACM", |
1687 | acm_tty_driver->major = ACM_TTY_MAJOR, | 1681 | acm_tty_driver->major = ACM_TTY_MAJOR, |
1688 | acm_tty_driver->minor_start = 0, | 1682 | acm_tty_driver->minor_start = 0, |
1689 | acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, | 1683 | acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, |
1690 | acm_tty_driver->subtype = SERIAL_TYPE_NORMAL, | 1684 | acm_tty_driver->subtype = SERIAL_TYPE_NORMAL, |
1691 | acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 1685 | acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
1692 | acm_tty_driver->init_termios = tty_std_termios; | 1686 | acm_tty_driver->init_termios = tty_std_termios; |
1693 | acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | | 1687 | acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | |
1694 | HUPCL | CLOCAL; | 1688 | HUPCL | CLOCAL; |
1695 | tty_set_operations(acm_tty_driver, &acm_ops); | 1689 | tty_set_operations(acm_tty_driver, &acm_ops); |
1696 | 1690 | ||
1697 | retval = tty_register_driver(acm_tty_driver); | 1691 | retval = tty_register_driver(acm_tty_driver); |
1698 | if (retval) { | 1692 | if (retval) { |
1699 | put_tty_driver(acm_tty_driver); | 1693 | put_tty_driver(acm_tty_driver); |
1700 | return retval; | 1694 | return retval; |
1701 | } | 1695 | } |
1702 | 1696 | ||
1703 | retval = usb_register(&acm_driver); | 1697 | retval = usb_register(&acm_driver); |
1704 | if (retval) { | 1698 | if (retval) { |
1705 | tty_unregister_driver(acm_tty_driver); | 1699 | tty_unregister_driver(acm_tty_driver); |
1706 | put_tty_driver(acm_tty_driver); | 1700 | put_tty_driver(acm_tty_driver); |
1707 | return retval; | 1701 | return retval; |
1708 | } | 1702 | } |
1709 | 1703 | ||
1710 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); | 1704 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); |
1711 | 1705 | ||
1712 | return 0; | 1706 | return 0; |
1713 | } | 1707 | } |
1714 | 1708 | ||
1715 | static void __exit acm_exit(void) | 1709 | static void __exit acm_exit(void) |
1716 | { | 1710 | { |
1717 | usb_deregister(&acm_driver); | 1711 | usb_deregister(&acm_driver); |
1718 | tty_unregister_driver(acm_tty_driver); | 1712 | tty_unregister_driver(acm_tty_driver); |
1719 | put_tty_driver(acm_tty_driver); | 1713 | put_tty_driver(acm_tty_driver); |
1720 | } | 1714 | } |
1721 | 1715 | ||
1722 | module_init(acm_init); | 1716 | module_init(acm_init); |
1723 | module_exit(acm_exit); | 1717 | module_exit(acm_exit); |
1724 | 1718 | ||
1725 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1719 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1726 | MODULE_DESCRIPTION(DRIVER_DESC); | 1720 | MODULE_DESCRIPTION(DRIVER_DESC); |
1727 | MODULE_LICENSE("GPL"); | 1721 | MODULE_LICENSE("GPL"); |
1728 | MODULE_ALIAS_CHARDEV_MAJOR(ACM_TTY_MAJOR); | 1722 | MODULE_ALIAS_CHARDEV_MAJOR(ACM_TTY_MAJOR); |
1729 | 1723 |
drivers/usb/class/cdc-acm.h
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * Includes for cdc-acm.c | 3 | * Includes for cdc-acm.c |
4 | * | 4 | * |
5 | * Mainly take from usbnet's cdc-ether part | 5 | * Mainly take from usbnet's cdc-ether part |
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * CMSPAR, some architectures can't have space and mark parity. | 10 | * CMSPAR, some architectures can't have space and mark parity. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef CMSPAR | 13 | #ifndef CMSPAR |
14 | #define CMSPAR 0 | 14 | #define CMSPAR 0 |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | /* | 17 | /* |
18 | * Major and minor numbers. | 18 | * Major and minor numbers. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #define ACM_TTY_MAJOR 166 | 21 | #define ACM_TTY_MAJOR 166 |
22 | #define ACM_TTY_MINORS 32 | 22 | #define ACM_TTY_MINORS 32 |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * Requests. | 25 | * Requests. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) | 28 | #define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Output control lines. | 31 | * Output control lines. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #define ACM_CTRL_DTR 0x01 | 34 | #define ACM_CTRL_DTR 0x01 |
35 | #define ACM_CTRL_RTS 0x02 | 35 | #define ACM_CTRL_RTS 0x02 |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Input control lines and line errors. | 38 | * Input control lines and line errors. |
39 | */ | 39 | */ |
40 | 40 | ||
41 | #define ACM_CTRL_DCD 0x01 | 41 | #define ACM_CTRL_DCD 0x01 |
42 | #define ACM_CTRL_DSR 0x02 | 42 | #define ACM_CTRL_DSR 0x02 |
43 | #define ACM_CTRL_BRK 0x04 | 43 | #define ACM_CTRL_BRK 0x04 |
44 | #define ACM_CTRL_RI 0x08 | 44 | #define ACM_CTRL_RI 0x08 |
45 | 45 | ||
46 | #define ACM_CTRL_FRAMING 0x10 | 46 | #define ACM_CTRL_FRAMING 0x10 |
47 | #define ACM_CTRL_PARITY 0x20 | 47 | #define ACM_CTRL_PARITY 0x20 |
48 | #define ACM_CTRL_OVERRUN 0x40 | 48 | #define ACM_CTRL_OVERRUN 0x40 |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Internal driver structures. | 51 | * Internal driver structures. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * The only reason to have several buffers is to accommodate assumptions | 55 | * The only reason to have several buffers is to accommodate assumptions |
56 | * in line disciplines. They ask for empty space amount, receive our URB size, | 56 | * in line disciplines. They ask for empty space amount, receive our URB size, |
57 | * and proceed to issue several 1-character writes, assuming they will fit. | 57 | * and proceed to issue several 1-character writes, assuming they will fit. |
58 | * The very first write takes a complete URB. Fortunately, this only happens | 58 | * The very first write takes a complete URB. Fortunately, this only happens |
59 | * when processing onlcr, so we only need 2 buffers. These values must be | 59 | * when processing onlcr, so we only need 2 buffers. These values must be |
60 | * powers of 2. | 60 | * powers of 2. |
61 | */ | 61 | */ |
62 | #define ACM_NW 16 | 62 | #define ACM_NW 16 |
63 | #define ACM_NR 16 | 63 | #define ACM_NR 16 |
64 | 64 | ||
65 | struct acm_wb { | 65 | struct acm_wb { |
66 | unsigned char *buf; | 66 | unsigned char *buf; |
67 | dma_addr_t dmah; | 67 | dma_addr_t dmah; |
68 | int len; | 68 | int len; |
69 | int use; | 69 | int use; |
70 | struct urb *urb; | 70 | struct urb *urb; |
71 | struct acm *instance; | 71 | struct acm *instance; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct acm_rb { | 74 | struct acm_rb { |
75 | struct list_head list; | 75 | struct list_head list; |
76 | int size; | 76 | int size; |
77 | unsigned char *base; | 77 | unsigned char *base; |
78 | dma_addr_t dma; | 78 | dma_addr_t dma; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct acm_ru { | 81 | struct acm_ru { |
82 | struct list_head list; | 82 | struct list_head list; |
83 | struct acm_rb *buffer; | 83 | struct acm_rb *buffer; |
84 | struct urb *urb; | 84 | struct urb *urb; |
85 | struct acm *instance; | 85 | struct acm *instance; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | struct acm { | 88 | struct acm { |
89 | struct usb_device *dev; /* the corresponding usb device */ | 89 | struct usb_device *dev; /* the corresponding usb device */ |
90 | struct usb_interface *control; /* control interface */ | 90 | struct usb_interface *control; /* control interface */ |
91 | struct usb_interface *data; /* data interface */ | 91 | struct usb_interface *data; /* data interface */ |
92 | struct tty_port port; /* our tty port data */ | 92 | struct tty_port port; /* our tty port data */ |
93 | struct urb *ctrlurb; /* urbs */ | 93 | struct urb *ctrlurb; /* urbs */ |
94 | u8 *ctrl_buffer; /* buffers of urbs */ | 94 | u8 *ctrl_buffer; /* buffers of urbs */ |
95 | dma_addr_t ctrl_dma; /* dma handles of buffers */ | 95 | dma_addr_t ctrl_dma; /* dma handles of buffers */ |
96 | u8 *country_codes; /* country codes from device */ | 96 | u8 *country_codes; /* country codes from device */ |
97 | unsigned int country_code_size; /* size of this buffer */ | 97 | unsigned int country_code_size; /* size of this buffer */ |
98 | unsigned int country_rel_date; /* release date of version */ | 98 | unsigned int country_rel_date; /* release date of version */ |
99 | struct acm_wb wb[ACM_NW]; | 99 | struct acm_wb wb[ACM_NW]; |
100 | struct acm_ru ru[ACM_NR]; | 100 | struct acm_ru ru[ACM_NR]; |
101 | struct acm_rb rb[ACM_NR]; | 101 | struct acm_rb rb[ACM_NR]; |
102 | int rx_buflimit; | 102 | int rx_buflimit; |
103 | int rx_endpoint; | 103 | int rx_endpoint; |
104 | spinlock_t read_lock; | 104 | spinlock_t read_lock; |
105 | struct list_head spare_read_urbs; | 105 | struct list_head spare_read_urbs; |
106 | struct list_head spare_read_bufs; | 106 | struct list_head spare_read_bufs; |
107 | struct list_head filled_read_bufs; | 107 | struct list_head filled_read_bufs; |
108 | int write_used; /* number of non-empty write buffers */ | 108 | int write_used; /* number of non-empty write buffers */ |
109 | int processing; | 109 | int processing; |
110 | int transmitting; | 110 | int transmitting; |
111 | spinlock_t write_lock; | 111 | spinlock_t write_lock; |
112 | struct mutex mutex; | 112 | struct mutex mutex; |
113 | struct usb_cdc_line_coding line; /* bits, stop, parity */ | 113 | struct usb_cdc_line_coding line; /* bits, stop, parity */ |
114 | struct work_struct work; /* work queue entry for line discipline waking up */ | 114 | struct work_struct work; /* work queue entry for line discipline waking up */ |
115 | wait_queue_head_t drain_wait; /* close processing */ | ||
116 | struct tasklet_struct urb_task; /* rx processing */ | 115 | struct tasklet_struct urb_task; /* rx processing */ |
117 | spinlock_t throttle_lock; /* synchronize throtteling and read callback */ | 116 | spinlock_t throttle_lock; /* synchronize throtteling and read callback */ |
118 | unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ | 117 | unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ |
119 | unsigned int ctrlout; /* output control lines (DTR, RTS) */ | 118 | unsigned int ctrlout; /* output control lines (DTR, RTS) */ |
120 | unsigned int writesize; /* max packet size for the output bulk endpoint */ | 119 | unsigned int writesize; /* max packet size for the output bulk endpoint */ |
121 | unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ | 120 | unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ |
122 | unsigned int minor; /* acm minor number */ | 121 | unsigned int minor; /* acm minor number */ |
123 | unsigned char throttle; /* throttled by tty layer */ | 122 | unsigned char throttle; /* throttled by tty layer */ |
124 | unsigned char clocal; /* termios CLOCAL */ | 123 | unsigned char clocal; /* termios CLOCAL */ |
125 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ | 124 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ |
126 | unsigned int susp_count; /* number of suspended interfaces */ | 125 | unsigned int susp_count; /* number of suspended interfaces */ |
127 | unsigned int combined_interfaces:1; /* control and data collapsed */ | 126 | unsigned int combined_interfaces:1; /* control and data collapsed */ |
128 | unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */ | 127 | unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */ |
129 | u8 bInterval; | 128 | u8 bInterval; |
130 | struct acm_wb *delayed_wb; /* write queued for a device about to be woken */ | 129 | struct acm_wb *delayed_wb; /* write queued for a device about to be woken */ |
131 | }; | 130 | }; |
132 | 131 | ||
133 | #define CDC_DATA_INTERFACE_TYPE 0x0a | 132 | #define CDC_DATA_INTERFACE_TYPE 0x0a |
134 | 133 | ||
135 | /* constants describing various quirks and errors */ | 134 | /* constants describing various quirks and errors */ |
136 | #define NO_UNION_NORMAL 1 | 135 | #define NO_UNION_NORMAL 1 |
137 | #define SINGLE_RX_URB 2 | 136 | #define SINGLE_RX_URB 2 |
138 | #define NO_CAP_LINE 4 | 137 | #define NO_CAP_LINE 4 |
139 | #define NOT_A_MODEM 8 | 138 | #define NOT_A_MODEM 8 |
140 | 139 |