/*
* composite.c - infrastructure for Composite USB Gadgets
*
* Copyright (C) 2006-2008 David Brownell
*
* 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.
*
* 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.
*
* 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
*/
/* #define VERBOSE_DEBUG */
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/usb/composite.h>
/*
* The code in this file is utility code, used to build a gadget driver
* from one or more "function" drivers, one or more "configuration"
* objects, and a "usb_composite_driver" by gluing them together along
* with the relevant device-wide data.
*/
/* big enough to hold our biggest descriptor */
#define USB_BUFSIZ 512
static struct usb_composite_driver *composite;
/* Some systems will need runtime overrides for the product identifers
* published in the device descriptor, either numbers or strings or both.
* String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
*/
static ushort idVendor;
module_param(idVendor, ushort, 0);
MODULE_PARM_DESC(idVendor, "USB Vendor ID");
static ushort idProduct;
module_param(idProduct, ushort, 0);
MODULE_PARM_DESC(idProduct, "USB Product ID");
static ushort bcdDevice;
module_param(bcdDevice, ushort, 0);
MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
static char *iManufacturer;
module_param(iManufacturer, charp, 0);
MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
static char *iProduct;
module_param(iProduct, charp, 0);
MODULE_PARM_DESC(iProduct, "USB Product string");
static char *iSerialNumber;
module_param(iSerialNumber, charp, 0);
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
/*-------------------------------------------------------------------------*/
/**
* usb_add_function() - add a function to a configuration
* @config: the configuration
* @function: the function being added
* Context: single threaded during gadget setup
*
* After initialization, each configuration must have one or more
* functions added to it. Adding a function involves calling its @bind()
* method to allocate resources such as interface and string identifiers
* and endpoints.
*
* This function returns the value of the function's bind(), which is
* zero for success else a negative errno value.
*/
int __init usb_add_function(struct usb_configuration *config,
struct usb_function *function)
{
int value = -EINVAL;
DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
function->name, function,
config->label, config);
if (!function->set_alt || !function->disable)
goto done;
function->config = config;
list_add_tail(&function->list, &config->functions);
/* REVISIT *require* function->bind? */
if (function->bind) {
value = function->bind(config, function);
if (value < 0) {
list_del(&function->list);
function->config = NULL;
}
} else
value = 0;
/* We allow configurations that don't work at both speeds.
* If we run into a lowspeed Linux system, treat it the same
* as full speed ... it's the function drivers that will need
* to avoid bulk and ISO transfers.
*/
if (!config->fullspeed && function->descriptors)
config->fullspeed = true;
if (!config->highspeed && function->hs_descriptors)
config->highspeed = true;
done:
if (value)
DBG(config->cdev, "adding '%s'/%p --> %d\n",
function->name, function, value);
return value;
}
/**
* usb_function_deactivate - prevent function and gadget enumeration
* @function: the function that isn't yet ready to respond
*
* Blocks response of the gadget driver to host enumeration by
* preventing the data line pullup from being activated. This is
* normally called during @bind() processing to change from the
* initial "ready to respond" state, or when a required resource
* becomes available.
*
* For example, drivers that serve as a passthrough to a userspace
* daemon can block enumeration unless that daemon (such as an OBEX,
* MTP, or print server) is ready to handle host requests.
*
* Not all systems support software control of their USB peripheral
* data pullups.
*
* Returns zero on success, else negative errno.
*/
int usb_function_deactivate(struct usb_function *function)
{
struct usb_composite_dev *cdev = function->config->cdev;
unsigned long flags;
int status = 0;
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->deactivations == 0)
status = usb_gadget_disconnect(cdev->gadget);
if (status == 0)
cdev-