aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@googlemail.com>2011-11-17 08:12:08 -0500
committerJiri Kosina <jkosina@suse.cz>2011-11-22 17:09:56 -0500
commita53535014b7af750df3d8eda471dce21b2aa339c (patch)
tree66cd66019376ce9acafcf589de558c589613b56c /drivers
parentb17b57a5d0fcfc1d6ba582a086b3a22510aef03d (diff)
HID: wiimote: Parse nunchuck data
The Nintendo Nunchuck extension reports accelerometer values, one analog stick and two buttons. See inline comments for data layout. We report all data to userspace through extension input device. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/hid-wiimote-ext.c105
1 files changed, 104 insertions, 1 deletions
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index ceec0cef326..f05f1549d94 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -36,6 +36,17 @@ enum wiiext_type {
36 WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ 36 WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */
37}; 37};
38 38
39enum wiiext_keys {
40 WIIEXT_KEY_C,
41 WIIEXT_KEY_Z,
42 WIIEXT_KEY_COUNT
43};
44
45static __u16 wiiext_keymap[] = {
46 BTN_C, /* WIIEXT_KEY_C */
47 BTN_Z, /* WIIEXT_KEY_Z */
48};
49
39/* diable all extensions */ 50/* diable all extensions */
40static void ext_disable(struct wiimote_ext *ext) 51static void ext_disable(struct wiimote_ext *ext)
41{ 52{
@@ -272,6 +283,82 @@ static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload)
272 283
273static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) 284static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
274{ 285{
286 __s16 x, y, z, bx, by;
287
288 /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 |
289 * -----+----------+---------+---------+----+-----+
290 * 1 | Button X <7:0> |
291 * 2 | Button Y <7:0> |
292 * -----+----------+---------+---------+----+-----+
293 * 3 | Speed X <9:2> |
294 * 4 | Speed Y <9:2> |
295 * 5 | Speed Z <9:2> |
296 * -----+----------+---------+---------+----+-----+
297 * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ |
298 * -----+----------+---------+---------+----+-----+
299 * Button X/Y is the analog stick. Speed X, Y and Z are the
300 * accelerometer data in the same format as the wiimote's accelerometer.
301 * The 6th byte contains the LSBs of the accelerometer data.
302 * BC and BZ are the C and Z buttons: 0 means pressed
303 *
304 * If reported interleaved with motionp, then the layout changes. The
305 * 5th and 6th byte changes to:
306 * -----+-----------------------------------+-----+
307 * 5 | Speed Z <9:3> | EXT |
308 * -----+--------+-----+-----+----+----+----+-----+
309 * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 |
310 * -----+--------+-----+-----+----+----+----+-----+
311 * All three accelerometer values lose their LSB. The other data is
312 * still available but slightly moved.
313 *
314 * Center data for button values is 128. Center value for accelerometer
315 * values it 512 / 0x200
316 */
317
318 bx = payload[0];
319 by = payload[1];
320 bx -= 128;
321 by -= 128;
322
323 x = payload[2] << 2;
324 y = payload[3] << 2;
325 z = payload[4] << 2;
326
327 if (ext->motionp) {
328 x |= (payload[5] >> 3) & 0x02;
329 y |= (payload[5] >> 4) & 0x02;
330 z &= ~0x4;
331 z |= (payload[5] >> 5) & 0x06;
332 } else {
333 x |= (payload[5] >> 2) & 0x03;
334 y |= (payload[5] >> 4) & 0x03;
335 z |= (payload[5] >> 6) & 0x03;
336 }
337
338 x -= 0x200;
339 y -= 0x200;
340 z -= 0x200;
341
342 input_report_abs(ext->input, ABS_HAT0X, bx);
343 input_report_abs(ext->input, ABS_HAT0Y, by);
344
345 input_report_abs(ext->input, ABS_RX, x);
346 input_report_abs(ext->input, ABS_RY, y);
347 input_report_abs(ext->input, ABS_RZ, z);
348
349 if (ext->motionp) {
350 input_report_key(ext->input,
351 wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04));
352 input_report_key(ext->input,
353 wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08));
354 } else {
355 input_report_key(ext->input,
356 wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01));
357 input_report_key(ext->input,
358 wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02));
359 }
360
361 input_sync(ext->input);
275} 362}
276 363
277static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) 364static void handler_classic(struct wiimote_ext *ext, const __u8 *payload)
@@ -383,7 +470,7 @@ int wiiext_init(struct wiimote_data *wdata)
383{ 470{
384 struct wiimote_ext *ext; 471 struct wiimote_ext *ext;
385 unsigned long flags; 472 unsigned long flags;
386 int ret; 473 int ret, i;
387 474
388 ext = kzalloc(sizeof(*ext), GFP_KERNEL); 475 ext = kzalloc(sizeof(*ext), GFP_KERNEL);
389 if (!ext) 476 if (!ext)
@@ -408,6 +495,22 @@ int wiiext_init(struct wiimote_data *wdata)
408 ext->input->id.version = wdata->hdev->version; 495 ext->input->id.version = wdata->hdev->version;
409 ext->input->name = WIIMOTE_NAME " Extension"; 496 ext->input->name = WIIMOTE_NAME " Extension";
410 497
498 set_bit(EV_KEY, ext->input->evbit);
499 for (i = 0; i < WIIEXT_KEY_COUNT; ++i)
500 set_bit(wiiext_keymap[i], ext->input->keybit);
501
502 set_bit(EV_ABS, ext->input->evbit);
503 set_bit(ABS_HAT0X, ext->input->absbit);
504 set_bit(ABS_HAT0Y, ext->input->absbit);
505 input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4);
506 input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4);
507 set_bit(ABS_RX, ext->input->absbit);
508 set_bit(ABS_RY, ext->input->absbit);
509 set_bit(ABS_RZ, ext->input->absbit);
510 input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4);
511 input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4);
512 input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4);
513
411 ret = input_register_device(ext->input); 514 ret = input_register_device(ext->input);
412 if (ret) { 515 if (ret) {
413 input_free_device(ext->input); 516 input_free_device(ext->input);