From: David Herrmann <dh.herrmann@googlemail.com>
To: linux-input@vger.kernel.org
Cc: jkosina@suse.cz, padovan@profusion.mobi, dh.herrmann@googlemail.com
Subject: [PATCH 08/16] HID: wiimote: Parse IR input and report to userspace
Date: Thu, 28 Jul 2011 18:08:28 +0200 [thread overview]
Message-ID: <1311869316-17128-9-git-send-email-dh.herrmann@googlemail.com> (raw)
In-Reply-To: <1311869316-17128-1-git-send-email-dh.herrmann@googlemail.com>
A wiimote sends IR pointing information for up to 4 trackable IR lights. If less
lights are visible, the missing lights report max value. This patch adds parser
functions for IR input and reports this via ABS_HAT*XY values to the input
subsystem.
The IR cam can be in four states: off, basic, extended, full
The DRM chooser automatically chosses an DRM that matches the current IR cam
state so no information is lost.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/hid/hid-wiimote.c | 101 +++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 97 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c
index 6947c2d..ed7feb2 100644
--- a/drivers/hid/hid-wiimote.c
+++ b/drivers/hid/hid-wiimote.c
@@ -53,8 +53,13 @@ struct wiimote_data {
#define WIIPROTO_FLAG_LED4 0x08
#define WIIPROTO_FLAG_RUMBLE 0x10
#define WIIPROTO_FLAG_ACCEL 0x20
+#define WIIPROTO_FLAG_IR_BASIC 0x40
+#define WIIPROTO_FLAG_IR_EXT 0x80
+#define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */
#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \
WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4)
+#define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \
+ WIIPROTO_FLAG_IR_FULL)
enum wiiproto_reqs {
WIIPROTO_REQ_NULL = 0x0,
@@ -67,6 +72,7 @@ enum wiiproto_reqs {
WIIPROTO_REQ_DRM_KA = 0x31,
WIIPROTO_REQ_DRM_KAI = 0x33,
WIIPROTO_REQ_DRM_KAE = 0x35,
+ WIIPROTO_REQ_DRM_KIE = 0x36,
WIIPROTO_REQ_DRM_KAIE = 0x37,
WIIPROTO_REQ_DRM_SKAI1 = 0x3e,
WIIPROTO_REQ_DRM_SKAI2 = 0x3f,
@@ -247,10 +253,22 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds)
*/
static __u8 select_drm(struct wiimote_data *wdata)
{
- if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
- return WIIPROTO_REQ_DRM_KA;
- else
- return WIIPROTO_REQ_DRM_K;
+ __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR;
+ if (ir == WIIPROTO_FLAG_IR_BASIC) {
+ if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+ return WIIPROTO_REQ_DRM_KAIE;
+ else
+ return WIIPROTO_REQ_DRM_KIE;
+ } else if (ir == WIIPROTO_FLAG_IR_EXT) {
+ return WIIPROTO_REQ_DRM_KAI;
+ } else if (ir == WIIPROTO_FLAG_IR_FULL) {
+ return WIIPROTO_REQ_DRM_SKAI1;
+ } else {
+ if (wdata->state.flags & WIIPROTO_FLAG_ACCEL)
+ return WIIPROTO_REQ_DRM_KA;
+ else
+ return WIIPROTO_REQ_DRM_K;
+ }
}
static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm)
@@ -469,6 +487,40 @@ static void handler_accel(struct wiimote_data *wdata, const __u8 *payload)
input_event(wdata->input, EV_ABS, ABS_Z, z - 0x200);
}
+#define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT0X, ABS_HAT0Y)
+#define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT1X, ABS_HAT1Y)
+#define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT2X, ABS_HAT2Y)
+#define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \
+ ABS_HAT3X, ABS_HAT3Y)
+
+static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
+ bool packed, __u8 xid, __u8 yid)
+{
+ __u16 x, y;
+
+ if (!(wdata->state.flags & WIIPROTO_FLAGS_IR))
+ return;
+
+ if (packed) {
+ x = ir[1] << 2;
+ y = ir[2] << 2;
+
+ x |= ir[0] & 0x3;
+ y |= (ir[0] >> 2) & 0x3;
+ } else {
+ x = ir[0] << 2;
+ y = ir[1] << 2;
+
+ x |= (ir[2] >> 4) & 0x3;
+ y |= (ir[2] >> 6) & 0x3;
+ }
+
+ input_event(wdata->input, EV_ABS, xid, x);
+ input_event(wdata->input, EV_ABS, yid, y);
+}
static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
{
@@ -500,6 +552,19 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload)
{
handler_keys(wdata, payload);
handler_accel(wdata, payload);
+ ir_to_input0(wdata, &payload[5], false);
+ ir_to_input1(wdata, &payload[8], false);
+ ir_to_input2(wdata, &payload[11], false);
+ ir_to_input3(wdata, &payload[14], false);
+}
+
+static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload)
+{
+ handler_keys(wdata, payload);
+ ir_to_input0(wdata, &payload[2], false);
+ ir_to_input1(wdata, &payload[4], true);
+ ir_to_input2(wdata, &payload[7], false);
+ ir_to_input3(wdata, &payload[9], true);
}
static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload)
@@ -512,6 +577,10 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload)
{
handler_keys(wdata, payload);
handler_accel(wdata, payload);
+ ir_to_input0(wdata, &payload[5], false);
+ ir_to_input1(wdata, &payload[7], true);
+ ir_to_input2(wdata, &payload[10], false);
+ ir_to_input3(wdata, &payload[12], true);
}
static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
@@ -521,6 +590,9 @@ static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload)
wdata->state.accel_split[0] = payload[2];
wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20);
wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80);
+
+ ir_to_input0(wdata, &payload[3], false);
+ ir_to_input1(wdata, &payload[12], false);
}
static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
@@ -538,6 +610,9 @@ static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload)
buf[3] = payload[2];
buf[4] = wdata->state.accel_split[1];
handler_accel(wdata, buf);
+
+ ir_to_input2(wdata, &payload[3], false);
+ ir_to_input3(wdata, &payload[12], false);
}
struct wiiproto_handler {
@@ -553,6 +628,7 @@ static struct wiiproto_handler handlers[] = {
{ .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
{ .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
{ .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
+ { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
{ .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
{ .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
{ .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
@@ -628,6 +704,23 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev)
input_set_abs_params(wdata->input, ABS_Y, -500, 500, 2, 4);
input_set_abs_params(wdata->input, ABS_Z, -500, 500, 2, 4);
+ set_bit(ABS_HAT0X, wdata->input->absbit);
+ set_bit(ABS_HAT0Y, wdata->input->absbit);
+ set_bit(ABS_HAT1X, wdata->input->absbit);
+ set_bit(ABS_HAT1Y, wdata->input->absbit);
+ set_bit(ABS_HAT2X, wdata->input->absbit);
+ set_bit(ABS_HAT2Y, wdata->input->absbit);
+ set_bit(ABS_HAT3X, wdata->input->absbit);
+ set_bit(ABS_HAT3Y, wdata->input->absbit);
+ input_set_abs_params(wdata->input, ABS_HAT0X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT0Y, 0, 767, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT1X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT1Y, 0, 767, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT2X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT2Y, 0, 767, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT3X, 0, 1023, 2, 4);
+ input_set_abs_params(wdata->input, ABS_HAT3Y, 0, 767, 2, 4);
+
spin_lock_init(&wdata->qlock);
INIT_WORK(&wdata->worker, wiimote_worker);
--
1.7.6
next prev parent reply other threads:[~2011-07-28 16:09 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-28 16:08 [PATCH 00/16] Extended wiimote support David Herrmann
2011-07-28 16:08 ` [PATCH 01/16] HID: wiimote: Support rumble device David Herrmann
2011-07-28 16:08 ` [PATCH 02/16] HID: wiimote: Add sysfs rumble attribute David Herrmann
2011-07-28 16:08 ` [PATCH 03/16] HID: wiimote: Add drm request David Herrmann
2011-07-28 18:05 ` Oliver Neukum
2011-07-28 18:41 ` David Herrmann
2011-07-28 18:47 ` Oliver Neukum
2011-07-28 16:08 ` [PATCH 04/16] HID: wiimote: Add status and return request handlers David Herrmann
2011-07-28 16:08 ` [PATCH 05/16] HID: wiimote: Reduce input syncs David Herrmann
2011-07-28 16:08 ` [PATCH 06/16] HID: wiimote: Enable accelerometer on request David Herrmann
2011-07-28 18:08 ` Oliver Neukum
2011-07-28 19:01 ` David Herrmann
2011-07-28 19:32 ` Oliver Neukum
2011-07-28 16:08 ` [PATCH 07/16] HID: wiimote: Parse accelerometer data David Herrmann
2011-07-28 18:12 ` Oliver Neukum
2011-07-28 18:51 ` David Herrmann
2011-08-10 11:55 ` Jiri Kosina
2011-07-28 16:08 ` David Herrmann [this message]
2011-07-28 16:08 ` [PATCH 09/16] HID: wiimote: Add missing extension DRM handlers David Herrmann
2011-07-28 16:08 ` [PATCH 10/16] HID: wiimote: Add register/eeprom memory support David Herrmann
2011-07-28 16:08 ` [PATCH 11/16] HID: wiimote: Helper functions for synchronous requests David Herrmann
2011-07-28 16:08 ` [PATCH 12/16] HID: wiimote: Add write-register helpers David Herrmann
2011-07-28 16:08 ` [PATCH 13/16] HID: wiimote: Add IR initializer David Herrmann
2011-07-28 16:08 ` [PATCH 14/16] HID: wiimote: Allow userspace to control IR cam David Herrmann
2011-07-28 16:08 ` [PATCH 15/16] HID: wiimote: Read wiimote battery charge level David Herrmann
2011-07-28 16:08 ` [PATCH 16/16] HID: wiimote: Allow EEPROM debugfs access David Herrmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1311869316-17128-9-git-send-email-dh.herrmann@googlemail.com \
--to=dh.herrmann@googlemail.com \
--cc=jkosina@suse.cz \
--cc=linux-input@vger.kernel.org \
--cc=padovan@profusion.mobi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).