aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2010-05-05 17:45:01 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:42 -0400
commite877048417454b0baca5d4a5aceed72a6602c3be (patch)
treec15539742bdeb84a58cc87abadb679b6ac7d90c3 /drivers/usb
parentd3901a064cfedf892c00704aa4e51d119f04a65e (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.c53
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);