aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-09-06 07:50:34 -0400
committerJiri Kosina <jkosina@suse.cz>2011-09-07 07:25:17 -0400
commit29d28064e27d11433c4249369f469fab86826d0c (patch)
treeb1d25e0472636c029bf30361c56fd02e9b38f97d /drivers/hid
parentbe1ecd62e619dae8d7c5b7f212333558fcc85d4d (diff)
HID: wiimote: Helper functions for synchronous requests
To initialize wiimote peripherals, the stream to the wiimote must be held exclusively by the initializer, otherwise the initialization will fail. Many initializations require multiple memory requests to be sent synchronously so we need a way to lock the stream and release it when we are done. This adds several helper functions which allow to lock the stream, then send requests, wait for the answers and release the stream again. When holding the lock, the function may sleep and interrupted by signals. Also it returns after a short timeout so userspace shouldn't notice long delays. 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.c56
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
36struct wiimote_data { 44struct 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 */
130static 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 */
137static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
138{
139 wdata->state.cmd = WIIPROTO_REQ_NULL;
140 complete(&wdata->state.ready);
141}
142
143static 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 */
149static 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
157static inline void wiimote_cmd_release(struct wiimote_data *wdata)
158{
159 mutex_unlock(&wdata->state.sync);
160}
161
162static 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
121static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, 175static 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