summaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-05-05 23:13:07 +0200
committerJiri Kosina <jkosina@suse.cz>2013-06-03 11:07:06 +0200
commit9f329741a6d7253f044677af00a999b47e85721e (patch)
tree83e95fb89963553dc418c09022ffb138518e7133 /drivers/hid
parent45ec9fff8629dda47d0c7645174220bcf5d9b6ba (diff)
downloadlinux-9f329741a6d7253f044677af00a999b47e85721e.tar.gz
linux-9f329741a6d7253f044677af00a999b47e85721e.tar.bz2
linux-9f329741a6d7253f044677af00a999b47e85721e.zip
HID: wiimote: add MP quirks
Devices which have built-in motion plus ports don't need MP detection logic. The new WIIMOD_BUILTIN_MP modules sets the WIIPROTO_FLAG_BUILTIN_MP flag which disables polling for MP. Some other devices erroneously report that they support motion-plus. For these devices and all devices without extension ports, we load WIIMOD_NO_MP which sets WIIPROTO_FLAG_NO_MP. This effectively disables all MP detection logic. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-wiimote-core.c25
-rw-r--r--drivers/hid/hid-wiimote-modules.c74
-rw-r--r--drivers/hid/hid-wiimote.h4
3 files changed, 98 insertions, 5 deletions
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index fa58045cf7e0..3e696562c944 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -555,6 +555,7 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = {
WIIMOD_NULL,
},
[WIIMOTE_DEV_UNKNOWN] = (const __u8[]){
+ WIIMOD_NO_MP,
WIIMOD_NULL,
},
[WIIMOTE_DEV_GENERIC] = (const __u8[]){
@@ -591,11 +592,13 @@ static const __u8 * const wiimote_devtype_mods[WIIMOTE_DEV_NUM] = {
WIIMOD_LED4,
WIIMOD_ACCEL,
WIIMOD_IR,
+ WIIMOD_BUILTIN_MP,
WIIMOD_NULL,
},
[WIIMOTE_DEV_BALANCE_BOARD] = (const __u8[]) {
WIIMOD_BATTERY,
WIIMOD_LED1,
+ WIIMOD_NO_MP,
WIIMOD_NULL,
},
};
@@ -867,8 +870,13 @@ static void wiimote_init_detect(struct wiimote_data *wdata)
out_release:
wiimote_cmd_release(wdata);
wiimote_init_set_type(wdata, exttype);
+
/* schedule MP timer */
- mod_timer(&wdata->timer, jiffies + HZ * 4);
+ spin_lock_irq(&wdata->state.lock);
+ if (!(wdata->state.flags & WIIPROTO_FLAG_BUILTIN_MP) &&
+ !(wdata->state.flags & WIIPROTO_FLAG_NO_MP))
+ mod_timer(&wdata->timer, jiffies + HZ * 4);
+ spin_unlock_irq(&wdata->state.lock);
}
/*
@@ -1037,7 +1045,8 @@ out_release:
wiimote_cmd_release(wdata);
/* only poll for MP if requested and if state didn't change */
- if (ret && poll_mp)
+ if (ret && poll_mp && !(flags & WIIPROTO_FLAG_BUILTIN_MP) &&
+ !(flags & WIIPROTO_FLAG_NO_MP))
wiimote_init_poll_mp(wdata);
return ret;
@@ -1082,8 +1091,12 @@ static void wiimote_init_hotplug(struct wiimote_data *wdata)
/* init extension and MP (deactivates current extension or MP) */
wiimote_cmd_init_ext(wdata);
- wiimote_cmd_init_mp(wdata);
- mp = wiimote_cmd_read_mp(wdata, mpdata);
+ if (flags & WIIPROTO_FLAG_NO_MP) {
+ mp = false;
+ } else {
+ wiimote_cmd_init_mp(wdata);
+ mp = wiimote_cmd_read_mp(wdata, mpdata);
+ }
exttype = wiimote_cmd_read_ext(wdata, extdata);
wiimote_cmd_release(wdata);
@@ -1133,7 +1146,9 @@ static void wiimote_init_hotplug(struct wiimote_data *wdata)
del_timer_sync(&wdata->timer);
} else {
/* reschedule MP hotplug timer */
- mod_timer(&wdata->timer, jiffies + HZ * 4);
+ if (!(flags & WIIPROTO_FLAG_BUILTIN_MP) &&
+ !(flags & WIIPROTO_FLAG_NO_MP))
+ mod_timer(&wdata->timer, jiffies + HZ * 4);
}
spin_lock_irq(&wdata->state.lock);
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 19b8b1c4acb4..e2afe065991d 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1540,6 +1540,78 @@ static const struct wiimod_ops wiimod_bboard = {
};
/*
+ * Builtin Motion Plus
+ * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
+ * disables polling for Motion-Plus. This should be set only for devices which
+ * don't allow MP hotplugging.
+ */
+
+static int wiimod_builtin_mp_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_BUILTIN_MP;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_builtin_mp_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_BUILTIN_MP;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static const struct wiimod_ops wiimod_builtin_mp = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_builtin_mp_probe,
+ .remove = wiimod_builtin_mp_remove,
+};
+
+/*
+ * No Motion Plus
+ * This module simply sets the WIIPROTO_FLAG_NO_MP protocol flag which
+ * disables motion-plus. This is needed for devices that advertise this but we
+ * don't know how to use it (or whether it is actually present).
+ */
+
+static int wiimod_no_mp_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_NO_MP;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_no_mp_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_NO_MP;
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static const struct wiimod_ops wiimod_no_mp = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_no_mp_probe,
+ .remove = wiimod_no_mp_remove,
+};
+
+/*
* Motion Plus
* The Motion Plus extension provides rotation sensors (gyro) as a small
* extension device for Wii Remotes. Many devices have them built-in so
@@ -1706,6 +1778,8 @@ const struct wiimod_ops *wiimod_table[WIIMOD_NUM] = {
[WIIMOD_LED4] = &wiimod_leds[3],
[WIIMOD_ACCEL] = &wiimod_accel,
[WIIMOD_IR] = &wiimod_ir,
+ [WIIMOD_BUILTIN_MP] = &wiimod_builtin_mp,
+ [WIIMOD_NO_MP] = &wiimod_no_mp,
};
const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index d406a398e54c..5cf8bcb81095 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -44,6 +44,8 @@
#define WIIPROTO_FLAG_MP_ACTIVE 0x2000
#define WIIPROTO_FLAG_EXITING 0x4000
#define WIIPROTO_FLAG_DRM_LOCKED 0x8000
+#define WIIPROTO_FLAG_BUILTIN_MP 0x010000
+#define WIIPROTO_FLAG_NO_MP 0x020000
#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
@@ -165,6 +167,8 @@ enum wiimod_module {
WIIMOD_LED4,
WIIMOD_ACCEL,
WIIMOD_IR,
+ WIIMOD_BUILTIN_MP,
+ WIIMOD_NO_MP,
WIIMOD_NUM,
WIIMOD_NULL = WIIMOD_NUM,
};