#include <xf86.h>
#include <xf86Xinput.h>
+#ifdef _F_PROXY_DEVICE_ENABLED_
+#include <xorg/optionstr.h>
+#endif //_F_PROXY_DEVICE_ENABLED_
#include <exevents.h>
#include <xorgVersion.h>
#include <xkbsrv.h>
#define MAXDEVICES MAX_DEVICES
#endif
+#ifdef _F_PICTURE_OFF_MODE_ENABLE_
+#define XI_PROP_PICTURE_OFF_MODE "PICTURE_OFF_MODE"
+static Atom atomPictureOffMode;
+#endif //_F_PICTURE_OFF_MODE_ENABLE_
+
#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
#define MIN_KEYCODE 8
BTN_TOOL_LENS,
};
+extern char * strcasestr(const char *haystack, const char *needle);
+
static int EvdevOn(DeviceIntPtr);
static int EvdevCache(InputInfoPtr pInfo);
static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
static int EvdevOpenDevice(InputInfoPtr pInfo);
+static void EvdevCloseDevice(InputInfoPtr pInfo);
static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms);
static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
#ifdef _F_TOUCH_TRANSFORM_MATRIX_
static void EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix);
#endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
+#ifdef _F_SUPPORT_ROTATION_ANGLE_
+static void EvdevSetRotationAngle(EvdevPtr pEvdev, int angle);
+#endif /* _F_SUPPORT_ROTATION_ANGLE_ */
#ifdef _F_EVDEV_CONFINE_REGION_
Bool IsMaster(DeviceIntPtr dev);
DeviceIntPtr GetPairedDevice(DeviceIntPtr dev);
static void EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox);
static void EvdevSetCursorLimits(InputInfoPtr pInfo, int region[6], int isSet);
static void EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[6]);
+
+#ifdef MULTITOUCH
+static int num_slots(EvdevPtr pEvdev);
+#endif
+
+static Atom prop_confine_region = 0;
+#endif /* _F_EVDEV_CONFINE_REGION_ */
#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
static CARD32 EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg);
#endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
+#ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_
+static BOOL isButtonPressed = FALSE;
+#endif //_F_DONOT_SEND_RMA_BTN_RELEASE_
-static Atom prop_confine_region = 0;
-#endif /* _F_EVDEV_CONFINE_REGION_ */
static Atom prop_product_id;
static Atom prop_invert;
static Atom prop_calibration;
static Atom prop_relative_move_status;
static Atom prop_relative_move_ack;
#endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
+
+#ifdef _F_BLOCK_MOTION_DEVICE_
+static Atom prop_block_motion_status; /* Atom to block motion device */
+int block_motion_device = 0; /* Variable to set/unset of motion device */
+#endif //_F_BLOCK_MOTION_DEVICE_
+#ifdef _F_PICTURE_OFF_MODE_ENABLE_
+int pictureOffMode;
+#endif //_F_PICTURE_OFF_MODE_ENABLE_
+#ifdef _F_BOOST_PULSE_
+static int fd_boostpulse = 0;
+#endif //_F_BOOST_PULSE_
+
#ifdef _F_TOUCH_TRANSFORM_MATRIX_
static Atom prop_transform;
#endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
static Atom prop_xkb_rules = None;
#endif //_F_USE_DEFAULT_XKB_RULES_
+#ifdef _F_SUPPORT_ROTATION_ANGLE_
+static Atom prop_rotation_angle = 0;
+static Atom prop_rotation_node = 0;
+#endif //_F_SUPPORT_ROTATION_ANGLE_
+
+#ifdef _F_PROXY_DEVICE_ENABLED_
+static Atom prop_use_proxy_slave_device;
+static InputInfoPtr pCreatorInfo = NULL;
+static InputInfoPtr pProxyDeviceInfo = NULL;
+#define PROXY_DEV_NAME "HWKeys"
+#define OPT_TYPE_VAL "ProxyDev"
+
+static int EvdevSetProxyDevice(DeviceIntPtr dev, int val);
+static InputOption *EvdevOptionDupConvert(pointer original);
+static void EvdevFreeInputOpts(InputOption* opts);
+static void EvdevReplaceOption(InputOption *opts,const char* key, char * value);
+static InputInfoPtr EvdevCreateProxyDevice(InputInfoPtr pInfo);
+static void EvdevProxydevReadInput(InputInfoPtr pInfo);
+static void MakeClassesChangedEvent(DeviceChangedEvent *dce, DeviceIntPtr master, DeviceIntPtr slave, int flags);
+#ifndef _F_PROXY_DEVICE_CHANGE_SOURCE_ID
+static void EvdevPostDevChangeEvent(InputInfoPtr pInfo);
+#else /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
+static void EvdevCheckDevChange(EvdevPtr pEvdev, int deviceid);
+#endif /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
+
/* All devices the evdev driver has allocated and knows about.
* MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
* cannot be used by evdev, leaving us with a space of 2 at the end. */
if (!ev->keyremap) {
ev->keyremap=(EvdevKeyRemapPtr)calloc(sizeof(EvdevKeyRemap),1);
+ if (!ev->keyremap) return;
}
if (!ev->keyremap->sl[slice]) {
ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)calloc(sizeof(EvdevKeyRemapSlice),1);
+ if (!ev->keyremap->sl[slice]) return;
}
ev->keyremap->sl[slice]->cd[offs]=value;
}
c=s;
while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) {
c+=consumed;
- if (code < 0 || code > 65535L) {
+ if (code > 65535L) {
xf86Msg(X_ERROR,"%s: input code %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code);
continue;
}
xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n",
pInfo->name, c);
}
+ free(s);
}
#endif //_F_REMAP_KEYS_
-static EventQueuePtr
+static EvdevEventQueuePtr
EvdevNextInQueue(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = pInfo->private;
#else //_F_REMAP_KEYS_
int code = ev->code + MIN_KEYCODE;
#endif //_F_REMAP_KEYS_
- EventQueuePtr pQueue;
+ EvdevEventQueuePtr pQueue;
/* Filter all repeated events from device.
We'll do softrepeat in the server, but only since 1.6 */
if (value == 2)
return;
+#ifdef _F_BOOST_PULSE_
+ if (fd_boostpulse && value == 1)
+ write(fd_boostpulse, (void *) "1", 1);
+#endif //_F_BOOST_PULSE_
+
if ((pQueue = EvdevNextInQueue(pInfo)))
{
pQueue->type = EV_QUEUE_KEY;
void
EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
{
- EventQueuePtr pQueue;
+ EvdevEventQueuePtr pQueue;
+
+#ifdef _F_BOOST_PULSE_
+ if (fd_boostpulse && value == 1)
+ write(fd_boostpulse, (void *) "1", 1);
+#endif //_F_BOOST_PULSE_
if ((pQueue = EvdevNextInQueue(pInfo)))
{
void
EvdevQueueProximityEvent(InputInfoPtr pInfo, int value)
{
- EventQueuePtr pQueue;
+ EvdevEventQueuePtr pQueue;
if ((pQueue = EvdevNextInQueue(pInfo)))
{
pQueue->type = EV_QUEUE_PROXIMITY;
EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask,
uint16_t evtype)
{
- EventQueuePtr pQueue;
+ EvdevEventQueuePtr pQueue;
if ((pQueue = EvdevNextInQueue(pInfo)))
{
pQueue->type = EV_QUEUE_TOUCH;
if (EvdevMBEmuFilterEvent(pInfo, button, value))
return;
- if (button)
- EvdevQueueButtonEvent(pInfo, button, value);
+ if (button) {
+#ifdef _F_PICTURE_OFF_MODE_ENABLE_
+ if((pictureOffMode == 1) && (button == 1)) {
+ if(value == 0) {
+ /* Send right button press and release instead of left button press/release */
+ button = 3;
+ EvdevQueueButtonEvent(pInfo, button, 1);
+ EvdevQueueButtonEvent(pInfo, button, 0);
+ } else ; /* Do nothing Ignore the left button press event */
+ }
+ else {
+ /* When button is pressed, cancel timer for cursor hide*/
+ if(value == 1) {
+ isButtonPressed = TRUE;
+ } else {
+ isButtonPressed = FALSE;
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ TimerCancel(pEvdev->rel_move_timer);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ }
+ EvdevQueueButtonEvent(pInfo, button, value);
+ }
+#else //_F_PICTURE_OFF_MODE_ENABLE_
+ EvdevQueueButtonEvent(pInfo, button, value);
+#endif //_F_PICTURE_OFF_MODE_ENABLE_
+ }
else
EvdevQueueKbdEvent(pInfo, ev, value);
}
EvdevPtr pEvdev = pInfo->private;
int map;
+ TTRACE_BEGIN("XORG:EVDEV:PROCESS_REL_MOTION");
+
/* Get the signed value, earlier kernels had this as unsigned */
value = ev->value;
#endif
default:
/* Ignore EV_REL events if we never set up for them. */
- if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS))
+ if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS)) {
+ TTRACE_END();
return;
+ }
/* Handle mouse wheel emulation */
- if (EvdevWheelEmuFilterMotion(pInfo, ev))
+ if (EvdevWheelEmuFilterMotion(pInfo, ev)) {
+ TTRACE_END();
return;
+ }
pEvdev->rel_queued = 1;
pEvdev->delta[ev->code] += value;
valuator_mask_set(pEvdev->vals, map, value);
break;
}
+ TTRACE_END();
}
#ifdef MULTITOUCH
else
type = XI_TouchUpdate;
-
EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type);
pEvdev->slot_state = SLOTSTATE_EMPTY;
static int
num_slots(EvdevPtr pEvdev)
{
- int value = pEvdev->absinfo[ABS_MT_SLOT].maximum -
- pEvdev->absinfo[ABS_MT_SLOT].minimum + 1;
+ int value = 0;
+
+ if (pEvdev->mtdev) {
+ value = pEvdev->mtdev->caps.slot.maximum + 1;
+ }
+ else {
+ value= pEvdev->absinfo[ABS_MT_SLOT].maximum -
+ pEvdev->absinfo[ABS_MT_SLOT].minimum + 1;
+ }
/* If we don't know how many slots there are, assume at least 10 */
return value > 1 ? value : 10;
EvdevPtr pEvdev = pInfo->private;
int map;
+ TTRACE_BEGIN("XORG:EVDEV:PROCESS_ABS_MOTION");
+
/* Get the signed value, earlier kernels had this as unsigned */
value = ev->value;
#ifdef _F_EVDEV_SUPPORT_GAMEPAD
if(pEvdev->flags & EVDEV_GAMEPAD)
{
EvdevMappingGamepadAbsToKey(pInfo, ev);
- return;
+ goto out;
}
#endif//_F_EVDEV_SUPPORT_GAMEPAD
/* Ignore EV_ABS events if we never set up for them. */
if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
- return;
+ goto out;
if (ev->code > ABS_MAX)
- return;
+ goto out;
if (EvdevWheelEmuFilterMotion(pInfo, ev))
- return;
+ goto out;
if (ev->code >= ABS_MT_SLOT) {
EvdevProcessTouchEvent(pInfo, ev);
if(map < 0)
{
xf86IDrvMsg(pInfo, X_INFO, "[EvdevProcessAbsoluteMotionEvent] Invalid valuator (=%d), value=%d\nThis is going to be skipped.", map, value);
- return;
+ goto out;
}
valuator_mask_set(pEvdev->vals, map, value);
pEvdev->abs_queued = 1;
}
+out:
+ TTRACE_END();
}
/**
int value, i;
EvdevPtr pEvdev = pInfo->private;
+ TTRACE_BEGIN("XORG:EVDEV:PROCESS_KEY_MOTION");
+
/* Get the signed value, earlier kernels had this as unsigned */
value = ev->value;
/* don't repeat mouse buttons */
- if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
- if (value == 2)
- return;
-
+ if (ev->code >= BTN_MOUSE && ev->code < KEY_OK) {
+ if (value == 2) {
+ goto out;
+ }
+ }
#ifdef _F_EVDEV_SUPPORT_GAMEPAD
if(pEvdev->flags & EVDEV_GAMEPAD)
{
EvdevMappingGamepadKeyToKey(pInfo, ev);
- if (ev->code == 0)
- return;
+ if (ev->code == 0) {
+ goto out;
+ }
}
#endif//_F_EVDEV_SUPPORT_GAMEPAD
if (ev->code == proximity_bits[i])
{
EvdevProcessProximityEvent(pInfo, ev);
- return;
+ goto out;
}
}
EvdevProcessButtonEvent(pInfo, ev);
break;
}
+out:
+ TTRACE_END();
}
#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
else return 0;
if(!pEvdev) return 0;
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
if(pEvdev->rel_move_timer)
TimerCancel(pEvdev->rel_move_timer);
- pEvdev->rel_move_timer = NULL;
-
- pEvdev->rel_move_status = 0;
- pEvdev->rel_move_ack = 0;
- int rc = XIDeleteDeviceProperty(pInfo->dev, prop_relative_move_status, TRUE);
-
- if (rc != Success)
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+#ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_
+ if(!isButtonPressed)
{
- xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to delete device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status);
- }
+#endif //_F_DONOT_SEND_RMA_BTN_RELEASE_
+ pEvdev->rel_move_status = 0;
+ if (pEvdev->rel_move_ack != 2)
+ pEvdev->rel_move_ack = 0;
+ int rc = XIDeleteDeviceProperty(pInfo->dev, prop_relative_move_status, TRUE);
- ErrorF("[%s] pEvdev->rel_move_status=%d\n", __FUNCTION__, pEvdev->rel_move_status);
+ if (rc != Success)
+ { if (pEvdev->rel_move_ack != 2)
+ pEvdev->rel_move_ack = 0;
+ xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to delete device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status);
+ }
+#ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_
+ }
+#endif //_F_DONOT_SEND_RMA_BTN_RELEASE_
return 0;
}
{
EvdevPtr pEvdev = pInfo->private;
+#ifdef _F_BLOCK_MOTION_DEVICE_
+ if (pEvdev->rel_queued && (block_motion_device ==0)) {
+#else //_F_BLOCK_MOTION_DEVICE_
if (pEvdev->rel_queued) {
+#endif //_F_BLOCK_MOTION_DEVICE_
#ifdef _F_EVDEV_SUPPORT_ROTARY_
if (pEvdev->flags & EVDEV_OFM) {
pEvdev->extra_rel_post_ofm(pInfo, num_v, first_v, v);
RegisterBlockAndWakeupHandlers(EvdevBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
}
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
TimerCancel(pEvdev->rel_move_timer);
- pEvdev->rel_move_timer = NULL;
- pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, 15000, EvdevRelativeMoveTimer, pInfo);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
#endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
xf86PostMotionEventM(pInfo->dev, Relative, pEvdev->vals);
}
* pEvdev->in_proximity is initialized to 1 so devices that don't use
* this scheme still just work.
*/
+#ifdef _F_BLOCK_MOTION_DEVICE_
+ if (pEvdev->abs_queued && pEvdev->in_proximity && block_motion_device == 0 ) {
+#else //_F_BLOCK_MOTION_DEVICE_
if (pEvdev->abs_queued && pEvdev->in_proximity) {
+#endif //_F_BLOCK_MOTION_DEVICE_
xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->vals);
}
}
EvdevPtr pEvdev = pInfo->private;
+#ifdef _F_PROXY_DEVICE_ENABLED_
+#ifdef _F_PROXY_DEVICE_CHANGE_SOURCE_ID
+ if(!(pInfo->dev))
+ {
+ return;
+ }
+
+ EvdevCheckDevChange(pEvdev, pInfo->dev->id);
+#else
+ if(pEvdev->proxy_device){
+ EvdevPostDevChangeEvent(pEvdev->proxy_device);
+ }
+#endif
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
+
for (i = 0; i < pEvdev->num_queue; i++) {
switch (pEvdev->queue[i].type) {
case EV_QUEUE_KEY:
} else
xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key,
pEvdev->queue[i].val, 0, 0);
+
break;
case EV_QUEUE_PROXIMITY:
break;
if ((XI_TouchBegin == event_type) && (slot_idx == 0))
{
- if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_BEGIN))
- {
- sync_value = MTOUCH_FRAME_SYNC_BEGIN;
- EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
- }
- }
+ if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_BEGIN))
+ {
+ sync_value = MTOUCH_FRAME_SYNC_BEGIN;
+ EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
+ }
+ }
xf86PostTouchEvent(pInfo->dev, slot_idx,
event_type, 0,
if ((sync_value < 0) && (XI_TouchEnd == event_type))
{
- if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_END))
- {
- EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_END);
- }
+ if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_END))
+ {
+ EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_END);
+ }
+ else
+ {
+ EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_UPDATE);
+ }
}
}
#else /* #ifdef _F_GESTURE_EXTENSION_ */
int num_v = 0, first_v = 0;
int v[MAX_VALUATORS] = {};
EvdevPtr pEvdev = pInfo->private;
+ TTRACE_BEGIN("XORG:EVDEV:PROCESS_SYNC_MOTION");
EvdevProcessProximityState(pInfo);
memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
for (i = 0; i < ArrayLength(pEvdev->queue); i++)
{
- EventQueuePtr queue = &pEvdev->queue[i];
+ EvdevEventQueuePtr queue = &pEvdev->queue[i];
queue->detail.key = 0;
queue->type = 0;
queue->val = 0;
pEvdev->rel_queued = 0;
pEvdev->prox_queued = 0;
+ TTRACE_END();
}
/**
static void
EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
{
+ TTRACE_BEGIN("XORG:EVDEV:PROCESS_EVENT");
+
+ EvdevPtr pEvdev = pInfo->private;
+ int result = 0;
+
+#ifdef _F_EVDEV_SUPPORT_SMARTRC_
+ if (pEvdev->extra_input_process) {
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+ result = pEvdev->extra_input_process(&pInfo, ev);
+#else
+ result = pEvdev->extra_input_process(pInfo, ev);
+#endif
+ if (!result) {
+ return;
+ }
+ }
+#endif //_F_EVDEV_SUPPORT_SMARTRC_
+
+#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
+ if (pEvdev->rel_move_ack == 2) {
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ TimerCancel(pEvdev->rel_move_timer);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ pEvdev->rel_move_status = 0;
+
+ return;
+ }
+#endif//_F_ENABLE_REL_MOVE_STATUS_PROP_
switch (ev->type) {
case EV_REL:
EvdevProcessRelativeMotionEvent(pInfo, ev);
EvdevProcessSyncEvent(pInfo, ev);
break;
}
+ TTRACE_END();
}
#undef ABS_X_VALUE
static void
EvdevFreeMasks(EvdevPtr pEvdev)
{
+#ifdef MULTITOUCH
int i;
+#endif
valuator_mask_free(&pEvdev->vals);
valuator_mask_free(&pEvdev->old_vals);
struct input_event ev[NUM_EVENTS];
int i, len = sizeof(ev);
+ TTRACE_BEGIN("XORG:EVDEV:READ_INPUT");
+
while (len == sizeof(ev))
{
#ifdef MULTITOUCH
EvdevMBEmuFinalize(pInfo);
Evdev3BEmuFinalize(pInfo);
xf86RemoveEnabledDevice(pInfo);
- close(pInfo->fd);
- pInfo->fd = -1;
- } else if (errno != EAGAIN)
+ }
+ else if (errno != EAGAIN)
{
/* We use X_NONE here because it doesn't alloc */
xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
for (i = 0; i < len/sizeof(ev[0]); i++)
EvdevProcessEvent(pInfo, &ev[i]);
}
+ TTRACE_END();
}
static void
}
#ifdef MULTITOUCH
if (num_mt_axes_total > 0) {
+ pEvdev->num_mt_vals = num_mt_axes_total;
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",
i = 0;
for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
+#ifdef MULTITOUCH
int j;
+#endif
int mapping;
pEvdev->axis_map[axis] = -1;
if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) ||
int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
XIDependentTouch : XIDirectTouch;
- if (pEvdev->mtdev && pEvdev->mtdev->caps.slot.maximum > 0)
- num_touches = pEvdev->mtdev->caps.slot.maximum;
+ num_touches = num_slots(pEvdev);
if (!InitTouchClassDeviceStruct(device, num_touches, mode,
num_mt_axes_total)) {
else if (axis == REL_DIAL)
SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_NONE);
else if (axis == REL_HWHEEL)
- SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE);
+ SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE);
#endif
}
/* Check for user-defined button mapping */
if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
{
- char *map, *s = " ";
+ char *map, *s = NULL;
int btn = 0;
xf86IDrvMsg(pInfo, X_CONFIG, "ButtonMapping '%s'\n", mapping);
map = mapping;
- while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS)
+ do
{
btn = strtol(map, &s, 10);
pEvdev->btnmap[nbuttons++] = btn;
map = s;
- }
+ } while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS);
free(mapping);
}
pInfo = device->public.devicePrivate;
pEvdev = pInfo->private;
+ TTRACE_BEGIN("XORG:EVDEV:INIT");
/* clear all axis_map entries */
for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
* unregister is when the device dies. In which case we don't have to
* unregister anyway */
EvdevInitProperty(device);
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ if (!strncmp(pInfo->name, PROXY_DEV_NAME, sizeof(PROXY_DEV_NAME))) {
+ EvdevProxyInit(device);
+ }
+ else
+ XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
+#else //_F_PROXY_DEVICE_ENABLED_
XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
+#endif //_F_PROXY_DEVICE_ENABLED_
EvdevMBEmuInitProperty(device);
Evdev3BEmuInitProperty(device);
EvdevWheelEmuInitProperty(device);
#ifdef _F_EVDEV_SUPPORT_ROTARY_
EvdevRotaryInit(device);
#endif //_F_EVDEV_SUPPORT_ROTARY_
+#ifdef _F_EVDEV_SUPPORT_SMARTRC_
+ EvdevRCInit(device);
+#endif //_F_EVDEV_SUPPORT_SMARTRC_
+
+ TTRACE_END();
return Success;
}
InputInfoPtr pInfo;
EvdevPtr pEvdev;
int rc = Success;
+ ErrorF("[EvdevOn][id:%d] find device (%s)\n", device->id, device->name);
+ TTRACE_BEGIN("XORG:EVDEV:ON");
pInfo = device->public.devicePrivate;
pEvdev = pInfo->private;
+
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ /*Check if its proxy device.. in that case just set flag and return..*/
+ if(pEvdev->b_proxy_device)
+ {
+ pEvdev->flags |= EVDEV_INITIALIZED;
+ device->public.on = TRUE;
+ return Success;
+ }
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
+
/* after PreInit fd is still open */
rc = EvdevOpenDevice(pInfo);
- if (rc != Success)
+ if (rc != Success) {
+ TTRACE_END();
return rc;
+ }
EvdevGrabDevice(pInfo, 1, 0);
pEvdev->flags |= EVDEV_INITIALIZED;
device->public.on = TRUE;
+ TTRACE_END();
return Success;
}
return EvdevOn(device);
case DEVICE_OFF:
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ if(pEvdev->b_proxy_device)
+ {
+ if (pEvdev->flags & EVDEV_INITIALIZED)
+ {
+ pEvdev->min_maj = 0;
+ pEvdev->flags &= ~EVDEV_INITIALIZED;
+ device->public.on = FALSE;
+ }
+ if (pInfo->fd != -1)
+ {
+ xf86RemoveEnabledDevice(pInfo);
+ close(pInfo->fd);
+ pInfo->fd = -1;
+ }
+ return Success;
+ }
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
if (pEvdev->flags & EVDEV_INITIALIZED)
{
EvdevMBEmuFinalize(pInfo);
{
EvdevGrabDevice(pInfo, 0, 1);
xf86RemoveEnabledDevice(pInfo);
- close(pInfo->fd);
- pInfo->fd = -1;
+ EvdevCloseDevice(pInfo);
}
#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
if (pEvdev->rel_move_timer)
{
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
TimerCancel(pEvdev->rel_move_timer);
- pEvdev->rel_move_timer = NULL;
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
pEvdev->rel_move_status = 0;
pEvdev->rel_move_ack = 0;
ErrorF("[%s][dev:%d] DEVICE_OFF (rel_move_status=%d, rel_move_prop_set=%d)\n", __FUNCTION__, pInfo->dev->id, pEvdev->rel_move_status,
EvdevSetConfineRegion(pInfo, 1, ®ion[0]);
#endif /* _F_EVDEV_CONFINE_REGION_ */
xf86IDrvMsg(pInfo, X_INFO, "Close\n");
- if (pInfo->fd != -1) {
- close(pInfo->fd);
- pInfo->fd = -1;
- }
+ EvdevCloseDevice(pInfo);
EvdevFreeMasks(pEvdev);
EvdevRemoveDevice(pInfo);
#ifdef _F_REMAP_KEYS_
goto error;
}
- strcpy(pEvdev->name, name);
+ len = strlen(name);
+ if (len < sizeof(pEvdev->name)) {
+ strncpy(pEvdev->name, name, len+1);
+ } else {
+ strncpy(pEvdev->name, name, sizeof(pEvdev->name)-1);
+ xf86DrvMsg(pInfo, X_WARNING, "Device's name(%s) is too long. Restrict name to inside of buffer size\n", pEvdev->name);
+ }
len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
if (len < 0) {
}
}
#endif
-
+#ifdef _F_EVDEV_SUPPORT_SMARTRC_
+ if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_EXTRA))
+ {
+ xf86IDrvMsg(pInfo, X_PROBED, "Found extra button\n");
+ if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE)))
+ {
+ xf86IDrvMsg(pInfo, X_PROBED, "... regarding smart rc\n");
+ pEvdev->flags |= EVDEV_SMART_RC;
+ }
+ }
+ if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_SIDE))
+ {
+ xf86IDrvMsg(pInfo, X_PROBED, "Found extra button\n");
+ if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE)))
+ {
+ xf86IDrvMsg(pInfo, X_PROBED, "... regarding smart rc\n");
+ pEvdev->flags |= EVDEV_SMART_RC;
+ }
+ }
+#endif //_F_EVDEV_SUPPORT_SMARTRC_
if (ignore_abs && has_abs_axes)
{
xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n");
xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchscreen\n");
pInfo->type_name = XI_TOUCHSCREEN;
} else {
+ if (!EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) ||
+ !EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y))
+ EvdevForceXY(pInfo, Relative);
xf86IDrvMsg(pInfo, X_INFO, "Configuring as mouse\n");
pInfo->type_name = XI_MOUSE;
}
pEvdev->flags |= EVDEV_HALLIC;
}
#endif //_F_EVDEV_SUPPORT_ROTARY_
+#ifdef _F_EVDEV_SUPPORT_SMARTRC_
+ if (pEvdev->flags & EVDEV_SMART_RC) {
+ xf86IDrvMsg(pInfo, X_INFO, "Configuring as smart rc\n");
+ pInfo->type_name = XI_MOUSE;
+ EvdevSetBit(pEvdev->rel_bitmask, REL_WHEEL);
+ EvdevSetBit(pEvdev->rel_bitmask, REL_HWHEEL);
+ }
+ pEvdev->origin_input_process = EvdevProcessEvent;
+#endif //_F_EVDEV_SUPPORT_SMARTRC_
if (rc)
xf86IDrvMsg(pInfo, X_WARNING, "Don't know how to use device\n");
}
}
+#ifdef MULTITOUCH
+ if (!pEvdev->mtdev) { /* after PreInit mtdev is still valid */
+ pEvdev->mtdev = mtdev_new_open(pInfo->fd);
+ if (!pEvdev->mtdev) {
+ xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
+ EvdevCloseDevice(pInfo);
+ return FALSE;
+ }
+ }
+ if (pEvdev->mtdev)
+ pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
+#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");
+ EvdevCloseDevice(pInfo);
+ return BadMatch;
+ }
+
+ return Success;
+}
+
+static void
+EvdevCloseDevice(InputInfoPtr pInfo)
+{
+ EvdevPtr pEvdev = pInfo->private;
+ if (pInfo->fd >= 0)
+ {
close(pInfo->fd);
+ pInfo->fd = -1;
+ }
+
#ifdef MULTITOUCH
+ if (pEvdev->mtdev)
+ {
mtdev_close_delete(pEvdev->mtdev);
pEvdev->mtdev = NULL;
-#endif
- return BadMatch;
}
+#endif
- return Success;
}
#ifdef _F_EVDEV_CONFINE_REGION_
}
#endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
+#ifdef _F_SUPPORT_ROTATION_ANGLE_
+static void
+EvdevSetRotationAngle(EvdevPtr pEvdev, int angle)
+{
+ if(pEvdev->rotation_node <= 0)
+ {
+ xf86Msg(X_INFO, "[%s] Rotation node doesn't exist. Ignored. (angle=%d)\n", __FUNCTION__, angle);
+ return;
+ }
+
+ if(pEvdev->rotation_angle != angle)
+ {
+ {
+ int nwrite = 0;
+ char buf;
+
+ buf = (char)(angle + '0');
+
+ nwrite = write(pEvdev->rotation_node, &buf, sizeof(buf));
+
+ if(nwrite <= 0)
+ xf86Msg(X_ERROR, "[%s] Failed to write angle(=%d) on rotation_node. (errno=%d)\n", __FUNCTION__, angle, errno);
+ else
+ xf86Msg(X_ERROR, "[%s] Succeed to write angle(=%d) on rotation_node.\n", __FUNCTION__, angle);
+ }
+
+ pEvdev->rotation_angle = angle;
+ }
+ else
+ {
+ xf86Msg(X_INFO, "[%s] Rotation angle has not been changed. Ignored. (angle=%d)\n", __FUNCTION__, angle);
+ }
+}
+#endif// _F_SUPPORT_ROTATION_ANGLE_
+
static void
EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
{
/* Release string allocated in EvdevOpenDevice. */
free(pEvdev->device);
pEvdev->device = NULL;
+ free(pEvdev);
+ pEvdev = NULL;
}
xf86DeleteInput(pInfo, flags);
}
const char *str;
#endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ char *type;
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
+
+#ifdef _F_BOOST_PULSE_
+ if(fd_boostpulse == NULL)
+ fd_boostpulse = open("sys/kernel/hmp/boostpulse", O_RDWR);
+#endif //_F_BOOST_PULSE_
+
if (!(pEvdev = calloc(sizeof(EvdevRec), 1)))
{
xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory for private member of pInfo !\n");
goto error;
}
+ TTRACE_END();
+
pInfo->private = pEvdev;
pInfo->type_name = "UNKNOWN";
pInfo->device_control = EvdevProc;
pInfo->read_input = EvdevReadInput;
pInfo->switch_mode = EvdevSwitchMode;
+#ifdef _F_EVDEV_SUPPORT_SMARTRC_
+ pEvdev->extra_input_process = NULL;
+ pEvdev->rc_state = 0;
+ pEvdev->proxy_enabled = xf86SetBoolOption(pInfo->options, "ProxyDeviceEnabled", FALSE);
+#endif //_F_EVDEV_SUPPORT_SMARTRC_
+
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ /* If Type == ProxyDev, this is a proxy device */
+ type = xf86CheckStrOption(pInfo->options, "Type", NULL);
+
+ xf86Msg(X_INFO, "%s: Evdev Type %s found\n", pInfo->name, type);
+
+ if (type != NULL && strcmp(type, OPT_TYPE_VAL) == 0)
+ {
+ EvdevPtr pCreatorEvdev;
+ free(type);
+ if (!pCreatorInfo){
+ return Success;
+ }
+ pCreatorEvdev = pCreatorInfo->private;
+ xf86Msg(X_INFO, "%s: Evdev proxy device found\n", pInfo->name);
+ memcpy(pEvdev, pCreatorEvdev, sizeof(EvdevRec));
+ pInfo->read_input = EvdevProxydevReadInput;
+ pInfo->type_name = pCreatorInfo->type_name;
+ pEvdev->b_proxy_device = TRUE;
+ pEvdev->proxy_device = NULL;
+ return Success;
+ }
+ else
+ {
+ free(type);
+ pEvdev->b_proxy_device = FALSE;
+ pEvdev->proxy_device = NULL;
+ }
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
+
#ifdef _F_EVDEV_SUPPORT_ROTARY_
pEvdev->extra_rel_post_hallic= NULL;
pEvdev->extra_rel_post_ofm= NULL;
#ifdef MULTITOUCH
pEvdev->cur_slot = -1;
#endif
+#ifdef MULTI_PASSIVE_GRAB_
+ pEvdev->activatedkeylist = NULL;
+#endif //MULTI_PASSIVE_GRAB_
/*
* We initialize pEvdev->in_proximity to 1 so that device that doesn't use
else
{
xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
+ TTRACE_END();
return FALSE;
}
}
#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
pEvdev->rel_move_timer = NULL;
+ if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
+ {
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ if (!pEvdev->b_proxy_device)
+ {
+#endif //_F_PROXY_DEVICE_ENABLED_
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ TimerCancel(pEvdev->rel_move_timer);
+ ErrorF("[EvdevPreinit] Device: %s has relative events create RMS timer(%p)\n", pInfo->name, pEvdev->rel_move_timer);
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ }
+#endif //_F_PROXY_DEVICE_ENABLED_
+ }
pEvdev->rel_move_prop_set = 0;
pEvdev->rel_move_status = 0;
#endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
pEvdev->keycode_btnPlay = xf86SetIntOption(pInfo->options, "GamePad_ButtonPlay", 0);
#endif//_F_EVDEV_SUPPORT_GAMEPAD
+#ifdef _F_SUPPORT_ROTATION_ANGLE_
+ pEvdev->rotation_angle = xf86SetIntOption(pInfo->options, "RotationAngle", 0);
+
+ str = xf86CheckStrOption(pInfo->options, "RotationNode", NULL);
+ if (str)
+ {
+ do {
+ pEvdev->rotation_node = open(str, O_WRONLY, 0);
+ } while (pEvdev->rotation_node < 0 && errno == EINTR);
+ }
+ else xf86Msg(X_INFO, "%s: No rotation node exists..\n", pInfo->name);
+
+ if (pEvdev->rotation_node < 0) {
+ xf86Msg(X_ERROR, "Unable to open evdevmultitouch rotation_node\"%s\".\n", str);
+ xf86Msg(X_ERROR, "Input rotation will be done inside evdevmultitouch driver.\n");
+ pEvdev->rotation_node = 0;
+ }
+#endif// _F_SUPPORT_ROTATION_ANGLE_
+
+ TTRACE_END();
return Success;
error:
- if ((pInfo) && (pInfo->fd >= 0))
- close(pInfo->fd);
+ EvdevCloseDevice(pInfo);
+ TTRACE_END();
return rc;
}
#ifdef _F_EVDEV_CONFINE_REGION_
int region[6] = { 0, };
#endif /* _F_EVDEV_CONFINE_REGION_ */
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ int slave_proxy;
+#endif /* _F_PROXY_DEVICE_ENABLED_ */
CARD32 product[2];
-
+#ifdef _F_PICTURE_OFF_MODE_ENABLE_
+ atomPictureOffMode = MakeAtom(XI_PROP_PICTURE_OFF_MODE,strlen(XI_PROP_PICTURE_OFF_MODE), TRUE);
+#endif //_F_PICTURE_OFF_MODE_ENABLE_
prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID, strlen(XI_PROP_PRODUCT_ID), TRUE);
product[0] = pEvdev->id_vendor;
product[1] = pEvdev->id_product;
device_node = strdup(pEvdev->device);
prop_device = MakeAtom(XI_PROP_DEVICE_NODE,
strlen(XI_PROP_DEVICE_NODE), TRUE);
- rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8,
- PropModeReplace,
- (device_node?strlen(device_node):0), device_node,
- FALSE);
- free(device_node);
-
- if (rc != Success)
- return;
+ if (device_node)
+ {
+ rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8,
+ PropModeReplace,
+ strlen(device_node), device_node,
+ FALSE);
+ free(device_node);
- XISetDevicePropertyDeletable(dev, prop_device, FALSE);
+ if (rc == Success)
+ XISetDevicePropertyDeletable(dev, prop_device, FALSE);
+ }
#ifdef _F_ENABLE_DEVICE_TYPE_PROP_
/* Device node property */
device_type = strdup(pInfo->type_name);
prop_device_type = MakeAtom(XI_PROP_DEVICE_TYPE,
strlen(XI_PROP_DEVICE_TYPE), TRUE);
- rc = XIChangeDeviceProperty(dev, prop_device_type, XA_STRING, 8,
- PropModeReplace,
- (device_type?strlen(device_type):0), device_type,
- FALSE);
- free(device_type);
-
- if (rc != Success)
- return;
+ if (device_type)
+ {
+ rc = XIChangeDeviceProperty(dev, prop_device_type, XA_STRING, 8,
+ PropModeReplace,
+ strlen(device_type), device_type,
+ FALSE);
+ free(device_type);
+ }
#endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
strlen(XI_PROP_REL_MOVE_STATUS), TRUE);
prop_relative_move_ack = MakeAtom(XI_PROP_REL_MOVE_ACK,
strlen(XI_PROP_REL_MOVE_ACK), TRUE);
-
+#ifdef _F_BLOCK_MOTION_DEVICE_
+ prop_block_motion_status = MakeAtom(XI_PROP_BLOCK_MOTION_DEVICE,
+ strlen(XI_PROP_BLOCK_MOTION_DEVICE), TRUE);
+#endif //_F_BLOCK_MOTION_DEVICE_
ErrorF("[%s] prop_relative_move_status = %d, prop_relative_move_ack = %d\n", __FUNCTION__, prop_relative_move_status, prop_relative_move_ack);
#endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
{
int mode;
- Atom atoms[pEvdev->num_vals];
+ int num_axes = pEvdev->num_vals + pEvdev->num_mt_vals;
+ Atom atoms[num_axes];
if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
mode = Absolute;
mode = Absolute;
}
- EvdevInitAxesLabels(pEvdev, mode, pEvdev->num_vals, atoms);
+ EvdevInitAxesLabels(pEvdev, mode, num_axes, atoms);
XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
- PropModeReplace, pEvdev->num_vals, atoms, FALSE);
+ PropModeReplace, num_axes, atoms, FALSE);
XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
}
/* Button labelling */
PropModeReplace, pEvdev->num_buttons, atoms, FALSE);
XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
}
- }
+#ifdef _F_SUPPORT_ROTATION_ANGLE_
+ if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
+ int rotation_angle;
+ prop_rotation_angle = MakeAtom(EVDEV_PROP_ROTATION_ANGLE,
+ strlen(EVDEV_PROP_ROTATION_ANGLE), TRUE);
+
+ rotation_angle = pEvdev->rotation_angle;
+ rc = XIChangeDeviceProperty(dev, prop_rotation_angle, XA_INTEGER, 8,
+ PropModeReplace, 1, &rotation_angle, TRUE);
+ if (rc != Success)
+ return;
+
+ XISetDevicePropertyDeletable(dev, prop_rotation_angle, FALSE);
+
+ int rotation_node;
+ prop_rotation_node = MakeAtom(EVDEV_PROP_ROTATION_NODE,
+ strlen(EVDEV_PROP_ROTATION_NODE), TRUE);
+
+ rotation_node = pEvdev->rotation_node;
+ rc = XIChangeDeviceProperty(dev, prop_rotation_node, XA_INTEGER, 32,
+ PropModeReplace, 1, &rotation_node, FALSE);
+ if (rc != Success)
+ return;
+
+ XISetDevicePropertyDeletable(dev, prop_rotation_node, FALSE);
+ }
+#endif //_F_SUPPORT_ROTATION_ANGLE_
+
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ slave_proxy = 0;
+ prop_use_proxy_slave_device = MakeAtom(XI_PROP_USE_PROXY_SLAVE_DEVICE, strlen(XI_PROP_USE_PROXY_SLAVE_DEVICE), TRUE);
+ XIChangeDeviceProperty(dev, prop_use_proxy_slave_device, XA_INTEGER, 8,
+ PropModeReplace, 1, &slave_proxy, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_use_proxy_slave_device, FALSE);
+ pEvdev->proxy_device = NULL;
+#endif // _F_PROXY_DEVICE_ENABLED_
+ }
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ slave_proxy = 0;
+ prop_use_proxy_slave_device = MakeAtom(XI_PROP_USE_PROXY_SLAVE_DEVICE, strlen(XI_PROP_USE_PROXY_SLAVE_DEVICE), TRUE);
+ XIChangeDeviceProperty(dev, prop_use_proxy_slave_device, XA_INTEGER, 8,
+ PropModeReplace, 1, &slave_proxy, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_use_proxy_slave_device, FALSE);
+ pEvdev->proxy_device = NULL;
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
}
static int
#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
else if (atom == prop_relative_move_ack)
{
+ int data;
+
if (val->format != 8 || val->type != XA_INTEGER)
return BadMatch;
if (val->size != 1)
return BadMatch;
- if (!checkonly)
- pEvdev->rel_move_ack = 1;
+ if (!checkonly) {
+ data = *((CARD8*)val->data);
+ pEvdev->rel_move_ack = data;
+ }
+
+ if ((pEvdev->rel_move_ack == 2) || (pEvdev->rel_move_ack == 3))
+ {
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ TimerCancel(pEvdev->rel_move_timer);
+ if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
+ pEvdev->rel_move_status = 0;
+ }
}
#endif /* _F_ENABLE_REL_MOVE_STATUS_PROP_ */
+#ifdef _F_GESTURE_EXTENSION_
+ else if (atom == XIGetKnownProperty(XI_PROP_ENABLED))
+ {
+ if (val->format != 8 || val->type != XA_INTEGER)
+ return BadMatch;
+
+ if (val->size != 1)
+ return BadMatch;
+
+ if (!checkonly && strcasestr(dev->name, "touchscreen"))
+ {
+ DeviceIntPtr device;
+ for (device = inputInfo.devices; device; device = device->next)
+ {
+ if(!strncmp(device->name, GESTURE_DEV_NAME, sizeof(GESTURE_DEV_NAME)-1))
+ {
+ InputInfoPtr gestureInfo = device->public.devicePrivate;
+ ErrorF("[EvdevSetProperty][id:%d] find device (%s)\n", device->id, device->name);
+ gestureInfo->device_control(device, DEVICE_READY);
+ break;
+ }
+ }
+ }
+ }
+#endif //_F_GESTURE_EXTENSION_
+
+#ifdef _F_SUPPORT_ROTATION_ANGLE_
+ else if (atom == prop_rotation_angle)
+ {
+ int data;
+ char cdata;
+ if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
+ return BadMatch;
+
+ if (!checkonly)
+ {
+ cdata = *((char*)val->data);
+ data = (int)cdata;
+
+ EvdevSetRotationAngle(pEvdev, data);
+ }
+ }
+#endif //_F_SUPPORT_ROTATION_ANGLE_
+
+#ifdef _F_PROXY_DEVICE_ENABLED_
+ else if (atom == prop_use_proxy_slave_device)
+ {
+ int data;
+
+ if (val->format != 8 || val->type != XA_INTEGER)
+ return BadMatch;
+ if (val->size != 1)
+ return BadMatch;
+ if (!pEvdev->proxy_enabled)
+ return Success;
+
+ if (!checkonly) {
+ data = *((CARD8*)val->data);
+ EvdevSetProxyDevice(dev,data);
+ }
+ }
+#endif // #ifdef _F_PROXY_DEVICE_ENABLED_
+#ifdef _F_BLOCK_MOTION_DEVICE_
+ else if (atom == prop_block_motion_status )
+ {
+ int data;
+
+ if (!checkonly) {
+ data = *((CARD8*)val->data);
+ block_motion_device = data;
+ }
+ }
+ else if ((atom == atomPictureOffMode))
+ {
+ int data;
+ data = *((CARD8*)val->data);
+ pictureOffMode = data;
+ }
+#endif //_F_BLOCK_MOTION_DEVICE_
return Success;
}
+
+#ifdef _F_PROXY_DEVICE_ENABLED_
+
+static int EvdevSetProxyDevice(DeviceIntPtr dev, int val)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ EvdevPtr pEvdev = pInfo->private;
+ if(0 == val) {
+ pEvdev->proxy_device = NULL;
+ } else {
+ if(NULL == pProxyDeviceInfo) {
+ pProxyDeviceInfo = EvdevCreateProxyDevice(pInfo);
+ }
+ pEvdev->proxy_device = pProxyDeviceInfo;
+ }
+ return 1;
+}
+
+/* Duplicate xf86 options and convert them to InputOption */
+static InputOption *EvdevOptionDupConvert(pointer original)
+{
+ InputOption *iopts = NULL, *new;
+ InputInfoRec dummy;
+
+ memset(&dummy, 0, sizeof(dummy));
+ dummy.options = xf86OptionListDuplicate(original);
+
+ while(dummy.options)
+ {
+ if (xf86NameCmp(xf86OptionName(dummy.options), "config_info") == 0) {
+ /*should not copy config_info as its used by hotplugging layer*/
+ dummy.options = xf86NextOption(dummy.options);
+ continue;
+ }
+ new = calloc(1, sizeof(struct _InputOption));
+ if (!new) return iopts;
+
+ new->opt_name = xf86OptionName(dummy.options);
+ new->opt_val = xf86OptionValue(dummy.options);
+ new->list.next = iopts;
+ iopts = new;
+ dummy.options = xf86NextOption(dummy.options);
+ }
+
+ return iopts;
+}
+
+static void EvdevFreeInputOpts(InputOption* opts)
+{
+ InputOption *tmp = opts;
+ while(opts)
+ {
+ tmp = opts->list.next;
+ free(opts->opt_name);
+ free(opts->opt_val);
+ free(opts);
+ opts = tmp;
+ }
+}
+
+static void EvdevReplaceOption(InputOption *opts,const char* key, char * value)
+{
+ while(opts)
+ {
+ if (xf86NameCmp(opts->opt_name, key) == 0)
+ {
+ free(opts->opt_val);
+ opts->opt_val = strdup(value);
+ }
+ opts = opts->list.next;
+ }
+}
+
+
+/*
+* @return 0 if successful, 1 if failure pProxyDeviceInfo
+*/
+static InputInfoPtr
+EvdevCreateProxyDevice(InputInfoPtr pInfo) {
+ InputInfoPtr pProxyDev;
+
+ DeviceIntPtr dev; /* dummy */
+ InputOption *input_options = NULL;
+ char* name;
+ char str_OPT_TYPE_VAL[sizeof(OPT_TYPE_VAL)];
+ char str_dev_null[sizeof("/dev/null")];
+
+ pInfo->options = xf86AddNewOption(pInfo->options, "Type", "core");
+ pInfo->options = xf86AddNewOption(pInfo->options, "SendCoreEvents", "on");
+
+ /* Create new device */
+ input_options = EvdevOptionDupConvert(pInfo->options);
+ snprintf(str_OPT_TYPE_VAL, sizeof(OPT_TYPE_VAL), OPT_TYPE_VAL);
+ EvdevReplaceOption(input_options, "type",str_OPT_TYPE_VAL);
+
+ name = malloc( (strlen(PROXY_DEV_NAME) + 1)*sizeof(char));
+
+ if( !name )
+ {
+ EvdevFreeInputOpts(input_options);
+ xf86DrvMsg(-1, X_ERROR, "[X11][%s] Failed to allocate memory !\n", __FUNCTION__);
+ return NULL;
+ }
+
+ snprintf(name, strlen(PROXY_DEV_NAME)+1, PROXY_DEV_NAME);
+ snprintf(str_dev_null, sizeof("/dev/null"), "/dev/null");
+ EvdevReplaceOption(input_options, "name",name);
+ EvdevReplaceOption(input_options, "Device",str_dev_null);
+ EvdevReplaceOption(input_options, "Path",str_dev_null);
+
+ pCreatorInfo = pInfo;
+ NewInputDeviceRequest(input_options, NULL, &dev);
+ pProxyDev = dev->public.devicePrivate;
+ pCreatorInfo = NULL;
+
+ EvdevFreeInputOpts(input_options);
+
+ free(name);
+ return pProxyDev;
+}
+
+static void
+EvdevProxydevReadInput(InputInfoPtr pInfo)
+{
+
+}
+
+static void
+MakeClassesChangedEvent(DeviceChangedEvent *dce,
+ DeviceIntPtr master, DeviceIntPtr slave, int flags)
+{
+ int i;
+ CARD32 ms = GetTimeInMillis();
+
+ memset(dce, 0, sizeof(DeviceChangedEvent));
+ dce->deviceid = slave->id;
+ dce->masterid = master ? master->id : 0;
+ dce->header = ET_Internal;
+ dce->length = sizeof(DeviceChangedEvent);
+ dce->type = ET_DeviceChanged;
+ dce->time = ms;
+ dce->flags = flags;
+ dce->sourceid = slave->id;
+
+ if (slave->button) {
+ dce->buttons.num_buttons = slave->button->numButtons;
+ for (i = 0; i < dce->buttons.num_buttons; i++)
+ dce->buttons.names[i] = slave->button->labels[i];
+ }
+ if (slave->valuator) {
+ dce->num_valuators = slave->valuator->numAxes;
+ for (i = 0; i < dce->num_valuators; i++) {
+ dce->valuators[i].min = slave->valuator->axes[i].min_value;
+ dce->valuators[i].max = slave->valuator->axes[i].max_value;
+ dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
+ dce->valuators[i].mode = slave->valuator->axes[i].mode;
+ dce->valuators[i].name = slave->valuator->axes[i].label;
+ dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
+ }
+ }
+ if (slave->key) {
+ dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
+ dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
+ }
+}
+#ifndef _F_PROXY_DEVICE_CHANGE_SOURCE_ID
+static void EvdevPostDevChangeEvent(InputInfoPtr pInfo)
+{
+ DeviceChangedEvent event;
+ DeviceIntPtr master = inputInfo.keyboard;
+ DeviceIntPtr dummyDevice = pInfo->dev;
+ int flag;
+
+ if(master->last.slave == dummyDevice) {
+ return;
+ }
+
+ flag = DEVCHANGE_KEYBOARD_EVENT | DEVCHANGE_SLAVE_SWITCH;
+
+ MakeClassesChangedEvent(&event,master,dummyDevice,flag);
+
+ master->last.slave = dummyDevice;
+
+ mieqEnqueue (dummyDevice, (InternalEvent*)&event);
+}
+#else /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
+static void EvdevCheckDevChange(EvdevPtr pEvdev, int deviceid)
+{
+ DeviceChangedEvent event;
+ DeviceIntPtr master;
+ DeviceIntPtr dummyDevice;
+ int flag;
+ if(!pProxyDeviceInfo || !pEvdev) return;
+
+ //if proxydevice is created but is not used by the current device,
+ //reset the sourcedid of keyclass of the proxy device to its own id
+ //and return..
+ if(pProxyDeviceInfo && !pEvdev->proxy_device) {
+ pProxyDeviceInfo->dev->key->sourceid = pProxyDeviceInfo->dev->id;
+ return;
+ }
+
+ master = inputInfo.keyboard;
+ dummyDevice = pProxyDeviceInfo->dev;
+
+ //if nothing has changed.. return
+ //the first check is for differentiating between attached slaves and the second
+ //differentiates between the floating slaves represented by the proxy device
+ if(master->last.slave == dummyDevice &&
+ pProxyDeviceInfo->dev->key->sourceid == deviceid) {
+ return;
+ }
+
+ flag = DEVCHANGE_KEYBOARD_EVENT | DEVCHANGE_SLAVE_SWITCH;
+
+ MakeClassesChangedEvent(&event,master,dummyDevice,flag);
+
+ master->last.slave = dummyDevice;
+
+ //setting the source id of the device key class to the id of the actual slave it represents.
+ //clients can query the same to know which device the actual events are coming from
+ pProxyDeviceInfo->dev->key->sourceid = deviceid;
+
+ mieqEnqueue (dummyDevice, (InternalEvent*)&event);
+}
+#endif /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
+#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
--- /dev/null
+/*
+ *
+ * xserver-xorg-input-evdev
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ * Sangjin LEE <lsj119@samsung.com>
+ * Jeonghyun Kang <jhyuni.kang@samsung.com>
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright © 2004-2008 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ * Adam Jackson (ajax@redhat.com)
+ * Peter Hutterer (peter.hutterer@redhat.com)
+ * Oliver McFadden (oliver.mcfadden@nokia.com)
+ */
+
+#ifdef _F_EVDEV_SUPPORT_SMARTRC_
+ #ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <evdev.h>
+#include <evdev-properties.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <exevents.h>
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <X11/Xatom.h>
+
+#define ABS(x) (((x) < 0) ? -(x) : (x))
+#define XI_PROP_TOUCH_ON "Evdev SmartRC Moved"
+#define XI_PROP_SMARTRC_DISCANCE_MOVED "Evdev SmartRC Distance Moved"
+#define XI_PROP_START_CALCULATE_DISTANCE "Start Calcualting Distance"
+
+#define IF_KEY_CODE_TOUCH (ev->code == BTN_EXTRA || ev->code == BTN_SIDE)
+#define IF_NOT_KEY_CODE_TOUCH (ev->code != BTN_EXTRA && ev->code != BTN_SIDE)
+
+static Atom atomDistanceMoved;
+static Atom atomCalculateDistance;
+static Atom prop_move_start;
+static int calculateDistance=0;
+#define INITIAL_CURSOR_DISTANCE_TO_MOVE 0
+
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+static InputInfoPtr pSmartRCKbdDeviceInfo = NULL;
+#endif
+extern int block_motion_device;
+
+enum device_state
+{
+ STATE_NONE=0,
+ STATE_NORMAL,
+ RC_STATE_DR_KEY,
+ RC_STATE_AIR_TOUCH
+};
+
+enum abs_move_state
+{
+ ABS_MOVE_END=0,
+ ABS_MOVE_ON,
+ ABS_MOVE_START
+};
+
+enum scroll_direction_state
+{
+ SCROLL_NONE=0,
+ SCROLL_VERTICAL,
+ SCROLL_HORIZEN
+};
+
+static void EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead);
+static void EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead);
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev);
+#else
+static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
+#endif
+int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev);
+int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev);
+void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev);
+int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary);
+int EvdevRCIsSwipe(struct input_event *ev);
+void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value);
+int EvdevRCIsBoundary(struct input_event *ev, int rc_range);
+static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
+ XIPropertyValuePtr val, BOOL checkonly);
+
+typedef struct _tagRCState
+{
+ int velocity;
+ int velo_time;
+ int move_state;
+ BOOL is_touch_on;
+ BOOL isSmartRC_15;
+ Atom atomTouchOn;
+}RCState, *RCStatePtr;
+
+RCState rcstate;
+
+static void
+EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+ InputInfoPtr pInfo = (InputInfoPtr)data;
+ int rc;
+
+ RemoveBlockAndWakeupHandlers(EvdevRCBlockHandler,
+ (WakeupHandlerProcPtr)NoopDDA,
+ data);
+
+ ErrorF("15 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on);
+
+ if (rcstate.is_touch_on == TRUE)
+ {
+ rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8,
+ PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
+
+ // In case of 2015 smartRC, cursor is enable when touch on device. (prop_move_start is set to "1")
+ if (block_motion_device == 0)
+ rc = XIChangeDeviceProperty(pInfo->dev, prop_move_start, XA_INTEGER, 8,
+ PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
+ }
+ else
+ rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE);
+
+ if (rc != Success)
+ {
+ xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn);
+ }
+}
+
+static void
+EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+ InputInfoPtr pInfo = (InputInfoPtr)data;
+ int rc;
+
+ RemoveBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014,
+ (WakeupHandlerProcPtr)NoopDDA,
+ data);
+
+ ErrorF("14 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on);
+
+ if (rcstate.is_touch_on == TRUE)
+ {
+ rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8,
+ PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
+ }
+ else
+ rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE);
+
+ if (rc != Success)
+ {
+ xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn);
+ }
+}
+
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev)
+#else
+static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
+#endif
+{
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+ InputInfoPtr pInfo = *ppInfo;
+#endif
+ EvdevPtr pEvdev = pInfo->private;
+ int res = 0;
+ // Start of Coord Cal
+ static int mismatchX = 0, mismatchY = 0;
+
+ if( rcstate.isSmartRC_15 == TRUE && ev->type == EV_ABS )
+ {
+ if(ev->code == ABS_X)
+ {
+ int calX = ev->value - pInfo->dev->spriteInfo->sprite->hot.x;
+ if(calX == 0)
+ {
+ mismatchX = 0;
+ return 0;
+ }
+ if(++mismatchX < 10)
+ {
+ return 0;
+ }
+ mismatchX = 0;
+ ev->type = EV_REL;
+ ev->code = REL_X;
+ ev->value = calX;
+ }
+ if(ev->code == ABS_Y)
+ {
+ int calY = ev->value - pInfo->dev->spriteInfo->sprite->hot.y;
+ if(calY == 0)
+ {
+ mismatchY = 0;
+ return 0;
+ }
+ if(++mismatchY < 10)
+ {
+ return 0;
+ }
+ mismatchY = 0;
+ ev->type = EV_REL;
+ ev->code = REL_Y;
+ ev->value = calY;
+ }
+ }
+ // End of Coord Cal
+
+ if (pEvdev->rel_move_ack == 3 || block_motion_device == 1)
+ {
+ if (ev->type == EV_REL || ev->type == EV_ABS)
+ {
+ return res;
+ }
+ if (ev->type == EV_KEY && ev->code == BTN_LEFT)
+ {
+ ev->code = KEY_ENTER;
+ }
+ }
+
+ if (ev->type == EV_KEY && ev->code == BTN_EXTRA)
+ {
+ if (ev->value == 0)
+ {
+ rcstate.move_state = ABS_MOVE_END;
+ rcstate.is_touch_on = FALSE;
+ rcstate.isSmartRC_15 = FALSE;
+ }
+ else if (ev->value == 1)
+ {
+ rcstate.move_state = ABS_MOVE_ON;
+ rcstate.is_touch_on = TRUE;
+ rcstate.isSmartRC_15 = TRUE;
+ }
+ OsBlockSIGIO();
+ RegisterBlockAndWakeupHandlers(EvdevRCBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
+ OsReleaseSIGIO();
+ }
+ else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN)
+ {
+ rcstate.move_state = ABS_MOVE_START;
+ }
+
+
+ if (ev->type == EV_KEY && ev->code == BTN_SIDE)
+ {
+ if (ev->value == 0)
+ {
+ rcstate.move_state = ABS_MOVE_END;
+ rcstate.is_touch_on = FALSE;
+ }
+ else if (ev->value == 1)
+ {
+ rcstate.move_state = ABS_MOVE_ON;
+ rcstate.is_touch_on = TRUE;
+ }
+ OsBlockSIGIO();
+ RegisterBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014 ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
+ OsReleaseSIGIO();
+ }
+ else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN)
+ {
+ rcstate.move_state = ABS_MOVE_START;
+ }
+
+ switch (pEvdev->rc_state)
+ {
+ case STATE_NORMAL:
+ res = EvdevRCProcessNormalState(pInfo, ev);
+ break;
+ case RC_STATE_DR_KEY:
+ res = EvdevRCProcessDRKeyState(pInfo, ev);
+ break;
+ case RC_STATE_AIR_TOUCH:
+ res = EvdevRCProcessAirTouchState(pInfo, ev, 1);
+ break;
+ default:
+ break;
+ }
+
+ if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
+ return 0;
+ else
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+ {
+ if (pEvdev->rc_state == RC_STATE_DR_KEY)
+ {
+ if(pSmartRCKbdDeviceInfo) *ppInfo = pSmartRCKbdDeviceInfo;
+ }
+ }
+#endif
+ return res;
+}
+
+int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev)
+{
+ EvdevPtr pEvdev = pInfo->private;
+ int res = 0;
+
+ if (ev->type == EV_REL || ev->type == EV_ABS)
+ return res;
+
+ if (ev->type == EV_KEY)
+ {
+ if (IF_KEY_CODE_TOUCH && ev->value == 1)
+ {
+ pEvdev->rc_state = RC_STATE_AIR_TOUCH;
+ res = EvdevRCProcessAirTouchState(pInfo, ev, 1);
+ }
+ else if ( (ev->code == KEY_UP || ev->code == KEY_LEFT || ev->code == KEY_DOWN || ev->code == KEY_RIGHT || ev->code == KEY_ENTER)
+ && (ev->value == 1))
+ {
+ pEvdev->rc_state = RC_STATE_DR_KEY;
+ res = EvdevRCProcessDRKeyState(pInfo, ev);
+ }
+ else if (IF_KEY_CODE_TOUCH && ev->value == 0)
+ {
+ return res;
+ }
+ else
+ res = 1;
+ }
+ else
+ res = 1;
+
+ return res;
+}
+
+int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev)
+{
+ EvdevPtr pEvdev = pInfo->private;
+ int res = 0;
+ static int pressed_flag = 0;
+ static BOOL extra_pressed = FALSE;
+ static int last_key = -1;
+
+ if (ev->type == EV_KEY && ev->code == BTN_LEFT)
+ {
+ ev->code = KEY_ENTER;
+ }
+
+ if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH)
+ {
+ if ( (last_key >= 0) && (ev->code != last_key))
+ {
+ return res;
+ }
+ if (ev->value == 1) {
+ pressed_flag++;
+ last_key = ev->code;
+ }
+ else {
+ pressed_flag--;
+ last_key = -1;
+ if (pressed_flag<0)
+ pressed_flag = 0;
+ }
+ }
+ else if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
+ {
+ if (pressed_flag == 0)
+ {
+ res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
+ extra_pressed = FALSE;
+ }
+ else if (ev->value == 1)
+ {
+ extra_pressed = TRUE;
+ }
+ else
+ {
+ extra_pressed = FALSE;
+ }
+ }
+ if (extra_pressed == TRUE && (ev->type == EV_REL || ev->type == EV_ABS))
+ {
+ return res;
+ }
+
+ if ((pressed_flag==0) && block_motion_device == 0)
+ {
+ if (rcstate.isSmartRC_15 == TRUE)
+ {
+ pEvdev->rc_state = RC_STATE_AIR_TOUCH;
+ res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
+ return res;
+ }
+ else
+ {
+ // calculate distance to change air touch mode(2014 smartRC)
+ if(EvdevRCIsBoundary(ev, 150))
+ {
+ pEvdev->rc_state = RC_STATE_AIR_TOUCH;
+ res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
+ return res;
+ }
+ }
+ }
+
+ if (ev->type == EV_REL || ev->type == EV_ABS)
+ {
+ return res;
+ }
+ else
+ res = 1;
+
+ return res;
+
+}
+
+int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary)
+{
+ EvdevPtr pEvdev = pInfo->private;
+ int res = 0;
+ int rc;
+ int temp_res;
+
+ if( calculateDistance && EvdevRCIsBoundary(ev, INITIAL_CURSOR_DISTANCE_TO_MOVE))
+ {
+ rc = XIChangeDeviceProperty(pInfo->dev, atomDistanceMoved, XA_INTEGER, 8,
+ PropModeReplace, 1, &pEvdev->rel_move_status, TRUE);
+ if (rc != Success)
+ ErrorF("[EvdevRCProcessAirTouchState] Failed to change atomDistanceMoved\n");
+ calculateDistance=0;
+ }
+
+ if (ev->type == EV_KEY && (IF_NOT_KEY_CODE_TOUCH && ev->code != BTN_LEFT))
+ return res;
+
+ if (ev->type == EV_REL && (ev->code == REL_HWHEEL || ev->code == REL_WHEEL))
+ {
+ res = 1;
+ return res;
+ }
+
+ if (ev->type == EV_ABS || (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) || ev->type == EV_SYN)
+ {
+ EvdevRCWheelScroll(pInfo, ev);
+ }
+
+ if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH && ev->value == 0)
+ {
+ temp_res = EvdevRCIsBoundary(ev, 0);
+ if (pEvdev->rc_state != RC_STATE_DR_KEY)
+ pEvdev->rc_state = STATE_NORMAL;
+ if (temp_res == 1)
+ res = temp_res;
+ return res;
+ }
+ else if (check_boundary && ev->type == EV_REL)
+ {
+ if (!EvdevRCIsBoundary(ev, 0))
+ return res;
+ else
+ {
+ if (block_motion_device == 0)
+ pEvdev->rc_state = RC_STATE_AIR_TOUCH;
+ }
+ }
+
+ res = 1;
+
+ return res;
+}
+
+void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev)
+{
+ static int before_x=-1, before_y=-1;
+ static int before_x_utime = -1, before_y_utime = -1;
+ static int before_x_time = -1, before_y_time = -1;
+
+ int time_diff = 0;
+ float velo_x=0;
+
+ float velo_y = 0;
+ static int velo_y_count=0, velo_x_count = 0;
+
+ static int wheel_direction_flag = SCROLL_NONE;
+
+ if (ev->type == EV_REL || ev->type == EV_SYN)
+ return;
+ if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH)
+ return;
+
+ if (ev->type == EV_KEY)
+ wheel_direction_flag = SCROLL_NONE;
+
+ if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_ABS)
+ {
+ velo_y_count=0;
+ if (ev->code == ABS_X)
+ {
+ before_x = ev->value;
+ before_x_time = ev->time.tv_sec;
+ before_x_utime = ev->time.tv_usec;
+
+ if ((before_x < 150) || (350 < before_x))
+ {
+ wheel_direction_flag = SCROLL_HORIZEN;
+ }
+ return;
+ }
+ else if (ev->code == ABS_Y)
+ {
+ before_y = ev->value;
+ before_y_time = ev->time.tv_sec;
+ before_y_utime = ev->time.tv_usec;
+
+ if ((before_y < 150) || (350 < before_y))
+ {
+ wheel_direction_flag = SCROLL_VERTICAL;
+ }
+ return;
+ }
+ }
+
+ if (ev->type == EV_ABS && ev->code == ABS_X && wheel_direction_flag != SCROLL_VERTICAL)
+ {
+ time_diff = (ev->time.tv_sec - before_x_time) * 1000 + (ev->time.tv_usec - before_x_utime)/1000;
+ if (time_diff == 0)
+ {
+ ErrorF("before and current events had same event time...\n");
+ return;
+ }
+
+ velo_x = (float)((ABS(before_x - ev->value)) / time_diff);
+
+ if (velo_x > 1)
+ {
+ velo_x_count = velo_x_count + (int)velo_x;
+ }
+
+ if (velo_x_count > 2)
+ {
+ wheel_direction_flag = SCROLL_HORIZEN;
+ velo_x_count = (velo_x_count / 4);
+ if (velo_x_count > 2)
+ velo_x_count = velo_x_count * 2;
+
+ EvdevRCSendEvent(pInfo, EV_REL, REL_HWHEEL, ((before_x - ev->value) < 0)? -velo_x_count: velo_x_count);
+ velo_x_count = 0;
+ }
+
+ before_x = ev->value;
+ before_x_time = ev->time.tv_sec;
+ before_x_utime = ev->time.tv_usec;
+ }
+ else if (ev->type == EV_ABS && ev->code == ABS_Y && wheel_direction_flag != SCROLL_HORIZEN)
+ {
+ time_diff = (ev->time.tv_sec - before_y_time) * 1000 + (ev->time.tv_usec - before_y_utime)/1000;
+ if (time_diff == 0)
+ {
+ ErrorF("before and current events had same event time...\n");
+ return;
+ }
+ velo_y = (float)((ABS(before_y - ev->value)) / time_diff);
+
+ if (velo_y > 1)
+ {
+ velo_y_count = velo_y_count + (int)velo_y;
+ }
+
+ if (velo_y_count > 2)
+ {
+ wheel_direction_flag = SCROLL_VERTICAL;
+ velo_y_count = (velo_y_count / 4);
+ if (velo_y_count > 2)
+ velo_y_count = velo_y_count * 2;
+
+ EvdevRCSendEvent(pInfo, EV_REL, REL_WHEEL, ((before_y - ev->value) < 0)? -velo_y_count: velo_y_count);
+ velo_y_count = 0;
+ }
+
+ before_y = ev->value;
+ before_y_time = ev->time.tv_sec;
+ before_y_utime = ev->time.tv_usec;
+ }
+}
+
+int EvdevRCIsSwipe(struct input_event *ev)
+{
+ int res = 0;
+ static int base_point_x = -1;
+ static int base_point_y = -1;
+
+ if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
+ {
+ base_point_x = -1;
+ base_point_y = -1;
+ }
+
+ if (ev->type == EV_ABS)
+ {
+ if (ev->code == ABS_X)
+ {
+ if (base_point_x == -1)
+ {
+ base_point_x = ev->value;
+ }
+ else if (ABS(base_point_x - ev->value) > 300)
+ {
+ res = 1;
+ }
+ }
+ else if (ev->code == ABS_Y)
+ {
+ if (base_point_y == -1)
+ {
+ base_point_y = ev->value;
+ }
+ else if (ABS(base_point_y - ev->value) > 300)
+ {
+ res = 1;
+ }
+ }
+ }
+
+ return res;
+}
+
+void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value)
+{
+ EvdevPtr pEvdev = pInfo->private;
+ struct input_event ev;
+
+ ev.type = type;
+ ev.code = code;
+ ev.value = value;
+
+ pEvdev->origin_input_process(pInfo, &ev);
+}
+
+static int
+EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ EvdevPtr pEvdev = pInfo->private;
+
+ if (atom == atomCalculateDistance )
+ {
+ calculateDistance=1;
+ }
+ return 0;
+}
+int EvdevRCIsBoundary(struct input_event *ev, int rc_range)
+{
+ static int x_diff=0, y_diff = 0;
+ int res = 0;
+
+ if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
+ {
+ x_diff = y_diff = 0;
+ }
+
+ if (ev->type == EV_REL)
+ {
+ if (ev->code == REL_X)
+ x_diff = x_diff + ev->value;
+ if (ev->code == REL_Y)
+ y_diff = y_diff + ev->value;
+ }
+
+ if ((ABS(x_diff) > rc_range) || (ABS(y_diff) > rc_range))
+ {
+ res = 1;
+ }
+ return res;
+}
+
+void EvdevRCInit(DeviceIntPtr device)
+{
+ InputInfoPtr pInfo;
+ EvdevPtr pEvdev;
+
+ pInfo = device->public.devicePrivate;
+ pEvdev = pInfo->private;
+
+ if (pEvdev->flags & EVDEV_SMART_RC)
+ {
+ ErrorF("[%s] id: %d, smart rc... hook \n", __FUNCTION__, device->id);
+ pEvdev->extra_input_process = EvdevRCProcessEvent;
+ pEvdev->rc_state = STATE_NORMAL;
+ rcstate.velocity = 3;
+ rcstate.atomTouchOn = MakeAtom(XI_PROP_TOUCH_ON, strlen(XI_PROP_TOUCH_ON), TRUE);
+ atomDistanceMoved = MakeAtom(XI_PROP_SMARTRC_DISCANCE_MOVED,strlen(XI_PROP_SMARTRC_DISCANCE_MOVED), TRUE);
+ atomCalculateDistance= MakeAtom(XI_PROP_START_CALCULATE_DISTANCE,strlen(XI_PROP_START_CALCULATE_DISTANCE), TRUE);
+ prop_move_start = MakeAtom(XI_PROP_REL_MOVE_STATUS, strlen(XI_PROP_REL_MOVE_STATUS), TRUE);
+ }
+#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
+ else
+ {
+ if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE))) pSmartRCKbdDeviceInfo = pInfo;
+ }
+#endif
+ XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
+ return;
+}
+#endif //_F_EVDEV_SUPPORT_SMARTRC_
\ No newline at end of file