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 | ||
