usb: gadget: Add function devices to the parent
authorBadhri Jagan Sridharan <Badhri@google.com>
Fri, 27 Mar 2015 21:15:19 +0000 (14:15 -0700)
committerJohn Stultz <john.stultz@linaro.org>
Tue, 16 Feb 2016 21:52:09 +0000 (13:52 -0800)
Added create_function_device to create child
function devices for USB gadget functions.
Android UsbDeviceManager relies on communicating
to the devices created by the gadget functions
to implement functions such as audio_source.

Signed-off-by: Badhri Jagan Sridharan <Badhri@google.com>
Change-Id: I0df9ad86ac32d8cdacdea164e9fed49891b45fc2

drivers/usb/gadget/configfs.c

index 8c527eb2289c832eaee1dc44eb0500b9ff3f8207..38077becbf2c074fe2e3ae71bc13479fe6e656a9 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/platform_device.h>
 #include <linux/kdev_t.h>
 #include <linux/usb/ch9.h>
-#include "u_fs.h"
 
 #ifdef CONFIG_USB_CONFIGFS_F_ACC
 extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
@@ -21,6 +20,18 @@ extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
 void acc_disconnect(void);
 #endif
 static struct class *android_class;
+static struct device *android_device;
+static int index;
+
+struct device *create_function_device(char *name)
+{
+       if (android_device && !IS_ERR(android_device))
+               return device_create(android_class, android_device,
+                       MKDEV(0, index++), NULL, name);
+       else
+               return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(create_function_device);
 #endif
 
 int check_user_usb_string(const char *name,
@@ -1420,19 +1431,22 @@ static void android_work(struct work_struct *data)
        spin_unlock_irqrestore(&cdev->lock, flags);
 
        if (status[0]) {
-               kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, connected);
+               kobject_uevent_env(&android_device->kobj,
+                                       KOBJ_CHANGE, connected);
                pr_info("%s: sent uevent %s\n", __func__, connected[0]);
                uevent_sent = true;
        }
 
        if (status[1]) {
-               kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, configured);
+               kobject_uevent_env(&android_device->kobj,
+                                       KOBJ_CHANGE, configured);
                pr_info("%s: sent uevent %s\n", __func__, configured[0]);
                uevent_sent = true;
        }
 
        if (status[2]) {
-               kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, disconnected);
+               kobject_uevent_env(&android_device->kobj,
+                                       KOBJ_CHANGE, disconnected);
                pr_info("%s: sent uevent %s\n", __func__, disconnected[0]);
                uevent_sent = true;
        }
@@ -1554,7 +1568,6 @@ static struct config_group *gadgets_make(
        gi = kzalloc(sizeof(*gi), GFP_KERNEL);
        if (!gi)
                return ERR_PTR(-ENOMEM);
-
        gi->group.default_groups = gi->default_groups;
        gi->group.default_groups[0] = &gi->functions_group;
        gi->group.default_groups[1] = &gi->configs_group;
@@ -1592,8 +1605,10 @@ static struct config_group *gadgets_make(
 
 #ifdef CONFIG_USB_CONFIGFS_UEVENT
        INIT_WORK(&gi->work, android_work);
-       gi->dev = device_create(android_class, NULL,
+       android_device = device_create(android_class, NULL,
                                MKDEV(0, 0), NULL, "android0");
+       if (IS_ERR(android_device))
+               goto err;
 #endif
 
        if (!gi->composite.gadget_driver.function)
@@ -1610,6 +1625,9 @@ err:
 static void gadgets_drop(struct config_group *group, struct config_item *item)
 {
        config_item_put(item);
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+       device_destroy(android_device->class, android_device->devt);
+#endif
 }
 
 static struct configfs_group_operations gadgets_ops = {
@@ -1661,5 +1679,10 @@ module_init(gadget_cfs_init);
 static void __exit gadget_cfs_exit(void)
 {
        configfs_unregister_subsystem(&gadget_subsys);
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+       if (!IS_ERR(android_class))
+               class_destroy(android_class);
+#endif
+
 }
 module_exit(gadget_cfs_exit);