summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@no.no.james.local>2015-12-28 11:06:03 (GMT)
committer root <root@no.no.james.local>2015-12-28 11:06:03 (GMT)
commit5a84d0ece0af652f3453088e1b2524c36730dff7 (patch)
treed5d3ec766db6002d876c468d7d18132f469cb719
downloadxorg-input-kobomultitouch-pq-5a84d0ece0af652f3453088e1b2524c36730dff7.zip
xorg-input-kobomultitouch-pq-5a84d0ece0af652f3453088e1b2524c36730dff7.tar.gz
xorg-input-kobomultitouch-pq-5a84d0ece0af652f3453088e1b2524c36730dff7.tar.bz2
first commitHEADmaster
-rw-r--r--master/jmm-fix-racy-zforce-driver204
-rw-r--r--master/marek-010e9b62eabfed042f35b72e8fa510df2dd7f679181
-rw-r--r--master/marek-15901bb725ac072ca24569a27d8086924bf2888b168
-rw-r--r--master/marek-56db7c190af3cc7a9eca276a31a0efb58f106f7d833
-rw-r--r--master/marek-d81b0fcb81100cd01728040529e90a21da5e189c134
-rw-r--r--master/marek-e96436b2a69bf3f8e9f85c5dd4acfd203286561e65
-rw-r--r--master/marek-f198907e2b4dda2b548baf557b32d94c1f5e7a1a281
-rw-r--r--master/series7
-rw-r--r--master/status0
9 files changed, 1873 insertions, 0 deletions
diff --git a/master/jmm-fix-racy-zforce-driver b/master/jmm-fix-racy-zforce-driver
new file mode 100644
index 0000000..1873acb
--- /dev/null
+++ b/master/jmm-fix-racy-zforce-driver
@@ -0,0 +1,204 @@
+diff --git a/driver/kobomultitouch_drv.c b/driver/kobomultitouch_drv.c
+index 1dbdb9d..8e39c53 100644
+--- a/driver/kobomultitouch_drv.c
++++ b/driver/kobomultitouch_drv.c
+@@ -19,6 +19,14 @@
+ *
+ **************************************************************************/
+
++/* The zforce driver deactivates the touch screen some time after close() */
++/* and doesn't check for an open that might have occured mean while */
++/* thus leaving the device dead in the water */
++/* define this to open and close the device only once, discarding packets */
++/* when the Xserver doesn't want them */
++
++#define DRIVER_IS_RACY
++
+ #include "gestures.h"
+
+ #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+@@ -38,6 +46,14 @@ static const float hswipe_fraction = 0.25;
+ static const float scale_fraction = 0.05;
+ static const float rot_fraction = 0.05;
+
++struct Private {
++ struct MTouch *mt;
++ int on;
++ void *input_handler;
++};
++
++static void read_input(LocalDevicePtr local);
++
+ /* button mapping simplified */
+ #define PROPMAP(m, x, y) m[x] = XIGetKnownProperty(y)
+
+@@ -86,9 +102,18 @@ static void initButtonLabels(Atom map[DIM_BUTTON])
+ }
+ #endif
+
++static void read_input_handler(int fd, pointer data)
++{
++ LocalDevicePtr local = (LocalDevicePtr) data;
++ struct Private *priv = local->private;
++
++ read_input(local);
++}
++
+ static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
+ {
+- struct MTouch *mt = local->private;
++ struct Private *priv = local->private;
++ struct MTouch *mt = priv->mt;
+ unsigned char btmap[DIM_BUTTON + 1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ };
+@@ -107,7 +132,17 @@ static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
+ xf86Msg(X_ERROR, "kobomultitouch: cannot configure device\n");
+ return !Success;
+ }
++#ifndef DRIVER_IS_RACY
+ xf86CloseSerial(local->fd);
++#else
++ if (open_mtouch(mt, local->fd)) {
++ xf86Msg(X_ERROR, "kobomultitouch: cannot grab device\n");
++ return !Success;
++ }
++
++ priv->on = 0;
++ priv->input_handler = xf86AddInputHandler(local->fd, read_input_handler, local);
++#endif
+
+ #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+ InitPointerDeviceStruct((DevicePtr)dev,
+@@ -164,7 +199,10 @@ static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
+
+ static int device_on(LocalDevicePtr local)
+ {
+- struct MTouch *mt = local->private;
++ struct Private *priv = local->private;
++ struct MTouch *mt = priv->mt;
++
++#ifndef DRIVER_IS_RACY
+ local->fd = xf86OpenSerial(local->options);
+ if (local->fd < 0) {
+ xf86Msg(X_ERROR, "kobomultitouch: cannot open device\n");
+@@ -175,16 +213,26 @@ static int device_on(LocalDevicePtr local)
+ return !Success;
+ }
+ xf86AddEnabledDevice(local);
++#else
++ priv->on = 1;
++#endif
+ return Success;
+ }
+
+ static int device_off(LocalDevicePtr local)
+ {
+- struct MTouch *mt = local->private;
++ struct Private *priv = local->private;
++ struct MTouch *mt = priv->mt;
++
++#ifndef DRIVER_IS_RACY
+ xf86RemoveEnabledDevice(local);
+ if (close_mtouch(mt, local->fd))
+ xf86Msg(X_WARNING, "kobomultitouch: cannot ungrab device\n");
+ xf86CloseSerial(local->fd);
++#else
++ priv->on = 0;
++#endif
++
+ return Success;
+ }
+
+@@ -281,7 +329,8 @@ static void handle_gestures(LocalDevicePtr local,
+ static void read_input(LocalDevicePtr local)
+ {
+ struct Gestures gs;
+- struct MTouch *mt = local->private;
++ struct Private *priv = local->private;
++ struct MTouch *mt = priv->mt;
+
+ //while (read_packet(mt, local->fd) > 0) {
+ // extract_gestures(&gs, mt);
+@@ -292,6 +341,7 @@ static void read_input(LocalDevicePtr local)
+ // handle_gestures(local, &gs, &mt->caps);
+ //}
+ while (read_packet(mt, local->fd) > 0) {
++ if (!priv->on) continue;
+ extract_mouse_gestures(&gs, mt);
+ handle_gestures(local, &gs, &mt->caps);
+ }
+@@ -324,12 +374,21 @@ static Bool device_control(DeviceIntPtr dev, int mode)
+ static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+ {
+ struct MTouch *mt;
++ struct Private *priv;
+
+ mt = calloc(1, sizeof(*mt));
+ if (!mt)
+ return BadAlloc;
+
+- pInfo->private = mt;
++ priv = calloc(1, sizeof(*priv));
++ if (!priv) {
++ free(mt);
++ return BadAlloc;
++ }
++
++ priv->mt = mt;
++
++ pInfo->private = priv;
+ pInfo->type_name = XI_TOUCHSCREEN;
+ pInfo->device_control = device_control;
+ pInfo->read_input = read_input;
+@@ -343,18 +402,26 @@ static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+ static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
+ {
+ struct MTouch *mt;
++ struct Private *priv;
+ InputInfoPtr local = xf86AllocateInput(drv, 0);
++
+ if (!local)
+ goto error;
+ mt = calloc(1, sizeof(struct MTouch));
+ if (!mt)
+ goto error;
++ priv = calloc(1, sizeof(*priv));
++ if (!priv) {
++ free(mt);
++ return BadAlloc;
++ }
++ priv->mt = mt;
+
+ local->name = dev->identifier;
+ local->type_name = XI_TOUCHSCREEN;
+ local->device_control = device_control;
+ local->read_input = read_input;
+- local->private = mt;
++ local->private = priv;
+ local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ local->conf_idev = dev;
+
+@@ -370,7 +437,21 @@ static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
+
+ static void uninit(InputDriverPtr drv, InputInfoPtr local, int flags)
+ {
+- free(local->private);
++ struct Private *priv = local->private;
++
++ xf86Msg(X_WARNING, "%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__);
++
++#ifdef DRIVER_IS_RACY
++ if (priv->input_handler) xf86RemoveInputHandler(priv->input_handler);
++
++ if (close_mtouch(priv->mt, local->fd))
++ xf86Msg(X_WARNING, "kobomultitouch: cannot ungrab device\n");
++
++ xf86CloseSerial(local->fd);
++#endif
++
++ if (priv) free(priv->mt);
++ free(priv);
+ local->private = 0;
+ xf86DeleteInput(local, 0);
+ }
diff --git a/master/marek-010e9b62eabfed042f35b72e8fa510df2dd7f679 b/master/marek-010e9b62eabfed042f35b72e8fa510df2dd7f679
new file mode 100644
index 0000000..9b411ae
--- /dev/null
+++ b/master/marek-010e9b62eabfed042f35b72e8fa510df2dd7f679
@@ -0,0 +1,181 @@
+diff --git a/driver/kobomultitouch_drv.c b/driver/kobomultitouch_drv.c
+index fca41b9..4a034c6 100644
+--- a/driver/kobomultitouch_drv.c
++++ b/driver/kobomultitouch_drv.c
+@@ -193,24 +193,25 @@ static int device_close(LocalDevicePtr local)
+ return Success;
+ }
+
+-static void tickle_button(LocalDevicePtr local, int id)
++static void tickle_button(LocalDevicePtr local, int id, int posx, int posy)
+ {
+- xf86PostButtonEvent(local->dev, FALSE, id, 1, 0, 0);
+- xf86PostButtonEvent(local->dev, FALSE, id, 0, 0, 0);
++ xf86PostMotionEvent(local->dev, 1, 0, 2, posx, posy);
++ xf86PostButtonEvent(local->dev, 1, id, 1, 0, 0);
++ xf86PostButtonEvent(local->dev, 1, id, 0, 0, 0);
+ }
+
+ static void button_scroll(LocalDevicePtr local,
+ int btdec, int btinc,
+ int *scroll, int step,
+- int delta)
++ int delta, int posx, int posy)
+ {
+ *scroll += delta;
+ while (*scroll > step) {
+- tickle_button(local, btinc);
++ tickle_button(local, btinc, posx, posy);
+ *scroll -= step;
+ }
+ while (*scroll < -step) {
+- tickle_button(local, btdec);
++ tickle_button(local, btdec, posx, posy);
+ *scroll += step;
+ }
+ }
+@@ -227,47 +228,49 @@ static void handle_gestures(LocalDevicePtr local,
+ vswipe = 0;
+ hswipe = 0;
+ }
+- foreach_bit(i, gs->btmask)
+- xf86PostButtonEvent(local->dev, FALSE,
++ foreach_bit(i, gs->btmask) {
++ xf86PostMotionEvent(local->dev, 1, 0, 2, gs->posx, gs->posy);
++ xf86PostButtonEvent(local->dev, 1,
+ i + 1, GETBIT(gs->btdata, i), 0, 0);
+- if (GETBIT(gs->type, GS_MOVE))
+- xf86PostMotionEvent(local->dev, 0, 0, 2, gs->dx, gs->dy);
+-
++ }
++ if (GETBIT(gs->type, GS_MOVE)) {
++ xf86PostMotionEvent(local->dev, 1, 0, 2, gs->posx, gs->posy);
++ }
+ if (GETBIT(gs->type, GS_VSCROLL)) {
+ int step = 1 + vscroll_fraction * get_cap_ysize(caps);
+- button_scroll(local, 4, 5, &vscroll, step, gs->dy);
++ button_scroll(local, 4, 5, &vscroll, step, gs->dy, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_HSCROLL)) {
+ int step = 1 + hscroll_fraction * get_cap_xsize(caps);
+- button_scroll(local, 6, 7, &hscroll, step, gs->dx);
++ button_scroll(local, 6, 7, &hscroll, step, gs->dx, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_VSWIPE)) {
+ int step = 1 + vswipe_fraction * get_cap_ysize(caps);
+- button_scroll(local, 8, 9, &vswipe, step, gs->dy);
++ button_scroll(local, 8, 9, &vswipe, step, gs->dy, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_HSWIPE)) {
+ int step = 1 + hswipe_fraction * get_cap_xsize(caps);
+- button_scroll(local, 10, 11, &hswipe, step, gs->dx);
++ button_scroll(local, 10, 11, &hswipe, step, gs->dx, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_SCALE)) {
+ int step = 1 + scale_fraction * get_cap_xsize(caps);
+- button_scroll(local, 12, 13, &scale, step, gs->scale);
++ button_scroll(local, 12, 13, &scale, step, gs->scale, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_ROTATE)) {
+ int step = 1 + rot_fraction * get_cap_xsize(caps);
+- button_scroll(local, 14, 15, &rot, step, gs->rot);
++ button_scroll(local, 14, 15, &rot, step, gs->rot, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_TAP) && gs->ntap == 1) {
+ foreach_bit(i, gs->tapmask)
+- tickle_button(local, i + 1);
++ tickle_button(local, i + 1, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_VSWIPE4)) {
+ int step = 1 + vswipe_fraction * get_cap_ysize(caps);
+- button_scroll(local, 16, 17, &vswipe, step, gs->dy);
++ button_scroll(local, 16, 17, &vswipe, step, gs->dy, gs->posx, gs->posy);
+ }
+ if (GETBIT(gs->type, GS_HSWIPE4)) {
+ int step = 1 + hswipe_fraction * get_cap_xsize(caps);
+- button_scroll(local, 18, 19, &hswipe, step, gs->dx);
++ button_scroll(local, 18, 19, &hswipe, step, gs->dx, gs->posx, gs->posy);
+ }
+ }
+
+@@ -319,7 +322,7 @@ static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+ return BadAlloc;
+
+ pInfo->private = mt;
+- pInfo->type_name = XI_TOUCHPAD;
++ pInfo->type_name = XI_TOUCHSCREEN;
+ pInfo->device_control = device_control;
+ pInfo->read_input = read_input;
+ pInfo->switch_mode = 0;
+@@ -340,7 +343,7 @@ static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
+ goto error;
+
+ local->name = dev->identifier;
+- local->type_name = XI_TOUCHPAD;
++ local->type_name = XI_TOUCHSCREEN;
+ local->device_control = device_control;
+ local->read_input = read_input;
+ local->private = mt;
+diff --git a/include/gestures.h b/include/gestures.h
+index b512121..659c95a 100644
+--- a/include/gestures.h
++++ b/include/gestures.h
+@@ -38,7 +38,7 @@
+
+ struct Gestures {
+ bitmask_t type, btmask, btdata;
+- int same_fingers, dx, dy, scale, rot;
++ int same_fingers, posx, posy, dx, dy, scale, rot;
+ bitmask_t tapmask;
+ int ntap;
+ };
+diff --git a/src/gestures.c b/src/gestures.c
+index cc95e9b..cbc5ac6 100644
+--- a/src/gestures.c
++++ b/src/gestures.c
+@@ -82,7 +82,6 @@ static void extract_movement(struct Gestures *gs, struct MTouch* mt)
+ float move, xmove = 0, ymove = 0;
+ float rad, rad2 = 0, scale = 0, rot = 0;
+
+-
+ if (!nmove || nmove != npoint)
+ return;
+
+@@ -182,9 +181,15 @@ static void extract_movement(struct Gestures *gs, struct MTouch* mt)
+ void extract_gestures(struct Gestures *gs, struct MTouch* mt)
+ {
+ memset(gs, 0, sizeof(struct Gestures));
++
++ gs->posx = mt->state.finger[0].position_x;
++ gs->posy = mt->state.finger[0].position_y;
++
+ gs->same_fingers = mt->mem.same;
++
+ extract_buttons(gs, mt);
+ extract_movement(gs, mt);
++
+ mt->prev_state = mt->state;
+ }
+
+@@ -201,6 +206,9 @@ void extract_delayed_gestures(struct Gestures *gs, struct MTouch* mt)
+ memset(gs, 0, sizeof(struct Gestures));
+ mt->mem.wait = 0;
+
++ gs->posx = mt->state.finger[0].position_x;
++ gs->posy = mt->state.finger[0].position_y;
++
+ if (mt->mem.tpdown < mt->mem.tpup) {
+ switch (mt->mem.maxtap) {
+ case 1:
+@@ -227,8 +235,10 @@ void output_gesture(const struct Gestures *gs)
+ foreach_bit(i, gs->btmask)
+ xf86Msg(X_INFO, "button bit: %d %d\n",
+ i, GETBIT(gs->btdata, i));
+- if (GETBIT(gs->type, GS_MOVE))
++ if (GETBIT(gs->type, GS_MOVE)) {
++ xf86Msg(X_INFO, "position: %d %d\n", gs->posx, gs->posy);
+ xf86Msg(X_INFO, "motion: %d %d\n", gs->dx, gs->dy);
++ }
+ if (GETBIT(gs->type, GS_VSCROLL))
+ xf86Msg(X_INFO, "vscroll: %d\n", gs->dy);
+ if (GETBIT(gs->type, GS_HSCROLL))
diff --git a/master/marek-15901bb725ac072ca24569a27d8086924bf2888b b/master/marek-15901bb725ac072ca24569a27d8086924bf2888b
new file mode 100644
index 0000000..26c418d
--- /dev/null
+++ b/master/marek-15901bb725ac072ca24569a27d8086924bf2888b
@@ -0,0 +1,168 @@
+diff --git a/driver/kobomultitouch_drv.c b/driver/kobomultitouch_drv.c
+index 4a034c6..bca2b51 100644
+--- a/driver/kobomultitouch_drv.c
++++ b/driver/kobomultitouch_drv.c
+@@ -279,12 +279,17 @@ static void read_input(LocalDevicePtr local)
+ {
+ struct Gestures gs;
+ struct MTouch *mt = local->private;
++
++ //while (read_packet(mt, local->fd) > 0) {
++ // extract_gestures(&gs, mt);
++ // handle_gestures(local, &gs, &mt->caps);
++ //}
++ //if (has_delayed_gestures(mt, local->fd)) {
++ // extract_delayed_gestures(&gs, mt);
++ // handle_gestures(local, &gs, &mt->caps);
++ //}
+ while (read_packet(mt, local->fd) > 0) {
+- extract_gestures(&gs, mt);
+- handle_gestures(local, &gs, &mt->caps);
+- }
+- if (has_delayed_gestures(mt, local->fd)) {
+- extract_delayed_gestures(&gs, mt);
++ extract_mouse_gestures(&gs, mt);
+ handle_gestures(local, &gs, &mt->caps);
+ }
+ }
+diff --git a/include/gestures.h b/include/gestures.h
+index 659c95a..1ef2176 100644
+--- a/include/gestures.h
++++ b/include/gestures.h
+@@ -44,6 +44,7 @@ struct Gestures {
+ };
+
+ void extract_gestures(struct Gestures *gs, struct MTouch* mt);
++void extract_mouse_gestures(struct Gestures *gs, struct MTouch* mt);
+ void extract_delayed_gestures(struct Gestures *gs, struct MTouch* mt);
+ void output_gesture(const struct Gestures *gs);
+
+diff --git a/src/gestures.c b/src/gestures.c
+index cbc5ac6..bf19bdf 100644
+--- a/src/gestures.c
++++ b/src/gestures.c
+@@ -29,6 +29,51 @@ static const int FINGER_THUMB_MS = 600;
+ static const int BUTTON_HOLD_MS = 200;
+
+ /**
++ *
++ * Extract mouse gestures.
++ *
++ */
++void extract_mouse(struct Gestures *gs, struct MTouch* mt)
++{
++ int nmove = bitcount(mt->mem.moving);
++
++ if (GETBIT(mt->mem.added, 0)) {
++ // pressed first finger
++
++ // lmb pressed
++ gs->posx = mt->state.finger[0].position_x;
++ gs->posy = mt->state.finger[0].position_y;
++ SETBIT(gs->btmask, MT_BUTTON_LEFT);
++ SETBIT(gs->btdata, MT_BUTTON_LEFT);
++ mt->mem.btdata = BITMASK(MT_BUTTON_LEFT);
++
++ return;
++ }
++
++ if (GETBIT(mt->mem.btdata, MT_BUTTON_LEFT) && !GETBIT(mt->mem.fingers, 0)) {
++ // released first finger
++
++ // lmb released
++ gs->posx = mt->state.finger[0].position_x;
++ gs->posy = mt->state.finger[0].position_y;
++ SETBIT(gs->btmask, MT_BUTTON_LEFT);
++ CLEARBIT(gs->btdata, MT_BUTTON_LEFT);
++ mt->mem.btdata = 0;
++
++ return;
++ }
++
++ if (GETBIT(mt->mem.btdata, MT_BUTTON_LEFT)) {
++ if (nmove == 1) {
++ // mouse move
++ gs->posx = mt->state.finger[0].position_x;
++ gs->posy = mt->state.finger[0].position_y;
++ SETBIT(gs->type, GS_MOVE);
++ }
++ }
++}
++
++/**
+ * extract_buttons
+ *
+ * Set the button gesture.
+@@ -171,6 +216,25 @@ static void extract_movement(struct Gestures *gs, struct MTouch* mt)
+ }
+
+ /**
++ * extract_mouse_gestures
++ *
++ * Extract the mouse gestures.
++ *
++ * Reset memory after use.
++ *
++ */
++void extract_mouse_gestures(struct Gestures *gs, struct MTouch* mt)
++{
++ memset(gs, 0, sizeof(struct Gestures));
++
++ gs->same_fingers = mt->mem.same;
++
++ extract_mouse(gs, mt);
++
++ mt->prev_state = mt->state;
++}
++
++/**
+ * extract_gestures
+ *
+ * Extract the gestures.
+@@ -233,11 +297,10 @@ void output_gesture(const struct Gestures *gs)
+ {
+ int i;
+ foreach_bit(i, gs->btmask)
+- xf86Msg(X_INFO, "button bit: %d %d\n",
+- i, GETBIT(gs->btdata, i));
++ xf86Msg(X_INFO, "button bit: %d %d (pos: %d %d)\n",
++ i, GETBIT(gs->btdata, i), gs->posx, gs->posy);
+ if (GETBIT(gs->type, GS_MOVE)) {
+- xf86Msg(X_INFO, "position: %d %d\n", gs->posx, gs->posy);
+- xf86Msg(X_INFO, "motion: %d %d\n", gs->dx, gs->dy);
++ xf86Msg(X_INFO, "position: %d %d (motion: %d %d)\n", gs->posx, gs->posy, gs->dx, gs->dy);
+ }
+ if (GETBIT(gs->type, GS_VSCROLL))
+ xf86Msg(X_INFO, "vscroll: %d\n", gs->dy);
+@@ -253,4 +316,5 @@ void output_gesture(const struct Gestures *gs)
+ xf86Msg(X_INFO, "rotate: %d\n", gs->rot);
+ foreach_bit(i, gs->tapmask)
+ xf86Msg(X_INFO, "tap: %d %d\n", i, gs->ntap);
++ xf86Msg(X_INFO, "+");
+ }
+diff --git a/src/test.c b/src/test.c
+index 1b67986..5afa8b4 100644
+--- a/src/test.c
++++ b/src/test.c
+@@ -36,12 +36,16 @@ static void loop_device(int fd)
+ return;
+ }
+ while (!mtdev_idle(&mt.dev, fd, 5000)) {
++ //while (read_packet(&mt, fd) > 0) {
++ // extract_gestures(&gs, &mt);
++ // output_gesture(&gs);
++ //}
++ //if (has_delayed_gestures(&mt, fd)) {
++ // extract_delayed_gestures(&gs, &mt);
++ // output_gesture(&gs);
++ //}
+ while (read_packet(&mt, fd) > 0) {
+- extract_gestures(&gs, &mt);
+- output_gesture(&gs);
+- }
+- if (has_delayed_gestures(&mt, fd)) {
+- extract_delayed_gestures(&gs, &mt);
++ extract_mouse_gestures(&gs, &mt);
+ output_gesture(&gs);
+ }
+ }
diff --git a/master/marek-56db7c190af3cc7a9eca276a31a0efb58f106f7d b/master/marek-56db7c190af3cc7a9eca276a31a0efb58f106f7d
new file mode 100644
index 0000000..980b2ce
--- /dev/null
+++ b/master/marek-56db7c190af3cc7a9eca276a31a0efb58f106f7d
@@ -0,0 +1,833 @@
+diff --git a/Makefile b/Makefile
+index eb5d087..7efc80d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -2,13 +2,13 @@ VERSION = 1
+ PATCHLEVEL = 0
+ EXTRAVERSION = rc3
+
+-LIBRARY = multitouch.so
++LIBRARY = kobomultitouch_drv.so
+ MODULES = src
+ XMODULES = driver
+
+ o_src = capabilities hwstate mtstate memory mtouch gestures
+
+-o_driver= multitouch
++o_driver= kobomultitouch_drv
+
+ TARGETS += src/test
+
+@@ -57,7 +57,7 @@ clean:
+ rm -rf bin obj
+
+ distclean: clean
+- rm -rf debian/*.log debian/files debian/xf86-input-multitouch*
++ rm -rf debian/*.log debian/files debian/xf86-input-kobomultitouch*
+
+ install: $(TLIB)
+ install -d "$(DESTDIR)/$(DLIB)"
+diff --git a/driver/kobomultitouch_drv.c b/driver/kobomultitouch_drv.c
+new file mode 100644
+index 0000000..fca41b9
+--- /dev/null
++++ b/driver/kobomultitouch_drv.c
+@@ -0,0 +1,396 @@
++/***************************************************************************
++ *
++ * Multitouch X driver
++ * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ **************************************************************************/
++
++#include "gestures.h"
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
++#include <X11/Xatom.h>
++#include <xserver-properties.h>
++#endif
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
++typedef InputInfoPtr LocalDevicePtr;
++#endif
++
++/* these should be user-configurable at some point */
++static const float vscroll_fraction = 0.025;
++static const float hscroll_fraction = 0.05;
++static const float vswipe_fraction = 0.25;
++static const float hswipe_fraction = 0.25;
++static const float scale_fraction = 0.05;
++static const float rot_fraction = 0.05;
++
++/* button mapping simplified */
++#define PROPMAP(m, x, y) m[x] = XIGetKnownProperty(y)
++
++static void pointer_control(DeviceIntPtr dev, PtrCtrl *ctrl)
++{
++ xf86Msg(X_INFO, "pointer_control\n");
++}
++
++static int pointer_property(DeviceIntPtr dev,
++ Atom property,
++ XIPropertyValuePtr prop,
++ BOOL checkonly)
++{
++ xf86Msg(X_INFO, "pointer_property\n");
++ return Success;
++}
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
++static void initAxesLabels(Atom map[2])
++{
++ memset(map, 0, 2 * sizeof(Atom));
++ PROPMAP(map, 0, AXIS_LABEL_PROP_REL_X);
++ PROPMAP(map, 1, AXIS_LABEL_PROP_REL_Y);
++}
++
++static void initButtonLabels(Atom map[DIM_BUTTON])
++{
++ memset(map, 0, DIM_BUTTON * sizeof(Atom));
++ PROPMAP(map, MT_BUTTON_LEFT, BTN_LABEL_PROP_BTN_LEFT);
++ PROPMAP(map, MT_BUTTON_MIDDLE, BTN_LABEL_PROP_BTN_MIDDLE);
++ PROPMAP(map, MT_BUTTON_RIGHT, BTN_LABEL_PROP_BTN_RIGHT);
++ PROPMAP(map, MT_BUTTON_WHEEL_UP, BTN_LABEL_PROP_BTN_WHEEL_UP);
++ PROPMAP(map, MT_BUTTON_WHEEL_DOWN, BTN_LABEL_PROP_BTN_WHEEL_DOWN);
++ PROPMAP(map, MT_BUTTON_HWHEEL_LEFT, BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
++ PROPMAP(map, MT_BUTTON_HWHEEL_RIGHT, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
++ /* how to map swipe buttons? */
++ PROPMAP(map, MT_BUTTON_SWIPE_UP, BTN_LABEL_PROP_BTN_0);
++ PROPMAP(map, MT_BUTTON_SWIPE_DOWN, BTN_LABEL_PROP_BTN_1);
++ PROPMAP(map, MT_BUTTON_SWIPE_LEFT, BTN_LABEL_PROP_BTN_2);
++ PROPMAP(map, MT_BUTTON_SWIPE_RIGHT, BTN_LABEL_PROP_BTN_3);
++ /* how to map scale and rotate? */
++ PROPMAP(map, MT_BUTTON_SCALE_DOWN, BTN_LABEL_PROP_BTN_4);
++ PROPMAP(map, MT_BUTTON_SCALE_UP, BTN_LABEL_PROP_BTN_5);
++ PROPMAP(map, MT_BUTTON_ROTATE_LEFT, BTN_LABEL_PROP_BTN_6);
++ PROPMAP(map, MT_BUTTON_ROTATE_RIGHT, BTN_LABEL_PROP_BTN_7);
++}
++#endif
++
++static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
++{
++ struct MTouch *mt = local->private;
++ unsigned char btmap[DIM_BUTTON + 1] = {
++ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
++ };
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
++ Atom axes_labels[2], btn_labels[DIM_BUTTON];
++ initAxesLabels(axes_labels);
++ initButtonLabels(btn_labels);
++#endif
++
++ local->fd = xf86OpenSerial(local->options);
++ if (local->fd < 0) {
++ xf86Msg(X_ERROR, "kobomultitouch: cannot open device\n");
++ return !Success;
++ }
++ if (configure_mtouch(mt, local->fd)) {
++ xf86Msg(X_ERROR, "kobomultitouch: cannot configure device\n");
++ return !Success;
++ }
++ xf86CloseSerial(local->fd);
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
++ InitPointerDeviceStruct((DevicePtr)dev,
++ btmap, DIM_BUTTON,
++ GetMotionHistory,
++ pointer_control,
++ GetMotionHistorySize(),
++ 2);
++#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7
++ InitPointerDeviceStruct((DevicePtr)dev,
++ btmap, DIM_BUTTON,
++ pointer_control,
++ GetMotionHistorySize(),
++ 2);
++#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
++ InitPointerDeviceStruct((DevicePtr)dev,
++ btmap, DIM_BUTTON, btn_labels,
++ pointer_control,
++ GetMotionHistorySize(),
++ 2, axes_labels);
++#else
++#error "Unsupported ABI_XINPUT_VERSION"
++#endif
++
++ xf86InitValuatorAxisStruct(dev, 0,
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
++ axes_labels[0],
++#endif
++ mt->caps.abs[MTDEV_POSITION_X].minimum,
++ mt->caps.abs[MTDEV_POSITION_X].maximum,
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
++ 1, 0, 1, Absolute);
++#else
++ 1, 0, 1);
++#endif
++ xf86InitValuatorDefaults(dev, 0);
++ xf86InitValuatorAxisStruct(dev, 1,
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
++ axes_labels[1],
++#endif
++ mt->caps.abs[MTDEV_POSITION_Y].minimum,
++ mt->caps.abs[MTDEV_POSITION_Y].maximum,
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
++ 1, 0, 1, Absolute);
++#else
++ 1, 0, 1);
++#endif
++ xf86InitValuatorDefaults(dev, 1);
++
++ XIRegisterPropertyHandler(dev, pointer_property, NULL, NULL);
++
++ return Success;
++}
++
++static int device_on(LocalDevicePtr local)
++{
++ struct MTouch *mt = local->private;
++ local->fd = xf86OpenSerial(local->options);
++ if (local->fd < 0) {
++ xf86Msg(X_ERROR, "kobomultitouch: cannot open device\n");
++ return !Success;
++ }
++ if (open_mtouch(mt, local->fd)) {
++ xf86Msg(X_ERROR, "kobomultitouch: cannot grab device\n");
++ return !Success;
++ }
++ xf86AddEnabledDevice(local);
++ return Success;
++}
++
++static int device_off(LocalDevicePtr local)
++{
++ struct MTouch *mt = local->private;
++ xf86RemoveEnabledDevice(local);
++ if (close_mtouch(mt, local->fd))
++ xf86Msg(X_WARNING, "kobomultitouch: cannot ungrab device\n");
++ xf86CloseSerial(local->fd);
++ return Success;
++}
++
++static int device_close(LocalDevicePtr local)
++{
++ return Success;
++}
++
++static void tickle_button(LocalDevicePtr local, int id)
++{
++ xf86PostButtonEvent(local->dev, FALSE, id, 1, 0, 0);
++ xf86PostButtonEvent(local->dev, FALSE, id, 0, 0, 0);
++}
++
++static void button_scroll(LocalDevicePtr local,
++ int btdec, int btinc,
++ int *scroll, int step,
++ int delta)
++{
++ *scroll += delta;
++ while (*scroll > step) {
++ tickle_button(local, btinc);
++ *scroll -= step;
++ }
++ while (*scroll < -step) {
++ tickle_button(local, btdec);
++ *scroll += step;
++ }
++}
++
++static void handle_gestures(LocalDevicePtr local,
++ const struct Gestures *gs,
++ const struct Capabilities *caps)
++{
++ static int vscroll, hscroll, vswipe, hswipe, scale, rot;
++ int i;
++ if (!gs->same_fingers) {
++ vscroll = 0;
++ hscroll = 0;
++ vswipe = 0;
++ hswipe = 0;
++ }
++ foreach_bit(i, gs->btmask)
++ xf86PostButtonEvent(local->dev, FALSE,
++ i + 1, GETBIT(gs->btdata, i), 0, 0);
++ if (GETBIT(gs->type, GS_MOVE))
++ xf86PostMotionEvent(local->dev, 0, 0, 2, gs->dx, gs->dy);
++
++ if (GETBIT(gs->type, GS_VSCROLL)) {
++ int step = 1 + vscroll_fraction * get_cap_ysize(caps);
++ button_scroll(local, 4, 5, &vscroll, step, gs->dy);
++ }
++ if (GETBIT(gs->type, GS_HSCROLL)) {
++ int step = 1 + hscroll_fraction * get_cap_xsize(caps);
++ button_scroll(local, 6, 7, &hscroll, step, gs->dx);
++ }
++ if (GETBIT(gs->type, GS_VSWIPE)) {
++ int step = 1 + vswipe_fraction * get_cap_ysize(caps);
++ button_scroll(local, 8, 9, &vswipe, step, gs->dy);
++ }
++ if (GETBIT(gs->type, GS_HSWIPE)) {
++ int step = 1 + hswipe_fraction * get_cap_xsize(caps);
++ button_scroll(local, 10, 11, &hswipe, step, gs->dx);
++ }
++ if (GETBIT(gs->type, GS_SCALE)) {
++ int step = 1 + scale_fraction * get_cap_xsize(caps);
++ button_scroll(local, 12, 13, &scale, step, gs->scale);
++ }
++ if (GETBIT(gs->type, GS_ROTATE)) {
++ int step = 1 + rot_fraction * get_cap_xsize(caps);
++ button_scroll(local, 14, 15, &rot, step, gs->rot);
++ }
++ if (GETBIT(gs->type, GS_TAP) && gs->ntap == 1) {
++ foreach_bit(i, gs->tapmask)
++ tickle_button(local, i + 1);
++ }
++ if (GETBIT(gs->type, GS_VSWIPE4)) {
++ int step = 1 + vswipe_fraction * get_cap_ysize(caps);
++ button_scroll(local, 16, 17, &vswipe, step, gs->dy);
++ }
++ if (GETBIT(gs->type, GS_HSWIPE4)) {
++ int step = 1 + hswipe_fraction * get_cap_xsize(caps);
++ button_scroll(local, 18, 19, &hswipe, step, gs->dx);
++ }
++}
++
++/* called for each full received packet from the touchpad */
++static void read_input(LocalDevicePtr local)
++{
++ struct Gestures gs;
++ struct MTouch *mt = local->private;
++ while (read_packet(mt, local->fd) > 0) {
++ extract_gestures(&gs, mt);
++ handle_gestures(local, &gs, &mt->caps);
++ }
++ if (has_delayed_gestures(mt, local->fd)) {
++ extract_delayed_gestures(&gs, mt);
++ handle_gestures(local, &gs, &mt->caps);
++ }
++}
++
++static Bool device_control(DeviceIntPtr dev, int mode)
++{
++ LocalDevicePtr local = dev->public.devicePrivate;
++ switch (mode) {
++ case DEVICE_INIT:
++ xf86Msg(X_INFO, "device control: init\n");
++ return device_init(dev, local);
++ case DEVICE_ON:
++ xf86Msg(X_INFO, "device control: on\n");
++ return device_on(local);
++ case DEVICE_OFF:
++ xf86Msg(X_INFO, "device control: off\n");
++ return device_off(local);
++ case DEVICE_CLOSE:
++ xf86Msg(X_INFO, "device control: close\n");
++ return device_close(local);
++ default:
++ xf86Msg(X_INFO, "device control: default\n");
++ return BadValue;
++ }
++}
++
++
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
++static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
++{
++ struct MTouch *mt;
++
++ mt = calloc(1, sizeof(*mt));
++ if (!mt)
++ return BadAlloc;
++
++ pInfo->private = mt;
++ pInfo->type_name = XI_TOUCHPAD;
++ pInfo->device_control = device_control;
++ pInfo->read_input = read_input;
++ pInfo->switch_mode = 0;
++ //xf86CollectInputOptions(local, NULL);
++ //xf86ProcessCommonOptions(local, local->options);
++
++ return Success;
++}
++#else
++static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
++{
++ struct MTouch *mt;
++ InputInfoPtr local = xf86AllocateInput(drv, 0);
++ if (!local)
++ goto error;
++ mt = calloc(1, sizeof(struct MTouch));
++ if (!mt)
++ goto error;
++
++ local->name = dev->identifier;
++ local->type_name = XI_TOUCHPAD;
++ local->device_control = device_control;
++ local->read_input = read_input;
++ local->private = mt;
++ local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
++ local->conf_idev = dev;
++
++ xf86CollectInputOptions(local, NULL, NULL);
++ /* xf86OptionListReport(local->options); */
++ xf86ProcessCommonOptions(local, local->options);
++
++ local->flags |= XI86_CONFIGURED;
++ error:
++ return local;
++}
++#endif
++
++static void uninit(InputDriverPtr drv, InputInfoPtr local, int flags)
++{
++ free(local->private);
++ local->private = 0;
++ xf86DeleteInput(local, 0);
++}
++
++static InputDriverRec MULTITOUCH = {
++ 1,
++ "kobomultitouch",
++ NULL,
++ preinit,
++ uninit,
++ NULL,
++ 0
++};
++
++static XF86ModuleVersionInfo VERSION = {
++ "kobomultitouch",
++ MODULEVENDORSTRING,
++ MODINFOSTRING1,
++ MODINFOSTRING2,
++ XORG_VERSION_CURRENT,
++ 0, 1, 0,
++ ABI_CLASS_XINPUT,
++ ABI_XINPUT_VERSION,
++ MOD_CLASS_XINPUT,
++ {0, 0, 0, 0}
++};
++
++static pointer setup(pointer module, pointer options, int *errmaj, int *errmin)
++{
++ xf86AddInputDriver(&MULTITOUCH, module, 0);
++ return module;
++}
++
++XF86ModuleData kobomultitouchModuleData = {&VERSION, &setup, NULL };
+diff --git a/driver/multitouch.c b/driver/multitouch.c
+deleted file mode 100644
+index a083adc..0000000
+--- a/driver/multitouch.c
++++ /dev/null
+@@ -1,396 +0,0 @@
+-/***************************************************************************
+- *
+- * Multitouch X driver
+- * Copyright (C) 2008 Henrik Rydberg <rydberg@euromail.se>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+- *
+- **************************************************************************/
+-
+-#include "gestures.h"
+-
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+-#include <X11/Xatom.h>
+-#include <xserver-properties.h>
+-#endif
+-
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+-typedef InputInfoPtr LocalDevicePtr;
+-#endif
+-
+-/* these should be user-configurable at some point */
+-static const float vscroll_fraction = 0.025;
+-static const float hscroll_fraction = 0.05;
+-static const float vswipe_fraction = 0.25;
+-static const float hswipe_fraction = 0.25;
+-static const float scale_fraction = 0.05;
+-static const float rot_fraction = 0.05;
+-
+-/* button mapping simplified */
+-#define PROPMAP(m, x, y) m[x] = XIGetKnownProperty(y)
+-
+-static void pointer_control(DeviceIntPtr dev, PtrCtrl *ctrl)
+-{
+- xf86Msg(X_INFO, "pointer_control\n");
+-}
+-
+-static int pointer_property(DeviceIntPtr dev,
+- Atom property,
+- XIPropertyValuePtr prop,
+- BOOL checkonly)
+-{
+- xf86Msg(X_INFO, "pointer_property\n");
+- return Success;
+-}
+-
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+-static void initAxesLabels(Atom map[2])
+-{
+- memset(map, 0, 2 * sizeof(Atom));
+- PROPMAP(map, 0, AXIS_LABEL_PROP_REL_X);
+- PROPMAP(map, 1, AXIS_LABEL_PROP_REL_Y);
+-}
+-
+-static void initButtonLabels(Atom map[DIM_BUTTON])
+-{
+- memset(map, 0, DIM_BUTTON * sizeof(Atom));
+- PROPMAP(map, MT_BUTTON_LEFT, BTN_LABEL_PROP_BTN_LEFT);
+- PROPMAP(map, MT_BUTTON_MIDDLE, BTN_LABEL_PROP_BTN_MIDDLE);
+- PROPMAP(map, MT_BUTTON_RIGHT, BTN_LABEL_PROP_BTN_RIGHT);
+- PROPMAP(map, MT_BUTTON_WHEEL_UP, BTN_LABEL_PROP_BTN_WHEEL_UP);
+- PROPMAP(map, MT_BUTTON_WHEEL_DOWN, BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+- PROPMAP(map, MT_BUTTON_HWHEEL_LEFT, BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+- PROPMAP(map, MT_BUTTON_HWHEEL_RIGHT, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+- /* how to map swipe buttons? */
+- PROPMAP(map, MT_BUTTON_SWIPE_UP, BTN_LABEL_PROP_BTN_0);
+- PROPMAP(map, MT_BUTTON_SWIPE_DOWN, BTN_LABEL_PROP_BTN_1);
+- PROPMAP(map, MT_BUTTON_SWIPE_LEFT, BTN_LABEL_PROP_BTN_2);
+- PROPMAP(map, MT_BUTTON_SWIPE_RIGHT, BTN_LABEL_PROP_BTN_3);
+- /* how to map scale and rotate? */
+- PROPMAP(map, MT_BUTTON_SCALE_DOWN, BTN_LABEL_PROP_BTN_4);
+- PROPMAP(map, MT_BUTTON_SCALE_UP, BTN_LABEL_PROP_BTN_5);
+- PROPMAP(map, MT_BUTTON_ROTATE_LEFT, BTN_LABEL_PROP_BTN_6);
+- PROPMAP(map, MT_BUTTON_ROTATE_RIGHT, BTN_LABEL_PROP_BTN_7);
+-}
+-#endif
+-
+-static int device_init(DeviceIntPtr dev, LocalDevicePtr local)
+-{
+- struct MTouch *mt = local->private;
+- unsigned char btmap[DIM_BUTTON + 1] = {
+- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+- };
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- Atom axes_labels[2], btn_labels[DIM_BUTTON];
+- initAxesLabels(axes_labels);
+- initButtonLabels(btn_labels);
+-#endif
+-
+- local->fd = xf86OpenSerial(local->options);
+- if (local->fd < 0) {
+- xf86Msg(X_ERROR, "multitouch: cannot open device\n");
+- return !Success;
+- }
+- if (configure_mtouch(mt, local->fd)) {
+- xf86Msg(X_ERROR, "multitouch: cannot configure device\n");
+- return !Success;
+- }
+- xf86CloseSerial(local->fd);
+-
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+- InitPointerDeviceStruct((DevicePtr)dev,
+- btmap, DIM_BUTTON,
+- GetMotionHistory,
+- pointer_control,
+- GetMotionHistorySize(),
+- 2);
+-#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 7
+- InitPointerDeviceStruct((DevicePtr)dev,
+- btmap, DIM_BUTTON,
+- pointer_control,
+- GetMotionHistorySize(),
+- 2);
+-#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- InitPointerDeviceStruct((DevicePtr)dev,
+- btmap, DIM_BUTTON, btn_labels,
+- pointer_control,
+- GetMotionHistorySize(),
+- 2, axes_labels);
+-#else
+-#error "Unsupported ABI_XINPUT_VERSION"
+-#endif
+-
+- xf86InitValuatorAxisStruct(dev, 0,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- axes_labels[0],
+-#endif
+- mt->caps.abs[MTDEV_POSITION_X].minimum,
+- mt->caps.abs[MTDEV_POSITION_X].maximum,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+- 1, 0, 1, Absolute);
+-#else
+- 1, 0, 1);
+-#endif
+- xf86InitValuatorDefaults(dev, 0);
+- xf86InitValuatorAxisStruct(dev, 1,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- axes_labels[1],
+-#endif
+- mt->caps.abs[MTDEV_POSITION_Y].minimum,
+- mt->caps.abs[MTDEV_POSITION_Y].maximum,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+- 1, 0, 1, Absolute);
+-#else
+- 1, 0, 1);
+-#endif
+- xf86InitValuatorDefaults(dev, 1);
+-
+- XIRegisterPropertyHandler(dev, pointer_property, NULL, NULL);
+-
+- return Success;
+-}
+-
+-static int device_on(LocalDevicePtr local)
+-{
+- struct MTouch *mt = local->private;
+- local->fd = xf86OpenSerial(local->options);
+- if (local->fd < 0) {
+- xf86Msg(X_ERROR, "multitouch: cannot open device\n");
+- return !Success;
+- }
+- if (open_mtouch(mt, local->fd)) {
+- xf86Msg(X_ERROR, "multitouch: cannot grab device\n");
+- return !Success;
+- }
+- xf86AddEnabledDevice(local);
+- return Success;
+-}
+-
+-static int device_off(LocalDevicePtr local)
+-{
+- struct MTouch *mt = local->private;
+- xf86RemoveEnabledDevice(local);
+- if (close_mtouch(mt, local->fd))
+- xf86Msg(X_WARNING, "multitouch: cannot ungrab device\n");
+- xf86CloseSerial(local->fd);
+- return Success;
+-}
+-
+-static int device_close(LocalDevicePtr local)
+-{
+- return Success;
+-}
+-
+-static void tickle_button(LocalDevicePtr local, int id)
+-{
+- xf86PostButtonEvent(local->dev, FALSE, id, 1, 0, 0);
+- xf86PostButtonEvent(local->dev, FALSE, id, 0, 0, 0);
+-}
+-
+-static void button_scroll(LocalDevicePtr local,
+- int btdec, int btinc,
+- int *scroll, int step,
+- int delta)
+-{
+- *scroll += delta;
+- while (*scroll > step) {
+- tickle_button(local, btinc);
+- *scroll -= step;
+- }
+- while (*scroll < -step) {
+- tickle_button(local, btdec);
+- *scroll += step;
+- }
+-}
+-
+-static void handle_gestures(LocalDevicePtr local,
+- const struct Gestures *gs,
+- const struct Capabilities *caps)
+-{
+- static int vscroll, hscroll, vswipe, hswipe, scale, rot;
+- int i;
+- if (!gs->same_fingers) {
+- vscroll = 0;
+- hscroll = 0;
+- vswipe = 0;
+- hswipe = 0;
+- }
+- foreach_bit(i, gs->btmask)
+- xf86PostButtonEvent(local->dev, FALSE,
+- i + 1, GETBIT(gs->btdata, i), 0, 0);
+- if (GETBIT(gs->type, GS_MOVE))
+- xf86PostMotionEvent(local->dev, 0, 0, 2, gs->dx, gs->dy);
+-
+- if (GETBIT(gs->type, GS_VSCROLL)) {
+- int step = 1 + vscroll_fraction * get_cap_ysize(caps);
+- button_scroll(local, 4, 5, &vscroll, step, gs->dy);
+- }
+- if (GETBIT(gs->type, GS_HSCROLL)) {
+- int step = 1 + hscroll_fraction * get_cap_xsize(caps);
+- button_scroll(local, 6, 7, &hscroll, step, gs->dx);
+- }
+- if (GETBIT(gs->type, GS_VSWIPE)) {
+- int step = 1 + vswipe_fraction * get_cap_ysize(caps);
+- button_scroll(local, 8, 9, &vswipe, step, gs->dy);
+- }
+- if (GETBIT(gs->type, GS_HSWIPE)) {
+- int step = 1 + hswipe_fraction * get_cap_xsize(caps);
+- button_scroll(local, 10, 11, &hswipe, step, gs->dx);
+- }
+- if (GETBIT(gs->type, GS_SCALE)) {
+- int step = 1 + scale_fraction * get_cap_xsize(caps);
+- button_scroll(local, 12, 13, &scale, step, gs->scale);
+- }
+- if (GETBIT(gs->type, GS_ROTATE)) {
+- int step = 1 + rot_fraction * get_cap_xsize(caps);
+- button_scroll(local, 14, 15, &rot, step, gs->rot);
+- }
+- if (GETBIT(gs->type, GS_TAP) && gs->ntap == 1) {
+- foreach_bit(i, gs->tapmask)
+- tickle_button(local, i + 1);
+- }
+- if (GETBIT(gs->type, GS_VSWIPE4)) {
+- int step = 1 + vswipe_fraction * get_cap_ysize(caps);
+- button_scroll(local, 16, 17, &vswipe, step, gs->dy);
+- }
+- if (GETBIT(gs->type, GS_HSWIPE4)) {
+- int step = 1 + hswipe_fraction * get_cap_xsize(caps);
+- button_scroll(local, 18, 19, &hswipe, step, gs->dx);
+- }
+-}
+-
+-/* called for each full received packet from the touchpad */
+-static void read_input(LocalDevicePtr local)
+-{
+- struct Gestures gs;
+- struct MTouch *mt = local->private;
+- while (read_packet(mt, local->fd) > 0) {
+- extract_gestures(&gs, mt);
+- handle_gestures(local, &gs, &mt->caps);
+- }
+- if (has_delayed_gestures(mt, local->fd)) {
+- extract_delayed_gestures(&gs, mt);
+- handle_gestures(local, &gs, &mt->caps);
+- }
+-}
+-
+-static Bool device_control(DeviceIntPtr dev, int mode)
+-{
+- LocalDevicePtr local = dev->public.devicePrivate;
+- switch (mode) {
+- case DEVICE_INIT:
+- xf86Msg(X_INFO, "device control: init\n");
+- return device_init(dev, local);
+- case DEVICE_ON:
+- xf86Msg(X_INFO, "device control: on\n");
+- return device_on(local);
+- case DEVICE_OFF:
+- xf86Msg(X_INFO, "device control: off\n");
+- return device_off(local);
+- case DEVICE_CLOSE:
+- xf86Msg(X_INFO, "device control: close\n");
+- return device_close(local);
+- default:
+- xf86Msg(X_INFO, "device control: default\n");
+- return BadValue;
+- }
+-}
+-
+-
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+-static int preinit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+-{
+- struct MTouch *mt;
+-
+- mt = calloc(1, sizeof(*mt));
+- if (!mt)
+- return BadAlloc;
+-
+- pInfo->private = mt;
+- pInfo->type_name = XI_TOUCHPAD;
+- pInfo->device_control = device_control;
+- pInfo->read_input = read_input;
+- pInfo->switch_mode = 0;
+- //xf86CollectInputOptions(local, NULL);
+- //xf86ProcessCommonOptions(local, local->options);
+-
+- return Success;
+-}
+-#else
+-static InputInfoPtr preinit(InputDriverPtr drv, IDevPtr dev, int flags)
+-{
+- struct MTouch *mt;
+- InputInfoPtr local = xf86AllocateInput(drv, 0);
+- if (!local)
+- goto error;
+- mt = calloc(1, sizeof(struct MTouch));
+- if (!mt)
+- goto error;
+-
+- local->name = dev->identifier;
+- local->type_name = XI_TOUCHPAD;
+- local->device_control = device_control;
+- local->read_input = read_input;
+- local->private = mt;
+- local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+- local->conf_idev = dev;
+-
+- xf86CollectInputOptions(local, NULL, NULL);
+- /* xf86OptionListReport(local->options); */
+- xf86ProcessCommonOptions(local, local->options);
+-
+- local->flags |= XI86_CONFIGURED;
+- error:
+- return local;
+-}
+-#endif
+-
+-static void uninit(InputDriverPtr drv, InputInfoPtr local, int flags)
+-{
+- free(local->private);
+- local->private = 0;
+- xf86DeleteInput(local, 0);
+-}
+-
+-static InputDriverRec MULTITOUCH = {
+- 1,
+- "multitouch",
+- NULL,
+- preinit,
+- uninit,
+- NULL,
+- 0
+-};
+-
+-static XF86ModuleVersionInfo VERSION = {
+- "multitouch",
+- MODULEVENDORSTRING,
+- MODINFOSTRING1,
+- MODINFOSTRING2,
+- XORG_VERSION_CURRENT,
+- 0, 1, 0,
+- ABI_CLASS_XINPUT,
+- ABI_XINPUT_VERSION,
+- MOD_CLASS_XINPUT,
+- {0, 0, 0, 0}
+-};
+-
+-static pointer setup(pointer module, pointer options, int *errmaj, int *errmin)
+-{
+- xf86AddInputDriver(&MULTITOUCH, module, 0);
+- return module;
+-}
+-
+-XF86ModuleData multitouchModuleData = {&VERSION, &setup, NULL };
diff --git a/master/marek-d81b0fcb81100cd01728040529e90a21da5e189c b/master/marek-d81b0fcb81100cd01728040529e90a21da5e189c
new file mode 100644
index 0000000..784d6d7
--- /dev/null
+++ b/master/marek-d81b0fcb81100cd01728040529e90a21da5e189c
@@ -0,0 +1,134 @@
+diff --git a/driver/kobomultitouch_drv.c b/driver/kobomultitouch_drv.c
+index bca2b51..1dbdb9d 100644
+--- a/driver/kobomultitouch_drv.c
++++ b/driver/kobomultitouch_drv.c
+@@ -229,9 +229,12 @@ static void handle_gestures(LocalDevicePtr local,
+ hswipe = 0;
+ }
+ foreach_bit(i, gs->btmask) {
+- xf86PostMotionEvent(local->dev, 1, 0, 2, gs->posx, gs->posy);
+- xf86PostButtonEvent(local->dev, 1,
+- i + 1, GETBIT(gs->btdata, i), 0, 0);
++ if (GETBIT(gs->btdata, i)) {
++ xf86PostMotionEvent(local->dev, 1, 0, 2, gs->posx, gs->posy);
++ xf86PostButtonEvent(local->dev, 1, i + 1, 1, 0, 0);
++ } else {
++ xf86PostButtonEvent(local->dev, 1, i + 1, 0, 0, 0);
++ }
+ }
+ if (GETBIT(gs->type, GS_MOVE)) {
+ xf86PostMotionEvent(local->dev, 1, 0, 2, gs->posx, gs->posy);
+diff --git a/src/gestures.c b/src/gestures.c
+index bf19bdf..9ed2273 100644
+--- a/src/gestures.c
++++ b/src/gestures.c
+@@ -35,12 +35,13 @@ static const int BUTTON_HOLD_MS = 200;
+ */
+ void extract_mouse(struct Gestures *gs, struct MTouch* mt)
+ {
+- int nmove = bitcount(mt->mem.moving);
++ static int tracking_id = -1;
++
++ if (mt->prev_state.nfinger == 0 && mt->state.nfinger == 1) {
++ // pressed exactly one finger
+
+- if (GETBIT(mt->mem.added, 0)) {
+- // pressed first finger
+-
+ // lmb pressed
++ tracking_id = mt->state.finger[0].tracking_id;
+ gs->posx = mt->state.finger[0].position_x;
+ gs->posy = mt->state.finger[0].position_y;
+ SETBIT(gs->btmask, MT_BUTTON_LEFT);
+@@ -50,24 +51,24 @@ void extract_mouse(struct Gestures *gs, struct MTouch* mt)
+ return;
+ }
+
+- if (GETBIT(mt->mem.btdata, MT_BUTTON_LEFT) && !GETBIT(mt->mem.fingers, 0)) {
+- // released first finger
++ if (GETBIT(mt->mem.btdata, MT_BUTTON_LEFT)) {
++ // lmb is pressed
+
+- // lmb released
+- gs->posx = mt->state.finger[0].position_x;
+- gs->posy = mt->state.finger[0].position_y;
+- SETBIT(gs->btmask, MT_BUTTON_LEFT);
+- CLEARBIT(gs->btdata, MT_BUTTON_LEFT);
+- mt->mem.btdata = 0;
++ const struct FingerState *finger_state = find_finger(&mt->state, tracking_id);
+
+- return;
+- }
++ if (finger_state == NULL) {
++ // released first finger
+
+- if (GETBIT(mt->mem.btdata, MT_BUTTON_LEFT)) {
+- if (nmove == 1) {
++ // lmb released
++ tracking_id = -1;
++ SETBIT(gs->btmask, MT_BUTTON_LEFT);
++ CLEARBIT(gs->btdata, MT_BUTTON_LEFT);
++ mt->mem.btdata = 0;
++ }
++ else {
+ // mouse move
+- gs->posx = mt->state.finger[0].position_x;
+- gs->posy = mt->state.finger[0].position_y;
++ gs->posx = finger_state->position_x;
++ gs->posy = finger_state->position_y;
+ SETBIT(gs->type, GS_MOVE);
+ }
+ }
+@@ -316,5 +317,5 @@ void output_gesture(const struct Gestures *gs)
+ xf86Msg(X_INFO, "rotate: %d\n", gs->rot);
+ foreach_bit(i, gs->tapmask)
+ xf86Msg(X_INFO, "tap: %d %d\n", i, gs->ntap);
+- xf86Msg(X_INFO, "+");
++ xf86Msg(X_INFO, "\n");
+ }
+diff --git a/src/mtstate.c b/src/mtstate.c
+index e24a1e8..d2f9de5 100644
+--- a/src/mtstate.c
++++ b/src/mtstate.c
+@@ -103,25 +103,12 @@ const struct FingerState *find_finger(const struct MTState *s, int id)
+ void output_mtstate(const struct MTState *s)
+ {
+ int i;
+- xf86Msg(X_INFO, "buttons: %d%d%d\n",
+- GETBIT(s->button, MT_BUTTON_LEFT),
+- GETBIT(s->button, MT_BUTTON_MIDDLE),
+- GETBIT(s->button, MT_BUTTON_RIGHT));
+- xf86Msg(X_INFO, "fingers: %d\n",
+- s->nfinger);
+- xf86Msg(X_INFO, "evtime: %lld\n",
+- s->evtime);
++ xf86Msg(X_INFO, "-- fingers: %d, time: %lld\n",
++ s->nfinger, s->evtime);
+ for (i = 0; i < s->nfinger; i++) {
+ xf86Msg(X_INFO,
+- " %+02d %+05d:%+05d +%05d:%+05d "
+- "%+06d %+06d %+05d:%+05d\n",
++ " id: %+02d x: %+05d y: %+05d\n",
+ s->finger[i].tracking_id,
+- s->finger[i].touch_major,
+- s->finger[i].touch_minor,
+- s->finger[i].width_major,
+- s->finger[i].width_minor,
+- s->finger[i].orientation,
+- s->finger[i].pressure,
+ s->finger[i].position_x,
+ s->finger[i].position_y);
+ }
+diff --git a/src/test.c b/src/test.c
+index 5afa8b4..3597823 100644
+--- a/src/test.c
++++ b/src/test.c
+@@ -35,7 +35,7 @@ static void loop_device(int fd)
+ fprintf(stderr, "error: could not open device\n");
+ return;
+ }
+- while (!mtdev_idle(&mt.dev, fd, 5000)) {
++ while (1 == 1) { //(!mtdev_idle(&mt.dev, fd, 5000)) {
+ //while (read_packet(&mt, fd) > 0) {
+ // extract_gestures(&gs, &mt);
+ // output_gesture(&gs);
diff --git a/master/marek-e96436b2a69bf3f8e9f85c5dd4acfd203286561e b/master/marek-e96436b2a69bf3f8e9f85c5dd4acfd203286561e
new file mode 100644
index 0000000..8e0f796
--- /dev/null
+++ b/master/marek-e96436b2a69bf3f8e9f85c5dd4acfd203286561e
@@ -0,0 +1,65 @@
+diff --git a/src/gestures.c b/src/gestures.c
+index 9ed2273..c728f10 100644
+--- a/src/gestures.c
++++ b/src/gestures.c
+@@ -37,21 +37,20 @@ void extract_mouse(struct Gestures *gs, struct MTouch* mt)
+ {
+ static int tracking_id = -1;
+
+- if (mt->prev_state.nfinger == 0 && mt->state.nfinger == 1) {
+- // pressed exactly one finger
++ if (tracking_id == -1) {
++ // looking for lmb down
+
+- // lmb pressed
+- tracking_id = mt->state.finger[0].tracking_id;
+- gs->posx = mt->state.finger[0].position_x;
+- gs->posy = mt->state.finger[0].position_y;
+- SETBIT(gs->btmask, MT_BUTTON_LEFT);
+- SETBIT(gs->btdata, MT_BUTTON_LEFT);
+- mt->mem.btdata = BITMASK(MT_BUTTON_LEFT);
++ if (mt->state.nfinger == 1) {
++ // lmb pressed
+
+- return;
+- }
+-
+- if (GETBIT(mt->mem.btdata, MT_BUTTON_LEFT)) {
++ tracking_id = mt->state.finger[0].tracking_id;
++ gs->posx = mt->state.finger[0].position_x;
++ gs->posy = mt->state.finger[0].position_y;
++ SETBIT(gs->btmask, MT_BUTTON_LEFT);
++ SETBIT(gs->btdata, MT_BUTTON_LEFT);
++ mt->mem.btdata = BITMASK(MT_BUTTON_LEFT);
++ }
++ } else {
+ // lmb is pressed
+
+ const struct FingerState *finger_state = find_finger(&mt->state, tracking_id);
+diff --git a/src/mtouch.c b/src/mtouch.c
+index a6b96b8..388d68e 100644
+--- a/src/mtouch.c
++++ b/src/mtouch.c
+@@ -43,6 +43,10 @@ int open_mtouch(struct MTouch *mt, int fd)
+ init_mtstate(&mt->prev_state);
+ init_mtstate(&mt->state);
+ init_memory(&mt->mem);
++
++ mtdev_set_abs_fuzz(&mt->dev, ABS_MT_POSITION_X, 0);
++ mtdev_set_abs_fuzz(&mt->dev, ABS_MT_POSITION_Y, 0);
++
+ if (use_grab) {
+ SYSCALL(ret = ioctl(fd, EVIOCGRAB, 1));
+ if (ret)
+@@ -74,9 +78,9 @@ int read_packet(struct MTouch *mt, int fd)
+ if (ret <= 0)
+ return ret;
+ extract_mtstate(&mt->state, &mt->hs, &mt->caps);
+-#if 0
++//#if 0
+ output_mtstate(&mt->state);
+-#endif
++//#endif
+ refresh_memory(&mt->mem, &mt->prev_state, &mt->state, &mt->caps);
+ #if 0
+ output_memory(&mt->mem);
diff --git a/master/marek-f198907e2b4dda2b548baf557b32d94c1f5e7a1a b/master/marek-f198907e2b4dda2b548baf557b32d94c1f5e7a1a
new file mode 100644
index 0000000..e8aa141
--- /dev/null
+++ b/master/marek-f198907e2b4dda2b548baf557b32d94c1f5e7a1a
@@ -0,0 +1,281 @@
+diff --git a/Makefile b/Makefile
+index 7efc80d..505a2cd 100644
+--- a/Makefile
++++ b/Makefile
+@@ -6,7 +6,7 @@ LIBRARY = kobomultitouch_drv.so
+ MODULES = src
+ XMODULES = driver
+
+-o_src = capabilities hwstate mtstate memory mtouch gestures
++o_src = capabilities hwstate mtstate memory mtouch gestures variance_filter jitter_filter
+
+ o_driver= kobomultitouch_drv
+
+diff --git a/include/jitter_filter.h b/include/jitter_filter.h
+new file mode 100644
+index 0000000..00acf98
+--- /dev/null
++++ b/include/jitter_filter.h
+@@ -0,0 +1,8 @@
++#ifndef __JITTER_FILTER_H__
++#define __JITTER_FILTER_H__
++
++#include "mtstate.h"
++
++int jitter_filter(struct MTState *state);
++
++#endif
+diff --git a/include/variance_filter.h b/include/variance_filter.h
+new file mode 100644
+index 0000000..3aad910
+--- /dev/null
++++ b/include/variance_filter.h
+@@ -0,0 +1,8 @@
++#ifndef __VARIANCE_FILTER_H__
++#define __VARIANCE_FILTER_H__
++
++#include "mtstate.h"
++
++int variance_filter(struct MTState *state);
++
++#endif
+diff --git a/src/jitter_filter.c b/src/jitter_filter.c
+new file mode 100644
+index 0000000..2c50adc
+--- /dev/null
++++ b/src/jitter_filter.c
+@@ -0,0 +1,185 @@
++/*
++ * Taken and modified from:
++ *
++ * tslib/plugins/dejitter.c
++ *
++ * Copyright (C) 2001 Russell King.
++ *
++ * This file is placed under the LGPL. Please see the file
++ * COPYING for more details.
++ *
++ *
++ * Problem: some touchscreens read the X/Y values from ADC with a
++ * great level of noise in their lowest bits. This produces "jitter"
++ * in touchscreen output, e.g. even if we hold the stylus still,
++ * we get a great deal of X/Y coordinate pairs that are close enough
++ * but not equal. Also if we try to draw a straight line in a painter
++ * program, we'll get a line full of spikes.
++ *
++ * Solution: we apply a smoothing filter on the last several values
++ * thus excluding spikes from output. If we detect a substantial change
++ * in coordinates, we reset the backlog of pen positions, thus avoiding
++ * smoothing coordinates that are not supposed to be smoothed. This
++ * supposes all noise has been filtered by the lower-level filter,
++ * e.g. by the "variance" module.
++ */
++#include "jitter_filter.h"
++
++/**
++ * This filter works as follows: we keep track of latest N samples,
++ * and average them with certain weights. The oldest samples have the
++ * least weight and the most recent samples have the most weight.
++ * This helps remove the jitter and at the same time doesn't influence
++ * responsivity because for each input sample we generate one output
++ * sample; pen movement becomes just somehow more smooth.
++ */
++
++#define NR_SAMPHISTLEN 8
++#define MAX_FINGERS 2
++
++/* To keep things simple (avoiding division) we ensure that
++ * SUM(weight) = power-of-two. Also we must know how to approximate
++ * measurements when we have less than NR_SAMPHISTLEN samples.
++ */
++static const unsigned char weight [NR_SAMPHISTLEN - 1][NR_SAMPHISTLEN + 1] =
++{
++ /* The last element is pow2(SUM(0..3)) */
++ { 5, 3, 0, 0, 0, 0, 0, 0, 3 }, /* When we have 2 samples ... */
++ { 8, 5, 3, 0, 0, 0, 0, 0, 4 }, /* When we have 3 samples ... */
++ { 6, 4, 3, 3, 0, 0, 0, 0, 4 }, /* When we have 4 samples ... */
++ { 10, 8, 5, 5, 4, 0, 0, 0, 5 }, /* When we have 5 samples ... */
++ { 9, 7, 5, 4, 4, 3, 0, 0, 5 }, /* When we have 6 samples ... */
++ { 9, 6, 5, 4, 3, 3, 2, 0, 5 }, /* When we have 7 samples ... */
++ { 9, 5, 4, 3, 3, 3, 3, 2, 5 }, /* When we have 8 samples ... */
++};
++
++struct ts_hist {
++ int x;
++ int y;
++ unsigned int p;
++};
++
++struct tslib_dejitter {
++ int delta;
++ int x;
++ int y;
++ int down;
++ int nr;
++ int head;
++ struct ts_hist hist[NR_SAMPHISTLEN];
++};
++
++static struct tslib_dejitter *djts = NULL;
++
++static int sqr (int x)
++{
++ return x * x;
++}
++
++static void average(struct tslib_dejitter *djt, struct FingerState *samp)
++{
++ const unsigned char *w;
++ int sn = djt->head;
++ int i, x = 0, y = 0;
++ unsigned int p = 0;
++
++ w = weight[djt->nr - 2];
++
++ for (i = 0; i < djt->nr; i++) {
++ x += djt->hist [sn].x * w [i];
++ y += djt->hist [sn].y * w [i];
++ p += djt->hist [sn].p * w [i];
++ sn = (sn - 1) & (NR_SAMPHISTLEN - 1);
++ }
++
++ samp->position_x = x >> w [NR_SAMPHISTLEN];
++ samp->position_y = y >> w [NR_SAMPHISTLEN];
++ samp->pressure = p >> w [NR_SAMPHISTLEN];
++//#ifdef DEBUG
++ //fprintf(stderr,"DEJITTER----------------> %d %d %d (nr: %d)\n",
++ // samp->position_x, samp->position_y, samp->pressure, djt->nr);
++//#endif
++}
++
++static void init()
++{
++ int i;
++
++ djts = malloc(sizeof(struct tslib_dejitter) * MAX_FINGERS);
++ memset(djts, 0, sizeof(struct tslib_dejitter) * MAX_FINGERS);
++
++ for (i = 0; i < MAX_FINGERS; i++) {
++ djts[i].delta = 15;
++ djts[i].head = 0;
++ }
++}
++
++void jitter_finger(struct FingerState *s)
++{
++ struct tslib_dejitter *djt;
++
++ djt = &djts[s->tracking_id];
++
++ /* If the pen moves too fast, reset the backlog. */
++ if (djt->nr) {
++ int prev = (djt->head - 1) & (NR_SAMPHISTLEN - 1);
++ if (sqr (s->position_x - djt->hist [prev].x) +
++ sqr (s->position_y - djt->hist [prev].y) > djt->delta) {
++#ifdef DEBUG
++ //fprintf (stderr, "DEJITTER: pen movement exceeds threshold\n");
++#endif
++ djt->nr = 0;
++ }
++ }
++
++ djt->hist[djt->head].x = s->position_x;
++ djt->hist[djt->head].y = s->position_y;
++ djt->hist[djt->head].p = s->pressure;
++ if (djt->nr < NR_SAMPHISTLEN)
++ djt->nr++;
++
++ /* We'll pass through the very first sample since
++ * we can't average it (no history yet).
++ */
++ if (djt->nr > 1) {
++ average (djt, s);
++ }
++
++ djt->head = (djt->head + 1) & (NR_SAMPHISTLEN - 1);
++}
++
++int jitter_filter(struct MTState *state)
++{
++ int i;
++ static prev_fingers[MAX_FINGERS];
++
++ if (djts == NULL) {
++ init();
++ for (i = 0; i < MAX_FINGERS; i++)
++ prev_fingers[i] = 0;
++ }
++
++ for (i = 0; i < state->nfinger; i++) {
++ struct FingerState *s = &state->finger[i];
++ if (s->tracking_id < 0 || s->tracking_id >= MAX_FINGERS)
++ continue;
++
++ if (prev_fingers[s->tracking_id] == 0) {
++ // first event - leave it as it is
++ // and place in history
++ djts[s->tracking_id].nr = 0;
++ }
++
++ jitter_finger(s);
++ }
++
++ for (i = 0; i < MAX_FINGERS; i++)
++ prev_fingers[i] = 0;
++ for (i = 0; i < state->nfinger; i++) {
++ struct FingerState *s = &state->finger[i];
++ prev_fingers[s->tracking_id] = 1;
++ }
++
++ return 1;
++}
++
+diff --git a/src/mtouch.c b/src/mtouch.c
+index 388d68e..7b8801e 100644
+--- a/src/mtouch.c
++++ b/src/mtouch.c
+@@ -20,6 +20,8 @@
+ **************************************************************************/
+
+ #include "mtouch.h"
++#include "variance_filter.h"
++#include "jitter_filter.h"
+
+ static const int use_grab = 0;
+
+@@ -44,6 +46,7 @@ int open_mtouch(struct MTouch *mt, int fd)
+ init_mtstate(&mt->state);
+ init_memory(&mt->mem);
+
++ // we have better filters than included in mtdev
+ mtdev_set_abs_fuzz(&mt->dev, ABS_MT_POSITION_X, 0);
+ mtdev_set_abs_fuzz(&mt->dev, ABS_MT_POSITION_Y, 0);
+
+@@ -78,6 +81,15 @@ int read_packet(struct MTouch *mt, int fd)
+ if (ret <= 0)
+ return ret;
+ extract_mtstate(&mt->state, &mt->hs, &mt->caps);
++
++ // apply filters
++ ret = variance_filter(&mt->state);
++ if (ret <= 0)
++ return ret;
++ ret = jitter_filter(&mt->state);
++ if (ret <= 0)
++ return ret;
++
+ //#if 0
+ output_mtstate(&mt->state);
+ //#endif
+diff --git a/src/variance_filter.c b/src/variance_filter.c
+new file mode 100644
+index 0000000..e420bfe
+--- /dev/null
++++ b/src/variance_filter.c
+@@ -0,0 +1,6 @@
++#include "variance_filter.h"
++
++int variance_filter(struct MTState *state)
++{
++ return 1;
++}
diff --git a/master/series b/master/series
new file mode 100644
index 0000000..dfb28b8
--- /dev/null
+++ b/master/series
@@ -0,0 +1,7 @@
+marek-56db7c190af3cc7a9eca276a31a0efb58f106f7d
+marek-010e9b62eabfed042f35b72e8fa510df2dd7f679
+marek-15901bb725ac072ca24569a27d8086924bf2888b
+marek-d81b0fcb81100cd01728040529e90a21da5e189c
+marek-e96436b2a69bf3f8e9f85c5dd4acfd203286561e
+marek-f198907e2b4dda2b548baf557b32d94c1f5e7a1a
+jmm-fix-racy-zforce-driver
diff --git a/master/status b/master/status
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/master/status