11.12.2019 19:03, Michał Mirosław пишет: > Support ELAN touchpad sensor with older firmware as found on eg. Asus > Transformer Pads. > > Signed-off-by: Michał Mirosław <mirq-linux@xxxxxxxxxxxx> > --- > drivers/input/touchscreen/elants_i2c.c | 36 ++++++++++++++++++-------- > 1 file changed, 25 insertions(+), 11 deletions(-) > > diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c > index 887888c53996..eadd26d5a06f 100644 > --- a/drivers/input/touchscreen/elants_i2c.c > +++ b/drivers/input/touchscreen/elants_i2c.c > @@ -65,6 +65,7 @@ > #define CMD_HEADER_REK 0x66 > > /* FW position data */ > +#define PACKET_SIZE_OLD 40 > #define PACKET_SIZE 55 > #define MAX_CONTACT_NUM 10 > #define FW_POS_HEADER 0 > @@ -792,7 +793,8 @@ static int elants_i2c_fw_update(struct elants_data *ts) > * Event reporting. > */ > > -static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) > +static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf, > + size_t report_len) > { > struct input_dev *input = ts->input; > unsigned int n_fingers; > @@ -804,7 +806,8 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) > buf[FW_POS_STATE]; > > dev_dbg(&ts->client->dev, > - "n_fingers: %u, state: %04x\n", n_fingers, finger_state); > + "n_fingers: %u, state: %04x, report_len: %zu\n", > + n_fingers, finger_state, report_len); > > for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) { > if (finger_state & 1) { > @@ -814,8 +817,16 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) > pos = &buf[FW_POS_XY + i * 3]; > x = (((u16)pos[0] & 0xf0) << 4) | pos[1]; > y = (((u16)pos[0] & 0x0f) << 8) | pos[2]; > - p = buf[FW_POS_PRESSURE + i]; > - w = buf[FW_POS_WIDTH + i]; > + if (report_len == PACKET_SIZE_OLD) { > + w = buf[FW_POS_WIDTH + i / 2]; > + w >>= 4 * (~i & 1); // little-endian-nibbles > + w |= w << 4; > + w |= !w; > + p = w; Did you copy this from the downstream driver as-is? I'm looking at the Nexus 7 driver and it does the following for older format: u8 size_idx[] = { 35, 35, 36, 36, 37, 37, 38, 38, 39, 39 }; unsigned int s; if (i & 1) s = buf[size_idx[i]]; else s = buf[size_idx[i]] / 16; w = s & 0xf; p = s * 16; > + } else { > + p = buf[FW_POS_PRESSURE + i]; > + w = buf[FW_POS_WIDTH + i]; > + } > > dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n", > i, x, y, p, w); > @@ -848,7 +859,8 @@ static u8 elants_i2c_calculate_checksum(u8 *buf) > return checksum; > } > > -static void elants_i2c_event(struct elants_data *ts, u8 *buf) > +static void elants_i2c_event(struct elants_data *ts, u8 *buf, > + size_t report_len) > { > u8 checksum = elants_i2c_calculate_checksum(buf); > > @@ -862,7 +874,7 @@ static void elants_i2c_event(struct elants_data *ts, u8 *buf) > "%s: unknown packet type: %02x\n", > __func__, buf[FW_POS_HEADER]); > else > - elants_i2c_mt_event(ts, buf); > + elants_i2c_mt_event(ts, buf, report_len); > } > > static irqreturn_t elants_i2c_irq(int irq, void *_dev) > @@ -920,7 +932,8 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) > break; > > case QUEUE_HEADER_SINGLE: > - elants_i2c_event(ts, &ts->buf[HEADER_SIZE]); > + elants_i2c_event(ts, &ts->buf[HEADER_SIZE], > + ts->buf[FW_HDR_LENGTH]); > break; > > case QUEUE_HEADER_NORMAL: > @@ -933,17 +946,18 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) > } > > report_len = ts->buf[FW_HDR_LENGTH] / report_count; > - if (report_len != PACKET_SIZE) { > + if (report_len != PACKET_SIZE && > + report_len != PACKET_SIZE_OLD) { > dev_err(&client->dev, > - "mismatching report length: %*ph\n", > + "unsupported report length: %*ph\n", > HEADER_SIZE, ts->buf); > break; > } > > for (i = 0; i < report_count; i++) { > u8 *buf = ts->buf + HEADER_SIZE + > - i * PACKET_SIZE; > - elants_i2c_event(ts, buf); > + i * report_len; > + elants_i2c_event(ts, buf, report_len); > } > break; > >