1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <linux/kernel.h>
46#include <linux/sched.h>
47#include <linux/signal.h>
48#include <linux/errno.h>
49#include <linux/poll.h>
50#include <linux/init.h>
51#include <linux/slab.h>
52#include <linux/fcntl.h>
53#include <linux/tty.h>
54#include <linux/tty_driver.h>
55#include <linux/tty_flip.h>
56#include <linux/module.h>
57#include <linux/smp_lock.h>
58#undef DEBUG
59#include <linux/usb.h>
60
61
62
63
64#define DRIVER_VERSION "v0.21"
65#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
66#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
67
68
69
70
71
72#ifndef CMSPAR
73#define CMSPAR 0
74#endif
75
76
77
78
79
80#define ACM_TTY_MAJOR 166
81#define ACM_TTY_MINORS 32
82
83
84
85
86
87#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
88
89#define ACM_REQ_COMMAND 0x00
90#define ACM_REQ_RESPONSE 0x01
91#define ACM_REQ_SET_FEATURE 0x02
92#define ACM_REQ_GET_FEATURE 0x03
93#define ACM_REQ_CLEAR_FEATURE 0x04
94
95#define ACM_REQ_SET_LINE 0x20
96#define ACM_REQ_GET_LINE 0x21
97#define ACM_REQ_SET_CONTROL 0x22
98#define ACM_REQ_SEND_BREAK 0x23
99
100
101
102
103
104#define ACM_IRQ_NETWORK 0x00
105#define ACM_IRQ_LINE_STATE 0x20
106
107
108
109
110
111#define ACM_CTRL_DTR 0x01
112#define ACM_CTRL_RTS 0x02
113
114
115
116
117
118#define ACM_CTRL_DCD 0x01
119#define ACM_CTRL_DSR 0x02
120#define ACM_CTRL_BRK 0x04
121#define ACM_CTRL_RI 0x08
122
123#define ACM_CTRL_FRAMING 0x10
124#define ACM_CTRL_PARITY 0x20
125#define ACM_CTRL_OVERRUN 0x40
126
127
128
129
130
131struct acm_line {
132 __u32 speed;
133 __u8 stopbits;
134 __u8 parity;
135 __u8 databits;
136} __attribute__ ((packed));
137
138
139
140
141
142struct acm {
143 struct usb_device *dev;
144 struct usb_interface *iface;
145 struct tty_struct *tty;
146 struct urb ctrlurb, readurb, writeurb;
147 struct acm_line line;
148 struct tq_struct tqueue;
149 unsigned int ctrlin;
150 unsigned int ctrlout;
151 unsigned int writesize;
152 unsigned int used;
153 unsigned int minor;
154 unsigned char throttle;
155 unsigned char clocal;
156};
157
158static struct usb_driver acm_driver;
159static struct tty_driver acm_tty_driver;
160static struct acm *acm_table[ACM_TTY_MINORS];
161
162#define ACM_READY(acm) (acm && acm->dev && acm->used)
163
164
165
166
167
168static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
169{
170 int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
171 request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
172 dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
173 return retval < 0 ? retval : 0;
174}
175
176#define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
177#define acm_set_line(acm, line) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
178#define acm_send_break(acm, ms) acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
179
180
181
182
183
184static void acm_ctrl_irq(struct urb *urb)
185{
186 struct acm *acm = urb->context;
187 struct usb_ctrlrequest *dr = urb->transfer_buffer;
188 unsigned char *data = (unsigned char *)(dr + 1);
189 int newctrl;
190
191 if (!ACM_READY(acm)) return;
192
193 if (urb->status < 0) {
194 dbg("nonzero ctrl irq status received: %d", urb->status);
195 return;
196 }
197
198 switch (dr->bRequest) {
199
200 case ACM_IRQ_NETWORK:
201
202 dbg("%s network", data[0] ? "connected to" : "disconnected from");
203 return;
204
205 case ACM_IRQ_LINE_STATE:
206
207 newctrl = le16_to_cpup((__u16 *) data);
208
209 if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
210 dbg("calling hangup");
211 tty_hangup(acm->tty);
212 }
213
214 acm->ctrlin = newctrl;
215
216 dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
217 acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
218 acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
219 acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
220 acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
221
222 return;
223
224 default:
225 dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
226 dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
227 return;
228 }
229}
230
231static void acm_read_bulk(struct urb *urb)
232{
233 struct acm *acm = urb->context;
234 struct tty_struct *tty = acm->tty;
235 unsigned char *data = urb->transfer_buffer;
236 int i = 0;
237
238 if (!ACM_READY(acm)) return;
239
240 if (urb->status)
241 dbg("nonzero read bulk status received: %d", urb->status);
242
243 if (!urb->status && !acm->throttle) {
244 for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
245
246
247 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
248 tty_flip_buffer_push(tty);
249 }
250 tty_insert_flip_char(tty, data[i], 0);
251 }
252 tty_flip_buffer_push(tty);
253 }
254
255 if (acm->throttle) {
256 memmove(data, data + i, urb->actual_length - i);
257 urb->actual_length -= i;
258 return;
259 }
260
261 urb->actual_length = 0;
262 urb->dev = acm->dev;
263
264 if (usb_submit_urb(urb))
265 dbg("failed resubmitting read urb");
266}
267
268static void acm_write_bulk(struct urb *urb)
269{
270 struct acm *acm = (struct acm *)urb->context;
271
272 if (!ACM_READY(acm)) return;
273
274 if (urb->status)
275 dbg("nonzero write bulk status received: %d", urb->status);
276
277 queue_task(&acm->tqueue, &tq_immediate);
278 mark_bh(IMMEDIATE_BH);
279}
280
281static void acm_softint(void *private)
282{
283 struct acm *acm = private;
284 struct tty_struct *tty = acm->tty;
285
286 if (!ACM_READY(acm)) return;
287
288 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
289 (tty->ldisc.write_wakeup)(tty);
290
291 wake_up_interruptible(&tty->write_wait);
292}
293
294
295
296
297
298static int acm_tty_open(struct tty_struct *tty, struct file *filp)
299{
300 struct acm *acm = acm_table[MINOR(tty->device)];
301
302 if (!acm || !acm->dev) return -EINVAL;
303
304 tty->driver_data = acm;
305 acm->tty = tty;
306
307 MOD_INC_USE_COUNT;
308
309 lock_kernel();
310
311 if (acm->used++) {
312 unlock_kernel();
313 return 0;
314 }
315
316 unlock_kernel();
317
318 acm->ctrlurb.dev = acm->dev;
319 if (usb_submit_urb(&acm->ctrlurb))
320 dbg("usb_submit_urb(ctrl irq) failed");
321
322 acm->readurb.dev = acm->dev;
323 if (usb_submit_urb(&acm->readurb))
324 dbg("usb_submit_urb(read bulk) failed");
325
326 acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
327
328
329
330 tty->low_latency = 1;
331
332 return 0;
333}
334
335static void acm_tty_close(struct tty_struct *tty, struct file *filp)
336{
337 struct acm *acm = tty->driver_data;
338
339 if (!acm || !acm->used) return;
340
341 if (!--acm->used) {
342 if (acm->dev) {
343 acm_set_control(acm, acm->ctrlout = 0);
344 usb_unlink_urb(&acm->ctrlurb);
345 usb_unlink_urb(&acm->writeurb);
346 usb_unlink_urb(&acm->readurb);
347 } else {
348 tty_unregister_devfs(&acm_tty_driver, acm->minor);
349 acm_table[acm->minor] = NULL;
350 kfree(acm);
351 }
352 }
353 MOD_DEC_USE_COUNT;
354}
355
356static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
357{
358 struct acm *acm = tty->driver_data;
359
360 if (!ACM_READY(acm)) return -EINVAL;
361 if (acm->writeurb.status == -EINPROGRESS) return 0;
362 if (!count) return 0;
363
364 count = (count > acm->writesize) ? acm->writesize : count;
365
366 if (from_user) {
367 if (copy_from_user(acm->writeurb.transfer_buffer, buf, count))
368 return -EFAULT;
369 } else
370 memcpy(acm->writeurb.transfer_buffer, buf, count);
371
372 acm->writeurb.transfer_buffer_length = count;
373 acm->writeurb.dev = acm->dev;
374
375 if (usb_submit_urb(&acm->writeurb))
376 dbg("usb_submit_urb(write bulk) failed");
377
378 return count;
379}
380
381static int acm_tty_write_room(struct tty_struct *tty)
382{
383 struct acm *acm = tty->driver_data;
384 if (!ACM_READY(acm)) return -EINVAL;
385 return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize;
386}
387
388static int acm_tty_chars_in_buffer(struct tty_struct *tty)
389{
390 struct acm *acm = tty->driver_data;
391 if (!ACM_READY(acm)) return -EINVAL;
392 return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length : 0;
393}
394
395static void acm_tty_throttle(struct tty_struct *tty)
396{
397 struct acm *acm = tty->driver_data;
398 if (!ACM_READY(acm)) return;
399 acm->throttle = 1;
400}
401
402static void acm_tty_unthrottle(struct tty_struct *tty)
403{
404 struct acm *acm = tty->driver_data;
405 if (!ACM_READY(acm)) return;
406 acm->throttle = 0;
407 if (acm->readurb.status != -EINPROGRESS)
408 acm_read_bulk(&acm->readurb);
409}
410
411static void acm_tty_break_ctl(struct tty_struct *tty, int state)
412{
413 struct acm *acm = tty->driver_data;
414 if (!ACM_READY(acm)) return;
415 if (acm_send_break(acm, state ? 0xffff : 0))
416 dbg("send break failed");
417}
418
419static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
420{
421 struct acm *acm = tty->driver_data;
422 unsigned int mask, newctrl;
423
424 if (!ACM_READY(acm)) return -EINVAL;
425
426 switch (cmd) {
427
428 case TIOCMGET:
429
430 return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
431 (acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
432 (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
433 (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
434 (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
435 TIOCM_CTS, (unsigned long *) arg);
436
437 case TIOCMSET:
438 case TIOCMBIS:
439 case TIOCMBIC:
440
441 if (get_user(mask, (unsigned long *) arg))
442 return -EFAULT;
443
444 newctrl = acm->ctrlout;
445 mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
446
447 switch (cmd) {
448 case TIOCMSET: newctrl = mask; break;
449 case TIOCMBIS: newctrl |= mask; break;
450 case TIOCMBIC: newctrl &= ~mask; break;
451 }
452
453 if (acm->ctrlout == newctrl) return 0;
454 return acm_set_control(acm, acm->ctrlout = newctrl);
455 }
456
457 return -ENOIOCTLCMD;
458}
459
460static __u32 acm_tty_speed[] = {
461 0, 50, 75, 110, 134, 150, 200, 300, 600,
462 1200, 1800, 2400, 4800, 9600, 19200, 38400,
463 57600, 115200, 230400, 460800, 500000, 576000,
464 921600, 1000000, 1152000, 1500000, 2000000,
465 2500000, 3000000, 3500000, 4000000
466};
467
468static __u8 acm_tty_size[] = {
469 5, 6, 7, 8
470};
471
472static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
473{
474 struct acm *acm = tty->driver_data;
475 struct termios *termios = tty->termios;
476 struct acm_line newline;
477 int newctrl = acm->ctrlout;
478
479 if (!ACM_READY(acm)) return;
480
481 newline.speed = cpu_to_le32p(acm_tty_speed +
482 (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
483 newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
484 newline.parity = termios->c_cflag & PARENB ?
485 (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
486 newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
487
488 acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
489
490 if (!newline.speed) {
491 newline.speed = acm->line.speed;
492 newctrl &= ~ACM_CTRL_DTR;
493 } else newctrl |= ACM_CTRL_DTR;
494
495 if (newctrl != acm->ctrlout)
496 acm_set_control(acm, acm->ctrlout = newctrl);
497
498 if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
499 memcpy(&acm->line, &newline, sizeof(struct acm_line));
500 dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
501 acm_set_line(acm, &acm->line);
502 }
503}
504
505
506
507
508
509static void *acm_probe(struct usb_device *dev, unsigned int ifnum,
510 const struct usb_device_id *id)
511{
512 struct acm *acm;
513 struct usb_config_descriptor *cfacm;
514 struct usb_interface_descriptor *ifcom, *ifdata;
515 struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
516 int readsize, ctrlsize, minor, i, j;
517 unsigned char *buf;
518
519 for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
520
521 cfacm = dev->config + i;
522
523 dbg("probing config %d", cfacm->bConfigurationValue);
524
525 for (j = 0; j < cfacm->bNumInterfaces - 1; j++) {
526
527 if (usb_interface_claimed(cfacm->interface + j) ||
528 usb_interface_claimed(cfacm->interface + j + 1))
529 continue;
530
531 ifcom = cfacm->interface[j].altsetting + 0;
532 ifdata = cfacm->interface[j + 1].altsetting + 0;
533
534 if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) {
535 ifcom = cfacm->interface[j + 1].altsetting + 0;
536 ifdata = cfacm->interface[j].altsetting + 0;
537 if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2)
538 continue;
539 }
540
541 if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
542 ifcom->bInterfaceProtocol < 1 || ifcom->bInterfaceProtocol > 6 ||
543 ifcom->bNumEndpoints < 1)
544 continue;
545
546 epctrl = ifcom->endpoint + 0;
547 epread = ifdata->endpoint + 0;
548 epwrite = ifdata->endpoint + 1;
549
550 if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
551 (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
552 ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
553 continue;
554
555 dbg("using interface %d\n", j);
556
557 if ((epread->bEndpointAddress & 0x80) != 0x80) {
558 epread = ifdata->endpoint + 1;
559 epwrite = ifdata->endpoint + 0;
560 }
561
562 usb_set_configuration(dev, cfacm->bConfigurationValue);
563
564 for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
565 if (acm_table[minor]) {
566 err("no more free acm devices");
567 return NULL;
568 }
569
570 if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
571 err("out of memory");
572 return NULL;
573 }
574 memset(acm, 0, sizeof(struct acm));
575
576 ctrlsize = epctrl->wMaxPacketSize;
577 readsize = epread->wMaxPacketSize;
578 acm->writesize = epwrite->wMaxPacketSize;
579 acm->iface = cfacm->interface + j;
580 acm->minor = minor;
581 acm->dev = dev;
582
583 acm->tqueue.routine = acm_softint;
584 acm->tqueue.data = acm;
585
586 if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
587 err("out of memory");
588 kfree(acm);
589 return NULL;
590 }
591
592 FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
593 buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
594
595 FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
596 buf += ctrlsize, readsize, acm_read_bulk, acm);
597 acm->readurb.transfer_flags |= USB_NO_FSBR;
598
599 FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
600 buf += readsize, acm->writesize, acm_write_bulk, acm);
601 acm->writeurb.transfer_flags |= USB_NO_FSBR;
602
603 printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
604
605 acm_set_control(acm, acm->ctrlout);
606
607 acm->line.speed = cpu_to_le32(9600);
608 acm->line.databits = 8;
609 acm_set_line(acm, &acm->line);
610
611 usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
612 usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
613
614 tty_register_devfs(&acm_tty_driver, 0, minor);
615 return acm_table[minor] = acm;
616 }
617 }
618
619 return NULL;
620}
621
622static void acm_disconnect(struct usb_device *dev, void *ptr)
623{
624 struct acm *acm = ptr;
625
626 if (!acm || !acm->dev) {
627 dbg("disconnect on nonexisting interface");
628 return;
629 }
630
631 acm->dev = NULL;
632
633 usb_unlink_urb(&acm->ctrlurb);
634 usb_unlink_urb(&acm->readurb);
635 usb_unlink_urb(&acm->writeurb);
636
637 kfree(acm->ctrlurb.transfer_buffer);
638
639 usb_driver_release_interface(&acm_driver, acm->iface + 0);
640 usb_driver_release_interface(&acm_driver, acm->iface + 1);
641
642 if (!acm->used) {
643 tty_unregister_devfs(&acm_tty_driver, acm->minor);
644 acm_table[acm->minor] = NULL;
645 kfree(acm);
646 return;
647 }
648
649 if (acm->tty)
650 tty_hangup(acm->tty);
651}
652
653
654
655
656
657static struct usb_device_id acm_ids[] = {
658 { USB_DEVICE(0x22B8, 0x1005) },
659 { USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
660 { USB_DEVICE_INFO(USB_CLASS_COMM, 2, 0) },
661 { }
662};
663
664MODULE_DEVICE_TABLE (usb, acm_ids);
665
666static struct usb_driver acm_driver = {
667 name: "acm",
668 probe: acm_probe,
669 disconnect: acm_disconnect,
670 id_table: acm_ids,
671};
672
673
674
675
676
677static int acm_tty_refcount;
678
679static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
680static struct termios *acm_tty_termios[ACM_TTY_MINORS];
681static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
682
683static struct tty_driver acm_tty_driver = {
684 magic: TTY_DRIVER_MAGIC,
685 driver_name: "acm",
686 name: "usb/acm/%d",
687 major: ACM_TTY_MAJOR,
688 minor_start: 0,
689 num: ACM_TTY_MINORS,
690 type: TTY_DRIVER_TYPE_SERIAL,
691 subtype: SERIAL_TYPE_NORMAL,
692 flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
693
694 refcount: &acm_tty_refcount,
695
696 table: acm_tty_table,
697 termios: acm_tty_termios,
698 termios_locked: acm_tty_termios_locked,
699
700 open: acm_tty_open,
701 close: acm_tty_close,
702 write: acm_tty_write,
703 write_room: acm_tty_write_room,
704 ioctl: acm_tty_ioctl,
705 throttle: acm_tty_throttle,
706 unthrottle: acm_tty_unthrottle,
707 chars_in_buffer: acm_tty_chars_in_buffer,
708 break_ctl: acm_tty_break_ctl,
709 set_termios: acm_tty_set_termios
710};
711
712
713
714
715
716static int __init acm_init(void)
717{
718 acm_tty_driver.init_termios = tty_std_termios;
719 acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
720
721 if (tty_register_driver(&acm_tty_driver))
722 return -1;
723
724 if (usb_register(&acm_driver) < 0) {
725 tty_unregister_driver(&acm_tty_driver);
726 return -1;
727 }
728
729 info(DRIVER_VERSION ":" DRIVER_DESC);
730
731 return 0;
732}
733
734static void __exit acm_exit(void)
735{
736 usb_deregister(&acm_driver);
737 tty_unregister_driver(&acm_tty_driver);
738}
739
740module_init(acm_init);
741module_exit(acm_exit);
742
743MODULE_AUTHOR( DRIVER_AUTHOR );
744MODULE_DESCRIPTION( DRIVER_DESC );
745MODULE_LICENSE("GPL");
746
747