aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2016-07-13 12:06:10 -0400
committerJiri Kosina <jkosina@suse.cz>2016-08-05 07:39:19 -0400
commit97f5541fc0c7ed107103e6f87a6522f5327ab4b0 (patch)
treefa1e72787ac36f7fb130a20d12cad0227bb21717
parent9f1015d45f62d3b1c6719a1ccffaded89b157e10 (diff)
HID: wacom: leds: use the ledclass instead of custom made sysfs files
The now obsolete sysfs files for LEDs and EKRemote are kept for backward compatibility. Both the EKR (read-only) and the regular Cintiqs and Intuos are now sharing the same led API. 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--Documentation/ABI/testing/sysfs-driver-wacom5
-rw-r--r--drivers/hid/wacom.h19
-rw-r--r--drivers/hid/wacom_sys.c195
3 files changed, 209 insertions, 10 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom
index dca429340772..2aa5503ee200 100644
--- a/Documentation/ABI/testing/sysfs-driver-wacom
+++ b/Documentation/ABI/testing/sysfs-driver-wacom
@@ -24,6 +24,7 @@ What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status0_luminance
24Date: August 2014 24Date: August 2014
25Contact: linux-input@vger.kernel.org 25Contact: linux-input@vger.kernel.org
26Description: 26Description:
27 <obsoleted by the LED class API now exported by the driver>
27 Writing to this file sets the status LED luminance (1..127) 28 Writing to this file sets the status LED luminance (1..127)
28 when the stylus does not touch the tablet surface, and no 29 when the stylus does not touch the tablet surface, and no
29 button is pressed on the stylus. This luminance level is 30 button is pressed on the stylus. This luminance level is
@@ -33,6 +34,7 @@ What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status1_luminance
33Date: August 2014 34Date: August 2014
34Contact: linux-input@vger.kernel.org 35Contact: linux-input@vger.kernel.org
35Description: 36Description:
37 <obsoleted by the LED class API now exported by the driver>
36 Writing to this file sets the status LED luminance (1..127) 38 Writing to this file sets the status LED luminance (1..127)
37 when the stylus touches the tablet surface, or any button is 39 when the stylus touches the tablet surface, or any button is
38 pressed on the stylus. 40 pressed on the stylus.
@@ -41,6 +43,7 @@ What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led0_select
41Date: August 2014 43Date: August 2014
42Contact: linux-input@vger.kernel.org 44Contact: linux-input@vger.kernel.org
43Description: 45Description:
46 <obsoleted by the LED class API now exported by the driver>
44 Writing to this file sets which one of the four (for Intuos 4 47 Writing to this file sets which one of the four (for Intuos 4
45 and Intuos 5) or of the right four (for Cintiq 21UX2 and Cintiq 48 and Intuos 5) or of the right four (for Cintiq 21UX2 and Cintiq
46 24HD) status LEDs is active (0..3). The other three LEDs on the 49 24HD) status LEDs is active (0..3). The other three LEDs on the
@@ -50,6 +53,7 @@ What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led1_select
50Date: August 2014 53Date: August 2014
51Contact: linux-input@vger.kernel.org 54Contact: linux-input@vger.kernel.org
52Description: 55Description:
56 <obsoleted by the LED class API now exported by the driver>
53 Writing to this file sets which one of the left four (for Cintiq 21UX2 57 Writing to this file sets which one of the left four (for Cintiq 21UX2
54 and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on 58 and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on
55 the left are always inactive. 59 the left are always inactive.
@@ -91,6 +95,7 @@ What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_remote/<serial_number>/r
91Date: July 2015 95Date: July 2015
92Contact: linux-input@vger.kernel.org 96Contact: linux-input@vger.kernel.org
93Description: 97Description:
98 <obsoleted by the LED class API now exported by the driver>
94 Reading from this file reports the mode status of the 99 Reading from this file reports the mode status of the
95 remote as indicated by the LED lights on the device. If no 100 remote as indicated by the LED lights on the device. If no
96 reports have been received from the paired device, reading 101 reports have been received from the paired device, reading
diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h
index 768d69602e7a..0c498c46de5f 100644
--- a/drivers/hid/wacom.h
+++ b/drivers/hid/wacom.h
@@ -91,6 +91,7 @@
91#include <linux/mod_devicetable.h> 91#include <linux/mod_devicetable.h>
92#include <linux/hid.h> 92#include <linux/hid.h>
93#include <linux/kfifo.h> 93#include <linux/kfifo.h>
94#include <linux/leds.h>
94#include <linux/usb/input.h> 95#include <linux/usb/input.h>
95#include <linux/power_supply.h> 96#include <linux/power_supply.h>
96#include <asm/unaligned.h> 97#include <asm/unaligned.h>
@@ -112,8 +113,23 @@ enum wacom_worker {
112 WACOM_WORKER_REMOTE, 113 WACOM_WORKER_REMOTE,
113}; 114};
114 115
116struct wacom;
117
118struct wacom_led {
119 struct led_classdev cdev;
120 struct led_trigger trigger;
121 struct wacom *wacom;
122 unsigned int group;
123 unsigned int id;
124 u8 llv;
125 u8 hlv;
126 bool held;
127};
128
115struct wacom_group_leds { 129struct wacom_group_leds {
116 u8 select; /* status led selector (0..3) */ 130 u8 select; /* status led selector (0..3) */
131 struct wacom_led *leds;
132 unsigned int count;
117}; 133};
118 134
119struct wacom_battery { 135struct wacom_battery {
@@ -154,9 +170,12 @@ struct wacom {
154 struct wacom_remote *remote; 170 struct wacom_remote *remote;
155 struct wacom_leds { 171 struct wacom_leds {
156 struct wacom_group_leds *groups; 172 struct wacom_group_leds *groups;
173 unsigned int count;
157 u8 llv; /* status led brightness no button (1..127) */ 174 u8 llv; /* status led brightness no button (1..127) */
158 u8 hlv; /* status led brightness button pressed (1..127) */ 175 u8 hlv; /* status led brightness button pressed (1..127) */
159 u8 img_lum; /* OLED matrix display brightness */ 176 u8 img_lum; /* OLED matrix display brightness */
177 u8 max_llv; /* maximum brightness of LED (llv) */
178 u8 max_hlv; /* maximum brightness of LED (hlv) */
160 } led; 179 } led;
161 struct wacom_battery battery; 180 struct wacom_battery battery;
162 bool resources; 181 bool resources;
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 1d79215a7968..c5d518da0d0f 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -647,6 +647,9 @@ static int wacom_led_control(struct wacom *wacom)
647 unsigned char report_id = WAC_CMD_LED_CONTROL; 647 unsigned char report_id = WAC_CMD_LED_CONTROL;
648 int buf_size = 9; 648 int buf_size = 9;
649 649
650 if (!hid_get_drvdata(wacom->hdev))
651 return -ENODEV;
652
650 if (!wacom->led.groups) 653 if (!wacom->led.groups)
651 return -ENOTSUPP; 654 return -ENOTSUPP;
652 655
@@ -966,31 +969,194 @@ static int wacom_devm_sysfs_create_group(struct wacom *wacom,
966 group); 969 group);
967} 970}
968 971
972static enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
973{
974 struct wacom *wacom = led->wacom;
975
976 if (wacom->led.max_hlv)
977 return led->hlv * LED_FULL / wacom->led.max_hlv;
978
979 if (wacom->led.max_llv)
980 return led->llv * LED_FULL / wacom->led.max_llv;
981
982 /* device doesn't support brightness tuning */
983 return LED_FULL;
984}
985
986static enum led_brightness __wacom_led_brightness_get(struct led_classdev *cdev)
987{
988 struct wacom_led *led = container_of(cdev, struct wacom_led, cdev);
989 struct wacom *wacom = led->wacom;
990
991 if (wacom->led.groups[led->group].select != led->id)
992 return LED_OFF;
993
994 return wacom_leds_brightness_get(led);
995}
996
997static int wacom_led_brightness_set(struct led_classdev *cdev,
998 enum led_brightness brightness)
999{
1000 struct wacom_led *led = container_of(cdev, struct wacom_led, cdev);
1001 struct wacom *wacom = led->wacom;
1002 int error;
1003
1004 mutex_lock(&wacom->lock);
1005
1006 if (!wacom->led.groups || (brightness == LED_OFF &&
1007 wacom->led.groups[led->group].select != led->id)) {
1008 error = 0;
1009 goto out;
1010 }
1011
1012 led->llv = wacom->led.llv = wacom->led.max_llv * brightness / LED_FULL;
1013 led->hlv = wacom->led.hlv = wacom->led.max_hlv * brightness / LED_FULL;
1014
1015 wacom->led.groups[led->group].select = led->id;
1016
1017 error = wacom_led_control(wacom);
1018
1019out:
1020 mutex_unlock(&wacom->lock);
1021
1022 return error;
1023}
1024
1025static void wacom_led_readonly_brightness_set(struct led_classdev *cdev,
1026 enum led_brightness brightness)
1027{
1028}
1029
1030static int wacom_led_register_one(struct device *dev, struct wacom *wacom,
1031 struct wacom_led *led, unsigned int group,
1032 unsigned int id, bool read_only)
1033{
1034 int error;
1035 char *name;
1036
1037 name = devm_kasprintf(dev, GFP_KERNEL,
1038 "%s::wacom-%d.%d",
1039 dev_name(dev),
1040 group,
1041 id);
1042 if (!name)
1043 return -ENOMEM;
1044
1045 led->group = group;
1046 led->id = id;
1047 led->wacom = wacom;
1048 led->llv = wacom->led.llv;
1049 led->hlv = wacom->led.hlv;
1050 led->cdev.name = name;
1051 led->cdev.max_brightness = LED_FULL;
1052 led->cdev.flags = LED_HW_PLUGGABLE;
1053 led->cdev.brightness_get = __wacom_led_brightness_get;
1054 if (!read_only)
1055 led->cdev.brightness_set_blocking = wacom_led_brightness_set;
1056 else
1057 led->cdev.brightness_set = wacom_led_readonly_brightness_set;
1058
1059 error = devm_led_classdev_register(dev, &led->cdev);
1060 if (error) {
1061 hid_err(wacom->hdev,
1062 "failed to register LED %s: %d\n",
1063 led->cdev.name, error);
1064 led->cdev.name = NULL;
1065 return error;
1066 }
1067
1068 return 0;
1069}
1070
1071static int wacom_led_groups_alloc_and_register_one(struct device *dev,
1072 struct wacom *wacom,
1073 int group_id, int count,
1074 bool read_only)
1075{
1076 struct wacom_led *leds;
1077 int i, error;
1078
1079 if (group_id >= wacom->led.count || count <= 0)
1080 return -EINVAL;
1081
1082 if (!devres_open_group(dev, &wacom->led.groups[group_id], GFP_KERNEL))
1083 return -ENOMEM;
1084
1085 leds = devm_kzalloc(dev, sizeof(struct wacom_led) * count, GFP_KERNEL);
1086 if (!leds) {
1087 error = -ENOMEM;
1088 goto err;
1089 }
1090
1091 wacom->led.groups[group_id].leds = leds;
1092 wacom->led.groups[group_id].count = count;
1093
1094 for (i = 0; i < count; i++) {
1095 error = wacom_led_register_one(dev, wacom, &leds[i],
1096 group_id, i, read_only);
1097 if (error)
1098 goto err;
1099 }
1100
1101 devres_remove_group(dev, &wacom->led.groups[group_id]);
1102 return 0;
1103
1104err:
1105 devres_release_group(dev, &wacom->led.groups[group_id]);
1106 return error;
1107}
1108
969static void wacom_led_groups_release(void *data) 1109static void wacom_led_groups_release(void *data)
970{ 1110{
971 struct wacom *wacom = data; 1111 struct wacom *wacom = data;
972 1112
973 wacom->led.groups = NULL; 1113 wacom->led.groups = NULL;
1114 wacom->led.count = 0;
974} 1115}
975 1116
976static int wacom_led_groups_allocate(struct wacom *wacom, int count) 1117static int wacom_led_groups_allocate(struct wacom *wacom, int count)
977{ 1118{
1119 struct device *dev = &wacom->hdev->dev;
978 struct wacom_group_leds *groups; 1120 struct wacom_group_leds *groups;
979 int error; 1121 int error;
980 1122
981 groups = devm_kzalloc(&wacom->hdev->dev, 1123 groups = devm_kzalloc(dev, sizeof(struct wacom_group_leds) * count,
982 sizeof(struct wacom_group_leds) * count,
983 GFP_KERNEL); 1124 GFP_KERNEL);
984 if (!groups) 1125 if (!groups)
985 return -ENOMEM; 1126 return -ENOMEM;
986 1127
987 error = devm_add_action_or_reset(&wacom->hdev->dev, 1128 error = devm_add_action_or_reset(dev, wacom_led_groups_release, wacom);
988 wacom_led_groups_release,
989 wacom);
990 if (error) 1129 if (error)
991 return error; 1130 return error;
992 1131
993 wacom->led.groups = groups; 1132 wacom->led.groups = groups;
1133 wacom->led.count = count;
1134
1135 return 0;
1136}
1137
1138static int wacom_leds_alloc_and_register(struct wacom *wacom, int group_count,
1139 int led_per_group, bool read_only)
1140{
1141 struct device *dev;
1142 int i, error;
1143
1144 if (!wacom->wacom_wac.pad_input)
1145 return -EINVAL;
1146
1147 dev = &wacom->wacom_wac.pad_input->dev;
1148
1149 error = wacom_led_groups_allocate(wacom, group_count);
1150 if (error)
1151 return error;
1152
1153 for (i = 0; i < group_count; i++) {
1154 error = wacom_led_groups_alloc_and_register_one(dev, wacom, i,
1155 led_per_group,
1156 read_only);
1157 if (error)
1158 return error;
1159 }
994 1160
995 return 0; 1161 return 0;
996} 1162}
@@ -1010,9 +1176,11 @@ static int wacom_initialize_leds(struct wacom *wacom)
1010 case INTUOS4L: 1176 case INTUOS4L:
1011 wacom->led.llv = 10; 1177 wacom->led.llv = 10;
1012 wacom->led.hlv = 20; 1178 wacom->led.hlv = 20;
1179 wacom->led.max_llv = 127;
1180 wacom->led.max_hlv = 127;
1013 wacom->led.img_lum = 10; 1181 wacom->led.img_lum = 10;
1014 1182
1015 error = wacom_led_groups_allocate(wacom, 1); 1183 error = wacom_leds_alloc_and_register(wacom, 1, 4, false);
1016 if (error) { 1184 if (error) {
1017 hid_err(wacom->hdev, 1185 hid_err(wacom->hdev,
1018 "cannot create leds err: %d\n", error); 1186 "cannot create leds err: %d\n", error);
@@ -1029,7 +1197,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
1029 wacom->led.hlv = 0; 1197 wacom->led.hlv = 0;
1030 wacom->led.img_lum = 0; 1198 wacom->led.img_lum = 0;
1031 1199
1032 error = wacom_led_groups_allocate(wacom, 2); 1200 error = wacom_leds_alloc_and_register(wacom, 2, 4, false);
1033 if (error) { 1201 if (error) {
1034 hid_err(wacom->hdev, 1202 hid_err(wacom->hdev,
1035 "cannot create leds err: %d\n", error); 1203 "cannot create leds err: %d\n", error);
@@ -1047,10 +1215,9 @@ static int wacom_initialize_leds(struct wacom *wacom)
1047 case INTUOSPM: 1215 case INTUOSPM:
1048 case INTUOSPL: 1216 case INTUOSPL:
1049 wacom->led.llv = 32; 1217 wacom->led.llv = 32;
1050 wacom->led.hlv = 0; 1218 wacom->led.max_llv = 96;
1051 wacom->led.img_lum = 0;
1052 1219
1053 error = wacom_led_groups_allocate(wacom, 1); 1220 error = wacom_leds_alloc_and_register(wacom, 1, 4, false);
1054 if (error) { 1221 if (error) {
1055 hid_err(wacom->hdev, 1222 hid_err(wacom->hdev,
1056 "cannot create leds err: %d\n", error); 1223 "cannot create leds err: %d\n", error);
@@ -1062,6 +1229,8 @@ static int wacom_initialize_leds(struct wacom *wacom)
1062 break; 1229 break;
1063 1230
1064 case REMOTE: 1231 case REMOTE:
1232 wacom->led.llv = 255;
1233 wacom->led.max_llv = 255;
1065 error = wacom_led_groups_allocate(wacom, 5); 1234 error = wacom_led_groups_allocate(wacom, 5);
1066 if (error) { 1235 if (error) {
1067 hid_err(wacom->hdev, 1236 hid_err(wacom->hdev,
@@ -1987,6 +2156,12 @@ static int wacom_remote_create_one(struct wacom *wacom, u32 serial,
1987 if (error) 2156 if (error)
1988 goto fail; 2157 goto fail;
1989 2158
2159 error = wacom_led_groups_alloc_and_register_one(
2160 &remote->remotes[index].input->dev,
2161 wacom, index, 3, true);
2162 if (error)
2163 goto fail;
2164
1990 remote->remotes[index].registered = true; 2165 remote->remotes[index].registered = true;
1991 2166
1992 devres_close_group(dev, &remote->remotes[index]); 2167 devres_close_group(dev, &remote->remotes[index]);