forked from mirrors/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>
This commit is contained in:
		
							parent
							
								
									308fee18e0
								
							
						
					
					
						commit
						0943d8ead3
					
				
					 1 changed files with 20 additions and 12 deletions
				
			
		|  | @ -504,6 +504,25 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | ||||||
| 	return tty_port_open(&acm->port, tty, filp); | 	return tty_port_open(&acm->port, tty, filp); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void acm_port_dtr_rts(struct tty_port *port, int raise) | ||||||
|  | { | ||||||
|  | 	struct acm *acm = container_of(port, struct acm, port); | ||||||
|  | 	int val; | ||||||
|  | 	int res; | ||||||
|  | 
 | ||||||
|  | 	if (raise) | ||||||
|  | 		val = ACM_CTRL_DTR | ACM_CTRL_RTS; | ||||||
|  | 	else | ||||||
|  | 		val = 0; | ||||||
|  | 
 | ||||||
|  | 	/* FIXME: add missing ctrlout locking throughout driver */ | ||||||
|  | 	acm->ctrlout = val; | ||||||
|  | 
 | ||||||
|  | 	res = acm_set_control(acm, val); | ||||||
|  | 	if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE)) | ||||||
|  | 		dev_err(&acm->control->dev, "failed to set dtr/rts\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) | static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) | ||||||
| { | { | ||||||
| 	struct acm *acm = container_of(port, struct acm, port); | 	struct acm *acm = container_of(port, struct acm, port); | ||||||
|  | @ -535,11 +554,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) | ||||||
| 		goto error_submit_urb; | 		goto error_submit_urb; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; |  | ||||||
| 	retval = acm_set_control(acm, acm->ctrlout); |  | ||||||
| 	if (retval < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE)) |  | ||||||
| 		goto error_set_control; |  | ||||||
| 
 |  | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Unthrottle device in case the TTY was closed while throttled. | 	 * Unthrottle device in case the TTY was closed while throttled. | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -561,9 +575,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) | ||||||
| error_submit_read_urbs: | error_submit_read_urbs: | ||||||
| 	for (i = 0; i < acm->rx_buflimit; i++) | 	for (i = 0; i < acm->rx_buflimit; i++) | ||||||
| 		usb_kill_urb(acm->read_urbs[i]); | 		usb_kill_urb(acm->read_urbs[i]); | ||||||
| 	acm->ctrlout = 0; |  | ||||||
| 	acm_set_control(acm, acm->ctrlout); |  | ||||||
| error_set_control: |  | ||||||
| 	usb_kill_urb(acm->ctrlurb); | 	usb_kill_urb(acm->ctrlurb); | ||||||
| error_submit_urb: | error_submit_urb: | ||||||
| 	usb_autopm_put_interface(acm->control); | 	usb_autopm_put_interface(acm->control); | ||||||
|  | @ -595,8 +606,6 @@ static void acm_port_shutdown(struct tty_port *port) | ||||||
| 
 | 
 | ||||||
| 	dev_dbg(&acm->control->dev, "%s\n", __func__); | 	dev_dbg(&acm->control->dev, "%s\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	acm_set_control(acm, acm->ctrlout = 0); |  | ||||||
| 
 |  | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Need to grab write_lock to prevent race with resume, but no need to | 	 * Need to grab write_lock to prevent race with resume, but no need to | ||||||
| 	 * hold it due to the tty-port initialised flag. | 	 * hold it due to the tty-port initialised flag. | ||||||
|  | @ -992,6 +1001,7 @@ static void acm_tty_set_termios(struct tty_struct *tty, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct tty_port_operations acm_port_ops = { | static const struct tty_port_operations acm_port_ops = { | ||||||
|  | 	.dtr_rts = acm_port_dtr_rts, | ||||||
| 	.shutdown = acm_port_shutdown, | 	.shutdown = acm_port_shutdown, | ||||||
| 	.activate = acm_port_activate, | 	.activate = acm_port_activate, | ||||||
| 	.destruct = acm_port_destruct, | 	.destruct = acm_port_destruct, | ||||||
|  | @ -1429,8 +1439,6 @@ static int acm_probe(struct usb_interface *intf, | ||||||
| 
 | 
 | ||||||
| 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); | 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); | ||||||
| 
 | 
 | ||||||
| 	acm_set_control(acm, acm->ctrlout); |  | ||||||
| 
 |  | ||||||
| 	acm->line.dwDTERate = cpu_to_le32(9600); | 	acm->line.dwDTERate = cpu_to_le32(9600); | ||||||
| 	acm->line.bDataBits = 8; | 	acm->line.bDataBits = 8; | ||||||
| 	acm_set_line(acm, &acm->line); | 	acm_set_line(acm, &acm->line); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Johan Hovold
						Johan Hovold