diff options
Diffstat (limited to 'drivers/hid/hid-wiimote-modules.c')
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 174 |
1 files changed, 174 insertions, 0 deletions
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 | }; |