Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c466cd2b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

USB: serial: ftdi_sio: add support for TIOCSERGETLSR



Willem-Jan noticed that the ftdi_sio driver did not support the
TIOCSERGETLSR ioctl, and some userspace programs rely on it.  This patch
adds the support.

Reported-by: default avatarWillem-Jan de Hoog <wdehoog@exalondelft.nl>
Tested-by: default avatarWillem-Jan de Hoog <wdehoog@exalondelft.nl>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 0247a7bc
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ struct ftdi_private {
	unsigned long last_dtr_rts;	/* saved modem control outputs */
	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
	char transmit_empty;	/* If transmitter is empty or not */
	struct usb_serial_port *port;
	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface
				   (0 for FT232/245) */
@@ -1322,6 +1323,23 @@ static int set_serial_info(struct tty_struct *tty,
	return 0;
}

static int get_lsr_info(struct usb_serial_port *port,
			struct serial_struct __user *retinfo)
{
	struct ftdi_private *priv = usb_get_serial_port_data(port);
	unsigned int result = 0;

	if (!retinfo)
		return -EFAULT;

	if (priv->transmit_empty)
		result = TIOCSER_TEMT;

	if (copy_to_user(retinfo, &result, sizeof(unsigned int)))
		return -EFAULT;
	return 0;
}


/* Determine type of FTDI chip based on USB config and descriptor. */
static void ftdi_determine_type(struct usb_serial_port *port)
@@ -1871,6 +1889,12 @@ static int ftdi_process_packet(struct tty_struct *tty,
			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
	}

	/* save if the transmitter is empty or not */
	if (packet[1] & FTDI_RS_TEMT)
		priv->transmit_empty = 1;
	else
		priv->transmit_empty = 0;

	len -= 2;
	if (!len)
		return 0;	/* status only */
@@ -2234,6 +2258,9 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
			}
		}
		return 0;
	case TIOCSERGETLSR:
		return get_lsr_info(port, (struct serial_struct __user *)arg);
		break;
	default:
		break;
	}