1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Device Modules for Nintendo Wii / Wii U HID Driver
4*4882a593Smuzhiyun * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun /*
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun * Wiimote Modules
12*4882a593Smuzhiyun * Nintendo devices provide different peripherals and many new devices lack
13*4882a593Smuzhiyun * initial features like the IR camera. Therefore, each peripheral device is
14*4882a593Smuzhiyun * implemented as an independent module and we probe on each device only the
15*4882a593Smuzhiyun * modules for the hardware that really is available.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * Module registration is sequential. Unregistration is done in reverse order.
18*4882a593Smuzhiyun * After device detection, the needed modules are loaded. Users can trigger
19*4882a593Smuzhiyun * re-detection which causes all modules to be unloaded and then reload the
20*4882a593Smuzhiyun * modules for the new detected device.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * wdata->input is a shared input device. It is always initialized prior to
23*4882a593Smuzhiyun * module registration. If at least one registered module is marked as
24*4882a593Smuzhiyun * WIIMOD_FLAG_INPUT, then the input device will get registered after all
25*4882a593Smuzhiyun * modules were registered.
26*4882a593Smuzhiyun * Please note that it is unregistered _before_ the "remove" callbacks are
27*4882a593Smuzhiyun * called. This guarantees that no input interaction is done, anymore. However,
28*4882a593Smuzhiyun * the wiimote core keeps a reference to the input device so it is freed only
29*4882a593Smuzhiyun * after all modules were removed. It is safe to send events to unregistered
30*4882a593Smuzhiyun * input devices.
31*4882a593Smuzhiyun */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include <linux/device.h>
34*4882a593Smuzhiyun #include <linux/hid.h>
35*4882a593Smuzhiyun #include <linux/input.h>
36*4882a593Smuzhiyun #include <linux/spinlock.h>
37*4882a593Smuzhiyun #include "hid-wiimote.h"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun * Keys
41*4882a593Smuzhiyun * The initial Wii Remote provided a bunch of buttons that are reported as
42*4882a593Smuzhiyun * part of the core protocol. Many later devices dropped these and report
43*4882a593Smuzhiyun * invalid data in the core button reports. Load this only on devices which
44*4882a593Smuzhiyun * correctly send button reports.
45*4882a593Smuzhiyun * It uses the shared input device.
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static const __u16 wiimod_keys_map[] = {
49*4882a593Smuzhiyun KEY_LEFT, /* WIIPROTO_KEY_LEFT */
50*4882a593Smuzhiyun KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */
51*4882a593Smuzhiyun KEY_UP, /* WIIPROTO_KEY_UP */
52*4882a593Smuzhiyun KEY_DOWN, /* WIIPROTO_KEY_DOWN */
53*4882a593Smuzhiyun KEY_NEXT, /* WIIPROTO_KEY_PLUS */
54*4882a593Smuzhiyun KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */
55*4882a593Smuzhiyun BTN_1, /* WIIPROTO_KEY_ONE */
56*4882a593Smuzhiyun BTN_2, /* WIIPROTO_KEY_TWO */
57*4882a593Smuzhiyun BTN_A, /* WIIPROTO_KEY_A */
58*4882a593Smuzhiyun BTN_B, /* WIIPROTO_KEY_B */
59*4882a593Smuzhiyun BTN_MODE, /* WIIPROTO_KEY_HOME */
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
wiimod_keys_in_keys(struct wiimote_data * wdata,const __u8 * keys)62*4882a593Smuzhiyun static void wiimod_keys_in_keys(struct wiimote_data *wdata, const __u8 *keys)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_LEFT],
65*4882a593Smuzhiyun !!(keys[0] & 0x01));
66*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_RIGHT],
67*4882a593Smuzhiyun !!(keys[0] & 0x02));
68*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_DOWN],
69*4882a593Smuzhiyun !!(keys[0] & 0x04));
70*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_UP],
71*4882a593Smuzhiyun !!(keys[0] & 0x08));
72*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_PLUS],
73*4882a593Smuzhiyun !!(keys[0] & 0x10));
74*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_TWO],
75*4882a593Smuzhiyun !!(keys[1] & 0x01));
76*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_ONE],
77*4882a593Smuzhiyun !!(keys[1] & 0x02));
78*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_B],
79*4882a593Smuzhiyun !!(keys[1] & 0x04));
80*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_A],
81*4882a593Smuzhiyun !!(keys[1] & 0x08));
82*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_MINUS],
83*4882a593Smuzhiyun !!(keys[1] & 0x10));
84*4882a593Smuzhiyun input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_HOME],
85*4882a593Smuzhiyun !!(keys[1] & 0x80));
86*4882a593Smuzhiyun input_sync(wdata->input);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
wiimod_keys_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)89*4882a593Smuzhiyun static int wiimod_keys_probe(const struct wiimod_ops *ops,
90*4882a593Smuzhiyun struct wiimote_data *wdata)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun unsigned int i;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun set_bit(EV_KEY, wdata->input->evbit);
95*4882a593Smuzhiyun for (i = 0; i < WIIPROTO_KEY_COUNT; ++i)
96*4882a593Smuzhiyun set_bit(wiimod_keys_map[i], wdata->input->keybit);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun return 0;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun static const struct wiimod_ops wiimod_keys = {
102*4882a593Smuzhiyun .flags = WIIMOD_FLAG_INPUT,
103*4882a593Smuzhiyun .arg = 0,
104*4882a593Smuzhiyun .probe = wiimod_keys_probe,
105*4882a593Smuzhiyun .remove = NULL,
106*4882a593Smuzhiyun .in_keys = wiimod_keys_in_keys,
107*4882a593Smuzhiyun };
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /*
110*4882a593Smuzhiyun * Rumble
111*4882a593Smuzhiyun * Nearly all devices provide a rumble feature. A small motor for
112*4882a593Smuzhiyun * force-feedback effects. We provide an FF_RUMBLE memless ff device on the
113*4882a593Smuzhiyun * shared input device if this module is loaded.
114*4882a593Smuzhiyun * The rumble motor is controlled via a flag on almost every output report so
115*4882a593Smuzhiyun * the wiimote core handles the rumble flag. But if a device doesn't provide
116*4882a593Smuzhiyun * the rumble motor, this flag shouldn't be set.
117*4882a593Smuzhiyun */
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* used by wiimod_rumble and wiipro_rumble */
wiimod_rumble_worker(struct work_struct * work)120*4882a593Smuzhiyun static void wiimod_rumble_worker(struct work_struct *work)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun struct wiimote_data *wdata = container_of(work, struct wiimote_data,
123*4882a593Smuzhiyun rumble_worker);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun spin_lock_irq(&wdata->state.lock);
126*4882a593Smuzhiyun wiiproto_req_rumble(wdata, wdata->state.cache_rumble);
127*4882a593Smuzhiyun spin_unlock_irq(&wdata->state.lock);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
wiimod_rumble_play(struct input_dev * dev,void * data,struct ff_effect * eff)130*4882a593Smuzhiyun static int wiimod_rumble_play(struct input_dev *dev, void *data,
131*4882a593Smuzhiyun struct ff_effect *eff)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
134*4882a593Smuzhiyun __u8 value;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun * The wiimote supports only a single rumble motor so if any magnitude
138*4882a593Smuzhiyun * is set to non-zero then we start the rumble motor. If both are set to
139*4882a593Smuzhiyun * zero, we stop the rumble motor.
140*4882a593Smuzhiyun */
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
143*4882a593Smuzhiyun value = 1;
144*4882a593Smuzhiyun else
145*4882a593Smuzhiyun value = 0;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* Locking state.lock here might deadlock with input_event() calls.
148*4882a593Smuzhiyun * schedule_work acts as barrier. Merging multiple changes is fine. */
149*4882a593Smuzhiyun wdata->state.cache_rumble = value;
150*4882a593Smuzhiyun schedule_work(&wdata->rumble_worker);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun return 0;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
wiimod_rumble_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)155*4882a593Smuzhiyun static int wiimod_rumble_probe(const struct wiimod_ops *ops,
156*4882a593Smuzhiyun struct wiimote_data *wdata)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun set_bit(FF_RUMBLE, wdata->input->ffbit);
161*4882a593Smuzhiyun if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play))
162*4882a593Smuzhiyun return -ENOMEM;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun return 0;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
wiimod_rumble_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)167*4882a593Smuzhiyun static void wiimod_rumble_remove(const struct wiimod_ops *ops,
168*4882a593Smuzhiyun struct wiimote_data *wdata)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun unsigned long flags;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun cancel_work_sync(&wdata->rumble_worker);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
175*4882a593Smuzhiyun wiiproto_req_rumble(wdata, 0);
176*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun static const struct wiimod_ops wiimod_rumble = {
180*4882a593Smuzhiyun .flags = WIIMOD_FLAG_INPUT,
181*4882a593Smuzhiyun .arg = 0,
182*4882a593Smuzhiyun .probe = wiimod_rumble_probe,
183*4882a593Smuzhiyun .remove = wiimod_rumble_remove,
184*4882a593Smuzhiyun };
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun /*
187*4882a593Smuzhiyun * Battery
188*4882a593Smuzhiyun * 1 byte of battery capacity information is sent along every protocol status
189*4882a593Smuzhiyun * report. The wiimote core caches it but we try to update it on every
190*4882a593Smuzhiyun * user-space request.
191*4882a593Smuzhiyun * This is supported by nearly every device so it's almost always enabled.
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun static enum power_supply_property wiimod_battery_props[] = {
195*4882a593Smuzhiyun POWER_SUPPLY_PROP_CAPACITY,
196*4882a593Smuzhiyun POWER_SUPPLY_PROP_SCOPE,
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun
wiimod_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)199*4882a593Smuzhiyun static int wiimod_battery_get_property(struct power_supply *psy,
200*4882a593Smuzhiyun enum power_supply_property psp,
201*4882a593Smuzhiyun union power_supply_propval *val)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun struct wiimote_data *wdata = power_supply_get_drvdata(psy);
204*4882a593Smuzhiyun int ret = 0, state;
205*4882a593Smuzhiyun unsigned long flags;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun if (psp == POWER_SUPPLY_PROP_SCOPE) {
208*4882a593Smuzhiyun val->intval = POWER_SUPPLY_SCOPE_DEVICE;
209*4882a593Smuzhiyun return 0;
210*4882a593Smuzhiyun } else if (psp != POWER_SUPPLY_PROP_CAPACITY) {
211*4882a593Smuzhiyun return -EINVAL;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun ret = wiimote_cmd_acquire(wdata);
215*4882a593Smuzhiyun if (ret)
216*4882a593Smuzhiyun return ret;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
219*4882a593Smuzhiyun wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0);
220*4882a593Smuzhiyun wiiproto_req_status(wdata);
221*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun wiimote_cmd_wait(wdata);
224*4882a593Smuzhiyun wiimote_cmd_release(wdata);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
227*4882a593Smuzhiyun state = wdata->state.cmd_battery;
228*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun val->intval = state * 100 / 255;
231*4882a593Smuzhiyun return ret;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
wiimod_battery_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)234*4882a593Smuzhiyun static int wiimod_battery_probe(const struct wiimod_ops *ops,
235*4882a593Smuzhiyun struct wiimote_data *wdata)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct power_supply_config psy_cfg = { .drv_data = wdata, };
238*4882a593Smuzhiyun int ret;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun wdata->battery_desc.properties = wiimod_battery_props;
241*4882a593Smuzhiyun wdata->battery_desc.num_properties = ARRAY_SIZE(wiimod_battery_props);
242*4882a593Smuzhiyun wdata->battery_desc.get_property = wiimod_battery_get_property;
243*4882a593Smuzhiyun wdata->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
244*4882a593Smuzhiyun wdata->battery_desc.use_for_apm = 0;
245*4882a593Smuzhiyun wdata->battery_desc.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s",
246*4882a593Smuzhiyun wdata->hdev->uniq);
247*4882a593Smuzhiyun if (!wdata->battery_desc.name)
248*4882a593Smuzhiyun return -ENOMEM;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun wdata->battery = power_supply_register(&wdata->hdev->dev,
251*4882a593Smuzhiyun &wdata->battery_desc,
252*4882a593Smuzhiyun &psy_cfg);
253*4882a593Smuzhiyun if (IS_ERR(wdata->battery)) {
254*4882a593Smuzhiyun hid_err(wdata->hdev, "cannot register battery device\n");
255*4882a593Smuzhiyun ret = PTR_ERR(wdata->battery);
256*4882a593Smuzhiyun goto err_free;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun power_supply_powers(wdata->battery, &wdata->hdev->dev);
260*4882a593Smuzhiyun return 0;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun err_free:
263*4882a593Smuzhiyun kfree(wdata->battery_desc.name);
264*4882a593Smuzhiyun wdata->battery_desc.name = NULL;
265*4882a593Smuzhiyun return ret;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
wiimod_battery_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)268*4882a593Smuzhiyun static void wiimod_battery_remove(const struct wiimod_ops *ops,
269*4882a593Smuzhiyun struct wiimote_data *wdata)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun if (!wdata->battery_desc.name)
272*4882a593Smuzhiyun return;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun power_supply_unregister(wdata->battery);
275*4882a593Smuzhiyun kfree(wdata->battery_desc.name);
276*4882a593Smuzhiyun wdata->battery_desc.name = NULL;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun static const struct wiimod_ops wiimod_battery = {
280*4882a593Smuzhiyun .flags = 0,
281*4882a593Smuzhiyun .arg = 0,
282*4882a593Smuzhiyun .probe = wiimod_battery_probe,
283*4882a593Smuzhiyun .remove = wiimod_battery_remove,
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /*
287*4882a593Smuzhiyun * LED
288*4882a593Smuzhiyun * 0 to 4 player LEDs are supported by devices. The "arg" field of the
289*4882a593Smuzhiyun * wiimod_ops structure specifies which LED this module controls. This allows
290*4882a593Smuzhiyun * to register a limited number of LEDs.
291*4882a593Smuzhiyun * State is managed by wiimote core.
292*4882a593Smuzhiyun */
293*4882a593Smuzhiyun
wiimod_led_get(struct led_classdev * led_dev)294*4882a593Smuzhiyun static enum led_brightness wiimod_led_get(struct led_classdev *led_dev)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun struct device *dev = led_dev->dev->parent;
297*4882a593Smuzhiyun struct wiimote_data *wdata = dev_to_wii(dev);
298*4882a593Smuzhiyun int i;
299*4882a593Smuzhiyun unsigned long flags;
300*4882a593Smuzhiyun bool value = false;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun for (i = 0; i < 4; ++i) {
303*4882a593Smuzhiyun if (wdata->leds[i] == led_dev) {
304*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
305*4882a593Smuzhiyun value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1);
306*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun return value ? LED_FULL : LED_OFF;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
wiimod_led_set(struct led_classdev * led_dev,enum led_brightness value)314*4882a593Smuzhiyun static void wiimod_led_set(struct led_classdev *led_dev,
315*4882a593Smuzhiyun enum led_brightness value)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct device *dev = led_dev->dev->parent;
318*4882a593Smuzhiyun struct wiimote_data *wdata = dev_to_wii(dev);
319*4882a593Smuzhiyun int i;
320*4882a593Smuzhiyun unsigned long flags;
321*4882a593Smuzhiyun __u8 state, flag;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun for (i = 0; i < 4; ++i) {
324*4882a593Smuzhiyun if (wdata->leds[i] == led_dev) {
325*4882a593Smuzhiyun flag = WIIPROTO_FLAG_LED(i + 1);
326*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
327*4882a593Smuzhiyun state = wdata->state.flags;
328*4882a593Smuzhiyun if (value == LED_OFF)
329*4882a593Smuzhiyun wiiproto_req_leds(wdata, state & ~flag);
330*4882a593Smuzhiyun else
331*4882a593Smuzhiyun wiiproto_req_leds(wdata, state | flag);
332*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
333*4882a593Smuzhiyun break;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
wiimod_led_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)338*4882a593Smuzhiyun static int wiimod_led_probe(const struct wiimod_ops *ops,
339*4882a593Smuzhiyun struct wiimote_data *wdata)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun struct device *dev = &wdata->hdev->dev;
342*4882a593Smuzhiyun size_t namesz = strlen(dev_name(dev)) + 9;
343*4882a593Smuzhiyun struct led_classdev *led;
344*4882a593Smuzhiyun unsigned long flags;
345*4882a593Smuzhiyun char *name;
346*4882a593Smuzhiyun int ret;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
349*4882a593Smuzhiyun if (!led)
350*4882a593Smuzhiyun return -ENOMEM;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun name = (void*)&led[1];
353*4882a593Smuzhiyun snprintf(name, namesz, "%s:blue:p%lu", dev_name(dev), ops->arg);
354*4882a593Smuzhiyun led->name = name;
355*4882a593Smuzhiyun led->brightness = 0;
356*4882a593Smuzhiyun led->max_brightness = 1;
357*4882a593Smuzhiyun led->brightness_get = wiimod_led_get;
358*4882a593Smuzhiyun led->brightness_set = wiimod_led_set;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun wdata->leds[ops->arg] = led;
361*4882a593Smuzhiyun ret = led_classdev_register(dev, led);
362*4882a593Smuzhiyun if (ret)
363*4882a593Smuzhiyun goto err_free;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun /* enable LED1 to stop initial LED-blinking */
366*4882a593Smuzhiyun if (ops->arg == 0) {
367*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
368*4882a593Smuzhiyun wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1);
369*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun return 0;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun err_free:
375*4882a593Smuzhiyun wdata->leds[ops->arg] = NULL;
376*4882a593Smuzhiyun kfree(led);
377*4882a593Smuzhiyun return ret;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
wiimod_led_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)380*4882a593Smuzhiyun static void wiimod_led_remove(const struct wiimod_ops *ops,
381*4882a593Smuzhiyun struct wiimote_data *wdata)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun if (!wdata->leds[ops->arg])
384*4882a593Smuzhiyun return;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun led_classdev_unregister(wdata->leds[ops->arg]);
387*4882a593Smuzhiyun kfree(wdata->leds[ops->arg]);
388*4882a593Smuzhiyun wdata->leds[ops->arg] = NULL;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun static const struct wiimod_ops wiimod_leds[4] = {
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun .flags = 0,
394*4882a593Smuzhiyun .arg = 0,
395*4882a593Smuzhiyun .probe = wiimod_led_probe,
396*4882a593Smuzhiyun .remove = wiimod_led_remove,
397*4882a593Smuzhiyun },
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun .flags = 0,
400*4882a593Smuzhiyun .arg = 1,
401*4882a593Smuzhiyun .probe = wiimod_led_probe,
402*4882a593Smuzhiyun .remove = wiimod_led_remove,
403*4882a593Smuzhiyun },
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun .flags = 0,
406*4882a593Smuzhiyun .arg = 2,
407*4882a593Smuzhiyun .probe = wiimod_led_probe,
408*4882a593Smuzhiyun .remove = wiimod_led_remove,
409*4882a593Smuzhiyun },
410*4882a593Smuzhiyun {
411*4882a593Smuzhiyun .flags = 0,
412*4882a593Smuzhiyun .arg = 3,
413*4882a593Smuzhiyun .probe = wiimod_led_probe,
414*4882a593Smuzhiyun .remove = wiimod_led_remove,
415*4882a593Smuzhiyun },
416*4882a593Smuzhiyun };
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /*
419*4882a593Smuzhiyun * Accelerometer
420*4882a593Smuzhiyun * 3 axis accelerometer data is part of nearly all DRMs. If not supported by a
421*4882a593Smuzhiyun * device, it's mostly cleared to 0. This module parses this data and provides
422*4882a593Smuzhiyun * it via a separate input device.
423*4882a593Smuzhiyun */
424*4882a593Smuzhiyun
wiimod_accel_in_accel(struct wiimote_data * wdata,const __u8 * accel)425*4882a593Smuzhiyun static void wiimod_accel_in_accel(struct wiimote_data *wdata,
426*4882a593Smuzhiyun const __u8 *accel)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun __u16 x, y, z;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL))
431*4882a593Smuzhiyun return;
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun /*
434*4882a593Smuzhiyun * payload is: BB BB XX YY ZZ
435*4882a593Smuzhiyun * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ
436*4882a593Smuzhiyun * contain the upper 8 bits of each value. The lower 2 bits are
437*4882a593Smuzhiyun * contained in the buttons data BB BB.
438*4882a593Smuzhiyun * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the
439*4882a593Smuzhiyun * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y
440*4882a593Smuzhiyun * accel value and bit 6 is the second bit of the Z value.
441*4882a593Smuzhiyun * The first bit of Y and Z values is not available and always set to 0.
442*4882a593Smuzhiyun * 0x200 is returned on no movement.
443*4882a593Smuzhiyun */
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun x = accel[2] << 2;
446*4882a593Smuzhiyun y = accel[3] << 2;
447*4882a593Smuzhiyun z = accel[4] << 2;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun x |= (accel[0] >> 5) & 0x3;
450*4882a593Smuzhiyun y |= (accel[1] >> 4) & 0x2;
451*4882a593Smuzhiyun z |= (accel[1] >> 5) & 0x2;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun input_report_abs(wdata->accel, ABS_RX, x - 0x200);
454*4882a593Smuzhiyun input_report_abs(wdata->accel, ABS_RY, y - 0x200);
455*4882a593Smuzhiyun input_report_abs(wdata->accel, ABS_RZ, z - 0x200);
456*4882a593Smuzhiyun input_sync(wdata->accel);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
wiimod_accel_open(struct input_dev * dev)459*4882a593Smuzhiyun static int wiimod_accel_open(struct input_dev *dev)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
462*4882a593Smuzhiyun unsigned long flags;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
465*4882a593Smuzhiyun wiiproto_req_accel(wdata, true);
466*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun return 0;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
wiimod_accel_close(struct input_dev * dev)471*4882a593Smuzhiyun static void wiimod_accel_close(struct input_dev *dev)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
474*4882a593Smuzhiyun unsigned long flags;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
477*4882a593Smuzhiyun wiiproto_req_accel(wdata, false);
478*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun
wiimod_accel_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)481*4882a593Smuzhiyun static int wiimod_accel_probe(const struct wiimod_ops *ops,
482*4882a593Smuzhiyun struct wiimote_data *wdata)
483*4882a593Smuzhiyun {
484*4882a593Smuzhiyun int ret;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun wdata->accel = input_allocate_device();
487*4882a593Smuzhiyun if (!wdata->accel)
488*4882a593Smuzhiyun return -ENOMEM;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun input_set_drvdata(wdata->accel, wdata);
491*4882a593Smuzhiyun wdata->accel->open = wiimod_accel_open;
492*4882a593Smuzhiyun wdata->accel->close = wiimod_accel_close;
493*4882a593Smuzhiyun wdata->accel->dev.parent = &wdata->hdev->dev;
494*4882a593Smuzhiyun wdata->accel->id.bustype = wdata->hdev->bus;
495*4882a593Smuzhiyun wdata->accel->id.vendor = wdata->hdev->vendor;
496*4882a593Smuzhiyun wdata->accel->id.product = wdata->hdev->product;
497*4882a593Smuzhiyun wdata->accel->id.version = wdata->hdev->version;
498*4882a593Smuzhiyun wdata->accel->name = WIIMOTE_NAME " Accelerometer";
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun set_bit(EV_ABS, wdata->accel->evbit);
501*4882a593Smuzhiyun set_bit(ABS_RX, wdata->accel->absbit);
502*4882a593Smuzhiyun set_bit(ABS_RY, wdata->accel->absbit);
503*4882a593Smuzhiyun set_bit(ABS_RZ, wdata->accel->absbit);
504*4882a593Smuzhiyun input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4);
505*4882a593Smuzhiyun input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4);
506*4882a593Smuzhiyun input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4);
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun ret = input_register_device(wdata->accel);
509*4882a593Smuzhiyun if (ret) {
510*4882a593Smuzhiyun hid_err(wdata->hdev, "cannot register input device\n");
511*4882a593Smuzhiyun goto err_free;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun return 0;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun err_free:
517*4882a593Smuzhiyun input_free_device(wdata->accel);
518*4882a593Smuzhiyun wdata->accel = NULL;
519*4882a593Smuzhiyun return ret;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
wiimod_accel_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)522*4882a593Smuzhiyun static void wiimod_accel_remove(const struct wiimod_ops *ops,
523*4882a593Smuzhiyun struct wiimote_data *wdata)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun if (!wdata->accel)
526*4882a593Smuzhiyun return;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun input_unregister_device(wdata->accel);
529*4882a593Smuzhiyun wdata->accel = NULL;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun static const struct wiimod_ops wiimod_accel = {
533*4882a593Smuzhiyun .flags = 0,
534*4882a593Smuzhiyun .arg = 0,
535*4882a593Smuzhiyun .probe = wiimod_accel_probe,
536*4882a593Smuzhiyun .remove = wiimod_accel_remove,
537*4882a593Smuzhiyun .in_accel = wiimod_accel_in_accel,
538*4882a593Smuzhiyun };
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /*
541*4882a593Smuzhiyun * IR Cam
542*4882a593Smuzhiyun * Up to 4 IR sources can be tracked by a normal Wii Remote. The IR cam needs
543*4882a593Smuzhiyun * to be initialized with a fairly complex procedure and consumes a lot of
544*4882a593Smuzhiyun * power. Therefore, as long as no application uses the IR input device, it is
545*4882a593Smuzhiyun * kept offline.
546*4882a593Smuzhiyun * Nearly no other device than the normal Wii Remotes supports the IR cam so
547*4882a593Smuzhiyun * you can disable this module for these devices.
548*4882a593Smuzhiyun */
549*4882a593Smuzhiyun
wiimod_ir_in_ir(struct wiimote_data * wdata,const __u8 * ir,bool packed,unsigned int id)550*4882a593Smuzhiyun static void wiimod_ir_in_ir(struct wiimote_data *wdata, const __u8 *ir,
551*4882a593Smuzhiyun bool packed, unsigned int id)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun __u16 x, y;
554*4882a593Smuzhiyun __u8 xid, yid;
555*4882a593Smuzhiyun bool sync = false;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (!(wdata->state.flags & WIIPROTO_FLAGS_IR))
558*4882a593Smuzhiyun return;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun switch (id) {
561*4882a593Smuzhiyun case 0:
562*4882a593Smuzhiyun xid = ABS_HAT0X;
563*4882a593Smuzhiyun yid = ABS_HAT0Y;
564*4882a593Smuzhiyun break;
565*4882a593Smuzhiyun case 1:
566*4882a593Smuzhiyun xid = ABS_HAT1X;
567*4882a593Smuzhiyun yid = ABS_HAT1Y;
568*4882a593Smuzhiyun break;
569*4882a593Smuzhiyun case 2:
570*4882a593Smuzhiyun xid = ABS_HAT2X;
571*4882a593Smuzhiyun yid = ABS_HAT2Y;
572*4882a593Smuzhiyun break;
573*4882a593Smuzhiyun case 3:
574*4882a593Smuzhiyun xid = ABS_HAT3X;
575*4882a593Smuzhiyun yid = ABS_HAT3Y;
576*4882a593Smuzhiyun sync = true;
577*4882a593Smuzhiyun break;
578*4882a593Smuzhiyun default:
579*4882a593Smuzhiyun return;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun /*
583*4882a593Smuzhiyun * Basic IR data is encoded into 3 bytes. The first two bytes are the
584*4882a593Smuzhiyun * lower 8 bit of the X/Y data, the 3rd byte contains the upper 2 bits
585*4882a593Smuzhiyun * of both.
586*4882a593Smuzhiyun * If data is packed, then the 3rd byte is put first and slightly
587*4882a593Smuzhiyun * reordered. This allows to interleave packed and non-packed data to
588*4882a593Smuzhiyun * have two IR sets in 5 bytes instead of 6.
589*4882a593Smuzhiyun * The resulting 10bit X/Y values are passed to the ABS_HAT? input dev.
590*4882a593Smuzhiyun */
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun if (packed) {
593*4882a593Smuzhiyun x = ir[1] | ((ir[0] & 0x03) << 8);
594*4882a593Smuzhiyun y = ir[2] | ((ir[0] & 0x0c) << 6);
595*4882a593Smuzhiyun } else {
596*4882a593Smuzhiyun x = ir[0] | ((ir[2] & 0x30) << 4);
597*4882a593Smuzhiyun y = ir[1] | ((ir[2] & 0xc0) << 2);
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun input_report_abs(wdata->ir, xid, x);
601*4882a593Smuzhiyun input_report_abs(wdata->ir, yid, y);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (sync)
604*4882a593Smuzhiyun input_sync(wdata->ir);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
wiimod_ir_change(struct wiimote_data * wdata,__u16 mode)607*4882a593Smuzhiyun static int wiimod_ir_change(struct wiimote_data *wdata, __u16 mode)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun int ret;
610*4882a593Smuzhiyun unsigned long flags;
611*4882a593Smuzhiyun __u8 format = 0;
612*4882a593Smuzhiyun static const __u8 data_enable[] = { 0x01 };
613*4882a593Smuzhiyun static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01,
614*4882a593Smuzhiyun 0x00, 0xaa, 0x00, 0x64 };
615*4882a593Smuzhiyun static const __u8 data_sens2[] = { 0x63, 0x03 };
616*4882a593Smuzhiyun static const __u8 data_fin[] = { 0x08 };
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) {
621*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
622*4882a593Smuzhiyun return 0;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun if (mode == 0) {
626*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
627*4882a593Smuzhiyun wiiproto_req_ir1(wdata, 0);
628*4882a593Smuzhiyun wiiproto_req_ir2(wdata, 0);
629*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
630*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
631*4882a593Smuzhiyun return 0;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun ret = wiimote_cmd_acquire(wdata);
637*4882a593Smuzhiyun if (ret)
638*4882a593Smuzhiyun return ret;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun /* send PIXEL CLOCK ENABLE cmd first */
641*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
642*4882a593Smuzhiyun wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0);
643*4882a593Smuzhiyun wiiproto_req_ir1(wdata, 0x06);
644*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun ret = wiimote_cmd_wait(wdata);
647*4882a593Smuzhiyun if (ret)
648*4882a593Smuzhiyun goto unlock;
649*4882a593Smuzhiyun if (wdata->state.cmd_err) {
650*4882a593Smuzhiyun ret = -EIO;
651*4882a593Smuzhiyun goto unlock;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun /* enable IR LOGIC */
655*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
656*4882a593Smuzhiyun wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0);
657*4882a593Smuzhiyun wiiproto_req_ir2(wdata, 0x06);
658*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun ret = wiimote_cmd_wait(wdata);
661*4882a593Smuzhiyun if (ret)
662*4882a593Smuzhiyun goto unlock;
663*4882a593Smuzhiyun if (wdata->state.cmd_err) {
664*4882a593Smuzhiyun ret = -EIO;
665*4882a593Smuzhiyun goto unlock;
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* enable IR cam but do not make it send data, yet */
669*4882a593Smuzhiyun ret = wiimote_cmd_write(wdata, 0xb00030, data_enable,
670*4882a593Smuzhiyun sizeof(data_enable));
671*4882a593Smuzhiyun if (ret)
672*4882a593Smuzhiyun goto unlock;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun /* write first sensitivity block */
675*4882a593Smuzhiyun ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1,
676*4882a593Smuzhiyun sizeof(data_sens1));
677*4882a593Smuzhiyun if (ret)
678*4882a593Smuzhiyun goto unlock;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun /* write second sensitivity block */
681*4882a593Smuzhiyun ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2,
682*4882a593Smuzhiyun sizeof(data_sens2));
683*4882a593Smuzhiyun if (ret)
684*4882a593Smuzhiyun goto unlock;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /* put IR cam into desired state */
687*4882a593Smuzhiyun switch (mode) {
688*4882a593Smuzhiyun case WIIPROTO_FLAG_IR_FULL:
689*4882a593Smuzhiyun format = 5;
690*4882a593Smuzhiyun break;
691*4882a593Smuzhiyun case WIIPROTO_FLAG_IR_EXT:
692*4882a593Smuzhiyun format = 3;
693*4882a593Smuzhiyun break;
694*4882a593Smuzhiyun case WIIPROTO_FLAG_IR_BASIC:
695*4882a593Smuzhiyun format = 1;
696*4882a593Smuzhiyun break;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format));
699*4882a593Smuzhiyun if (ret)
700*4882a593Smuzhiyun goto unlock;
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun /* make IR cam send data */
703*4882a593Smuzhiyun ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin));
704*4882a593Smuzhiyun if (ret)
705*4882a593Smuzhiyun goto unlock;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun /* request new DRM mode compatible to IR mode */
708*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
709*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAGS_IR;
710*4882a593Smuzhiyun wdata->state.flags |= mode & WIIPROTO_FLAGS_IR;
711*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
712*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun unlock:
715*4882a593Smuzhiyun wiimote_cmd_release(wdata);
716*4882a593Smuzhiyun return ret;
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
wiimod_ir_open(struct input_dev * dev)719*4882a593Smuzhiyun static int wiimod_ir_open(struct input_dev *dev)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun return wiimod_ir_change(wdata, WIIPROTO_FLAG_IR_BASIC);
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
wiimod_ir_close(struct input_dev * dev)726*4882a593Smuzhiyun static void wiimod_ir_close(struct input_dev *dev)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun wiimod_ir_change(wdata, 0);
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun
wiimod_ir_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)733*4882a593Smuzhiyun static int wiimod_ir_probe(const struct wiimod_ops *ops,
734*4882a593Smuzhiyun struct wiimote_data *wdata)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun int ret;
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun wdata->ir = input_allocate_device();
739*4882a593Smuzhiyun if (!wdata->ir)
740*4882a593Smuzhiyun return -ENOMEM;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun input_set_drvdata(wdata->ir, wdata);
743*4882a593Smuzhiyun wdata->ir->open = wiimod_ir_open;
744*4882a593Smuzhiyun wdata->ir->close = wiimod_ir_close;
745*4882a593Smuzhiyun wdata->ir->dev.parent = &wdata->hdev->dev;
746*4882a593Smuzhiyun wdata->ir->id.bustype = wdata->hdev->bus;
747*4882a593Smuzhiyun wdata->ir->id.vendor = wdata->hdev->vendor;
748*4882a593Smuzhiyun wdata->ir->id.product = wdata->hdev->product;
749*4882a593Smuzhiyun wdata->ir->id.version = wdata->hdev->version;
750*4882a593Smuzhiyun wdata->ir->name = WIIMOTE_NAME " IR";
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun set_bit(EV_ABS, wdata->ir->evbit);
753*4882a593Smuzhiyun set_bit(ABS_HAT0X, wdata->ir->absbit);
754*4882a593Smuzhiyun set_bit(ABS_HAT0Y, wdata->ir->absbit);
755*4882a593Smuzhiyun set_bit(ABS_HAT1X, wdata->ir->absbit);
756*4882a593Smuzhiyun set_bit(ABS_HAT1Y, wdata->ir->absbit);
757*4882a593Smuzhiyun set_bit(ABS_HAT2X, wdata->ir->absbit);
758*4882a593Smuzhiyun set_bit(ABS_HAT2Y, wdata->ir->absbit);
759*4882a593Smuzhiyun set_bit(ABS_HAT3X, wdata->ir->absbit);
760*4882a593Smuzhiyun set_bit(ABS_HAT3Y, wdata->ir->absbit);
761*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4);
762*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4);
763*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4);
764*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4);
765*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4);
766*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4);
767*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4);
768*4882a593Smuzhiyun input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4);
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun ret = input_register_device(wdata->ir);
771*4882a593Smuzhiyun if (ret) {
772*4882a593Smuzhiyun hid_err(wdata->hdev, "cannot register input device\n");
773*4882a593Smuzhiyun goto err_free;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun return 0;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun err_free:
779*4882a593Smuzhiyun input_free_device(wdata->ir);
780*4882a593Smuzhiyun wdata->ir = NULL;
781*4882a593Smuzhiyun return ret;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
wiimod_ir_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)784*4882a593Smuzhiyun static void wiimod_ir_remove(const struct wiimod_ops *ops,
785*4882a593Smuzhiyun struct wiimote_data *wdata)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun if (!wdata->ir)
788*4882a593Smuzhiyun return;
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun input_unregister_device(wdata->ir);
791*4882a593Smuzhiyun wdata->ir = NULL;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun static const struct wiimod_ops wiimod_ir = {
795*4882a593Smuzhiyun .flags = 0,
796*4882a593Smuzhiyun .arg = 0,
797*4882a593Smuzhiyun .probe = wiimod_ir_probe,
798*4882a593Smuzhiyun .remove = wiimod_ir_remove,
799*4882a593Smuzhiyun .in_ir = wiimod_ir_in_ir,
800*4882a593Smuzhiyun };
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun /*
803*4882a593Smuzhiyun * Nunchuk Extension
804*4882a593Smuzhiyun * The Nintendo Wii Nunchuk was the first official extension published by
805*4882a593Smuzhiyun * Nintendo. It provides two additional keys and a separate accelerometer. It
806*4882a593Smuzhiyun * can be hotplugged to standard Wii Remotes.
807*4882a593Smuzhiyun */
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun enum wiimod_nunchuk_keys {
810*4882a593Smuzhiyun WIIMOD_NUNCHUK_KEY_C,
811*4882a593Smuzhiyun WIIMOD_NUNCHUK_KEY_Z,
812*4882a593Smuzhiyun WIIMOD_NUNCHUK_KEY_NUM,
813*4882a593Smuzhiyun };
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun static const __u16 wiimod_nunchuk_map[] = {
816*4882a593Smuzhiyun BTN_C, /* WIIMOD_NUNCHUK_KEY_C */
817*4882a593Smuzhiyun BTN_Z, /* WIIMOD_NUNCHUK_KEY_Z */
818*4882a593Smuzhiyun };
819*4882a593Smuzhiyun
wiimod_nunchuk_in_ext(struct wiimote_data * wdata,const __u8 * ext)820*4882a593Smuzhiyun static void wiimod_nunchuk_in_ext(struct wiimote_data *wdata, const __u8 *ext)
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun __s16 x, y, z, bx, by;
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 |
825*4882a593Smuzhiyun * -----+----------+---------+---------+----+-----+
826*4882a593Smuzhiyun * 1 | Button X <7:0> |
827*4882a593Smuzhiyun * 2 | Button Y <7:0> |
828*4882a593Smuzhiyun * -----+----------+---------+---------+----+-----+
829*4882a593Smuzhiyun * 3 | Speed X <9:2> |
830*4882a593Smuzhiyun * 4 | Speed Y <9:2> |
831*4882a593Smuzhiyun * 5 | Speed Z <9:2> |
832*4882a593Smuzhiyun * -----+----------+---------+---------+----+-----+
833*4882a593Smuzhiyun * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ |
834*4882a593Smuzhiyun * -----+----------+---------+---------+----+-----+
835*4882a593Smuzhiyun * Button X/Y is the analog stick. Speed X, Y and Z are the
836*4882a593Smuzhiyun * accelerometer data in the same format as the wiimote's accelerometer.
837*4882a593Smuzhiyun * The 6th byte contains the LSBs of the accelerometer data.
838*4882a593Smuzhiyun * BC and BZ are the C and Z buttons: 0 means pressed
839*4882a593Smuzhiyun *
840*4882a593Smuzhiyun * If reported interleaved with motionp, then the layout changes. The
841*4882a593Smuzhiyun * 5th and 6th byte changes to:
842*4882a593Smuzhiyun * -----+-----------------------------------+-----+
843*4882a593Smuzhiyun * 5 | Speed Z <9:3> | EXT |
844*4882a593Smuzhiyun * -----+--------+-----+-----+----+----+----+-----+
845*4882a593Smuzhiyun * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 |
846*4882a593Smuzhiyun * -----+--------+-----+-----+----+----+----+-----+
847*4882a593Smuzhiyun * All three accelerometer values lose their LSB. The other data is
848*4882a593Smuzhiyun * still available but slightly moved.
849*4882a593Smuzhiyun *
850*4882a593Smuzhiyun * Center data for button values is 128. Center value for accelerometer
851*4882a593Smuzhiyun * values it 512 / 0x200
852*4882a593Smuzhiyun */
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun bx = ext[0];
855*4882a593Smuzhiyun by = ext[1];
856*4882a593Smuzhiyun bx -= 128;
857*4882a593Smuzhiyun by -= 128;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun x = ext[2] << 2;
860*4882a593Smuzhiyun y = ext[3] << 2;
861*4882a593Smuzhiyun z = ext[4] << 2;
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
864*4882a593Smuzhiyun x |= (ext[5] >> 3) & 0x02;
865*4882a593Smuzhiyun y |= (ext[5] >> 4) & 0x02;
866*4882a593Smuzhiyun z &= ~0x4;
867*4882a593Smuzhiyun z |= (ext[5] >> 5) & 0x06;
868*4882a593Smuzhiyun } else {
869*4882a593Smuzhiyun x |= (ext[5] >> 2) & 0x03;
870*4882a593Smuzhiyun y |= (ext[5] >> 4) & 0x03;
871*4882a593Smuzhiyun z |= (ext[5] >> 6) & 0x03;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun x -= 0x200;
875*4882a593Smuzhiyun y -= 0x200;
876*4882a593Smuzhiyun z -= 0x200;
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT0X, bx);
879*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT0Y, by);
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_RX, x);
882*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_RY, y);
883*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_RZ, z);
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
886*4882a593Smuzhiyun input_report_key(wdata->extension.input,
887*4882a593Smuzhiyun wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_Z],
888*4882a593Smuzhiyun !(ext[5] & 0x04));
889*4882a593Smuzhiyun input_report_key(wdata->extension.input,
890*4882a593Smuzhiyun wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_C],
891*4882a593Smuzhiyun !(ext[5] & 0x08));
892*4882a593Smuzhiyun } else {
893*4882a593Smuzhiyun input_report_key(wdata->extension.input,
894*4882a593Smuzhiyun wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_Z],
895*4882a593Smuzhiyun !(ext[5] & 0x01));
896*4882a593Smuzhiyun input_report_key(wdata->extension.input,
897*4882a593Smuzhiyun wiimod_nunchuk_map[WIIMOD_NUNCHUK_KEY_C],
898*4882a593Smuzhiyun !(ext[5] & 0x02));
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun input_sync(wdata->extension.input);
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun
wiimod_nunchuk_open(struct input_dev * dev)904*4882a593Smuzhiyun static int wiimod_nunchuk_open(struct input_dev *dev)
905*4882a593Smuzhiyun {
906*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
907*4882a593Smuzhiyun unsigned long flags;
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
910*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
911*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
912*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun return 0;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
wiimod_nunchuk_close(struct input_dev * dev)917*4882a593Smuzhiyun static void wiimod_nunchuk_close(struct input_dev *dev)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
920*4882a593Smuzhiyun unsigned long flags;
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
923*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
924*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
925*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
wiimod_nunchuk_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)928*4882a593Smuzhiyun static int wiimod_nunchuk_probe(const struct wiimod_ops *ops,
929*4882a593Smuzhiyun struct wiimote_data *wdata)
930*4882a593Smuzhiyun {
931*4882a593Smuzhiyun int ret, i;
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun wdata->extension.input = input_allocate_device();
934*4882a593Smuzhiyun if (!wdata->extension.input)
935*4882a593Smuzhiyun return -ENOMEM;
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun input_set_drvdata(wdata->extension.input, wdata);
938*4882a593Smuzhiyun wdata->extension.input->open = wiimod_nunchuk_open;
939*4882a593Smuzhiyun wdata->extension.input->close = wiimod_nunchuk_close;
940*4882a593Smuzhiyun wdata->extension.input->dev.parent = &wdata->hdev->dev;
941*4882a593Smuzhiyun wdata->extension.input->id.bustype = wdata->hdev->bus;
942*4882a593Smuzhiyun wdata->extension.input->id.vendor = wdata->hdev->vendor;
943*4882a593Smuzhiyun wdata->extension.input->id.product = wdata->hdev->product;
944*4882a593Smuzhiyun wdata->extension.input->id.version = wdata->hdev->version;
945*4882a593Smuzhiyun wdata->extension.input->name = WIIMOTE_NAME " Nunchuk";
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun set_bit(EV_KEY, wdata->extension.input->evbit);
948*4882a593Smuzhiyun for (i = 0; i < WIIMOD_NUNCHUK_KEY_NUM; ++i)
949*4882a593Smuzhiyun set_bit(wiimod_nunchuk_map[i],
950*4882a593Smuzhiyun wdata->extension.input->keybit);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun set_bit(EV_ABS, wdata->extension.input->evbit);
953*4882a593Smuzhiyun set_bit(ABS_HAT0X, wdata->extension.input->absbit);
954*4882a593Smuzhiyun set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
955*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
956*4882a593Smuzhiyun ABS_HAT0X, -120, 120, 2, 4);
957*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
958*4882a593Smuzhiyun ABS_HAT0Y, -120, 120, 2, 4);
959*4882a593Smuzhiyun set_bit(ABS_RX, wdata->extension.input->absbit);
960*4882a593Smuzhiyun set_bit(ABS_RY, wdata->extension.input->absbit);
961*4882a593Smuzhiyun set_bit(ABS_RZ, wdata->extension.input->absbit);
962*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
963*4882a593Smuzhiyun ABS_RX, -500, 500, 2, 4);
964*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
965*4882a593Smuzhiyun ABS_RY, -500, 500, 2, 4);
966*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
967*4882a593Smuzhiyun ABS_RZ, -500, 500, 2, 4);
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun ret = input_register_device(wdata->extension.input);
970*4882a593Smuzhiyun if (ret)
971*4882a593Smuzhiyun goto err_free;
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun return 0;
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun err_free:
976*4882a593Smuzhiyun input_free_device(wdata->extension.input);
977*4882a593Smuzhiyun wdata->extension.input = NULL;
978*4882a593Smuzhiyun return ret;
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun
wiimod_nunchuk_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)981*4882a593Smuzhiyun static void wiimod_nunchuk_remove(const struct wiimod_ops *ops,
982*4882a593Smuzhiyun struct wiimote_data *wdata)
983*4882a593Smuzhiyun {
984*4882a593Smuzhiyun if (!wdata->extension.input)
985*4882a593Smuzhiyun return;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun input_unregister_device(wdata->extension.input);
988*4882a593Smuzhiyun wdata->extension.input = NULL;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun static const struct wiimod_ops wiimod_nunchuk = {
992*4882a593Smuzhiyun .flags = 0,
993*4882a593Smuzhiyun .arg = 0,
994*4882a593Smuzhiyun .probe = wiimod_nunchuk_probe,
995*4882a593Smuzhiyun .remove = wiimod_nunchuk_remove,
996*4882a593Smuzhiyun .in_ext = wiimod_nunchuk_in_ext,
997*4882a593Smuzhiyun };
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun /*
1000*4882a593Smuzhiyun * Classic Controller
1001*4882a593Smuzhiyun * Another official extension from Nintendo. It provides a classic
1002*4882a593Smuzhiyun * gamecube-like controller that can be hotplugged on the Wii Remote.
1003*4882a593Smuzhiyun * It has several hardware buttons and switches that are all reported via
1004*4882a593Smuzhiyun * a normal extension device.
1005*4882a593Smuzhiyun */
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun enum wiimod_classic_keys {
1008*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_A,
1009*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_B,
1010*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_X,
1011*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_Y,
1012*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_ZL,
1013*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_ZR,
1014*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_PLUS,
1015*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_MINUS,
1016*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_HOME,
1017*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_LEFT,
1018*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_RIGHT,
1019*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_UP,
1020*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_DOWN,
1021*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_LT,
1022*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_RT,
1023*4882a593Smuzhiyun WIIMOD_CLASSIC_KEY_NUM,
1024*4882a593Smuzhiyun };
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun static const __u16 wiimod_classic_map[] = {
1027*4882a593Smuzhiyun BTN_A, /* WIIMOD_CLASSIC_KEY_A */
1028*4882a593Smuzhiyun BTN_B, /* WIIMOD_CLASSIC_KEY_B */
1029*4882a593Smuzhiyun BTN_X, /* WIIMOD_CLASSIC_KEY_X */
1030*4882a593Smuzhiyun BTN_Y, /* WIIMOD_CLASSIC_KEY_Y */
1031*4882a593Smuzhiyun BTN_TL2, /* WIIMOD_CLASSIC_KEY_ZL */
1032*4882a593Smuzhiyun BTN_TR2, /* WIIMOD_CLASSIC_KEY_ZR */
1033*4882a593Smuzhiyun KEY_NEXT, /* WIIMOD_CLASSIC_KEY_PLUS */
1034*4882a593Smuzhiyun KEY_PREVIOUS, /* WIIMOD_CLASSIC_KEY_MINUS */
1035*4882a593Smuzhiyun BTN_MODE, /* WIIMOD_CLASSIC_KEY_HOME */
1036*4882a593Smuzhiyun KEY_LEFT, /* WIIMOD_CLASSIC_KEY_LEFT */
1037*4882a593Smuzhiyun KEY_RIGHT, /* WIIMOD_CLASSIC_KEY_RIGHT */
1038*4882a593Smuzhiyun KEY_UP, /* WIIMOD_CLASSIC_KEY_UP */
1039*4882a593Smuzhiyun KEY_DOWN, /* WIIMOD_CLASSIC_KEY_DOWN */
1040*4882a593Smuzhiyun BTN_TL, /* WIIMOD_CLASSIC_KEY_LT */
1041*4882a593Smuzhiyun BTN_TR, /* WIIMOD_CLASSIC_KEY_RT */
1042*4882a593Smuzhiyun };
1043*4882a593Smuzhiyun
wiimod_classic_in_ext(struct wiimote_data * wdata,const __u8 * ext)1044*4882a593Smuzhiyun static void wiimod_classic_in_ext(struct wiimote_data *wdata, const __u8 *ext)
1045*4882a593Smuzhiyun {
1046*4882a593Smuzhiyun __s8 rx, ry, lx, ly, lt, rt;
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
1049*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1050*4882a593Smuzhiyun * 1 | RX <5:4> | LX <5:0> |
1051*4882a593Smuzhiyun * 2 | RX <3:2> | LY <5:0> |
1052*4882a593Smuzhiyun * -----+-----+-----+-----+-----------------------------+
1053*4882a593Smuzhiyun * 3 |RX<1>| LT <5:4> | RY <5:1> |
1054*4882a593Smuzhiyun * -----+-----+-----------+-----------------------------+
1055*4882a593Smuzhiyun * 4 | LT <3:1> | RT <5:1> |
1056*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1057*4882a593Smuzhiyun * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 |
1058*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1059*4882a593Smuzhiyun * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU |
1060*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1061*4882a593Smuzhiyun * All buttons are 0 if pressed
1062*4882a593Smuzhiyun * RX and RY are right analog stick
1063*4882a593Smuzhiyun * LX and LY are left analog stick
1064*4882a593Smuzhiyun * LT is left trigger, RT is right trigger
1065*4882a593Smuzhiyun * BLT is 0 if left trigger is fully pressed
1066*4882a593Smuzhiyun * BRT is 0 if right trigger is fully pressed
1067*4882a593Smuzhiyun * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons
1068*4882a593Smuzhiyun * BZL is left Z button and BZR is right Z button
1069*4882a593Smuzhiyun * B-, BH, B+ are +, HOME and - buttons
1070*4882a593Smuzhiyun * BB, BY, BA, BX are A, B, X, Y buttons
1071*4882a593Smuzhiyun * LSB of RX, RY, LT, and RT are not transmitted and always 0.
1072*4882a593Smuzhiyun *
1073*4882a593Smuzhiyun * With motionp enabled it changes slightly to this:
1074*4882a593Smuzhiyun * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
1075*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1076*4882a593Smuzhiyun * 1 | RX <5:4> | LX <5:1> | BDU |
1077*4882a593Smuzhiyun * 2 | RX <3:2> | LY <5:1> | BDL |
1078*4882a593Smuzhiyun * -----+-----+-----+-----+-----------------------+-----+
1079*4882a593Smuzhiyun * 3 |RX<1>| LT <5:4> | RY <5:1> |
1080*4882a593Smuzhiyun * -----+-----+-----------+-----------------------------+
1081*4882a593Smuzhiyun * 4 | LT <3:1> | RT <5:1> |
1082*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1083*4882a593Smuzhiyun * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT |
1084*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1085*4882a593Smuzhiyun * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 |
1086*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1087*4882a593Smuzhiyun * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest
1088*4882a593Smuzhiyun * is the same as before.
1089*4882a593Smuzhiyun */
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun static const s8 digital_to_analog[3] = {0x20, 0, -0x20};
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
1094*4882a593Smuzhiyun if (wiimote_dpad_as_analog) {
1095*4882a593Smuzhiyun lx = digital_to_analog[1 - !(ext[4] & 0x80)
1096*4882a593Smuzhiyun + !(ext[1] & 0x01)];
1097*4882a593Smuzhiyun ly = digital_to_analog[1 - !(ext[4] & 0x40)
1098*4882a593Smuzhiyun + !(ext[0] & 0x01)];
1099*4882a593Smuzhiyun } else {
1100*4882a593Smuzhiyun lx = (ext[0] & 0x3e) - 0x20;
1101*4882a593Smuzhiyun ly = (ext[1] & 0x3e) - 0x20;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun } else {
1104*4882a593Smuzhiyun if (wiimote_dpad_as_analog) {
1105*4882a593Smuzhiyun lx = digital_to_analog[1 - !(ext[4] & 0x80)
1106*4882a593Smuzhiyun + !(ext[5] & 0x02)];
1107*4882a593Smuzhiyun ly = digital_to_analog[1 - !(ext[4] & 0x40)
1108*4882a593Smuzhiyun + !(ext[5] & 0x01)];
1109*4882a593Smuzhiyun } else {
1110*4882a593Smuzhiyun lx = (ext[0] & 0x3f) - 0x20;
1111*4882a593Smuzhiyun ly = (ext[1] & 0x3f) - 0x20;
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun rx = (ext[0] >> 3) & 0x18;
1116*4882a593Smuzhiyun rx |= (ext[1] >> 5) & 0x06;
1117*4882a593Smuzhiyun rx |= (ext[2] >> 7) & 0x01;
1118*4882a593Smuzhiyun ry = ext[2] & 0x1f;
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun rt = ext[3] & 0x1f;
1121*4882a593Smuzhiyun lt = (ext[2] >> 2) & 0x18;
1122*4882a593Smuzhiyun lt |= (ext[3] >> 5) & 0x07;
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun rx <<= 1;
1125*4882a593Smuzhiyun ry <<= 1;
1126*4882a593Smuzhiyun rt <<= 1;
1127*4882a593Smuzhiyun lt <<= 1;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT1X, lx);
1130*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT1Y, ly);
1131*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT2X, rx - 0x20);
1132*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT2Y, ry - 0x20);
1133*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT3X, rt);
1134*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT3Y, lt);
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1137*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_LT],
1138*4882a593Smuzhiyun !(ext[4] & 0x20));
1139*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1140*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_MINUS],
1141*4882a593Smuzhiyun !(ext[4] & 0x10));
1142*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1143*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_HOME],
1144*4882a593Smuzhiyun !(ext[4] & 0x08));
1145*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1146*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_PLUS],
1147*4882a593Smuzhiyun !(ext[4] & 0x04));
1148*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1149*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_RT],
1150*4882a593Smuzhiyun !(ext[4] & 0x02));
1151*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1152*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZL],
1153*4882a593Smuzhiyun !(ext[5] & 0x80));
1154*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1155*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_B],
1156*4882a593Smuzhiyun !(ext[5] & 0x40));
1157*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1158*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_Y],
1159*4882a593Smuzhiyun !(ext[5] & 0x20));
1160*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1161*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_A],
1162*4882a593Smuzhiyun !(ext[5] & 0x10));
1163*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1164*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_X],
1165*4882a593Smuzhiyun !(ext[5] & 0x08));
1166*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1167*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_ZR],
1168*4882a593Smuzhiyun !(ext[5] & 0x04));
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun if (!wiimote_dpad_as_analog) {
1171*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1172*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_RIGHT],
1173*4882a593Smuzhiyun !(ext[4] & 0x80));
1174*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1175*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_DOWN],
1176*4882a593Smuzhiyun !(ext[4] & 0x40));
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
1179*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1180*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
1181*4882a593Smuzhiyun !(ext[1] & 0x01));
1182*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1183*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
1184*4882a593Smuzhiyun !(ext[0] & 0x01));
1185*4882a593Smuzhiyun } else {
1186*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1187*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_LEFT],
1188*4882a593Smuzhiyun !(ext[5] & 0x02));
1189*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1190*4882a593Smuzhiyun wiimod_classic_map[WIIMOD_CLASSIC_KEY_UP],
1191*4882a593Smuzhiyun !(ext[5] & 0x01));
1192*4882a593Smuzhiyun }
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun input_sync(wdata->extension.input);
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun
wiimod_classic_open(struct input_dev * dev)1198*4882a593Smuzhiyun static int wiimod_classic_open(struct input_dev *dev)
1199*4882a593Smuzhiyun {
1200*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1201*4882a593Smuzhiyun unsigned long flags;
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1204*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
1205*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1206*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun return 0;
1209*4882a593Smuzhiyun }
1210*4882a593Smuzhiyun
wiimod_classic_close(struct input_dev * dev)1211*4882a593Smuzhiyun static void wiimod_classic_close(struct input_dev *dev)
1212*4882a593Smuzhiyun {
1213*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1214*4882a593Smuzhiyun unsigned long flags;
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1217*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
1218*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1219*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1220*4882a593Smuzhiyun }
1221*4882a593Smuzhiyun
wiimod_classic_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)1222*4882a593Smuzhiyun static int wiimod_classic_probe(const struct wiimod_ops *ops,
1223*4882a593Smuzhiyun struct wiimote_data *wdata)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun int ret, i;
1226*4882a593Smuzhiyun
1227*4882a593Smuzhiyun wdata->extension.input = input_allocate_device();
1228*4882a593Smuzhiyun if (!wdata->extension.input)
1229*4882a593Smuzhiyun return -ENOMEM;
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun input_set_drvdata(wdata->extension.input, wdata);
1232*4882a593Smuzhiyun wdata->extension.input->open = wiimod_classic_open;
1233*4882a593Smuzhiyun wdata->extension.input->close = wiimod_classic_close;
1234*4882a593Smuzhiyun wdata->extension.input->dev.parent = &wdata->hdev->dev;
1235*4882a593Smuzhiyun wdata->extension.input->id.bustype = wdata->hdev->bus;
1236*4882a593Smuzhiyun wdata->extension.input->id.vendor = wdata->hdev->vendor;
1237*4882a593Smuzhiyun wdata->extension.input->id.product = wdata->hdev->product;
1238*4882a593Smuzhiyun wdata->extension.input->id.version = wdata->hdev->version;
1239*4882a593Smuzhiyun wdata->extension.input->name = WIIMOTE_NAME " Classic Controller";
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun set_bit(EV_KEY, wdata->extension.input->evbit);
1242*4882a593Smuzhiyun for (i = 0; i < WIIMOD_CLASSIC_KEY_NUM; ++i)
1243*4882a593Smuzhiyun set_bit(wiimod_classic_map[i],
1244*4882a593Smuzhiyun wdata->extension.input->keybit);
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun set_bit(EV_ABS, wdata->extension.input->evbit);
1247*4882a593Smuzhiyun set_bit(ABS_HAT1X, wdata->extension.input->absbit);
1248*4882a593Smuzhiyun set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
1249*4882a593Smuzhiyun set_bit(ABS_HAT2X, wdata->extension.input->absbit);
1250*4882a593Smuzhiyun set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
1251*4882a593Smuzhiyun set_bit(ABS_HAT3X, wdata->extension.input->absbit);
1252*4882a593Smuzhiyun set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
1253*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1254*4882a593Smuzhiyun ABS_HAT1X, -30, 30, 1, 1);
1255*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1256*4882a593Smuzhiyun ABS_HAT1Y, -30, 30, 1, 1);
1257*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1258*4882a593Smuzhiyun ABS_HAT2X, -30, 30, 1, 1);
1259*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1260*4882a593Smuzhiyun ABS_HAT2Y, -30, 30, 1, 1);
1261*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1262*4882a593Smuzhiyun ABS_HAT3X, -30, 30, 1, 1);
1263*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1264*4882a593Smuzhiyun ABS_HAT3Y, -30, 30, 1, 1);
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun ret = input_register_device(wdata->extension.input);
1267*4882a593Smuzhiyun if (ret)
1268*4882a593Smuzhiyun goto err_free;
1269*4882a593Smuzhiyun
1270*4882a593Smuzhiyun return 0;
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun err_free:
1273*4882a593Smuzhiyun input_free_device(wdata->extension.input);
1274*4882a593Smuzhiyun wdata->extension.input = NULL;
1275*4882a593Smuzhiyun return ret;
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun
wiimod_classic_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)1278*4882a593Smuzhiyun static void wiimod_classic_remove(const struct wiimod_ops *ops,
1279*4882a593Smuzhiyun struct wiimote_data *wdata)
1280*4882a593Smuzhiyun {
1281*4882a593Smuzhiyun if (!wdata->extension.input)
1282*4882a593Smuzhiyun return;
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun input_unregister_device(wdata->extension.input);
1285*4882a593Smuzhiyun wdata->extension.input = NULL;
1286*4882a593Smuzhiyun }
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun static const struct wiimod_ops wiimod_classic = {
1289*4882a593Smuzhiyun .flags = 0,
1290*4882a593Smuzhiyun .arg = 0,
1291*4882a593Smuzhiyun .probe = wiimod_classic_probe,
1292*4882a593Smuzhiyun .remove = wiimod_classic_remove,
1293*4882a593Smuzhiyun .in_ext = wiimod_classic_in_ext,
1294*4882a593Smuzhiyun };
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun /*
1297*4882a593Smuzhiyun * Balance Board Extension
1298*4882a593Smuzhiyun * The Nintendo Wii Balance Board provides four hardware weight sensor plus a
1299*4882a593Smuzhiyun * single push button. No other peripherals are available. However, the
1300*4882a593Smuzhiyun * balance-board data is sent via a standard Wii Remote extension. All other
1301*4882a593Smuzhiyun * data for non-present hardware is zeroed out.
1302*4882a593Smuzhiyun * Some 3rd party devices react allergic if we try to access normal Wii Remote
1303*4882a593Smuzhiyun * hardware, so this extension module should be the only module that is loaded
1304*4882a593Smuzhiyun * on balance boards.
1305*4882a593Smuzhiyun * The balance board needs 8 bytes extension data instead of basic 6 bytes so
1306*4882a593Smuzhiyun * it needs the WIIMOD_FLAG_EXT8 flag.
1307*4882a593Smuzhiyun */
1308*4882a593Smuzhiyun
wiimod_bboard_in_keys(struct wiimote_data * wdata,const __u8 * keys)1309*4882a593Smuzhiyun static void wiimod_bboard_in_keys(struct wiimote_data *wdata, const __u8 *keys)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun input_report_key(wdata->extension.input, BTN_A,
1312*4882a593Smuzhiyun !!(keys[1] & 0x08));
1313*4882a593Smuzhiyun input_sync(wdata->extension.input);
1314*4882a593Smuzhiyun }
1315*4882a593Smuzhiyun
wiimod_bboard_in_ext(struct wiimote_data * wdata,const __u8 * ext)1316*4882a593Smuzhiyun static void wiimod_bboard_in_ext(struct wiimote_data *wdata,
1317*4882a593Smuzhiyun const __u8 *ext)
1318*4882a593Smuzhiyun {
1319*4882a593Smuzhiyun __s32 val[4], tmp, div;
1320*4882a593Smuzhiyun unsigned int i;
1321*4882a593Smuzhiyun struct wiimote_state *s = &wdata->state;
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun /*
1324*4882a593Smuzhiyun * Balance board data layout:
1325*4882a593Smuzhiyun *
1326*4882a593Smuzhiyun * Byte | 8 7 6 5 4 3 2 1 |
1327*4882a593Smuzhiyun * -----+--------------------------+
1328*4882a593Smuzhiyun * 1 | Top Right <15:8> |
1329*4882a593Smuzhiyun * 2 | Top Right <7:0> |
1330*4882a593Smuzhiyun * -----+--------------------------+
1331*4882a593Smuzhiyun * 3 | Bottom Right <15:8> |
1332*4882a593Smuzhiyun * 4 | Bottom Right <7:0> |
1333*4882a593Smuzhiyun * -----+--------------------------+
1334*4882a593Smuzhiyun * 5 | Top Left <15:8> |
1335*4882a593Smuzhiyun * 6 | Top Left <7:0> |
1336*4882a593Smuzhiyun * -----+--------------------------+
1337*4882a593Smuzhiyun * 7 | Bottom Left <15:8> |
1338*4882a593Smuzhiyun * 8 | Bottom Left <7:0> |
1339*4882a593Smuzhiyun * -----+--------------------------+
1340*4882a593Smuzhiyun *
1341*4882a593Smuzhiyun * These values represent the weight-measurements of the Wii-balance
1342*4882a593Smuzhiyun * board with 16bit precision.
1343*4882a593Smuzhiyun *
1344*4882a593Smuzhiyun * The balance-board is never reported interleaved with motionp.
1345*4882a593Smuzhiyun */
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun val[0] = ext[0];
1348*4882a593Smuzhiyun val[0] <<= 8;
1349*4882a593Smuzhiyun val[0] |= ext[1];
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun val[1] = ext[2];
1352*4882a593Smuzhiyun val[1] <<= 8;
1353*4882a593Smuzhiyun val[1] |= ext[3];
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun val[2] = ext[4];
1356*4882a593Smuzhiyun val[2] <<= 8;
1357*4882a593Smuzhiyun val[2] |= ext[5];
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun val[3] = ext[6];
1360*4882a593Smuzhiyun val[3] <<= 8;
1361*4882a593Smuzhiyun val[3] |= ext[7];
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun /* apply calibration data */
1364*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1365*4882a593Smuzhiyun if (val[i] <= s->calib_bboard[i][0]) {
1366*4882a593Smuzhiyun tmp = 0;
1367*4882a593Smuzhiyun } else if (val[i] < s->calib_bboard[i][1]) {
1368*4882a593Smuzhiyun tmp = val[i] - s->calib_bboard[i][0];
1369*4882a593Smuzhiyun tmp *= 1700;
1370*4882a593Smuzhiyun div = s->calib_bboard[i][1] - s->calib_bboard[i][0];
1371*4882a593Smuzhiyun tmp /= div ? div : 1;
1372*4882a593Smuzhiyun } else {
1373*4882a593Smuzhiyun tmp = val[i] - s->calib_bboard[i][1];
1374*4882a593Smuzhiyun tmp *= 1700;
1375*4882a593Smuzhiyun div = s->calib_bboard[i][2] - s->calib_bboard[i][1];
1376*4882a593Smuzhiyun tmp /= div ? div : 1;
1377*4882a593Smuzhiyun tmp += 1700;
1378*4882a593Smuzhiyun }
1379*4882a593Smuzhiyun val[i] = tmp;
1380*4882a593Smuzhiyun }
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT0X, val[0]);
1383*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT0Y, val[1]);
1384*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT1X, val[2]);
1385*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT1Y, val[3]);
1386*4882a593Smuzhiyun input_sync(wdata->extension.input);
1387*4882a593Smuzhiyun }
1388*4882a593Smuzhiyun
wiimod_bboard_open(struct input_dev * dev)1389*4882a593Smuzhiyun static int wiimod_bboard_open(struct input_dev *dev)
1390*4882a593Smuzhiyun {
1391*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1392*4882a593Smuzhiyun unsigned long flags;
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1395*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
1396*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1397*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun return 0;
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun
wiimod_bboard_close(struct input_dev * dev)1402*4882a593Smuzhiyun static void wiimod_bboard_close(struct input_dev *dev)
1403*4882a593Smuzhiyun {
1404*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1405*4882a593Smuzhiyun unsigned long flags;
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1408*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
1409*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1410*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1411*4882a593Smuzhiyun }
1412*4882a593Smuzhiyun
wiimod_bboard_calib_show(struct device * dev,struct device_attribute * attr,char * out)1413*4882a593Smuzhiyun static ssize_t wiimod_bboard_calib_show(struct device *dev,
1414*4882a593Smuzhiyun struct device_attribute *attr,
1415*4882a593Smuzhiyun char *out)
1416*4882a593Smuzhiyun {
1417*4882a593Smuzhiyun struct wiimote_data *wdata = dev_to_wii(dev);
1418*4882a593Smuzhiyun int i, j, ret;
1419*4882a593Smuzhiyun __u16 val;
1420*4882a593Smuzhiyun __u8 buf[24], offs;
1421*4882a593Smuzhiyun
1422*4882a593Smuzhiyun ret = wiimote_cmd_acquire(wdata);
1423*4882a593Smuzhiyun if (ret)
1424*4882a593Smuzhiyun return ret;
1425*4882a593Smuzhiyun
1426*4882a593Smuzhiyun ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12);
1427*4882a593Smuzhiyun if (ret != 12) {
1428*4882a593Smuzhiyun wiimote_cmd_release(wdata);
1429*4882a593Smuzhiyun return ret < 0 ? ret : -EIO;
1430*4882a593Smuzhiyun }
1431*4882a593Smuzhiyun ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12);
1432*4882a593Smuzhiyun if (ret != 12) {
1433*4882a593Smuzhiyun wiimote_cmd_release(wdata);
1434*4882a593Smuzhiyun return ret < 0 ? ret : -EIO;
1435*4882a593Smuzhiyun }
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun wiimote_cmd_release(wdata);
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun spin_lock_irq(&wdata->state.lock);
1440*4882a593Smuzhiyun offs = 0;
1441*4882a593Smuzhiyun for (i = 0; i < 3; ++i) {
1442*4882a593Smuzhiyun for (j = 0; j < 4; ++j) {
1443*4882a593Smuzhiyun wdata->state.calib_bboard[j][i] = buf[offs];
1444*4882a593Smuzhiyun wdata->state.calib_bboard[j][i] <<= 8;
1445*4882a593Smuzhiyun wdata->state.calib_bboard[j][i] |= buf[offs + 1];
1446*4882a593Smuzhiyun offs += 2;
1447*4882a593Smuzhiyun }
1448*4882a593Smuzhiyun }
1449*4882a593Smuzhiyun spin_unlock_irq(&wdata->state.lock);
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun ret = 0;
1452*4882a593Smuzhiyun for (i = 0; i < 3; ++i) {
1453*4882a593Smuzhiyun for (j = 0; j < 4; ++j) {
1454*4882a593Smuzhiyun val = wdata->state.calib_bboard[j][i];
1455*4882a593Smuzhiyun if (i == 2 && j == 3)
1456*4882a593Smuzhiyun ret += sprintf(&out[ret], "%04x\n", val);
1457*4882a593Smuzhiyun else
1458*4882a593Smuzhiyun ret += sprintf(&out[ret], "%04x:", val);
1459*4882a593Smuzhiyun }
1460*4882a593Smuzhiyun }
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun return ret;
1463*4882a593Smuzhiyun }
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun static DEVICE_ATTR(bboard_calib, S_IRUGO, wiimod_bboard_calib_show, NULL);
1466*4882a593Smuzhiyun
wiimod_bboard_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)1467*4882a593Smuzhiyun static int wiimod_bboard_probe(const struct wiimod_ops *ops,
1468*4882a593Smuzhiyun struct wiimote_data *wdata)
1469*4882a593Smuzhiyun {
1470*4882a593Smuzhiyun int ret, i, j;
1471*4882a593Smuzhiyun __u8 buf[24], offs;
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun wiimote_cmd_acquire_noint(wdata);
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun ret = wiimote_cmd_read(wdata, 0xa40024, buf, 12);
1476*4882a593Smuzhiyun if (ret != 12) {
1477*4882a593Smuzhiyun wiimote_cmd_release(wdata);
1478*4882a593Smuzhiyun return ret < 0 ? ret : -EIO;
1479*4882a593Smuzhiyun }
1480*4882a593Smuzhiyun ret = wiimote_cmd_read(wdata, 0xa40024 + 12, buf + 12, 12);
1481*4882a593Smuzhiyun if (ret != 12) {
1482*4882a593Smuzhiyun wiimote_cmd_release(wdata);
1483*4882a593Smuzhiyun return ret < 0 ? ret : -EIO;
1484*4882a593Smuzhiyun }
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun wiimote_cmd_release(wdata);
1487*4882a593Smuzhiyun
1488*4882a593Smuzhiyun offs = 0;
1489*4882a593Smuzhiyun for (i = 0; i < 3; ++i) {
1490*4882a593Smuzhiyun for (j = 0; j < 4; ++j) {
1491*4882a593Smuzhiyun wdata->state.calib_bboard[j][i] = buf[offs];
1492*4882a593Smuzhiyun wdata->state.calib_bboard[j][i] <<= 8;
1493*4882a593Smuzhiyun wdata->state.calib_bboard[j][i] |= buf[offs + 1];
1494*4882a593Smuzhiyun offs += 2;
1495*4882a593Smuzhiyun }
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun wdata->extension.input = input_allocate_device();
1499*4882a593Smuzhiyun if (!wdata->extension.input)
1500*4882a593Smuzhiyun return -ENOMEM;
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun ret = device_create_file(&wdata->hdev->dev,
1503*4882a593Smuzhiyun &dev_attr_bboard_calib);
1504*4882a593Smuzhiyun if (ret) {
1505*4882a593Smuzhiyun hid_err(wdata->hdev, "cannot create sysfs attribute\n");
1506*4882a593Smuzhiyun goto err_free;
1507*4882a593Smuzhiyun }
1508*4882a593Smuzhiyun
1509*4882a593Smuzhiyun input_set_drvdata(wdata->extension.input, wdata);
1510*4882a593Smuzhiyun wdata->extension.input->open = wiimod_bboard_open;
1511*4882a593Smuzhiyun wdata->extension.input->close = wiimod_bboard_close;
1512*4882a593Smuzhiyun wdata->extension.input->dev.parent = &wdata->hdev->dev;
1513*4882a593Smuzhiyun wdata->extension.input->id.bustype = wdata->hdev->bus;
1514*4882a593Smuzhiyun wdata->extension.input->id.vendor = wdata->hdev->vendor;
1515*4882a593Smuzhiyun wdata->extension.input->id.product = wdata->hdev->product;
1516*4882a593Smuzhiyun wdata->extension.input->id.version = wdata->hdev->version;
1517*4882a593Smuzhiyun wdata->extension.input->name = WIIMOTE_NAME " Balance Board";
1518*4882a593Smuzhiyun
1519*4882a593Smuzhiyun set_bit(EV_KEY, wdata->extension.input->evbit);
1520*4882a593Smuzhiyun set_bit(BTN_A, wdata->extension.input->keybit);
1521*4882a593Smuzhiyun
1522*4882a593Smuzhiyun set_bit(EV_ABS, wdata->extension.input->evbit);
1523*4882a593Smuzhiyun set_bit(ABS_HAT0X, wdata->extension.input->absbit);
1524*4882a593Smuzhiyun set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
1525*4882a593Smuzhiyun set_bit(ABS_HAT1X, wdata->extension.input->absbit);
1526*4882a593Smuzhiyun set_bit(ABS_HAT1Y, wdata->extension.input->absbit);
1527*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1528*4882a593Smuzhiyun ABS_HAT0X, 0, 65535, 2, 4);
1529*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1530*4882a593Smuzhiyun ABS_HAT0Y, 0, 65535, 2, 4);
1531*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1532*4882a593Smuzhiyun ABS_HAT1X, 0, 65535, 2, 4);
1533*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1534*4882a593Smuzhiyun ABS_HAT1Y, 0, 65535, 2, 4);
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun ret = input_register_device(wdata->extension.input);
1537*4882a593Smuzhiyun if (ret)
1538*4882a593Smuzhiyun goto err_file;
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun return 0;
1541*4882a593Smuzhiyun
1542*4882a593Smuzhiyun err_file:
1543*4882a593Smuzhiyun device_remove_file(&wdata->hdev->dev,
1544*4882a593Smuzhiyun &dev_attr_bboard_calib);
1545*4882a593Smuzhiyun err_free:
1546*4882a593Smuzhiyun input_free_device(wdata->extension.input);
1547*4882a593Smuzhiyun wdata->extension.input = NULL;
1548*4882a593Smuzhiyun return ret;
1549*4882a593Smuzhiyun }
1550*4882a593Smuzhiyun
wiimod_bboard_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)1551*4882a593Smuzhiyun static void wiimod_bboard_remove(const struct wiimod_ops *ops,
1552*4882a593Smuzhiyun struct wiimote_data *wdata)
1553*4882a593Smuzhiyun {
1554*4882a593Smuzhiyun if (!wdata->extension.input)
1555*4882a593Smuzhiyun return;
1556*4882a593Smuzhiyun
1557*4882a593Smuzhiyun input_unregister_device(wdata->extension.input);
1558*4882a593Smuzhiyun wdata->extension.input = NULL;
1559*4882a593Smuzhiyun device_remove_file(&wdata->hdev->dev,
1560*4882a593Smuzhiyun &dev_attr_bboard_calib);
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun static const struct wiimod_ops wiimod_bboard = {
1564*4882a593Smuzhiyun .flags = WIIMOD_FLAG_EXT8,
1565*4882a593Smuzhiyun .arg = 0,
1566*4882a593Smuzhiyun .probe = wiimod_bboard_probe,
1567*4882a593Smuzhiyun .remove = wiimod_bboard_remove,
1568*4882a593Smuzhiyun .in_keys = wiimod_bboard_in_keys,
1569*4882a593Smuzhiyun .in_ext = wiimod_bboard_in_ext,
1570*4882a593Smuzhiyun };
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyun /*
1573*4882a593Smuzhiyun * Pro Controller
1574*4882a593Smuzhiyun * Released with the Wii U was the Nintendo Wii U Pro Controller. It does not
1575*4882a593Smuzhiyun * work together with the classic Wii, but only with the new Wii U. However, it
1576*4882a593Smuzhiyun * uses the same protocol and provides a builtin "classic controller pro"
1577*4882a593Smuzhiyun * extension, few standard buttons, a rumble motor, 4 LEDs and a battery.
1578*4882a593Smuzhiyun * We provide all these via a standard extension device as the device doesn't
1579*4882a593Smuzhiyun * feature an extension port.
1580*4882a593Smuzhiyun */
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun enum wiimod_pro_keys {
1583*4882a593Smuzhiyun WIIMOD_PRO_KEY_A,
1584*4882a593Smuzhiyun WIIMOD_PRO_KEY_B,
1585*4882a593Smuzhiyun WIIMOD_PRO_KEY_X,
1586*4882a593Smuzhiyun WIIMOD_PRO_KEY_Y,
1587*4882a593Smuzhiyun WIIMOD_PRO_KEY_PLUS,
1588*4882a593Smuzhiyun WIIMOD_PRO_KEY_MINUS,
1589*4882a593Smuzhiyun WIIMOD_PRO_KEY_HOME,
1590*4882a593Smuzhiyun WIIMOD_PRO_KEY_LEFT,
1591*4882a593Smuzhiyun WIIMOD_PRO_KEY_RIGHT,
1592*4882a593Smuzhiyun WIIMOD_PRO_KEY_UP,
1593*4882a593Smuzhiyun WIIMOD_PRO_KEY_DOWN,
1594*4882a593Smuzhiyun WIIMOD_PRO_KEY_TL,
1595*4882a593Smuzhiyun WIIMOD_PRO_KEY_TR,
1596*4882a593Smuzhiyun WIIMOD_PRO_KEY_ZL,
1597*4882a593Smuzhiyun WIIMOD_PRO_KEY_ZR,
1598*4882a593Smuzhiyun WIIMOD_PRO_KEY_THUMBL,
1599*4882a593Smuzhiyun WIIMOD_PRO_KEY_THUMBR,
1600*4882a593Smuzhiyun WIIMOD_PRO_KEY_NUM,
1601*4882a593Smuzhiyun };
1602*4882a593Smuzhiyun
1603*4882a593Smuzhiyun static const __u16 wiimod_pro_map[] = {
1604*4882a593Smuzhiyun BTN_EAST, /* WIIMOD_PRO_KEY_A */
1605*4882a593Smuzhiyun BTN_SOUTH, /* WIIMOD_PRO_KEY_B */
1606*4882a593Smuzhiyun BTN_NORTH, /* WIIMOD_PRO_KEY_X */
1607*4882a593Smuzhiyun BTN_WEST, /* WIIMOD_PRO_KEY_Y */
1608*4882a593Smuzhiyun BTN_START, /* WIIMOD_PRO_KEY_PLUS */
1609*4882a593Smuzhiyun BTN_SELECT, /* WIIMOD_PRO_KEY_MINUS */
1610*4882a593Smuzhiyun BTN_MODE, /* WIIMOD_PRO_KEY_HOME */
1611*4882a593Smuzhiyun BTN_DPAD_LEFT, /* WIIMOD_PRO_KEY_LEFT */
1612*4882a593Smuzhiyun BTN_DPAD_RIGHT, /* WIIMOD_PRO_KEY_RIGHT */
1613*4882a593Smuzhiyun BTN_DPAD_UP, /* WIIMOD_PRO_KEY_UP */
1614*4882a593Smuzhiyun BTN_DPAD_DOWN, /* WIIMOD_PRO_KEY_DOWN */
1615*4882a593Smuzhiyun BTN_TL, /* WIIMOD_PRO_KEY_TL */
1616*4882a593Smuzhiyun BTN_TR, /* WIIMOD_PRO_KEY_TR */
1617*4882a593Smuzhiyun BTN_TL2, /* WIIMOD_PRO_KEY_ZL */
1618*4882a593Smuzhiyun BTN_TR2, /* WIIMOD_PRO_KEY_ZR */
1619*4882a593Smuzhiyun BTN_THUMBL, /* WIIMOD_PRO_KEY_THUMBL */
1620*4882a593Smuzhiyun BTN_THUMBR, /* WIIMOD_PRO_KEY_THUMBR */
1621*4882a593Smuzhiyun };
1622*4882a593Smuzhiyun
wiimod_pro_in_ext(struct wiimote_data * wdata,const __u8 * ext)1623*4882a593Smuzhiyun static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext)
1624*4882a593Smuzhiyun {
1625*4882a593Smuzhiyun __s16 rx, ry, lx, ly;
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
1628*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1629*4882a593Smuzhiyun * 1 | LX <7:0> |
1630*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1631*4882a593Smuzhiyun * 2 | 0 0 0 0 | LX <11:8> |
1632*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1633*4882a593Smuzhiyun * 3 | RX <7:0> |
1634*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1635*4882a593Smuzhiyun * 4 | 0 0 0 0 | RX <11:8> |
1636*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1637*4882a593Smuzhiyun * 5 | LY <7:0> |
1638*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1639*4882a593Smuzhiyun * 6 | 0 0 0 0 | LY <11:8> |
1640*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1641*4882a593Smuzhiyun * 7 | RY <7:0> |
1642*4882a593Smuzhiyun * -----+-----------------------+-----------------------+
1643*4882a593Smuzhiyun * 8 | 0 0 0 0 | RY <11:8> |
1644*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1645*4882a593Smuzhiyun * 9 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 |
1646*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1647*4882a593Smuzhiyun * 10 | BZL | BB | BY | BA | BX | BZR | BDL | BDU |
1648*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
1649*4882a593Smuzhiyun * 11 | 1 | BATTERY | USB |CHARG|LTHUM|RTHUM|
1650*4882a593Smuzhiyun * -----+-----+-----------------+-----------+-----+-----+
1651*4882a593Smuzhiyun * All buttons are low-active (0 if pressed)
1652*4882a593Smuzhiyun * RX and RY are right analog stick
1653*4882a593Smuzhiyun * LX and LY are left analog stick
1654*4882a593Smuzhiyun * BLT is left trigger, BRT is right trigger.
1655*4882a593Smuzhiyun * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons
1656*4882a593Smuzhiyun * BZL is left Z button and BZR is right Z button
1657*4882a593Smuzhiyun * B-, BH, B+ are +, HOME and - buttons
1658*4882a593Smuzhiyun * BB, BY, BA, BX are A, B, X, Y buttons
1659*4882a593Smuzhiyun *
1660*4882a593Smuzhiyun * Bits marked as 0/1 are unknown and never changed during tests.
1661*4882a593Smuzhiyun *
1662*4882a593Smuzhiyun * Not entirely verified:
1663*4882a593Smuzhiyun * CHARG: 1 if uncharging, 0 if charging
1664*4882a593Smuzhiyun * USB: 1 if not connected, 0 if connected
1665*4882a593Smuzhiyun * BATTERY: battery capacity from 000 (empty) to 100 (full)
1666*4882a593Smuzhiyun */
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun lx = (ext[0] & 0xff) | ((ext[1] & 0x0f) << 8);
1669*4882a593Smuzhiyun rx = (ext[2] & 0xff) | ((ext[3] & 0x0f) << 8);
1670*4882a593Smuzhiyun ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8);
1671*4882a593Smuzhiyun ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8);
1672*4882a593Smuzhiyun
1673*4882a593Smuzhiyun /* zero-point offsets */
1674*4882a593Smuzhiyun lx -= 0x800;
1675*4882a593Smuzhiyun ly = 0x800 - ly;
1676*4882a593Smuzhiyun rx -= 0x800;
1677*4882a593Smuzhiyun ry = 0x800 - ry;
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun /* Trivial automatic calibration. We don't know any calibration data
1680*4882a593Smuzhiyun * in the EEPROM so we must use the first report to calibrate the
1681*4882a593Smuzhiyun * null-position of the analog sticks. Users can retrigger calibration
1682*4882a593Smuzhiyun * via sysfs, or set it explicitly. If data is off more than abs(500),
1683*4882a593Smuzhiyun * we skip calibration as the sticks are likely to be moved already. */
1684*4882a593Smuzhiyun if (!(wdata->state.flags & WIIPROTO_FLAG_PRO_CALIB_DONE)) {
1685*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE;
1686*4882a593Smuzhiyun if (abs(lx) < 500)
1687*4882a593Smuzhiyun wdata->state.calib_pro_sticks[0] = -lx;
1688*4882a593Smuzhiyun if (abs(ly) < 500)
1689*4882a593Smuzhiyun wdata->state.calib_pro_sticks[1] = -ly;
1690*4882a593Smuzhiyun if (abs(rx) < 500)
1691*4882a593Smuzhiyun wdata->state.calib_pro_sticks[2] = -rx;
1692*4882a593Smuzhiyun if (abs(ry) < 500)
1693*4882a593Smuzhiyun wdata->state.calib_pro_sticks[3] = -ry;
1694*4882a593Smuzhiyun }
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun /* apply calibration data */
1697*4882a593Smuzhiyun lx += wdata->state.calib_pro_sticks[0];
1698*4882a593Smuzhiyun ly += wdata->state.calib_pro_sticks[1];
1699*4882a593Smuzhiyun rx += wdata->state.calib_pro_sticks[2];
1700*4882a593Smuzhiyun ry += wdata->state.calib_pro_sticks[3];
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_X, lx);
1703*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_Y, ly);
1704*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_RX, rx);
1705*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_RY, ry);
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1708*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT],
1709*4882a593Smuzhiyun !(ext[8] & 0x80));
1710*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1711*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_DOWN],
1712*4882a593Smuzhiyun !(ext[8] & 0x40));
1713*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1714*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_TL],
1715*4882a593Smuzhiyun !(ext[8] & 0x20));
1716*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1717*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_MINUS],
1718*4882a593Smuzhiyun !(ext[8] & 0x10));
1719*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1720*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_HOME],
1721*4882a593Smuzhiyun !(ext[8] & 0x08));
1722*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1723*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_PLUS],
1724*4882a593Smuzhiyun !(ext[8] & 0x04));
1725*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1726*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_TR],
1727*4882a593Smuzhiyun !(ext[8] & 0x02));
1728*4882a593Smuzhiyun
1729*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1730*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_ZL],
1731*4882a593Smuzhiyun !(ext[9] & 0x80));
1732*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1733*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_B],
1734*4882a593Smuzhiyun !(ext[9] & 0x40));
1735*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1736*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_Y],
1737*4882a593Smuzhiyun !(ext[9] & 0x20));
1738*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1739*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_A],
1740*4882a593Smuzhiyun !(ext[9] & 0x10));
1741*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1742*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_X],
1743*4882a593Smuzhiyun !(ext[9] & 0x08));
1744*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1745*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_ZR],
1746*4882a593Smuzhiyun !(ext[9] & 0x04));
1747*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1748*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_LEFT],
1749*4882a593Smuzhiyun !(ext[9] & 0x02));
1750*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1751*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_UP],
1752*4882a593Smuzhiyun !(ext[9] & 0x01));
1753*4882a593Smuzhiyun
1754*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1755*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_THUMBL],
1756*4882a593Smuzhiyun !(ext[10] & 0x02));
1757*4882a593Smuzhiyun input_report_key(wdata->extension.input,
1758*4882a593Smuzhiyun wiimod_pro_map[WIIMOD_PRO_KEY_THUMBR],
1759*4882a593Smuzhiyun !(ext[10] & 0x01));
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun input_sync(wdata->extension.input);
1762*4882a593Smuzhiyun }
1763*4882a593Smuzhiyun
wiimod_pro_open(struct input_dev * dev)1764*4882a593Smuzhiyun static int wiimod_pro_open(struct input_dev *dev)
1765*4882a593Smuzhiyun {
1766*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1767*4882a593Smuzhiyun unsigned long flags;
1768*4882a593Smuzhiyun
1769*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1770*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
1771*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1772*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1773*4882a593Smuzhiyun
1774*4882a593Smuzhiyun return 0;
1775*4882a593Smuzhiyun }
1776*4882a593Smuzhiyun
wiimod_pro_close(struct input_dev * dev)1777*4882a593Smuzhiyun static void wiimod_pro_close(struct input_dev *dev)
1778*4882a593Smuzhiyun {
1779*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1780*4882a593Smuzhiyun unsigned long flags;
1781*4882a593Smuzhiyun
1782*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1783*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
1784*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
1785*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1786*4882a593Smuzhiyun }
1787*4882a593Smuzhiyun
wiimod_pro_play(struct input_dev * dev,void * data,struct ff_effect * eff)1788*4882a593Smuzhiyun static int wiimod_pro_play(struct input_dev *dev, void *data,
1789*4882a593Smuzhiyun struct ff_effect *eff)
1790*4882a593Smuzhiyun {
1791*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
1792*4882a593Smuzhiyun __u8 value;
1793*4882a593Smuzhiyun
1794*4882a593Smuzhiyun /*
1795*4882a593Smuzhiyun * The wiimote supports only a single rumble motor so if any magnitude
1796*4882a593Smuzhiyun * is set to non-zero then we start the rumble motor. If both are set to
1797*4882a593Smuzhiyun * zero, we stop the rumble motor.
1798*4882a593Smuzhiyun */
1799*4882a593Smuzhiyun
1800*4882a593Smuzhiyun if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
1801*4882a593Smuzhiyun value = 1;
1802*4882a593Smuzhiyun else
1803*4882a593Smuzhiyun value = 0;
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun /* Locking state.lock here might deadlock with input_event() calls.
1806*4882a593Smuzhiyun * schedule_work acts as barrier. Merging multiple changes is fine. */
1807*4882a593Smuzhiyun wdata->state.cache_rumble = value;
1808*4882a593Smuzhiyun schedule_work(&wdata->rumble_worker);
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun return 0;
1811*4882a593Smuzhiyun }
1812*4882a593Smuzhiyun
wiimod_pro_calib_show(struct device * dev,struct device_attribute * attr,char * out)1813*4882a593Smuzhiyun static ssize_t wiimod_pro_calib_show(struct device *dev,
1814*4882a593Smuzhiyun struct device_attribute *attr,
1815*4882a593Smuzhiyun char *out)
1816*4882a593Smuzhiyun {
1817*4882a593Smuzhiyun struct wiimote_data *wdata = dev_to_wii(dev);
1818*4882a593Smuzhiyun int r;
1819*4882a593Smuzhiyun
1820*4882a593Smuzhiyun r = 0;
1821*4882a593Smuzhiyun r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[0]);
1822*4882a593Smuzhiyun r += sprintf(&out[r], "%+06hd ", wdata->state.calib_pro_sticks[1]);
1823*4882a593Smuzhiyun r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[2]);
1824*4882a593Smuzhiyun r += sprintf(&out[r], "%+06hd\n", wdata->state.calib_pro_sticks[3]);
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun return r;
1827*4882a593Smuzhiyun }
1828*4882a593Smuzhiyun
wiimod_pro_calib_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1829*4882a593Smuzhiyun static ssize_t wiimod_pro_calib_store(struct device *dev,
1830*4882a593Smuzhiyun struct device_attribute *attr,
1831*4882a593Smuzhiyun const char *buf, size_t count)
1832*4882a593Smuzhiyun {
1833*4882a593Smuzhiyun struct wiimote_data *wdata = dev_to_wii(dev);
1834*4882a593Smuzhiyun int r;
1835*4882a593Smuzhiyun s16 x1, y1, x2, y2;
1836*4882a593Smuzhiyun
1837*4882a593Smuzhiyun if (!strncmp(buf, "scan\n", 5)) {
1838*4882a593Smuzhiyun spin_lock_irq(&wdata->state.lock);
1839*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE;
1840*4882a593Smuzhiyun spin_unlock_irq(&wdata->state.lock);
1841*4882a593Smuzhiyun } else {
1842*4882a593Smuzhiyun r = sscanf(buf, "%hd:%hd %hd:%hd", &x1, &y1, &x2, &y2);
1843*4882a593Smuzhiyun if (r != 4)
1844*4882a593Smuzhiyun return -EINVAL;
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun spin_lock_irq(&wdata->state.lock);
1847*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE;
1848*4882a593Smuzhiyun spin_unlock_irq(&wdata->state.lock);
1849*4882a593Smuzhiyun
1850*4882a593Smuzhiyun wdata->state.calib_pro_sticks[0] = x1;
1851*4882a593Smuzhiyun wdata->state.calib_pro_sticks[1] = y1;
1852*4882a593Smuzhiyun wdata->state.calib_pro_sticks[2] = x2;
1853*4882a593Smuzhiyun wdata->state.calib_pro_sticks[3] = y2;
1854*4882a593Smuzhiyun }
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun return strnlen(buf, PAGE_SIZE);
1857*4882a593Smuzhiyun }
1858*4882a593Smuzhiyun
1859*4882a593Smuzhiyun static DEVICE_ATTR(pro_calib, S_IRUGO|S_IWUSR|S_IWGRP, wiimod_pro_calib_show,
1860*4882a593Smuzhiyun wiimod_pro_calib_store);
1861*4882a593Smuzhiyun
wiimod_pro_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)1862*4882a593Smuzhiyun static int wiimod_pro_probe(const struct wiimod_ops *ops,
1863*4882a593Smuzhiyun struct wiimote_data *wdata)
1864*4882a593Smuzhiyun {
1865*4882a593Smuzhiyun int ret, i;
1866*4882a593Smuzhiyun unsigned long flags;
1867*4882a593Smuzhiyun
1868*4882a593Smuzhiyun INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
1869*4882a593Smuzhiyun wdata->state.calib_pro_sticks[0] = 0;
1870*4882a593Smuzhiyun wdata->state.calib_pro_sticks[1] = 0;
1871*4882a593Smuzhiyun wdata->state.calib_pro_sticks[2] = 0;
1872*4882a593Smuzhiyun wdata->state.calib_pro_sticks[3] = 0;
1873*4882a593Smuzhiyun
1874*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1875*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE;
1876*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun wdata->extension.input = input_allocate_device();
1879*4882a593Smuzhiyun if (!wdata->extension.input)
1880*4882a593Smuzhiyun return -ENOMEM;
1881*4882a593Smuzhiyun
1882*4882a593Smuzhiyun set_bit(FF_RUMBLE, wdata->extension.input->ffbit);
1883*4882a593Smuzhiyun input_set_drvdata(wdata->extension.input, wdata);
1884*4882a593Smuzhiyun
1885*4882a593Smuzhiyun if (input_ff_create_memless(wdata->extension.input, NULL,
1886*4882a593Smuzhiyun wiimod_pro_play)) {
1887*4882a593Smuzhiyun ret = -ENOMEM;
1888*4882a593Smuzhiyun goto err_free;
1889*4882a593Smuzhiyun }
1890*4882a593Smuzhiyun
1891*4882a593Smuzhiyun ret = device_create_file(&wdata->hdev->dev,
1892*4882a593Smuzhiyun &dev_attr_pro_calib);
1893*4882a593Smuzhiyun if (ret) {
1894*4882a593Smuzhiyun hid_err(wdata->hdev, "cannot create sysfs attribute\n");
1895*4882a593Smuzhiyun goto err_free;
1896*4882a593Smuzhiyun }
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun wdata->extension.input->open = wiimod_pro_open;
1899*4882a593Smuzhiyun wdata->extension.input->close = wiimod_pro_close;
1900*4882a593Smuzhiyun wdata->extension.input->dev.parent = &wdata->hdev->dev;
1901*4882a593Smuzhiyun wdata->extension.input->id.bustype = wdata->hdev->bus;
1902*4882a593Smuzhiyun wdata->extension.input->id.vendor = wdata->hdev->vendor;
1903*4882a593Smuzhiyun wdata->extension.input->id.product = wdata->hdev->product;
1904*4882a593Smuzhiyun wdata->extension.input->id.version = wdata->hdev->version;
1905*4882a593Smuzhiyun wdata->extension.input->name = WIIMOTE_NAME " Pro Controller";
1906*4882a593Smuzhiyun
1907*4882a593Smuzhiyun set_bit(EV_KEY, wdata->extension.input->evbit);
1908*4882a593Smuzhiyun for (i = 0; i < WIIMOD_PRO_KEY_NUM; ++i)
1909*4882a593Smuzhiyun set_bit(wiimod_pro_map[i],
1910*4882a593Smuzhiyun wdata->extension.input->keybit);
1911*4882a593Smuzhiyun
1912*4882a593Smuzhiyun set_bit(EV_ABS, wdata->extension.input->evbit);
1913*4882a593Smuzhiyun set_bit(ABS_X, wdata->extension.input->absbit);
1914*4882a593Smuzhiyun set_bit(ABS_Y, wdata->extension.input->absbit);
1915*4882a593Smuzhiyun set_bit(ABS_RX, wdata->extension.input->absbit);
1916*4882a593Smuzhiyun set_bit(ABS_RY, wdata->extension.input->absbit);
1917*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1918*4882a593Smuzhiyun ABS_X, -0x400, 0x400, 4, 100);
1919*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1920*4882a593Smuzhiyun ABS_Y, -0x400, 0x400, 4, 100);
1921*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1922*4882a593Smuzhiyun ABS_RX, -0x400, 0x400, 4, 100);
1923*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
1924*4882a593Smuzhiyun ABS_RY, -0x400, 0x400, 4, 100);
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun ret = input_register_device(wdata->extension.input);
1927*4882a593Smuzhiyun if (ret)
1928*4882a593Smuzhiyun goto err_file;
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun return 0;
1931*4882a593Smuzhiyun
1932*4882a593Smuzhiyun err_file:
1933*4882a593Smuzhiyun device_remove_file(&wdata->hdev->dev,
1934*4882a593Smuzhiyun &dev_attr_pro_calib);
1935*4882a593Smuzhiyun err_free:
1936*4882a593Smuzhiyun input_free_device(wdata->extension.input);
1937*4882a593Smuzhiyun wdata->extension.input = NULL;
1938*4882a593Smuzhiyun return ret;
1939*4882a593Smuzhiyun }
1940*4882a593Smuzhiyun
wiimod_pro_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)1941*4882a593Smuzhiyun static void wiimod_pro_remove(const struct wiimod_ops *ops,
1942*4882a593Smuzhiyun struct wiimote_data *wdata)
1943*4882a593Smuzhiyun {
1944*4882a593Smuzhiyun unsigned long flags;
1945*4882a593Smuzhiyun
1946*4882a593Smuzhiyun if (!wdata->extension.input)
1947*4882a593Smuzhiyun return;
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun input_unregister_device(wdata->extension.input);
1950*4882a593Smuzhiyun wdata->extension.input = NULL;
1951*4882a593Smuzhiyun cancel_work_sync(&wdata->rumble_worker);
1952*4882a593Smuzhiyun device_remove_file(&wdata->hdev->dev,
1953*4882a593Smuzhiyun &dev_attr_pro_calib);
1954*4882a593Smuzhiyun
1955*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
1956*4882a593Smuzhiyun wiiproto_req_rumble(wdata, 0);
1957*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
1958*4882a593Smuzhiyun }
1959*4882a593Smuzhiyun
1960*4882a593Smuzhiyun static const struct wiimod_ops wiimod_pro = {
1961*4882a593Smuzhiyun .flags = WIIMOD_FLAG_EXT16,
1962*4882a593Smuzhiyun .arg = 0,
1963*4882a593Smuzhiyun .probe = wiimod_pro_probe,
1964*4882a593Smuzhiyun .remove = wiimod_pro_remove,
1965*4882a593Smuzhiyun .in_ext = wiimod_pro_in_ext,
1966*4882a593Smuzhiyun };
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun /*
1969*4882a593Smuzhiyun * Drums
1970*4882a593Smuzhiyun * Guitar-Hero, Rock-Band and other games came bundled with drums which can
1971*4882a593Smuzhiyun * be plugged as extension to a Wiimote. Drum-reports are still not entirely
1972*4882a593Smuzhiyun * figured out, but the most important information is known.
1973*4882a593Smuzhiyun * We create a separate device for drums and report all information via this
1974*4882a593Smuzhiyun * input device.
1975*4882a593Smuzhiyun */
1976*4882a593Smuzhiyun
wiimod_drums_report_pressure(struct wiimote_data * wdata,__u8 none,__u8 which,__u8 pressure,__u8 onoff,__u8 * store,__u16 code,__u8 which_code)1977*4882a593Smuzhiyun static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata,
1978*4882a593Smuzhiyun __u8 none, __u8 which,
1979*4882a593Smuzhiyun __u8 pressure, __u8 onoff,
1980*4882a593Smuzhiyun __u8 *store, __u16 code,
1981*4882a593Smuzhiyun __u8 which_code)
1982*4882a593Smuzhiyun {
1983*4882a593Smuzhiyun static const __u8 default_pressure = 3;
1984*4882a593Smuzhiyun
1985*4882a593Smuzhiyun if (!none && which == which_code) {
1986*4882a593Smuzhiyun *store = pressure;
1987*4882a593Smuzhiyun input_report_abs(wdata->extension.input, code, *store);
1988*4882a593Smuzhiyun } else if (onoff != !!*store) {
1989*4882a593Smuzhiyun *store = onoff ? default_pressure : 0;
1990*4882a593Smuzhiyun input_report_abs(wdata->extension.input, code, *store);
1991*4882a593Smuzhiyun }
1992*4882a593Smuzhiyun }
1993*4882a593Smuzhiyun
wiimod_drums_in_ext(struct wiimote_data * wdata,const __u8 * ext)1994*4882a593Smuzhiyun static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext)
1995*4882a593Smuzhiyun {
1996*4882a593Smuzhiyun __u8 pressure, which, none, hhp, sx, sy;
1997*4882a593Smuzhiyun __u8 o, r, y, g, b, bass, bm, bp;
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
2000*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2001*4882a593Smuzhiyun * 1 | 0 | 0 | SX <5:0> |
2002*4882a593Smuzhiyun * 2 | 0 | 0 | SY <5:0> |
2003*4882a593Smuzhiyun * -----+-----+-----+-----------------------------+-----+
2004*4882a593Smuzhiyun * 3 | HPP | NON | WHICH <5:1> | ? |
2005*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2006*4882a593Smuzhiyun * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? |
2007*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2008*4882a593Smuzhiyun * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 | ? |
2009*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2010*4882a593Smuzhiyun * 6 | O | R | Y | G | B | BSS | 1 | 1 |
2011*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2012*4882a593Smuzhiyun * All buttons are 0 if pressed
2013*4882a593Smuzhiyun *
2014*4882a593Smuzhiyun * With Motion+ enabled, the following bits will get invalid:
2015*4882a593Smuzhiyun * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
2016*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2017*4882a593Smuzhiyun * 1 | 0 | 0 | SX <5:1> |XXXXX|
2018*4882a593Smuzhiyun * 2 | 0 | 0 | SY <5:1> |XXXXX|
2019*4882a593Smuzhiyun * -----+-----+-----+-----------------------------+-----+
2020*4882a593Smuzhiyun * 3 | HPP | NON | WHICH <5:1> | ? |
2021*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2022*4882a593Smuzhiyun * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? |
2023*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2024*4882a593Smuzhiyun * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 |XXXXX|
2025*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2026*4882a593Smuzhiyun * 6 | O | R | Y | G | B | BSS |XXXXX|XXXXX|
2027*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2028*4882a593Smuzhiyun */
2029*4882a593Smuzhiyun
2030*4882a593Smuzhiyun pressure = 7 - (ext[3] >> 5);
2031*4882a593Smuzhiyun which = (ext[2] >> 1) & 0x1f;
2032*4882a593Smuzhiyun none = !!(ext[2] & 0x40);
2033*4882a593Smuzhiyun hhp = !(ext[2] & 0x80);
2034*4882a593Smuzhiyun sx = ext[0] & 0x3f;
2035*4882a593Smuzhiyun sy = ext[1] & 0x3f;
2036*4882a593Smuzhiyun o = !(ext[5] & 0x80);
2037*4882a593Smuzhiyun r = !(ext[5] & 0x40);
2038*4882a593Smuzhiyun y = !(ext[5] & 0x20);
2039*4882a593Smuzhiyun g = !(ext[5] & 0x10);
2040*4882a593Smuzhiyun b = !(ext[5] & 0x08);
2041*4882a593Smuzhiyun bass = !(ext[5] & 0x04);
2042*4882a593Smuzhiyun bm = !(ext[4] & 0x10);
2043*4882a593Smuzhiyun bp = !(ext[4] & 0x04);
2044*4882a593Smuzhiyun
2045*4882a593Smuzhiyun if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
2046*4882a593Smuzhiyun sx &= 0x3e;
2047*4882a593Smuzhiyun sy &= 0x3e;
2048*4882a593Smuzhiyun }
2049*4882a593Smuzhiyun
2050*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, which, pressure,
2051*4882a593Smuzhiyun o, &wdata->state.pressure_drums[0],
2052*4882a593Smuzhiyun ABS_HAT2Y, 0x0e);
2053*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, which, pressure,
2054*4882a593Smuzhiyun r, &wdata->state.pressure_drums[1],
2055*4882a593Smuzhiyun ABS_HAT0X, 0x19);
2056*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, which, pressure,
2057*4882a593Smuzhiyun y, &wdata->state.pressure_drums[2],
2058*4882a593Smuzhiyun ABS_HAT2X, 0x11);
2059*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, which, pressure,
2060*4882a593Smuzhiyun g, &wdata->state.pressure_drums[3],
2061*4882a593Smuzhiyun ABS_HAT1X, 0x12);
2062*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, which, pressure,
2063*4882a593Smuzhiyun b, &wdata->state.pressure_drums[4],
2064*4882a593Smuzhiyun ABS_HAT0Y, 0x0f);
2065*4882a593Smuzhiyun
2066*4882a593Smuzhiyun /* Bass shares pressure with hi-hat (set via hhp) */
2067*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, hhp ? 0xff : which, pressure,
2068*4882a593Smuzhiyun bass, &wdata->state.pressure_drums[5],
2069*4882a593Smuzhiyun ABS_HAT3X, 0x1b);
2070*4882a593Smuzhiyun /* Hi-hat has no on/off values, just pressure. Force to off/0. */
2071*4882a593Smuzhiyun wiimod_drums_report_pressure(wdata, none, hhp ? which : 0xff, pressure,
2072*4882a593Smuzhiyun 0, &wdata->state.pressure_drums[6],
2073*4882a593Smuzhiyun ABS_HAT3Y, 0x0e);
2074*4882a593Smuzhiyun
2075*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
2076*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
2077*4882a593Smuzhiyun
2078*4882a593Smuzhiyun input_report_key(wdata->extension.input, BTN_START, bp);
2079*4882a593Smuzhiyun input_report_key(wdata->extension.input, BTN_SELECT, bm);
2080*4882a593Smuzhiyun
2081*4882a593Smuzhiyun input_sync(wdata->extension.input);
2082*4882a593Smuzhiyun }
2083*4882a593Smuzhiyun
wiimod_drums_open(struct input_dev * dev)2084*4882a593Smuzhiyun static int wiimod_drums_open(struct input_dev *dev)
2085*4882a593Smuzhiyun {
2086*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
2087*4882a593Smuzhiyun unsigned long flags;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2090*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
2091*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2092*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2093*4882a593Smuzhiyun
2094*4882a593Smuzhiyun return 0;
2095*4882a593Smuzhiyun }
2096*4882a593Smuzhiyun
wiimod_drums_close(struct input_dev * dev)2097*4882a593Smuzhiyun static void wiimod_drums_close(struct input_dev *dev)
2098*4882a593Smuzhiyun {
2099*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
2100*4882a593Smuzhiyun unsigned long flags;
2101*4882a593Smuzhiyun
2102*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2103*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
2104*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2105*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2106*4882a593Smuzhiyun }
2107*4882a593Smuzhiyun
wiimod_drums_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)2108*4882a593Smuzhiyun static int wiimod_drums_probe(const struct wiimod_ops *ops,
2109*4882a593Smuzhiyun struct wiimote_data *wdata)
2110*4882a593Smuzhiyun {
2111*4882a593Smuzhiyun int ret;
2112*4882a593Smuzhiyun
2113*4882a593Smuzhiyun wdata->extension.input = input_allocate_device();
2114*4882a593Smuzhiyun if (!wdata->extension.input)
2115*4882a593Smuzhiyun return -ENOMEM;
2116*4882a593Smuzhiyun
2117*4882a593Smuzhiyun input_set_drvdata(wdata->extension.input, wdata);
2118*4882a593Smuzhiyun wdata->extension.input->open = wiimod_drums_open;
2119*4882a593Smuzhiyun wdata->extension.input->close = wiimod_drums_close;
2120*4882a593Smuzhiyun wdata->extension.input->dev.parent = &wdata->hdev->dev;
2121*4882a593Smuzhiyun wdata->extension.input->id.bustype = wdata->hdev->bus;
2122*4882a593Smuzhiyun wdata->extension.input->id.vendor = wdata->hdev->vendor;
2123*4882a593Smuzhiyun wdata->extension.input->id.product = wdata->hdev->product;
2124*4882a593Smuzhiyun wdata->extension.input->id.version = wdata->hdev->version;
2125*4882a593Smuzhiyun wdata->extension.input->name = WIIMOTE_NAME " Drums";
2126*4882a593Smuzhiyun
2127*4882a593Smuzhiyun set_bit(EV_KEY, wdata->extension.input->evbit);
2128*4882a593Smuzhiyun set_bit(BTN_START, wdata->extension.input->keybit);
2129*4882a593Smuzhiyun set_bit(BTN_SELECT, wdata->extension.input->keybit);
2130*4882a593Smuzhiyun
2131*4882a593Smuzhiyun set_bit(EV_ABS, wdata->extension.input->evbit);
2132*4882a593Smuzhiyun set_bit(ABS_X, wdata->extension.input->absbit);
2133*4882a593Smuzhiyun set_bit(ABS_Y, wdata->extension.input->absbit);
2134*4882a593Smuzhiyun set_bit(ABS_HAT0X, wdata->extension.input->absbit);
2135*4882a593Smuzhiyun set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
2136*4882a593Smuzhiyun set_bit(ABS_HAT1X, wdata->extension.input->absbit);
2137*4882a593Smuzhiyun set_bit(ABS_HAT2X, wdata->extension.input->absbit);
2138*4882a593Smuzhiyun set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
2139*4882a593Smuzhiyun set_bit(ABS_HAT3X, wdata->extension.input->absbit);
2140*4882a593Smuzhiyun set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
2141*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2142*4882a593Smuzhiyun ABS_X, -32, 31, 1, 1);
2143*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2144*4882a593Smuzhiyun ABS_Y, -32, 31, 1, 1);
2145*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2146*4882a593Smuzhiyun ABS_HAT0X, 0, 7, 0, 0);
2147*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2148*4882a593Smuzhiyun ABS_HAT0Y, 0, 7, 0, 0);
2149*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2150*4882a593Smuzhiyun ABS_HAT1X, 0, 7, 0, 0);
2151*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2152*4882a593Smuzhiyun ABS_HAT2X, 0, 7, 0, 0);
2153*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2154*4882a593Smuzhiyun ABS_HAT2Y, 0, 7, 0, 0);
2155*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2156*4882a593Smuzhiyun ABS_HAT3X, 0, 7, 0, 0);
2157*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2158*4882a593Smuzhiyun ABS_HAT3Y, 0, 7, 0, 0);
2159*4882a593Smuzhiyun
2160*4882a593Smuzhiyun ret = input_register_device(wdata->extension.input);
2161*4882a593Smuzhiyun if (ret)
2162*4882a593Smuzhiyun goto err_free;
2163*4882a593Smuzhiyun
2164*4882a593Smuzhiyun return 0;
2165*4882a593Smuzhiyun
2166*4882a593Smuzhiyun err_free:
2167*4882a593Smuzhiyun input_free_device(wdata->extension.input);
2168*4882a593Smuzhiyun wdata->extension.input = NULL;
2169*4882a593Smuzhiyun return ret;
2170*4882a593Smuzhiyun }
2171*4882a593Smuzhiyun
wiimod_drums_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)2172*4882a593Smuzhiyun static void wiimod_drums_remove(const struct wiimod_ops *ops,
2173*4882a593Smuzhiyun struct wiimote_data *wdata)
2174*4882a593Smuzhiyun {
2175*4882a593Smuzhiyun if (!wdata->extension.input)
2176*4882a593Smuzhiyun return;
2177*4882a593Smuzhiyun
2178*4882a593Smuzhiyun input_unregister_device(wdata->extension.input);
2179*4882a593Smuzhiyun wdata->extension.input = NULL;
2180*4882a593Smuzhiyun }
2181*4882a593Smuzhiyun
2182*4882a593Smuzhiyun static const struct wiimod_ops wiimod_drums = {
2183*4882a593Smuzhiyun .flags = 0,
2184*4882a593Smuzhiyun .arg = 0,
2185*4882a593Smuzhiyun .probe = wiimod_drums_probe,
2186*4882a593Smuzhiyun .remove = wiimod_drums_remove,
2187*4882a593Smuzhiyun .in_ext = wiimod_drums_in_ext,
2188*4882a593Smuzhiyun };
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun /*
2191*4882a593Smuzhiyun * Guitar
2192*4882a593Smuzhiyun * Guitar-Hero, Rock-Band and other games came bundled with guitars which can
2193*4882a593Smuzhiyun * be plugged as extension to a Wiimote.
2194*4882a593Smuzhiyun * We create a separate device for guitars and report all information via this
2195*4882a593Smuzhiyun * input device.
2196*4882a593Smuzhiyun */
2197*4882a593Smuzhiyun
2198*4882a593Smuzhiyun enum wiimod_guitar_keys {
2199*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_G,
2200*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_R,
2201*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_Y,
2202*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_B,
2203*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_O,
2204*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_UP,
2205*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_DOWN,
2206*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_PLUS,
2207*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_MINUS,
2208*4882a593Smuzhiyun WIIMOD_GUITAR_KEY_NUM,
2209*4882a593Smuzhiyun };
2210*4882a593Smuzhiyun
2211*4882a593Smuzhiyun static const __u16 wiimod_guitar_map[] = {
2212*4882a593Smuzhiyun BTN_1, /* WIIMOD_GUITAR_KEY_G */
2213*4882a593Smuzhiyun BTN_2, /* WIIMOD_GUITAR_KEY_R */
2214*4882a593Smuzhiyun BTN_3, /* WIIMOD_GUITAR_KEY_Y */
2215*4882a593Smuzhiyun BTN_4, /* WIIMOD_GUITAR_KEY_B */
2216*4882a593Smuzhiyun BTN_5, /* WIIMOD_GUITAR_KEY_O */
2217*4882a593Smuzhiyun BTN_DPAD_UP, /* WIIMOD_GUITAR_KEY_UP */
2218*4882a593Smuzhiyun BTN_DPAD_DOWN, /* WIIMOD_GUITAR_KEY_DOWN */
2219*4882a593Smuzhiyun BTN_START, /* WIIMOD_GUITAR_KEY_PLUS */
2220*4882a593Smuzhiyun BTN_SELECT, /* WIIMOD_GUITAR_KEY_MINUS */
2221*4882a593Smuzhiyun };
2222*4882a593Smuzhiyun
wiimod_guitar_in_ext(struct wiimote_data * wdata,const __u8 * ext)2223*4882a593Smuzhiyun static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext)
2224*4882a593Smuzhiyun {
2225*4882a593Smuzhiyun __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu;
2226*4882a593Smuzhiyun
2227*4882a593Smuzhiyun /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
2228*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2229*4882a593Smuzhiyun * 1 | 0 | 0 | SX <5:0> |
2230*4882a593Smuzhiyun * 2 | 0 | 0 | SY <5:0> |
2231*4882a593Smuzhiyun * -----+-----+-----+-----+-----------------------------+
2232*4882a593Smuzhiyun * 3 | 0 | 0 | 0 | TB <4:0> |
2233*4882a593Smuzhiyun * -----+-----+-----+-----+-----------------------------+
2234*4882a593Smuzhiyun * 4 | 0 | 0 | 0 | WB <4:0> |
2235*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2236*4882a593Smuzhiyun * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 | 1 |
2237*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2238*4882a593Smuzhiyun * 6 | BO | BR | BB | BG | BY | 1 | 1 | BU |
2239*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2240*4882a593Smuzhiyun * All buttons are 0 if pressed
2241*4882a593Smuzhiyun *
2242*4882a593Smuzhiyun * With Motion+ enabled, it will look like this:
2243*4882a593Smuzhiyun * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
2244*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2245*4882a593Smuzhiyun * 1 | 0 | 0 | SX <5:1> | BU |
2246*4882a593Smuzhiyun * 2 | 0 | 0 | SY <5:1> | 1 |
2247*4882a593Smuzhiyun * -----+-----+-----+-----+-----------------------+-----+
2248*4882a593Smuzhiyun * 3 | 0 | 0 | 0 | TB <4:0> |
2249*4882a593Smuzhiyun * -----+-----+-----+-----+-----------------------------+
2250*4882a593Smuzhiyun * 4 | 0 | 0 | 0 | WB <4:0> |
2251*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2252*4882a593Smuzhiyun * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 |XXXXX|
2253*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2254*4882a593Smuzhiyun * 6 | BO | BR | BB | BG | BY | 1 |XXXXX|XXXXX|
2255*4882a593Smuzhiyun * -----+-----+-----+-----+-----+-----+-----+-----+-----+
2256*4882a593Smuzhiyun */
2257*4882a593Smuzhiyun
2258*4882a593Smuzhiyun sx = ext[0] & 0x3f;
2259*4882a593Smuzhiyun sy = ext[1] & 0x3f;
2260*4882a593Smuzhiyun tb = ext[2] & 0x1f;
2261*4882a593Smuzhiyun wb = ext[3] & 0x1f;
2262*4882a593Smuzhiyun bd = !(ext[4] & 0x40);
2263*4882a593Smuzhiyun bm = !(ext[4] & 0x10);
2264*4882a593Smuzhiyun bp = !(ext[4] & 0x04);
2265*4882a593Smuzhiyun bo = !(ext[5] & 0x80);
2266*4882a593Smuzhiyun br = !(ext[5] & 0x40);
2267*4882a593Smuzhiyun bb = !(ext[5] & 0x20);
2268*4882a593Smuzhiyun bg = !(ext[5] & 0x10);
2269*4882a593Smuzhiyun by = !(ext[5] & 0x08);
2270*4882a593Smuzhiyun bu = !(ext[5] & 0x01);
2271*4882a593Smuzhiyun
2272*4882a593Smuzhiyun if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
2273*4882a593Smuzhiyun bu = !(ext[0] & 0x01);
2274*4882a593Smuzhiyun sx &= 0x3e;
2275*4882a593Smuzhiyun sy &= 0x3e;
2276*4882a593Smuzhiyun }
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
2279*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
2280*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT0X, tb);
2281*4882a593Smuzhiyun input_report_abs(wdata->extension.input, ABS_HAT1X, wb - 0x10);
2282*4882a593Smuzhiyun
2283*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2284*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_G],
2285*4882a593Smuzhiyun bg);
2286*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2287*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_R],
2288*4882a593Smuzhiyun br);
2289*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2290*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_Y],
2291*4882a593Smuzhiyun by);
2292*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2293*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_B],
2294*4882a593Smuzhiyun bb);
2295*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2296*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_O],
2297*4882a593Smuzhiyun bo);
2298*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2299*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_UP],
2300*4882a593Smuzhiyun bu);
2301*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2302*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_DOWN],
2303*4882a593Smuzhiyun bd);
2304*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2305*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_PLUS],
2306*4882a593Smuzhiyun bp);
2307*4882a593Smuzhiyun input_report_key(wdata->extension.input,
2308*4882a593Smuzhiyun wiimod_guitar_map[WIIMOD_GUITAR_KEY_MINUS],
2309*4882a593Smuzhiyun bm);
2310*4882a593Smuzhiyun
2311*4882a593Smuzhiyun input_sync(wdata->extension.input);
2312*4882a593Smuzhiyun }
2313*4882a593Smuzhiyun
wiimod_guitar_open(struct input_dev * dev)2314*4882a593Smuzhiyun static int wiimod_guitar_open(struct input_dev *dev)
2315*4882a593Smuzhiyun {
2316*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
2317*4882a593Smuzhiyun unsigned long flags;
2318*4882a593Smuzhiyun
2319*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2320*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
2321*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2322*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2323*4882a593Smuzhiyun
2324*4882a593Smuzhiyun return 0;
2325*4882a593Smuzhiyun }
2326*4882a593Smuzhiyun
wiimod_guitar_close(struct input_dev * dev)2327*4882a593Smuzhiyun static void wiimod_guitar_close(struct input_dev *dev)
2328*4882a593Smuzhiyun {
2329*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
2330*4882a593Smuzhiyun unsigned long flags;
2331*4882a593Smuzhiyun
2332*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2333*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
2334*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2335*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2336*4882a593Smuzhiyun }
2337*4882a593Smuzhiyun
wiimod_guitar_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)2338*4882a593Smuzhiyun static int wiimod_guitar_probe(const struct wiimod_ops *ops,
2339*4882a593Smuzhiyun struct wiimote_data *wdata)
2340*4882a593Smuzhiyun {
2341*4882a593Smuzhiyun int ret, i;
2342*4882a593Smuzhiyun
2343*4882a593Smuzhiyun wdata->extension.input = input_allocate_device();
2344*4882a593Smuzhiyun if (!wdata->extension.input)
2345*4882a593Smuzhiyun return -ENOMEM;
2346*4882a593Smuzhiyun
2347*4882a593Smuzhiyun input_set_drvdata(wdata->extension.input, wdata);
2348*4882a593Smuzhiyun wdata->extension.input->open = wiimod_guitar_open;
2349*4882a593Smuzhiyun wdata->extension.input->close = wiimod_guitar_close;
2350*4882a593Smuzhiyun wdata->extension.input->dev.parent = &wdata->hdev->dev;
2351*4882a593Smuzhiyun wdata->extension.input->id.bustype = wdata->hdev->bus;
2352*4882a593Smuzhiyun wdata->extension.input->id.vendor = wdata->hdev->vendor;
2353*4882a593Smuzhiyun wdata->extension.input->id.product = wdata->hdev->product;
2354*4882a593Smuzhiyun wdata->extension.input->id.version = wdata->hdev->version;
2355*4882a593Smuzhiyun wdata->extension.input->name = WIIMOTE_NAME " Guitar";
2356*4882a593Smuzhiyun
2357*4882a593Smuzhiyun set_bit(EV_KEY, wdata->extension.input->evbit);
2358*4882a593Smuzhiyun for (i = 0; i < WIIMOD_GUITAR_KEY_NUM; ++i)
2359*4882a593Smuzhiyun set_bit(wiimod_guitar_map[i],
2360*4882a593Smuzhiyun wdata->extension.input->keybit);
2361*4882a593Smuzhiyun
2362*4882a593Smuzhiyun set_bit(EV_ABS, wdata->extension.input->evbit);
2363*4882a593Smuzhiyun set_bit(ABS_X, wdata->extension.input->absbit);
2364*4882a593Smuzhiyun set_bit(ABS_Y, wdata->extension.input->absbit);
2365*4882a593Smuzhiyun set_bit(ABS_HAT0X, wdata->extension.input->absbit);
2366*4882a593Smuzhiyun set_bit(ABS_HAT1X, wdata->extension.input->absbit);
2367*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2368*4882a593Smuzhiyun ABS_X, -32, 31, 1, 1);
2369*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2370*4882a593Smuzhiyun ABS_Y, -32, 31, 1, 1);
2371*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2372*4882a593Smuzhiyun ABS_HAT0X, 0, 0x1f, 1, 1);
2373*4882a593Smuzhiyun input_set_abs_params(wdata->extension.input,
2374*4882a593Smuzhiyun ABS_HAT1X, 0, 0x0f, 1, 1);
2375*4882a593Smuzhiyun
2376*4882a593Smuzhiyun ret = input_register_device(wdata->extension.input);
2377*4882a593Smuzhiyun if (ret)
2378*4882a593Smuzhiyun goto err_free;
2379*4882a593Smuzhiyun
2380*4882a593Smuzhiyun return 0;
2381*4882a593Smuzhiyun
2382*4882a593Smuzhiyun err_free:
2383*4882a593Smuzhiyun input_free_device(wdata->extension.input);
2384*4882a593Smuzhiyun wdata->extension.input = NULL;
2385*4882a593Smuzhiyun return ret;
2386*4882a593Smuzhiyun }
2387*4882a593Smuzhiyun
wiimod_guitar_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)2388*4882a593Smuzhiyun static void wiimod_guitar_remove(const struct wiimod_ops *ops,
2389*4882a593Smuzhiyun struct wiimote_data *wdata)
2390*4882a593Smuzhiyun {
2391*4882a593Smuzhiyun if (!wdata->extension.input)
2392*4882a593Smuzhiyun return;
2393*4882a593Smuzhiyun
2394*4882a593Smuzhiyun input_unregister_device(wdata->extension.input);
2395*4882a593Smuzhiyun wdata->extension.input = NULL;
2396*4882a593Smuzhiyun }
2397*4882a593Smuzhiyun
2398*4882a593Smuzhiyun static const struct wiimod_ops wiimod_guitar = {
2399*4882a593Smuzhiyun .flags = 0,
2400*4882a593Smuzhiyun .arg = 0,
2401*4882a593Smuzhiyun .probe = wiimod_guitar_probe,
2402*4882a593Smuzhiyun .remove = wiimod_guitar_remove,
2403*4882a593Smuzhiyun .in_ext = wiimod_guitar_in_ext,
2404*4882a593Smuzhiyun };
2405*4882a593Smuzhiyun
2406*4882a593Smuzhiyun /*
2407*4882a593Smuzhiyun * Builtin Motion Plus
2408*4882a593Smuzhiyun * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
2409*4882a593Smuzhiyun * disables polling for Motion-Plus. This should be set only for devices which
2410*4882a593Smuzhiyun * don't allow MP hotplugging.
2411*4882a593Smuzhiyun */
2412*4882a593Smuzhiyun
wiimod_builtin_mp_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)2413*4882a593Smuzhiyun static int wiimod_builtin_mp_probe(const struct wiimod_ops *ops,
2414*4882a593Smuzhiyun struct wiimote_data *wdata)
2415*4882a593Smuzhiyun {
2416*4882a593Smuzhiyun unsigned long flags;
2417*4882a593Smuzhiyun
2418*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2419*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_BUILTIN_MP;
2420*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2421*4882a593Smuzhiyun
2422*4882a593Smuzhiyun return 0;
2423*4882a593Smuzhiyun }
2424*4882a593Smuzhiyun
wiimod_builtin_mp_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)2425*4882a593Smuzhiyun static void wiimod_builtin_mp_remove(const struct wiimod_ops *ops,
2426*4882a593Smuzhiyun struct wiimote_data *wdata)
2427*4882a593Smuzhiyun {
2428*4882a593Smuzhiyun unsigned long flags;
2429*4882a593Smuzhiyun
2430*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2431*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_BUILTIN_MP;
2432*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2433*4882a593Smuzhiyun }
2434*4882a593Smuzhiyun
2435*4882a593Smuzhiyun static const struct wiimod_ops wiimod_builtin_mp = {
2436*4882a593Smuzhiyun .flags = 0,
2437*4882a593Smuzhiyun .arg = 0,
2438*4882a593Smuzhiyun .probe = wiimod_builtin_mp_probe,
2439*4882a593Smuzhiyun .remove = wiimod_builtin_mp_remove,
2440*4882a593Smuzhiyun };
2441*4882a593Smuzhiyun
2442*4882a593Smuzhiyun /*
2443*4882a593Smuzhiyun * No Motion Plus
2444*4882a593Smuzhiyun * This module simply sets the WIIPROTO_FLAG_NO_MP protocol flag which
2445*4882a593Smuzhiyun * disables motion-plus. This is needed for devices that advertise this but we
2446*4882a593Smuzhiyun * don't know how to use it (or whether it is actually present).
2447*4882a593Smuzhiyun */
2448*4882a593Smuzhiyun
wiimod_no_mp_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)2449*4882a593Smuzhiyun static int wiimod_no_mp_probe(const struct wiimod_ops *ops,
2450*4882a593Smuzhiyun struct wiimote_data *wdata)
2451*4882a593Smuzhiyun {
2452*4882a593Smuzhiyun unsigned long flags;
2453*4882a593Smuzhiyun
2454*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2455*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_NO_MP;
2456*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2457*4882a593Smuzhiyun
2458*4882a593Smuzhiyun return 0;
2459*4882a593Smuzhiyun }
2460*4882a593Smuzhiyun
wiimod_no_mp_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)2461*4882a593Smuzhiyun static void wiimod_no_mp_remove(const struct wiimod_ops *ops,
2462*4882a593Smuzhiyun struct wiimote_data *wdata)
2463*4882a593Smuzhiyun {
2464*4882a593Smuzhiyun unsigned long flags;
2465*4882a593Smuzhiyun
2466*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2467*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_NO_MP;
2468*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2469*4882a593Smuzhiyun }
2470*4882a593Smuzhiyun
2471*4882a593Smuzhiyun static const struct wiimod_ops wiimod_no_mp = {
2472*4882a593Smuzhiyun .flags = 0,
2473*4882a593Smuzhiyun .arg = 0,
2474*4882a593Smuzhiyun .probe = wiimod_no_mp_probe,
2475*4882a593Smuzhiyun .remove = wiimod_no_mp_remove,
2476*4882a593Smuzhiyun };
2477*4882a593Smuzhiyun
2478*4882a593Smuzhiyun /*
2479*4882a593Smuzhiyun * Motion Plus
2480*4882a593Smuzhiyun * The Motion Plus extension provides rotation sensors (gyro) as a small
2481*4882a593Smuzhiyun * extension device for Wii Remotes. Many devices have them built-in so
2482*4882a593Smuzhiyun * you cannot see them from the outside.
2483*4882a593Smuzhiyun * Motion Plus extensions are special because they are on a separate extension
2484*4882a593Smuzhiyun * port and allow other extensions to be used simultaneously. This is all
2485*4882a593Smuzhiyun * handled by the Wiimote Core so we don't have to deal with it.
2486*4882a593Smuzhiyun */
2487*4882a593Smuzhiyun
wiimod_mp_in_mp(struct wiimote_data * wdata,const __u8 * ext)2488*4882a593Smuzhiyun static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext)
2489*4882a593Smuzhiyun {
2490*4882a593Smuzhiyun __s32 x, y, z;
2491*4882a593Smuzhiyun
2492*4882a593Smuzhiyun /* | 8 7 6 5 4 3 | 2 | 1 |
2493*4882a593Smuzhiyun * -----+------------------------------+-----+-----+
2494*4882a593Smuzhiyun * 1 | Yaw Speed <7:0> |
2495*4882a593Smuzhiyun * 2 | Roll Speed <7:0> |
2496*4882a593Smuzhiyun * 3 | Pitch Speed <7:0> |
2497*4882a593Smuzhiyun * -----+------------------------------+-----+-----+
2498*4882a593Smuzhiyun * 4 | Yaw Speed <13:8> | Yaw |Pitch|
2499*4882a593Smuzhiyun * -----+------------------------------+-----+-----+
2500*4882a593Smuzhiyun * 5 | Roll Speed <13:8> |Roll | Ext |
2501*4882a593Smuzhiyun * -----+------------------------------+-----+-----+
2502*4882a593Smuzhiyun * 6 | Pitch Speed <13:8> | 1 | 0 |
2503*4882a593Smuzhiyun * -----+------------------------------+-----+-----+
2504*4882a593Smuzhiyun * The single bits Yaw, Roll, Pitch in the lower right corner specify
2505*4882a593Smuzhiyun * whether the wiimote is rotating fast (0) or slow (1). Speed for slow
2506*4882a593Smuzhiyun * roation is 8192/440 units / deg/s and for fast rotation 8192/2000
2507*4882a593Smuzhiyun * units / deg/s. To get a linear scale for fast rotation we multiply
2508*4882a593Smuzhiyun * by 2000/440 = ~4.5454 and scale both fast and slow by 9 to match the
2509*4882a593Smuzhiyun * previous scale reported by this driver.
2510*4882a593Smuzhiyun * This leaves a linear scale with 8192*9/440 (~167.564) units / deg/s.
2511*4882a593Smuzhiyun * If the wiimote is not rotating the sensor reports 2^13 = 8192.
2512*4882a593Smuzhiyun * Ext specifies whether an extension is connected to the motionp.
2513*4882a593Smuzhiyun * which is parsed by wiimote-core.
2514*4882a593Smuzhiyun */
2515*4882a593Smuzhiyun
2516*4882a593Smuzhiyun x = ext[0];
2517*4882a593Smuzhiyun y = ext[1];
2518*4882a593Smuzhiyun z = ext[2];
2519*4882a593Smuzhiyun
2520*4882a593Smuzhiyun x |= (((__u16)ext[3]) << 6) & 0xff00;
2521*4882a593Smuzhiyun y |= (((__u16)ext[4]) << 6) & 0xff00;
2522*4882a593Smuzhiyun z |= (((__u16)ext[5]) << 6) & 0xff00;
2523*4882a593Smuzhiyun
2524*4882a593Smuzhiyun x -= 8192;
2525*4882a593Smuzhiyun y -= 8192;
2526*4882a593Smuzhiyun z -= 8192;
2527*4882a593Smuzhiyun
2528*4882a593Smuzhiyun if (!(ext[3] & 0x02))
2529*4882a593Smuzhiyun x = (x * 2000 * 9) / 440;
2530*4882a593Smuzhiyun else
2531*4882a593Smuzhiyun x *= 9;
2532*4882a593Smuzhiyun if (!(ext[4] & 0x02))
2533*4882a593Smuzhiyun y = (y * 2000 * 9) / 440;
2534*4882a593Smuzhiyun else
2535*4882a593Smuzhiyun y *= 9;
2536*4882a593Smuzhiyun if (!(ext[3] & 0x01))
2537*4882a593Smuzhiyun z = (z * 2000 * 9) / 440;
2538*4882a593Smuzhiyun else
2539*4882a593Smuzhiyun z *= 9;
2540*4882a593Smuzhiyun
2541*4882a593Smuzhiyun input_report_abs(wdata->mp, ABS_RX, x);
2542*4882a593Smuzhiyun input_report_abs(wdata->mp, ABS_RY, y);
2543*4882a593Smuzhiyun input_report_abs(wdata->mp, ABS_RZ, z);
2544*4882a593Smuzhiyun input_sync(wdata->mp);
2545*4882a593Smuzhiyun }
2546*4882a593Smuzhiyun
wiimod_mp_open(struct input_dev * dev)2547*4882a593Smuzhiyun static int wiimod_mp_open(struct input_dev *dev)
2548*4882a593Smuzhiyun {
2549*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
2550*4882a593Smuzhiyun unsigned long flags;
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2553*4882a593Smuzhiyun wdata->state.flags |= WIIPROTO_FLAG_MP_USED;
2554*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2555*4882a593Smuzhiyun __wiimote_schedule(wdata);
2556*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2557*4882a593Smuzhiyun
2558*4882a593Smuzhiyun return 0;
2559*4882a593Smuzhiyun }
2560*4882a593Smuzhiyun
wiimod_mp_close(struct input_dev * dev)2561*4882a593Smuzhiyun static void wiimod_mp_close(struct input_dev *dev)
2562*4882a593Smuzhiyun {
2563*4882a593Smuzhiyun struct wiimote_data *wdata = input_get_drvdata(dev);
2564*4882a593Smuzhiyun unsigned long flags;
2565*4882a593Smuzhiyun
2566*4882a593Smuzhiyun spin_lock_irqsave(&wdata->state.lock, flags);
2567*4882a593Smuzhiyun wdata->state.flags &= ~WIIPROTO_FLAG_MP_USED;
2568*4882a593Smuzhiyun wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
2569*4882a593Smuzhiyun __wiimote_schedule(wdata);
2570*4882a593Smuzhiyun spin_unlock_irqrestore(&wdata->state.lock, flags);
2571*4882a593Smuzhiyun }
2572*4882a593Smuzhiyun
wiimod_mp_probe(const struct wiimod_ops * ops,struct wiimote_data * wdata)2573*4882a593Smuzhiyun static int wiimod_mp_probe(const struct wiimod_ops *ops,
2574*4882a593Smuzhiyun struct wiimote_data *wdata)
2575*4882a593Smuzhiyun {
2576*4882a593Smuzhiyun int ret;
2577*4882a593Smuzhiyun
2578*4882a593Smuzhiyun wdata->mp = input_allocate_device();
2579*4882a593Smuzhiyun if (!wdata->mp)
2580*4882a593Smuzhiyun return -ENOMEM;
2581*4882a593Smuzhiyun
2582*4882a593Smuzhiyun input_set_drvdata(wdata->mp, wdata);
2583*4882a593Smuzhiyun wdata->mp->open = wiimod_mp_open;
2584*4882a593Smuzhiyun wdata->mp->close = wiimod_mp_close;
2585*4882a593Smuzhiyun wdata->mp->dev.parent = &wdata->hdev->dev;
2586*4882a593Smuzhiyun wdata->mp->id.bustype = wdata->hdev->bus;
2587*4882a593Smuzhiyun wdata->mp->id.vendor = wdata->hdev->vendor;
2588*4882a593Smuzhiyun wdata->mp->id.product = wdata->hdev->product;
2589*4882a593Smuzhiyun wdata->mp->id.version = wdata->hdev->version;
2590*4882a593Smuzhiyun wdata->mp->name = WIIMOTE_NAME " Motion Plus";
2591*4882a593Smuzhiyun
2592*4882a593Smuzhiyun set_bit(EV_ABS, wdata->mp->evbit);
2593*4882a593Smuzhiyun set_bit(ABS_RX, wdata->mp->absbit);
2594*4882a593Smuzhiyun set_bit(ABS_RY, wdata->mp->absbit);
2595*4882a593Smuzhiyun set_bit(ABS_RZ, wdata->mp->absbit);
2596*4882a593Smuzhiyun input_set_abs_params(wdata->mp,
2597*4882a593Smuzhiyun ABS_RX, -16000, 16000, 4, 8);
2598*4882a593Smuzhiyun input_set_abs_params(wdata->mp,
2599*4882a593Smuzhiyun ABS_RY, -16000, 16000, 4, 8);
2600*4882a593Smuzhiyun input_set_abs_params(wdata->mp,
2601*4882a593Smuzhiyun ABS_RZ, -16000, 16000, 4, 8);
2602*4882a593Smuzhiyun
2603*4882a593Smuzhiyun ret = input_register_device(wdata->mp);
2604*4882a593Smuzhiyun if (ret)
2605*4882a593Smuzhiyun goto err_free;
2606*4882a593Smuzhiyun
2607*4882a593Smuzhiyun return 0;
2608*4882a593Smuzhiyun
2609*4882a593Smuzhiyun err_free:
2610*4882a593Smuzhiyun input_free_device(wdata->mp);
2611*4882a593Smuzhiyun wdata->mp = NULL;
2612*4882a593Smuzhiyun return ret;
2613*4882a593Smuzhiyun }
2614*4882a593Smuzhiyun
wiimod_mp_remove(const struct wiimod_ops * ops,struct wiimote_data * wdata)2615*4882a593Smuzhiyun static void wiimod_mp_remove(const struct wiimod_ops *ops,
2616*4882a593Smuzhiyun struct wiimote_data *wdata)
2617*4882a593Smuzhiyun {
2618*4882a593Smuzhiyun if (!wdata->mp)
2619*4882a593Smuzhiyun return;
2620*4882a593Smuzhiyun
2621*4882a593Smuzhiyun input_unregister_device(wdata->mp);
2622*4882a593Smuzhiyun wdata->mp = NULL;
2623*4882a593Smuzhiyun }
2624*4882a593Smuzhiyun
2625*4882a593Smuzhiyun const struct wiimod_ops wiimod_mp = {
2626*4882a593Smuzhiyun .flags = 0,
2627*4882a593Smuzhiyun .arg = 0,
2628*4882a593Smuzhiyun .probe = wiimod_mp_probe,
2629*4882a593Smuzhiyun .remove = wiimod_mp_remove,
2630*4882a593Smuzhiyun .in_mp = wiimod_mp_in_mp,
2631*4882a593Smuzhiyun };
2632*4882a593Smuzhiyun
2633*4882a593Smuzhiyun /* module table */
2634*4882a593Smuzhiyun
2635*4882a593Smuzhiyun static const struct wiimod_ops wiimod_dummy;
2636*4882a593Smuzhiyun
2637*4882a593Smuzhiyun const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = {
2638*4882a593Smuzhiyun [WIIMOD_KEYS] = &wiimod_keys,
2639*4882a593Smuzhiyun [WIIMOD_RUMBLE] = &wiimod_rumble,
2640*4882a593Smuzhiyun [WIIMOD_BATTERY] = &wiimod_battery,
2641*4882a593Smuzhiyun [WIIMOD_LED1] = &wiimod_leds[0],
2642*4882a593Smuzhiyun [WIIMOD_LED2] = &wiimod_leds[1],
2643*4882a593Smuzhiyun [WIIMOD_LED3] = &wiimod_leds[2],
2644*4882a593Smuzhiyun [WIIMOD_LED4] = &wiimod_leds[3],
2645*4882a593Smuzhiyun [WIIMOD_ACCEL] = &wiimod_accel,
2646*4882a593Smuzhiyun [WIIMOD_IR] = &wiimod_ir,
2647*4882a593Smuzhiyun [WIIMOD_BUILTIN_MP] = &wiimod_builtin_mp,
2648*4882a593Smuzhiyun [WIIMOD_NO_MP] = &wiimod_no_mp,
2649*4882a593Smuzhiyun };
2650*4882a593Smuzhiyun
2651*4882a593Smuzhiyun const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
2652*4882a593Smuzhiyun [WIIMOTE_EXT_NONE] = &wiimod_dummy,
2653*4882a593Smuzhiyun [WIIMOTE_EXT_UNKNOWN] = &wiimod_dummy,
2654*4882a593Smuzhiyun [WIIMOTE_EXT_NUNCHUK] = &wiimod_nunchuk,
2655*4882a593Smuzhiyun [WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic,
2656*4882a593Smuzhiyun [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
2657*4882a593Smuzhiyun [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
2658*4882a593Smuzhiyun [WIIMOTE_EXT_DRUMS] = &wiimod_drums,
2659*4882a593Smuzhiyun [WIIMOTE_EXT_GUITAR] = &wiimod_guitar,
2660*4882a593Smuzhiyun };
2661