Custom Search
|
|
Re: [PATCH 4/4] input: wacom - add 0xE5 (MT device) support | |
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] | |
On Tue, Dec 27, 2011 at 6:48 PM, Ping Cheng <pinglinux@xxxxxxxxx> wrote:
> On Wed, Dec 21, 2011 at 8:14 PM, Chris Bagwell <chris@xxxxxxxxxxxxxx> wrote:
>>
>> On Wed, Dec 21, 2011 at 12:43 PM, Ping Cheng <pinglinux@xxxxxxxxx> wrote:
>> > On Sun, Dec 18, 2011 at 6:07 PM, Chris Bagwell <chris@xxxxxxxxxxxxxx> wrote:
>> >>
>> >> On Fri, Dec 16, 2011 at 6:38 PM, Ping Cheng <pinglinux@xxxxxxxxx> wrote:
>> >> > Signed-off-by: Ping Cheng <pingc@xxxxxxxxx>
>> >> > ---
>> >> > drivers/input/tablet/wacom_sys.c | 26 ++++++------
>> >> > drivers/input/tablet/wacom_wac.c | 82
>> >> > +++++++++++++++++++++++++++++++++++++-
>> >> > drivers/input/tablet/wacom_wac.h | 8 ++++
>> >> > 3 files changed, 101 insertions(+), 15 deletions(-)
>> >> >
>> >> > diff --git a/drivers/input/tablet/wacom_sys.c
>> >> > b/drivers/input/tablet/wacom_sys.c
>> >> > index b9736fb..eee06ef 100644
>> >> > --- a/drivers/input/tablet/wacom_sys.c
>> >> > +++ b/drivers/input/tablet/wacom_sys.c
>> >> > @@ -297,6 +297,10 @@ static int wacom_parse_hid(struct usb_interface
>> >> > *intf,
>> >> > features->pktlen
>> >> > = WACOM_PKGLEN_TPC2FG;
>> >> >
>> >> > features->touch_max = 2;
>> >> > }
>> >> > +
>> >> > + if (features->type ==
>> >> > MTSCREEN)
>> >> > + features->pktlen
>> >> > = WACOM_PKGLEN_MTOUCH;
>> >> > +
>> >> > if (features->type ==
>> >> > BAMBOO_PT) {
>> >> > /* need to reset
>> >> > back */
>> >> > features->pktlen
>> >> > = WACOM_PKGLEN_BBTOUCH;
>> >> > @@ -331,18 +335,15 @@ static int wacom_parse_hid(struct usb_interface
>> >> > *intf,
>> >> > case HID_USAGE_Y:
>> >> > if (usage == WCM_DESKTOP) {
>> >> > if (finger) {
>> >> > - features->device_type =
>> >> > BTN_TOOL_FINGER;
>> >> > - if (features->type ==
>> >> > TABLETPC2FG) {
>> >> > - /* need to reset
>> >> > back */
>> >> > - features->pktlen
>> >> > = WACOM_PKGLEN_TPC2FG;
>> >> > + int type =
>> >> > features->type;
>> >> > +
>> >> > + if (type == TABLETPC2FG
>> >> > || type == MTSCREEN) {
>> >> > features->y_max =
>> >> >
>> >> > get_unaligned_le16(&report[i + 3]);
>> >> > features->y_phy =
>> >> >
>> >> > get_unaligned_le16(&report[i + 6]);
>> >> > i += 7;
>> >> > - } else if
>> >> > (features->type == BAMBOO_PT) {
>> >> > - /* need to reset
>> >> > back */
>> >> > - features->pktlen
>> >> > = WACOM_PKGLEN_BBTOUCH;
>> >> > + } else if (type ==
>> >> > BAMBOO_PT) {
>> >> > features->y_phy =
>> >> >
>> >> > get_unaligned_le16(&report[i + 3]);distracted me.
>> >> > features->y_max =
>> >> > @@ -356,10 +357,6 @@ static int wacom_parse_hid(struct usb_interface
>> >> > *intf,
>> >> > i += 4;
>> >> > }
>> >> > } else if (pen) {
>> >> > - /* penabled only accepts
>> >> > exact bytes of data */
>> >> > - if (features->type ==
>> >> > TABLETPC2FG)
>> >> > - features->pktlen
>> >> > = WACOM_PKGLEN_GRAPHIRE;
>> >> > - features->device_type =
>> >> > BTN_TOOL_PEN;
>> >>
>> >> All makes sense. Getting rid of duplicate code since X/Y will always
>> >> be present. Maybe worth a 1 line comment now that its cleaned up so
>> >> someone doesn't let it creep back in.
>> >
>> >
>> > I'll add some comments in v2.
>> >
>> >>
>> >> > features->y_max =
>> >> >
>> >> > get_unaligned_le16(&report[i + 3]);
>> >> > i += 4;
>> >> > @@ -432,7 +429,8 @@ static int wacom_query_tablet_data(struct
>> >> > usb_interface *intf, struct wacom_feat
>> >> >
>> >> > /* ask to report tablet data if it is MT Tablet PC or
>> >> > * not a Tablet PC */
>> >> > - if (features->type == TABLETPC2FG) {
>> >> > + if (((features->type == TABLETPC2FG) || (features->type ==
>> >> > MTSCREEN))
>> >> > + && features->device_type != BTN_TOOL_PEN) {
>> >>
>> >> Glad to see this device_type check. I thought it was probably needed.
>> >>
>> >> I'll have to trust you on this one but its different than Bamboo's.
>> >> The set on Bamboo is on Pen and causes it to start sending pen
>> >> packets. IIR, the touch packets are always sending. So this is
>> >> opposite and enables something related to touch?
>> >
>> >
>> > There are two types' of devices: tabletPC or non-tabletPC. For all tabletPC
>> > devices that support more than one finger/contact, a set call is needed. For
>> > all non-tabletPC devices, a set call is needed. Bamboo is a non-tabletPC
>> > device.
>> >
>> >>
>> >> Assuming you say yes, do you mind changing that to an affirmative
>> >> check for TOUCH so it reads:
>> >
>> >
>> > Well, it does not depend on whether it is touch or pen. It depends on the
>> > type of the device as explained above. Do you still want me to use your
>> > below logic?
>>
>> Let me ask this way. On Bamboo there are 2 interfaces, 1 pen and 1
>> touch. I need to set feature report 2 to a specific value on the pen
>> interface to get useful packets. If I set feature report 2 to
>> something on touch interface, I get an error response back from
>> device. This aligns with HID descriptor because only the pen
>> interface declares that feature report #2.
>>
>> I'm sure its similar for Tablet PC's. Its also writing to feature
>> report #2 but unique data values. What ever the values are, it
>> probably also doesn't make sense to write to both pen interface and
>> touch interface on Tablet PC.
>>
>> If the feature report is only on one of two interfaces I do suggest
>> changing the if() to something like below to make it more obvious ("if
>> (TOUCH)" is more obvious that your looking for specific interface then
>> "if (!PEN)"). If its on both and only 1 needs to be written to then
>> that would probably be a good comment as well.
>
> I see your point. I'll use TOUCH/PEN for the if-statement and add a comment.
>
Thanks.
>> >>
>> >> if (TOUCH)
>> >> /* do TOUCH set's */
>> >> if (PEN)
>> >> /* do PEN set's */
>> >>
>> >>
>> >> > do {
>> >> > rep_data[0] = 3;
>> >> > rep_data[1] = 4;
>> >> > @@ -479,9 +477,9 @@ static int wacom_retrieve_hid_descriptor(struct
>> >> > usb_interface *intf,
>> >> > features->pressure_fuzz = 0;
>> >> > features->distance_fuzz = 0;
>> >> >
>> >> > - /* only Tablet PCs and Bamboo P&T need to retrieve the info */
>> >> > + /* only devices that support touch need to retrieve the info */
>> >> > if ((features->type != TABLETPC) && (features->type !=
>> >> > TABLETPC2FG) &&
>> >> > - (features->type != BAMBOO_PT))
>> >> > + (features->type != BAMBOO_PT) && (features->type !=
>> >> > MTSCREEN))
>> >> > goto out;
>> >> >
>> >> > if (usb_get_extra_descriptor(interface, HID_DEVICET_HID,
>> >> > &hid_desc)) {
>> >> > diff --git a/drivers/input/tablet/wacom_wac.c
>> >> > b/drivers/input/tablet/wacom_wac.c
>> >> > index 8dc185d..1a887a1 100644
>> >> > --- a/drivers/input/tablet/wacom_wac.c
>> >> > +++ b/drivers/input/tablet/wacom_wac.c
>> >> > @@ -729,6 +729,73 @@ static int wacom_intuos_irq(struct wacom_wac
>> >> > *wacom)
>> >> > return 1;
>> >> > }
>> >> >
>> >> > +static int wacom_mt_touch(struct wacom_wac *wacom)
>> >> > +{
>> >> > + struct wacom_features *features = &wacom->features;
>> >> > + struct input_dev *input = wacom->input;
>> >> > + char *data = wacom->data;
>> >> > + struct input_mt_slot *mt;
>> >> > + int i, id = -1, j = 0, k = 4;
>> >> > + int x = 0, y = 0;
>> >> > + int current_num_contacts = data[2];
>> >> > + int contacts_to_send = 0;
>> >> > + bool touch = false;
>> >> > +
>> >> > + /* reset the counter by the first packet */
>> >> > + if (current_num_contacts) {
>> >> > + features->num_contacts = current_num_contacts;
>> >> > + features->num_contacts_left = current_num_contacts;
>> >> > + }
>> >>
>> >> It seems that the saved contact values are only processed in case were
>> >> data[2] indicates no contact counts in packet. I would think that
>> >> packets with no contacts could be ignored (return) unless there is
>> >> some data that must be implied. Why is it not ignored?
>> >
>> >
>> > current_num_contacts is only reported, hence updated, by the first set of
>> > data. Later touch data will be processed as long as number of contacts does
>> > not exceed current_num_contacts.
>> >
>> >>
>> >>
>> >> > +
>> >> > + /* There are at most 5 contacts per packet */
>> >> > + contacts_to_send = min(5, (int)features->num_contacts_left);
>> >>
>> >> Its not obvious to me if data[2] contains touches in packet or total
>> >> touches on screen.
>> >
>> >
>> > Total touches on the screen.
>>
>> OK. I understand now. It would be nice to add that to above comment
>> (the fact that num_contacts_left is total on screen).
>
> num_contacts_left is normally not the total on the screen. It is the
> number of contacts that need to be processed. num_contacts is the
> total on the screen. contacts_to_send is the number of contacts we are
> going to send.
OK. With understanding that data[2] is # of touches in packet and not
total touches on screen then my questions change slightly.
I assume if user put 6 touches a screen and moves around you'd get 2
packets with movement; 1 with data[2] == 5 and 1 with data[2] == 1.
There is this code then:
int current_num_contacts = data[2];
if (current_num_contacts) {
features->num_contacts = current_num_contacts;
features->num_contacts_left = current_num_contacts;
}
So it seems to me that num_contacts can never reach 6 (total touches
on screen). Maybe that needs to be a += or something?
>
>> >>
>> >> > +
>> >> > + for (i = 0; i < contacts_to_send; i++) {
>> >> > + id = le16_to_cpup((__le16 *)&data[k]);
>> >> > +
>> >> > + /* is there an existing slot for this contact? */
>> >> > + for (j = 0; j < features->touch_max; j++) {
>> >> > + mt = &input->mt[j];
>> >> > + if (input_mt_get_value(mt, ABS_MT_TRACKING_ID)
>> >> > == id )
>> >> > + break;
>> >> > + }
>> >> > +
>> >> > + /* no. then find an unused slot to fill */
>> >> > + if (j >= features->touch_max) {
>> >> > + for (j = 0; j < features->touch_max; j++) {
>> >> > + mt = &input->mt[j];
>> >> > + if (input_mt_get_value(mt,
>> >> > ABS_MT_TRACKING_ID) == -1 )
>> >> > + break;
>> >> > + }
>> >> > + }
>> >>
>> >> This may need a little more thought since hid-multitouch doesn't query
>> >> old value. Is there a case were a touch is removed and new touch
>> >> added in same packet? Probably that would never send the -1 to user
>> >> land.
>> >
>> >
>> > Once a touch leaves the screen, a -1 will always be sent to indicate the
>> > touch is out. When a new touch is added, it may use any available packet.
>> > Hence the one used by the just removed touch can also be used. Do I get your
>> > question properly?
>>
>> I'm thinking of this sequence inside 1 packet (probably not easy to
>> produce in the wild):
>>
>> * 1st location in packet shows Finger with ID of 100 as not touching any more.
>> * Loops threw and finds matching ID and sets to -1.
>> * 2nd location in packet shows Finger with ID of 101 as touching. Its new.
>> * Loops threw to find 1st slot with -1 and uses one we just cleared.
>> * Sync window occurs. User only sees Contact ID change from 100 and 101.
>
> Oh, I know where you are. You are in the real world, not in the
> firmware ;). The firmware can not tell if the second finger (101) is
> the same finger as the first one (100) or not. All it can do is:
> report a finger out then a finger in. So, in any moment if there is
> one finger on the screen, it report one finger. If none, it reports
> none. If, by any chance, the second one (101) touches before the first
> one out, we get two finger data before one if out.
>
> Your case won't happen, at least in theory.
OK. I only wanted to bring up the possibility. Depending on firmware
design its possible that never could happen.
>
>> >> > +
>> >> > + touch = data[k - 1] & 0x1;
>> >> > + input_mt_slot(input, j);
>> >> > + if (touch) {
>> >> > + x = le16_to_cpup((__le16 *)&data[k + 6]);
>> >> > + y = le16_to_cpup((__le16 *)&data[k + 8]);
>> >> > +
>> >> > + input_report_abs(input, ABS_MT_POSITION_X, x);
>> >> > + input_report_abs(input, ABS_MT_POSITION_Y, y);
>> >> > + } else
>> >> > + id = -1;
>> >> > +
>> >> > + /* keep the id from firmware since we need
>> >> > + * it to process future events
>> >> > + */
>> >> > + input_report_abs(input, ABS_MT_TRACKING_ID, id);
>> >> > +
>> >> > + k += WACOM_BYTES_PER_MT_PACKET;
>> >> > + }
>> >> > +
>> >> > + input_mt_report_pointer_emulation(input, true);
>> >> > +
>> >> > + features->num_contacts_left -= contacts_to_send;
>> >> > + if (features->num_contacts_left < 0)
>> >> > + features->num_contacts_left = 0;
>> >>
>> >> Same comment as above. Could use a comment on why storing this would be
>> >> needed.
>> >
>> >
>> > If you understood the value of current_num_contacts, it would be easier to
>> > see the need for num_contacts_left. I'll add a comment for
>> > current_num_contacts.
>>
>> I guess I still don't see why its needed or how its being used.
>>
>> Now that I understand that current_num_contacts is total touches, I do
>> understand you need to know when a packet contains 5 full touches and
>> when it contains less than 5. For example if 6 touches then 1st
>> packet could have 5 and next packet could have 1. So you need to know
>> to stop looping after 1. But I do not see how this num_contacts_left
>> helps that. It looks like it would set contacts_to_send to 5 in both
>> packets.
>
> Why do you think contacts_to_send could be 5? If num_contacts_left is
> 1, min(5, (int)features->num_contacts_left) should return 1, which is
> the contacts_to_send. Do I miss something?
I think it stemmed from my misunderstanding of what data[2] contained.
If it contains 1 for 2nd packet with 6th finger then
num_contacts_left would be 1 as well and it would work.
With my new understanding that data[2] is touches in packet (1 to 5)
then it seems all this num_contacts and num_contacts_left is trying to
compute total touches on the screen but then its never used by
anything. I'd get rid of it and just keep the camp of data[2] to <=
5/contacts_to_send part.
Chris
>
> Ping
--
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
![]() |