diff options
| -rw-r--r-- | drivers/hid/hid-input.c | 67 | ||||
| -rw-r--r-- | include/linux/hid.h | 1 |
2 files changed, 60 insertions, 8 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 7463ee2a1df2..fea6d4898f15 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -1500,15 +1500,56 @@ static void report_features(struct hid_device *hid) | |||
| 1500 | } | 1500 | } |
| 1501 | } | 1501 | } |
| 1502 | 1502 | ||
| 1503 | static struct hid_input *hidinput_allocate(struct hid_device *hid) | 1503 | static struct hid_input *hidinput_allocate(struct hid_device *hid, |
| 1504 | unsigned int application) | ||
| 1504 | { | 1505 | { |
| 1505 | struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); | 1506 | struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); |
| 1506 | struct input_dev *input_dev = input_allocate_device(); | 1507 | struct input_dev *input_dev = input_allocate_device(); |
| 1507 | if (!hidinput || !input_dev) { | 1508 | const char *suffix = NULL; |
| 1508 | kfree(hidinput); | 1509 | |
| 1509 | input_free_device(input_dev); | 1510 | if (!hidinput || !input_dev) |
| 1510 | hid_err(hid, "Out of memory during hid input probe\n"); | 1511 | goto fail; |
| 1511 | return NULL; | 1512 | |
| 1513 | if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) && | ||
| 1514 | hid->maxapplication > 1) { | ||
| 1515 | switch (application) { | ||
| 1516 | case HID_GD_KEYBOARD: | ||
| 1517 | suffix = "Keyboard"; | ||
| 1518 | break; | ||
| 1519 | case HID_GD_KEYPAD: | ||
| 1520 | suffix = "Keypad"; | ||
| 1521 | break; | ||
| 1522 | case HID_GD_MOUSE: | ||
| 1523 | suffix = "Mouse"; | ||
| 1524 | break; | ||
| 1525 | case HID_DG_STYLUS: | ||
| 1526 | suffix = "Pen"; | ||
| 1527 | break; | ||
| 1528 | case HID_DG_TOUCHSCREEN: | ||
| 1529 | suffix = "Touchscreen"; | ||
| 1530 | break; | ||
| 1531 | case HID_DG_TOUCHPAD: | ||
| 1532 | suffix = "Touchpad"; | ||
| 1533 | break; | ||
| 1534 | case HID_GD_SYSTEM_CONTROL: | ||
| 1535 | suffix = "System Control"; | ||
| 1536 | break; | ||
| 1537 | case HID_CP_CONSUMER_CONTROL: | ||
| 1538 | suffix = "Consumer Control"; | ||
| 1539 | break; | ||
| 1540 | case HID_GD_WIRELESS_RADIO_CTLS: | ||
| 1541 | suffix = "Wireless Radio Control"; | ||
| 1542 | break; | ||
| 1543 | default: | ||
| 1544 | break; | ||
| 1545 | } | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | if (suffix) { | ||
| 1549 | hidinput->name = kasprintf(GFP_KERNEL, "%s %s", | ||
| 1550 | hid->name, suffix); | ||
| 1551 | if (!hidinput->name) | ||
| 1552 | goto fail; | ||
| 1512 | } | 1553 | } |
| 1513 | 1554 | ||
| 1514 | input_set_drvdata(input_dev, hid); | 1555 | input_set_drvdata(input_dev, hid); |
| @@ -1518,7 +1559,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) | |||
| 1518 | input_dev->setkeycode = hidinput_setkeycode; | 1559 | input_dev->setkeycode = hidinput_setkeycode; |
| 1519 | input_dev->getkeycode = hidinput_getkeycode; | 1560 | input_dev->getkeycode = hidinput_getkeycode; |
| 1520 | 1561 | ||
| 1521 | input_dev->name = hid->name; | 1562 | input_dev->name = hidinput->name ? hidinput->name : hid->name; |
| 1522 | input_dev->phys = hid->phys; | 1563 | input_dev->phys = hid->phys; |
| 1523 | input_dev->uniq = hid->uniq; | 1564 | input_dev->uniq = hid->uniq; |
| 1524 | input_dev->id.bustype = hid->bus; | 1565 | input_dev->id.bustype = hid->bus; |
| @@ -1533,6 +1574,12 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) | |||
| 1533 | INIT_LIST_HEAD(&hidinput->reports); | 1574 | INIT_LIST_HEAD(&hidinput->reports); |
| 1534 | 1575 | ||
| 1535 | return hidinput; | 1576 | return hidinput; |
| 1577 | |||
| 1578 | fail: | ||
| 1579 | kfree(hidinput); | ||
| 1580 | input_free_device(input_dev); | ||
| 1581 | hid_err(hid, "Out of memory during hid input probe\n"); | ||
| 1582 | return NULL; | ||
| 1536 | } | 1583 | } |
| 1537 | 1584 | ||
| 1538 | static bool hidinput_has_been_populated(struct hid_input *hidinput) | 1585 | static bool hidinput_has_been_populated(struct hid_input *hidinput) |
| @@ -1578,6 +1625,7 @@ static void hidinput_cleanup_hidinput(struct hid_device *hid, | |||
| 1578 | 1625 | ||
| 1579 | list_del(&hidinput->list); | 1626 | list_del(&hidinput->list); |
| 1580 | input_free_device(hidinput->input); | 1627 | input_free_device(hidinput->input); |
| 1628 | kfree(hidinput->name); | ||
| 1581 | 1629 | ||
| 1582 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | 1630 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { |
| 1583 | if (k == HID_OUTPUT_REPORT && | 1631 | if (k == HID_OUTPUT_REPORT && |
| @@ -1646,6 +1694,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1646 | struct hid_driver *drv = hid->driver; | 1694 | struct hid_driver *drv = hid->driver; |
| 1647 | struct hid_report *report; | 1695 | struct hid_report *report; |
| 1648 | struct hid_input *next, *hidinput = NULL; | 1696 | struct hid_input *next, *hidinput = NULL; |
| 1697 | unsigned int application; | ||
| 1649 | int i, k; | 1698 | int i, k; |
| 1650 | 1699 | ||
| 1651 | INIT_LIST_HEAD(&hid->inputs); | 1700 | INIT_LIST_HEAD(&hid->inputs); |
| @@ -1678,6 +1727,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1678 | if (!report->maxfield) | 1727 | if (!report->maxfield) |
| 1679 | continue; | 1728 | continue; |
| 1680 | 1729 | ||
| 1730 | application = report->application; | ||
| 1731 | |||
| 1681 | /* | 1732 | /* |
| 1682 | * Find the previous hidinput report attached | 1733 | * Find the previous hidinput report attached |
| 1683 | * to this report id. | 1734 | * to this report id. |
| @@ -1689,7 +1740,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1689 | hidinput = hidinput_match_application(report); | 1740 | hidinput = hidinput_match_application(report); |
| 1690 | 1741 | ||
| 1691 | if (!hidinput) { | 1742 | if (!hidinput) { |
| 1692 | hidinput = hidinput_allocate(hid); | 1743 | hidinput = hidinput_allocate(hid, application); |
| 1693 | if (!hidinput) | 1744 | if (!hidinput) |
| 1694 | goto out_unwind; | 1745 | goto out_unwind; |
| 1695 | } | 1746 | } |
diff --git a/include/linux/hid.h b/include/linux/hid.h index bcc91bfdd2cb..f03d7a410c5d 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -512,6 +512,7 @@ struct hid_input { | |||
| 512 | struct list_head list; | 512 | struct list_head list; |
| 513 | struct hid_report *report; | 513 | struct hid_report *report; |
| 514 | struct input_dev *input; | 514 | struct input_dev *input; |
| 515 | const char *name; | ||
| 515 | bool registered; | 516 | bool registered; |
| 516 | struct list_head reports; /* the list of reports */ | 517 | struct list_head reports; /* the list of reports */ |
| 517 | }; | 518 | }; |
