Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct serial_struct new_serial;
struct ftdi_private old_priv;
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
return -EFAULT;
old_priv = * priv;
/* Do error checking and permission checking */
if (!capable(CAP_SYS_ADMIN)) {
if (((new_serial.flags & ~ASYNC_USR_MASK) !=
(priv->flags & ~ASYNC_USR_MASK)))
return -EPERM;
priv->flags = ((priv->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
priv->custom_divisor = new_serial.custom_divisor;
goto check_and_exit;
}
if ((new_serial.baud_base != priv->baud_base) &&
(new_serial.baud_base < 9600))
return -EINVAL;
/* Make the changes - these are privileged changes! */
priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
priv->custom_divisor = new_serial.custom_divisor;
tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
check_and_exit:
if ((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) {
if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
}
if (((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) ||
(((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(old_priv.custom_divisor != priv->custom_divisor))) {
/* Determine type of FTDI chip based on USB config and descriptor. */
static void ftdi_determine_type(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
struct usb_device *udev = serial->dev;
unsigned version;
unsigned interfaces;
/* Assume it is not the original SIO device for now. */
priv->baud_base = 48000000 / 2;
priv->write_offset = 0;
version = le16_to_cpu(udev->descriptor.bcdDevice);
interfaces = udev->actconfig->desc.bNumInterfaces;
dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__,
version, interfaces);
if (interfaces > 1) {
int inter;
/* Multiple interfaces. Assume FT2232C. */
priv->chip_type = FT2232C;
/* Determine interface code. */
inter = serial->interface->altsetting->desc.bInterfaceNumber;
if (inter == 0) {
priv->interface = PIT_SIOA;
} else {
priv->interface = PIT_SIOB;
}
/* BM-type devices have a bug where bcdDevice gets set
* to 0x200 when iSerialNumber is 0. */
if (version < 0x500) {
dbg("%s: something fishy - bcdDevice too low for multi-interface device",
}
} else if (version < 0x200) {
/* Old device. Assume its the original SIO. */
priv->chip_type = SIO;
priv->baud_base = 12000000 / 16;
priv->write_offset = 1;
} else if (version < 0x400) {
/* Assume its an FT8U232AM (or FT8U245AM) */
/* (It might be a BM because of the iSerialNumber bug,
* but it will still work as an AM device.) */
priv->chip_type = FT8U232AM;
/* Assume its an FT232BM (or FT245BM) */
priv->chip_type = FT232BM;
} else {
/* Assume its an FT232R */
priv->chip_type = FT232RL;
}
info("Detected %s", ftdi_chip_name[priv->chip_type]);
}
/*
* ***************************************************************************
* Sysfs Attribute
* ***************************************************************************
*/
Yani Ioannou
committed
static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
Jim Radford
committed
struct usb_device *udev = port->serial->dev;
rv = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
dev_err(dev, "Unable to read latency timer: %i\n", rv);
return -EIO;
}
return sprintf(buf, "%i\n", latency);
}
/* Write a new value of the latency timer, in units of milliseconds. */
Yani Ioannou
committed
static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf,
size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
Jim Radford
committed
struct usb_device *udev = port->serial->dev;
char buf[1];
int v = simple_strtoul(valbuf, NULL, 10);
int rv = 0;
dbg("%s: setting latency timer = %i", __func__, v);
rv = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
dev_err(dev, "Unable to write latency timer: %i\n", rv);
return count;
}
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
Yani Ioannou
committed
static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf,
size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
Jim Radford
committed
struct usb_device *udev = port->serial->dev;
char buf[1];
int v = simple_strtoul(valbuf, NULL, 10);
int rv = 0;
dbg("%s: setting event char = %i", __func__, v);
rv = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
FTDI_SIO_SET_EVENT_CHAR_REQUEST,
FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE,
if (rv < 0) {
dbg("Unable to write event character: %i", rv);
return -EIO;
}
return count;
}
static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
Jim Radford
committed
static int create_sysfs_attrs(struct usb_serial_port *port)
Jim Radford
committed
struct ftdi_private *priv = usb_get_serial_port_data(port);
int retval = 0;
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */
if (priv->chip_type != SIO) {
dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
Jim Radford
committed
retval = device_create_file(&port->dev, &dev_attr_event_char);
if ((!retval) &&
(priv->chip_type == FT232BM ||
priv->chip_type == FT2232C ||
priv->chip_type == FT232RL)) {
Jim Radford
committed
retval = device_create_file(&port->dev,
&dev_attr_latency_timer);
return retval;
Jim Radford
committed
static void remove_sysfs_attrs(struct usb_serial_port *port)
Jim Radford
committed
struct ftdi_private *priv = usb_get_serial_port_data(port);
/* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) {
Jim Radford
committed
device_remove_file(&port->dev, &dev_attr_event_char);
if (priv->chip_type == FT232BM ||
priv->chip_type == FT2232C ||
priv->chip_type == FT232RL) {
Jim Radford
committed
device_remove_file(&port->dev, &dev_attr_latency_timer);
}
/*
* ***************************************************************************
* FTDI driver specific functions
* ***************************************************************************
*/
/* Probe function to check for special devices */
static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id)
{
struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info;
if (quirk && quirk->probe) {
int ret = quirk->probe(serial);
if (ret != 0)
return ret;
}
usb_set_serial_data(serial, (void *)id->driver_info);
return 0;
Jim Radford
committed
static int ftdi_sio_port_probe(struct usb_serial_port *port)
struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
return -ENOMEM;
}
spin_lock_init(&priv->rx_lock);
spin_lock_init(&priv->tx_lock);
init_waitqueue_head(&priv->delta_msr_wait);
/* This will push the characters through immediately rather
than queue a task to deliver them */
priv->flags = ASYNC_LOW_LATENCY;
if (quirk && quirk->port_probe)
quirk->port_probe(priv);
kfree(port->bulk_in_buffer);
port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
if (!port->bulk_in_buffer) {
kfree (priv);
return -ENOMEM;
}
if (port->read_urb) {
port->read_urb->transfer_buffer = port->bulk_in_buffer;
port->read_urb->transfer_buffer_length = BUFSZ;
}
INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read);
priv->port = port;
/* Free port's existing write urb and transfer buffer. */
if (port->write_urb) {
usb_free_urb (port->write_urb);
port->write_urb = NULL;
}
kfree(port->bulk_out_buffer);
port->bulk_out_buffer = NULL;
Jim Radford
committed
usb_set_serial_port_data(port, priv);
Jim Radford
committed
ftdi_determine_type (port);
create_sysfs_attrs(port);
return 0;
}
/* Setup for the USB-UIRT device, which requires hardwired
* baudrate (38400 gets mapped to 312500) */
static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
priv->force_baud = 38400;
} /* ftdi_USB_UIRT_setup */
/* Setup for the HE-TIRA1 device, which requires hardwired
* baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */
static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
priv->force_baud = 38400;
} /* ftdi_HE_TIRA1_setup */
* First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
* Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
* userspace using openocd.
static int ftdi_jtag_probe(struct usb_serial *serial)
{
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
if (interface == udev->actconfig->interface[0]) {
info("Ignoring serial port reserved for JTAG");
return -ENODEV;
}
return 0;
}
/*
* The Matrix Orbital VK204-25-USB has an invalid IN endpoint.
* We have to correct it if we want to read from it.
*/
static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
{
struct usb_host_endpoint *ep = serial->dev->ep_in[1];
struct usb_endpoint_descriptor *ep_desc = &ep->desc;
if (ep->enabled && ep_desc->wMaxPacketSize == 0) {
ep_desc->wMaxPacketSize = cpu_to_le16(0x40);
info("Fixing invalid wMaxPacketSize on read pipe");
}
return 0;
}
/* ftdi_shutdown is called from usbserial:usb_serial_disconnect
* it is called when the usb device is disconnected
*
* usbserial:usb_serial_disconnect
* calls __serial_close for each open of the port
* shutdown is called then (ie ftdi_shutdown)
*/
static void ftdi_shutdown (struct usb_serial *serial)
Jim Radford
committed
{
Jim Radford
committed
}
Jim Radford
committed
static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
Jim Radford
committed
remove_sysfs_attrs(port);
/* all open ports are closed at this point
* (by usbserial.c:__serial_close, which calls ftdi_close)
*/
if (priv) {
usb_set_serial_port_data(port, NULL);
kfree(priv);
}
Jim Radford
committed
return 0;
}
static int ftdi_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
{ /* ftdi_open */
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result = 0;
char buf[1]; /* Needed for the usb_control_msg I think */
spin_lock_irqsave(&priv->tx_lock, flags);
priv->tx_bytes = 0;
spin_unlock_irqrestore(&priv->tx_lock, flags);
spin_lock_irqsave(&priv->rx_lock, flags);
priv->rx_bytes = 0;
spin_unlock_irqrestore(&priv->rx_lock, flags);
if (tty)
tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE,
FTDI_SIO_RESET_SIO,
priv->interface, buf, 0, WDR_TIMEOUT);
/* Termios defaults are set by usb_serial_init. We don't change
port->tty->termios - this would loose speed settings, etc.
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
if (tty)
ftdi_set_termios(tty, port, tty->termios);
/* FIXME: Flow control might be enabled, so it should be checked -
we have no control of defaults! */
/* Turn on RTS and DTR since we are not flow controlling by default */
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
/* Not throttled */
spin_lock_irqsave(&priv->rx_lock, flags);
priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* Start reading from the device */
priv->rx_processed = 0;
usb_fill_bulk_urb(port->read_urb, dev,
usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
err("%s - failed submitting read urb, error %d", __func__, result);
return result;
} /* ftdi_open */
* usbserial:__serial_close only calls ftdi_close if the point is open
*
* This only gets called when it is the last close
static void ftdi_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)
struct ftdi_private *priv = usb_get_serial_port_data(port);
char buf[1];
mutex_lock(&port->serial->disc_mutex);
if (c_cflag & HUPCL && !port->serial->disconnected){
usb_sndctrlpipe(port->serial->dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
0, priv->interface, buf, 0,
WDR_TIMEOUT) < 0) {
err("error from flowcontrol urb");
/* drop RTS and DTR */
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
mutex_unlock(&port->serial->disc_mutex);
/* cancel any scheduled reading */
cancel_delayed_work(&priv->rx_work);
flush_scheduled_work();
/* The SIO requires the first byte to have:
* B0 1
* B1 0
* B2..7 length of message excluding byte 0
*
* The new devices do not require this byte
*/
static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{ /* ftdi_write */
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct urb *urb;
unsigned char *buffer;
int data_offset ; /* will be 1 for the SIO and 0 otherwise */
int status;
int transfer_size;
dbg("%s port %d, %d bytes", __func__, port->number, count);
if (count == 0) {
dbg("write request of 0 bytes");
return 0;
}
spin_lock_irqsave(&priv->tx_lock, flags);
if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
spin_unlock_irqrestore(&priv->tx_lock, flags);
dbg("%s - write limit hit\n", __func__);
spin_unlock_irqrestore(&priv->tx_lock, flags);
data_offset = priv->write_offset;
dbg("data_offset set to %d",data_offset);
/* Determine total transfer size */
transfer_size = count;
if (data_offset > 0) {
/* Original sio needs control bytes too... */
transfer_size += (data_offset *
((count + (PKTSZ - 1 - data_offset)) /
(PKTSZ - data_offset)));
}
buffer = kmalloc (transfer_size, GFP_ATOMIC);
if (!buffer) {
err("%s ran out of kernel memory for urb ...", __func__);
count = -ENOMEM;
goto error_no_buffer;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
err("%s - no more free urbs", __func__);
}
/* Copy data */
if (data_offset > 0) {
/* Original sio requires control byte at start of each packet. */
int user_pktsz = PKTSZ - data_offset;
int todo = count;
unsigned char *first_byte = buffer;
const unsigned char *current_position = buf;
while (todo > 0) {
if (user_pktsz > todo) {
user_pktsz = todo;
}
/* Write the control byte at the front of the packet*/
/* Copy data for packet */
memcpy (first_byte + data_offset,
current_position, user_pktsz);
first_byte += user_pktsz + data_offset;
current_position += user_pktsz;
todo -= user_pktsz;
}
} else {
/* No control byte required. */
/* Copy in the data to send */
memcpy (buffer, buf, count);
}
usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
usb_fill_bulk_urb(urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
buffer, transfer_size,
ftdi_write_bulk_callback, port);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err("%s - failed submitting write urb, error %d", __func__, status);
} else {
spin_lock_irqsave(&priv->tx_lock, flags);
priv->tx_outstanding_bytes += count;
priv->tx_bytes += count;
spin_unlock_irqrestore(&priv->tx_lock, flags);
}
/* we are done with this urb, so let the host driver
* really free it when it is finished with it */
dbg("%s write returning: %d", __func__, count);
error:
usb_free_urb(urb);
error_no_urb:
kfree (buffer);
error_no_buffer:
spin_lock_irqsave(&priv->tx_lock, flags);
priv->tx_outstanding_urbs--;
spin_unlock_irqrestore(&priv->tx_lock, flags);
return count;
} /* ftdi_write */
/* This function may get called when the device is closed */
static void ftdi_write_bulk_callback (struct urb *urb)
struct usb_serial_port *port = urb->context;
struct ftdi_private *priv;
int data_offset; /* will be 1 for the SIO and 0 otherwise */
unsigned long countback;
int status = urb->status;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
dbg("%s - port %d", __func__, port->number);
if (status) {
dbg("nonzero write bulk status received: %d", status);
priv = usb_get_serial_port_data(port);
if (!priv) {
dbg("%s - bad port private data pointer - exiting", __func__);
return;
}
/* account for transferred data */
countback = urb->actual_length;
data_offset = priv->write_offset;
if (data_offset > 0) {
/* Subtract the control bytes */
countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ));
}
spin_lock_irqsave(&priv->tx_lock, flags);
--priv->tx_outstanding_urbs;
priv->tx_outstanding_bytes -= countback;
spin_unlock_irqrestore(&priv->tx_lock, flags);
usb_serial_port_softint(port);
static int ftdi_write_room(struct tty_struct *tty)
struct ftdi_private *priv = usb_get_serial_port_data(port);
int room;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->tx_lock, flags);
if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
/*
* We really can take anything the user throws at us
* but let's pick a nice big number to tell the tty
* layer that we have lots of free space
*/
room = 2048;
} else {
room = 0;
}
spin_unlock_irqrestore(&priv->tx_lock, flags);
return room;
static int ftdi_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int buffered;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->tx_lock, flags);
buffered = (int)priv->tx_outstanding_bytes;
spin_unlock_irqrestore(&priv->tx_lock, flags);
if (buffered < 0) {
err("%s outstanding tx bytes is negative!", __func__);
buffered = 0;
}
return buffered;
static void ftdi_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
struct ftdi_private *priv;
unsigned long countread;
unsigned long flags;
int status = urb->status;
err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
err("%s transfer_flags %x ", __func__,urb->transfer_flags );
dbg("%s - port %d", __func__, port->number);
dbg("%s - bad tty pointer - exiting",__func__);
return;
}
priv = usb_get_serial_port_data(port);
if (!priv) {
dbg("%s - bad port private data pointer - exiting", __func__);
return;
}
if (urb != port->read_urb) {
err("%s - Not my urb!", __func__);
/* This will happen at close every time so it is a dbg not an err */
dbg("(this is ok on close) nonzero read bulk status received: "
"%d", status);
/* count data bytes, but not status bytes */
countread = urb->actual_length;
spin_lock_irqsave(&priv->rx_lock, flags);
priv->rx_bytes += countread;
spin_unlock_irqrestore(&priv->rx_lock, flags);
static void ftdi_process_read (struct work_struct *work)
struct ftdi_private *priv =
container_of(work, struct ftdi_private, rx_work.work);
struct usb_serial_port *port = priv->port;
struct urb *urb;
struct tty_struct *tty;
char error_flag;
int i;
int result;
int need_flip;
int packet_offset;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
dbg("%s - bad tty pointer - exiting",__func__);
return;
}
priv = usb_get_serial_port_data(port);
if (!priv) {
dbg("%s - bad port private data pointer - exiting", __func__);
return;
}
urb = port->read_urb;
if (!urb) {
dbg("%s - bad read_urb pointer - exiting", __func__);
return;
}
data = urb->transfer_buffer;
if (priv->rx_processed) {
dbg("%s - already processed: %d bytes, %d remain", __func__,
priv->rx_processed,
urb->actual_length - priv->rx_processed);
/* The first two bytes of every read packet are status */
if (urb->actual_length > 2) {
usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
} else {
dbg("Status only: %03oo %03oo",data[0],data[1]);
}
}
/* TO DO -- check for hung up line and handle appropriately: */
/* send hangup */
/* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
/* if CD is dropped and the line is not CLOCAL then we should hangup */
need_flip = 0;
for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
int length;
/* Compare new line status to the old one, signal if different */
/* N.B. packet may be processed more than once, but differences
* are only processed once. */
if (priv != NULL) {
char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
priv->diff_status |= new_status ^ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = new_status;
}
}
length = min(PKTSZ, urb->actual_length-packet_offset)-2;
if (length < 0) {
err("%s - bad packet length: %d", __func__, length+2);
length = 0;
}
if (priv->rx_flags & THROTTLED) {
dbg("%s - throttled", __func__);
break;
}
if (tty_buffer_request_room(tty, length) < length) {
/* break out & wait for throttling/unthrottling to happen */
dbg("%s - receive room low", __func__);
break;
}
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
/* Handle errors and break */
error_flag = TTY_NORMAL;
/* Although the device uses a bitmask and hence can have multiple */
/* errors on a packet - the order here sets the priority the */
/* error is returned to the tty layer */
if ( data[packet_offset+1] & FTDI_RS_OE ) {
error_flag = TTY_OVERRUN;
dbg("OVERRRUN error");
}
if ( data[packet_offset+1] & FTDI_RS_BI ) {
error_flag = TTY_BREAK;
dbg("BREAK received");
}
if ( data[packet_offset+1] & FTDI_RS_PE ) {
error_flag = TTY_PARITY;
dbg("PARITY error");
}
if ( data[packet_offset+1] & FTDI_RS_FE ) {
error_flag = TTY_FRAME;
dbg("FRAMING error");
}
if (length > 0) {
for (i = 2; i < length+2; i++) {
/* Note that the error flag is duplicated for
every character received since we don't know
which character it applied to */
tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
}
need_flip = 1;
}
#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
/* if a parity error is detected you get status packets forever
until a character is sent without a parity error.
This doesn't work well since the application receives a never
ending stream of bad data - even though new data hasn't been sent.
Therefore I (bill) have taken this out.
However - this might make sense for framing errors and so on
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
so I am leaving the code in for now.
*/
else {
if (error_flag != TTY_NORMAL){
dbg("error_flag is not normal");
/* In this case it is just status - if that is an error send a bad character */
if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
tty_insert_flip_char(tty, 0xff, error_flag);
need_flip = 1;
}
}
#endif
} /* "for(packet_offset=0..." */
/* Low latency */
if (need_flip) {
tty_flip_buffer_push(tty);
}
if (packet_offset < urb->actual_length) {
/* not completely processed - record progress */
priv->rx_processed = packet_offset;
dbg("%s - incomplete, %d bytes processed, %d remain",
__func__, packet_offset,
urb->actual_length - packet_offset);
/* check if we were throttled while processing */
spin_lock_irqsave(&priv->rx_lock, flags);
if (priv->rx_flags & THROTTLED) {
priv->rx_flags |= ACTUALLY_THROTTLED;
spin_unlock_irqrestore(&priv->rx_lock, flags);
dbg("%s - deferring remainder until unthrottled",
return;
}
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* if the port is closed stop trying to read */
/* delay processing of remainder */
schedule_delayed_work(&priv->rx_work, 1);
} else {
dbg("%s - port is closed", __func__);
}
return;
}
/* urb is completely processed */
priv->rx_processed = 0;
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err("%s - failed resubmitting read urb, error %d", __func__, result);
}
return;
} /* ftdi_process_read */
static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
struct ftdi_private *priv = usb_get_serial_port_data(port);
/* break_state = -1 to turn on break, and 0 to turn off break */
/* see drivers/char/tty_io.c to see it used */
/* last_set_data_urb_value NEVER has the break bit set in it */
if (break_state) {
urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
} else {
urb_value = priv->last_set_data_urb_value;