mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
HID: Scan the device for group info before adding it
In order to allow the report descriptor to influence the hid device properties, one needs to parse the descriptor early, without reference to any driver. Scan the descriptor for group information during device add, before the device has been broadcast to userland. The device modalias will contain group information which can be used to differentiate between modules. For starters, just handle the generic group. Signed-off-by: Henrik Rydberg <[email protected]> Acked-by: Benjamin Tissoires <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
This commit is contained in:
parent
4d53b8012f
commit
734c660931
2 changed files with 67 additions and 0 deletions
|
|
@ -658,6 +658,58 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void hid_scan_usage(struct hid_device *hid, u32 usage)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan a report descriptor before the device is added to the bus.
|
||||
* Sets device groups and other properties that determine what driver
|
||||
* to load.
|
||||
*/
|
||||
static int hid_scan_report(struct hid_device *hid)
|
||||
{
|
||||
unsigned int page = 0, delim = 0;
|
||||
__u8 *start = hid->dev_rdesc;
|
||||
__u8 *end = start + hid->dev_rsize;
|
||||
unsigned int u, u_min = 0, u_max = 0;
|
||||
struct hid_item item;
|
||||
|
||||
hid->group = HID_GROUP_GENERIC;
|
||||
while ((start = fetch_item(start, end, &item)) != NULL) {
|
||||
if (item.format != HID_ITEM_FORMAT_SHORT)
|
||||
return -EINVAL;
|
||||
if (item.type == HID_ITEM_TYPE_GLOBAL) {
|
||||
if (item.tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE)
|
||||
page = item_udata(&item) << 16;
|
||||
} else if (item.type == HID_ITEM_TYPE_LOCAL) {
|
||||
if (delim > 1)
|
||||
break;
|
||||
u = item_udata(&item);
|
||||
if (item.size <= 2)
|
||||
u += page;
|
||||
switch (item.tag) {
|
||||
case HID_LOCAL_ITEM_TAG_DELIMITER:
|
||||
delim += !!u;
|
||||
break;
|
||||
case HID_LOCAL_ITEM_TAG_USAGE:
|
||||
hid_scan_usage(hid, u);
|
||||
break;
|
||||
case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
|
||||
u_min = u;
|
||||
break;
|
||||
case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
|
||||
u_max = u;
|
||||
for (u = u_min; u <= u_max; u++)
|
||||
hid_scan_usage(hid, u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hid_parse_report - parse device report
|
||||
*
|
||||
|
|
@ -2171,6 +2223,16 @@ int hid_add_device(struct hid_device *hdev)
|
|||
if (!hdev->dev_rdesc)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Scan generic devices for group information
|
||||
*/
|
||||
if (hid_ignore_special_drivers ||
|
||||
!hid_match_id(hdev, hid_have_special_driver)) {
|
||||
ret = hid_scan_report(hdev);
|
||||
if (ret)
|
||||
hid_warn(hdev, "bad device descriptor (%d)\n", ret);
|
||||
}
|
||||
|
||||
/* XXX hack, any other cleaner solution after the driver core
|
||||
* is converted to allow more than 20 bytes as the device name? */
|
||||
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
|
||||
|
|
|
|||
Loading…
Reference in a new issue