Merge "usb: gadget: Send dedicate uevent for ML client connection"
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 50e4e44..f915e55 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -14,11 +14,16 @@
#include <linux/kdev_t.h>
#include <linux/usb/ch9.h>
+#ifdef CONFIG_USB_F_NCM
+#include <function/u_ncm.h>
+#endif
+
#ifdef CONFIG_USB_CONFIGFS_F_ACC
extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl);
void acc_disconnect(void);
#endif
+
static struct class *android_class;
static struct device *android_device;
static int index;
@@ -1508,6 +1513,18 @@ static int android_setup(struct usb_gadget *gadget,
}
}
+#ifdef CONFIG_USB_F_NCM
+ if (value < 0)
+ value = ncm_ctrlrequest(cdev, c);
+
+ /*
+ * for mirror link command case, if it already been handled,
+ * do not pass to composite_setup
+ */
+ if (value == 0)
+ return value;
+#endif
+
#ifdef CONFIG_USB_CONFIGFS_F_ACC
if (value < 0)
value = acc_ctrlrequest(cdev, c);
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index d2fbed7..98e353d 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1605,10 +1605,57 @@ static struct config_item_type ncm_func_type = {
.ct_owner = THIS_MODULE,
};
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+
+struct ncm_setup_desc {
+ struct work_struct work;
+ struct device *device;
+ uint8_t major; // Mirror Link major version
+ uint8_t minor; // Mirror Link minor version
+};
+
+static struct ncm_setup_desc *_ncm_setup_desc;
+
+#define MIRROR_LINK_STRING_LENGTH_MAX 32
+static void ncm_setup_work(struct work_struct *data)
+{
+ char mirror_link_string[MIRROR_LINK_STRING_LENGTH_MAX];
+ char *envp[2] = { mirror_link_string, NULL };
+
+ snprintf(mirror_link_string, MIRROR_LINK_STRING_LENGTH_MAX,
+ "MirrorLink=V%d.%d",
+ _ncm_setup_desc->major, _ncm_setup_desc->minor);
+ kobject_uevent_env(&_ncm_setup_desc->device->kobj, KOBJ_CHANGE, envp);
+}
+
+int ncm_ctrlrequest(struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *ctrl)
+{
+ int value = -EOPNOTSUPP;
+
+ if (ctrl->bRequestType == 0x40 && ctrl->bRequest == 0xF0) {
+ _ncm_setup_desc->minor = (uint8_t)(ctrl->wValue >> 8);
+ _ncm_setup_desc->major = (uint8_t)(ctrl->wValue & 0xFF);
+ schedule_work(&_ncm_setup_desc->work);
+ value = 0;
+ }
+
+ return value;
+}
+#endif
+
static void ncm_free_inst(struct usb_function_instance *f)
{
struct f_ncm_opts *opts;
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+ /* release _ncm_setup_desc related resource */
+ device_destroy(_ncm_setup_desc->device->class,
+ _ncm_setup_desc->device->devt);
+ cancel_work(&_ncm_setup_desc->work);
+ kfree(_ncm_setup_desc);
+#endif
+
opts = container_of(f, struct f_ncm_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
@@ -1627,6 +1674,14 @@ static struct usb_function_instance *ncm_alloc_inst(void)
config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type);
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+ _ncm_setup_desc = kzalloc(sizeof(*_ncm_setup_desc), GFP_KERNEL);
+ if (!_ncm_setup_desc)
+ return ERR_PTR(-ENOMEM);
+ INIT_WORK(&_ncm_setup_desc->work, ncm_setup_work);
+ _ncm_setup_desc->device = create_function_device("f_ncm");
+#endif
+
return &opts->func_inst;
}
diff --git a/drivers/usb/gadget/function/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h
index ce0f3a7..b4541e2 100644
--- a/drivers/usb/gadget/function/u_ncm.h
+++ b/drivers/usb/gadget/function/u_ncm.h
@@ -33,4 +33,8 @@ struct f_ncm_opts {
int refcnt;
};
+extern struct device *create_function_device(char *name);
+int ncm_ctrlrequest(struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *ctrl);
+
#endif /* U_NCM_H */