diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2011-11-17 08:12:07 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-22 17:09:45 -0500 |
commit | b17b57a5d0fcfc1d6ba582a086b3a22510aef03d (patch) | |
tree | 7f15f6289c72ab1dc2a8ea5dc311102e08457230 /drivers/hid | |
parent | 0b6815d75d8bf214998455d94061a40f3b4a77f3 (diff) |
HID: wiimote: Parse motion+ data
Motion+ reports rotation gyro data which we report to userspace as ABS_RX/Y/Z
values. The device reports them either in fast or slow mode. We adjust the
values to get a linear scale so userspace does not need to know about slow and
fast mode.
The motion+ also reports whether an extension is connected to it. We keep track
of this value and reinitialize the extensions if an extension is plugged or
unplugged.
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-ext.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index ecc7b7b9b171..ceec0cef3268 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c | |||
@@ -25,6 +25,7 @@ struct wiimote_ext { | |||
25 | atomic_t opened; | 25 | atomic_t opened; |
26 | atomic_t mp_opened; | 26 | atomic_t mp_opened; |
27 | bool plugged; | 27 | bool plugged; |
28 | bool mp_plugged; | ||
28 | bool motionp; | 29 | bool motionp; |
29 | __u8 ext_type; | 30 | __u8 ext_type; |
30 | }; | 31 | }; |
@@ -182,6 +183,10 @@ void wiiext_event(struct wiimote_data *wdata, bool plugged) | |||
182 | return; | 183 | return; |
183 | 184 | ||
184 | wdata->ext->plugged = plugged; | 185 | wdata->ext->plugged = plugged; |
186 | |||
187 | if (!plugged) | ||
188 | wdata->ext->mp_plugged = false; | ||
189 | |||
185 | /* | 190 | /* |
186 | * We need to call wiiext_schedule(wdata->ext) here, however, the | 191 | * We need to call wiiext_schedule(wdata->ext) here, however, the |
187 | * extension initialization logic is not fully understood and so | 192 | * extension initialization logic is not fully understood and so |
@@ -206,6 +211,63 @@ bool wiiext_active(struct wiimote_data *wdata) | |||
206 | 211 | ||
207 | static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) | 212 | static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) |
208 | { | 213 | { |
214 | __s32 x, y, z; | ||
215 | bool plugged; | ||
216 | |||
217 | /* | 8 7 6 5 4 3 | 2 | 1 | | ||
218 | * -----+------------------------------+-----+-----+ | ||
219 | * 1 | Yaw Speed <7:0> | | ||
220 | * 2 | Roll Speed <7:0> | | ||
221 | * 3 | Pitch Speed <7:0> | | ||
222 | * -----+------------------------------+-----+-----+ | ||
223 | * 4 | Yaw Speed <13:8> | Yaw |Pitch| | ||
224 | * -----+------------------------------+-----+-----+ | ||
225 | * 5 | Roll Speed <13:8> |Roll | Ext | | ||
226 | * -----+------------------------------+-----+-----+ | ||
227 | * 6 | Pitch Speed <13:8> | 1 | 0 | | ||
228 | * -----+------------------------------+-----+-----+ | ||
229 | * The single bits Yaw, Roll, Pitch in the lower right corner specify | ||
230 | * whether the wiimote is rotating fast (0) or slow (1). Speed for slow | ||
231 | * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a | ||
232 | * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast | ||
233 | * and 9 for slow. | ||
234 | * If the wiimote is not rotating the sensor reports 2^13 = 8192. | ||
235 | * Ext specifies whether an extension is connected to the motionp. | ||
236 | */ | ||
237 | |||
238 | x = payload[0]; | ||
239 | y = payload[1]; | ||
240 | z = payload[2]; | ||
241 | |||
242 | x |= (((__u16)payload[3]) << 6) & 0xff00; | ||
243 | y |= (((__u16)payload[4]) << 6) & 0xff00; | ||
244 | z |= (((__u16)payload[5]) << 6) & 0xff00; | ||
245 | |||
246 | x -= 8192; | ||
247 | y -= 8192; | ||
248 | z -= 8192; | ||
249 | |||
250 | if (!(payload[3] & 0x02)) | ||
251 | x *= 18; | ||
252 | else | ||
253 | x *= 9; | ||
254 | if (!(payload[4] & 0x02)) | ||
255 | y *= 18; | ||
256 | else | ||
257 | y *= 9; | ||
258 | if (!(payload[3] & 0x01)) | ||
259 | z *= 18; | ||
260 | else | ||
261 | z *= 9; | ||
262 | |||
263 | input_report_abs(ext->mp_input, ABS_RX, x); | ||
264 | input_report_abs(ext->mp_input, ABS_RY, y); | ||
265 | input_report_abs(ext->mp_input, ABS_RZ, z); | ||
266 | input_sync(ext->mp_input); | ||
267 | |||
268 | plugged = payload[5] & 0x01; | ||
269 | if (plugged != ext->mp_plugged) | ||
270 | ext->mp_plugged = plugged; | ||
209 | } | 271 | } |
210 | 272 | ||
211 | static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) | 273 | static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) |
@@ -368,6 +430,14 @@ int wiiext_init(struct wiimote_data *wdata) | |||
368 | ext->mp_input->id.version = wdata->hdev->version; | 430 | ext->mp_input->id.version = wdata->hdev->version; |
369 | ext->mp_input->name = WIIMOTE_NAME " Motion+"; | 431 | ext->mp_input->name = WIIMOTE_NAME " Motion+"; |
370 | 432 | ||
433 | set_bit(EV_ABS, ext->mp_input->evbit); | ||
434 | set_bit(ABS_RX, ext->mp_input->absbit); | ||
435 | set_bit(ABS_RY, ext->mp_input->absbit); | ||
436 | set_bit(ABS_RZ, ext->mp_input->absbit); | ||
437 | input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8); | ||
438 | input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8); | ||
439 | input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8); | ||
440 | |||
371 | ret = input_register_device(ext->mp_input); | 441 | ret = input_register_device(ext->mp_input); |
372 | if (ret) { | 442 | if (ret) { |
373 | input_free_device(ext->mp_input); | 443 | input_free_device(ext->mp_input); |