From: Chris Bagwell <ch...@cnpbagwell.com> Bamboo P&T/Tablet PC code supports multi-touch but is using the standard input driver's ABS_X/Y/PRESSURE which filters duplicate events since it does not know they are unrelated. Its also using Wacom-specific "serial channels" concept to inform X driver which finger is currently being sent.
This patch converts the 2 finger touch events over to this new multi-touch interface. Input layer's MT support is backwards compatible so that older xdrv's will still seeing 1 finger. xdrvs will need updates to see both fingers again. Patch has support for both >=2.6.30 and <2.6.30. Leave code wrapped in "#if 1" in 2.6.30 kernel drivers and remove "#if 0" code. For older kernels, remove "#if 1" logic and enable the "#if 0" logic. Signed-off-by: Chris Bagwell <ch...@cnpbagwell.com> --- src/2.6.27/wacom.h | 1 + src/2.6.27/wacom_sys.c | 28 +++++ src/2.6.27/wacom_wac.c | 318 +++++++++++++++++++++++------------------------ 3 files changed, 185 insertions(+), 162 deletions(-) diff --git a/src/2.6.27/wacom.h b/src/2.6.27/wacom.h index dc17d51..697dbf6 100755 --- a/src/2.6.27/wacom.h +++ b/src/2.6.27/wacom.h @@ -134,6 +134,7 @@ extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value); extern void wacom_input_sync(void *wcombo); +extern void wacom_input_mt_sync(void *wcombo); extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); diff --git a/src/2.6.27/wacom_sys.c b/src/2.6.27/wacom_sys.c index 96a40b5..da96c6e 100755 --- a/src/2.6.27/wacom_sys.c +++ b/src/2.6.27/wacom_sys.c @@ -145,6 +145,11 @@ void wacom_input_sync(void *wcombo) input_sync(get_input_dev((struct wacom_combo *)wcombo)); } +void wacom_input_mt_sync(void *wcombo) +{ + input_mt_sync(get_input_dev((struct wacom_combo *)wcombo)); +} + static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); @@ -190,8 +195,19 @@ void input_dev_bpt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) wacom_wac->features.x_phy, 0, 0); input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features.y_phy, 0, 0); + + /* finger position */ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + wacom_wac->features.x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + wacom_wac->features.y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, + wacom_wac->features.pressure_max, 0, 0); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); +#if 0 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); +#endif input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); @@ -314,7 +330,19 @@ void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) { + /* finger position */ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + wacom_wac->features.x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + wacom_wac->features.y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, + wacom_wac->features.pressure_max, + 0, 0); + +#if 0 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + +#endif input_dev->evbit[0] |= BIT_MASK(EV_MSC); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); } diff --git a/src/2.6.27/wacom_wac.c b/src/2.6.27/wacom_wac.c index 2a93788..be67444 100755 --- a/src/2.6.27/wacom_wac.c +++ b/src/2.6.27/wacom_wac.c @@ -151,75 +151,73 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) return 1; } -static void wacom_bpt_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) -{ - int x = 0, y = 0, pressure; - int finger = idx + 1; - - pressure = (data[2 + (idx * 9)] & 0xff); - x = wacom_be16_to_cpu ((unsigned char *)&data[3 + (idx * 9)]) & 0x7ff; - y = wacom_be16_to_cpu ((unsigned char *)&data[5 + (idx * 9)]) & 0x7ff; - - wacom_report_abs(wcombo, ABS_X, x + finger*3); - wacom_report_abs(wcombo, ABS_Y, y + finger*3); - wacom_report_abs(wcombo, ABS_PRESSURE, pressure + finger*3); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[idx], 1); - - if (!idx) - wacom_report_key(wcombo, BTN_TOUCH, 1); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, finger); -} - -static void wacom_bpt_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) -{ - int finger = idx + 1; - - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_report_key(wcombo, wacom->tool[idx], 0); - - if (!idx) - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, finger); -} - -static void wacom_bpt_touch_in(struct wacom_wac *wacom, void *wcombo) +static void wacom_bpt_touch(struct wacom_wac *wacom, void *wcombo, + int force_out) { char *data = wacom->data; - - wacom->id[1] = (((data[3] & 0x80) >> 7) & 0x1) | - (((data[12] & 0x80) >> 6) & 0x2); - - /* First finger down */ - if (data[3] & 0x80) { - wacom_bpt_finger_in(wacom, wcombo, data, 0); - wacom->tool[0] = BTN_TOOL_DOUBLETAP; - wacom->id[0] = TOUCH_DEVICE_ID; - } else if (wacom->tool[0]) - wacom_bpt_touch_out(wacom, wcombo, 0); - - /* Second finger down */ - if (data[12] & 0x80) { - /* sync first finger data */ - if (wacom->tool[0]) - wacom_input_sync(wcombo); - - wacom_bpt_finger_in(wacom, wcombo, data, 1); - wacom->tool[1] = BTN_TOOL_TRIPLETAP; - } else if (wacom->tool[1]) { - /* sync first finger data */ - if (wacom->tool[0]) - wacom_input_sync(wcombo); - - wacom_bpt_touch_out(wacom, wcombo, 1); - wacom->tool[1] = 0; + int pressure1 = 0, x1 = 0, y1 = 0, pressure2 = 0, x2 = 0, y2 = 0; + int prox1 = 0, prox2 = 0; + + if (!force_out) + { + prox1 = data[3] & 0x80; + if (prox1) + { + pressure1 = (data[2] & 0xff); + x1 = wacom_be16_to_cpu ((unsigned char *)&data[3]) & 0x7ff; + y1 = wacom_be16_to_cpu ((unsigned char *)&data[5]) & 0x7ff; + } + + prox2 = data[12] & 0x80; + if (prox2) + { + pressure2 = (data[11] & 0xff); + x2 = wacom_be16_to_cpu ((unsigned char *)&data[12]) & 0x7ff; + y2 = wacom_be16_to_cpu ((unsigned char *)&data[14]) & 0x7ff; + } } - - if (!(data[3] & 0x80)) - wacom->tool[0] = 0; + +#if 1 + wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox1 != 0); + wacom_report_abs(wcombo, ABS_MT_POSITION_X, x1); + wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y1); + + wacom_input_mt_sync(wcombo); + + wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox2 != 0); + wacom_report_abs(wcombo, ABS_MT_POSITION_X, x2); + wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y2); + + wacom_input_mt_sync(wcombo); +#endif + + wacom_report_key(wcombo, BTN_TOUCH, prox1); +#if 1 + wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1 && prox2); +#else + wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1); +#endif + + wacom_report_abs(wcombo, ABS_PRESSURE, pressure1); + wacom_report_abs(wcombo, ABS_X, x1); + wacom_report_abs(wcombo, ABS_Y, y1); + + wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); + wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1); + wacom_input_sync(wcombo); + +#if 0 + wacom_report_key(wcombo, BTN_TOOL_TRIPLETAP, prox2); + + wacom_report_abs(wcombo, ABS_PRESSURE, pressure2); + wacom_report_abs(wcombo, ABS_X, x2); + wacom_report_abs(wcombo, ABS_Y, y2); + + wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); + wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 2); + wacom_input_sync(wcombo); +#endif + } static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo) @@ -258,17 +256,9 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, void *wcombo) prox = (data[17] & 0x30 >> 4); if (prox) - wacom_bpt_touch_in(wacom, wcombo); + wacom_bpt_touch(wacom, wcombo, 0); else { - if (wacom->id[1] & 0x1) { - wacom_bpt_touch_out(wacom, wcombo, 0); - /* sync first finger event */ - if (wacom->id[1] & 0x2) - wacom_input_sync(wcombo); - } - if (wacom->id[1] & 0x2) - wacom_bpt_touch_out(wacom, wcombo, 1); - wacom->id[0] = 0; + wacom_bpt_touch(wacom, wcombo, 1); } retval = 1; } else if (urb->actual_length == WACOM_PKGLEN_BBFUN) { /* Penabled */ @@ -757,82 +747,96 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) return 1; } -static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) +static void wacom_tpc_touch(struct wacom_wac *wacom, void *wcombo, + int force_out) { - wacom_report_abs(wcombo, ABS_X, - (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_Y, - (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[idx], 1); - if (!idx) - wacom_report_key(wcombo, BTN_TOUCH, 1); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, idx + 1); -} - -static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) -{ - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_report_key(wcombo, wacom->tool[idx], 0); - if (!idx) - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, idx + 1); - return; -} - -static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) -{ - char *data = wacom->data; - struct urb *urb = ((struct wacom_combo *)wcombo)->urb; - - wacom->tool[0] = BTN_TOOL_DOUBLETAP; - wacom->id[0] = TOUCH_DEVICE_ID; - wacom->tool[1] = BTN_TOOL_TRIPLETAP; - - if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { - switch (data[0]) { - case WACOM_REPORT_TPC1FG: - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); - wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 1); - break; - case WACOM_REPORT_TPC2FG: - if (data[1] & 0x01) { - wacom_tpc_finger_in(wacom, wcombo, data, 0); - } else if (wacom->id[1] & 0x01) { - wacom_tpc_touch_out(wacom, wcombo, 0); - } - - if (data[1] & 0x02) { - /* sync first finger data */ - if (wacom->id[1] & 0x01) - wacom_input_sync(wcombo); - - wacom_tpc_finger_in(wacom, wcombo, data, 1); - } else if (wacom->id[1] & 0x02) { - /* sync first finger data */ - if (wacom->id[1] & 0x01) - wacom_input_sync(wcombo); - - wacom_tpc_touch_out(wacom, wcombo, 1); - } - /* keep this byte to send proper out-prox event */ - wacom->id[1] = data[1] & 0x03; - break; + char *data = wacom->data; + struct urb *urb = ((struct wacom_combo *)wcombo)->urb; + int pressure1 = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; + int prox1 = 0, prox2 = 0; + int send_multi = 0, send_pressure = 0; + + if (!force_out && urb->actual_length != WACOM_PKGLEN_TPC1FG) { + if (data[0] == WACOM_REPORT_TPC1FG) { + prox1 = data[1] & 0x01; + if (prox1) + { + x1 = wacom_le16_to_cpu(&data[2]); + y1 = wacom_le16_to_cpu(&data[4]); + pressure1 = wacom_le16_to_cpu(&data[6]); } - } else { - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_key(wcombo, BTN_TOUCH, 1); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 1); + send_pressure = 1; + } else if (data[0] == WACOM_REPORT_TPC2FG) { + prox1 = data[1] & 0x01; + if (prox1) + { + x1 = (data[2] & 0xff) | ((data[3] & 0x7f) << 8); + y1 = (data[6] & 0xff) | ((data[7] & 0x7f) << 8); + } + + prox2 = data[1] & 0x01; + if (prox2) + { + x2 = (data[4] & 0xff) | ((data[5] & 0x7f) << 8); + y2 = (data[8] & 0xff) | ((data[9] & 0x7f) << 8); + } + + send_multi = 1; + } + } else if (!force_out) { + prox1 = data[0] & 0x01; + if (prox1) + { + x1 = wacom_le16_to_cpu(&data[1]); + y1 = wacom_le16_to_cpu(&data[3]); + } } - return; + +#if 1 + if (send_multi) + { + wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox1 != 0); + wacom_report_abs(wcombo, ABS_MT_POSITION_X, x1); + wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y1); + + wacom_input_mt_sync(wcombo); + + wacom_report_abs(wcombo, ABS_MT_TOUCH_MAJOR, prox2 != 0); + wacom_report_abs(wcombo, ABS_MT_POSITION_X, x2); + wacom_report_abs(wcombo, ABS_MT_POSITION_Y, y2); + + wacom_input_mt_sync(wcombo); + } +#endif + + wacom_report_key(wcombo, BTN_TOUCH, prox1); +#if 1 + wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1 && prox2); +#else + wacom_report_key(wcombo, BTN_TOOL_DOUBLETAP, prox1); +#endif + + if (send_pressure) + wacom_report_abs(wcombo, ABS_PRESSURE, pressure1); + wacom_report_abs(wcombo, ABS_X, x1); + wacom_report_abs(wcombo, ABS_Y, y1); + + wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); + wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 1); + wacom_input_sync(wcombo); + +#if 0 + wacom_report_key(wcombo, BTN_TOOL_TRIPLETAP, prox2); + + wacom_report_abs(wcombo, ABS_X, x2); + wacom_report_abs(wcombo, ABS_Y, y2); + + wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); + wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 2); + wacom_input_sync(wcombo); +#endif + + return; } static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) @@ -859,23 +863,13 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) if (!wacom->shared->stylus_in_proximity) { if (prox) { - wacom_tpc_touch_in(wacom, wcombo); + wacom_tpc_touch(wacom, wcombo, 0); return 1; } } - /* 2FGT out-prox */ - if (data[0] == WACOM_REPORT_TPC2FG) { - if (wacom->id[1] & 0x01) { - wacom_tpc_touch_out(wacom, wcombo, 0); - /* sync first finger event */ - if (wacom->id[1] & 0x02) - wacom_input_sync(wcombo); - } - if (wacom->id[1] & 0x02) - wacom_tpc_touch_out(wacom, wcombo, 1); - } else /* one finger touch */ - wacom_tpc_touch_out(wacom, wcombo, 0); + /* force out-of-prox */ + wacom_tpc_touch(wacom, wcombo, 1); /* don't reset id when pen is in prox */ if (!wacom->shared->stylus_in_proximity) -- 1.6.6.1 ------------------------------------------------------------------------------ Download Intel® Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel