{
struct usb_function *f;
list_for_each_entry(f, &android_config_driver.functions, list) {
- if (product_has_function(p, f) == !!f->disabled)
+ if (product_has_function(p, f) == !!f->hidden)
return 0;
}
return 1;
int disable = !enable;
int product_id;
- if (!!f->disabled != disable) {
- usb_function_set_enabled(f, !disable);
+ if (!!f->hidden != disable) {
+ f->hidden = disable;
#ifdef CONFIG_USB_ANDROID_RNDIS
if (!strcmp(f->name, "rndis")) {
*/
list_for_each_entry(func, &android_config_driver.functions, list) {
if (!strcmp(func->name, "usb_mass_storage")) {
- usb_function_set_enabled(func, !enable);
+ func->hidden = enable;
break;
}
}
device_desc.idProduct = __constant_cpu_to_le16(product_id);
if (dev->cdev)
dev->cdev->desc.idProduct = device_desc.idProduct;
- usb_composite_force_reset(dev->cdev);
+
+ /* force reenumeration */
+ if (dev->cdev && dev->cdev->gadget &&
+ dev->cdev->gadget->speed != USB_SPEED_UNKNOWN) {
+ usb_gadget_disconnect(dev->cdev->gadget);
+ msleep(10);
+ usb_gadget_connect(dev->cdev->gadget);
+ }
}
}
char *buf)
{
struct usb_function *f = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", !f->disabled);
+ return sprintf(buf, "%d\n", !f->hidden);
}
static ssize_t enable_store(
if (driver->enable_function)
driver->enable_function(f, value);
else
- usb_function_set_enabled(f, value);
+ f->hidden = !value;
return size;
}
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
-void usb_function_set_enabled(struct usb_function *f, int enabled)
-{
- f->disabled = !enabled;
- kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
-}
-
-
-void usb_composite_force_reset(struct usb_composite_dev *cdev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cdev->lock, flags);
- /* force reenumeration */
- if (cdev && cdev->gadget &&
- cdev->gadget->speed != USB_SPEED_UNKNOWN) {
- /* avoid sending a disconnect switch event until after we disconnect */
- cdev->mute_switch = 1;
- spin_unlock_irqrestore(&cdev->lock, flags);
-
- usb_gadget_disconnect(cdev->gadget);
- msleep(10);
- usb_gadget_connect(cdev->gadget);
- } else {
- spin_unlock_irqrestore(&cdev->lock, flags);
- }
-}
/**
* usb_add_function() - add a function to a configuration
descriptors = f->hs_descriptors;
else
descriptors = f->descriptors;
- if (f->disabled || !descriptors || descriptors[0] == NULL)
+ if (f->hidden || !descriptors || descriptors[0] == NULL)
continue;
status = usb_descriptor_fillbuf(next, len,
(const struct usb_descriptor_header **) descriptors);
if (!f)
break;
- if (f->disabled)
+ if (f->hidden)
continue;
result = f->set_alt(f, tmp, 0);
power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
done:
usb_gadget_vbus_draw(gadget, power);
-
- schedule_work(&cdev->switch_work);
return result;
}
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config)
reset_config(cdev);
-
- if (cdev->mute_switch)
- cdev->mute_switch = 0;
- else
- schedule_work(&cdev->switch_work);
spin_unlock_irqrestore(&cdev->lock, flags);
}
kfree(cdev->req->buf);
usb_ep_free_request(gadget->ep0, cdev->req);
}
-
- switch_dev_unregister(&cdev->sdev);
kfree(cdev);
set_gadget_data(gadget, NULL);
composite = NULL;
}
}
-static void
-composite_switch_work(struct work_struct *data)
-{
- struct usb_composite_dev *cdev =
- container_of(data, struct usb_composite_dev, switch_work);
- struct usb_configuration *config = cdev->config;
-
- if (config)
- switch_set_state(&cdev->sdev, config->bConfigurationValue);
- else
- switch_set_state(&cdev->sdev, 0);
-}
-
static int __init composite_bind(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
if (status < 0)
goto fail;
- cdev->sdev.name = "usb_configuration";
- status = switch_dev_register(&cdev->sdev);
- if (status < 0)
- goto fail;
- INIT_WORK(&cdev->switch_work, composite_switch_work);
-
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
}
}
-static int
-composite_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct usb_function *f = dev_get_drvdata(dev);
-
- if (!f) {
- /* this happens when the device is first created */
- return 0;
- }
-
- if (add_uevent_var(env, "FUNCTION=%s", f->name))
- return -ENOMEM;
- if (add_uevent_var(env, "ENABLED=%d", !f->disabled))
- return -ENOMEM;
- return 0;
-}
-
/*-------------------------------------------------------------------------*/
static struct usb_gadget_driver composite_driver = {
driver->class = class_create(THIS_MODULE, "usb_composite");
if (IS_ERR(driver->class))
return PTR_ERR(driver->class);
- driver->class->dev_uevent = composite_uevent;
return usb_gadget_register_driver(&composite_driver);
}
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <linux/switch.h>
-struct usb_composite_dev;
struct usb_configuration;
/**
struct usb_descriptor_header **hs_descriptors;
struct usb_configuration *config;
-
- /* disabled is zero if the function is enabled */
- int disabled;
+ int hidden;
/* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis. See if
int usb_interface_id(struct usb_configuration *, struct usb_function *);
-void usb_function_set_enabled(struct usb_function *, int);
-void usb_composite_force_reset(struct usb_composite_dev *);
-
/**
* ep_choose - select descriptor endpoint at current device speed
* @g: gadget, connected and running at some speed
/* protects at least deactivation count */
spinlock_t lock;
-
- struct switch_dev sdev;
- /* used by usb_composite_force_reset to avoid signalling switch changes */
- bool mute_switch;
- struct work_struct switch_work;
};
extern int usb_string_id(struct usb_composite_dev *c);