All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johan Hovold <johan-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
To: Janne Kanniainen
	<janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: jkosina-AlSwsSmVLrQ@public.gmane.org,
	johan-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	cooloney-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-leds-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v9] leds: USB: HID: Add support for MSI GT683R led panels
Date: Wed, 18 Jun 2014 18:11:50 +0200	[thread overview]
Message-ID: <20140618161150.GH31163@localhost> (raw)
In-Reply-To: <1403107502-14106-1-git-send-email-janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Wed, Jun 18, 2014 at 07:05:02PM +0300, Janne Kanniainen wrote:
> This driver adds support for USB controlled led panels that exists in
> MSI GT683R laptop
> 
> Signed-off-by: Janne Kanniainen <janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Reviewed-by: Johan Hovold <johan-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Thanks, Janne!

Johan

> ---
> Changes in v2:
> 	- sorted headers to alphabetic order
> 	- using devm_kzalloc
> 	- using BIT(n)
> 	- using usb_control_msg instead of usb_submit_urb
> 	- removing unneeded code
> Changes in v3:
> 	- implemented as HID device
> 	- some cleanups and bug fixes
> 
> Changes in v4:
> 	- more cleanups
> 	- support for selecting leds
> 	- suppport for selecting status
> 
> Changes in v5:
> 	- mode attribute documented under Documentation/ABI
> 	- made array for led_classdev
> 	- led devices uses now recommended naming scheme
> 
> Changes in v6:
> 	- flush_work added
> 	- using hid device name instead of hard coded gt683r
> 	- allocating name buffers with devm_kzalloc
> 
> Changes in v7:
> 	- buf with for fixed
> 
> Changes in v8:
> 	- some cleanups and bugs fixed
> 
> Changes in v9:
> 	- few style issues fixed
> 
>  .../ABI/testing/sysfs-class-hid-driver-gt683r      |  14 +
>  drivers/hid/Kconfig                                |  14 +
>  drivers/hid/Makefile                               |   1 +
>  drivers/hid/hid-core.c                             |   1 +
>  drivers/hid/hid-gt683r.c                           | 309 +++++++++++++++++++++
>  drivers/hid/hid-ids.h                              |   2 +-
>  drivers/hid/usbhid/hid-quirks.c                    |   2 +-
>  7 files changed, 341 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
>  create mode 100644 drivers/hid/hid-gt683r.c
> 
> diff --git a/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> new file mode 100644
> index 0000000..317e9d5
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> @@ -0,0 +1,14 @@
> +What:		/sys/class/hidraw/<hidraw>/device/leds_mode
> +Date:		Jun 2014
> +KernelVersion:	3.17
> +Contact:	Janne Kanniainen <janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> +Description:
> +		Set the mode of LEDs
> +
> +		0 - normal
> +		1 - audio
> +		2 - breathing
> +
> +		Normal: LEDs are fully on when enabled
> +		Audio:  LEDs brightness depends on sound level
> +		Breathing: LEDs brightness varies at human breathing rate
> \ No newline at end of file
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 7af9d0b..e2f4590 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -261,6 +261,20 @@ config HOLTEK_FF
>  	  Say Y here if you have a Holtek On Line Grip based game controller
>  	  and want to have force feedback support for it.
>  
> +config HID_GT683R
> +	tristate "MSI GT68xR LED support"
> +	depends on LEDS_CLASS && USB_HID
> +	---help---
> +	Say Y here if you want to enable support for the three MSI GT68xR LEDs
> +
> +	This driver support following modes:
> +	  - Normal: LEDs are fully on when enabled
> +	  - Audio:  LEDs brightness depends on sound level
> +	  - Breathing: LEDs brightness varies at human breathing rate
> +
> +	Currently the following devices are know to be supported:
> +	  - MSI GT683R
> +
>  config HID_HUION
>  	tristate "Huion tablets"
>  	depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index fc712dd..7129311 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -48,6 +48,7 @@ obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
>  obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
>  obj-$(CONFIG_HID_ELO)		+= hid-elo.o
>  obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
> +obj-$(CONFIG_HID_GT683R)	+= hid-gt683r.o
>  obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
>  obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-kbd.o
>  obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-mouse.o
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index da52279..ec88fdb 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1827,6 +1827,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
> diff --git a/drivers/hid/hid-gt683r.c b/drivers/hid/hid-gt683r.c
> new file mode 100644
> index 0000000..077f7a1
> --- /dev/null
> +++ b/drivers/hid/hid-gt683r.c
> @@ -0,0 +1,309 @@
> +/*
> + * MSI GT683R led driver
> + *
> + * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/kernel.h>
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +
> +#include "hid-ids.h"
> +
> +#define GT683R_BUFFER_SIZE			8
> +
> +/*
> + * GT683R_LED_OFF: all LEDs are off
> + * GT683R_LED_AUDIO: LEDs brightness depends on sound level
> + * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate
> + * GT683R_LED_NORMAL: LEDs are fully on when enabled
> + */
> +enum gt683r_led_mode {
> +	GT683R_LED_OFF = 0,
> +	GT683R_LED_AUDIO = 2,
> +	GT683R_LED_BREATHING = 3,
> +	GT683R_LED_NORMAL = 5
> +};
> +
> +enum gt683r_panels {
> +	GT683R_LED_BACK = 0,
> +	GT683R_LED_SIDE = 1,
> +	GT683R_LED_FRONT = 2,
> +	GT683R_LED_COUNT,
> +};
> +
> +static const char * const gt683r_panel_names[] = {
> +	"back",
> +	"side",
> +	"front",
> +};
> +
> +struct gt683r_led {
> +	struct hid_device *hdev;
> +	struct led_classdev led_devs[GT683R_LED_COUNT];
> +	struct mutex lock;
> +	struct work_struct work;
> +	enum led_brightness brightnesses[GT683R_LED_COUNT];
> +	enum gt683r_led_mode mode;
> +};
> +
> +static const struct hid_device_id gt683r_led_id[] = {
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
> +	{ }
> +};
> +
> +static void gt683r_brightness_set(struct led_classdev *led_cdev,
> +				enum led_brightness brightness)
> +{
> +	int i;
> +	struct device *dev = led_cdev->dev->parent;
> +	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +	for (i = 0; i < GT683R_LED_COUNT; i++) {
> +		if (led_cdev == &led->led_devs[i])
> +			break;
> +	}
> +
> +	if (i < GT683R_LED_COUNT) {
> +		led->brightnesses[i] = brightness;
> +		schedule_work(&led->work);
> +	}
> +}
> +
> +static ssize_t leds_mode_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	u8 sysfs_mode;
> +	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +	if (led->mode == GT683R_LED_NORMAL)
> +		sysfs_mode = 0;
> +	else if (led->mode == GT683R_LED_AUDIO)
> +		sysfs_mode = 1;
> +	else
> +		sysfs_mode = 2;
> +
> +	return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode);
> +}
> +
> +static ssize_t leds_mode_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	u8 sysfs_mode;
> +	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +
> +	if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2)
> +		return -EINVAL;
> +
> +	mutex_lock(&led->lock);
> +
> +	if (sysfs_mode == 0)
> +		led->mode = GT683R_LED_NORMAL;
> +	else if (sysfs_mode == 1)
> +		led->mode = GT683R_LED_AUDIO;
> +	else
> +		led->mode = GT683R_LED_BREATHING;
> +
> +	mutex_unlock(&led->lock);
> +	schedule_work(&led->work);
> +
> +	return count;
> +}
> +
> +static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg)
> +{
> +	int ret;
> +
> +	ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE,
> +				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
> +	if (ret != GT683R_BUFFER_SIZE) {
> +		hid_err(led->hdev,
> +			"failed to send set report request: %i\n", ret);
> +		if (ret < 0)
> +			return ret;
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int gt683r_leds_set(struct gt683r_led *led, u8 leds)
> +{
> +	int ret;
> +	u8 *buffer;
> +
> +	buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	buffer[0] = 0x01;
> +	buffer[1] = 0x02;
> +	buffer[2] = 0x30;
> +	buffer[3] = leds;
> +	ret = gt683r_led_snd_msg(led, buffer);
> +
> +	kfree(buffer);
> +	return ret;
> +}
> +
> +static int gt683r_mode_set(struct gt683r_led *led, u8 mode)
> +{
> +	int ret;
> +	u8 *buffer;
> +
> +	buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	buffer[0] = 0x01;
> +	buffer[1] = 0x02;
> +	buffer[2] = 0x20;
> +	buffer[3] = mode;
> +	buffer[4] = 0x01;
> +	ret = gt683r_led_snd_msg(led, buffer);
> +
> +	kfree(buffer);
> +	return ret;
> +}
> +
> +static void gt683r_led_work(struct work_struct *work)
> +{
> +	int i;
> +	u8 leds = 0;
> +	u8 mode;
> +	struct gt683r_led *led = container_of(work, struct gt683r_led, work);
> +
> +	mutex_lock(&led->lock);
> +
> +	for (i = 0; i < GT683R_LED_COUNT; i++) {
> +		if (led->brightnesses[i])
> +			leds |= BIT(i);
> +	}
> +
> +	if (gt683r_leds_set(led, leds))
> +		goto fail;
> +
> +	if (leds)
> +		mode = led->mode;
> +	else
> +		mode = GT683R_LED_OFF;
> +
> +	gt683r_mode_set(led, mode);
> +fail:
> +	mutex_unlock(&led->lock);
> +}
> +
> +static DEVICE_ATTR_RW(leds_mode);
> +
> +static int gt683r_led_probe(struct hid_device *hdev,
> +			const struct hid_device_id *id)
> +{
> +	int i;
> +	int ret;
> +	int name_sz;
> +	char *name;
> +	struct gt683r_led *led;
> +
> +	led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL);
> +	if (!led)
> +		return -ENOMEM;
> +
> +	led->mode = GT683R_LED_NORMAL;
> +	led->hdev = hdev;
> +	hid_set_drvdata(hdev, led);
> +
> +	ret = hid_parse(hdev);
> +	if (ret) {
> +		hid_err(hdev, "hid parsing failed\n");
> +		return ret;
> +	}
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
> +	if (ret) {
> +		hid_err(hdev, "hw start failed\n");
> +		return ret;
> +	}
> +
> +	for (i = 0; i < GT683R_LED_COUNT; i++) {
> +		name_sz = strlen(dev_name(&hdev->dev)) +
> +				strlen(gt683r_panel_names[i]) + 3;
> +
> +		name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
> +		if (!name) {
> +			ret = -ENOMEM;
> +			goto fail;
> +		}
> +
> +		snprintf(name, name_sz, "%s::%s",
> +				dev_name(&hdev->dev), gt683r_panel_names[i]);
> +		led->led_devs[i].name = name;
> +		led->led_devs[i].max_brightness = 1;
> +		led->led_devs[i].brightness_set = gt683r_brightness_set;
> +		ret = led_classdev_register(&hdev->dev, &led->led_devs[i]);
> +		if (ret) {
> +			hid_err(hdev, "could not register led device\n");
> +			goto fail;
> +		}
> +	}
> +
> +	ret = device_create_file(&led->hdev->dev, &dev_attr_leds_mode);
> +	if (ret) {
> +		hid_err(hdev, "could not make mode attribute file\n");
> +		goto fail;
> +	}
> +
> +	mutex_init(&led->lock);
> +	INIT_WORK(&led->work, gt683r_led_work);
> +
> +	return 0;
> +
> +fail:
> +	for (i = i - 1; i >= 0; i--)
> +		led_classdev_unregister(&led->led_devs[i]);
> +	hid_hw_stop(hdev);
> +	return ret;
> +}
> +
> +static void gt683r_led_remove(struct hid_device *hdev)
> +{
> +	int i;
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +	device_remove_file(&hdev->dev, &dev_attr_leds_mode);
> +	for (i = 0; i < GT683R_LED_COUNT; i++)
> +		led_classdev_unregister(&led->led_devs[i]);
> +	flush_work(&led->work);
> +	hid_hw_stop(hdev);
> +}
> +
> +static struct hid_driver gt683r_led_driver = {
> +	.probe = gt683r_led_probe,
> +	.remove = gt683r_led_remove,
> +	.name = "gt683r_led",
> +	.id_table = gt683r_led_id,
> +};
> +
> +module_hid_driver(gt683r_led_driver);
> +
> +MODULE_AUTHOR("Janne Kanniainen");
> +MODULE_DESCRIPTION("MSI GT683R led driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 34bb220..3692d37 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -641,7 +641,7 @@
>  #define USB_DEVICE_ID_GENIUS_KB29E	0x3004
>  
>  #define USB_VENDOR_ID_MSI		0x1770
> -#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL	0xff00
> +#define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
>  
>  #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
>  #define USB_DEVICE_ID_N_S_HARMONY	0xc359
> diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
> index 8e4ddb3..c640e1d 100644
> --- a/drivers/hid/usbhid/hid-quirks.c
> +++ b/drivers/hid/usbhid/hid-quirks.c
> @@ -73,7 +73,7 @@ static const struct hid_blacklist {
>  	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
>  	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
> -	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
> +	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

WARNING: multiple messages have this Message-ID (diff)
From: Johan Hovold <johan@kernel.org>
To: Janne Kanniainen <janne.kanniainen@gmail.com>
Cc: jkosina@suse.cz, johan@kernel.org, cooloney@gmail.com,
	linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org,
	linux-usb@vger.kernel.org, linux-input@vger.kernel.org
Subject: Re: [PATCH v9] leds: USB: HID: Add support for MSI GT683R led panels
Date: Wed, 18 Jun 2014 18:11:50 +0200	[thread overview]
Message-ID: <20140618161150.GH31163@localhost> (raw)
In-Reply-To: <1403107502-14106-1-git-send-email-janne.kanniainen@gmail.com>

On Wed, Jun 18, 2014 at 07:05:02PM +0300, Janne Kanniainen wrote:
> This driver adds support for USB controlled led panels that exists in
> MSI GT683R laptop
> 
> Signed-off-by: Janne Kanniainen <janne.kanniainen@gmail.com>

Reviewed-by: Johan Hovold <johan@kernel.org>

Thanks, Janne!

Johan

> ---
> Changes in v2:
> 	- sorted headers to alphabetic order
> 	- using devm_kzalloc
> 	- using BIT(n)
> 	- using usb_control_msg instead of usb_submit_urb
> 	- removing unneeded code
> Changes in v3:
> 	- implemented as HID device
> 	- some cleanups and bug fixes
> 
> Changes in v4:
> 	- more cleanups
> 	- support for selecting leds
> 	- suppport for selecting status
> 
> Changes in v5:
> 	- mode attribute documented under Documentation/ABI
> 	- made array for led_classdev
> 	- led devices uses now recommended naming scheme
> 
> Changes in v6:
> 	- flush_work added
> 	- using hid device name instead of hard coded gt683r
> 	- allocating name buffers with devm_kzalloc
> 
> Changes in v7:
> 	- buf with for fixed
> 
> Changes in v8:
> 	- some cleanups and bugs fixed
> 
> Changes in v9:
> 	- few style issues fixed
> 
>  .../ABI/testing/sysfs-class-hid-driver-gt683r      |  14 +
>  drivers/hid/Kconfig                                |  14 +
>  drivers/hid/Makefile                               |   1 +
>  drivers/hid/hid-core.c                             |   1 +
>  drivers/hid/hid-gt683r.c                           | 309 +++++++++++++++++++++
>  drivers/hid/hid-ids.h                              |   2 +-
>  drivers/hid/usbhid/hid-quirks.c                    |   2 +-
>  7 files changed, 341 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
>  create mode 100644 drivers/hid/hid-gt683r.c
> 
> diff --git a/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> new file mode 100644
> index 0000000..317e9d5
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> @@ -0,0 +1,14 @@
> +What:		/sys/class/hidraw/<hidraw>/device/leds_mode
> +Date:		Jun 2014
> +KernelVersion:	3.17
> +Contact:	Janne Kanniainen <janne.kanniainen@gmail.com>
> +Description:
> +		Set the mode of LEDs
> +
> +		0 - normal
> +		1 - audio
> +		2 - breathing
> +
> +		Normal: LEDs are fully on when enabled
> +		Audio:  LEDs brightness depends on sound level
> +		Breathing: LEDs brightness varies at human breathing rate
> \ No newline at end of file
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 7af9d0b..e2f4590 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -261,6 +261,20 @@ config HOLTEK_FF
>  	  Say Y here if you have a Holtek On Line Grip based game controller
>  	  and want to have force feedback support for it.
>  
> +config HID_GT683R
> +	tristate "MSI GT68xR LED support"
> +	depends on LEDS_CLASS && USB_HID
> +	---help---
> +	Say Y here if you want to enable support for the three MSI GT68xR LEDs
> +
> +	This driver support following modes:
> +	  - Normal: LEDs are fully on when enabled
> +	  - Audio:  LEDs brightness depends on sound level
> +	  - Breathing: LEDs brightness varies at human breathing rate
> +
> +	Currently the following devices are know to be supported:
> +	  - MSI GT683R
> +
>  config HID_HUION
>  	tristate "Huion tablets"
>  	depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index fc712dd..7129311 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -48,6 +48,7 @@ obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
>  obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
>  obj-$(CONFIG_HID_ELO)		+= hid-elo.o
>  obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
> +obj-$(CONFIG_HID_GT683R)	+= hid-gt683r.o
>  obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
>  obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-kbd.o
>  obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-mouse.o
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index da52279..ec88fdb 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1827,6 +1827,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
> diff --git a/drivers/hid/hid-gt683r.c b/drivers/hid/hid-gt683r.c
> new file mode 100644
> index 0000000..077f7a1
> --- /dev/null
> +++ b/drivers/hid/hid-gt683r.c
> @@ -0,0 +1,309 @@
> +/*
> + * MSI GT683R led driver
> + *
> + * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen@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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/kernel.h>
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +
> +#include "hid-ids.h"
> +
> +#define GT683R_BUFFER_SIZE			8
> +
> +/*
> + * GT683R_LED_OFF: all LEDs are off
> + * GT683R_LED_AUDIO: LEDs brightness depends on sound level
> + * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate
> + * GT683R_LED_NORMAL: LEDs are fully on when enabled
> + */
> +enum gt683r_led_mode {
> +	GT683R_LED_OFF = 0,
> +	GT683R_LED_AUDIO = 2,
> +	GT683R_LED_BREATHING = 3,
> +	GT683R_LED_NORMAL = 5
> +};
> +
> +enum gt683r_panels {
> +	GT683R_LED_BACK = 0,
> +	GT683R_LED_SIDE = 1,
> +	GT683R_LED_FRONT = 2,
> +	GT683R_LED_COUNT,
> +};
> +
> +static const char * const gt683r_panel_names[] = {
> +	"back",
> +	"side",
> +	"front",
> +};
> +
> +struct gt683r_led {
> +	struct hid_device *hdev;
> +	struct led_classdev led_devs[GT683R_LED_COUNT];
> +	struct mutex lock;
> +	struct work_struct work;
> +	enum led_brightness brightnesses[GT683R_LED_COUNT];
> +	enum gt683r_led_mode mode;
> +};
> +
> +static const struct hid_device_id gt683r_led_id[] = {
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
> +	{ }
> +};
> +
> +static void gt683r_brightness_set(struct led_classdev *led_cdev,
> +				enum led_brightness brightness)
> +{
> +	int i;
> +	struct device *dev = led_cdev->dev->parent;
> +	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +	for (i = 0; i < GT683R_LED_COUNT; i++) {
> +		if (led_cdev == &led->led_devs[i])
> +			break;
> +	}
> +
> +	if (i < GT683R_LED_COUNT) {
> +		led->brightnesses[i] = brightness;
> +		schedule_work(&led->work);
> +	}
> +}
> +
> +static ssize_t leds_mode_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	u8 sysfs_mode;
> +	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +	if (led->mode == GT683R_LED_NORMAL)
> +		sysfs_mode = 0;
> +	else if (led->mode == GT683R_LED_AUDIO)
> +		sysfs_mode = 1;
> +	else
> +		sysfs_mode = 2;
> +
> +	return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode);
> +}
> +
> +static ssize_t leds_mode_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	u8 sysfs_mode;
> +	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +
> +	if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2)
> +		return -EINVAL;
> +
> +	mutex_lock(&led->lock);
> +
> +	if (sysfs_mode == 0)
> +		led->mode = GT683R_LED_NORMAL;
> +	else if (sysfs_mode == 1)
> +		led->mode = GT683R_LED_AUDIO;
> +	else
> +		led->mode = GT683R_LED_BREATHING;
> +
> +	mutex_unlock(&led->lock);
> +	schedule_work(&led->work);
> +
> +	return count;
> +}
> +
> +static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg)
> +{
> +	int ret;
> +
> +	ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE,
> +				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
> +	if (ret != GT683R_BUFFER_SIZE) {
> +		hid_err(led->hdev,
> +			"failed to send set report request: %i\n", ret);
> +		if (ret < 0)
> +			return ret;
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int gt683r_leds_set(struct gt683r_led *led, u8 leds)
> +{
> +	int ret;
> +	u8 *buffer;
> +
> +	buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	buffer[0] = 0x01;
> +	buffer[1] = 0x02;
> +	buffer[2] = 0x30;
> +	buffer[3] = leds;
> +	ret = gt683r_led_snd_msg(led, buffer);
> +
> +	kfree(buffer);
> +	return ret;
> +}
> +
> +static int gt683r_mode_set(struct gt683r_led *led, u8 mode)
> +{
> +	int ret;
> +	u8 *buffer;
> +
> +	buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
> +	if (!buffer)
> +		return -ENOMEM;
> +
> +	buffer[0] = 0x01;
> +	buffer[1] = 0x02;
> +	buffer[2] = 0x20;
> +	buffer[3] = mode;
> +	buffer[4] = 0x01;
> +	ret = gt683r_led_snd_msg(led, buffer);
> +
> +	kfree(buffer);
> +	return ret;
> +}
> +
> +static void gt683r_led_work(struct work_struct *work)
> +{
> +	int i;
> +	u8 leds = 0;
> +	u8 mode;
> +	struct gt683r_led *led = container_of(work, struct gt683r_led, work);
> +
> +	mutex_lock(&led->lock);
> +
> +	for (i = 0; i < GT683R_LED_COUNT; i++) {
> +		if (led->brightnesses[i])
> +			leds |= BIT(i);
> +	}
> +
> +	if (gt683r_leds_set(led, leds))
> +		goto fail;
> +
> +	if (leds)
> +		mode = led->mode;
> +	else
> +		mode = GT683R_LED_OFF;
> +
> +	gt683r_mode_set(led, mode);
> +fail:
> +	mutex_unlock(&led->lock);
> +}
> +
> +static DEVICE_ATTR_RW(leds_mode);
> +
> +static int gt683r_led_probe(struct hid_device *hdev,
> +			const struct hid_device_id *id)
> +{
> +	int i;
> +	int ret;
> +	int name_sz;
> +	char *name;
> +	struct gt683r_led *led;
> +
> +	led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL);
> +	if (!led)
> +		return -ENOMEM;
> +
> +	led->mode = GT683R_LED_NORMAL;
> +	led->hdev = hdev;
> +	hid_set_drvdata(hdev, led);
> +
> +	ret = hid_parse(hdev);
> +	if (ret) {
> +		hid_err(hdev, "hid parsing failed\n");
> +		return ret;
> +	}
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
> +	if (ret) {
> +		hid_err(hdev, "hw start failed\n");
> +		return ret;
> +	}
> +
> +	for (i = 0; i < GT683R_LED_COUNT; i++) {
> +		name_sz = strlen(dev_name(&hdev->dev)) +
> +				strlen(gt683r_panel_names[i]) + 3;
> +
> +		name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
> +		if (!name) {
> +			ret = -ENOMEM;
> +			goto fail;
> +		}
> +
> +		snprintf(name, name_sz, "%s::%s",
> +				dev_name(&hdev->dev), gt683r_panel_names[i]);
> +		led->led_devs[i].name = name;
> +		led->led_devs[i].max_brightness = 1;
> +		led->led_devs[i].brightness_set = gt683r_brightness_set;
> +		ret = led_classdev_register(&hdev->dev, &led->led_devs[i]);
> +		if (ret) {
> +			hid_err(hdev, "could not register led device\n");
> +			goto fail;
> +		}
> +	}
> +
> +	ret = device_create_file(&led->hdev->dev, &dev_attr_leds_mode);
> +	if (ret) {
> +		hid_err(hdev, "could not make mode attribute file\n");
> +		goto fail;
> +	}
> +
> +	mutex_init(&led->lock);
> +	INIT_WORK(&led->work, gt683r_led_work);
> +
> +	return 0;
> +
> +fail:
> +	for (i = i - 1; i >= 0; i--)
> +		led_classdev_unregister(&led->led_devs[i]);
> +	hid_hw_stop(hdev);
> +	return ret;
> +}
> +
> +static void gt683r_led_remove(struct hid_device *hdev)
> +{
> +	int i;
> +	struct gt683r_led *led = hid_get_drvdata(hdev);
> +
> +	device_remove_file(&hdev->dev, &dev_attr_leds_mode);
> +	for (i = 0; i < GT683R_LED_COUNT; i++)
> +		led_classdev_unregister(&led->led_devs[i]);
> +	flush_work(&led->work);
> +	hid_hw_stop(hdev);
> +}
> +
> +static struct hid_driver gt683r_led_driver = {
> +	.probe = gt683r_led_probe,
> +	.remove = gt683r_led_remove,
> +	.name = "gt683r_led",
> +	.id_table = gt683r_led_id,
> +};
> +
> +module_hid_driver(gt683r_led_driver);
> +
> +MODULE_AUTHOR("Janne Kanniainen");
> +MODULE_DESCRIPTION("MSI GT683R led driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 34bb220..3692d37 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -641,7 +641,7 @@
>  #define USB_DEVICE_ID_GENIUS_KB29E	0x3004
>  
>  #define USB_VENDOR_ID_MSI		0x1770
> -#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL	0xff00
> +#define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
>  
>  #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
>  #define USB_DEVICE_ID_N_S_HARMONY	0xc359
> diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
> index 8e4ddb3..c640e1d 100644
> --- a/drivers/hid/usbhid/hid-quirks.c
> +++ b/drivers/hid/usbhid/hid-quirks.c
> @@ -73,7 +73,7 @@ static const struct hid_blacklist {
>  	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
>  	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
> -	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
> +	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
>  	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },

  parent reply	other threads:[~2014-06-18 16:11 UTC|newest]

Thread overview: 81+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-05 21:29 [PATCH v2] leds: USB: Add support for MSI GT683R led panels Janne Kanniainen
2014-06-06  9:47 ` Johan Hovold
2014-06-07 10:12   ` Janne Kanniainen
2014-06-09 11:42     ` Johan Hovold
2014-06-10 21:10       ` Janne Kanniainen
2014-06-10 21:21         ` [PATCH v3] leds: USB: HID: " Janne Kanniainen
2014-06-11 11:25           ` Jiri Kosina
2014-06-11 14:06             ` Johan Hovold
     [not found]           ` <1402435299-16410-1-git-send-email-janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-06-11 14:05             ` Johan Hovold
2014-06-11 14:05               ` Johan Hovold
2014-06-11 15:30               ` Johan Hovold
2014-06-11 17:34               ` Johan Hovold
2014-06-11 22:48                 ` [PATCH v4] " Janne Kanniainen
2014-06-12  9:06                   ` Johan Hovold
2014-06-12 20:34                     ` [PATCH v5] " Janne Kanniainen
2014-06-13  7:54                       ` Johan Hovold
2014-06-13 17:19                         ` Janne Kanniainen
2014-06-15 14:59                           ` Janne Kanniainen
2014-06-16  7:39                             ` Johan Hovold
2014-06-16 17:23                         ` [PATCH v6] " Janne Kanniainen
2014-06-16 22:01                           ` Janne Kanniainen
2014-06-17 13:46                             ` Johan Hovold
2014-06-17 16:41                               ` [PATCH v8] " Janne Kanniainen
     [not found]                                 ` <1403023304-7953-1-git-send-email-janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-06-18  7:39                                   ` Johan Hovold
2014-06-18  7:39                                     ` Johan Hovold
2014-06-18 16:05                                     ` [PATCH v9] " Janne Kanniainen
     [not found]                                       ` <1403107502-14106-1-git-send-email-janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-06-18 16:11                                         ` Johan Hovold [this message]
2014-06-18 16:11                                           ` Johan Hovold
2014-06-18 18:41                                           ` Janne Kanniainen
2014-06-18 18:46                                             ` Johan Hovold
2014-06-18 22:10                                           ` Jiri Kosina
2014-06-23 14:35                                       ` Oliver Neukum
2014-06-23 14:42                                         ` Johan Hovold
2014-06-23 16:17                                           ` Greg KH
2014-06-23 17:16                                             ` [PATCH v10] " Janne Kanniainen
2014-06-23 17:27                                               ` Johan Hovold
     [not found]                                               ` <1403543808-8228-1-git-send-email-janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-06-23 18:23                                                 ` Greg KH
2014-06-23 18:23                                                   ` Greg KH
2014-06-23 18:24                                                   ` Greg KH
2014-06-23 19:31                                                     ` Johan Hovold
2014-06-23 19:40                                                       ` Greg KH
2014-06-23 19:52                                                         ` Johan Hovold
2014-06-23 20:24                                                           ` Greg KH
2014-06-23 20:44                                                             ` Johan Hovold
2014-06-24 13:10                                                               ` Bjørn Mork
2014-06-24 13:10                                                                 ` Bjørn Mork
2014-06-24 14:50                                                                 ` Johan Hovold
2014-06-24 19:38                                                                   ` [PATCH 1/2] HID: leds: fix race condition in MSI GT683R driver Janne Kanniainen
2014-06-24 19:38                                                                     ` [PATCH 2/2] HID: leds: move led_mode attribute to led-class devices " Janne Kanniainen
2014-06-24 19:56                                                                       ` Greg KH
2014-06-25 11:55                                                                         ` Johan Hovold
2014-06-25 15:59                                                                           ` [PATCH 2/2 v2] HID: leds: Use attribute-groups " Janne Kanniainen
2014-06-25 17:41                                                                             ` Johan Hovold
2014-06-25 18:13                                                                               ` [PATCH 2/2 v3] HID: leds: move led_mode attribute to led-class devices " Janne Kanniainen
2014-06-30 10:39                                                                                 ` Johan Hovold
2014-07-01 17:50                                                                                   ` [PATCH 2/2 v4] " Janne Kanniainen
2014-07-01 20:16                                                                                     ` Johan Hovold
2014-07-02 17:37                                                                                       ` [PATCH 2/2 v5] " Janne Kanniainen
2014-07-03  8:28                                                                                         ` Johan Hovold
2014-07-03 17:17                                                                                           ` [PATCH 1/2 v6] HID: gt683r: fix race condition Janne Kanniainen
2014-07-03 17:17                                                                                             ` [PATCH 2/2 v6] HID: gt683r: move mode attribute to led-class devices Janne Kanniainen
2014-07-03 17:40                                                                                               ` Johan Hovold
2014-07-03 17:40                                                                                                 ` Johan Hovold
2014-07-03 18:17                                                                                                 ` Bryan Wu
2014-07-03 18:28                                                                                                   ` Janne Kanniainen
2014-07-03 17:34                                                                                             ` [PATCH 1/2 v6] HID: gt683r: fix race condition Johan Hovold
2014-07-03 17:34                                                                                               ` Johan Hovold
2014-07-03 18:13                                                                                               ` Bryan Wu
2014-06-25 19:09                                                                               ` [PATCH 2/2 v2] HID: leds: Use attribute-groups in MSI GT683R driver Jiri Kosina
2014-06-25 22:55                                                                                 ` Bryan Wu
2014-06-30 10:47                                                                                   ` Johan Hovold
2014-06-30 11:33                                                                                     ` Jiri Kosina
2014-06-30 23:17                                                                                       ` Bryan Wu
2014-07-01  8:48                                                                                         ` Johan Hovold
2014-07-01 15:48                                                                                           ` Bryan Wu
2014-07-01 17:53                                                                                             ` Janne Kanniainen
2014-07-02  8:56                                                                                             ` Jiri Kosina
2014-06-23 16:20                                           ` [PATCH v9] leds: USB: HID: Add support for MSI GT683R led panels Janne Kanniainen
2014-06-14 22:42                       ` [PATCH v5] " Pavel Machek
2014-06-14 23:23                         ` Janne Kanniainen
2014-06-16  7:45                           ` Johan Hovold

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=20140618161150.GH31163@localhost \
    --to=johan-dgejt+ai2ygdnm+yrofe0a@public.gmane.org \
    --cc=cooloney-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=janne.kanniainen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=jkosina-AlSwsSmVLrQ@public.gmane.org \
    --cc=linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-leds-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /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.