Home
Apple Touchpad Driver for FreeBSD
This Wiki describes a FreeBSD driver for the Apple Internal Trackpad device found on MacBooks and potentially other Apple laptops.
Compatibility
This driver has been developed on a MacBook4,1 running FreeBSD8.0. It should be compatible with touchpads with the following product-ids:
- 0×21{7,8,9}
- 0×21{a,b,c}
- 0×22{9,a,b}
You can discover yours from the output oflshalby searching for ‘Trackpad’ and looking up the propertyusb_device.product_id.
I’d be willing to help if you wish to reverse engineer a newer model on your laptop.
Features
- Movement smoothening with configurable sensitivity. The smoothening algorithm takes into consideration the X and Y motions together in order to better replicate finger motion.
- Simulation of a three-button mouse using finger-finger tap detection. Two-finger tap maps to the middle button; whereas a three-finger tap gets treated as the right button.
- Filtering away of activity at the horizontal edges—this is to keep the palms from interfering.
- Double-tap followed by a drag is treated as a selection gesture; a virtual button click is assumed for the lifespan of the drag.
- Infrastructure has been put in place to track multiple concurrent strokes; this may permit gesture detection in the future.
Installation
Build Instructions
On a machine with FreeBSD8.0 or similar, you may build the driver as a kernel module using:
$ git clone git://github.com/rgrover/freebsd-atp.git
$ cd freebsd-atp
$ make
The resulting module is atp.ko.
Loading atp.ko
You may already be using the generic USB mouse driver ums for the touchpad. If ums is loaded as a kernel module then you should unload ‘ums.ko’ before atp picks up the touchpad; otherwise if ums is compiled into the kernel then:
- you’ll need to install atp.ko under
/boot/kernel/(see instructions below), - arrange to have atp.ko autoloaded at boot (through settings in
/boot/loader.conf), - and then reboot before atp takes effect.
Atp and ums can co-exist in a system. At boot time, both these drivers report compatibility with the touchpad device, but atp is able to attach to the device with greater affinity—the ums driver may still attach to other USB-mice as before. Note: in order to make ums behave as described here, I had to use the following patch:
--- dev/usb/input/ums.c (revision 198470) +++ dev/usb/input/ums.c (working copy) @@ -372,7 +372,7 @@if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) && (uaa->info.bInterfaceProtocol == UIPROTO_MOUSE)) - return (0); + return (BUS_PROBE_GENERIC);error = usbd_req_get_hid_desc(uaa->device, NULL, &d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex); @@ -382,7 +382,7 @@if (hid_is_collection(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) - error = 0; + error = BUS_PROBE_GENERIC; else error = ENXIO;
If ums is loaded as a kernel module (as opposed to being compiled into the kernel), then you won’t need to reboot in order to try atp. We shall proceed with this assumption.
Ums may be unloaded to free up the touchpad device using the following:
$ sudo kldunload ums
Atp may now be loaded to pickup the touchpad:
$ sudo kldload ./atp.ko
This should emit some diagnostic output on the console; which may also be inspected using dmesg.
Changes to /etc/rc.conf
Atp creates a pseudo-device file /dev/atp which may be accessed (through read()s and ioctl()s) to obtain information about the touchpad. Such access is typically done by moused, which passes the data along to the sysmouse driver so that any user process which wants to utilize mouse operation (such as the X server) may simply open /dev/sysmouse and read mouse data from that device. There is some reason to this complicated state of affairs: moused is responsible for collecting mouse data from potentially multiple input devices (trackpad, trackpoint, external mice etc.); whereas the sysmouse driver serves as the common collection point for this data and aims to provide a coherent view of the system’s mice.
You can configure moused to use /dev/atp by adding the following to /etc/rc.conf.
moused_enable="YES"
moused_type="auto"
moused_port="/dev/atp"
If you want moused to also probe for external USB mice or other devices, then add something like the following to /etc/rc.conf (note: you may require to change the following as appropriate to your settings).
moused_nondefault_enable="YES"
moused_ums0_enable="YES"
moused_ums1_enable="YES"
X server to use /dev/sysmouse
The X server should be fetching mouse data from /dev/sysmouse. Ensure that you have something like the following in your /etc/X11/xorg.conf.
Section "InputDevice"
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/sysmouse"
Option "ZAxisMapping" "4 5 6 7"
EndSection
Restarting moused
Atp is enabled only when some user process (moused) accesses /dev/atp. After editing /etc/rc.conf (as above), moused will be automatically started at boot to read from /dev/atp; but if you’re trying out atp without a reboot, moused may be restarted using:
$ sudo /etc/rc.d/moused restart
And voila! You should be able to use the trackpad now.
Installing atp.ko under /boot/kernel
If you are satisfied with atp, you may install it under /boot/kernel by executing the following from the build directory:
$ sudo make install
Loading atp Automatically at Boot
If you want to autoload atp.ko upon boot, you should install it under /boot/kernel and add the following to /boot/loader.conf:
atp_load="YES"
Configuration
Atp may be configured using ‘sysctls’.
$ sysctl hw.usb.atp
hw.usb.atp.debug: 1
hw.usb.atp.pspan_max_width: 4
hw.usb.atp.pspan_min_cum_pressure: 10
hw.usb.atp.sensor_noise_threshold: 2
hw.usb.atp.stroke_maturity_threshold: 2
hw.usb.atp.slide_min_movement: 8
hw.usb.atp.max_delta_mickeys: 96
hw.usb.atp.small_movement: 8
hw.usb.atp.scale_factor: 64
hw.usb.atp.touch_timeout: 125000
Scale Factor
Of the above sysctls, the most important is hw.usb.atp.scale_factor. Finger movement on the touchpad is converted to motion units using this scale factor. Larger values for this tunable parameter will make movements more pronounced.
Debug
Extra diagnostics may be dumped on the console by setting higher values for hw.usb.atp.debug. Setting this tunable to 3 will display a information about the internal state of strokes as the device is used.
