summaryrefslogtreecommitdiffstats
path: root/drivers/hid/wacom_sys.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2016-07-13 18:06:12 +0200
committerJiri Kosina <jkosina@suse.cz>2016-08-05 13:39:20 +0200
commit34736aa96e313d304ffe0746519833167e66c978 (patch)
treecf36446f9a6b047668a5d67e3952026b9edea9de /drivers/hid/wacom_sys.c
parentHID: wacom: leds: actually release the LEDs on disconnect (diff)
downloadlinux-34736aa96e313d304ffe0746519833167e66c978.tar.xz
linux-34736aa96e313d304ffe0746519833167e66c978.zip
HID: wacom: leds: handle the switch of the LEDs directly in the kernel
The EKR switches the LED directly, and there is no point in having userspace handling the switch it self when it's easy enough to do in the kernel. The other benefit is that now userspace does not need to have root access to the LED but need only to read them with user privileges. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Acked-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/wacom_sys.c')
-rw-r--r--drivers/hid/wacom_sys.c63
1 files changed, 60 insertions, 3 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 3a651e288776..7e83352adbde 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -969,7 +969,7 @@ static int wacom_devm_sysfs_create_group(struct wacom *wacom,
group);
}
-static enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
+enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
{
struct wacom *wacom = led->wacom;
@@ -1042,6 +1042,17 @@ static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
if (!name)
return -ENOMEM;
+ if (!read_only) {
+ led->trigger.name = name;
+ error = devm_led_trigger_register(dev, &led->trigger);
+ if (error) {
+ hid_err(wacom->hdev,
+ "failed to register LED trigger %s: %d\n",
+ led->cdev.name, error);
+ return error;
+ }
+ }
+
led->group = group;
led->id = id;
led->wacom = wacom;
@@ -1051,10 +1062,12 @@ static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
led->cdev.max_brightness = LED_FULL;
led->cdev.flags = LED_HW_PLUGGABLE;
led->cdev.brightness_get = __wacom_led_brightness_get;
- if (!read_only)
+ if (!read_only) {
led->cdev.brightness_set_blocking = wacom_led_brightness_set;
- else
+ led->cdev.default_trigger = led->cdev.name;
+ } else {
led->cdev.brightness_set = wacom_led_readonly_brightness_set;
+ }
error = devm_led_classdev_register(dev, &led->cdev);
if (error) {
@@ -1131,6 +1144,50 @@ err:
return error;
}
+struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group_id,
+ unsigned int id)
+{
+ struct wacom_group_leds *group;
+
+ if (group_id >= wacom->led.count)
+ return NULL;
+
+ group = &wacom->led.groups[group_id];
+
+ if (!group->leds)
+ return NULL;
+
+ id %= group->count;
+
+ return &group->leds[id];
+}
+
+/**
+ * wacom_led_next: gives the next available led with a wacom trigger.
+ *
+ * returns the next available struct wacom_led which has its default trigger
+ * or the current one if none is available.
+ */
+struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur)
+{
+ struct wacom_led *next_led;
+ int group, next;
+
+ if (!wacom || !cur)
+ return NULL;
+
+ group = cur->group;
+ next = cur->id;
+
+ do {
+ next_led = wacom_led_find(wacom, group, ++next);
+ if (!next_led || next_led == cur)
+ return next_led;
+ } while (next_led->cdev.trigger != &next_led->trigger);
+
+ return next_led;
+}
+
static void wacom_led_groups_release(void *data)
{
struct wacom *wacom = data;