Commit 3c1c2fce authored by David Herrmann's avatar David Herrmann Committed by Jiri Kosina

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: default avatarDavid Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 32a0d9a5
What: /sys/bus/hid/drivers/wiimote/<dev>/led1
What: /sys/bus/hid/drivers/wiimote/<dev>/led2
What: /sys/bus/hid/drivers/wiimote/<dev>/led3
What: /sys/bus/hid/drivers/wiimote/<dev>/led4
Date: July 2011
KernelVersion: 3.1
Contact: David Herrmann <dh.herrmann@googlemail.com>
Description: Make it possible to set/get current led state. Reading from it
returns 0 if led is off and 1 if it is on. Writing 0 to it
disables the led, writing 1 enables it.
...@@ -87,6 +87,9 @@ static __u16 wiiproto_keymap[] = { ...@@ -87,6 +87,9 @@ static __u16 wiiproto_keymap[] = {
BTN_MODE, /* WIIPROTO_KEY_HOME */ BTN_MODE, /* WIIPROTO_KEY_HOME */
}; };
#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
dev))
static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
size_t count) size_t count)
{ {
...@@ -189,6 +192,55 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) ...@@ -189,6 +192,55 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
wiimote_queue(wdata, cmd, sizeof(cmd)); wiimote_queue(wdata, cmd, sizeof(cmd));
} }
#define wiifs_led_show_set(num) \
static ssize_t wiifs_led_show_##num(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct wiimote_data *wdata = dev_to_wii(dev); \
unsigned long flags; \
int state; \
\
if (!atomic_read(&wdata->ready)) \
return -EBUSY; \
\
spin_lock_irqsave(&wdata->state.lock, flags); \
state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \
spin_unlock_irqrestore(&wdata->state.lock, flags); \
\
return sprintf(buf, "%d\n", state); \
} \
static ssize_t wiifs_led_set_##num(struct device *dev, \
struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct wiimote_data *wdata = dev_to_wii(dev); \
int tmp = simple_strtoul(buf, NULL, 10); \
unsigned long flags; \
__u8 state; \
\
if (!atomic_read(&wdata->ready)) \
return -EBUSY; \
\
spin_lock_irqsave(&wdata->state.lock, flags); \
\
state = wdata->state.flags; \
\
if (tmp) \
wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\
else \
wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\
\
spin_unlock_irqrestore(&wdata->state.lock, flags); \
\
return count; \
} \
static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \
wiifs_led_set_##num)
wiifs_led_show_set(1);
wiifs_led_show_set(2);
wiifs_led_show_set(3);
wiifs_led_show_set(4);
static int wiimote_input_event(struct input_dev *dev, unsigned int type, static int wiimote_input_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value) unsigned int code, int value)
{ {
...@@ -325,6 +377,19 @@ static int wiimote_hid_probe(struct hid_device *hdev, ...@@ -325,6 +377,19 @@ static int wiimote_hid_probe(struct hid_device *hdev,
return -ENOMEM; return -ENOMEM;
} }
ret = device_create_file(&hdev->dev, &dev_attr_led1);
if (ret)
goto err;
ret = device_create_file(&hdev->dev, &dev_attr_led2);
if (ret)
goto err;
ret = device_create_file(&hdev->dev, &dev_attr_led3);
if (ret)
goto err;
ret = device_create_file(&hdev->dev, &dev_attr_led4);
if (ret)
goto err;
ret = hid_parse(hdev); ret = hid_parse(hdev);
if (ret) { if (ret) {
hid_err(hdev, "HID parse failed\n"); hid_err(hdev, "HID parse failed\n");
...@@ -359,6 +424,10 @@ static int wiimote_hid_probe(struct hid_device *hdev, ...@@ -359,6 +424,10 @@ static int wiimote_hid_probe(struct hid_device *hdev,
hid_hw_stop(hdev); hid_hw_stop(hdev);
err: err:
input_free_device(wdata->input); input_free_device(wdata->input);
device_remove_file(&hdev->dev, &dev_attr_led1);
device_remove_file(&hdev->dev, &dev_attr_led2);
device_remove_file(&hdev->dev, &dev_attr_led3);
device_remove_file(&hdev->dev, &dev_attr_led4);
wiimote_destroy(wdata); wiimote_destroy(wdata);
return ret; return ret;
} }
...@@ -369,6 +438,11 @@ static void wiimote_hid_remove(struct hid_device *hdev) ...@@ -369,6 +438,11 @@ static void wiimote_hid_remove(struct hid_device *hdev)
hid_info(hdev, "Device removed\n"); hid_info(hdev, "Device removed\n");
device_remove_file(&hdev->dev, &dev_attr_led1);
device_remove_file(&hdev->dev, &dev_attr_led2);
device_remove_file(&hdev->dev, &dev_attr_led3);
device_remove_file(&hdev->dev, &dev_attr_led4);
hid_hw_stop(hdev); hid_hw_stop(hdev);
input_unregister_device(wdata->input); input_unregister_device(wdata->input);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment