| /* |
| * Device Modules for Nintendo Wii / Wii U HID Driver |
| * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com> |
| */ |
| |
| /* |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| */ |
| |
| /* |
| * Wiimote Modules |
| * Nintendo devices provide different peripherals and many new devices lack |
| * initial features like the IR camera. Therefore, each peripheral device is |
| * implemented as an independent module and we probe on each device only the |
| * modules for the hardware that really is available. |
| * |
| * Module registration is sequential. Unregistration is done in reverse order. |
| * After device detection, the needed modules are loaded. Users can trigger |
| * re-detection which causes all modules to be unloaded and then reload the |
| * modules for the new detected device. |
| * |
| * wdata->input is a shared input device. It is always initialized prior to |
| * module registration. If at least one registered module is marked as |
| * WIIMOD_FLAG_INPUT, then the input device will get registered after all |
| * modules were registered. |
| * Please note that it is unregistered _before_ the "remove" callbacks are |
| * called. This guarantees that no input interaction is done, anymore. However, |
| * the wiimote core keeps a reference to the input device so it is freed only |
| * after all modules were removed. It is safe to send events to unregistered |
| * input devices. |
| */ |
| |
| #include <linux/device.h> |
| #include <linux/hid.h> |
| #include <linux/input.h> |
| #include <linux/spinlock.h> |
| #include "hid-wiimote.h" |
| |
| /* |
| * Keys |
| * The initial Wii Remote provided a bunch of buttons that are reported as |
| * part of the core protocol. Many later devices dropped these and report |
| * invalid data in the core button reports. Load this only on devices which |
| * correctly send button reports. |
| * It uses the shared input device. |
| */ |
| |
| static const __u16 wiimod_keys_map[] = { |
| KEY_LEFT, /* WIIPROTO_KEY_LEFT */ |
| KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ |
| KEY_UP, /* WIIPROTO_KEY_UP */ |
| KEY_DOWN, /* WIIPROTO_KEY_DOWN */ |
| KEY_NEXT, /* WIIPROTO_KEY_PLUS */ |
| KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ |
| BTN_1, /* WIIPROTO_KEY_ONE */ |
| BTN_2, /* WIIPROTO_KEY_TWO */ |
| BTN_A, /* WIIPROTO_KEY_A */ |
| BTN_B, /* WIIPROTO_KEY_B */ |
| BTN_MODE, /* WIIPROTO_KEY_HOME */ |
| }; |
| |
| static void wiimod_keys_in_keys(struct wiimote_data *wdata, const __u8 *keys) |
| { |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_LEFT], |
| !!(keys[0] & 0x01)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_RIGHT], |
| !!(keys[0] & 0x02)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_DOWN], |
| !!(keys[0] & 0x04)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_UP], |
| !!(keys[0] & 0x08)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_PLUS], |
| !!(keys[0] & 0x10)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_TWO], |
| !!(keys[1] & 0x01)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_ONE], |
| !!(keys[1] & 0x02)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_B], |
| !!(keys[1] & 0x04)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_A], |
| !!(keys[1] & 0x08)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_MINUS], |
| !!(keys[1] & 0x10)); |
| input_report_key(wdata->input, wiimod_keys_map[WIIPROTO_KEY_HOME], |
| !!(keys[1] & 0x80)); |
| input_sync(wdata->input); |
| } |
| |
| static int wiimod_keys_probe(const struct wiimod_ops *ops, |
| struct wiimote_data *wdata) |
| { |
| unsigned int i; |
| |
| set_bit(EV_KEY, wdata->input->evbit); |
| for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) |
| set_bit(wiimod_keys_map[i], wdata->input->keybit); |
| |
| return 0; |
| } |
| |
| static const struct wiimod_ops wiimod_keys = { |
| .flags = WIIMOD_FLAG_INPUT, |
| .arg = 0, |
| .probe = wiimod_keys_probe, |
| .remove = NULL, |
| .in_keys = wiimod_keys_in_keys, |
| }; |
| |
| /* |
| * Rumble |
| * Nearly all devices provide a rumble feature. A small motor for |
| * force-feedback effects. We provide an FF_RUMBLE memless ff device on the |
| * shared input device if this module is loaded. |
| * The rumble motor is controlled via a flag on almost every output report so |
| * the wiimote core handles the rumble flag. But if a device doesn't provide |
| * the rumble motor, this flag shouldn't be set. |
| */ |
| |
| static int wiimod_rumble_play(struct input_dev *dev, void *data, |
| struct ff_effect *eff) |
| { |
| struct wiimote_data *wdata = input_get_drvdata(dev); |
| __u8 value; |
| unsigned long flags; |
| |
| /* |
| * The wiimote supports only a single rumble motor so if any magnitude |
| * is set to non-zero then we start the rumble motor. If both are set to |
| * zero, we stop the rumble motor. |
| */ |
| |
| if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) |
| value = 1; |
| else |
| value = 0; |
| |
| spin_lock_irqsave(&wdata->state.lock, flags); |
| wiiproto_req_rumble(wdata, value); |
| spin_unlock_irqrestore(&wdata->state.lock, flags); |
| |
| return 0; |
| } |
| |
| static int wiimod_rumble_probe(const struct wiimod_ops *ops, |
| struct wiimote_data *wdata) |
| { |
| set_bit(FF_RUMBLE, wdata->input->ffbit); |
| if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play)) |
| return -ENOMEM; |
| |
| return 0; |
| } |
| |
| static void wiimod_rumble_remove(const struct wiimod_ops *ops, |
| struct wiimote_data *wdata) |
| { |
| unsigned long flags; |
| |
| spin_lock_irqsave(&wdata->state.lock, flags); |
| wiiproto_req_rumble(wdata, 0); |
| spin_unlock_irqrestore(&wdata->state.lock, flags); |
| } |
| |
| static const struct wiimod_ops wiimod_rumble = { |
| .flags = WIIMOD_FLAG_INPUT, |
| .arg = 0, |
| .probe = wiimod_rumble_probe, |
| .remove = wiimod_rumble_remove, |
| }; |
| |
| /* module table */ |
| |
| const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = { |
| [WIIMOD_KEYS] = &wiimod_keys, |
| [WIIMOD_RUMBLE] = &wiimod_rumble, |
| }; |