diff options
author | Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com> | 2013-08-26 13:14:48 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-09-04 04:44:17 -0400 |
commit | 8e22ecb603c88b7397ab2e80b7b0811b8a1318f5 (patch) | |
tree | bdd599a39eaa8eef420f8bbfc1c1ec25ed6d943f /drivers/hid | |
parent | 73f8645db1913ab2475ec3c1cee8d5f748963aa7 (diff) |
HID: wiimote: add support for Guitar-Hero guitars
Apart from drums, Guitar-Hero also ships with guitars. Use the recently
introduced input ABS/BTN-bits to report this to user-space.
Devices are reported as "Nintendo Wii Remote Guitar". 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.
Signed-off-by: Nicolas.Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
(add commit-msg and adjust to new BTN_* IDs)
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 | 7 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 174 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.h | 1 |
3 files changed, 182 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 946cdeff4798..d3055d1dbc06 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c | |||
@@ -459,6 +459,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem) | |||
459 | if (rmem[0] == 0x01 && rmem[1] == 0x00 && | 459 | if (rmem[0] == 0x01 && rmem[1] == 0x00 && |
460 | rmem[4] == 0x01 && rmem[5] == 0x03) | 460 | rmem[4] == 0x01 && rmem[5] == 0x03) |
461 | return WIIMOTE_EXT_GUITAR_HERO_DRUMS; | 461 | return WIIMOTE_EXT_GUITAR_HERO_DRUMS; |
462 | if (rmem[0] == 0x00 && rmem[1] == 0x00 && | ||
463 | rmem[4] == 0x01 && rmem[5] == 0x03) | ||
464 | return WIIMOTE_EXT_GUITAR_HERO_GUITAR; | ||
462 | 465 | ||
463 | return WIIMOTE_EXT_UNKNOWN; | 466 | return WIIMOTE_EXT_UNKNOWN; |
464 | } | 467 | } |
@@ -493,6 +496,7 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype) | |||
493 | switch (exttype) { | 496 | switch (exttype) { |
494 | case WIIMOTE_EXT_CLASSIC_CONTROLLER: | 497 | case WIIMOTE_EXT_CLASSIC_CONTROLLER: |
495 | case WIIMOTE_EXT_GUITAR_HERO_DRUMS: | 498 | case WIIMOTE_EXT_GUITAR_HERO_DRUMS: |
499 | case WIIMOTE_EXT_GUITAR_HERO_GUITAR: | ||
496 | wmem = 0x07; | 500 | wmem = 0x07; |
497 | break; | 501 | break; |
498 | case WIIMOTE_EXT_NUNCHUK: | 502 | case WIIMOTE_EXT_NUNCHUK: |
@@ -1084,6 +1088,7 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = { | |||
1084 | [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board", | 1088 | [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board", |
1085 | [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", | 1089 | [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller", |
1086 | [WIIMOTE_EXT_GUITAR_HERO_DRUMS] = "Nintendo Wii Guitar Hero Drums", | 1090 | [WIIMOTE_EXT_GUITAR_HERO_DRUMS] = "Nintendo Wii Guitar Hero Drums", |
1091 | [WIIMOTE_EXT_GUITAR_HERO_GUITAR] = "Nintendo Wii Guitar Hero Guitar", | ||
1087 | }; | 1092 | }; |
1088 | 1093 | ||
1089 | /* | 1094 | /* |
@@ -1672,6 +1677,8 @@ static ssize_t wiimote_ext_show(struct device *dev, | |||
1672 | return sprintf(buf, "procontroller\n"); | 1677 | return sprintf(buf, "procontroller\n"); |
1673 | case WIIMOTE_EXT_GUITAR_HERO_DRUMS: | 1678 | case WIIMOTE_EXT_GUITAR_HERO_DRUMS: |
1674 | return sprintf(buf, "drums\n"); | 1679 | return sprintf(buf, "drums\n"); |
1680 | case WIIMOTE_EXT_GUITAR_HERO_GUITAR: | ||
1681 | return sprintf(buf, "guitar\n"); | ||
1675 | case WIIMOTE_EXT_UNKNOWN: | 1682 | case WIIMOTE_EXT_UNKNOWN: |
1676 | /* fallthrough */ | 1683 | /* fallthrough */ |
1677 | default: | 1684 | default: |
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 08a44a7fc5fd..7e124c351e67 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c | |||
@@ -2051,6 +2051,179 @@ static const struct wiimod_ops wiimod_drums = { | |||
2051 | }; | 2051 | }; |
2052 | 2052 | ||
2053 | /* | 2053 | /* |
2054 | * Guitar | ||
2055 | * Guitar-Hero, Rock-Band and other games came bundled with guitars which can | ||
2056 | * be plugged as extension to a Wiimote. | ||
2057 | * We create a separate device for guitars and report all information via this | ||
2058 | * input device. | ||
2059 | */ | ||
2060 | |||
2061 | static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext) | ||
2062 | { | ||
2063 | __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu; | ||
2064 | |||
2065 | /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
2066 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2067 | * 1 | 0 | 0 | SX <5:0> | | ||
2068 | * 2 | 0 | 0 | SY <5:0> | | ||
2069 | * -----+-----+-----+-----+-----------------------------+ | ||
2070 | * 3 | 0 | 0 | 0 | TB <4:0> | | ||
2071 | * -----+-----+-----+-----+-----------------------------+ | ||
2072 | * 4 | 0 | 0 | 0 | WB <4:0> | | ||
2073 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2074 | * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 | 1 | | ||
2075 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2076 | * 6 | BO | BR | BB | BG | BY | 1 | 1 | BU | | ||
2077 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2078 | * All buttons are 0 if pressed | ||
2079 | * | ||
2080 | * With Motion+ enabled, the following bits will get invalid: | ||
2081 | * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
2082 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2083 | * 1 | 0 | 0 | SX <5:1> |XXXXX| | ||
2084 | * 2 | 0 | 0 | SY <5:1> |XXXXX| | ||
2085 | * -----+-----+-----+-----+-----------------------+-----+ | ||
2086 | * 3 | 0 | 0 | 0 | TB <4:0> | | ||
2087 | * -----+-----+-----+-----+-----------------------------+ | ||
2088 | * 4 | 0 | 0 | 0 | WB <4:0> | | ||
2089 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2090 | * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 |XXXXX| | ||
2091 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2092 | * 6 | BO | BR | BB | BG | BY | 1 |XXXXX|XXXXX| | ||
2093 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
2094 | */ | ||
2095 | |||
2096 | sx = ext[0] & 0x3f; | ||
2097 | sy = ext[1] & 0x3f; | ||
2098 | tb = ext[2] & 0x1f; | ||
2099 | wb = ext[3] & 0x1f; | ||
2100 | bd = !(ext[4] & 0x40); | ||
2101 | bm = !(ext[4] & 0x10); | ||
2102 | bp = !(ext[4] & 0x04); | ||
2103 | bo = !(ext[5] & 0x80); | ||
2104 | br = !(ext[5] & 0x40); | ||
2105 | bb = !(ext[5] & 0x20); | ||
2106 | bg = !(ext[5] & 0x10); | ||
2107 | by = !(ext[5] & 0x08); | ||
2108 | bu = !(ext[5] & 0x01); | ||
2109 | |||
2110 | input_report_abs(wdata->extension.input, ABS_X, sx - 0x20); | ||
2111 | input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20); | ||
2112 | input_report_abs(wdata->extension.input, ABS_FRET_BOARD, tb); | ||
2113 | input_report_abs(wdata->extension.input, ABS_WHAMMY_BAR, wb - 0x10); | ||
2114 | |||
2115 | input_report_key(wdata->extension.input, BTN_MODE, bm); | ||
2116 | input_report_key(wdata->extension.input, BTN_START, bp); | ||
2117 | input_report_key(wdata->extension.input, BTN_STRUM_BAR_UP, bu); | ||
2118 | input_report_key(wdata->extension.input, BTN_STRUM_BAR_DOWN, bd); | ||
2119 | input_report_key(wdata->extension.input, BTN_FRET_FAR_UP, bg); | ||
2120 | input_report_key(wdata->extension.input, BTN_FRET_UP, br); | ||
2121 | input_report_key(wdata->extension.input, BTN_FRET_MID, by); | ||
2122 | input_report_key(wdata->extension.input, BTN_FRET_LOW, bb); | ||
2123 | input_report_key(wdata->extension.input, BTN_FRET_FAR_LOW, bo); | ||
2124 | |||
2125 | input_sync(wdata->extension.input); | ||
2126 | } | ||
2127 | |||
2128 | static int wiimod_guitar_open(struct input_dev *dev) | ||
2129 | { | ||
2130 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
2131 | unsigned long flags; | ||
2132 | |||
2133 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
2134 | wdata->state.flags |= WIIPROTO_FLAG_EXT_USED; | ||
2135 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
2136 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
2137 | |||
2138 | return 0; | ||
2139 | } | ||
2140 | |||
2141 | static void wiimod_guitar_close(struct input_dev *dev) | ||
2142 | { | ||
2143 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
2144 | unsigned long flags; | ||
2145 | |||
2146 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
2147 | wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED; | ||
2148 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
2149 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
2150 | } | ||
2151 | |||
2152 | static int wiimod_guitar_probe(const struct wiimod_ops *ops, | ||
2153 | struct wiimote_data *wdata) | ||
2154 | { | ||
2155 | int ret; | ||
2156 | |||
2157 | wdata->extension.input = input_allocate_device(); | ||
2158 | if (!wdata->extension.input) | ||
2159 | return -ENOMEM; | ||
2160 | |||
2161 | input_set_drvdata(wdata->extension.input, wdata); | ||
2162 | wdata->extension.input->open = wiimod_guitar_open; | ||
2163 | wdata->extension.input->close = wiimod_guitar_close; | ||
2164 | wdata->extension.input->dev.parent = &wdata->hdev->dev; | ||
2165 | wdata->extension.input->id.bustype = wdata->hdev->bus; | ||
2166 | wdata->extension.input->id.vendor = wdata->hdev->vendor; | ||
2167 | wdata->extension.input->id.product = wdata->hdev->product; | ||
2168 | wdata->extension.input->id.version = wdata->hdev->version; | ||
2169 | wdata->extension.input->name = WIIMOTE_NAME " Guitar"; | ||
2170 | |||
2171 | set_bit(EV_KEY, wdata->extension.input->evbit); | ||
2172 | set_bit(BTN_MODE, wdata->extension.input->keybit); | ||
2173 | set_bit(BTN_START, wdata->extension.input->keybit); | ||
2174 | set_bit(BTN_FRET_FAR_UP, wdata->extension.input->keybit); | ||
2175 | set_bit(BTN_FRET_UP, wdata->extension.input->keybit); | ||
2176 | set_bit(BTN_FRET_MID, wdata->extension.input->keybit); | ||
2177 | set_bit(BTN_FRET_LOW, wdata->extension.input->keybit); | ||
2178 | set_bit(BTN_FRET_FAR_LOW, wdata->extension.input->keybit); | ||
2179 | set_bit(BTN_STRUM_BAR_UP, wdata->extension.input->keybit); | ||
2180 | set_bit(BTN_STRUM_BAR_DOWN, wdata->extension.input->keybit); | ||
2181 | |||
2182 | set_bit(EV_ABS, wdata->extension.input->evbit); | ||
2183 | set_bit(ABS_X, wdata->extension.input->absbit); | ||
2184 | set_bit(ABS_Y, wdata->extension.input->absbit); | ||
2185 | set_bit(ABS_FRET_BOARD, wdata->extension.input->absbit); | ||
2186 | set_bit(ABS_WHAMMY_BAR, wdata->extension.input->absbit); | ||
2187 | input_set_abs_params(wdata->extension.input, | ||
2188 | ABS_X, -32, 31, 1, 1); | ||
2189 | input_set_abs_params(wdata->extension.input, | ||
2190 | ABS_Y, -32, 31, 1, 1); | ||
2191 | input_set_abs_params(wdata->extension.input, | ||
2192 | ABS_FRET_BOARD, 0, 0x1f, 1, 1); | ||
2193 | input_set_abs_params(wdata->extension.input, | ||
2194 | ABS_WHAMMY_BAR, 0, 0x0f, 1, 1); | ||
2195 | |||
2196 | ret = input_register_device(wdata->extension.input); | ||
2197 | if (ret) | ||
2198 | goto err_free; | ||
2199 | |||
2200 | return 0; | ||
2201 | |||
2202 | err_free: | ||
2203 | input_free_device(wdata->extension.input); | ||
2204 | wdata->extension.input = NULL; | ||
2205 | return ret; | ||
2206 | } | ||
2207 | |||
2208 | static void wiimod_guitar_remove(const struct wiimod_ops *ops, | ||
2209 | struct wiimote_data *wdata) | ||
2210 | { | ||
2211 | if (!wdata->extension.input) | ||
2212 | return; | ||
2213 | |||
2214 | input_unregister_device(wdata->extension.input); | ||
2215 | wdata->extension.input = NULL; | ||
2216 | } | ||
2217 | |||
2218 | static const struct wiimod_ops wiimod_guitar = { | ||
2219 | .flags = 0, | ||
2220 | .arg = 0, | ||
2221 | .probe = wiimod_guitar_probe, | ||
2222 | .remove = wiimod_guitar_remove, | ||
2223 | .in_ext = wiimod_guitar_in_ext, | ||
2224 | }; | ||
2225 | |||
2226 | /* | ||
2054 | * Builtin Motion Plus | 2227 | * Builtin Motion Plus |
2055 | * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which | 2228 | * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which |
2056 | * disables polling for Motion-Plus. This should be set only for devices which | 2229 | * disables polling for Motion-Plus. This should be set only for devices which |
@@ -2301,4 +2474,5 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = { | |||
2301 | [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard, | 2474 | [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard, |
2302 | [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro, | 2475 | [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro, |
2303 | [WIIMOTE_EXT_GUITAR_HERO_DRUMS] = &wiimod_drums, | 2476 | [WIIMOTE_EXT_GUITAR_HERO_DRUMS] = &wiimod_drums, |
2477 | [WIIMOTE_EXT_GUITAR_HERO_GUITAR] = &wiimod_guitar, | ||
2304 | }; | 2478 | }; |
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 6e18b55951fb..379cdfb6bd25 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
@@ -89,6 +89,7 @@ enum wiimote_exttype { | |||
89 | WIIMOTE_EXT_BALANCE_BOARD, | 89 | WIIMOTE_EXT_BALANCE_BOARD, |
90 | WIIMOTE_EXT_PRO_CONTROLLER, | 90 | WIIMOTE_EXT_PRO_CONTROLLER, |
91 | WIIMOTE_EXT_GUITAR_HERO_DRUMS, | 91 | WIIMOTE_EXT_GUITAR_HERO_DRUMS, |
92 | WIIMOTE_EXT_GUITAR_HERO_GUITAR, | ||
92 | WIIMOTE_EXT_NUM, | 93 | WIIMOTE_EXT_NUM, |
93 | }; | 94 | }; |
94 | 95 | ||