aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2012-04-23 06:07:02 -0400
committerJiri Kosina <jkosina@suse.cz>2012-05-01 06:54:54 -0400
commit4d53b8012f1f01ddb3f24db2031b042bb4cbd0d0 (patch)
tree4536bb9fefb51c212f28dee84e810ab0d6854a6e
parenta7197c2e4120ce40e7e3f5580336b9a1dc791220 (diff)
HID: Add device group to modalias
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 device group to the hid device id, and broadcasts it using uevent and the device modalias. The module alias generation is modified to match. As a consequence, a device with a non-zero group will be processed by the corresponding group driver instead of by the generic hid driver. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-core.c24
-rw-r--r--include/linux/hid.h1
-rw-r--r--include/linux/mod_devicetable.h3
-rw-r--r--scripts/mod/file2alias.c2
4 files changed, 27 insertions, 3 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9ed4ff37dc2b..cfcb69eb17d6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1222,6 +1222,7 @@ static bool hid_match_one_id(struct hid_device *hdev,
1222 const struct hid_device_id *id) 1222 const struct hid_device_id *id)
1223{ 1223{
1224 return id->bus == hdev->bus && 1224 return id->bus == hdev->bus &&
1225 (id->group == HID_GROUP_ANY || id->group == hdev->group) &&
1225 (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && 1226 (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
1226 (id->product == HID_ANY_ID || id->product == hdev->product); 1227 (id->product == HID_ANY_ID || id->product == hdev->product);
1227} 1228}
@@ -1694,6 +1695,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf,
1694 return -ENOMEM; 1695 return -ENOMEM;
1695 1696
1696 dynid->id.bus = bus; 1697 dynid->id.bus = bus;
1698 dynid->id.group = HID_GROUP_ANY;
1697 dynid->id.vendor = vendor; 1699 dynid->id.vendor = vendor;
1698 dynid->id.product = product; 1700 dynid->id.product = product;
1699 dynid->id.driver_data = driver_data; 1701 dynid->id.driver_data = driver_data;
@@ -1817,6 +1819,23 @@ static int hid_device_remove(struct device *dev)
1817 return 0; 1819 return 0;
1818} 1820}
1819 1821
1822static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
1823 char *buf)
1824{
1825 struct hid_device *hdev = container_of(dev, struct hid_device, dev);
1826 int len;
1827
1828 len = snprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n",
1829 hdev->bus, hdev->group, hdev->vendor, hdev->product);
1830
1831 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
1832}
1833
1834static struct device_attribute hid_dev_attrs[] = {
1835 __ATTR_RO(modalias),
1836 __ATTR_NULL,
1837};
1838
1820static int hid_uevent(struct device *dev, struct kobj_uevent_env *env) 1839static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
1821{ 1840{
1822 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 1841 struct hid_device *hdev = container_of(dev, struct hid_device, dev);
@@ -1834,8 +1853,8 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
1834 if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq)) 1853 if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq))
1835 return -ENOMEM; 1854 return -ENOMEM;
1836 1855
1837 if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X", 1856 if (add_uevent_var(env, "MODALIAS=hid:b%04Xg%04Xv%08Xp%08X",
1838 hdev->bus, hdev->vendor, hdev->product)) 1857 hdev->bus, hdev->group, hdev->vendor, hdev->product))
1839 return -ENOMEM; 1858 return -ENOMEM;
1840 1859
1841 return 0; 1860 return 0;
@@ -1843,6 +1862,7 @@ static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
1843 1862
1844static struct bus_type hid_bus_type = { 1863static struct bus_type hid_bus_type = {
1845 .name = "hid", 1864 .name = "hid",
1865 .dev_attrs = hid_dev_attrs,
1846 .match = hid_bus_match, 1866 .match = hid_bus_match,
1847 .probe = hid_device_probe, 1867 .probe = hid_device_probe,
1848 .remove = hid_device_remove, 1868 .remove = hid_device_remove,
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d8e7cc7f894f..a0e27ddb887d 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -476,6 +476,7 @@ struct hid_device { /* device report descriptor */
476 unsigned maxcollection; /* Number of parsed collections */ 476 unsigned maxcollection; /* Number of parsed collections */
477 unsigned maxapplication; /* Number of applications */ 477 unsigned maxapplication; /* Number of applications */
478 __u16 bus; /* BUS ID */ 478 __u16 bus; /* BUS ID */
479 __u16 group; /* Report group */
479 __u32 vendor; /* Vendor ID */ 480 __u32 vendor; /* Vendor ID */
480 __u32 product; /* Product ID */ 481 __u32 product; /* Product ID */
481 __u32 version; /* HID version */ 482 __u32 version; /* HID version */
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 501da4cb8a6d..55ed0b0dc610 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -132,10 +132,11 @@ struct usb_device_id {
132#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 132#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
133 133
134#define HID_ANY_ID (~0) 134#define HID_ANY_ID (~0)
135#define HID_GROUP_ANY 0x0000
135 136
136struct hid_device_id { 137struct hid_device_id {
137 __u16 bus; 138 __u16 bus;
138 __u16 pad1; 139 __u16 group;
139 __u32 vendor; 140 __u32 vendor;
140 __u32 product; 141 __u32 product;
141 kernel_ulong_t driver_data 142 kernel_ulong_t driver_data
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 8e730ccc3f2b..fe967cee7371 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -336,10 +336,12 @@ static int do_hid_entry(const char *filename,
336 struct hid_device_id *id, char *alias) 336 struct hid_device_id *id, char *alias)
337{ 337{
338 id->bus = TO_NATIVE(id->bus); 338 id->bus = TO_NATIVE(id->bus);
339 id->group = TO_NATIVE(id->group);
339 id->vendor = TO_NATIVE(id->vendor); 340 id->vendor = TO_NATIVE(id->vendor);
340 id->product = TO_NATIVE(id->product); 341 id->product = TO_NATIVE(id->product);
341 342
342 sprintf(alias, "hid:b%04X", id->bus); 343 sprintf(alias, "hid:b%04X", id->bus);
344 ADD(alias, "g", id->group != HID_GROUP_ANY, id->group);
343 ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); 345 ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
344 ADD(alias, "p", id->product != HID_ANY_ID, id->product); 346 ADD(alias, "p", id->product != HID_ANY_ID, id->product);
345 347