diff options
Diffstat (limited to 'drivers/input/touchscreen/wacom_w8001.c')
-rw-r--r-- | drivers/input/touchscreen/wacom_w8001.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 56dc35c94bb1..bc642f1be376 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -62,6 +62,7 @@ struct w8001 { | |||
62 | unsigned char response[W8001_MAX_LENGTH]; | 62 | unsigned char response[W8001_MAX_LENGTH]; |
63 | unsigned char data[W8001_MAX_LENGTH]; | 63 | unsigned char data[W8001_MAX_LENGTH]; |
64 | char phys[32]; | 64 | char phys[32]; |
65 | int type; | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | static void parse_data(u8 *data, struct w8001_coord *coord) | 68 | static void parse_data(u8 *data, struct w8001_coord *coord) |
@@ -88,11 +89,52 @@ static void parse_data(u8 *data, struct w8001_coord *coord) | |||
88 | coord->tilt_y = data[8] & 0x7F; | 89 | coord->tilt_y = data[8] & 0x7F; |
89 | } | 90 | } |
90 | 91 | ||
92 | static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | ||
93 | { | ||
94 | struct input_dev *dev = w8001->dev; | ||
95 | |||
96 | /* | ||
97 | * We have 1 bit for proximity (rdy) and 3 bits for tip, side, | ||
98 | * side2/eraser. If rdy && f2 are set, this can be either pen + side2, | ||
99 | * or eraser. assume | ||
100 | * - if dev is already in proximity and f2 is toggled → pen + side2 | ||
101 | * - if dev comes into proximity with f2 set → eraser | ||
102 | * If f2 disappears after assuming eraser, fake proximity out for | ||
103 | * eraser and in for pen. | ||
104 | */ | ||
105 | |||
106 | if (!w8001->type) { | ||
107 | w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
108 | } else if (w8001->type == BTN_TOOL_RUBBER) { | ||
109 | if (!coord->f2) { | ||
110 | input_report_abs(dev, ABS_PRESSURE, 0); | ||
111 | input_report_key(dev, BTN_TOUCH, 0); | ||
112 | input_report_key(dev, BTN_STYLUS, 0); | ||
113 | input_report_key(dev, BTN_STYLUS2, 0); | ||
114 | input_report_key(dev, BTN_TOOL_RUBBER, 0); | ||
115 | input_sync(dev); | ||
116 | w8001->type = BTN_TOOL_PEN; | ||
117 | } | ||
118 | } else { | ||
119 | input_report_key(dev, BTN_STYLUS2, coord->f2); | ||
120 | } | ||
121 | |||
122 | input_report_abs(dev, ABS_X, coord->x); | ||
123 | input_report_abs(dev, ABS_Y, coord->y); | ||
124 | input_report_abs(dev, ABS_PRESSURE, coord->pen_pressure); | ||
125 | input_report_key(dev, BTN_TOUCH, coord->tsw); | ||
126 | input_report_key(dev, BTN_STYLUS, coord->f1); | ||
127 | input_report_key(dev, w8001->type, coord->rdy); | ||
128 | input_sync(dev); | ||
129 | |||
130 | if (!coord->rdy) | ||
131 | w8001->type = 0; | ||
132 | } | ||
133 | |||
91 | static irqreturn_t w8001_interrupt(struct serio *serio, | 134 | static irqreturn_t w8001_interrupt(struct serio *serio, |
92 | unsigned char data, unsigned int flags) | 135 | unsigned char data, unsigned int flags) |
93 | { | 136 | { |
94 | struct w8001 *w8001 = serio_get_drvdata(serio); | 137 | struct w8001 *w8001 = serio_get_drvdata(serio); |
95 | struct input_dev *dev = w8001->dev; | ||
96 | struct w8001_coord coord; | 138 | struct w8001_coord coord; |
97 | unsigned char tmp; | 139 | unsigned char tmp; |
98 | 140 | ||
@@ -112,11 +154,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
112 | 154 | ||
113 | w8001->idx = 0; | 155 | w8001->idx = 0; |
114 | parse_data(w8001->data, &coord); | 156 | parse_data(w8001->data, &coord); |
115 | input_report_abs(dev, ABS_X, coord.x); | 157 | report_pen_events(w8001, &coord); |
116 | input_report_abs(dev, ABS_Y, coord.y); | ||
117 | input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure); | ||
118 | input_report_key(dev, BTN_TOUCH, coord.tsw); | ||
119 | input_sync(dev); | ||
120 | break; | 158 | break; |
121 | 159 | ||
122 | case 10: | 160 | case 10: |
@@ -221,6 +259,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
221 | 259 | ||
222 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 260 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
223 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 261 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
262 | input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN); | ||
263 | input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER); | ||
264 | input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS); | ||
265 | input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2); | ||
224 | 266 | ||
225 | serio_set_drvdata(serio, w8001); | 267 | serio_set_drvdata(serio, w8001); |
226 | err = serio_open(serio, drv); | 268 | err = serio_open(serio, drv); |