diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2011-11-17 08:12:09 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-22 17:10:10 -0500 |
commit | 5906215bab9fccf7aa2c4305accf0716c4634d69 (patch) | |
tree | e5646569126c01d256582f91d4b29fbdebd867d9 | |
parent | a53535014b7af750df3d8eda471dce21b2aa339c (diff) |
HID: wiimote: Parse classic controller data
Nintendo Classic Controller extension reports lots of keys, two analog sticks
and two analog buttons. We report all data through extension input device to
userspace.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-wiimote-ext.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index f05f1549d943..aa958706c0e5 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c | |||
@@ -39,12 +39,42 @@ enum wiiext_type { | |||
39 | enum wiiext_keys { | 39 | enum wiiext_keys { |
40 | WIIEXT_KEY_C, | 40 | WIIEXT_KEY_C, |
41 | WIIEXT_KEY_Z, | 41 | WIIEXT_KEY_Z, |
42 | WIIEXT_KEY_A, | ||
43 | WIIEXT_KEY_B, | ||
44 | WIIEXT_KEY_X, | ||
45 | WIIEXT_KEY_Y, | ||
46 | WIIEXT_KEY_ZL, | ||
47 | WIIEXT_KEY_ZR, | ||
48 | WIIEXT_KEY_PLUS, | ||
49 | WIIEXT_KEY_MINUS, | ||
50 | WIIEXT_KEY_HOME, | ||
51 | WIIEXT_KEY_LEFT, | ||
52 | WIIEXT_KEY_RIGHT, | ||
53 | WIIEXT_KEY_UP, | ||
54 | WIIEXT_KEY_DOWN, | ||
55 | WIIEXT_KEY_LT, | ||
56 | WIIEXT_KEY_RT, | ||
42 | WIIEXT_KEY_COUNT | 57 | WIIEXT_KEY_COUNT |
43 | }; | 58 | }; |
44 | 59 | ||
45 | static __u16 wiiext_keymap[] = { | 60 | static __u16 wiiext_keymap[] = { |
46 | BTN_C, /* WIIEXT_KEY_C */ | 61 | BTN_C, /* WIIEXT_KEY_C */ |
47 | BTN_Z, /* WIIEXT_KEY_Z */ | 62 | BTN_Z, /* WIIEXT_KEY_Z */ |
63 | BTN_A, /* WIIEXT_KEY_A */ | ||
64 | BTN_B, /* WIIEXT_KEY_B */ | ||
65 | BTN_X, /* WIIEXT_KEY_X */ | ||
66 | BTN_Y, /* WIIEXT_KEY_Y */ | ||
67 | BTN_TL2, /* WIIEXT_KEY_ZL */ | ||
68 | BTN_TR2, /* WIIEXT_KEY_ZR */ | ||
69 | KEY_NEXT, /* WIIEXT_KEY_PLUS */ | ||
70 | KEY_PREVIOUS, /* WIIEXT_KEY_MINUS */ | ||
71 | BTN_MODE, /* WIIEXT_KEY_HOME */ | ||
72 | KEY_LEFT, /* WIIEXT_KEY_LEFT */ | ||
73 | KEY_RIGHT, /* WIIEXT_KEY_RIGHT */ | ||
74 | KEY_UP, /* WIIEXT_KEY_UP */ | ||
75 | KEY_DOWN, /* WIIEXT_KEY_DOWN */ | ||
76 | BTN_TL, /* WIIEXT_KEY_LT */ | ||
77 | BTN_TR, /* WIIEXT_KEY_RT */ | ||
48 | }; | 78 | }; |
49 | 79 | ||
50 | /* diable all extensions */ | 80 | /* diable all extensions */ |
@@ -363,6 +393,120 @@ static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) | |||
363 | 393 | ||
364 | static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) | 394 | static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) |
365 | { | 395 | { |
396 | __s8 rx, ry, lx, ly, lt, rt; | ||
397 | |||
398 | /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
399 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
400 | * 1 | RX <5:4> | LX <5:0> | | ||
401 | * 2 | RX <3:2> | LY <5:0> | | ||
402 | * -----+-----+-----+-----+-----------------------------+ | ||
403 | * 3 |RX<1>| LT <5:4> | RY <5:1> | | ||
404 | * -----+-----+-----------+-----------------------------+ | ||
405 | * 4 | LT <3:1> | RT <5:1> | | ||
406 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
407 | * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | | ||
408 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
409 | * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | | ||
410 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
411 | * All buttons are 0 if pressed | ||
412 | * RX and RY are right analog stick | ||
413 | * LX and LY are left analog stick | ||
414 | * LT is left trigger, RT is right trigger | ||
415 | * BLT is 0 if left trigger is fully pressed | ||
416 | * BRT is 0 if right trigger is fully pressed | ||
417 | * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons | ||
418 | * BZL is left Z button and BZR is right Z button | ||
419 | * B-, BH, B+ are +, HOME and - buttons | ||
420 | * BB, BY, BA, BX are A, B, X, Y buttons | ||
421 | * LSB of RX, RY, LT, and RT are not transmitted and always 0. | ||
422 | * | ||
423 | * With motionp enabled it changes slightly to this: | ||
424 | * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
425 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
426 | * 1 | RX <4:3> | LX <5:1> | BDU | | ||
427 | * 2 | RX <2:1> | LY <5:1> | BDL | | ||
428 | * -----+-----+-----+-----+-----------------------+-----+ | ||
429 | * 3 |RX<0>| LT <4:3> | RY <4:0> | | ||
430 | * -----+-----+-----------+-----------------------------+ | ||
431 | * 4 | LT <2:0> | RT <4:0> | | ||
432 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
433 | * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT | | ||
434 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
435 | * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 | | ||
436 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
437 | * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest | ||
438 | * is the same as before. | ||
439 | */ | ||
440 | |||
441 | if (ext->motionp) { | ||
442 | lx = payload[0] & 0x3e; | ||
443 | ly = payload[0] & 0x3e; | ||
444 | } else { | ||
445 | lx = payload[0] & 0x3f; | ||
446 | ly = payload[0] & 0x3f; | ||
447 | } | ||
448 | |||
449 | rx = (payload[0] >> 3) & 0x14; | ||
450 | rx |= (payload[1] >> 5) & 0x06; | ||
451 | rx |= (payload[2] >> 7) & 0x01; | ||
452 | ry = payload[2] & 0x1f; | ||
453 | |||
454 | rt = payload[3] & 0x1f; | ||
455 | lt = (payload[2] >> 2) & 0x18; | ||
456 | lt |= (payload[3] >> 5) & 0x07; | ||
457 | |||
458 | rx <<= 1; | ||
459 | ry <<= 1; | ||
460 | rt <<= 1; | ||
461 | lt <<= 1; | ||
462 | |||
463 | input_report_abs(ext->input, ABS_HAT1X, lx - 0x20); | ||
464 | input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20); | ||
465 | input_report_abs(ext->input, ABS_HAT2X, rx - 0x20); | ||
466 | input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20); | ||
467 | input_report_abs(ext->input, ABS_HAT3X, rt - 0x20); | ||
468 | input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20); | ||
469 | |||
470 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT], | ||
471 | !!(payload[4] & 0x80)); | ||
472 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN], | ||
473 | !!(payload[4] & 0x40)); | ||
474 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT], | ||
475 | !!(payload[4] & 0x20)); | ||
476 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS], | ||
477 | !!(payload[4] & 0x10)); | ||
478 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME], | ||
479 | !!(payload[4] & 0x08)); | ||
480 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS], | ||
481 | !!(payload[4] & 0x04)); | ||
482 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT], | ||
483 | !!(payload[4] & 0x02)); | ||
484 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL], | ||
485 | !!(payload[5] & 0x80)); | ||
486 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B], | ||
487 | !!(payload[5] & 0x40)); | ||
488 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y], | ||
489 | !!(payload[5] & 0x20)); | ||
490 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A], | ||
491 | !!(payload[5] & 0x10)); | ||
492 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X], | ||
493 | !!(payload[5] & 0x08)); | ||
494 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR], | ||
495 | !!(payload[5] & 0x04)); | ||
496 | |||
497 | if (ext->motionp) { | ||
498 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | ||
499 | !!(payload[0] & 0x01)); | ||
500 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | ||
501 | !!(payload[1] & 0x01)); | ||
502 | } else { | ||
503 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | ||
504 | !!(payload[5] & 0x01)); | ||
505 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | ||
506 | !!(payload[5] & 0x02)); | ||
507 | } | ||
508 | |||
509 | input_sync(ext->input); | ||
366 | } | 510 | } |
367 | 511 | ||
368 | /* call this with state.lock spinlock held */ | 512 | /* call this with state.lock spinlock held */ |
@@ -502,8 +646,20 @@ int wiiext_init(struct wiimote_data *wdata) | |||
502 | set_bit(EV_ABS, ext->input->evbit); | 646 | set_bit(EV_ABS, ext->input->evbit); |
503 | set_bit(ABS_HAT0X, ext->input->absbit); | 647 | set_bit(ABS_HAT0X, ext->input->absbit); |
504 | set_bit(ABS_HAT0Y, ext->input->absbit); | 648 | set_bit(ABS_HAT0Y, ext->input->absbit); |
649 | set_bit(ABS_HAT1X, ext->input->absbit); | ||
650 | set_bit(ABS_HAT1Y, ext->input->absbit); | ||
651 | set_bit(ABS_HAT2X, ext->input->absbit); | ||
652 | set_bit(ABS_HAT2Y, ext->input->absbit); | ||
653 | set_bit(ABS_HAT3X, ext->input->absbit); | ||
654 | set_bit(ABS_HAT3Y, ext->input->absbit); | ||
505 | input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4); | 655 | 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); | 656 | input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4); |
657 | input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1); | ||
658 | input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1); | ||
659 | input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1); | ||
660 | input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1); | ||
661 | input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1); | ||
662 | input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1); | ||
507 | set_bit(ABS_RX, ext->input->absbit); | 663 | set_bit(ABS_RX, ext->input->absbit); |
508 | set_bit(ABS_RY, ext->input->absbit); | 664 | set_bit(ABS_RY, ext->input->absbit); |
509 | set_bit(ABS_RZ, ext->input->absbit); | 665 | set_bit(ABS_RZ, ext->input->absbit); |