diff options
| author | David Herrmann <dh.herrmann@googlemail.com> | 2011-07-05 07:45:19 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-07-11 08:30:24 -0400 |
| commit | 3c1c2fce64fdfa2f0c0ff4fffb3bb171ea6361ca (patch) | |
| tree | 58ba2f4c42cf84fbe23e0d7661c7c232ecf5c8de | |
| parent | 32a0d9a522b577d0efa6ce793a6ac0516c5e3627 (diff) | |
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>
| -rw-r--r-- | Documentation/ABI/testing/sysfs-driver-hid-wiimote | 10 | ||||
| -rw-r--r-- | drivers/hid/hid-wiimote.c | 74 |
2 files changed, 84 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-wiimote b/Documentation/ABI/testing/sysfs-driver-hid-wiimote new file mode 100644 index 000000000000..5d5a16ea57c6 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-wiimote | |||
| @@ -0,0 +1,10 @@ | |||
| 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. | ||
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index f9a3bcb6b240..a594383ce03d 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
| @@ -87,6 +87,9 @@ static __u16 wiiproto_keymap[] = { | |||
| 87 | BTN_MODE, /* WIIPROTO_KEY_HOME */ | 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 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | 93 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, |
| 91 | size_t count) | 94 | size_t count) |
| 92 | { | 95 | { |
| @@ -189,6 +192,55 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |||
| 189 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 192 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 190 | } | 193 | } |
| 191 | 194 | ||
| 195 | #define wiifs_led_show_set(num) \ | ||
| 196 | static ssize_t wiifs_led_show_##num(struct device *dev, \ | ||
| 197 | struct device_attribute *attr, char *buf) \ | ||
| 198 | { \ | ||
| 199 | struct wiimote_data *wdata = dev_to_wii(dev); \ | ||
| 200 | unsigned long flags; \ | ||
| 201 | int state; \ | ||
| 202 | \ | ||
| 203 | if (!atomic_read(&wdata->ready)) \ | ||
| 204 | return -EBUSY; \ | ||
| 205 | \ | ||
| 206 | spin_lock_irqsave(&wdata->state.lock, flags); \ | ||
| 207 | state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ | ||
| 208 | spin_unlock_irqrestore(&wdata->state.lock, flags); \ | ||
| 209 | \ | ||
| 210 | return sprintf(buf, "%d\n", state); \ | ||
| 211 | } \ | ||
| 212 | static ssize_t wiifs_led_set_##num(struct device *dev, \ | ||
| 213 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 214 | { \ | ||
| 215 | struct wiimote_data *wdata = dev_to_wii(dev); \ | ||
| 216 | int tmp = simple_strtoul(buf, NULL, 10); \ | ||
| 217 | unsigned long flags; \ | ||
| 218 | __u8 state; \ | ||
| 219 | \ | ||
| 220 | if (!atomic_read(&wdata->ready)) \ | ||
| 221 | return -EBUSY; \ | ||
| 222 | \ | ||
| 223 | spin_lock_irqsave(&wdata->state.lock, flags); \ | ||
| 224 | \ | ||
| 225 | state = wdata->state.flags; \ | ||
| 226 | \ | ||
| 227 | if (tmp) \ | ||
| 228 | wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ | ||
| 229 | else \ | ||
| 230 | wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ | ||
| 231 | \ | ||
| 232 | spin_unlock_irqrestore(&wdata->state.lock, flags); \ | ||
| 233 | \ | ||
| 234 | return count; \ | ||
| 235 | } \ | ||
| 236 | static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ | ||
| 237 | wiifs_led_set_##num) | ||
| 238 | |||
| 239 | wiifs_led_show_set(1); | ||
| 240 | wiifs_led_show_set(2); | ||
| 241 | wiifs_led_show_set(3); | ||
| 242 | wiifs_led_show_set(4); | ||
| 243 | |||
| 192 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, | 244 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, |
| 193 | unsigned int code, int value) | 245 | unsigned int code, int value) |
| 194 | { | 246 | { |
| @@ -325,6 +377,19 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
| 325 | return -ENOMEM; | 377 | return -ENOMEM; |
| 326 | } | 378 | } |
| 327 | 379 | ||
| 380 | ret = device_create_file(&hdev->dev, &dev_attr_led1); | ||
| 381 | if (ret) | ||
| 382 | goto err; | ||
| 383 | ret = device_create_file(&hdev->dev, &dev_attr_led2); | ||
| 384 | if (ret) | ||
| 385 | goto err; | ||
| 386 | ret = device_create_file(&hdev->dev, &dev_attr_led3); | ||
| 387 | if (ret) | ||
| 388 | goto err; | ||
| 389 | ret = device_create_file(&hdev->dev, &dev_attr_led4); | ||
| 390 | if (ret) | ||
| 391 | goto err; | ||
| 392 | |||
| 328 | ret = hid_parse(hdev); | 393 | ret = hid_parse(hdev); |
| 329 | if (ret) { | 394 | if (ret) { |
| 330 | hid_err(hdev, "HID parse failed\n"); | 395 | hid_err(hdev, "HID parse failed\n"); |
| @@ -359,6 +424,10 @@ err_stop: | |||
| 359 | hid_hw_stop(hdev); | 424 | hid_hw_stop(hdev); |
| 360 | err: | 425 | err: |
| 361 | input_free_device(wdata->input); | 426 | input_free_device(wdata->input); |
| 427 | device_remove_file(&hdev->dev, &dev_attr_led1); | ||
| 428 | device_remove_file(&hdev->dev, &dev_attr_led2); | ||
| 429 | device_remove_file(&hdev->dev, &dev_attr_led3); | ||
| 430 | device_remove_file(&hdev->dev, &dev_attr_led4); | ||
| 362 | wiimote_destroy(wdata); | 431 | wiimote_destroy(wdata); |
| 363 | return ret; | 432 | return ret; |
| 364 | } | 433 | } |
| @@ -369,6 +438,11 @@ static void wiimote_hid_remove(struct hid_device *hdev) | |||
| 369 | 438 | ||
| 370 | hid_info(hdev, "Device removed\n"); | 439 | hid_info(hdev, "Device removed\n"); |
| 371 | 440 | ||
| 441 | device_remove_file(&hdev->dev, &dev_attr_led1); | ||
| 442 | device_remove_file(&hdev->dev, &dev_attr_led2); | ||
| 443 | device_remove_file(&hdev->dev, &dev_attr_led3); | ||
| 444 | device_remove_file(&hdev->dev, &dev_attr_led4); | ||
| 445 | |||
| 372 | hid_hw_stop(hdev); | 446 | hid_hw_stop(hdev); |
| 373 | input_unregister_device(wdata->input); | 447 | input_unregister_device(wdata->input); |
| 374 | 448 | ||
