Re: BUG: hid-multitouch causes 10 second delay and error

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

 



Hi Henrik,

well, most of the comments you in-lined addressed the fact that I
tried to make the smallest patch possible.

On Fri, Oct 28, 2011 at 13:16, Henrik Rydberg <rydberg@xxxxxxxxxxx> wrote:
> Hi Benjamin,
>
>> Hi Sean, can you test the following patch please:
>>
>>
>> From 488272baf9bc95718dba2b9a0f62fe3309ca578f Mon Sep 17 00:00:00 2001
>> From: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxx>
>> Date: Thu, 27 Oct 2011 13:36:05 +0200
>> Subject: [PATCH 1/2] hid-multitouch: fix interaction with other hid drivers
>
> I took this patch, fixed it up, applied it to jikos/multitouch, and
> did a "git diff HEAD~3" to see the actual changes applied so far for
> generic hid-mt support. That diff is quite small, so I would recommend
> rewinding the tree once things settle down. I have commented on the
> diff below, and at the end there are three alternative (untested)
> patches, as a suggestion.
>
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 956f849..78253ae 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1212,6 +1212,11 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
>        if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
>                                connect_mask & HID_CONNECT_HIDINPUT_FORCE))
>                hdev->claimed |= HID_CLAIMED_INPUT;
> +       if (hdev->quirks & HID_QUIRK_MULTITOUCH) {
> +               /* this device should be handled by hid-multitouch, skip it */
> +               return -ENODEV;
> +       }
> +
>        if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
>                        !hdev->hiddev_connect(hdev,
>                                connect_mask & HID_CONNECT_HIDDEV_FORCE))
>
> The regret here is that hid-core needs to know about hit-mt at
> all. What it needs to know is whether the device should be dropped.
>
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 6559e2e..f333139 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -474,6 +474,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
>                        map_key_clear(BTN_STYLUS2);
>                        break;
>
> +               case 0x51: /* ContactID */
> +                       device->quirks |= HID_QUIRK_MULTITOUCH;
> +                       goto unknown;
> +
>                default:  goto unknown;
>                }
>                break;
>
> So in addition to the detection here,
>
> @@ -978,6 +982,13 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
>                }
>        }
>
> +       if (hid->quirks & HID_QUIRK_MULTITOUCH) {
> +               /* generic hid does not know how to handle multitouch devices */
> +               if (hidinput)
> +                       goto out_cleanup;
> +               goto out_unwind;
> +       }
> +
>        if (hidinput && input_register_device(hidinput->input))
>                goto out_cleanup;
>
> One could instead drop handling based on a quirk designed for that
> purpose (HID_QUIRK_HIDINPUT_DROP).
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index f1c909f..28f8ff2 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -291,6 +291,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
>                        td->last_slot_field = usage->hid;
>                        td->last_field_index = field->index;
>                        td->last_mt_collection = usage->collection_index;
> +                       hdev->quirks &= ~HID_QUIRK_MULTITOUCH;
>                        return 1;
>                case HID_DG_WIDTH:
>                        hid_map_usage(hi, usage, bit, max,
>
> Although correct per se, it is clearer to reset this flag in mt_probe().
>
> @@ -535,6 +536,12 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>        struct mt_device *td;
>        struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
>
> +       if (!id->driver_data && !(hdev->quirks & HID_QUIRK_MULTITOUCH))
> +               /* cought by HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID),
> +                * and either in hid_have_special_driver
> +                * or not detected as multitouch by hid-core */
> +               return -ENODEV;
> +
>        for (i = 0; mt_classes[i].name ; i++) {
>                if (id->driver_data == mt_classes[i].name) {
>                        mtclass = &(mt_classes[i]);
>
> Very neat solution indeed!
>
> @@ -542,10 +549,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>                }
>        }
>
> -       /* This allows the driver to correctly support devices
> -        * that emit events over several HID messages.
> -        */
> -       hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
>
>        td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
>        if (!td) {
>
> It seems there is no longer any reason to move this line around, since
> we now only come here when the device is really meant for this driver.
>
> @@ -561,10 +564,16 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>        if (ret != 0)
>                goto fail;
>
> +       hdev->quirks |= HID_QUIRK_MULTITOUCH;
>
> This is unnecessary and makes the logic blurred.
>
>        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
>        if (ret)
>                goto fail;
>
> +       /* This allows the driver to correctly support devices
> +        * that emit events over several HID messages.
> +        */
> +       hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
> +
>        td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
>                                GFP_KERNEL);
>        if (!td->slots) {
>
> In addition to not needing to be moved, this line introduces a race
> with hid-input, since the device has already started when this line is
> executed.

Well, we should use instead the new input_register callback to avoid any races.
I've got the patch, I've tested it, but I never sent it.... shame on me.

>
> @@ -758,6 +767,9 @@ static const struct hid_device_id mt_devices[] = {
>                HID_USB_DEVICE(USB_VENDOR_ID_XAT,
>                        USB_DEVICE_ID_XAT_CSR) },
>
> +       /* Rest of the world */
> +       { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
> +
>        { }
>  };
>  MODULE_DEVICE_TABLE(hid, mt_devices);
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 9cf8e7a..6fb743d 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -312,6 +312,7 @@ struct hid_item {
>  #define HID_QUIRK_BADPAD                       0x00000020
>  #define HID_QUIRK_MULTI_INPUT                  0x00000040
>  #define HID_QUIRK_HIDINPUT_FORCE               0x00000080
> +#define HID_QUIRK_MULTITOUCH                   0x00000100
>  #define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00010000
>  #define HID_QUIRK_FULLSPEED_INTERVAL           0x10000000
>  #define HID_QUIRK_NO_INIT_REPORTS              0x20000000
>
> As an alternative, here are three untested and uncommited patches
> which implements the comments above.
>

Except a comment in the second patch, I've tested it, and it worked
without any surprises ;-)

But I'm not sure we can rewind the tree as those patches are in
for-next since nearly a month.
I'll let you do the reverts, because on my local trees, it was quite
difficult (and I'm still on a 3.0.x, so I can not test against
for-next)


> --
>
> From defdac444919b99a932368ee1a8ad290dc724933 Mon Sep 17 00:00:00 2001
> From: Henrik Rydberg <rydberg@xxxxxxxxxxx>
> Date: Fri, 28 Oct 2011 11:36:36 +0200
> Subject: [PATCH 1/3] hid: Allow an input device to be dropped after parsing
>
> Some devices need a special driver based on the input mapping of the
> device. This patch enables a mechanism where hidinput can set
> HID_QUIRK_HIDINPUT_DROP to leave a device to be picked up by a special
> driver which intercepts the input mapping.
> ---
>  drivers/hid/hid-core.c  |    3 +++
>  drivers/hid/hid-input.c |    6 ++++++
>  include/linux/hid.h     |    1 +
>  3 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 956f849..2628f9c 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1212,6 +1212,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
>        if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
>                                connect_mask & HID_CONNECT_HIDINPUT_FORCE))
>                hdev->claimed |= HID_CLAIMED_INPUT;
> +       if (hdev->quirks & HID_QUIRK_HIDINPUT_DROP)
> +               return -ENODEV;
> +
>        if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
>                        !hdev->hiddev_connect(hdev,
>                                connect_mask & HID_CONNECT_HIDDEV_FORCE))
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 6559e2e..aa3ce2e 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -978,6 +978,12 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
>                }
>        }
>
> +       if (hid->quirks & HID_QUIRK_HIDINPUT_DROP) {
> +               if (hidinput)
> +                       goto out_cleanup;
> +               goto out_unwind;
> +       }
> +
>        if (hidinput && input_register_device(hidinput->input))
>                goto out_cleanup;
>
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 9cf8e7a..4028a27 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -312,6 +312,7 @@ struct hid_item {
>  #define HID_QUIRK_BADPAD                       0x00000020
>  #define HID_QUIRK_MULTI_INPUT                  0x00000040
>  #define HID_QUIRK_HIDINPUT_FORCE               0x00000080
> +#define HID_QUIRK_HIDINPUT_DROP                        0x00000100
>  #define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00010000
>  #define HID_QUIRK_FULLSPEED_INTERVAL           0x10000000
>  #define HID_QUIRK_NO_INIT_REPORTS              0x20000000
> --
> 1.7.7
>
> From 5f4fe6ef4cab9721c6b277f57d5374d6b549359d Mon Sep 17 00:00:00 2001
> From: Henrik Rydberg <rydberg@xxxxxxxxxxx>
> Date: Fri, 28 Oct 2011 11:42:39 +0200
> Subject: [PATCH 2/3] hid-input: Drop generic handling of hid-mt multitouch
>  devices
>
> The hid-mt devices are recognized by the ContactID field. This patch
> sets HID_QUIRK_MULTITOUCH accordingly, and leaves the device to be
> picked up by any driver which intercepts the ContactID field.
>
> All in-tree hid-mt drivers intercept the ContactID, so this patch has
> no other effect than to skip generic handling of hid-mt devices.

Please add here the link to
http://www.microsoft.com/whdc/device/input/DigitizerDrvs_touch.mspx
to keep the origin of this statement: ContactID means multitouch

Cheers,
Benjamin

> ---
>  drivers/hid/hid-input.c |    6 ++++++
>  include/linux/hid.h     |    1 +
>  2 files changed, 7 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index aa3ce2e..108830fc 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -474,6 +474,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
>                        map_key_clear(BTN_STYLUS2);
>                        break;
>
> +               case 0x51: /* ContactID */
> +                       device->quirks |= HID_QUIRK_MULTITOUCH;
> +                       /* hid-mt is not handled by generic hid */
> +                       device->quirks |= HID_QUIRK_HIDINPUT_DROP;
> +                       goto unknown;
> +
>                default:  goto unknown;
>                }
>                break;
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 4028a27..b9c4296 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -313,6 +313,7 @@ struct hid_item {
>  #define HID_QUIRK_MULTI_INPUT                  0x00000040
>  #define HID_QUIRK_HIDINPUT_FORCE               0x00000080
>  #define HID_QUIRK_HIDINPUT_DROP                        0x00000100
> +#define HID_QUIRK_MULTITOUCH                   0x00000200
>  #define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00010000
>  #define HID_QUIRK_FULLSPEED_INTERVAL           0x10000000
>  #define HID_QUIRK_NO_INIT_REPORTS              0x20000000
> --
> 1.7.7
>
> From 6b1ecc88b3f5cca7c9178e3900c6766544db0798 Mon Sep 17 00:00:00 2001
> From: Henrik Rydberg <rydberg@xxxxxxxxxxx>
> Date: Fri, 28 Oct 2011 12:01:08 +0200
> Subject: [PATCH 3/3] hid-multitouch: Pick up all hid-mt devices
>
> This patch adds a catch-all device entry, which "undrops" all devices
> that have been identified as hid-mt by the hid core.
> ---
>  drivers/hid/hid-multitouch.c |   12 ++++++++++++
>  1 files changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index f1c909f..1f051eb 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -535,6 +535,15 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>        struct mt_device *td;
>        struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
>
> +       if (!id->driver_data && !(hdev->quirks & HID_QUIRK_MULTITOUCH))
> +               /* cought by HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID),
> +                * and either in hid_have_special_driver
> +                * or not detected as multitouch by hid-core */
> +               return -ENODEV;
> +
> +       /* pick up the device that was dropped by hid-core */
> +       hdev->quirks &= ~HID_QUIRK_HIDINPUT_DROP;
> +
>        for (i = 0; mt_classes[i].name ; i++) {
>                if (id->driver_data == mt_classes[i].name) {
>                        mtclass = &(mt_classes[i]);
> @@ -758,6 +767,9 @@ static const struct hid_device_id mt_devices[] = {
>                HID_USB_DEVICE(USB_VENDOR_ID_XAT,
>                        USB_DEVICE_ID_XAT_CSR) },
>
> +       /* Rest of the world */
> +       { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
> +
>        { }
>  };
>  MODULE_DEVICE_TABLE(hid, mt_devices);
> --
> 1.7.7
>
>
--
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