From: Przemo Firszt <przemo@xxxxxxxxx> Add sysfs attribute to control LED selector on Wacom Intuos4. There are 4 different LEDs on the tablet and they can be turned on by something like: echo 50 > /sys/class/leds/(device # here)\:selector\:1/brightness Only one can be lit at a time. The brightness range is 0 to 127. This patch also contains short ABI description. Signed-off-by: Przemo Firszt <przemo@xxxxxxxxx> Signed-off-by: Jiri Kosina <jkosina@xxxxxxx> (cherry picked from commit d13f5454e4acbbe2a470cc6743c2998cfcd607a8) Conflicts: drivers/hid/hid-wacom.c (cherry picked from commit 56cfa5441a9ba011a39d37c0a269da8574e22a5a) --- Documentation/ABI/testing/sysfs-driver-wacom | 8 ++ drivers/hid/Kconfig | 1 + drivers/hid/hid-wacom.c | 126 ++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom index 0130d66..56c5455 100644 --- a/Documentation/ABI/testing/sysfs-driver-wacom +++ b/Documentation/ABI/testing/sysfs-driver-wacom @@ -9,6 +9,14 @@ Description: or 0 otherwise. Writing to this file one of these values switches reporting speed. +What: /sys/class/leds/0005\:056A\:00BD.0001\:selector\:*/ +Date: May 2012 +Kernel Version: 3.5 +Contact: linux-bluetooth@xxxxxxxxxxxxxxx +Description: + LED selector for Intuos4 WL. There are 4 leds, but only one LED + can be lit at a time. Max brightness is 127. + What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led Date: August 2011 Contact: linux-input@xxxxxxxxxxxxxxx diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index a421abd..a7e9fbf 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -627,6 +627,7 @@ config HID_WACOM_POWER_SUPPLY bool "Wacom Bluetooth devices power supply status support" depends on HID_WACOM select POWER_SUPPLY + select LEDS_CLASS ---help--- Say Y here if you want to enable power supply status monitoring for Wacom Bluetooth devices. diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 9614f93..9f2f5c7 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -24,6 +24,7 @@ #include <linux/device.h> #include <linux/hid.h> #include <linux/module.h> +#include <linux/leds.h> #include <linux/slab.h> #ifdef CONFIG_HID_WACOM_POWER_SUPPLY #include <linux/power_supply.h> @@ -33,6 +34,8 @@ #define PAD_DEVICE_ID 0x0F +#define WAC_CMD_LED_CONTROL 0x20 + struct wacom_data { __u16 tool; __u16 butstate; @@ -46,6 +49,8 @@ struct wacom_data { struct power_supply battery; struct power_supply ac; #endif + __u8 led_selector; + struct led_classdev *leds[4]; }; #ifdef CONFIG_HID_WACOM_POWER_SUPPLY @@ -64,6 +69,117 @@ static enum power_supply_property wacom_ac_props[] = { POWER_SUPPLY_PROP_SCOPE, }; +static void wacom_leds_set_brightness(struct led_classdev *led_dev, + enum led_brightness value) +{ + struct device *dev = led_dev->dev->parent; + struct hid_device *hdev; + struct wacom_data *wdata; + unsigned char *buf; + __u8 led = 0; + int i; + + hdev = container_of(dev, struct hid_device, dev); + wdata = hid_get_drvdata(hdev); + for (i = 0; i < 4; ++i) { + if (wdata->leds[i] == led_dev) + wdata->led_selector = i; + } + + led = wdata->led_selector | 0x04; + buf = kzalloc(9, GFP_KERNEL); + if (buf) { + buf[0] = WAC_CMD_LED_CONTROL; + buf[1] = led; + buf[2] = value; + hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT); + kfree(buf); + } + + return; +} + +static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev) +{ + struct wacom_data *wdata; + struct device *dev = led_dev->dev->parent; + int value = 0; + int i; + + wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); + + for (i = 0; i < 4; ++i) { + if (wdata->leds[i] == led_dev) { + value = wdata->leds[i]->brightness; + break; + } + } + + return value; +} + + +static int wacom_initialize_leds(struct hid_device *hdev) +{ + struct wacom_data *wdata = hid_get_drvdata(hdev); + struct led_classdev *led; + struct device *dev = &hdev->dev; + size_t namesz = strlen(dev_name(dev)) + 12; + char *name; + int i, ret; + + wdata->led_selector = 0; + + for (i = 0; i < 4; i++) { + led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); + if (!led) { + hid_warn(hdev, + "can't allocate memory for LED selector\n"); + ret = -ENOMEM; + goto err; + } + + name = (void *)&led[1]; + snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i); + led->name = name; + led->brightness = 0; + led->max_brightness = 127; + led->brightness_get = wacom_leds_get_brightness; + led->brightness_set = wacom_leds_set_brightness; + + wdata->leds[i] = led; + + ret = led_classdev_register(dev, wdata->leds[i]); + + if (ret) { + wdata->leds[i] = NULL; + kfree(led); + hid_warn(hdev, "can't register LED\n"); + goto err; + } + } + +err: + return ret; +} + +static void wacom_destroy_leds(struct hid_device *hdev) +{ + struct wacom_data *wdata = hid_get_drvdata(hdev); + struct led_classdev *led; + int i; + + for (i = 0; i < 4; ++i) { + if (wdata->leds[i]) { + led = wdata->leds[i]; + wdata->leds[i] = NULL; + led_classdev_unregister(led); + kfree(led); + } + } + +} + static int wacom_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -599,6 +715,12 @@ static int wacom_probe(struct hid_device *hdev, case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: wdata->features = 0; wacom_set_features(hdev); + ret = wacom_initialize_leds(hdev); + if (ret) { + hid_warn(hdev, + "can't create led attribute, err: %d\n", ret); + goto destroy_leds; + } break; } @@ -645,6 +767,8 @@ err_battery: device_remove_file(&hdev->dev, &dev_attr_speed); hid_hw_stop(hdev); #endif +destroy_leds: + wacom_destroy_leds(hdev); err_free: kfree(wdata); return ret; @@ -655,6 +779,8 @@ static void wacom_remove(struct hid_device *hdev) #ifdef CONFIG_HID_WACOM_POWER_SUPPLY struct wacom_data *wdata = hid_get_drvdata(hdev); #endif + + wacom_destroy_leds(hdev); device_remove_file(&hdev->dev, &dev_attr_speed); hid_hw_stop(hdev); -- 1.7.10.1 _______________________________________________ kernel mailing list kernel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/kernel