Commit a64171f2 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

[PATCH] USB: ftdi_sio: add support for new tty tiocmget and tiocmset functions.

parent 73330824
...@@ -175,6 +175,8 @@ static int ftdi_sio_write_room (struct usb_serial_port *port); ...@@ -175,6 +175,8 @@ static int ftdi_sio_write_room (struct usb_serial_port *port);
static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs); static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
static void ftdi_sio_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void ftdi_sio_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old); static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file);
static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state ); static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state );
...@@ -198,6 +200,8 @@ static struct usb_serial_device_type ftdi_sio_device = { ...@@ -198,6 +200,8 @@ static struct usb_serial_device_type ftdi_sio_device = {
.ioctl = ftdi_sio_ioctl, .ioctl = ftdi_sio_ioctl,
.set_termios = ftdi_sio_set_termios, .set_termios = ftdi_sio_set_termios,
.break_ctl = ftdi_sio_break_ctl, .break_ctl = ftdi_sio_break_ctl,
.tiocmget = ftdi_sio_tiocmget,
.tiocmset = ftdi_sio_tiocmset,
.attach = ftdi_sio_startup, .attach = ftdi_sio_startup,
.shutdown = ftdi_sio_shutdown, .shutdown = ftdi_sio_shutdown,
}; };
...@@ -219,6 +223,8 @@ static struct usb_serial_device_type ftdi_8U232AM_device = { ...@@ -219,6 +223,8 @@ static struct usb_serial_device_type ftdi_8U232AM_device = {
.ioctl = ftdi_sio_ioctl, .ioctl = ftdi_sio_ioctl,
.set_termios = ftdi_sio_set_termios, .set_termios = ftdi_sio_set_termios,
.break_ctl = ftdi_sio_break_ctl, .break_ctl = ftdi_sio_break_ctl,
.tiocmget = ftdi_sio_tiocmget,
.tiocmset = ftdi_sio_tiocmset,
.attach = ftdi_8U232AM_startup, .attach = ftdi_8U232AM_startup,
.shutdown = ftdi_sio_shutdown, .shutdown = ftdi_sio_shutdown,
}; };
...@@ -823,125 +829,100 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * ...@@ -823,125 +829,100 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
return; return;
} /* ftdi_sio_set_termios */ } /* ftdi_sio_set_termios */
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value=0; /* Will hold the new flags */ char *buf = NULL;
char buf[2]; int ret = -EINVAL;
int ret, mask; int size;
dbg("%s cmd 0x%04x", __FUNCTION__, cmd); dbg("%s", __FUNCTION__);
/* Based on code from acm.c and others */ buf = kmalloc(2, GFP_KERNEL);
switch (cmd) { if (!buf)
goto exit;
case TIOCMGET: if (priv->ftdi_type == sio) {
dbg("%s TIOCMGET", __FUNCTION__); size = 1;
if (priv->ftdi_type == 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);
}
} else { } else {
/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same /* 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 */ format as the data returned from the in point */
if ((ret = usb_control_msg(serial->dev, size = 2;
}
ret = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0), usb_rcvctrlpipe(serial->dev, 0),
FTDI_SIO_GET_MODEM_STATUS_REQUEST, FTDI_SIO_GET_MODEM_STATUS_REQUEST,
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, 0, 0, 0, buf, size, WDR_TIMEOUT);
buf, 2, WDR_TIMEOUT)) < 0 ) { if (ret < 0) {
err("%s Could not get modem status of device - err: %d", __FUNCTION__, err("%s Could not get modem status of device - err: %d",
ret); __FUNCTION__, ret);
return(ret); goto exit;
}
} }
return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
(buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
(buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0);
(unsigned long *) arg);
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */ exit:
dbg("%s TIOCMSET", __FUNCTION__); kfree(buf);
if (get_user(mask, (unsigned long *) arg)) return ret;
return -EFAULT; }
urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file,
err("Error from DTR set urb (TIOCMSET)"); unsigned int set, unsigned int clear)
} {
urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW); struct usb_serial *serial = port->serial;
if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ int ret = 0;
err("Error from RTS set urb (TIOCMSET)");
dbg("%s", __FUNCTION__);
if (set & TIOCM_RTS)
if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0) {
err("Urb to set RTS failed");
goto exit;
} }
break;
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ if (set & TIOCM_DTR)
dbg("%s TIOCMBIS", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (mask & TIOCM_DTR){
if ((ret = set_dtr(serial->dev, if ((ret = set_dtr(serial->dev,
usb_sndctrlpipe(serial->dev, 0), usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0) { HIGH)) < 0) {
err("Urb to set DTR failed"); err("Urb to set DTR failed");
return(ret); goto exit;
}
} }
if (mask & TIOCM_RTS) {
if (clear & TIOCM_RTS)
if ((ret = set_rts(serial->dev, if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0), usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0){ LOW)) < 0) {
err("Urb to set RTS failed"); err("Urb to unset RTS failed");
return(ret); goto exit;
}
} }
break;
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ if (clear & TIOCM_DTR)
dbg("%s TIOCMBIC", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (mask & TIOCM_DTR){
if ((ret = set_dtr(serial->dev, if ((ret = set_dtr(serial->dev,
usb_sndctrlpipe(serial->dev, 0), usb_sndctrlpipe(serial->dev, 0),
LOW)) < 0){ LOW)) < 0) {
err("Urb to unset DTR failed"); err("Urb to unset DTR failed");
return(ret); goto exit;
} }
}
if (mask & TIOCM_RTS) {
if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
LOW)) < 0){
err("Urb to unset RTS failed");
return(ret);
}
}
break;
/* exit:
* I had originally implemented TCSET{A,S}{,F,W} and return ret;
* TCGET{A,S} here separately, however when testing I }
* found that the higher layers actually do the termios
* conversions themselves and pass the call onto static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
* ftdi_sio_set_termios. {
* dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
*/
switch (cmd) {
default: default:
/* This is not an error - turns out the higher layers will do /* This is not an error - turns out the higher layers will do
* some ioctls itself (see comment above) * some ioctls itself
*/ */
dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd); dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd);
return(-ENOIOCTLCMD); return(-ENOIOCTLCMD);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment