Import 2.3.50
[davej-history.git] / drivers / usb / acm.c
blobafcd5d1057708769d5808ed23a5a79259cbef177
1 /*
2 * acm.c Version 0.16
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 <jerdfelt@valinux.com>
7 * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
9 * USB Abstract Control Model driver for USB modems and ISDN adapters
11 * Sponsored by SuSE
13 * ChangeLog:
14 * v0.9 - thorough cleaning, URBification, almost a rewrite
15 * v0.10 - some more cleanups
16 * v0.11 - fixed flow control, read error doesn't stop reads
17 * v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
18 * v0.13 - added termios, added hangup
19 * v0.14 - sized down struct acm
20 * v0.15 - fixed flow control again - characters could be lost
21 * v0.16 - added code for modems with swapped data and control interfaces
25 * This program is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 #include <linux/signal.h>
43 #include <linux/errno.h>
44 #include <linux/poll.h>
45 #include <linux/init.h>
46 #include <linux/malloc.h>
47 #include <linux/fcntl.h>
48 #include <linux/tty_driver.h>
49 #include <linux/tty_flip.h>
50 #include <linux/tty.h>
51 #include <linux/module.h>
53 #define DEBUG
55 #include "usb.h"
58 * CMSPAR, some architectures can't have space and mark parity.
61 #ifndef CMSPAR
62 #define CMSPAR 0
63 #endif
66 * Major and minor numbers.
69 #define ACM_TTY_MAJOR 166
70 #define ACM_TTY_MINORS 32
73 * Requests.
76 #define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
78 #define ACM_REQ_COMMAND 0x00
79 #define ACM_REQ_RESPONSE 0x01
80 #define ACM_REQ_SET_FEATURE 0x02
81 #define ACM_REQ_GET_FEATURE 0x03
82 #define ACM_REQ_CLEAR_FEATURE 0x04
84 #define ACM_REQ_SET_LINE 0x20
85 #define ACM_REQ_GET_LINE 0x21
86 #define ACM_REQ_SET_CONTROL 0x22
87 #define ACM_REQ_SEND_BREAK 0x23
90 * IRQs.
93 #define ACM_IRQ_NETWORK 0x00
94 #define ACM_IRQ_LINE_STATE 0x20
97 * Output control lines.
100 #define ACM_CTRL_DTR 0x01
101 #define ACM_CTRL_RTS 0x02
104 * Input control lines and line errors.
107 #define ACM_CTRL_DCD 0x01
108 #define ACM_CTRL_DSR 0x02
109 #define ACM_CTRL_BRK 0x04
110 #define ACM_CTRL_RI 0x08
112 #define ACM_CTRL_FRAMING 0x10
113 #define ACM_CTRL_PARITY 0x20
114 #define ACM_CTRL_OVERRUN 0x40
117 * Line speed and caracter encoding.
120 struct acm_line {
121 __u32 speed;
122 __u8 stopbits;
123 __u8 parity;
124 __u8 databits;
125 } __attribute__ ((packed));
128 * Internal driver structures.
131 struct acm {
132 struct usb_device *dev; /* the coresponding usb device */
133 struct usb_interface *iface; /* the interfaces - +0 control +1 data */
134 struct tty_struct *tty; /* the coresponding tty */
135 struct urb ctrlurb, readurb, writeurb; /* urbs */
136 struct acm_line line; /* line coding (bits, stop, parity) */
137 struct tq_struct tqueue; /* task queue for line discipline waking up */
138 unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
139 unsigned int ctrlout; /* output control lines (DTR, RTS) */
140 unsigned int writesize; /* max packet size for the output bulk endpoint */
141 unsigned int used; /* someone has this acm's device open */
142 unsigned int minor; /* acm minor number */
143 unsigned char throttle; /* throttled by tty layer */
144 unsigned char clocal; /* termios CLOCAL */
147 static struct usb_driver acm_driver;
148 static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ };
150 #define ACM_READY(acm) (acm && acm->dev && acm->used)
153 * Functions for ACM control messages.
156 static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
158 int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
159 request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
160 dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
161 return retval < 0 ? retval : 0;
164 #define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
165 #define acm_set_line(acm, line) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
166 #define acm_send_break(acm, ms) acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
169 * Interrupt handler for various ACM control events
172 static void acm_ctrl_irq(struct urb *urb)
174 struct acm *acm = urb->context;
175 devrequest *dr = urb->transfer_buffer;
176 unsigned char *data = (unsigned char *)(dr + 1);
177 int newctrl;
179 if (!ACM_READY(acm)) return;
181 if (urb->status < 0) {
182 dbg("nonzero ctrl irq status received: %d", urb->status);
183 return;
186 switch (dr->request) {
188 case ACM_IRQ_NETWORK:
190 dbg("%s network", data[0] ? "connected to" : "disconnected from");
191 return;
193 case ACM_IRQ_LINE_STATE:
195 newctrl = le16_to_cpup((__u16 *) data);
197 #if 0
198 /* Please someone tell me how to do this properly to kill pppd and not kill minicom */
199 if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
200 dbg("calling hangup");
201 tty_hangup(acm->tty);
203 #endif
205 acm->ctrlin = newctrl;
207 dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
208 acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
209 acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
210 acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
211 acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
213 return;
215 default:
216 dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
217 dr->request, dr->index, dr->length, data[0], data[1]);
218 return;
222 static void acm_read_bulk(struct urb *urb)
224 struct acm *acm = urb->context;
225 struct tty_struct *tty = acm->tty;
226 unsigned char *data = urb->transfer_buffer;
227 int i = 0;
229 if (!ACM_READY(acm)) return;
231 if (urb->status)
232 dbg("nonzero read bulk status received: %d", urb->status);
234 if (!urb->status & !acm->throttle) {
235 for (i = 0; i < urb->actual_length && !acm->throttle; i++)
236 tty_insert_flip_char(tty, data[i], 0);
237 tty_flip_buffer_push(tty);
240 if (acm->throttle) {
241 memmove(data, data + i, urb->actual_length - i);
242 urb->actual_length -= i;
243 return;
246 urb->actual_length = 0;
248 if (usb_submit_urb(urb))
249 dbg("failed resubmitting read urb");
252 static void acm_write_bulk(struct urb *urb)
254 struct acm *acm = (struct acm *)urb->context;
256 if (!ACM_READY(acm)) return;
258 if (urb->status)
259 dbg("nonzero write bulk status received: %d", urb->status);
261 queue_task(&acm->tqueue, &tq_scheduler);
264 static void acm_softint(void *private)
266 struct acm *acm = private;
267 struct tty_struct *tty = acm->tty;
269 if (!ACM_READY(acm)) return;
271 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
272 (tty->ldisc.write_wakeup)(tty);
274 wake_up_interruptible(&tty->write_wait);
278 * TTY handlers
281 static int acm_tty_open(struct tty_struct *tty, struct file *filp)
283 struct acm *acm = acm_table[MINOR(tty->device)];
285 if (!acm || !acm->dev) return -EINVAL;
287 tty->driver_data = acm;
288 acm->tty = tty;
290 MOD_INC_USE_COUNT;
292 if (acm->used++) return 0;
294 if (usb_submit_urb(&acm->ctrlurb))
295 dbg("usb_submit_urb(ctrl irq) failed");
297 if (usb_submit_urb(&acm->readurb))
298 dbg("usb_submit_urb(read bulk) failed");
300 acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
302 return 0;
305 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
307 struct acm *acm = tty->driver_data;
309 if (!acm || !acm->used) return;
311 MOD_DEC_USE_COUNT;
313 if (--acm->used) return;
315 if (acm->dev) {
316 acm_set_control(acm, acm->ctrlout = 0);
317 usb_unlink_urb(&acm->ctrlurb);
318 usb_unlink_urb(&acm->writeurb);
319 usb_unlink_urb(&acm->readurb);
320 return;
323 acm_table[acm->minor] = NULL;
324 kfree(acm);
327 static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
329 struct acm *acm = tty->driver_data;
331 if (!ACM_READY(acm)) return -EINVAL;
332 if (acm->writeurb.status == -EINPROGRESS) return 0;
334 count = (count > acm->writesize) ? acm->writesize : count;
336 if (from_user)
337 copy_from_user(acm->writeurb.transfer_buffer, buf, count);
338 else
339 memcpy(acm->writeurb.transfer_buffer, buf, count);
341 acm->writeurb.transfer_buffer_length = count;
343 if (usb_submit_urb(&acm->writeurb))
344 dbg("usb_submit_urb(write bulk) failed");
346 return count;
349 static int acm_tty_write_room(struct tty_struct *tty)
351 struct acm *acm = tty->driver_data;
352 if (!ACM_READY(acm)) return -EINVAL;
353 return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize;
356 static int acm_tty_chars_in_buffer(struct tty_struct *tty)
358 struct acm *acm = tty->driver_data;
359 if (!ACM_READY(acm)) return -EINVAL;
360 return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length : 0;
363 static void acm_tty_throttle(struct tty_struct *tty)
365 struct acm *acm = tty->driver_data;
366 if (!ACM_READY(acm)) return;
367 acm->throttle = 1;
370 static void acm_tty_unthrottle(struct tty_struct *tty)
372 struct acm *acm = tty->driver_data;
373 if (!ACM_READY(acm)) return;
374 acm->throttle = 0;
375 if (acm->readurb.status != -EINPROGRESS)
376 acm_read_bulk(&acm->readurb);
379 static void acm_tty_break_ctl(struct tty_struct *tty, int state)
381 struct acm *acm = tty->driver_data;
382 if (!ACM_READY(acm)) return;
383 if (acm_send_break(acm, state ? 0xffff : 0))
384 dbg("send break failed");
387 static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
389 struct acm *acm = tty->driver_data;
390 unsigned int retval, mask, newctrl;
392 if (!ACM_READY(acm)) return -EINVAL;
394 switch (cmd) {
396 case TIOCMGET:
398 return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
399 (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
400 (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
401 (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
402 (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
403 TIOCM_CTS, (unsigned long *) arg);
405 case TIOCMSET:
406 case TIOCMBIS:
407 case TIOCMBIC:
409 if ((retval = get_user(mask, (unsigned long *) arg))) return retval;
411 newctrl = acm->ctrlout;
412 mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
414 switch (cmd) {
415 case TIOCMSET: newctrl = mask; break;
416 case TIOCMBIS: newctrl |= mask; break;
417 case TIOCMBIC: newctrl &= ~mask; break;
420 if (acm->ctrlout == newctrl) return 0;
421 return acm_set_control(acm, acm->ctrlout = newctrl);
424 return -ENOIOCTLCMD;
427 static __u32 acm_tty_speed[] = {
428 0, 50, 75, 110, 134, 150, 200, 300, 600,
429 1200, 1800, 2400, 4800, 9600, 19200, 38400,
430 57600, 115200, 230400, 460800, 500000, 576000,
431 921600, 1000000, 1152000, 1500000, 2000000,
432 2500000, 3000000, 3500000, 4000000
435 static __u8 acm_tty_size[] = {
436 5, 6, 7, 8
439 static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
441 struct acm *acm = tty->driver_data;
442 struct termios *termios = tty->termios;
443 struct acm_line newline;
444 int newctrl = acm->ctrlout;
446 if (!ACM_READY(acm)) return;
448 newline.speed = cpu_to_le32p(acm_tty_speed +
449 (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
450 newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
451 newline.parity = termios->c_cflag & PARENB ?
452 (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
453 newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
455 acm->clocal = termios->c_cflag & CLOCAL;
457 if (!newline.speed) {
458 newline.speed = acm->line.speed;
459 newctrl &= ~ACM_CTRL_DTR;
460 } else newctrl |= ACM_CTRL_DTR;
462 if (newctrl != acm->ctrlout)
463 acm_set_control(acm, acm->ctrlout = newctrl);
465 if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
466 memcpy(&acm->line, &newline, sizeof(struct acm_line));
467 dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
468 acm_set_line(acm, &acm->line);
473 * USB probe and disconnect routines.
476 static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
478 struct acm *acm;
479 struct usb_config_descriptor *cfacm;
480 struct usb_interface_descriptor *ifcom, *ifdata;
481 struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
482 int readsize, ctrlsize, minor, i;
483 unsigned char *buf;
485 if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0
486 || dev->descriptor.bDeviceProtocol != 0) return NULL;
488 for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
490 cfacm = dev->config + i;
492 dbg("probing config %d", cfacm->bConfigurationValue);
494 if (cfacm->bNumInterfaces != 2 ||
495 usb_interface_claimed(cfacm->interface + 0) ||
496 usb_interface_claimed(cfacm->interface + 1))
497 continue;
499 ifcom = cfacm->interface[0].altsetting + 0;
500 ifdata = cfacm->interface[1].altsetting + 0;
502 if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2) {
503 ifcom = cfacm->interface[1].altsetting + 0;
504 ifdata = cfacm->interface[0].altsetting + 0;
505 if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2)
506 continue;
509 if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
510 ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1)
511 continue;
513 epctrl = ifcom->endpoint + 0;
514 epread = ifdata->endpoint + 0;
515 epwrite = ifdata->endpoint + 1;
517 if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
518 (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
519 ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
520 continue;
522 if ((epread->bEndpointAddress & 0x80) != 0x80) {
523 epread = ifdata->endpoint + 1;
524 epwrite = ifdata->endpoint + 0;
527 usb_set_configuration(dev, cfacm->bConfigurationValue);
529 for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
530 if (acm_table[minor]) {
531 err("no more free acm devices");
532 return NULL;
535 if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
536 err("out of memory");
537 return NULL;
539 memset(acm, 0, sizeof(struct acm));
541 ctrlsize = epctrl->wMaxPacketSize;
542 readsize = epread->wMaxPacketSize;
543 acm->writesize = epwrite->wMaxPacketSize;
544 acm->iface = cfacm->interface;
545 acm->minor = minor;
546 acm->dev = dev;
548 acm->tqueue.routine = acm_softint;
549 acm->tqueue.data = acm;
551 if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
552 err("out of memory");
553 kfree(acm);
554 return NULL;
557 FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
558 buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
560 FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
561 buf += ctrlsize, readsize, acm_read_bulk, acm);
563 FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
564 buf += readsize, acm->writesize, acm_write_bulk, acm);
566 printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
568 acm_set_control(acm, acm->ctrlout);
570 acm->line.speed = cpu_to_le32(9600);
571 acm->line.databits = 8;
572 acm_set_line(acm, &acm->line);
574 usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
575 usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
577 return acm_table[minor] = acm;
580 return NULL;
583 static void acm_disconnect(struct usb_device *dev, void *ptr)
585 struct acm *acm = ptr;
587 if (!acm || !acm->dev) {
588 dbg("disconnect on nonexisting interface");
589 return;
592 acm->dev = NULL;
594 usb_unlink_urb(&acm->ctrlurb);
595 usb_unlink_urb(&acm->readurb);
596 usb_unlink_urb(&acm->writeurb);
598 kfree(acm->ctrlurb.transfer_buffer);
600 usb_driver_release_interface(&acm_driver, acm->iface + 0);
601 usb_driver_release_interface(&acm_driver, acm->iface + 1);
603 if (!acm->used) {
604 acm_table[acm->minor] = NULL;
605 kfree(acm);
606 return;
609 if (acm->tty)
610 tty_hangup(acm->tty);
614 * USB driver structure.
617 static struct usb_driver acm_driver = {
618 name: "acm",
619 probe: acm_probe,
620 disconnect: acm_disconnect
624 * TTY driver structures.
627 static int acm_tty_refcount;
629 static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
630 static struct termios *acm_tty_termios[ACM_TTY_MINORS];
631 static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
633 static struct tty_driver acm_tty_driver = {
634 magic: TTY_DRIVER_MAGIC,
635 driver_name: "usb",
636 name: "ttyACM",
637 major: ACM_TTY_MAJOR,
638 minor_start: 0,
639 num: ACM_TTY_MINORS,
640 type: TTY_DRIVER_TYPE_SERIAL,
641 subtype: SERIAL_TYPE_NORMAL,
642 flags: TTY_DRIVER_REAL_RAW,
644 refcount: &acm_tty_refcount,
646 table: acm_tty_table,
647 termios: acm_tty_termios,
648 termios_locked: acm_tty_termios_locked,
650 open: acm_tty_open,
651 close: acm_tty_close,
652 write: acm_tty_write,
653 write_room: acm_tty_write_room,
654 ioctl: acm_tty_ioctl,
655 throttle: acm_tty_throttle,
656 unthrottle: acm_tty_unthrottle,
657 chars_in_buffer: acm_tty_chars_in_buffer,
658 break_ctl: acm_tty_break_ctl,
659 set_termios: acm_tty_set_termios
663 * Init / exit.
666 static int __init acm_init(void)
668 acm_tty_driver.init_termios = tty_std_termios;
669 acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
671 if (tty_register_driver(&acm_tty_driver))
672 return -1;
674 if (usb_register(&acm_driver) < 0) {
675 tty_unregister_driver(&acm_tty_driver);
676 return -1;
679 return 0;
682 static void __exit acm_exit(void)
684 usb_deregister(&acm_driver);
685 tty_unregister_driver(&acm_tty_driver);
688 module_init(acm_init);
689 module_exit(acm_exit);