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;

Reply via email to