usb: gadget: patches for v3.9 merge window

finally getting rid of the old ->start()/->stop() methods
 in favor of the better and improved ->udc_start()/->udc_stop().
 
 There were surprisingly quite a few users left, but all of them
 have been converted.
 
 f_mass_storage removed some dead code, which is always great ;-)
 
 There's also a big cleanup to the gadget framework from Sebastian
 which gets us a lot closer to having only function drivers in
 kernel and move over to configfs-based binding.
 
 Other than these, there's the usual set of cleanups: s3c UDCs are
 moving over to devm_regulator_bulk_get() API, at91_udc removed
 an unnecessary check for work_pending() before scheduling and
 there's the removal of an unused variable from uac2_pcm_trigger().
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJRAqbFAAoJEIaOsuA1yqREkXsQAInuD5h4OE4gMQSFWJbYY+it
 BWN3JAIxm5NTKD9cez7d0vQ45v+9qDygBpHP4lsGGjhI0tkOr+nQ/g/sfSi3xbHM
 HQ6/z7Y68pNz9k57ans9NfIt0AuIsHE79tlOx3g+QVvryLHmQSAUzk9ru0VUHw4D
 rSI3Czk3yCA4UnRITxJYpsnmEAZw/M7DwyMANqdNFzZaruMB77phsCWGIM2O0h1T
 lw3sgcBoFcvYodWCzi90NWMA8FccQLMxBg6G+7ViaqGvAPqSuYwNTHJxxUwPHdbI
 o28gQY7gkxZY9MwbnFZ+7jSbpcmzRpYtpgBflubf4iAkv+197lG6I5XyVgfdEZSF
 AF3qi7asrXX/jjFoXASpmphBdCazz6G9bTmtdT3RpV3MKC6fnS1tXImBgreveIWh
 sjhPQCleCCZI2+KLpVOujk3kUVHc9aJ5zbqcNLu03Ux1qqqK0VlZ9bahtip6HQ8H
 GYhEdOmgIAe83CcJeWBdWAoz2c7fzEEvCj+TxxbyB7nE8TRsOYooKrBcfEM1plVy
 qWcXULlhTdD4aWpQLanL8XSamKFvyDk+lEn4803of0eaVpE9gUxKi0fwD+j6UOMV
 iBa7mEx5zIym7gJI4+SlvXIn8fPHfcHGX4BPLASd+G4ndkLIPc2wAb/KqVyIUCXt
 I5K8UNYb0DiuQtxKXg8R
 =PCP4
 -----END PGP SIGNATURE-----

Merge tag 'gadget-for-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:
	usb: gadget: patches for v3.9 merge window

	finally getting rid of the old ->start()/->stop() methods
	in favor of the better and improved ->udc_start()/->udc_stop().

	There were surprisingly quite a few users left, but all of them
	have been converted.

	f_mass_storage removed some dead code, which is always great ;-)

	There's also a big cleanup to the gadget framework from Sebastian
	which gets us a lot closer to having only function drivers in
	kernel and move over to configfs-based binding.

	Other than these, there's the usual set of cleanups: s3c UDCs are
	moving over to devm_regulator_bulk_get() API, at91_udc removed
	an unnecessary check for work_pending() before scheduling and
	there's the removal of an unused variable from uac2_pcm_trigger().
This commit is contained in:
Greg Kroah-Hartman 2013-01-25 09:08:05 -08:00
Родитель a9b8676c17 eeef458766
Коммит cba6c85027
55 изменённых файлов: 1761 добавлений и 1493 удалений

Просмотреть файл

@ -500,6 +500,15 @@ config USB_LIBCOMPOSITE
tristate
depends on USB_GADGET
config USB_F_ACM
tristate
config USB_F_SS_LB
tristate
config USB_U_SERIAL
tristate
choice
tristate "USB Gadget Drivers"
default USB_ETH
@ -524,6 +533,7 @@ choice
config USB_ZERO
tristate "Gadget Zero (DEVELOPMENT)"
select USB_LIBCOMPOSITE
select USB_F_SS_LB
help
Gadget Zero is a two-configuration device. It either sinks and
sources bulk data; or it loops back a configurable number of
@ -750,6 +760,8 @@ config USB_GADGET_TARGET
config USB_G_SERIAL
tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
select USB_U_SERIAL
select USB_F_ACM
select USB_LIBCOMPOSITE
help
The Serial Gadget talks to the Linux-USB generic serial driver.
@ -803,6 +815,8 @@ config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
depends on NET
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_F_ACM
help
This driver provides two functions in one configuration:
a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
@ -818,6 +832,7 @@ config USB_G_NOKIA
tristate "Nokia composite gadget"
depends on PHONET
select USB_LIBCOMPOSITE
select USB_U_SERIAL
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
@ -829,6 +844,8 @@ config USB_G_ACM_MS
tristate "CDC Composite Device (ACM and mass storage)"
depends on BLOCK
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_F_ACM
help
This driver provides two functions in one configuration:
a mass storage, and a CDC ACM (serial port) link.
@ -841,6 +858,8 @@ config USB_G_MULTI
depends on BLOCK && NET
select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_F_ACM
help
The Multifunction Composite Gadget provides Ethernet (RNDIS
and/or CDC Ethernet), mass storage and ACM serial link
@ -916,6 +935,7 @@ config USB_G_DBGP_PRINTK
config USB_G_DBGP_SERIAL
depends on USB_G_DBGP
select USB_U_SERIAL
bool "serial"
help
Userland can interact using /dev/ttyGSxxx.

Просмотреть файл

@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
libcomposite-y += composite.o
libcomposite-y += composite.o functions.o
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o
@ -74,3 +74,9 @@ obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
# USB Functions
obj-$(CONFIG_USB_F_ACM) += f_acm.o
f_ss_lb-y := f_loopback.o f_sourcesink.o
obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.o
obj-$(CONFIG_USB_U_SERIAL) += u_serial.o

Просмотреть файл

@ -40,9 +40,6 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "u_serial.c"
#include "f_acm.c"
#include "f_mass_storage.c"
/*-------------------------------------------------------------------------*/
@ -112,12 +109,15 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
static struct fsg_common fsg_common;
/*-------------------------------------------------------------------------*/
static unsigned char tty_line;
static struct usb_function *f_acm;
static struct usb_function_instance *f_acm_inst;
/*
* We _always_ have both ACM and mass storage functions.
*/
static int __init acm_ms_do_config(struct usb_configuration *c)
{
struct f_serial_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@ -125,16 +125,35 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
f_acm_inst = usb_get_function_instance("acm");
if (IS_ERR(f_acm_inst))
return PTR_ERR(f_acm_inst);
status = acm_bind_config(c, 0);
opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
opts->port_num = tty_line;
f_acm = usb_get_function(f_acm_inst);
if (IS_ERR(f_acm)) {
status = PTR_ERR(f_acm);
goto err_func;
}
status = usb_add_function(c, f_acm);
if (status < 0)
return status;
goto err_conf;
status = fsg_bind_config(c->cdev, c, &fsg_common);
if (status < 0)
return status;
goto err_fsg;
return 0;
err_fsg:
usb_remove_function(c, f_acm);
err_conf:
usb_put_function(f_acm);
err_func:
usb_put_function_instance(f_acm_inst);
return status;
}
static struct usb_configuration acm_ms_config_driver = {
@ -153,7 +172,7 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
void *retp;
/* set up serial link layer */
status = gserial_setup(cdev->gadget, 1);
status = gserial_alloc_line(&tty_line);
if (status < 0)
return status;
@ -189,14 +208,15 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
fail1:
fsg_common_put(&fsg_common);
fail0:
gserial_cleanup();
gserial_free_line(tty_line);
return status;
}
static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
{
gserial_cleanup();
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
gserial_free_line(tty_line);
return 0;
}

Просмотреть файл

@ -1400,15 +1400,16 @@ static int udc_wakeup(struct usb_gadget *gadget)
return 0;
}
static int amd5536_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int amd5536_stop(struct usb_gadget_driver *driver);
static int amd5536_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int amd5536_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
/* gadget operations */
static const struct usb_gadget_ops udc_ops = {
.wakeup = udc_wakeup,
.get_frame = udc_get_frame,
.start = amd5536_start,
.stop = amd5536_stop,
.udc_start = amd5536_udc_start,
.udc_stop = amd5536_udc_stop,
};
/* Setups endpoint parameters, adds endpoints to linked list */
@ -1913,41 +1914,22 @@ static int setup_ep0(struct udc *dev)
}
/* Called by gadget driver to register itself */
static int amd5536_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int amd5536_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct udc *dev = udc;
int retval;
struct udc *dev = to_amd5536_udc(g);
u32 tmp;
if (!driver || !bind || !driver->setup
|| driver->max_speed < USB_SPEED_HIGH)
return -EINVAL;
if (!dev)
return -ENODEV;
if (dev->driver)
return -EBUSY;
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = bind(&dev->gadget, driver);
/* Some gadget drivers use both ep0 directions.
* NOTE: to gadget driver, ep0 is just one endpoint...
*/
dev->ep[UDC_EP0OUT_IX].ep.driver_data =
dev->ep[UDC_EP0IN_IX].ep.driver_data;
if (retval) {
DBG(dev, "binding to %s returning %d\n",
driver->driver.name, retval);
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
return retval;
}
/* get ready for ep0 traffic */
setup_ep0(dev);
@ -1969,14 +1951,9 @@ __acquires(dev->lock)
{
int tmp;
if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
spin_unlock(&dev->lock);
driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
/* empty queues and init hardware */
udc_basic_init(dev);
for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
empty_req_queue(&dev->ep[tmp]);
@ -1984,23 +1961,18 @@ __acquires(dev->lock)
}
/* Called by gadget driver to unregister itself */
static int amd5536_stop(struct usb_gadget_driver *driver)
static int amd5536_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct udc *dev = udc;
unsigned long flags;
struct udc *dev = to_amd5536_udc(g);
unsigned long flags;
u32 tmp;
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
udc_mask_unused_interrupts(dev);
shutdown(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
driver->unbind(&dev->gadget);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
@ -2009,9 +1981,6 @@ static int amd5536_stop(struct usb_gadget_driver *driver)
tmp |= AMD_BIT(UDC_DEVCTL_SD);
writel(tmp, &dev->regs->ctl);
DBG(dev, "%s: unregistered\n", driver->driver.name);
return 0;
}

Просмотреть файл

@ -563,6 +563,8 @@ struct udc {
u16 cur_alt;
};
#define to_amd5536_udc(g) (container_of((g), struct udc, gadget))
/* setup request data */
union udc_setup_data {
u32 data[2];

Просмотреть файл

@ -1621,8 +1621,7 @@ static void at91_vbus_timer(unsigned long data)
* bus such as i2c or spi which may sleep, so schedule some work
* to read the vbus gpio
*/
if (!work_pending(&udc->vbus_timer_work))
schedule_work(&udc->vbus_timer_work);
schedule_work(&udc->vbus_timer_work);
}
static int at91_start(struct usb_gadget *gadget,
@ -1739,7 +1738,7 @@ static int at91udc_probe(struct platform_device *pdev)
/* rm9200 needs manual D+ pullup; off by default */
if (cpu_is_at91rm9200()) {
if (gpio_is_valid(udc->board.pullup_pin)) {
if (!gpio_is_valid(udc->board.pullup_pin)) {
DBG("no D+ pullup?\n");
retval = -ENODEV;
goto fail0;

Просмотреть файл

@ -42,9 +42,6 @@ USB_GADGET_COMPOSITE_OPTIONS();
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "u_serial.c"
#include "f_acm.c"
#include "f_ecm.c"
#include "u_ether.c"
@ -108,12 +105,16 @@ static struct usb_gadget_strings *dev_strings[] = {
static u8 hostaddr[ETH_ALEN];
/*-------------------------------------------------------------------------*/
static struct usb_function *f_acm;
static struct usb_function_instance *fi_serial;
static unsigned char tty_line;
/*
* We _always_ have both CDC ECM and CDC ACM functions.
*/
static int __init cdc_do_config(struct usb_configuration *c)
{
struct f_serial_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@ -125,11 +126,26 @@ static int __init cdc_do_config(struct usb_configuration *c)
if (status < 0)
return status;
status = acm_bind_config(c, 0);
if (status < 0)
return status;
fi_serial = usb_get_function_instance("acm");
if (IS_ERR(fi_serial))
return PTR_ERR(fi_serial);
opts = container_of(fi_serial, struct f_serial_opts, func_inst);
opts->port_num = tty_line;
f_acm = usb_get_function(fi_serial);
if (IS_ERR(f_acm))
goto err_func_acm;
status = usb_add_function(c, f_acm);
if (status)
goto err_conf;
return 0;
err_conf:
usb_put_function(f_acm);
err_func_acm:
usb_put_function_instance(fi_serial);
return status;
}
static struct usb_configuration cdc_config_driver = {
@ -158,7 +174,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return status;
/* set up serial link layer */
status = gserial_setup(cdev->gadget, 1);
status = gserial_alloc_line(&tty_line);
if (status < 0)
goto fail0;
@ -184,7 +200,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return 0;
fail1:
gserial_cleanup();
gserial_free_line(tty_line);
fail0:
gether_cleanup();
return status;
@ -192,7 +208,9 @@ fail0:
static int __exit cdc_unbind(struct usb_composite_dev *cdev)
{
gserial_cleanup();
usb_put_function(f_acm);
usb_put_function_instance(fi_serial);
gserial_free_line(tty_line);
gether_cleanup();
return 0;
}

Просмотреть файл

@ -28,6 +28,12 @@
* with the relevant device-wide data.
*/
static struct usb_gadget_strings **get_containers_gs(
struct usb_gadget_string_container *uc)
{
return (struct usb_gadget_strings **)uc->stash;
}
/**
* next_ep_desc() - advance to the next EP descriptor
* @t: currect pointer within descriptor array
@ -215,6 +221,18 @@ done:
}
EXPORT_SYMBOL_GPL(usb_add_function);
void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
{
if (f->disable)
f->disable(f);
bitmap_zero(f->endpoints, 32);
list_del(&f->list);
if (f->unbind)
f->unbind(c, f);
}
EXPORT_SYMBOL_GPL(usb_remove_function);
/**
* usb_function_deactivate - prevent function and gadget enumeration
* @function: the function that isn't yet ready to respond
@ -320,6 +338,25 @@ int usb_interface_id(struct usb_configuration *config,
}
EXPORT_SYMBOL_GPL(usb_interface_id);
static u8 encode_bMaxPower(enum usb_device_speed speed,
struct usb_configuration *c)
{
unsigned val;
if (c->MaxPower)
val = c->MaxPower;
else
val = CONFIG_USB_GADGET_VBUS_DRAW;
if (!val)
return 0;
switch (speed) {
case USB_SPEED_SUPER:
return DIV_ROUND_UP(val, 8);
default:
return DIV_ROUND_UP(val, 2);
};
}
static int config_buf(struct usb_configuration *config,
enum usb_device_speed speed, void *buf, u8 type)
{
@ -339,7 +376,7 @@ static int config_buf(struct usb_configuration *config,
c->bConfigurationValue = config->bConfigurationValue;
c->iConfiguration = config->iConfiguration;
c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2);
c->bMaxPower = encode_bMaxPower(speed, config);
/* There may be e.g. OTG descriptors */
if (config->descriptors) {
@ -656,7 +693,7 @@ static int set_config(struct usb_composite_dev *cdev,
}
/* when we return, be sure our power usage is valid */
power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
done:
usb_gadget_vbus_draw(gadget, power);
if (result >= 0 && cdev->delayed_status)
@ -664,6 +701,31 @@ done:
return result;
}
int usb_add_config_only(struct usb_composite_dev *cdev,
struct usb_configuration *config)
{
struct usb_configuration *c;
if (!config->bConfigurationValue)
return -EINVAL;
/* Prevent duplicate configuration identifiers */
list_for_each_entry(c, &cdev->configs, list) {
if (c->bConfigurationValue == config->bConfigurationValue)
return -EBUSY;
}
config->cdev = cdev;
list_add_tail(&config->list, &cdev->configs);
INIT_LIST_HEAD(&config->functions);
config->next_interface_id = 0;
memset(config->interface, 0, sizeof(config->interface));
return 0;
}
EXPORT_SYMBOL_GPL(usb_add_config_only);
/**
* usb_add_config() - add a configuration to a device.
* @cdev: wraps the USB gadget
@ -684,30 +746,18 @@ int usb_add_config(struct usb_composite_dev *cdev,
int (*bind)(struct usb_configuration *))
{
int status = -EINVAL;
struct usb_configuration *c;
if (!bind)
goto done;
DBG(cdev, "adding config #%u '%s'/%p\n",
config->bConfigurationValue,
config->label, config);
if (!config->bConfigurationValue || !bind)
status = usb_add_config_only(cdev, config);
if (status)
goto done;
/* Prevent duplicate configuration identifiers */
list_for_each_entry(c, &cdev->configs, list) {
if (c->bConfigurationValue == config->bConfigurationValue) {
status = -EBUSY;
goto done;
}
}
config->cdev = cdev;
list_add_tail(&config->list, &cdev->configs);
INIT_LIST_HEAD(&config->functions);
config->next_interface_id = 0;
memset(config->interface, 0, sizeof(config->interface));
status = bind(config);
if (status < 0) {
while (!list_empty(&config->functions)) {
@ -860,6 +910,7 @@ static int get_string(struct usb_composite_dev *cdev,
void *buf, u16 language, int id)
{
struct usb_composite_driver *composite = cdev->driver;
struct usb_gadget_string_container *uc;
struct usb_configuration *c;
struct usb_function *f;
int len;
@ -892,6 +943,12 @@ static int get_string(struct usb_composite_dev *cdev,
collect_langs(sp, s->wData);
}
}
list_for_each_entry(uc, &cdev->gstrings, list) {
struct usb_gadget_strings **sp;
sp = get_containers_gs(uc);
collect_langs(sp, s->wData);
}
for (len = 0; len <= 126 && s->wData[len]; len++)
continue;
@ -902,6 +959,15 @@ static int get_string(struct usb_composite_dev *cdev,
return s->bLength;
}
list_for_each_entry(uc, &cdev->gstrings, list) {
struct usb_gadget_strings **sp;
sp = get_containers_gs(uc);
len = lookup_string(sp, buf, language, id);
if (len > 0)
return len;
}
/* String IDs are device-scoped, so we look up each string
* table we're told about. These lookups are infrequent;
* simpler-is-better here.
@ -987,6 +1053,119 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
}
EXPORT_SYMBOL_GPL(usb_string_ids_tab);
static struct usb_gadget_string_container *copy_gadget_strings(
struct usb_gadget_strings **sp, unsigned n_gstrings,
unsigned n_strings)
{
struct usb_gadget_string_container *uc;
struct usb_gadget_strings **gs_array;
struct usb_gadget_strings *gs;
struct usb_string *s;
unsigned mem;
unsigned n_gs;
unsigned n_s;
void *stash;
mem = sizeof(*uc);
mem += sizeof(void *) * (n_gstrings + 1);
mem += sizeof(struct usb_gadget_strings) * n_gstrings;
mem += sizeof(struct usb_string) * (n_strings + 1) * (n_gstrings);
uc = kmalloc(mem, GFP_KERNEL);
if (!uc)
return ERR_PTR(-ENOMEM);
gs_array = get_containers_gs(uc);
stash = uc->stash;
stash += sizeof(void *) * (n_gstrings + 1);
for (n_gs = 0; n_gs < n_gstrings; n_gs++) {
struct usb_string *org_s;
gs_array[n_gs] = stash;
gs = gs_array[n_gs];
stash += sizeof(struct usb_gadget_strings);
gs->language = sp[n_gs]->language;
gs->strings = stash;
org_s = sp[n_gs]->strings;
for (n_s = 0; n_s < n_strings; n_s++) {
s = stash;
stash += sizeof(struct usb_string);
if (org_s->s)
s->s = org_s->s;
else
s->s = "";
org_s++;
}
s = stash;
s->s = NULL;
stash += sizeof(struct usb_string);
}
gs_array[n_gs] = NULL;
return uc;
}
/**
* usb_gstrings_attach() - attach gadget strings to a cdev and assign ids
* @cdev: the device whose string descriptor IDs are being allocated
* and attached.
* @sp: an array of usb_gadget_strings to attach.
* @n_strings: number of entries in each usb_strings array (sp[]->strings)
*
* This function will create a deep copy of usb_gadget_strings and usb_string
* and attach it to the cdev. The actual string (usb_string.s) will not be
* copied but only a referenced will be made. The struct usb_gadget_strings
* array may contain multiple languges and should be NULL terminated.
* The ->language pointer of each struct usb_gadget_strings has to contain the
* same amount of entries.
* For instance: sp[0] is en-US, sp[1] is es-ES. It is expected that the first
* usb_string entry of es-ES containts the translation of the first usb_string
* entry of en-US. Therefore both entries become the same id assign.
*/
struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
struct usb_gadget_strings **sp, unsigned n_strings)
{
struct usb_gadget_string_container *uc;
struct usb_gadget_strings **n_gs;
unsigned n_gstrings = 0;
unsigned i;
int ret;
for (i = 0; sp[i]; i++)
n_gstrings++;
if (!n_gstrings)
return ERR_PTR(-EINVAL);
uc = copy_gadget_strings(sp, n_gstrings, n_strings);
if (IS_ERR(uc))
return ERR_PTR(PTR_ERR(uc));
n_gs = get_containers_gs(uc);
ret = usb_string_ids_tab(cdev, n_gs[0]->strings);
if (ret)
goto err;
for (i = 1; i < n_gstrings; i++) {
struct usb_string *m_s;
struct usb_string *s;
unsigned n;
m_s = n_gs[0]->strings;
s = n_gs[i]->strings;
for (n = 0; n < n_strings; n++) {
s->id = m_s->id;
s++;
m_s++;
}
}
list_add_tail(&uc->list, &cdev->gstrings);
return n_gs[0]->strings;
err:
kfree(uc);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(usb_gstrings_attach);
/**
* usb_string_ids_n() - allocate unused string IDs in batch
* @c: the device whose string descriptor IDs are being allocated
@ -1033,7 +1212,7 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
* housekeeping for the gadget function we're implementing. Most of
* the work is in config and function specific setup.
*/
static int
int
composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
@ -1300,7 +1479,7 @@ done:
return value;
}
static void composite_disconnect(struct usb_gadget *gadget)
void composite_disconnect(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
unsigned long flags;
@ -1330,8 +1509,7 @@ static ssize_t composite_show_suspended(struct device *dev,
static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL);
static void
composite_unbind(struct usb_gadget *gadget)
static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
@ -1348,19 +1526,21 @@ composite_unbind(struct usb_gadget *gadget)
struct usb_configuration, list);
remove_config(cdev, c);
}
if (cdev->driver->unbind)
if (cdev->driver->unbind && unbind_driver)
cdev->driver->unbind(cdev);
if (cdev->req) {
kfree(cdev->req->buf);
usb_ep_free_request(gadget->ep0, cdev->req);
}
device_remove_file(&gadget->dev, &dev_attr_suspended);
composite_dev_cleanup(cdev);
kfree(cdev->def_manufacturer);
kfree(cdev);
set_gadget_data(gadget, NULL);
}
static void composite_unbind(struct usb_gadget *gadget)
{
__composite_unbind(gadget, true);
}
static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
const struct usb_device_descriptor *old)
{
@ -1399,34 +1579,25 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
new->iProduct = iProduct;
}
static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv)
int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *cdev)
{
return container_of(gdrv, struct usb_composite_driver, gadget_driver);
}
static int composite_bind(struct usb_gadget *gadget,
struct usb_gadget_driver *gdriver)
{
struct usb_composite_dev *cdev;
struct usb_composite_driver *composite = to_cdriver(gdriver);
int status = -ENOMEM;
cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
if (!cdev)
return status;
spin_lock_init(&cdev->lock);
cdev->gadget = gadget;
set_gadget_data(gadget, cdev);
INIT_LIST_HEAD(&cdev->configs);
struct usb_gadget *gadget = cdev->gadget;
int ret = -ENOMEM;
/* preallocate control response and buffer */
cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
if (!cdev->req)
goto fail;
return -ENOMEM;
cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
if (!cdev->req->buf)
goto fail;
ret = device_create_file(&gadget->dev, &dev_attr_suspended);
if (ret)
goto fail_dev;
cdev->req->complete = composite_setup_complete;
gadget->ep0->driver_data = cdev;
@ -1444,7 +1615,51 @@ static int composite_bind(struct usb_gadget *gadget,
* we force endpoints to start unassigned; few controller
* drivers will zero ep->driver_data.
*/
usb_ep_autoconfig_reset(cdev->gadget);
usb_ep_autoconfig_reset(gadget);
return 0;
fail_dev:
kfree(cdev->req->buf);
fail:
usb_ep_free_request(gadget->ep0, cdev->req);
cdev->req = NULL;
return ret;
}
void composite_dev_cleanup(struct usb_composite_dev *cdev)
{
struct usb_gadget_string_container *uc, *tmp;
list_for_each_entry_safe(uc, tmp, &cdev->gstrings, list) {
list_del(&uc->list);
kfree(uc);
}
if (cdev->req) {
kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
}
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
}
static int composite_bind(struct usb_gadget *gadget,
struct usb_gadget_driver *gdriver)
{
struct usb_composite_dev *cdev;
struct usb_composite_driver *composite = to_cdriver(gdriver);
int status = -ENOMEM;
cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
if (!cdev)
return status;
spin_lock_init(&cdev->lock);
cdev->gadget = gadget;
set_gadget_data(gadget, cdev);
INIT_LIST_HEAD(&cdev->configs);
INIT_LIST_HEAD(&cdev->gstrings);
status = composite_dev_prepare(composite, cdev);
if (status)
goto fail;
/* composite gadget needs to assign strings for whole device (like
* serial number), register function drivers, potentially update
@ -1460,16 +1675,11 @@ static int composite_bind(struct usb_gadget *gadget,
if (composite->needs_serial && !cdev->desc.iSerialNumber)
WARNING(cdev, "userspace failed to provide iSerialNumber\n");
/* finish up */
status = device_create_file(&gadget->dev, &dev_attr_suspended);
if (status)
goto fail;
INFO(cdev, "%s ready\n", composite->name);
return 0;
fail:
composite_unbind(gadget);
__composite_unbind(gadget, false);
return status;
}
@ -1518,10 +1728,10 @@ composite_resume(struct usb_gadget *gadget)
f->resume(f);
}
maxpower = cdev->config->bMaxPower;
maxpower = cdev->config->MaxPower;
usb_gadget_vbus_draw(gadget, maxpower ?
(2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW);
maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
}
cdev->suspended = 0;

Просмотреть файл

@ -13,9 +13,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#ifdef CONFIG_USB_G_DBGP_SERIAL
#include "u_serial.c"
#endif
#include "u_serial.h"
#define DRIVER_VENDOR_ID 0x0525 /* NetChip */
#define DRIVER_PRODUCT_ID 0xc0de /* undefined */
@ -233,6 +231,10 @@ static void dbgp_unbind(struct usb_gadget *gadget)
gadget->ep0->driver_data = NULL;
}
#ifdef CONFIG_USB_G_DBGP_SERIAL
static unsigned char tty_line;
#endif
static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
{
int stp;
@ -270,7 +272,7 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
dbgp.serial->in->desc = &i_desc;
dbgp.serial->out->desc = &o_desc;
if (gserial_setup(gadget, 1) < 0) {
if (gserial_alloc_line(&tty_line)) {
stp = 3;
goto fail_3;
}
@ -379,7 +381,7 @@ static int dbgp_setup(struct usb_gadget *gadget,
#ifdef CONFIG_USB_G_DBGP_PRINTK
err = dbgp_enable_ep();
#else
err = gserial_connect(dbgp.serial, 0);
err = gserial_connect(dbgp.serial, tty_line);
#endif
if (err < 0)
goto fail;
@ -422,7 +424,7 @@ static void __exit dbgp_exit(void)
{
usb_gadget_unregister_driver(&dbgp_driver);
#ifdef CONFIG_USB_G_DBGP_SERIAL
gserial_cleanup();
gserial_free_line(tty_line);
#endif
}

Просмотреть файл

@ -16,7 +16,9 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/err.h>
#include "u_serial.h"
#include "gadget_chips.h"
@ -283,7 +285,6 @@ static struct usb_string acm_string_defs[] = {
[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
[ACM_DATA_IDX].s = "CDC ACM Data",
[ACM_IAD_IDX ].s = "CDC Serial",
{ /* ZEROES END LIST */ },
};
static struct usb_gadget_strings acm_string_table = {
@ -605,9 +606,23 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_acm *acm = func_to_acm(f);
struct usb_string *us;
int status;
struct usb_ep *ep;
/* REVISIT might want instance-specific strings to help
* distinguish instances ...
*/
/* maybe allocate device-global string IDs, and patch descriptors */
us = usb_gstrings_attach(cdev, acm_strings,
ARRAY_SIZE(acm_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
acm_control_interface_desc.iInterface = us[ACM_CTRL_IDX].id;
acm_data_interface_desc.iInterface = us[ACM_DATA_IDX].id;
acm_iad_descriptor.iFunction = us[ACM_IAD_IDX].id;
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
@ -700,24 +715,42 @@ fail:
return status;
}
static struct f_acm *acm_alloc_basic_func(void)
{
struct f_acm *acm;
acm = kzalloc(sizeof(*acm), GFP_KERNEL);
if (!acm)
return NULL;
spin_lock_init(&acm->lock);
acm->port.connect = acm_connect;
acm->port.disconnect = acm_disconnect;
acm->port.send_break = acm_send_break;
acm->port.func.name = "acm";
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;
acm->port.func.set_alt = acm_set_alt;
acm->port.func.setup = acm_setup;
acm->port.func.disable = acm_disable;
return acm;
}
#ifdef USB_FACM_INCLUDED
static void
acm_unbind(struct usb_configuration *c, struct usb_function *f)
acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
acm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
gs_free_req(acm->notify, acm->notify_req);
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);
}
/* Some controllers can't support CDC ACM ... */
static inline bool can_support_cdc(struct usb_configuration *c)
{
/* everything else is *probably* fine ... */
return true;
}
/**
* acm_bind_config - add a CDC ACM function to a configuration
* @c: the configuration to support the CDC ACM instance
@ -726,58 +759,80 @@ static inline bool can_support_cdc(struct usb_configuration *c)
*
* Returns zero on success, else negative errno.
*
* Caller must have called @gserial_setup() with enough ports to
* handle all the ones it binds. Caller is also responsible
* for calling @gserial_cleanup() before module unload.
*/
int acm_bind_config(struct usb_configuration *c, u8 port_num)
{
struct f_acm *acm;
int status;
if (!can_support_cdc(c))
return -EINVAL;
/* REVISIT might want instance-specific strings to help
* distinguish instances ...
*/
/* maybe allocate device-global string IDs, and patch descriptors */
if (acm_string_defs[0].id == 0) {
status = usb_string_ids_tab(c->cdev, acm_string_defs);
if (status < 0)
return status;
acm_control_interface_desc.iInterface =
acm_string_defs[ACM_CTRL_IDX].id;
acm_data_interface_desc.iInterface =
acm_string_defs[ACM_DATA_IDX].id;
acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
}
/* allocate and initialize one new instance */
acm = kzalloc(sizeof *acm, GFP_KERNEL);
acm = acm_alloc_basic_func();
if (!acm)
return -ENOMEM;
spin_lock_init(&acm->lock);
acm->port_num = port_num;
acm->port.connect = acm_connect;
acm->port.disconnect = acm_disconnect;
acm->port.send_break = acm_send_break;
acm->port.func.name = "acm";
acm->port.func.strings = acm_strings;
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;
acm->port.func.unbind = acm_unbind;
acm->port.func.set_alt = acm_set_alt;
acm->port.func.setup = acm_setup;
acm->port.func.disable = acm_disable;
acm->port.func.unbind = acm_old_unbind;
status = usb_add_function(c, &acm->port.func);
if (status)
kfree(acm);
return status;
}
#else
static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
acm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
}
static void acm_free_func(struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
kfree(acm);
}
static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
{
struct f_serial_opts *opts;
struct f_acm *acm;
acm = acm_alloc_basic_func();
if (!acm)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_serial_opts, func_inst);
acm->port_num = opts->port_num;
acm->port.func.unbind = acm_unbind;
acm->port.func.free_func = acm_free_func;
return &acm->port.func;
}
static void acm_free_instance(struct usb_function_instance *fi)
{
struct f_serial_opts *opts;
opts = container_of(fi, struct f_serial_opts, func_inst);
kfree(opts);
}
static struct usb_function_instance *acm_alloc_instance(void)
{
struct f_serial_opts *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = acm_free_instance;
return &opts->func_inst;
}
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
MODULE_LICENSE("GPL");
#endif

Просмотреть файл

@ -1103,8 +1103,8 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
return 0;
for (;;) {
char *end, *eq, *comma;
unsigned long value;
char *eq, *comma;
/* Option limit */
comma = strchr(opts, ',');
@ -1120,8 +1120,7 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
*eq = 0;
/* Parse value */
value = simple_strtoul(eq + 1, &end, 0);
if (unlikely(*end != ',' && *end != 0)) {
if (kstrtoul(eq + 1, 0, &value)) {
pr_err("%s: invalid value: %s\n", opts, eq + 1);
return -EINVAL;
}

Просмотреть файл

@ -15,10 +15,11 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/usb/composite.h>
#include "g_zero.h"
#include "gadget_chips.h"
/*
* LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
@ -44,9 +45,8 @@ static inline struct f_loopback *func_to_loop(struct usb_function *f)
return container_of(f, struct f_loopback, function);
}
static unsigned qlen = 32;
module_param(qlen, uint, 0);
MODULE_PARM_DESC(qlenn, "depth of loopback queue");
static unsigned qlen;
static unsigned buflen;
/*-------------------------------------------------------------------------*/
@ -171,8 +171,7 @@ static struct usb_gadget_strings *loopback_strings[] = {
/*-------------------------------------------------------------------------*/
static int __init
loopback_bind(struct usb_configuration *c, struct usb_function *f)
static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_loopback *loop = func_to_loop(f);
@ -185,6 +184,12 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
return id;
loopback_intf.bInterfaceNumber = id;
id = usb_string_id(cdev);
if (id < 0)
return id;
strings_loopback[0].id = id;
loopback_intf.iInterface = id;
/* allocate endpoints */
loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
@ -223,8 +228,7 @@ autoconf_fail:
return 0;
}
static void
loopback_unbind(struct usb_configuration *c, struct usb_function *f)
static void lb_free_func(struct usb_function *f)
{
usb_free_all_descriptors(f);
kfree(func_to_loop(f));
@ -366,63 +370,64 @@ static void loopback_disable(struct usb_function *f)
disable_loopback(loop);
}
/*-------------------------------------------------------------------------*/
static int __init loopback_bind_config(struct usb_configuration *c)
static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
{
struct f_loopback *loop;
int status;
struct f_lb_opts *lb_opts;
loop = kzalloc(sizeof *loop, GFP_KERNEL);
if (!loop)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
lb_opts = container_of(fi, struct f_lb_opts, func_inst);
buflen = lb_opts->bulk_buflen;
qlen = lb_opts->qlen;
if (!qlen)
qlen = 32;
loop->function.name = "loopback";
loop->function.bind = loopback_bind;
loop->function.unbind = loopback_unbind;
loop->function.set_alt = loopback_set_alt;
loop->function.disable = loopback_disable;
loop->function.strings = loopback_strings;
status = usb_add_function(c, &loop->function);
if (status)
kfree(loop);
return status;
loop->function.free_func = lb_free_func;
return &loop->function;
}
static struct usb_configuration loopback_driver = {
.label = "loopback",
.strings = loopback_strings,
.bConfigurationValue = 2,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
/* .iConfiguration = DYNAMIC */
};
/**
* loopback_add - add a loopback testing configuration to a device
* @cdev: the device to support the loopback configuration
*/
int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
static void lb_free_instance(struct usb_function_instance *fi)
{
int id;
struct f_lb_opts *lb_opts;
/* allocate string ID(s) */
id = usb_string_id(cdev);
if (id < 0)
return id;
strings_loopback[0].id = id;
loopback_intf.iInterface = id;
loopback_driver.iConfiguration = id;
/* support autoresume for remote wakeup testing */
if (autoresume)
loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
loopback_driver.descriptors = otg_desc;
loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return usb_add_config(cdev, &loopback_driver, loopback_bind_config);
lb_opts = container_of(fi, struct f_lb_opts, func_inst);
kfree(lb_opts);
}
static struct usb_function_instance *loopback_alloc_instance(void)
{
struct f_lb_opts *lb_opts;
lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
if (!lb_opts)
return ERR_PTR(-ENOMEM);
lb_opts->func_inst.free_func_inst = lb_free_instance;
return &lb_opts->func_inst;
}
DECLARE_USB_FUNCTION(Loopback, loopback_alloc_instance, loopback_alloc);
int __init lb_modinit(void)
{
int ret;
ret = usb_function_register(&Loopbackusb_func);
if (ret)
return ret;
return ret;
}
void __exit lb_modexit(void)
{
usb_function_unregister(&Loopbackusb_func);
}
MODULE_LICENSE("GPL");

Просмотреть файл

@ -246,20 +246,6 @@ struct fsg_operations {
* set).
*/
int (*thread_exits)(struct fsg_common *common);
/*
* Called prior to ejection. Negative return means error,
* zero means to continue with ejection, positive means not to
* eject.
*/
int (*pre_eject)(struct fsg_common *common,
struct fsg_lun *lun, int num);
/*
* Called after ejection. Negative return means error, zero
* or positive is just a success.
*/
int (*post_eject)(struct fsg_common *common,
struct fsg_lun *lun, int num);
};
/* Data shared by all the FSG instances. */
@ -1374,26 +1360,13 @@ static int do_start_stop(struct fsg_common *common)
if (!loej)
return 0;
/* Simulate an unload/eject */
if (common->ops && common->ops->pre_eject) {
int r = common->ops->pre_eject(common, curlun,
curlun - common->luns);
if (unlikely(r < 0))
return r;
else if (r)
return 0;
}
up_read(&common->filesem);
down_write(&common->filesem);
fsg_lun_close(curlun);
up_write(&common->filesem);
down_read(&common->filesem);
return common->ops && common->ops->post_eject
? min(0, common->ops->post_eject(common, curlun,
curlun - common->luns))
: 0;
return 0;
}
static int do_prevent_allow(struct fsg_common *common)
@ -1718,7 +1691,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
int needs_medium, const char *name)
{
int i;
int lun = common->cmnd[1] >> 5;
unsigned int lun = common->cmnd[1] >> 5;
static const char dirletter[4] = {'u', 'o', 'i', 'n'};
char hdlen[20];
struct fsg_lun *curlun;
@ -1784,7 +1757,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
/* Check that the LUN values are consistent */
if (common->lun != lun)
DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n",
DBG(common, "using LUN %u from CBW, not LUN %u from CDB\n",
common->lun, lun);
/* Check the LUN */
@ -1804,7 +1777,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
*/
if (common->cmnd[0] != INQUIRY &&
common->cmnd[0] != REQUEST_SENSE) {
DBG(common, "unsupported LUN %d\n", common->lun);
DBG(common, "unsupported LUN %u\n", common->lun);
return -EINVAL;
}
}
@ -2196,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
if (common->data_size == 0)
common->data_dir = DATA_DIR_NONE;
common->lun = cbw->Lun;
if (common->lun >= 0 && common->lun < common->nluns)
if (common->lun < common->nluns)
common->curlun = &common->luns[common->lun];
else
common->curlun = NULL;

Просмотреть файл

@ -56,8 +56,9 @@ struct f_ncm {
u8 notify_state;
bool is_open;
struct ndp_parser_opts *parser_opts;
const struct ndp_parser_opts *parser_opts;
bool is_crc;
u32 ndp_sign;
/*
* for notification, it is accessed from both
@ -390,8 +391,8 @@ struct ndp_parser_opts {
.next_fp_index = 2, \
}
static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
static const struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
{
@ -732,8 +733,7 @@ static int ncm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
default:
goto invalid;
}
ncm->parser_opts->ndp_sign &= ~NCM_NDP_HDR_CRC_MASK;
ncm->parser_opts->ndp_sign |= ndp_hdr_crc;
ncm->ndp_sign = ncm->parser_opts->ndp_sign | ndp_hdr_crc;
value = 0;
break;
}
@ -875,7 +875,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
int ndp_align;
int ndp_pad;
unsigned max_size = ncm->port.fixed_in_len;
struct ndp_parser_opts *opts = ncm->parser_opts;
const struct ndp_parser_opts *opts = ncm->parser_opts;
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
@ -921,7 +921,7 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
tmp = (void *)tmp + ndp_pad;
/* NDP */
put_unaligned_le32(opts->ndp_sign, tmp); /* dwSignature */
put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
tmp += 2;
/* wLength */
put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
@ -965,7 +965,7 @@ static int ncm_unwrap_ntb(struct gether *port,
struct sk_buff *skb2;
int ret = -EINVAL;
unsigned max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
struct ndp_parser_opts *opts = ncm->parser_opts;
const struct ndp_parser_opts *opts = ncm->parser_opts;
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
int dgram_counter;
@ -1002,7 +1002,7 @@ static int ncm_unwrap_ntb(struct gether *port,
/* walk through NDP */
tmp = ((void *)skb->data) + index;
if (get_unaligned_le32(tmp) != opts->ndp_sign) {
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
goto err;
}

Просмотреть файл

@ -406,10 +406,6 @@ static inline bool can_support_obex(struct usb_configuration *c)
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
* Caller must have called @gserial_setup() with enough ports to
* handle all the ones it binds. Caller is also responsible
* for calling @gserial_cleanup() before module unload.
*/
int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
{

Просмотреть файл

@ -260,10 +260,6 @@ gser_unbind(struct usb_configuration *c, struct usb_function *f)
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
* Caller must have called @gserial_setup() with enough ports to
* handle all the ones it binds. Caller is also responsible
* for calling @gserial_cleanup() before module unload.
*/
int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
{

Просмотреть файл

@ -16,11 +16,12 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/usb/composite.h>
#include <linux/err.h>
#include "g_zero.h"
#include "gadget_chips.h"
/*
* SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
* controller drivers.
@ -62,24 +63,11 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
}
static unsigned pattern;
module_param(pattern, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
static unsigned isoc_interval = 4;
module_param(isoc_interval, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_interval, "1 - 16");
static unsigned isoc_maxpacket = 1024;
module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
static unsigned isoc_interval;
static unsigned isoc_maxpacket;
static unsigned isoc_mult;
module_param(isoc_mult, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
static unsigned isoc_maxburst;
module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
static unsigned buflen;
/*-------------------------------------------------------------------------*/
@ -313,7 +301,57 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
/*-------------------------------------------------------------------------*/
static int __init
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
if (len)
req->length = len;
else
req->length = buflen;
req->buf = kmalloc(req->length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
}
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
kfree(req->buf);
usb_ep_free_request(ep, req);
}
static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
{
int value;
if (ep->driver_data) {
value = usb_ep_disable(ep);
if (value < 0)
DBG(cdev, "disable %s --> %d\n",
ep->name, value);
ep->driver_data = NULL;
}
}
void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,
struct usb_ep *iso_in, struct usb_ep *iso_out)
{
disable_ep(cdev, in);
disable_ep(cdev, out);
if (iso_in)
disable_ep(cdev, iso_in);
if (iso_out)
disable_ep(cdev, iso_out);
}
static int
sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@ -450,7 +488,7 @@ no_iso:
}
static void
sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
sourcesink_free_func(struct usb_function *f)
{
usb_free_all_descriptors(f);
kfree(func_to_ss(f));
@ -531,8 +569,7 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
check_read_data(ss, req);
if (pattern != 2)
memset(req->buf, 0x55, req->length);
} else
reinit_write_data(ep, req);
}
break;
/* this endpoint is normally active while we're configured */
@ -758,31 +795,10 @@ static void sourcesink_disable(struct usb_function *f)
/*-------------------------------------------------------------------------*/
static int __init sourcesink_bind_config(struct usb_configuration *c)
{
struct f_sourcesink *ss;
int status;
ss = kzalloc(sizeof *ss, GFP_KERNEL);
if (!ss)
return -ENOMEM;
ss->function.name = "source/sink";
ss->function.bind = sourcesink_bind;
ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt;
ss->function.get_alt = sourcesink_get_alt;
ss->function.disable = sourcesink_disable;
status = usb_add_function(c, &ss->function);
if (status)
kfree(ss);
return status;
}
static int sourcesink_setup(struct usb_configuration *c,
static int sourcesink_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
struct usb_configuration *c = f->config;
struct usb_request *req = c->cdev->req;
int value = -EOPNOTSUPP;
u16 w_index = le16_to_cpu(ctrl->wIndex);
@ -851,42 +867,76 @@ unknown:
return value;
}
static struct usb_configuration sourcesink_driver = {
.label = "source/sink",
.strings = sourcesink_strings,
.setup = sourcesink_setup,
.bConfigurationValue = 3,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
/* .iConfiguration = DYNAMIC */
};
/**
* sourcesink_add - add a source/sink testing configuration to a device
* @cdev: the device to support the configuration
*/
int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
static struct usb_function *source_sink_alloc_func(
struct usb_function_instance *fi)
{
int id;
struct f_sourcesink *ss;
struct f_ss_opts *ss_opts;
/* allocate string ID(s) */
id = usb_string_id(cdev);
if (id < 0)
return id;
strings_sourcesink[0].id = id;
ss = kzalloc(sizeof(*ss), GFP_KERNEL);
if (!ss)
return NULL;
source_sink_intf_alt0.iInterface = id;
source_sink_intf_alt1.iInterface = id;
sourcesink_driver.iConfiguration = id;
ss_opts = container_of(fi, struct f_ss_opts, func_inst);
pattern = ss_opts->pattern;
isoc_interval = ss_opts->isoc_interval;
isoc_maxpacket = ss_opts->isoc_maxpacket;
isoc_mult = ss_opts->isoc_mult;
isoc_maxburst = ss_opts->isoc_maxburst;
buflen = ss_opts->bulk_buflen;
/* support autoresume for remote wakeup testing */
if (autoresume)
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
ss->function.name = "source/sink";
ss->function.bind = sourcesink_bind;
ss->function.set_alt = sourcesink_set_alt;
ss->function.get_alt = sourcesink_get_alt;
ss->function.disable = sourcesink_disable;
ss->function.setup = sourcesink_setup;
ss->function.strings = sourcesink_strings;
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
sourcesink_driver.descriptors = otg_desc;
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
ss->function.free_func = sourcesink_free_func;
return usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config);
return &ss->function;
}
static void acm_free_instance(struct usb_function_instance *fi)
{
struct f_ss_opts *ss_opts;
ss_opts = container_of(fi, struct f_ss_opts, func_inst);
kfree(ss_opts);
}
static struct usb_function_instance *source_sink_alloc_inst(void)
{
struct f_ss_opts *ss_opts;
ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
if (!ss_opts)
return ERR_PTR(-ENOMEM);
ss_opts->func_inst.free_func_inst = acm_free_instance;
return &ss_opts->func_inst;
}
DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,
source_sink_alloc_func);
static int __init sslb_modinit(void)
{
int ret;
ret = usb_function_register(&SourceSinkusb_func);
if (ret)
return ret;
ret = lb_modinit();
if (ret)
usb_function_unregister(&SourceSinkusb_func);
return ret;
}
static void __exit sslb_modexit(void)
{
usb_function_unregister(&SourceSinkusb_func);
lb_modexit();
}
module_init(sslb_modinit);
module_exit(sslb_modexit);
MODULE_LICENSE("GPL");

Просмотреть файл

@ -260,19 +260,14 @@ static int
uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
struct audio_dev *agdev = uac2_to_agdev(uac2);
struct uac2_rtd_params *prm;
unsigned long flags;
struct usb_ep *ep;
int err = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ep = agdev->in_ep;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
prm = &uac2->p_prm;
} else {
ep = agdev->out_ep;
else
prm = &uac2->c_prm;
}
spin_lock_irqsave(&prm->lock, flags);

Просмотреть файл

@ -1894,7 +1894,7 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
struct usb_gadget_driver *driver);
/* defined in usb_gadget.h */
static struct usb_gadget_ops qe_gadget_ops = {
static const struct usb_gadget_ops qe_gadget_ops = {
.get_frame = qe_get_frame,
.udc_start = fsl_qe_start,
.udc_stop = fsl_qe_stop,

Просмотреть файл

@ -1254,19 +1254,20 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static int fsl_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int fsl_stop(struct usb_gadget_driver *driver);
static int fsl_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int fsl_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
/* defined in gadget.h */
static struct usb_gadget_ops fsl_gadget_ops = {
static const struct usb_gadget_ops fsl_gadget_ops = {
.get_frame = fsl_get_frame,
.wakeup = fsl_wakeup,
/* .set_selfpowered = fsl_set_selfpowered, */ /* Always selfpowered */
.vbus_session = fsl_vbus_session,
.vbus_draw = fsl_vbus_draw,
.pullup = fsl_pullup,
.start = fsl_start,
.stop = fsl_stop,
.udc_start = fsl_udc_start,
.udc_stop = fsl_udc_stop,
};
/* Set protocol stall on ep0, protocol stall will automatically be cleared
@ -1950,22 +1951,12 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
* Hook to gadget drivers
* Called by initialization code of gadget drivers
*----------------------------------------------------------------*/
static int fsl_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int fsl_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
int retval = -ENODEV;
int retval = 0;
unsigned long flags = 0;
if (!udc_controller)
return -ENODEV;
if (!driver || driver->max_speed < USB_SPEED_FULL
|| !bind || !driver->disconnect || !driver->setup)
return -EINVAL;
if (udc_controller->driver)
return -EBUSY;
/* lock is needed but whether should use this lock or another */
spin_lock_irqsave(&udc_controller->lock, flags);
@ -1975,15 +1966,6 @@ static int fsl_start(struct usb_gadget_driver *driver,
udc_controller->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc_controller->lock, flags);
/* bind udc driver to gadget driver */
retval = bind(&udc_controller->gadget, driver);
if (retval) {
VDBG("bind to %s --> %d", driver->driver.name, retval);
udc_controller->gadget.dev.driver = NULL;
udc_controller->driver = NULL;
goto out;
}
if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* Suspend the controller until OTG enable it */
udc_controller->stopped = 1;
@ -2009,28 +1991,17 @@ static int fsl_start(struct usb_gadget_driver *driver,
udc_controller->ep0_state = WAIT_FOR_SETUP;
udc_controller->ep0_dir = 0;
}
printk(KERN_INFO "%s: bind to driver %s\n",
udc_controller->gadget.name, driver->driver.name);
out:
if (retval)
printk(KERN_WARNING "gadget driver register failed %d\n",
retval);
return retval;
}
/* Disconnect from gadget driver */
static int fsl_stop(struct usb_gadget_driver *driver)
static int fsl_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct fsl_ep *loop_ep;
unsigned long flags;
if (!udc_controller)
return -ENODEV;
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
otg_set_peripheral(udc_controller->transceiver->otg, NULL);
@ -2051,16 +2022,9 @@ static int fsl_stop(struct usb_gadget_driver *driver)
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
/* report disconnect; the controller is already quiesced */
driver->disconnect(&udc_controller->gadget);
/* unbind gadget and unhook driver. */
driver->unbind(&udc_controller->gadget);
udc_controller->gadget.dev.driver = NULL;
udc_controller->driver = NULL;
printk(KERN_WARNING "unregistered gadget driver '%s'\n",
driver->driver.name);
return 0;
}

Просмотреть файл

@ -0,0 +1,116 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/usb/composite.h>
static LIST_HEAD(func_list);
static DEFINE_MUTEX(func_lock);
static struct usb_function_instance *try_get_usb_function_instance(const char *name)
{
struct usb_function_driver *fd;
struct usb_function_instance *fi;
fi = ERR_PTR(-ENOENT);
mutex_lock(&func_lock);
list_for_each_entry(fd, &func_list, list) {
if (strcmp(name, fd->name))
continue;
if (!try_module_get(fd->mod)) {
fi = ERR_PTR(-EBUSY);
break;
}
fi = fd->alloc_inst();
if (IS_ERR(fi))
module_put(fd->mod);
else
fi->fd = fd;
break;
}
mutex_unlock(&func_lock);
return fi;
}
struct usb_function_instance *usb_get_function_instance(const char *name)
{
struct usb_function_instance *fi;
int ret;
fi = try_get_usb_function_instance(name);
if (!IS_ERR(fi))
return fi;
ret = PTR_ERR(fi);
if (ret != -ENOENT)
return fi;
ret = request_module("usbfunc:%s", name);
if (ret < 0)
return ERR_PTR(ret);
return try_get_usb_function_instance(name);
}
EXPORT_SYMBOL_GPL(usb_get_function_instance);
struct usb_function *usb_get_function(struct usb_function_instance *fi)
{
struct usb_function *f;
f = fi->fd->alloc_func(fi);
if (IS_ERR(f))
return f;
f->fi = fi;
return f;
}
EXPORT_SYMBOL_GPL(usb_get_function);
void usb_put_function_instance(struct usb_function_instance *fi)
{
struct module *mod;
if (!fi)
return;
mod = fi->fd->mod;
fi->free_func_inst(fi);
module_put(mod);
}
EXPORT_SYMBOL_GPL(usb_put_function_instance);
void usb_put_function(struct usb_function *f)
{
if (!f)
return;
f->free_func(f);
}
EXPORT_SYMBOL_GPL(usb_put_function);
int usb_function_register(struct usb_function_driver *newf)
{
struct usb_function_driver *fd;
int ret;
ret = -EEXIST;
mutex_lock(&func_lock);
list_for_each_entry(fd, &func_list, list) {
if (!strcmp(fd->name, newf->name))
goto out;
}
ret = 0;
list_add_tail(&newf->list, &func_list);
out:
mutex_unlock(&func_lock);
return ret;
}
EXPORT_SYMBOL_GPL(usb_function_register);
void usb_function_unregister(struct usb_function_driver *fd)
{
mutex_lock(&func_lock);
list_del(&fd->list);
mutex_unlock(&func_lock);
}
EXPORT_SYMBOL_GPL(usb_function_unregister);

Просмотреть файл

@ -1308,65 +1308,28 @@ static void init_controller(struct fusb300 *fusb300)
iowrite32(0xcfffff9f, fusb300->reg + FUSB300_OFFSET_IGER1);
}
/*------------------------------------------------------------------------*/
static struct fusb300 *the_controller;
static int fusb300_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int fusb300_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct fusb300 *fusb300 = the_controller;
int retval;
if (!driver
|| driver->max_speed < USB_SPEED_FULL
|| !bind
|| !driver->setup)
return -EINVAL;
if (!fusb300)
return -ENODEV;
if (fusb300->driver)
return -EBUSY;
struct fusb300 *fusb300 = to_fusb300(g);
/* hook up the driver */
driver->driver.bus = NULL;
fusb300->driver = driver;
fusb300->gadget.dev.driver = &driver->driver;
retval = device_add(&fusb300->gadget.dev);
if (retval) {
pr_err("device_add error (%d)\n", retval);
goto error;
}
retval = bind(&fusb300->gadget, driver);
if (retval) {
pr_err("bind to driver error (%d)\n", retval);
device_del(&fusb300->gadget.dev);
goto error;
}
return 0;
error:
fusb300->driver = NULL;
fusb300->gadget.dev.driver = NULL;
return retval;
}
static int fusb300_udc_stop(struct usb_gadget_driver *driver)
static int fusb300_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct fusb300 *fusb300 = the_controller;
if (driver != fusb300->driver || !driver->unbind)
return -EINVAL;
struct fusb300 *fusb300 = to_fusb300(g);
driver->unbind(&fusb300->gadget);
fusb300->gadget.dev.driver = NULL;
init_controller(fusb300);
device_del(&fusb300->gadget.dev);
fusb300->driver = NULL;
return 0;
@ -1378,10 +1341,10 @@ static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
return 0;
}
static struct usb_gadget_ops fusb300_gadget_ops = {
static const struct usb_gadget_ops fusb300_gadget_ops = {
.pullup = fusb300_udc_pullup,
.start = fusb300_udc_start,
.stop = fusb300_udc_stop,
.udc_start = fusb300_udc_start,
.udc_stop = fusb300_udc_stop,
};
static int __exit fusb300_remove(struct platform_device *pdev)
@ -1505,8 +1468,6 @@ static int __init fusb300_probe(struct platform_device *pdev)
fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
the_controller = fusb300;
fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
GFP_KERNEL);
if (fusb300->ep0_req == NULL)
@ -1517,9 +1478,19 @@ static int __init fusb300_probe(struct platform_device *pdev)
if (ret)
goto err_add_udc;
ret = device_add(&fusb300->gadget.dev);
if (ret) {
pr_err("device_add error (%d)\n", ret);
goto err_add_device;
}
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
err_add_device:
usb_del_gadget_udc(&fusb300->gadget);
err_add_udc:
fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);

Просмотреть файл

@ -673,4 +673,6 @@ struct fusb300 {
u8 reenum; /* if re-enumeration */
};
#define to_fusb300(g) (container_of((g), struct fusb300, gadget))
#endif

Просмотреть файл

@ -6,11 +6,34 @@
#ifndef __G_ZERO_H
#define __G_ZERO_H
#include <linux/usb/composite.h>
struct usb_zero_options {
unsigned pattern;
unsigned isoc_interval;
unsigned isoc_maxpacket;
unsigned isoc_mult;
unsigned isoc_maxburst;
unsigned bulk_buflen;
unsigned qlen;
};
/* global state */
extern unsigned buflen;
extern const struct usb_descriptor_header *otg_desc[];
struct f_ss_opts {
struct usb_function_instance func_inst;
unsigned pattern;
unsigned isoc_interval;
unsigned isoc_maxpacket;
unsigned isoc_mult;
unsigned isoc_maxburst;
unsigned bulk_buflen;
};
struct f_lb_opts {
struct usb_function_instance func_inst;
unsigned bulk_buflen;
unsigned qlen;
};
void lb_modexit(void);
int lb_modinit(void);
/* common utilities */
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len);
@ -19,8 +42,4 @@ void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,
struct usb_ep *iso_in, struct usb_ep *iso_out);
/* configuration-specific linkup */
int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
int loopback_add(struct usb_composite_dev *cdev, bool autoresume);
#endif /* __G_ZERO_H */

Просмотреть файл

@ -125,7 +125,7 @@ static struct usb_configuration midi_config = {
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_ONE,
.bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW,
};
static int __init midi_bind_config(struct usb_configuration *c)

Просмотреть файл

@ -993,14 +993,15 @@ static int goku_get_frame(struct usb_gadget *_gadget)
return -EOPNOTSUPP;
}
static int goku_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int goku_stop(struct usb_gadget_driver *driver);
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int goku_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static const struct usb_gadget_ops goku_ops = {
.get_frame = goku_get_frame,
.start = goku_start,
.stop = goku_stop,
.udc_start = goku_udc_start,
.udc_stop = goku_udc_stop,
// no remote wakeup
// not selfpowered
};
@ -1339,50 +1340,28 @@ static void udc_enable(struct goku_udc *dev)
* - one function driver, initted second
*/
static struct goku_udc *the_controller;
/* when a driver is successfully registered, it will receive
* control requests including set_configuration(), which enables
* non-control requests. then usb traffic follows until a
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
static int goku_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct goku_udc *dev = the_controller;
int retval;
if (!driver
|| driver->max_speed < USB_SPEED_FULL
|| !bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
if (dev->driver)
return -EBUSY;
struct goku_udc *dev = to_goku_udc(g);
/* hook up the driver */
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = bind(&dev->gadget, driver);
if (retval) {
DBG(dev, "bind to driver %s --> error %d\n",
driver->driver.name, retval);
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
return retval;
}
/* then enable host detection and ep0; and we're ready
/*
* then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
*/
udc_enable(dev);
DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
return 0;
}
@ -1400,35 +1379,23 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
udc_reset (dev);
for (i = 0; i < 4; i++)
nuke(&dev->ep [i], -ESHUTDOWN);
if (driver) {
spin_unlock(&dev->lock);
driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
if (dev->driver)
udc_enable(dev);
}
static int goku_stop(struct usb_gadget_driver *driver)
static int goku_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct goku_udc *dev = the_controller;
struct goku_udc *dev = to_goku_udc(g);
unsigned long flags;
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
dev->driver = NULL;
stop_activity(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
driver->unbind(&dev->gadget);
dev->gadget.dev.driver = NULL;
DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
return 0;
}
@ -1754,7 +1721,6 @@ static void goku_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
dev->regs = NULL;
the_controller = NULL;
INFO(dev, "unbind\n");
}
@ -1770,13 +1736,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
void __iomem *base = NULL;
int retval;
/* if you want to support more than one controller in a system,
* usb_gadget_driver_{register,unregister}() must change.
*/
if (the_controller) {
pr_warning("ignoring %s\n", pci_name(pdev));
return -EBUSY;
}
if (!pdev->irq) {
printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
retval = -ENODEV;
@ -1851,7 +1810,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
#endif
the_controller = dev;
retval = device_register(&dev->gadget.dev);
if (retval) {
put_device(&dev->gadget.dev);

Просмотреть файл

@ -261,6 +261,7 @@ struct goku_udc {
/* statistics... */
unsigned long irqs;
};
#define to_goku_udc(g) (container_of((g), struct goku_udc, gadget))
/*-------------------------------------------------------------------------*/

Просмотреть файл

@ -1463,42 +1463,16 @@ static struct usb_ep_ops m66592_ep_ops = {
};
/*-------------------------------------------------------------------------*/
static struct m66592 *the_controller;
static int m66592_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int m66592_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct m66592 *m66592 = the_controller;
int retval;
if (!driver
|| driver->max_speed < USB_SPEED_HIGH
|| !bind
|| !driver->setup)
return -EINVAL;
if (!m66592)
return -ENODEV;
if (m66592->driver)
return -EBUSY;
struct m66592 *m66592 = to_m66592(g);
/* hook up the driver */
driver->driver.bus = NULL;
m66592->driver = driver;
m66592->gadget.dev.driver = &driver->driver;
retval = device_add(&m66592->gadget.dev);
if (retval) {
pr_err("device_add error (%d)\n", retval);
goto error;
}
retval = bind(&m66592->gadget, driver);
if (retval) {
pr_err("bind to driver error (%d)\n", retval);
device_del(&m66592->gadget.dev);
goto error;
}
m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
m66592_start_xclock(m66592);
@ -1510,26 +1484,12 @@ static int m66592_start(struct usb_gadget_driver *driver,
}
return 0;
error:
m66592->driver = NULL;
m66592->gadget.dev.driver = NULL;
return retval;
}
static int m66592_stop(struct usb_gadget_driver *driver)
static int m66592_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct m66592 *m66592 = the_controller;
unsigned long flags;
if (driver != m66592->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&m66592->lock, flags);
if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
m66592_usb_disconnect(m66592);
spin_unlock_irqrestore(&m66592->lock, flags);
struct m66592 *m66592 = to_m66592(g);
m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
@ -1539,8 +1499,8 @@ static int m66592_stop(struct usb_gadget_driver *driver)
init_controller(m66592);
disable_controller(m66592);
device_del(&m66592->gadget.dev);
m66592->driver = NULL;
return 0;
}
@ -1566,10 +1526,10 @@ static int m66592_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static struct usb_gadget_ops m66592_gadget_ops = {
static const struct usb_gadget_ops m66592_gadget_ops = {
.get_frame = m66592_get_frame,
.start = m66592_start,
.stop = m66592_stop,
.udc_start = m66592_udc_start,
.udc_stop = m66592_udc_stop,
.pullup = m66592_pullup,
};
@ -1578,6 +1538,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
struct m66592 *m66592 = dev_get_drvdata(&pdev->dev);
usb_del_gadget_udc(&m66592->gadget);
device_del(&m66592->gadget.dev);
del_timer_sync(&m66592->timer);
iounmap(m66592->reg);
@ -1706,8 +1667,6 @@ static int __init m66592_probe(struct platform_device *pdev)
m66592->pipenum2ep[0] = &m66592->ep[0];
m66592->epaddr2ep[0] = &m66592->ep[0];
the_controller = m66592;
m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
if (m66592->ep0_req == NULL)
goto clean_up3;
@ -1715,6 +1674,12 @@ static int __init m66592_probe(struct platform_device *pdev)
init_controller(m66592);
ret = device_add(&m66592->gadget.dev);
if (ret) {
pr_err("device_add error (%d)\n", ret);
goto err_device_add;
}
ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
if (ret)
goto err_add_udc;
@ -1723,6 +1688,9 @@ static int __init m66592_probe(struct platform_device *pdev)
return 0;
err_add_udc:
device_del(&m66592->gadget.dev);
err_device_add:
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
clean_up3:

Просмотреть файл

@ -492,6 +492,7 @@ struct m66592 {
int isochronous;
int num_dma;
};
#define to_m66592(g) (container_of((g), struct m66592, gadget))
#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
#define m66592_to_gadget(m66592) (&m66592->gadget)

Просмотреть файл

@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include "u_serial.h"
#if defined USB_ETH_RNDIS
# undef USB_ETH_RNDIS
#endif
@ -42,9 +43,6 @@ MODULE_LICENSE("GPL");
*/
#include "f_mass_storage.c"
#include "u_serial.c"
#include "f_acm.c"
#include "f_ecm.c"
#include "f_subset.c"
#ifdef USB_ETH_RNDIS
@ -137,10 +135,13 @@ static struct fsg_common fsg_common;
static u8 hostaddr[ETH_ALEN];
static unsigned char tty_line;
static struct usb_function_instance *fi_acm;
/********** RNDIS **********/
#ifdef USB_ETH_RNDIS
static struct usb_function *f_acm_rndis;
static __init int rndis_do_config(struct usb_configuration *c)
{
@ -155,15 +156,25 @@ static __init int rndis_do_config(struct usb_configuration *c)
if (ret < 0)
return ret;
ret = acm_bind_config(c, 0);
if (ret < 0)
return ret;
f_acm_rndis = usb_get_function(fi_acm);
if (IS_ERR(f_acm_rndis))
goto err_func_acm;
ret = usb_add_function(c, f_acm_rndis);
if (ret)
goto err_conf;
ret = fsg_bind_config(c->cdev, c, &fsg_common);
if (ret < 0)
return ret;
goto err_fsg;
return 0;
err_fsg:
usb_remove_function(c, f_acm_rndis);
err_conf:
usb_put_function(f_acm_rndis);
err_func_acm:
return ret;
}
static int rndis_config_register(struct usb_composite_dev *cdev)
@ -192,6 +203,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev)
/********** CDC ECM **********/
#ifdef CONFIG_USB_G_MULTI_CDC
static struct usb_function *f_acm_multi;
static __init int cdc_do_config(struct usb_configuration *c)
{
@ -206,15 +218,26 @@ static __init int cdc_do_config(struct usb_configuration *c)
if (ret < 0)
return ret;
ret = acm_bind_config(c, 0);
if (ret < 0)
return ret;
/* implicit port_num is zero */
f_acm_multi = usb_get_function(fi_acm);
if (IS_ERR(f_acm_multi))
goto err_func_acm;
ret = usb_add_function(c, f_acm_multi);
if (ret)
goto err_conf;
ret = fsg_bind_config(c->cdev, c, &fsg_common);
if (ret < 0)
return ret;
goto err_fsg;
return 0;
err_fsg:
usb_remove_function(c, f_acm_multi);
err_conf:
usb_put_function(f_acm_multi);
err_func_acm:
return ret;
}
static int cdc_config_register(struct usb_composite_dev *cdev)
@ -243,10 +266,10 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
/****************************** Gadget Bind ******************************/
static int __ref multi_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_serial_opts *opts;
int status;
if (!can_support_ecm(cdev->gadget)) {
@ -261,10 +284,19 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
return status;
/* set up serial link layer */
status = gserial_setup(cdev->gadget, 1);
status = gserial_alloc_line(&tty_line);
if (status < 0)
goto fail0;
fi_acm = usb_get_function_instance("acm");
if (IS_ERR(fi_acm)) {
status = PTR_ERR(fi_acm);
goto fail0dot5;
}
opts = container_of(fi_acm, struct f_serial_opts, func_inst);
opts->port_num = tty_line;
/* set up mass storage function */
{
void *retp;
@ -301,7 +333,9 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
fail2:
fsg_common_put(&fsg_common);
fail1:
gserial_cleanup();
usb_put_function_instance(fi_acm);
fail0dot5:
gserial_free_line(tty_line);
fail0:
gether_cleanup();
return status;
@ -309,7 +343,14 @@ fail0:
static int __exit multi_unbind(struct usb_composite_dev *cdev)
{
gserial_cleanup();
#ifdef CONFIG_USB_G_MULTI_CDC
usb_put_function(f_acm_multi);
#endif
#ifdef USB_ETH_RNDIS
usb_put_function(f_acm_rndis);
#endif
usb_put_function_instance(fi_acm);
gserial_free_line(tty_line);
gether_cleanup();
return 0;
}

Просмотреть файл

@ -61,9 +61,6 @@ static DECLARE_COMPLETION(release_done);
static const char driver_name[] = "mv_udc";
static const char driver_desc[] = DRIVER_DESC;
/* controller device global variable */
static struct mv_udc *the_controller;
static void nuke(struct mv_ep *ep, int status);
static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
@ -1268,9 +1265,8 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
return retval;
}
static int mv_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int mv_udc_stop(struct usb_gadget_driver *driver);
static int mv_udc_start(struct usb_gadget *, struct usb_gadget_driver *);
static int mv_udc_stop(struct usb_gadget *, struct usb_gadget_driver *);
/* device controller usb_gadget_ops structure */
static const struct usb_gadget_ops mv_ops = {
@ -1285,8 +1281,8 @@ static const struct usb_gadget_ops mv_ops = {
/* D+ pullup, software-controlled connect/disconnect to USB host */
.pullup = mv_udc_pullup,
.start = mv_udc_start,
.stop = mv_udc_stop,
.udc_start = mv_udc_start,
.udc_stop = mv_udc_stop,
};
static int eps_init(struct mv_udc *udc)
@ -1373,15 +1369,14 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
}
}
static int mv_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int mv_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
struct mv_udc *udc = the_controller;
struct mv_udc *udc;
int retval = 0;
unsigned long flags;
if (!udc)
return -ENODEV;
udc = container_of(gadget, struct mv_udc, gadget);
if (udc->driver)
return -EBUSY;
@ -1399,26 +1394,14 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
spin_unlock_irqrestore(&udc->lock, flags);
retval = bind(&udc->gadget, driver);
if (retval) {
dev_err(&udc->dev->dev, "bind to driver %s --> %d\n",
driver->driver.name, retval);
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
return retval;
}
if (!IS_ERR_OR_NULL(udc->transceiver)) {
if (udc->transceiver) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
dev_err(&udc->dev->dev,
"unable to register peripheral to otg\n");
if (driver->unbind) {
driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
}
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
return retval;
}
}
@ -1433,13 +1416,13 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
return 0;
}
static int mv_udc_stop(struct usb_gadget_driver *driver)
static int mv_udc_stop(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
struct mv_udc *udc = the_controller;
struct mv_udc *udc;
unsigned long flags;
if (!udc)
return -ENODEV;
udc = container_of(gadget, struct mv_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
@ -1454,7 +1437,6 @@ static int mv_udc_stop(struct usb_gadget_driver *driver)
spin_unlock_irqrestore(&udc->lock, flags);
/* unbind gadget driver */
driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
@ -1472,10 +1454,13 @@ static void mv_set_ptc(struct mv_udc *udc, u32 mode)
static void prime_status_complete(struct usb_ep *ep, struct usb_request *_req)
{
struct mv_udc *udc = the_controller;
struct mv_ep *mvep = container_of(ep, struct mv_ep, ep);
struct mv_req *req = container_of(_req, struct mv_req, req);
struct mv_udc *udc;
unsigned long flags;
udc = mvep->udc;
dev_info(&udc->dev->dev, "switch to test mode %d\n", req->test_mode);
spin_lock_irqsave(&udc->lock, flags);
@ -2123,15 +2108,18 @@ static void mv_udc_vbus_work(struct work_struct *work)
/* release device structure */
static void gadget_release(struct device *_dev)
{
struct mv_udc *udc = the_controller;
struct mv_udc *udc;
udc = dev_get_drvdata(_dev);
complete(udc->done);
}
static int mv_udc_remove(struct platform_device *dev)
static int mv_udc_remove(struct platform_device *pdev)
{
struct mv_udc *udc = the_controller;
int clk_i;
struct mv_udc *udc;
udc = platform_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
@ -2140,57 +2128,27 @@ static int mv_udc_remove(struct platform_device *dev)
destroy_workqueue(udc->qwork);
}
/*
* If we have transceiver inited,
* then vbus irq will not be requested in udc driver.
*/
if (udc->pdata && udc->pdata->vbus
&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(udc->pdata->vbus->irq, &dev->dev);
/* free memory allocated in probe */
if (udc->dtd_pool)
dma_pool_destroy(udc->dtd_pool);
if (udc->ep_dqh)
dma_free_coherent(&dev->dev, udc->ep_dqh_size,
dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
udc->ep_dqh, udc->ep_dqh_dma);
kfree(udc->eps);
if (udc->irq)
free_irq(udc->irq, &dev->dev);
mv_udc_disable(udc);
if (udc->cap_regs)
iounmap(udc->cap_regs);
if (udc->phy_regs)
iounmap(udc->phy_regs);
if (udc->status_req) {
kfree(udc->status_req->req.buf);
kfree(udc->status_req);
}
for (clk_i = 0; clk_i <= udc->clknum; clk_i++)
clk_put(udc->clk[clk_i]);
device_unregister(&udc->gadget.dev);
/* free dev, wait for the release() finished */
wait_for_completion(udc->done);
kfree(udc);
the_controller = NULL;
return 0;
}
static int mv_udc_probe(struct platform_device *dev)
static int mv_udc_probe(struct platform_device *pdev)
{
struct mv_usb_platform_data *pdata = dev->dev.platform_data;
struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
struct mv_udc *udc;
int retval = 0;
int clk_i = 0;
@ -2198,71 +2156,73 @@ static int mv_udc_probe(struct platform_device *dev)
size_t size;
if (pdata == NULL) {
dev_err(&dev->dev, "missing platform_data\n");
dev_err(&pdev->dev, "missing platform_data\n");
return -ENODEV;
}
size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
udc = kzalloc(size, GFP_KERNEL);
udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (udc == NULL) {
dev_err(&dev->dev, "failed to allocate memory for udc\n");
dev_err(&pdev->dev, "failed to allocate memory for udc\n");
return -ENOMEM;
}
the_controller = udc;
udc->done = &release_done;
udc->pdata = dev->dev.platform_data;
udc->pdata = pdev->dev.platform_data;
spin_lock_init(&udc->lock);
udc->dev = dev;
udc->dev = pdev;
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->mode == MV_USB_MODE_OTG)
udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (pdata->mode == MV_USB_MODE_OTG) {
udc->transceiver = devm_usb_get_phy(&pdev->dev,
USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(udc->transceiver)) {
udc->transceiver = NULL;
return -ENODEV;
}
}
#endif
udc->clknum = pdata->clknum;
for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]);
udc->clk[clk_i] = devm_clk_get(&pdev->dev,
pdata->clkname[clk_i]);
if (IS_ERR(udc->clk[clk_i])) {
retval = PTR_ERR(udc->clk[clk_i]);
goto err_put_clk;
return retval;
}
}
r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
if (r == NULL) {
dev_err(&dev->dev, "no I/O memory resource defined\n");
retval = -ENODEV;
goto err_put_clk;
dev_err(&pdev->dev, "no I/O memory resource defined\n");
return -ENODEV;
}
udc->cap_regs = (struct mv_cap_regs __iomem *)
ioremap(r->start, resource_size(r));
devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (udc->cap_regs == NULL) {
dev_err(&dev->dev, "failed to map I/O memory\n");
retval = -EBUSY;
goto err_put_clk;
dev_err(&pdev->dev, "failed to map I/O memory\n");
return -EBUSY;
}
r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs");
if (r == NULL) {
dev_err(&dev->dev, "no phy I/O memory resource defined\n");
retval = -ENODEV;
goto err_iounmap_capreg;
dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
return -ENODEV;
}
udc->phy_regs = ioremap(r->start, resource_size(r));
if (udc->phy_regs == NULL) {
dev_err(&dev->dev, "failed to map phy I/O memory\n");
retval = -EBUSY;
goto err_iounmap_capreg;
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
return -EBUSY;
}
/* we will acces controller register, so enable the clk */
retval = mv_udc_enable_internal(udc);
if (retval)
goto err_iounmap_phyreg;
return retval;
udc->op_regs =
(struct mv_op_regs __iomem *)((unsigned long)udc->cap_regs
@ -2279,11 +2239,11 @@ static int mv_udc_probe(struct platform_device *dev)
size = udc->max_eps * sizeof(struct mv_dqh) *2;
size = (size + DQH_ALIGNMENT - 1) & ~(DQH_ALIGNMENT - 1);
udc->ep_dqh = dma_alloc_coherent(&dev->dev, size,
udc->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
&udc->ep_dqh_dma, GFP_KERNEL);
if (udc->ep_dqh == NULL) {
dev_err(&dev->dev, "allocate dQH memory failed\n");
dev_err(&pdev->dev, "allocate dQH memory failed\n");
retval = -ENOMEM;
goto err_disable_clock;
}
@ -2291,7 +2251,7 @@ static int mv_udc_probe(struct platform_device *dev)
/* create dTD dma_pool resource */
udc->dtd_pool = dma_pool_create("mv_dtd",
&dev->dev,
&pdev->dev,
sizeof(struct mv_dtd),
DTD_ALIGNMENT,
DMA_BOUNDARY);
@ -2302,19 +2262,20 @@ static int mv_udc_probe(struct platform_device *dev)
}
size = udc->max_eps * sizeof(struct mv_ep) *2;
udc->eps = kzalloc(size, GFP_KERNEL);
udc->eps = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (udc->eps == NULL) {
dev_err(&dev->dev, "allocate ep memory failed\n");
dev_err(&pdev->dev, "allocate ep memory failed\n");
retval = -ENOMEM;
goto err_destroy_dma;
}
/* initialize ep0 status request structure */
udc->status_req = kzalloc(sizeof(struct mv_req), GFP_KERNEL);
udc->status_req = devm_kzalloc(&pdev->dev, sizeof(struct mv_req),
GFP_KERNEL);
if (!udc->status_req) {
dev_err(&dev->dev, "allocate status_req memory failed\n");
dev_err(&pdev->dev, "allocate status_req memory failed\n");
retval = -ENOMEM;
goto err_free_eps;
goto err_destroy_dma;
}
INIT_LIST_HEAD(&udc->status_req->queue);
@ -2329,17 +2290,17 @@ static int mv_udc_probe(struct platform_device *dev)
r = platform_get_resource(udc->dev, IORESOURCE_IRQ, 0);
if (r == NULL) {
dev_err(&dev->dev, "no IRQ resource defined\n");
dev_err(&pdev->dev, "no IRQ resource defined\n");
retval = -ENODEV;
goto err_free_status_req;
goto err_destroy_dma;
}
udc->irq = r->start;
if (request_irq(udc->irq, mv_udc_irq,
if (devm_request_irq(&pdev->dev, udc->irq, mv_udc_irq,
IRQF_SHARED, driver_name, udc)) {
dev_err(&dev->dev, "Request irq %d for UDC failed\n",
dev_err(&pdev->dev, "Request irq %d for UDC failed\n",
udc->irq);
retval = -ENODEV;
goto err_free_status_req;
goto err_destroy_dma;
}
/* initialize gadget structure */
@ -2351,26 +2312,27 @@ static int mv_udc_probe(struct platform_device *dev)
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.dev.parent = &dev->dev;
udc->gadget.dev.dma_mask = dev->dev.dma_mask;
udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
udc->gadget.dev.release = gadget_release;
udc->gadget.name = driver_name; /* gadget name */
retval = device_register(&udc->gadget.dev);
if (retval)
goto err_free_irq;
goto err_destroy_dma;
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
if (!IS_ERR_OR_NULL(udc->transceiver))
if (udc->transceiver)
udc->clock_gating = 1;
else if (pdata->vbus) {
udc->clock_gating = 1;
retval = request_threaded_irq(pdata->vbus->irq, NULL,
retval = devm_request_threaded_irq(&pdev->dev,
pdata->vbus->irq, NULL,
mv_udc_vbus_irq, IRQF_ONESHOT, "vbus", udc);
if (retval) {
dev_info(&dev->dev,
dev_info(&pdev->dev,
"Can not request irq for VBUS, "
"disable clock gating\n");
udc->clock_gating = 0;
@ -2378,7 +2340,7 @@ static int mv_udc_probe(struct platform_device *dev)
udc->qwork = create_singlethread_workqueue("mv_udc_queue");
if (!udc->qwork) {
dev_err(&dev->dev, "cannot create workqueue\n");
dev_err(&pdev->dev, "cannot create workqueue\n");
retval = -ENOMEM;
goto err_unregister;
}
@ -2396,53 +2358,40 @@ static int mv_udc_probe(struct platform_device *dev)
else
udc->vbus_active = 1;
retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (retval)
goto err_unregister;
goto err_create_workqueue;
dev_info(&dev->dev, "successful probe UDC device %s clock gating.\n",
platform_set_drvdata(pdev, udc);
dev_info(&pdev->dev, "successful probe UDC device %s clock gating.\n",
udc->clock_gating ? "with" : "without");
return 0;
err_create_workqueue:
destroy_workqueue(udc->qwork);
err_unregister:
if (udc->pdata && udc->pdata->vbus
&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(pdata->vbus->irq, &dev->dev);
device_unregister(&udc->gadget.dev);
err_free_irq:
free_irq(udc->irq, &dev->dev);
err_free_status_req:
kfree(udc->status_req->req.buf);
kfree(udc->status_req);
err_free_eps:
kfree(udc->eps);
err_destroy_dma:
dma_pool_destroy(udc->dtd_pool);
err_free_dma:
dma_free_coherent(&dev->dev, udc->ep_dqh_size,
dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
udc->ep_dqh, udc->ep_dqh_dma);
err_disable_clock:
mv_udc_disable_internal(udc);
err_iounmap_phyreg:
iounmap(udc->phy_regs);
err_iounmap_capreg:
iounmap(udc->cap_regs);
err_put_clk:
for (clk_i--; clk_i >= 0; clk_i--)
clk_put(udc->clk[clk_i]);
the_controller = NULL;
kfree(udc);
return retval;
}
#ifdef CONFIG_PM
static int mv_udc_suspend(struct device *_dev)
static int mv_udc_suspend(struct device *dev)
{
struct mv_udc *udc = the_controller;
struct mv_udc *udc;
udc = dev_get_drvdata(dev);
/* if OTG is enabled, the following will be done in OTG driver*/
if (!IS_ERR_OR_NULL(udc->transceiver))
if (udc->transceiver)
return 0;
if (udc->pdata->vbus && udc->pdata->vbus->poll)
@ -2469,13 +2418,15 @@ static int mv_udc_suspend(struct device *_dev)
return 0;
}
static int mv_udc_resume(struct device *_dev)
static int mv_udc_resume(struct device *dev)
{
struct mv_udc *udc = the_controller;
struct mv_udc *udc;
int retval;
udc = dev_get_drvdata(dev);
/* if OTG is enabled, the following will be done in OTG driver*/
if (!IS_ERR_OR_NULL(udc->transceiver))
if (udc->transceiver)
return 0;
if (!udc->clock_gating) {
@ -2499,11 +2450,12 @@ static const struct dev_pm_ops mv_udc_pm_ops = {
};
#endif
static void mv_udc_shutdown(struct platform_device *dev)
static void mv_udc_shutdown(struct platform_device *pdev)
{
struct mv_udc *udc = the_controller;
struct mv_udc *udc;
u32 mode;
udc = platform_get_drvdata(pdev);
/* reset controller mode to IDLE */
mv_udc_enable(udc);
mode = readl(&udc->op_regs->usbmode);
@ -2514,7 +2466,7 @@ static void mv_udc_shutdown(struct platform_device *dev)
static struct platform_driver udc_driver = {
.probe = mv_udc_probe,
.remove = __exit_p(mv_udc_remove),
.remove = mv_udc_remove,
.shutdown = mv_udc_shutdown,
.driver = {
.owner = THIS_MODULE,

Просмотреть файл

@ -37,7 +37,7 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "u_serial.c"
#define USB_FACM_INCLUDED
#include "f_acm.c"
#include "f_ecm.c"
#include "f_obex.c"
@ -101,6 +101,15 @@ MODULE_LICENSE("GPL");
static u8 hostaddr[ETH_ALEN];
enum {
TTY_PORT_OBEX0,
TTY_PORT_OBEX1,
TTY_PORT_ACM,
TTY_PORTS_MAX,
};
static unsigned char tty_lines[TTY_PORTS_MAX];
static int __init nokia_bind_config(struct usb_configuration *c)
{
int status = 0;
@ -109,15 +118,15 @@ static int __init nokia_bind_config(struct usb_configuration *c)
if (status)
printk(KERN_DEBUG "could not bind phonet config\n");
status = obex_bind_config(c, 0);
status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
status = obex_bind_config(c, 1);
status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
status = acm_bind_config(c, 2);
status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
if (status)
printk(KERN_DEBUG "could not bind acm config\n");
@ -133,7 +142,7 @@ static struct usb_configuration nokia_config_500ma_driver = {
.bConfigurationValue = 1,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_ONE,
.bMaxPower = 250, /* 500mA */
.MaxPower = 500,
};
static struct usb_configuration nokia_config_100ma_driver = {
@ -141,21 +150,24 @@ static struct usb_configuration nokia_config_100ma_driver = {
.bConfigurationValue = 2,
/* .iConfiguration = DYNAMIC */
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 50, /* 100 mA */
.MaxPower = 100,
};
static int __init nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
int status;
int cur_line;
status = gphonet_setup(cdev->gadget);
if (status < 0)
goto err_phonet;
status = gserial_setup(cdev->gadget, 3);
if (status < 0)
goto err_serial;
for (cur_line = 0; cur_line < TTY_PORTS_MAX; cur_line++) {
status = gserial_alloc_line(&tty_lines[cur_line]);
if (status)
goto err_ether;
}
status = gether_setup(cdev->gadget, hostaddr);
if (status < 0)
@ -192,8 +204,10 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
err_usb:
gether_cleanup();
err_ether:
gserial_cleanup();
err_serial:
cur_line--;
while (cur_line >= 0)
gserial_free_line(tty_lines[cur_line--]);
gphonet_cleanup();
err_phonet:
return status;
@ -201,8 +215,13 @@ err_phonet:
static int __exit nokia_unbind(struct usb_composite_dev *cdev)
{
int i;
gphonet_cleanup();
gserial_cleanup();
for (i = 0; i < TTY_PORTS_MAX; i++)
gserial_free_line(tty_lines[i]);
gether_cleanup();
return 0;

Просмотреть файл

@ -1309,19 +1309,20 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static int omap_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int omap_udc_stop(struct usb_gadget_driver *driver);
static int omap_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
static int omap_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static struct usb_gadget_ops omap_gadget_ops = {
static const struct usb_gadget_ops omap_gadget_ops = {
.get_frame = omap_get_frame,
.wakeup = omap_wakeup,
.set_selfpowered = omap_set_selfpowered,
.vbus_session = omap_vbus_session,
.vbus_draw = omap_vbus_draw,
.pullup = omap_pullup,
.start = omap_udc_start,
.stop = omap_udc_stop,
.udc_start = omap_udc_start,
.udc_stop = omap_udc_stop,
};
/*-------------------------------------------------------------------------*/
@ -2041,28 +2042,15 @@ static inline int machine_without_vbus_sense(void)
|| cpu_is_omap7xx();
}
static int omap_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int omap_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
int status = -ENODEV;
struct omap_ep *ep;
unsigned long flags;
/* basic sanity tests */
if (!udc)
return -ENODEV;
if (!driver
/* FIXME if otg, check: driver->is_otg */
|| driver->max_speed < USB_SPEED_FULL
|| !bind || !driver->setup)
return -EINVAL;
spin_lock_irqsave(&udc->lock, flags);
if (udc->driver) {
spin_unlock_irqrestore(&udc->lock, flags);
return -EBUSY;
}
/* reset state */
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
ep->irqs = 0;
@ -2084,15 +2072,6 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
if (udc->dc_clk != NULL)
omap_udc_enable_clock(1);
status = bind(&udc->gadget, driver);
if (status) {
DBG("bind to %s --> %d\n", driver->driver.name, status);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
goto done;
}
DBG("bound to driver %s\n", driver->driver.name);
omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
/* connect to bus through transceiver */
@ -2124,19 +2103,16 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
done:
if (udc->dc_clk != NULL)
omap_udc_enable_clock(0);
return status;
}
static int omap_udc_stop(struct usb_gadget_driver *driver)
static int omap_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
unsigned long flags;
int status = -ENODEV;
if (!udc)
return -ENODEV;
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
if (udc->dc_clk != NULL)
omap_udc_enable_clock(1);
@ -2152,13 +2128,12 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
udc_quiesce(udc);
spin_unlock_irqrestore(&udc->lock, flags);
driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
if (udc->dc_clk != NULL)
omap_udc_enable_clock(0);
DBG("unregistered driver '%s'\n", driver->driver.name);
return status;
}

Просмотреть файл

@ -375,6 +375,7 @@ struct pch_udc_dev {
struct pch_udc_cfg_data cfg_data;
struct pch_vbus_gpio_data vbus_gpio;
};
#define to_pch_udc(g) (container_of((g), struct pch_udc_dev, gadget))
#define PCH_UDC_PCI_BAR 1
#define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808
@ -384,7 +385,6 @@ struct pch_udc_dev {
static const char ep0_string[] = "ep0in";
static DEFINE_SPINLOCK(udc_stall_spinlock); /* stall spin lock */
struct pch_udc_dev *pch_udc; /* pointer to device object */
static bool speed_fs;
module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
@ -1235,9 +1235,10 @@ static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
return -EOPNOTSUPP;
}
static int pch_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int pch_udc_stop(struct usb_gadget_driver *driver);
static int pch_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int pch_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static const struct usb_gadget_ops pch_udc_ops = {
.get_frame = pch_udc_pcd_get_frame,
.wakeup = pch_udc_pcd_wakeup,
@ -1245,8 +1246,8 @@ static const struct usb_gadget_ops pch_udc_ops = {
.pullup = pch_udc_pcd_pullup,
.vbus_session = pch_udc_pcd_vbus_session,
.vbus_draw = pch_udc_pcd_vbus_draw,
.start = pch_udc_start,
.stop = pch_udc_stop,
.udc_start = pch_udc_start,
.udc_stop = pch_udc_stop,
};
/**
@ -2981,40 +2982,15 @@ static int init_dma_pools(struct pch_udc_dev *dev)
return 0;
}
static int pch_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int pch_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct pch_udc_dev *dev = pch_udc;
int retval;
struct pch_udc_dev *dev = to_pch_udc(g);
if (!driver || (driver->max_speed == USB_SPEED_UNKNOWN) || !bind ||
!driver->setup || !driver->unbind || !driver->disconnect) {
dev_err(&dev->pdev->dev,
"%s: invalid driver parameter\n", __func__);
return -EINVAL;
}
if (!dev)
return -ENODEV;
if (dev->driver) {
dev_err(&dev->pdev->dev, "%s: already bound\n", __func__);
return -EBUSY;
}
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
/* Invoke the bind routine of the gadget driver */
retval = bind(&dev->gadget, driver);
if (retval) {
dev_err(&dev->pdev->dev, "%s: binding to %s returning %d\n",
__func__, driver->driver.name, retval);
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
return retval;
}
/* get ready for ep0 traffic */
pch_udc_setup_ep0(dev);
@ -3026,30 +3002,21 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
return 0;
}
static int pch_udc_stop(struct usb_gadget_driver *driver)
static int pch_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct pch_udc_dev *dev = pch_udc;
if (!dev)
return -ENODEV;
if (!driver || (driver != dev->driver)) {
dev_err(&dev->pdev->dev,
"%s: invalid driver parameter\n", __func__);
return -EINVAL;
}
struct pch_udc_dev *dev = to_pch_udc(g);
pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
/* Assures that there are no pending requests with this driver */
driver->disconnect(&dev->gadget);
driver->unbind(&dev->gadget);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
dev->connected = 0;
/* set SD */
pch_udc_set_disconnect(dev);
return 0;
}
@ -3164,11 +3131,6 @@ static int pch_udc_probe(struct pci_dev *pdev,
int retval;
struct pch_udc_dev *dev;
/* one udc only */
if (pch_udc) {
pr_err("%s: already probed\n", __func__);
return -EBUSY;
}
/* init */
dev = kzalloc(sizeof *dev, GFP_KERNEL);
if (!dev) {
@ -3207,7 +3169,6 @@ static int pch_udc_probe(struct pci_dev *pdev,
retval = -ENODEV;
goto finished;
}
pch_udc = dev;
/* initialize the hardware */
if (pch_udc_pcd_init(dev)) {
retval = -ENODEV;

Просмотреть файл

@ -996,9 +996,10 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
return -EOPNOTSUPP;
}
static int pxa25x_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int pxa25x_stop(struct usb_gadget_driver *driver);
static int pxa25x_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int pxa25x_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static const struct usb_gadget_ops pxa25x_udc_ops = {
.get_frame = pxa25x_udc_get_frame,
@ -1006,8 +1007,8 @@ static const struct usb_gadget_ops pxa25x_udc_ops = {
.vbus_session = pxa25x_udc_vbus_session,
.pullup = pxa25x_udc_pullup,
.vbus_draw = pxa25x_udc_vbus_draw,
.start = pxa25x_start,
.stop = pxa25x_stop,
.udc_start = pxa25x_udc_start,
.udc_stop = pxa25x_udc_stop,
};
/*-------------------------------------------------------------------------*/
@ -1254,23 +1255,12 @@ static void udc_enable (struct pxa25x_udc *dev)
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
static int pxa25x_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int pxa25x_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct pxa25x_udc *dev = the_controller;
struct pxa25x_udc *dev = to_pxa25x(g);
int retval;
if (!driver
|| driver->max_speed < USB_SPEED_FULL
|| !bind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
if (dev->driver)
return -EBUSY;
/* first hook up the driver ... */
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
@ -1278,34 +1268,20 @@ static int pxa25x_start(struct usb_gadget_driver *driver,
retval = device_add (&dev->gadget.dev);
if (retval) {
fail:
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
return retval;
}
retval = bind(&dev->gadget, driver);
if (retval) {
DMSG("bind to driver %s --> error %d\n",
driver->driver.name, retval);
device_del (&dev->gadget.dev);
goto fail;
}
/* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
*/
DMSG("registered gadget driver '%s'\n", driver->driver.name);
/* connect to bus through transceiver */
if (!IS_ERR_OR_NULL(dev->transceiver)) {
retval = otg_set_peripheral(dev->transceiver->otg,
&dev->gadget);
if (retval) {
DMSG("can't bind to transceiver\n");
if (driver->unbind)
driver->unbind(&dev->gadget);
if (retval)
goto bind_fail;
}
}
pullup(dev);
@ -1334,22 +1310,14 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
}
del_timer_sync(&dev->timer);
/* report disconnect; the driver is already quiesced */
if (driver)
driver->disconnect(&dev->gadget);
/* re-init driver-visible data structures */
udc_reinit(dev);
}
static int pxa25x_stop(struct usb_gadget_driver *driver)
static int pxa25x_udc_stop(struct usb_gadget*g,
struct usb_gadget_driver *driver)
{
struct pxa25x_udc *dev = the_controller;
if (!dev)
return -ENODEV;
if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
struct pxa25x_udc *dev = to_pxa25x(g);
local_irq_disable();
dev->pullup = 0;
@ -1360,14 +1328,12 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
driver->unbind(&dev->gadget);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
device_del (&dev->gadget.dev);
DMSG("unregistered gadget driver '%s'\n", driver->driver.name);
dump_state(dev);
return 0;
}

Просмотреть файл

@ -126,6 +126,7 @@ struct pxa25x_udc {
struct dentry *debugfs_udc;
#endif
};
#define to_pxa25x(g) (container_of((g), struct pxa25x_udc, gadget))
/*-------------------------------------------------------------------------*/

Просмотреть файл

@ -1671,9 +1671,10 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
return -EOPNOTSUPP;
}
static int pxa27x_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int pxa27x_udc_stop(struct usb_gadget_driver *driver);
static int pxa27x_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int pxa27x_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static const struct usb_gadget_ops pxa_udc_ops = {
.get_frame = pxa_udc_get_frame,
@ -1681,8 +1682,8 @@ static const struct usb_gadget_ops pxa_udc_ops = {
.pullup = pxa_udc_pullup,
.vbus_session = pxa_udc_vbus_session,
.vbus_draw = pxa_udc_vbus_draw,
.start = pxa27x_udc_start,
.stop = pxa27x_udc_stop,
.udc_start = pxa27x_udc_start,
.udc_stop = pxa27x_udc_stop,
};
/**
@ -1802,20 +1803,12 @@ static void udc_enable(struct pxa_udc *udc)
*
* Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
*/
static int pxa27x_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int pxa27x_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct pxa_udc *udc = the_controller;
struct pxa_udc *udc = to_pxa(g);
int retval;
if (!driver || driver->max_speed < USB_SPEED_FULL || !bind
|| !driver->disconnect || !driver->setup)
return -EINVAL;
if (!udc)
return -ENODEV;
if (udc->driver)
return -EBUSY;
/* first hook up the driver ... */
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
@ -1824,23 +1817,14 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
retval = device_add(&udc->gadget.dev);
if (retval) {
dev_err(udc->dev, "device_add error %d\n", retval);
goto add_fail;
goto fail;
}
retval = bind(&udc->gadget, driver);
if (retval) {
dev_err(udc->dev, "bind to driver %s --> error %d\n",
driver->driver.name, retval);
goto bind_fail;
}
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name);
if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
dev_err(udc->dev, "can't bind to transceiver\n");
goto transceiver_fail;
goto fail;
}
}
@ -1848,12 +1832,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
udc_enable(udc);
return 0;
transceiver_fail:
if (driver->unbind)
driver->unbind(&udc->gadget);
bind_fail:
device_del(&udc->gadget.dev);
add_fail:
fail:
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
return retval;
@ -1878,9 +1857,6 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
for (i = 0; i < NR_USB_ENDPOINTS; i++)
pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep);
if (driver)
driver->disconnect(&udc->gadget);
}
/**
@ -1889,25 +1865,18 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
*
* Returns 0 if no error, -ENODEV, -EINVAL otherwise
*/
static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
static int pxa27x_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct pxa_udc *udc = the_controller;
if (!udc)
return -ENODEV;
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
struct pxa_udc *udc = to_pxa(g);
stop_activity(udc, driver);
udc_disable(udc);
dplus_pullup(udc, 0);
driver->unbind(&udc->gadget);
udc->driver = NULL;
device_del(&udc->gadget.dev);
dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);

Просмотреть файл

@ -473,6 +473,7 @@ struct pxa_udc {
struct dentry *debugfs_eps;
#endif
};
#define to_pxa(g) (container_of((g), struct pxa_udc, gadget))
static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
{

Просмотреть файл

@ -1812,7 +1812,7 @@ static int r8a66597_set_selfpowered(struct usb_gadget *gadget, int is_self)
return 0;
}
static struct usb_gadget_ops r8a66597_gadget_ops = {
static const struct usb_gadget_ops r8a66597_gadget_ops = {
.get_frame = r8a66597_get_frame,
.udc_start = r8a66597_start,
.udc_stop = r8a66597_stop,

Просмотреть файл

@ -3055,7 +3055,7 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
.get_frame = s3c_hsotg_gadget_getframe,
.udc_start = s3c_hsotg_udc_start,
.udc_stop = s3c_hsotg_udc_stop,
@ -3572,7 +3572,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
if (ret) {
dev_err(dev, "failed to request supplies: %d\n", ret);
@ -3662,8 +3662,6 @@ err_ep_mem:
kfree(eps);
err_supplies:
s3c_hsotg_phy_disable(hsotg);
regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
err_clk:
clk_disable_unprepare(hsotg->clk);
@ -3688,7 +3686,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
}
s3c_hsotg_phy_disable(hsotg);
regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
clk_disable_unprepare(hsotg->clk);

Просмотреть файл

@ -435,7 +435,7 @@ static void s3c_hsudc_epin_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
struct s3c_hsudc_req *hsreq;
u32 csr;
csr = readl((u32)hsudc->regs + S3C_ESR);
csr = readl(hsudc->regs + S3C_ESR);
if (csr & S3C_ESR_STALL) {
writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
return;
@ -468,7 +468,7 @@ static void s3c_hsudc_epout_intr(struct s3c_hsudc *hsudc, u32 ep_idx)
struct s3c_hsudc_req *hsreq;
u32 csr;
csr = readl((u32)hsudc->regs + S3C_ESR);
csr = readl(hsudc->regs + S3C_ESR);
if (csr & S3C_ESR_STALL) {
writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR);
return;
@ -901,12 +901,12 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
if (list_empty(&hsep->queue) && !hsep->stopped) {
offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR;
if (ep_is_in(hsep)) {
csr = readl((u32)hsudc->regs + offset);
csr = readl(hsudc->regs + offset);
if (!(csr & S3C_ESR_TX_SUCCESS) &&
(s3c_hsudc_write_fifo(hsep, hsreq) == 1))
hsreq = NULL;
} else {
csr = readl((u32)hsudc->regs + offset);
csr = readl(hsudc->regs + offset);
if ((csr & S3C_ESR_RX_SUCCESS)
&& (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
hsreq = NULL;
@ -1254,7 +1254,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
return -EOPNOTSUPP;
}
static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
static const struct usb_gadget_ops s3c_hsudc_gadget_ops = {
.get_frame = s3c_hsudc_gadget_getframe,
.udc_start = s3c_hsudc_start,
.udc_stop = s3c_hsudc_stop,
@ -1286,7 +1286,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
ret = regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsudc->supplies),
hsudc->supplies);
if (ret != 0) {
dev_err(dev, "failed to request supplies: %d\n", ret);
@ -1367,7 +1367,6 @@ err_res:
if (!IS_ERR_OR_NULL(hsudc->transceiver))
usb_put_phy(hsudc->transceiver);
regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
err_supplies:
return ret;
}

Просмотреть файл

@ -1538,9 +1538,10 @@ static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
return -ENOTSUPP;
}
static int s3c2410_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
static int s3c2410_udc_stop(struct usb_gadget_driver *driver);
static int s3c2410_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int s3c2410_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static const struct usb_gadget_ops s3c2410_ops = {
.get_frame = s3c2410_udc_get_frame,
@ -1549,8 +1550,8 @@ static const struct usb_gadget_ops s3c2410_ops = {
.pullup = s3c2410_udc_pullup,
.vbus_session = s3c2410_udc_vbus_session,
.vbus_draw = s3c2410_vbus_draw,
.start = s3c2410_udc_start,
.stop = s3c2410_udc_stop,
.udc_start = s3c2410_udc_start,
.udc_stop = s3c2410_udc_stop,
};
static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
@ -1664,33 +1665,14 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
}
static int s3c2410_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
static int s3c2410_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct s3c2410_udc *udc = the_controller;
struct s3c2410_udc *udc = to_s3c2410(g)
int retval;
dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
/* Sanity checks */
if (!udc)
return -ENODEV;
if (udc->driver)
return -EBUSY;
if (!bind || !driver->setup || driver->max_speed < USB_SPEED_FULL) {
dev_err(&udc->gadget.dev, "Invalid driver: bind %p setup %p speed %d\n",
bind, driver->setup, driver->max_speed);
return -EINVAL;
}
#if defined(MODULE)
if (!driver->unbind) {
dev_err(&udc->gadget.dev, "Invalid driver: no unbind method\n");
return -EINVAL;
}
#endif
/* Hook the driver */
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
@ -1702,15 +1684,6 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver,
goto register_error;
}
dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
driver->driver.name);
retval = bind(&udc->gadget, driver);
if (retval) {
device_del(&udc->gadget.dev);
goto register_error;
}
/* Enable udc */
s3c2410_udc_enable(udc);
@ -1722,24 +1695,10 @@ register_error:
return retval;
}
static int s3c2410_udc_stop(struct usb_gadget_driver *driver)
static int s3c2410_udc_stop(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
struct s3c2410_udc *udc = the_controller;
if (!udc)
return -ENODEV;
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
driver->driver.name);
/* report disconnect */
if (driver->disconnect)
driver->disconnect(&udc->gadget);
driver->unbind(&udc->gadget);
struct s3c2410_udc *udc = to_s3c2410(g);
device_del(&udc->gadget.dev);
udc->driver = NULL;

Просмотреть файл

@ -95,5 +95,6 @@ struct s3c2410_udc {
u8 vbus;
struct dentry *regs_info;
};
#define to_s3c2410(g) (container_of((g), struct s3c2410_udc, gadget))
#endif

Просмотреть файл

@ -36,10 +36,8 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "f_acm.c"
#include "f_obex.c"
#include "f_serial.c"
#include "u_serial.c"
/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
@ -128,20 +126,25 @@ module_param(n_ports, uint, 0);
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
/*-------------------------------------------------------------------------*/
static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
static int __init serial_bind_config(struct usb_configuration *c)
static int __init serial_bind_obex_config(struct usb_configuration *c)
{
unsigned i;
int status = 0;
for (i = 0; i < n_ports && status == 0; i++) {
if (use_acm)
status = acm_bind_config(c, i);
else if (use_obex)
status = obex_bind_config(c, i);
else
status = gser_bind_config(c, i);
}
for (i = 0; i < n_ports && status == 0; i++)
status = obex_bind_config(c, tty_lines[i]);
return status;
}
static int __init serial_bind_gser_config(struct usb_configuration *c)
{
unsigned i;
int status = 0;
for (i = 0; i < n_ports && status == 0; i++)
status = gser_bind_config(c, tty_lines[i]);
return status;
}
@ -152,13 +155,70 @@ static struct usb_configuration serial_config_driver = {
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
static struct usb_function_instance *fi_serial[MAX_U_SERIAL_PORTS];
static struct usb_function *f_serial[MAX_U_SERIAL_PORTS];
static int serial_register_ports(struct usb_composite_dev *cdev,
struct usb_configuration *c, const char *f_name)
{
int i;
int ret;
ret = usb_add_config_only(cdev, c);
if (ret)
goto out;
for (i = 0; i < n_ports; i++) {
struct f_serial_opts *opts;
fi_serial[i] = usb_get_function_instance(f_name);
if (IS_ERR(fi_serial[i])) {
ret = PTR_ERR(fi_serial[i]);
goto fail;
}
opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
opts->port_num = tty_lines[i];
f_serial[i] = usb_get_function(fi_serial[i]);
if (IS_ERR(f_serial[i])) {
ret = PTR_ERR(f_serial[i]);
goto err_get_func;
}
ret = usb_add_function(c, f_serial[i]);
if (ret)
goto err_add_func;
}
return 0;
err_add_func:
usb_put_function(f_serial[i]);
err_get_func:
usb_put_function_instance(fi_serial[i]);
fail:
i--;
while (i >= 0) {
usb_remove_function(c, f_serial[i]);
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
i--;
}
out:
return ret;
}
static int __init gs_bind(struct usb_composite_dev *cdev)
{
int status;
int cur_line;
status = gserial_setup(cdev->gadget, n_ports);
if (status < 0)
return status;
for (cur_line = 0; cur_line < n_ports; cur_line++) {
status = gserial_alloc_line(&tty_lines[cur_line]);
if (status)
goto fail;
}
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@ -178,8 +238,16 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
}
/* register our configuration */
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_config);
if (use_acm) {
status = serial_register_ports(cdev, &serial_config_driver,
"acm");
usb_ep_autoconfig_reset(cdev->gadget);
} else if (use_obex)
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_obex_config);
else
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_gser_config);
if (status < 0)
goto fail;
@ -189,16 +257,31 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
return 0;
fail:
gserial_cleanup();
cur_line--;
while (cur_line >= 0)
gserial_free_line(tty_lines[cur_line--]);
return status;
}
static int gs_unbind(struct usb_composite_dev *cdev)
{
int i;
for (i = 0; i < n_ports; i++) {
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
gserial_free_line(tty_lines[i]);
}
return 0;
}
static __refdata struct usb_composite_driver gserial_driver = {
.name = "g_serial",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_SUPER,
.bind = gs_bind,
.unbind = gs_unbind,
};
static int __init init(void)
@ -234,6 +317,5 @@ module_init(init);
static void __exit cleanup(void)
{
usb_composite_unregister(&gserial_driver);
gserial_cleanup();
}
module_exit(cleanup);

Просмотреть файл

@ -93,18 +93,6 @@
/*-------------------------------------------------------------------------*/
/* CBI Interrupt data structure */
struct interrupt_data {
u8 bType;
u8 bValue;
};
#define CBI_INTERRUPT_DATA_LEN 2
/* CBI Accept Device-Specific Command request */
#define USB_CBI_ADSC_REQUEST 0x00
/* Length of a SCSI Command Data Block */
#define MAX_COMMAND_SIZE 16
@ -385,41 +373,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
/*.bMaxBurst = DYNAMIC, */
};
static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
.bLength = USB_DT_USB_EXT_CAP_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
.bDevCapabilityType = USB_CAP_TYPE_EXT,
.bmAttributes = cpu_to_le32(USB_LPM_SUPPORT),
};
static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = {
.bLength = USB_DT_USB_SS_CAP_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
.bDevCapabilityType = USB_SS_CAP_TYPE,
/* .bmAttributes = LTM is not supported yet */
.wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION
| USB_FULL_SPEED_OPERATION
| USB_HIGH_SPEED_OPERATION
| USB_5GBPS_OPERATION),
.bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT,
.bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
};
static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
.wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE
+ USB_DT_USB_EXT_CAP_SIZE
+ USB_DT_USB_SS_CAP_SIZE),
.bNumDeviceCaps = 2,
};
static struct usb_descriptor_header *fsg_ss_function[] = {
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
@ -429,20 +382,6 @@ static struct usb_descriptor_header *fsg_ss_function[] = {
NULL,
};
/* Maxpacket and other transfer characteristics vary by speed. */
static __maybe_unused struct usb_endpoint_descriptor *
fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
struct usb_endpoint_descriptor *hs,
struct usb_endpoint_descriptor *ss)
{
if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
return ss;
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
return hs;
return fs;
}
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
static struct usb_string fsg_strings[] = {
{FSG_STRING_INTERFACE, fsg_string_interface},

Просмотреть файл

@ -26,6 +26,7 @@
#include <linux/tty_flip.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/module.h>
#include "u_serial.h"
@ -35,11 +36,12 @@
* "serial port" functionality through the USB gadget stack. Each such
* port is exposed through a /dev/ttyGS* node.
*
* After initialization (gserial_setup), these TTY port devices stay
* available until they are removed (gserial_cleanup). Each one may be
* connected to a USB function (gserial_connect), or disconnected (with
* gserial_disconnect) when the USB host issues a config change event.
* Data can only flow when the port is connected to the host.
* After this module has been loaded, the individual TTY port can be requested
* (gserial_alloc_line()) and it will stay available until they are removed
* (gserial_free_line()). Each one may be connected to a USB function
* (gserial_connect), or disconnected (with gserial_disconnect) when the USB
* host issues a config change event. Data can only flow when the port is
* connected to the host.
*
* A given TTY port can be made available in multiple configurations.
* For example, each one might expose a ttyGS0 node which provides a
@ -119,13 +121,10 @@ struct gs_port {
struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
};
/* increase N_PORTS if you need more */
#define N_PORTS 4
static struct portmaster {
struct mutex lock; /* protect open/close */
struct gs_port *port;
} ports[N_PORTS];
static unsigned n_ports;
} ports[MAX_U_SERIAL_PORTS];
#define GS_CLOSE_TIMEOUT 15 /* seconds */
@ -309,6 +308,7 @@ gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
return req;
}
EXPORT_SYMBOL_GPL(gs_alloc_req);
/*
* gs_free_req
@ -320,6 +320,7 @@ void gs_free_req(struct usb_ep *ep, struct usb_request *req)
kfree(req->buf);
usb_ep_free_request(ep, req);
}
EXPORT_SYMBOL_GPL(gs_free_req);
/*
* gs_send_packet
@ -1030,10 +1031,19 @@ static int
gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
{
struct gs_port *port;
int ret = 0;
mutex_lock(&ports[port_num].lock);
if (ports[port_num].port) {
ret = -EBUSY;
goto out;
}
port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
if (port == NULL)
return -ENOMEM;
if (port == NULL) {
ret = -ENOMEM;
goto out;
}
tty_port_init(&port->port);
spin_lock_init(&port->port_lock);
@ -1049,109 +1059,9 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
port->port_line_coding = *coding;
ports[port_num].port = port;
return 0;
}
/**
* gserial_setup - initialize TTY driver for one or more ports
* @g: gadget to associate with these ports
* @count: how many ports to support
* Context: may sleep
*
* The TTY stack needs to know in advance how many devices it should
* plan to manage. Use this call to set up the ports you will be
* exporting through USB. Later, connect them to functions based
* on what configuration is activated by the USB host; and disconnect
* them as appropriate.
*
* An example would be a two-configuration device in which both
* configurations expose port 0, but through different functions.
* One configuration could even expose port 1 while the other
* one doesn't.
*
* Returns negative errno or zero.
*/
int gserial_setup(struct usb_gadget *g, unsigned count)
{
unsigned i;
struct usb_cdc_line_coding coding;
int status;
if (count == 0 || count > N_PORTS)
return -EINVAL;
gs_tty_driver = alloc_tty_driver(count);
if (!gs_tty_driver)
return -ENOMEM;
gs_tty_driver->driver_name = "g_serial";
gs_tty_driver->name = PREFIX;
/* uses dynamically assigned dev_t values */
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
gs_tty_driver->init_termios = tty_std_termios;
/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
* MS-Windows. Otherwise, most of these flags shouldn't affect
* anything unless we were to actually hook up to a serial line.
*/
gs_tty_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
gs_tty_driver->init_termios.c_ispeed = 9600;
gs_tty_driver->init_termios.c_ospeed = 9600;
coding.dwDTERate = cpu_to_le32(9600);
coding.bCharFormat = 8;
coding.bParityType = USB_CDC_NO_PARITY;
coding.bDataBits = USB_CDC_1_STOP_BITS;
tty_set_operations(gs_tty_driver, &gs_tty_ops);
/* make devices be openable */
for (i = 0; i < count; i++) {
mutex_init(&ports[i].lock);
status = gs_port_alloc(i, &coding);
if (status) {
count = i;
goto fail;
}
}
n_ports = count;
/* export the driver ... */
status = tty_register_driver(gs_tty_driver);
if (status) {
pr_err("%s: cannot register, err %d\n",
__func__, status);
goto fail;
}
/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
for (i = 0; i < count; i++) {
struct device *tty_dev;
tty_dev = tty_port_register_device(&ports[i].port->port,
gs_tty_driver, i, &g->dev);
if (IS_ERR(tty_dev))
pr_warning("%s: no classdev for port %d, err %ld\n",
__func__, i, PTR_ERR(tty_dev));
}
pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
count, (count == 1) ? "" : "s");
return status;
fail:
while (count--) {
tty_port_destroy(&ports[count].port->port);
kfree(ports[count].port);
}
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
return status;
out:
mutex_unlock(&ports[port_num].lock);
return ret;
}
static int gs_closed(struct gs_port *port)
@ -1164,55 +1074,77 @@ static int gs_closed(struct gs_port *port)
return cond;
}
/**
* gserial_cleanup - remove TTY-over-USB driver and devices
* Context: may sleep
*
* This is called to free all resources allocated by @gserial_setup().
* Accordingly, it may need to wait until some open /dev/ files have
* closed.
*
* The caller must have issued @gserial_disconnect() for any ports
* that had previously been connected, so that there is never any
* I/O pending when it's called.
*/
void gserial_cleanup(void)
static void gserial_free_port(struct gs_port *port)
{
tasklet_kill(&port->push);
/* wait for old opens to finish */
wait_event(port->port.close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL);
tty_port_destroy(&port->port);
kfree(port);
}
void gserial_free_line(unsigned char port_num)
{
unsigned i;
struct gs_port *port;
if (!gs_tty_driver)
mutex_lock(&ports[port_num].lock);
if (WARN_ON(!ports[port_num].port)) {
mutex_unlock(&ports[port_num].lock);
return;
/* start sysfs and /dev/ttyGS* node removal */
for (i = 0; i < n_ports; i++)
tty_unregister_device(gs_tty_driver, i);
for (i = 0; i < n_ports; i++) {
/* prevent new opens */
mutex_lock(&ports[i].lock);
port = ports[i].port;
ports[i].port = NULL;
mutex_unlock(&ports[i].lock);
tasklet_kill(&port->push);
/* wait for old opens to finish */
wait_event(port->port.close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL);
tty_port_destroy(&port->port);
kfree(port);
}
n_ports = 0;
port = ports[port_num].port;
ports[port_num].port = NULL;
mutex_unlock(&ports[port_num].lock);
tty_unregister_driver(gs_tty_driver);
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
pr_debug("%s: cleaned up ttyGS* support\n", __func__);
gserial_free_port(port);
tty_unregister_device(gs_tty_driver, port_num);
}
EXPORT_SYMBOL_GPL(gserial_free_line);
int gserial_alloc_line(unsigned char *line_num)
{
struct usb_cdc_line_coding coding;
struct device *tty_dev;
int ret;
int port_num;
coding.dwDTERate = cpu_to_le32(9600);
coding.bCharFormat = 8;
coding.bParityType = USB_CDC_NO_PARITY;
coding.bDataBits = USB_CDC_1_STOP_BITS;
for (port_num = 0; port_num < MAX_U_SERIAL_PORTS; port_num++) {
ret = gs_port_alloc(port_num, &coding);
if (ret == -EBUSY)
continue;
if (ret)
return ret;
break;
}
if (ret)
return ret;
/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
tty_dev = tty_port_register_device(&ports[port_num].port->port,
gs_tty_driver, port_num, NULL);
if (IS_ERR(tty_dev)) {
struct gs_port *port;
pr_err("%s: failed to register tty for port %d, err %ld\n",
__func__, port_num, PTR_ERR(tty_dev));
ret = PTR_ERR(tty_dev);
port = ports[port_num].port;
ports[port_num].port = NULL;
gserial_free_port(port);
goto err;
}
*line_num = port_num;
err:
return ret;
}
EXPORT_SYMBOL_GPL(gserial_alloc_line);
/**
* gserial_connect - notify TTY I/O glue that USB link is active
@ -1229,8 +1161,8 @@ void gserial_cleanup(void)
*
* Caller needs to have set up the endpoints and USB function in @dev
* before calling this, as well as the appropriate (speed-specific)
* endpoint descriptors, and also have set up the TTY driver by calling
* @gserial_setup().
* endpoint descriptors, and also have allocate @port_num by calling
* @gserial_alloc_line().
*
* Returns negative errno or zero.
* On success, ep->driver_data will be overwritten.
@ -1241,11 +1173,18 @@ int gserial_connect(struct gserial *gser, u8 port_num)
unsigned long flags;
int status;
if (!gs_tty_driver || port_num >= n_ports)
if (port_num >= MAX_U_SERIAL_PORTS)
return -ENXIO;
/* we "know" gserial_cleanup() hasn't been called */
port = ports[port_num].port;
if (!port) {
pr_err("serial line %d not allocated.\n", port_num);
return -EINVAL;
}
if (port->port_usb) {
pr_err("serial line %d is in use.\n", port_num);
return -EBUSY;
}
/* activate the endpoints */
status = usb_ep_enable(gser->in);
@ -1292,7 +1231,7 @@ fail_out:
gser->in->driver_data = NULL;
return status;
}
EXPORT_SYMBOL_GPL(gserial_connect);
/**
* gserial_disconnect - notify TTY I/O glue that USB link is inactive
* @gser: the function, on which gserial_connect() was called
@ -1347,3 +1286,65 @@ void gserial_disconnect(struct gserial *gser)
spin_unlock_irqrestore(&port->port_lock, flags);
}
EXPORT_SYMBOL_GPL(gserial_disconnect);
static int userial_init(void)
{
unsigned i;
int status;
gs_tty_driver = alloc_tty_driver(MAX_U_SERIAL_PORTS);
if (!gs_tty_driver)
return -ENOMEM;
gs_tty_driver->driver_name = "g_serial";
gs_tty_driver->name = PREFIX;
/* uses dynamically assigned dev_t values */
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
gs_tty_driver->init_termios = tty_std_termios;
/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
* MS-Windows. Otherwise, most of these flags shouldn't affect
* anything unless we were to actually hook up to a serial line.
*/
gs_tty_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
gs_tty_driver->init_termios.c_ispeed = 9600;
gs_tty_driver->init_termios.c_ospeed = 9600;
tty_set_operations(gs_tty_driver, &gs_tty_ops);
for (i = 0; i < MAX_U_SERIAL_PORTS; i++)
mutex_init(&ports[i].lock);
/* export the driver ... */
status = tty_register_driver(gs_tty_driver);
if (status) {
pr_err("%s: cannot register, err %d\n",
__func__, status);
goto fail;
}
pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
MAX_U_SERIAL_PORTS,
(MAX_U_SERIAL_PORTS == 1) ? "" : "s");
return status;
fail:
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
return status;
}
module_init(userial_init);
static void userial_cleanup(void)
{
tty_unregister_driver(gs_tty_driver);
put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL;
}
module_exit(userial_cleanup);
MODULE_LICENSE("GPL");

Просмотреть файл

@ -15,6 +15,13 @@
#include <linux/usb/composite.h>
#include <linux/usb/cdc.h>
#define MAX_U_SERIAL_PORTS 4
struct f_serial_opts {
struct usb_function_instance func_inst;
u8 port_num;
};
/*
* One non-multiplexed "serial" I/O port ... there can be several of these
* on any given USB peripheral device, if it provides enough endpoints.
@ -49,9 +56,9 @@ struct gserial {
struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
void gs_free_req(struct usb_ep *, struct usb_request *req);
/* port setup/teardown is handled by gadget driver */
int gserial_setup(struct usb_gadget *g, unsigned n_ports);
void gserial_cleanup(void);
/* management of individual TTY ports */
int gserial_alloc_line(unsigned char *port_line);
void gserial_free_line(unsigned char port_line);
/* connect/disconnect is handled by individual functions */
int gserial_connect(struct gserial *, u8 port_num);

Просмотреть файл

@ -101,28 +101,6 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
/* ------------------------------------------------------------------------- */
/**
* usb_gadget_start - tells usb device controller to start up
* @gadget: The gadget we want to get started
* @driver: The driver we want to bind to @gadget
* @bind: The bind function for @driver
*
* This call is issued by the UDC Class driver when it's about
* to register a gadget driver to the device controller, before
* calling gadget driver's bind() method.
*
* It allows the controller to be powered off until strictly
* necessary to have it powered on.
*
* Returns zero on success, else negative errno.
*/
static inline int usb_gadget_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
{
return gadget->ops->start(driver, bind);
}
/**
* usb_gadget_udc_start - tells usb device controller to start up
* @gadget: The gadget we want to get started
@ -143,24 +121,6 @@ static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
return gadget->ops->udc_start(gadget, driver);
}
/**
* usb_gadget_stop - tells usb device controller we don't need it anymore
* @gadget: The device we want to stop activity
* @driver: The driver to unbind from @gadget
*
* This call is issued by the UDC Class driver after calling
* gadget driver's unbind() method.
*
* The details are implementation specific, but it can go as
* far as powering off UDC completely and disable its data
* line pullups.
*/
static inline void usb_gadget_stop(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
gadget->ops->stop(driver);
}
/**
* usb_gadget_udc_stop - tells usb device controller we don't need it anymore
* @gadget: The device we want to stop activity
@ -246,14 +206,6 @@ err1:
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
static int udc_is_newstyle(struct usb_udc *udc)
{
if (udc->gadget->ops->udc_start && udc->gadget->ops->udc_stop)
return 1;
return 0;
}
static void usb_gadget_remove_driver(struct usb_udc *udc)
{
dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
@ -261,14 +213,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
if (udc_is_newstyle(udc)) {
usb_gadget_disconnect(udc->gadget);
udc->driver->disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
usb_gadget_udc_stop(udc->gadget, udc->driver);
} else {
usb_gadget_stop(udc->gadget, udc->driver);
}
usb_gadget_disconnect(udc->gadget);
udc->driver->disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
usb_gadget_udc_stop(udc->gadget, udc->driver);
udc->driver = NULL;
udc->dev.driver = NULL;
@ -311,6 +259,62 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
/* ------------------------------------------------------------------------- */
static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
{
int ret;
dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
driver->function);
udc->driver = driver;
udc->dev.driver = &driver->driver;
ret = driver->bind(udc->gadget, driver);
if (ret)
goto err1;
ret = usb_gadget_udc_start(udc->gadget, driver);
if (ret) {
driver->unbind(udc->gadget);
goto err1;
}
usb_gadget_connect(udc->gadget);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
return 0;
err1:
dev_err(&udc->dev, "failed to start %s: %d\n",
udc->driver->function, ret);
udc->driver = NULL;
udc->dev.driver = NULL;
return ret;
}
int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
{
struct usb_udc *udc = NULL;
int ret = -ENODEV;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list) {
ret = strcmp(name, dev_name(&udc->dev));
if (!ret)
break;
}
if (ret) {
ret = -ENODEV;
goto out;
}
if (udc->driver) {
ret = -EBUSY;
goto out;
}
ret = udc_bind_to_driver(udc, driver);
out:
mutex_unlock(&udc_lock);
return ret;
}
EXPORT_SYMBOL_GPL(udc_attach_driver);
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
{
struct usb_udc *udc = NULL;
@ -329,41 +333,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
pr_debug("couldn't find an available UDC\n");
mutex_unlock(&udc_lock);
return -ENODEV;
found:
dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
driver->function);
udc->driver = driver;
udc->dev.driver = &driver->driver;
if (udc_is_newstyle(udc)) {
ret = driver->bind(udc->gadget, driver);
if (ret)
goto err1;
ret = usb_gadget_udc_start(udc->gadget, driver);
if (ret) {
driver->unbind(udc->gadget);
goto err1;
}
usb_gadget_connect(udc->gadget);
} else {
ret = usb_gadget_start(udc->gadget, driver, driver->bind);
if (ret)
goto err1;
}
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&udc_lock);
return 0;
err1:
dev_err(&udc->dev, "failed to start %s: %d\n",
udc->driver->function, ret);
udc->driver = NULL;
udc->dev.driver = NULL;
ret = udc_bind_to_driver(udc, driver);
mutex_unlock(&udc_lock);
return ret;
}
@ -410,13 +381,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
if (sysfs_streq(buf, "connect")) {
if (udc_is_newstyle(udc))
usb_gadget_udc_start(udc->gadget, udc->driver);
usb_gadget_udc_start(udc->gadget, udc->driver);
usb_gadget_connect(udc->gadget);
} else if (sysfs_streq(buf, "disconnect")) {
usb_gadget_disconnect(udc->gadget);
if (udc_is_newstyle(udc))
usb_gadget_udc_stop(udc->gadget, udc->driver);
usb_gadget_udc_stop(udc->gadget, udc->driver);
} else {
dev_err(dev, "unsupported command '%s'\n", buf);
return -EINVAL;

Просмотреть файл

@ -336,7 +336,7 @@ static struct usb_configuration webcam_config_driver = {
.bConfigurationValue = 1,
.iConfiguration = 0, /* dynamic */
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW,
};
static int /* __init_or_exit */

Просмотреть файл

@ -10,7 +10,6 @@
* (at your option) any later version.
*/
/*
* Gadget Zero only needs two bulk endpoints, and is an example of how you
* can write a hardware-agnostic gadget driver running inside a USB device.
@ -43,23 +42,11 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/usb/composite.h>
#include "g_zero.h"
#include "gadget_chips.h"
/*-------------------------------------------------------------------------*/
/*
* Kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "f_sourcesink.c"
#include "f_loopback.c"
/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
@ -67,9 +54,6 @@ USB_GADGET_COMPOSITE_OPTIONS();
static const char longname[] = "Gadget Zero";
unsigned buflen = 4096; /* only used for bulk endpoints */
module_param(buflen, uint, 0);
/*
* Normally the "loopback" configuration is second (index 1) so
* it's not the default. Here's where to change that order, to
@ -79,6 +63,13 @@ module_param(buflen, uint, 0);
static bool loopdefault = 0;
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
static struct usb_zero_options gzero_options = {
.isoc_interval = 4,
.isoc_maxpacket = 1024,
.bulk_buflen = 4096,
.qlen = 32,
};
/*-------------------------------------------------------------------------*/
/* Thanks to NetChip Technologies for donating this product ID.
@ -129,20 +120,27 @@ static struct usb_otg_descriptor otg_descriptor = {
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
const struct usb_descriptor_header *otg_desc[] = {
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
#else
#define otg_desc NULL
#endif
/* string IDs are assigned dynamically */
/* default serial number takes at least two packets */
static char serial[] = "0123456789.0123456789.0123456789";
#define USB_GZERO_SS_DESC (USB_GADGET_FIRST_AVAIL_IDX + 0)
#define USB_GZERO_LB_DESC (USB_GADGET_FIRST_AVAIL_IDX + 1)
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
[USB_GADGET_PRODUCT_IDX].s = longname,
[USB_GADGET_SERIAL_IDX].s = serial,
[USB_GZERO_SS_DESC].s = "source and sink data",
[USB_GZERO_LB_DESC].s = "loop input to output",
{ } /* end of list */
};
@ -158,58 +156,6 @@ static struct usb_gadget_strings *dev_strings[] = {
/*-------------------------------------------------------------------------*/
struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
if (len)
req->length = len;
else
req->length = buflen;
req->buf = kmalloc(req->length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
}
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
kfree(req->buf);
usb_ep_free_request(ep, req);
}
static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
{
int value;
if (ep->driver_data) {
value = usb_ep_disable(ep);
if (value < 0)
DBG(cdev, "disable %s --> %d\n",
ep->name, value);
ep->driver_data = NULL;
}
}
void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,
struct usb_ep *iso_in, struct usb_ep *iso_out)
{
disable_ep(cdev, in);
disable_ep(cdev, out);
if (iso_in)
disable_ep(cdev, iso_in);
if (iso_out)
disable_ep(cdev, iso_out);
}
/*-------------------------------------------------------------------------*/
static struct timer_list autoresume_timer;
static void zero_autoresume(unsigned long _c)
@ -251,8 +197,65 @@ static void zero_resume(struct usb_composite_dev *cdev)
/*-------------------------------------------------------------------------*/
static struct usb_configuration loopback_driver = {
.label = "loopback",
.bConfigurationValue = 2,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
/* .iConfiguration = DYNAMIC */
};
static struct usb_function *func_ss;
static struct usb_function_instance *func_inst_ss;
static int ss_config_setup(struct usb_configuration *c,
const struct usb_ctrlrequest *ctrl)
{
switch (ctrl->bRequest) {
case 0x5b:
case 0x5c:
return func_ss->setup(func_ss, ctrl);
default:
return -EOPNOTSUPP;
}
}
static struct usb_configuration sourcesink_driver = {
.label = "source/sink",
.setup = ss_config_setup,
.bConfigurationValue = 3,
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
/* .iConfiguration = DYNAMIC */
};
module_param_named(buflen, gzero_options.bulk_buflen, uint, 0);
module_param_named(pattern, gzero_options.pattern, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none");
module_param_named(isoc_interval, gzero_options.isoc_interval, uint,
S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_interval, "1 - 16");
module_param_named(isoc_maxpacket, gzero_options.isoc_maxpacket, uint,
S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
module_param_named(isoc_mult, gzero_options.isoc_mult, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)");
module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint,
S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
static struct usb_function *func_lb;
static struct usb_function_instance *func_inst_lb;
module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(qlen, "depth of loopback queue");
static int __init zero_bind(struct usb_composite_dev *cdev)
{
struct f_ss_opts *ss_opts;
struct f_lb_opts *lb_opts;
int status;
/* Allocate string descriptor numbers ... note that string
@ -268,27 +271,105 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
func_inst_ss = usb_get_function_instance("SourceSink");
if (IS_ERR(func_inst_ss))
return PTR_ERR(func_inst_ss);
ss_opts = container_of(func_inst_ss, struct f_ss_opts, func_inst);
ss_opts->pattern = gzero_options.pattern;
ss_opts->isoc_interval = gzero_options.isoc_interval;
ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
ss_opts->isoc_mult = gzero_options.isoc_mult;
ss_opts->isoc_maxburst = gzero_options.isoc_maxpacket;
ss_opts->bulk_buflen = gzero_options.bulk_buflen;
func_ss = usb_get_function(func_inst_ss);
if (IS_ERR(func_ss))
goto err_put_func_inst_ss;
func_inst_lb = usb_get_function_instance("Loopback");
if (IS_ERR(func_inst_lb))
goto err_put_func_ss;
lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);
lb_opts->bulk_buflen = gzero_options.bulk_buflen;
lb_opts->qlen = gzero_options.qlen;
func_lb = usb_get_function(func_inst_lb);
if (IS_ERR(func_lb)) {
status = PTR_ERR(func_lb);
goto err_put_func_inst_lb;
}
sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id;
loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id;
/* support autoresume for remote wakeup testing */
sourcesink_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
loopback_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
sourcesink_driver.descriptors = NULL;
loopback_driver.descriptors = NULL;
if (autoresume) {
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
sourcesink_driver.descriptors = otg_desc;
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_driver.descriptors = otg_desc;
loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
/* Register primary, then secondary configuration. Note that
* SH3 only allows one config...
*/
if (loopdefault) {
loopback_add(cdev, autoresume != 0);
sourcesink_add(cdev, autoresume != 0);
usb_add_config_only(cdev, &loopback_driver);
usb_add_config_only(cdev, &sourcesink_driver);
} else {
sourcesink_add(cdev, autoresume != 0);
loopback_add(cdev, autoresume != 0);
usb_add_config_only(cdev, &sourcesink_driver);
usb_add_config_only(cdev, &loopback_driver);
}
status = usb_add_function(&sourcesink_driver, func_ss);
if (status)
goto err_conf_flb;
usb_ep_autoconfig_reset(cdev->gadget);
status = usb_add_function(&loopback_driver, func_lb);
if (status)
goto err_conf_flb;
usb_ep_autoconfig_reset(cdev->gadget);
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
return 0;
err_conf_flb:
usb_put_function(func_lb);
func_lb = NULL;
err_put_func_inst_lb:
usb_put_function_instance(func_inst_lb);
func_inst_lb = NULL;
err_put_func_ss:
usb_put_function(func_ss);
func_ss = NULL;
err_put_func_inst_ss:
usb_put_function_instance(func_inst_ss);
func_inst_ss = NULL;
return status;
}
static int zero_unbind(struct usb_composite_dev *cdev)
{
del_timer_sync(&autoresume_timer);
if (!IS_ERR_OR_NULL(func_ss))
usb_put_function(func_ss);
if (!IS_ERR_OR_NULL(func_lb))
usb_put_function(func_lb);
return 0;
}

Просмотреть файл

@ -302,7 +302,6 @@ static int mv_ehci_remove(struct platform_device *pdev)
{
struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
struct usb_hcd *hcd = ehci_mv->hcd;
int clk_i;
if (hcd->rh_registered)
usb_remove_hcd(hcd);

Просмотреть файл

@ -662,18 +662,9 @@ static struct attribute_group inputs_attr_group = {
int mv_otg_remove(struct platform_device *pdev)
{
struct mv_otg *mvotg = platform_get_drvdata(pdev);
int clk_i;
sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
if (mvotg->irq)
free_irq(mvotg->irq, mvotg);
if (mvotg->pdata->vbus)
free_irq(mvotg->pdata->vbus->irq, mvotg);
if (mvotg->pdata->id)
free_irq(mvotg->pdata->id->irq, mvotg);
if (mvotg->qwork) {
flush_workqueue(mvotg->qwork);
destroy_workqueue(mvotg->qwork);
@ -681,21 +672,9 @@ int mv_otg_remove(struct platform_device *pdev)
mv_otg_disable(mvotg);
if (mvotg->cap_regs)
iounmap(mvotg->cap_regs);
if (mvotg->phy_regs)
iounmap(mvotg->phy_regs);
for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
clk_put(mvotg->clk[clk_i]);
usb_remove_phy(&mvotg->phy);
platform_set_drvdata(pdev, NULL);
kfree(mvotg->phy.otg);
kfree(mvotg);
return 0;
}
@ -714,17 +693,15 @@ static int mv_otg_probe(struct platform_device *pdev)
}
size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
mvotg = kzalloc(size, GFP_KERNEL);
mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!mvotg) {
dev_err(&pdev->dev, "failed to allocate memory!\n");
return -ENOMEM;
}
otg = kzalloc(sizeof *otg, GFP_KERNEL);
if (!otg) {
kfree(mvotg);
otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
if (!otg)
return -ENOMEM;
}
platform_set_drvdata(pdev, mvotg);
@ -733,18 +710,18 @@ static int mv_otg_probe(struct platform_device *pdev)
mvotg->clknum = pdata->clknum;
for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]);
mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
pdata->clkname[clk_i]);
if (IS_ERR(mvotg->clk[clk_i])) {
retval = PTR_ERR(mvotg->clk[clk_i]);
goto err_put_clk;
return retval;
}
}
mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
if (!mvotg->qwork) {
dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
retval = -ENOMEM;
goto err_put_clk;
return -ENOMEM;
}
INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
@ -772,7 +749,7 @@ static int mv_otg_probe(struct platform_device *pdev)
goto err_destroy_workqueue;
}
mvotg->phy_regs = ioremap(r->start, resource_size(r));
mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (mvotg->phy_regs == NULL) {
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
retval = -EFAULT;
@ -784,21 +761,21 @@ static int mv_otg_probe(struct platform_device *pdev)
if (r == NULL) {
dev_err(&pdev->dev, "no I/O memory resource defined\n");
retval = -ENODEV;
goto err_unmap_phyreg;
goto err_destroy_workqueue;
}
mvotg->cap_regs = ioremap(r->start, resource_size(r));
mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (mvotg->cap_regs == NULL) {
dev_err(&pdev->dev, "failed to map I/O memory\n");
retval = -EFAULT;
goto err_unmap_phyreg;
goto err_destroy_workqueue;
}
/* we will acces controller register, so enable the udc controller */
retval = mv_otg_enable_internal(mvotg);
if (retval) {
dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
goto err_unmap_capreg;
goto err_destroy_workqueue;
}
mvotg->op_regs =
@ -806,9 +783,9 @@ static int mv_otg_probe(struct platform_device *pdev)
+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
if (pdata->id) {
retval = request_threaded_irq(pdata->id->irq, NULL,
mv_otg_inputs_irq,
IRQF_ONESHOT, "id", mvotg);
retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
NULL, mv_otg_inputs_irq,
IRQF_ONESHOT, "id", mvotg);
if (retval) {
dev_info(&pdev->dev,
"Failed to request irq for ID\n");
@ -818,9 +795,9 @@ static int mv_otg_probe(struct platform_device *pdev)
if (pdata->vbus) {
mvotg->clock_gating = 1;
retval = request_threaded_irq(pdata->vbus->irq, NULL,
mv_otg_inputs_irq,
IRQF_ONESHOT, "vbus", mvotg);
retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
NULL, mv_otg_inputs_irq,
IRQF_ONESHOT, "vbus", mvotg);
if (retval) {
dev_info(&pdev->dev,
"Failed to request irq for VBUS, "
@ -844,7 +821,7 @@ static int mv_otg_probe(struct platform_device *pdev)
}
mvotg->irq = r->start;
if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
driver_name, mvotg)) {
dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
mvotg->irq);
@ -857,14 +834,14 @@ static int mv_otg_probe(struct platform_device *pdev)
if (retval < 0) {
dev_err(&pdev->dev, "can't register transceiver, %d\n",
retval);
goto err_free_irq;
goto err_disable_clk;
}
retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
if (retval < 0) {
dev_dbg(&pdev->dev,
"Can't register sysfs attr group: %d\n", retval);
goto err_set_transceiver;
goto err_remove_phy;
}
spin_lock_init(&mvotg->wq_lock);
@ -879,30 +856,15 @@ static int mv_otg_probe(struct platform_device *pdev)
return 0;
err_set_transceiver:
err_remove_phy:
usb_remove_phy(&mvotg->phy);
err_free_irq:
free_irq(mvotg->irq, mvotg);
err_disable_clk:
if (pdata->vbus)
free_irq(pdata->vbus->irq, mvotg);
if (pdata->id)
free_irq(pdata->id->irq, mvotg);
mv_otg_disable_internal(mvotg);
err_unmap_capreg:
iounmap(mvotg->cap_regs);
err_unmap_phyreg:
iounmap(mvotg->phy_regs);
err_destroy_workqueue:
flush_workqueue(mvotg->qwork);
destroy_workqueue(mvotg->qwork);
err_put_clk:
for (clk_i--; clk_i >= 0; clk_i--)
clk_put(mvotg->clk[clk_i]);
platform_set_drvdata(pdev, NULL);
kfree(otg);
kfree(mvotg);
return retval;
}

Просмотреть файл

@ -900,7 +900,7 @@ static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
return 0;
}
static struct usb_gadget_ops usbhsg_gadget_ops = {
static const struct usb_gadget_ops usbhsg_gadget_ops = {
.get_frame = usbhsg_get_frame,
.set_selfpowered = usbhsg_set_selfpowered,
.udc_start = usbhsg_gadget_start,

Просмотреть файл

@ -77,6 +77,8 @@ struct usb_configuration;
* in interface or class descriptors; endpoints; I/O buffers; and so on.
* @unbind: Reverses @bind; called as a side effect of unregistering the
* driver which added this function.
* @free_func: free the struct usb_function.
* @mod: (internal) points to the module that created this structure.
* @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
* initialize usb_ep.driver data at this time (when it is used).
* Note that setting an interface to its current altsetting resets
@ -116,6 +118,7 @@ struct usb_configuration;
* two or more distinct instances within the same configuration, providing
* several independent logical data links to a USB host.
*/
struct usb_function {
const char *name;
struct usb_gadget_strings **strings;
@ -136,6 +139,8 @@ struct usb_function {
struct usb_function *);
void (*unbind)(struct usb_configuration *,
struct usb_function *);
void (*free_func)(struct usb_function *f);
struct module *mod;
/* runtime state management */
int (*set_alt)(struct usb_function *,
@ -156,6 +161,7 @@ struct usb_function {
/* internals */
struct list_head list;
DECLARE_BITMAP(endpoints, 32);
const struct usb_function_instance *fi;
};
int usb_add_function(struct usb_configuration *, struct usb_function *);
@ -184,7 +190,8 @@ int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
* @bConfigurationValue: Copied into configuration descriptor.
* @iConfiguration: Copied into configuration descriptor.
* @bmAttributes: Copied into configuration descriptor.
* @bMaxPower: Copied into configuration descriptor.
* @MaxPower: Power consumtion in mA. Used to compute bMaxPower in the
* configuration descriptor after considering the bus speed.
* @cdev: assigned by @usb_add_config() before calling @bind(); this is
* the device associated with this configuration.
*
@ -230,7 +237,7 @@ struct usb_configuration {
u8 bConfigurationValue;
u8 iConfiguration;
u8 bmAttributes;
u8 bMaxPower;
u16 MaxPower;
struct usb_composite_dev *cdev;
@ -316,7 +323,15 @@ struct usb_composite_driver {
extern int usb_composite_probe(struct usb_composite_driver *driver);
extern void usb_composite_unregister(struct usb_composite_driver *driver);
extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
extern int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *cdev);
void composite_dev_cleanup(struct usb_composite_dev *cdev);
static inline struct usb_composite_driver *to_cdriver(
struct usb_gadget_driver *gdrv)
{
return container_of(gdrv, struct usb_composite_driver, gadget_driver);
}
/**
* struct usb_composite_device - represents one composite usb gadget
@ -360,6 +375,7 @@ struct usb_composite_dev {
unsigned int suspended:1;
struct usb_device_descriptor desc;
struct list_head configs;
struct list_head gstrings;
struct usb_composite_driver *driver;
u8 next_string_id;
char *def_manufacturer;
@ -381,8 +397,15 @@ struct usb_composite_dev {
extern int usb_string_id(struct usb_composite_dev *c);
extern int usb_string_ids_tab(struct usb_composite_dev *c,
struct usb_string *str);
extern struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
struct usb_gadget_strings **sp, unsigned n_strings);
extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
extern void composite_disconnect(struct usb_gadget *gadget);
extern int composite_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
/*
* Some systems will need runtime overrides for the product identifiers
* published in the device descriptor, either numbers or strings or both.
@ -431,6 +454,54 @@ static inline u16 get_default_bcdDevice(void)
return bcdDevice;
}
struct usb_function_driver {
const char *name;
struct module *mod;
struct list_head list;
struct usb_function_instance *(*alloc_inst)(void);
struct usb_function *(*alloc_func)(struct usb_function_instance *inst);
};
struct usb_function_instance {
struct usb_function_driver *fd;
void (*free_func_inst)(struct usb_function_instance *inst);
};
void usb_function_unregister(struct usb_function_driver *f);
int usb_function_register(struct usb_function_driver *newf);
void usb_put_function_instance(struct usb_function_instance *fi);
void usb_put_function(struct usb_function *f);
struct usb_function_instance *usb_get_function_instance(const char *name);
struct usb_function *usb_get_function(struct usb_function_instance *fi);
struct usb_configuration *usb_get_config(struct usb_composite_dev *cdev,
int val);
int usb_add_config_only(struct usb_composite_dev *cdev,
struct usb_configuration *config);
void usb_remove_function(struct usb_configuration *c, struct usb_function *f);
#define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
static struct usb_function_driver _name ## usb_func = { \
.name = __stringify(_name), \
.mod = THIS_MODULE, \
.alloc_inst = _inst_alloc, \
.alloc_func = _func_alloc, \
}; \
MODULE_ALIAS("usbfunc:"__stringify(_name));
#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc) \
DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
static int __init _name ## mod_init(void) \
{ \
return usb_function_register(&_name ## usb_func); \
} \
static void __exit _name ## mod_exit(void) \
{ \
usb_function_unregister(&_name ## usb_func); \
} \
module_init(_name ## mod_init); \
module_exit(_name ## mod_exit)
/* messaging utils */
#define DBG(d, fmt, args...) \
dev_dbg(&(d)->gadget->dev , fmt , ## args)

Просмотреть файл

@ -471,12 +471,6 @@ struct usb_gadget_ops {
struct usb_gadget_driver *);
int (*udc_stop)(struct usb_gadget *,
struct usb_gadget_driver *);
/* Those two are deprecated */
int (*start)(struct usb_gadget_driver *,
int (*bind)(struct usb_gadget *,
struct usb_gadget_driver *driver));
int (*stop)(struct usb_gadget_driver *);
};
/**
@ -880,6 +874,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
extern void usb_del_gadget_udc(struct usb_gadget *gadget);
extern int udc_attach_driver(const char *name,
struct usb_gadget_driver *driver);
/*-------------------------------------------------------------------------*/
@ -911,6 +907,11 @@ struct usb_gadget_strings {
struct usb_string *strings;
};
struct usb_gadget_string_container {
struct list_head list;
u8 *stash[0];
};
/* put descriptor for string with that id into buf (buflen >= 256) */
int usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf);