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 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 #include <linux/usb.h> 56 * CMSPAR, some architectures can't have space and mark parity. 64 * Major and minor numbers. 67 #define ACM_TTY_MAJOR 166 68 #define ACM_TTY_MINORS 32 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 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. 123 }__attribute__((packed
)); 126 * Internal driver structures. 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); 178 if(!ACM_READY(acm
))return; 181 dbg("nonzero ctrl irq status received: %d", urb
->status
); 185 switch(dr
->request
) { 187 case ACM_IRQ_NETWORK
: 189 dbg("%s network", data
[0] ?"connected to":"disconnected from"); 192 case ACM_IRQ_LINE_STATE
: 194 newctrl
=le16_to_cpup((__u16
*) data
); 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
); 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
?'+':'-'); 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]); 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
; 228 if(!ACM_READY(acm
))return; 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
); 240 memmove(data
, data
+ i
, urb
->actual_length
- i
); 241 urb
->actual_length
-= i
; 245 urb
->actual_length
=0; 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; 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
); 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
; 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
); 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; 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
); 321 tty_unregister_devfs(&acm_tty_driver
, acm
->minor
); 322 acm_table
[acm
->minor
] = NULL
; 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; 337 count
= (count
> acm
->writesize
) ? acm
->writesize
: count
; 340 copy_from_user(acm
->writeurb
.transfer_buffer
, buf
, count
); 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"); 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; 374 static voidacm_tty_unthrottle(struct tty_struct
*tty
) 376 struct acm
*acm
= tty
->driver_data
; 377 if(!ACM_READY(acm
))return; 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
; 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
); 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); 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
); 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
[] = { 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
; 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
) 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
; 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)) 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) 513 if(ifcom
->bInterfaceClass
!=2|| ifcom
->bInterfaceSubClass
!=2|| 514 ifcom
->bInterfaceProtocol
!=1|| ifcom
->bNumEndpoints
!=1) 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) 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"); 539 if(!(acm
=kmalloc(sizeof(struct acm
), GFP_KERNEL
))) { 540 err("out of memory"); 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
; 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"); 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
; 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"); 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); 611 tty_unregister_devfs(&acm_tty_driver
, acm
->minor
); 612 acm_table
[acm
->minor
] = NULL
; 618 tty_hangup(acm
->tty
); 622 * USB driver structure. 625 static struct usb_driver acm_driver
= { 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
, 645 major
: ACM_TTY_MAJOR
, 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
, 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
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
)) 682 if(usb_register(&acm_driver
) <0) { 683 tty_unregister_driver(&acm_tty_driver
); 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");