123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- /*
- * 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,
- };
|