From 4754af9ddbd55c5637b56bd9f37d0d3414c839a8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 11 Mar 2014 14:20:51 +1000 Subject: [PATCH 1/6] config: only free odev->attrib_name for string types Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- config/config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/config.c b/config/config.c index 7971b8740..4ad733000 100644 --- a/config/config.c +++ b/config/config.c @@ -246,7 +246,8 @@ config_odev_free_attributes(struct OdevAttributes *attribs) case ODEV_ATTRIB_FD: fd = iter->attrib_value; break; } xorg_list_del(&iter->member); - free(iter->attrib_name); + if (iter->attrib_type == ODEV_ATTRIB_STRING) + free(iter->attrib_name); free(iter); } From fdb4ec86c29d85c1f68418a26e64bcc05b9c14ae Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 11 Mar 2014 14:21:27 +1000 Subject: [PATCH 2/6] xfree86: handle xorg.conf devices with logind Only devices from the config backend have their attributes set, devices from the xorg.conf only have Option "Device". That option is also set by the config backend, so use it. And since the config backend sets our major/minor but xorg.conf devices don't have that set, make sure we try to stat it first where needed. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- hw/xfree86/common/xf86Xinput.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 7c3e479e5..36b92a9f7 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -81,6 +81,7 @@ #include #include /* for int64_t */ +#include #include #include "mi.h" @@ -804,6 +805,18 @@ xf86InputDevicePostInit(DeviceIntPtr dev) return Success; } +static void +xf86stat(const char *path, int *maj, int *min) +{ + struct stat st; + + if (stat(path, &st) == -1) + return; + + *maj = major(st.st_rdev); + *min = minor(st.st_rdev); +} + /** * Create a new input device, activate and enable it. * @@ -828,6 +841,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) DeviceIntPtr dev = NULL; Bool paused; int rval; + const char *path; /* Memory leak for every attached device if we don't * test if the module is already loaded first */ @@ -841,9 +855,13 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) goto unwind; } - if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) { + path = xf86CheckStrOption(pInfo->options, "Device", NULL); + if (path && pInfo->major == 0 && pInfo->minor == 0) + xf86stat(path, &pInfo->major, &pInfo->minor); + + if (path && (drv->capabilities & XI86_DRV_CAP_SERVER_FD)){ int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor, - pInfo->attrs->device, &paused); + path, &paused); if (fd != -1) { if (paused) { /* Put on new_input_devices list for delayed probe */ From dda2468e579762dbd1fed2c75b5587d98f841e9c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Feb 2014 16:03:19 +1000 Subject: [PATCH 3/6] xkb: factor out the StateNotify flag check Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- xkb/xkbActions.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c index 1443498f6..3da57f76e 100644 --- a/xkb/xkbActions.c +++ b/xkb/xkbActions.c @@ -1127,6 +1127,22 @@ _XkbApplyFilters(XkbSrvInfoPtr xkbi, unsigned kc, XkbAction *pAction) return send; } +static int +_XkbEnsureStateChange(XkbSrvInfoPtr xkbi) +{ + Bool genStateNotify = FALSE; + + /* The state may change, so if we're not in the middle of sending a state + * notify, prepare for it */ + if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) { + xkbi->prev_state = xkbi->state; + xkbi->flags |= _XkbStateNotifyInProgress; + genStateNotify = TRUE; + } + + return genStateNotify; +} + void XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event) { @@ -1146,15 +1162,8 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event) keyc = kbd->key; xkbi = keyc->xkbInfo; key = event->detail.key; - /* The state may change, so if we're not in the middle of sending a state - * notify, prepare for it */ - if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) { - xkbi->prev_state = xkbi->state; - xkbi->flags |= _XkbStateNotifyInProgress; - genStateNotify = TRUE; - } - else - genStateNotify = FALSE; + + genStateNotify = _XkbEnsureStateChange(xkbi); xkbi->clearMods = xkbi->setMods = 0; xkbi->groupChange = 0; From 656841798c99bcd79da47c03ec666a48b855541f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Feb 2014 16:16:10 +1000 Subject: [PATCH 4/6] xkb: factor out state update into a function No functional changes Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- xkb/xkbActions.c | 55 ++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c index 3da57f76e..7e5512c1e 100644 --- a/xkb/xkbActions.c +++ b/xkb/xkbActions.c @@ -1143,13 +1143,43 @@ _XkbEnsureStateChange(XkbSrvInfoPtr xkbi) return genStateNotify; } +static void +_XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key) +{ + XkbSrvInfoPtr xkbi = dev->key->xkbInfo; + int changed; + + XkbComputeDerivedState(xkbi); + + changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state); + if (genStateNotify) { + if (changed) { + xkbStateNotify sn; + + sn.keycode = key; + sn.eventType = evtype; + sn.requestMajor = sn.requestMinor = 0; + sn.changed = changed; + XkbSendStateNotify(dev, &sn); + } + xkbi->flags &= ~_XkbStateNotifyInProgress; + } + + changed = XkbIndicatorsToUpdate(dev, changed, FALSE); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause, key, evtype); + XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause); + } +} + void XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event) { int key, bit, i; XkbSrvInfoPtr xkbi; KeyClassPtr keyc; - int changed, sendEvent; + int sendEvent; Bool genStateNotify; XkbAction act; XkbFilterPtr filter; @@ -1296,28 +1326,7 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event) FixKeyState(event, dev); } - XkbComputeDerivedState(xkbi); - changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state); - if (genStateNotify) { - if (changed) { - xkbStateNotify sn; - - sn.keycode = key; - sn.eventType = event->type; - sn.requestMajor = sn.requestMinor = 0; - sn.changed = changed; - XkbSendStateNotify(dev, &sn); - } - xkbi->flags &= ~_XkbStateNotifyInProgress; - } - changed = XkbIndicatorsToUpdate(dev, changed, FALSE); - if (changed) { - XkbEventCauseRec cause; - - XkbSetCauseKey(&cause, key, event->type); - XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause); - } - return; + _XkbApplyState(dev, genStateNotify, event->type, key); } int From 45fb3a934dc0db51584aba37c2f9d73deff9191d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Feb 2014 16:20:08 +1000 Subject: [PATCH 5/6] xkb: push locked modifier state down to attached slave devices Whenever the master changes, push the locked modifier state to the attached slave devices, then update the indicators. This way, when NumLock or CapsLock are hit on any device, the LED will light up on all devices. Likewise, a new keyboard attached to a master device will light up with the correct indicators. The indicators are handled per-keyboard, depending on the layout, i.e. if one keyboard has grp_led:num set, the NumLock LED won't light up on that keyboard. Signed-off-by: Peter Hutterer Reviewed-by: Daniel Stone --- dix/devices.c | 3 +++ include/xkbsrv.h | 4 ++++ xkb/xkbActions.c | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/dix/devices.c b/dix/devices.c index 1c86d5242..ab923d574 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -416,6 +416,8 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent) XISendDeviceHierarchyEvent(flags); } + if (!IsMaster(dev)) + XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0); RecalculateMasterButtons(dev); /* initialise an idle timer for this device*/ @@ -2649,6 +2651,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) dev->spriteInfo->paired = master; dev->spriteInfo->spriteOwner = FALSE; + XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0); RecalculateMasterButtons(master); } diff --git a/include/xkbsrv.h b/include/xkbsrv.h index e79979927..f857b2280 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -638,6 +638,10 @@ extern _X_EXPORT void XkbHandleActions(DeviceIntPtr /* dev */ , DeviceEvent * /* event */ ); +extern void XkbPushLockedStateToSlaves(DeviceIntPtr /* master */, + int /* evtype */, + int /* key */); + extern _X_EXPORT Bool XkbEnableDisableControls(XkbSrvInfoPtr /* xkbi */ , unsigned long /* change */ , unsigned long /* newValues */ , diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c index 7e5512c1e..c44f44bc1 100644 --- a/xkb/xkbActions.c +++ b/xkb/xkbActions.c @@ -1173,6 +1173,25 @@ _XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key) } } +void +XkbPushLockedStateToSlaves(DeviceIntPtr master, int evtype, int key) +{ + DeviceIntPtr dev; + Bool genStateNotify; + + nt_list_for_each_entry(dev, inputInfo.devices, next) { + if (!dev->key || GetMaster(dev, MASTER_KEYBOARD) != master) + continue; + + genStateNotify = _XkbEnsureStateChange(dev->key->xkbInfo); + + dev->key->xkbInfo->state.locked_mods = + master->key->xkbInfo->state.locked_mods; + + _XkbApplyState(dev, genStateNotify, evtype, key); + } +} + void XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event) { @@ -1327,6 +1346,7 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event) } _XkbApplyState(dev, genStateNotify, event->type, key); + XkbPushLockedStateToSlaves(dev, event->type, key); } int From 795066477ee81b5b82e490eac8bed6b656d01f17 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Feb 2014 07:54:56 +1000 Subject: [PATCH 6/6] config: search for PnPID on all parents (#75513) The PnPID for a device may not be on the immediate parent, so search up the device tree until we find one. X.Org Bug 75513 Signed-off-by: Peter Hutterer Tested-by: Benjamin Tissoires --- config/hal.c | 16 +++++++++++++--- config/udev.c | 15 +++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/config/hal.c b/config/hal.c index 94cb6e7cd..ea574ca52 100644 --- a/config/hal.c +++ b/config/hal.c @@ -185,8 +185,7 @@ device_added(LibHalContext * hal_ctx, const char *udi) parent = get_prop_string(hal_ctx, udi, "info.parent"); if (parent) { int usb_vendor, usb_product; - - attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + char *old_parent; /* construct USB ID in lowercase - "0000:ffff" */ usb_vendor = libhal_device_get_property_int(hal_ctx, parent, @@ -204,7 +203,18 @@ device_added(LibHalContext * hal_ctx, const char *udi) == -1) attrs.usb_id = NULL; - free(parent); + attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + old_parent = parent; + + while (!attrs.pnp_id && + (parent = get_prop_string(hal_ctx, parent, "info.parent"))) { + attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + + free(old_parent); + old_parent = parent; + } + + free(old_parent); } input_options = input_option_new(NULL, "_source", "server/hal"); diff --git a/config/udev.c b/config/udev.c index d70eeb48c..d88abaaa1 100644 --- a/config/udev.c +++ b/config/udev.c @@ -149,10 +149,6 @@ device_added(struct udev_device *udev_device) LOG_PROPERTY(ppath, "NAME", name); } - if (pnp_id) - attrs.pnp_id = strdup(pnp_id); - LOG_SYSATTR(ppath, "id", pnp_id); - /* construct USB ID in lowercase hex - "0000:ffff" */ if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) { @@ -164,6 +160,17 @@ device_added(struct udev_device *udev_device) LOG_PROPERTY(ppath, "PRODUCT", product); attrs.usb_id = usb_id; } + + while (!pnp_id && (parent = udev_device_get_parent(parent))) { + pnp_id = udev_device_get_sysattr_value(parent, "id"); + if (!pnp_id) + continue; + + attrs.pnp_id = strdup(pnp_id); + ppath = udev_device_get_devnode(parent); + LOG_SYSATTR(ppath, "id", pnp_id); + } + } if (!name) name = "(unnamed)";