From patchwork Sun Feb 14 22:24:32 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ed Tomlinson X-Patchwork-Id: 79326 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1EMPBLg028828 for ; Sun, 14 Feb 2010 22:25:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752383Ab0BNWYm (ORCPT ); Sun, 14 Feb 2010 17:24:42 -0500 Received: from mail001.aei.ca ([206.123.6.130]:58661 "EHLO mail001.aei.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752070Ab0BNWYl (ORCPT ); Sun, 14 Feb 2010 17:24:41 -0500 Received: (qmail 10989 invoked by uid 89); 14 Feb 2010 22:24:39 -0000 Received: by simscan 1.2.0 ppid: 10978, pid: 10986, t: 0.0024s scanners: regex: 1.2.0 attach: 1.2.0 Received: from mail002.aei.ca (HELO mail002.contact.net) (206.123.6.132) by mail001.aei.ca with (DHE-RSA-AES256-SHA encrypted) SMTP; 14 Feb 2010 22:24:39 -0000 Received: (qmail 12829 invoked by uid 89); 14 Feb 2010 22:24:39 -0000 Received: by simscan 1.2.0 ppid: 12814, pid: 12816, t: 0.8895s scanners: regex: 1.2.0 attach: 1.2.0 clamav: 0.95.3/m:51 spam: 3.3.0 X-Spam-Checker-Version: SpamAssassin 3.3.0 (2010-01-18) X-Spam-Level: X-Spam-Status: No, hits=-3.0 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham version=3.3.0 Received: from dsl-62-152.aei.ca (HELO grover.localnet) (edt@aei.ca@216.221.62.152) by mail.aei.ca with ESMTPA; 14 Feb 2010 22:24:38 -0000 From: Ed Tomlinson To: Jiri Kosina Subject: [PATCH 1/1] Enable xy scrolling for Apple Magic Mouse Date: Sun, 14 Feb 2010 17:24:32 -0500 User-Agent: KMail/1.13.0 (Linux/2.6.32.8-crc; KDE/4.4.0; x86_64; ; ) Cc: Michael Poole , linux-input@vger.kernel.org, Marcel Holtmann , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org References: <87y6j2eeqv.fsf_-_@troilus.org> In-Reply-To: MIME-Version: 1.0 Message-Id: <201002141724.33223.edt@aei.ca> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sun, 14 Feb 2010 22:25:12 +0000 (UTC) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index b20484a..3075d78 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -59,7 +59,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie * @delta_time: 18-bit difference between the two most recent touch * reports from the mouse. * @ntouches: Number of touches in most recent touch report. - * @scroll_accel: Number of consecutive scroll motions. + * @scroll_accely: Number of consecutive scroll motions. * @scroll_jiffies: Time of last scroll motion. * @touches: Most recent data for a touch, indexed by tracking ID. * @tracking_ids: Mapping of current touch input data to @touches. @@ -71,11 +71,13 @@ struct magicmouse_sc { int last_timestamp; int delta_time; int ntouches; - int scroll_accel; + int scroll_accely; + int scroll_accelx; unsigned long scroll_jiffies; struct { short x; + short scroll_x; short y; short scroll_y; u8 size; @@ -139,8 +141,10 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) input_report_key(msc->input, BTN_LEFT, state & 1); input_report_key(msc->input, BTN_RIGHT, state & 2); - if (state != last_state) - msc->scroll_accel = 0; + if (state != last_state) { + msc->scroll_accely = 0; + msc->scroll_accelx = 0; + } } static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) @@ -159,34 +163,46 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda msc->touches[id].size = misc & 63; /* If requested, emulate a scroll wheel by detecting small - * vertical touch motions along the middle of the mouse. + * touch motions on the mouse. */ if (emulate_scroll_wheel && - middle_button_start < x && x < middle_button_stop) { + msc->ntouches == 1) { static const int accel_profile[] = { - 256, 228, 192, 160, 128, 96, 64, 32, + 192, 160, 128, 96, 64, 48, 32, 24, }; unsigned long now = jiffies; - int step = msc->touches[id].scroll_y - y; + int stepx, stepy; /* Reset acceleration after half a second. */ - if (time_after(now, msc->scroll_jiffies + HZ / 2)) - msc->scroll_accel = 0; + if (time_after(now, msc->scroll_jiffies + HZ / 2)) { + msc->scroll_accely = 0; + msc->scroll_accelx = 0; + } - /* Calculate and apply the scroll motion. */ switch (tdata[7] & TOUCH_STATE_MASK) { case TOUCH_STATE_START: msc->touches[id].scroll_y = y; - msc->scroll_accel = min_t(int, msc->scroll_accel + 1, - ARRAY_SIZE(accel_profile) - 1); + msc->touches[id].scroll_x = x; break; case TOUCH_STATE_DRAG: - step = step / accel_profile[msc->scroll_accel]; - if (step != 0) { + /* Calculate and apply the scroll motion. */ + stepy = (msc->touches[id].scroll_y - y)/accel_profile[msc->scroll_accely]; + stepx = (msc->touches[id].scroll_x - x)/accel_profile[msc->scroll_accelx]; + + /* tell input about any motions */ + if (stepy != 0) { msc->touches[id].scroll_y = y; - msc->scroll_jiffies = now; - input_report_rel(input, REL_WHEEL, step); + input_report_rel(input, REL_WHEEL, stepy); + msc->scroll_accely = min_t(int, msc->scroll_accely + 1, + ARRAY_SIZE(accel_profile) - 1); } + if (stepx != 0) { + msc->touches[id].scroll_x = x; + input_report_rel(input, REL_HWHEEL, stepx); + msc->scroll_accelx = min_t(int, msc->scroll_accelx + 1, + ARRAY_SIZE(accel_profile) - 1); + } + msc->scroll_jiffies = now; break; } } @@ -300,8 +316,10 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h __set_bit(EV_REL, input->evbit); __set_bit(REL_X, input->relbit); __set_bit(REL_Y, input->relbit); - if (emulate_scroll_wheel) + if (emulate_scroll_wheel) { __set_bit(REL_WHEEL, input->relbit); + __set_bit(REL_HWHEEL, input->relbit); + } if (report_touches) { __set_bit(EV_ABS, input->evbit);