diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-05-05 17:45:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:42 -0400 |
commit | e877048417454b0baca5d4a5aceed72a6602c3be (patch) | |
tree | c15539742bdeb84a58cc87abadb679b6ac7d90c3 /drivers/usb | |
parent | d3901a064cfedf892c00704aa4e51d119f04a65e (diff) |
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 53 |
1 files changed, 13 insertions, 40 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a41974e17687..f515f32cde68 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -71,10 +71,6 @@ struct ftdi_private { | |||
71 | /* the last data state set - needed for doing | 71 | /* the last data state set - needed for doing |
72 | * a break | 72 | * a break |
73 | */ | 73 | */ |
74 | int write_offset; /* This is the offset in the usb data block to | ||
75 | * write the serial data - it varies between | ||
76 | * devices | ||
77 | */ | ||
78 | int flags; /* some ASYNC_xxxx flags are supported */ | 74 | int flags; /* some ASYNC_xxxx flags are supported */ |
79 | unsigned long last_dtr_rts; /* saved modem control outputs */ | 75 | unsigned long last_dtr_rts; /* saved modem control outputs */ |
80 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | 76 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ |
@@ -1279,7 +1275,6 @@ static void ftdi_determine_type(struct usb_serial_port *port) | |||
1279 | 1275 | ||
1280 | /* Assume it is not the original SIO device for now. */ | 1276 | /* Assume it is not the original SIO device for now. */ |
1281 | priv->baud_base = 48000000 / 2; | 1277 | priv->baud_base = 48000000 / 2; |
1282 | priv->write_offset = 0; | ||
1283 | 1278 | ||
1284 | version = le16_to_cpu(udev->descriptor.bcdDevice); | 1279 | version = le16_to_cpu(udev->descriptor.bcdDevice); |
1285 | interfaces = udev->actconfig->desc.bNumInterfaces; | 1280 | interfaces = udev->actconfig->desc.bNumInterfaces; |
@@ -1321,7 +1316,6 @@ static void ftdi_determine_type(struct usb_serial_port *port) | |||
1321 | /* Old device. Assume it's the original SIO. */ | 1316 | /* Old device. Assume it's the original SIO. */ |
1322 | priv->chip_type = SIO; | 1317 | priv->chip_type = SIO; |
1323 | priv->baud_base = 12000000 / 16; | 1318 | priv->baud_base = 12000000 / 16; |
1324 | priv->write_offset = 1; | ||
1325 | } else if (version < 0x400) { | 1319 | } else if (version < 0x400) { |
1326 | /* Assume it's an FT8U232AM (or FT8U245AM) */ | 1320 | /* Assume it's an FT8U232AM (or FT8U245AM) */ |
1327 | /* (It might be a BM because of the iSerialNumber bug, | 1321 | /* (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, | |||
1757 | { | 1751 | { |
1758 | struct ftdi_private *priv; | 1752 | struct ftdi_private *priv; |
1759 | unsigned char *buffer; | 1753 | unsigned char *buffer; |
1760 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ | 1754 | int len; |
1761 | int transfer_size; | ||
1762 | 1755 | ||
1763 | priv = usb_get_serial_port_data(port); | 1756 | priv = usb_get_serial_port_data(port); |
1764 | 1757 | ||
1765 | data_offset = priv->write_offset; | 1758 | len = count; |
1766 | dbg("data_offset set to %d", data_offset); | 1759 | if (priv->chip_type == SIO && count != 0) |
1760 | len += ((count - 1) / (priv->max_packet_size - 1)) + 1; | ||
1767 | 1761 | ||
1768 | /* Determine total transfer size */ | 1762 | buffer = kmalloc(len, GFP_ATOMIC); |
1769 | transfer_size = count; | ||
1770 | if (data_offset > 0) { | ||
1771 | /* Original sio needs control bytes too... */ | ||
1772 | transfer_size += (data_offset * | ||
1773 | ((count + (priv->max_packet_size - 1 - data_offset)) / | ||
1774 | (priv->max_packet_size - data_offset))); | ||
1775 | } | ||
1776 | |||
1777 | buffer = kmalloc(transfer_size, GFP_ATOMIC); | ||
1778 | if (!buffer) { | 1763 | if (!buffer) { |
1779 | dev_err(&port->dev, "%s - could not allocate buffer\n", | 1764 | dev_err(&port->dev, "%s - could not allocate buffer\n", |
1780 | __func__); | 1765 | __func__); |
1781 | return -ENOMEM; | 1766 | return -ENOMEM; |
1782 | } | 1767 | } |
1783 | 1768 | ||
1784 | /* Copy data */ | 1769 | if (priv->chip_type == SIO) { |
1785 | if (data_offset > 0) { | 1770 | int i, msg_len; |
1786 | /* Original sio requires control byte at start of | 1771 | |
1787 | each packet. */ | 1772 | for (i = 0; i < len; i += priv->max_packet_size) { |
1788 | int user_pktsz = priv->max_packet_size - data_offset; | 1773 | msg_len = min_t(int, len - i, priv->max_packet_size) - 1; |
1789 | int todo = count; | 1774 | buffer[i] = (msg_len << 2) + 1; |
1790 | unsigned char *first_byte = buffer; | 1775 | memcpy(&buffer[i + 1], src, msg_len); |
1791 | const unsigned char *current_position = src; | 1776 | src += msg_len; |
1792 | |||
1793 | while (todo > 0) { | ||
1794 | if (user_pktsz > todo) | ||
1795 | user_pktsz = todo; | ||
1796 | /* Write the control byte at the front of the packet*/ | ||
1797 | *first_byte = 1 | ((user_pktsz) << 2); | ||
1798 | /* Copy data for packet */ | ||
1799 | memcpy(first_byte + data_offset, | ||
1800 | current_position, user_pktsz); | ||
1801 | first_byte += user_pktsz + data_offset; | ||
1802 | current_position += user_pktsz; | ||
1803 | todo -= user_pktsz; | ||
1804 | } | 1777 | } |
1805 | } else { | 1778 | } else { |
1806 | memcpy(buffer, src, count); | 1779 | memcpy(buffer, src, count); |