xserver-multidpi/hw/dmx/dmxinput.c
Peter Hutterer d13cb97442 ddx: add new call to purge input devices that weren't added
Special case for the systemd-logind case in xfree86: when we're vt-switched
away and a device is plugged in, we get a paused fd from logind. Since we
can't probe the device or do anything with it, we store that device in the
xfree86 and handle it later when we vt-switch back. The device is not added to
inputInfo.devices until that time.

When the device is removed while still vt-switched away, the the config system
never notifies the DDX. It only runs through inputInfo.devices and our device
was never added to that.

When a device is plugged in, removed, and plugged in again while vt-switched
away, we have two entries in the xfree86-specific list that refer to the same
device node, both pending for addition later. On VT switch back, the first one
(the already removed one) will be added successfully, the second one (the
still plugged-in one) fails. Since the fd is correct, the device works until
it is removed again. The removed devices' config_info (i.e. the syspath)
doesn't match the actual device we addded tough (the input number increases
with each plug), it doesn't get removed, the fd remains open and we lose track
of the fd count. Plugging the device in again leads to a dead device.

Fix this by adding a call to notify the DDX to purge any remainders of devices
with the given config_info, that's the only identifiable bit we have at this
point.

https://bugs.freedesktop.org/show_bug.cgi?id=97928

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2016-10-26 15:35:07 +10:00

131 lines
3.5 KiB
C

/*
* Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Authors:
* David H. Dawes <dawes@xfree86.org>
* Kevin E. Martin <kem@redhat.com>
* Rickard E. (Rik) Faith <faith@redhat.com>
*
*/
/** \file
* Provide the main entry points for input initialization and processing
* that arequired by the dix layer.
*/
#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#include "dmx.h"
#include "dmxlog.h"
#include "dmxinput.h"
#include "inputstr.h"
#include "input.h"
#include "mi.h"
/** Returns TRUE if the key is a valid modifier. For PC-class
* keyboards, all keys can be used as modifiers, so return TRUE
* always. */
Bool
LegalModifier(unsigned int key, DeviceIntPtr pDev)
{
return TRUE;
}
/** Called from dix/main.c on each server generation to initialize
* inputs. All the work is done in dmxInputInit. \see
* dmxInputInit() */
void
InitInput(int argc, char **argv)
{
int i;
DMXInputInfo *dmxInput;
if (!dmxNumInputs)
dmxLog(dmxFatal, "InitInput: no inputs specified\n");
for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
dmxInputInit(dmxInput);
mieqInit();
}
void
CloseInput(void)
{
mieqFini();
}
/** Called from dix/dispatch.c in Dispatch() whenever input events
* require processing. All the work is done in the lower level
* routines. */
void
ProcessInputEvents(void)
{
int i;
DMXInputInfo *dmxInput;
for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
if (!dmxInput->detached && dmxInput->processInputEvents)
dmxInput->processInputEvents(dmxInput);
}
/** This routine is called from \a dmxwindow.c whenever the layout of
* windows on the display might have changed. This information is used
* by input drivers (currently only the console driver) that provide
* information about window layout to the user. */
void
dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow)
{
int i;
DMXInputInfo *dmxInput;
for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
if (!dmxInput->detached && dmxInput->updateWindowInfo)
dmxInput->updateWindowInfo(dmxInput, type, pWindow);
}
int
NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
DeviceIntPtr *pdev)
{
return BadRequest;
}
void
DeleteInputDeviceRequest(DeviceIntPtr pDev)
{
}
void
RemoveInputDeviceTraces(const char *config_info)
{
}