diff options
| -rw-r--r-- | drivers/hid/hid-wiimote.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index c811a7d14174..0a5e458820b2 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
| @@ -10,11 +10,13 @@ | |||
| 10 | * any later version. | 10 | * any later version. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/completion.h> | ||
| 13 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 14 | #include <linux/hid.h> | 15 | #include <linux/hid.h> |
| 15 | #include <linux/input.h> | 16 | #include <linux/input.h> |
| 16 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
| 17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/mutex.h> | ||
| 18 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
| 19 | #include "hid-ids.h" | 21 | #include "hid-ids.h" |
| 20 | 22 | ||
| @@ -31,6 +33,12 @@ struct wiimote_state { | |||
| 31 | spinlock_t lock; | 33 | spinlock_t lock; |
| 32 | __u8 flags; | 34 | __u8 flags; |
| 33 | __u8 accel_split[2]; | 35 | __u8 accel_split[2]; |
| 36 | |||
| 37 | /* synchronous cmd requests */ | ||
| 38 | struct mutex sync; | ||
| 39 | struct completion ready; | ||
| 40 | int cmd; | ||
| 41 | __u32 opt; | ||
| 34 | }; | 42 | }; |
| 35 | 43 | ||
| 36 | struct wiimote_data { | 44 | struct wiimote_data { |
| @@ -118,6 +126,52 @@ static __u16 wiiproto_keymap[] = { | |||
| 118 | BTN_MODE, /* WIIPROTO_KEY_HOME */ | 126 | BTN_MODE, /* WIIPROTO_KEY_HOME */ |
| 119 | }; | 127 | }; |
| 120 | 128 | ||
| 129 | /* requires the state.lock spinlock to be held */ | ||
| 130 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | ||
| 131 | __u32 opt) | ||
| 132 | { | ||
| 133 | return wdata->state.cmd == cmd && wdata->state.opt == opt; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* requires the state.lock spinlock to be held */ | ||
| 137 | static inline void wiimote_cmd_complete(struct wiimote_data *wdata) | ||
| 138 | { | ||
| 139 | wdata->state.cmd = WIIPROTO_REQ_NULL; | ||
| 140 | complete(&wdata->state.ready); | ||
| 141 | } | ||
| 142 | |||
| 143 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) | ||
| 144 | { | ||
| 145 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* requires the state.lock spinlock to be held */ | ||
| 149 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, | ||
| 150 | __u32 opt) | ||
| 151 | { | ||
| 152 | INIT_COMPLETION(wdata->state.ready); | ||
| 153 | wdata->state.cmd = cmd; | ||
| 154 | wdata->state.opt = opt; | ||
| 155 | } | ||
| 156 | |||
| 157 | static inline void wiimote_cmd_release(struct wiimote_data *wdata) | ||
| 158 | { | ||
| 159 | mutex_unlock(&wdata->state.sync); | ||
| 160 | } | ||
| 161 | |||
| 162 | static inline int wiimote_cmd_wait(struct wiimote_data *wdata) | ||
| 163 | { | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); | ||
| 167 | if (ret < 0) | ||
| 168 | return -ERESTARTSYS; | ||
| 169 | else if (ret == 0) | ||
| 170 | return -EIO; | ||
| 171 | else | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 121 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | 175 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, |
| 122 | size_t count) | 176 | size_t count) |
| 123 | { | 177 | { |
| @@ -875,6 +929,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
| 875 | INIT_WORK(&wdata->worker, wiimote_worker); | 929 | INIT_WORK(&wdata->worker, wiimote_worker); |
| 876 | 930 | ||
| 877 | spin_lock_init(&wdata->state.lock); | 931 | spin_lock_init(&wdata->state.lock); |
| 932 | init_completion(&wdata->state.ready); | ||
| 933 | mutex_init(&wdata->state.sync); | ||
| 878 | 934 | ||
| 879 | return wdata; | 935 | return wdata; |
| 880 | 936 | ||
