From patchwork Sat Apr 13 10:47:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 2440441 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 194FC3FD1A for ; Sat, 13 Apr 2013 10:48:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753241Ab3DMKs6 (ORCPT ); Sat, 13 Apr 2013 06:48:58 -0400 Received: from mail-ea0-f179.google.com ([209.85.215.179]:48206 "EHLO mail-ea0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753371Ab3DMKs5 (ORCPT ); Sat, 13 Apr 2013 06:48:57 -0400 Received: by mail-ea0-f179.google.com with SMTP id f15so1532995eak.24 for ; Sat, 13 Apr 2013 03:48:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=Epw6X8mbVKsT1/foZKxDudX+5XlZx8ObEiUY5LoONZA=; b=Rz9rMVcdai8oVOG+BMjczRir+fVmL3XUIxTZbszIhBkZmrOxA1v2b3mKBgbk0m/htp vsZW7ZWwIK9IfFUBmnI/nzR8MhYiQ4sLkNmz36KejU5jWpLtZuNPvjgEvenWjIWijv0T w7O6dmEs7+7Mtu6BrdWEIqjhon31+sTW8g6MrDSs8xQrypCkgDNUp8bf+HEXf20KtVHA zNyoHma1Pju+Hj04eWQek+nu8COVhRh4LJVf6vdDivXMrUAua3ztO1UZrzf6UNsbfTmv hRgclFbuTjSTSscsLnw65oyv01z/Tf1K+Op0p8Tz6ZyNuovyQp2g8SdiP6ZZop10uk4h OPBg== X-Received: by 10.15.81.136 with SMTP id x8mr38496225eey.9.1365850136602; Sat, 13 Apr 2013 03:48:56 -0700 (PDT) Received: from localhost.localdomain (stgt-5f71827d.pool.mediaWays.net. [95.113.130.125]) by mx.google.com with ESMTPS id t4sm15859796eel.0.2013.04.13.03.48.54 (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 13 Apr 2013 03:48:55 -0700 (PDT) From: David Herrmann To: linux-input@vger.kernel.org Cc: Jiri Kosina , David Herrmann Subject: [PATCH 17/21] HID: wiimote: add Motion Plus extension module Date: Sat, 13 Apr 2013 12:47:58 +0200 Message-Id: <1365850082-3585-18-git-send-email-dh.herrmann@gmail.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1365850082-3585-1-git-send-email-dh.herrmann@gmail.com> References: <1365850082-3585-1-git-send-email-dh.herrmann@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Add parsers for motion plus data so we can hotplug motion plus extensions and make use of them. This is mostly the same as the old static motion plus parser. Signed-off-by: David Herrmann --- drivers/hid/hid-wiimote-modules.c | 144 ++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-wiimote.h | 1 + 2 files changed, 145 insertions(+) diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index a1a4438..c3e823d 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c @@ -1475,11 +1475,155 @@ static const struct wiimod_ops wiimod_bboard = { /* * 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 + * you cannot see them from the outside. + * Motion Plus extensions are special because they are on a separate extension + * port and allow other extensions to be used simultaneously. This is all + * handled by the Wiimote Core so we don't have to deal with it. */ +static void wiimod_mp_in_mp(struct wiimote_data *wdata, const __u8 *ext) +{ + __s32 x, y, z; + + /* | 8 7 6 5 4 3 | 2 | 1 | + * -----+------------------------------+-----+-----+ + * 1 | Yaw Speed <7:0> | + * 2 | Roll Speed <7:0> | + * 3 | Pitch Speed <7:0> | + * -----+------------------------------+-----+-----+ + * 4 | Yaw Speed <13:8> | Yaw |Pitch| + * -----+------------------------------+-----+-----+ + * 5 | Roll Speed <13:8> |Roll | Ext | + * -----+------------------------------+-----+-----+ + * 6 | Pitch Speed <13:8> | 1 | 0 | + * -----+------------------------------+-----+-----+ + * The single bits Yaw, Roll, Pitch in the lower right corner specify + * whether the wiimote is rotating fast (0) or slow (1). Speed for slow + * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a + * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast + * and 9 for slow. + * If the wiimote is not rotating the sensor reports 2^13 = 8192. + * Ext specifies whether an extension is connected to the motionp. + * which is parsed by wiimote-core. + */ + + x = ext[0]; + y = ext[1]; + z = ext[2]; + + x |= (((__u16)ext[3]) << 6) & 0xff00; + y |= (((__u16)ext[4]) << 6) & 0xff00; + z |= (((__u16)ext[5]) << 6) & 0xff00; + + x -= 8192; + y -= 8192; + z -= 8192; + + if (!(ext[3] & 0x02)) + x *= 18; + else + x *= 9; + if (!(ext[4] & 0x02)) + y *= 18; + else + y *= 9; + if (!(ext[3] & 0x01)) + z *= 18; + else + z *= 9; + + input_report_abs(wdata->mp, ABS_RX, x); + input_report_abs(wdata->mp, ABS_RY, y); + input_report_abs(wdata->mp, ABS_RZ, z); + input_sync(wdata->mp); +} + +static int wiimod_mp_open(struct input_dev *dev) +{ + struct wiimote_data *wdata = input_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&wdata->state.lock, flags); + wdata->state.flags |= WIIPROTO_FLAG_MP_USED; + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); + __wiimote_schedule(wdata); + spin_unlock_irqrestore(&wdata->state.lock, flags); + + return 0; +} + +static void wiimod_mp_close(struct input_dev *dev) +{ + struct wiimote_data *wdata = input_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&wdata->state.lock, flags); + wdata->state.flags &= ~WIIPROTO_FLAG_MP_USED; + wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); + __wiimote_schedule(wdata); + spin_unlock_irqrestore(&wdata->state.lock, flags); +} + +static int wiimod_mp_probe(const struct wiimod_ops *ops, + struct wiimote_data *wdata) +{ + int ret; + + wdata->mp = input_allocate_device(); + if (!wdata->mp) + return -ENOMEM; + + input_set_drvdata(wdata->mp, wdata); + wdata->mp->open = wiimod_mp_open; + wdata->mp->close = wiimod_mp_close; + wdata->mp->dev.parent = &wdata->hdev->dev; + wdata->mp->id.bustype = wdata->hdev->bus; + wdata->mp->id.vendor = wdata->hdev->vendor; + wdata->mp->id.product = wdata->hdev->product; + wdata->mp->id.version = wdata->hdev->version; + wdata->mp->name = WIIMOTE_NAME " Motion Plus"; + + set_bit(EV_ABS, wdata->mp->evbit); + set_bit(ABS_RX, wdata->mp->absbit); + set_bit(ABS_RY, wdata->mp->absbit); + set_bit(ABS_RZ, wdata->mp->absbit); + input_set_abs_params(wdata->mp, + ABS_RX, -16000, 16000, 4, 8); + input_set_abs_params(wdata->mp, + ABS_RY, -16000, 16000, 4, 8); + input_set_abs_params(wdata->mp, + ABS_RZ, -16000, 16000, 4, 8); + + ret = input_register_device(wdata->mp); + if (ret) + goto err_free; + + return 0; + +err_free: + input_free_device(wdata->mp); + wdata->mp = NULL; + return ret; +} + +static void wiimod_mp_remove(const struct wiimod_ops *ops, + struct wiimote_data *wdata) +{ + if (!wdata->mp) + return; + + input_unregister_device(wdata->mp); + wdata->mp = NULL; +} + const struct wiimod_ops wiimod_mp = { .flags = 0, .arg = 0, + .probe = wiimod_mp_probe, + .remove = wiimod_mp_remove, + .in_mp = wiimod_mp_in_mp, }; /* module table */ diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 324d442..46457f6 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h @@ -139,6 +139,7 @@ struct wiimote_data { struct input_dev *accel; struct input_dev *ir; struct power_supply battery; + struct input_dev *mp; struct timer_list timer; struct wiimote_ext *ext; struct wiimote_debug *debug;