aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-wiimote.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-08-17 05:43:22 -0400
committerJiri Kosina <jkosina@suse.cz>2011-08-23 04:55:21 -0400
commit23a5a4a39eddbe515a832767a371cc54e82cc25e (patch)
tree749dfe3d46b6ae45af39d8df6026e511bdf5e2e5 /drivers/hid/hid-wiimote.c
parent26af17484a737aaa991a7ce578cb15809a582fbc (diff)
HID: wiimote: Register led class devices
This registers 4 led devices to allow controlling the wiimote leds via standard LED sysfs API. It removes the four sysfs attributes so we don't have two APIs for one device. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-wiimote.c')
-rw-r--r--drivers/hid/hid-wiimote.c165
1 files changed, 106 insertions, 59 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index d49f67c7a00c..29edd55d4bb0 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -13,6 +13,7 @@
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/hid.h> 14#include <linux/hid.h>
15#include <linux/input.h> 15#include <linux/input.h>
16#include <linux/leds.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/spinlock.h> 18#include <linux/spinlock.h>
18#include "hid-ids.h" 19#include "hid-ids.h"
@@ -34,6 +35,7 @@ struct wiimote_state {
34struct wiimote_data { 35struct wiimote_data {
35 struct hid_device *hdev; 36 struct hid_device *hdev;
36 struct input_dev *input; 37 struct input_dev *input;
38 struct led_classdev *leds[4];
37 39
38 spinlock_t qlock; 40 spinlock_t qlock;
39 __u8 head; 41 __u8 head;
@@ -51,6 +53,9 @@ struct wiimote_data {
51#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ 53#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
52 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) 54 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
53 55
56/* return flag for led \num */
57#define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1))
58
54enum wiiproto_reqs { 59enum wiiproto_reqs {
55 WIIPROTO_REQ_LED = 0x11, 60 WIIPROTO_REQ_LED = 0x11,
56 WIIPROTO_REQ_DRM_K = 0x30, 61 WIIPROTO_REQ_DRM_K = 0x30,
@@ -85,9 +90,6 @@ static __u16 wiiproto_keymap[] = {
85 BTN_MODE, /* WIIPROTO_KEY_HOME */ 90 BTN_MODE, /* WIIPROTO_KEY_HOME */
86}; 91};
87 92
88#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
89 dev))
90
91static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, 93static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
92 size_t count) 94 size_t count)
93{ 95{
@@ -190,48 +192,53 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
190 wiimote_queue(wdata, cmd, sizeof(cmd)); 192 wiimote_queue(wdata, cmd, sizeof(cmd));
191} 193}
192 194
193#define wiifs_led_show_set(num) \ 195static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev)
194static ssize_t wiifs_led_show_##num(struct device *dev, \ 196{
195 struct device_attribute *attr, char *buf) \ 197 struct wiimote_data *wdata;
196{ \ 198 struct device *dev = led_dev->dev->parent;
197 struct wiimote_data *wdata = dev_to_wii(dev); \ 199 int i;
198 unsigned long flags; \ 200 unsigned long flags;
199 int state; \ 201 bool value = false;
200 \ 202
201 spin_lock_irqsave(&wdata->state.lock, flags); \ 203 wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
202 state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ 204
203 spin_unlock_irqrestore(&wdata->state.lock, flags); \ 205 for (i = 0; i < 4; ++i) {
204 \ 206 if (wdata->leds[i] == led_dev) {
205 return sprintf(buf, "%d\n", state); \ 207 spin_lock_irqsave(&wdata->state.lock, flags);
206} \ 208 value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1);
207static ssize_t wiifs_led_set_##num(struct device *dev, \ 209 spin_unlock_irqrestore(&wdata->state.lock, flags);
208 struct device_attribute *attr, const char *buf, size_t count) \ 210 break;
209{ \ 211 }
210 struct wiimote_data *wdata = dev_to_wii(dev); \ 212 }
211 int tmp = simple_strtoul(buf, NULL, 10); \ 213
212 unsigned long flags; \ 214 return value ? LED_FULL : LED_OFF;
213 __u8 state; \ 215}
214 \ 216
215 spin_lock_irqsave(&wdata->state.lock, flags); \ 217static void wiimote_leds_set(struct led_classdev *led_dev,
216 \ 218 enum led_brightness value)
217 state = wdata->state.flags; \ 219{
218 \ 220 struct wiimote_data *wdata;
219 if (tmp) \ 221 struct device *dev = led_dev->dev->parent;
220 wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ 222 int i;
221 else \ 223 unsigned long flags;
222 wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ 224 __u8 state, flag;
223 \ 225
224 spin_unlock_irqrestore(&wdata->state.lock, flags); \ 226 wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
225 \ 227
226 return count; \ 228 for (i = 0; i < 4; ++i) {
227} \ 229 if (wdata->leds[i] == led_dev) {
228static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ 230 flag = WIIPROTO_FLAG_LED(i + 1);
229 wiifs_led_set_##num) 231 spin_lock_irqsave(&wdata->state.lock, flags);
230 232 state = wdata->state.flags;
231wiifs_led_show_set(1); 233 if (value == LED_OFF)
232wiifs_led_show_set(2); 234 wiiproto_req_leds(wdata, state & ~flag);
233wiifs_led_show_set(3); 235 else
234wiifs_led_show_set(4); 236 wiiproto_req_leds(wdata, state | flag);
237 spin_unlock_irqrestore(&wdata->state.lock, flags);
238 break;
239 }
240 }
241}
235 242
236static int wiimote_input_event(struct input_dev *dev, unsigned int type, 243static int wiimote_input_event(struct input_dev *dev, unsigned int type,
237 unsigned int code, int value) 244 unsigned int code, int value)
@@ -315,6 +322,58 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
315 return 0; 322 return 0;
316} 323}
317 324
325static void wiimote_leds_destroy(struct wiimote_data *wdata)
326{
327 int i;
328 struct led_classdev *led;
329
330 for (i = 0; i < 4; ++i) {
331 if (wdata->leds[i]) {
332 led = wdata->leds[i];
333 wdata->leds[i] = NULL;
334 led_classdev_unregister(led);
335 kfree(led);
336 }
337 }
338}
339
340static int wiimote_leds_create(struct wiimote_data *wdata)
341{
342 int i, ret;
343 struct device *dev = &wdata->hdev->dev;
344 size_t namesz = strlen(dev_name(dev)) + 9;
345 struct led_classdev *led;
346 char *name;
347
348 for (i = 0; i < 4; ++i) {
349 led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
350 if (!led) {
351 ret = -ENOMEM;
352 goto err;
353 }
354 name = (void*)&led[1];
355 snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i);
356 led->name = name;
357 led->brightness = 0;
358 led->max_brightness = 1;
359 led->brightness_get = wiimote_leds_get;
360 led->brightness_set = wiimote_leds_set;
361
362 ret = led_classdev_register(dev, led);
363 if (ret) {
364 kfree(led);
365 goto err;
366 }
367 wdata->leds[i] = led;
368 }
369
370 return 0;
371
372err:
373 wiimote_leds_destroy(wdata);
374 return ret;
375}
376
318static struct wiimote_data *wiimote_create(struct hid_device *hdev) 377static struct wiimote_data *wiimote_create(struct hid_device *hdev)
319{ 378{
320 struct wiimote_data *wdata; 379 struct wiimote_data *wdata;
@@ -358,10 +417,7 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
358 417
359static void wiimote_destroy(struct wiimote_data *wdata) 418static void wiimote_destroy(struct wiimote_data *wdata)
360{ 419{
361 device_remove_file(&wdata->hdev->dev, &dev_attr_led1); 420 wiimote_leds_destroy(wdata);
362 device_remove_file(&wdata->hdev->dev, &dev_attr_led2);
363 device_remove_file(&wdata->hdev->dev, &dev_attr_led3);
364 device_remove_file(&wdata->hdev->dev, &dev_attr_led4);
365 421
366 input_unregister_device(wdata->input); 422 input_unregister_device(wdata->input);
367 cancel_work_sync(&wdata->worker); 423 cancel_work_sync(&wdata->worker);
@@ -400,16 +456,7 @@ static int wiimote_hid_probe(struct hid_device *hdev,
400 goto err_stop; 456 goto err_stop;
401 } 457 }
402 458
403 ret = device_create_file(&hdev->dev, &dev_attr_led1); 459 ret = wiimote_leds_create(wdata);
404 if (ret)
405 goto err_free;
406 ret = device_create_file(&hdev->dev, &dev_attr_led2);
407 if (ret)
408 goto err_free;
409 ret = device_create_file(&hdev->dev, &dev_attr_led3);
410 if (ret)
411 goto err_free;
412 ret = device_create_file(&hdev->dev, &dev_attr_led4);
413 if (ret) 460 if (ret)
414 goto err_free; 461 goto err_free;
415 462