Package: xserver-xorg-input-synaptics Version: 1.9.1-1 Followup-For: Bug #818471
Dear Maintainer, I am experiencing similar problem. The core of the issue is that some laptops have separated touchpad-like driver for the touchpad itself and for the buttons. As a result, two touchpad devices can be found in xinput -list. In my case these are: SYNA3071:00 06CB:82F1 Touchpad SynPS/2 Synaptics TouchPad The synclient and syndaemon programs are taking blindly the first touchpad-like device they find, which is unfortunatelly the generic SynPS/2 one. A possible dirty workaround is to disable 'psmouse' module, which makes that SynPS/2 touchpad to disappear, but at the same time the buttons next to the touchpad stop (partly) working. Attached is a patch to the synclient and syndaemon code, which makes sure the SynPS/2 device is used only when there is no other touchpad-like device found. At the same time a new option "-n device" is added so that user can select (by name) which device is to be used by the synclient and syndaemon programs. Feel free to alter the patch as/if needed. Best regards, Pavel
--- old/tools/synclient.c +++ new/tools/synclient.c @@ -30,6 +30,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/time.h> @@ -74,6 +75,8 @@ int prop_offset; /* Offset inside property */ }; +static const char *dev_substring; + static struct Parameter params[] = { {"LeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 0}, {"RightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 1}, @@ -245,12 +248,27 @@ return dpy; } +static void +dp_get_device_unwind(Atom ** properties, XDevice ** dev, int error, Display * dpy, XDeviceInfo * info) +{ + if ( *properties ) { + XFree(*properties); + *properties = NULL; + } + if ( info ) XFreeDeviceList(info); + if ( error && (*dev) ) { + XCloseDevice(dpy, *dev); + *dev = NULL; + } +} + static XDevice * dp_get_device(Display * dpy) { XDevice *dev = NULL; XDeviceInfo *info = NULL; int ndevices = 0; + int generic_device = -1; Atom touchpad_type = 0; Atom synaptics_property = 0; Atom *properties = NULL; @@ -267,16 +285,16 @@ if (!dev) { fprintf(stderr, "Failed to open device '%s'.\n", info[ndevices].name); - error = 1; - goto unwind; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; } properties = XListDeviceProperties(dpy, dev, &nprops); if (!properties || !nprops) { fprintf(stderr, "No properties on device '%s'.\n", info[ndevices].name); - error = 1; - goto unwind; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; } while (nprops--) { @@ -286,23 +304,41 @@ if (!nprops) { fprintf(stderr, "No synaptics properties on device '%s'.\n", info[ndevices].name); - error = 1; - goto unwind; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; } - break; /* Yay, device is suitable */ + fprintf(stderr, "Found device '%s'.\n", info[ndevices].name); + + if ( dev_substring != NULL && strlen(dev_substring) > 0 && !strstr(info[ndevices].name, dev_substring) ) { + fprintf(stderr, " - device '%s' not matching requested name '%s'.\n", + info[ndevices].name, dev_substring); + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; + } + + if ( !strcmp(info[ndevices].name, "SynPS/2 Synaptics TouchPad") ) { + fprintf(stderr, " - device '%s' is generic one, searching for another candidate.\n", + info[ndevices].name); + generic_device = ndevices; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; + } + + fprintf(stderr, "Taking device '%s'.\n", info[ndevices].name); + error = 0; + break; /* Yay, device is suitable */ } } - unwind: - XFree(properties); - XFreeDeviceList(info); - if (!dev) - fprintf(stderr, "Unable to find a synaptics device.\n"); - else if (error && dev) { - XCloseDevice(dpy, dev); - dev = NULL; + if ( generic_device != -1 && error && !dev ) { + fprintf(stderr, "Reverting back to generic device '%s'.\n", + info[generic_device].name); + dev = XOpenDevice(dpy, info[generic_device].id); + error = 0; } + dp_get_device_unwind(&properties, &dev, error, dpy, info); + return dev; } @@ -470,6 +506,7 @@ { fprintf(stderr, "Usage: synclient [-h] [-l] [-V] [-?] [var1=value1 [var2=value2] ...]\n"); fprintf(stderr, " -l List current user settings\n"); + fprintf(stderr, " -n Name (substring) of the touchpad device (xinput -list).\n"); fprintf(stderr, " -V Print synclient version string and exit\n"); fprintf(stderr, " -? Show this help message\n"); fprintf(stderr, " var=value Set user parameter 'var' to 'value'.\n"); @@ -490,11 +527,14 @@ dump_settings = 1; /* Parse command line parameters */ - while ((c = getopt(argc, argv, "lV?")) != -1) { + while ((c = getopt(argc, argv, "ln:V?")) != -1) { switch (c) { case 'l': dump_settings = 1; break; + case 'n': + dev_substring = optarg; + break; case 'V': printf("%s\n", VERSION); exit(0); --- old/tools/syndaemon.c +++ new/tools/syndaemon.c @@ -65,6 +65,7 @@ static int ignore_modifier_keys; static int background; static const char *pid_file; +static const char *dev_substring; static Display *display; static XDevice *dev; static Atom touchpad_off_prop; @@ -79,7 +80,7 @@ usage(void) { fprintf(stderr, - "Usage: syndaemon [-i idle-time] [-m poll-delay] [-d] [-t] [-k]\n"); + "Usage: syndaemon (reznicek) [-i idle-time] [-m poll-delay] [-d] [-t] [-k]\n"); fprintf(stderr, " -i How many seconds to wait after the last key press before\n"); fprintf(stderr, " enabling the touchpad. (default is 2.0s)\n"); @@ -87,6 +88,7 @@ fprintf(stderr, " (default is 200ms)\n"); fprintf(stderr, " -d Start as a daemon, i.e. in the background.\n"); fprintf(stderr, " -p Create a pid file with the specified name.\n"); + fprintf(stderr, " -n Name (substring) of the touchpad device (xinput -list).\n"); fprintf(stderr, " -t Only disable tapping and scrolling, not mouse movements.\n"); fprintf(stderr, @@ -502,12 +504,26 @@ } #endif /* HAVE_X11_EXTENSIONS_RECORD_H */ +dp_get_device_unwind(Atom ** properties, XDevice ** dev, int error, Display * dpy, XDeviceInfo * info) +{ + if ( *properties ) { + XFree(*properties); + *properties = NULL; + } + if ( info ) XFreeDeviceList(info); + if ( error && (*dev) ) { + XCloseDevice(dpy, *dev); + *dev = NULL; + } +} + static XDevice * dp_get_device(Display * dpy) { XDevice *dev = NULL; XDeviceInfo *info = NULL; int ndevices = 0; + int generic_device = -1; Atom touchpad_type = 0; Atom *properties = NULL; int nprops = 0; @@ -523,16 +539,16 @@ if (!dev) { fprintf(stderr, "Failed to open device '%s'.\n", info[ndevices].name); - error = 1; - goto unwind; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; } properties = XListDeviceProperties(dpy, dev, &nprops); if (!properties || !nprops) { fprintf(stderr, "No properties on device '%s'.\n", info[ndevices].name); - error = 1; - goto unwind; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; } while (nprops--) { @@ -542,23 +558,41 @@ if (nprops < 0) { fprintf(stderr, "No synaptics properties on device '%s'.\n", info[ndevices].name); - error = 1; - goto unwind; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; + } + + fprintf(stderr, "Found device '%s'.\n", info[ndevices].name); + + if ( dev_substring != NULL && strlen(dev_substring) > 0 && !strstr(info[ndevices].name, dev_substring) ) { + fprintf(stderr, " - device '%s' not matching requested name '%s'.\n", + info[ndevices].name, dev_substring); + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; + } + + if ( !strcmp(info[ndevices].name, "SynPS/2 Synaptics TouchPad") ) { + fprintf(stderr, " - device '%s' is generic one, searching for another candidate.\n", + info[ndevices].name); + generic_device = ndevices; + dp_get_device_unwind(&properties, &dev, error = 1, dpy, NULL); + continue; } - break; /* Yay, device is suitable */ + fprintf(stderr, "Taking device '%s'.\n", info[ndevices].name); + error = 0; + break; /* Yay, device is suitable */ } } - unwind: - XFree(properties); - XFreeDeviceList(info); - if (!dev) - fprintf(stderr, "Unable to find a synaptics device.\n"); - else if (error && dev) { - XCloseDevice(dpy, dev); - dev = NULL; + if ( generic_device != -1 && error && !dev ) { + fprintf(stderr, "Reverting back to generic device '%s'.\n", + info[generic_device].name); + dev = XOpenDevice(dpy, info[generic_device].id); + error = 0; } + dp_get_device_unwind(&properties, &dev, error, dpy, info); + return dev; } @@ -571,7 +605,7 @@ int use_xrecord = 0; /* Parse command line parameters */ - while ((c = getopt(argc, argv, "i:m:dtp:kKR?v")) != EOF) { + while ((c = getopt(argc, argv, "i:m:dtp:n:kKR?v")) != EOF) { switch (c) { case 'i': idle_time = atof(optarg); @@ -588,6 +622,9 @@ case 'p': pid_file = optarg; break; + case 'n': + dev_substring = optarg; + break; case 'k': ignore_modifier_keys = 1; break;