On 22 September 2016 at 20:23, Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx> wrote: > On Thu, Sep 22, 2016 at 07:43:59PM +0800, Baolin Wang wrote: >> From: Badhri Jagan Sridharan <Badhri@xxxxxxxxxx> >> >> Some USB managament on userspace (like Android system) rely on the uevents >> generated by the composition driver to generate user notifications. Thus this >> patch adds uevents to be generated whenever USB changes its state: connected, >> disconnected, configured. >> >> The original code was created by Badhri Jagan Sridharan, and I did some >> optimization. >> >> Signed-off-by: Badhri Jagan Sridharan <Badhri@xxxxxxxxxx> > > You can't just add someone's signed-off-by to a patch, go read what the > legal agreement you just made for someone else at a different company > (hint, you might get a nasty-gram from a google lawyer...) OK. I will talk with Badhri if I can upstream these. > >> Signed-off-by: Baolin Wang <baolin.wang@xxxxxxxxxx> >> --- >> Changes since v1: >> - Add Badhri's Signed-off-by. >> --- >> drivers/usb/gadget/Kconfig | 8 +++ >> drivers/usb/gadget/configfs.c | 107 +++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 115 insertions(+) >> >> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig >> index 2ea3fc3..9f5d0c6 100644 >> --- a/drivers/usb/gadget/Kconfig >> +++ b/drivers/usb/gadget/Kconfig >> @@ -223,6 +223,14 @@ config USB_CONFIGFS >> appropriate symbolic links. >> For more information see Documentation/usb/gadget_configfs.txt. >> >> +config USB_CONFIGFS_UEVENT >> + boolean "Uevent notification of Gadget state" >> + depends on USB_CONFIGFS > > > >> + help >> + Enable uevent notifications to userspace when the gadget >> + state changes. The gadget can be in any of the following >> + three states: "CONNECTED/DISCONNECTED/CONFIGURED" >> + >> config USB_CONFIGFS_SERIAL >> bool "Generic serial bulk in/out" >> depends on USB_CONFIGFS >> diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c >> index 3984787..4c2bc27 100644 >> --- a/drivers/usb/gadget/configfs.c >> +++ b/drivers/usb/gadget/configfs.c >> @@ -60,6 +60,11 @@ struct gadget_info { >> bool use_os_desc; >> char b_vendor_code; >> char qw_sign[OS_STRING_QW_SIGN_LEN]; >> +#ifdef CONFIG_USB_CONFIGFS_UEVENT >> + bool connected; >> + bool sw_connected; >> + struct work_struct work; >> +#endif >> }; >> >> static inline struct gadget_info *to_gadget_info(struct config_item *item) >> @@ -1197,6 +1202,57 @@ int composite_dev_prepare(struct usb_composite_driver *composite, >> int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, >> struct usb_ep *ep0); >> >> +#ifdef CONFIG_USB_CONFIGFS_UEVENT >> +static void configfs_work(struct work_struct *data) >> +{ >> + struct gadget_info *gi = container_of(data, struct gadget_info, work); >> + struct usb_composite_dev *cdev = &gi->cdev; >> + char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL }; >> + char *connected[2] = { "USB_STATE=CONNECTED", NULL }; >> + char *configured[2] = { "USB_STATE=CONFIGURED", NULL }; >> + /* 0-connected 1-configured 2-disconnected */ >> + bool status[3] = { false, false, false }; >> + unsigned long flags; >> + bool uevent_sent = false; >> + >> + spin_lock_irqsave(&cdev->lock, flags); >> + if (cdev->config && gi->connected) >> + status[1] = true; >> + >> + if (gi->connected != gi->sw_connected) { >> + if (gi->connected) >> + status[0] = true; >> + else >> + status[2] = true; >> + gi->sw_connected = gi->connected; >> + } >> + spin_unlock_irqrestore(&cdev->lock, flags); >> + >> + if (status[0]) { >> + kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, connected); >> + pr_info("%s: sent uevent %s\n", __func__, connected[0]); > > You are kidding, right? > >> + uevent_sent = true; >> + } >> + >> + if (status[1]) { >> + kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, configured); >> + pr_info("%s: sent uevent %s\n", __func__, configured[0]); > > Come on, please... > >> + uevent_sent = true; >> + } >> + >> + if (status[2]) { >> + kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, disconnected); >> + pr_info("%s: sent uevent %s\n", __func__, disconnected[0]); > > This is getting funny... > >> + uevent_sent = true; >> + } >> + >> + if (!uevent_sent) { >> + pr_info("%s: did not send uevent (%d %d %p)\n", __func__, >> + gi->connected, gi->sw_connected, cdev->config); > > Nope, not funny anymore. > >> + } >> +} >> +#endif >> + >> static void purge_configs_funcs(struct gadget_info *gi) >> { >> struct usb_configuration *c; >> @@ -1386,13 +1442,60 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) >> set_gadget_data(gadget, NULL); >> } >> >> +#ifdef CONFIG_USB_CONFIGFS_UEVENT >> +static int configfs_setup(struct usb_gadget *gadget, >> + const struct usb_ctrlrequest *c) >> +{ >> + struct usb_composite_dev *cdev = get_gadget_data(gadget); >> + struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); >> + int value = -EOPNOTSUPP; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&cdev->lock, flags); >> + if (!gi->connected) { >> + gi->connected = 1; >> + schedule_work(&gi->work); >> + } >> + spin_unlock_irqrestore(&cdev->lock, flags); >> + >> + value = composite_setup(gadget, c); >> + >> + spin_lock_irqsave(&cdev->lock, flags); >> + if (c->bRequest == USB_REQ_SET_CONFIGURATION && cdev->config) >> + schedule_work(&gi->work); >> + spin_unlock_irqrestore(&cdev->lock, flags); >> + >> + return value; >> +} >> + >> +static void configfs_disconnect(struct usb_gadget *gadget) >> +{ >> + struct usb_composite_dev *cdev = get_gadget_data(gadget); >> + struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); >> + unsigned long flags; >> + >> + spin_lock_irqsave(&cdev->lock, flags); >> + gi->connected = 0; >> + schedule_work(&gi->work); >> + spin_unlock_irqrestore(&cdev->lock, flags); >> + >> + composite_disconnect(gadget); >> +} >> +#endif >> + >> static const struct usb_gadget_driver configfs_driver_template = { >> .bind = configfs_composite_bind, >> .unbind = configfs_composite_unbind, >> >> +#ifdef CONFIG_USB_CONFIGFS_UEVENT >> + .setup = configfs_setup, >> + .reset = configfs_disconnect, >> + .disconnect = configfs_disconnect, >> +#else >> .setup = composite_setup, >> .reset = composite_disconnect, >> .disconnect = composite_disconnect, >> +#endif >> >> .suspend = composite_suspend, >> .resume = composite_resume, >> @@ -1453,6 +1556,10 @@ static struct config_group *gadgets_make( >> gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); >> gi->composite.name = gi->composite.gadget_driver.function; >> >> +#ifdef CONFIG_USB_CONFIGFS_UEVENT >> + INIT_WORK(&gi->work, configfs_work); >> +#endif > > This is just way too ugly, please make it so there are no #ifdefs in the > .c files. > > Or, as others said, why is this a build option at all, why would you not > always want this enabled if you are relying on it all of the time? Sometimes userspace does not need the notification, it is not all the time. Anyway I will remove the macro if you still insist on that. -- Baolin.wang Best Regards -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html