Commit ca2bdf4b authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman
Browse files

USB: gadget: gadget zero cleanups



Clean up gadget zero, using newer APIs and conventions:

 - gadget_is_dualspeed() and gadget_is_otg() ... #ifdef removal

 - Remove many now-needless #includes

 - Use the VERBOSE_DEBUG convention

 - Some whitespace fixes.

 - A few comment updates
 
 - Plus a few other small cleanups:  don't pass gfp_t around when it's
   always going to be GFP_ATOMIC, and do static init of serial number.

Also go to straight GPL; there's no real point in dual licensing this
stuff any more.

Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 2e806f67
Loading
Loading
Loading
Loading
+96 −141
Original line number Diff line number Diff line
/*
 * zero.c -- Gadget Zero, for USB development
 *
 * Copyright (C) 2003-2004 David Brownell
 * Copyright (C) 2003-2007 David Brownell
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The names of the above-listed copyright holders may not be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * ALTERNATIVELY, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") as published by the Free Software
 * Foundation, either version 2 of that License or (at your option) any
 * later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


@@ -57,30 +41,18 @@
 * Many drivers will only have one configuration, letting them be much
 * simpler if they also don't support high speed operation (like this
 * driver does).
 *
 * Why is *this* driver using two configurations, rather than setting up
 * two interfaces with different functions?  To help verify that multiple
 * configuration infrastucture is working correctly; also, so that it can
 * work with low capability USB controllers without four bulk endpoints.
 */

#define DEBUG 1
// #define VERBOSE
/* #define VERBOSE_DEBUG */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/utsname.h>
#include <linux/device.h>
#include <linux/moduleparam.h>

#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>

#include <linux/usb/ch9.h>
#include <linux/usb_gadget.h>
@@ -90,7 +62,7 @@

/*-------------------------------------------------------------------------*/

#define DRIVER_VERSION		"St Patrick's Day 2004"
#define DRIVER_VERSION		"Lughnasadh, 2007"

static const char shortname [] = "zero";
static const char longname [] = "Gadget Zero";
@@ -131,30 +103,16 @@ struct zero_dev {
	struct timer_list	resume;
};

#define xprintk(d,level,fmt,args...) \
	dev_printk(level , &(d)->gadget->dev , fmt , ## args)

#ifdef DEBUG
#define DBG(dev,fmt,args...) \
	xprintk(dev , KERN_DEBUG , fmt , ## args)
#else
#define DBG(dev,fmt,args...) \
	do { } while (0)
#endif /* DEBUG */

#ifdef VERBOSE
#define VDBG	DBG
#else
#define VDBG(dev,fmt,args...) \
	do { } while (0)
#endif /* VERBOSE */

#define ERROR(dev,fmt,args...) \
	xprintk(dev , KERN_ERR , fmt , ## args)
#define WARN(dev,fmt,args...) \
	xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
	xprintk(dev , KERN_INFO , fmt , ## args)
#define DBG(d, fmt, args...) \
	dev_dbg(&(d)->gadget->dev , fmt , ## args)
#define VDBG(d, fmt, args...) \
	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
#define ERROR(d, fmt, args...) \
	dev_err(&(d)->gadget->dev , fmt , ## args)
#define WARN(d, fmt, args...) \
	dev_warn(&(d)->gadget->dev , fmt , ## args)
#define INFO(d, fmt, args...) \
	dev_info(&(d)->gadget->dev , fmt , ## args)

/*-------------------------------------------------------------------------*/

@@ -326,8 +284,6 @@ static const struct usb_descriptor_header *fs_loopback_function [] = {
	NULL,
};

#ifdef	CONFIG_USB_GADGET_DUALSPEED

/*
 * usb 2.0 devices need to expose both high speed and full speed
 * descriptors, unless they only run at full speed.
@@ -383,17 +339,20 @@ static const struct usb_descriptor_header *hs_loopback_function [] = {
};

/* maxpacket and other transfer characteristics vary by speed. */
#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))

#else
static inline struct usb_endpoint_descriptor *
ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
		struct usb_endpoint_descriptor *fs)
{
	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
		return hs;
	return fs;
}

/* if there's no high speed support, maxpacket doesn't change. */
#define ep_desc(g,hs,fs) fs
static char manufacturer[50];

#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
/* default serial number takes at least two packets */
static char serial[] = "0123456789.0123456789.0123456789";

static char				manufacturer [50];
static char				serial [40];

/* static strings, in UTF-8 */
static struct usb_string		strings [] = {
@@ -435,30 +394,29 @@ config_buf (struct usb_gadget *gadget,
	int				is_source_sink;
	int				len;
	const struct usb_descriptor_header **function;
#ifdef CONFIG_USB_GADGET_DUALSPEED
	int				hs = (gadget->speed == USB_SPEED_HIGH);
#endif
	int				hs = 0;

	/* two configurations will always be index 0 and index 1 */
	if (index > 1)
		return -EINVAL;
	is_source_sink = loopdefault ? (index == 1) : (index == 0);

#ifdef CONFIG_USB_GADGET_DUALSPEED
	if (gadget_is_dualspeed(gadget)) {
		hs = (gadget->speed == USB_SPEED_HIGH);
		if (type == USB_DT_OTHER_SPEED_CONFIG)
			hs = !hs;
	}
	if (hs)
		function = is_source_sink
			? hs_source_sink_function
			: hs_loopback_function;
	else
#endif
		function = is_source_sink
			? fs_source_sink_function
			: fs_loopback_function;

	/* for now, don't advertise srp-only devices */
	if (!gadget->is_otg)
	if (!gadget_is_otg(gadget))
		function++;

	len = usb_gadget_config_buf (is_source_sink
@@ -498,6 +456,19 @@ static void free_ep_req (struct usb_ep *ep, struct usb_request *req)

/*-------------------------------------------------------------------------*/

/*
 * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals,
 * this just sinks bulk packets OUT to the peripheral and sources them IN
 * to the host, optionally with specific data patterns.
 *
 * In terms of control messaging, this supports all the standard requests
 * plus two that support control-OUT tests.
 *
 * Note that because this doesn't queue more than one request at a time,
 * some other function must be used to test queueing logic.  The network
 * link (g_ether) is probably the best option for that.
 */

/* optionally require specific source/sink data patterns  */

static int
@@ -534,12 +505,7 @@ check_read_data (
	return 0;
}

static void
reinit_write_data (
	struct zero_dev		*dev,
	struct usb_ep		*ep,
	struct usb_request	*req
)
static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
{
	unsigned	i;
	u8		*buf = req->buf;
@@ -571,7 +537,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
			check_read_data (dev, ep, req);
			memset (req->buf, 0x55, req->length);
		} else
			reinit_write_data (dev, ep, req);
			reinit_write_data(ep, req);
		break;

	/* this endpoint is normally active while we're configured */
@@ -607,8 +573,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
	}
}

static struct usb_request *
source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
static struct usb_request *source_sink_start_ep(struct usb_ep *ep)
{
	struct usb_request	*req;
	int			status;
@@ -621,11 +586,11 @@ source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
	req->complete = source_sink_complete;

	if (strcmp (ep->name, EP_IN_NAME) == 0)
		reinit_write_data (ep->driver_data, ep, req);
		reinit_write_data(ep, req);
	else
		memset (req->buf, 0x55, req->length);

	status = usb_ep_queue (ep, req, gfp_flags);
	status = usb_ep_queue(ep, req, GFP_ATOMIC);
	if (status) {
		struct zero_dev	*dev = ep->driver_data;

@@ -637,8 +602,7 @@ source_sink_start_ep (struct usb_ep *ep, gfp_t gfp_flags)
	return req;
}

static int
set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
static int set_source_sink_config(struct zero_dev *dev)
{
	int			result = 0;
	struct usb_ep		*ep;
@@ -653,8 +617,7 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
			result = usb_ep_enable (ep, d);
			if (result == 0) {
				ep->driver_data = dev;
				if (source_sink_start_ep(ep, gfp_flags)
						!= NULL) {
				if (source_sink_start_ep(ep) != NULL) {
					dev->in_ep = ep;
					continue;
				}
@@ -668,8 +631,7 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
			result = usb_ep_enable (ep, d);
			if (result == 0) {
				ep->driver_data = dev;
				if (source_sink_start_ep(ep, gfp_flags)
						!= NULL) {
				if (source_sink_start_ep(ep) != NULL) {
					dev->out_ep = ep;
					continue;
				}
@@ -743,8 +705,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
	}
}

static int
set_loopback_config (struct zero_dev *dev, gfp_t gfp_flags)
static int set_loopback_config(struct zero_dev *dev)
{
	int			result = 0;
	struct usb_ep		*ep;
@@ -844,8 +805,7 @@ static void zero_reset_config (struct zero_dev *dev)
 * code can do, perhaps by disallowing more than one configuration or
 * by limiting configuration choices (like the pxa2xx).
 */
static int
zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)
static int zero_set_config(struct zero_dev *dev, unsigned number)
{
	int			result = 0;
	struct usb_gadget	*gadget = dev->gadget;
@@ -855,17 +815,17 @@ zero_set_config (struct zero_dev *dev, unsigned number, gfp_t gfp_flags)

	if (gadget_is_sa1100 (gadget) && dev->config) {
		/* tx fifo is full, but we can't clear it...*/
		INFO (dev, "can't change configurations\n");
		ERROR(dev, "can't change configurations\n");
		return -ESPIPE;
	}
	zero_reset_config (dev);

	switch (number) {
	case CONFIG_SOURCE_SINK:
		result = set_source_sink_config (dev, gfp_flags);
		result = set_source_sink_config(dev);
		break;
	case CONFIG_LOOPBACK:
		result = set_loopback_config (dev, gfp_flags);
		result = set_loopback_config(dev);
		break;
	default:
		result = -EINVAL;
@@ -938,19 +898,17 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
			value = min (w_length, (u16) sizeof device_desc);
			memcpy (req->buf, &device_desc, value);
			break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
		case USB_DT_DEVICE_QUALIFIER:
			if (!gadget->is_dualspeed)
			if (!gadget_is_dualspeed(gadget))
				break;
			value = min (w_length, (u16) sizeof dev_qualifier);
			memcpy (req->buf, &dev_qualifier, value);
			break;

		case USB_DT_OTHER_SPEED_CONFIG:
			if (!gadget->is_dualspeed)
			if (!gadget_is_dualspeed(gadget))
				break;
			// FALLTHROUGH
#endif /* CONFIG_USB_GADGET_DUALSPEED */
		case USB_DT_CONFIG:
			value = config_buf (gadget, req->buf,
					w_value >> 8,
@@ -984,7 +942,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
		else
			VDBG (dev, "HNP inactive\n");
		spin_lock (&dev->lock);
		value = zero_set_config (dev, w_value, GFP_ATOMIC);
		value = zero_set_config(dev, w_value);
		spin_unlock (&dev->lock);
		break;
	case USB_REQ_GET_CONFIGURATION:
@@ -1013,7 +971,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
			 * use this "reset the config" shortcut.
			 */
			zero_reset_config (dev);
			zero_set_config (dev, config, GFP_ATOMIC);
			zero_set_config(dev, config);
			value = 0;
		}
		spin_unlock (&dev->lock);
@@ -1207,16 +1165,18 @@ zero_bind (struct usb_gadget *gadget)

	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

#ifdef CONFIG_USB_GADGET_DUALSPEED
	if (gadget_is_dualspeed(gadget)) {
		/* assume ep0 uses the same value for both speeds ... */
		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;

		/* and that all endpoints are dual-speed */
	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
#endif
		hs_source_desc.bEndpointAddress =
				fs_source_desc.bEndpointAddress;
		hs_sink_desc.bEndpointAddress =
				fs_sink_desc.bEndpointAddress;
	}

	if (gadget->is_otg) {
	if (gadget_is_otg(gadget)) {
		otg_descriptor.bmAttributes |= USB_OTG_HNP,
		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
@@ -1301,16 +1261,11 @@ static struct usb_gadget_driver zero_driver = {
};

MODULE_AUTHOR("David Brownell");
MODULE_LICENSE ("Dual BSD/GPL");
MODULE_LICENSE("GPL");


static int __init init (void)
{
	/* a real value would likely come through some id prom
	 * or module option.  this one takes at least two packets.
	 */
	strlcpy (serial, "0123456789.0123456789.0123456789", sizeof serial);

	return usb_gadget_register_driver (&zero_driver);
}
module_init (init);