[PATCH] elo: Support non-pressure-sensitive ELO touchscreens * Use the touch status bit rather than the pressure bits to distinguish a BTN_TOUCH event. Non-pressure-sensitive touchscreens always report full pressure. * Report ABS_PRESSURE information only if the touchscreen supports it. * Implement the checksum calculation correctly, and verify that the transmitted checksum is correct. * Use dev_dbg to log errors in the protocol. Signed-off-by: Shaun Jackman diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index c86a2eb..b972184 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -35,6 +35,8 @@ MODULE_LICENSE("GPL"); */ #define ELO_MAX_LENGTH 10 +#define ELO10_TOUCH 0x03 +#define ELO10_PRESSURE 0x80 /* * Per-touchscreen data. @@ -53,38 +55,40 @@ struct elo { static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs) { struct input_dev *dev = elo->dev; + struct device *dbg = &elo->serio->dev; - elo->csum += elo->data[elo->idx] = data; - + elo->data[elo->idx] = data; switch (elo->idx++) { - case 0: + elo->csum = 0xaa; if (data != 'U') { + dev_dbg(dbg, "unsynchronized data: 0x%02x\n", data); elo->idx = 0; - elo->csum = 0; } break; - - case 1: - if (data != 'T') { - elo->idx = 0; - elo->csum = 0; - } - break; - case 9: - if (elo->csum) { - input_regs(dev, regs); - input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); - input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); - input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]); - input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]); - input_sync(dev); - } elo->idx = 0; - elo->csum = 0; + if (elo->csum != elo->data[9]) { + dev_dbg(dbg, "bad checksum: 0x%02x, expected 0x%02x\n", + elo->data[9], elo->csum); + break; + } + if (elo->data[1] != 'T') { + dev_dbg(dbg, "unexpected packet: 0x%02x\n", + elo->data[1]); + break; + } + input_regs(dev, regs); + input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); + input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); + if (elo->data[2] & ELO10_PRESSURE) + input_report_abs(dev, ABS_PRESSURE, + (elo->data[8] << 8) | elo->data[7]); + input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); + input_sync(dev); break; } + elo->csum += data; } static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)