aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/class/cdc-acm.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c942
1 files changed, 942 insertions, 0 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
new file mode 100644
index 000000000000..6d1f9b6aecff
--- /dev/null
+++ b/drivers/usb/class/cdc-acm.c
@@ -0,0 +1,942 @@
1/*
2 * cdc-acm.c
3 *
4 * Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de>
5 * Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
6 * Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
7 * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
8 * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name>
9 *
10 * USB Abstract Control Model driver for USB modems and ISDN adapters
11 *
12 * Sponsored by SuSE
13 *
14 * ChangeLog:
15 * v0.9 - thorough cleaning, URBification, almost a rewrite
16 * v0.10 - some more cleanups
17 * v0.11 - fixed flow control, read error doesn't stop reads
18 * v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
19 * v0.13 - added termios, added hangup
20 * v0.14 - sized down struct acm
21 * v0.15 - fixed flow control again - characters could be lost
22 * v0.16 - added code for modems with swapped data and control interfaces
23 * v0.17 - added new style probing
24 * v0.18 - fixed new style probing for devices with more configurations
25 * v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan)
26 * v0.20 - switched to probing on interface (rather than device) class
27 * v0.21 - revert to probing on device for devices with multiple configs
28 * v0.22 - probe only the control interface. if usbcore doesn't choose the
29 * config we want, sysadmin changes bConfigurationValue in sysfs.
30 * v0.23 - use softirq for rx processing, as needed by tty layer
31 * v0.24 - change probe method to evaluate CDC union descriptor
32 */
33
34/*
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation; either version 2 of the License, or
38 * (at your option) any later version.
39 *
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
44 *
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
48 */
49
50#undef DEBUG
51
52#include <linux/kernel.h>
53#include <linux/errno.h>
54#include <linux/init.h>
55#include <linux/slab.h>
56#include <linux/tty.h>
57#include <linux/tty_driver.h>
58#include <linux/tty_flip.h>
59#include <linux/module.h>
60#include <linux/smp_lock.h>
61#include <asm/uaccess.h>
62#include <linux/usb.h>
63#include <linux/usb_cdc.h>
64#include <asm/byteorder.h>
65#include <asm/unaligned.h>
66
67#include "cdc-acm.h"
68
69/*
70 * Version Information
71 */
72#define DRIVER_VERSION "v0.23"
73#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
74#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
75
76static struct usb_driver acm_driver;
77static struct tty_driver *acm_tty_driver;
78static struct acm *acm_table[ACM_TTY_MINORS];
79
80static DECLARE_MUTEX(open_sem);
81
82#define ACM_READY(acm) (acm && acm->dev && acm->used)
83
84/*
85 * Functions for ACM control messages.
86 */
87
88static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
89{
90 int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
91 request, USB_RT_ACM, value,
92 acm->control->altsetting[0].desc.bInterfaceNumber,
93 buf, len, 5000);
94 dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
95 return retval < 0 ? retval : 0;
96}
97
98/* devices aren't required to support these requests.
99 * the cdc acm descriptor tells whether they do...
100 */
101#define acm_set_control(acm, control) \
102 acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0)
103#define acm_set_line(acm, line) \
104 acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line))
105#define acm_send_break(acm, ms) \
106 acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0)
107
108/*
109 * Interrupt handlers for various ACM device responses
110 */
111
112/* control interface reports status changes with "interrupt" transfers */
113static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
114{
115 struct acm *acm = urb->context;
116 struct usb_cdc_notification *dr = urb->transfer_buffer;
117 unsigned char *data;
118 int newctrl;
119 int status;
120
121 switch (urb->status) {
122 case 0:
123 /* success */
124 break;
125 case -ECONNRESET:
126 case -ENOENT:
127 case -ESHUTDOWN:
128 /* this urb is terminated, clean up */
129 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
130 return;
131 default:
132 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
133 goto exit;
134 }
135
136 if (!ACM_READY(acm))
137 goto exit;
138
139 data = (unsigned char *)(dr + 1);
140 switch (dr->bNotificationType) {
141
142 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
143
144 dbg("%s network", dr->wValue ? "connected to" : "disconnected from");
145 break;
146
147 case USB_CDC_NOTIFY_SERIAL_STATE:
148
149 newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
150
151 if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
152 dbg("calling hangup");
153 tty_hangup(acm->tty);
154 }
155
156 acm->ctrlin = newctrl;
157
158 dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
159 acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
160 acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
161 acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
162 acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
163
164 break;
165
166 default:
167 dbg("unknown notification %d received: index %d len %d data0 %d data1 %d",
168 dr->bNotificationType, dr->wIndex,
169 dr->wLength, data[0], data[1]);
170 break;
171 }
172exit:
173 status = usb_submit_urb (urb, GFP_ATOMIC);
174 if (status)
175 err ("%s - usb_submit_urb failed with result %d",
176 __FUNCTION__, status);
177}
178
179/* data interface returns incoming bytes, or we got unthrottled */
180static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
181{
182 struct acm *acm = urb->context;
183 dbg("Entering acm_read_bulk with status %d\n", urb->status);
184
185 if (!ACM_READY(acm))
186 return;
187
188 if (urb->status)
189 dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
190
191 /* calling tty_flip_buffer_push() in_irq() isn't allowed */
192 tasklet_schedule(&acm->bh);
193}
194
195static void acm_rx_tasklet(unsigned long _acm)
196{
197 struct acm *acm = (void *)_acm;
198 struct urb *urb = acm->readurb;
199 struct tty_struct *tty = acm->tty;
200 unsigned char *data = urb->transfer_buffer;
201 int i = 0;
202 dbg("Entering acm_rx_tasklet");
203
204 if (urb->actual_length > 0 && !acm->throttle) {
205 for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
206 /* if we insert more than TTY_FLIPBUF_SIZE characters,
207 * we drop them. */
208 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
209 tty_flip_buffer_push(tty);
210 }
211 tty_insert_flip_char(tty, data[i], 0);
212 }
213 dbg("Handed %d bytes to tty layer", i+1);
214 tty_flip_buffer_push(tty);
215 }
216
217 spin_lock(&acm->throttle_lock);
218 if (acm->throttle) {
219 dbg("Throtteling noticed");
220 memmove(data, data + i, urb->actual_length - i);
221 urb->actual_length -= i;
222 acm->resubmit_to_unthrottle = 1;
223 spin_unlock(&acm->throttle_lock);
224 return;
225 }
226 spin_unlock(&acm->throttle_lock);
227
228 urb->actual_length = 0;
229 urb->dev = acm->dev;
230
231 i = usb_submit_urb(urb, GFP_ATOMIC);
232 if (i)
233 dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
234}
235
236/* data interface wrote those outgoing bytes */
237static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
238{
239 struct acm *acm = (struct acm *)urb->context;
240 dbg("Entering acm_write_bulk with status %d\n", urb->status);
241
242 if (!ACM_READY(acm))
243 goto out;
244
245 if (urb->status)
246 dbg("nonzero write bulk status received: %d", urb->status);
247
248 schedule_work(&acm->work);
249out:
250 acm->ready_for_write = 1;
251}
252
253static void acm_softint(void *private)
254{
255 struct acm *acm = private;
256 dbg("Entering acm_softint.\n");
257
258 if (!ACM_READY(acm))
259 return;
260 tty_wakeup(acm->tty);
261}
262
263/*
264 * TTY handlers
265 */
266
267static int acm_tty_open(struct tty_struct *tty, struct file *filp)
268{
269 struct acm *acm;
270 int rv = -EINVAL;
271 dbg("Entering acm_tty_open.\n");
272
273 down(&open_sem);
274
275 acm = acm_table[tty->index];
276 if (!acm || !acm->dev)
277 goto err_out;
278 else
279 rv = 0;
280
281 tty->driver_data = acm;
282 acm->tty = tty;
283
284
285
286 if (acm->used++) {
287 goto done;
288 }
289
290 acm->ctrlurb->dev = acm->dev;
291 if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
292 dbg("usb_submit_urb(ctrl irq) failed");
293 goto bail_out;
294 }
295
296 acm->readurb->dev = acm->dev;
297 if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
298 dbg("usb_submit_urb(read bulk) failed");
299 goto bail_out_and_unlink;
300 }
301
302 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
303 goto full_bailout;
304
305 /* force low_latency on so that our tty_push actually forces the data through,
306 otherwise it is scheduled, and with high data rates data can get lost. */
307 tty->low_latency = 1;
308
309done:
310err_out:
311 up(&open_sem);
312 return rv;
313
314full_bailout:
315 usb_kill_urb(acm->readurb);
316bail_out_and_unlink:
317 usb_kill_urb(acm->ctrlurb);
318bail_out:
319 acm->used--;
320 up(&open_sem);
321 return -EIO;
322}
323
324static void acm_tty_close(struct tty_struct *tty, struct file *filp)
325{
326 struct acm *acm = tty->driver_data;
327
328 if (!acm || !acm->used)
329 return;
330
331 down(&open_sem);
332 if (!--acm->used) {
333 if (acm->dev) {
334 acm_set_control(acm, acm->ctrlout = 0);
335 usb_kill_urb(acm->ctrlurb);
336 usb_kill_urb(acm->writeurb);
337 usb_kill_urb(acm->readurb);
338 } else {
339 tty_unregister_device(acm_tty_driver, acm->minor);
340 acm_table[acm->minor] = NULL;
341 usb_free_urb(acm->ctrlurb);
342 usb_free_urb(acm->readurb);
343 usb_free_urb(acm->writeurb);
344 kfree(acm);
345 }
346 }
347 up(&open_sem);
348}
349
350static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
351{
352 struct acm *acm = tty->driver_data;
353 int stat;
354 dbg("Entering acm_tty_write to write %d bytes,\n", count);
355
356 if (!ACM_READY(acm))
357 return -EINVAL;
358 if (!acm->ready_for_write)
359 return 0;
360 if (!count)
361 return 0;
362
363 count = (count > acm->writesize) ? acm->writesize : count;
364
365 dbg("Get %d bytes...", count);
366 memcpy(acm->write_buffer, buf, count);
367 dbg(" Successfully copied.\n");
368
369 acm->writeurb->transfer_buffer_length = count;
370 acm->writeurb->dev = acm->dev;
371
372 acm->ready_for_write = 0;
373 stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);
374 if (stat < 0) {
375 dbg("usb_submit_urb(write bulk) failed");
376 acm->ready_for_write = 1;
377 return stat;
378 }
379
380 return count;
381}
382
383static int acm_tty_write_room(struct tty_struct *tty)
384{
385 struct acm *acm = tty->driver_data;
386 if (!ACM_READY(acm))
387 return -EINVAL;
388 return !acm->ready_for_write ? 0 : acm->writesize;
389}
390
391static int acm_tty_chars_in_buffer(struct tty_struct *tty)
392{
393 struct acm *acm = tty->driver_data;
394 if (!ACM_READY(acm))
395 return -EINVAL;
396 return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0;
397}
398
399static void acm_tty_throttle(struct tty_struct *tty)
400{
401 struct acm *acm = tty->driver_data;
402 if (!ACM_READY(acm))
403 return;
404 spin_lock_bh(&acm->throttle_lock);
405 acm->throttle = 1;
406 spin_unlock_bh(&acm->throttle_lock);
407}
408
409static void acm_tty_unthrottle(struct tty_struct *tty)
410{
411 struct acm *acm = tty->driver_data;
412 if (!ACM_READY(acm))
413 return;
414 spin_lock_bh(&acm->throttle_lock);
415 acm->throttle = 0;
416 spin_unlock_bh(&acm->throttle_lock);
417 if (acm->resubmit_to_unthrottle) {
418 acm->resubmit_to_unthrottle = 0;
419 acm_read_bulk(acm->readurb, NULL);
420 }
421}
422
423static void acm_tty_break_ctl(struct tty_struct *tty, int state)
424{
425 struct acm *acm = tty->driver_data;
426 if (!ACM_READY(acm))
427 return;
428 if (acm_send_break(acm, state ? 0xffff : 0))
429 dbg("send break failed");
430}
431
432static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
433{
434 struct acm *acm = tty->driver_data;
435
436 if (!ACM_READY(acm))
437 return -EINVAL;
438
439 return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
440 (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
441 (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
442 (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
443 (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
444 TIOCM_CTS;
445}
446
447static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
448 unsigned int set, unsigned int clear)
449{
450 struct acm *acm = tty->driver_data;
451 unsigned int newctrl;
452
453 if (!ACM_READY(acm))
454 return -EINVAL;
455
456 newctrl = acm->ctrlout;
457 set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0);
458 clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0);
459
460 newctrl = (newctrl & ~clear) | set;
461
462 if (acm->ctrlout == newctrl)
463 return 0;
464 return acm_set_control(acm, acm->ctrlout = newctrl);
465}
466
467static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
468{
469 struct acm *acm = tty->driver_data;
470
471 if (!ACM_READY(acm))
472 return -EINVAL;
473
474 return -ENOIOCTLCMD;
475}
476
477static __u32 acm_tty_speed[] = {
478 0, 50, 75, 110, 134, 150, 200, 300, 600,
479 1200, 1800, 2400, 4800, 9600, 19200, 38400,
480 57600, 115200, 230400, 460800, 500000, 576000,
481 921600, 1000000, 1152000, 1500000, 2000000,
482 2500000, 3000000, 3500000, 4000000
483};
484
485static __u8 acm_tty_size[] = {
486 5, 6, 7, 8
487};
488
489static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
490{
491 struct acm *acm = tty->driver_data;
492 struct termios *termios = tty->termios;
493 struct usb_cdc_line_coding newline;
494 int newctrl = acm->ctrlout;
495
496 if (!ACM_READY(acm))
497 return;
498
499 newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
500 (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
501 newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
502 newline.bParityType = termios->c_cflag & PARENB ?
503 (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
504 newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
505
506 acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
507
508 if (!newline.dwDTERate) {
509 newline.dwDTERate = acm->line.dwDTERate;
510 newctrl &= ~ACM_CTRL_DTR;
511 } else newctrl |= ACM_CTRL_DTR;
512
513 if (newctrl != acm->ctrlout)
514 acm_set_control(acm, acm->ctrlout = newctrl);
515
516 if (memcmp(&acm->line, &newline, sizeof newline)) {
517 memcpy(&acm->line, &newline, sizeof newline);
518 dbg("set line: %d %d %d %d", le32_to_cpu(newline.dwDTERate),
519 newline.bCharFormat, newline.bParityType,
520 newline.bDataBits);
521 acm_set_line(acm, &acm->line);
522 }
523}
524
525/*
526 * USB probe and disconnect routines.
527 */
528
529static int acm_probe (struct usb_interface *intf,
530 const struct usb_device_id *id)
531{
532 struct usb_cdc_union_desc *union_header = NULL;
533 char *buffer = intf->altsetting->extra;
534 int buflen = intf->altsetting->extralen;
535 struct usb_interface *control_interface;
536 struct usb_interface *data_interface;
537 struct usb_endpoint_descriptor *epctrl;
538 struct usb_endpoint_descriptor *epread;
539 struct usb_endpoint_descriptor *epwrite;
540 struct usb_device *usb_dev = interface_to_usbdev(intf);
541 struct acm *acm;
542 int minor;
543 int ctrlsize,readsize;
544 u8 *buf;
545 u8 ac_management_function = 0;
546 u8 call_management_function = 0;
547 int call_interface_num = -1;
548 int data_interface_num;
549 unsigned long quirks;
550
551 /* handle quirks deadly to normal probing*/
552 quirks = (unsigned long)id->driver_info;
553 if (quirks == NO_UNION_NORMAL) {
554 data_interface = usb_ifnum_to_if(usb_dev, 1);
555 control_interface = usb_ifnum_to_if(usb_dev, 0);
556 goto skip_normal_probe;
557 }
558
559 /* normal probing*/
560 if (!buffer) {
561 err("Wierd descriptor references\n");
562 return -EINVAL;
563 }
564
565 if (!buflen) {
566 if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
567 dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
568 buflen = intf->cur_altsetting->endpoint->extralen;
569 buffer = intf->cur_altsetting->endpoint->extra;
570 } else {
571 err("Zero length descriptor references\n");
572 return -EINVAL;
573 }
574 }
575
576 while (buflen > 0) {
577 if (buffer [1] != USB_DT_CS_INTERFACE) {
578 err("skipping garbage\n");
579 goto next_desc;
580 }
581
582 switch (buffer [2]) {
583 case USB_CDC_UNION_TYPE: /* we've found it */
584 if (union_header) {
585 err("More than one union descriptor, skipping ...");
586 goto next_desc;
587 }
588 union_header = (struct usb_cdc_union_desc *)
589 buffer;
590 break;
591 case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
592 break; /* for now we ignore it */
593 case USB_CDC_HEADER_TYPE: /* maybe check version */
594 break; /* for now we ignore it */
595 case USB_CDC_ACM_TYPE:
596 ac_management_function = buffer[3];
597 break;
598 case USB_CDC_CALL_MANAGEMENT_TYPE:
599 call_management_function = buffer[3];
600 call_interface_num = buffer[4];
601 if ((call_management_function & 3) != 3)
602 err("This device cannot do calls on its own. It is no modem.");
603 break;
604
605 default:
606 err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
607 break;
608 }
609next_desc:
610 buflen -= buffer[0];
611 buffer += buffer[0];
612 }
613
614 if (!union_header) {
615 if (call_interface_num > 0) {
616 dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
617 data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
618 control_interface = intf;
619 } else {
620 dev_dbg(&intf->dev,"No union descriptor, giving up\n");
621 return -ENODEV;
622 }
623 } else {
624 control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
625 data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
626 if (!control_interface || !data_interface) {
627 dev_dbg(&intf->dev,"no interfaces\n");
628 return -ENODEV;
629 }
630 }
631
632 if (data_interface_num != call_interface_num)
633 dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
634
635skip_normal_probe:
636
637 /*workaround for switched interfaces */
638 if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
639 if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
640 struct usb_interface *t;
641 dev_dbg(&intf->dev,"Your device has switched interfaces.\n");
642
643 t = control_interface;
644 control_interface = data_interface;
645 data_interface = t;
646 } else {
647 return -EINVAL;
648 }
649 }
650
651 if (usb_interface_claimed(data_interface)) { /* valid in this context */
652 dev_dbg(&intf->dev,"The data interface isn't available\n");
653 return -EBUSY;
654 }
655
656
657 if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
658 return -EINVAL;
659
660 epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
661 epread = &data_interface->cur_altsetting->endpoint[0].desc;
662 epwrite = &data_interface->cur_altsetting->endpoint[1].desc;
663
664
665 /* workaround for switched endpoints */
666 if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
667 /* descriptors are swapped */
668 struct usb_endpoint_descriptor *t;
669 dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
670
671 t = epread;
672 epread = epwrite;
673 epwrite = t;
674 }
675 dbg("interfaces are valid");
676 for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
677
678 if (minor == ACM_TTY_MINORS) {
679 err("no more free acm devices");
680 return -ENODEV;
681 }
682
683 if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
684 dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
685 goto alloc_fail;
686 }
687 memset(acm, 0, sizeof(struct acm));
688
689 ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
690 readsize = le16_to_cpu(epread->wMaxPacketSize);
691 acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
692 acm->control = control_interface;
693 acm->data = data_interface;
694 acm->minor = minor;
695 acm->dev = usb_dev;
696 acm->ctrl_caps = ac_management_function;
697 acm->ctrlsize = ctrlsize;
698 acm->readsize = readsize;
699 acm->bh.func = acm_rx_tasklet;
700 acm->bh.data = (unsigned long) acm;
701 INIT_WORK(&acm->work, acm_softint, acm);
702 spin_lock_init(&acm->throttle_lock);
703 acm->ready_for_write = 1;
704
705 buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
706 if (!buf) {
707 dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
708 goto alloc_fail2;
709 }
710 acm->ctrl_buffer = buf;
711
712 buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
713 if (!buf) {
714 dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
715 goto alloc_fail3;
716 }
717 acm->read_buffer = buf;
718
719 buf = usb_buffer_alloc(usb_dev, acm->writesize, GFP_KERNEL, &acm->write_dma);
720 if (!buf) {
721 dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
722 goto alloc_fail4;
723 }
724 acm->write_buffer = buf;
725
726 acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
727 if (!acm->ctrlurb) {
728 dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
729 goto alloc_fail5;
730 }
731 acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
732 if (!acm->readurb) {
733 dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
734 goto alloc_fail6;
735 }
736 acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
737 if (!acm->writeurb) {
738 dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
739 goto alloc_fail7;
740 }
741
742 usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
743 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
744 acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
745 acm->ctrlurb->transfer_dma = acm->ctrl_dma;
746
747 usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
748 acm->read_buffer, readsize, acm_read_bulk, acm);
749 acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
750 acm->readurb->transfer_dma = acm->read_dma;
751
752 usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
753 acm->write_buffer, acm->writesize, acm_write_bulk, acm);
754 acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
755 acm->writeurb->transfer_dma = acm->write_dma;
756
757 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
758
759 acm_set_control(acm, acm->ctrlout);
760
761 acm->line.dwDTERate = cpu_to_le32(9600);
762 acm->line.bDataBits = 8;
763 acm_set_line(acm, &acm->line);
764
765 usb_driver_claim_interface(&acm_driver, data_interface, acm);
766
767 tty_register_device(acm_tty_driver, minor, &intf->dev);
768
769 acm_table[minor] = acm;
770 usb_set_intfdata (intf, acm);
771 return 0;
772
773alloc_fail7:
774 usb_free_urb(acm->readurb);
775alloc_fail6:
776 usb_free_urb(acm->ctrlurb);
777alloc_fail5:
778 usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);
779alloc_fail4:
780 usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
781alloc_fail3:
782 usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
783alloc_fail2:
784 kfree(acm);
785alloc_fail:
786 return -ENOMEM;
787}
788
789static void acm_disconnect(struct usb_interface *intf)
790{
791 struct acm *acm = usb_get_intfdata (intf);
792 struct usb_device *usb_dev = interface_to_usbdev(intf);
793
794 if (!acm || !acm->dev) {
795 dbg("disconnect on nonexisting interface");
796 return;
797 }
798
799 down(&open_sem);
800 acm->dev = NULL;
801 usb_set_intfdata (intf, NULL);
802
803 usb_kill_urb(acm->ctrlurb);
804 usb_kill_urb(acm->readurb);
805 usb_kill_urb(acm->writeurb);
806
807 flush_scheduled_work(); /* wait for acm_softint */
808
809 usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma);
810 usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
811 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
812
813 usb_driver_release_interface(&acm_driver, acm->data);
814
815 if (!acm->used) {
816 tty_unregister_device(acm_tty_driver, acm->minor);
817 acm_table[acm->minor] = NULL;
818 usb_free_urb(acm->ctrlurb);
819 usb_free_urb(acm->readurb);
820 usb_free_urb(acm->writeurb);
821 kfree(acm);
822 up(&open_sem);
823 return;
824 }
825
826 up(&open_sem);
827
828 if (acm->tty)
829 tty_hangup(acm->tty);
830}
831
832/*
833 * USB driver structure.
834 */
835
836static struct usb_device_id acm_ids[] = {
837 /* quirky and broken devices */
838 { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
839 .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
840 },
841 /* control interfaces with various AT-command sets */
842 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
843 USB_CDC_ACM_PROTO_AT_V25TER) },
844 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
845 USB_CDC_ACM_PROTO_AT_PCCA101) },
846 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
847 USB_CDC_ACM_PROTO_AT_PCCA101_WAKE) },
848 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
849 USB_CDC_ACM_PROTO_AT_GSM) },
850 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
851 USB_CDC_ACM_PROTO_AT_3G ) },
852 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
853 USB_CDC_ACM_PROTO_AT_CDMA) },
854
855 /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */
856 { }
857};
858
859MODULE_DEVICE_TABLE (usb, acm_ids);
860
861static struct usb_driver acm_driver = {
862 .owner = THIS_MODULE,
863 .name = "cdc_acm",
864 .probe = acm_probe,
865 .disconnect = acm_disconnect,
866 .id_table = acm_ids,
867};
868
869/*
870 * TTY driver structures.
871 */
872
873static struct tty_operations acm_ops = {
874 .open = acm_tty_open,
875 .close = acm_tty_close,
876 .write = acm_tty_write,
877 .write_room = acm_tty_write_room,
878 .ioctl = acm_tty_ioctl,
879 .throttle = acm_tty_throttle,
880 .unthrottle = acm_tty_unthrottle,
881 .chars_in_buffer = acm_tty_chars_in_buffer,
882 .break_ctl = acm_tty_break_ctl,
883 .set_termios = acm_tty_set_termios,
884 .tiocmget = acm_tty_tiocmget,
885 .tiocmset = acm_tty_tiocmset,
886};
887
888/*
889 * Init / exit.
890 */
891
892static int __init acm_init(void)
893{
894 int retval;
895 acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS);
896 if (!acm_tty_driver)
897 return -ENOMEM;
898 acm_tty_driver->owner = THIS_MODULE,
899 acm_tty_driver->driver_name = "acm",
900 acm_tty_driver->name = "ttyACM",
901 acm_tty_driver->devfs_name = "usb/acm/",
902 acm_tty_driver->major = ACM_TTY_MAJOR,
903 acm_tty_driver->minor_start = 0,
904 acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
905 acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
906 acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
907 acm_tty_driver->init_termios = tty_std_termios;
908 acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
909 tty_set_operations(acm_tty_driver, &acm_ops);
910
911 retval = tty_register_driver(acm_tty_driver);
912 if (retval) {
913 put_tty_driver(acm_tty_driver);
914 return retval;
915 }
916
917 retval = usb_register(&acm_driver);
918 if (retval) {
919 tty_unregister_driver(acm_tty_driver);
920 put_tty_driver(acm_tty_driver);
921 return retval;
922 }
923
924 info(DRIVER_VERSION ":" DRIVER_DESC);
925
926 return 0;
927}
928
929static void __exit acm_exit(void)
930{
931 usb_deregister(&acm_driver);
932 tty_unregister_driver(acm_tty_driver);
933 put_tty_driver(acm_tty_driver);
934}
935
936module_init(acm_init);
937module_exit(acm_exit);
938
939MODULE_AUTHOR( DRIVER_AUTHOR );
940MODULE_DESCRIPTION( DRIVER_DESC );
941MODULE_LICENSE("GPL");
942