Re: [PATCH 3/3 v2] input - wacom_w8001: Add one finger touch support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 29, 2010 at 2:30 PM, Ping Cheng <pinglinux@xxxxxxxxx> wrote:
> Dmitry,
>
> Thank you for your effort in updating the patch. Most changes work for
> me. I do have comments related to raw touch data scaling for MT and
> single touch legacy client support. Details are inline.

After revisited the change you made, I think I can accept both
suggestions. The legacy client support may introduce issue. But it
won't hurt too much, I hope ;).  The MT scaling offers a consistent
support between one and two finger touch, which is good.

So, the only change left is to scale the raw x,y of 2FGT to max_pen. I
can make a version 3 of this patch for you or you can change those two
lines if you don't mind. Just let me know.

Thank you.

Ping

> On Tue, Dec 28, 2010 at 11:40 PM, Dmitry Torokhov
> <dmitry.torokhov@xxxxxxxxx> wrote:
>> Hi Ping,
>>
>> On Fri, Dec 17, 2010 at 09:37:54AM -0800, Ping Cheng wrote:
>>> Signed-off-by: Ping Cheng <pingc@xxxxxxxxx>
>>> ---
>>> Âdrivers/input/touchscreen/wacom_w8001.c | Â 89 ++++++++++++++++++++++++++++---
>>> Â1 files changed, 82 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
>>> index 59664a8..763eb8f 100644
>>> --- a/drivers/input/touchscreen/wacom_w8001.c
>>> +++ b/drivers/input/touchscreen/wacom_w8001.c
>>> @@ -3,6 +3,7 @@
>>> Â *
>>> Â * Copyright (c) 2008 Jaya Kumar
>>> Â * Copyright (c) 2010 Red Hat, Inc.
>>> + * Copyright (c) 2010 Ping Cheng, Wacom. <pingc@xxxxxxxxx>
>>> Â *
>>> Â * This file is subject to the terms and conditions of the GNU General Public
>>> Â * License. See the file COPYING in the main directory of this archive for
>>> @@ -86,6 +87,12 @@ struct w8001 {
>>> Â Â Â char phys[32];
>>> Â Â Â int type;
>>> Â Â Â unsigned int pktlen;
>>> + Â Â bool pen_in_prox;
>>> + Â Â bool has_touch;
>>
>> We already have type, why do we need these 2 fields a well?
>>
>> Actually, I tried massaging the patch a bit, could you please tell me if
>> the patch below still works for you?
>>
>> Thanks.
>>
>> --
>> Dmitry
>>
>>
>> Input: wacom_w8001 - add one finger touch support
>>
>> From: Ping Cheng <pinglinux@xxxxxxxxx>
>>
>> Signed-off-by: Ping Cheng <pingc@xxxxxxxxx>
>> Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
>> ---
>>
>> Âdrivers/input/touchscreen/wacom_w8001.c | Â123 +++++++++++++++++++++++++------
>> Â1 files changed, 101 insertions(+), 22 deletions(-)
>>
>>
>> diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
>> index 4774c09..ce8c8e1 100644
>> --- a/drivers/input/touchscreen/wacom_w8001.c
>> +++ b/drivers/input/touchscreen/wacom_w8001.c
>> @@ -3,6 +3,7 @@
>> Â*
>> Â* Copyright (c) 2008 Jaya Kumar
>> Â* Copyright (c) 2010 Red Hat, Inc.
>> + * Copyright (c) 2010 Ping Cheng, Wacom. <pingc@xxxxxxxxx>
>> Â*
>> Â* This file is subject to the terms and conditions of the GNU General Public
>> Â* License. See the file COPYING in the main directory of this archive for
>> @@ -63,11 +64,11 @@ struct w8001_coord {
>>
>> Â/* touch query reply packet */
>> Âstruct w8001_touch_query {
>> + Â Â Â u16 x;
>> + Â Â Â u16 y;
>> Â Â Â Âu8 panel_res;
>> Â Â Â Âu8 capacity_res;
>> Â Â Â Âu8 sensor_id;
>> - Â Â Â u16 x;
>> - Â Â Â u16 y;
>> Â};
>>
>> Â/*
>> @@ -86,9 +87,13 @@ struct w8001 {
>> Â Â Â Âchar phys[32];
>> Â Â Â Âint type;
>> Â Â Â Âunsigned int pktlen;
>> + Â Â Â u16 max_touch_x;
>> + Â Â Â u16 max_touch_y;
>> + Â Â Â u16 max_pen_x;
>> + Â Â Â u16 max_pen_y;
>> Â};
>>
>> -static void parse_data(u8 *data, struct w8001_coord *coord)
>> +static void parse_pen_data(u8 *data, struct w8001_coord *coord)
>> Â{
>> Â Â Â Âmemset(coord, 0, sizeof(*coord));
>>
>> @@ -112,7 +117,14 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
>> Â Â Â Âcoord->tilt_y = data[8] & 0x7F;
>> Â}
>>
>> -static void parse_touch(struct w8001 *w8001)
>> +static void parse_single_touch(u8 *data, struct w8001_coord *coord)
>> +{
>> + Â Â Â coord->x = (data[1] << 7) | data[2];
>> + Â Â Â coord->y = (data[3] << 7) | data[4];
>> + Â Â Â coord->tsw = data[0] & 0x01;
>> +}
>> +
>> +static void parse_multi_touch(struct w8001 *w8001)
>> Â{
>> Â Â Â Âstruct input_dev *dev = w8001->dev;
>> Â Â Â Âunsigned char *data = w8001->data;
>> @@ -124,8 +136,8 @@ static void parse_touch(struct w8001 *w8001)
>> Â Â Â Â Â Â Â Âinput_mt_slot(dev, i);
>> Â Â Â Â Â Â Â Âinput_mt_report_slot_state(dev, MT_TOOL_FINGER, touch);
>> Â Â Â Â Â Â Â Âif (touch) {
>> - Â Â Â Â Â Â Â Â Â Â Â int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
>> - Â Â Â Â Â Â Â Â Â Â Â int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
>> + Â Â Â Â Â Â Â Â Â Â Â int x = (data[6 * i + 1] << 7) | data[6 * i + 2];
>> + Â Â Â Â Â Â Â Â Â Â Â int y = (data[6 * i + 3] << 7) | data[6 * i + 4];
>
> Since you scaled MT max_touch_x/y to max_pen_x/y, you would need to
> scale the x and y here as well. I didn't scale MT touch data since MT
> protocol can report touch resolution on its own. See more comments
> below.
>
>> Â Â Â Â Â Â Â Â Â Â Â Â/* data[5,6] and [11,12] is finger capacity */
>>
>> Â Â Â Â Â Â Â Â Â Â Â Âinput_report_abs(dev, ABS_MT_POSITION_X, x);
>> @@ -151,6 +163,15 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query)
>> Â Â Â Âquery->y = data[5] << 9;
>> Â Â Â Âquery->y |= data[6] << 2;
>> Â Â Â Âquery->y |= (data[2] >> 3) & 0x3;
>> +
>> + Â Â Â /* Early days' single-finger touch models need the following defaults */
>> + Â Â Â if (!query->x && !query->y) {
>> + Â Â Â Â Â Â Â query->x = 1024;
>> + Â Â Â Â Â Â Â query->y = 1024;
>> + Â Â Â Â Â Â Â if (query->panel_res)
>> + Â Â Â Â Â Â Â Â Â Â Â query->x = query->y = (1 << query->panel_res);
>> + Â Â Â Â Â Â Â query->panel_res = 10;
>> + Â Â Â }
>> Â}
>>
>> Âstatic void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
>> @@ -160,16 +181,15 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
>> Â Â Â Â/*
>> Â Â Â Â * 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
>> + Â Â Â Â* 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) {
>> + Â Â Â switch (w8001->type) {
>> + Â Â Â case BTN_TOOL_RUBBER:
>> Â Â Â Â Â Â Â Âif (!coord->f2) {
>> Â Â Â Â Â Â Â Â Â Â Â Âinput_report_abs(dev, ABS_PRESSURE, 0);
>> Â Â Â Â Â Â Â Â Â Â Â Âinput_report_key(dev, BTN_TOUCH, 0);
>> @@ -179,8 +199,21 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
>> Â Â Â Â Â Â Â Â Â Â Â Âinput_sync(dev);
>> Â Â Â Â Â Â Â Â Â Â Â Âw8001->type = BTN_TOOL_PEN;
>> Â Â Â Â Â Â Â Â}
>> - Â Â Â } else {
>> + Â Â Â Â Â Â Â break;
>> +
>> + Â Â Â case BTN_TOOL_FINGER:
>> + Â Â Â Â Â Â Â input_report_key(dev, BTN_TOUCH, 0);
>> + Â Â Â Â Â Â Â input_report_key(dev, BTN_TOOL_FINGER, 0);
>> + Â Â Â Â Â Â Â input_sync(dev);
>> + Â Â Â Â Â Â Â /* fall through */
>> +
>> + Â Â Â case KEY_RESERVED:
>> + Â Â Â Â Â Â Â w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
>> + Â Â Â Â Â Â Â break;
>> +
>> + Â Â Â default:
>> Â Â Â Â Â Â Â Âinput_report_key(dev, BTN_STYLUS2, coord->f2);
>> + Â Â Â Â Â Â Â break;
>> Â Â Â Â}
>>
>> Â Â Â Âinput_report_abs(dev, ABS_X, coord->x);
>> @@ -192,7 +225,30 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
>> Â Â Â Âinput_sync(dev);
>>
>> Â Â Â Âif (!coord->rdy)
>> - Â Â Â Â Â Â Â w8001->type = 0;
>> + Â Â Â Â Â Â Â w8001->type = KEY_RESERVED;
>> +}
>> +
>> +static void report_single_touch(struct w8001 *w8001, struct w8001_coord *coord)
>> +{
>> + Â Â Â struct input_dev *dev = w8001->dev;
>> + Â Â Â unsigned int x = coord->x;
>> + Â Â Â unsigned int y = coord->y;
>> +
>> + Â Â Â /* scale to pen maximum */
>> + Â Â Â if (w8001->max_pen_x && w8001->max_touch_x)
>> + Â Â Â Â Â Â Â x = x * w8001->max_pen_x / w8001->max_touch_x;
>> +
>> + Â Â Â if (w8001->max_pen_y && w8001->max_touch_y)
>> + Â Â Â Â Â Â Â y = y * w8001->max_pen_y / w8001->max_touch_y;
>> +
>> + Â Â Â input_report_abs(dev, ABS_X, x);
>> + Â Â Â input_report_abs(dev, ABS_Y, y);
>> + Â Â Â input_report_key(dev, BTN_TOUCH, coord->tsw);
>> + Â Â Â input_report_key(dev, BTN_TOOL_FINGER, coord->tsw);
>> +
>> + Â Â Â input_sync(dev);
>> +
>> + Â Â Â w8001->type = coord->tsw ? BTN_TOOL_FINGER : KEY_RESERVED;
>> Â}
>>
>> Âstatic irqreturn_t w8001_interrupt(struct serio *serio,
>> @@ -213,9 +269,18 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
>>
>> Â Â Â Âcase W8001_PKTLEN_TOUCH93 - 1:
>> Â Â Â Âcase W8001_PKTLEN_TOUCH9A - 1:
>> - Â Â Â Â Â Â Â /* ignore one-finger touch packet. */
>> - Â Â Â Â Â Â Â if (w8001->pktlen == w8001->idx)
>> + Â Â Â Â Â Â Â tmp = w8001->data[0] & W8001_TOUCH_BYTE;
>> + Â Â Â Â Â Â Â if (tmp != W8001_TOUCH_BYTE)
>> + Â Â Â Â Â Â Â Â Â Â Â break;
>> +
>> + Â Â Â Â Â Â Â if (w8001->pktlen == w8001->idx) {
>> Â Â Â Â Â Â Â Â Â Â Â Âw8001->idx = 0;
>> + Â Â Â Â Â Â Â Â Â Â Â if (w8001->type != BTN_TOOL_PEN &&
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â w8001->type != BTN_TOOL_RUBBER) {
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â parse_single_touch(w8001->data, &coord);
>> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â report_single_touch(w8001, &coord);
>> + Â Â Â Â Â Â Â Â Â Â Â }
>> + Â Â Â Â Â Â Â }
>> Â Â Â Â Â Â Â Âbreak;
>>
>> Â Â Â Â/* Pen coordinates packet */
>> @@ -224,18 +289,18 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
>> Â Â Â Â Â Â Â Âif (unlikely(tmp == W8001_TAB_BYTE))
>> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
>>
>> - Â Â Â Â Â Â Â tmp = (w8001->data[0] & W8001_TOUCH_BYTE);
>> + Â Â Â Â Â Â Â tmp = w8001->data[0] & W8001_TOUCH_BYTE;
>> Â Â Â Â Â Â Â Âif (tmp == W8001_TOUCH_BYTE)
>> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
>>
>> Â Â Â Â Â Â Â Âw8001->idx = 0;
>> - Â Â Â Â Â Â Â parse_data(w8001->data, &coord);
>> + Â Â Â Â Â Â Â parse_pen_data(w8001->data, &coord);
>> Â Â Â Â Â Â Â Âreport_pen_events(w8001, &coord);
>> Â Â Â Â Â Â Â Âbreak;
>>
>> Â Â Â Â/* control packet */
>> Â Â Â Âcase W8001_PKTLEN_TPCCTL - 1:
>> - Â Â Â Â Â Â Â tmp = (w8001->data[0] & W8001_TOUCH_MASK);
>> + Â Â Â Â Â Â Â tmp = w8001->data[0] & W8001_TOUCH_MASK;
>> Â Â Â Â Â Â Â Âif (tmp == W8001_TOUCH_BYTE)
>> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
>>
>> @@ -248,7 +313,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
>> Â Â Â Â/* 2 finger touch packet */
>> Â Â Â Âcase W8001_PKTLEN_TOUCH2FG - 1:
>> Â Â Â Â Â Â Â Âw8001->idx = 0;
>> - Â Â Â Â Â Â Â parse_touch(w8001);
>> + Â Â Â Â Â Â Â parse_multi_touch(w8001);
>> Â Â Â Â Â Â Â Âbreak;
>> Â Â Â Â}
>>
>> @@ -278,6 +343,7 @@ static int w8001_setup(struct w8001 *w8001)
>> Â{
>> Â Â Â Âstruct input_dev *dev = w8001->dev;
>> Â Â Â Âstruct w8001_coord coord;
>> + Â Â Â struct w8001_touch_query touch;
>> Â Â Â Âint error;
>>
>> Â Â Â Âerror = w8001_command(w8001, W8001_CMD_STOP, false);
>> @@ -289,11 +355,15 @@ static int w8001_setup(struct w8001 *w8001)
>> Â Â Â Â/* penabled? */
>> Â Â Â Âerror = w8001_command(w8001, W8001_CMD_QUERY, true);
>> Â Â Â Âif (!error) {
>> + Â Â Â Â Â Â Â __set_bit(BTN_TOUCH, dev->keybit);
>> Â Â Â Â Â Â Â Â__set_bit(BTN_TOOL_PEN, dev->keybit);
>> Â Â Â Â Â Â Â Â__set_bit(BTN_TOOL_RUBBER, dev->keybit);
>> Â Â Â Â Â Â Â Â__set_bit(BTN_STYLUS, dev->keybit);
>> Â Â Â Â Â Â Â Â__set_bit(BTN_STYLUS2, dev->keybit);
>> - Â Â Â Â Â Â Â parse_data(w8001->response, &coord);
>> +
>> + Â Â Â Â Â Â Â parse_pen_data(w8001->response, &coord);
>> + Â Â Â Â Â Â Â w8001->max_pen_x = coord.x;
>> + Â Â Â Â Â Â Â w8001->max_pen_y = coord.y;
>>
>> Â Â Â Â Â Â Â Âinput_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
>> Â Â Â Â Â Â Â Âinput_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
>> @@ -312,24 +382,34 @@ static int w8001_setup(struct w8001 *w8001)
>> Â Â Â Â * second byte is empty, which indicates touch is not supported.
>> Â Â Â Â */
>> Â Â Â Âif (!error && w8001->response[1]) {
>> - Â Â Â Â Â Â Â struct w8001_touch_query touch;
>> + Â Â Â Â Â Â Â __set_bit(BTN_TOUCH, dev->keybit);
>> + Â Â Â Â Â Â Â __set_bit(BTN_TOOL_FINGER, dev->keybit);
>
> I do not think we want to set BTN_TOUCH and BTN_TOOL_FINGER for MT
> device since we do not need to support single touch for this MT
> device. Please refer to my comments for your other patch in the next
> email.
>
>> Â Â Â Â Â Â Â Âparse_touchquery(w8001->response, &touch);
>> + Â Â Â Â Â Â Â w8001->max_touch_x = touch.x;
>> + Â Â Â Â Â Â Â w8001->max_touch_y = touch.y;
>> +
>> + Â Â Â Â Â Â Â /* scale to pen maximum */
>> + Â Â Â Â Â Â Â if (w8001->max_pen_x && w8001->max_pen_y) {
>> + Â Â Â Â Â Â Â Â Â Â Â touch.x = w8001->max_pen_x;
>> + Â Â Â Â Â Â Â Â Â Â Â touch.y = w8001->max_pen_y;
>> + Â Â Â Â Â Â Â }
>
> If we scale touch for both single and MT, we need to scale the raw
> (x,y) for both too. I purposely did not want to scale MT touch since
> they can be supported in different resolution from pen by MT protocol
> now.
>
>>
>> Â Â Â Â Â Â Â Âinput_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
>> Â Â Â Â Â Â Â Âinput_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
>> - Â Â Â Â Â Â Â __set_bit(BTN_TOOL_FINGER, dev->keybit);
>>
>> Â Â Â Â Â Â Â Âswitch (touch.sensor_id) {
>> Â Â Â Â Â Â Â Âcase 0:
>> Â Â Â Â Â Â Â Âcase 2:
>> Â Â Â Â Â Â Â Â Â Â Â Âw8001->pktlen = W8001_PKTLEN_TOUCH93;
>> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
>> +
>> Â Â Â Â Â Â Â Âcase 1:
>> Â Â Â Â Â Â Â Âcase 3:
>> Â Â Â Â Â Â Â Âcase 4:
>> Â Â Â Â Â Â Â Â Â Â Â Âw8001->pktlen = W8001_PKTLEN_TOUCH9A;
>> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
>> +
>> Â Â Â Â Â Â Â Âcase 5:
>> Â Â Â Â Â Â Â Â Â Â Â Âw8001->pktlen = W8001_PKTLEN_TOUCH2FG;
>>
>> @@ -397,7 +477,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
>> Â Â Â Âinput_dev->dev.parent = &serio->dev;
>>
>> Â Â Â Âinput_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
>> - Â Â Â __set_bit(BTN_TOUCH, input_dev->keybit);
>>
>> Â Â Â Âserio_set_drvdata(serio, w8001);
>> Â Â Â Âerr = serio_open(serio, drv);
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux