diff options
| author | Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com> | 2018-06-20 06:55:15 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2018-06-25 09:26:06 -0400 |
| commit | d4bdf2d2ba737c2c02ec014bdc2db40a030595d0 (patch) | |
| tree | d18fa5634b270af13f021472874c55f37bd42f19 /drivers/hid | |
| parent | fdea70d26a471e002f2afc3a48821323b699f1e6 (diff) | |
HID: wiimote: add support for Guitar-Hero devices
This adds the drums and guitar extensions for Wiimote devices.
Devices are reported as "Nintendo Wii Remote Guitar/Drums". If I ever
get my hands on "RockBand" guitars, I will try to report them via the
same interface so user-space does not have to bother which device it
deals with.
This is a rebase of the original commits 8e22ecb603c8 and 73f8645db191.
They were reverted several years ago, since they were dependent on the
ABS_* rework of the input core. Sadly, this never worked out so these
commits were never pushed into a release. This rebase now uses the
ABS_HAT* event codes to report all pressure information.
Signed-off-by: Nicolas.Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
(Original commits by Nicolas, adapted to v4.18 by David)
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
| -rw-r--r-- | drivers/hid/hid-wiimote-core.c | 14 | ||||
| -rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 440 | ||||
| -rw-r--r-- | drivers/hid/hid-wiimote.h | 3 |
3 files changed, 457 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 579884ebd94d..7780da4fe897 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c | |||
| @@ -455,6 +455,12 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem) | |||
| 455 | return WIIMOTE_EXT_BALANCE_BOARD; | 455 | return WIIMOTE_EXT_BALANCE_BOARD; |
| 456 | if (rmem[4] == 0x01 && rmem[5] == 0x20) | 456 | if (rmem[4] == 0x01 && rmem[5] == 0x20) |
| 457 | return WIIMOTE_EXT_PRO_CONTROLLER; | 457 | return WIIMOTE_EXT_PRO_CONTROLLER; |
| 458 | if (rmem[0] == 0x01 && rmem[1] == 0x00 && | ||
| 459 | rmem[4] == 0x01 && rmem[5] == 0x03) | ||
| 460 | return WIIMOTE_EXT_DRUMS; | ||
| 461 | if (rmem[0] == 0x00 && rmem[1] == 0x00 && | ||
| 462 | rmem[4] == 0x01 && rmem[5] == 0x03) | ||
| 463 | return WIIMOTE_EXT_GUITAR; | ||
| 458 | 464 | ||
| 459 | return WIIMOTE_EXT_UNKNOWN; | 465 | return WIIMOTE_EXT_UNKNOWN; |
| 460 | } | 466 | } |
| @@ -488,6 +494,8 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype) | |||
| 488 | /* map MP with correct pass-through mode */ | 494 | /* map MP with correct pass-through mode */ |
| 489 | switch (exttype) { | 495 | switch (exttype) { |
| 490 | case WIIMOTE_EXT_CLASSIC_CONTROLLER: | 496 | case WIIMOTE_EXT_CLASSIC_CONTROLLER: |
| 497 | case WIIMOTE_EXT_DRUMS: | ||
| 498 | case WIIMOTE_EXT_GUITAR: | ||
| 491 | wmem = 0x07; | 499 | wmem = 0x07; |
| 492 | break; | 500 | break; |
| 493 | case WIIMOTE_EXT_NUNCHUK: | 501 | case WIIMOTE_EXT_NUNCHUK: |
| @@ -1075,6 +1083,8 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = { | |||
| 1075 | [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller", | 1083 | [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller", |
| 1076 | [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board", | 1084 | [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board", |
| 1077 | [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", | 1085 | [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", |
| 1086 | [WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums", | ||
| 1087 | [WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar", | ||
| 1078 | }; | 1088 | }; |
| 1079 | 1089 | ||
| 1080 | /* | 1090 | /* |
| @@ -1660,6 +1670,10 @@ static ssize_t wiimote_ext_show(struct device *dev, | |||
| 1660 | return sprintf(buf, "balanceboard\n"); | 1670 | return sprintf(buf, "balanceboard\n"); |
| 1661 | case WIIMOTE_EXT_PRO_CONTROLLER: | 1671 | case WIIMOTE_EXT_PRO_CONTROLLER: |
| 1662 | return sprintf(buf, "procontroller\n"); | 1672 | return sprintf(buf, "procontroller\n"); |
| 1673 | case WIIMOTE_EXT_DRUMS: | ||
| 1674 | return sprintf(buf, "drums\n"); | ||
| 1675 | case WIIMOTE_EXT_GUITAR: | ||
| 1676 | return sprintf(buf, "guitar\n"); | ||
| 1663 | case WIIMOTE_EXT_UNKNOWN: | 1677 | case WIIMOTE_EXT_UNKNOWN: |
| 1664 | /* fallthrough */ | 1678 | /* fallthrough */ |
| 1665 | default: | 1679 | default: |
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index c830ed39348f..aa72eb9a8e2f 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c | |||
| @@ -1950,6 +1950,444 @@ static const struct wiimod_ops wiimod_pro = { | |||
| 1950 | }; | 1950 | }; |
| 1951 | 1951 | ||
| 1952 | /* | 1952 | /* |
| 1953 | * Drums | ||
| 1954 | * Guitar-Hero, Rock-Band and other games came bundled with drums which can | ||
| 1955 | * be plugged as extension to a Wiimote. Drum-reports are still not entirely | ||
| 1956 | * figured out, but the most important information is known. | ||
| 1957 | * We create a separate device for drums and report all information via this | ||
| 1958 | * input device. | ||
| 1959 | */ | ||
| 1960 | |||
| 1961 | static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata, | ||
| 1962 | __u8 none, __u8 which, | ||
| 1963 | __u8 pressure, __u8 onoff, | ||
| 1964 | __u8 *store, __u16 code, | ||
| 1965 | __u8 which_code) | ||
| 1966 | { | ||
| 1967 | static const __u8 default_pressure = 3; | ||
| 1968 | |||
| 1969 | if (!none && which == which_code) { | ||
| 1970 | *store = pressure; | ||
| 1971 | input_report_abs(wdata->extension.input, code, *store); | ||
| 1972 | } else if (onoff != !!*store) { | ||
| 1973 | *store = onoff ? default_pressure : 0; | ||
| 1974 | input_report_abs(wdata->extension.input, code, *store); | ||
| 1975 | } | ||
| 1976 | } | ||
| 1977 | |||
| 1978 | static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext) | ||
| 1979 | { | ||
| 1980 | __u8 pressure, which, none, hhp, sx, sy; | ||
| 1981 | __u8 o, r, y, g, b, bass, bm, bp; | ||
| 1982 | |||
| 1983 | /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
| 1984 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 1985 | * 1 | 0 | 0 | SX <5:0> | | ||
| 1986 | * 2 | 0 | 0 | SY <5:0> | | ||
| 1987 | * -----+-----+-----+-----------------------------+-----+ | ||
| 1988 | * 3 | HPP | NON | WHICH <5:1> | ? | | ||
| 1989 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 1990 | * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? | | ||
| 1991 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 1992 | * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 | ? | | ||
| 1993 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 1994 | * 6 | O | R | Y | G | B | BSS | 1 | 1 | | ||
| 1995 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 1996 | * All buttons are 0 if pressed | ||
| 1997 | * | ||
| 1998 | * With Motion+ enabled, the following bits will get invalid: | ||
| 1999 | * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
| 2000 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2001 | * 1 | 0 | 0 | SX <5:1> |XXXXX| | ||
| 2002 | * 2 | 0 | 0 | SY <5:1> |XXXXX| | ||
| 2003 | * -----+-----+-----+-----------------------------+-----+ | ||
| 2004 | * 3 | HPP | NON | WHICH <5:1> | ? | | ||
| 2005 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2006 | * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? | | ||
| 2007 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2008 | * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 |XXXXX| | ||
| 2009 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2010 | * 6 | O | R | Y | G | B | BSS |XXXXX|XXXXX| | ||
| 2011 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2012 | */ | ||
| 2013 | |||
| 2014 | pressure = 7 - (ext[3] >> 5); | ||
| 2015 | which = (ext[2] >> 1) & 0x1f; | ||
| 2016 | none = !!(ext[2] & 0x40); | ||
| 2017 | hhp = !(ext[2] & 0x80); | ||
| 2018 | sx = ext[0] & 0x3f; | ||
| 2019 | sy = ext[1] & 0x3f; | ||
| 2020 | o = !(ext[5] & 0x80); | ||
| 2021 | r = !(ext[5] & 0x40); | ||
| 2022 | y = !(ext[5] & 0x20); | ||
| 2023 | g = !(ext[5] & 0x10); | ||
| 2024 | b = !(ext[5] & 0x08); | ||
| 2025 | bass = !(ext[5] & 0x04); | ||
| 2026 | bm = !(ext[4] & 0x10); | ||
| 2027 | bp = !(ext[4] & 0x04); | ||
| 2028 | |||
| 2029 | if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | ||
| 2030 | sx &= 0x3e; | ||
| 2031 | sy &= 0x3e; | ||
| 2032 | } | ||
| 2033 | |||
| 2034 | wiimod_drums_report_pressure(wdata, none, which, pressure, | ||
| 2035 | o, &wdata->state.pressure_drums[0], | ||
| 2036 | ABS_HAT2Y, 0x0e); | ||
| 2037 | wiimod_drums_report_pressure(wdata, none, which, pressure, | ||
| 2038 | r, &wdata->state.pressure_drums[1], | ||
| 2039 | ABS_HAT0X, 0x19); | ||
| 2040 | wiimod_drums_report_pressure(wdata, none, which, pressure, | ||
| 2041 | y, &wdata->state.pressure_drums[2], | ||
| 2042 | ABS_HAT2X, 0x11); | ||
| 2043 | wiimod_drums_report_pressure(wdata, none, which, pressure, | ||
| 2044 | g, &wdata->state.pressure_drums[3], | ||
| 2045 | ABS_HAT1X, 0x12); | ||
| 2046 | wiimod_drums_report_pressure(wdata, none, which, pressure, | ||
| 2047 | b, &wdata->state.pressure_drums[4], | ||
| 2048 | ABS_HAT0Y, 0x0f); | ||
| 2049 | |||
| 2050 | /* Bass shares pressure with hi-hat (set via hhp) */ | ||
| 2051 | wiimod_drums_report_pressure(wdata, none, hhp ? 0xff : which, pressure, | ||
| 2052 | bass, &wdata->state.pressure_drums[5], | ||
| 2053 | ABS_HAT3X, 0x1b); | ||
| 2054 | /* Hi-hat has no on/off values, just pressure. Force to off/0. */ | ||
| 2055 | wiimod_drums_report_pressure(wdata, none, hhp ? which : 0xff, pressure, | ||
| 2056 | 0, &wdata->state.pressure_drums[6], | ||
| 2057 | ABS_HAT3Y, 0x0e); | ||
| 2058 | |||
| 2059 | input_report_abs(wdata->extension.input, ABS_X, sx - 0x20); | ||
| 2060 | input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20); | ||
| 2061 | |||
| 2062 | input_report_key(wdata->extension.input, BTN_START, bp); | ||
| 2063 | input_report_key(wdata->extension.input, BTN_SELECT, bm); | ||
| 2064 | |||
| 2065 | input_sync(wdata->extension.input); | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | static int wiimod_drums_open(struct input_dev *dev) | ||
| 2069 | { | ||
| 2070 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
| 2071 | unsigned long flags; | ||
| 2072 | |||
| 2073 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 2074 | wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | ||
| 2075 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
| 2076 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 2077 | |||
| 2078 | return 0; | ||
| 2079 | } | ||
| 2080 | |||
| 2081 | static void wiimod_drums_close(struct input_dev *dev) | ||
| 2082 | { | ||
| 2083 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
| 2084 | unsigned long flags; | ||
| 2085 | |||
| 2086 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 2087 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | ||
| 2088 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
| 2089 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 2090 | } | ||
| 2091 | |||
| 2092 | static int wiimod_drums_probe(const struct wiimod_ops *ops, | ||
| 2093 | struct wiimote_data *wdata) | ||
| 2094 | { | ||
| 2095 | int ret; | ||
| 2096 | |||
| 2097 | wdata->extension.input = input_allocate_device(); | ||
| 2098 | if (!wdata->extension.input) | ||
| 2099 | return -ENOMEM; | ||
| 2100 | |||
| 2101 | input_set_drvdata(wdata->extension.input, wdata); | ||
| 2102 | wdata->extension.input->open = wiimod_drums_open; | ||
| 2103 | wdata->extension.input->close = wiimod_drums_close; | ||
| 2104 | wdata->extension.input->dev.parent = &wdata->hdev->dev; | ||
| 2105 | wdata->extension.input->id.bustype = wdata->hdev->bus; | ||
| 2106 | wdata->extension.input->id.vendor = wdata->hdev->vendor; | ||
| 2107 | wdata->extension.input->id.product = wdata->hdev->product; | ||
| 2108 | wdata->extension.input->id.version = wdata->hdev->version; | ||
| 2109 | wdata->extension.input->name = WIIMOTE_NAME " Drums"; | ||
| 2110 | |||
| 2111 | set_bit(EV_KEY, wdata->extension.input->evbit); | ||
| 2112 | set_bit(BTN_START, wdata->extension.input->keybit); | ||
| 2113 | set_bit(BTN_SELECT, wdata->extension.input->keybit); | ||
| 2114 | |||
| 2115 | set_bit(EV_ABS, wdata->extension.input->evbit); | ||
| 2116 | set_bit(ABS_X, wdata->extension.input->absbit); | ||
| 2117 | set_bit(ABS_Y, wdata->extension.input->absbit); | ||
| 2118 | set_bit(ABS_HAT0X, wdata->extension.input->absbit); | ||
| 2119 | set_bit(ABS_HAT0Y, wdata->extension.input->absbit); | ||
| 2120 | set_bit(ABS_HAT1X, wdata->extension.input->absbit); | ||
| 2121 | set_bit(ABS_HAT2X, wdata->extension.input->absbit); | ||
| 2122 | set_bit(ABS_HAT2Y, wdata->extension.input->absbit); | ||
| 2123 | set_bit(ABS_HAT3X, wdata->extension.input->absbit); | ||
| 2124 | set_bit(ABS_HAT3Y, wdata->extension.input->absbit); | ||
| 2125 | input_set_abs_params(wdata->extension.input, | ||
| 2126 | ABS_X, -32, 31, 1, 1); | ||
| 2127 | input_set_abs_params(wdata->extension.input, | ||
| 2128 | ABS_Y, -32, 31, 1, 1); | ||
| 2129 | input_set_abs_params(wdata->extension.input, | ||
| 2130 | ABS_HAT0X, 0, 7, 0, 0); | ||
| 2131 | input_set_abs_params(wdata->extension.input, | ||
| 2132 | ABS_HAT0Y, 0, 7, 0, 0); | ||
| 2133 | input_set_abs_params(wdata->extension.input, | ||
| 2134 | ABS_HAT1X, 0, 7, 0, 0); | ||
| 2135 | input_set_abs_params(wdata->extension.input, | ||
| 2136 | ABS_HAT2X, 0, 7, 0, 0); | ||
| 2137 | input_set_abs_params(wdata->extension.input, | ||
| 2138 | ABS_HAT2Y, 0, 7, 0, 0); | ||
| 2139 | input_set_abs_params(wdata->extension.input, | ||
| 2140 | ABS_HAT3X, 0, 7, 0, 0); | ||
| 2141 | input_set_abs_params(wdata->extension.input, | ||
| 2142 | ABS_HAT3Y, 0, 7, 0, 0); | ||
| 2143 | |||
| 2144 | ret = input_register_device(wdata->extension.input); | ||
| 2145 | if (ret) | ||
| 2146 | goto err_free; | ||
| 2147 | |||
| 2148 | return 0; | ||
| 2149 | |||
| 2150 | err_free: | ||
| 2151 | input_free_device(wdata->extension.input); | ||
| 2152 | wdata->extension.input = NULL; | ||
| 2153 | return ret; | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | static void wiimod_drums_remove(const struct wiimod_ops *ops, | ||
| 2157 | struct wiimote_data *wdata) | ||
| 2158 | { | ||
| 2159 | if (!wdata->extension.input) | ||
| 2160 | return; | ||
| 2161 | |||
| 2162 | input_unregister_device(wdata->extension.input); | ||
| 2163 | wdata->extension.input = NULL; | ||
| 2164 | } | ||
| 2165 | |||
| 2166 | static const struct wiimod_ops wiimod_drums = { | ||
| 2167 | .flags = 0, | ||
| 2168 | .arg = 0, | ||
| 2169 | .probe = wiimod_drums_probe, | ||
| 2170 | .remove = wiimod_drums_remove, | ||
| 2171 | .in_ext = wiimod_drums_in_ext, | ||
| 2172 | }; | ||
| 2173 | |||
| 2174 | /* | ||
| 2175 | * Guitar | ||
| 2176 | * Guitar-Hero, Rock-Band and other games came bundled with guitars which can | ||
| 2177 | * be plugged as extension to a Wiimote. | ||
| 2178 | * We create a separate device for guitars and report all information via this | ||
| 2179 | * input device. | ||
| 2180 | */ | ||
| 2181 | |||
| 2182 | enum wiimod_guitar_keys { | ||
| 2183 | WIIMOD_GUITAR_KEY_G, | ||
| 2184 | WIIMOD_GUITAR_KEY_R, | ||
| 2185 | WIIMOD_GUITAR_KEY_Y, | ||
| 2186 | WIIMOD_GUITAR_KEY_B, | ||
| 2187 | WIIMOD_GUITAR_KEY_O, | ||
| 2188 | WIIMOD_GUITAR_KEY_UP, | ||
| 2189 | WIIMOD_GUITAR_KEY_DOWN, | ||
| 2190 | WIIMOD_GUITAR_KEY_PLUS, | ||
| 2191 | WIIMOD_GUITAR_KEY_MINUS, | ||
| 2192 | WIIMOD_GUITAR_KEY_NUM, | ||
| 2193 | }; | ||
| 2194 | |||
| 2195 | static const __u16 wiimod_guitar_map[] = { | ||
| 2196 | BTN_1, /* WIIMOD_GUITAR_KEY_G */ | ||
| 2197 | BTN_2, /* WIIMOD_GUITAR_KEY_R */ | ||
| 2198 | BTN_3, /* WIIMOD_GUITAR_KEY_Y */ | ||
| 2199 | BTN_4, /* WIIMOD_GUITAR_KEY_B */ | ||
| 2200 | BTN_5, /* WIIMOD_GUITAR_KEY_O */ | ||
| 2201 | BTN_DPAD_UP, /* WIIMOD_GUITAR_KEY_UP */ | ||
| 2202 | BTN_DPAD_DOWN, /* WIIMOD_GUITAR_KEY_DOWN */ | ||
| 2203 | BTN_START, /* WIIMOD_GUITAR_KEY_PLUS */ | ||
| 2204 | BTN_SELECT, /* WIIMOD_GUITAR_KEY_MINUS */ | ||
| 2205 | }; | ||
| 2206 | |||
| 2207 | static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext) | ||
| 2208 | { | ||
| 2209 | __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu; | ||
| 2210 | |||
| 2211 | /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
| 2212 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2213 | * 1 | 0 | 0 | SX <5:0> | | ||
| 2214 | * 2 | 0 | 0 | SY <5:0> | | ||
| 2215 | * -----+-----+-----+-----+-----------------------------+ | ||
| 2216 | * 3 | 0 | 0 | 0 | TB <4:0> | | ||
| 2217 | * -----+-----+-----+-----+-----------------------------+ | ||
| 2218 | * 4 | 0 | 0 | 0 | WB <4:0> | | ||
| 2219 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2220 | * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 | 1 | | ||
| 2221 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2222 | * 6 | BO | BR | BB | BG | BY | 1 | 1 | BU | | ||
| 2223 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2224 | * All buttons are 0 if pressed | ||
| 2225 | * | ||
| 2226 | * With Motion+ enabled, it will look like this: | ||
| 2227 | * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
| 2228 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2229 | * 1 | 0 | 0 | SX <5:1> | BU | | ||
| 2230 | * 2 | 0 | 0 | SY <5:1> | 1 | | ||
| 2231 | * -----+-----+-----+-----+-----------------------+-----+ | ||
| 2232 | * 3 | 0 | 0 | 0 | TB <4:0> | | ||
| 2233 | * -----+-----+-----+-----+-----------------------------+ | ||
| 2234 | * 4 | 0 | 0 | 0 | WB <4:0> | | ||
| 2235 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2236 | * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 |XXXXX| | ||
| 2237 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2238 | * 6 | BO | BR | BB | BG | BY | 1 |XXXXX|XXXXX| | ||
| 2239 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 2240 | */ | ||
| 2241 | |||
| 2242 | sx = ext[0] & 0x3f; | ||
| 2243 | sy = ext[1] & 0x3f; | ||
| 2244 | tb = ext[2] & 0x1f; | ||
| 2245 | wb = ext[3] & 0x1f; | ||
| 2246 | bd = !(ext[4] & 0x40); | ||
| 2247 | bm = !(ext[4] & 0x10); | ||
| 2248 | bp = !(ext[4] & 0x04); | ||
| 2249 | bo = !(ext[5] & 0x80); | ||
| 2250 | br = !(ext[5] & 0x40); | ||
| 2251 | bb = !(ext[5] & 0x20); | ||
| 2252 | bg = !(ext[5] & 0x10); | ||
| 2253 | by = !(ext[5] & 0x08); | ||
| 2254 | bu = !(ext[5] & 0x01); | ||
| 2255 | |||
| 2256 | if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) { | ||
| 2257 | bu = !(ext[0] & 0x01); | ||
| 2258 | sx &= 0x3e; | ||
| 2259 | sy &= 0x3e; | ||
| 2260 | } | ||
| 2261 | |||
| 2262 | input_report_abs(wdata->extension.input, ABS_X, sx - 0x20); | ||
| 2263 | input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20); | ||
| 2264 | input_report_abs(wdata->extension.input, ABS_HAT0X, tb); | ||
| 2265 | input_report_abs(wdata->extension.input, ABS_HAT1X, wb - 0x10); | ||
| 2266 | |||
| 2267 | input_report_key(wdata->extension.input, | ||
| 2268 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_G], | ||
| 2269 | bg); | ||
| 2270 | input_report_key(wdata->extension.input, | ||
| 2271 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_R], | ||
| 2272 | br); | ||
| 2273 | input_report_key(wdata->extension.input, | ||
| 2274 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_Y], | ||
| 2275 | by); | ||
| 2276 | input_report_key(wdata->extension.input, | ||
| 2277 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_B], | ||
| 2278 | bb); | ||
| 2279 | input_report_key(wdata->extension.input, | ||
| 2280 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_O], | ||
| 2281 | bo); | ||
| 2282 | input_report_key(wdata->extension.input, | ||
| 2283 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_UP], | ||
| 2284 | bu); | ||
| 2285 | input_report_key(wdata->extension.input, | ||
| 2286 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_DOWN], | ||
| 2287 | bd); | ||
| 2288 | input_report_key(wdata->extension.input, | ||
| 2289 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_PLUS], | ||
| 2290 | bp); | ||
| 2291 | input_report_key(wdata->extension.input, | ||
| 2292 | wiimod_guitar_map[WIIMOD_GUITAR_KEY_MINUS], | ||
| 2293 | bm); | ||
| 2294 | |||
| 2295 | input_sync(wdata->extension.input); | ||
| 2296 | } | ||
| 2297 | |||
| 2298 | static int wiimod_guitar_open(struct input_dev *dev) | ||
| 2299 | { | ||
| 2300 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
| 2301 | unsigned long flags; | ||
| 2302 | |||
| 2303 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 2304 | wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | ||
| 2305 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
| 2306 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 2307 | |||
| 2308 | return 0; | ||
| 2309 | } | ||
| 2310 | |||
| 2311 | static void wiimod_guitar_close(struct input_dev *dev) | ||
| 2312 | { | ||
| 2313 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
| 2314 | unsigned long flags; | ||
| 2315 | |||
| 2316 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 2317 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | ||
| 2318 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
| 2319 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 2320 | } | ||
| 2321 | |||
| 2322 | static int wiimod_guitar_probe(const struct wiimod_ops *ops, | ||
| 2323 | struct wiimote_data *wdata) | ||
| 2324 | { | ||
| 2325 | int ret, i; | ||
| 2326 | |||
| 2327 | wdata->extension.input = input_allocate_device(); | ||
| 2328 | if (!wdata->extension.input) | ||
| 2329 | return -ENOMEM; | ||
| 2330 | |||
| 2331 | input_set_drvdata(wdata->extension.input, wdata); | ||
| 2332 | wdata->extension.input->open = wiimod_guitar_open; | ||
| 2333 | wdata->extension.input->close = wiimod_guitar_close; | ||
| 2334 | wdata->extension.input->dev.parent = &wdata->hdev->dev; | ||
| 2335 | wdata->extension.input->id.bustype = wdata->hdev->bus; | ||
| 2336 | wdata->extension.input->id.vendor = wdata->hdev->vendor; | ||
| 2337 | wdata->extension.input->id.product = wdata->hdev->product; | ||
| 2338 | wdata->extension.input->id.version = wdata->hdev->version; | ||
| 2339 | wdata->extension.input->name = WIIMOTE_NAME " Guitar"; | ||
| 2340 | |||
| 2341 | set_bit(EV_KEY, wdata->extension.input->evbit); | ||
| 2342 | for (i = 0; i < WIIMOD_GUITAR_KEY_NUM; ++i) | ||
| 2343 | set_bit(wiimod_guitar_map[i], | ||
| 2344 | wdata->extension.input->keybit); | ||
| 2345 | |||
| 2346 | set_bit(EV_ABS, wdata->extension.input->evbit); | ||
| 2347 | set_bit(ABS_X, wdata->extension.input->absbit); | ||
| 2348 | set_bit(ABS_Y, wdata->extension.input->absbit); | ||
| 2349 | set_bit(ABS_HAT0X, wdata->extension.input->absbit); | ||
| 2350 | set_bit(ABS_HAT1X, wdata->extension.input->absbit); | ||
| 2351 | input_set_abs_params(wdata->extension.input, | ||
| 2352 | ABS_X, -32, 31, 1, 1); | ||
| 2353 | input_set_abs_params(wdata->extension.input, | ||
| 2354 | ABS_Y, -32, 31, 1, 1); | ||
| 2355 | input_set_abs_params(wdata->extension.input, | ||
| 2356 | ABS_HAT0X, 0, 0x1f, 1, 1); | ||
| 2357 | input_set_abs_params(wdata->extension.input, | ||
| 2358 | ABS_HAT1X, 0, 0x0f, 1, 1); | ||
| 2359 | |||
| 2360 | ret = input_register_device(wdata->extension.input); | ||
| 2361 | if (ret) | ||
| 2362 | goto err_free; | ||
| 2363 | |||
| 2364 | return 0; | ||
| 2365 | |||
| 2366 | err_free: | ||
| 2367 | input_free_device(wdata->extension.input); | ||
| 2368 | wdata->extension.input = NULL; | ||
| 2369 | return ret; | ||
| 2370 | } | ||
| 2371 | |||
| 2372 | static void wiimod_guitar_remove(const struct wiimod_ops *ops, | ||
| 2373 | struct wiimote_data *wdata) | ||
| 2374 | { | ||
| 2375 | if (!wdata->extension.input) | ||
| 2376 | return; | ||
| 2377 | |||
| 2378 | input_unregister_device(wdata->extension.input); | ||
| 2379 | wdata->extension.input = NULL; | ||
| 2380 | } | ||
| 2381 | |||
| 2382 | static const struct wiimod_ops wiimod_guitar = { | ||
| 2383 | .flags = 0, | ||
| 2384 | .arg = 0, | ||
| 2385 | .probe = wiimod_guitar_probe, | ||
| 2386 | .remove = wiimod_guitar_remove, | ||
| 2387 | .in_ext = wiimod_guitar_in_ext, | ||
| 2388 | }; | ||
| 2389 | |||
| 2390 | /* | ||
| 1953 | * Builtin Motion Plus | 2391 | * Builtin Motion Plus |
| 1954 | * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which | 2392 | * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which |
| 1955 | * disables polling for Motion-Plus. This should be set only for devices which | 2393 | * disables polling for Motion-Plus. This should be set only for devices which |
| @@ -2201,4 +2639,6 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = { | |||
| 2201 | [WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic, | 2639 | [WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic, |
| 2202 | [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard, | 2640 | [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard, |
| 2203 | [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro, | 2641 | [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro, |
| 2642 | [WIIMOTE_EXT_DRUMS] = &wiimod_drums, | ||
| 2643 | [WIIMOTE_EXT_GUITAR] = &wiimod_guitar, | ||
| 2204 | }; | 2644 | }; |
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 510ca77fe14e..3bf3d3cc1c38 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
| @@ -89,6 +89,8 @@ enum wiimote_exttype { | |||
| 89 | WIIMOTE_EXT_CLASSIC_CONTROLLER, | 89 | WIIMOTE_EXT_CLASSIC_CONTROLLER, |
| 90 | WIIMOTE_EXT_BALANCE_BOARD, | 90 | WIIMOTE_EXT_BALANCE_BOARD, |
| 91 | WIIMOTE_EXT_PRO_CONTROLLER, | 91 | WIIMOTE_EXT_PRO_CONTROLLER, |
| 92 | WIIMOTE_EXT_DRUMS, | ||
| 93 | WIIMOTE_EXT_GUITAR, | ||
| 92 | WIIMOTE_EXT_NUM, | 94 | WIIMOTE_EXT_NUM, |
| 93 | }; | 95 | }; |
| 94 | 96 | ||
| @@ -137,6 +139,7 @@ struct wiimote_state { | |||
| 137 | /* calibration/cache data */ | 139 | /* calibration/cache data */ |
| 138 | __u16 calib_bboard[4][3]; | 140 | __u16 calib_bboard[4][3]; |
| 139 | __s16 calib_pro_sticks[4]; | 141 | __s16 calib_pro_sticks[4]; |
| 142 | __u8 pressure_drums[7]; | ||
| 140 | __u8 cache_rumble; | 143 | __u8 cache_rumble; |
| 141 | }; | 144 | }; |
| 142 | 145 | ||
