Commit 32a0d9a5 authored by David Herrmann's avatar David Herrmann Committed by Jiri Kosina

HID: wiimote: Cache wiimote led state

Save the current state of the leds in the wiimote data structure. This
allows us to discard new led requests that wouldn't change anything.
Protect the whole state structure by a spinlock. Every wiiproto_*
function expects this spinlock to be held when called.
Signed-off-by: default avatarDavid Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent db308346
...@@ -27,6 +27,11 @@ struct wiimote_buf { ...@@ -27,6 +27,11 @@ struct wiimote_buf {
size_t size; size_t size;
}; };
struct wiimote_state {
spinlock_t lock;
__u8 flags;
};
struct wiimote_data { struct wiimote_data {
atomic_t ready; atomic_t ready;
struct hid_device *hdev; struct hid_device *hdev;
...@@ -37,12 +42,16 @@ struct wiimote_data { ...@@ -37,12 +42,16 @@ struct wiimote_data {
__u8 tail; __u8 tail;
struct wiimote_buf outq[WIIMOTE_BUFSIZE]; struct wiimote_buf outq[WIIMOTE_BUFSIZE];
struct work_struct worker; struct work_struct worker;
struct wiimote_state state;
}; };
#define WIIPROTO_FLAG_LED1 0x01 #define WIIPROTO_FLAG_LED1 0x01
#define WIIPROTO_FLAG_LED2 0x02 #define WIIPROTO_FLAG_LED2 0x02
#define WIIPROTO_FLAG_LED3 0x04 #define WIIPROTO_FLAG_LED3 0x04
#define WIIPROTO_FLAG_LED4 0x08 #define WIIPROTO_FLAG_LED4 0x08
#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
enum wiiproto_reqs { enum wiiproto_reqs {
WIIPROTO_REQ_LED = 0x11, WIIPROTO_REQ_LED = 0x11,
...@@ -160,6 +169,11 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) ...@@ -160,6 +169,11 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
{ {
__u8 cmd[2]; __u8 cmd[2];
leds &= WIIPROTO_FLAGS_LEDS;
if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds)
return;
wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds;
cmd[0] = WIIPROTO_REQ_LED; cmd[0] = WIIPROTO_REQ_LED;
cmd[1] = 0; cmd[1] = 0;
...@@ -232,6 +246,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, ...@@ -232,6 +246,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
struct wiimote_data *wdata = hid_get_drvdata(hdev); struct wiimote_data *wdata = hid_get_drvdata(hdev);
struct wiiproto_handler *h; struct wiiproto_handler *h;
int i; int i;
unsigned long flags;
if (!atomic_read(&wdata->ready)) if (!atomic_read(&wdata->ready))
return -EBUSY; return -EBUSY;
...@@ -241,12 +256,16 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, ...@@ -241,12 +256,16 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
if (size < 1) if (size < 1)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&wdata->state.lock, flags);
for (i = 0; handlers[i].id; ++i) { for (i = 0; handlers[i].id; ++i) {
h = &handlers[i]; h = &handlers[i];
if (h->id == raw_data[0] && h->size < size) if (h->id == raw_data[0] && h->size < size)
h->func(wdata, &raw_data[1]); h->func(wdata, &raw_data[1]);
} }
spin_unlock_irqrestore(&wdata->state.lock, flags);
return 0; return 0;
} }
...@@ -284,6 +303,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) ...@@ -284,6 +303,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
spin_lock_init(&wdata->qlock); spin_lock_init(&wdata->qlock);
INIT_WORK(&wdata->worker, wiimote_worker); INIT_WORK(&wdata->worker, wiimote_worker);
spin_lock_init(&wdata->state.lock);
return wdata; return wdata;
} }
...@@ -326,7 +347,12 @@ static int wiimote_hid_probe(struct hid_device *hdev, ...@@ -326,7 +347,12 @@ static int wiimote_hid_probe(struct hid_device *hdev,
smp_wmb(); smp_wmb();
atomic_set(&wdata->ready, 1); atomic_set(&wdata->ready, 1);
hid_info(hdev, "New device registered\n"); hid_info(hdev, "New device registered\n");
/* by default set led1 after device initialization */
spin_lock_irq(&wdata->state.lock);
wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1);
spin_unlock_irq(&wdata->state.lock);
return 0; return 0;
err_stop: err_stop:
......
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