diff options
-rw-r--r-- | drivers/hid/hid-wiimote.c | 73 |
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 | |||
491 | static 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 | ||
483 | static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | 527 | static 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 | |||
564 | static 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 | ||
515 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) | 574 | static 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 | ||
527 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) | 591 | static 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 | ||
536 | static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) | 604 | static 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 | ||
553 | struct wiiproto_handler { | 625 | struct 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 }, |