aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2016-07-13 12:06:12 -0400
committerJiri Kosina <jkosina@suse.cz>2016-08-05 07:39:20 -0400
commit34736aa96e313d304ffe0746519833167e66c978 (patch)
treecf36446f9a6b047668a5d67e3952026b9edea9de
parent589e5060206b97a9602534d19d53264d35cd969f (diff)
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>
-rw-r--r--drivers/hid/Kconfig1
-rw-r--r--drivers/hid/wacom.h4
-rw-r--r--drivers/hid/wacom_sys.c63
-rw-r--r--drivers/hid/wacom_wac.c53
4 files changed, 118 insertions, 3 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 78ac4811bd3c..bdacb552f0a3 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -862,6 +862,7 @@ config HID_WACOM
862 select POWER_SUPPLY 862 select POWER_SUPPLY
863 select NEW_LEDS 863 select NEW_LEDS
864 select LEDS_CLASS 864 select LEDS_CLASS
865 select LEDS_TRIGGERS
865 help 866 help
866 Say Y here if you want to use the USB or BT version of the Wacom Intuos 867 Say Y here if you want to use the USB or BT version of the Wacom Intuos
867 or Graphire tablet. 868 or Graphire tablet.
diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h
index 9159dd3e4b90..8f8a16243f07 100644
--- a/drivers/hid/wacom.h
+++ b/drivers/hid/wacom.h
@@ -216,4 +216,8 @@ int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
216 struct hid_usage *usage, __s32 value); 216 struct hid_usage *usage, __s32 value);
217void wacom_wac_report(struct hid_device *hdev, struct hid_report *report); 217void wacom_wac_report(struct hid_device *hdev, struct hid_report *report);
218void wacom_battery_work(struct work_struct *work); 218void wacom_battery_work(struct work_struct *work);
219enum led_brightness wacom_leds_brightness_get(struct wacom_led *led);
220struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group,
221 unsigned int id);
222struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur);
219#endif 223#endif
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,
969 group); 969 group);
970} 970}
971 971
972static enum led_brightness wacom_leds_brightness_get(struct wacom_led *led) 972enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
973{ 973{
974 struct wacom *wacom = led->wacom; 974 struct wacom *wacom = led->wacom;
975 975
@@ -1042,6 +1042,17 @@ static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
1042 if (!name) 1042 if (!name)
1043 return -ENOMEM; 1043 return -ENOMEM;
1044 1044
1045 if (!read_only) {
1046 led->trigger.name = name;
1047 error = devm_led_trigger_register(dev, &led->trigger);
1048 if (error) {
1049 hid_err(wacom->hdev,
1050 "failed to register LED trigger %s: %d\n",
1051 led->cdev.name, error);
1052 return error;
1053 }
1054 }
1055
1045 led->group = group; 1056 led->group = group;
1046 led->id = id; 1057 led->id = id;
1047 led->wacom = wacom; 1058 led->wacom = wacom;
@@ -1051,10 +1062,12 @@ static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
1051 led->cdev.max_brightness = LED_FULL; 1062 led->cdev.max_brightness = LED_FULL;
1052 led->cdev.flags = LED_HW_PLUGGABLE; 1063 led->cdev.flags = LED_HW_PLUGGABLE;
1053 led->cdev.brightness_get = __wacom_led_brightness_get; 1064 led->cdev.brightness_get = __wacom_led_brightness_get;
1054 if (!read_only) 1065 if (!read_only) {
1055 led->cdev.brightness_set_blocking = wacom_led_brightness_set; 1066 led->cdev.brightness_set_blocking = wacom_led_brightness_set;
1056 else 1067 led->cdev.default_trigger = led->cdev.name;
1068 } else {
1057 led->cdev.brightness_set = wacom_led_readonly_brightness_set; 1069 led->cdev.brightness_set = wacom_led_readonly_brightness_set;
1070 }
1058 1071
1059 error = devm_led_classdev_register(dev, &led->cdev); 1072 error = devm_led_classdev_register(dev, &led->cdev);
1060 if (error) { 1073 if (error) {
@@ -1131,6 +1144,50 @@ err:
1131 return error; 1144 return error;
1132} 1145}
1133 1146
1147struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group_id,
1148 unsigned int id)
1149{
1150 struct wacom_group_leds *group;
1151
1152 if (group_id >= wacom->led.count)
1153 return NULL;
1154
1155 group = &wacom->led.groups[group_id];
1156
1157 if (!group->leds)
1158 return NULL;
1159
1160 id %= group->count;
1161
1162 return &group->leds[id];
1163}
1164
1165/**
1166 * wacom_led_next: gives the next available led with a wacom trigger.
1167 *
1168 * returns the next available struct wacom_led which has its default trigger
1169 * or the current one if none is available.
1170 */
1171struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur)
1172{
1173 struct wacom_led *next_led;
1174 int group, next;
1175
1176 if (!wacom || !cur)
1177 return NULL;
1178
1179 group = cur->group;
1180 next = cur->id;
1181
1182 do {
1183 next_led = wacom_led_find(wacom, group, ++next);
1184 if (!next_led || next_led == cur)
1185 return next_led;
1186 } while (next_led->cdev.trigger != &next_led->trigger);
1187
1188 return next_led;
1189}
1190
1134static void wacom_led_groups_release(void *data) 1191static void wacom_led_groups_release(void *data)
1135{ 1192{
1136 struct wacom *wacom = data; 1193 struct wacom *wacom = data;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 1c882bb70f14..00e0c80be6d5 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2763,11 +2763,64 @@ static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
2763 __set_bit(BTN_BASE + (i-16), input_dev->keybit); 2763 __set_bit(BTN_BASE + (i-16), input_dev->keybit);
2764} 2764}
2765 2765
2766static bool wacom_is_led_toggled(struct wacom *wacom, int button_count,
2767 int mask, int group)
2768{
2769 int button_per_group;
2770
2771 button_per_group = button_count/wacom->led.count;
2772
2773 return mask & (1 << (group * button_per_group));
2774}
2775
2776static void wacom_update_led(struct wacom *wacom, int button_count, int mask,
2777 int group)
2778{
2779 struct wacom_led *led, *next_led;
2780 int cur;
2781 bool pressed;
2782
2783 pressed = wacom_is_led_toggled(wacom, button_count, mask, group);
2784 cur = wacom->led.groups[group].select;
2785
2786 led = wacom_led_find(wacom, group, cur);
2787 if (!led) {
2788 hid_err(wacom->hdev, "can't find current LED %d in group %d\n",
2789 cur, group);
2790 return;
2791 }
2792
2793 if (!pressed) {
2794 led->held = false;
2795 return;
2796 }
2797
2798 if (led->held && pressed)
2799 return;
2800
2801 next_led = wacom_led_next(wacom, led);
2802 if (!next_led) {
2803 hid_err(wacom->hdev, "can't find next LED in group %d\n",
2804 group);
2805 return;
2806 }
2807 if (next_led == led)
2808 return;
2809
2810 next_led->held = true;
2811 led_trigger_event(&next_led->trigger,
2812 wacom_leds_brightness_get(next_led));
2813}
2814
2766static void wacom_report_numbered_buttons(struct input_dev *input_dev, 2815static void wacom_report_numbered_buttons(struct input_dev *input_dev,
2767 int button_count, int mask) 2816 int button_count, int mask)
2768{ 2817{
2818 struct wacom *wacom = input_get_drvdata(input_dev);
2769 int i; 2819 int i;
2770 2820
2821 for (i = 0; i < wacom->led.count; i++)
2822 wacom_update_led(wacom, button_count, mask, i);
2823
2771 for (i = 0; i < button_count && i < 10; i++) 2824 for (i = 0; i < button_count && i < 10; i++)
2772 input_report_key(input_dev, BTN_0 + i, mask & (1 << i)); 2825 input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
2773 for (i = 10; i < button_count && i < 16; i++) 2826 for (i = 10; i < button_count && i < 16; i++)