Linux 2.4.0-test10pre1
[davej-history.git] / drivers / usb / acm.c
blob24ca4858d3ed3a64997b33b0f45e98e26f2be706
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>
52 #undef DEBUG
53 #include <linux/usb.h>
56 * CMSPAR, some architectures can't have space and mark parity.
59 #ifndef CMSPAR
60 #define CMSPAR 0
61 #endif
64 * Major and minor numbers.
67 #define ACM_TTY_MAJOR 166
68 #define ACM_TTY_MINORS 32
71 * Requests.
74 #define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
76 #define ACM_REQ_COMMAND 0x00
77 #define ACM_REQ_RESPONSE 0x01
78 #define ACM_REQ_SET_FEATURE 0x02
79 #define ACM_REQ_GET_FEATURE 0x03
80 #define ACM_REQ_CLEAR_FEATURE 0x04
82 #define ACM_REQ_SET_LINE 0x20
83 #define ACM_REQ_GET_LINE 0x21
84 #define ACM_REQ_SET_CONTROL 0x22
85 #define ACM_REQ_SEND_BREAK 0x23
88 * IRQs.
91 #define ACM_IRQ_NETWORK 0x00
92 #define ACM_IRQ_LINE_STATE 0x20
95 * Output control lines.
98 #define ACM_CTRL_DTR 0x01
99 #define ACM_CTRL_RTS 0x02
102 * Input control lines and line errors.
105 #define ACM_CTRL_DCD 0x01
106 #define ACM_CTRL_DSR 0x02
107 #define ACM_CTRL_BRK 0x04
108 #define ACM_CTRL_RI 0x08
110 #define ACM_CTRL_FRAMING 0x10
111 #define ACM_CTRL_PARITY 0x20
112 #define ACM_CTRL_OVERRUN 0x40
115 * Line speed and caracter encoding.
118 struct acm_line {
119 __u32 speed;
120 __u8 stopbits;
121 __u8 parity;
122 __u8 databits;
123 }__attribute__((packed));
126 * Internal driver structures.
129 struct acm {
130 struct usb_device *dev;/* the coresponding usb device */
131 struct usb_interface *iface;/* the interfaces - +0 control +1 data */
132 struct tty_struct *tty;/* the coresponding tty */
133 struct urb ctrlurb, readurb, writeurb;/* urbs */
134 struct acm_line line;/* line coding (bits, stop, parity) */
135 struct tq_struct tqueue;/* task queue for line discipline waking up */
136 unsigned int ctrlin;/* input control lines (DCD, DSR, RI, break, overruns) */
137 unsigned int ctrlout;/* output control lines (DTR, RTS) */
138 unsigned int writesize;/* max packet size for the output bulk endpoint */
139 unsigned int used;/* someone has this acm's device open */
140 unsigned int minor;/* acm minor number */
141 unsigned char throttle;/* throttled by tty layer */
142 unsigned char clocal;/* termios CLOCAL */
145 static struct usb_driver acm_driver;
146 static struct tty_driver acm_tty_driver;
147 static struct acm *acm_table[ACM_TTY_MINORS] = { NULL,/* .... */};
149 #define ACM_READY(acm) (acm && acm->dev && acm->used)
152 * Functions for ACM control messages.
155 static intacm_ctrl_msg(struct acm *acm,int request,int value,void*buf,int len)
157 int retval =usb_control_msg(acm->dev,usb_sndctrlpipe(acm->dev,0),
158 request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ *5);
159 dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
160 return retval <0? retval :0;
163 #define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
164 #define acm_set_line(acm, line) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
165 #define acm_send_break(acm, ms) acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
168 * Interrupt handler for various ACM control events
171 static voidacm_ctrl_irq(struct urb *urb)
173 struct acm *acm = urb->context;
174 devrequest *dr = urb->transfer_buffer;
175 unsigned char*data = (unsigned char*)(dr +1);
176 int newctrl;
178 if(!ACM_READY(acm))return;
180 if(urb->status <0) {
181 dbg("nonzero ctrl irq status received: %d", urb->status);
182 return;
185 switch(dr->request) {
187 case ACM_IRQ_NETWORK:
189 dbg("%s network", data[0] ?"connected to":"disconnected from");
190 return;
192 case ACM_IRQ_LINE_STATE:
194 newctrl =le16_to_cpup((__u16 *) data);
196 #if 0
197 /* Please someone tell me how to do this properly to kill pppd and not kill minicom */
198 if(acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
199 dbg("calling hangup");
200 tty_hangup(acm->tty);
202 #endif
204 acm->ctrlin = newctrl;
206 dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
207 acm->ctrlin & ACM_CTRL_DCD ?'+':'-', acm->ctrlin & ACM_CTRL_DSR ?'+':'-',
208 acm->ctrlin & ACM_CTRL_BRK ?'+':'-', acm->ctrlin & ACM_CTRL_RI ?'+':'-',
209 acm->ctrlin & ACM_CTRL_FRAMING ?'+':'-', acm->ctrlin & ACM_CTRL_PARITY ?'+':'-',
210 acm->ctrlin & ACM_CTRL_OVERRUN ?'+':'-');
212 return;
214 default:
215 dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
216 dr->request, dr->index, dr->length, data[0], data[1]);
217 return;
221 static voidacm_read_bulk(struct urb *urb)
223 struct acm *acm = urb->context;
224 struct tty_struct *tty = acm->tty;
225 unsigned char*data = urb->transfer_buffer;
226 int i =0;
228 if(!ACM_READY(acm))return;
230 if(urb->status)
231 dbg("nonzero read bulk status received: %d", urb->status);
233 if(!urb->status & !acm->throttle) {
234 for(i =0; i < urb->actual_length && !acm->throttle; i++)
235 tty_insert_flip_char(tty, data[i],0);
236 tty_flip_buffer_push(tty);
239 if(acm->throttle) {
240 memmove(data, data + i, urb->actual_length - i);
241 urb->actual_length -= i;
242 return;
245 urb->actual_length =0;
246 urb->dev = acm->dev;
248 if(usb_submit_urb(urb))
249 dbg("failed resubmitting read urb");
252 static voidacm_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_immediate);
262 mark_bh(IMMEDIATE_BH);
265 static voidacm_softint(void*private)
267 struct acm *acm =private;
268 struct tty_struct *tty = acm->tty;
270 if(!ACM_READY(acm))return;
272 if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
273 (tty->ldisc.write_wakeup)(tty);
275 wake_up_interruptible(&tty->write_wait);
279 * TTY handlers
282 static intacm_tty_open(struct tty_struct *tty,struct file *filp)
284 struct acm *acm = acm_table[MINOR(tty->device)];
286 if(!acm || !acm->dev)return-EINVAL;
288 tty->driver_data = acm;
289 acm->tty = tty;
291 MOD_INC_USE_COUNT;
293 if(acm->used++)return0;
295 acm->ctrlurb.dev = acm->dev;
296 if(usb_submit_urb(&acm->ctrlurb))
297 dbg("usb_submit_urb(ctrl irq) failed");
299 acm->readurb.dev = acm->dev;
300 if(usb_submit_urb(&acm->readurb))
301 dbg("usb_submit_urb(read bulk) failed");
303 acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
305 return0;
308 static voidacm_tty_close(struct tty_struct *tty,struct file *filp)
310 struct acm *acm = tty->driver_data;
312 if(!acm || !acm->used)return;
314 if(!--acm->used) {
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 }else{
321 tty_unregister_devfs(&acm_tty_driver, acm->minor);
322 acm_table[acm->minor] = NULL;
323 kfree(acm);
326 MOD_DEC_USE_COUNT;
329 static intacm_tty_write(struct tty_struct *tty,int from_user,const unsigned char*buf,int count)
331 struct acm *acm = tty->driver_data;
333 if(!ACM_READY(acm))return-EINVAL;
334 if(acm->writeurb.status == -EINPROGRESS)return0;
335 if(!count)return0;
337 count = (count > acm->writesize) ? acm->writesize : count;
339 if(from_user)
340 copy_from_user(acm->writeurb.transfer_buffer, buf, count);
341 else
342 memcpy(acm->writeurb.transfer_buffer, buf, count);
344 acm->writeurb.transfer_buffer_length = count;
345 acm->writeurb.dev = acm->dev;
347 if(usb_submit_urb(&acm->writeurb))
348 dbg("usb_submit_urb(write bulk) failed");
350 return count;
353 static intacm_tty_write_room(struct tty_struct *tty)
355 struct acm *acm = tty->driver_data;
356 if(!ACM_READY(acm))return-EINVAL;
357 return acm->writeurb.status == -EINPROGRESS ?0: acm->writesize;
360 static intacm_tty_chars_in_buffer(struct tty_struct *tty)
362 struct acm *acm = tty->driver_data;
363 if(!ACM_READY(acm))return-EINVAL;
364 return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length :0;
367 static voidacm_tty_throttle(struct tty_struct *tty)
369 struct acm *acm = tty->driver_data;
370 if(!ACM_READY(acm))return;
371 acm->throttle =1;
374 static voidacm_tty_unthrottle(struct tty_struct *tty)
376 struct acm *acm = tty->driver_data;
377 if(!ACM_READY(acm))return;
378 acm->throttle =0;
379 if(acm->readurb.status != -EINPROGRESS)
380 acm_read_bulk(&acm->readurb);
383 static voidacm_tty_break_ctl(struct tty_struct *tty,int state)
385 struct acm *acm = tty->driver_data;
386 if(!ACM_READY(acm))return;
387 if(acm_send_break(acm, state ?0xffff:0))
388 dbg("send break failed");
391 static intacm_tty_ioctl(struct tty_struct *tty,struct file *file,unsigned int cmd,unsigned long arg)
393 struct acm *acm = tty->driver_data;
394 unsigned int retval, mask, newctrl;
396 if(!ACM_READY(acm))return-EINVAL;
398 switch(cmd) {
400 case TIOCMGET:
402 returnput_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR :0) |
403 (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS :0) |
404 (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR :0) |
405 (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI :0) |
406 (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD :0) |
407 TIOCM_CTS, (unsigned long*) arg);
409 case TIOCMSET:
410 case TIOCMBIS:
411 case TIOCMBIC:
413 if((retval =get_user(mask, (unsigned long*) arg)))return retval;
415 newctrl = acm->ctrlout;
416 mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR :0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS :0);
418 switch(cmd) {
419 case TIOCMSET: newctrl = mask;break;
420 case TIOCMBIS: newctrl |= mask;break;
421 case TIOCMBIC: newctrl &= ~mask;break;
424 if(acm->ctrlout == newctrl)return0;
425 returnacm_set_control(acm, acm->ctrlout = newctrl);
428 return-ENOIOCTLCMD;
431 static __u32 acm_tty_speed[] = {
432 0,50,75,110,134,150,200,300,600,
433 1200,1800,2400,4800,9600,19200,38400,
434 57600,115200,230400,460800,500000,576000,
435 921600,1000000,1152000,1500000,2000000,
436 2500000,3000000,3500000,4000000
439 static __u8 acm_tty_size[] = {
440 5,6,7,8
443 static voidacm_tty_set_termios(struct tty_struct *tty,struct termios *termios_old)
445 struct acm *acm = tty->driver_data;
446 struct termios *termios = tty->termios;
447 struct acm_line newline;
448 int newctrl = acm->ctrlout;
450 if(!ACM_READY(acm))return;
452 newline.speed =cpu_to_le32p(acm_tty_speed +
453 (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ?15:0));
454 newline.stopbits = termios->c_cflag & CSTOPB ?2:0;
455 newline.parity = termios->c_cflag & PARENB ?
456 (termios->c_cflag & PARODD ?1:2) + (termios->c_cflag & CMSPAR ?2:0) :0;
457 newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >>4];
459 acm->clocal = termios->c_cflag & CLOCAL;
461 if(!newline.speed) {
462 newline.speed = acm->line.speed;
463 newctrl &= ~ACM_CTRL_DTR;
464 }else newctrl |= ACM_CTRL_DTR;
466 if(newctrl != acm->ctrlout)
467 acm_set_control(acm, acm->ctrlout = newctrl);
469 if(memcmp(&acm->line, &newline,sizeof(struct acm_line))) {
470 memcpy(&acm->line, &newline,sizeof(struct acm_line));
471 dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
472 acm_set_line(acm, &acm->line);
477 * USB probe and disconnect routines.
480 static void*acm_probe(struct usb_device *dev,unsigned int ifnum)
482 struct acm *acm;
483 struct usb_config_descriptor *cfacm;
484 struct usb_interface_descriptor *ifcom, *ifdata;
485 struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
486 int readsize, ctrlsize, minor, i;
487 unsigned char*buf;
489 if(dev->descriptor.bDeviceClass !=2|| dev->descriptor.bDeviceSubClass !=0
490 || dev->descriptor.bDeviceProtocol !=0)return NULL;
492 for(i =0; i < dev->descriptor.bNumConfigurations; i++) {
494 cfacm = dev->config + i;
496 dbg("probing config %d", cfacm->bConfigurationValue);
498 if(cfacm->bNumInterfaces !=2||
499 usb_interface_claimed(cfacm->interface +0) ||
500 usb_interface_claimed(cfacm->interface +1))
501 continue;
503 ifcom = cfacm->interface[0].altsetting +0;
504 ifdata = cfacm->interface[1].altsetting +0;
506 if(ifdata->bInterfaceClass !=10|| ifdata->bNumEndpoints !=2) {
507 ifcom = cfacm->interface[1].altsetting +0;
508 ifdata = cfacm->interface[0].altsetting +0;
509 if(ifdata->bInterfaceClass !=10|| ifdata->bNumEndpoints !=2)
510 continue;
513 if(ifcom->bInterfaceClass !=2|| ifcom->bInterfaceSubClass !=2||
514 ifcom->bInterfaceProtocol !=1|| ifcom->bNumEndpoints !=1)
515 continue;
517 epctrl = ifcom->endpoint +0;
518 epread = ifdata->endpoint +0;
519 epwrite = ifdata->endpoint +1;
521 if((epctrl->bEndpointAddress &0x80) !=0x80|| (epctrl->bmAttributes &3) !=3||
522 (epread->bmAttributes &3) !=2|| (epwrite->bmAttributes &3) !=2||
523 ((epread->bEndpointAddress &0x80) ^ (epwrite->bEndpointAddress &0x80)) !=0x80)
524 continue;
526 if((epread->bEndpointAddress &0x80) !=0x80) {
527 epread = ifdata->endpoint +1;
528 epwrite = ifdata->endpoint +0;
531 usb_set_configuration(dev, cfacm->bConfigurationValue);
533 for(minor =0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
534 if(acm_table[minor]) {
535 err("no more free acm devices");
536 return NULL;
539 if(!(acm =kmalloc(sizeof(struct acm), GFP_KERNEL))) {
540 err("out of memory");
541 return NULL;
543 memset(acm,0,sizeof(struct acm));
545 ctrlsize = epctrl->wMaxPacketSize;
546 readsize = epread->wMaxPacketSize;
547 acm->writesize = epwrite->wMaxPacketSize;
548 acm->iface = cfacm->interface;
549 acm->minor = minor;
550 acm->dev = dev;
552 acm->tqueue.routine = acm_softint;
553 acm->tqueue.data = acm;
555 if(!(buf =kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
556 err("out of memory");
557 kfree(acm);
558 return NULL;
561 FILL_INT_URB(&acm->ctrlurb, dev,usb_rcvintpipe(dev, epctrl->bEndpointAddress),
562 buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
564 FILL_BULK_URB(&acm->readurb, dev,usb_rcvbulkpipe(dev, epread->bEndpointAddress),
565 buf += ctrlsize, readsize, acm_read_bulk, acm);
566 acm->readurb.transfer_flags |= USB_NO_FSBR;
568 FILL_BULK_URB(&acm->writeurb, dev,usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
569 buf += readsize, acm->writesize, acm_write_bulk, acm);
570 acm->writeurb.transfer_flags |= USB_NO_FSBR;
572 printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
574 acm_set_control(acm, acm->ctrlout);
576 acm->line.speed =cpu_to_le32(9600);
577 acm->line.databits =8;
578 acm_set_line(acm, &acm->line);
580 usb_driver_claim_interface(&acm_driver, acm->iface +0, acm);
581 usb_driver_claim_interface(&acm_driver, acm->iface +1, acm);
583 tty_register_devfs(&acm_tty_driver,0, minor);
584 return acm_table[minor] = acm;
587 return NULL;
590 static voidacm_disconnect(struct usb_device *dev,void*ptr)
592 struct acm *acm = ptr;
594 if(!acm || !acm->dev) {
595 dbg("disconnect on nonexisting interface");
596 return;
599 acm->dev = NULL;
601 usb_unlink_urb(&acm->ctrlurb);
602 usb_unlink_urb(&acm->readurb);
603 usb_unlink_urb(&acm->writeurb);
605 kfree(acm->ctrlurb.transfer_buffer);
607 usb_driver_release_interface(&acm_driver, acm->iface +0);
608 usb_driver_release_interface(&acm_driver, acm->iface +1);
610 if(!acm->used) {
611 tty_unregister_devfs(&acm_tty_driver, acm->minor);
612 acm_table[acm->minor] = NULL;
613 kfree(acm);
614 return;
617 if(acm->tty)
618 tty_hangup(acm->tty);
622 * USB driver structure.
625 static struct usb_driver acm_driver = {
626 name:"acm",
627 probe: acm_probe,
628 disconnect: acm_disconnect
632 * TTY driver structures.
635 static int acm_tty_refcount;
637 static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
638 static struct termios *acm_tty_termios[ACM_TTY_MINORS];
639 static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
641 static struct tty_driver acm_tty_driver = {
642 magic: TTY_DRIVER_MAGIC,
643 driver_name:"acm",
644 name:"usb/acm/%d",
645 major: ACM_TTY_MAJOR,
646 minor_start:0,
647 num: ACM_TTY_MINORS,
648 type: TTY_DRIVER_TYPE_SERIAL,
649 subtype: SERIAL_TYPE_NORMAL,
650 flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
652 refcount: &acm_tty_refcount,
654 table: acm_tty_table,
655 termios: acm_tty_termios,
656 termios_locked: acm_tty_termios_locked,
658 open: acm_tty_open,
659 close: acm_tty_close,
660 write: acm_tty_write,
661 write_room: acm_tty_write_room,
662 ioctl: acm_tty_ioctl,
663 throttle: acm_tty_throttle,
664 unthrottle: acm_tty_unthrottle,
665 chars_in_buffer: acm_tty_chars_in_buffer,
666 break_ctl: acm_tty_break_ctl,
667 set_termios: acm_tty_set_termios
671 * Init / exit.
674 static int __init acm_init(void)
676 acm_tty_driver.init_termios = tty_std_termios;
677 acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
679 if(tty_register_driver(&acm_tty_driver))
680 return-1;
682 if(usb_register(&acm_driver) <0) {
683 tty_unregister_driver(&acm_tty_driver);
684 return-1;
687 return0;
690 static void __exit acm_exit(void)
692 usb_deregister(&acm_driver);
693 tty_unregister_driver(&acm_tty_driver);
696 module_init(acm_init);
697 module_exit(acm_exit);
699 MODULE_AUTHOR("Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik");
700 MODULE_DESCRIPTION("USB Abstract Control Model driver for USB modems and ISDN adapters");
close