These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / usb / gadget / configfs.c
index 0495c94..163d305 100644 (file)
@@ -41,6 +41,8 @@ int check_user_usb_string(const char *name,
 #define MAX_NAME_LEN   40
 #define MAX_USB_STRING_LANGS 2
 
+static const struct usb_descriptor_header *otg_desc[2];
+
 struct gadget_info {
        struct config_group group;
        struct config_group functions_group;
@@ -55,9 +57,6 @@ struct gadget_info {
        struct list_head available_func;
 
        const char *udc_name;
-#ifdef CONFIG_USB_OTG
-       struct usb_otg_descriptor otg;
-#endif
        struct usb_composite_driver composite;
        struct usb_composite_dev cdev;
        bool use_os_desc;
@@ -65,6 +64,11 @@ struct gadget_info {
        char qw_sign[OS_STRING_QW_SIGN_LEN];
 };
 
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+        return container_of(to_config_group(item), struct gadget_info, group);
+}
+
 struct config_usb_cfg {
        struct config_group group;
        struct config_group strings_group;
@@ -75,6 +79,12 @@ struct config_usb_cfg {
        struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
 };
 
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct config_usb_cfg,
+                       group);
+}
+
 struct gadget_strings {
        struct usb_gadget_strings stringtab_dev;
        struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
@@ -118,32 +128,25 @@ static int usb_string_copy(const char *s, char **s_copy)
        return 0;
 }
 
-CONFIGFS_ATTR_STRUCT(gadget_info);
-CONFIGFS_ATTR_STRUCT(config_usb_cfg);
-
-#define GI_DEVICE_DESC_ITEM_ATTR(name) \
-       static struct gadget_info_attribute gadget_cdev_desc_##name = \
-               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
-                               gadget_dev_desc_##name##_show,          \
-                               gadget_dev_desc_##name##_store)
-
 #define GI_DEVICE_DESC_SIMPLE_R_u8(__name)     \
-       static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
                        char *page)     \
 {      \
-       return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \
+       return sprintf(page, "0x%02x\n", \
+               to_gadget_info(item)->cdev.desc.__name); \
 }
 
 #define GI_DEVICE_DESC_SIMPLE_R_u16(__name)    \
-       static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
                        char *page)     \
 {      \
-       return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+       return sprintf(page, "0x%04x\n", \
+               le16_to_cpup(&to_gadget_info(item)->cdev.desc.__name)); \
 }
 
 
 #define GI_DEVICE_DESC_SIMPLE_W_u8(_name)              \
-       static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
                const char *page, size_t len)           \
 {                                                      \
        u8 val;                                         \
@@ -151,12 +154,12 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
        ret = kstrtou8(page, 0, &val);                  \
        if (ret)                                        \
                return ret;                             \
-       gi->cdev.desc._name = val;                      \
+       to_gadget_info(item)->cdev.desc._name = val;    \
        return len;                                     \
 }
 
 #define GI_DEVICE_DESC_SIMPLE_W_u16(_name)     \
-       static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
                const char *page, size_t len)           \
 {                                                      \
        u16 val;                                        \
@@ -164,7 +167,7 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
        ret = kstrtou16(page, 0, &val);                 \
        if (ret)                                        \
                return ret;                             \
-       gi->cdev.desc._name = cpu_to_le16p(&val);       \
+       to_gadget_info(item)->cdev.desc._name = cpu_to_le16p(&val);     \
        return len;                                     \
 }
 
@@ -194,7 +197,7 @@ static ssize_t is_valid_bcd(u16 bcd_val)
        return 0;
 }
 
-static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdDevice_store(struct config_item *item,
                const char *page, size_t len)
 {
        u16 bcdDevice;
@@ -207,11 +210,11 @@ static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
        if (ret)
                return ret;
 
-       gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+       to_gadget_info(item)->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
        return len;
 }
 
-static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdUSB_store(struct config_item *item,
                const char *page, size_t len)
 {
        u16 bcdUSB;
@@ -224,13 +227,13 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
        if (ret)
                return ret;
 
-       gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+       to_gadget_info(item)->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
        return len;
 }
 
-static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%s\n", gi->udc_name ?: "");
+       return sprintf(page, "%s\n", to_gadget_info(item)->udc_name ?: "");
 }
 
 static int unregister_gadget(struct gadget_info *gi)
@@ -248,9 +251,10 @@ static int unregister_gadget(struct gadget_info *gi)
        return 0;
 }
 
-static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
                const char *page, size_t len)
 {
+       struct gadget_info *gi = to_gadget_info(item);
        char *name;
        int ret;
 
@@ -284,34 +288,29 @@ err:
        return ret;
 }
 
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
-GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
-GI_DEVICE_DESC_ITEM_ATTR(idVendor);
-GI_DEVICE_DESC_ITEM_ATTR(idProduct);
-GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
-GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
-GI_DEVICE_DESC_ITEM_ATTR(UDC);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
+CONFIGFS_ATTR(gadget_dev_desc_, bMaxPacketSize0);
+CONFIGFS_ATTR(gadget_dev_desc_, idVendor);
+CONFIGFS_ATTR(gadget_dev_desc_, idProduct);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
+CONFIGFS_ATTR(gadget_dev_desc_, UDC);
 
 static struct configfs_attribute *gadget_root_attrs[] = {
-       &gadget_cdev_desc_bDeviceClass.attr,
-       &gadget_cdev_desc_bDeviceSubClass.attr,
-       &gadget_cdev_desc_bDeviceProtocol.attr,
-       &gadget_cdev_desc_bMaxPacketSize0.attr,
-       &gadget_cdev_desc_idVendor.attr,
-       &gadget_cdev_desc_idProduct.attr,
-       &gadget_cdev_desc_bcdDevice.attr,
-       &gadget_cdev_desc_bcdUSB.attr,
-       &gadget_cdev_desc_UDC.attr,
+       &gadget_dev_desc_attr_bDeviceClass,
+       &gadget_dev_desc_attr_bDeviceSubClass,
+       &gadget_dev_desc_attr_bDeviceProtocol,
+       &gadget_dev_desc_attr_bMaxPacketSize0,
+       &gadget_dev_desc_attr_idVendor,
+       &gadget_dev_desc_attr_idProduct,
+       &gadget_dev_desc_attr_bcdDevice,
+       &gadget_dev_desc_attr_bcdUSB,
+       &gadget_dev_desc_attr_UDC,
        NULL,
 };
 
-static inline struct gadget_info *to_gadget_info(struct config_item *item)
-{
-        return container_of(to_config_group(item), struct gadget_info, group);
-}
-
 static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
 {
         return container_of(to_config_group(item), struct gadget_strings,
@@ -325,12 +324,6 @@ static inline struct gadget_config_name *to_gadget_config_name(
                         group);
 }
 
-static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
-{
-       return container_of(to_config_group(item), struct config_usb_cfg,
-                       group);
-}
-
 static inline struct usb_function_instance *to_usb_function_instance(
                struct config_item *item)
 {
@@ -349,12 +342,8 @@ static void gadget_info_attr_release(struct config_item *item)
        kfree(gi);
 }
 
-CONFIGFS_ATTR_OPS(gadget_info);
-
 static struct configfs_item_operations gadget_root_item_ops = {
        .release                = gadget_info_attr_release,
-       .show_attribute         = gadget_info_attr_show,
-       .store_attribute        = gadget_info_attr_store,
 };
 
 static void gadget_config_attr_release(struct config_item *item)
@@ -455,24 +444,20 @@ static int config_usb_cfg_unlink(
        return 0;
 }
 
-CONFIGFS_ATTR_OPS(config_usb_cfg);
-
 static struct configfs_item_operations gadget_config_item_ops = {
        .release                = gadget_config_attr_release,
-       .show_attribute         = config_usb_cfg_attr_show,
-       .store_attribute        = config_usb_cfg_attr_store,
        .allow_link             = config_usb_cfg_link,
        .drop_link              = config_usb_cfg_unlink,
 };
 
 
-static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_show(struct config_item *item,
                char *page)
 {
-       return sprintf(page, "%u\n", cfg->c.MaxPower);
+       return sprintf(page, "%u\n", to_config_usb_cfg(item)->c.MaxPower);
 }
 
-static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_store(struct config_item *item,
                const char *page, size_t len)
 {
        u16 val;
@@ -482,17 +467,18 @@ static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
                return ret;
        if (DIV_ROUND_UP(val, 8) > 0xff)
                return -ERANGE;
-       cfg->c.MaxPower = val;
+       to_config_usb_cfg(item)->c.MaxPower = val;
        return len;
 }
 
-static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_item *item,
                char *page)
 {
-       return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+       return sprintf(page, "0x%02x\n",
+               to_config_usb_cfg(item)->c.bmAttributes);
 }
 
-static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_item *item,
                const char *page, size_t len)
 {
        u8 val;
@@ -505,22 +491,16 @@ static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
        if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
                                USB_CONFIG_ATT_WAKEUP))
                return -EINVAL;
-       cfg->c.bmAttributes = val;
+       to_config_usb_cfg(item)->c.bmAttributes = val;
        return len;
 }
 
-#define CFG_CONFIG_DESC_ITEM_ATTR(name)        \
-       static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
-               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
-                               gadget_config_desc_##name##_show,       \
-                               gadget_config_desc_##name##_store)
-
-CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
-CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+CONFIGFS_ATTR(gadget_config_desc_, MaxPower);
+CONFIGFS_ATTR(gadget_config_desc_, bmAttributes);
 
 static struct configfs_attribute *gadget_config_attrs[] = {
-       &gadget_usb_cfg_MaxPower.attr,
-       &gadget_usb_cfg_bmAttributes.attr,
+       &gadget_config_desc_attr_MaxPower,
+       &gadget_config_desc_attr_bmAttributes,
        NULL,
 };
 
@@ -571,7 +551,7 @@ static struct config_group *function_make(
        if (IS_ERR(fi))
                return ERR_CAST(fi);
 
-       ret = config_item_set_name(&fi->group.cg_item, name);
+       ret = config_item_set_name(&fi->group.cg_item, "%s", name);
        if (ret) {
                usb_put_function_instance(fi);
                return ERR_PTR(ret);
@@ -617,11 +597,10 @@ static struct config_item_type functions_type = {
        .ct_owner       = THIS_MODULE,
 };
 
-CONFIGFS_ATTR_STRUCT(gadget_config_name);
 GS_STRINGS_RW(gadget_config_name, configuration);
 
 static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
-       &gadget_config_name_configuration.attr,
+       &gadget_config_name_attr_configuration,
        NULL,
 };
 
@@ -720,15 +699,14 @@ static struct config_item_type config_desc_type = {
        .ct_owner       = THIS_MODULE,
 };
 
-CONFIGFS_ATTR_STRUCT(gadget_strings);
 GS_STRINGS_RW(gadget_strings, manufacturer);
 GS_STRINGS_RW(gadget_strings, product);
 GS_STRINGS_RW(gadget_strings, serialnumber);
 
 static struct configfs_attribute *gadget_strings_langid_attrs[] = {
-       &gadget_strings_manufacturer.attr,
-       &gadget_strings_product.attr,
-       &gadget_strings_serialnumber.attr,
+       &gadget_strings_attr_manufacturer,
+       &gadget_strings_attr_product,
+       &gadget_strings_attr_serialnumber,
        NULL,
 };
 
@@ -752,27 +730,25 @@ static inline struct os_desc *to_os_desc(struct config_item *item)
        return container_of(to_config_group(item), struct os_desc, group);
 }
 
-CONFIGFS_ATTR_STRUCT(os_desc);
-CONFIGFS_ATTR_OPS(os_desc);
-
-static ssize_t os_desc_use_show(struct os_desc *os_desc, char *page)
+static inline struct gadget_info *os_desc_item_to_gadget_info(
+               struct config_item *item)
 {
-       struct gadget_info *gi;
-
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+       return to_gadget_info(to_os_desc(item)->group.cg_item.ci_parent);
+}
 
-       return sprintf(page, "%d", gi->use_os_desc);
+static ssize_t os_desc_use_show(struct config_item *item, char *page)
+{
+       return sprintf(page, "%d",
+                       os_desc_item_to_gadget_info(item)->use_os_desc);
 }
 
-static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_use_store(struct config_item *item, const char *page,
                                 size_t len)
 {
-       struct gadget_info *gi;
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
        int ret;
        bool use;
 
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
        mutex_lock(&gi->lock);
        ret = strtobool(page, &use);
        if (!ret) {
@@ -784,29 +760,19 @@ static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
        return ret;
 }
 
-static struct os_desc_attribute os_desc_use =
-       __CONFIGFS_ATTR(use, S_IRUGO | S_IWUSR,
-                       os_desc_use_show,
-                       os_desc_use_store);
-
-static ssize_t os_desc_b_vendor_code_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page)
 {
-       struct gadget_info *gi;
-
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
-       return sprintf(page, "%d", gi->b_vendor_code);
+       return sprintf(page, "%d",
+                       os_desc_item_to_gadget_info(item)->b_vendor_code);
 }
 
-static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
+static ssize_t os_desc_b_vendor_code_store(struct config_item *item,
                                           const char *page, size_t len)
 {
-       struct gadget_info *gi;
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
        int ret;
        u8 b_vendor_code;
 
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
        mutex_lock(&gi->lock);
        ret = kstrtou8(page, 0, &b_vendor_code);
        if (!ret) {
@@ -818,29 +784,20 @@ static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
        return ret;
 }
 
-static struct os_desc_attribute os_desc_b_vendor_code =
-       __CONFIGFS_ATTR(b_vendor_code, S_IRUGO | S_IWUSR,
-                       os_desc_b_vendor_code_show,
-                       os_desc_b_vendor_code_store);
-
-static ssize_t os_desc_qw_sign_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)
 {
-       struct gadget_info *gi;
-
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
 
        memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
-
        return OS_STRING_QW_SIGN_LEN;
 }
 
-static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
                                     size_t len)
 {
-       struct gadget_info *gi;
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
        int res, l;
 
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
        l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
        if (page[l - 1] == '\n')
                --l;
@@ -856,15 +813,14 @@ static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
        return res;
 }
 
-static struct os_desc_attribute os_desc_qw_sign =
-       __CONFIGFS_ATTR(qw_sign, S_IRUGO | S_IWUSR,
-                       os_desc_qw_sign_show,
-                       os_desc_qw_sign_store);
+CONFIGFS_ATTR(os_desc_, use);
+CONFIGFS_ATTR(os_desc_, b_vendor_code);
+CONFIGFS_ATTR(os_desc_, qw_sign);
 
 static struct configfs_attribute *os_desc_attrs[] = {
-       &os_desc_use.attr,
-       &os_desc_b_vendor_code.attr,
-       &os_desc_qw_sign.attr,
+       &os_desc_attr_use,
+       &os_desc_attr_b_vendor_code,
+       &os_desc_attr_qw_sign,
        NULL,
 };
 
@@ -927,8 +883,6 @@ static int os_desc_unlink(struct config_item *os_desc_ci,
 
 static struct configfs_item_operations os_desc_ops = {
        .release                = os_desc_attr_release,
-       .show_attribute         = os_desc_attr_show,
-       .store_attribute        = os_desc_attr_store,
        .allow_link             = os_desc_link,
        .drop_link              = os_desc_unlink,
 };
@@ -939,28 +893,21 @@ static struct config_item_type os_desc_type = {
        .ct_owner       = THIS_MODULE,
 };
 
-CONFIGFS_ATTR_STRUCT(usb_os_desc);
-CONFIGFS_ATTR_OPS(usb_os_desc);
-
-
 static inline struct usb_os_desc_ext_prop
 *to_usb_os_desc_ext_prop(struct config_item *item)
 {
        return container_of(item, struct usb_os_desc_ext_prop, item);
 }
 
-CONFIGFS_ATTR_STRUCT(usb_os_desc_ext_prop);
-CONFIGFS_ATTR_OPS(usb_os_desc_ext_prop);
-
-static ssize_t ext_prop_type_show(struct usb_os_desc_ext_prop *ext_prop,
-                                 char *page)
+static ssize_t ext_prop_type_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%d", ext_prop->type);
+       return sprintf(page, "%d", to_usb_os_desc_ext_prop(item)->type);
 }
 
-static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_type_store(struct config_item *item,
                                   const char *page, size_t len)
 {
+       struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
        struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
        u8 type;
        int ret;
@@ -998,9 +945,9 @@ end:
        return ret;
 }
 
-static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
-                                 char *page)
+static ssize_t ext_prop_data_show(struct config_item *item, char *page)
 {
+       struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
        int len = ext_prop->data_len;
 
        if (ext_prop->type == USB_EXT_PROP_UNICODE ||
@@ -1012,9 +959,10 @@ static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
        return len;
 }
 
-static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_data_store(struct config_item *item,
                                   const char *page, size_t len)
 {
+       struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
        struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
        char *new_data;
        size_t ret_len = len;
@@ -1045,17 +993,12 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
        return ret_len;
 }
 
-static struct usb_os_desc_ext_prop_attribute ext_prop_type =
-       __CONFIGFS_ATTR(type, S_IRUGO | S_IWUSR,
-                       ext_prop_type_show, ext_prop_type_store);
-
-static struct usb_os_desc_ext_prop_attribute ext_prop_data =
-       __CONFIGFS_ATTR(data, S_IRUGO | S_IWUSR,
-                       ext_prop_data_show, ext_prop_data_store);
+CONFIGFS_ATTR(ext_prop_, type);
+CONFIGFS_ATTR(ext_prop_, data);
 
 static struct configfs_attribute *ext_prop_attrs[] = {
-       &ext_prop_type.attr,
-       &ext_prop_data.attr,
+       &ext_prop_attr_type,
+       &ext_prop_attr_data,
        NULL,
 };
 
@@ -1068,8 +1011,6 @@ static void usb_os_desc_ext_prop_release(struct config_item *item)
 
 static struct configfs_item_operations ext_prop_ops = {
        .release                = usb_os_desc_ext_prop_release,
-       .show_attribute         = usb_os_desc_ext_prop_attr_show,
-       .store_attribute        = usb_os_desc_ext_prop_attr_store,
 };
 
 static struct config_item *ext_prop_make(
@@ -1138,21 +1079,17 @@ static struct configfs_group_operations interf_grp_ops = {
        .drop_item      = &ext_prop_drop,
 };
 
-static struct configfs_item_operations interf_item_ops = {
-       .show_attribute         = usb_os_desc_attr_show,
-       .store_attribute        = usb_os_desc_attr_store,
-};
-
-static ssize_t interf_grp_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_show(struct config_item *item,
                                             char *page)
 {
-       memcpy(page, desc->ext_compat_id, 8);
+       memcpy(page, to_usb_os_desc(item)->ext_compat_id, 8);
        return 8;
 }
 
-static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_store(struct config_item *item,
                                              const char *page, size_t len)
 {
+       struct usb_os_desc *desc = to_usb_os_desc(item);
        int l;
 
        l = min_t(int, 8, len);
@@ -1168,21 +1105,17 @@ static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
        return len;
 }
 
-static struct usb_os_desc_attribute interf_grp_attr_compatible_id =
-       __CONFIGFS_ATTR(compatible_id, S_IRUGO | S_IWUSR,
-                       interf_grp_compatible_id_show,
-                       interf_grp_compatible_id_store);
-
-static ssize_t interf_grp_sub_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_show(struct config_item *item,
                                                 char *page)
 {
-       memcpy(page, desc->ext_compat_id + 8, 8);
+       memcpy(page, to_usb_os_desc(item)->ext_compat_id + 8, 8);
        return 8;
 }
 
-static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_store(struct config_item *item,
                                                  const char *page, size_t len)
 {
+       struct usb_os_desc *desc = to_usb_os_desc(item);
        int l;
 
        l = min_t(int, 8, len);
@@ -1198,14 +1131,12 @@ static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
        return len;
 }
 
-static struct usb_os_desc_attribute interf_grp_attr_sub_compatible_id =
-       __CONFIGFS_ATTR(sub_compatible_id, S_IRUGO | S_IWUSR,
-                       interf_grp_sub_compatible_id_show,
-                       interf_grp_sub_compatible_id_store);
+CONFIGFS_ATTR(interf_grp_, compatible_id);
+CONFIGFS_ATTR(interf_grp_, sub_compatible_id);
 
 static struct configfs_attribute *interf_grp_attrs[] = {
-       &interf_grp_attr_compatible_id.attr,
-       &interf_grp_attr_sub_compatible_id.attr,
+       &interf_grp_attr_compatible_id,
+       &interf_grp_attr_sub_compatible_id,
        NULL
 };
 
@@ -1243,7 +1174,6 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
        f_default_groups[0] = os_desc_group;
 
        os_desc_group->default_groups = interface_groups;
-       interface_type->ct_item_ops = &interf_item_ops;
        interface_type->ct_group_ops = &interf_grp_ops;
        interface_type->ct_attrs = interf_grp_attrs;
        interface_type->ct_owner = owner;
@@ -1376,6 +1306,19 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
                memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
        }
 
+       if (gadget_is_otg(gadget) && !otg_desc[0]) {
+               struct usb_descriptor_header *usb_desc;
+
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+               if (!usb_desc) {
+                       ret = -ENOMEM;
+                       goto err_comp_cleanup;
+               }
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
+       }
+
        /* Go through all configs, attach all functions */
        list_for_each_entry(c, &gi->cdev.configs, list) {
                struct config_usb_cfg *cfg;
@@ -1383,6 +1326,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
                struct usb_function *tmp;
                struct gadget_config_name *cn;
 
+               if (gadget_is_otg(gadget))
+                       c->descriptors = otg_desc;
+
                cfg = container_of(c, struct config_usb_cfg, c);
                if (!list_empty(&cfg->string_list)) {
                        i = 0;
@@ -1437,6 +1383,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
        cdev = get_gadget_data(gadget);
        gi = container_of(cdev, struct gadget_info, cdev);
 
+       kfree(otg_desc[0]);
+       otg_desc[0] = NULL;
        purge_configs_funcs(gi);
        composite_dev_cleanup(cdev);
        usb_ep_autoconfig_reset(cdev->gadget);
@@ -1510,12 +1458,6 @@ static struct config_group *gadgets_make(
        if (!gi->composite.gadget_driver.function)
                goto err;
 
-#ifdef CONFIG_USB_OTG
-       gi->otg.bLength = sizeof(struct usb_otg_descriptor);
-       gi->otg.bDescriptorType = USB_DT_OTG;
-       gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
-#endif
-
        config_group_init_type_name(&gi->group, name,
                                &gadget_root_type);
        return &gi->group;