lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 20 Aug 2010 14:55:33 +1000
From:	Peter Hutterer <peter.hutterer@...-t.net>
To:	linux-input@...r.kernel.org, linux-kernel@...r.kernel.org,
	pinglinux@...il.com, rydberg@...omail.se
Cc:	Peter Hutterer <peter.hutterer@...-t.net>
Subject: [PATCH 1/3] input: send BTN_TOOL_PEN/RUBBER and BTN_STYLUS for the w8001.

The protocol used by the w8001 supports status fields for tip, side
switch and eraser as well as a RDY field for proximity.

The protocol has a double usage for the f2 bit in the packet. If set,
the data is either pen + side2 button or eraser. Assume eraser if the
device comes into proximity with the f2 bit set, otherwise trigger the
side2 button.
If the device comes into proximity with the f2 bit and that bit
disappears afterwards, fake proximity out for the eraser and proximity
in for the pen.

Signed-off-by: Peter Hutterer <peter.hutterer@...-t.net>
---
 drivers/input/touchscreen/wacom_w8001.c |   51 +++++++++++++++++++++++++++----
 1 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 56dc35c..0e14ae1 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -62,6 +62,7 @@ struct w8001 {
 	unsigned char response[W8001_MAX_LENGTH];
 	unsigned char data[W8001_MAX_LENGTH];
 	char phys[32];
+	int type;
 };
 
 static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -88,11 +89,49 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
 	coord->tilt_y = data[8] & 0x7F;
 }
 
+static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
+{
+	struct input_dev *dev = w8001->dev;
+
+	/* We have 1 bit for proximity (rdy) and 3 bits for tip, side,
+	 * side2/eraser. If rdy && f2 are set, this can be either pen + side2,
+	 * or eraser. assume
+	 * - if dev is already in proximity and f2 is toggled → pen + side2
+	 * - if dev comes into proximity with f2 set → eraser
+	 * If f2 disappears after assuming eraser, fake proximity out for
+	 * eraser and in for pen.
+	 */
+
+	if (!w8001->type) {
+		w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+	} else if (w8001->type == BTN_TOOL_RUBBER) {
+		if (!coord->f2) {
+			input_report_abs(dev, ABS_PRESSURE, 0);
+			input_report_key(dev, BTN_TOUCH, 0);
+			input_report_key(dev, BTN_STYLUS, 0);
+			input_report_key(dev, BTN_STYLUS2, 0);
+			input_report_key(dev, BTN_TOOL_RUBBER, 0);
+			input_sync(dev);
+			w8001->type = BTN_TOOL_PEN;
+		}
+	} else
+		input_report_key(dev, BTN_STYLUS2, coord->f2);
+
+	input_report_abs(dev, ABS_X, coord->x);
+	input_report_abs(dev, ABS_Y, coord->y);
+	input_report_abs(dev, ABS_PRESSURE, coord->pen_pressure);
+	input_report_key(dev, BTN_TOUCH, coord->tsw);
+	input_report_key(dev, BTN_STYLUS, coord->f1);
+	input_report_key(dev, w8001->type, coord->rdy);
+	input_sync(dev);
+	if (!coord->rdy)
+		w8001->type = 0;
+}
+
 static irqreturn_t w8001_interrupt(struct serio *serio,
 				   unsigned char data, unsigned int flags)
 {
 	struct w8001 *w8001 = serio_get_drvdata(serio);
-	struct input_dev *dev = w8001->dev;
 	struct w8001_coord coord;
 	unsigned char tmp;
 
@@ -112,11 +151,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
 
 		w8001->idx = 0;
 		parse_data(w8001->data, &coord);
-		input_report_abs(dev, ABS_X, coord.x);
-		input_report_abs(dev, ABS_Y, coord.y);
-		input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
-		input_report_key(dev, BTN_TOUCH, coord.tsw);
-		input_sync(dev);
+		report_pen_events(w8001, &coord);
 		break;
 
 	case 10:
@@ -221,6 +256,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN);
+	input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER);
+	input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS);
+	input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2);
 
 	serio_set_drvdata(serio, w8001);
 	err = serio_open(serio, drv);
-- 
1.7.2.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ