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

HID: wiimote: Add sysfs support to wiimote driver

Add sysfs files for each led of the wiimote. Writing 1 to the file
enables the led and 0 disables the led.

We do not need memory barriers when checking wdata->ready since we use
a spinlock directly after it.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

David Herrmann and committed by
Jiri Kosina
3c1c2fce 32a0d9a5

+84
+10
Documentation/ABI/testing/sysfs-driver-hid-wiimote
··· 1 + What: /sys/bus/hid/drivers/wiimote/<dev>/led1 2 + What: /sys/bus/hid/drivers/wiimote/<dev>/led2 3 + What: /sys/bus/hid/drivers/wiimote/<dev>/led3 4 + What: /sys/bus/hid/drivers/wiimote/<dev>/led4 5 + Date: July 2011 6 + KernelVersion: 3.1 7 + Contact: David Herrmann <dh.herrmann@googlemail.com> 8 + Description: Make it possible to set/get current led state. Reading from it 9 + returns 0 if led is off and 1 if it is on. Writing 0 to it 10 + disables the led, writing 1 enables it.
+74
drivers/hid/hid-wiimote.c
··· 87 87 BTN_MODE, /* WIIPROTO_KEY_HOME */ 88 88 }; 89 89 90 + #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ 91 + dev)) 92 + 90 93 static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, 91 94 size_t count) 92 95 { ··· 191 188 192 189 wiimote_queue(wdata, cmd, sizeof(cmd)); 193 190 } 191 + 192 + #define wiifs_led_show_set(num) \ 193 + static ssize_t wiifs_led_show_##num(struct device *dev, \ 194 + struct device_attribute *attr, char *buf) \ 195 + { \ 196 + struct wiimote_data *wdata = dev_to_wii(dev); \ 197 + unsigned long flags; \ 198 + int state; \ 199 + \ 200 + if (!atomic_read(&wdata->ready)) \ 201 + return -EBUSY; \ 202 + \ 203 + spin_lock_irqsave(&wdata->state.lock, flags); \ 204 + state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ 205 + spin_unlock_irqrestore(&wdata->state.lock, flags); \ 206 + \ 207 + return sprintf(buf, "%d\n", state); \ 208 + } \ 209 + static ssize_t wiifs_led_set_##num(struct device *dev, \ 210 + struct device_attribute *attr, const char *buf, size_t count) \ 211 + { \ 212 + struct wiimote_data *wdata = dev_to_wii(dev); \ 213 + int tmp = simple_strtoul(buf, NULL, 10); \ 214 + unsigned long flags; \ 215 + __u8 state; \ 216 + \ 217 + if (!atomic_read(&wdata->ready)) \ 218 + return -EBUSY; \ 219 + \ 220 + spin_lock_irqsave(&wdata->state.lock, flags); \ 221 + \ 222 + state = wdata->state.flags; \ 223 + \ 224 + if (tmp) \ 225 + wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ 226 + else \ 227 + wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ 228 + \ 229 + spin_unlock_irqrestore(&wdata->state.lock, flags); \ 230 + \ 231 + return count; \ 232 + } \ 233 + static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ 234 + wiifs_led_set_##num) 235 + 236 + wiifs_led_show_set(1); 237 + wiifs_led_show_set(2); 238 + wiifs_led_show_set(3); 239 + wiifs_led_show_set(4); 194 240 195 241 static int wiimote_input_event(struct input_dev *dev, unsigned int type, 196 242 unsigned int code, int value) ··· 377 325 return -ENOMEM; 378 326 } 379 327 328 + ret = device_create_file(&hdev->dev, &dev_attr_led1); 329 + if (ret) 330 + goto err; 331 + ret = device_create_file(&hdev->dev, &dev_attr_led2); 332 + if (ret) 333 + goto err; 334 + ret = device_create_file(&hdev->dev, &dev_attr_led3); 335 + if (ret) 336 + goto err; 337 + ret = device_create_file(&hdev->dev, &dev_attr_led4); 338 + if (ret) 339 + goto err; 340 + 380 341 ret = hid_parse(hdev); 381 342 if (ret) { 382 343 hid_err(hdev, "HID parse failed\n"); ··· 424 359 hid_hw_stop(hdev); 425 360 err: 426 361 input_free_device(wdata->input); 362 + device_remove_file(&hdev->dev, &dev_attr_led1); 363 + device_remove_file(&hdev->dev, &dev_attr_led2); 364 + device_remove_file(&hdev->dev, &dev_attr_led3); 365 + device_remove_file(&hdev->dev, &dev_attr_led4); 427 366 wiimote_destroy(wdata); 428 367 return ret; 429 368 } ··· 437 368 struct wiimote_data *wdata = hid_get_drvdata(hdev); 438 369 439 370 hid_info(hdev, "Device removed\n"); 371 + 372 + device_remove_file(&hdev->dev, &dev_attr_led1); 373 + device_remove_file(&hdev->dev, &dev_attr_led2); 374 + device_remove_file(&hdev->dev, &dev_attr_led3); 375 + device_remove_file(&hdev->dev, &dev_attr_led4); 440 376 441 377 hid_hw_stop(hdev); 442 378 input_unregister_device(wdata->input);