Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: cdc-acm: use tty-port dtr_rts

Add dtr_rts tty-port operation which implements proper DTR/RTS handling
(e.g. only lower DTR/RTS during shutdown if HUPCL is set).

Note that modem-control locking still needs to be added throughout the
driver.

Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Johan Hovold and committed by
Greg Kroah-Hartman
0943d8ea 308fee18

+20 -12
+20 -12
drivers/usb/class/cdc-acm.c
··· 504 504 return tty_port_open(&acm->port, tty, filp); 505 505 } 506 506 507 + static void acm_port_dtr_rts(struct tty_port *port, int raise) 508 + { 509 + struct acm *acm = container_of(port, struct acm, port); 510 + int val; 511 + int res; 512 + 513 + if (raise) 514 + val = ACM_CTRL_DTR | ACM_CTRL_RTS; 515 + else 516 + val = 0; 517 + 518 + /* FIXME: add missing ctrlout locking throughout driver */ 519 + acm->ctrlout = val; 520 + 521 + res = acm_set_control(acm, val); 522 + if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE)) 523 + dev_err(&acm->control->dev, "failed to set dtr/rts\n"); 524 + } 525 + 507 526 static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) 508 527 { 509 528 struct acm *acm = container_of(port, struct acm, port); ··· 554 535 goto error_submit_urb; 555 536 } 556 537 557 - acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; 558 - retval = acm_set_control(acm, acm->ctrlout); 559 - if (retval < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE)) 560 - goto error_set_control; 561 - 562 538 /* 563 539 * Unthrottle device in case the TTY was closed while throttled. 564 540 */ ··· 575 561 error_submit_read_urbs: 576 562 for (i = 0; i < acm->rx_buflimit; i++) 577 563 usb_kill_urb(acm->read_urbs[i]); 578 - acm->ctrlout = 0; 579 - acm_set_control(acm, acm->ctrlout); 580 - error_set_control: 581 564 usb_kill_urb(acm->ctrlurb); 582 565 error_submit_urb: 583 566 usb_autopm_put_interface(acm->control); ··· 605 594 int i; 606 595 607 596 dev_dbg(&acm->control->dev, "%s\n", __func__); 608 - 609 - acm_set_control(acm, acm->ctrlout = 0); 610 597 611 598 /* 612 599 * Need to grab write_lock to prevent race with resume, but no need to ··· 1001 992 } 1002 993 1003 994 static const struct tty_port_operations acm_port_ops = { 995 + .dtr_rts = acm_port_dtr_rts, 1004 996 .shutdown = acm_port_shutdown, 1005 997 .activate = acm_port_activate, 1006 998 .destruct = acm_port_destruct, ··· 1438 1428 acm->ctrlurb->transfer_dma = acm->ctrl_dma; 1439 1429 1440 1430 dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); 1441 - 1442 - acm_set_control(acm, acm->ctrlout); 1443 1431 1444 1432 acm->line.dwDTERate = cpu_to_le32(9600); 1445 1433 acm->line.bDataBits = 8;