Skip to content

Commit

Permalink
Apply fixes from kernel 5.15. Refers to #12.
Browse files Browse the repository at this point in the history
  • Loading branch information
RicardoEPRodrigues committed Jul 16, 2021
1 parent 71570b7 commit c21b7cc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Linux Apple Magic Mouse 2 and Magic Trackpad 2 Driver

This repository contains the linux hid-magicmouse driver with Magic Trackpad 2 and Magic Mouse 2 support for Linux 4.18. For older kernels you might have to diff and backport. It also contains 2 fixes to the Magic Mouse 2 regarding Bluetooth random disconnections and this driver not loading on bluetooth reconnection.
This repository contains the linux hid-magicmouse driver with Magic Trackpad 2 and Magic Mouse 2 support for Linux 4.18 onwards. For older kernels you might have to diff and backport. It also contains 2 fixes to the Magic Mouse 2 regarding Bluetooth random disconnections and this driver not loading on bluetooth reconnection.

This driver is based off of the work of @robotrovsky, @svartalf, @0xABAD and probably others.

Please help to test this driver and report issues.

**NOTE**: Since kernel version 5.15, there is support for the mouse without the need for this driver. We try to backport changes to this driver to have it up-to-date with the one on the kernel and try to offer a bit more functionality but it is not perfect. If you want the mouse to just work either install a more recent kernel or proceed with this driver installation.

## Ubuntu (and derivatives)

A `.deb` file is now available in Releases. Get the [latest version here](https://github.com/RicardoEPRodrigues/magicmouse-hid/releases/latest).
Expand Down
57 changes: 55 additions & 2 deletions linux/drivers/hid/hid-magicmouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
#define TOUCH_STATE_START 0x30
#define TOUCH_STATE_DRAG 0x40

/* Number of high-resolution events for each low-resolution detent. */
#define SCROLL_HR_STEPS 10
#define SCROLL_HR_MULT (120 / SCROLL_HR_STEPS)
#define SCROLL_HR_THRESHOLD 90 /* units */
#define SCROLL_ACCEL_DEFAULT 3

/* Touch surface information. Dimension is in hundredths of a mm, min and max
Expand Down Expand Up @@ -169,7 +173,11 @@ struct magicmouse_sc {
short y;
short scroll_x;
short scroll_y;
short scroll_x_hr;
short scroll_y_hr;
u8 size;
bool scroll_x_active;
bool scroll_y_active;
} touches[MAX_TOUCHES];
int tracking_ids[MAX_TOUCHES];

Expand Down Expand Up @@ -346,6 +354,10 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id,
unsigned long now = jiffies;
int step_x = msc->touches[id].scroll_x - x;
int step_y = msc->touches[id].scroll_y - y;
int step_hr = ((64 - (int)scroll_speed) * msc->scroll_accel) /
SCROLL_HR_STEPS;
int step_x_hr = msc->touches[id].scroll_x_hr - x;
int step_y_hr = msc->touches[id].scroll_y_hr - y;

/* Determine if the mouse has moved, if so then disable scrolling. */
bool continue_scroll = true;
Expand All @@ -360,6 +372,10 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id,
case TOUCH_STATE_START:
msc->touches[id].scroll_x = x;
msc->touches[id].scroll_y = y;
msc->touches[id].scroll_x_hr = x;
msc->touches[id].scroll_y_hr = y;
msc->touches[id].scroll_x_active = false;
msc->touches[id].scroll_y_active = false;

/* Reset acceleration after half a second. */
if (scroll_acceleration && time_before(now,
Expand Down Expand Up @@ -400,6 +416,40 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id,
msc->scroll_jiffies = now;
input_report_rel(input, REL_WHEEL, step_y);
}

if (!msc->touches[id].scroll_x_active &&
abs(step_x_hr) > SCROLL_HR_THRESHOLD) {
msc->touches[id].scroll_x_active = true;
msc->touches[id].scroll_x_hr = x;
step_x_hr = 0;
}

step_x_hr /= step_hr;
if (step_x_hr != 0 &&
msc->touches[id].scroll_x_active) {
msc->touches[id].scroll_x_hr -= step_x_hr *
step_hr;
input_report_rel(input,
REL_HWHEEL_HI_RES,
-step_x_hr * SCROLL_HR_MULT);
}

if (!msc->touches[id].scroll_y_active &&
abs(step_y_hr) > SCROLL_HR_THRESHOLD) {
msc->touches[id].scroll_y_active = true;
msc->touches[id].scroll_y_hr = y;
step_y_hr = 0;
}

step_y_hr /= step_hr;
if (step_y_hr != 0 &&
msc->touches[id].scroll_y_active) {
msc->touches[id].scroll_y_hr -= step_y_hr *
step_hr;
input_report_rel(input,
REL_WHEEL_HI_RES,
step_y_hr * SCROLL_HR_MULT);
}
break;
}
}
Expand Down Expand Up @@ -623,6 +673,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
if (emulate_scroll_wheel) {
__set_bit(REL_WHEEL, input->relbit);
__set_bit(REL_HWHEEL, input->relbit);
__set_bit(REL_WHEEL_HI_RES, input->relbit);
__set_bit(REL_HWHEEL_HI_RES, input->relbit);
}
} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD){
/* input->keybit is initialized with incorrect button info
Expand Down Expand Up @@ -835,7 +887,7 @@ static int magicmouse_probe(struct hid_device *hdev,
if (id->vendor == USB_VENDOR_ID_APPLE &&
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
hdev->type != HID_TYPE_USBMOUSE)
return 0;
return -ENODEV;

msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
if (msc == NULL) {
Expand Down Expand Up @@ -922,7 +974,8 @@ static int magicmouse_probe(struct hid_device *hdev,
static void magicmouse_remove(struct hid_device *hdev)
{
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
cancel_delayed_work_sync(&msc->work);
if (msc)
cancel_delayed_work_sync(&msc->work);
hid_hw_stop(hdev);
}

Expand Down

0 comments on commit c21b7cc

Please sign in to comment.