summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2021-11-25 21:03:39 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2021-12-20 15:01:56 +1000
commitd5ca999f35c7de7032a7e2c7df25019a636e59f6 (patch)
treeb8c4619563e6acab23445a2b6d54d396ef0e4234 /src
parent91cbc367947556420e546a5c48107aa62da6231f (diff)
downloadxf86-input-wacom-d5ca999f35c7de7032a7e2c7df25019a636e59f6.tar.gz
Add a helper function to iterate over local devices to the driver layer
wcmForeachDevice() calls a callback on each device that uses the wacom driver. Switch our loops over to use that instead of iterating manually - this makes the driver code independent of the X way of iterating through devices (and finding those using the wacom driver). Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'src')
-rw-r--r--src/wcmConfig.c211
-rw-r--r--src/wcmValidateDevice.c82
-rw-r--r--src/xf86Wacom.c27
-rw-r--r--src/xf86Wacom.h13
4 files changed, 186 insertions, 147 deletions
diff --git a/src/wcmConfig.c b/src/wcmConfig.c
index 7b85b8f..b637938 100644
--- a/src/wcmConfig.c
+++ b/src/wcmConfig.c
@@ -258,44 +258,36 @@ void wcmDisableTool(WacomDevicePtr priv)
wcmEnableDisableTool(priv, FALSE);
}
+static int unlinkDevice(WacomDevicePtr tmppriv, /* tmppriv is the iterated device */
+ void *data)
+{
+ WacomDevicePtr priv = data; /* our device is the data argument */
+ WacomCommonPtr common = priv->common;
+ WacomCommonPtr tmpcommon = tmppriv->common;
+ Bool touch_device = (common->wcmTouchDevice || tmpcommon->wcmTouchDevice);
+
+ if (!touch_device || tmpcommon->tablet_id != common->tablet_id)
+ return -ENODEV;
+
+ common->wcmTouchDevice = NULL;
+ tmpcommon->wcmTouchDevice = NULL;
+ common->tablet_type &= ~WCM_PENTOUCH;
+ tmpcommon->tablet_type &= ~WCM_PENTOUCH;
+ return 0;
+}
+
+
/**
* Unlink the touch tool from the pen of the same device
*/
void wcmUnlinkTouchAndPen(WacomDevicePtr priv)
{
WacomCommonPtr common = priv->common;
- InputInfoPtr device = xf86FirstLocalDevice();
- WacomCommonPtr tmpcommon = NULL;
- WacomDevicePtr tmppriv = NULL;
- Bool touch_device = FALSE;
if (!TabletHasFeature(common, WCM_PENTOUCH))
return;
- /* Lookup to find the associated pen and touch */
- for (; device != NULL; device = device->next)
- {
- if (!strcmp(device->drv->driverName, "wacom"))
- {
- tmppriv = (WacomDevicePtr) device->private;
- tmpcommon = tmppriv->common;
- touch_device = (common->wcmTouchDevice ||
- tmpcommon->wcmTouchDevice);
-
- /* skip the same tool or unlinked devices */
- if ((tmppriv == priv) || !touch_device)
- continue;
-
- if (tmpcommon->tablet_id == common->tablet_id)
- {
- common->wcmTouchDevice = NULL;
- tmpcommon->wcmTouchDevice = NULL;
- common->tablet_type &= ~WCM_PENTOUCH;
- tmpcommon->tablet_type &= ~WCM_PENTOUCH;
- return;
- }
- }
- }
+ wcmForeachDevice(priv, unlinkDevice, priv);
}
/**
@@ -346,14 +338,9 @@ static void wcmSplitName(char* devicename, char *basename, char *subdevice, char
* when a tablet reports 'pen' and 'touch' through separate device
* nodes.
*/
-static Bool wcmIsSiblingDevice(InputInfoPtr a, InputInfoPtr b, Bool logical_only)
+static Bool wcmIsSiblingDevice(WacomDevicePtr privA,
+ WacomDevicePtr privB, Bool logical_only)
{
- WacomDevicePtr privA = (WacomDevicePtr)a->private;
- WacomDevicePtr privB = (WacomDevicePtr)b->private;
-
- if (strcmp(a->drv->driverName, "wacom") || strcmp(b->drv->driverName, "wacom"))
- return FALSE;
-
if (privA == privB)
return FALSE;
@@ -386,6 +373,30 @@ static Bool wcmIsSiblingDevice(InputInfoPtr a, InputInfoPtr b, Bool logical_only
return FALSE;
}
+
+static int matchDevice(WacomDevicePtr privMatch, void *data)
+{
+ WacomDevicePtr priv = data;
+
+ if (!wcmIsSiblingDevice(priv, privMatch, TRUE))
+ return -ENODEV;
+
+ DBG(2, priv, "port share between %s and %s\n",
+ priv->name, privMatch->name);
+ /* FIXME: we loose the common->wcmTool here but it
+ * gets re-added during wcmParseOptions. This is
+ * currently required by the code, adding the tool
+ * again here means we trigger the duplicate tool
+ * detection */
+ wcmFreeCommon(&priv->common);
+ priv->common = wcmRefCommon(privMatch->common);
+ priv->next = priv->common->wcmDevices;
+ priv->common->wcmDevices = priv;
+
+ return 0;
+}
+
+
/* wcmMatchDevice - locate matching device and merge common structure. If an
* already initialized device shares the same device file and driver, remove
* the new device's "common" struct and point to the one of the already
@@ -397,36 +408,16 @@ static Bool wcmIsSiblingDevice(InputInfoPtr a, InputInfoPtr b, Bool logical_only
*/
static Bool wcmMatchDevice(WacomDevicePtr priv, WacomCommonPtr *common_return)
{
- InputInfoPtr pLocal = priv->pInfo;
WacomCommonPtr common = priv->common;
- InputInfoPtr pMatch = xf86FirstLocalDevice();
*common_return = common;
if (!common->device_path)
return 0;
- for (; pMatch != NULL; pMatch = pMatch->next)
- {
- WacomDevicePtr privMatch = (WacomDevicePtr)pMatch->private;
-
- if (wcmIsSiblingDevice(pLocal, pMatch, TRUE))
- {
- DBG(2, priv, "port share between %s and %s\n",
- pLocal->name, pMatch->name);
- /* FIXME: we loose the common->wcmTool here but it
- * gets re-added during wcmParseOptions. This is
- * currently required by the code, adding the tool
- * again here means we trigger the duplicate tool
- * detection */
- wcmFreeCommon(&priv->common);
- priv->common = wcmRefCommon(privMatch->common);
- priv->next = priv->common->wcmDevices;
- priv->common->wcmDevices = priv;
- *common_return = priv->common;
- return 1;
- }
- }
+ /* If a match is found, priv->common has been replaced */
+ if (wcmForeachDevice(priv, matchDevice, priv) == 0)
+ *common_return = priv->common;
return 0;
}
@@ -467,6 +458,56 @@ wcmInitModel(WacomDevicePtr priv)
return TRUE;
}
+static int linkDevice(WacomDevicePtr tmppriv, /* the device iterated on */
+ void *data) /* our device */
+{
+ WacomDevicePtr priv = data;
+ WacomCommonPtr common = priv->common;
+ WacomCommonPtr tmpcommon = tmppriv->common;
+
+ if (!wcmIsSiblingDevice(priv, tmppriv, FALSE))
+ return -ENODEV;
+
+ DBG(4, priv, "Considering link with %s...\n", tmppriv->name);
+
+ /* already linked devices */
+ if (tmpcommon->wcmTouchDevice)
+ {
+ DBG(4, priv, "A link is already in place. Ignoring.\n");
+ return -ENODEV;
+ }
+
+ if (IsTouch(tmppriv))
+ {
+ common->wcmTouchDevice = tmppriv;
+ tmpcommon->wcmTouchDevice = tmppriv;
+ }
+ else if (IsTouch(priv))
+ {
+ common->wcmTouchDevice = priv;
+ tmpcommon->wcmTouchDevice = priv;
+ }
+ else
+ {
+ DBG(4, priv, "A link is not necessary. Ignoring.\n");
+ }
+
+ if ((common->wcmTouchDevice && IsTablet(priv)) ||
+ (tmpcommon->wcmTouchDevice && IsTablet(tmppriv)))
+ {
+ TabletSetFeature(common, WCM_PENTOUCH);
+ TabletSetFeature(tmpcommon, WCM_PENTOUCH);
+ }
+
+ if (common->wcmTouchDevice)
+ {
+ DBG(4, priv, "Link created!\n");
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
/**
* Lookup to find the associated pen and touch for the same device.
* Store touch tool in wcmTouchDevice for pen and touch, respectively,
@@ -478,65 +519,15 @@ wcmInitModel(WacomDevicePtr priv)
*/
static Bool wcmLinkTouchAndPen(WacomDevicePtr priv)
{
- InputInfoPtr pInfo = priv->pInfo;
- WacomCommonPtr common = priv->common;
- InputInfoPtr device = xf86FirstLocalDevice();
- WacomCommonPtr tmpcommon = NULL;
- WacomDevicePtr tmppriv = NULL;
-
if (IsPad(priv))
{
DBG(4, priv, "No need to link up pad devices.\n");
return FALSE;
}
- /* Lookup to find the associated pen and touch */
- for (; device != NULL; device = device->next)
- {
- if (!wcmIsSiblingDevice(pInfo, device, FALSE))
- continue;
+ if (wcmForeachDevice(priv, linkDevice, priv) <= 0)
+ DBG(4, priv, "No suitable device to link with found.\n");
- tmppriv = (WacomDevicePtr) device->private;
- tmpcommon = tmppriv->common;
-
- DBG(4, priv, "Considering link with %s...\n", tmppriv->name);
-
- /* already linked devices */
- if (tmpcommon->wcmTouchDevice)
- {
- DBG(4, priv, "A link is already in place. Ignoring.\n");
- continue;
- }
-
- if (IsTouch(tmppriv))
- {
- common->wcmTouchDevice = tmppriv;
- tmpcommon->wcmTouchDevice = tmppriv;
- }
- else if (IsTouch(priv))
- {
- common->wcmTouchDevice = priv;
- tmpcommon->wcmTouchDevice = priv;
- }
- else
- {
- DBG(4, priv, "A link is not necessary. Ignoring.\n");
- }
-
- if ((common->wcmTouchDevice && IsTablet(priv)) ||
- (tmpcommon->wcmTouchDevice && IsTablet(tmppriv)))
- {
- TabletSetFeature(common, WCM_PENTOUCH);
- TabletSetFeature(tmpcommon, WCM_PENTOUCH);
- }
-
- if (common->wcmTouchDevice)
- {
- DBG(4, priv, "Link created!\n");
- return TRUE;
- }
- }
- DBG(4, priv, "No suitable device to link with found.\n");
return FALSE;
}
diff --git a/src/wcmValidateDevice.c b/src/wcmValidateDevice.c
index 8cd95a0..c30d2ba 100644
--- a/src/wcmValidateDevice.c
+++ b/src/wcmValidateDevice.c
@@ -24,6 +24,40 @@
#include <fcntl.h>
#include <unistd.h>
+struct checkData {
+ dev_t min_maj;
+ const char *source;
+};
+
+static int checkSource(WacomDevicePtr other, void *data)
+{
+ InputInfoPtr pInfo = other->pInfo;
+ char *device = xf86CheckStrOption(pInfo->options, "Device", NULL);
+ WacomCommonPtr pCommon;
+ struct checkData *check = data;
+ Bool match = FALSE;
+
+ /* device can be NULL on some distros */
+ if (!device)
+ return -ENODEV;
+
+ free(device);
+
+ pCommon = other->common;
+ if (pCommon->min_maj && pCommon->min_maj == check->min_maj)
+ {
+ char* source = xf86CheckStrOption(pInfo->options, "_source", "");
+
+ /* only add the new tool if the matching major/minor
+ * was from the same source */
+ if (strcmp(check->source, source))
+ match = TRUE;
+ free(source);
+ }
+
+ return match ? 0 : -ENODEV;
+}
+
/* wcmCheckSource - Check if there is another source defined this device
* before or not: don't add the tool by hal/udev if user has defined at least
* one tool for the device in xorg.conf. One device can have multiple tools
@@ -31,44 +65,18 @@
static Bool wcmCheckSource(WacomDevicePtr priv, dev_t min_maj)
{
InputInfoPtr pInfo = priv->pInfo;
- int match = 0;
- InputInfoPtr pDevices = xf86FirstLocalDevice();
-
- for (; !match && pDevices != NULL; pDevices = pDevices->next)
- {
- char *device;
- WacomCommonPtr pCommon;
-
- if (pInfo == pDevices)
- continue;
-
- if (!strstr(pDevices->drv->driverName, "wacom"))
- continue;
-
- device = xf86CheckStrOption(pDevices->options, "Device", NULL);
- /* device can be NULL on some distros */
- if (!device)
- continue;
- free(device);
-
- pCommon = ((WacomDevicePtr)pDevices->private)->common;
- if (pCommon->min_maj && pCommon->min_maj == min_maj)
- {
- char* fsource = xf86CheckStrOption(pInfo->options, "_source", "");
- char* psource = xf86CheckStrOption(pDevices->options, "_source", "");
-
- /* only add the new tool if the matching major/minor
- * was from the same source */
- if (strcmp(fsource, psource))
- match = 1;
- free(fsource);
- free(psource);
- }
- }
- if (match)
+ int nmatch;
+ struct checkData check = {
+ .min_maj = min_maj,
+ .source = xf86CheckStrOption(pInfo->options, "_source", ""),
+ };
+
+ nmatch = wcmForeachDevice(priv, checkSource, &check);
+ if (nmatch > 0)
wcmLog(priv, W_WARNING,
- "device file already in use by %s. Ignoring.\n", pDevices->name);
- return match;
+ "device file already in use. Ignoring.\n");
+ free((char*)check.source);
+ return nmatch;
}
/* check if the device has been added.
diff --git a/src/xf86Wacom.c b/src/xf86Wacom.c
index 68987ea..e23d95f 100644
--- a/src/xf86Wacom.c
+++ b/src/xf86Wacom.c
@@ -284,6 +284,33 @@ Bool wcmInitTouch(WacomDevicePtr priv, int ntouches, Bool is_direct_touch)
2);
}
+int wcmForeachDevice(WacomDevicePtr priv, WacomDeviceCallback func, void *data)
+{
+ InputInfoPtr pInfo = priv->pInfo;
+ InputInfoPtr pOther;
+ int nmatch = 0;
+
+ for (pOther = xf86FirstLocalDevice(); pOther; pOther = pOther->next)
+ {
+ WacomDevicePtr pPriv;
+ int rc;
+
+ if (pInfo == pOther || !strstr(pOther->drv->driverName, "wacom"))
+ continue;
+
+ pPriv = pOther->private;
+ rc = func(pPriv, data);
+ if (rc == -ENODEV)
+ continue;
+ if (rc < 0)
+ return -rc;
+ nmatch += 1; /* zero counts as matched */
+ if (rc == 0)
+ break;
+ }
+
+ return nmatch;
+}
/*****************************************************************************
* wcmOpen --
diff --git a/src/xf86Wacom.h b/src/xf86Wacom.h
index 2603470..391523e 100644
--- a/src/xf86Wacom.h
+++ b/src/xf86Wacom.h
@@ -125,6 +125,19 @@ void wcmDevClose(WacomDevicePtr priv);
Bool wcmDevStart(WacomDevicePtr priv);
void wcmDevStop(WacomDevicePtr priv);
+/**
+ * @retval 0 to abort the loop (counts as match)
+ * @retval -ENOENT if the device is not a match
+ * @retval 1 for success (counts as match).
+ * @retval -errno for an error (to abort)
+ */
+typedef int (*WacomDeviceCallback)(WacomDevicePtr priv, void *data);
+
+/**
+ * Returns the number of devices processed or a negative errno
+ */
+extern int wcmForeachDevice(WacomDevicePtr priv, WacomDeviceCallback func, void *data);
+
/* Open the device with the right serial parmeters */
extern Bool wcmOpen(WacomDevicePtr priv);