blob: adff5a77e31f4f731c5f337e2f5bb391d7aea6f7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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/*
Oliver Neukum884b6002005-04-21 21:28:02 +0200109 * Write buffer management.
110 * All of these assume proper locks taken by the caller.
111 */
112
113static int acm_wb_alloc(struct acm *acm)
114{
115 int i, wbn;
116 struct acm_wb *wb;
117
118 wbn = acm->write_current;
119 i = 0;
120 for (;;) {
121 wb = &acm->wb[wbn];
122 if (!wb->use) {
123 wb->use = 1;
124 return wbn;
125 }
126 wbn = (wbn + 1) % ACM_NWB;
127 if (++i >= ACM_NWB)
128 return -1;
129 }
130}
131
132static void acm_wb_free(struct acm *acm, int wbn)
133{
134 acm->wb[wbn].use = 0;
135}
136
137static int acm_wb_is_avail(struct acm *acm)
138{
139 int i, n;
140
141 n = 0;
142 for (i = 0; i < ACM_NWB; i++) {
143 if (!acm->wb[i].use)
144 n++;
145 }
146 return n;
147}
148
149static inline int acm_wb_is_used(struct acm *acm, int wbn)
150{
151 return acm->wb[wbn].use;
152}
153
154/*
155 * Finish write.
156 */
157static void acm_write_done(struct acm *acm)
158{
159 unsigned long flags;
160 int wbn;
161
162 spin_lock_irqsave(&acm->write_lock, flags);
163 acm->write_ready = 1;
164 wbn = acm->write_current;
165 acm_wb_free(acm, wbn);
166 acm->write_current = (wbn + 1) % ACM_NWB;
167 spin_unlock_irqrestore(&acm->write_lock, flags);
168}
169
170/*
171 * Poke write.
172 */
173static int acm_write_start(struct acm *acm)
174{
175 unsigned long flags;
176 int wbn;
177 struct acm_wb *wb;
178 int rc;
179
180 spin_lock_irqsave(&acm->write_lock, flags);
181 if (!acm->dev) {
182 spin_unlock_irqrestore(&acm->write_lock, flags);
183 return -ENODEV;
184 }
185
186 if (!acm->write_ready) {
187 spin_unlock_irqrestore(&acm->write_lock, flags);
188 return 0; /* A white lie */
189 }
190
191 wbn = acm->write_current;
192 if (!acm_wb_is_used(acm, wbn)) {
193 spin_unlock_irqrestore(&acm->write_lock, flags);
194 return 0;
195 }
196 wb = &acm->wb[wbn];
197
198 acm->write_ready = 0;
199 spin_unlock_irqrestore(&acm->write_lock, flags);
200
201 acm->writeurb->transfer_buffer = wb->buf;
202 acm->writeurb->transfer_dma = wb->dmah;
203 acm->writeurb->transfer_buffer_length = wb->len;
204 acm->writeurb->dev = acm->dev;
205
206 if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) {
207 dbg("usb_submit_urb(write bulk) failed: %d", rc);
208 acm_write_done(acm);
209 }
210 return rc;
211}
212
213/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 * Interrupt handlers for various ACM device responses
215 */
216
217/* control interface reports status changes with "interrupt" transfers */
218static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
219{
220 struct acm *acm = urb->context;
221 struct usb_cdc_notification *dr = urb->transfer_buffer;
222 unsigned char *data;
223 int newctrl;
224 int status;
225
226 switch (urb->status) {
227 case 0:
228 /* success */
229 break;
230 case -ECONNRESET:
231 case -ENOENT:
232 case -ESHUTDOWN:
233 /* this urb is terminated, clean up */
234 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
235 return;
236 default:
237 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
238 goto exit;
239 }
240
241 if (!ACM_READY(acm))
242 goto exit;
243
244 data = (unsigned char *)(dr + 1);
245 switch (dr->bNotificationType) {
246
247 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
248
249 dbg("%s network", dr->wValue ? "connected to" : "disconnected from");
250 break;
251
252 case USB_CDC_NOTIFY_SERIAL_STATE:
253
254 newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
255
256 if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
257 dbg("calling hangup");
258 tty_hangup(acm->tty);
259 }
260
261 acm->ctrlin = newctrl;
262
263 dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
264 acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
265 acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
266 acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
267 acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
268
269 break;
270
271 default:
272 dbg("unknown notification %d received: index %d len %d data0 %d data1 %d",
273 dr->bNotificationType, dr->wIndex,
274 dr->wLength, data[0], data[1]);
275 break;
276 }
277exit:
278 status = usb_submit_urb (urb, GFP_ATOMIC);
279 if (status)
280 err ("%s - usb_submit_urb failed with result %d",
281 __FUNCTION__, status);
282}
283
284/* data interface returns incoming bytes, or we got unthrottled */
285static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
286{
287 struct acm *acm = urb->context;
288 dbg("Entering acm_read_bulk with status %d\n", urb->status);
289
290 if (!ACM_READY(acm))
291 return;
292
293 if (urb->status)
294 dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
295
296 /* calling tty_flip_buffer_push() in_irq() isn't allowed */
297 tasklet_schedule(&acm->bh);
298}
299
300static void acm_rx_tasklet(unsigned long _acm)
301{
302 struct acm *acm = (void *)_acm;
303 struct urb *urb = acm->readurb;
304 struct tty_struct *tty = acm->tty;
305 unsigned char *data = urb->transfer_buffer;
306 int i = 0;
307 dbg("Entering acm_rx_tasklet");
308
309 if (urb->actual_length > 0 && !acm->throttle) {
310 for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
311 /* if we insert more than TTY_FLIPBUF_SIZE characters,
312 * we drop them. */
313 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
314 tty_flip_buffer_push(tty);
315 }
316 tty_insert_flip_char(tty, data[i], 0);
317 }
318 dbg("Handed %d bytes to tty layer", i+1);
319 tty_flip_buffer_push(tty);
320 }
321
322 spin_lock(&acm->throttle_lock);
323 if (acm->throttle) {
324 dbg("Throtteling noticed");
325 memmove(data, data + i, urb->actual_length - i);
326 urb->actual_length -= i;
327 acm->resubmit_to_unthrottle = 1;
328 spin_unlock(&acm->throttle_lock);
329 return;
330 }
331 spin_unlock(&acm->throttle_lock);
332
333 urb->actual_length = 0;
334 urb->dev = acm->dev;
335
336 i = usb_submit_urb(urb, GFP_ATOMIC);
337 if (i)
338 dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
339}
340
341/* data interface wrote those outgoing bytes */
342static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
343{
344 struct acm *acm = (struct acm *)urb->context;
Oliver Neukum884b6002005-04-21 21:28:02 +0200345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 dbg("Entering acm_write_bulk with status %d\n", urb->status);
347
Oliver Neukum884b6002005-04-21 21:28:02 +0200348 acm_write_done(acm);
349 acm_write_start(acm);
350 if (ACM_READY(acm))
351 schedule_work(&acm->work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352}
353
354static void acm_softint(void *private)
355{
356 struct acm *acm = private;
357 dbg("Entering acm_softint.\n");
358
359 if (!ACM_READY(acm))
360 return;
361 tty_wakeup(acm->tty);
362}
363
364/*
365 * TTY handlers
366 */
367
368static int acm_tty_open(struct tty_struct *tty, struct file *filp)
369{
370 struct acm *acm;
371 int rv = -EINVAL;
372 dbg("Entering acm_tty_open.\n");
373
374 down(&open_sem);
375
376 acm = acm_table[tty->index];
377 if (!acm || !acm->dev)
378 goto err_out;
379 else
380 rv = 0;
381
382 tty->driver_data = acm;
383 acm->tty = tty;
384
385
386
387 if (acm->used++) {
388 goto done;
389 }
390
391 acm->ctrlurb->dev = acm->dev;
392 if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
393 dbg("usb_submit_urb(ctrl irq) failed");
394 goto bail_out;
395 }
396
397 acm->readurb->dev = acm->dev;
398 if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
399 dbg("usb_submit_urb(read bulk) failed");
400 goto bail_out_and_unlink;
401 }
402
403 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
404 goto full_bailout;
405
406 /* force low_latency on so that our tty_push actually forces the data through,
407 otherwise it is scheduled, and with high data rates data can get lost. */
408 tty->low_latency = 1;
409
410done:
411err_out:
412 up(&open_sem);
413 return rv;
414
415full_bailout:
416 usb_kill_urb(acm->readurb);
417bail_out_and_unlink:
418 usb_kill_urb(acm->ctrlurb);
419bail_out:
420 acm->used--;
421 up(&open_sem);
422 return -EIO;
423}
424
brian@murphy.dk83ef3442005-06-29 16:53:29 -0700425static void acm_tty_unregister(struct acm *acm)
426{
427 tty_unregister_device(acm_tty_driver, acm->minor);
428 usb_put_intf(acm->control);
429 acm_table[acm->minor] = NULL;
430 usb_free_urb(acm->ctrlurb);
431 usb_free_urb(acm->readurb);
432 usb_free_urb(acm->writeurb);
433 kfree(acm);
434}
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436static void acm_tty_close(struct tty_struct *tty, struct file *filp)
437{
438 struct acm *acm = tty->driver_data;
439
440 if (!acm || !acm->used)
441 return;
442
443 down(&open_sem);
444 if (!--acm->used) {
445 if (acm->dev) {
446 acm_set_control(acm, acm->ctrlout = 0);
447 usb_kill_urb(acm->ctrlurb);
448 usb_kill_urb(acm->writeurb);
449 usb_kill_urb(acm->readurb);
brian@murphy.dk83ef3442005-06-29 16:53:29 -0700450 } else
451 acm_tty_unregister(acm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 }
453 up(&open_sem);
454}
455
456static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
457{
458 struct acm *acm = tty->driver_data;
459 int stat;
Oliver Neukum884b6002005-04-21 21:28:02 +0200460 unsigned long flags;
461 int wbn;
462 struct acm_wb *wb;
463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 dbg("Entering acm_tty_write to write %d bytes,\n", count);
465
466 if (!ACM_READY(acm))
467 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 if (!count)
469 return 0;
470
Oliver Neukum884b6002005-04-21 21:28:02 +0200471 spin_lock_irqsave(&acm->write_lock, flags);
472 if ((wbn = acm_wb_alloc(acm)) < 0) {
473 spin_unlock_irqrestore(&acm->write_lock, flags);
474 acm_write_start(acm);
475 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
Oliver Neukum884b6002005-04-21 21:28:02 +0200477 wb = &acm->wb[wbn];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Oliver Neukum884b6002005-04-21 21:28:02 +0200479 count = (count > acm->writesize) ? acm->writesize : count;
480 dbg("Get %d bytes...", count);
481 memcpy(wb->buf, buf, count);
482 wb->len = count;
483 spin_unlock_irqrestore(&acm->write_lock, flags);
484
485 if ((stat = acm_write_start(acm)) < 0)
486 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 return count;
488}
489
490static int acm_tty_write_room(struct tty_struct *tty)
491{
492 struct acm *acm = tty->driver_data;
493 if (!ACM_READY(acm))
494 return -EINVAL;
Oliver Neukum884b6002005-04-21 21:28:02 +0200495 /*
496 * Do not let the line discipline to know that we have a reserve,
497 * or it might get too enthusiastic.
498 */
499 return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500}
501
502static int acm_tty_chars_in_buffer(struct tty_struct *tty)
503{
504 struct acm *acm = tty->driver_data;
505 if (!ACM_READY(acm))
506 return -EINVAL;
Oliver Neukum884b6002005-04-21 21:28:02 +0200507 /*
508 * This is inaccurate (overcounts), but it works.
509 */
510 return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511}
512
513static void acm_tty_throttle(struct tty_struct *tty)
514{
515 struct acm *acm = tty->driver_data;
516 if (!ACM_READY(acm))
517 return;
518 spin_lock_bh(&acm->throttle_lock);
519 acm->throttle = 1;
520 spin_unlock_bh(&acm->throttle_lock);
521}
522
523static void acm_tty_unthrottle(struct tty_struct *tty)
524{
525 struct acm *acm = tty->driver_data;
526 if (!ACM_READY(acm))
527 return;
528 spin_lock_bh(&acm->throttle_lock);
529 acm->throttle = 0;
530 spin_unlock_bh(&acm->throttle_lock);
531 if (acm->resubmit_to_unthrottle) {
532 acm->resubmit_to_unthrottle = 0;
533 acm_read_bulk(acm->readurb, NULL);
534 }
535}
536
537static void acm_tty_break_ctl(struct tty_struct *tty, int state)
538{
539 struct acm *acm = tty->driver_data;
540 if (!ACM_READY(acm))
541 return;
542 if (acm_send_break(acm, state ? 0xffff : 0))
543 dbg("send break failed");
544}
545
546static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
547{
548 struct acm *acm = tty->driver_data;
549
550 if (!ACM_READY(acm))
551 return -EINVAL;
552
553 return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
554 (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
555 (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
556 (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
557 (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
558 TIOCM_CTS;
559}
560
561static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
562 unsigned int set, unsigned int clear)
563{
564 struct acm *acm = tty->driver_data;
565 unsigned int newctrl;
566
567 if (!ACM_READY(acm))
568 return -EINVAL;
569
570 newctrl = acm->ctrlout;
571 set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0);
572 clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0);
573
574 newctrl = (newctrl & ~clear) | set;
575
576 if (acm->ctrlout == newctrl)
577 return 0;
578 return acm_set_control(acm, acm->ctrlout = newctrl);
579}
580
581static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
582{
583 struct acm *acm = tty->driver_data;
584
585 if (!ACM_READY(acm))
586 return -EINVAL;
587
588 return -ENOIOCTLCMD;
589}
590
591static __u32 acm_tty_speed[] = {
592 0, 50, 75, 110, 134, 150, 200, 300, 600,
593 1200, 1800, 2400, 4800, 9600, 19200, 38400,
594 57600, 115200, 230400, 460800, 500000, 576000,
595 921600, 1000000, 1152000, 1500000, 2000000,
596 2500000, 3000000, 3500000, 4000000
597};
598
599static __u8 acm_tty_size[] = {
600 5, 6, 7, 8
601};
602
603static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
604{
605 struct acm *acm = tty->driver_data;
606 struct termios *termios = tty->termios;
607 struct usb_cdc_line_coding newline;
608 int newctrl = acm->ctrlout;
609
610 if (!ACM_READY(acm))
611 return;
612
613 newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
614 (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
615 newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
616 newline.bParityType = termios->c_cflag & PARENB ?
617 (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
618 newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
619
620 acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
621
622 if (!newline.dwDTERate) {
623 newline.dwDTERate = acm->line.dwDTERate;
624 newctrl &= ~ACM_CTRL_DTR;
625 } else newctrl |= ACM_CTRL_DTR;
626
627 if (newctrl != acm->ctrlout)
628 acm_set_control(acm, acm->ctrlout = newctrl);
629
630 if (memcmp(&acm->line, &newline, sizeof newline)) {
631 memcpy(&acm->line, &newline, sizeof newline);
632 dbg("set line: %d %d %d %d", le32_to_cpu(newline.dwDTERate),
633 newline.bCharFormat, newline.bParityType,
634 newline.bDataBits);
635 acm_set_line(acm, &acm->line);
636 }
637}
638
639/*
640 * USB probe and disconnect routines.
641 */
642
Oliver Neukum884b6002005-04-21 21:28:02 +0200643/* Little helper: write buffers free */
644static void acm_write_buffers_free(struct acm *acm)
645{
646 int i;
647 struct acm_wb *wb;
648
649 for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {
650 usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
651 }
652}
653
654/* Little helper: write buffers allocate */
655static int acm_write_buffers_alloc(struct acm *acm)
656{
657 int i;
658 struct acm_wb *wb;
659
660 for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {
661 wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
662 &wb->dmah);
663 if (!wb->buf) {
664 while (i != 0) {
665 --i;
666 --wb;
667 usb_buffer_free(acm->dev, acm->writesize,
668 wb->buf, wb->dmah);
669 }
670 return -ENOMEM;
671 }
672 }
673 return 0;
674}
675
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676static int acm_probe (struct usb_interface *intf,
677 const struct usb_device_id *id)
678{
679 struct usb_cdc_union_desc *union_header = NULL;
680 char *buffer = intf->altsetting->extra;
681 int buflen = intf->altsetting->extralen;
682 struct usb_interface *control_interface;
683 struct usb_interface *data_interface;
684 struct usb_endpoint_descriptor *epctrl;
685 struct usb_endpoint_descriptor *epread;
686 struct usb_endpoint_descriptor *epwrite;
687 struct usb_device *usb_dev = interface_to_usbdev(intf);
688 struct acm *acm;
689 int minor;
690 int ctrlsize,readsize;
691 u8 *buf;
692 u8 ac_management_function = 0;
693 u8 call_management_function = 0;
694 int call_interface_num = -1;
695 int data_interface_num;
696 unsigned long quirks;
697
698 /* handle quirks deadly to normal probing*/
699 quirks = (unsigned long)id->driver_info;
700 if (quirks == NO_UNION_NORMAL) {
701 data_interface = usb_ifnum_to_if(usb_dev, 1);
702 control_interface = usb_ifnum_to_if(usb_dev, 0);
703 goto skip_normal_probe;
704 }
705
706 /* normal probing*/
707 if (!buffer) {
708 err("Wierd descriptor references\n");
709 return -EINVAL;
710 }
711
712 if (!buflen) {
713 if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
714 dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
715 buflen = intf->cur_altsetting->endpoint->extralen;
716 buffer = intf->cur_altsetting->endpoint->extra;
717 } else {
718 err("Zero length descriptor references\n");
719 return -EINVAL;
720 }
721 }
722
723 while (buflen > 0) {
724 if (buffer [1] != USB_DT_CS_INTERFACE) {
725 err("skipping garbage\n");
726 goto next_desc;
727 }
728
729 switch (buffer [2]) {
730 case USB_CDC_UNION_TYPE: /* we've found it */
731 if (union_header) {
732 err("More than one union descriptor, skipping ...");
733 goto next_desc;
734 }
735 union_header = (struct usb_cdc_union_desc *)
736 buffer;
737 break;
738 case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
739 break; /* for now we ignore it */
740 case USB_CDC_HEADER_TYPE: /* maybe check version */
741 break; /* for now we ignore it */
742 case USB_CDC_ACM_TYPE:
743 ac_management_function = buffer[3];
744 break;
745 case USB_CDC_CALL_MANAGEMENT_TYPE:
746 call_management_function = buffer[3];
747 call_interface_num = buffer[4];
748 if ((call_management_function & 3) != 3)
749 err("This device cannot do calls on its own. It is no modem.");
750 break;
751
752 default:
753 err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
754 break;
755 }
756next_desc:
757 buflen -= buffer[0];
758 buffer += buffer[0];
759 }
760
761 if (!union_header) {
762 if (call_interface_num > 0) {
763 dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
764 data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
765 control_interface = intf;
766 } else {
767 dev_dbg(&intf->dev,"No union descriptor, giving up\n");
768 return -ENODEV;
769 }
770 } else {
771 control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
772 data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
773 if (!control_interface || !data_interface) {
774 dev_dbg(&intf->dev,"no interfaces\n");
775 return -ENODEV;
776 }
777 }
778
779 if (data_interface_num != call_interface_num)
780 dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
781
782skip_normal_probe:
783
784 /*workaround for switched interfaces */
785 if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
786 if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
787 struct usb_interface *t;
788 dev_dbg(&intf->dev,"Your device has switched interfaces.\n");
789
790 t = control_interface;
791 control_interface = data_interface;
792 data_interface = t;
793 } else {
794 return -EINVAL;
795 }
796 }
797
798 if (usb_interface_claimed(data_interface)) { /* valid in this context */
799 dev_dbg(&intf->dev,"The data interface isn't available\n");
800 return -EBUSY;
801 }
802
803
804 if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
805 return -EINVAL;
806
807 epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
808 epread = &data_interface->cur_altsetting->endpoint[0].desc;
809 epwrite = &data_interface->cur_altsetting->endpoint[1].desc;
810
811
812 /* workaround for switched endpoints */
813 if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
814 /* descriptors are swapped */
815 struct usb_endpoint_descriptor *t;
816 dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
817
818 t = epread;
819 epread = epwrite;
820 epwrite = t;
821 }
822 dbg("interfaces are valid");
823 for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
824
825 if (minor == ACM_TTY_MINORS) {
826 err("no more free acm devices");
827 return -ENODEV;
828 }
829
830 if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
831 dev_dbg(&intf->dev, "out of memory (acm kmalloc)\n");
832 goto alloc_fail;
833 }
834 memset(acm, 0, sizeof(struct acm));
835
836 ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
837 readsize = le16_to_cpu(epread->wMaxPacketSize);
838 acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
839 acm->control = control_interface;
840 acm->data = data_interface;
841 acm->minor = minor;
842 acm->dev = usb_dev;
843 acm->ctrl_caps = ac_management_function;
844 acm->ctrlsize = ctrlsize;
845 acm->readsize = readsize;
846 acm->bh.func = acm_rx_tasklet;
847 acm->bh.data = (unsigned long) acm;
848 INIT_WORK(&acm->work, acm_softint, acm);
849 spin_lock_init(&acm->throttle_lock);
Oliver Neukum884b6002005-04-21 21:28:02 +0200850 spin_lock_init(&acm->write_lock);
851 acm->write_ready = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
853 buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
854 if (!buf) {
855 dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
856 goto alloc_fail2;
857 }
858 acm->ctrl_buffer = buf;
859
860 buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
861 if (!buf) {
862 dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
863 goto alloc_fail3;
864 }
865 acm->read_buffer = buf;
866
Oliver Neukum884b6002005-04-21 21:28:02 +0200867 if (acm_write_buffers_alloc(acm) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
869 goto alloc_fail4;
870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
873 if (!acm->ctrlurb) {
874 dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
875 goto alloc_fail5;
876 }
877 acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
878 if (!acm->readurb) {
879 dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
880 goto alloc_fail6;
881 }
882 acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
883 if (!acm->writeurb) {
884 dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
885 goto alloc_fail7;
886 }
887
888 usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
889 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
890 acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
891 acm->ctrlurb->transfer_dma = acm->ctrl_dma;
892
893 usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
894 acm->read_buffer, readsize, acm_read_bulk, acm);
895 acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
896 acm->readurb->transfer_dma = acm->read_dma;
897
898 usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
Oliver Neukum884b6002005-04-21 21:28:02 +0200899 NULL, acm->writesize, acm_write_bulk, acm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
Oliver Neukum884b6002005-04-21 21:28:02 +0200901 /* acm->writeurb->transfer_dma = 0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
903 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
904
905 acm_set_control(acm, acm->ctrlout);
906
907 acm->line.dwDTERate = cpu_to_le32(9600);
908 acm->line.bDataBits = 8;
909 acm_set_line(acm, &acm->line);
910
911 usb_driver_claim_interface(&acm_driver, data_interface, acm);
912
brian@murphy.dk83ef3442005-06-29 16:53:29 -0700913 usb_get_intf(control_interface);
914 tty_register_device(acm_tty_driver, minor, &control_interface->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
916 acm_table[minor] = acm;
917 usb_set_intfdata (intf, acm);
918 return 0;
919
920alloc_fail7:
921 usb_free_urb(acm->readurb);
922alloc_fail6:
923 usb_free_urb(acm->ctrlurb);
924alloc_fail5:
Oliver Neukum884b6002005-04-21 21:28:02 +0200925 acm_write_buffers_free(acm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926alloc_fail4:
927 usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
928alloc_fail3:
929 usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
930alloc_fail2:
931 kfree(acm);
932alloc_fail:
933 return -ENOMEM;
934}
935
936static void acm_disconnect(struct usb_interface *intf)
937{
938 struct acm *acm = usb_get_intfdata (intf);
939 struct usb_device *usb_dev = interface_to_usbdev(intf);
940
941 if (!acm || !acm->dev) {
942 dbg("disconnect on nonexisting interface");
943 return;
944 }
945
946 down(&open_sem);
947 acm->dev = NULL;
948 usb_set_intfdata (intf, NULL);
949
950 usb_kill_urb(acm->ctrlurb);
951 usb_kill_urb(acm->readurb);
952 usb_kill_urb(acm->writeurb);
953
954 flush_scheduled_work(); /* wait for acm_softint */
955
Oliver Neukum884b6002005-04-21 21:28:02 +0200956 acm_write_buffers_free(acm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
958 usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
959
960 usb_driver_release_interface(&acm_driver, acm->data);
961
962 if (!acm->used) {
brian@murphy.dk83ef3442005-06-29 16:53:29 -0700963 acm_tty_unregister(acm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 up(&open_sem);
965 return;
966 }
967
968 up(&open_sem);
969
970 if (acm->tty)
971 tty_hangup(acm->tty);
972}
973
974/*
975 * USB driver structure.
976 */
977
978static struct usb_device_id acm_ids[] = {
979 /* quirky and broken devices */
980 { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
981 .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
982 },
983 /* control interfaces with various AT-command sets */
984 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
985 USB_CDC_ACM_PROTO_AT_V25TER) },
986 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
987 USB_CDC_ACM_PROTO_AT_PCCA101) },
988 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
989 USB_CDC_ACM_PROTO_AT_PCCA101_WAKE) },
990 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
991 USB_CDC_ACM_PROTO_AT_GSM) },
992 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
993 USB_CDC_ACM_PROTO_AT_3G ) },
994 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
995 USB_CDC_ACM_PROTO_AT_CDMA) },
996
997 /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */
998 { }
999};
1000
1001MODULE_DEVICE_TABLE (usb, acm_ids);
1002
1003static struct usb_driver acm_driver = {
1004 .owner = THIS_MODULE,
1005 .name = "cdc_acm",
1006 .probe = acm_probe,
1007 .disconnect = acm_disconnect,
1008 .id_table = acm_ids,
1009};
1010
1011/*
1012 * TTY driver structures.
1013 */
1014
1015static struct tty_operations acm_ops = {
1016 .open = acm_tty_open,
1017 .close = acm_tty_close,
1018 .write = acm_tty_write,
1019 .write_room = acm_tty_write_room,
1020 .ioctl = acm_tty_ioctl,
1021 .throttle = acm_tty_throttle,
1022 .unthrottle = acm_tty_unthrottle,
1023 .chars_in_buffer = acm_tty_chars_in_buffer,
1024 .break_ctl = acm_tty_break_ctl,
1025 .set_termios = acm_tty_set_termios,
1026 .tiocmget = acm_tty_tiocmget,
1027 .tiocmset = acm_tty_tiocmset,
1028};
1029
1030/*
1031 * Init / exit.
1032 */
1033
1034static int __init acm_init(void)
1035{
1036 int retval;
1037 acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS);
1038 if (!acm_tty_driver)
1039 return -ENOMEM;
1040 acm_tty_driver->owner = THIS_MODULE,
1041 acm_tty_driver->driver_name = "acm",
1042 acm_tty_driver->name = "ttyACM",
1043 acm_tty_driver->devfs_name = "usb/acm/",
1044 acm_tty_driver->major = ACM_TTY_MAJOR,
1045 acm_tty_driver->minor_start = 0,
1046 acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
1047 acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
1048 acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
1049 acm_tty_driver->init_termios = tty_std_termios;
1050 acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1051 tty_set_operations(acm_tty_driver, &acm_ops);
1052
1053 retval = tty_register_driver(acm_tty_driver);
1054 if (retval) {
1055 put_tty_driver(acm_tty_driver);
1056 return retval;
1057 }
1058
1059 retval = usb_register(&acm_driver);
1060 if (retval) {
1061 tty_unregister_driver(acm_tty_driver);
1062 put_tty_driver(acm_tty_driver);
1063 return retval;
1064 }
1065
1066 info(DRIVER_VERSION ":" DRIVER_DESC);
1067
1068 return 0;
1069}
1070
1071static void __exit acm_exit(void)
1072{
1073 usb_deregister(&acm_driver);
1074 tty_unregister_driver(acm_tty_driver);
1075 put_tty_driver(acm_tty_driver);
1076}
1077
1078module_init(acm_init);
1079module_exit(acm_exit);
1080
1081MODULE_AUTHOR( DRIVER_AUTHOR );
1082MODULE_DESCRIPTION( DRIVER_DESC );
1083MODULE_LICENSE("GPL");
1084