diff options
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 43 |
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; | |||
30 | module_param(emulate_scroll_wheel, bool, 0644); | 30 | module_param(emulate_scroll_wheel, bool, 0644); |
31 | MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); | 31 | MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); |
32 | 32 | ||
33 | static unsigned int scroll_speed = 32; | ||
34 | static 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 | } | ||
41 | module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644); | ||
42 | MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)"); | ||
43 | |||
33 | static bool scroll_acceleration = false; | 44 | static bool scroll_acceleration = false; |
34 | module_param(scroll_acceleration, bool, 0644); | 45 | module_param(scroll_acceleration, bool, 0644); |
35 | MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); | 46 | MODULE_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 | ||
151 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) | 164 | static 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 | ||