aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerecke <killertofu@gmail.com>2018-05-18 10:17:18 -0400
committerJiri Kosina <jkosina@suse.cz>2018-05-22 08:35:14 -0400
commit8947b0cfdcc111722b2293f26debdab8697f4c68 (patch)
treef31ec4a547bdfd8d0a489346d1fc604703d7073e
parent008464a9360e31b14677457dcd976fbf9dd58e2e (diff)
HID: wacom: Support "in range" for Intuos/Bamboo tablets where possible
The 1st-generation Intuos tablets (CTL-X80) include an "in range" flag like some professional tablets. To ensure the pen remains usable at as large as distance as possible (and to preemptively disable touch when it is nearby) we need to ensure that we handle these "in range" events. Handling of tool type identification has been moved to occur only when the pen is fully in prox rather than any time the "stylus_in_proximity" flag changes (which is controlled by the further-out "in range" flag). Link: https://sourceforge.net/p/linuxwacom/bugs/358/ Link: https://github.com/linuxwacom/xf86-input-wacom/issues/14 Link: https://github.com/linuxwacom/xf86-input-wacom/issues/17 Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> Tested-by: Ping Cheng <ping.cheng@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/wacom_wac.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 5f947ec20dcb..0bb44d0088ed 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2894,24 +2894,31 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
2894 struct wacom_features *features = &wacom->features; 2894 struct wacom_features *features = &wacom->features;
2895 struct input_dev *input = wacom->pen_input; 2895 struct input_dev *input = wacom->pen_input;
2896 unsigned char *data = wacom->data; 2896 unsigned char *data = wacom->data;
2897 int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; 2897 int x = 0, y = 0, p = 0, d = 0;
2898 bool pen = false, btn1 = false, btn2 = false;
2899 bool range, prox, rdy;
2898 2900
2899 if (data[0] != WACOM_REPORT_PENABLED) 2901 if (data[0] != WACOM_REPORT_PENABLED)
2900 return 0; 2902 return 0;
2901 2903
2902 prox = (data[1] & 0x20) == 0x20; 2904 range = (data[1] & 0x80) == 0x80;
2905 prox = (data[1] & 0x40) == 0x40;
2906 rdy = (data[1] & 0x20) == 0x20;
2907
2908 wacom->shared->stylus_in_proximity = range;
2909 if (delay_pen_events(wacom))
2910 return 0;
2911
2912 if (rdy) {
2913 p = le16_to_cpup((__le16 *)&data[6]);
2914 pen = data[1] & 0x01;
2915 btn1 = data[1] & 0x02;
2916 btn2 = data[1] & 0x04;
2917 }
2918 if (prox) {
2919 x = le16_to_cpup((__le16 *)&data[2]);
2920 y = le16_to_cpup((__le16 *)&data[4]);
2903 2921
2904 /*
2905 * All reports shared between PEN and RUBBER tool must be
2906 * forced to a known starting value (zero) when transitioning to
2907 * out-of-prox.
2908 *
2909 * If not reset then, to userspace, it will look like lost events
2910 * if new tool comes in-prox with same values as previous tool sent.
2911 *
2912 * Hardware does report zero in most out-of-prox cases but not all.
2913 */
2914 if (!wacom->shared->stylus_in_proximity) {
2915 if (data[1] & 0x08) { 2922 if (data[1] & 0x08) {
2916 wacom->tool[0] = BTN_TOOL_RUBBER; 2923 wacom->tool[0] = BTN_TOOL_RUBBER;
2917 wacom->id[0] = ERASER_DEVICE_ID; 2924 wacom->id[0] = ERASER_DEVICE_ID;
@@ -2919,16 +2926,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
2919 wacom->tool[0] = BTN_TOOL_PEN; 2926 wacom->tool[0] = BTN_TOOL_PEN;
2920 wacom->id[0] = STYLUS_DEVICE_ID; 2927 wacom->id[0] = STYLUS_DEVICE_ID;
2921 } 2928 }
2929 wacom->reporting_data = true;
2922 } 2930 }
2923 2931 if (range) {
2924 wacom->shared->stylus_in_proximity = prox;
2925 if (delay_pen_events(wacom))
2926 return 0;
2927
2928 if (prox) {
2929 x = le16_to_cpup((__le16 *)&data[2]);
2930 y = le16_to_cpup((__le16 *)&data[4]);
2931 p = le16_to_cpup((__le16 *)&data[6]);
2932 /* 2932 /*
2933 * Convert distance from out prox to distance from tablet. 2933 * Convert distance from out prox to distance from tablet.
2934 * distance will be greater than distance_max once 2934 * distance will be greater than distance_max once
@@ -2937,25 +2937,29 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
2937 */ 2937 */
2938 if (data[8] <= features->distance_max) 2938 if (data[8] <= features->distance_max)
2939 d = features->distance_max - data[8]; 2939 d = features->distance_max - data[8];
2940
2941 pen = data[1] & 0x01;
2942 btn1 = data[1] & 0x02;
2943 btn2 = data[1] & 0x04;
2944 } else { 2940 } else {
2945 wacom->id[0] = 0; 2941 wacom->id[0] = 0;
2946 } 2942 }
2947 2943
2948 input_report_key(input, BTN_TOUCH, pen); 2944 if (wacom->reporting_data) {
2949 input_report_key(input, BTN_STYLUS, btn1); 2945 input_report_key(input, BTN_TOUCH, pen);
2950 input_report_key(input, BTN_STYLUS2, btn2); 2946 input_report_key(input, BTN_STYLUS, btn1);
2947 input_report_key(input, BTN_STYLUS2, btn2);
2951 2948
2952 input_report_abs(input, ABS_X, x); 2949 if (prox || !range) {
2953 input_report_abs(input, ABS_Y, y); 2950 input_report_abs(input, ABS_X, x);
2954 input_report_abs(input, ABS_PRESSURE, p); 2951 input_report_abs(input, ABS_Y, y);
2955 input_report_abs(input, ABS_DISTANCE, d); 2952 }
2953 input_report_abs(input, ABS_PRESSURE, p);
2954 input_report_abs(input, ABS_DISTANCE, d);
2956 2955
2957 input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */ 2956 input_report_key(input, wacom->tool[0], range); /* PEN or RUBBER */
2958 input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */ 2957 input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
2958 }
2959
2960 if (!range) {
2961 wacom->reporting_data = false;
2962 }
2959 2963
2960 return 1; 2964 return 1;
2961} 2965}