|
|
|
|
@@ -263,8 +263,17 @@ PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
|
|
|
|
|
static char warned[KEY_CNT];
|
|
|
|
|
|
|
|
|
|
/* Filter all repeated events from device.
|
|
|
|
|
We'll do softrepeat in the server */
|
|
|
|
|
if (value == 2)
|
|
|
|
|
We'll do softrepeat in the server, but only since 1.6 */
|
|
|
|
|
if (value == 2
|
|
|
|
|
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) <= 2
|
|
|
|
|
&& (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
|
|
|
|
|
ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT ||
|
|
|
|
|
ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT ||
|
|
|
|
|
ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA ||
|
|
|
|
|
ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK ||
|
|
|
|
|
ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */
|
|
|
|
|
#endif
|
|
|
|
|
)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (code > 255)
|
|
|
|
|
@@ -333,6 +342,9 @@ EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
|
|
|
|
|
return 100; /* come back in 100 ms */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define ABS_X_VALUE 0x1
|
|
|
|
|
#define ABS_Y_VALUE 0x2
|
|
|
|
|
#define ABS_VALUE 0x4
|
|
|
|
|
/**
|
|
|
|
|
* Take one input event and process it accordingly.
|
|
|
|
|
*/
|
|
|
|
|
@@ -350,6 +362,10 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
|
|
|
|
|
|
|
|
|
|
switch (ev->type) {
|
|
|
|
|
case EV_REL:
|
|
|
|
|
/* Ignore EV_REL events if we never set up for them. */
|
|
|
|
|
if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Handle mouse wheel emulation */
|
|
|
|
|
if (EvdevWheelEmuFilterMotion(pInfo, ev))
|
|
|
|
|
break;
|
|
|
|
|
@@ -380,10 +396,19 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case EV_ABS:
|
|
|
|
|
/* Ignore EV_ABS events if we never set up for them. */
|
|
|
|
|
if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (ev->code > ABS_MAX)
|
|
|
|
|
break;
|
|
|
|
|
pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
|
|
|
|
|
abs = 1;
|
|
|
|
|
if (ev->code == ABS_X)
|
|
|
|
|
abs |= ABS_X_VALUE;
|
|
|
|
|
else if (ev->code == ABS_Y)
|
|
|
|
|
abs |= ABS_Y_VALUE;
|
|
|
|
|
else
|
|
|
|
|
abs |= ABS_VALUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case EV_KEY:
|
|
|
|
|
@@ -434,17 +459,20 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
|
|
|
|
|
case EV_SYN:
|
|
|
|
|
/* convert to relative motion for touchpads */
|
|
|
|
|
if (abs && (pEvdev->flags & EVDEV_TOUCHPAD)) {
|
|
|
|
|
abs = 0;
|
|
|
|
|
if (pEvdev->tool) { /* meaning, touch is active */
|
|
|
|
|
if (pEvdev->old_vals[0] != -1)
|
|
|
|
|
delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
|
|
|
|
|
if (pEvdev->old_vals[1] != -1)
|
|
|
|
|
delta[REL_Y] = pEvdev->vals[1] - pEvdev->old_vals[1];
|
|
|
|
|
pEvdev->old_vals[0] = pEvdev->vals[0];
|
|
|
|
|
pEvdev->old_vals[1] = pEvdev->vals[1];
|
|
|
|
|
if (abs & ABS_X_VALUE)
|
|
|
|
|
pEvdev->old_vals[0] = pEvdev->vals[0];
|
|
|
|
|
if (abs & ABS_Y_VALUE)
|
|
|
|
|
pEvdev->old_vals[1] = pEvdev->vals[1];
|
|
|
|
|
} else {
|
|
|
|
|
pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1;
|
|
|
|
|
}
|
|
|
|
|
abs = 0;
|
|
|
|
|
rel = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rel) {
|
|
|
|
|
@@ -527,6 +555,10 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef ABS_X_VALUE
|
|
|
|
|
#undef ABS_Y_VALUE
|
|
|
|
|
#undef ABS_VALUE
|
|
|
|
|
|
|
|
|
|
/* just a magic number to reduce the number of reads */
|
|
|
|
|
#define NUM_EVENTS 16
|
|
|
|
|
|
|
|
|
|
@@ -540,25 +572,32 @@ EvdevReadInput(InputInfoPtr pInfo)
|
|
|
|
|
while (len == sizeof(ev))
|
|
|
|
|
{
|
|
|
|
|
len = read(pInfo->fd, &ev, sizeof(ev));
|
|
|
|
|
if (len == 0)
|
|
|
|
|
if (len <= 0)
|
|
|
|
|
{
|
|
|
|
|
if (errno == ENODEV) /* May happen after resume */
|
|
|
|
|
{
|
|
|
|
|
xf86RemoveEnabledDevice(pInfo);
|
|
|
|
|
close(pInfo->fd);
|
|
|
|
|
pInfo->fd = -1;
|
|
|
|
|
pEvdev->reopen_left = pEvdev->reopen_attempts;
|
|
|
|
|
pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
|
|
|
|
|
if (pEvdev->reopen_timer)
|
|
|
|
|
{
|
|
|
|
|
pEvdev->reopen_left = pEvdev->reopen_attempts;
|
|
|
|
|
pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);
|
|
|
|
|
}
|
|
|
|
|
} else if (errno != EAGAIN)
|
|
|
|
|
xf86Msg(X_ERROR, "%s: Read error: %s\n", pInfo->name,
|
|
|
|
|
{
|
|
|
|
|
/* We use X_NONE here because it doesn't alloc */
|
|
|
|
|
xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
|
|
|
|
|
strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The kernel promises that we always only read a complete
|
|
|
|
|
* event, so len != sizeof ev is an error. */
|
|
|
|
|
if (len % sizeof(ev[0])) {
|
|
|
|
|
/* The kernel promises that we always only read a complete
|
|
|
|
|
* event, so len != sizeof ev is an error. */
|
|
|
|
|
xf86Msg(X_ERROR, "%s: Read error: %s\n", pInfo->name, strerror(errno));
|
|
|
|
|
/* We use X_NONE here because it doesn't alloc */
|
|
|
|
|
xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1022,6 +1061,9 @@ EvdevAddRelClass(DeviceIntPtr device)
|
|
|
|
|
if (TestBit(REL_DIAL, pEvdev->rel_bitmask))
|
|
|
|
|
num_axes--;
|
|
|
|
|
|
|
|
|
|
if (num_axes <= 0)
|
|
|
|
|
return !Success;
|
|
|
|
|
|
|
|
|
|
pEvdev->num_vals = num_axes;
|
|
|
|
|
memset(pEvdev->vals, 0, num_axes * sizeof(int));
|
|
|
|
|
|
|
|
|
|
@@ -1064,9 +1106,7 @@ EvdevAddButtonClass(DeviceIntPtr device)
|
|
|
|
|
pInfo = device->public.devicePrivate;
|
|
|
|
|
pEvdev = pInfo->private;
|
|
|
|
|
|
|
|
|
|
/* FIXME: count number of actual buttons */
|
|
|
|
|
if (!InitButtonClassDeviceStruct(device, ArrayLength(pEvdev->btnmap),
|
|
|
|
|
pEvdev->btnmap))
|
|
|
|
|
if (!InitButtonClassDeviceStruct(device, pEvdev->buttons, pEvdev->btnmap))
|
|
|
|
|
return !Success;
|
|
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
|
@@ -1123,32 +1163,103 @@ EvdevInitButtonMapping(InputInfoPtr pInfo)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
EvdevInitAbsClass(DeviceIntPtr device, EvdevPtr pEvdev)
|
|
|
|
|
{
|
|
|
|
|
if (EvdevAddAbsClass(device) == Success) {
|
|
|
|
|
|
|
|
|
|
xf86Msg(X_INFO,"%s: initialized for absolute axes.\n", device->name);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
xf86Msg(X_ERROR,"%s: failed to initialize for absolute axes.\n",
|
|
|
|
|
device->name);
|
|
|
|
|
|
|
|
|
|
pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
EvdevInitRelClass(DeviceIntPtr device, EvdevPtr pEvdev)
|
|
|
|
|
{
|
|
|
|
|
int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS;
|
|
|
|
|
|
|
|
|
|
if (EvdevAddRelClass(device) == Success) {
|
|
|
|
|
|
|
|
|
|
xf86Msg(X_INFO,"%s: initialized for relative axes.\n", device->name);
|
|
|
|
|
|
|
|
|
|
if (has_abs_axes) {
|
|
|
|
|
|
|
|
|
|
xf86Msg(X_WARNING,"%s: ignoring absolute axes.\n", device->name);
|
|
|
|
|
pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
xf86Msg(X_ERROR,"%s: failed to initialize for relative axes.\n",
|
|
|
|
|
device->name);
|
|
|
|
|
|
|
|
|
|
pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
|
|
|
|
|
|
|
|
|
|
if (has_abs_axes)
|
|
|
|
|
EvdevInitAbsClass(device, pEvdev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
EvdevInitTouchDevice(DeviceIntPtr device, EvdevPtr pEvdev)
|
|
|
|
|
{
|
|
|
|
|
if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) {
|
|
|
|
|
|
|
|
|
|
xf86Msg(X_WARNING,"%s: touchpads and touchscreens ignore relative "
|
|
|
|
|
"axes.\n", device->name);
|
|
|
|
|
|
|
|
|
|
pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EvdevInitAbsClass(device, pEvdev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
EvdevInit(DeviceIntPtr device)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
InputInfoPtr pInfo;
|
|
|
|
|
EvdevPtr pEvdev;
|
|
|
|
|
|
|
|
|
|
pInfo = device->public.devicePrivate;
|
|
|
|
|
pEvdev = pInfo->private;
|
|
|
|
|
|
|
|
|
|
/* clear all axis_map entries */
|
|
|
|
|
for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
|
|
|
|
|
pEvdev->axis_map[i]=-1;
|
|
|
|
|
|
|
|
|
|
if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS)
|
|
|
|
|
EvdevAddKeyClass(device);
|
|
|
|
|
if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
|
|
|
|
|
EvdevAddButtonClass(device);
|
|
|
|
|
/* We don't allow relative and absolute axes on the same device. Reason
|
|
|
|
|
Reason being that some devices (MS Optical Desktop 2000) register both
|
|
|
|
|
rel and abs axes for x/y.
|
|
|
|
|
The abs axes register min/max, this min/max then also applies to the
|
|
|
|
|
relative device (the mouse) and caps it at 0..255 for both axis.
|
|
|
|
|
So unless you have a small screen, you won't be enjoying it much.
|
|
|
|
|
|
|
|
|
|
FIXME: somebody volunteer to fix this.
|
|
|
|
|
/* We don't allow relative and absolute axes on the same device. The
|
|
|
|
|
* reason is that some devices (MS Optical Desktop 2000) register both
|
|
|
|
|
* rel and abs axes for x/y.
|
|
|
|
|
*
|
|
|
|
|
* The abs axes register min/max; this min/max then also applies to the
|
|
|
|
|
* relative device (the mouse) and caps it at 0..255 for both axes.
|
|
|
|
|
* So, unless you have a small screen, you won't be enjoying it much;
|
|
|
|
|
* consequently, absolute axes are generally ignored.
|
|
|
|
|
*
|
|
|
|
|
* However, currenly only a device with absolute axes can be registered
|
|
|
|
|
* as a touch{pad,screen}. Thus, given such a device, absolute axes are
|
|
|
|
|
* used and relative axes are ignored.
|
|
|
|
|
*/
|
|
|
|
|
if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
|
|
|
|
|
EvdevAddRelClass(device);
|
|
|
|
|
|
|
|
|
|
if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN))
|
|
|
|
|
EvdevInitTouchDevice(device, pEvdev);
|
|
|
|
|
else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
|
|
|
|
|
EvdevInitRelClass(device, pEvdev);
|
|
|
|
|
else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
|
|
|
|
|
EvdevAddAbsClass(device);
|
|
|
|
|
EvdevInitAbsClass(device, pEvdev);
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_PROPERTIES
|
|
|
|
|
/* We drop the return value, the only time we ever want the handlers to
|
|
|
|
|
@@ -1197,7 +1308,7 @@ EvdevOn(DeviceIntPtr device)
|
|
|
|
|
if (pInfo->fd == -1)
|
|
|
|
|
{
|
|
|
|
|
pEvdev->reopen_left = pEvdev->reopen_attempts;
|
|
|
|
|
pEvdev->reopen_timer = TimerSet(NULL, 0, 100, EvdevReopenTimer, pInfo);
|
|
|
|
|
pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
|
|
|
|
|
@@ -1208,6 +1319,8 @@ EvdevOn(DeviceIntPtr device)
|
|
|
|
|
return !Success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 0, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
xf86FlushInput(pInfo->fd);
|
|
|
|
|
xf86AddEnabledDevice(pInfo);
|
|
|
|
|
EvdevMBEmuOn(pInfo);
|
|
|
|
|
@@ -1428,8 +1541,14 @@ EvdevProbe(InputInfoPtr pInfo)
|
|
|
|
|
/* count all buttons */
|
|
|
|
|
for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
|
|
|
|
|
{
|
|
|
|
|
int mapping = 0;
|
|
|
|
|
if (TestBit(i, pEvdev->key_bitmask))
|
|
|
|
|
num_buttons++;
|
|
|
|
|
{
|
|
|
|
|
mapping =
|
|
|
|
|
pEvdev->btnmap[EvdevUtilButtonEventToButtonNumber(pEvdev, i)];
|
|
|
|
|
if (mapping > num_buttons)
|
|
|
|
|
num_buttons = mapping;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (num_buttons)
|
|
|
|
|
@@ -1462,9 +1581,9 @@ EvdevProbe(InputInfoPtr pInfo)
|
|
|
|
|
TestBit(ABS_Y, pEvdev->abs_bitmask)) {
|
|
|
|
|
xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
|
|
|
|
|
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
|
|
|
|
|
if (!TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) &&
|
|
|
|
|
TestBit(BTN_TOUCH, pEvdev->key_bitmask)) {
|
|
|
|
|
if (num_buttons) {
|
|
|
|
|
if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) ||
|
|
|
|
|
TestBit(BTN_TOUCH, pEvdev->key_bitmask)) {
|
|
|
|
|
if (num_buttons || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) {
|
|
|
|
|
xf86Msg(X_INFO, "%s: Found absolute touchpad\n", pInfo->name);
|
|
|
|
|
pEvdev->flags |= EVDEV_TOUCHPAD;
|
|
|
|
|
memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals);
|
|
|
|
|
@@ -1490,7 +1609,10 @@ EvdevProbe(InputInfoPtr pInfo)
|
|
|
|
|
if (has_axes && num_buttons) {
|
|
|
|
|
pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
|
|
|
|
|
XI86_CONFIGURED;
|
|
|
|
|
if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask)) {
|
|
|
|
|
if (pEvdev->flags & EVDEV_TOUCHPAD) {
|
|
|
|
|
xf86Msg(X_INFO, "%s: Configuring as touchpad\n", pInfo->name);
|
|
|
|
|
pInfo->type_name = XI_TOUCHPAD;
|
|
|
|
|
} else if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask)) {
|
|
|
|
|
xf86Msg(X_INFO, "%s: Configuring as tablet\n", pInfo->name);
|
|
|
|
|
pInfo->type_name = XI_TABLET;
|
|
|
|
|
} else {
|
|
|
|
|
@@ -1722,6 +1844,17 @@ EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
|
|
|
|
|
button = (TestBit(BTN_RIGHT, pEvdev->key_bitmask)) ? 10 : 3;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* FIXME: BTN_3.. and BTN_SIDE.. have the same button mapping */
|
|
|
|
|
case BTN_3:
|
|
|
|
|
case BTN_4:
|
|
|
|
|
case BTN_5:
|
|
|
|
|
case BTN_6:
|
|
|
|
|
case BTN_7:
|
|
|
|
|
case BTN_8:
|
|
|
|
|
case BTN_9:
|
|
|
|
|
button = (code - BTN_0 + 5);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BTN_SIDE:
|
|
|
|
|
case BTN_EXTRA:
|
|
|
|
|
case BTN_FORWARD:
|
|
|
|
|
@@ -1941,7 +2074,7 @@ EvdevInitProperty(DeviceIntPtr dev)
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_LABELS
|
|
|
|
|
/* Axis labelling */
|
|
|
|
|
if ((prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
|
|
|
|
|
if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
|
|
|
|
|
{
|
|
|
|
|
Atom atom, atoms[pEvdev->num_vals];
|
|
|
|
|
int natoms = pEvdev->num_vals;
|
|
|
|
|
@@ -1985,14 +2118,14 @@ EvdevInitProperty(DeviceIntPtr dev)
|
|
|
|
|
XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
|
|
|
|
|
}
|
|
|
|
|
/* Button labelling */
|
|
|
|
|
if ((prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
|
|
|
|
|
if ((pEvdev->buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
|
|
|
|
|
{
|
|
|
|
|
Atom atom, atoms[pEvdev->buttons];
|
|
|
|
|
Atom atom, atoms[EVDEV_MAXBUTTONS];
|
|
|
|
|
int button, bmap;
|
|
|
|
|
|
|
|
|
|
/* First, make sure all atoms are initialized */
|
|
|
|
|
atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
|
|
|
|
|
for (button = 0; button < pEvdev->buttons; button++)
|
|
|
|
|
for (button = 0; button < ArrayLength(atoms); button++)
|
|
|
|
|
atoms[button] = atom;
|
|
|
|
|
|
|
|
|
|
for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
|
|
|
|
|
|