aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-07-05 07:45:18 -0400
committerJiri Kosina <jkosina@suse.cz>2011-07-11 08:30:24 -0400
commit32a0d9a522b577d0efa6ce793a6ac0516c5e3627 (patch)
tree901b90f2c9488d10359c71a64875bac862eb938d /drivers/hid
parentdb3083467f1527816fca95ae2d8bfe5d81503a8e (diff)
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: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index 3fb18fbe080c..f9a3bcb6b240 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -27,6 +27,11 @@ struct wiimote_buf {
27 size_t size; 27 size_t size;
28}; 28};
29 29
30struct wiimote_state {
31 spinlock_t lock;
32 __u8 flags;
33};
34
30struct wiimote_data { 35struct wiimote_data {
31 atomic_t ready; 36 atomic_t ready;
32 struct hid_device *hdev; 37 struct hid_device *hdev;
@@ -37,12 +42,16 @@ struct wiimote_data {
37 __u8 tail; 42 __u8 tail;
38 struct wiimote_buf outq[WIIMOTE_BUFSIZE]; 43 struct wiimote_buf outq[WIIMOTE_BUFSIZE];
39 struct work_struct worker; 44 struct work_struct worker;
45
46 struct wiimote_state state;
40}; 47};
41 48
42#define WIIPROTO_FLAG_LED1 0x01 49#define WIIPROTO_FLAG_LED1 0x01
43#define WIIPROTO_FLAG_LED2 0x02 50#define WIIPROTO_FLAG_LED2 0x02
44#define WIIPROTO_FLAG_LED3 0x04 51#define WIIPROTO_FLAG_LED3 0x04
45#define WIIPROTO_FLAG_LED4 0x08 52#define WIIPROTO_FLAG_LED4 0x08
53#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
54 WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
46 55
47enum wiiproto_reqs { 56enum wiiproto_reqs {
48 WIIPROTO_REQ_LED = 0x11, 57 WIIPROTO_REQ_LED = 0x11,
@@ -160,6 +169,11 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
160{ 169{
161 __u8 cmd[2]; 170 __u8 cmd[2];
162 171
172 leds &= WIIPROTO_FLAGS_LEDS;
173 if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds)
174 return;
175 wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds;
176
163 cmd[0] = WIIPROTO_REQ_LED; 177 cmd[0] = WIIPROTO_REQ_LED;
164 cmd[1] = 0; 178 cmd[1] = 0;
165 179
@@ -232,6 +246,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
232 struct wiimote_data *wdata = hid_get_drvdata(hdev); 246 struct wiimote_data *wdata = hid_get_drvdata(hdev);
233 struct wiiproto_handler *h; 247 struct wiiproto_handler *h;
234 int i; 248 int i;
249 unsigned long flags;
235 250
236 if (!atomic_read(&wdata->ready)) 251 if (!atomic_read(&wdata->ready))
237 return -EBUSY; 252 return -EBUSY;
@@ -241,12 +256,16 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
241 if (size < 1) 256 if (size < 1)
242 return -EINVAL; 257 return -EINVAL;
243 258
259 spin_lock_irqsave(&wdata->state.lock, flags);
260
244 for (i = 0; handlers[i].id; ++i) { 261 for (i = 0; handlers[i].id; ++i) {
245 h = &handlers[i]; 262 h = &handlers[i];
246 if (h->id == raw_data[0] && h->size < size) 263 if (h->id == raw_data[0] && h->size < size)
247 h->func(wdata, &raw_data[1]); 264 h->func(wdata, &raw_data[1]);
248 } 265 }
249 266
267 spin_unlock_irqrestore(&wdata->state.lock, flags);
268
250 return 0; 269 return 0;
251} 270}
252 271
@@ -284,6 +303,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
284 spin_lock_init(&wdata->qlock); 303 spin_lock_init(&wdata->qlock);
285 INIT_WORK(&wdata->worker, wiimote_worker); 304 INIT_WORK(&wdata->worker, wiimote_worker);
286 305
306 spin_lock_init(&wdata->state.lock);
307
287 return wdata; 308 return wdata;
288} 309}
289 310
@@ -326,7 +347,12 @@ static int wiimote_hid_probe(struct hid_device *hdev,
326 smp_wmb(); 347 smp_wmb();
327 atomic_set(&wdata->ready, 1); 348 atomic_set(&wdata->ready, 1);
328 hid_info(hdev, "New device registered\n"); 349 hid_info(hdev, "New device registered\n");
350
351 /* by default set led1 after device initialization */
352 spin_lock_irq(&wdata->state.lock);
329 wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); 353 wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1);
354 spin_unlock_irq(&wdata->state.lock);
355
330 return 0; 356 return 0;
331 357
332err_stop: 358err_stop: