Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754298AbbGXGt1 (ORCPT ); Fri, 24 Jul 2015 02:49:27 -0400 Received: from smtp2.provo.novell.com ([137.65.250.81]:59737 "EHLO smtp2.provo.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754220AbbGXGtU (ORCPT ); Fri, 24 Jul 2015 02:49:20 -0400 From: Petr Tesarik To: Johan Hovold , Greg Kroah-Hartman Cc: Petr Tesarik , linux-usb@vger.kernel.org (open list:USB SERIAL SUBSYSTEM), linux-kernel@vger.kernel.org (open list), Petr Tesarik Subject: [PATCH 2/4] cp210x: Unify code for set/get config control messages Date: Fri, 24 Jul 2015 08:48:09 +0200 Message-Id: <1437720491-28702-3-git-send-email-ptesarik@suse.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1437720491-28702-1-git-send-email-ptesarik@suse.com> References: <1437720491-28702-1-git-send-email-ptesarik@suse.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5714 Lines: 174 From: Petr Tesarik 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 --- 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/