diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2011-07-05 07:45:12 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-07-11 08:30:22 -0400 |
commit | 4d36e9754f6b71870a476e84f418a864c2ddf77c (patch) | |
tree | 0fa70d8c1f443d6077cc1bcd0996bc6b39a48dd3 /drivers/hid | |
parent | 672bc4e090c9a2c655c28f8295e981609a1b84ba (diff) |
HID: wiimote: Synchronize wiimote input and hid event handling
The wiimote first starts HID hardware and then registers the input
device. We need to synchronize the startup so no event handler will
start parsing events when the wiimote device is not ready, yet.
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.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index deaf23207812..3416f69302cd 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * any later version. | 10 | * any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/atomic.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> |
@@ -20,6 +21,7 @@ | |||
20 | #define WIIMOTE_NAME "Nintendo Wii Remote" | 21 | #define WIIMOTE_NAME "Nintendo Wii Remote" |
21 | 22 | ||
22 | struct wiimote_data { | 23 | struct wiimote_data { |
24 | atomic_t ready; | ||
23 | struct hid_device *hdev; | 25 | struct hid_device *hdev; |
24 | struct input_dev *input; | 26 | struct input_dev *input; |
25 | }; | 27 | }; |
@@ -27,12 +29,26 @@ struct wiimote_data { | |||
27 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, | 29 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, |
28 | unsigned int code, int value) | 30 | unsigned int code, int value) |
29 | { | 31 | { |
32 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
33 | |||
34 | if (!atomic_read(&wdata->ready)) | ||
35 | return -EBUSY; | ||
36 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
37 | smp_rmb(); | ||
38 | |||
30 | return 0; | 39 | return 0; |
31 | } | 40 | } |
32 | 41 | ||
33 | static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, | 42 | static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, |
34 | u8 *raw_data, int size) | 43 | u8 *raw_data, int size) |
35 | { | 44 | { |
45 | struct wiimote_data *wdata = hid_get_drvdata(hdev); | ||
46 | |||
47 | if (!atomic_read(&wdata->ready)) | ||
48 | return -EBUSY; | ||
49 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
50 | smp_rmb(); | ||
51 | |||
36 | if (size < 1) | 52 | if (size < 1) |
37 | return -EINVAL; | 53 | return -EINVAL; |
38 | 54 | ||
@@ -103,6 +119,9 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
103 | goto err_stop; | 119 | goto err_stop; |
104 | } | 120 | } |
105 | 121 | ||
122 | /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */ | ||
123 | smp_wmb(); | ||
124 | atomic_set(&wdata->ready, 1); | ||
106 | hid_info(hdev, "New device registered\n"); | 125 | hid_info(hdev, "New device registered\n"); |
107 | return 0; | 126 | return 0; |
108 | 127 | ||