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))