aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/wacom_w8001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/wacom_w8001.c')
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c54
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
67static void parse_data(u8 *data, struct w8001_coord *coord) 68static 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
92static 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
91static irqreturn_t w8001_interrupt(struct serio *serio, 134static 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);