|
|
|
|
@ -38,6 +38,7 @@ |
|
|
|
|
|
|
|
|
|
#include <linux/version.h> |
|
|
|
|
#include <sys/stat.h> |
|
|
|
|
#include <libudev.h> |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#include <errno.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
@ -56,6 +57,10 @@ |
|
|
|
|
#define XI_PROP_PRODUCT_ID "Device Product ID" |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifndef XI_PROP_VIRTUAL_DEVICE |
|
|
|
|
#define XI_PROP_VIRTUAL_DEVICE "Virtual Device" |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* removed from server, purge when dropping support for server 1.10 */ |
|
|
|
|
#define XI86_SEND_DRAG_EVENTS 0x08 |
|
|
|
|
|
|
|
|
|
@ -80,6 +85,14 @@ |
|
|
|
|
#define MODEFLAG 8 |
|
|
|
|
#define COMPOSEFLAG 16 |
|
|
|
|
|
|
|
|
|
#ifndef ABS_MT_SLOT |
|
|
|
|
#define ABS_MT_SLOT 0x2f |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifndef ABS_MT_TRACKING_ID |
|
|
|
|
#define ABS_MT_TRACKING_ID 0x39 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static char *evdevDefaults[] = { |
|
|
|
|
"XkbRules", "evdev", |
|
|
|
|
"XkbModel", "evdev", |
|
|
|
|
@ -119,6 +132,7 @@ static Atom prop_swap; |
|
|
|
|
static Atom prop_axis_label; |
|
|
|
|
static Atom prop_btn_label; |
|
|
|
|
static Atom prop_device; |
|
|
|
|
static Atom prop_virtual; |
|
|
|
|
|
|
|
|
|
/* All devices the evdev driver has allocated and knows about.
|
|
|
|
|
* MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK) |
|
|
|
|
@ -277,6 +291,39 @@ SetXkbOption(InputInfoPtr pInfo, char *name, char **option) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static BOOL |
|
|
|
|
EvdevDeviceIsVirtual(const char* devicenode) |
|
|
|
|
{ |
|
|
|
|
struct udev *udev = NULL; |
|
|
|
|
struct udev_device *device = NULL; |
|
|
|
|
struct stat st; |
|
|
|
|
int rc = FALSE; |
|
|
|
|
const char *devpath; |
|
|
|
|
|
|
|
|
|
udev = udev_new(); |
|
|
|
|
if (!udev) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
stat(devicenode, &st); |
|
|
|
|
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); |
|
|
|
|
|
|
|
|
|
if (!device) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
devpath = udev_device_get_devpath(device); |
|
|
|
|
if (!devpath) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
if (strstr(devpath, "LNXSYSTM")) |
|
|
|
|
rc = TRUE; |
|
|
|
|
|
|
|
|
|
out: |
|
|
|
|
udev_device_unref(device); |
|
|
|
|
udev_unref(udev); |
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifndef HAVE_SMOOTH_SCROLLING |
|
|
|
|
static int wheel_up_button = 4; |
|
|
|
|
static int wheel_down_button = 5; |
|
|
|
|
@ -313,7 +360,7 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) |
|
|
|
|
if ((pQueue = EvdevNextInQueue(pInfo))) |
|
|
|
|
{ |
|
|
|
|
pQueue->type = EV_QUEUE_KEY; |
|
|
|
|
pQueue->key = code; |
|
|
|
|
pQueue->detail.key = code; |
|
|
|
|
pQueue->val = value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -326,7 +373,7 @@ EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value) |
|
|
|
|
if ((pQueue = EvdevNextInQueue(pInfo))) |
|
|
|
|
{ |
|
|
|
|
pQueue->type = EV_QUEUE_BTN; |
|
|
|
|
pQueue->key = button; |
|
|
|
|
pQueue->detail.key = button; |
|
|
|
|
pQueue->val = value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -338,19 +385,36 @@ EvdevQueueProximityEvent(InputInfoPtr pInfo, int value) |
|
|
|
|
if ((pQueue = EvdevNextInQueue(pInfo))) |
|
|
|
|
{ |
|
|
|
|
pQueue->type = EV_QUEUE_PROXIMITY; |
|
|
|
|
pQueue->key = 0; |
|
|
|
|
pQueue->detail.key = 0; |
|
|
|
|
pQueue->val = value; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
void |
|
|
|
|
EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask, |
|
|
|
|
uint16_t evtype) |
|
|
|
|
{ |
|
|
|
|
EventQueuePtr pQueue; |
|
|
|
|
if ((pQueue = EvdevNextInQueue(pInfo))) |
|
|
|
|
{ |
|
|
|
|
pQueue->type = EV_QUEUE_TOUCH; |
|
|
|
|
pQueue->detail.touch = touch; |
|
|
|
|
valuator_mask_copy(pQueue->touchMask, mask); |
|
|
|
|
pQueue->val = evtype; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Post button event right here, right now. |
|
|
|
|
* Interface for MB emulation since these need to post immediately. |
|
|
|
|
*/ |
|
|
|
|
void |
|
|
|
|
EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value) |
|
|
|
|
EvdevPostButtonEvent(InputInfoPtr pInfo, int button, enum ButtonAction act) |
|
|
|
|
{ |
|
|
|
|
xf86PostButtonEvent(pInfo->dev, Relative, button, value, 0, 0); |
|
|
|
|
xf86PostButtonEvent(pInfo->dev, Relative, button, |
|
|
|
|
(act == BUTTON_PRESS) ? 1 : 0, 0, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
@ -653,6 +717,64 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
static void |
|
|
|
|
EvdevProcessTouch(InputInfoPtr pInfo) |
|
|
|
|
{ |
|
|
|
|
EvdevPtr pEvdev = pInfo->private; |
|
|
|
|
int type; |
|
|
|
|
|
|
|
|
|
if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
/* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */ |
|
|
|
|
if (pEvdev->slot_state == SLOTSTATE_EMPTY) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (pEvdev->slot_state == SLOTSTATE_CLOSE) |
|
|
|
|
type = XI_TouchEnd; |
|
|
|
|
else if (pEvdev->slot_state == SLOTSTATE_OPEN) |
|
|
|
|
type = XI_TouchBegin; |
|
|
|
|
else |
|
|
|
|
type = XI_TouchUpdate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type); |
|
|
|
|
|
|
|
|
|
pEvdev->slot_state = SLOTSTATE_EMPTY; |
|
|
|
|
|
|
|
|
|
valuator_mask_zero(pEvdev->mt_mask); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
{ |
|
|
|
|
EvdevPtr pEvdev = pInfo->private; |
|
|
|
|
int map; |
|
|
|
|
|
|
|
|
|
if (ev->code == ABS_MT_SLOT) { |
|
|
|
|
EvdevProcessTouch(pInfo); |
|
|
|
|
pEvdev->cur_slot = ev->value; |
|
|
|
|
} else |
|
|
|
|
{ |
|
|
|
|
if (pEvdev->slot_state == SLOTSTATE_EMPTY) |
|
|
|
|
pEvdev->slot_state = SLOTSTATE_UPDATE; |
|
|
|
|
if (ev->code == ABS_MT_TRACKING_ID) { |
|
|
|
|
if (ev->value >= 0) |
|
|
|
|
pEvdev->slot_state = SLOTSTATE_OPEN; |
|
|
|
|
else |
|
|
|
|
pEvdev->slot_state = SLOTSTATE_CLOSE; |
|
|
|
|
} else { |
|
|
|
|
map = pEvdev->axis_map[ev->code]; |
|
|
|
|
valuator_mask_set(pEvdev->mt_mask, map, ev->value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
#define EvdevProcessTouch(pInfo) |
|
|
|
|
#define EvdevProcessTouchEvent(pInfo, ev) |
|
|
|
|
#endif /* MULTITOUCH */ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Take the absolute motion input event and process it accordingly. |
|
|
|
|
*/ |
|
|
|
|
@ -676,9 +798,14 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
if (EvdevWheelEmuFilterMotion(pInfo, ev)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
map = pEvdev->axis_map[ev->code]; |
|
|
|
|
valuator_mask_set(pEvdev->vals, map, value); |
|
|
|
|
pEvdev->abs_queued = 1; |
|
|
|
|
if (ev->code >= ABS_MT_SLOT) { |
|
|
|
|
EvdevProcessTouchEvent(pInfo, ev); |
|
|
|
|
pEvdev->abs_queued = 1; |
|
|
|
|
} else if (!pEvdev->mt_mask) { |
|
|
|
|
map = pEvdev->axis_map[ev->code]; |
|
|
|
|
valuator_mask_set(pEvdev->vals, map, value); |
|
|
|
|
pEvdev->abs_queued = 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -713,7 +840,8 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
* BTN_TOUCH as the proximity notifier */ |
|
|
|
|
if (!pEvdev->use_proximity) |
|
|
|
|
pEvdev->in_proximity = value ? ev->code : 0; |
|
|
|
|
if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET))) |
|
|
|
|
if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)) || |
|
|
|
|
pEvdev->mt_mask) |
|
|
|
|
break; |
|
|
|
|
/* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
|
|
|
|
|
* BTN_LEFT. */ |
|
|
|
|
@ -774,6 +902,9 @@ EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v, |
|
|
|
|
switch (pEvdev->queue[i].type) { |
|
|
|
|
case EV_QUEUE_KEY: |
|
|
|
|
case EV_QUEUE_BTN: |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
case EV_QUEUE_TOUCH: |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
case EV_QUEUE_PROXIMITY: |
|
|
|
|
if (pEvdev->queue[i].val == which) |
|
|
|
|
@ -796,26 +927,33 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, |
|
|
|
|
for (i = 0; i < pEvdev->num_queue; i++) { |
|
|
|
|
switch (pEvdev->queue[i].type) { |
|
|
|
|
case EV_QUEUE_KEY: |
|
|
|
|
xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key, |
|
|
|
|
xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key, |
|
|
|
|
pEvdev->queue[i].val); |
|
|
|
|
break; |
|
|
|
|
case EV_QUEUE_BTN: |
|
|
|
|
if (Evdev3BEmuFilterEvent(pInfo, |
|
|
|
|
pEvdev->queue[i].key, |
|
|
|
|
pEvdev->queue[i].detail.key, |
|
|
|
|
pEvdev->queue[i].val)) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
if (pEvdev->abs_queued && pEvdev->in_proximity) { |
|
|
|
|
xf86PostButtonEventP(pInfo->dev, Absolute, pEvdev->queue[i].key, |
|
|
|
|
xf86PostButtonEventP(pInfo->dev, Absolute, pEvdev->queue[i].detail.key, |
|
|
|
|
pEvdev->queue[i].val, first_v, num_v, |
|
|
|
|
v + first_v); |
|
|
|
|
|
|
|
|
|
} else |
|
|
|
|
xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].key, |
|
|
|
|
xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key, |
|
|
|
|
pEvdev->queue[i].val, 0, 0); |
|
|
|
|
break; |
|
|
|
|
case EV_QUEUE_PROXIMITY: |
|
|
|
|
break; |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
case EV_QUEUE_TOUCH: |
|
|
|
|
xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch, |
|
|
|
|
pEvdev->queue[i].val, 0, |
|
|
|
|
pEvdev->queue[i].touchMask); |
|
|
|
|
break; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -827,6 +965,7 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, |
|
|
|
|
static void |
|
|
|
|
EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
int num_v = 0, first_v = 0; |
|
|
|
|
int v[MAX_VALUATORS] = {}; |
|
|
|
|
EvdevPtr pEvdev = pInfo->private; |
|
|
|
|
@ -834,6 +973,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
EvdevProcessProximityState(pInfo); |
|
|
|
|
|
|
|
|
|
EvdevProcessValuators(pInfo); |
|
|
|
|
EvdevProcessTouch(pInfo); |
|
|
|
|
|
|
|
|
|
EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v); |
|
|
|
|
EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v); |
|
|
|
|
@ -842,7 +982,15 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) |
|
|
|
|
EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v); |
|
|
|
|
|
|
|
|
|
memset(pEvdev->delta, 0, sizeof(pEvdev->delta)); |
|
|
|
|
memset(pEvdev->queue, 0, sizeof(pEvdev->queue)); |
|
|
|
|
for (i = 0; i < ArrayLength(pEvdev->queue); i++) |
|
|
|
|
{ |
|
|
|
|
EventQueuePtr queue = &pEvdev->queue[i]; |
|
|
|
|
queue->detail.key = 0; |
|
|
|
|
queue->type = 0; |
|
|
|
|
queue->val = 0; |
|
|
|
|
/* don't reset the touchMask */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (pEvdev->vals) |
|
|
|
|
valuator_mask_zero(pEvdev->vals); |
|
|
|
|
pEvdev->num_queue = 0; |
|
|
|
|
@ -890,7 +1038,16 @@ EvdevReadInput(InputInfoPtr pInfo) |
|
|
|
|
|
|
|
|
|
while (len == sizeof(ev)) |
|
|
|
|
{ |
|
|
|
|
len = read(pInfo->fd, &ev, sizeof(ev)); |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
EvdevPtr pEvdev = pInfo->private; |
|
|
|
|
|
|
|
|
|
if (pEvdev->mtdev) |
|
|
|
|
len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) * |
|
|
|
|
sizeof(struct input_event); |
|
|
|
|
else |
|
|
|
|
#endif |
|
|
|
|
len = read(pInfo->fd, &ev, sizeof(ev)); |
|
|
|
|
|
|
|
|
|
if (len <= 0) |
|
|
|
|
{ |
|
|
|
|
if (errno == ENODEV) /* May happen after resume */ |
|
|
|
|
@ -986,12 +1143,50 @@ EvdevAddKeyClass(DeviceIntPtr device) |
|
|
|
|
return Success; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* MT axes are counted twice - once as ABS_X (which the kernel keeps for
|
|
|
|
|
* backwards compatibility), once as ABS_MT_POSITION_X. So we need to keep a |
|
|
|
|
* mapping of those axes to make sure we only count them once |
|
|
|
|
*/ |
|
|
|
|
struct mt_axis_mappings { |
|
|
|
|
int mt_code; |
|
|
|
|
int code; |
|
|
|
|
Bool needs_mapping; /* TRUE if both code and mt_code are present */ |
|
|
|
|
int mapping; /* Logical mapping of 'code' axis */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static struct mt_axis_mappings mt_axis_mappings[] = { |
|
|
|
|
{ABS_MT_POSITION_X, ABS_X}, |
|
|
|
|
{ABS_MT_POSITION_Y, ABS_Y}, |
|
|
|
|
{ABS_MT_PRESSURE, ABS_PRESSURE}, |
|
|
|
|
{ABS_MT_DISTANCE, ABS_DISTANCE}, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return TRUE if the axis is not one we should count as true axis |
|
|
|
|
*/ |
|
|
|
|
static int |
|
|
|
|
is_blacklisted_axis(int axis) |
|
|
|
|
{ |
|
|
|
|
switch(axis) |
|
|
|
|
{ |
|
|
|
|
case ABS_MT_SLOT: |
|
|
|
|
case ABS_MT_TRACKING_ID: |
|
|
|
|
return TRUE; |
|
|
|
|
default: |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
EvdevAddAbsValuatorClass(DeviceIntPtr device) |
|
|
|
|
{ |
|
|
|
|
InputInfoPtr pInfo; |
|
|
|
|
EvdevPtr pEvdev; |
|
|
|
|
int num_axes, axis, i = 0; |
|
|
|
|
int num_mt_axes = 0, /* number of MT-only axes */ |
|
|
|
|
num_mt_axes_total = 0; /* total number of MT axes, including
|
|
|
|
|
double-counted ones, excluding blacklisted */ |
|
|
|
|
Atom *atoms; |
|
|
|
|
|
|
|
|
|
pInfo = device->public.devicePrivate; |
|
|
|
|
@ -1004,11 +1199,45 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) |
|
|
|
|
if (num_axes < 1) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
if (num_axes > MAX_VALUATORS) { |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
for (axis = ABS_MT_SLOT; axis < ABS_MAX; axis++) |
|
|
|
|
{ |
|
|
|
|
if (EvdevBitIsSet(pEvdev->abs_bitmask, axis)) |
|
|
|
|
{ |
|
|
|
|
int j; |
|
|
|
|
Bool skip = FALSE; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < ArrayLength(mt_axis_mappings); j++) |
|
|
|
|
{ |
|
|
|
|
if (mt_axis_mappings[j].mt_code == axis && |
|
|
|
|
BitIsOn(pEvdev->abs_bitmask, mt_axis_mappings[j].code)) |
|
|
|
|
{ |
|
|
|
|
mt_axis_mappings[j].needs_mapping = TRUE; |
|
|
|
|
skip = TRUE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!is_blacklisted_axis(axis)) |
|
|
|
|
{ |
|
|
|
|
num_mt_axes_total++; |
|
|
|
|
if (!skip) |
|
|
|
|
num_mt_axes++; |
|
|
|
|
} |
|
|
|
|
num_axes--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
if (num_axes + num_mt_axes > MAX_VALUATORS) { |
|
|
|
|
xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS); |
|
|
|
|
num_axes = MAX_VALUATORS; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (num_axes < 1 && num_mt_axes_total < 1) { |
|
|
|
|
xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n", |
|
|
|
|
device->name); |
|
|
|
|
return !Success; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pEvdev->num_vals = num_axes; |
|
|
|
|
if (num_axes > 0) { |
|
|
|
|
pEvdev->vals = valuator_mask_new(num_axes); |
|
|
|
|
@ -1018,25 +1247,81 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
atoms = malloc(pEvdev->num_vals * sizeof(Atom)); |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
if (num_mt_axes_total > 0) { |
|
|
|
|
pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total); |
|
|
|
|
if (!pEvdev->mt_mask) { |
|
|
|
|
xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n", |
|
|
|
|
device->name); |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < EVDEV_MAXQUEUE; i++) { |
|
|
|
|
pEvdev->queue[i].touchMask = |
|
|
|
|
valuator_mask_new(num_mt_axes_total); |
|
|
|
|
if (!pEvdev->queue[i].touchMask) { |
|
|
|
|
xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for " |
|
|
|
|
"evdev event queue.\n", device->name); |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom)); |
|
|
|
|
|
|
|
|
|
i = 0; |
|
|
|
|
for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { |
|
|
|
|
int j; |
|
|
|
|
int mapping; |
|
|
|
|
pEvdev->axis_map[axis] = -1; |
|
|
|
|
if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis)) |
|
|
|
|
if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) || |
|
|
|
|
is_blacklisted_axis(axis)) |
|
|
|
|
continue; |
|
|
|
|
pEvdev->axis_map[axis] = i; |
|
|
|
|
i++; |
|
|
|
|
|
|
|
|
|
mapping = i; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < ArrayLength(mt_axis_mappings); j++) |
|
|
|
|
{ |
|
|
|
|
if (mt_axis_mappings[j].code == axis) |
|
|
|
|
mt_axis_mappings[j].mapping = mapping; |
|
|
|
|
else if (mt_axis_mappings[j].mt_code == axis && |
|
|
|
|
mt_axis_mappings[j].needs_mapping) |
|
|
|
|
mapping = mt_axis_mappings[j].mapping; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pEvdev->axis_map[axis] = mapping; |
|
|
|
|
if (mapping == i) |
|
|
|
|
i++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms); |
|
|
|
|
EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms); |
|
|
|
|
|
|
|
|
|
if (!InitValuatorClassDeviceStruct(device, num_axes, atoms, |
|
|
|
|
if (!InitValuatorClassDeviceStruct(device, num_axes + num_mt_axes, atoms, |
|
|
|
|
GetMotionHistorySize(), Absolute)) { |
|
|
|
|
xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n"); |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (axis = ABS_X; axis <= ABS_MAX; axis++) { |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
if (num_mt_axes_total > 0) |
|
|
|
|
{ |
|
|
|
|
int num_touches = 0; |
|
|
|
|
int mode = pEvdev->flags & EVDEV_TOUCHPAD ? |
|
|
|
|
XIDependentTouch : XIDirectTouch; |
|
|
|
|
|
|
|
|
|
if (pEvdev->mtdev->caps.slot.maximum > 0) |
|
|
|
|
num_touches = pEvdev->mtdev->caps.slot.maximum; |
|
|
|
|
|
|
|
|
|
if (!InitTouchClassDeviceStruct(device, num_touches, mode, |
|
|
|
|
num_mt_axes_total)) { |
|
|
|
|
xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n", |
|
|
|
|
device->name); |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) { |
|
|
|
|
int axnum = pEvdev->axis_map[axis]; |
|
|
|
|
int resolution = 10000; |
|
|
|
|
|
|
|
|
|
@ -1057,6 +1342,40 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) |
|
|
|
|
xf86InitValuatorDefaults(device, axnum); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) { |
|
|
|
|
int axnum = pEvdev->axis_map[axis]; |
|
|
|
|
int resolution = 10000; |
|
|
|
|
int j; |
|
|
|
|
BOOL skip = FALSE; |
|
|
|
|
|
|
|
|
|
if (axnum < 0) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < ArrayLength(mt_axis_mappings); j++) |
|
|
|
|
if (mt_axis_mappings[j].mt_code == axis && |
|
|
|
|
mt_axis_mappings[j].needs_mapping) |
|
|
|
|
{ |
|
|
|
|
skip = TRUE; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* MT axis is mapped, don't set up twice */ |
|
|
|
|
if (skip) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (pEvdev->absinfo[axis].resolution) |
|
|
|
|
resolution = pEvdev->absinfo[axis].resolution * 1000; |
|
|
|
|
|
|
|
|
|
xf86InitValuatorAxisStruct(device, axnum, |
|
|
|
|
atoms[axnum], |
|
|
|
|
pEvdev->absinfo[axis].minimum, |
|
|
|
|
pEvdev->absinfo[axis].maximum, |
|
|
|
|
resolution, 0, resolution, |
|
|
|
|
Absolute); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
free(atoms); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ArrayLength(proximity_bits); i++) |
|
|
|
|
@ -1107,6 +1426,11 @@ out: |
|
|
|
|
valuator_mask_free(&pEvdev->vals); |
|
|
|
|
valuator_mask_free(&pEvdev->old_vals); |
|
|
|
|
valuator_mask_free(&pEvdev->prox); |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
valuator_mask_free(&pEvdev->mt_mask); |
|
|
|
|
for (i = 0; i < EVDEV_MAXQUEUE; i++) |
|
|
|
|
valuator_mask_free(&pEvdev->queue[i].touchMask); |
|
|
|
|
#endif |
|
|
|
|
return !Success; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1440,6 +1764,9 @@ EvdevProc(DeviceIntPtr device, int what) |
|
|
|
|
{ |
|
|
|
|
InputInfoPtr pInfo; |
|
|
|
|
EvdevPtr pEvdev; |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
int i; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
pInfo = device->public.devicePrivate; |
|
|
|
|
pEvdev = pInfo->private; |
|
|
|
|
@ -1479,6 +1806,13 @@ EvdevProc(DeviceIntPtr device, int what) |
|
|
|
|
valuator_mask_free(&pEvdev->vals); |
|
|
|
|
valuator_mask_free(&pEvdev->old_vals); |
|
|
|
|
valuator_mask_free(&pEvdev->prox); |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
valuator_mask_free(&pEvdev->mt_mask); |
|
|
|
|
for (i = 0; i < EVDEV_MAXQUEUE; i++) |
|
|
|
|
valuator_mask_free(&pEvdev->queue[i].touchMask); |
|
|
|
|
if (pEvdev->mtdev) |
|
|
|
|
mtdev_close(pEvdev->mtdev); |
|
|
|
|
#endif |
|
|
|
|
EvdevRemoveDevice(pInfo); |
|
|
|
|
pEvdev->min_maj = 0; |
|
|
|
|
break; |
|
|
|
|
@ -1626,6 +1960,7 @@ EvdevProbe(InputInfoPtr pInfo) |
|
|
|
|
{ |
|
|
|
|
int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll; |
|
|
|
|
int has_lmr; /* left middle right */ |
|
|
|
|
int has_mt; /* multitouch */ |
|
|
|
|
int ignore_abs = 0, ignore_rel = 0; |
|
|
|
|
EvdevPtr pEvdev = pInfo->private; |
|
|
|
|
int rc = 1; |
|
|
|
|
@ -1659,6 +1994,7 @@ EvdevProbe(InputInfoPtr pInfo) |
|
|
|
|
has_keys = FALSE; |
|
|
|
|
has_scroll = FALSE; |
|
|
|
|
has_lmr = FALSE; |
|
|
|
|
has_mt = FALSE; |
|
|
|
|
num_buttons = 0; |
|
|
|
|
|
|
|
|
|
/* count all buttons */ |
|
|
|
|
@ -1726,6 +2062,15 @@ EvdevProbe(InputInfoPtr pInfo) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
for (i = ABS_MT_SLOT; i < ABS_MAX; i++) { |
|
|
|
|
if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) { |
|
|
|
|
has_mt = TRUE; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (ignore_abs && has_abs_axes) |
|
|
|
|
{ |
|
|
|
|
xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n"); |
|
|
|
|
@ -1734,6 +2079,9 @@ EvdevProbe(InputInfoPtr pInfo) |
|
|
|
|
xf86IDrvMsg(pInfo, X_PROBED, "Found absolute axes\n"); |
|
|
|
|
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS; |
|
|
|
|
|
|
|
|
|
if (has_mt) |
|
|
|
|
xf86IDrvMsg(pInfo, X_PROBED, "Found absolute multitouch axes\n"); |
|
|
|
|
|
|
|
|
|
if ((EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) && |
|
|
|
|
EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))) { |
|
|
|
|
xf86IDrvMsg(pInfo, X_PROBED, "Found x and y absolute axes\n"); |
|
|
|
|
@ -1891,12 +2239,26 @@ EvdevOpenDevice(InputInfoPtr pInfo) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
pEvdev->mtdev = mtdev_new_open(pInfo->fd); |
|
|
|
|
if (pEvdev->mtdev) |
|
|
|
|
pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value; |
|
|
|
|
else { |
|
|
|
|
xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name); |
|
|
|
|
return FALSE; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* Check major/minor of device node to avoid adding duplicate devices. */ |
|
|
|
|
pEvdev->min_maj = EvdevGetMajorMinor(pInfo); |
|
|
|
|
if (EvdevIsDuplicate(pInfo)) |
|
|
|
|
{ |
|
|
|
|
xf86IDrvMsg(pInfo, X_WARNING, "device file is duplicate. Ignoring.\n"); |
|
|
|
|
close(pInfo->fd); |
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
mtdev_close_delete(pEvdev->mtdev); |
|
|
|
|
pEvdev->mtdev = NULL; |
|
|
|
|
#endif |
|
|
|
|
return BadMatch; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1937,6 +2299,10 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) |
|
|
|
|
if (rc != Success) |
|
|
|
|
goto error; |
|
|
|
|
|
|
|
|
|
#ifdef MULTITOUCH |
|
|
|
|
pEvdev->cur_slot = -1; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We initialize pEvdev->in_proximity to 1 so that device that doesn't use |
|
|
|
|
* proximity will still report events. |
|
|
|
|
@ -2334,6 +2700,17 @@ EvdevInitProperty(DeviceIntPtr dev) |
|
|
|
|
if (rc != Success) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (EvdevDeviceIsVirtual(pEvdev->device)) |
|
|
|
|
{ |
|
|
|
|
BOOL virtual = 1; |
|
|
|
|
prop_virtual = MakeAtom(XI_PROP_VIRTUAL_DEVICE, |
|
|
|
|
strlen(XI_PROP_VIRTUAL_DEVICE), TRUE); |
|
|
|
|
rc = XIChangeDeviceProperty(dev, prop_virtual, XA_INTEGER, 8, |
|
|
|
|
PropModeReplace, 1, &virtual, FALSE); |
|
|
|
|
XISetDevicePropertyDeletable(dev, prop_virtual, FALSE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XISetDevicePropertyDeletable(dev, prop_device, FALSE); |
|
|
|
|
|
|
|
|
|
if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS)) |
|
|
|
|
@ -2443,7 +2820,8 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, |
|
|
|
|
if (!checkonly) |
|
|
|
|
pEvdev->swap_axes = *((BOOL*)val->data); |
|
|
|
|
} else if (atom == prop_axis_label || atom == prop_btn_label || |
|
|
|
|
atom == prop_product_id || atom == prop_device) |
|
|
|
|
atom == prop_product_id || atom == prop_device || |
|
|
|
|
atom == prop_virtual) |
|
|
|
|
return BadAccess; /* Read-only properties */ |
|
|
|
|
|
|
|
|
|
return Success; |
|
|
|
|
|