question about magic mouse drivers

I am resurrecting this very old post on purpose because I suspect many people are frustrated of being unable to scroll with their Magic Mouse on FreeBSD.

Yet, after having scoured the web for hours in search for information about that, to the point of shamefully asking one or two well-known LLMs who consistently spew out very creative nonsense about the problem, I concluded my findings were well worth posting for future readers, who will inevitably land here because that's where a Google search will lead them to.

TL;DR:

To have the Magic Mouse scroll events working in FreeBSD:
sysctl kern.evdev.rcpt_mask=9
(use this one if the Magic Mouse is meant to be your only pointing device).

To have the Magic Mouse *and* other pointing devices send scroll events:
sysctl kern.evdev.rcpt_mask=13
(with a gotcha: enable "System Mouse" in Xorg when you use the Magic Mouse and disable all the other mice, and disable "System Mouse" when you use another sort of mouse).

You can put these values in /etc/sysctl.conf.

Long story.
  1. FreeBSD has two redundant subsystems to receive mouse events. The legacy "sysmouse" and the newer "evdev". I understand the latter to be a sort of general-purpose hardware event catcher and dispatcher inspired from the Linux world.
  2. The sysctl I posted above instructs the drivers where to send keyboard and mouse events: either the legacy sysmouse subsystem, or the legacy keyboard multiplexer, or the newer hardware mouse through evdev, or newer hardware keyboard through evdev, or a combination of them, because it's a bitmap:
    0x1 - dispatch the event using the sysmouse semantics
    0x2 - dispatch an event for the keyboard multiplexer
    0x4 - dispatch an evdev mouse event
    0x8 - dispatch an evdev keyboard
    So for example setting this sysctl to 15 (1+2+4+8) would dispatch the keyboard or mouse event everywhere, which would possibly cause duplicate events, depending on which drivers are loaded - people would want to avoid that.
  3. On modern FreeBSD, the value of this sysctl is 12 (evdev mouse + evdev keyboard) because evdev is a mature system now, and every well-mannered driver should be using it.
  4. As per the comments in /sys/dev/evdev/evdev.h, this sysctl mask looks like a mere indication that other software are invited to follow, but does not enforce any sort of filtering. And, regarding the Magic Mouse, it happens that the piece of software (I'm not knowledgeable enough at the moment to tell what it is) that currently drives the Magic Mouse sends the mouse movements both to sysmouse and evdev, but sends scroll events to sysmouse only.
  5. At this point, one would say: if sysmouse receives both moves and scroll events, just set the sysctl to 9 = 1+8 (sysmouse + evdev keyboard), and let the good ole' sysmouse driver handle the Magic Mouse ; problem solved. Right? Almost.
  6. While setting that sysctl to 9 would work for the Magic Mouse, it has the downside that other mice (e.g. wired USB mice) can no longer scroll - I assume that's because their scroll events are sent to evdev only and not the old sysmouse. Just the other way around as the Magic Mouse.
  7. I don't carry the Magic Mouse everywhere with me. I often use whatever mouse I find at hand when I carry my FreeBSD laptop, and some of them are USB mice. I want their scroll wheels to work too. To do so, I conclude it is necessary to set the evdev.rcpt_mask sysctl to 13 (sysmouse+evdev mouse+evded keyboard), so that:
    - the Magic Mouse sends its move events to sysmouse+evdev and its scroll events to sysmouse,
    - the other mice send their move events to sysmouse+evdev and their scroll events to evdev.
  8. Now everybody scrolls up and down, but all the moves and button click events are processed twice. This is undesirable. To fix that, change your Xorg's input settings so that when you use the Magic Mouse, only the sysmouse ("System Mouse") device is enabled, and when you use another mouse, the sysmouse input is disabled and all the other mice are enabled back (note: it might be possible to automate this Xorg settings switch depending on what mouse is detected to be sending events at a lower level).
In hindsight, but I might be wrong, it looks like the Magic Mouse driver (I haven't found yet what piece of software in the src/sys tree drives it) is an old piece of code that was initially designed for the legacy sysmouse, and was later only partly adapted to generate evdev events in addition to sysmouse ones - the move events have been ported, but the scroll events are missing.

Unfortunately for us, the seemingly excellent NetBSD driver for the Magic Mouse and the Magic Trackpad can not be easily ported to FreeBSD, because the Bluetooth stacks are completely different.

One last remark. The sysmouse-based event handling of the Magic Mouse, although it's the only one with which the scrolling works, feels less comfortable than the evdev one (e.g. some doubleclicks are missed). The solution I described above is a sort of "hack" anyway; but I'm a rather experienced programmer. So if a good soul could point me at where I need to look to implement the missing evdev events for scrolling with the Magic Mouse, I might have a try at submitting my first official FreeBSD source code contribution...
 
Back
Top