aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-wiimote-core.c26
-rw-r--r--drivers/hid/hid-wiimote-modules.c211
-rw-r--r--drivers/hid/hid-wiimote.h9
3 files changed, 246 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 836611e3e37e..90ea5a2565d4 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -202,6 +202,14 @@ static __u8 select_drm(struct wiimote_data *wdata)
202 ext = (wdata->state.flags & WIIPROTO_FLAG_EXT_USED) || 202 ext = (wdata->state.flags & WIIPROTO_FLAG_EXT_USED) ||
203 (wdata->state.flags & WIIPROTO_FLAG_MP_USED); 203 (wdata->state.flags & WIIPROTO_FLAG_MP_USED);
204 204
205 /* some 3rd-party balance-boards are hard-coded to KEE, *sigh* */
206 if (wdata->state.devtype == WIIMOTE_DEV_BALANCE_BOARD) {
207 if (ext)
208 return WIIPROTO_REQ_DRM_KEE;
209 else
210 return WIIPROTO_REQ_DRM_K;
211 }
212
205 if (ir == WIIPROTO_FLAG_IR_BASIC) { 213 if (ir == WIIPROTO_FLAG_IR_BASIC) {
206 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { 214 if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) {
207 if (ext) 215 if (ext)
@@ -436,6 +444,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
436 rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff) 444 rmem[3] == 0xff && rmem[4] == 0xff && rmem[5] == 0xff)
437 return WIIMOTE_EXT_NONE; 445 return WIIMOTE_EXT_NONE;
438 446
447 if (rmem[4] == 0x04 && rmem[5] == 0x02)
448 return WIIMOTE_EXT_BALANCE_BOARD;
449
439 return WIIMOTE_EXT_UNKNOWN; 450 return WIIMOTE_EXT_UNKNOWN;
440} 451}
441 452
@@ -570,6 +581,11 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = {
570 WIIMOD_IR, 581 WIIMOD_IR,
571 WIIMOD_NULL, 582 WIIMOD_NULL,
572 }, 583 },
584 [WIIMOTE_DEV_BALANCE_BOARD] = (const __u8[]) {
585 WIIMOD_BATTERY,
586 WIIMOD_LED1,
587 WIIMOD_NULL,
588 },
573}; 589};
574 590
575static void wiimote_modules_load(struct wiimote_data *wdata, 591static void wiimote_modules_load(struct wiimote_data *wdata,
@@ -753,6 +769,7 @@ static const char *wiimote_devtype_names[WIIMOTE_DEV_NUM] = {
753 [WIIMOTE_DEV_GENERIC] = "Generic", 769 [WIIMOTE_DEV_GENERIC] = "Generic",
754 [WIIMOTE_DEV_GEN10] = "Nintendo Wii Remote (Gen 1)", 770 [WIIMOTE_DEV_GEN10] = "Nintendo Wii Remote (Gen 1)",
755 [WIIMOTE_DEV_GEN20] = "Nintendo Wii Remote Plus (Gen 2)", 771 [WIIMOTE_DEV_GEN20] = "Nintendo Wii Remote Plus (Gen 2)",
772 [WIIMOTE_DEV_BALANCE_BOARD] = "Nintendo Wii Balance Board",
756}; 773};
757 774
758/* Try to guess the device type based on all collected information. We 775/* Try to guess the device type based on all collected information. We
@@ -770,12 +787,20 @@ static void wiimote_init_set_type(struct wiimote_data *wdata,
770 product = wdata->hdev->product; 787 product = wdata->hdev->product;
771 name = wdata->hdev->name; 788 name = wdata->hdev->name;
772 789
790 if (exttype == WIIMOTE_EXT_BALANCE_BOARD) {
791 devtype = WIIMOTE_DEV_BALANCE_BOARD;
792 goto done;
793 }
794
773 if (!strcmp(name, "Nintendo RVL-CNT-01")) { 795 if (!strcmp(name, "Nintendo RVL-CNT-01")) {
774 devtype = WIIMOTE_DEV_GEN10; 796 devtype = WIIMOTE_DEV_GEN10;
775 goto done; 797 goto done;
776 } else if (!strcmp(name, "Nintendo RVL-CNT-01-TR")) { 798 } else if (!strcmp(name, "Nintendo RVL-CNT-01-TR")) {
777 devtype = WIIMOTE_DEV_GEN20; 799 devtype = WIIMOTE_DEV_GEN20;
778 goto done; 800 goto done;
801 } else if (!strcmp(name, "Nintendo RVL-WBC-01")) {
802 devtype = WIIMOTE_DEV_BALANCE_BOARD;
803 goto done;
779 } 804 }
780 805
781 if (vendor == USB_VENDOR_ID_NINTENDO) { 806 if (vendor == USB_VENDOR_ID_NINTENDO) {
@@ -1009,6 +1034,7 @@ out_release:
1009static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = { 1034static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
1010 [WIIMOTE_EXT_NONE] = "None", 1035 [WIIMOTE_EXT_NONE] = "None",
1011 [WIIMOTE_EXT_UNKNOWN] = "Unknown", 1036 [WIIMOTE_EXT_UNKNOWN] = "Unknown",
1037 [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
1012}; 1038};
1013 1039
1014/* 1040/*
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index d3eef771b00b..6239cd87f1ed 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -789,6 +789,216 @@ static const struct wiimod_ops wiimod_ir = {
789}; 789};
790 790
791/* 791/*
792 * Balance Board Extension
793 * The Nintendo Wii Balance Board provides four hardware weight sensor plus a
794 * single push button. No other peripherals are available. However, the
795 * balance-board data is sent via a standard Wii Remote extension. All other
796 * data for non-present hardware is zeroed out.
797 * Some 3rd party devices react allergic if we try to access normal Wii Remote
798 * hardware, so this extension module should be the only module that is loaded
799 * on balance boards.
800 * The balance board needs 8 bytes extension data instead of basic 6 bytes so
801 * it needs the WIIMOD_FLAG_EXT8 flag.
802 */
803
804static void wiimod_bboard_in_keys(struct wiimote_data *wdata, const __u8 *keys)
805{
806 input_report_key(wdata->extension.input, BTN_A,
807 !!(keys[1] & 0x08));
808 input_sync(wdata->extension.input);
809}
810
811static void wiimod_bboard_in_ext(struct wiimote_data *wdata,
812 const __u8 *ext)
813{
814 __s32 val[4], tmp, div;
815 unsigned int i;
816 struct wiimote_state *s = &wdata->state;
817
818 /*
819 * Balance board data layout:
820 *
821 * Byte | 8 7 6 5 4 3 2 1 |
822 * -----+--------------------------+
823 * 1 | Top Right <15:8> |
824 * 2 | Top Right <7:0> |
825 * -----+--------------------------+
826 * 3 | Bottom Right <15:8> |
827 * 4 | Bottom Right <7:0> |
828 * -----+--------------------------+
829 * 5 | Top Left <15:8> |
830 * 6 | Top Left <7:0> |
831 * -----+--------------------------+
832 * 7 | Bottom Left <15:8> |
833 * 8 | Bottom Left <7:0> |
834 * -----+--------------------------+
835 *
836 * These values represent the weight-measurements of the Wii-balance
837 * board with 16bit precision.
838 *
839 * The balance-board is never reported interleaved with motionp.
840 */
841
842 val[0] = ext[0];
843 val[0] <<= 8;
844 val[0] |= ext[1];
845
846 val[1] = ext[2];
847 val[1] <<= 8;
848 val[1] |= ext[3];
849
850 val[2] = ext[4];
851 val[2] <<= 8;
852 val[2] |= ext[5];
853
854 val[3] = ext[6];
855 val[3] <<= 8;
856 val[3] |= ext[7];
857
858 /* apply calibration data */
859 for (i = 0; i < 4; i++) {
860 if (val[i] <= s->calib_bboard[i][0]) {
861 tmp = 0;
862 } else if (val[i] < s->calib_bboard[i][1]) {
863 tmp = val[i] - s->calib_bboard[i][0];
864 tmp *= 1700;
865 div = s->calib_bboard[i][1] - s->calib_bboard[i][0];
866 tmp /= div ? div : 1;
867 } else {
868 tmp = val[i] - s->calib_bboard[i][1];
869 tmp *= 1700;
870 div = s->calib_bboard[i][2] - s->calib_bboard[i][1];
871 tmp /= div ? div : 1;
872 tmp += 1700;
873 }
874 val[i] = tmp;
875 }
876
877 input_report_abs(wdata->extension.input, ABS_HAT0X, val[0]);
878 input_report_abs(wdata->extension.input, ABS_HAT0Y, val[1]);
879 input_report_abs(wdata->extension.input, ABS_HAT1X, val[2]);
880 input_report_abs(wdata->extension.input, ABS_HAT1Y, val[3]);
881 input_sync(wdata->extension.input);
882}
883
884static int wiimod_bboard_open(struct input_dev *dev)
885{
886 struct wiimote_data *wdata = input_get_drvdata(dev);
887 unsigned long flags;
888
889 spin_lock_irqsave(&wdata->state.lock, flags);
890 wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
891 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
892 spin_unlock_irqrestore(&wdata->state.lock, flags);
893
894 return 0;
895}
896
897static void wiimod_bboard_close(struct input_dev *dev)
898{
899 struct wiimote_data *wdata = input_get_drvdata(dev);
900 unsigned long flags;
901
902 spin_lock_irqsave(&wdata->state.lock, flags);
903 wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
904 wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
905 spin_unlock_irqrestore(&wdata->state.lock, flags);
906}
907
908static int wiimod_bboard_probe(const struct wiimod_ops *ops,
909 struct wiimote_data *wdata)
910{
911 int ret, i, j;
912 __u8 buf[24], offs;
913
914 wiimote_cmd_acquire_noint(wdata);
915
916 ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12);
917 if (ret != 12) {
918 wiimote_cmd_release(wdata);
919 return ret < 0 ? ret : -EIO;
920 }
921 ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12);
922 if (ret != 12) {
923 wiimote_cmd_release(wdata);
924 return ret < 0 ? ret : -EIO;
925 }
926
927 wiimote_cmd_release(wdata);
928
929 offs = 0;
930 for (i = 0; i < 3; ++i) {
931 for (j = 0; j < 4; ++j) {
932 wdata->state.calib_bboard[j][i] = buf[offs];
933 wdata->state.calib_bboard[j][i] <<= 8;
934 wdata->state.calib_bboard[j][i] |= buf[offs + 1];
935 offs += 2;
936 }
937 }
938
939 wdata->extension.input = input_allocate_device();
940 if (!wdata->extension.input)
941 return -ENOMEM;
942
943 input_set_drvdata(wdata->extension.input, wdata);
944 wdata->extension.input->open = wiimod_bboard_open;
945 wdata->extension.input->close = wiimod_bboard_close;
946 wdata->extension.input->dev.parent = &wdata->hdev->dev;
947 wdata->extension.input->id.bustype = wdata->hdev->bus;
948 wdata->extension.input->id.vendor = wdata->hdev->vendor;
949 wdata->extension.input->id.product = wdata->hdev->product;
950 wdata->extension.input->id.version = wdata->hdev->version;
951 wdata->extension.input->name = WIIMOTE_NAME " Balance Board";
952
953 set_bit(EV_KEY, wdata->extension.input->evbit);
954 set_bit(BTN_A, wdata->extension.input->keybit);
955
956 set_bit(EV_ABS, wdata->extension.input->evbit);
957 set_bit(ABS_HAT0X, wdata->extension.input->absbit);
958 set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
959 set_bit(ABS_HAT1X, wdata->extension.input->absbit);
960 set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
961 input_set_abs_params(wdata->extension.input,
962 ABS_HAT0X, 0, 65535, 2, 4);
963 input_set_abs_params(wdata->extension.input,
964 ABS_HAT0Y, 0, 65535, 2, 4);
965 input_set_abs_params(wdata->extension.input,
966 ABS_HAT1X, 0, 65535, 2, 4);
967 input_set_abs_params(wdata->extension.input,
968 ABS_HAT1Y, 0, 65535, 2, 4);
969
970 ret = input_register_device(wdata->extension.input);
971 if (ret)
972 goto err_free;
973
974 return 0;
975
976err_free:
977 input_free_device(wdata->extension.input);
978 wdata->extension.input = NULL;
979 return ret;
980}
981
982static void wiimod_bboard_remove(const struct wiimod_ops *ops,
983 struct wiimote_data *wdata)
984{
985 if (!wdata->extension.input)
986 return;
987
988 input_unregister_device(wdata->extension.input);
989 wdata->extension.input = NULL;
990}
991
992static const struct wiimod_ops wiimod_bboard = {
993 .flags = WIIMOD_FLAG_EXT8,
994 .arg = 0,
995 .probe = wiimod_bboard_probe,
996 .remove = wiimod_bboard_remove,
997 .in_keys = wiimod_bboard_in_keys,
998 .in_ext = wiimod_bboard_in_ext,
999};
1000
1001/*
792 * Motion Plus 1002 * Motion Plus
793 */ 1003 */
794 1004
@@ -816,4 +1026,5 @@ const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = {
816const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = { 1026const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
817 [WIIMOTE_EXT_NONE] = &wiimod_dummy, 1027 [WIIMOTE_EXT_NONE] = &wiimod_dummy,
818 [WIIMOTE_EXT_UNKNOWN] = &wiimod_dummy, 1028 [WIIMOTE_EXT_UNKNOWN] = &wiimod_dummy,
1029 [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
819}; 1030};
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 0afc9f9a9bd6..8d314ae429b6 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -73,12 +73,14 @@ enum wiimote_devtype {
73 WIIMOTE_DEV_GENERIC, 73 WIIMOTE_DEV_GENERIC,
74 WIIMOTE_DEV_GEN10, 74 WIIMOTE_DEV_GEN10,
75 WIIMOTE_DEV_GEN20, 75 WIIMOTE_DEV_GEN20,
76 WIIMOTE_DEV_BALANCE_BOARD,
76 WIIMOTE_DEV_NUM, 77 WIIMOTE_DEV_NUM,
77}; 78};
78 79
79enum wiimote_exttype { 80enum wiimote_exttype {
80 WIIMOTE_EXT_NONE, 81 WIIMOTE_EXT_NONE,
81 WIIMOTE_EXT_UNKNOWN, 82 WIIMOTE_EXT_UNKNOWN,
83 WIIMOTE_EXT_BALANCE_BOARD,
82 WIIMOTE_EXT_NUM, 84 WIIMOTE_EXT_NUM,
83}; 85};
84 86
@@ -123,6 +125,9 @@ struct wiimote_state {
123 __u8 cmd_err; 125 __u8 cmd_err;
124 __u8 *cmd_read_buf; 126 __u8 *cmd_read_buf;
125 __u8 cmd_read_size; 127 __u8 cmd_read_size;
128
129 /* calibration data */
130 __u16 calib_bboard[4][3];
126}; 131};
127 132
128struct wiimote_data { 133struct wiimote_data {
@@ -136,6 +141,10 @@ struct wiimote_data {
136 struct wiimote_ext *ext; 141 struct wiimote_ext *ext;
137 struct wiimote_debug *debug; 142 struct wiimote_debug *debug;
138 143
144 union {
145 struct input_dev *input;
146 } extension;
147
139 struct wiimote_queue queue; 148 struct wiimote_queue queue;
140 struct wiimote_state state; 149 struct wiimote_state state;
141 struct work_struct init_worker; 150 struct work_struct init_worker;