summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2012-04-23 12:07:02 +0200
committerJiri Kosina <jkosina@suse.cz>2012-05-01 12:54:54 +0200
commit4d53b8012f1f01ddb3f24db2031b042bb4cbd0d0 (patch)
tree4536bb9fefb51c212f28dee84e810ab0d6854a6e /drivers/hid
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>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-core.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9ed4ff37dc2..cfcb69eb17d 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,
const struct hid_device_id *id)
{
return id->bus == hdev->bus &&
+ (id->group == HID_GROUP_ANY || id->group == hdev->group) &&
(id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
(id->product == HID_ANY_ID || id->product == hdev->product);
}
@@ -1694,6 +1695,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf,
return -ENOMEM;
dynid->id.bus = bus;
+ dynid->id.group = HID_GROUP_ANY;
dynid->id.vendor = vendor;
dynid->id.product = product;
dynid->id.driver_data = driver_data;
@@ -1817,6 +1819,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%04Xg%04Xv%08Xp%08X\n",
+ hdev->bus, hdev->group, 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);
@@ -1834,8 +1853,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%04Xg%04Xv%08Xp%08X",
+ hdev->bus, hdev->group, hdev->vendor, hdev->product))
return -ENOMEM;
return 0;
@@ -1843,6 +1862,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,