HID: wiimote: add sub-device module infrastructure
To avoid loading all sub-device drivers for every Wii Remote, even though
the required hardware might not be available, we introduce a module layer.
The module layer specifies which sub-devices are available on each
device-type. After device detection, we only load the modules for the
detected device. If module loading fails, we unload everything and mark
the device as WIIMOTE_DEV_UNKNOWN. As long as a device is marked as
"unknown", no sub-devices will be used and the device is considered
unsupported.
All the different sub-devices, including KEYS, RUMBLE, BATTERY, LEDS,
ACCELEROMETER, IR and more will be ported in follow-up patches to the new
module layer.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-05-06 04:12:51 +07:00
|
|
|
/*
|
|
|
|
* 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"
|
|
|
|
|
2013-05-06 04:12:52 +07:00
|
|
|
/*
|
|
|
|
* 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,
|
|
|
|
};
|
|
|
|
|
HID: wiimote: add sub-device module infrastructure
To avoid loading all sub-device drivers for every Wii Remote, even though
the required hardware might not be available, we introduce a module layer.
The module layer specifies which sub-devices are available on each
device-type. After device detection, we only load the modules for the
detected device. If module loading fails, we unload everything and mark
the device as WIIMOTE_DEV_UNKNOWN. As long as a device is marked as
"unknown", no sub-devices will be used and the device is considered
unsupported.
All the different sub-devices, including KEYS, RUMBLE, BATTERY, LEDS,
ACCELEROMETER, IR and more will be ported in follow-up patches to the new
module layer.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-05-06 04:12:51 +07:00
|
|
|
/* module table */
|
|
|
|
|
|
|
|
const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = {
|
2013-05-06 04:12:52 +07:00
|
|
|
[WIIMOD_KEYS] = &wiimod_keys,
|
|
|
|
[WIIMOD_RUMBLE] = &wiimod_rumble,
|
HID: wiimote: add sub-device module infrastructure
To avoid loading all sub-device drivers for every Wii Remote, even though
the required hardware might not be available, we introduce a module layer.
The module layer specifies which sub-devices are available on each
device-type. After device detection, we only load the modules for the
detected device. If module loading fails, we unload everything and mark
the device as WIIMOTE_DEV_UNKNOWN. As long as a device is marked as
"unknown", no sub-devices will be used and the device is considered
unsupported.
All the different sub-devices, including KEYS, RUMBLE, BATTERY, LEDS,
ACCELEROMETER, IR and more will be ported in follow-up patches to the new
module layer.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-05-06 04:12:51 +07:00
|
|
|
};
|