USB: ftdi_sio: clean up SIO write support
The original SIO devices require a control byte for every packet written. Clean up the unnecessarily messy implementation of this. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
d3901a064c
commit
e877048417
@ -71,10 +71,6 @@ struct ftdi_private {
|
|||||||
/* the last data state set - needed for doing
|
/* the last data state set - needed for doing
|
||||||
* a break
|
* a break
|
||||||
*/
|
*/
|
||||||
int write_offset; /* This is the offset in the usb data block to
|
|
||||||
* write the serial data - it varies between
|
|
||||||
* devices
|
|
||||||
*/
|
|
||||||
int flags; /* some ASYNC_xxxx flags are supported */
|
int flags; /* some ASYNC_xxxx flags are supported */
|
||||||
unsigned long last_dtr_rts; /* saved modem control outputs */
|
unsigned long last_dtr_rts; /* saved modem control outputs */
|
||||||
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
|
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
|
||||||
@ -1279,7 +1275,6 @@ static void ftdi_determine_type(struct usb_serial_port *port)
|
|||||||
|
|
||||||
/* Assume it is not the original SIO device for now. */
|
/* Assume it is not the original SIO device for now. */
|
||||||
priv->baud_base = 48000000 / 2;
|
priv->baud_base = 48000000 / 2;
|
||||||
priv->write_offset = 0;
|
|
||||||
|
|
||||||
version = le16_to_cpu(udev->descriptor.bcdDevice);
|
version = le16_to_cpu(udev->descriptor.bcdDevice);
|
||||||
interfaces = udev->actconfig->desc.bNumInterfaces;
|
interfaces = udev->actconfig->desc.bNumInterfaces;
|
||||||
@ -1321,7 +1316,6 @@ static void ftdi_determine_type(struct usb_serial_port *port)
|
|||||||
/* Old device. Assume it's the original SIO. */
|
/* Old device. Assume it's the original SIO. */
|
||||||
priv->chip_type = SIO;
|
priv->chip_type = SIO;
|
||||||
priv->baud_base = 12000000 / 16;
|
priv->baud_base = 12000000 / 16;
|
||||||
priv->write_offset = 1;
|
|
||||||
} else if (version < 0x400) {
|
} else if (version < 0x400) {
|
||||||
/* Assume it's an FT8U232AM (or FT8U245AM) */
|
/* Assume it's an FT8U232AM (or FT8U245AM) */
|
||||||
/* (It might be a BM because of the iSerialNumber bug,
|
/* (It might be a BM because of the iSerialNumber bug,
|
||||||
@ -1757,50 +1751,29 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
|
|||||||
{
|
{
|
||||||
struct ftdi_private *priv;
|
struct ftdi_private *priv;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
int data_offset ; /* will be 1 for the SIO and 0 otherwise */
|
int len;
|
||||||
int transfer_size;
|
|
||||||
|
|
||||||
priv = usb_get_serial_port_data(port);
|
priv = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
data_offset = priv->write_offset;
|
len = count;
|
||||||
dbg("data_offset set to %d", data_offset);
|
if (priv->chip_type == SIO && count != 0)
|
||||||
|
len += ((count - 1) / (priv->max_packet_size - 1)) + 1;
|
||||||
|
|
||||||
/* Determine total transfer size */
|
buffer = kmalloc(len, GFP_ATOMIC);
|
||||||
transfer_size = count;
|
|
||||||
if (data_offset > 0) {
|
|
||||||
/* Original sio needs control bytes too... */
|
|
||||||
transfer_size += (data_offset *
|
|
||||||
((count + (priv->max_packet_size - 1 - data_offset)) /
|
|
||||||
(priv->max_packet_size - data_offset)));
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = kmalloc(transfer_size, GFP_ATOMIC);
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
dev_err(&port->dev, "%s - could not allocate buffer\n",
|
dev_err(&port->dev, "%s - could not allocate buffer\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy data */
|
if (priv->chip_type == SIO) {
|
||||||
if (data_offset > 0) {
|
int i, msg_len;
|
||||||
/* Original sio requires control byte at start of
|
|
||||||
each packet. */
|
|
||||||
int user_pktsz = priv->max_packet_size - data_offset;
|
|
||||||
int todo = count;
|
|
||||||
unsigned char *first_byte = buffer;
|
|
||||||
const unsigned char *current_position = src;
|
|
||||||
|
|
||||||
while (todo > 0) {
|
for (i = 0; i < len; i += priv->max_packet_size) {
|
||||||
if (user_pktsz > todo)
|
msg_len = min_t(int, len - i, priv->max_packet_size) - 1;
|
||||||
user_pktsz = todo;
|
buffer[i] = (msg_len << 2) + 1;
|
||||||
/* Write the control byte at the front of the packet*/
|
memcpy(&buffer[i + 1], src, msg_len);
|
||||||
*first_byte = 1 | ((user_pktsz) << 2);
|
src += msg_len;
|
||||||
/* 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 {
|
} else {
|
||||||
memcpy(buffer, src, count);
|
memcpy(buffer, src, count);
|
||||||
|
Loading…
Reference in New Issue
Block a user