Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: HID: Steelseries SRW-S1 Add support controlling all LEDs simultaneously

This patch to the SRW-S1 driver adds the ability to control all
LEDs simultaneously as testing showed that it was slow (noticably!!)
when seting or clearing all the LEDs in turn.

It adds a 'RPMALL' LED, whose behavoir is asserted to all the LEDs in
the bar graph, individual LEDs can subsequently be turned on/off
individually.

Signed-off-by: Simon Wood <simon@mungewell.org>
Tested-by: John Murphy <rosegardener@freeode.co.uk>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Simon Wood and committed by
Jiri Kosina
e25d7805 2e2daff3

+62 -4
+1
Documentation/ABI/testing/sysfs-driver-hid-srws1
··· 13 13 What: /sys/class/leds/SRWS1::<serial>::RPM13 14 14 What: /sys/class/leds/SRWS1::<serial>::RPM14 15 15 What: /sys/class/leds/SRWS1::<serial>::RPM15 16 + What: /sys/class/leds/SRWS1::<serial>::RPMALL 16 17 Date: Jan 2013 17 18 KernelVersion: 3.9 18 19 Contact: Simon Wood <simon@mungewell.org>
+61 -4
drivers/hid/hid-steelseries-srws1.c
··· 136 136 /* Note: LED change does not show on device until the device is read/polled */ 137 137 } 138 138 139 + static void steelseries_srws1_led_all_set_brightness(struct led_classdev *led_cdev, 140 + enum led_brightness value) 141 + { 142 + struct device *dev = led_cdev->dev->parent; 143 + struct hid_device *hid = container_of(dev, struct hid_device, dev); 144 + struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid); 145 + 146 + if (!drv_data) { 147 + hid_err(hid, "Device data not found."); 148 + return; 149 + } 150 + 151 + if (value == LED_OFF) 152 + drv_data->led_state = 0; 153 + else 154 + drv_data->led_state = (1 << (SRWS1_NUMBER_LEDS + 1)) - 1; 155 + 156 + steelseries_srws1_set_leds(hid, drv_data->led_state); 157 + } 158 + 159 + static enum led_brightness steelseries_srws1_led_all_get_brightness(struct led_classdev *led_cdev) 160 + { 161 + struct device *dev = led_cdev->dev->parent; 162 + struct hid_device *hid = container_of(dev, struct hid_device, dev); 163 + struct steelseries_srws1_data *drv_data; 164 + 165 + drv_data = hid_get_drvdata(hid); 166 + 167 + if (!drv_data) { 168 + hid_err(hid, "Device data not found."); 169 + return LED_OFF; 170 + } 171 + 172 + return (drv_data->led_state >> SRWS1_NUMBER_LEDS) ? LED_FULL : LED_OFF; 173 + } 174 + 139 175 static void steelseries_srws1_led_set_brightness(struct led_classdev *led_cdev, 140 176 enum led_brightness value) 141 177 { ··· 255 219 256 220 /* register led subsystem */ 257 221 drv_data->led_state = 0; 258 - for (i = 0; i < SRWS1_NUMBER_LEDS; i++) 222 + for (i = 0; i < SRWS1_NUMBER_LEDS + 1; i++) 259 223 drv_data->led[i] = NULL; 260 224 261 225 steelseries_srws1_set_leds(hdev, 0); 262 226 263 - name_sz = strlen(hdev->uniq) + 15; 227 + name_sz = strlen(hdev->uniq) + 16; 264 228 229 + /* 'ALL', for setting all LEDs simultaneously */ 230 + led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); 231 + if (!led) { 232 + hid_err(hdev, "can't allocate memory for LED ALL\n"); 233 + goto err_led; 234 + } 235 + 236 + name = (void *)(&led[1]); 237 + snprintf(name, name_sz, "SRWS1::%s::RPMALL", hdev->uniq); 238 + led->name = name; 239 + led->brightness = 0; 240 + led->max_brightness = 1; 241 + led->brightness_get = steelseries_srws1_led_all_get_brightness; 242 + led->brightness_set = steelseries_srws1_led_all_set_brightness; 243 + 244 + drv_data->led[SRWS1_NUMBER_LEDS] = led; 245 + ret = led_classdev_register(&hdev->dev, led); 246 + if (ret) 247 + goto err_led; 248 + 249 + /* Each individual LED */ 265 250 for (i = 0; i < SRWS1_NUMBER_LEDS; i++) { 266 251 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); 267 252 if (!led) { ··· 305 248 hid_err(hdev, "failed to register LED %d. Aborting.\n", i); 306 249 err_led: 307 250 /* Deregister all LEDs (if any) */ 308 - for (i = 0; i < SRWS1_NUMBER_LEDS; i++) { 251 + for (i = 0; i < SRWS1_NUMBER_LEDS + 1; i++) { 309 252 led = drv_data->led[i]; 310 253 drv_data->led[i] = NULL; 311 254 if (!led) ··· 332 275 333 276 if (drv_data) { 334 277 /* Deregister LEDs (if any) */ 335 - for (i = 0; i < SRWS1_NUMBER_LEDS; i++) { 278 + for (i = 0; i < SRWS1_NUMBER_LEDS + 1; i++) { 336 279 led = drv_data->led[i]; 337 280 drv_data->led[i] = NULL; 338 281 if (!led)