From patchwork Sun May 5 21:13:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 2521501 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 992EB3FD4E for ; Sun, 5 May 2013 21:14:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752233Ab3EEVOM (ORCPT ); Sun, 5 May 2013 17:14:12 -0400 Received: from mail-bk0-f52.google.com ([209.85.214.52]:55353 "EHLO mail-bk0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752266Ab3EEVOM (ORCPT ); Sun, 5 May 2013 17:14:12 -0400 Received: by mail-bk0-f52.google.com with SMTP id q16so1329692bkw.11 for ; Sun, 05 May 2013 14:14:10 -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=cvUz+2cH/AoqZs3gwcLzXhcaK3AmOewGgLiaoBDhzQY=; b=x3shiTvC7DM/IOq+1SXsnPFu7vMj8pDPvzggXvnsXIBuakjUvIUgqa+CH+1XC74Wrf nqFmGl98iBdp+21VXE+AIhbRljAr66FdHHYVLI+HV4rVZ1rknCMomWsHO+IyFwWFwE1K KDrAG1/NZv0SoFV44FMrVUQiua6/ZvxJ9XHA81sLkF/nQb1aGjxNgttRAY7Clj3Y4Gnp 1DQKG7xIfBvt/9N9cspFn/1SwDd/aKDpRGcdIF70gks0XP+e9oNvbe6BNh3pCntve+Ui 3pi2/CljUlkmKzaf301XIGZPtAJS+3pyGtesP+BwMjmWgi1v4jz/jk10Mc5EpbmzUPDs 3vRw== X-Received: by 10.204.232.8 with SMTP id js8mr7393395bkb.109.1367788450646; Sun, 05 May 2013 14:14:10 -0700 (PDT) Received: from localhost.localdomain (stgt-5f71a35b.pool.mediaWays.net. [95.113.163.91]) by mx.google.com with ESMTPSA id cv9sm4667233bkb.5.2013.05.05.14.14.08 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 05 May 2013 14:14:09 -0700 (PDT) From: David Herrmann To: linux-input@vger.kernel.org Cc: Jiri Kosina , David Herrmann Subject: [PATCH 17/26] HID: wiimote: add Motion Plus extension module Date: Sun, 5 May 2013 23:13:01 +0200 Message-Id: <1367788390-29835-18-git-send-email-dh.herrmann@gmail.com> X-Mailer: git-send-email 1.8.2.2 In-Reply-To: <1367788390-29835-1-git-send-email-dh.herrmann@gmail.com> References: <1367788390-29835-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 daeb679..aee1b2c 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 118520a..3a8bdb9 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;