From: Petr Tesarik <ptesa...@suse.cz>

There is a lot of overlap between the two functions (e.g. calculation
of the buffer size), so this removes a bit of code duplication, but
most importantly, a more generic function can be easily reused for
other message types.

Signed-off-by: Petr Tesarik <ptesa...@suse.com>
---
 drivers/usb/serial/cp210x.c | 109 ++++++++++++++++++++------------------------
 1 file changed, 49 insertions(+), 60 deletions(-)

diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 1bae015..69f03b6 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -307,14 +307,17 @@ enum cp210x_request_type {
 #define CONTROL_WRITE_RTS      0x0200
 
 /*
- * cp210x_get_config
- * Reads from the CP210x configuration registers
+ * cp210x_control_msg
+ * Sends a generic control message, taking care of endianness
+ * and error messages.
  * 'size' is specified in bytes.
- * 'data' is a pointer to a pre-allocated array of integers large
- * enough to hold 'size' bytes (with 4 bytes to each integer)
+ * 'data' is a pointer to the input/output buffer. For output, it holds
+ * the data (in host order) to be sent. For input, it receives data from
+ * the device and must be big enough to hold 'size' bytes.
  */
-static int cp210x_get_config(struct usb_serial_port *port, u8 request,
-               unsigned int *data, int size)
+static int cp210x_control_msg(struct usb_serial_port *port, u8 request,
+                             u8 requesttype, u16 value, u32 *data, int size,
+                             int timeout)
 {
        struct usb_serial *serial = port->serial;
        struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
@@ -328,20 +331,22 @@ static int cp210x_get_config(struct usb_serial_port 
*port, u8 request,
        if (!buf)
                return -ENOMEM;
 
-       /* Issue the request, attempting to read 'size' bytes */
-       result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-                               request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
-                               spriv->bInterfaceNumber, buf, size,
-                               USB_CTRL_GET_TIMEOUT);
+       if (!(requesttype & USB_DIR_IN)) {
+               for (i = 0; i < length; i++)
+                       buf[i] = cpu_to_le32(data[i]);
+       }
 
-       /* Convert data into an array of integers */
-       for (i = 0; i < length; i++)
-               data[i] = le32_to_cpu(buf[i]);
+       result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                                request, requesttype, value,
+                                spriv->bInterfaceNumber, buf, size, timeout);
 
-       kfree(buf);
+       if (requesttype & USB_DIR_IN) {
+               for (i = 0; i < length; i++)
+                       data[i] = le32_to_cpu(buf[i]);
+       }
 
        if (result != size) {
-               dev_dbg(&port->dev, "%s - Unable to send config request, 
request=0x%x size=%d result=%d\n",
+               dev_dbg(&port->dev, "%s - Unable to send request, request=0x%x 
size=%d result=%d\n",
                        __func__, request, size, result);
                if (result > 0)
                        result = -EPROTO;
@@ -349,7 +354,23 @@ static int cp210x_get_config(struct usb_serial_port *port, 
u8 request,
                return result;
        }
 
-       return 0;
+       kfree(buf);
+
+       return result;
+}
+
+/*
+ * cp210x_get_config
+ * Reads from the CP210x configuration registers
+ * 'size' is specified in bytes.
+ * 'data' is a pointer to a pre-allocated array of integers large
+ * enough to hold 'size' bytes (with 4 bytes to each integer)
+ */
+static int cp210x_get_config(struct usb_serial_port *port, u8 request,
+               unsigned int *data, int size)
+{
+       return cp210x_control_msg(port, request, REQTYPE_INTERFACE_TO_HOST,
+                               0x0000, data, size, USB_CTRL_GET_TIMEOUT);
 }
 
 /*
@@ -361,48 +382,14 @@ static int cp210x_get_config(struct usb_serial_port 
*port, u8 request,
 static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
-       struct usb_serial *serial = port->serial;
-       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
-       __le32 *buf;
-       int result, i, length;
-
-       /* Number of integers required to contain the array */
-       length = (((size - 1) | 3) + 1) / 4;
-
-       buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       /* Array of integers into bytes */
-       for (i = 0; i < length; i++)
-               buf[i] = cpu_to_le32(data[i]);
-
-       if (size > 2) {
-               result = usb_control_msg(serial->dev,
-                               usb_sndctrlpipe(serial->dev, 0),
-                               request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
-                               spriv->bInterfaceNumber, buf, size,
-                               USB_CTRL_SET_TIMEOUT);
-       } else {
-               result = usb_control_msg(serial->dev,
-                               usb_sndctrlpipe(serial->dev, 0),
-                               request, REQTYPE_HOST_TO_INTERFACE, data[0],
-                               spriv->bInterfaceNumber, NULL, 0,
-                               USB_CTRL_SET_TIMEOUT);
-       }
-
-       kfree(buf);
-
-       if ((size > 2 && result != size) || result < 0) {
-               dev_dbg(&port->dev, "%s - Unable to send request, request=0x%x 
size=%d result=%d\n",
-                       __func__, request, size, result);
-               if (result > 0)
-                       result = -EPROTO;
-
-               return result;
-       }
-
-       return 0;
+       if (size > 2)
+               return cp210x_control_msg(port, request,
+                               REQTYPE_HOST_TO_INTERFACE, 0x0000,
+                               data, size, USB_CTRL_SET_TIMEOUT);
+       else
+               return cp210x_control_msg(port, request,
+                               REQTYPE_HOST_TO_INTERFACE, data[0],
+                               NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 /*
@@ -413,7 +400,9 @@ static int cp210x_set_config(struct usb_serial_port *port, 
u8 request,
 static inline int cp210x_set_config_single(struct usb_serial_port *port,
                u8 request, unsigned int data)
 {
-       return cp210x_set_config(port, request, &data, 2);
+       return cp210x_control_msg(port, request,
+                       REQTYPE_HOST_TO_INTERFACE, data,
+                       NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 /*
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to