Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f329741 authored by David Herrmann's avatar David Herrmann Committed by Jiri Kosina
Browse files

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: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 45ec9fff
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -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 */
	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 @@ static bool wiimote_init_check(struct wiimote_data *wdata)
	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);
	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,6 +1146,8 @@ static void wiimote_init_hotplug(struct wiimote_data *wdata)
		del_timer_sync(&wdata->timer);
	} else {
		/* reschedule MP hotplug timer */
		if (!(flags & WIIPROTO_FLAG_BUILTIN_MP) &&
		    !(flags & WIIPROTO_FLAG_NO_MP))
			mod_timer(&wdata->timer, jiffies + HZ * 4);
	}

+74 −0
Original line number Diff line number Diff line
@@ -1539,6 +1539,78 @@ static const struct wiimod_ops wiimod_bboard = {
	.in_ext = wiimod_bboard_in_ext,
};

/*
 * 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
@@ -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] = {
+4 −0
Original line number Diff line number Diff line
@@ -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,
};