Re: [RFC 4/5] hid: Add idtags to modalias
From: Benjamin Tissoires
Date: Tue Apr 03 2012 - 04:45:07 EST
On Tue, Apr 3, 2012 at 09:05, Henrik Rydberg <rydberg@xxxxxxxxxxx> wrote:
> HID devices are only partially presented to userland. Hotplugged
> devices emit events containing a modalias based on the basic bus,
> vendor and product entities. However, in practise a hid device can
> depend on details such as a single usb interface or a particular item
> in a report descriptor.
>
> This patch adds a special interface tag to the hid device id, and
> broadcasts it using both uevent and modalias. Matching ids are
> introduced for the hid-multitouch driver. As a consequence, generic
> hid will no longer match multitouch devices, and udev will
> automatically load hid-multitouch instead.
>
> Signed-off-by: Henrik Rydberg <rydberg@xxxxxxxxxxx>
> ---
> drivers/hid/hid-core.c | 28 +++++++++++++++++++++++++---
> drivers/hid/hid-multitouch.c | 7 ++++++-
> include/linux/hid.h | 7 +++++++
> include/linux/mod_devicetable.h | 2 +-
> scripts/mod/file2alias.c | 2 ++
> 5 files changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index 8a7b59e..1cf6cb5 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -205,6 +205,10 @@ static int hid_add_usage(struct hid_parser *parser, unsigned usage)
> parser->collection_stack_ptr ?
> parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
> parser->local.usage_index++;
> +
> + if (usage == HID_DG_CONTACTID)
> + parser->device->idtags |= HID_IDTAG_MULTITOUCH;
> +
> return 0;
> }
>
> @@ -1154,7 +1158,7 @@ EXPORT_SYMBOL_GPL(hid_input_report);
> static bool hid_match_one_id(struct hid_device *hdev,
> const struct hid_device_id *id)
> {
> - return id->bus == hdev->bus &&
> + return id->bus == hdev->bus && id->idtags == hdev->idtags &&
> (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
> (id->product == HID_ANY_ID || id->product == hdev->product);
> }
> @@ -1723,6 +1727,23 @@ static int hid_device_remove(struct device *dev)
> return 0;
> }
>
> +static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
> + char *buf)
> +{
> + struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> + int len;
> +
> + len = snprintf(buf, PAGE_SIZE, "hid:b%04Xi%04Xv%08Xp%08X\n",
> + hdev->bus, hdev->idtags, hdev->vendor, hdev->product);
> +
> + return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
> +}
> +
> +static struct device_attribute hid_dev_attrs[] = {
> + __ATTR_RO(modalias),
> + __ATTR_NULL,
> +};
> +
> static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
> {
> struct hid_device *hdev = container_of(dev, struct hid_device, dev);
> @@ -1740,8 +1761,8 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
> if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq))
> return -ENOMEM;
>
> - if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X",
> - hdev->bus, hdev->vendor, hdev->product))
> + if (add_uevent_var(env, "MODALIAS=hid:b%04Xi%04Xv%08Xp%08X",
> + hdev->bus, hdev->idtags, hdev->vendor, hdev->product))
> return -ENOMEM;
>
> return 0;
> @@ -1749,6 +1770,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
>
> static struct bus_type hid_bus_type = {
> .name = "hid",
> + .dev_attrs = hid_dev_attrs,
> .match = hid_bus_match,
> .probe = hid_device_probe,
> .remove = hid_device_remove,
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index 421b16c..80ceab5 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -104,7 +104,7 @@ struct mt_device {
> #define MT_DEFAULT_MAXCONTACT 10
>
> #define HID_USB_MT_DEVICE(v, p) \
> - HID_USB_DEVICE(v, p)
> + .idtags = HID_IDTAG_MULTITOUCH, HID_USB_DEVICE(v, p)
>
> /*
> * these device-dependent functions determine what slot corresponds
> @@ -886,6 +886,11 @@ static const struct hid_device_id mt_devices[] = {
> HID_USB_MT_DEVICE(USB_VENDOR_ID_XIROKU,
> USB_DEVICE_ID_XIROKU_CSR2) },
>
> + /* Generic MT device */
> + { .driver_data = MT_CLS_DEFAULT,
> + HID_USB_MT_DEVICE(HID_ANY_ID,
> + HID_ANY_ID) },
This breaks the mechanism used to detect serial protocol.
A better solution would be to keep .driver_data = 0 -> this would tell
us that the device is unknown and that we can override the given
settings.
Thanks,
Benjamin
> +
> { }
> };
> MODULE_DEVICE_TABLE(hid, mt_devices);
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 5b3be43..1e68543 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -62,6 +62,12 @@
>
> #define HID_MAX_DESCRIPTOR_SIZE 4096
>
> +/*
> + * HID identifying tags extracted from reports
> + */
> +#define HID_IDTAG_MULTITOUCH 0x0001
> +
> +
> #ifdef __KERNEL__
>
> #include <linux/types.h>
> @@ -473,6 +479,7 @@ struct hid_device { /* device report descriptor */
> unsigned maxcollection; /* Number of parsed collections */
> unsigned maxapplication; /* Number of applications */
> __u16 bus; /* BUS ID */
> + __u16 idtags; /* Identifying tags extracted from reports */
> __u32 vendor; /* Vendor ID */
> __u32 product; /* Product ID */
> __u32 version; /* HID version */
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 83ac071..25446f0 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -135,7 +135,7 @@ struct usb_device_id {
>
> struct hid_device_id {
> __u16 bus;
> - __u16 pad1;
> + __u16 idtags;
> __u32 vendor;
> __u32 product;
> kernel_ulong_t driver_data
> diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
> index b89efe6..d0c3a2b 100644
> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -336,10 +336,12 @@ static int do_hid_entry(const char *filename,
> struct hid_device_id *id, char *alias)
> {
> id->bus = TO_NATIVE(id->bus);
> + id->idtags = TO_NATIVE(id->idtags);
> id->vendor = TO_NATIVE(id->vendor);
> id->product = TO_NATIVE(id->product);
>
> sprintf(alias, "hid:b%04X", id->bus);
> + ADD(alias, "i", true, id->idtags);
> ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
> ADD(alias, "p", id->product != HID_ANY_ID, id->product);
>
> --
> 1.7.9.5
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/