aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-07-05 07:45:19 -0400
committerJiri Kosina <jkosina@suse.cz>2011-07-11 08:30:24 -0400
commit3c1c2fce64fdfa2f0c0ff4fffb3bb171ea6361ca (patch)
tree58ba2f4c42cf84fbe23e0d7661c7c232ecf5c8de
parent32a0d9a522b577d0efa6ce793a6ac0516c5e3627 (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-wiimote10
-rw-r--r--drivers/hid/hid-wiimote.c74
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 @@
1What: /sys/bus/hid/drivers/wiimote/<dev>/led1
2What: /sys/bus/hid/drivers/wiimote/<dev>/led2
3What: /sys/bus/hid/drivers/wiimote/<dev>/led3
4What: /sys/bus/hid/drivers/wiimote/<dev>/led4
5Date: July 2011
6KernelVersion: 3.1
7Contact: David Herrmann <dh.herrmann@googlemail.com>
8Description: 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
90static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, 93static 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) \
196static 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} \
212static 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} \
236static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \
237 wiifs_led_set_##num)
238
239wiifs_led_show_set(1);
240wiifs_led_show_set(2);
241wiifs_led_show_set(3);
242wiifs_led_show_set(4);
243
192static int wiimote_input_event(struct input_dev *dev, unsigned int type, 244static 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);
360err: 425err:
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