aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-wiimote.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index 4cdaaf6e0307..3a7dec0c9fe6 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -479,6 +479,50 @@ static void handler_accel(struct wiimote_data *wdata, const __u8 *payload)
479 input_sync(wdata->accel); 479 input_sync(wdata->accel);
480} 480}
481 481
482#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
483 ABS_HAT0X, ABS_HAT0Y)
484#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
485 ABS_HAT1X, ABS_HAT1Y)
486#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
487 ABS_HAT2X, ABS_HAT2Y)
488#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
489 ABS_HAT3X, ABS_HAT3Y)
490
491static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
492 bool packed, __u8 xid, __u8 yid)
493{
494 __u16 x, y;
495
496 if (!(wdata->state.flags & WIIPROTO_FLAGS_IR))
497 return;
498
499 /*
500 * Basic IR data is encoded into 3 bytes. The first two bytes are the
501 * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits
502 * of both.
503 * If data is packed, then the 3rd byte is put first and slightly
504 * reordered. This allows to interleave packed and non-packed data to
505 * have two IR sets in 5 bytes instead of 6.
506 * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev.
507 */
508
509 if (packed) {
510 x = ir[1] << 2;
511 y = ir[2] << 2;
512
513 x |= ir[0] & 0x3;
514 y |= (ir[0] >> 2) & 0x3;
515 } else {
516 x = ir[0] << 2;
517 y = ir[1] << 2;
518
519 x |= (ir[2] >> 4) & 0x3;
520 y |= (ir[2] >> 6) & 0x3;
521 }
522
523 input_report_abs(wdata->ir, xid, x);
524 input_report_abs(wdata->ir, yid, y);
525}
482 526
483static void handler_status(struct wiimote_data *wdata, const __u8 *payload) 527static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
484{ 528{
@@ -510,6 +554,21 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
510{ 554{
511 handler_keys(wdata, payload); 555 handler_keys(wdata, payload);
512 handler_accel(wdata, payload); 556 handler_accel(wdata, payload);
557 ir_to_input0(wdata, &payload[5], false);
558 ir_to_input1(wdata, &payload[8], false);
559 ir_to_input2(wdata, &payload[11], false);
560 ir_to_input3(wdata, &payload[14], false);
561 input_sync(wdata->ir);
562}
563
564static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
565{
566 handler_keys(wdata, payload);
567 ir_to_input0(wdata, &payload[2], false);
568 ir_to_input1(wdata, &payload[4], true);
569 ir_to_input2(wdata, &payload[7], false);
570 ir_to_input3(wdata, &payload[9], true);
571 input_sync(wdata->ir);
513} 572}
514 573
515static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) 574static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
@@ -522,6 +581,11 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
522{ 581{
523 handler_keys(wdata, payload); 582 handler_keys(wdata, payload);
524 handler_accel(wdata, payload); 583 handler_accel(wdata, payload);
584 ir_to_input0(wdata, &payload[5], false);
585 ir_to_input1(wdata, &payload[7], true);
586 ir_to_input2(wdata, &payload[10], false);
587 ir_to_input3(wdata, &payload[12], true);
588 input_sync(wdata->ir);
525} 589}
526 590
527static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) 591static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
@@ -531,6 +595,10 @@ static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
531 wdata->state.accel_split[0] = payload[2]; 595 wdata->state.accel_split[0] = payload[2];
532 wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20); 596 wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20);
533 wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80); 597 wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80);
598
599 ir_to_input0(wdata, &payload[3], false);
600 ir_to_input1(wdata, &payload[12], false);
601 input_sync(wdata->ir);
534} 602}
535 603
536static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) 604static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
@@ -548,6 +616,10 @@ static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
548 buf[3] = payload[2]; 616 buf[3] = payload[2];
549 buf[4] = wdata->state.accel_split[1]; 617 buf[4] = wdata->state.accel_split[1];
550 handler_accel(wdata, buf); 618 handler_accel(wdata, buf);
619
620 ir_to_input2(wdata, &payload[3], false);
621 ir_to_input3(wdata, &payload[12], false);
622 input_sync(wdata->ir);
551} 623}
552 624
553struct wiiproto_handler { 625struct wiiproto_handler {
@@ -563,6 +635,7 @@ static struct wiiproto_handler handlers[] = {
563 { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA }, 635 { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
564 { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI }, 636 { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
565 { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE }, 637 { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
638 { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
566 { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE }, 639 { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
567 { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 }, 640 { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
568 { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 }, 641 { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },