diff options
author | pingc <pingc> | 2009-11-10 01:40:04 +0000 |
---|---|---|
committer | pingc <pingc> | 2009-11-10 01:40:04 +0000 |
commit | 336c6d03d3a36145508fc449b2b15a70671d4f48 (patch) | |
tree | a24d52eb9ef5653de8b7c1fea7a76b162d8c5b4b | |
parent | 9fd91ce680abaa07303d9be62df30b27801a4e06 (diff) | |
download | xf86-input-wacom-336c6d03d3a36145508fc449b2b15a70671d4f48.tar.gz |
Support two finger touchrelease-0.8.5-2
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rwxr-xr-x | src/2.6.24/wacom_sys.c | 58 | ||||
-rwxr-xr-x | src/2.6.26/wacom_sys.c | 58 | ||||
-rw-r--r-- | src/2.6.28/wacom_sys.c | 62 | ||||
-rwxr-xr-x | src/2.6.28/wacom_wac.c | 229 | ||||
-rwxr-xr-x | src/2.6.28/wacom_wac.h | 8 | ||||
-rw-r--r-- | src/include/xdrv-config.h.in | 3 | ||||
-rwxr-xr-x | src/util/wacomcfg.c | 4 | ||||
-rwxr-xr-x | src/util/xsetwacom.c | 16 | ||||
-rwxr-xr-x | src/xdrv/Makefile.am | 8 | ||||
-rwxr-xr-x | src/xdrv/wcmCommon.c | 726 | ||||
-rwxr-xr-x | src/xdrv/wcmConfig.c | 340 | ||||
-rwxr-xr-x | src/xdrv/wcmISDV4.c | 34 | ||||
-rwxr-xr-x | src/xdrv/wcmMapping.c | 874 | ||||
-rwxr-xr-x | src/xdrv/wcmSerial.c | 8 | ||||
-rw-r--r-- | src/xdrv/wcmTouchFilter.c | 392 | ||||
-rwxr-xr-x | src/xdrv/wcmUSB.c | 261 | ||||
-rwxr-xr-x | src/xdrv/wcmValidateDevice.c | 306 | ||||
-rw-r--r-- | src/xdrv/wcmXCommand.c | 31 | ||||
-rwxr-xr-x | src/xdrv/xf86Wacom.c | 286 | ||||
-rwxr-xr-x | src/xdrv/xf86Wacom.h | 6 | ||||
-rwxr-xr-x | src/xdrv/xf86WacomDefs.h | 69 |
23 files changed, 2211 insertions, 1594 deletions
@@ -1,3 +1,11 @@ +2009-11-09 Ping Cheng <pingc@wacom.com> + * Added right click, scroll, and zoom for two finger touch + * Updated kernel driver + * Validating tool by retriving device type from kernel driver + * Fixed a bug in xsetwacom TWINVIEW option + * Fixed a device id issue in xsetwacom TOOLID option + * Label 0.8.5-2 + 2009-10-31 Ping Cheng <pingc@wacom.com> * Avoid duplicated devices * Validate tool type before adding it diff --git a/configure.in b/configure.in index 6ee6f6a..1a22de0 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_PREREQ(2.58) -AC_INIT(linuxwacom, 0.8.5) +AC_INIT(linuxwacom, 0.8.5-2) AM_INIT_AUTOMAKE AM_MAINTAINER_MODE @@ -456,6 +456,22 @@ if test "$WCM_ENV_XFREE86" != yes; then ], , [WCM_XORG_XORG=yes], [WCM_XORG_XORG=no]) CFLAGS="$save_CFLAGS" AC_MSG_RESULT($WCM_XORG_XORG) + AC_MSG_CHECKING([if Xorg server is version 1.5.2 or later]) + save_CFLAGS="$CFLAGS" + CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS" + AC_TRY_COMPILE([ +#include <xorg-server.h> +#include <xorgVersion.h> +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 5, 2, 0, 0) +# error "X.org < 1.5.2 " +#endif +], , [WCM_XORG_XSERVER_1_5_2=yes], [WCM_XORG_XSERVER_1_5_2=no]) + CFLAGS="$save_CFLAGS" + AC_MSG_RESULT($WCM_XORG_XSERVER_1_5_2) + if test "$WCM_XORG_XSERVER_1_5_2" = "yes"; then + AC_DEFINE(WCM_XORG_XSERVER_1_5_2, 1, + [Using version 1.5.2 or later of X.org]) + fi AC_MSG_CHECKING([if Xorg server is version 1.6 or later]) save_CFLAGS="$CFLAGS" CFLAGS="-I$WCM_XORGSDK_DIR $CFLAGS" diff --git a/src/2.6.24/wacom_sys.c b/src/2.6.24/wacom_sys.c index 5273942..bd6f83b 100755 --- a/src/2.6.24/wacom_sys.c +++ b/src/2.6.24/wacom_sys.c @@ -197,6 +197,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); } @@ -244,6 +245,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); @@ -257,7 +259,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | + BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); } void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -267,16 +270,20 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->touch_x_max, 4, 0); - input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->touch_y_max, 4, 0); - input_set_abs_params(input_dev, ABS_Z, 0, wacom_wac->features->touch_x_res, 0, 0); - input_set_abs_params(input_dev, ABS_RZ, 0, wacom_wac->features->touch_y_res, 0, 0); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) { + input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + } } void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) { + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + input_dev->evbit[0] |= BIT_MASK(EV_MSC); + input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); + } } static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, @@ -327,14 +334,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_X: if (usage == WCM_DESKTOP) { if (finger) { - features->touch_x_max = + features->device_type = BTN_TOOL_DOUBLETAP; + features->x_max = wacom_le16_to_cpu(&report[i + 3]); - features->touch_x_res = + features->x_phy = wacom_le16_to_cpu(&report[i + 6]); features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; } else if (pen) { + features->device_type = BTN_TOOL_PEN; features->x_max = (wacom_le16_to_cpu(&report[i+3])); i += 4; @@ -351,20 +360,22 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { + features->device_type = BTN_TOOL_DOUBLETAP; if (strstr(features->name, "Wacom ISDv4 E")) { - features->touch_y_max = + features->y_max = wacom_le16_to_cpu(&report[i + 3]); - features->touch_y_res = + features->y_phy = wacom_le16_to_cpu(&report[i + 6]); i += 7; } else { - features->touch_y_max = - features->touch_x_max; - features->touch_y_res = + features->y_max = + features->x_max; + features->y_phy = wacom_le16_to_cpu(&report[i + 3]); i += 4; } } else if (pen) { + features->device_type = BTN_TOOL_PEN; features->y_max = (wacom_le16_to_cpu(&report[i+3])); i += 4; } @@ -435,6 +446,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom_wac->features = get_wacom_feature(id); BUG_ON(wacom_wac->features->pktlen > WACOM_PKGLEN_MAX); + /* default device to penabled */ + if (wacom_wac->features->device_type) + wacom_wac->features->device_type = BTN_TOOL_PEN; + input_dev->name = wacom_wac->features->name; wacom->wacom_wac = wacom_wac; usb_to_input_id(dev, &input_dev->id); @@ -448,10 +463,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i endpoint = &intf->cur_altsetting->endpoint[0].desc; - /* Initialize touch_x_max and touch_y_max in case it is not defined */ if (wacom_wac->features->type == TABLETPC || wacom_wac->features->type == TABLETPC2FG) { - wacom_wac->features->touch_x_max = 1023; - wacom_wac->features->touch_y_max = 1023; /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { @@ -464,14 +476,16 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i error = wacom_parse_hid(intf, hid_desc, wacom_wac); if (error) goto fail2; - } else { - wacom_wac->features->touch_x_max = 0; - wacom_wac->features->touch_y_max = 0; + + /* touch device found but size is not defined. use default */ + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP && !wacom_wac->features->x_max) { + wacom_wac->features->x_max = 1023; + wacom_wac->features->y_max = 1023; + } } input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | - BIT_MASK(BTN_TOUCH); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); diff --git a/src/2.6.26/wacom_sys.c b/src/2.6.26/wacom_sys.c index d797b73..af1102e 100755 --- a/src/2.6.26/wacom_sys.c +++ b/src/2.6.26/wacom_sys.c @@ -214,6 +214,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); } @@ -261,6 +262,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); @@ -274,7 +276,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | + BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); } void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -284,16 +287,20 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->touch_x_max, 4, 0); - input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->touch_y_max, 4, 0); - input_set_abs_params(input_dev, ABS_Z, 0, wacom_wac->features->touch_x_res, 0, 0); - input_set_abs_params(input_dev, ABS_RZ, 0, wacom_wac->features->touch_y_res, 0, 0); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) { + input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + } } void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) { + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + input_dev->evbit[0] |= BIT_MASK(EV_MSC); + input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); + } } static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, @@ -344,14 +351,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_X: if (usage == WCM_DESKTOP) { if (finger) { - features->touch_x_max = + features->device_type = BTN_TOOL_DOUBLETAP; + features->x_max = wacom_le16_to_cpu(&report[i + 3]); - features->touch_x_res = + features->x_phy = wacom_le16_to_cpu(&report[i + 6]); features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; } else if (pen) { + features->device_type = BTN_TOOL_PEN; features->x_max = (wacom_le16_to_cpu(&report[i+3])); i += 4; } @@ -367,20 +376,22 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { + features->device_type = BTN_TOOL_DOUBLETAP; if (strstr(features->name, "Wacom ISDv4 E")) { - features->touch_y_max = + features->y_max = wacom_le16_to_cpu(&report[i + 3]); - features->touch_y_res = + features->y_phy = wacom_le16_to_cpu(&report[i + 6]); i += 7; } else { - features->touch_y_max = - features->touch_x_max; - features->touch_y_res = + features->y_max = + features->x_max; + features->y_phy = wacom_le16_to_cpu(&report[i + 3]); i += 4; } } else if (pen) { + features->device_type = BTN_TOOL_PEN; features->y_max = (wacom_le16_to_cpu(&report[i+3])); i += 4; } @@ -453,6 +464,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom_wac->features = get_wacom_feature(id); BUG_ON(wacom_wac->features->pktlen > WACOM_PKGLEN_MAX); + /* default device to penabled */ + if (features->device_type) + features->device_type = BTN_TOOL_PEN; + input_dev->name = wacom_wac->features->name; wacom->wacom_wac = wacom_wac; usb_to_input_id(dev, &input_dev->id); @@ -466,10 +481,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i endpoint = &intf->cur_altsetting->endpoint[0].desc; - /* Initialize touch_x_max and touch_y_max in case it is not defined */ if (wacom_wac->features->type == TABLETPC || wacom_wac->features->type == TABLETPC2FG) { - wacom_wac->features->touch_x_max = 1023; - wacom_wac->features->touch_y_max = 1023; /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { @@ -482,14 +494,16 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i error = wacom_parse_hid(intf, hid_desc, wacom_wac); if (error) goto fail2; - } else { - wacom_wac->features->touch_x_max = 0; - wacom_wac->features->touch_y_max = 0; + + /* touch device found but size is not defined. use default */ + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP && !wacom_wac->features->x_max) { + wacom_wac->features->x_max = 1023; + wacom_wac->features->y_max = 1023; + } } input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | - BIT_MASK(BTN_TOUCH); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); diff --git a/src/2.6.28/wacom_sys.c b/src/2.6.28/wacom_sys.c index b3113b0..e9c27f7 100644 --- a/src/2.6.28/wacom_sys.c +++ b/src/2.6.28/wacom_sys.c @@ -209,6 +209,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); } @@ -256,6 +257,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | + BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); @@ -269,7 +271,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | + BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); } void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -279,16 +282,20 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->touch_x_max, 4, 0); - input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->touch_y_max, 4, 0); - input_set_abs_params(input_dev, ABS_Z, 0, wacom_wac->features->touch_x_res, 0, 0); - input_set_abs_params(input_dev, ABS_RZ, 0, wacom_wac->features->touch_y_res, 0, 0); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) { + input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + } } void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) { + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); + input_dev->evbit[0] |= BIT_MASK(EV_MSC); + input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); + } } static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, @@ -342,14 +349,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_X: if (usage == WCM_DESKTOP) { if (finger) { - features->touch_x_max = + features->device_type = BTN_TOOL_DOUBLETAP; + features->x_max = wacom_le16_to_cpu(&report[i + 3]); - features->touch_x_res = + features->x_phy = wacom_le16_to_cpu(&report[i + 6]); features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; } else if (pen) { + features->device_type = BTN_TOOL_PEN; features->x_max = wacom_le16_to_cpu(&report[i + 3]); i += 4; @@ -367,20 +376,22 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { + features->device_type = BTN_TOOL_DOUBLETAP; if (strstr(features->name, "Wacom ISDv4 E")) { - features->touch_y_max = + features->y_max = wacom_le16_to_cpu(&report[i + 3]); - features->touch_y_res = + features->y_phy = wacom_le16_to_cpu(&report[i + 6]); i += 7; } else { - features->touch_y_max = - features->touch_x_max; - features->touch_y_res = + features->y_max = + features->x_max; + features->y_phy = wacom_le16_to_cpu(&report[i + 3]); i += 4; } } else if (pen) { + features->device_type = BTN_TOOL_PEN; features->y_max = wacom_le16_to_cpu(&report[i + 3]); i += 4; @@ -457,6 +468,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom_wac->features = features = get_wacom_feature(id); BUG_ON(features->pktlen > WACOM_PKGLEN_MAX); + /* default device to penabled */ + if (features->device_type) + features->device_type = BTN_TOOL_PEN; + input_dev->name = wacom_wac->features->name; wacom->wacom_wac = wacom_wac; usb_to_input_id(dev, &input_dev->id); @@ -470,10 +485,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i endpoint = &intf->cur_altsetting->endpoint[0].desc; - /* Initialize touch_x_max and touch_y_max in case it is not defined in HID descriptor */ if (features->type == TABLETPC || features->type == TABLETPC2FG) { - features->touch_x_max = 1023; - features->touch_y_max = 1023; /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { @@ -486,20 +498,20 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i error = wacom_parse_hid(intf, hid_desc, wacom_wac); if (error) goto fail2; - } else { - features->touch_x_max = 0; - features->touch_y_max = 0; - } + /* touch device found but size is not defined. use default */ + if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { + features->x_max = 1023; + features->y_max = 1023; + } + } input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | - BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); - input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); - + input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); diff --git a/src/2.6.28/wacom_wac.c b/src/2.6.28/wacom_wac.c index 1fb3c62..39b5d68 100755 --- a/src/2.6.28/wacom_wac.c +++ b/src/2.6.28/wacom_wac.c @@ -73,9 +73,9 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) prox = data[1] & 0x40; - wacom->id[0] = ERASER_DEVICE_ID; if (prox) { + wacom->id[0] = ERASER_DEVICE_ID; pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); if (wacom->features->pressure_max > 255) pressure = (pressure << 1) | ((data[4] >> 6) & 1); @@ -163,6 +163,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { unsigned char *data = wacom->data; int x, y, rw; + static int penData = 0; if ((data[0] & 0xff) != 2) { dbg("wacom_graphire_irq: received unknown report #%d", data[0]); @@ -171,7 +172,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) if (data[1] & 0x80) { /* in prox and not a pad data */ - + penData = 1; switch ((data[1] >> 5) & 3) { case 0: /* Pen */ @@ -187,8 +188,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) case 2: /* Mouse with wheel */ wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); if (wacom->features->type == WACOM_G4 || - wacom->features->type == WACOM_MO || - wacom->features->type == WACOM_GB ) { + wacom->features->type == WACOM_MO ) { rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); wacom_report_rel(wcombo, REL_WHEEL, -rw); } else @@ -201,8 +201,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); if (wacom->features->type == WACOM_G4 || - wacom->features->type == WACOM_MO || - wacom->features->type == WACOM_GB ) + wacom->features->type == WACOM_MO ) wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); else wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); @@ -242,7 +241,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) switch (wacom->features->type) { case WACOM_G4: if (data[7] & 0xf8) { - wacom_input_sync(wcombo); /* sync last event */ + if (penData) { + wacom_input_sync(wcombo); /* sync last event */ + if (!wacom->id[0]) + penData = 0; + } wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); @@ -252,10 +255,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } else if (wacom->id[1]) { - wacom_input_sync(wcombo); /* sync last event */ + if (penData) { + wacom_input_sync(wcombo); /* sync last event */ + if (!wacom->id[0]) + penData = 0; + } wacom->id[1] = 0; wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); + wacom_report_rel(wcombo, REL_WHEEL, 0); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); wacom_report_abs(wcombo, ABS_MISC, 0); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); @@ -263,7 +271,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) break; case WACOM_MO: if ((data[7] & 0xf8) || (data[8] & 0xff)) { - wacom_input_sync(wcombo); /* sync last event */ + if (penData) { + wacom_input_sync(wcombo); /* sync last event */ + if (!wacom->id[0]) + penData = 0; + } wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); @@ -274,7 +286,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } else if (wacom->id[1]) { - wacom_input_sync(wcombo); /* sync last event */ + if (penData) { + wacom_input_sync(wcombo); /* sync last event */ + if (!wacom->id[0]) + penData = 0; + } wacom->id[1] = 0; wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); @@ -286,24 +302,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } break; - case WACOM_GB: - if (data [7] & 0x03) { - wacom_input_sync(wcombo); /* sync last event */ - wacom->id[1] = PAD_DEVICE_ID; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x02)); - wacom_report_key(wcombo, BTN_1, (data[7] & 0x01)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - wacom_input_sync(wcombo); /* sync last event */ - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x02)); - wacom_report_key(wcombo, BTN_1, (data[7] & 0x01)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } } return 1; } @@ -634,13 +632,45 @@ 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) +{ + 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_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); + else + wacom_report_key(wcombo, BTN_TOUCH, 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_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); + else + wacom_report_key(wcombo, BTN_TOUCH, 0); + 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; + static int firstFinger = 0; + static int secondFinger = 0; 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] & 0xff) { case 6: @@ -648,80 +678,72 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) 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 13: + /* keep this byte to send proper out-prox event */ + wacom->id[1] = data[1] & 0x03; + if (data[1] & 0x01) { - if (data[1] & 0x02) { - wacom->tool[1] = BTN_TOOL_TRIPLETAP; - wacom_report_abs(wcombo, ABS_X, (data[4] & 0xff) | ((data[5] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_Y, (data[8] & 0xff) | ((data[9] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[1], 1); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - wacom_input_sync(wcombo); /* sync second finger data */ - } - wacom_report_abs(wcombo, ABS_X, (data[2] & 0xff) | ((data[3] & 0x7f) << 8)); - wacom_report_abs(wcombo, ABS_Y, (data[6] & 0xff) | ((data[7] & 0x7f) << 8)); + wacom_tpc_finger_in(wacom, wcombo, data, 0); + firstFinger = 1; + } else if (firstFinger) { + wacom_tpc_touch_out(wacom, wcombo, 0); + } + + if (data[1] & 0x02) { + /* sync first finger data */ + if (firstFinger) + wacom_input_sync(wcombo); + + wacom_tpc_finger_in(wacom, wcombo, data, 1); + secondFinger = 1; + } else if (secondFinger) { + /* sync first finger data */ + if (firstFinger) + wacom_input_sync(wcombo); + + wacom_tpc_touch_out(wacom, wcombo, 1); + secondFinger = 0; } - wacom_report_key(wcombo, BTN_TOUCH, 1); + if (!(data[1] & 0x01)) + firstFinger = 0; break; } } 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); } - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 1); - - return; -} - -static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo) -{ - 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[0], 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); return; } static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) { char *data = wacom->data; - int prox = 0, pressure; + int prox = 0, pressure, idx = -1; static int stylusInProx, touchInProx = 1, touchOut; struct urb *urb = ((struct wacom_combo *)wcombo)->urb; - static int secondFingerIn = 0; dbg("wacom_tpc_irq: received report #%d", data[0]); if (urb->actual_length == WACOM_PKGLEN_TPC1FG || ((data[0] & 0xff) == 6) /* single touch */ || (data[0] & 0xff) == 13 ) { /* 2FG touch */ if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ - prox = data[0] & 0x03; + prox = data[0] & 0x01; } else { /* with capacity */ - if ((data[0] & 0xff) == 6) /* single touch */ + if ((data[0] & 0xff) == 6) + /* single touch */ prox = data[1] & 0x01; - else /* 2FG touch data */ + else + /* 2FG touch data */ prox = data[1] & 0x03; } if (!stylusInProx) { /* stylus not in prox */ - if ((data[0] & 0xff) == 13) { - if (data[1] & 0x02) - secondFingerIn = 1; - else if (secondFingerIn == 1) { - 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[1], 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - wacom_input_sync(wcombo); /* sync second finger data */ - secondFingerIn = 0; - } - } if (prox) { if (touchInProx) { wacom_tpc_touch_in(wacom, wcombo); @@ -729,13 +751,26 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) return 1; } } else { - wacom_tpc_touch_out(wacom, wcombo); + /* 2FGT out-prox */ + if ((data[0] & 0xff) == 13) { + idx = (wacom->id[1] & 0x01) - 1; + if (idx == 0) { + wacom_tpc_touch_out(wacom, wcombo, idx); + /* sync first finger event */ + if (wacom->id[1] & 0x02) + wacom_input_sync(wcombo); + } + idx = (wacom->id[1] & 0x02) - 1; + if (idx == 1) + wacom_tpc_touch_out(wacom, wcombo, idx); + } else /* one finger touch */ + wacom_tpc_touch_out(wacom, wcombo, 0); touchOut = 0; touchInProx = 1; return 1; } } else if (touchOut || !prox) { /* force touch out-prox */ - wacom_tpc_touch_out(wacom, wcombo); + wacom_tpc_touch_out(wacom, wcombo, 0); touchOut = 0; touchInProx = 1; return 1; @@ -745,38 +780,14 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) touchInProx = 0; - wacom->id[0] = ERASER_DEVICE_ID; - - /* - * if going from out of proximity into proximity select between the eraser - * and the pen based on the state of the stylus2 button, choose eraser if - * pressed else choose pen. if not a proximity change from out to in, send - * an out of proximity for previous tool then a in for new tool. - */ if (prox) { /* in prox */ - if (!wacom->id[1]) { - /* Going into proximity select tool */ - wacom->tool[0] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (!wacom->id[0]) { + wacom->tool[0] = (data[1] & 0x0c) ? + BTN_TOOL_RUBBER : BTN_TOOL_PEN; if (wacom->tool[0] == BTN_TOOL_PEN) wacom->id[0] = STYLUS_DEVICE_ID; - } else if (wacom->tool[0] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { - /* - * was entered with stylus2 pressed - * report out proximity for previous tool - */ - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); - wacom_report_key(wcombo, wacom->tool[0], 0); - wacom_input_sync(wcombo); - - /* set new tool */ - wacom->tool[0] = BTN_TOOL_PEN; - wacom->id[0] = STYLUS_DEVICE_ID; - return 0; - } - if (wacom->tool[1] != BTN_TOOL_RUBBER) { - /* Unknown tool selected default to pen tool */ - wacom->tool[0] = BTN_TOOL_PEN; - wacom->id[0] = STYLUS_DEVICE_ID; + else + wacom->id[0] = ERASER_DEVICE_ID; } wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); @@ -786,7 +797,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) if (pressure < 0) pressure = wacom->features->pressure_max + pressure + 1; wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - wacom_report_key(wcombo, BTN_TOUCH, pressure); + wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); } else { wacom_report_abs(wcombo, ABS_X, 0); wacom_report_abs(wcombo, ABS_Y, 0); @@ -794,12 +805,13 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_STYLUS, 0); wacom_report_key(wcombo, BTN_STYLUS2, 0); wacom_report_key(wcombo, BTN_TOUCH, 0); - touchInProx = 1; /* pen is out so touch can be enabled now */ + wacom->id[0] = 0; + /* pen is out so touch can be enabled now */ + touchInProx = 1; } wacom_report_key(wcombo, wacom->tool[0], prox); wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); stylusInProx = prox; - wacom->id[1] = prox; /* use the prox info to distinguish up-side switch from eraser */ return 1; } return 0; @@ -817,7 +829,6 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) case WACOM_G4: case GRAPHIRE: case WACOM_MO: - case WACOM_GB: return wacom_graphire_irq(wacom_wac, wcombo); case PTU: @@ -851,7 +862,6 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w case WACOM_MO: input_dev_mo(input_dev, wacom_wac); case WACOM_G4: - case WACOM_GB: input_dev_g4(input_dev, wacom_wac); /* fall through */ case GRAPHIRE: @@ -883,6 +893,9 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w /* fall through */ case TABLETPC: input_dev_tpc(input_dev, wacom_wac); + if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP) + break; /* no need to process stylus stuff */ + /* fall through */ case PL: case PTU: @@ -952,7 +965,6 @@ static struct wacom_features wacom_features[] = { { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }, { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }, { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }, - { "Wacom Graphire Bluetooth", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_GB }, { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, @@ -1020,7 +1032,6 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x81) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, diff --git a/src/2.6.28/wacom_wac.h b/src/2.6.28/wacom_wac.h index 7d207fd..37e0eb3 100755 --- a/src/2.6.28/wacom_wac.h +++ b/src/2.6.28/wacom_wac.h @@ -37,7 +37,6 @@ enum { WACOM_MO, TABLETPC, TABLETPC2FG, - WACOM_GB, MAX_TYPE }; @@ -49,10 +48,9 @@ struct wacom_features { int pressure_max; int distance_max; int type; - int touch_x_res; - int touch_y_res; - int touch_x_max; - int touch_y_max; + int device_type; + int x_phy; + int y_phy; unsigned char unit; unsigned char unitExpo; }; diff --git a/src/include/xdrv-config.h.in b/src/include/xdrv-config.h.in index fade638..165d960 100644 --- a/src/include/xdrv-config.h.in +++ b/src/include/xdrv-config.h.in @@ -35,6 +35,9 @@ /* Xserver versions 1.4 and later call Uninit before closing a device. */ #undef WCM_XORG_XSERVER_1_4 +/* Xserver versions earlier than 1.5.2 call Uninit before closing a device. */ +#undef WCM_XORG_XSERVER_1_5_2 + /* Xserver versions 1.6 and later changed a few interfaces. */ #undef WCM_XORG_XSERVER_1_6 diff --git a/src/util/wacomcfg.c b/src/util/wacomcfg.c index f9eb7cd..7da42cc 100755 --- a/src/util/wacomcfg.c +++ b/src/util/wacomcfg.c @@ -281,8 +281,8 @@ WACOMDEVICETYPE mapStringToType (const char* name) return WACOMDEVICETYPE_TOUCH; else if (strstr(name,"pad") != NULL) return WACOMDEVICETYPE_PAD; - else - return WACOMDEVICETYPE_UNKNOWN; + else /* HAL eliminated stylus in the name for stylus */ + return WACOMDEVICETYPE_STYLUS; } diff --git a/src/util/xsetwacom.c b/src/util/xsetwacom.c index cbb06cc..de9c5b3 100755 --- a/src/util/xsetwacom.c +++ b/src/util/xsetwacom.c @@ -109,11 +109,11 @@ struct _PARAMINFO static const char* tv_char[] = { "none", - "xinerama" + "xinerama", "vertical", "horizontal", - "aboveof" - "leftof" + "aboveof", + "leftof", "NULL" }; @@ -692,7 +692,7 @@ static int ListDev(WACOMCONFIG *hConfig, char** argv) const char* pszType; WACOMDEVICEINFO* pInfo; unsigned int i, j, uCount; - char nameOut[60]; + char nameOut[60] = ""; static TYPEXLAT xTypes[] = { @@ -712,13 +712,14 @@ static int ListDev(WACOMCONFIG *hConfig, char** argv) for (i=0; i<uCount; ++i) { pszType = "unknown"; + nameOut[0] = 0; /* end of string */ for (j=0; j<sizeof(xTypes)/sizeof(*xTypes); ++j) if (xTypes[j].type == pInfo[i].type) pszType = xTypes[j].pszText; /* tcl/tk (wacomcpl) has problem to process spaced names - * so we make the name into one string */ - for(j=0; j<strlen(pInfo[i].pszName); j++) + * so we make them into the one string */ + for (j=0; j<strlen(pInfo[i].pszName); j++) { if(pInfo[i].pszName[j] == ' ') nameOut[j] = '_'; @@ -898,11 +899,14 @@ static int ParseValues(int nCount, const char* pszValues, int* nValues, if (p->nParamID == XWACOM_PARAM_TWINVIEW) option_char = tv_char; for (j = p->nMin; j <= p->nMax; j++) + { if (!strcasecmp(pszValues, option_char[j])) { check = 1; *nValue = j; + break; } + } if (!check) { fprintf(stderr,"ParseValues: Value '%s' is " diff --git a/src/xdrv/Makefile.am b/src/xdrv/Makefile.am index 0d451b1..4ed4291 100755 --- a/src/xdrv/Makefile.am +++ b/src/xdrv/Makefile.am @@ -12,7 +12,9 @@ EXTRA_DIST = xf86Wacom.c wcmXCommand.c xf86Wacom.h \ wcmSerial.c wcmISDV4.c wcmUSB.c \ wcmCommon.c wcmCompat.c wcmConfig.c \ wcmFilter.c wcmFilter.h wcmSerial.h \ - ../include/Xwacom.h wcmTilt2Rotation.c + ../include/Xwacom.h wcmTilt2Rotation.c \ + wcmTouchFilter.c wcmValidateDevice.c \ + wcmMapping.c if WCM_ENV_XORGSDK DRIVER_INCLUDES = -I../include -I$(WCM_XORGSDK_DIR) $(X_CFLAGS) @XORG_CFLAGS@ @@ -42,8 +44,8 @@ endif XF86OBJS = xf86Wacom.o wcmSerial.o wcmUSB.o wcmISDV4.o \ wcmXCommand.o wcmCommon.o wcmCompat.o wcmConfig.o \ - wcmFilter.o wcmTilt2Rotation.o - + wcmFilter.o wcmTilt2Rotation.o wcmTouchFilter.o \ + wcmValidateDevice.o wcmMapping.o $(XF86OBJS): $(CC) $(CFLAGS) $(WCM_DEPFLAGS) $(DLLOADER) -pipe $(WCM_CLEVEL) \ -pedantic -Wall -Wpointer-arith $(NO_MERGE_CONSTANTS) \ diff --git a/src/xdrv/wcmCommon.c b/src/xdrv/wcmCommon.c index 7f6fb86..696e4f9 100755 --- a/src/xdrv/wcmCommon.c +++ b/src/xdrv/wcmCommon.c @@ -44,9 +44,9 @@ WacomDeviceClass* wcmDeviceClasses[] = extern int xf86WcmDevSwitchModeCall(LocalDevicePtr local, int mode); extern void xf86WcmChangeScreen(LocalDevicePtr local, int value); -extern void xf86WcmInitialCoordinates(LocalDevicePtr local, int axes); -extern void xf86WcmVirtaulTabletSize(LocalDevicePtr local); extern void xf86WcmTilt2R(WacomDeviceStatePtr ds); +extern void xf86WcmFingerTapToClick(WacomCommonPtr common); +extern void xf86WcmSetScreen(LocalDevicePtr local, int v0, int v1); /***************************************************************************** * Static functions @@ -60,192 +60,6 @@ static void sendAButton(LocalDevicePtr local, int button, int mask, int rx, int ry, int rz, int v3, int v4, int v5); /***************************************************************************** - * xf86WcmMappingFactor -- - * calculate the proper tablet to screen mapping factor according to the - * screen/desktop size and the tablet size - ****************************************************************************/ - -void xf86WcmMappingFactor(LocalDevicePtr local) -{ - WacomDevicePtr priv = (WacomDevicePtr) local->private; - int screenX, screenY; - - DBG(10, priv->debugLevel, ErrorF("xf86WcmMappingFactor \n")); - - xf86WcmVirtaulTabletSize(local); - - if (!(priv->flags & ABSOLUTE_FLAG) || !priv->wcmMMonitor) - { - /* Get the current screen that the cursor is in */ -#if WCM_XINPUTABI_MAJOR == 0 - if (miPointerCurrentScreen()) - priv->currentScreen = miPointerCurrentScreen()->myNum; -#else - if (miPointerGetScreen(local->dev)) - priv->currentScreen = miPointerGetScreen(local->dev)->myNum; -#endif - } - else - { - if (priv->screen_no != -1) - priv->currentScreen = priv->screen_no; - else if (priv->currentScreen == -1) - { - /* Get the current screen that the cursor is in */ -#if WCM_XINPUTABI_MAJOR == 0 - if (miPointerCurrentScreen()) - priv->currentScreen = miPointerCurrentScreen()->myNum; -#else - if (miPointerGetScreen(local->dev)) - priv->currentScreen = miPointerGetScreen(local->dev)->myNum; -#endif - } - } - if (priv->currentScreen == -1) /* tool on the tablet */ - priv->currentScreen = 0; - - screenX = priv->maxWidth; - screenY = priv->maxHeight; - if (priv->screen_no != -1 || (priv->twinview > TV_XINERAMA) || (!priv->wcmMMonitor) ) - { - screenX = priv->screenBottomX[priv->currentScreen] - priv->screenTopX[priv->currentScreen]; - screenY = priv->screenBottomY[priv->currentScreen] - priv->screenTopY[priv->currentScreen]; - } - DBG(10, priv->debugLevel, ErrorF("xf86WcmMappingFactor" - " Active tablet area x=%d y=%d (virtual tablet area x=%d y=%d) map" - " to maxWidth =%d maxHeight =%d\n", - priv->bottomX, priv->bottomY, priv->sizeX, priv->sizeY, - screenX, screenY)); - - priv->factorX = (double)screenX / (double)priv->sizeX; - priv->factorY = (double)screenY / (double)priv->sizeY; - DBG(2, priv->debugLevel, ErrorF("X factor = %.3g, Y factor = %.3g\n", - priv->factorX, priv->factorY)); -} - -/***************************************************************************** - * xf86WcmSetScreen -- - * set to the proper screen according to the converted (x,y). - * this only supports for horizontal setup now. - * need to know screen's origin (x,y) to support - * combined horizontal and vertical setups - ****************************************************************************/ - -static void xf86WcmSetScreen(LocalDevicePtr local, int v0, int v1) -{ - WacomDevicePtr priv = (WacomDevicePtr) local->private; - int screenToSet = -1, i, j, x, y, tabletSize = 0; - - DBG(6, priv->debugLevel, ErrorF("xf86WcmSetScreen v0=%d v1=%d " - "currentScreen=%d\n", v0, v1, priv->currentScreen)); - - if (priv->screen_no != -1 && priv->screen_no >= priv->numScreen) - { - ErrorF("xf86WcmSetScreen Screen%d is larger than number of available screens (%d)\n", - priv->screen_no, priv->numScreen); - priv->screen_no = -1; - } - - if (!(local->flags & (XI86_ALWAYS_CORE | XI86_CORE_POINTER))) return; - - if (priv->twinview > TV_XINERAMA && priv->screen_no == -1 && (priv->flags & ABSOLUTE_FLAG)) - { - if (priv->twinview == TV_LEFT_RIGHT) - { - tabletSize = priv->bottomX - priv->tvoffsetX; - if (v0 > tabletSize && v0 <= priv->bottomX) - priv->currentScreen = 1; - if (v0 > priv->topX && v0 <= priv->topX + priv->tvoffsetX) - priv->currentScreen = 0; - } - if (priv->twinview == TV_ABOVE_BELOW) - { - tabletSize = priv->bottomY - priv->tvoffsetY; - if (v0 > tabletSize && v0 <= priv->bottomY) - priv->currentScreen = 1; - if (v0 > priv->topY && v0 <= priv->topY + priv->tvoffsetY) - priv->currentScreen = 0; - } - if (priv->twinview == TV_RIGHT_LEFT) - { - tabletSize = priv->bottomX - priv->tvoffsetX; - if (v0 > tabletSize && v0 <= priv->bottomX) - priv->currentScreen = 0; - if (v0 > priv->topX && v0 <= priv->topX + priv->tvoffsetX) - priv->currentScreen = 1; - } - if (priv->twinview == TV_BELOW_ABOVE) - { - tabletSize = priv->bottomY - priv->tvoffsetY; - if (v0 > tabletSize && v0 <= priv->bottomY) - priv->currentScreen = 0; - if (v0 > priv->topY && v0 <= priv->topY + priv->tvoffsetY) - priv->currentScreen = 1; - } - DBG(10, priv->debugLevel, ErrorF("xf86WcmSetScreen TwinView setup screenToSet=%d\n", - priv->currentScreen)); - } - - xf86WcmMappingFactor(local); - if (!(priv->flags & ABSOLUTE_FLAG) || screenInfo.numScreens == 1 || !priv->wcmMMonitor) - return; - - v0 = v0 - priv->topX; - v1 = v1 - priv->topY; - - if (priv->screen_no == -1) - { - for (i = 0; i < priv->numScreen; i++) - { - if (v0 * priv->factorX >= priv->screenTopX[i] && - v0 * priv->factorX < priv->screenBottomX[i] - 0.5) - { - - for (j = 0; j < priv->numScreen; j++) - { - if (v1 * priv->factorY >= priv->screenTopY[j] && - v1 * priv->factorY <= priv->screenBottomY[j] - 0.5) - { - if (j == i) - { - screenToSet = i; - break; - } - } - } - - if (screenToSet != -1) - break; - } - } - } - else - screenToSet = priv->screen_no; - - if (screenToSet == -1) - { - DBG(3, priv->debugLevel, ErrorF("xf86WcmSetScreen Error: " - "Can not find valid screen (currentScreen=%d)\n", - priv->currentScreen)); - return; - } - - priv->currentScreen = screenToSet; - xf86WcmMappingFactor(local); - x = ((double)v0 * priv->factorX) - priv->screenTopX[screenToSet] + 0.5; - y = ((double)v1 * priv->factorY) - priv->screenTopY[screenToSet] + 0.5; - - if (x >= screenInfo.screens[screenToSet]->width) - x = screenInfo.screens[screenToSet]->width - 1; - if (y >= screenInfo.screens[screenToSet]->height) - y = screenInfo.screens[screenToSet]->height - 1; - - xf86XInputSetScreen(local, screenToSet, x, y); - DBG(10, priv->debugLevel, ErrorF("xf86WcmSetScreen current=%d ToSet=%d\n", - priv->currentScreen, screenToSet)); -} - -/***************************************************************************** * xf86WcmSendButtons -- * Send button events by comparing the current button mask with the * previous one. @@ -395,7 +209,7 @@ static int ODDKEYSYM [][2] = { 0, 0} }; -static void emitKeysym (DeviceIntPtr keydev, int keysym, int state) +void emitKeysym (DeviceIntPtr keydev, int keysym, int state) { int i, j, alt_keysym = 0; @@ -552,7 +366,9 @@ static void sendAButton(LocalDevicePtr local, int button, int mask, case AC_DISPLAYTOGGLE: if (mask && priv->numScreen > 1) { - if (IsPad(priv)) /* toggle display (individual screens plus the whole desktop) for all tools except pad */ + /* toggle display (individual screens plus the whole desktop) + * for all tools except pad */ + if (IsPad(priv)) { WacomDevicePtr tmppriv; for (tmppriv = common->wcmDevices; tmppriv; tmppriv = tmppriv->next) @@ -566,7 +382,7 @@ static void sendAButton(LocalDevicePtr local, int button, int mask, } } } - else /* toggle display (individual screens plus the whole desktop) only for the selected tool */ + else { int screen = priv->screen_no; if (++screen >= priv->numScreen) @@ -579,7 +395,8 @@ static void sendAButton(LocalDevicePtr local, int button, int mask, case AC_SCREENTOGGLE: if (mask && priv->numScreen > 1) { - if (IsPad(priv)) /* toggle screens for all tools except pad */ + /* toggle screens for all tools except pad */ + if (IsPad(priv)) { WacomDevicePtr tmppriv; for (tmppriv = common->wcmDevices; tmppriv; tmppriv = tmppriv->next) @@ -804,6 +621,33 @@ static void sendCommonEvents(LocalDevicePtr local, const WacomDeviceState* ds, i sendWheelStripEvents(local, ds, x, y, z, v3, v4, v5); } +/* rotate the raw coordinates */ +void xf86WcmRotateCoordinates(LocalDevicePtr local, int x, int y) +{ + WacomDevicePtr priv = (WacomDevicePtr) local->private; + WacomCommonPtr common = priv->common; + int tmp_coord; + + /* rotation mixes x and y up a bit */ + if (common->wcmRotate == ROTATE_CW) + { + tmp_coord = x; + x = y; + y = common->wcmMaxY - tmp_coord; + } + else if (common->wcmRotate == ROTATE_CCW) + { + tmp_coord = y; + y = x; + x = common->wcmMaxX - tmp_coord; + } + else if (common->wcmRotate == ROTATE_HALF) + { + x = common->wcmMaxX - x; + y = common->wcmMaxY - y; + } +} + /***************************************************************************** * xf86WcmSendEvents -- * Send events according to the device state. @@ -825,9 +669,7 @@ void xf86WcmSendEvents(LocalDevicePtr local, const WacomDeviceState* ds) int rot = ds->rotation; int throttle = ds->throttle; int wheel = ds->abswheel; - int tmp_coord; WacomDevicePtr priv = (WacomDevicePtr) local->private; - WacomCommonPtr common = priv->common; int naxes = priv->naxes; int is_absolute = priv->flags & ABSOLUTE_FLAG; int v3, v4, v5; @@ -866,24 +708,7 @@ void xf86WcmSendEvents(LocalDevicePtr local, const WacomDeviceState* ds) x, y, z, is_button ? "true" : "false", buttons, tx, ty, wheel, rot, throttle)); - /* rotation mixes x and y up a bit */ - if (common->wcmRotate == ROTATE_CW) - { - tmp_coord = x; - x = y; - y = priv->wcmMaxY - tmp_coord; - } - else if (common->wcmRotate == ROTATE_CCW) - { - tmp_coord = y; - y = x; - x = priv->wcmMaxX - tmp_coord; - } - else if (common->wcmRotate == ROTATE_HALF) - { - x = priv->wcmMaxX - x; - y = priv->wcmMaxY - y; - } + xf86WcmRotateCoordinates(local, x, y); if (IsCursor(priv)) { @@ -1261,9 +1086,6 @@ void xf86WcmEvent(WacomCommonPtr common, unsigned int channel, * will need to change the values (ie. for error correction) */ ds = *pState; - /* timestamp to track the last event sent */ - ds.sample = (int)GetTimeInMillis(); - DBG(10, common->debugLevel, ErrorF("xf86WcmEvent: " "c=%d i=%d t=%d s=%u x=%d y=%d b=%d " "p=%d rz=%d tx=%d ty=%d aw=%d rw=%d " @@ -1336,17 +1158,13 @@ void xf86WcmEvent(WacomCommonPtr common, unsigned int channel, { DBG(10, common->debugLevel, ErrorF( "Raw filtering discarded data.\n")); - resetSampleCounter(pChannel); - return; /* discard */ + goto ret; /* discard */ } } /* Discard unwanted data */ suppress = xf86WcmSuppress(common, pLast, &ds); if (!suppress) - { - resetSampleCounter(pChannel); - return; - } + goto ret; } /* JEJ - Do not move this code without discussing it with me. @@ -1359,10 +1177,52 @@ void xf86WcmEvent(WacomCommonPtr common, unsigned int channel, memmove(pChannel->valid.states + 1, pChannel->valid.states, sizeof(WacomDeviceState) * (common->wcmRawSample - 1)); - pChannel->valid.state = ds; /*save last raw sample */ + pChannel->valid.state = ds; /* save last raw sample */ if (pChannel->nSamples < common->wcmRawSample) ++pChannel->nSamples; + + /* process second finger data if exists */ + if (ds.device_type == TOUCH_ID) + { + WacomChannelPtr pOtherChannel; + WacomDeviceState dsOther; + + /* exit gesture mode when both fingers are out */ + if (channel) + pOtherChannel = common->wcmChannel; + else + pOtherChannel = common->wcmChannel + 1; + dsOther = pOtherChannel->valid.state; + + /* This is the only place to reset gesture mode + * once a gesture mode is entered */ + if (!ds.proximity && !dsOther.proximity && common->wcmGestureMode) + { + common->wcmGestureMode = 0; + + /* send a touch out-prox event here + * in case the FF was out before the SF */ + channel = 0; + } + else + { + /* don't move the cursor if in gesture mode + * wait for second finger data to process gestures */ + if (!channel && common->wcmTouch && + common->wcmGesture && common->wcmGestureMode) + goto ret; + + /* process gesture when both touch and geature are enabled */ + if (channel && common->wcmTouch && common->wcmGesture) + { + xf86WcmFingerTapToClick(common); + goto ret; + } + } + } + /* everything else falls here */ commonDispatchDevice(common,channel,pChannel, suppress); +ret: resetSampleCounter(pChannel); } @@ -1504,12 +1364,7 @@ static void commonDispatchDevice(WacomCommonPtr common, unsigned int channel, if (tool->current) { /* Send soft prox-out for the old area */ - LocalDevicePtr oDev = outprox->device; - WacomDeviceState out = { 0 }; - out.device_type = DEVICE_ID(((WacomDevicePtr)(oDev->private))->flags); - DBG(2, common->debugLevel, ErrorF("Soft prox-out for %s\n", - outprox->device->name)); - xf86WcmSendEvents(oDev, &out); + xf86WcmSoftOutEvent(outprox->device); } else tool->current = outprox; @@ -1571,6 +1426,9 @@ static void commonDispatchDevice(WacomCommonPtr common, unsigned int channel, /* Lookup to see if associated touch was enabled */ for (; localDevices != NULL; localDevices = localDevices->next) { + /* we need to go through all enabled Wacom devices + * since USB pen and touch don't share the same logical port + */ if (strstr(localDevices->drv->driverName, "wacom")) { temppriv = (WacomDevicePtr) localDevices->private; @@ -1582,12 +1440,7 @@ static void commonDispatchDevice(WacomCommonPtr common, unsigned int channel, IsTouch(temppriv) && temppriv->oldProximity) { /* Send soft prox-out for touch first */ - WacomDeviceState out = { 0 }; - out.device_type = DEVICE_ID(temppriv->flags); - DBG(2, common->debugLevel, ErrorF( - "Send soft prox-out for %s first\n", - localDevices->name)); - xf86WcmSendEvents(localDevices, &out); + xf86WcmSoftOutEvent(localDevices); } } } @@ -1772,90 +1625,30 @@ static void commonDispatchDevice(WacomCommonPtr common, unsigned int channel, } } -/***************************************************************************** - * xf86WcmInitTablet -- common initialization for all tablets - ****************************************************************************/ - -int xf86WcmInitTablet(LocalDevicePtr local, const char* id, float version) +void xf86WcmSoftOutEvent(LocalDevicePtr local) { - WacomDevicePtr priv = (WacomDevicePtr)local->private; + /* Send a soft prox-out event for the device */ + WacomDeviceState out = { 0 }; + WacomDevicePtr priv = (WacomDevicePtr) local->private; WacomCommonPtr common = priv->common; - WacomModelPtr model = common->wcmModel; - - /* Initialize the tablet */ - model->Initialize(common,id,version); - - /* Get tablet resolution */ - if (model->GetResolution) - model->GetResolution(local); - - /* Get tablet range */ - if (model->GetRanges && (model->GetRanges(local) != Success)) - return !Success; - - /* Default threshold value if not set */ - if (common->wcmThreshold <= 0) - { - /* Threshold for counting pressure as a button */ - if (strstr(common->wcmModel->name, "Intuos4")) - common->wcmThreshold = common->wcmMaxZ * 3 / 25; - else - common->wcmThreshold = common->wcmMaxZ * 3 / 50; - ErrorF("%s Wacom using pressure threshold of %d for button 1\n", - XCONFIG_PROBED, common->wcmThreshold); - } - - /* Reset tablet to known state */ - if (model->Reset && (model->Reset(local) != Success)) - { - ErrorF("Wacom xf86WcmWrite error : %s\n", strerror(errno)); - return !Success; - } - /* Enable tilt mode, if requested and available */ - if ((common->wcmFlags & TILT_REQUEST_FLAG) && model->EnableTilt) - { - if (model->EnableTilt(local) != Success) - return !Success; - } - - /* Enable hardware suppress, if requested and available */ - if (model->EnableSuppress) - { - if (model->EnableSuppress(local) != Success) - return !Success; - } - - /* change the serial speed, if requested */ - if (model->SetLinkSpeed) - { - if (common->wcmLinkSpeed != 9600) - { - if (model->SetLinkSpeed(local) != Success) - return !Success; - } - } - else - { - DBG(2, common->debugLevel, ErrorF("Tablet does not support setting link " - "speed, or not yet implemented\n")); - } - - /* output tablet state as probed */ - if (xf86Verbose) - ErrorF("%s Wacom %s tablet speed=%d (%d) maxX=%d maxY=%d maxZ=%d " - "resX=%d resY=%d tilt=%s\n", - XCONFIG_PROBED, - model->name, common->wcmLinkSpeed, common->wcmISDV4Speed, - common->wcmMaxX, common->wcmMaxY, common->wcmMaxZ, - common->wcmResolX, common->wcmResolY, - HANDLE_TILT(common) ? "enabled" : "disabled"); - - /* start the tablet data */ - if (model->Start && (model->Start(local) != Success)) - return !Success; + out.device_type = DEVICE_ID(priv->flags); + DBG(2, common->debugLevel, ErrorF("Send soft prox-out for" + " %s first\n", local->name)); + xf86WcmSendEvents(local, &out); +} - return Success; +void xf86WcmSoftOut(WacomCommonPtr common, int channel) +{ + /* Send a soft prox-out for the device */ + WacomDeviceState out = { 0 }; + WacomChannelPtr pChannel = common->wcmChannel + channel; + WacomDeviceState ds = pChannel->valid.state; + + out.device_type = ds.device_type; + DBG(2, common->debugLevel, ErrorF("Send soft prox-out for" + " %s at channel %d \n", common->wcmModel->name, channel)); + xf86WcmEvent(common, channel, &out); } /***************************************************************************** @@ -1884,308 +1677,3 @@ static void transPressureCurve(WacomDevicePtr pDev, WacomDeviceStatePtr pState) } } -/***************************************************************************** - * xf86WcmInitialTVScreens - ****************************************************************************/ - -static void xf86WcmInitialTVScreens(LocalDevicePtr local) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - - if (priv->twinview <= TV_XINERAMA) - return; - - priv->numScreen = 2; - - if ((priv->twinview == TV_LEFT_RIGHT) || (priv->twinview == TV_RIGHT_LEFT)) - { - /* it does not need the offset if always map to a specific screen */ - if (priv->screen_no == -1) - { - priv->tvoffsetX = 60; - priv->tvoffsetY = 0; - } - - /* default resolution */ - if(!priv->tvResolution[0]) - { - priv->tvResolution[0] = screenInfo.screens[0]->width/2; - priv->tvResolution[1] = screenInfo.screens[0]->height; - priv->tvResolution[2] = priv->tvResolution[0]; - priv->tvResolution[3] = priv->tvResolution[1]; - } - } - else if ((priv->twinview == TV_ABOVE_BELOW) || (priv->twinview == TV_BELOW_ABOVE)) - { - /* it does not need the offset if always map to a specific screen */ - if (priv->screen_no == -1) - { - priv->tvoffsetX = 0; - priv->tvoffsetY = 60; - } - - /* default resolution */ - if(!priv->tvResolution[0]) - { - priv->tvResolution[0] = screenInfo.screens[0]->width; - priv->tvResolution[1] = screenInfo.screens[0]->height/2; - priv->tvResolution[2] = priv->tvResolution[0]; - priv->tvResolution[3] = priv->tvResolution[1]; - } - } - - /* initial screen info */ - if (priv->twinview == TV_ABOVE_BELOW) - { - priv->screenTopX[0] = 0; - priv->screenTopY[0] = 0; - priv->screenBottomX[0] = priv->tvResolution[0]; - priv->screenBottomY[0] = priv->tvResolution[1]; - priv->screenTopX[1] = 0; - priv->screenTopY[1] = priv->tvResolution[1]; - priv->screenBottomX[1] = priv->tvResolution[2]; - priv->screenBottomY[1] = priv->tvResolution[1] + priv->tvResolution[3]; - } - if (priv->twinview == TV_LEFT_RIGHT) - { - priv->screenTopX[0] = 0; - priv->screenTopY[0] = 0; - priv->screenBottomX[0] = priv->tvResolution[0]; - priv->screenBottomY[0] = priv->tvResolution[1]; - priv->screenTopX[1] = priv->tvResolution[0]; - priv->screenTopY[1] = 0; - priv->screenBottomX[1] = priv->tvResolution[0] + priv->tvResolution[2]; - priv->screenBottomY[1] = priv->tvResolution[3]; - } - if (priv->twinview == TV_BELOW_ABOVE) - { - priv->screenTopX[0] = 0; - priv->screenTopY[0] = priv->tvResolution[1]; - priv->screenBottomX[0] = priv->tvResolution[2]; - priv->screenBottomY[0] = priv->tvResolution[1] + priv->tvResolution[3]; - priv->screenTopX[1] = 0; - priv->screenTopY[1] = 0; - priv->screenBottomX[1] = priv->tvResolution[0]; - priv->screenBottomY[1] = priv->tvResolution[1]; - } - if (priv->twinview == TV_RIGHT_LEFT) - { - priv->screenTopX[0] = priv->tvResolution[0]; - priv->screenTopY[0] = 0; - priv->screenBottomX[0] = priv->tvResolution[0] + priv->tvResolution[2]; - priv->screenBottomY[0] = priv->tvResolution[3]; - priv->screenTopX[1] = 0; - priv->screenTopY[1] = 0; - priv->screenBottomX[1] = priv->tvResolution[0]; - priv->screenBottomY[1] = priv->tvResolution[1]; - } - - DBG(10, priv->debugLevel, ErrorF("xf86WcmInitialTVScreens for \"%s\" " - "topX0=%d topY0=%d bottomX0=%d bottomY0=%d " - "topX1=%d topY1=%d bottomX1=%d bottomY1=%d \n", - local->name, priv->screenTopX[0], priv->screenTopY[0], - priv->screenBottomX[0], priv->screenBottomY[0], - priv->screenTopX[1], priv->screenTopY[1], - priv->screenBottomX[1], priv->screenBottomY[1])); -} - -/***************************************************************************** - * xf86WcmInitialScreens - ****************************************************************************/ - -void xf86WcmInitialScreens(LocalDevicePtr local) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - int i; - - DBG(2, priv->debugLevel, ErrorF("xf86WcmInitialScreens for \"%s\" " - "number of screen=%d \n", local->name, screenInfo.numScreens)); - priv->tvoffsetX = 0; - priv->tvoffsetY = 0; - if (priv->twinview > TV_XINERAMA) - { - xf86WcmInitialTVScreens(local); - return; - } - - /* initial screen info */ - priv->numScreen = screenInfo.numScreens; - priv->screenTopX[0] = 0; - priv->screenTopY[0] = 0; - priv->screenBottomX[0] = 0; - priv->screenBottomY[0] = 0; - for (i=0; i<screenInfo.numScreens; i++) - { -#ifdef WCM_HAVE_DIXSCREENORIGINS - if (screenInfo.numScreens > 1) - { - priv->screenTopX[i] = dixScreenOrigins[i].x; - priv->screenTopY[i] = dixScreenOrigins[i].y; - priv->screenBottomX[i] = dixScreenOrigins[i].x; - priv->screenBottomY[i] = dixScreenOrigins[i].y; - - DBG(10, priv->debugLevel, ErrorF("xf86WcmInitialScreens from dix for \"%s\" " - "ScreenOrigins[%d].x=%d ScreenOrigins[%d].y=%d \n", - local->name, i, priv->screenTopX[i], i, priv->screenTopY[i])); - } -#else /* WCM_HAVE_DIXSCREENORIGINS */ - if (i > 0) - { - /* only support left to right in this case */ - priv->screenTopX[i] = priv->screenBottomX[i-1]; - priv->screenTopY[i] = 0; - priv->screenBottomX[i] = priv->screenTopX[i]; - priv->screenBottomY[i] = 0; - } -#endif /* WCM_HAVE_DIXSCREENORIGINS */ - priv->screenBottomX[i] += screenInfo.screens[i]->width; - priv->screenBottomY[i] += screenInfo.screens[i]->height; - - DBG(10, priv->debugLevel, ErrorF("xf86WcmInitialScreens for \"%s\" " - "topX[%d]=%d topY[%d]=%d bottomX[%d]=%d bottomY[%d]=%d \n", - local->name, i, priv->screenTopX[i], i, priv->screenTopY[i], - i, priv->screenBottomX[i], i, priv->screenBottomY[i])); - } -} - -/***************************************************************************** - * rotateOneTool - ****************************************************************************/ - -static void rotateOneTool(WacomDevicePtr priv) -{ - WacomCommonPtr common = priv->common; - WacomToolAreaPtr area = priv->toolarea; - int tmpTopX, tmpTopY, tmpBottomX, tmpBottomY, oldMaxX, oldMaxY; - - DBG(10, priv->debugLevel, ErrorF("rotateOneTool for \"%s\" \n", priv->local->name)); - - oldMaxX = priv->wcmMaxX; - oldMaxY = priv->wcmMaxY; - - tmpTopX = priv->topX; - tmpBottomX = priv->bottomX; - tmpTopY = priv->topY; - tmpBottomY = priv->bottomY; - - if (common->wcmRotate == ROTATE_CW || common->wcmRotate == ROTATE_CCW) - { - priv->wcmMaxX = oldMaxY; - priv->wcmMaxY = oldMaxX; - } - - switch (common->wcmRotate) { - case ROTATE_CW: - area->topX = priv->topX = tmpTopY; - area->bottomX = priv->bottomX = tmpBottomY; - area->topY = priv->topY = oldMaxX - tmpBottomX; - area->bottomY = priv->bottomY =oldMaxX - tmpTopX; - break; - case ROTATE_CCW: - area->topX = priv->topX = oldMaxY - tmpBottomY; - area->bottomX = priv->bottomX = oldMaxY - tmpTopY; - area->topY = priv->topY = tmpTopX; - area->bottomY = priv->bottomY = tmpBottomX; - break; - case ROTATE_HALF: - area->topX = priv->topX = oldMaxX - tmpBottomX; - area->bottomX = priv->bottomX = oldMaxX - tmpTopX; - area->topY = priv->topY= oldMaxY - tmpBottomY; - area->bottomY = priv->bottomY = oldMaxY - tmpTopY; - break; - } - xf86WcmInitialCoordinates(priv->local, 0); - xf86WcmInitialCoordinates(priv->local, 1); - - if (tmpTopX != priv->topX) - xf86ReplaceIntOption(priv->local->options, "TopX", priv->topX); - if (tmpTopY != priv->topY) - xf86ReplaceIntOption(priv->local->options, "TopY", priv->topY); - if (tmpBottomX != priv->bottomX) - xf86ReplaceIntOption(priv->local->options, "BottomX", priv->bottomX); - if (tmpBottomY != priv->bottomY) - xf86ReplaceIntOption(priv->local->options, "BottomY", priv->bottomY); -} - -/***************************************************************************** - * xf86WcmRotateTablet - ****************************************************************************/ - -void xf86WcmRotateTablet(LocalDevicePtr local, int value) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - WacomCommonPtr common = priv->common; - WacomDevicePtr tmppriv; - int oldRotation; - int tmpTopX, tmpTopY, tmpBottomX, tmpBottomY, oldMaxX, oldMaxY; - - DBG(10, priv->debugLevel, ErrorF("xf86WcmRotateTablet for \"%s\" \n", local->name)); - - if (common->wcmRotate == value) /* initialization */ - { - rotateOneTool(priv); - } - else - { - oldRotation = common->wcmRotate; - common->wcmRotate = value; - - /* rotate all devices at once! else they get misaligned */ - for (tmppriv = common->wcmDevices; tmppriv; tmppriv = tmppriv->next) - { - oldMaxX = tmppriv->wcmMaxX; - oldMaxY = tmppriv->wcmMaxY; - - if (oldRotation == ROTATE_CW || oldRotation == ROTATE_CCW) - { - tmppriv->wcmMaxX = oldMaxY; - tmppriv->wcmMaxY = oldMaxX; - } - - tmpTopX = tmppriv->topX; - tmpBottomX = tmppriv->bottomX; - tmpTopY = tmppriv->topY; - tmpBottomY = tmppriv->bottomY; - - /* recover to the unrotated xy-rectangles */ - switch (oldRotation) { - case ROTATE_CW: - tmppriv->topX = oldMaxY - tmpBottomY; - tmppriv->bottomX = oldMaxY - tmpTopY; - tmppriv->topY = tmpTopX; - tmppriv->bottomY = tmpBottomX; - break; - case ROTATE_CCW: - tmppriv->topX = tmpTopY; - tmppriv->bottomX = tmpBottomY; - tmppriv->topY = oldMaxX - tmpBottomX; - tmppriv->bottomY = oldMaxX - tmpTopX; - break; - case ROTATE_HALF: - tmppriv->topX = oldMaxX - tmpBottomX; - tmppriv->bottomX = oldMaxX - tmpTopX; - tmppriv->topY = oldMaxY - tmpBottomY; - tmppriv->bottomY = oldMaxY - tmpTopY; - break; - } - - /* and rotate them to the new value */ - rotateOneTool(tmppriv); - - switch(value) { - case ROTATE_NONE: - xf86ReplaceStrOption(local->options, "Rotate", "NONE"); - break; - case ROTATE_CW: - xf86ReplaceStrOption(local->options, "Rotate", "CW"); - break; - case ROTATE_CCW: - xf86ReplaceStrOption(local->options, "Rotate", "CCW"); - break; - case ROTATE_HALF: - xf86ReplaceStrOption(local->options, "Rotate", "HALF"); - break; - } - } - } -} diff --git a/src/xdrv/wcmConfig.c b/src/xdrv/wcmConfig.c index 4447f24..61a4410 100755 --- a/src/xdrv/wcmConfig.c +++ b/src/xdrv/wcmConfig.c @@ -20,11 +20,9 @@ #include "xf86Wacom.h" #include "wcmFilter.h" #ifdef WCM_XORG_XSERVER_1_4 - #include <fcntl.h> - #ifndef _XF86_ANSIC_H - #include <sys/stat.h> - #endif extern Bool xf86WcmIsWacomDevice (char* fname, struct input_id* id); + extern Bool wcmIsAValidType(char* device, LocalDevicePtr local, unsigned short id); + extern int wcmIsDuplicate(char* device, LocalDevicePtr local); #endif /***************************************************************************** @@ -108,24 +106,20 @@ LocalDevicePtr xf86WcmAllocate(char* name, int flag) priv->oldTiltY = 0; /* previous tilt in y direction */ priv->oldStripX = 0; /* previous left strip value */ priv->oldStripY = 0; /* previous right strip value */ - priv->oldButtons = 0; /* previous buttons state */ - priv->oldWheel = 0; /* previous wheel */ - priv->topX = 0; /* X top */ - priv->topY = 0; /* Y top */ - priv->bottomX = 0; /* X bottom */ - priv->bottomY = 0; /* Y bottom */ - priv->wcmMaxX = 0; /* max tool logical X value */ - priv->wcmMaxY = 0; /* max tool logical Y value */ - priv->wcmResolX = 0; /* tool X resolution in points/inch */ - priv->wcmResolY = 0; /* tool Y resolution in points/inch */ - priv->sizeX = 0; /* active X size */ - priv->sizeY = 0; /* active Y size */ - priv->factorX = 0.0; /* X factor */ - priv->factorY = 0.0; /* Y factor */ - priv->common = common; /* common info pointer */ - priv->oldProximity = 0; /* previous proximity */ - priv->hardProx = 1; /* previous hardware proximity */ - priv->old_serial = 0; /* last active tool's serial */ + priv->oldButtons = 0; /* previous buttons state */ + priv->oldWheel = 0; /* previous wheel */ + priv->topX = 0; /* X top */ + priv->topY = 0; /* Y top */ + priv->bottomX = 0; /* X bottom */ + priv->bottomY = 0; /* Y bottom */ + priv->sizeX = 0; /* active X size */ + priv->sizeY = 0; /* active Y size */ + priv->factorX = 0.0; /* X factor */ + priv->factorY = 0.0; /* Y factor */ + priv->common = common; /* common info pointer */ + priv->oldProximity = 0; /* previous proximity */ + priv->hardProx = 1; /* previous hardware proximity */ + priv->old_serial = 0; /* last active tool's serial */ priv->old_device_id = IsStylus(priv) ? STYLUS_DEVICE_ID : (IsEraser(priv) ? ERASER_DEVICE_ID : (IsCursor(priv) ? CURSOR_DEVICE_ID : @@ -151,15 +145,15 @@ LocalDevicePtr xf86WcmAllocate(char* name, int flag) priv->keys[i][j] = 0; priv->nbuttons = MAX_BUTTONS; /* Default number of buttons */ - priv->relup = 5; /* Default relative wheel up event */ - priv->reldn = 4; /* Default relative wheel down event */ + priv->relup = SCROLL_UP; /* Default relative wheel up event */ + priv->reldn = SCROLL_DOWN; /* Default relative wheel down event */ - priv->wheelup = IsPad (priv) ? 4 : 0; /* Default absolute wheel up event */ - priv->wheeldn = IsPad (priv) ? 5 : 0; /* Default absolute wheel down event */ - priv->striplup = 4; /* Default left strip up event */ - priv->stripldn = 5; /* Default left strip down event */ - priv->striprup = 4; /* Default right strip up event */ - priv->striprdn = 5; /* Default right strip down event */ + priv->wheelup = IsPad (priv) ? SCROLL_DOWN : 0; /* Default absolute wheel up event */ + priv->wheeldn = IsPad (priv) ? SCROLL_UP : 0; /* Default absolute wheel down event */ + priv->striplup = SCROLL_DOWN; /* Default left strip up event */ + priv->stripldn = SCROLL_UP; /* Default left strip down event */ + priv->striprup = SCROLL_DOWN; /* Default right strip up event */ + priv->striprdn = SCROLL_UP; /* Default right strip down event */ priv->naxes = 6; /* Default number of axes */ priv->debugLevel = 0; /* debug level */ priv->numScreen = screenInfo.numScreens; /* configured screens count */ @@ -182,9 +176,7 @@ LocalDevicePtr xf86WcmAllocate(char* name, int flag) priv->throttleLimit = -1; common->wcmDevice = ""; /* device file name */ -#ifdef WCM_XORG_XSERVER_1_6 common->min_maj = 0; /* device major and minor */ -#endif common->wcmFlags = RAW_FILTERING_FLAG; /* various flags */ common->wcmDevices = priv; common->npadkeys = 0; /* Default number of pad keys */ @@ -203,23 +195,24 @@ LocalDevicePtr xf86WcmAllocate(char* name, int flag) common->wcmTPCButtonDefault; /* set Tablet PC button on/off */ common->wcmTouch = 0; /* touch is disabled */ common->wcmTouchDefault = 0; /* default to disable when touch isn't supported */ + common->wcmGestureMode = 0; /* touch is not in Gesture mode */ common->wcmGesture = 0; /* touch Gesture is disabled */ common->wcmGestureDefault = 0; /* default to disable when touch Gesture isn't supported */ common->wcmCapacity = -1; /* Capacity is disabled */ - common->wcmCapacityDefault = -1; /* default to -1 when capacity isn't supported */ + common->wcmCapacityDefault = -1; /* default to -1 when capacity isn't supported */ /* 3 when capacity is supported */ common->wcmRotate = ROTATE_NONE; /* default tablet rotation to off */ - common->wcmMaxX = 0; /* max digitizer logical X value */ - common->wcmMaxY = 0; /* max digitizer logical Y value */ - common->wcmMaxTouchX = 1024; /* max touch X value */ - common->wcmMaxTouchY = 1024; /* max touch Y value */ + common->wcmMaxX = 0; /* max tool logical X value */ + common->wcmMaxY = 0; /* max tool logical Y value */ common->wcmMaxZ = 0; /* max Z value */ + common->wcmResolX = 0; /* tool X resolution in + * points/inch for penabled + * points/mm for touch */ + common->wcmResolY = 0; /* tool Y resolution in + * points/inch for penabled + * points/mm for touch */ common->wcmMaxCapacity = 0; /* max capacity value */ common->wcmMaxDist = 0; /* max distance value */ - common->wcmResolX = 0; /* digitizer X resolution in points/inch */ - common->wcmResolY = 0; /* digitizer Y resolution in points/inch */ - common->wcmTouchResolX = 0; /* touch X resolution in points/mm */ - common->wcmTouchResolY = 0; /* touch Y resolution in points/mm */ common->wcmMaxStripX = 4096; /* Max fingerstrip X */ common->wcmMaxStripY = 4096; /* Max fingerstrip Y */ common->wcmMaxtiltX = 128; /* Max tilt in X directory */ @@ -233,6 +226,10 @@ LocalDevicePtr xf86WcmAllocate(char* name, int flag) /* transmit position if increment is superior */ common->wcmRawSample = DEFAULT_SAMPLES; /* number of raw data to be used to for filtering */ +#ifdef WCM_ENABLE_LINUXINPUT + common->wcmLastToolSerial = 0; + common->wcmEventCnt = 0; +#endif /* tool */ priv->tool = tool; @@ -379,9 +376,9 @@ static void xf86WcmUninit(InputDriverPtr drv, LocalDevicePtr local, int flags) DBG(1, priv->debugLevel, ErrorF("xf86WcmUninit\n")); - /* Xservers 1.4 and later but earlier than 1.6 need this call */ + /* Xservers 1.4 and later but earlier than 1.5.2 need this call */ #ifdef WCM_XORG_XSERVER_1_4 - #ifndef WCM_XORG_XSERVER_1_6 + #ifndef WCM_XORG_XSERVER_1_5_2 gWacomModule.DevProc(local->dev, DEVICE_OFF); #endif #endif @@ -427,6 +424,8 @@ static Bool xf86WcmMatchDevice(LocalDevicePtr pMatch, LocalDevicePtr pLocal) } xfree(common); common = priv->common = privMatch->common; + + /* insert the device to the front of the wcmDevices list */ priv->next = common->wcmDevices; common->wcmDevices = priv; return 1; @@ -434,235 +433,6 @@ static Bool xf86WcmMatchDevice(LocalDevicePtr pMatch, LocalDevicePtr pLocal) return 0; } -#ifdef WCM_XORG_XSERVER_1_4 - -/* xf86WcmCheckTypeAndSource - Check if both devices have the same type OR - * the device has been used in xorg.conf: don't add the tool by hal/udev - * if user has defined at least one tool for the device in xorg.conf */ - -static Bool xf86WcmCheckTypeAndSource(LocalDevicePtr fakeLocal, LocalDevicePtr pLocal) -{ - int match = 1; - char* fsource = xf86CheckStrOption(fakeLocal->options, "_source", ""); - char* psource = xf86CheckStrOption(pLocal->options, "_source", ""); - char* type = xf86FindOptionValue(fakeLocal->options, "Type"); - WacomDevicePtr priv = (WacomDevicePtr) pLocal->private; - - /* only add the new tool if the matching major/minor - * was from the same source */ - if (!strcmp(fsource, psource)) - { - /* and the tools have different types */ - if (strcmp(type, xf86FindOptionValue(pLocal->options, "Type"))) - match = 0; - } - DBG(2, priv->debugLevel, xf86Msg(X_INFO, "xf86WcmCheckTypeAndSource " - "device %s from %s %s \n", fakeLocal->name, fsource, - match ? "will be added" : "will be ignored")); - return match; -} - -/* check if the device has been added */ -static int wcmIsDuplicate(char* device, LocalDevicePtr local) -{ -#ifdef _XF86_ANSIC_H - struct xf86stat st; -#else - struct stat st; -#endif - int isInUse = 0; - LocalDevicePtr localDevices = NULL; - WacomCommonPtr common = NULL; - - /* open the port */ - do { - local->fd = open(device, O_RDONLY, 0); - } while (local->fd < 0 && errno == EINTR); - - if (local->fd < 0) - { - /* can not open the device */ - xf86Msg(X_ERROR, "Unable to open Wacom device \"%s\".\n", device); - isInUse = 2; - goto ret; - } - -#ifdef _XF86_ANSIC_H - if (xf86fstat(local->fd, &st) == -1) -#else - if (fstat(local->fd, &st) == -1) -#endif - { - /* can not access major/minor to check device duplication */ - xf86Msg(X_ERROR, "%s: stat failed (%s). cannot check for duplicates.\n", - local->name, strerror(errno)); - - /* older systems don't support the required ioctl. let it pass */ - goto ret; - } - - if ((int)st.st_rdev) - { - localDevices = xf86FirstLocalDevice(); - - for (; localDevices != NULL; localDevices = localDevices->next) - { - device = xf86CheckStrOption(localDevices->options, "Device", NULL); - - /* device can be NULL on some distros */ - if (!device || !strstr(localDevices->drv->driverName, "wacom")) - continue; - - common = ((WacomDevicePtr)localDevices->private)->common; - if (local != localDevices && - common->min_maj && - common->min_maj == st.st_rdev) - { - /* device matches with another added port */ - if (xf86WcmCheckTypeAndSource(local, localDevices)) - { - xf86Msg(X_WARNING, "%s: device file already in use by %s. " - "Ignoring.\n", local->name, localDevices->name); - isInUse = 4; - goto ret; - } - } - } - } - else - { - /* major/minor can never be 0, right? */ - xf86Msg(X_ERROR, "%s: device opened with a major/minor of 0. " - "Something was wrong.\n", local->name); - isInUse = 5; - } -ret: - if (local->fd >= 0) - { - close(local->fd); - local->fd = -1; - } - return isInUse; -} - -static struct -{ - __u16 productID; - __u16 flags; -} validType [] = -{ - { 0x00, STYLUS_ID }, /* PenPartner */ - { 0x10, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire */ - { 0x11, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire2 4x5 */ - { 0x12, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire2 5x7 */ - - { 0x13, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire3 4x5 */ - { 0x14, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire3 6x8 */ - - { 0x15, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Graphire4 4x5 */ - { 0x16, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Graphire4 6x8 */ - { 0x17, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* BambooFun 4x5 */ - { 0x18, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* BambooFun 6x8 */ - { 0x19, STYLUS_ID | ERASER_ID }, /* Bamboo1 Medium*/ - { 0x81, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Graphire4 6x8 BlueTooth */ - - { 0x20, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 4x5 */ - { 0x21, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 6x8 */ - { 0x22, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 9x12 */ - { 0x23, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 12x12 */ - { 0x24, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 12x18 */ - - { 0x03, STYLUS_ID | ERASER_ID }, /* PTU600 */ - { 0x30, STYLUS_ID | ERASER_ID }, /* PL400 */ - { 0x31, STYLUS_ID | ERASER_ID }, /* PL500 */ - { 0x32, STYLUS_ID | ERASER_ID }, /* PL600 */ - { 0x33, STYLUS_ID | ERASER_ID }, /* PL600SX */ - { 0x34, STYLUS_ID | ERASER_ID }, /* PL550 */ - { 0x35, STYLUS_ID | ERASER_ID }, /* PL800 */ - { 0x37, STYLUS_ID | ERASER_ID }, /* PL700 */ - { 0x38, STYLUS_ID | ERASER_ID }, /* PL510 */ - { 0x39, STYLUS_ID | ERASER_ID }, /* PL710 */ - { 0xC0, STYLUS_ID | ERASER_ID }, /* DTF720 */ - { 0xC2, STYLUS_ID | ERASER_ID }, /* DTF720a */ - { 0xC4, STYLUS_ID | ERASER_ID }, /* DTF521 */ - { 0xC7, STYLUS_ID | ERASER_ID }, /* DTU1931 */ - - { 0x41, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 4x5 */ - { 0x42, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 6x8 */ - { 0x43, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 9x12 */ - { 0x44, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 12x12 */ - { 0x45, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 12x18 */ - { 0x47, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 6x8 */ - - { 0x60, STYLUS_ID }, /* Volito */ - { 0x61, STYLUS_ID }, /* PenStation */ - { 0x62, STYLUS_ID }, /* Volito2 4x5 */ - { 0x63, STYLUS_ID }, /* Volito2 2x3 */ - { 0x64, STYLUS_ID }, /* PenPartner2 */ - - { 0x65, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Bamboo */ - { 0x69, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Bamboo1 */ - - { 0xB0, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 4x5 */ - { 0xB1, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 6x8 */ - { 0xB2, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 9x12 */ - { 0xB3, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 12x12 */ - { 0xB4, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 12x19 */ - { 0xB5, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 6x11 */ - { 0xB7, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 4x6 */ - - { 0xB8, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 4x6 */ - { 0xB9, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 6x9 */ - { 0xBA, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 8x13 */ - { 0xBB, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 12x19*/ - - { 0x3F, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Cintiq 21UX */ - { 0xC5, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Cintiq 20WSX */ - { 0xC6, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Cintiq 12WX */ - - { 0x90, STYLUS_ID | ERASER_ID }, /* TabletPC 0x90 */ - { 0x93, STYLUS_ID | ERASER_ID | TOUCH_ID }, /* TabletPC 0x93 */ - { 0x9A, STYLUS_ID | ERASER_ID | TOUCH_ID }, /* TabletPC 0x9A */ - { 0x9F, TOUCH_ID }, /* CapPlus 0x9F */ - { 0xE2, TOUCH_ID }, /* TabletPC 0xE2 */ - { 0xE3, STYLUS_ID | ERASER_ID | TOUCH_ID } /* TabletPC 0xE3 */ -}; - -static struct -{ - const char* type; - __u16 id; -} wcmTypeAndID [] = -{ - { "stylus", STYLUS_ID }, - { "eraser", ERASER_ID }, - { "cursor", CURSOR_ID }, - { "touch", TOUCH_ID }, - { "pad", PAD_ID } -}; - -/* validate tool type for device/product */ -static int wcmIsAValidType(char* device, LocalDevicePtr local, unsigned short id) -{ - int i, j, ret = 0; - char* type = xf86FindOptionValue(local->options, "Type"); - - /* walkthrough all supported models */ - for (i = 0; i < sizeof (validType) / sizeof (validType [0]); i++) - { - if (validType[i].productID == id) - { - - /* walkthrough all types */ - for (j = 0; j < sizeof (wcmTypeAndID) / sizeof (wcmTypeAndID [0]); j++) - if (!strcmp(wcmTypeAndID[j].type, type)) - if (wcmTypeAndID[j].id & validType[i].flags) - ret = 1; - } - } - return ret; -} -#endif /* WCM_XORG_XSERVER_1_4 */ /* xf86WcmInit - called when the module subsection is found in XF86Config */ static LocalDevicePtr xf86WcmInit(InputDriverPtr drv, IDevPtr dev, int flags) @@ -704,11 +474,11 @@ static LocalDevicePtr xf86WcmInit(InputDriverPtr drv, IDevPtr dev, int flags) if (!xf86WcmIsWacomDevice(device, &id)) goto SetupProc_fail; - /* check if the type is valid for the device */ + /* check if the type is valid for the device */ if(!wcmIsAValidType(device, fakeLocal, id.product)) goto SetupProc_fail; - /* check if the device has been added */ + /* check if the device has been added */ if (wcmIsDuplicate(device, fakeLocal)) goto SetupProc_fail; } @@ -1046,26 +816,20 @@ static LocalDevicePtr xf86WcmInit(InputDriverPtr drv, IDevPtr dev, int flags) xf86Msg(X_CONFIG, "%s: threshold = %d\n", dev->identifier, common->wcmThreshold); - priv->wcmMaxX = xf86SetIntOption(local->options, "MaxX", + common->wcmMaxX = xf86SetIntOption(local->options, "MaxX", common->wcmMaxX); - if (priv->wcmMaxX > 0) + if (common->wcmMaxX > 0) { - xf86Msg(X_CONFIG, "%s: max x set to %d by xorg.conf\n", dev->identifier, - priv->wcmMaxX); - - /* Update tablet logical max X */ - if (!IsTouch(priv)) common->wcmMaxX = priv->wcmMaxX; + xf86Msg(X_CONFIG, "%s: max x set to %d \n", dev->identifier, + common->wcmMaxX); } - priv->wcmMaxY = xf86SetIntOption(local->options, "MaxY", + common->wcmMaxY = xf86SetIntOption(local->options, "MaxY", common->wcmMaxY); - if (priv->wcmMaxY > 0) + if (common->wcmMaxY > 0) { - xf86Msg(X_CONFIG, "%s: max y set to %d by xorg.conf\n", dev->identifier, - priv->wcmMaxY); - - /* Update tablet logical max Y */ - if (!IsTouch(priv)) common->wcmMaxY = priv->wcmMaxY; + xf86Msg(X_CONFIG, "%s: max y set to %d \n", dev->identifier, + common->wcmMaxY); } common->wcmMaxZ = xf86SetIntOption(local->options, "MaxZ", diff --git a/src/xdrv/wcmISDV4.c b/src/xdrv/wcmISDV4.c index 6f05393..1f7aa87 100755 --- a/src/xdrv/wcmISDV4.c +++ b/src/xdrv/wcmISDV4.c @@ -23,7 +23,7 @@ static Bool isdv4Detect(LocalDevicePtr); static Bool isdv4Init(LocalDevicePtr, char* id, float *version); -static void isdv4InitISDV4(WacomCommonPtr, const char* id, float version); +static void isdv4InitISDV4(WacomCommonPtr common, const char* id, float version); static int isdv4GetRanges(LocalDevicePtr); static int isdv4StartTablet(LocalDevicePtr); static int isdv4Parse(LocalDevicePtr, const unsigned char* data); @@ -235,7 +235,7 @@ static int isdv4GetRanges(LocalDevicePtr local) /* (data[2] & 0x07) == 0 is for resistive touch */ if (!(data[2] & 0x07) && data[1]) { - common->wcmMaxTouchX = common->wcmMaxTouchY = (int)(1 << data[1]); + common->wcmMaxX = common->wcmMaxY = (int)(1 << data[1]); } if ((data[0] & 0x41) && (data[2] & 0x07)) @@ -257,7 +257,7 @@ static int isdv4GetRanges(LocalDevicePtr local) /* touch logical size for tablet PC with touch */ if (data[1]) { - common->wcmMaxTouchX = common->wcmMaxTouchY = (int)(1 << data[1]); + common->wcmMaxX = common->wcmMaxY = (int)(1 << data[1]); } /* Max capacity */ @@ -265,9 +265,9 @@ static int isdv4GetRanges(LocalDevicePtr local) if (common->wcmMaxCapacity) { - common->wcmTouchResolX = common->wcmMaxTouchX / ( 2540 * + common->wcmResolX = common->wcmMaxX / ( 2540 * ((data[3] << 9) | (data[4] << 2) | ((data[2] & 0x60) >> 5))); - common->wcmTouchResolX = common->wcmMaxTouchX / ( 2540 * + common->wcmResolX = common->wcmMaxX / ( 2540 * ((data[5] << 9) | (data[6] << 2) | ((data[2] & 0x18) >> 3))); } } @@ -283,21 +283,12 @@ static int isdv4GetRanges(LocalDevicePtr local) * defaults to enable when it is a touch device */ common->wcmTouchDefault = 1; - - if (common->wcmMaxX && common->wcmMaxY && !common->wcmTouchResolX) - { - /* Some touch tablet don't report physical size */ - common->wcmTouchResolX = (int)((double)(common->wcmMaxTouchX * - common->wcmResolX) / (double)common->wcmMaxX + 0.5); - common->wcmTouchResolY = (int)((double)(common->wcmMaxTouchY * - common->wcmResolY) / (double)common->wcmMaxY + 0.5); - } } DBG(2, priv->debugLevel, ErrorF("isdv4GetRanges speed=%d maxX=%d maxY=%d " "maxZ=%d TouchresX=%d TouchresY=%d \n", common->wcmISDV4Speed, common->wcmMaxX, common->wcmMaxY, common->wcmMaxZ, - common->wcmTouchResolX, common->wcmTouchResolY)); + common->wcmResolX, common->wcmResolY)); return Success; } @@ -328,6 +319,7 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned char* data) DBG(10, common->debugLevel, ErrorF("isdv4Parse \n")); + channel = 0; /* determine the type of message (touch or stylus)*/ if (data[0] & 0x18) /* not a pen */ { @@ -353,7 +345,7 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned char* data) else if (!(data[0] & 0x01)) /* touch out-prox */ { touchInProx = 0; - channel = 1; + channel = 0; } else { @@ -374,9 +366,7 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned char* data) if (common->wcmChannel[1].valid.state.proximity) { /* let touch go */ - WacomDeviceState out = { 0 }; - out.device_type = TOUCH_ID; - xf86WcmEvent(common, 1, &out); + xf86WcmSoftOut(common, 1); return 0; } common->wcmPktLength = WACOM_PKGLEN_TPC; @@ -402,7 +392,8 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned char* data) ds = &common->wcmChannel[channel].work; RESET_RELATIVE(*ds); - if (common->wcmPktLength == WACOM_PKGLEN_TOUCH0 || common->wcmPktLength == WACOM_PKGLEN_TOUCH) /* a touch */ + if (common->wcmPktLength == WACOM_PKGLEN_TOUCH0 || + common->wcmPktLength == WACOM_PKGLEN_TOUCH) /* a touch */ { /* touch without capacity has 5 bytes of data * touch with capacity has 7 bytes of data @@ -450,8 +441,7 @@ static int isdv4Parse(LocalDevicePtr local, const unsigned char* data) (ds->device_type == ERASER_ID)) { /* send a prox-out for old device */ - WacomDeviceState out = { 0 }; - xf86WcmEvent(common, 0, &out); + xf86WcmSoftOut(common, 0); ds->device_type = cur_type; } } diff --git a/src/xdrv/wcmMapping.c b/src/xdrv/wcmMapping.c new file mode 100755 index 0000000..7b1caed --- /dev/null +++ b/src/xdrv/wcmMapping.c @@ -0,0 +1,874 @@ +/* + * Copyright 2009 by Ping Cheng, Wacom Technology. <pingc@wacom.com> + * + * 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "xf86Wacom.h" +#include "../include/Xwacom.h" + +static void xf86WcmInitialScreens(LocalDevicePtr local); + + +/***************************************************************************** + * xf86WcmDesktopSize -- + * calculate the whole desktop size + ****************************************************************************/ +static void xf86WcmDesktopSize(LocalDevicePtr local) +{ + WacomDevicePtr priv = (WacomDevicePtr) local->private; + int i = 0, minX = 0, minY = 0, maxX = 0, maxY = 0; + + xf86WcmInitialScreens(local); + + minX = priv->screenTopX[0]; + minY = priv->screenTopY[0]; + maxX = priv->screenBottomX[0]; + maxY = priv->screenBottomY[0]; + + if (priv->numScreen != 1) + { + for (i = 1; i < priv->numScreen; i++) + { + if (priv->screenTopX[i] < minX) + minX = priv->screenTopX[i]; + if (priv->screenTopY[i] < minY) + minY = priv->screenTopY[i]; + if (priv->screenBottomX[i] > maxX) + maxX = priv->screenBottomX[i]; + if (priv->screenBottomY[i] > maxY) + maxY = priv->screenBottomY[i]; + } + } + + priv->maxWidth = maxX - minX; + priv->maxHeight = maxY - minY; +} + +int xf86WcmInitArea(LocalDevicePtr local) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + WacomToolAreaPtr area = priv->toolarea, inlist; + WacomCommonPtr common = priv->common; + double screenRatio, tabletRatio; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmInitArea\n")); + + /* Verify Box */ + if (priv->topX > common->wcmMaxX) + { + area->topX = priv->topX = 0; + } + + if (priv->topY > common->wcmMaxY) + { + area->topY = priv->topY = 0; + } + + /* set unconfigured bottom to max */ + priv->bottomX = xf86SetIntOption(local->options, "BottomX", 0); + if (priv->bottomX < priv->topX || !priv->bottomX) + { + area->bottomX = priv->bottomX = common->wcmMaxX; + } + + /* set unconfigured bottom to max */ + priv->bottomY = xf86SetIntOption(local->options, "BottomY", 0); + if (priv->bottomY < priv->topY || !priv->bottomY) + { + area->bottomY = priv->bottomY = common->wcmMaxY; + } + + if (priv->twinview > TV_XINERAMA) + priv->numScreen = 2; + + if (priv->screen_no != -1 && + (priv->screen_no >= priv->numScreen || priv->screen_no < 0)) + { + if (priv->twinview <= TV_XINERAMA) + { + ErrorF("%s: invalid screen number %d, resetting to default (-1) \n", + local->name, priv->screen_no); + priv->screen_no = -1; + } + else if (priv->screen_no > 1) + { + ErrorF("%s: invalid screen number %d, resetting to default (-1) \n", + local->name, priv->screen_no); + priv->screen_no = -1; + } + } + + /* need maxWidth and maxHeight for keepshape */ + xf86WcmDesktopSize(local); + + /* Maintain aspect ratio to the whole desktop + * May need to consider a specific screen in multimonitor settings + */ + if (priv->flags & KEEP_SHAPE_FLAG) + { + + screenRatio = ((double)priv->maxWidth / (double)priv->maxHeight); + tabletRatio = ((double)(common->wcmMaxX - priv->topX) / + (double)(common->wcmMaxY - priv->topY)); + + DBG(2, priv->debugLevel, ErrorF("screenRatio = %.3g, " + "tabletRatio = %.3g\n", screenRatio, tabletRatio)); + + if (screenRatio > tabletRatio) + { + area->bottomX = priv->bottomX = common->wcmMaxX; + area->bottomY = priv->bottomY = (common->wcmMaxY - priv->topY) * + tabletRatio / screenRatio + priv->topY; + } + else + { + area->bottomX = priv->bottomX = (common->wcmMaxX - priv->topX) * + screenRatio / tabletRatio + priv->topX; + area->bottomY = priv->bottomY = common->wcmMaxY; + } + } + /* end keep shape */ + + inlist = priv->tool->arealist; + + /* The first one in the list is always valid */ + if (area != inlist && xf86WcmAreaListOverlap(area, inlist)) + { + inlist = priv->tool->arealist; + + /* remove this overlapped area from the list */ + for (; inlist; inlist=inlist->next) + { + if (inlist->next == area) + { + inlist->next = area->next; + xfree(area); + priv->toolarea = NULL; + break; + } + } + + /* Remove this device from the common struct */ + if (common->wcmDevices == priv) + common->wcmDevices = priv->next; + else + { + WacomDevicePtr tmp = common->wcmDevices; + while(tmp->next && tmp->next != priv) + tmp = tmp->next; + if(tmp) + tmp->next = priv->next; + } + xf86Msg(X_ERROR, "%s: Top/Bottom area overlaps with another devices.\n", + local->conf_idev->identifier); + return FALSE; + } + return TRUE; +} + +/***************************************************************************** + * xf86WcmVirtaulTabletSize(LocalDevicePtr local) + ****************************************************************************/ + +void xf86WcmVirtaulTabletSize(LocalDevicePtr local) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + + if (!(priv->flags & ABSOLUTE_FLAG)) + { + priv->sizeX = priv->bottomX - priv->topX; + priv->sizeY = priv->bottomY - priv->topY; + return; + } + + priv->sizeX = priv->bottomX - priv->topX - priv->tvoffsetX; + priv->sizeY = priv->bottomY - priv->topY - priv->tvoffsetY; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmVirtaulTabletSize for \"%s\" " + "x=%d y=%d \n", local->name, priv->sizeX, priv->sizeY)); + return; +} + +/***************************************************************************** + * xf86WcmInitialCoordinates + ****************************************************************************/ + +void xf86WcmInitialCoordinates(LocalDevicePtr local, int axes) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + int topx = 0, topy = 0, resolution; + WacomCommonPtr common = priv->common; + int bottomx = common->wcmMaxX, bottomy = common->wcmMaxY; + + xf86WcmMappingFactor(local); + + /* x ax */ + if ( !axes ) + { + if (priv->flags & ABSOLUTE_FLAG) + { + topx = priv->topX; + bottomx = priv->sizeX + priv->topX; + if ((priv->currentScreen == 1) && (priv->twinview > TV_XINERAMA)) + topx += priv->tvoffsetX; + if ((priv->currentScreen == 0) && (priv->twinview > TV_XINERAMA)) + bottomx -= priv->tvoffsetX; + } + + resolution = common->wcmResolX; +#ifdef WCM_XORG_TABLET_SCALING + /* Ugly hack for Xorg 7.3, which doesn't call xf86WcmDevConvert + * for coordinate conversion at the moment */ + topx = 0; + bottomx = priv->sizeX; + if ((priv->twinview == TV_LEFT_RIGHT) || (priv->twinview == TV_RIGHT_LEFT)) + bottomx *= 2; + bottomx = (int)((double)bottomx * priv->factorX + 0.5); + resolution = (int)((double)resolution * priv->factorX + 0.5); +#endif + + InitValuatorAxisStruct(local->dev, 0, topx, bottomx, + resolution, 0, resolution); + } + else /* y ax */ + { + if (priv->flags & ABSOLUTE_FLAG) + { + topy = priv->topY; + bottomy = priv->sizeY + priv->topY; + if ((priv->currentScreen == 1) && (priv->twinview > TV_XINERAMA)) + topy += priv->tvoffsetY; + if ((priv->currentScreen == 0) && (priv->twinview > TV_XINERAMA)) + bottomy -= priv->tvoffsetY; + } + + resolution = common->wcmResolY; +#ifdef WCM_XORG_TABLET_SCALING + /* Ugly hack for Xorg 7.3, which doesn't call xf86WcmDevConvert + * for coordinate conversion at the moment */ + topy = 0; + bottomy = priv->sizeY; + if ((priv->twinview == TV_ABOVE_BELOW) || (priv->twinview == TV_BELOW_ABOVE)) + bottomy *= 2; + bottomy = (int)((double)bottomy * priv->factorY + 0.5); + resolution = (int)((double)resolution * priv->factorY + 0.5); +#endif + + InitValuatorAxisStruct(local->dev, 1, topy, bottomy, + resolution, 0, resolution); + } + return; +} + +/***************************************************************************** + * xf86WcmMappingFactor -- + * calculate the proper tablet to screen mapping factor according to the + * screen/desktop size and the tablet size + ****************************************************************************/ + +void xf86WcmMappingFactor(LocalDevicePtr local) +{ + WacomDevicePtr priv = (WacomDevicePtr) local->private; + int screenX, screenY; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmMappingFactor \n")); + + xf86WcmVirtaulTabletSize(local); + + if (!(priv->flags & ABSOLUTE_FLAG) || !priv->wcmMMonitor) + { + /* Get the current screen that the cursor is in */ +#if WCM_XINPUTABI_MAJOR == 0 + if (miPointerCurrentScreen()) + priv->currentScreen = miPointerCurrentScreen()->myNum; +#else + if (miPointerGetScreen(local->dev)) + priv->currentScreen = miPointerGetScreen(local->dev)->myNum; +#endif + } + else + { + if (priv->screen_no != -1) + priv->currentScreen = priv->screen_no; + else if (priv->currentScreen == -1) + { + /* Get the current screen that the cursor is in */ +#if WCM_XINPUTABI_MAJOR == 0 + if (miPointerCurrentScreen()) + priv->currentScreen = miPointerCurrentScreen()->myNum; +#else + if (miPointerGetScreen(local->dev)) + priv->currentScreen = miPointerGetScreen(local->dev)->myNum; +#endif + } + } + if (priv->currentScreen == -1) /* tool on the tablet */ + priv->currentScreen = 0; + + screenX = priv->maxWidth; + screenY = priv->maxHeight; + if (priv->screen_no != -1 || (priv->twinview > TV_XINERAMA) || (!priv->wcmMMonitor) ) + { + screenX = priv->screenBottomX[priv->currentScreen] - priv->screenTopX[priv->currentScreen]; + screenY = priv->screenBottomY[priv->currentScreen] - priv->screenTopY[priv->currentScreen]; + } + DBG(10, priv->debugLevel, ErrorF("xf86WcmMappingFactor" + " Active tablet area x=%d y=%d (virtual tablet area x=%d y=%d) map" + " to maxWidth =%d maxHeight =%d\n", + priv->bottomX, priv->bottomY, priv->sizeX, priv->sizeY, + screenX, screenY)); + + priv->factorX = (double)screenX / (double)priv->sizeX; + priv->factorY = (double)screenY / (double)priv->sizeY; + DBG(2, priv->debugLevel, ErrorF("X factor = %.3g, Y factor = %.3g\n", + priv->factorX, priv->factorY)); +} + +/***************************************************************************** + * xf86WcmSetScreen -- + * set to the proper screen according to the converted (x,y). + * this only supports for horizontal setup now. + * need to know screen's origin (x,y) to support + * combined horizontal and vertical setups + ****************************************************************************/ + +void xf86WcmSetScreen(LocalDevicePtr local, int v0, int v1) +{ + WacomDevicePtr priv = (WacomDevicePtr) local->private; + int screenToSet = -1, i, j, x, y, tabletSize = 0; + + DBG(6, priv->debugLevel, ErrorF("xf86WcmSetScreen v0=%d v1=%d " + "currentScreen=%d\n", v0, v1, priv->currentScreen)); + + if (priv->screen_no != -1 && priv->screen_no >= priv->numScreen) + { + ErrorF("xf86WcmSetScreen Screen%d is larger than number of available screens (%d)\n", + priv->screen_no, priv->numScreen); + priv->screen_no = -1; + } + + if (!(local->flags & (XI86_ALWAYS_CORE | XI86_CORE_POINTER))) return; + + if (priv->twinview > TV_XINERAMA && priv->screen_no == -1 && (priv->flags & ABSOLUTE_FLAG)) + { + if (priv->twinview == TV_LEFT_RIGHT) + { + tabletSize = priv->bottomX - priv->tvoffsetX; + if (v0 > tabletSize && v0 <= priv->bottomX) + priv->currentScreen = 1; + if (v0 > priv->topX && v0 <= priv->topX + priv->tvoffsetX) + priv->currentScreen = 0; + } + if (priv->twinview == TV_ABOVE_BELOW) + { + tabletSize = priv->bottomY - priv->tvoffsetY; + if (v0 > tabletSize && v0 <= priv->bottomY) + priv->currentScreen = 1; + if (v0 > priv->topY && v0 <= priv->topY + priv->tvoffsetY) + priv->currentScreen = 0; + } + if (priv->twinview == TV_RIGHT_LEFT) + { + tabletSize = priv->bottomX - priv->tvoffsetX; + if (v0 > tabletSize && v0 <= priv->bottomX) + priv->currentScreen = 0; + if (v0 > priv->topX && v0 <= priv->topX + priv->tvoffsetX) + priv->currentScreen = 1; + } + if (priv->twinview == TV_BELOW_ABOVE) + { + tabletSize = priv->bottomY - priv->tvoffsetY; + if (v0 > tabletSize && v0 <= priv->bottomY) + priv->currentScreen = 0; + if (v0 > priv->topY && v0 <= priv->topY + priv->tvoffsetY) + priv->currentScreen = 1; + } + DBG(10, priv->debugLevel, ErrorF("xf86WcmSetScreen TwinView setup screenToSet=%d\n", + priv->currentScreen)); + } + + xf86WcmMappingFactor(local); + if (!(priv->flags & ABSOLUTE_FLAG) || screenInfo.numScreens == 1 || !priv->wcmMMonitor) + return; + + v0 = v0 - priv->topX; + v1 = v1 - priv->topY; + + if (priv->screen_no == -1) + { + for (i = 0; i < priv->numScreen; i++) + { + if (v0 * priv->factorX >= priv->screenTopX[i] && + v0 * priv->factorX < priv->screenBottomX[i] - 0.5) + { + + for (j = 0; j < priv->numScreen; j++) + { + if (v1 * priv->factorY >= priv->screenTopY[j] && + v1 * priv->factorY <= priv->screenBottomY[j] - 0.5) + { + if (j == i) + { + screenToSet = i; + break; + } + } + } + + if (screenToSet != -1) + break; + } + } + } + else + screenToSet = priv->screen_no; + + if (screenToSet == -1) + { + DBG(3, priv->debugLevel, ErrorF("xf86WcmSetScreen Error: " + "Can not find valid screen (currentScreen=%d)\n", + priv->currentScreen)); + return; + } + + priv->currentScreen = screenToSet; + xf86WcmMappingFactor(local); + x = ((double)v0 * priv->factorX) - priv->screenTopX[screenToSet] + 0.5; + y = ((double)v1 * priv->factorY) - priv->screenTopY[screenToSet] + 0.5; + + if (x >= screenInfo.screens[screenToSet]->width) + x = screenInfo.screens[screenToSet]->width - 1; + if (y >= screenInfo.screens[screenToSet]->height) + y = screenInfo.screens[screenToSet]->height - 1; + + xf86XInputSetScreen(local, screenToSet, x, y); + DBG(10, priv->debugLevel, ErrorF("xf86WcmSetScreen current=%d ToSet=%d\n", + priv->currentScreen, screenToSet)); +} + +/***************************************************************************** + * xf86WcmInitTablet -- common initialization for all tablets + ****************************************************************************/ + +int xf86WcmInitTablet(LocalDevicePtr local, const char* id, float version) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + WacomCommonPtr common = priv->common; + WacomModelPtr model = common->wcmModel; + + /* Initialize the tablet */ + model->Initialize(common,id,version); + + /* Get tablet resolution */ + if (model->GetResolution) + model->GetResolution(local); + + /* Get tablet range */ + if (model->GetRanges && (model->GetRanges(local) != Success)) + return !Success; + + /* Default threshold value if not set */ + if (common->wcmThreshold <= 0) + { + /* Threshold for counting pressure as a button */ + if (strstr(common->wcmModel->name, "Intuos4")) + common->wcmThreshold = common->wcmMaxZ * 3 / 25; + else + common->wcmThreshold = common->wcmMaxZ * 3 / 50; + ErrorF("%s Wacom using pressure threshold of %d for button 1\n", + XCONFIG_PROBED, common->wcmThreshold); + } + + /* Reset tablet to known state */ + if (model->Reset && (model->Reset(local) != Success)) + { + ErrorF("Wacom xf86WcmWrite error : %s\n", strerror(errno)); + return !Success; + } + + /* Enable tilt mode, if requested and available */ + if ((common->wcmFlags & TILT_REQUEST_FLAG) && model->EnableTilt) + { + if (model->EnableTilt(local) != Success) + return !Success; + } + + /* Enable hardware suppress, if requested and available */ + if (model->EnableSuppress) + { + if (model->EnableSuppress(local) != Success) + return !Success; + } + + /* change the serial speed, if requested */ + if (model->SetLinkSpeed) + { + if (common->wcmLinkSpeed != 9600) + { + if (model->SetLinkSpeed(local) != Success) + return !Success; + } + } + else + { + DBG(2, common->debugLevel, ErrorF("Tablet does not support setting link " + "speed, or not yet implemented\n")); + } + + /* output tablet state as probed */ + if (xf86Verbose) + ErrorF("%s Wacom %s tablet speed=%d (%d) maxX=%d maxY=%d maxZ=%d " + "resX=%d resY=%d tilt=%s\n", + XCONFIG_PROBED, + model->name, common->wcmLinkSpeed, common->wcmISDV4Speed, + common->wcmMaxX, common->wcmMaxY, common->wcmMaxZ, + common->wcmResolX, common->wcmResolY, + HANDLE_TILT(common) ? "enabled" : "disabled"); + + /* start the tablet data */ + if (model->Start && (model->Start(local) != Success)) + return !Success; + + return Success; +} + +/***************************************************************************** + * xf86WcmInitialTVScreens + ****************************************************************************/ + +static void xf86WcmInitialTVScreens(LocalDevicePtr local) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + + if (priv->twinview <= TV_XINERAMA) + return; + + priv->numScreen = 2; + + if ((priv->twinview == TV_LEFT_RIGHT) || (priv->twinview == TV_RIGHT_LEFT)) + { + /* it does not need the offset if always map to a specific screen */ + if (priv->screen_no == -1) + { + priv->tvoffsetX = 60; + priv->tvoffsetY = 0; + } + + /* default resolution */ + if(!priv->tvResolution[0]) + { + priv->tvResolution[0] = screenInfo.screens[0]->width/2; + priv->tvResolution[1] = screenInfo.screens[0]->height; + priv->tvResolution[2] = priv->tvResolution[0]; + priv->tvResolution[3] = priv->tvResolution[1]; + } + } + else if ((priv->twinview == TV_ABOVE_BELOW) || (priv->twinview == TV_BELOW_ABOVE)) + { + /* it does not need the offset if always map to a specific screen */ + if (priv->screen_no == -1) + { + priv->tvoffsetX = 0; + priv->tvoffsetY = 60; + } + + /* default resolution */ + if(!priv->tvResolution[0]) + { + priv->tvResolution[0] = screenInfo.screens[0]->width; + priv->tvResolution[1] = screenInfo.screens[0]->height/2; + priv->tvResolution[2] = priv->tvResolution[0]; + priv->tvResolution[3] = priv->tvResolution[1]; + } + } + + /* initial screen info */ + if (priv->twinview == TV_ABOVE_BELOW) + { + priv->screenTopX[0] = 0; + priv->screenTopY[0] = 0; + priv->screenBottomX[0] = priv->tvResolution[0]; + priv->screenBottomY[0] = priv->tvResolution[1]; + priv->screenTopX[1] = 0; + priv->screenTopY[1] = priv->tvResolution[1]; + priv->screenBottomX[1] = priv->tvResolution[2]; + priv->screenBottomY[1] = priv->tvResolution[1] + priv->tvResolution[3]; + } + if (priv->twinview == TV_LEFT_RIGHT) + { + priv->screenTopX[0] = 0; + priv->screenTopY[0] = 0; + priv->screenBottomX[0] = priv->tvResolution[0]; + priv->screenBottomY[0] = priv->tvResolution[1]; + priv->screenTopX[1] = priv->tvResolution[0]; + priv->screenTopY[1] = 0; + priv->screenBottomX[1] = priv->tvResolution[0] + priv->tvResolution[2]; + priv->screenBottomY[1] = priv->tvResolution[3]; + } + if (priv->twinview == TV_BELOW_ABOVE) + { + priv->screenTopX[0] = 0; + priv->screenTopY[0] = priv->tvResolution[1]; + priv->screenBottomX[0] = priv->tvResolution[2]; + priv->screenBottomY[0] = priv->tvResolution[1] + priv->tvResolution[3]; + priv->screenTopX[1] = 0; + priv->screenTopY[1] = 0; + priv->screenBottomX[1] = priv->tvResolution[0]; + priv->screenBottomY[1] = priv->tvResolution[1]; + } + if (priv->twinview == TV_RIGHT_LEFT) + { + priv->screenTopX[0] = priv->tvResolution[0]; + priv->screenTopY[0] = 0; + priv->screenBottomX[0] = priv->tvResolution[0] + priv->tvResolution[2]; + priv->screenBottomY[0] = priv->tvResolution[3]; + priv->screenTopX[1] = 0; + priv->screenTopY[1] = 0; + priv->screenBottomX[1] = priv->tvResolution[0]; + priv->screenBottomY[1] = priv->tvResolution[1]; + } + + DBG(10, priv->debugLevel, ErrorF("xf86WcmInitialTVScreens for \"%s\" " + "topX0=%d topY0=%d bottomX0=%d bottomY0=%d " + "topX1=%d topY1=%d bottomX1=%d bottomY1=%d \n", + local->name, priv->screenTopX[0], priv->screenTopY[0], + priv->screenBottomX[0], priv->screenBottomY[0], + priv->screenTopX[1], priv->screenTopY[1], + priv->screenBottomX[1], priv->screenBottomY[1])); +} + +/***************************************************************************** + * xf86WcmInitialScreens + ****************************************************************************/ + +static void xf86WcmInitialScreens(LocalDevicePtr local) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + int i; + + DBG(2, priv->debugLevel, ErrorF("xf86WcmInitialScreens for \"%s\" " + "number of screen=%d \n", local->name, screenInfo.numScreens)); + priv->tvoffsetX = 0; + priv->tvoffsetY = 0; + if (priv->twinview > TV_XINERAMA) + { + xf86WcmInitialTVScreens(local); + return; + } + + /* initial screen info */ + priv->numScreen = screenInfo.numScreens; + priv->screenTopX[0] = 0; + priv->screenTopY[0] = 0; + priv->screenBottomX[0] = 0; + priv->screenBottomY[0] = 0; + for (i=0; i<screenInfo.numScreens; i++) + { +#ifdef WCM_HAVE_DIXSCREENORIGINS + if (screenInfo.numScreens > 1) + { + priv->screenTopX[i] = dixScreenOrigins[i].x; + priv->screenTopY[i] = dixScreenOrigins[i].y; + priv->screenBottomX[i] = dixScreenOrigins[i].x; + priv->screenBottomY[i] = dixScreenOrigins[i].y; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmInitialScreens from dix for \"%s\" " + "ScreenOrigins[%d].x=%d ScreenOrigins[%d].y=%d \n", + local->name, i, priv->screenTopX[i], i, priv->screenTopY[i])); + } +#else /* WCM_HAVE_DIXSCREENORIGINS */ + if (i > 0) + { + /* only support left to right in this case */ + priv->screenTopX[i] = priv->screenBottomX[i-1]; + priv->screenTopY[i] = 0; + priv->screenBottomX[i] = priv->screenTopX[i]; + priv->screenBottomY[i] = 0; + } +#endif /* WCM_HAVE_DIXSCREENORIGINS */ + priv->screenBottomX[i] += screenInfo.screens[i]->width; + priv->screenBottomY[i] += screenInfo.screens[i]->height; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmInitialScreens for \"%s\" " + "topX[%d]=%d topY[%d]=%d bottomX[%d]=%d bottomY[%d]=%d \n", + local->name, i, priv->screenTopX[i], i, priv->screenTopY[i], + i, priv->screenBottomX[i], i, priv->screenBottomY[i])); + } +} + +/***************************************************************************** + * xf86WcmChangeScreen + ****************************************************************************/ + +void xf86WcmChangeScreen(LocalDevicePtr local, int value) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + + if (priv->screen_no != value) + { + priv->screen_no = value; + xf86ReplaceIntOption(local->options, "ScreenNo", value); + } + + if (priv->screen_no != -1) + priv->currentScreen = priv->screen_no; + xf86WcmInitialScreens(local); + xf86WcmInitialCoordinates(local, 0); + xf86WcmInitialCoordinates(local, 1); +} + +/***************************************************************************** + * rotateOneTool + ****************************************************************************/ + +static void rotateOneTool(WacomDevicePtr priv) +{ + WacomCommonPtr common = priv->common; + WacomToolAreaPtr area = priv->toolarea; + int tmpTopX, tmpTopY, tmpBottomX, tmpBottomY, oldMaxX, oldMaxY; + + DBG(10, priv->debugLevel, ErrorF("rotateOneTool for \"%s\" \n", priv->local->name)); + + oldMaxX = common->wcmMaxX; + oldMaxY = common->wcmMaxY; + + tmpTopX = priv->topX; + tmpBottomX = priv->bottomX; + tmpTopY = priv->topY; + tmpBottomY = priv->bottomY; + + if (common->wcmRotate == ROTATE_CW || common->wcmRotate == ROTATE_CCW) + { + common->wcmMaxX = oldMaxY; + common->wcmMaxY = oldMaxX; + } + + switch (common->wcmRotate) { + case ROTATE_CW: + area->topX = priv->topX = tmpTopY; + area->bottomX = priv->bottomX = tmpBottomY; + area->topY = priv->topY = oldMaxX - tmpBottomX; + area->bottomY = priv->bottomY =oldMaxX - tmpTopX; + break; + case ROTATE_CCW: + area->topX = priv->topX = oldMaxY - tmpBottomY; + area->bottomX = priv->bottomX = oldMaxY - tmpTopY; + area->topY = priv->topY = tmpTopX; + area->bottomY = priv->bottomY = tmpBottomX; + break; + case ROTATE_HALF: + area->topX = priv->topX = oldMaxX - tmpBottomX; + area->bottomX = priv->bottomX = oldMaxX - tmpTopX; + area->topY = priv->topY= oldMaxY - tmpBottomY; + area->bottomY = priv->bottomY = oldMaxY - tmpTopY; + break; + } + xf86WcmInitialCoordinates(priv->local, 0); + xf86WcmInitialCoordinates(priv->local, 1); + + if (tmpTopX != priv->topX) + xf86ReplaceIntOption(priv->local->options, "TopX", priv->topX); + if (tmpTopY != priv->topY) + xf86ReplaceIntOption(priv->local->options, "TopY", priv->topY); + if (tmpBottomX != priv->bottomX) + xf86ReplaceIntOption(priv->local->options, "BottomX", priv->bottomX); + if (tmpBottomY != priv->bottomY) + xf86ReplaceIntOption(priv->local->options, "BottomY", priv->bottomY); +} + +/***************************************************************************** + * xf86WcmRotateTablet + ****************************************************************************/ + +void xf86WcmRotateTablet(LocalDevicePtr local, int value) +{ + WacomDevicePtr priv = (WacomDevicePtr)local->private; + WacomCommonPtr common = priv->common; + WacomDevicePtr tmppriv; + int oldRotation; + int tmpTopX, tmpTopY, tmpBottomX, tmpBottomY, oldMaxX, oldMaxY; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmRotateTablet for \"%s\" \n", local->name)); + + if (common->wcmRotate == value) /* initialization */ + { + rotateOneTool(priv); + } + else + { + oldRotation = common->wcmRotate; + common->wcmRotate = value; + + /* rotate all devices at once! else they get misaligned */ + for (tmppriv = common->wcmDevices; tmppriv; tmppriv = tmppriv->next) + { + oldMaxX = common->wcmMaxX; + oldMaxY = common->wcmMaxY; + + if (oldRotation == ROTATE_CW || oldRotation == ROTATE_CCW) + { + common->wcmMaxX = oldMaxY; + common->wcmMaxY = oldMaxX; + } + + tmpTopX = tmppriv->topX; + tmpBottomX = tmppriv->bottomX; + tmpTopY = tmppriv->topY; + tmpBottomY = tmppriv->bottomY; + + /* recover to the unrotated xy-rectangles */ + switch (oldRotation) { + case ROTATE_CW: + tmppriv->topX = oldMaxY - tmpBottomY; + tmppriv->bottomX = oldMaxY - tmpTopY; + tmppriv->topY = tmpTopX; + tmppriv->bottomY = tmpBottomX; + break; + case ROTATE_CCW: + tmppriv->topX = tmpTopY; + tmppriv->bottomX = tmpBottomY; + tmppriv->topY = oldMaxX - tmpBottomX; + tmppriv->bottomY = oldMaxX - tmpTopX; + break; + case ROTATE_HALF: + tmppriv->topX = oldMaxX - tmpBottomX; + tmppriv->bottomX = oldMaxX - tmpTopX; + tmppriv->topY = oldMaxY - tmpBottomY; + tmppriv->bottomY = oldMaxY - tmpTopY; + break; + } + + /* and rotate them to the new value */ + rotateOneTool(tmppriv); + + switch(value) { + case ROTATE_NONE: + xf86ReplaceStrOption(local->options, "Rotate", "NONE"); + break; + case ROTATE_CW: + xf86ReplaceStrOption(local->options, "Rotate", "CW"); + break; + case ROTATE_CCW: + xf86ReplaceStrOption(local->options, "Rotate", "CCW"); + break; + case ROTATE_HALF: + xf86ReplaceStrOption(local->options, "Rotate", "HALF"); + break; + } + } + } +} + diff --git a/src/xdrv/wcmSerial.c b/src/xdrv/wcmSerial.c index 0307614..9b9a1b7 100755 --- a/src/xdrv/wcmSerial.c +++ b/src/xdrv/wcmSerial.c @@ -25,7 +25,7 @@ static Bool serialDetect(LocalDevicePtr pDev); static Bool serialInit(LocalDevicePtr pDev, char* id, float *version); -static int serialInitTablet(LocalDevicePtr local, char* id, float *version); +static int serialInitTablet(LocalDevicePtr pDev, char* id, float *version); static void serialInitIntuos(WacomCommonPtr common, const char* id, float version); static void serialInitIntuos2(WacomCommonPtr common, const char* id, float version); static void serialInitCintiq(WacomCommonPtr common, const char* id, float version); @@ -700,7 +700,7 @@ static int serialParseProtocol5(LocalDevicePtr local, const unsigned char* data) /* Protocol 5 devices support 2 data channels */ channel = data[0] & 0x01; - /* pick up where we left off, minus relative values */ + /* pick up where we left off, minus relative values */ ds = &common->wcmChannel[channel].work; RESET_RELATIVE(*ds); @@ -1269,9 +1269,7 @@ static void serialParseP4Common(LocalDevicePtr local, (ds->device_type == ERASER_ID)) { /* send a prox-out for old device */ - WacomDeviceState out = { 0 }; - out.device_type = ERASER_ID; - xf86WcmEvent(common, 0, &out); + xf86WcmSoftOut(common, 0); ds->device_type = cur_type; } } diff --git a/src/xdrv/wcmTouchFilter.c b/src/xdrv/wcmTouchFilter.c new file mode 100644 index 0000000..23971a3 --- /dev/null +++ b/src/xdrv/wcmTouchFilter.c @@ -0,0 +1,392 @@ +/* + * Copyright 2009 by Ping Cheng, Wacom Technology. <pingc@wacom.com> + * + * 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "xf86Wacom.h" +#include <math.h> + +// Defines for 2FC Gesture +#define WACOM_DIST_IN_POINT 300 +#define WACOM_APART_IN_POINT 350 +#define WACOM_MOTION_IN_POINT 50 +#define WACOM_PARA_MOTION_IN_POINT 50 +#define WACOM_DOWN_TIME_IN_MS 800 +#define WACOM_TIME_BETWEEN_IN_MS 400 +#define WACOM_HORIZ_ALLOWED 1 +#define WACOM_VERT_ALLOWED 2 + +#define GESTURE_TAP_MODE 1 +#define GESTURE_SCROLL_MODE 2 +#define GESTURE_ZOOM_MODE 4 + + +// Defines for Tap Add-a-Finger to Click +#define WACOM_TAP_TIME_IN_MS 150 + +extern void xf86WcmRotateCoordinates(LocalDevicePtr local, int x, int y); +extern void emitKeysym (DeviceIntPtr keydev, int keysym, int state); + +static void xf86WcmFingerScroll(WacomDevicePtr priv); +static void xf86WcmFingerZoom(WacomDevicePtr priv); + +static double touchDistance(WacomDeviceState ds0, WacomDeviceState ds1) +{ + int xDelta = ds0.x - ds1.x; + int yDelta = ds0.y - ds1.y; + double distance = sqrt((double)(xDelta*xDelta + yDelta*yDelta)); + return distance; +} + +static Bool pointsInLine(WacomDeviceState ds0, WacomDeviceState ds1, int *direction) +{ + Bool ret = FALSE; + + if (*direction == 0) + { + if ( abs(ds0.x - ds1.x) < WACOM_PARA_MOTION_IN_POINT) + { + *direction = WACOM_VERT_ALLOWED; + ret = TRUE; + } + else if (abs(ds0.y - ds1.y) < WACOM_PARA_MOTION_IN_POINT) + { + *direction = WACOM_HORIZ_ALLOWED; + ret = TRUE; + } + } + else if (*direction == WACOM_HORIZ_ALLOWED) + { + if ( abs(ds0.y - ds1.y) < WACOM_PARA_MOTION_IN_POINT) + ret = TRUE; + } + else if (*direction == WACOM_VERT_ALLOWED) + { + if ( abs(ds0.x - ds1.x) < WACOM_PARA_MOTION_IN_POINT) + ret = TRUE; + } + return ret; +} + +static Bool pointsInLineAfter(int p1, int p2) +{ + Bool ret = FALSE; + + if ( abs(p1 - p2) < WACOM_PARA_MOTION_IN_POINT) + ret = TRUE; + + return ret; +} + +static void xf86WcmSwitchLeftClick(WacomDevicePtr priv) +{ + WacomCommonPtr common = priv->common; + + if (common->wcmGestureMode) + { + /* send button one up */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + 1,0,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + priv->oldButtons = 0; + } +} + +/***************************************************************************** + * xf86WcmFingerTapToClick -- + * translate second finger tap to right click + ****************************************************************************/ + +void xf86WcmFingerTapToClick(WacomCommonPtr common) +{ + WacomDevicePtr priv = common->wcmDevices; + WacomChannelPtr firstChannel = common->wcmChannel; + WacomChannelPtr secondChannel = common->wcmChannel + 1; + WacomDeviceState ds[2] = { firstChannel->valid.states[0], + secondChannel->valid.states[0] }; + WacomDeviceState dsLast[2] = { firstChannel->valid.states[1], + secondChannel->valid.states[1] }; + int direction = 0; + + DBG(10, priv->debugLevel, ErrorF("xf86WcmFingerTapToClick \n")); + + /* skip initial second finger event */ + if (!dsLast[1].proximity) goto skipGesture; + + if (!IsTouch(priv)) + { + /* go through the shared port */ + for (; priv; priv = priv->next) + { + if (IsTouch(priv)) + break; + } + } + + if (priv) /* found the first finger */ + { + /* allow only second finger tap */ + if ((dsLast[0].sample < dsLast[1].sample) && ((GetTimeInMillis() - + dsLast[1].sample) <= WACOM_TAP_TIME_IN_MS)) + { + /* send right click when second finger taps within WACOM_TAP_TIMEms + * and both fingers stay within WACOM_DIST */ + if (!ds[1].proximity && dsLast[1].proximity) + { + if (touchDistance(ds[0], dsLast[1]) <= WACOM_DIST_IN_POINT) + { + /* send left up before sending right down */ + if (!common->wcmGestureMode) + xf86WcmSwitchLeftClick(priv); + common->wcmGestureMode = GESTURE_TAP_MODE; + + /* right button down */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + 3,1,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + /* right button up */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + 3,0,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + } + } + } + else if ((WACOM_TAP_TIME_IN_MS < (GetTimeInMillis() - dsLast[0].sample)) && + (WACOM_TAP_TIME_IN_MS < (GetTimeInMillis() - dsLast[1].sample)) + && ds[0].proximity && ds[1].proximity) + { + if (abs(touchDistance(ds[0], ds[1])) >= WACOM_APART_IN_POINT && + common->wcmGestureMode != GESTURE_TAP_MODE && + common->wcmGestureMode != GESTURE_SCROLL_MODE) + { + /* fingers moved apart more than WACOM_APART_IN_POINT + * zoom mode is entered */ + if (!common->wcmGestureMode) + xf86WcmSwitchLeftClick(priv); + common->wcmGestureMode = GESTURE_ZOOM_MODE; + xf86WcmFingerZoom(priv); + } + + if ( pointsInLine(ds[0], dsLast[0], &direction) && + pointsInLine(ds[1], dsLast[1], &direction) && + common->wcmGestureMode != GESTURE_ZOOM_MODE && + common->wcmGestureMode != GESTURE_TAP_MODE) + { + /* send scroll event when both fingers move in + * the same direction */ + if (!common->wcmGestureMode) + xf86WcmSwitchLeftClick(priv); + common->wcmGestureMode = GESTURE_SCROLL_MODE; + xf86WcmFingerScroll(priv); + } + } + } + else + /* this should never happen */ + xf86Msg(X_ERROR, "WACOM: No touch device found for %s \n", common->wcmDevice); +skipGesture: + /* keep the initial in-prox time */ + ds[0].sample = dsLast[0].sample; + ds[1].sample = dsLast[1].sample; + + /* keep the initial states for both fingers */ + if ( !(common->wcmGestureMode && (GESTURE_SCROLL_MODE | GESTURE_ZOOM_MODE)) + && ds[0].proximity && ds[1].proximity) + { + common->wcmGestureState[0] = ds[0]; + common->wcmGestureState[1] = ds[1]; + } +} + +static void xf86WcmSendVerticalScrollEvent(WacomDevicePtr priv, int dist, + int buttonUp, int buttonDn) +{ + int i = 0; + + for (i=0; i<(int)(((double)abs(dist)/ + (double)WACOM_MOTION_IN_POINT) + 0.5); i++) + { + if (dist > 0) + { + /* button down */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + buttonUp,1,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + /* button up */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + buttonUp,0,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + } + else + { + /* button down */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + buttonDn,1,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + /* button up */ + xf86PostButtonEvent(priv->local->dev, + priv->flags & ABSOLUTE_FLAG, + buttonDn,0,0,priv->naxes, priv->oldX, + priv->oldY,0,0,0,0); + } + } +} + +static void xf86WcmSendHorizontalScrollEvent(WacomDevicePtr priv, int dist, + int buttonUp, int buttonDn) +{ + int i = 0; + + for (i=0; i<(int)(((double)abs(dist)/ + (double)WACOM_MOTION_IN_POINT) + 0.5); i++) + { + if (dist > 0) + { + emitKeysym (priv->local->dev, XK_Left, 1); + emitKeysym (priv->local->dev, XK_Left, 0); + } + else + { + emitKeysym (priv->local->dev, XK_Right, 1); + emitKeysym (priv->local->dev, XK_Right, 0); + } + } +} + +static void xf86WcmFingerScroll(WacomDevicePtr priv) +{ + WacomCommonPtr common = priv->common; + WacomChannelPtr firstChannel = common->wcmChannel; + WacomChannelPtr secondChannel = common->wcmChannel + 1; + WacomDeviceState ds[2] = { firstChannel->valid.states[0], + secondChannel->valid.states[0] }; + WacomDeviceState dsLast[2] = { firstChannel->valid.states[1], + secondChannel->valid.states[1] }; + int midPoint_new = 0; + int midPoint_old = 0; + int i = 0, dist =0; + int gesture = 0; + WacomFilterState filterd; /* borrow this struct */ + + DBG(10, priv->debugLevel, ErrorF("xf86WcmFingerScroll \n")); + + /* initialize the points so we can rotate them */ + filterd.x[0] = ds[0].x; + filterd.y[0] = ds[0].y; + filterd.x[1] = ds[1].x; + filterd.y[1] = ds[1].y; + filterd.x[2] = common->wcmGestureState[0].x; + filterd.y[2] = common->wcmGestureState[0].y; + filterd.x[3] = common->wcmGestureState[1].x; + filterd.y[3] = common->wcmGestureState[1].y; + filterd.x[4] = dsLast[0].x; + filterd.y[4] = dsLast[0].y; + filterd.x[5] = dsLast[1].x; + filterd.y[5] = dsLast[1].y; + + /* rotate the coordinates first */ + for (i=0; i<6; i++) + xf86WcmRotateCoordinates(priv->local, filterd.x[i], filterd.y[i]); + + /* check vertical direction */ + midPoint_old = (((double)filterd.x[4] + (double)filterd.x[5]) / 2.); + midPoint_new = (((double)filterd.x[0] + (double)filterd.x[1]) / 2.); + if (pointsInLineAfter(midPoint_old, midPoint_new)) + { + midPoint_old = (((double)filterd.y[2] + (double)filterd.y[3]) / 2.); + midPoint_new = (((double)filterd.y[0] + (double)filterd.y[1]) / 2.); + dist = midPoint_old - midPoint_new; + + if (abs(dist) > WACOM_PARA_MOTION_IN_POINT) + { + gesture = 1; + xf86WcmSendVerticalScrollEvent(priv, dist, SCROLL_UP, SCROLL_DOWN); + } + + /* check horizontal direction */ + if (!gesture) + { + midPoint_old = (((double)filterd.y[4] + (double)filterd.y[5]) / 2.); + midPoint_new = (((double)filterd.y[0] + (double)filterd.y[1]) / 2.); + if (pointsInLineAfter(midPoint_old, midPoint_new)) + { + midPoint_old = (((double)filterd.x[2] + (double)filterd.x[3]) / 2.); + midPoint_new = (((double)filterd.x[0] + (double)filterd.x[1]) / 2.); + dist = midPoint_old - midPoint_new; + + if (abs(dist) > WACOM_PARA_MOTION_IN_POINT) + { + gesture = 1; + xf86WcmSendHorizontalScrollEvent(priv, dist, SCROLL_RIGHT, SCROLL_LEFT); + } + } + } + if (gesture) + { + /* reset initial states */ + common->wcmGestureState[0] = ds[0]; + common->wcmGestureState[1] = ds[1]; + } + } +} + +static void xf86WcmFingerZoom(WacomDevicePtr priv) +{ + WacomCommonPtr common = priv->common; + WacomChannelPtr firstChannel = common->wcmChannel; + WacomChannelPtr secondChannel = common->wcmChannel + 1; + WacomDeviceState ds[2] = { firstChannel->valid.states[0], + secondChannel->valid.states[0] }; + int i = 0; + int dist = touchDistance(common->wcmGestureState[0], common->wcmGestureState[1]); + + DBG(10, priv->debugLevel, ErrorF("xf86WcmFingerZoom \n")); + + dist = touchDistance(ds[0], ds[1]) - dist; + + /* zooming? */ + if (abs(dist) > WACOM_MOTION_IN_POINT) + { + for (i=0; i<(int)(((double)abs(dist)/ + (double)WACOM_MOTION_IN_POINT) + 0.5); i++) + { + emitKeysym (priv->local->dev, XK_Control_L, 1); + /* zooming in */ + if (dist > 0) + { + emitKeysym (priv->local->dev, XK_plus, 1); + emitKeysym (priv->local->dev, XK_plus, 0); + } + else /* zooming out */ + { + emitKeysym (priv->local->dev, XK_minus, 1); + emitKeysym (priv->local->dev, XK_minus, 0); + } + emitKeysym (priv->local->dev, XK_Control_L, 0); + } + + /* reset initial states */ + common->wcmGestureState[0] = ds[0]; + common->wcmGestureState[1] = ds[1]; + } +} + diff --git a/src/xdrv/wcmUSB.c b/src/xdrv/wcmUSB.c index 904aa64..cb0a81d 100755 --- a/src/xdrv/wcmUSB.c +++ b/src/xdrv/wcmUSB.c @@ -49,7 +49,7 @@ static int usbParse(LocalDevicePtr local, const unsigned char* data); static int usbDetectConfig(LocalDevicePtr local); static void usbParseEvent(LocalDevicePtr local, const struct input_event* event); -static void usbParseChannel(LocalDevicePtr local, int channel, int serial); +static void usbParseChannel(LocalDevicePtr local, int channel); WacomDeviceClass gWacomUSBDevice = { @@ -398,12 +398,6 @@ static Bool usbDetect(LocalDevicePtr local) /***************************************************************************** * wcmusbInit -- ****************************************************************************/ -#define BIT(x) (1<<((x) & (BITS_PER_LONG - 1))) -#define BITS_PER_LONG (sizeof(long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y)) -#define OFF(x) ((x)%BITS_PER_LONG) -#define LONG(x) ((x)/BITS_PER_LONG) /* Key codes used to mark tablet buttons -- must be in sync * with the keycode array in wacom.c kernel driver. @@ -548,13 +542,14 @@ Bool usbWcmInit(LocalDevicePtr local, char* id, float *version) { /* GestureDefault was off for all devices */ /* except when multi-touch is supported */ - common->wcmGestureDefault = 0; + common->wcmGestureDefault = 1; /* check if gesture was turned off in xorg.conf */ common->wcmGesture = xf86SetBoolOption(local->options, "Gesture", common->wcmGestureDefault); if ( common->wcmTouch && common->wcmGesture ) - xf86Msg(X_CONFIG, "%s: Touch Gesture is enabled \n", common->wcmDevice); + xf86Msg(X_CONFIG, "%s: " + "Touch Gesture is enabled \n", common->wcmDevice); } } @@ -686,11 +681,11 @@ int usbWcmGetRanges(LocalDevicePtr local) common->wcmMaxY = absinfo.maximum; /* max finger strip X for tablets with Expresskeys - * or touch logical X for TabletPCs with touch */ + * or touch physical X for TabletPCs with touch */ if (ioctl(local->fd, EVIOCGABS(ABS_RX), &absinfo) == 0) { if (common->wcmTouchDefault) - common->wcmMaxTouchX = absinfo.maximum; + common->wcmResolX = absinfo.maximum; else common->wcmMaxStripX = absinfo.maximum; @@ -698,45 +693,22 @@ int usbWcmGetRanges(LocalDevicePtr local) local->name, absinfo.maximum)); } - /* max finger strip y for tablets with Expresskeys - * or touch logical Y for TabletPCs with touch */ + /* max finger strip y for tablets with Expresskeys + * or touch physical Y for TabletPCs with touch */ if (ioctl(local->fd, EVIOCGABS(ABS_RY), &absinfo) == 0) { if (common->wcmTouchDefault) - common->wcmMaxTouchY = absinfo.maximum; + common->wcmResolY = absinfo.maximum; else common->wcmMaxStripY = absinfo.maximum; } - /* touch physical X for TabletPCs with touch */ - if (ioctl(local->fd, EVIOCGABS(ABS_Z), &absinfo) == 0) + if (common->wcmTouchDefault && common->wcmMaxX && common->wcmResolX) { - if (common->wcmTouchDefault) - common->wcmTouchResolX = absinfo.maximum; - } - - /* touch physical Y for TabletPCs with touch */ - if (ioctl(local->fd, EVIOCGABS(ABS_RZ), &absinfo) == 0) - { - if (common->wcmTouchDefault) - common->wcmTouchResolY = absinfo.maximum; - } - - if (common->wcmTouchDefault && common->wcmTouchResolX) - { - common->wcmTouchResolX = (int)(((double)common->wcmTouchResolX) - / ((double)common->wcmMaxTouchX) + 0.5); - common->wcmTouchResolY = (int)(((double)common->wcmTouchResolY) - / ((double)common->wcmMaxTouchY) + 0.5); - - if (!common->wcmTouchResolX || !common->wcmTouchResolY) - { - ErrorF("WACOM: touch resolution value(s) was wrong resX" - " = %d resY = %d.\n", common->wcmTouchResolX, - common->wcmTouchResolY); - return !Success; - } - + common->wcmResolX = (int)(((double)common->wcmResolX) + / ((double)common->wcmMaxX) + 0.5); + common->wcmResolY = (int)(((double)common->wcmResolY) + / ((double)common->wcmMaxY) + 0.5); } /* max z cannot be configured */ @@ -795,10 +767,89 @@ static int usbParse(LocalDevicePtr local, const unsigned char* data) return common->wcmPktLength; } -static void usbParseEvent(LocalDevicePtr local, - const struct input_event* event) + +static int usbChooseChannel(WacomCommonPtr common, int serial) { - int i, channel; + /* figure out the channel to use based on serial number */ + int i, channel = -1; + if (common->wcmProtocolLevel == 4) + { + /* Protocol 4 doesn't support tool serial numbers */ + if (serial == 0xf0) + channel = 1; + else + channel = 0; + } + else if (serial) /* serial number should never be 0 for V5 devices */ + { + /* dual input is supported */ + if ( strstr(common->wcmModel->name, "Intuos1") || strstr(common->wcmModel->name, "Intuos2") ) + { + /* find existing channel */ + for (i=0; i<MAX_CHANNELS; ++i) + { + if (common->wcmChannel[i].work.proximity && + common->wcmChannel[i].work.serial_num == serial) + { + channel = i; + break; + } + } + + /* find an empty channel */ + if (channel < 0) + { + for (i=0; i<MAX_CHANNELS; ++i) + { + if (!common->wcmChannel[i].work.proximity) + { + channel = i; + break; + } + } + } + } + else /* one transducer plus expresskey (pad) is supported */ + { + if (serial == -1) /* pad */ + channel = 1; + else if ( (common->wcmChannel[0].work.proximity && /* existing transducer */ + (common->wcmChannel[0].work.serial_num == serial)) || + !common->wcmChannel[0].work.proximity ) /* new transducer */ + channel = 0; + } + } + + /* fresh out of channels */ + if (channel < 0) + { + /* This should never happen in normal use. + * Let's start over again. Force prox-out for all channels. + */ + for (i=0; i<MAX_CHANNELS; ++i) + { + if (common->wcmChannel[i].work.proximity && + (common->wcmChannel[i].work.serial_num != -1)) + { + common->wcmChannel[i].work.proximity = 0; + /* dispatch event */ + xf86WcmEvent(common, i, &common->wcmChannel[i].work); + } + } + DBG(1, common->debugLevel, ErrorF("usbParse (device with serial number: %u)" + " at %d: Exceeded channel count; ignoring the events.\n", + serial, (int)GetTimeInMillis())); + } + else + common->wcmLastToolSerial = serial; + + return channel; +} + +static void usbParseEvent(LocalDevicePtr local, + const struct input_event* event) +{ + int channel; WacomDevicePtr priv = (WacomDevicePtr)local->private; WacomCommonPtr common = priv->common; @@ -829,8 +880,7 @@ static void usbParseEvent(LocalDevicePtr local, goto skipEvent; } - /* save the serial number so we can look up the channel number later */ - common->wcmLastToolSerial = event->value; + common->wcmLastToolSerial = event->value; /* if SYN_REPORT is end of record indicator, we are done */ if (USE_SYN_REPORTS(common)) @@ -858,86 +908,18 @@ static void usbParseEvent(LocalDevicePtr local, return; } - /* figure out the channel to use based on serial number */ - channel = -1; - if (common->wcmProtocolLevel == 4) + /* ignore events without information */ + if (common->wcmEventCnt <= 2) { - /* Protocol 4 doesn't support tool serial numbers */ - if (common->wcmLastToolSerial == 0xf0) - channel = 1; - else - channel = 0; + DBG(3, common->debugLevel, ErrorF("%s - usbParse: dropping empty event for serial %d\n", + local->name, common->wcmLastToolSerial)); + goto skipEvent; } - else if (common->wcmLastToolSerial) /* serial number should never be 0 */ - { - /* ignore events without information */ - if (common->wcmEventCnt <= 2) - { - DBG(3, common->debugLevel, ErrorF("%s - usbParse: dropping empty event for serial %d\n", - local->name, common->wcmLastToolSerial)); - goto skipEvent; - } - /* dual input is supported */ - if ( strstr(common->wcmModel->name, "Intuos1") || strstr(common->wcmModel->name, "Intuos2") ) - { - /* find existing channel */ - for (i=0; i<MAX_CHANNELS; ++i) - { - if (common->wcmChannel[i].work.proximity && - common->wcmChannel[i].work.serial_num == common->wcmLastToolSerial) - { - channel = i; - break; - } - } - - /* find an empty channel */ - if (channel < 0) - { - for (i=0; i<MAX_CHANNELS; ++i) - { - if (!common->wcmChannel[i].work.proximity) - { - channel = i; - break; - } - } - } - } - else /* one transducer plus expresskey (pad) is supported */ - { - if (common->wcmLastToolSerial == -1) /* pad */ - channel = 1; - else if ( (common->wcmChannel[0].work.proximity && /* existing transducer */ - (common->wcmChannel[0].work.serial_num == common->wcmLastToolSerial)) || - !common->wcmChannel[0].work.proximity ) /* new transducer */ - channel = 0; - } - } - else - goto skipEvent; + channel = usbChooseChannel(common, common->wcmLastToolSerial); - /* fresh out of channels */ - if (channel < 0) - { - /* This should never happen in normal use. - * Let's start over again. Force prox-out for all channels. - */ - for (i=0; i<MAX_CHANNELS; ++i) - { - if (common->wcmChannel[i].work.proximity && (common->wcmChannel[i].work.serial_num != -1)) - { - common->wcmChannel[i].work.proximity = 0; - /* dispatch event */ - xf86WcmEvent(common, i, &common->wcmChannel[i].work); - } - } - DBG(1, common->debugLevel, ErrorF("usbParse (%s with serial number: %u) at %d: Exceeded channel count; " - "ignoring the events.\n", local->name, common->wcmLastToolSerial, - (int)GetTimeInMillis())); - goto skipEvent; - } + /* couldn't decide channel? invalid data */ + if (channel == -1) goto skipEvent; if (!common->wcmChannel[channel].work.proximity) { @@ -947,14 +929,14 @@ static void usbParseEvent(LocalDevicePtr local, } /* dispatch event */ - usbParseChannel(local,channel,common->wcmLastToolSerial); + usbParseChannel(local, channel); skipEvent: common->wcmLastToolSerial = 0; common->wcmEventCnt = 0; } -static void usbParseChannel(LocalDevicePtr local, int channel, int serial) +static void usbParseChannel(LocalDevicePtr local, int channel) { int i, shift, nkeys; WacomDeviceState* ds; @@ -977,7 +959,7 @@ static void usbParseChannel(LocalDevicePtr local, int channel, int serial) /* all USB data operates from previous context except relative values*/ ds = &common->wcmChannel[channel].work; ds->relwheel = 0; - ds->serial_num = serial; + ds->serial_num = common->wcmLastToolSerial; /* loop through all events in group */ for (i=0; i<common->wcmEventCnt; ++i) @@ -1035,7 +1017,9 @@ static void usbParseChannel(LocalDevicePtr local, int channel, int serial) (event->code == BTN_TOOL_AIRBRUSH)) { ds->device_type = STYLUS_ID; - ds->device_id = STYLUS_DEVICE_ID; + /* V5 tools use ABS_MISC to report device_id */ + if (common->wcmProtocolLevel == 4) + ds->device_id = STYLUS_DEVICE_ID; ds->proximity = (event->value != 0); DBG(6, common->debugLevel, ErrorF( "USB stylus detected %x\n", @@ -1044,7 +1028,9 @@ static void usbParseChannel(LocalDevicePtr local, int channel, int serial) else if (event->code == BTN_TOOL_RUBBER) { ds->device_type = ERASER_ID; - ds->device_id = ERASER_DEVICE_ID; + /* V5 tools use ABS_MISC to report device_id */ + if (common->wcmProtocolLevel == 4) + ds->device_id = ERASER_DEVICE_ID; ds->proximity = (event->value != 0); if (ds->proximity) ds->proximity = ERASER_PROX; @@ -1059,7 +1045,9 @@ static void usbParseChannel(LocalDevicePtr local, int channel, int serial) "USB mouse detected %x (value=%d)\n", event->code, event->value)); ds->device_type = CURSOR_ID; - ds->device_id = CURSOR_DEVICE_ID; + /* V5 tools use ABS_MISC to report device_id */ + if (common->wcmProtocolLevel == 4) + ds->device_id = CURSOR_DEVICE_ID; ds->proximity = (event->value != 0); } else if (event->code == BTN_TOOL_FINGER) @@ -1073,12 +1061,18 @@ static void usbParseChannel(LocalDevicePtr local, int channel, int serial) } else if (event->code == BTN_TOOL_DOUBLETAP) { + WacomChannelPtr pChannel = common->wcmChannel + channel; + WacomDeviceState dslast = pChannel->valid.state; DBG(6, common->debugLevel, ErrorF( "USB Touch detected %x (value=%d)\n", event->code, event->value)); ds->device_type = TOUCH_ID; ds->device_id = TOUCH_DEVICE_ID; ds->proximity = event->value; + /* time stamp for 2GT gesture events */ + if ((ds->proximity && !dslast.proximity) || + (!ds->proximity && dslast.proximity)) + ds->sample = (int)GetTimeInMillis(); /* Left button is always pressed for touch without capacity * when the first finger touch event received. * For touch with capacity enabled, left button event will be decided @@ -1089,13 +1083,20 @@ static void usbParseChannel(LocalDevicePtr local, int channel, int serial) } else if (event->code == BTN_TOOL_TRIPLETAP) { + WacomChannelPtr pChannel = common->wcmChannel + channel; + WacomDeviceState dslast = pChannel->valid.state; DBG(6, common->debugLevel, ErrorF( "USB Touch second finger detected %x (value=%d)\n", event->code, event->value)); ds->device_type = TOUCH_ID; ds->device_id = TOUCH_DEVICE_ID; ds->proximity = event->value; - /* Second finger events will be combined with the first finger data */ + /* time stamp for 2GT gesture events */ + if ((ds->proximity && !dslast.proximity) || + (!ds->proximity && dslast.proximity)) + ds->sample = (int)GetTimeInMillis(); + /* Second finger events will be considered in + * combination with the first finger data */ } else if ((event->code == BTN_STYLUS) || (event->code == BTN_MIDDLE)) diff --git a/src/xdrv/wcmValidateDevice.c b/src/xdrv/wcmValidateDevice.c new file mode 100755 index 0000000..34114f2 --- /dev/null +++ b/src/xdrv/wcmValidateDevice.c @@ -0,0 +1,306 @@ +/* + * Copyright 2009 by Ping Cheng, Wacom. <pingc@wacom.com> + * + * 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 Lesser 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "xf86Wacom.h" +#include "wcmFilter.h" +#ifdef WCM_XORG_XSERVER_1_4 + #ifndef _XF86_ANSIC_H + #include <fcntl.h> + #include <sys/stat.h> + #endif + +/***************************************************************************** + * xf86WcmCheckTypeAndSource - Check if both devices have the same type OR + * the device has been used in xorg.conf: don't add the tool by hal/udev + * if user has defined at least one tool for the device in xorg.conf + ****************************************************************************/ +static Bool xf86WcmCheckTypeAndSource(LocalDevicePtr fakeLocal, LocalDevicePtr pLocal) +{ + int match = 1; + char* fsource = xf86CheckStrOption(fakeLocal->options, "_source", ""); + char* psource = xf86CheckStrOption(pLocal->options, "_source", ""); + char* type = xf86FindOptionValue(fakeLocal->options, "Type"); + WacomDevicePtr priv = (WacomDevicePtr) pLocal->private; + + /* only add the new tool if the matching major/minor + * was from the same source */ + if (!strcmp(fsource, psource)) + { + /* and the tools have different types */ + if (strcmp(type, xf86FindOptionValue(pLocal->options, "Type"))) + match = 0; + } + DBG(2, priv->debugLevel, xf86Msg(X_INFO, "xf86WcmCheckTypeAndSource " + "device %s from %s %s \n", fakeLocal->name, fsource, + match ? "will be added" : "will be ignored")); + return match; +} + +/* check if the device has been added */ +int wcmIsDuplicate(char* device, LocalDevicePtr local) +{ +#ifdef _XF86_ANSIC_H + struct xf86stat st; +#else + struct stat st; +#endif + int isInUse = 0; + LocalDevicePtr localDevices = NULL; + WacomCommonPtr common = NULL; + + /* open the port */ + do { + SYSCALL(local->fd = open(device, O_RDONLY, 0)); + } while (local->fd < 0 && errno == EINTR); + + if (local->fd < 0) + { + /* can not open the device */ + xf86Msg(X_ERROR, "Unable to open Wacom device \"%s\".\n", device); + isInUse = 2; + goto ret; + } + +#ifdef _XF86_ANSIC_H + if (xf86fstat(local->fd, &st) == -1) +#else + if (fstat(local->fd, &st) == -1) +#endif + { + /* can not access major/minor to check device duplication */ + xf86Msg(X_ERROR, "%s: stat failed (%s). cannot check for duplicates.\n", + local->name, strerror(errno)); + + /* older systems don't support the required ioctl. let it pass */ + goto ret; + } + + if ((int)st.st_rdev) + { + localDevices = xf86FirstLocalDevice(); + + for (; localDevices != NULL; localDevices = localDevices->next) + { + device = xf86CheckStrOption(localDevices->options, "Device", NULL); + + /* device can be NULL on some distros */ + if (!device || !strstr(localDevices->drv->driverName, "wacom")) + continue; + + common = ((WacomDevicePtr)localDevices->private)->common; + if (local != localDevices && + common->min_maj && + common->min_maj == st.st_rdev) + { + /* device matches with another added port */ + if (xf86WcmCheckTypeAndSource(local, localDevices)) + { + xf86Msg(X_WARNING, "%s: device file already in use by %s. " + "Ignoring.\n", local->name, localDevices->name); + isInUse = 4; + goto ret; + } + } + } + } + else + { + /* major/minor can never be 0, right? */ + xf86Msg(X_ERROR, "%s: device opened with a major/minor of 0. " + "Something was wrong.\n", local->name); + isInUse = 5; + } +ret: + if (local->fd >= 0) + { + close(local->fd); + local->fd = -1; + } + return isInUse; +} + +static struct +{ + __u16 productID; + __u16 flags; +} validType [] = +{ + { 0x00, STYLUS_ID }, /* PenPartner */ + { 0x10, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire */ + { 0x11, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire2 4x5 */ + { 0x12, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire2 5x7 */ + + { 0x13, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire3 4x5 */ + { 0x14, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Graphire3 6x8 */ + + { 0x15, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Graphire4 4x5 */ + { 0x16, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Graphire4 6x8 */ + { 0x17, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* BambooFun 4x5 */ + { 0x18, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* BambooFun 6x8 */ + { 0x19, STYLUS_ID | ERASER_ID }, /* Bamboo1 Medium*/ + { 0x81, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Graphire4 6x8 BlueTooth */ + + { 0x20, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 4x5 */ + { 0x21, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 6x8 */ + { 0x22, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 9x12 */ + { 0x23, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 12x12 */ + { 0x24, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos 12x18 */ + + { 0x03, STYLUS_ID | ERASER_ID }, /* PTU600 */ + { 0x30, STYLUS_ID | ERASER_ID }, /* PL400 */ + { 0x31, STYLUS_ID | ERASER_ID }, /* PL500 */ + { 0x32, STYLUS_ID | ERASER_ID }, /* PL600 */ + { 0x33, STYLUS_ID | ERASER_ID }, /* PL600SX */ + { 0x34, STYLUS_ID | ERASER_ID }, /* PL550 */ + { 0x35, STYLUS_ID | ERASER_ID }, /* PL800 */ + { 0x37, STYLUS_ID | ERASER_ID }, /* PL700 */ + { 0x38, STYLUS_ID | ERASER_ID }, /* PL510 */ + { 0x39, STYLUS_ID | ERASER_ID }, /* PL710 */ + { 0xC0, STYLUS_ID }, /* DTF720 */ + { 0xC2, STYLUS_ID }, /* DTF720a */ + { 0xC4, STYLUS_ID | ERASER_ID }, /* DTF521 */ + { 0xC7, STYLUS_ID | ERASER_ID }, /* DTU1931 */ + + { 0x41, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 4x5 */ + { 0x42, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 6x8 */ + { 0x43, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 9x12 */ + { 0x44, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 12x12 */ + { 0x45, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 12x18 */ + { 0x47, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos2 6x8 */ + + { 0x60, STYLUS_ID }, /* Volito */ + { 0x61, STYLUS_ID }, /* PenStation */ + { 0x62, STYLUS_ID }, /* Volito2 4x5 */ + { 0x63, STYLUS_ID }, /* Volito2 2x3 */ + { 0x64, STYLUS_ID }, /* PenPartner2 */ + + { 0x65, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Bamboo */ + { 0x69, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Bamboo1 */ + + { 0xB0, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 4x5 */ + { 0xB1, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 6x8 */ + { 0xB2, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 9x12 */ + { 0xB3, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 12x12 */ + { 0xB4, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 12x19 */ + { 0xB5, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 6x11 */ + { 0xB7, STYLUS_ID | ERASER_ID | CURSOR_ID }, /* Intuos3 4x6 */ + + { 0xB8, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 4x6 */ + { 0xB9, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 6x9 */ + { 0xBA, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 8x13 */ + { 0xBB, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Intuos4 12x19*/ + + { 0x3F, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Cintiq 21UX */ + { 0xC5, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Cintiq 20WSX */ + { 0xC6, STYLUS_ID | ERASER_ID | CURSOR_ID | PAD_ID }, /* Cintiq 12WX */ + + { 0x90, STYLUS_ID | ERASER_ID }, /* TabletPC 0x90 */ + { 0x93, STYLUS_ID | ERASER_ID | TOUCH_ID }, /* TabletPC 0x93 */ + { 0x9A, STYLUS_ID | ERASER_ID | TOUCH_ID }, /* TabletPC 0x9A */ + { 0x9F, TOUCH_ID }, /* CapPlus 0x9F */ + { 0xE2, TOUCH_ID }, /* TabletPC 0xE2 */ + { 0xE3, STYLUS_ID | ERASER_ID | TOUCH_ID } /* TabletPC 0xE3 */ +}; + +static struct +{ + const char* type; + __u16 id; +} wcmTypeAndID [] = +{ + { "stylus", STYLUS_ID }, + { "eraser", ERASER_ID }, + { "cursor", CURSOR_ID }, + { "touch", TOUCH_ID }, + { "pad", PAD_ID } +}; + +static Bool checkValidType(char* type, unsigned short id) +{ + int i, j, ret = FALSE; + + /* walkthrough all supported models */ + for (i = 0; i < sizeof (validType) / sizeof (validType [0]); i++) + { + if (validType[i].productID == id) + { + /* walkthrough all types */ + for (j = 0; j < sizeof (wcmTypeAndID) / sizeof (wcmTypeAndID [0]); j++) + if (!strcmp(wcmTypeAndID[j].type, type)) + if (wcmTypeAndID[j].id & validType[i].flags) + ret = TRUE; + } + } + return ret; +} + +static Bool aTouchPort(char* device) +{ + int fd = -1; + unsigned long keys[NBITS(KEY_MAX)]; + + SYSCALL(fd = open(device, O_RDONLY)); + if (fd < 0) + return FALSE; + + /* test if BTN_TOOL_DOUBLETAP set or not for touch device */ + if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keys)), keys) < 0) + { + xf86Msg(X_ERROR, "WACOM: aTouchPort unable to ioctl key bits.\n"); + return FALSE; + } + close(fd); + + /* BTN_TOOL_DOUBLETAP is used to define touch tools */ + if (ISBITSET (keys, BTN_TOOL_DOUBLETAP)) + return TRUE; + else + return FALSE; +} + +/* validate tool type for device/product */ +Bool wcmIsAValidType(char* device, LocalDevicePtr local, unsigned short id) +{ + Bool ret = FALSE; + char* type = xf86FindOptionValue(local->options, "Type"); + + /* touch tool has its own port. + * we need to distinguish it from the others first */ + if (checkValidType("touch", id)) + { + if (aTouchPort(device)) + { + if (strstr(type, "touch")) + return TRUE; + else + return FALSE; + } + else + { + if (strstr(type, "touch")) + return FALSE; + } + } + + /* not a touch tool or touch is not support forthe id */ + ret = checkValidType(type, id); + + return ret; +} +#endif /* WCM_XORG_XSERVER_1_4 */ + diff --git a/src/xdrv/wcmXCommand.c b/src/xdrv/wcmXCommand.c index 96e98a7..54fa4ce 100644 --- a/src/xdrv/wcmXCommand.c +++ b/src/xdrv/wcmXCommand.c @@ -33,9 +33,9 @@ #include "xf86Wacom.h" #include "wcmFilter.h" +extern void xf86WcmChangeScreen(LocalDevicePtr local, int value); extern void xf86WcmInitialCoordinates(LocalDevicePtr local, int axes); extern void xf86WcmRotateTablet(LocalDevicePtr local, int value); -extern void xf86WcmInitialScreens(LocalDevicePtr local); /***************************************************************************** * xf86WcmSetPadCoreMode @@ -122,27 +122,6 @@ int xf86WcmDevSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode) } /***************************************************************************** - * xf86WcmChangeScreen - ****************************************************************************/ - -void xf86WcmChangeScreen(LocalDevicePtr local, int value) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - - if (priv->screen_no != value) - { - priv->screen_no = value; - xf86ReplaceIntOption(local->options, "ScreenNo", value); - } - - if (priv->screen_no != -1) - priv->currentScreen = priv->screen_no; - xf86WcmInitialScreens(local); - xf86WcmInitialCoordinates(local, 0); - xf86WcmInitialCoordinates(local, 1); -} - -/***************************************************************************** * xf86WcmSetParam ****************************************************************************/ @@ -345,8 +324,8 @@ static int xf86WcmSetParam(LocalDevicePtr local, int param, int value) case XWACOM_PARAM_XYDEFAULT: xf86WcmSetParam (local, XWACOM_PARAM_TOPX, 0); xf86WcmSetParam (local, XWACOM_PARAM_TOPY, 0); - xf86WcmSetParam (local, XWACOM_PARAM_BOTTOMX, priv->wcmMaxX); - xf86WcmSetParam (local, XWACOM_PARAM_BOTTOMY, priv->wcmMaxY); + xf86WcmSetParam (local, XWACOM_PARAM_BOTTOMX, common->wcmMaxX); + xf86WcmSetParam (local, XWACOM_PARAM_BOTTOMY, common->wcmMaxY); break; case XWACOM_PARAM_MMT: if ((value != 0) && (value != 1)) @@ -979,9 +958,9 @@ static int xf86WcmGetDefaultParam(LocalDevicePtr local, int param) case XWACOM_PARAM_TOPY: return 0; case XWACOM_PARAM_BOTTOMX: - return priv->wcmMaxX; + return common->wcmMaxX; case XWACOM_PARAM_BOTTOMY: - return priv->wcmMaxY; + return common->wcmMaxY; case XWACOM_PARAM_BUTTON1: case XWACOM_PARAM_BUTTON2: case XWACOM_PARAM_BUTTON3: diff --git a/src/xdrv/xf86Wacom.c b/src/xdrv/xf86Wacom.c index 10e6c09..e930ecf 100755 --- a/src/xdrv/xf86Wacom.c +++ b/src/xdrv/xf86Wacom.c @@ -85,17 +85,18 @@ * 2009-10-15 47-pc0.8.4-4 - added calibration-only wacomcpl * 2009-10-19 47-pc0.8.5 - Added support for TPC (0xE2, 0xE3 & 0x9F) * 2009-10-31 47-pc0.8.5-1 - Avoid duplicated devices for Xorg 1.4 and later + * 2009-11-6 47-pc0.8.5-2 - Validate tool type associated with device */ -static const char identification[] = "$Identification: 47-0.8.5-1 $"; +static const char identification[] = "$Identification: 47-0.8.5-2 $"; /****************************************************************************/ #include "xf86Wacom.h" #include "wcmFilter.h" #ifdef WCM_XORG_XSERVER_1_4 - #include <fcntl.h> #ifndef _XF86_ANSIC_H + #include <fcntl.h> #include <sys/stat.h> #endif #endif @@ -114,7 +115,7 @@ extern int usbWcmGetRanges(LocalDevicePtr local); extern int xf86WcmDevChangeControl(LocalDevicePtr local, xDeviceCtl* control); extern int xf86WcmDevSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode); extern void xf86WcmRotateTablet(LocalDevicePtr local, int value); -extern void xf86WcmInitialScreens(LocalDevicePtr local); +extern int xf86WcmInitArea(LocalDevicePtr local); WacomModule gWacomModule = { @@ -143,259 +144,7 @@ static void xf86WcmBellCallback(int pct, DeviceIntPtr di, pointer ctrl, int x) static void xf86WcmKbdCtrlCallback(DeviceIntPtr di, KeybdCtrl* ctrl) { } -#endif /* WCM_KEY_SENDING_SUPPORT */ - -/***************************************************************************** - * xf86WcmDesktopSize -- - * calculate the whole desktop size - ****************************************************************************/ -static void xf86WcmDesktopSize(LocalDevicePtr local) -{ - WacomDevicePtr priv = (WacomDevicePtr) local->private; - int i = 0, minX = 0, minY = 0, maxX = 0, maxY = 0; - - xf86WcmInitialScreens(local); - - minX = priv->screenTopX[0]; - minY = priv->screenTopY[0]; - maxX = priv->screenBottomX[0]; - maxY = priv->screenBottomY[0]; - - if (priv->numScreen != 1) - { - for (i = 1; i < priv->numScreen; i++) - { - if (priv->screenTopX[i] < minX) - minX = priv->screenTopX[i]; - if (priv->screenTopY[i] < minY) - minY = priv->screenTopY[i]; - if (priv->screenBottomX[i] > maxX) - maxX = priv->screenBottomX[i]; - if (priv->screenBottomY[i] > maxY) - maxY = priv->screenBottomY[i]; - } - } - - priv->maxWidth = maxX - minX; - priv->maxHeight = maxY - minY; -} - -static int xf86WcmInitArea(LocalDevicePtr local) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - WacomToolAreaPtr area = priv->toolarea, inlist; - WacomCommonPtr common = priv->common; - double screenRatio, tabletRatio; - - DBG(10, priv->debugLevel, ErrorF("xf86WcmInitArea\n")); - - /* Verify Box */ - if (priv->topX > priv->wcmMaxX) - { - area->topX = priv->topX = 0; - } - - if (priv->topY > priv->wcmMaxY) - { - area->topY = priv->topY = 0; - } - - /* set unconfigured bottom to max */ - priv->bottomX = xf86SetIntOption(local->options, "BottomX", 0); - if (priv->bottomX < priv->topX || !priv->bottomX) - { - area->bottomX = priv->bottomX = priv->wcmMaxX; - } - - /* set unconfigured bottom to max */ - priv->bottomY = xf86SetIntOption(local->options, "BottomY", 0); - if (priv->bottomY < priv->topY || !priv->bottomY) - { - area->bottomY = priv->bottomY = priv->wcmMaxY; - } - - if (priv->twinview > TV_XINERAMA) - priv->numScreen = 2; - - if (priv->screen_no != -1 && - (priv->screen_no >= priv->numScreen || priv->screen_no < 0)) - { - if (priv->twinview <= TV_XINERAMA) - { - ErrorF("%s: invalid screen number %d, resetting to default (-1) \n", - local->name, priv->screen_no); - priv->screen_no = -1; - } - else if (priv->screen_no > 1) - { - ErrorF("%s: invalid screen number %d, resetting to default (-1) \n", - local->name, priv->screen_no); - priv->screen_no = -1; - } - } - - /* need maxWidth and maxHeight for keepshape */ - xf86WcmDesktopSize(local); - - /* Maintain aspect ratio to the whole desktop - * May need to consider a specific screen in multimonitor settings - */ - if (priv->flags & KEEP_SHAPE_FLAG) - { - - screenRatio = ((double)priv->maxWidth / (double)priv->maxHeight); - tabletRatio = ((double)(priv->wcmMaxX - priv->topX) / - (double)(priv->wcmMaxY - priv->topY)); - - DBG(2, priv->debugLevel, ErrorF("screenRatio = %.3g, " - "tabletRatio = %.3g\n", screenRatio, tabletRatio)); - - if (screenRatio > tabletRatio) - { - area->bottomX = priv->bottomX = priv->wcmMaxX; - area->bottomY = priv->bottomY = (priv->wcmMaxY - priv->topY) * - tabletRatio / screenRatio + priv->topY; - } - else - { - area->bottomX = priv->bottomX = (priv->wcmMaxX - priv->topX) * - screenRatio / tabletRatio + priv->topX; - area->bottomY = priv->bottomY = priv->wcmMaxY; - } - } - /* end keep shape */ - - inlist = priv->tool->arealist; - - /* The first one in the list is always valid */ - if (area != inlist && xf86WcmAreaListOverlap(area, inlist)) - { - inlist = priv->tool->arealist; - - /* remove this overlapped area from the list */ - for (; inlist; inlist=inlist->next) - { - if (inlist->next == area) - { - inlist->next = area->next; - xfree(area); - priv->toolarea = NULL; - break; - } - } - - /* Remove this device from the common struct */ - if (common->wcmDevices == priv) - common->wcmDevices = priv->next; - else - { - WacomDevicePtr tmp = common->wcmDevices; - while(tmp->next && tmp->next != priv) - tmp = tmp->next; - if(tmp) - tmp->next = priv->next; - } - xf86Msg(X_ERROR, "%s: Top/Bottom area overlaps with another devices.\n", - local->conf_idev->identifier); - return FALSE; - } - return TRUE; -} - -/***************************************************************************** - * xf86WcmVirtaulTabletSize(LocalDevicePtr local) - ****************************************************************************/ - -void xf86WcmVirtaulTabletSize(LocalDevicePtr local) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - - if (!(priv->flags & ABSOLUTE_FLAG)) - { - priv->sizeX = priv->bottomX - priv->topX; - priv->sizeY = priv->bottomY - priv->topY; - return; - } - - priv->sizeX = priv->bottomX - priv->topX - priv->tvoffsetX; - priv->sizeY = priv->bottomY - priv->topY - priv->tvoffsetY; - - DBG(10, priv->debugLevel, ErrorF("xf86WcmVirtaulTabletSize for \"%s\" " - "x=%d y=%d \n", local->name, priv->sizeX, priv->sizeY)); - return; -} - -/***************************************************************************** - * xf86WcmInitialCoordinates - ****************************************************************************/ -void xf86WcmInitialCoordinates(LocalDevicePtr local, int axes) -{ - WacomDevicePtr priv = (WacomDevicePtr)local->private; - int topx = 0, topy = 0, resolution; - int bottomx = priv->wcmMaxX, bottomy = priv->wcmMaxY; - - xf86WcmMappingFactor(local); - - /* x ax */ - if ( !axes ) - { - if (priv->flags & ABSOLUTE_FLAG) - { - topx = priv->topX; - bottomx = priv->sizeX + priv->topX; - if ((priv->currentScreen == 1) && (priv->twinview > TV_XINERAMA)) - topx += priv->tvoffsetX; - if ((priv->currentScreen == 0) && (priv->twinview > TV_XINERAMA)) - bottomx -= priv->tvoffsetX; - } - - resolution = priv->wcmResolX; -#ifdef WCM_XORG_TABLET_SCALING - /* Ugly hack for Xorg 7.3, which doesn't call xf86WcmDevConvert - * for coordinate conversion at the moment */ - topx = 0; - bottomx = priv->sizeX; - if ((priv->twinview == TV_LEFT_RIGHT) || (priv->twinview == TV_RIGHT_LEFT)) - bottomx *= 2; - bottomx = (int)((double)bottomx * priv->factorX + 0.5); - resolution = (int)((double)resolution * priv->factorX + 0.5); -#endif - - InitValuatorAxisStruct(local->dev, 0, topx, bottomx, - resolution, 0, resolution); - } - else /* y ax */ - { - if (priv->flags & ABSOLUTE_FLAG) - { - topy = priv->topY; - bottomy = priv->sizeY + priv->topY; - if ((priv->currentScreen == 1) && (priv->twinview > TV_XINERAMA)) - topy += priv->tvoffsetY; - if ((priv->currentScreen == 0) && (priv->twinview > TV_XINERAMA)) - bottomy -= priv->tvoffsetY; - } - - resolution = priv->wcmResolY; -#ifdef WCM_XORG_TABLET_SCALING - /* Ugly hack for Xorg 7.3, which doesn't call xf86WcmDevConvert - * for coordinate conversion at the moment */ - topy = 0; - bottomy = priv->sizeY; - if ((priv->twinview == TV_ABOVE_BELOW) || (priv->twinview == TV_BELOW_ABOVE)) - bottomy *= 2; - bottomy = (int)((double)bottomy * priv->factorY + 0.5); - resolution = (int)((double)resolution * priv->factorY + 0.5); -#endif - - InitValuatorAxisStruct(local->dev, 1, topy, bottomy, - resolution, 0, resolution); - } - return; -} - -#ifdef WCM_KEY_SENDING_SUPPORT /***************************************************************************** * xf86WcmRegisterX11Devices -- * Register the X11 input devices with X11 core. @@ -557,25 +306,10 @@ static void xf86WcmInitialToolSize(LocalDevicePtr local) WacomToolPtr toollist = common->wcmTool; WacomToolAreaPtr arealist; - if (IsTouch(priv)) - { - priv->wcmMaxX = common->wcmMaxTouchX; - priv->wcmMaxY = common->wcmMaxTouchY; - priv->wcmResolX = common->wcmTouchResolX; - priv->wcmResolY = common->wcmTouchResolY; - } - else - { - priv->wcmMaxX = common->wcmMaxX; - priv->wcmMaxY = common->wcmMaxY; - priv->wcmResolX = common->wcmResolX; - priv->wcmResolY = common->wcmResolY; - } - - DBG(2, common->debugLevel, ErrorF("Wacom \"%s\" " + DBG(2, priv->debugLevel, ErrorF("Wacom \"%s\" " "max X=%d max Y=%d resol X=%d resol Y=%d\n", local->name, common->wcmMaxX, common->wcmMaxY, - priv->wcmResolX, priv->wcmResolY)); + common->wcmResolX, common->wcmResolY)); for (; toollist; toollist=toollist->next) @@ -584,13 +318,13 @@ static void xf86WcmInitialToolSize(LocalDevicePtr local) for (; arealist; arealist=arealist->next) { if (!arealist->bottomX) - arealist->bottomX = priv->wcmMaxX; + arealist->bottomX = common->wcmMaxX; if (!arealist->bottomY) - arealist->bottomY = priv->wcmMaxY; + arealist->bottomY = common->wcmMaxY; } } - DBG(2, common->debugLevel, ErrorF("Wacom device \"%s\" " + DBG(2, priv->debugLevel, ErrorF("Wacom device \"%s\" " "top X=%d top Y=%d bottom X=%d bottom Y=%d \n", local->name, priv->topX, priv->topY, priv->bottomX, priv->bottomY)); @@ -813,7 +547,7 @@ Bool xf86WcmIsWacomDevice (char* fname, struct input_id* id) { int fd = -1; - fd = open(fname, O_RDONLY); + SYSCALL(fd = open(fname, O_RDONLY)); if (fd < 0) return FALSE; diff --git a/src/xdrv/xf86Wacom.h b/src/xdrv/xf86Wacom.h index 742f638..7d03a3a 100755 --- a/src/xdrv/xf86Wacom.h +++ b/src/xdrv/xf86Wacom.h @@ -233,5 +233,11 @@ int xf86WcmSetPadCoreMode(LocalDevicePtr local); /* calculate the proper tablet to screen mapping factor */ void xf86WcmMappingFactor(LocalDevicePtr local); +/* send a soft prox-out event for local */ +void xf86WcmSoftOutEvent(LocalDevicePtr local); + +/* send a soft prox-out event for device at the channel */ +void xf86WcmSoftOut(WacomCommonPtr common, int channel); + /****************************************************************************/ #endif /* __XF86WACOM_H */ diff --git a/src/xdrv/xf86WacomDefs.h b/src/xdrv/xf86WacomDefs.h index 833bf70..f2c26a3 100755 --- a/src/xdrv/xf86WacomDefs.h +++ b/src/xdrv/xf86WacomDefs.h @@ -24,9 +24,17 @@ * General Defines ****************************************************************************/ #ifdef WCM_ENABLE_LINUXINPUT -#include <asm/types.h> -#include <linux/input.h> -#define MAX_USB_EVENTS 32 + #include <asm/types.h> + #include <linux/input.h> + #define MAX_USB_EVENTS 32 + + /* for access TOOL, BTN, and key codes of USB tablets */ + #define BIT(x) (1<<((x) & (BITS_PER_LONG - 1))) + #define BITS_PER_LONG (sizeof(long) * 8) + #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) + #define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y)) + #define OFF(x) ((x)%BITS_PER_LONG) + #define LONG(x) ((x)/BITS_PER_LONG) #endif /* WCM_ENABLE_LINUXINPUT */ #define DEFAULT_SPEED 1.0 /* default relative cursor speed */ @@ -140,6 +148,11 @@ struct _WacomModel * tablet buttons besides the strips are * treated as buttons */ +#define SCROLL_UP 5 /* absolute/relative wheel/strip up event */ +#define SCROLL_DOWN 4 /* absolute/relative wheel/strip down event */ +#define SCROLL_LEFT 7 /* scroll left event for gesture */ +#define SCROLL_RIGHT 6 /* scroll right event for gesture */ + struct _WacomDeviceRec { /* configuration fields */ @@ -154,10 +167,6 @@ struct _WacomDeviceRec int bottomY; /* Y bottom */ int sizeX; /* active X size */ int sizeY; /* active Y size */ - int wcmMaxX; /* max tool logical X value */ - int wcmMaxY; /* max tool logical Y value */ - int wcmResolX; /* tool X resolution in points/inch */ - int wcmResolY; /* tool Y resolution in points/inch */ double factorX; /* X factor */ double factorY; /* Y factor */ unsigned int serial; /* device serial number */ @@ -306,10 +315,6 @@ struct _WacomChannel /* the following struct contains the current known state of the * device channel, as well as the previous MAX_SAMPLES states * for use in detecting hardware defects, jitter, trends, etc. */ - - /* the following union contains the current known state of the - * device channel, as well as the previous MAX_SAMPLES states - * for use in detecting hardware defects, jitter, trends, etc. */ union { WacomDeviceState state; /* current state */ @@ -355,6 +360,7 @@ struct _WacomDeviceClass #define DEVICE_ISDV4 0x000C #define MAX_CHANNELS 2 +#define MAX_FINGERS 2 struct _WacomCommonRec { @@ -366,16 +372,11 @@ struct _WacomCommonRec int fd_refs; /* number of references to fd; if =0, fd is invalid */ dev_t min_maj; /* minor/major number */ - /* These values are in tablet coordinates */ - int wcmMaxX; /* tablet logical max X value */ - int wcmMaxY; /* tablet logical max Y value */ + int wcmMaxX; /* max tool logical X value */ + int wcmMaxY; /* max tool logical Y value */ + int wcmResolX; /* tool X resolution in points/inch */ + int wcmResolY; /* tool Y resolution in points/inch */ int wcmMaxZ; /* tablet max Z value */ - int wcmMaxTouchX; /* touch panel logical max X value */ - int wcmMaxTouchY; /* touch panel logical max Y value */ - int wcmResolX; /* pen tool X resolution in points/inch */ - int wcmResolY; /* pen tool Y resolution in points/inch */ - int wcmTouchResolX; /* touch X resolution in points/mm */ - int wcmTouchResolY; /* touch Y resolution in points/mm */ /* tablet Z resolution is equivalent * to wcmMaxZ which is equal to 100% pressure */ int wcmMaxCapacity; /* max capacity value */ @@ -409,21 +410,23 @@ struct _WacomCommonRec WacomDeviceClassPtr wcmDevCls; /* device class functions */ WacomModelPtr wcmModel; /* model-specific functions */ - char * wcmEraserID; /* eraser associated with the stylus */ - int wcmTPCButton; /* set Tablet PC button on/off */ - int wcmTouch; /* disable/enable touch event */ - int wcmTPCButtonDefault; /* Tablet PC button default */ - int wcmTouchDefault; /* default touch to disable when not supported */ - int wcmGesture; /* disable/enable touch gesture */ - int wcmGestureDefault; /* default touch gesture to disable when not supported */ - int wcmCapacity; /* disable/enable capacity */ - int wcmCapacityDefault; /* default to -1 when capacity isn't supported/disabled */ - /* 3 when capacity is supported */ - int wcmMaxCursorDist; /* Max mouse distance reported so far */ - int wcmCursorProxoutDist; /* Max mouse distance for proxy-out max/256 units */ + char * wcmEraserID; /* eraser associated with the stylus */ + int wcmTPCButton; /* set Tablet PC button on/off */ + int wcmTouch; /* disable/enable touch event */ + int wcmTPCButtonDefault; /* Tablet PC button default */ + int wcmTouchDefault; /* default touch to disable when not supported */ + int wcmGestureMode; /* data is in Gesture Mode? */ + WacomDeviceState wcmGestureState[MAX_FINGERS]; /* inital state when in gesture mode */ + int wcmGesture; /* disable/enable touch gesture */ + int wcmGestureDefault; /* default touch gesture to disable when not supported */ + int wcmCapacity; /* disable/enable capacity */ + int wcmCapacityDefault; /* default to -1 when capacity isn't supported/disabled */ + /* 3 when capacity is supported */ + int wcmMaxCursorDist; /* Max mouse distance reported so far */ + int wcmCursorProxoutDist; /* Max mouse distance for proxy-out max/256 units */ int wcmCursorProxoutDistDefault; /* Default max mouse distance for proxy-out */ int wcmSuppress; /* transmit position on delta > supress */ - int wcmRawSample; /* Number of raw data used to filter an event */ + int wcmRawSample; /* Number of raw data used to filter an event */ int bufpos; /* position with buffer */ unsigned char buffer[BUFFER_SIZE]; /* data read from device */ |