aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-11-17 08:12:07 -0500
committerJiri Kosina <jkosina@suse.cz>2011-11-22 17:09:45 -0500
commitb17b57a5d0fcfc1d6ba582a086b3a22510aef03d (patch)
tree7f15f6289c72ab1dc2a8ea5dc311102e08457230 /drivers/hid
parent0b6815d75d8bf214998455d94061a40f3b4a77f3 (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.c70
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
207static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) 212static 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
211static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) 273static 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);