diff options
-rw-r--r-- | drivers/hid/hid-wiimote-core.c | 669 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 16 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.h | 49 |
3 files changed, 709 insertions, 25 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 1ea70c8a824d..836611e3e37e 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c | |||
@@ -179,17 +179,38 @@ void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |||
179 | * Check what peripherals of the wiimote are currently | 179 | * Check what peripherals of the wiimote are currently |
180 | * active and select a proper DRM that supports all of | 180 | * active and select a proper DRM that supports all of |
181 | * the requested data inputs. | 181 | * the requested data inputs. |
182 | * | ||
183 | * Not all combinations are actually supported. The following | ||
184 | * combinations work only with limitations: | ||
185 | * - IR cam in extended or full mode disables any data transmission | ||
186 | * of extension controllers. There is no DRM mode that supports | ||
187 | * extension bytes plus extended/full IR. | ||
188 | * - IR cam with accelerometer and extension *_EXT8 is not supported. | ||
189 | * However, all extensions that need *_EXT8 are devices that don't | ||
190 | * support IR cameras. Hence, this shouldn't happen under normal | ||
191 | * operation. | ||
192 | * - *_EXT16 is only supported in combination with buttons and | ||
193 | * accelerometer. No IR or similar can be active simultaneously. As | ||
194 | * above, all modules that require it are mutually exclusive with | ||
195 | * IR/etc. so this doesn't matter. | ||
182 | */ | 196 | */ |
183 | static __u8 select_drm(struct wiimote_data *wdata) | 197 | static __u8 select_drm(struct wiimote_data *wdata) |
184 | { | 198 | { |
185 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; | 199 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; |
186 | bool ext = wiiext_active(wdata); | 200 | bool ext; |
201 | |||
202 | ext = (wdata->state.flags & WIIPROTO_FLAG_EXT_USED) || | ||
203 | (wdata->state.flags & WIIPROTO_FLAG_MP_USED); | ||
187 | 204 | ||
188 | if (ir == WIIPROTO_FLAG_IR_BASIC) { | 205 | if (ir == WIIPROTO_FLAG_IR_BASIC) { |
189 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | 206 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { |
190 | return WIIPROTO_REQ_DRM_KAIE; | 207 | if (ext) |
191 | else | 208 | return WIIPROTO_REQ_DRM_KAIE; |
209 | else | ||
210 | return WIIPROTO_REQ_DRM_KAI; | ||
211 | } else { | ||
192 | return WIIPROTO_REQ_DRM_KIE; | 212 | return WIIPROTO_REQ_DRM_KIE; |
213 | } | ||
193 | } else if (ir == WIIPROTO_FLAG_IR_EXT) { | 214 | } else if (ir == WIIPROTO_FLAG_IR_EXT) { |
194 | return WIIPROTO_REQ_DRM_KAI; | 215 | return WIIPROTO_REQ_DRM_KAI; |
195 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { | 216 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { |
@@ -202,7 +223,7 @@ static __u8 select_drm(struct wiimote_data *wdata) | |||
202 | return WIIPROTO_REQ_DRM_KA; | 223 | return WIIPROTO_REQ_DRM_KA; |
203 | } else { | 224 | } else { |
204 | if (ext) | 225 | if (ext) |
205 | return WIIPROTO_REQ_DRM_KE; | 226 | return WIIPROTO_REQ_DRM_KEE; |
206 | else | 227 | else |
207 | return WIIPROTO_REQ_DRM_K; | 228 | return WIIPROTO_REQ_DRM_K; |
208 | } | 229 | } |
@@ -399,9 +420,8 @@ static int wiimote_cmd_init_ext(struct wiimote_data *wdata) | |||
399 | } | 420 | } |
400 | 421 | ||
401 | /* requires the cmd-mutex to be held */ | 422 | /* requires the cmd-mutex to be held */ |
402 | static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata) | 423 | static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem) |
403 | { | 424 | { |
404 | __u8 rmem[6]; | ||
405 | int ret; | 425 | int ret; |
406 | 426 | ||
407 | /* read extension ID */ | 427 | /* read extension ID */ |
@@ -409,6 +429,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata) | |||
409 | if (ret != 6) | 429 | if (ret != 6) |
410 | return WIIMOTE_EXT_NONE; | 430 | return WIIMOTE_EXT_NONE; |
411 | 431 | ||
432 | hid_dbg(wdata->hdev, "extension ID: %02x:%02x %02x:%02x %02x:%02x\n", | ||
433 | rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | ||
434 | |||
412 | if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && | 435 | if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && |
413 | rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) | 436 | rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) |
414 | return WIIMOTE_EXT_NONE; | 437 | return WIIMOTE_EXT_NONE; |
@@ -416,6 +439,92 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata) | |||
416 | return WIIMOTE_EXT_UNKNOWN; | 439 | return WIIMOTE_EXT_UNKNOWN; |
417 | } | 440 | } |
418 | 441 | ||
442 | /* requires the cmd-mutex to be held */ | ||
443 | static int wiimote_cmd_init_mp(struct wiimote_data *wdata) | ||
444 | { | ||
445 | __u8 wmem; | ||
446 | int ret; | ||
447 | |||
448 | /* initialize MP */ | ||
449 | wmem = 0x55; | ||
450 | ret = wiimote_cmd_write(wdata, 0xa600f0, &wmem, sizeof(wmem)); | ||
451 | if (ret) | ||
452 | return ret; | ||
453 | |||
454 | /* disable default encryption */ | ||
455 | wmem = 0x0; | ||
456 | ret = wiimote_cmd_write(wdata, 0xa600fb, &wmem, sizeof(wmem)); | ||
457 | if (ret) | ||
458 | return ret; | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | /* requires the cmd-mutex to be held */ | ||
464 | static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype) | ||
465 | { | ||
466 | __u8 wmem; | ||
467 | |||
468 | /* map MP with correct pass-through mode */ | ||
469 | switch (exttype) { | ||
470 | default: | ||
471 | wmem = 0x04; | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | return wiimote_cmd_write(wdata, 0xa600fe, &wmem, sizeof(wmem)); | ||
476 | } | ||
477 | |||
478 | /* requires the cmd-mutex to be held */ | ||
479 | static bool wiimote_cmd_read_mp(struct wiimote_data *wdata, __u8 *rmem) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | /* read motion plus ID */ | ||
484 | ret = wiimote_cmd_read(wdata, 0xa600fa, rmem, 6); | ||
485 | if (ret != 6) | ||
486 | return false; | ||
487 | |||
488 | hid_dbg(wdata->hdev, "motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", | ||
489 | rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | ||
490 | |||
491 | if (rmem[5] == 0x05) | ||
492 | return true; | ||
493 | |||
494 | hid_info(wdata->hdev, "unknown motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", | ||
495 | rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | ||
496 | |||
497 | return false; | ||
498 | } | ||
499 | |||
500 | /* requires the cmd-mutex to be held */ | ||
501 | static __u8 wiimote_cmd_read_mp_mapped(struct wiimote_data *wdata) | ||
502 | { | ||
503 | int ret; | ||
504 | __u8 rmem[6]; | ||
505 | |||
506 | /* read motion plus ID */ | ||
507 | ret = wiimote_cmd_read(wdata, 0xa400fa, rmem, 6); | ||
508 | if (ret != 6) | ||
509 | return WIIMOTE_MP_NONE; | ||
510 | |||
511 | hid_dbg(wdata->hdev, "mapped motion plus ID: %02x:%02x %02x:%02x %02x:%02x\n", | ||
512 | rmem[0], rmem[1], rmem[2], rmem[3], rmem[4], rmem[5]); | ||
513 | |||
514 | if (rmem[0] == 0xff && rmem[1] == 0xff && rmem[2] == 0xff && | ||
515 | rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) | ||
516 | return WIIMOTE_MP_NONE; | ||
517 | |||
518 | if (rmem[4] == 0x04 && rmem[5] == 0x05) | ||
519 | return WIIMOTE_MP_SINGLE; | ||
520 | else if (rmem[4] == 0x05 && rmem[5] == 0x05) | ||
521 | return WIIMOTE_MP_PASSTHROUGH_NUNCHUK; | ||
522 | else if (rmem[4] == 0x07 && rmem[5] == 0x05) | ||
523 | return WIIMOTE_MP_PASSTHROUGH_CLASSIC; | ||
524 | |||
525 | return WIIMOTE_MP_UNKNOWN; | ||
526 | } | ||
527 | |||
419 | /* device module handling */ | 528 | /* device module handling */ |
420 | 529 | ||
421 | static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { | 530 | static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = { |
@@ -561,6 +670,81 @@ static void wiimote_modules_unload(struct wiimote_data *wdata) | |||
561 | } | 670 | } |
562 | } | 671 | } |
563 | 672 | ||
673 | /* device extension handling */ | ||
674 | |||
675 | static void wiimote_ext_load(struct wiimote_data *wdata, unsigned int ext) | ||
676 | { | ||
677 | unsigned long flags; | ||
678 | const struct wiimod_ops *ops; | ||
679 | int ret; | ||
680 | |||
681 | ops = wiimod_ext_table[ext]; | ||
682 | |||
683 | if (ops->probe) { | ||
684 | ret = ops->probe(ops, wdata); | ||
685 | if (ret) | ||
686 | ext = WIIMOTE_EXT_UNKNOWN; | ||
687 | } | ||
688 | |||
689 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
690 | wdata->state.exttype = ext; | ||
691 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
692 | } | ||
693 | |||
694 | static void wiimote_ext_unload(struct wiimote_data *wdata) | ||
695 | { | ||
696 | unsigned long flags; | ||
697 | const struct wiimod_ops *ops; | ||
698 | |||
699 | ops = wiimod_ext_table[wdata->state.exttype]; | ||
700 | |||
701 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
702 | wdata->state.exttype = WIIMOTE_EXT_UNKNOWN; | ||
703 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | ||
704 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
705 | |||
706 | if (ops->remove) | ||
707 | ops->remove(ops, wdata); | ||
708 | } | ||
709 | |||
710 | static void wiimote_mp_load(struct wiimote_data *wdata) | ||
711 | { | ||
712 | unsigned long flags; | ||
713 | const struct wiimod_ops *ops; | ||
714 | int ret; | ||
715 | __u8 mode = 2; | ||
716 | |||
717 | ops = &wiimod_mp; | ||
718 | if (ops->probe) { | ||
719 | ret = ops->probe(ops, wdata); | ||
720 | if (ret) | ||
721 | mode = 1; | ||
722 | } | ||
723 | |||
724 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
725 | wdata->state.mp = mode; | ||
726 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
727 | } | ||
728 | |||
729 | static void wiimote_mp_unload(struct wiimote_data *wdata) | ||
730 | { | ||
731 | unsigned long flags; | ||
732 | const struct wiimod_ops *ops; | ||
733 | |||
734 | if (wdata->state.mp < 2) | ||
735 | return; | ||
736 | |||
737 | ops = &wiimod_mp; | ||
738 | |||
739 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
740 | wdata->state.mp = 0; | ||
741 | wdata->state.flags &= ~WIIPROTO_FLAG_MP_USED; | ||
742 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
743 | |||
744 | if (ops->remove) | ||
745 | ops->remove(ops, wdata); | ||
746 | } | ||
747 | |||
564 | /* device (re-)initialization and detection */ | 748 | /* device (re-)initialization and detection */ |
565 | 749 | ||
566 | static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = { | 750 | static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = { |
@@ -617,7 +801,7 @@ done: | |||
617 | 801 | ||
618 | static void wiimote_init_detect(struct wiimote_data *wdata) | 802 | static void wiimote_init_detect(struct wiimote_data *wdata) |
619 | { | 803 | { |
620 | __u8 exttype = WIIMOTE_EXT_NONE; | 804 | __u8 exttype = WIIMOTE_EXT_NONE, extdata[6]; |
621 | bool ext; | 805 | bool ext; |
622 | int ret; | 806 | int ret; |
623 | 807 | ||
@@ -641,11 +825,301 @@ static void wiimote_init_detect(struct wiimote_data *wdata) | |||
641 | goto out_release; | 825 | goto out_release; |
642 | 826 | ||
643 | wiimote_cmd_init_ext(wdata); | 827 | wiimote_cmd_init_ext(wdata); |
644 | exttype = wiimote_cmd_read_ext(wdata); | 828 | exttype = wiimote_cmd_read_ext(wdata, extdata); |
645 | 829 | ||
646 | out_release: | 830 | out_release: |
647 | wiimote_cmd_release(wdata); | 831 | wiimote_cmd_release(wdata); |
648 | wiimote_init_set_type(wdata, exttype); | 832 | wiimote_init_set_type(wdata, exttype); |
833 | /* schedule MP timer */ | ||
834 | mod_timer(&wdata->timer, jiffies + HZ * 4); | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * MP hotplug events are not generated by the wiimote. Therefore, we need | ||
839 | * polling to detect it. We use a 4s interval for polling MP registers. This | ||
840 | * seems reasonable considering applications can trigger it manually via | ||
841 | * sysfs requests. | ||
842 | */ | ||
843 | static void wiimote_init_poll_mp(struct wiimote_data *wdata) | ||
844 | { | ||
845 | bool mp; | ||
846 | __u8 mpdata[6]; | ||
847 | |||
848 | wiimote_cmd_acquire_noint(wdata); | ||
849 | wiimote_cmd_init_mp(wdata); | ||
850 | mp = wiimote_cmd_read_mp(wdata, mpdata); | ||
851 | wiimote_cmd_release(wdata); | ||
852 | |||
853 | /* load/unload MP module if it changed */ | ||
854 | if (mp) { | ||
855 | if (!wdata->state.mp) { | ||
856 | hid_info(wdata->hdev, "detected extension: Nintendo Wii Motion Plus\n"); | ||
857 | wiimote_mp_load(wdata); | ||
858 | } | ||
859 | } else if (wdata->state.mp) { | ||
860 | wiimote_mp_unload(wdata); | ||
861 | } | ||
862 | |||
863 | mod_timer(&wdata->timer, jiffies + HZ * 4); | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * Check whether the wiimote is in the expected state. The extension registers | ||
868 | * may change during hotplug and initialization so we might get hotplug events | ||
869 | * that we caused by remapping some memory. | ||
870 | * We use some heuristics here to check known states. If the wiimote is in the | ||
871 | * expected state, we can ignore the hotplug event. | ||
872 | * | ||
873 | * Returns "true" if the device is in expected state, "false" if we should | ||
874 | * redo hotplug handling and extension initialization. | ||
875 | */ | ||
876 | static bool wiimote_init_check(struct wiimote_data *wdata) | ||
877 | { | ||
878 | __u32 flags; | ||
879 | __u8 type, data[6]; | ||
880 | bool ret, poll_mp; | ||
881 | |||
882 | spin_lock_irq(&wdata->state.lock); | ||
883 | flags = wdata->state.flags; | ||
884 | spin_unlock_irq(&wdata->state.lock); | ||
885 | |||
886 | wiimote_cmd_acquire_noint(wdata); | ||
887 | |||
888 | /* If MP is used and active, but the extension is not, we expect: | ||
889 | * read_mp_mapped() == WIIMOTE_MP_SINGLE | ||
890 | * state.flags == !EXT_ACTIVE && !MP_PLUGGED && MP_ACTIVE | ||
891 | * We do not check EXT_PLUGGED because it might change during | ||
892 | * initialization of MP without extensions. | ||
893 | * - If MP is unplugged/replugged, read_mp_mapped() fails | ||
894 | * - If EXT is plugged, MP_PLUGGED will get set */ | ||
895 | if (wdata->state.exttype == WIIMOTE_EXT_NONE && | ||
896 | wdata->state.mp > 0 && (flags & WIIPROTO_FLAG_MP_USED)) { | ||
897 | type = wiimote_cmd_read_mp_mapped(wdata); | ||
898 | ret = type == WIIMOTE_MP_SINGLE; | ||
899 | |||
900 | spin_lock_irq(&wdata->state.lock); | ||
901 | ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | ||
902 | ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_MP_PLUGGED); | ||
903 | ret = ret && (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | ||
904 | spin_unlock_irq(&wdata->state.lock); | ||
905 | |||
906 | if (!ret) | ||
907 | hid_dbg(wdata->hdev, "state left: !EXT && MP\n"); | ||
908 | |||
909 | /* while MP is mapped, we get EXT_PLUGGED events */ | ||
910 | poll_mp = false; | ||
911 | |||
912 | goto out_release; | ||
913 | } | ||
914 | |||
915 | /* If MP is unused, but the extension port is used, we expect: | ||
916 | * read_ext == state.exttype | ||
917 | * state.flags == !MP_ACTIVE && EXT_ACTIVE | ||
918 | * - If MP is plugged/unplugged, our timer detects it | ||
919 | * - If EXT is unplugged/replugged, EXT_ACTIVE will become unset */ | ||
920 | if (!(flags & WIIPROTO_FLAG_MP_USED) && | ||
921 | wdata->state.exttype != WIIMOTE_EXT_NONE) { | ||
922 | type = wiimote_cmd_read_ext(wdata, data); | ||
923 | ret = type == wdata->state.exttype; | ||
924 | |||
925 | spin_lock_irq(&wdata->state.lock); | ||
926 | ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | ||
927 | ret = ret && (wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | ||
928 | spin_unlock_irq(&wdata->state.lock); | ||
929 | |||
930 | if (!ret) | ||
931 | hid_dbg(wdata->hdev, "state left: EXT && !MP\n"); | ||
932 | |||
933 | /* poll MP for hotplug events */ | ||
934 | poll_mp = true; | ||
935 | |||
936 | goto out_release; | ||
937 | } | ||
938 | |||
939 | /* If neither MP nor an extension are used, we expect: | ||
940 | * read_ext() == WIIMOTE_EXT_NONE | ||
941 | * state.flags == !MP_ACTIVE && !EXT_ACTIVE && !EXT_PLUGGED | ||
942 | * No need to perform any action in this case as everything is | ||
943 | * disabled already. | ||
944 | * - If MP is plugged/unplugged, our timer detects it | ||
945 | * - If EXT is plugged, EXT_PLUGGED will be set */ | ||
946 | if (!(flags & WIIPROTO_FLAG_MP_USED) && | ||
947 | wdata->state.exttype == WIIMOTE_EXT_NONE) { | ||
948 | type = wiimote_cmd_read_ext(wdata, data); | ||
949 | ret = type == wdata->state.exttype; | ||
950 | |||
951 | spin_lock_irq(&wdata->state.lock); | ||
952 | ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | ||
953 | ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | ||
954 | ret = ret && !(wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED); | ||
955 | spin_unlock_irq(&wdata->state.lock); | ||
956 | |||
957 | if (!ret) | ||
958 | hid_dbg(wdata->hdev, "state left: !EXT && !MP\n"); | ||
959 | |||
960 | /* poll MP for hotplug events */ | ||
961 | poll_mp = true; | ||
962 | |||
963 | goto out_release; | ||
964 | } | ||
965 | |||
966 | /* The trickiest part is if both EXT and MP are active. We cannot read | ||
967 | * the EXT ID, anymore, because MP is mapped over it. However, we use | ||
968 | * a handy trick here: | ||
969 | * - EXT_ACTIVE is unset whenever !MP_PLUGGED is sent | ||
970 | * MP_PLUGGED might be re-sent again before we are scheduled, but | ||
971 | * EXT_ACTIVE will stay unset. | ||
972 | * So it is enough to check for mp_mapped() and MP_ACTIVE and | ||
973 | * EXT_ACTIVE. EXT_PLUGGED is a sanity check. */ | ||
974 | if (wdata->state.exttype != WIIMOTE_EXT_NONE && | ||
975 | wdata->state.mp > 0 && (flags & WIIPROTO_FLAG_MP_USED)) { | ||
976 | type = wiimote_cmd_read_mp_mapped(wdata); | ||
977 | ret = type != WIIMOTE_MP_NONE; | ||
978 | ret = ret && type != WIIMOTE_MP_UNKNOWN; | ||
979 | ret = ret && type != WIIMOTE_MP_SINGLE; | ||
980 | |||
981 | spin_lock_irq(&wdata->state.lock); | ||
982 | ret = ret && (wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED); | ||
983 | ret = ret && (wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE); | ||
984 | ret = ret && (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE); | ||
985 | spin_unlock_irq(&wdata->state.lock); | ||
986 | |||
987 | if (!ret) | ||
988 | hid_dbg(wdata->hdev, "state left: EXT && MP\n"); | ||
989 | |||
990 | /* while MP is mapped, we get EXT_PLUGGED events */ | ||
991 | poll_mp = false; | ||
992 | |||
993 | goto out_release; | ||
994 | } | ||
995 | |||
996 | /* unknown state */ | ||
997 | ret = false; | ||
998 | |||
999 | out_release: | ||
1000 | wiimote_cmd_release(wdata); | ||
1001 | |||
1002 | /* only poll for MP if requested and if state didn't change */ | ||
1003 | if (ret && poll_mp) | ||
1004 | wiimote_init_poll_mp(wdata); | ||
1005 | |||
1006 | return ret; | ||
1007 | } | ||
1008 | |||
1009 | static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = { | ||
1010 | [WIIMOTE_EXT_NONE] = "None", | ||
1011 | [WIIMOTE_EXT_UNKNOWN] = "Unknown", | ||
1012 | }; | ||
1013 | |||
1014 | /* | ||
1015 | * Handle hotplug events | ||
1016 | * If we receive an hotplug event and the device-check failed, we deinitialize | ||
1017 | * the extension ports, re-read all extension IDs and set the device into | ||
1018 | * the desired state. This involves mapping MP into the main extension | ||
1019 | * registers, setting up extension passthrough modes and initializing the | ||
1020 | * requested extensions. | ||
1021 | */ | ||
1022 | static void wiimote_init_hotplug(struct wiimote_data *wdata) | ||
1023 | { | ||
1024 | __u8 exttype, extdata[6], mpdata[6]; | ||
1025 | __u32 flags; | ||
1026 | bool mp; | ||
1027 | |||
1028 | hid_dbg(wdata->hdev, "detect extensions..\n"); | ||
1029 | |||
1030 | wiimote_cmd_acquire_noint(wdata); | ||
1031 | |||
1032 | spin_lock_irq(&wdata->state.lock); | ||
1033 | |||
1034 | /* get state snapshot that we will then work on */ | ||
1035 | flags = wdata->state.flags; | ||
1036 | |||
1037 | /* disable event forwarding temporarily */ | ||
1038 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_ACTIVE; | ||
1039 | wdata->state.flags &= ~WIIPROTO_FLAG_MP_ACTIVE; | ||
1040 | |||
1041 | spin_unlock_irq(&wdata->state.lock); | ||
1042 | |||
1043 | /* init extension and MP (deactivates current extension or MP) */ | ||
1044 | wiimote_cmd_init_ext(wdata); | ||
1045 | wiimote_cmd_init_mp(wdata); | ||
1046 | mp = wiimote_cmd_read_mp(wdata, mpdata); | ||
1047 | exttype = wiimote_cmd_read_ext(wdata, extdata); | ||
1048 | |||
1049 | wiimote_cmd_release(wdata); | ||
1050 | |||
1051 | /* load/unload extension module if it changed */ | ||
1052 | if (exttype != wdata->state.exttype) { | ||
1053 | /* unload previous extension */ | ||
1054 | wiimote_ext_unload(wdata); | ||
1055 | |||
1056 | if (exttype == WIIMOTE_EXT_UNKNOWN) { | ||
1057 | hid_info(wdata->hdev, "cannot detect extension; %02x:%02x %02x:%02x %02x:%02x\n", | ||
1058 | extdata[0], extdata[1], extdata[2], | ||
1059 | extdata[3], extdata[4], extdata[5]); | ||
1060 | } else if (exttype == WIIMOTE_EXT_NONE) { | ||
1061 | spin_lock_irq(&wdata->state.lock); | ||
1062 | wdata->state.exttype = WIIMOTE_EXT_NONE; | ||
1063 | spin_unlock_irq(&wdata->state.lock); | ||
1064 | } else { | ||
1065 | hid_info(wdata->hdev, "detected extension: %s\n", | ||
1066 | wiimote_exttype_names[exttype]); | ||
1067 | /* try loading new extension */ | ||
1068 | wiimote_ext_load(wdata, exttype); | ||
1069 | } | ||
1070 | } | ||
1071 | |||
1072 | /* load/unload MP module if it changed */ | ||
1073 | if (mp) { | ||
1074 | if (!wdata->state.mp) { | ||
1075 | hid_info(wdata->hdev, "detected extension: Nintendo Wii Motion Plus\n"); | ||
1076 | wiimote_mp_load(wdata); | ||
1077 | } | ||
1078 | } else if (wdata->state.mp) { | ||
1079 | wiimote_mp_unload(wdata); | ||
1080 | } | ||
1081 | |||
1082 | /* if MP is not used, do not map or activate it */ | ||
1083 | if (!(flags & WIIPROTO_FLAG_MP_USED)) | ||
1084 | mp = false; | ||
1085 | |||
1086 | /* map MP into main extension registers if used */ | ||
1087 | if (mp) { | ||
1088 | wiimote_cmd_acquire_noint(wdata); | ||
1089 | wiimote_cmd_map_mp(wdata, exttype); | ||
1090 | wiimote_cmd_release(wdata); | ||
1091 | |||
1092 | /* delete MP hotplug timer */ | ||
1093 | del_timer_sync(&wdata->timer); | ||
1094 | } else { | ||
1095 | /* reschedule MP hotplug timer */ | ||
1096 | mod_timer(&wdata->timer, jiffies + HZ * 4); | ||
1097 | } | ||
1098 | |||
1099 | spin_lock_irq(&wdata->state.lock); | ||
1100 | |||
1101 | /* enable data forwarding again and set expected hotplug state */ | ||
1102 | if (mp) { | ||
1103 | wdata->state.flags |= WIIPROTO_FLAG_MP_ACTIVE; | ||
1104 | if (wdata->state.exttype == WIIMOTE_EXT_NONE) { | ||
1105 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | ||
1106 | wdata->state.flags &= ~WIIPROTO_FLAG_MP_PLUGGED; | ||
1107 | } else { | ||
1108 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | ||
1109 | wdata->state.flags |= WIIPROTO_FLAG_MP_PLUGGED; | ||
1110 | wdata->state.flags |= WIIPROTO_FLAG_EXT_ACTIVE; | ||
1111 | } | ||
1112 | } else if (wdata->state.exttype != WIIMOTE_EXT_NONE) { | ||
1113 | wdata->state.flags |= WIIPROTO_FLAG_EXT_ACTIVE; | ||
1114 | } | ||
1115 | |||
1116 | /* request status report for hotplug state updates */ | ||
1117 | wiiproto_req_status(wdata); | ||
1118 | |||
1119 | spin_unlock_irq(&wdata->state.lock); | ||
1120 | |||
1121 | hid_dbg(wdata->hdev, "detected extensions: MP: %d EXT: %d\n", | ||
1122 | wdata->state.mp, wdata->state.exttype); | ||
649 | } | 1123 | } |
650 | 1124 | ||
651 | static void wiimote_init_worker(struct work_struct *work) | 1125 | static void wiimote_init_worker(struct work_struct *work) |
@@ -655,6 +1129,30 @@ static void wiimote_init_worker(struct work_struct *work) | |||
655 | 1129 | ||
656 | if (wdata->state.devtype == WIIMOTE_DEV_PENDING) | 1130 | if (wdata->state.devtype == WIIMOTE_DEV_PENDING) |
657 | wiimote_init_detect(wdata); | 1131 | wiimote_init_detect(wdata); |
1132 | if (!wiimote_init_check(wdata)) | ||
1133 | wiimote_init_hotplug(wdata); | ||
1134 | } | ||
1135 | |||
1136 | void __wiimote_schedule(struct wiimote_data *wdata) | ||
1137 | { | ||
1138 | if (!(wdata->state.flags & WIIPROTO_FLAG_EXITING)) | ||
1139 | schedule_work(&wdata->init_worker); | ||
1140 | } | ||
1141 | |||
1142 | static void wiimote_schedule(struct wiimote_data *wdata) | ||
1143 | { | ||
1144 | unsigned long flags; | ||
1145 | |||
1146 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
1147 | __wiimote_schedule(wdata); | ||
1148 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
1149 | } | ||
1150 | |||
1151 | static void wiimote_init_timeout(unsigned long arg) | ||
1152 | { | ||
1153 | struct wiimote_data *wdata = (void*)arg; | ||
1154 | |||
1155 | wiimote_schedule(wdata); | ||
658 | } | 1156 | } |
659 | 1157 | ||
660 | /* protocol handlers */ | 1158 | /* protocol handlers */ |
@@ -664,6 +1162,12 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | |||
664 | const __u8 *iter, *mods; | 1162 | const __u8 *iter, *mods; |
665 | const struct wiimod_ops *ops; | 1163 | const struct wiimod_ops *ops; |
666 | 1164 | ||
1165 | ops = wiimod_ext_table[wdata->state.exttype]; | ||
1166 | if (ops->in_keys) { | ||
1167 | ops->in_keys(wdata, payload); | ||
1168 | return; | ||
1169 | } | ||
1170 | |||
667 | mods = wiimote_devtype_mods[wdata->state.devtype]; | 1171 | mods = wiimote_devtype_mods[wdata->state.devtype]; |
668 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | 1172 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { |
669 | ops = wiimod_table[*iter]; | 1173 | ops = wiimod_table[*iter]; |
@@ -679,6 +1183,12 @@ static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) | |||
679 | const __u8 *iter, *mods; | 1183 | const __u8 *iter, *mods; |
680 | const struct wiimod_ops *ops; | 1184 | const struct wiimod_ops *ops; |
681 | 1185 | ||
1186 | ops = wiimod_ext_table[wdata->state.exttype]; | ||
1187 | if (ops->in_accel) { | ||
1188 | ops->in_accel(wdata, payload); | ||
1189 | return; | ||
1190 | } | ||
1191 | |||
682 | mods = wiimote_devtype_mods[wdata->state.devtype]; | 1192 | mods = wiimote_devtype_mods[wdata->state.devtype]; |
683 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | 1193 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { |
684 | ops = wiimod_table[*iter]; | 1194 | ops = wiimod_table[*iter]; |
@@ -689,6 +1199,93 @@ static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) | |||
689 | } | 1199 | } |
690 | } | 1200 | } |
691 | 1201 | ||
1202 | static bool valid_ext_handler(const struct wiimod_ops *ops, size_t len) | ||
1203 | { | ||
1204 | if (!ops->in_ext) | ||
1205 | return false; | ||
1206 | if ((ops->flags & WIIMOD_FLAG_EXT8) && len < 8) | ||
1207 | return false; | ||
1208 | if ((ops->flags & WIIMOD_FLAG_EXT16) && len < 16) | ||
1209 | return false; | ||
1210 | |||
1211 | return true; | ||
1212 | } | ||
1213 | |||
1214 | static void handler_ext(struct wiimote_data *wdata, const __u8 *payload, | ||
1215 | size_t len) | ||
1216 | { | ||
1217 | const __u8 *iter, *mods; | ||
1218 | const struct wiimod_ops *ops; | ||
1219 | bool is_mp; | ||
1220 | |||
1221 | if (len < 6) | ||
1222 | return; | ||
1223 | |||
1224 | /* if MP is active, track MP slot hotplugging */ | ||
1225 | if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | ||
1226 | /* this bit is set for invalid events (eg. during hotplug) */ | ||
1227 | if (payload[5] & 0x01) | ||
1228 | return; | ||
1229 | |||
1230 | if (payload[4] & 0x01) { | ||
1231 | if (!(wdata->state.flags & WIIPROTO_FLAG_MP_PLUGGED)) { | ||
1232 | hid_dbg(wdata->hdev, "MP hotplug: 1\n"); | ||
1233 | wdata->state.flags |= WIIPROTO_FLAG_MP_PLUGGED; | ||
1234 | __wiimote_schedule(wdata); | ||
1235 | } | ||
1236 | } else { | ||
1237 | if (wdata->state.flags & WIIPROTO_FLAG_MP_PLUGGED) { | ||
1238 | hid_dbg(wdata->hdev, "MP hotplug: 0\n"); | ||
1239 | wdata->state.flags &= ~WIIPROTO_FLAG_MP_PLUGGED; | ||
1240 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_ACTIVE; | ||
1241 | __wiimote_schedule(wdata); | ||
1242 | } | ||
1243 | } | ||
1244 | |||
1245 | /* detect MP data that is sent interleaved with EXT data */ | ||
1246 | is_mp = payload[5] & 0x02; | ||
1247 | } else { | ||
1248 | is_mp = false; | ||
1249 | } | ||
1250 | |||
1251 | /* ignore EXT events if no extension is active */ | ||
1252 | if (!(wdata->state.flags & WIIPROTO_FLAG_EXT_ACTIVE) && !is_mp) | ||
1253 | return; | ||
1254 | |||
1255 | /* try forwarding to extension handler, first */ | ||
1256 | ops = wiimod_ext_table[wdata->state.exttype]; | ||
1257 | if (is_mp && ops->in_mp) { | ||
1258 | ops->in_mp(wdata, payload); | ||
1259 | return; | ||
1260 | } else if (!is_mp && valid_ext_handler(ops, len)) { | ||
1261 | ops->in_ext(wdata, payload); | ||
1262 | return; | ||
1263 | } | ||
1264 | |||
1265 | /* try forwarding to MP handler */ | ||
1266 | ops = &wiimod_mp; | ||
1267 | if (is_mp && ops->in_mp) { | ||
1268 | ops->in_mp(wdata, payload); | ||
1269 | return; | ||
1270 | } else if (!is_mp && valid_ext_handler(ops, len)) { | ||
1271 | ops->in_ext(wdata, payload); | ||
1272 | return; | ||
1273 | } | ||
1274 | |||
1275 | /* try forwarding to loaded modules */ | ||
1276 | mods = wiimote_devtype_mods[wdata->state.devtype]; | ||
1277 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | ||
1278 | ops = wiimod_table[*iter]; | ||
1279 | if (is_mp && ops->in_mp) { | ||
1280 | ops->in_mp(wdata, payload); | ||
1281 | return; | ||
1282 | } else if (!is_mp && valid_ext_handler(ops, len)) { | ||
1283 | ops->in_ext(wdata, payload); | ||
1284 | return; | ||
1285 | } | ||
1286 | } | ||
1287 | } | ||
1288 | |||
692 | #define ir_to_input0(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 0) | 1289 | #define ir_to_input0(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 0) |
693 | #define ir_to_input1(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 1) | 1290 | #define ir_to_input1(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 1) |
694 | #define ir_to_input2(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 2) | 1291 | #define ir_to_input2(wdata, ir, packed) handler_ir((wdata), (ir), (packed), 2) |
@@ -700,6 +1297,12 @@ static void handler_ir(struct wiimote_data *wdata, const __u8 *payload, | |||
700 | const __u8 *iter, *mods; | 1297 | const __u8 *iter, *mods; |
701 | const struct wiimod_ops *ops; | 1298 | const struct wiimod_ops *ops; |
702 | 1299 | ||
1300 | ops = wiimod_ext_table[wdata->state.exttype]; | ||
1301 | if (ops->in_ir) { | ||
1302 | ops->in_ir(wdata, payload, packed, id); | ||
1303 | return; | ||
1304 | } | ||
1305 | |||
703 | mods = wiimote_devtype_mods[wdata->state.devtype]; | 1306 | mods = wiimote_devtype_mods[wdata->state.devtype]; |
704 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { | 1307 | for (iter = mods; *iter != WIIMOD_NULL; ++iter) { |
705 | ops = wiimod_table[*iter]; | 1308 | ops = wiimod_table[*iter]; |
@@ -727,11 +1330,20 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |||
727 | 1330 | ||
728 | /* update extension status */ | 1331 | /* update extension status */ |
729 | if (payload[2] & 0x02) { | 1332 | if (payload[2] & 0x02) { |
730 | wdata->state.flags |= WIIPROTO_FLAG_EXT_PLUGGED; | 1333 | if (!(wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED)) { |
731 | wiiext_event(wdata, true); | 1334 | hid_dbg(wdata->hdev, "EXT hotplug: 1\n"); |
1335 | wdata->state.flags |= WIIPROTO_FLAG_EXT_PLUGGED; | ||
1336 | __wiimote_schedule(wdata); | ||
1337 | } | ||
732 | } else { | 1338 | } else { |
733 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | 1339 | if (wdata->state.flags & WIIPROTO_FLAG_EXT_PLUGGED) { |
734 | wiiext_event(wdata, false); | 1340 | hid_dbg(wdata->hdev, "EXT hotplug: 0\n"); |
1341 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_PLUGGED; | ||
1342 | wdata->state.flags &= ~WIIPROTO_FLAG_MP_PLUGGED; | ||
1343 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_ACTIVE; | ||
1344 | wdata->state.flags &= ~WIIPROTO_FLAG_MP_ACTIVE; | ||
1345 | __wiimote_schedule(wdata); | ||
1346 | } | ||
735 | } | 1347 | } |
736 | 1348 | ||
737 | wdata->state.cmd_battery = payload[5]; | 1349 | wdata->state.cmd_battery = payload[5]; |
@@ -791,7 +1403,7 @@ static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) | |||
791 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) | 1403 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) |
792 | { | 1404 | { |
793 | handler_keys(wdata, payload); | 1405 | handler_keys(wdata, payload); |
794 | wiiext_handle(wdata, &payload[2]); | 1406 | handler_ext(wdata, &payload[2], 8); |
795 | } | 1407 | } |
796 | 1408 | ||
797 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | 1409 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) |
@@ -807,7 +1419,7 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | |||
807 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) | 1419 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) |
808 | { | 1420 | { |
809 | handler_keys(wdata, payload); | 1421 | handler_keys(wdata, payload); |
810 | wiiext_handle(wdata, &payload[2]); | 1422 | handler_ext(wdata, &payload[2], 19); |
811 | } | 1423 | } |
812 | 1424 | ||
813 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | 1425 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) |
@@ -817,14 +1429,14 @@ static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | |||
817 | ir_to_input1(wdata, &payload[4], true); | 1429 | ir_to_input1(wdata, &payload[4], true); |
818 | ir_to_input2(wdata, &payload[7], false); | 1430 | ir_to_input2(wdata, &payload[7], false); |
819 | ir_to_input3(wdata, &payload[9], true); | 1431 | ir_to_input3(wdata, &payload[9], true); |
820 | wiiext_handle(wdata, &payload[12]); | 1432 | handler_ext(wdata, &payload[12], 9); |
821 | } | 1433 | } |
822 | 1434 | ||
823 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) | 1435 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) |
824 | { | 1436 | { |
825 | handler_keys(wdata, payload); | 1437 | handler_keys(wdata, payload); |
826 | handler_accel(wdata, payload); | 1438 | handler_accel(wdata, payload); |
827 | wiiext_handle(wdata, &payload[5]); | 1439 | handler_ext(wdata, &payload[5], 16); |
828 | } | 1440 | } |
829 | 1441 | ||
830 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | 1442 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) |
@@ -835,12 +1447,12 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | |||
835 | ir_to_input1(wdata, &payload[7], true); | 1447 | ir_to_input1(wdata, &payload[7], true); |
836 | ir_to_input2(wdata, &payload[10], false); | 1448 | ir_to_input2(wdata, &payload[10], false); |
837 | ir_to_input3(wdata, &payload[12], true); | 1449 | ir_to_input3(wdata, &payload[12], true); |
838 | wiiext_handle(wdata, &payload[15]); | 1450 | handler_ext(wdata, &payload[15], 6); |
839 | } | 1451 | } |
840 | 1452 | ||
841 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) | 1453 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) |
842 | { | 1454 | { |
843 | wiiext_handle(wdata, payload); | 1455 | handler_ext(wdata, payload, 21); |
844 | } | 1456 | } |
845 | 1457 | ||
846 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) | 1458 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) |
@@ -960,16 +1572,27 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
960 | wdata->state.cmd_battery = 0xff; | 1572 | wdata->state.cmd_battery = 0xff; |
961 | 1573 | ||
962 | INIT_WORK(&wdata->init_worker, wiimote_init_worker); | 1574 | INIT_WORK(&wdata->init_worker, wiimote_init_worker); |
1575 | setup_timer(&wdata->timer, wiimote_init_timeout, (long)wdata); | ||
963 | 1576 | ||
964 | return wdata; | 1577 | return wdata; |
965 | } | 1578 | } |
966 | 1579 | ||
967 | static void wiimote_destroy(struct wiimote_data *wdata) | 1580 | static void wiimote_destroy(struct wiimote_data *wdata) |
968 | { | 1581 | { |
1582 | unsigned long flags; | ||
1583 | |||
969 | wiidebug_deinit(wdata); | 1584 | wiidebug_deinit(wdata); |
970 | wiiext_deinit(wdata); | 1585 | |
1586 | /* prevent init_worker from being scheduled again */ | ||
1587 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
1588 | wdata->state.flags |= WIIPROTO_FLAG_EXITING; | ||
1589 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
971 | 1590 | ||
972 | cancel_work_sync(&wdata->init_worker); | 1591 | cancel_work_sync(&wdata->init_worker); |
1592 | del_timer_sync(&wdata->timer); | ||
1593 | |||
1594 | wiimote_mp_unload(wdata); | ||
1595 | wiimote_ext_unload(wdata); | ||
973 | wiimote_modules_unload(wdata); | 1596 | wiimote_modules_unload(wdata); |
974 | cancel_work_sync(&wdata->queue.worker); | 1597 | cancel_work_sync(&wdata->queue.worker); |
975 | hid_hw_close(wdata->hdev); | 1598 | hid_hw_close(wdata->hdev); |
@@ -1010,10 +1633,6 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1010 | goto err_stop; | 1633 | goto err_stop; |
1011 | } | 1634 | } |
1012 | 1635 | ||
1013 | ret = wiiext_init(wdata); | ||
1014 | if (ret) | ||
1015 | goto err_free; | ||
1016 | |||
1017 | ret = wiidebug_init(wdata); | 1636 | ret = wiidebug_init(wdata); |
1018 | if (ret) | 1637 | if (ret) |
1019 | goto err_free; | 1638 | goto err_free; |
@@ -1021,7 +1640,7 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
1021 | hid_info(hdev, "New device registered\n"); | 1640 | hid_info(hdev, "New device registered\n"); |
1022 | 1641 | ||
1023 | /* schedule device detection */ | 1642 | /* schedule device detection */ |
1024 | schedule_work(&wdata->init_worker); | 1643 | wiimote_schedule(wdata); |
1025 | 1644 | ||
1026 | return 0; | 1645 | return 0; |
1027 | 1646 | ||
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 5cc593a9c5a6..d3eef771b00b 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c | |||
@@ -788,8 +788,19 @@ static const struct wiimod_ops wiimod_ir = { | |||
788 | .in_ir = wiimod_ir_in_ir, | 788 | .in_ir = wiimod_ir_in_ir, |
789 | }; | 789 | }; |
790 | 790 | ||
791 | /* | ||
792 | * Motion Plus | ||
793 | */ | ||
794 | |||
795 | const struct wiimod_ops wiimod_mp = { | ||
796 | .flags = 0, | ||
797 | .arg = 0, | ||
798 | }; | ||
799 | |||
791 | /* module table */ | 800 | /* module table */ |
792 | 801 | ||
802 | static const struct wiimod_ops wiimod_dummy; | ||
803 | |||
793 | const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { | 804 | const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { |
794 | [WIIMOD_KEYS] = &wiimod_keys, | 805 | [WIIMOD_KEYS] = &wiimod_keys, |
795 | [WIIMOD_RUMBLE] = &wiimod_rumble, | 806 | [WIIMOD_RUMBLE] = &wiimod_rumble, |
@@ -801,3 +812,8 @@ const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { | |||
801 | [WIIMOD_ACCEL] = &wiimod_accel, | 812 | [WIIMOD_ACCEL] = &wiimod_accel, |
802 | [WIIMOD_IR] = &wiimod_ir, | 813 | [WIIMOD_IR] = &wiimod_ir, |
803 | }; | 814 | }; |
815 | |||
816 | const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = { | ||
817 | [WIIMOTE_EXT_NONE] = &wiimod_dummy, | ||
818 | [WIIMOTE_EXT_UNKNOWN] = &wiimod_dummy, | ||
819 | }; | ||
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 3a2d3a1d3d63..0afc9f9a9bd6 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/timer.h> | ||
25 | 26 | ||
26 | #define WIIMOTE_NAME "Nintendo Wii Remote" | 27 | #define WIIMOTE_NAME "Nintendo Wii Remote" |
27 | #define WIIMOTE_BUFSIZE 32 | 28 | #define WIIMOTE_BUFSIZE 32 |
@@ -36,6 +37,12 @@ | |||
36 | #define WIIPROTO_FLAG_IR_EXT 0x80 | 37 | #define WIIPROTO_FLAG_IR_EXT 0x80 |
37 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ | 38 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ |
38 | #define WIIPROTO_FLAG_EXT_PLUGGED 0x0100 | 39 | #define WIIPROTO_FLAG_EXT_PLUGGED 0x0100 |
40 | #define WIIPROTO_FLAG_EXT_USED 0x0200 | ||
41 | #define WIIPROTO_FLAG_EXT_ACTIVE 0x0400 | ||
42 | #define WIIPROTO_FLAG_MP_PLUGGED 0x0800 | ||
43 | #define WIIPROTO_FLAG_MP_USED 0x1000 | ||
44 | #define WIIPROTO_FLAG_MP_ACTIVE 0x2000 | ||
45 | #define WIIPROTO_FLAG_EXITING 0x4000 | ||
39 | 46 | ||
40 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | 47 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ |
41 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | 48 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) |
@@ -75,6 +82,14 @@ enum wiimote_exttype { | |||
75 | WIIMOTE_EXT_NUM, | 82 | WIIMOTE_EXT_NUM, |
76 | }; | 83 | }; |
77 | 84 | ||
85 | enum wiimote_mptype { | ||
86 | WIIMOTE_MP_NONE, | ||
87 | WIIMOTE_MP_UNKNOWN, | ||
88 | WIIMOTE_MP_SINGLE, | ||
89 | WIIMOTE_MP_PASSTHROUGH_NUNCHUK, | ||
90 | WIIMOTE_MP_PASSTHROUGH_CLASSIC, | ||
91 | }; | ||
92 | |||
78 | struct wiimote_buf { | 93 | struct wiimote_buf { |
79 | __u8 data[HID_MAX_BUFFER_SIZE]; | 94 | __u8 data[HID_MAX_BUFFER_SIZE]; |
80 | size_t size; | 95 | size_t size; |
@@ -94,6 +109,8 @@ struct wiimote_state { | |||
94 | __u8 accel_split[2]; | 109 | __u8 accel_split[2]; |
95 | __u8 drm; | 110 | __u8 drm; |
96 | __u8 devtype; | 111 | __u8 devtype; |
112 | __u8 exttype; | ||
113 | __u8 mp; | ||
97 | 114 | ||
98 | /* synchronous cmd requests */ | 115 | /* synchronous cmd requests */ |
99 | struct mutex sync; | 116 | struct mutex sync; |
@@ -115,6 +132,7 @@ struct wiimote_data { | |||
115 | struct input_dev *accel; | 132 | struct input_dev *accel; |
116 | struct input_dev *ir; | 133 | struct input_dev *ir; |
117 | struct power_supply battery; | 134 | struct power_supply battery; |
135 | struct timer_list timer; | ||
118 | struct wiimote_ext *ext; | 136 | struct wiimote_ext *ext; |
119 | struct wiimote_debug *debug; | 137 | struct wiimote_debug *debug; |
120 | 138 | ||
@@ -140,6 +158,8 @@ enum wiimod_module { | |||
140 | }; | 158 | }; |
141 | 159 | ||
142 | #define WIIMOD_FLAG_INPUT 0x0001 | 160 | #define WIIMOD_FLAG_INPUT 0x0001 |
161 | #define WIIMOD_FLAG_EXT8 0x0002 | ||
162 | #define WIIMOD_FLAG_EXT16 0x0004 | ||
143 | 163 | ||
144 | struct wiimod_ops { | 164 | struct wiimod_ops { |
145 | __u16 flags; | 165 | __u16 flags; |
@@ -153,9 +173,13 @@ struct wiimod_ops { | |||
153 | void (*in_accel) (struct wiimote_data *wdata, const __u8 *accel); | 173 | void (*in_accel) (struct wiimote_data *wdata, const __u8 *accel); |
154 | void (*in_ir) (struct wiimote_data *wdata, const __u8 *ir, bool packed, | 174 | void (*in_ir) (struct wiimote_data *wdata, const __u8 *ir, bool packed, |
155 | unsigned int id); | 175 | unsigned int id); |
176 | void (*in_mp) (struct wiimote_data *wdata, const __u8 *mp); | ||
177 | void (*in_ext) (struct wiimote_data *wdata, const __u8 *ext); | ||
156 | }; | 178 | }; |
157 | 179 | ||
158 | extern const struct wiimod_ops *wiimod_table[WIIMOD_NUM]; | 180 | extern const struct wiimod_ops *wiimod_table[WIIMOD_NUM]; |
181 | extern const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM]; | ||
182 | extern const struct wiimod_ops wiimod_mp; | ||
159 | 183 | ||
160 | /* wiimote requests */ | 184 | /* wiimote requests */ |
161 | 185 | ||
@@ -172,23 +196,48 @@ enum wiiproto_reqs { | |||
172 | WIIPROTO_REQ_STATUS = 0x20, | 196 | WIIPROTO_REQ_STATUS = 0x20, |
173 | WIIPROTO_REQ_DATA = 0x21, | 197 | WIIPROTO_REQ_DATA = 0x21, |
174 | WIIPROTO_REQ_RETURN = 0x22, | 198 | WIIPROTO_REQ_RETURN = 0x22, |
199 | |||
200 | /* DRM_K: BB*2 */ | ||
175 | WIIPROTO_REQ_DRM_K = 0x30, | 201 | WIIPROTO_REQ_DRM_K = 0x30, |
202 | |||
203 | /* DRM_KA: BB*2 AA*3 */ | ||
176 | WIIPROTO_REQ_DRM_KA = 0x31, | 204 | WIIPROTO_REQ_DRM_KA = 0x31, |
205 | |||
206 | /* DRM_KE: BB*2 EE*8 */ | ||
177 | WIIPROTO_REQ_DRM_KE = 0x32, | 207 | WIIPROTO_REQ_DRM_KE = 0x32, |
208 | |||
209 | /* DRM_KAI: BB*2 AA*3 II*12 */ | ||
178 | WIIPROTO_REQ_DRM_KAI = 0x33, | 210 | WIIPROTO_REQ_DRM_KAI = 0x33, |
211 | |||
212 | /* DRM_KEE: BB*2 EE*19 */ | ||
179 | WIIPROTO_REQ_DRM_KEE = 0x34, | 213 | WIIPROTO_REQ_DRM_KEE = 0x34, |
214 | |||
215 | /* DRM_KAE: BB*2 AA*3 EE*16 */ | ||
180 | WIIPROTO_REQ_DRM_KAE = 0x35, | 216 | WIIPROTO_REQ_DRM_KAE = 0x35, |
217 | |||
218 | /* DRM_KIE: BB*2 II*10 EE*9 */ | ||
181 | WIIPROTO_REQ_DRM_KIE = 0x36, | 219 | WIIPROTO_REQ_DRM_KIE = 0x36, |
220 | |||
221 | /* DRM_KAIE: BB*2 AA*3 II*10 EE*6 */ | ||
182 | WIIPROTO_REQ_DRM_KAIE = 0x37, | 222 | WIIPROTO_REQ_DRM_KAIE = 0x37, |
223 | |||
224 | /* DRM_E: EE*21 */ | ||
183 | WIIPROTO_REQ_DRM_E = 0x3d, | 225 | WIIPROTO_REQ_DRM_E = 0x3d, |
226 | |||
227 | /* DRM_SKAI1: BB*2 AA*1 II*18 */ | ||
184 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, | 228 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, |
229 | |||
230 | /* DRM_SKAI2: BB*2 AA*1 II*18 */ | ||
185 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, | 231 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, |
232 | |||
186 | WIIPROTO_REQ_MAX | 233 | WIIPROTO_REQ_MAX |
187 | }; | 234 | }; |
188 | 235 | ||
189 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ | 236 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ |
190 | dev)) | 237 | dev)) |
191 | 238 | ||
239 | void __wiimote_schedule(struct wiimote_data *wdata); | ||
240 | |||
192 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); | 241 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); |
193 | extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); | 242 | extern void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble); |
194 | extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); | 243 | extern void wiiproto_req_leds(struct wiimote_data *wdata, int leds); |