aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChase Douglas <chase.douglas@canonical.com>2010-06-20 21:32:30 -0400
committerJiri Kosina <jkosina@suse.cz>2010-06-24 04:49:39 -0400
commit0b778e76c1e7ccf49f8980b594e72f984095fd26 (patch)
tree54b14fb5a51c63c83dc332990cf3d34988837d34
parent8d93efb27ab8927ffc7a357f1b2d10039de50ed4 (diff)
HID: magicmouse: add param for scroll speed
The new scroll_speed param takes an integer value from 0 to 63, where 0 is slowest and 63 is fastest. The default of 32 remains the same. This parameter also affects scroll acceleration linearly. A second part of this change is a tightly coupled modification to the scroll acceleration. Previously, scroll acceleration could be reset without lifting the scroll finger. This is rather unintuitive and hard to control in the case where a user wants faster scrolling, but wants to hold the scroll touch for longer than a moment. Note that scroll acceleration levels are now 1-7, where 7 is slowest. In the previous implementation, there were 8 levels defined, but it was impossible to start at the slowest level. In order to keep the default scroll speed unchanged, only 7 levels are used now. Signed-off-by: Chase Douglas <chase.douglas@canonical.com> Acked-by: Michael Poole <mdpoole@troilus.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-magicmouse.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index f44aaf21e1e2..fe0c760d7e6e 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -30,6 +30,17 @@ static bool emulate_scroll_wheel = true;
30module_param(emulate_scroll_wheel, bool, 0644); 30module_param(emulate_scroll_wheel, bool, 0644);
31MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); 31MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
32 32
33static unsigned int scroll_speed = 32;
34static int param_set_scroll_speed(const char *val, struct kernel_param *kp) {
35 unsigned long speed;
36 if (!val || strict_strtoul(val, 0, &speed) || speed > 63)
37 return -EINVAL;
38 scroll_speed = speed;
39 return 0;
40}
41module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644);
42MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)");
43
33static bool scroll_acceleration = false; 44static bool scroll_acceleration = false;
34module_param(scroll_acceleration, bool, 0644); 45module_param(scroll_acceleration, bool, 0644);
35MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); 46MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events");
@@ -54,6 +65,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
54#define TOUCH_STATE_START 0x30 65#define TOUCH_STATE_START 0x30
55#define TOUCH_STATE_DRAG 0x40 66#define TOUCH_STATE_DRAG 0x40
56 67
68#define SCROLL_ACCEL_DEFAULT 7
69
57/** 70/**
58 * struct magicmouse_sc - Tracks Magic Mouse-specific data. 71 * struct magicmouse_sc - Tracks Magic Mouse-specific data.
59 * @input: Input device through which we report events. 72 * @input: Input device through which we report events.
@@ -145,7 +158,7 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state)
145 input_report_key(msc->input, BTN_RIGHT, state & 2); 158 input_report_key(msc->input, BTN_RIGHT, state & 2);
146 159
147 if (state != last_state) 160 if (state != last_state)
148 msc->scroll_accel = 0; 161 msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
149} 162}
150 163
151static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) 164static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata)
@@ -167,30 +180,28 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
167 * vertical touch motions. 180 * vertical touch motions.
168 */ 181 */
169 if (emulate_scroll_wheel) { 182 if (emulate_scroll_wheel) {
170 static const int accel_profile[] = {
171 256, 228, 192, 160, 128, 96, 64, 32,
172 };
173 unsigned long now = jiffies; 183 unsigned long now = jiffies;
174 int step = msc->touches[id].scroll_y - y; 184 int step = msc->touches[id].scroll_y - y;
175 185
176 /* Reset acceleration after half a second. */
177 if (time_after(now, msc->scroll_jiffies + HZ / 2))
178 msc->scroll_accel = 0;
179
180 /* Calculate and apply the scroll motion. */ 186 /* Calculate and apply the scroll motion. */
181 switch (tdata[7] & TOUCH_STATE_MASK) { 187 switch (tdata[7] & TOUCH_STATE_MASK) {
182 case TOUCH_STATE_START: 188 case TOUCH_STATE_START:
183 msc->touches[id].scroll_y = y; 189 msc->touches[id].scroll_y = y;
184 if (scroll_acceleration) 190
185 msc->scroll_accel = min_t(int, 191 /* Reset acceleration after half a second. */
186 msc->scroll_accel + 1, 192 if (scroll_acceleration && time_before(now,
187 ARRAY_SIZE(accel_profile) - 1); 193 msc->scroll_jiffies + HZ / 2))
194 msc->scroll_accel = max_t(int,
195 msc->scroll_accel - 1, 1);
196 else
197 msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
198
188 break; 199 break;
189 case TOUCH_STATE_DRAG: 200 case TOUCH_STATE_DRAG:
190 step = step / accel_profile[msc->scroll_accel]; 201 step /= (64 - (int)scroll_speed) * msc->scroll_accel;
191 if (step != 0) { 202 if (step != 0) {
192 msc->touches[id].scroll_y -= 203 msc->touches[id].scroll_y -= step *
193 step * accel_profile[msc->scroll_accel]; 204 (64 - scroll_speed) * msc->scroll_accel;
194 msc->scroll_jiffies = now; 205 msc->scroll_jiffies = now;
195 input_report_rel(input, REL_WHEEL, step); 206 input_report_rel(input, REL_WHEEL, step);
196 } 207 }
@@ -351,6 +362,8 @@ static int magicmouse_probe(struct hid_device *hdev,
351 return -ENOMEM; 362 return -ENOMEM;
352 } 363 }
353 364
365 msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
366
354 msc->quirks = id->driver_data; 367 msc->quirks = id->driver_data;
355 hid_set_drvdata(hdev, msc); 368 hid_set_drvdata(hdev, msc);
356 369