ChangeSet 1.1474.81.16, 2004/01/16 15:39:38-08:00, rohde@duff.dk

[PATCH] USB: Missing patch for ftdi_sio.c

On Sat, 2004-01-10 at 05:07, Greg KH wrote:
> On Thu, Dec 18, 2003 at 10:28:24PM +0100, Rasmus Rohde wrote:
> > I wrote to you earlier about a missing patch to ftdi_sio.c that appeared
> > in
> >
> > http://www.kernel.org/pub/linux/kernel/people/gregkh/usb/2.5/usb-ftdi_sio-2.5.68.patch
> >
> > It has to do with the introduction tiocmset and tiocmget.
> > This patch was dropped in
> >
> > http://www.kernel.org/pub/linux/kernel/people/gregkh/usb/2.5/usb-ftdi_sio-2.5.75.patch
> >
> > which unfortunately breaks the driver.
>
> Hm, sorry about that.  Care to send me a patch to fix it up?


 drivers/usb/serial/ftdi_sio.c |  158 ++++++++++++++++++++++++------------------
 1 files changed, 94 insertions(+), 64 deletions(-)


diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Tue Jan 20 17:36:15 2004
+++ b/drivers/usb/serial/ftdi_sio.c	Tue Jan 20 17:36:15 2004
@@ -577,6 +577,8 @@
 static void ftdi_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 static void ftdi_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 static void ftdi_set_termios		(struct usb_serial_port *port, struct termios * old);
+static int  ftdi_tiocmget               (struct usb_serial_port *port, struct file *file);
+static int  ftdi_tiocmset		(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
 static int  ftdi_ioctl			(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void ftdi_break_ctl		(struct usb_serial_port *port, int break_state );
 static void ftdi_throttle		(struct usb_serial_port *port);
@@ -604,6 +606,8 @@
 	.chars_in_buffer =	ftdi_chars_in_buffer,
 	.read_bulk_callback =	ftdi_read_bulk_callback,
 	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -628,6 +632,8 @@
 	.chars_in_buffer =	ftdi_chars_in_buffer,
 	.read_bulk_callback =	ftdi_read_bulk_callback,
 	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -652,6 +658,8 @@
 	.chars_in_buffer =	ftdi_chars_in_buffer,
 	.read_bulk_callback =	ftdi_read_bulk_callback,
 	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -676,6 +684,8 @@
 	.chars_in_buffer =	ftdi_chars_in_buffer,
 	.read_bulk_callback =	ftdi_read_bulk_callback,
 	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -702,6 +712,8 @@
 	.chars_in_buffer =	ftdi_chars_in_buffer,
 	.read_bulk_callback =	ftdi_read_bulk_callback,
 	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -1809,81 +1821,99 @@
 } /* ftdi_termios */
 
 
-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
 {
 	struct usb_serial *serial = port->serial;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	unsigned char buf[2];
+	int ret;
 
-	__u16 urb_value=0; /* Will hold the new flags */
-	char buf[2];
-	int  ret, mask;
-	
-	dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
-
-	/* Based on code from acm.c and others */
-	switch (cmd) {
-
-	case TIOCMGET:
-		dbg("%s TIOCMGET", __FUNCTION__);
-		switch (priv->chip_type) {
-		case SIO:
-			/* Request the status from the device */
-			if ((ret = usb_control_msg(serial->dev, 
-						   usb_rcvctrlpipe(serial->dev, 0),
-						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
-						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-						   0, 0, 
-						   buf, 1, WDR_TIMEOUT)) < 0 ) {
-				err("%s Could not get modem status of device - err: %d", __FUNCTION__,
-				    ret);
-				return(ret);
-			}
-			break;
-		case FT8U232AM:
-		case FT232BM:
-			/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
-			   format as the data returned from the in point */
-			if ((ret = usb_control_msg(serial->dev, 
-						   usb_rcvctrlpipe(serial->dev, 0),
-						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
-						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-						   0, 0, 
-						   buf, 2, WDR_TIMEOUT)) < 0 ) {
-				err("%s Could not get modem status of device - err: %d", __FUNCTION__,
-				    ret);
-				return(ret);
-			}
-			break;
-		default:
-			return -EFAULT;
-			break;
+	dbg("%s TIOCMGET", __FUNCTION__);
+	switch (priv->chip_type) {
+	case SIO:
+		/* Request the status from the device */
+		if ((ret = usb_control_msg(serial->dev, 
+					   usb_rcvctrlpipe(serial->dev, 0),
+					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+					   0, 0, 
+					   buf, 1, WDR_TIMEOUT)) < 0 ) {
+			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+			    ret);
+			return(ret);
 		}
-
-		return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
-				(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
-				(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
-				(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
-				priv->last_dtr_rts,
-				(unsigned long *) arg);
 		break;
+	case FT8U232AM:
+	case FT232BM:
+		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
+		   format as the data returned from the in point */
+		if ((ret = usb_control_msg(serial->dev, 
+					   usb_rcvctrlpipe(serial->dev, 0),
+					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+					   0, 0, 
+					   buf, 2, WDR_TIMEOUT)) < 0 ) {
+			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+			    ret);
+			return(ret);
+		}
+		break;
+	default:
+		return -EFAULT;
+		break;
+	}
+	
+	return  (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+		(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
+		(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
+		priv->last_dtr_rts;			
+}
 
-	case TIOCMSET: /* Turns on and off the lines as specified by the mask */
-		dbg("%s TIOCMSET", __FUNCTION__);
-		if (get_user(mask, (unsigned long *) arg))
-			return -EFAULT;
-		urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
-		if ((ret = set_dtr(port, urb_value)) < 0){
-			err("Error from DTR set urb (TIOCMSET)");
+static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+{
+	int ret;
+	
+	if (set & TIOCM_DTR){
+		if ((ret = set_dtr(port, HIGH)) < 0) {
+			err("Urb to set DTR failed");
 			return(ret);
 		}
-		urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
-		if ((ret = set_rts(port, urb_value)) < 0){
-			err("Error from RTS set urb (TIOCMSET)");
+	}
+	if (set & TIOCM_RTS) {
+		if ((ret = set_rts(port, HIGH)) < 0){
+			err("Urb to set RTS failed");
 			return(ret);
 		}
-		return(0);
-		break;
-					
+	}
+	
+	if (clear & TIOCM_DTR){
+		if ((ret = set_dtr(port, LOW)) < 0){
+			err("Urb to unset DTR failed");
+			return(ret);
+		}
+	}	
+	if (clear & TIOCM_RTS) {
+		if ((ret = set_rts(port, LOW)) < 0){
+			err("Urb to unset RTS failed");
+			return(ret);
+		}
+	}
+	return(0);
+}
+
+
+static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+
+	int  ret, mask;
+	
+	dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
+
+	/* Based on code from acm.c and others */
+	switch (cmd) {
+
 	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
 		dbg("%s TIOCMBIS", __FUNCTION__);
  	        if (get_user(mask, (unsigned long *) arg))
