size_t size;
};
+struct wiimote_state {
+ spinlock_t lock;
+ __u8 flags;
+};
+
struct wiimote_data {
atomic_t ready;
struct hid_device *hdev;
__u8 tail;
struct wiimote_buf outq[WIIMOTE_BUFSIZE];
struct work_struct worker;
+
+ struct wiimote_state state;
};
#define WIIPROTO_FLAG_LED1 0x01
#define WIIPROTO_FLAG_LED2 0x02
#define WIIPROTO_FLAG_LED3 0x04
#define WIIPROTO_FLAG_LED4 0x08
+#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
+ WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
enum wiiproto_reqs {
WIIPROTO_REQ_LED = 0x11,
{
__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[1] = 0;
struct wiimote_data *wdata = hid_get_drvdata(hdev);
struct wiiproto_handler *h;
int i;
+ unsigned long flags;
if (!atomic_read(&wdata->ready))
return -EBUSY;
if (size < 1)
return -EINVAL;
+ spin_lock_irqsave(&wdata->state.lock, flags);
+
for (i = 0; handlers[i].id; ++i) {
h = &handlers[i];
if (h->id == raw_data[0] && h->size < size)
h->func(wdata, &raw_data[1]);
}
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
return 0;
}
spin_lock_init(&wdata->qlock);
INIT_WORK(&wdata->worker, wiimote_worker);
+ spin_lock_init(&wdata->state.lock);
+
return wdata;
}
smp_wmb();
atomic_set(&wdata->ready, 1);
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);
+ spin_unlock_irq(&wdata->state.lock);
+
return 0;
err_stop: