Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ===== Synaptics Touchpad ===== ===== Introduction ===== 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 [[https://docs.freebsd.org/en/books/faq/#x-and-synaptic|FreeBSD FAQ: My laptop has a Synaptics Touchpad. Can I use it in X?]] ===== Features ===== * Improved movement smoothing. It's comparable to the Microsoft Windows driver from Synaptics, except when the finger reaches touchpad borders where the movement becomes chaotic. * Tap detection with one (left click), two (right click), or three (middle click) finger tap support. * Tap-hold detection with one, two, or three fingers. * Virtual scrolling. For now, an area must be dedicated to virtual scrolling; typically, one on the right (vertical scrolling) and one at the bottom (horizontal scrolling). Also, a patch must be applied to xf86-input-mouse to handle horizontal scrolling from sysmouse. Later, virtual scrolling with two fingers will be re-added, as found on Apple %%MacBook%%. ===== Setup ===== To enable psm(4) Synaptics support, add the following line to ''%%/boot/loader.conf%%'' <code> hw.psm.synaptics_support="1" </code> Enable moused(8). Add the following to ''%%/etc/rc.conf%%'' <code> moused_enable="YES" </code> 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%%'' <code> Section "InputDevice" Identifier "Mouse0" Driver "mouse" Option "Protocol" "auto" Option "Device" "/dev/sysmouse" Option "ZAxisMapping" "4 5 6 7" EndSection </code> Horizontal scrolling is disabled by default. To enable it, add the following to ''%%/etc/sysctl.conf%%'' <code> hw.psm.synaptics.vscroll_hor_area=1300 </code> ===== Touchpad Configuration ===== ==== Palm Detection ==== === Finger Pressure === <code> hw.psm.synaptics.min_pressure: 16 hw.psm.synaptics.max_pressure: 220 </code> 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: * z = 0: no finger contact * z = 10: finger hovering near the pad * z = 30: very light finger contact * z = 80: normal finger contact * z = 110: very heavy finger contact * z = 200: finger lying flat on pad surface * z = 255: maximum reportable Z === Finger Width === <code> hw.psm.synaptics.max_width: 10 </code> 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: * w = 4-7: finger of normal width (capPalmDetect needed) * w = 8-14: very wide finger or palm (capPalmDetect needed) * w = 15: maximum reportable width (capPalmDetect needed ==== Movement Smoothing ==== 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". <code> 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 </code> ''%%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%%''. <code> 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 </code> ''%%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%%''. <code> hw.psm.synaptics.multiplicator: 10000 </code> This multiplicator is used during averages and divisions to increase the precision. === How Movement Smoothing Works === The smoothing is based on a weighted average: <code cpp> average = (weight_current * delta + weight_previous * average) / (weight_current + weight_preivous) </code> 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: * If the movement is slow, we keep ''%%weight_previous%%'' at its original value. * If the movement is fast, ''%%weight_previous%%'' decreases and may reach 0 for the fastest movements. Internaly, the driver keeps the last 10 packets. Here is the simplified algorithm: <code cpp> 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); </code> 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 Borders (Margins) ==== Touchpad edges (borders) can generate a lot of noise in reported coordinates. There are two sets of sysctl tunables that control this area: <code> hw.psm.synaptics.margin_top: 200 hw.psm.synaptics.margin_right: 200 hw.psm.synaptics.margin_bottom: 200 hw.psm.synaptics.margin_left: 200 </code> These margins act as a high-pass filter: for instance, the point [50; 170] will be reported as [200;200]. <code> hw.psm.synaptics.na_top: 1783 hw.psm.synaptics.na_right: 563 hw.psm.synaptics.na_bottom: 1408 hw.psm.synaptics.na_left: 1600 </code> ''%%na%%'' stands for noisy area. Movements inside these larger margins will be smoothed using different max weight and divisor. See "Movement Smoothing". ==== Points History ==== <code> hw.psm.synaptics.window_min: 4 hw.psm.synaptics.window_max: 10 </code> ''%%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. ==== Tap and Tap-hold ==== <code> hw.psm.synaptics.tap_max_delta: 80 hw.psm.synaptics.tap_min_queue: 2 </code> ''%%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. <code> hw.psm.synaptics.taphold_timeout: 125000 </code> ''%%taphold_timeout%%'' is the time (in microseconds) between two taps to consider a tap-hols action. ==== Virtual Scrolling ==== <code> 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 </code> 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. ===== Toggling Synaptics Touchpad with devd ===== 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%%''. ==== Setup ==== 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: <code> #!/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 </code> Then you will want to make the script executable. <code> chmod +x synaptics-hotplug </code> Next you will want to open /etc/devd/usb.conf and navigate to line 5686, it should look like the following: <code> nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "intclass" "0x03"; match "intsubclass" "0x01"; match "intprotocol" "0x02"; action "kldload -n ums"; }; </code> That last line in the block, 'action' is what runs everytime we plug in our USB mouse, edit it so it runs our script: <code> action "kldload -n ums && /usr/local/bin/synaptics-hotplug disable"; </code> 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): <code> detach 100 { device-name "ums[0-9]+"; action "/usr/local/bin/synaptics-hotplug enable"; }; </code> With this done, the only thing you'll need to do is restart devd <code> service devd restart </code> 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. ===== Other Resources ===== * [[https://www.freshports.org/sysutils/iichid/|FreeBSD Port: sysutils/iichid -- Generic FreeBSD HID layer for I2C and USB devices]] ---- {{tag>HowTo}} {{tag>Laptop}} synapticstouchpad.txt Last modified: 2022/08/18 05:58by KubilayKocak