[PATCH 2/4] cp210x: Unify code for set/get config control messages
From: Petr Tesarik
Date: Fri Jul 24 2015 - 02:50:34 EST
From: Petr Tesarik <ptesarik@xxxxxxx>
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 <ptesarik@xxxxxxxx>
---
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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/