The Synaptics Touchpad is a pointing device found on many laptops and supported since FreeBSD 8.
By default, it is recognized and configured as a 3-buttons mouse. Additional features can be enabled with the hw.psm.synaptics_support sysctl tunable.
Also check out FreeBSD FAQ: My laptop has a Synaptics Touchpad. Can I use it in X?
To enable psm(4) Synaptics support, add the following line to /boot/loader.conf
hw.psm.synaptics_support="1"
Enable moused(8). Add the following to /etc/rc.conf
moused_enable="YES"
To use it within X.Org, disable the X.Org-specific Synaptics driver, and configure a sysmouse mouse. Here's an example section for /etc/X11/xorg.conf
Section "InputDevice"
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/sysmouse"
Option "ZAxisMapping" "4 5 6 7"
EndSection
Horizontal scrolling is disabled by default. To enable it, add the following to /etc/sysctl.conf
hw.psm.synaptics.vscroll_hor_area=1300
hw.psm.synaptics.min_pressure: 16 hw.psm.synaptics.max_pressure: 220
If the pressure is less than min_pressure or above max_pressure, the packet is ignored but the current action isn't terminated. The pressure is comprised between 0 and 255. Here are some meaningful values, as stated by Synaptics specifications:
hw.psm.synaptics.max_width: 10
If the finger width is above max_width, the packet is ignored but the current action isn't terminated. The width is comprised between 4 and 15. Here are some meningful values, as stated by Synaptics specifications:
For movement smoothing, we use a weighted average then a division where both the weight and the divisor vary, depending on the movement speed. See “How it works”.
hw.psm.synaptics.weight_current: 3 hw.psm.synaptics.weight_previous: 6 hw.psm.synaptics.weight_previous_na: 20 hw.psm.synaptics.weight_len_squared: 2000
weight_current and weight_previous define the range of weights to use when calculating the average. weight_previous_na is used instead of weight_previous when the finger is inside the noisy area (see “Touchpad borders”).
TODO: explain weight_len_squared.
hw.psm.synaptics.div_min: 9 hw.psm.synaptics.div_max: 17 hw.psm.synaptics.div_max_na: 30 hw.psm.synaptics.div_len: 100
div_min and div_max define the range of divisors to when calculating the final delta for x & y. div_max_na is used instead of div_max when the finger is inside the noisy area (see “Touchpad borders”).
TODO: explain div_len.
hw.psm.synaptics.multiplicator: 10000
This multiplicator is used during averages and divisions to increase the precision.
The smoothing is based on a weighted average:
average = (weight_current * delta + weight_previous * average) / (weight_current + weight_preivous)
where :
average is the previous average, which is kept between each packet.delta is the relative movement.weight_current and weight_previous are configurable weights.This average is calculated for each axis (x & y) separately.
The problem with a simple weighted average as above is that the user has to choose between a smooth but laggy movement (weight_previous greater then weight_current) or a sharp but imprecise movement at slow speed (weight_previous smaller or equal to weight_current).
The idea is then to change weight_previous based on the last packets:
weight_previous at its original value.weight_previous decreases and may reach 0 for the fastest movements.Internaly, the driver keeps the last 10 packets. Here is the simplified algorithm:
dx = abs(new_x - older_x) + 1; /* +1: to avoid a division by zero below. */ dy = abs(new_y - older_y) + 1; /* "len" is really the length squared. */ len = (dx * dx) + (dy * dy); /* "sysctl_weight_len_squared" is the length squared at which the * "weight_previous" will start to decrease. */ weight_previous = sysctl_weight_len_squared * weight_previous / len; weight_previous = imin(weight_previous, sysctl_weight_previous);
The driver will do almost the same with the divisor to calculate the acceleration. The rest of the division is also kept between each packet; otherwise, with slow movements, the pointer doesn't reproduce well what the finger is doing.
Touchpad edges (borders) can generate a lot of noise in reported coordinates. There are two sets of sysctl tunables that control this area:
hw.psm.synaptics.margin_top: 200 hw.psm.synaptics.margin_right: 200 hw.psm.synaptics.margin_bottom: 200 hw.psm.synaptics.margin_left: 200
These margins act as a high-pass filter: for instance, the point [50; 170] will be reported as [200;200].
hw.psm.synaptics.na_top: 1783 hw.psm.synaptics.na_right: 563 hw.psm.synaptics.na_bottom: 1408 hw.psm.synaptics.na_left: 1600
na stands for noisy area. Movements inside these larger margins will be smoothed using different max weight and divisor. See “Movement Smoothing”.
hw.psm.synaptics.window_min: 4 hw.psm.synaptics.window_max: 10
window_min indicates the minimum number of packets to receive before an action is considered to be real and wanted. window_max is the maximum number of packets to use in calculations.
hw.psm.synaptics.tap_max_delta: 80 hw.psm.synaptics.tap_min_queue: 2
tap_max_delta is the maximum delta between points to treat the action as a tap. This is to prevent any unwanted click. tap_min_queue is the minimum number of packets needed to consider a tap.
hw.psm.synaptics.taphold_timeout: 125000
taphold_timeout is the time (in microseconds) between two taps to consider a tap-hols action.
hw.psm.synaptics.vscroll_hor_area: 1300 hw.psm.synaptics.vscroll_ver_area: -600 hw.psm.synaptics.vscroll_min_delta: 50 hw.psm.synaptics.vscroll_div_min: 100 hw.psm.synaptics.vscroll_div_max: 150
An area must be dedicated to virtual scrolling for now. This area is defined by vscroll_hor_area (positive for an area at the bottom, negative for an area at the top) for horizontal scrolling and vscroll_ver_area (positive for an area on the left, negative for an area on the right) for vertical scrolling. vscroll_min_delta is the minimum delta between points to consider a scrolling action. This is to prevent unwanted scrolling when tapping for instance. vscroll_div_min and vscroll_div_max are the divisors used instead of div_min and div_max respectively.
Although touchpads can support palm detection, it is sometimes desirable to disable them if a USB mouse is plugged in.
These instructions assume a USB wired or wireless mouse. For a mouse that connects via Bluetooth, you will also need to identify your mouse device-name.
We will be triggering a script from devd in order to toggle synaptics.
Create a new script in /usr/local/bin named “synaptics-hotplug”.
In this script, paste the following:
#!/bin/sh
trackpad_disable(){
/sbin/sysctl hw.psm.synaptics.min_pressure=220
}
trackpad_enable(){
/sbin/kldunload ums
/sbin/sysctl hw.psm.synaptics.min_pressure=32
}
synaptics_$1
Then you will want to make the script executable.
chmod +x synaptics-hotplug
Next you will want to open /etc/devd/usb.conf and navigate to line 5686, it should look like the following:
nomatch 32 {
match "bus" "uhub[0-9]+";
match "mode" "host";
match "intclass" "0x03";
match "intsubclass" "0x01";
match "intprotocol" "0x02";
action "kldload -n ums";
};
That last line in the block, 'action' is what runs everytime we plug in our USB mouse, edit it so it runs our script:
action "kldload -n ums && /usr/local/bin/synaptics-hotplug disable";
Now everytime we plug in our USB mouse, it will run our script with the “disable” argument variable which runs our script's “synaptics_disable” function, this changes our synaptics trackpad minimal pressure to 220, disabling it.
Next open /etc/devd.conf as root and put the following at the end of the file(or anywhere):
detach 100 {
device-name "ums[0-9]+";
action "/usr/local/bin/synaptics-hotplug enable";
};
With this done, the only thing you'll need to do is restart devd
service devd restart
Once devd is restarted, the synaptics trackpad should turn off and on depending whether your USB mouse is plugged in.
Credit for scripted synpatics toggle via devd goes to SamuelGogarty.