diff options
author | Jiri Kosina <jkosina@suse.cz> | 2011-10-25 03:59:04 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-10-25 03:59:04 -0400 |
commit | b3aec7b686329e6bb65aa08c7f9458f7fd512f06 (patch) | |
tree | 67ae55567b5747f32ddd76dd63621bd2ca756a88 /drivers/hid/hid-core.c | |
parent | f6f12427844516bc8e9cf84f43aca7bbbaa48157 (diff) | |
parent | 1bcc20675a1ac1ba47eaa201e02a89b0508e17b2 (diff) |
Merge branch 'upstream' into for-linus
Conflicts:
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c5606724b77a..91adcc5bad28 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/semaphore.h> | ||
32 | 33 | ||
33 | #include <linux/hid.h> | 34 | #include <linux/hid.h> |
34 | #include <linux/hiddev.h> | 35 | #include <linux/hiddev.h> |
@@ -1085,16 +1086,25 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
1085 | struct hid_report *report; | 1086 | struct hid_report *report; |
1086 | char *buf; | 1087 | char *buf; |
1087 | unsigned int i; | 1088 | unsigned int i; |
1088 | int ret; | 1089 | int ret = 0; |
1089 | 1090 | ||
1090 | if (!hid || !hid->driver) | 1091 | if (!hid) |
1091 | return -ENODEV; | 1092 | return -ENODEV; |
1093 | |||
1094 | if (down_trylock(&hid->driver_lock)) | ||
1095 | return -EBUSY; | ||
1096 | |||
1097 | if (!hid->driver) { | ||
1098 | ret = -ENODEV; | ||
1099 | goto unlock; | ||
1100 | } | ||
1092 | report_enum = hid->report_enum + type; | 1101 | report_enum = hid->report_enum + type; |
1093 | hdrv = hid->driver; | 1102 | hdrv = hid->driver; |
1094 | 1103 | ||
1095 | if (!size) { | 1104 | if (!size) { |
1096 | dbg_hid("empty report\n"); | 1105 | dbg_hid("empty report\n"); |
1097 | return -1; | 1106 | ret = -1; |
1107 | goto unlock; | ||
1098 | } | 1108 | } |
1099 | 1109 | ||
1100 | buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | 1110 | buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); |
@@ -1118,18 +1128,24 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
1118 | nomem: | 1128 | nomem: |
1119 | report = hid_get_report(report_enum, data); | 1129 | report = hid_get_report(report_enum, data); |
1120 | 1130 | ||
1121 | if (!report) | 1131 | if (!report) { |
1122 | return -1; | 1132 | ret = -1; |
1133 | goto unlock; | ||
1134 | } | ||
1123 | 1135 | ||
1124 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { | 1136 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { |
1125 | ret = hdrv->raw_event(hid, report, data, size); | 1137 | ret = hdrv->raw_event(hid, report, data, size); |
1126 | if (ret != 0) | 1138 | if (ret != 0) { |
1127 | return ret < 0 ? ret : 0; | 1139 | ret = ret < 0 ? ret : 0; |
1140 | goto unlock; | ||
1141 | } | ||
1128 | } | 1142 | } |
1129 | 1143 | ||
1130 | hid_report_raw_event(hid, type, data, size, interrupt); | 1144 | hid_report_raw_event(hid, type, data, size, interrupt); |
1131 | 1145 | ||
1132 | return 0; | 1146 | unlock: |
1147 | up(&hid->driver_lock); | ||
1148 | return ret; | ||
1133 | } | 1149 | } |
1134 | EXPORT_SYMBOL_GPL(hid_input_report); | 1150 | EXPORT_SYMBOL_GPL(hid_input_report); |
1135 | 1151 | ||
@@ -1349,6 +1365,12 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1349 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, | 1365 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, |
1350 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, | 1366 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, |
1351 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, | 1367 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, |
1368 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, | ||
1369 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, | ||
1370 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, | ||
1371 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, | ||
1372 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, | ||
1373 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, | ||
1352 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, | 1374 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, |
1353 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, | 1375 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, |
1354 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1376 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
@@ -1472,6 +1494,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1472 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1494 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
1473 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, | 1495 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, |
1474 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1496 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1497 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | ||
1475 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | 1498 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, |
1476 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | 1499 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, |
1477 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
@@ -1512,6 +1535,10 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1512 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, | 1535 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, |
1513 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, | 1536 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, |
1514 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1537 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
1538 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, | ||
1539 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, | ||
1540 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, | ||
1541 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, | ||
1515 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1542 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
1516 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | 1543 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, |
1517 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | 1544 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, |
@@ -1631,10 +1658,15 @@ static int hid_device_probe(struct device *dev) | |||
1631 | const struct hid_device_id *id; | 1658 | const struct hid_device_id *id; |
1632 | int ret = 0; | 1659 | int ret = 0; |
1633 | 1660 | ||
1661 | if (down_interruptible(&hdev->driver_lock)) | ||
1662 | return -EINTR; | ||
1663 | |||
1634 | if (!hdev->driver) { | 1664 | if (!hdev->driver) { |
1635 | id = hid_match_device(hdev, hdrv); | 1665 | id = hid_match_device(hdev, hdrv); |
1636 | if (id == NULL) | 1666 | if (id == NULL) { |
1637 | return -ENODEV; | 1667 | ret = -ENODEV; |
1668 | goto unlock; | ||
1669 | } | ||
1638 | 1670 | ||
1639 | hdev->driver = hdrv; | 1671 | hdev->driver = hdrv; |
1640 | if (hdrv->probe) { | 1672 | if (hdrv->probe) { |
@@ -1647,14 +1679,20 @@ static int hid_device_probe(struct device *dev) | |||
1647 | if (ret) | 1679 | if (ret) |
1648 | hdev->driver = NULL; | 1680 | hdev->driver = NULL; |
1649 | } | 1681 | } |
1682 | unlock: | ||
1683 | up(&hdev->driver_lock); | ||
1650 | return ret; | 1684 | return ret; |
1651 | } | 1685 | } |
1652 | 1686 | ||
1653 | static int hid_device_remove(struct device *dev) | 1687 | static int hid_device_remove(struct device *dev) |
1654 | { | 1688 | { |
1655 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | 1689 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
1656 | struct hid_driver *hdrv = hdev->driver; | 1690 | struct hid_driver *hdrv; |
1691 | |||
1692 | if (down_interruptible(&hdev->driver_lock)) | ||
1693 | return -EINTR; | ||
1657 | 1694 | ||
1695 | hdrv = hdev->driver; | ||
1658 | if (hdrv) { | 1696 | if (hdrv) { |
1659 | if (hdrv->remove) | 1697 | if (hdrv->remove) |
1660 | hdrv->remove(hdev); | 1698 | hdrv->remove(hdev); |
@@ -1663,6 +1701,7 @@ static int hid_device_remove(struct device *dev) | |||
1663 | hdev->driver = NULL; | 1701 | hdev->driver = NULL; |
1664 | } | 1702 | } |
1665 | 1703 | ||
1704 | up(&hdev->driver_lock); | ||
1666 | return 0; | 1705 | return 0; |
1667 | } | 1706 | } |
1668 | 1707 | ||
@@ -1903,6 +1942,12 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
1903 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, | 1942 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, |
1904 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, | 1943 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, |
1905 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, | 1944 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, |
1945 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, | ||
1946 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, | ||
1947 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, | ||
1948 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, | ||
1949 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, | ||
1950 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, | ||
1906 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1951 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1907 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1952 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1908 | { } | 1953 | { } |
@@ -2010,6 +2055,7 @@ struct hid_device *hid_allocate_device(void) | |||
2010 | 2055 | ||
2011 | init_waitqueue_head(&hdev->debug_wait); | 2056 | init_waitqueue_head(&hdev->debug_wait); |
2012 | INIT_LIST_HEAD(&hdev->debug_list); | 2057 | INIT_LIST_HEAD(&hdev->debug_list); |
2058 | sema_init(&hdev->driver_lock, 1); | ||
2013 | 2059 | ||
2014 | return hdev; | 2060 | return hdev; |
2015 | err: | 2061 | err: |