diff options
| -rw-r--r-- | drivers/hid/wacom_wac.c | 74 |
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 | } |
