From: Jacek Anaszewski <j.anaszewski@samsung.com>
To: "Rafał Miłecki" <zajec5@gmail.com>
Cc: Richard Purdie <rpurdie@rpsys.net>,
Jonathan Corbet <corbet@lwn.net>,
Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>,
Geert Uytterhoeven <geert@linux-m68k.org>,
Stephan Linz <linz@li-pro.net>,
Matthias Brugger <mbrugger@suse.com>,
Boris Brezillon <boris.brezillon@free-electrons.com>,
"open list:DOCUMENTATION" <linux-doc@vger.kernel.org>,
open list <linux-kernel@vger.kernel.org>,
"open list:LED SUBSYSTEM" <linux-leds@vger.kernel.org>,
balbi@kernel.org
Subject: Re: [PATCH] leds: trigger: Introduce an USB port trigger
Date: Wed, 13 Jul 2016 16:48:04 +0200 [thread overview]
Message-ID: <578654A4.9030009@samsung.com> (raw)
In-Reply-To: <1468239883-22695-1-git-send-email-zajec5@gmail.com>
Hi Rafał,
Thanks for the patch.
On 07/11/2016 02:24 PM, Rafał Miłecki wrote:
> This commit adds a new trigger that can turn on LED when USB device gets
> connected to the USB port. This can can useful for various home routers
s/can can/can be/
> that have USB port and a proper LED telling user a device is connected.
>
> The trigger gets its documentation file but basically it just requires
> specifying USB port in a Linux format (e.g. echo 1-1 > new_port).
>
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> ---
> Documentation/leds/ledtrig-usbport.txt | 47 ++++++++
> drivers/leds/trigger/Kconfig | 8 ++
> drivers/leds/trigger/Makefile | 1 +
> drivers/leds/trigger/ledtrig-usbport.c | 196 +++++++++++++++++++++++++++++++++
> 4 files changed, 252 insertions(+)
> create mode 100644 Documentation/leds/ledtrig-usbport.txt
> create mode 100644 drivers/leds/trigger/ledtrig-usbport.c
>
> diff --git a/Documentation/leds/ledtrig-usbport.txt b/Documentation/leds/ledtrig-usbport.txt
> new file mode 100644
> index 0000000..d31dba2
> --- /dev/null
> +++ b/Documentation/leds/ledtrig-usbport.txt
> @@ -0,0 +1,47 @@
> +USB port LED trigger
> +====================
> +
> +This LED trigger can be used for signaling user a presence of USB device in a
s/signaling/signalling
s/user/to the user/
> +given port. It simply turns on LED when device appears and turns it off when it
> +disappears.
> +
> +It requires specifying a list of USB ports that should be observed. Used format
> +matches Linux kernel format and consists of a root hub number and a hub port
> +separated by a dash (e.g. 3-1).
> +
> +This also allows handling devices with internal hubs (when root hub's port has
> +always a device (hub) connected). User can simply specify specify internal hub
Maybe it would be possible to rearrange this so that there was no need
for nesting expression in brackets?
> +ports then (e.g. 1-1.1, 1-1.2, etc.).
> +
> +Please note that this trigger allows assigning multiple USB ports to a single
> +LED. This can be useful in two cases:
> +
> +1) Device with single USB LED and few physical ports
> +
> +In such case LED will be turned on as long as there is at least one connected
s/such/such a/
> +USB device.
> +
> +2) Device with a physical port handled by few controllers
> +
> +Some devices have e.g. one controller per PHY standard. E.g. USB 2.0 physical
> +port may be handled by ohci-platform, ehci-platform and xhci-hcd. If there is
> +only one LED user will most likely want to assign ports from all 3 hubs.
> +
> +
> +This trigger can be activated from user space on led class devices as shown
> +below:
> +
> + echo usbport > trigger
> +
> +This adds the following sysfs attributes to the LED:
> +
> + ports - allows listing all USB ports assigned to the trigger.
> +
> + new_port - allows adding a new USB port by simply writing to it.
> +
> +Example use-case:
> +
> + echo usbport > trigger
> + echo 4-1 > new_port
> + echo 2-1 > new_port
> + cat ports
I will need USB maintainer's ack for this patch.
Adding Felipe.
> diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
> index 3f9ddb9..bdd6fd2 100644
> --- a/drivers/leds/trigger/Kconfig
> +++ b/drivers/leds/trigger/Kconfig
> @@ -126,4 +126,12 @@ config LEDS_TRIGGER_PANIC
> a different trigger.
> If unsure, say Y.
>
> +config LEDS_TRIGGER_USBPORT
> + tristate "USB port LED trigger"
> + depends on LEDS_TRIGGERS && USB
> + help
> + This allows LEDs to be controlled by USB events. Enabling this option
> + allows specifying list of USB ports that should turn on LED when some
> + USB device gets connected.
> +
> endif # LEDS_TRIGGERS
> diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile
> index a72c43c..56e1741 100644
> --- a/drivers/leds/trigger/Makefile
> +++ b/drivers/leds/trigger/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
> obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
> obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
> obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
> +obj-$(CONFIG_LEDS_TRIGGER_USBPORT) += ledtrig-usbport.o
> diff --git a/drivers/leds/trigger/ledtrig-usbport.c b/drivers/leds/trigger/ledtrig-usbport.c
> new file mode 100644
> index 0000000..eb20a8f
> --- /dev/null
> +++ b/drivers/leds/trigger/ledtrig-usbport.c
> @@ -0,0 +1,196 @@
> +/*
> + * USB port LED trigger
> + *
> + * Copyright (C) 2016 Rafał Miłecki <rafal.milecki@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/usb.h>
> +#include "../leds.h"
> +
> +struct usbport_trig_port {
> + char *name;
> + struct list_head list;
> +};
> +
> +struct usbport_trig_data {
> + struct led_classdev *led_cdev;
> + struct list_head ports;
> + struct notifier_block nb;
> + int count; /* Amount of connected matching devices */
> +};
> +
> +static ssize_t ports_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
> + struct usbport_trig_data *usbport_data = led_cdev->trigger_data;
> + struct usbport_trig_port *port;
> + ssize_t ret = 0;
> + int len;
> +
> + list_for_each_entry(port, &usbport_data->ports, list) {
> + len = sprintf(buf + ret, "%s\n", port->name);
> + if (len >= 0)
> + ret += len;
> + }
> +
> + return ret;
> +}
> +
> +static DEVICE_ATTR(ports, S_IRUSR, ports_show, NULL);
> +
> +static ssize_t new_port_store(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t size)
> +{
> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
> + struct usbport_trig_data *usbport_data = led_cdev->trigger_data;
> + struct usbport_trig_port *port;
> + size_t len;
> +
> + port = kzalloc(sizeof(*port), GFP_KERNEL);
> + if (!port)
> + return -ENOMEM;
> +
> + len = strlen(buf);
> + if (len && buf[len - 1] == '\n')
> + len--;
> + if (!len)
> + return -EINVAL;
> +
> + port->name = kzalloc(strlen(buf), GFP_KERNEL);
> + if (!port->name) {
> + kfree(port);
> + return -ENOMEM;
> + }
> + strncpy(port->name, buf, len);
> +
> + list_add_tail(&port->list, &usbport_data->ports);
> +
> + return size;
> +}
> +
> +static DEVICE_ATTR(new_port, S_IWUSR, NULL, new_port_store);
> +
> +static bool usbport_trig_match(struct usbport_trig_data *usbport_data,
> + struct usb_device *usb_dev)
> +{
> + struct usbport_trig_port *port;
> + const char *name = dev_name(&usb_dev->dev);
> +
> + list_for_each_entry(port, &usbport_data->ports, list) {
> + if (!strcmp(port->name, name))
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static int usbport_trig_notify(struct notifier_block *nb, unsigned long action,
> + void *data)
> +{
> + struct usbport_trig_data *usbport_data =
> + container_of(nb, struct usbport_trig_data, nb);
> + struct led_classdev *led_cdev = usbport_data->led_cdev;
> +
> + switch (action) {
> + case USB_DEVICE_ADD:
> + if (usbport_trig_match(usbport_data, data)) {
> + if (usbport_data->count++ == 0)
> + led_set_brightness_nosleep(led_cdev, LED_FULL);
> + }
> + break;
> + case USB_DEVICE_REMOVE:
> + if (usbport_trig_match(usbport_data, data)) {
> + if (--usbport_data->count == 0)
> + led_set_brightness_nosleep(led_cdev, LED_OFF);
> + }
> + break;
> + }
> +
> + return NOTIFY_OK;
> +}
> +
> +static void usbport_trig_activate(struct led_classdev *led_cdev)
> +{
> + struct usbport_trig_data *usbport_data;
> + int err;
> +
> + usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL);
> + if (!usbport_data)
> + return;
> + usbport_data->led_cdev = led_cdev;
> + INIT_LIST_HEAD(&usbport_data->ports);
> + usbport_data->nb.notifier_call = usbport_trig_notify,
> + led_cdev->trigger_data = usbport_data;
> +
> + err = device_create_file(led_cdev->dev, &dev_attr_ports);
> + if (err)
> + goto err_free;
> + err = device_create_file(led_cdev->dev, &dev_attr_new_port);
> + if (err)
> + goto err_remove_ports;
Couldn't we live without new_port attr? Writing the ports attribute
would add the port. We should have a means for removing the port too,
possibly prepended with some character, like '-'.
> +
> + usb_register_notify(&usbport_data->nb);
> +
> + led_cdev->activated = true;
> + return;
> +
> +err_free:
> + kfree(usbport_data);
> +err_remove_ports:
> + device_remove_file(led_cdev->dev, &dev_attr_ports);
> +}
> +
> +static void usbport_trig_deactivate(struct led_classdev *led_cdev)
> +{
> + struct usbport_trig_data *usbport_data = led_cdev->trigger_data;
> + struct usbport_trig_port *port, *tmp;
> +
> + if (!led_cdev->activated)
> + return;
> +
> + usb_unregister_notify(&usbport_data->nb);
> +
> + list_for_each_entry_safe(port, tmp, &usbport_data->ports, list) {
> + kfree(port->name);
> + list_del(&port->list);
> + }
> +
> + device_remove_file(led_cdev->dev, &dev_attr_new_port);
> + device_remove_file(led_cdev->dev, &dev_attr_ports);
> + kfree(usbport_data);
> +
> + led_cdev->activated = false;
> +}
> +
> +static struct led_trigger usbport_led_trigger = {
> + .name = "usbport",
> + .activate = usbport_trig_activate,
> + .deactivate = usbport_trig_deactivate,
> +};
> +
> +static int __init usbport_trig_init(void)
> +{
> + return led_trigger_register(&usbport_led_trigger);
> +}
> +
> +static void __exit usbport_trig_exit(void)
> +{
> + led_trigger_unregister(&usbport_led_trigger);
> +}
> +
> +module_init(usbport_trig_init);
> +module_exit(usbport_trig_exit);
> +
> +MODULE_AUTHOR("Rafał Miłecki <rafal.milecki@gmail.com>");
> +MODULE_DESCRIPTION("USB port trigger");
> +MODULE_LICENSE("GPL");
>
--
Best regards,
Jacek Anaszewski
next prev parent reply other threads:[~2016-07-13 14:48 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-11 12:24 [PATCH] leds: trigger: Introduce an USB port trigger Rafał Miłecki
2016-07-11 12:24 ` Rafał Miłecki
2016-07-13 14:48 ` Jacek Anaszewski [this message]
2016-07-15 21:10 ` [PATCH V2] " Rafał Miłecki
2016-07-15 21:10 ` Rafał Miłecki
2016-07-18 2:31 ` Peter Chen
2016-07-18 4:44 ` Rafał Miłecki
2016-07-18 5:40 ` Peter Chen
2016-07-18 5:57 ` Rafał Miłecki
2016-07-18 5:53 ` Peter Chen
2016-07-18 6:55 ` Rafał Miłecki
2016-07-20 8:08 ` Pavel Machek
2016-07-20 8:06 ` Pavel Machek
2016-07-20 8:06 ` Pavel Machek
2016-07-20 1:02 ` Rob Herring
2016-07-20 8:06 ` Rafał Miłecki
2016-07-21 20:42 ` Rob Herring
2016-07-29 7:09 ` Rafał Miłecki
2016-08-16 21:22 ` Rafał Miłecki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=578654A4.9030009@samsung.com \
--to=j.anaszewski@samsung.com \
--cc=balbi@kernel.org \
--cc=boris.brezillon@free-electrons.com \
--cc=corbet@lwn.net \
--cc=ezequiel@vanguardiasur.com.ar \
--cc=geert@linux-m68k.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=linz@li-pro.net \
--cc=mbrugger@suse.com \
--cc=rpurdie@rpsys.net \
--cc=zajec5@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.