|
@@ -29,6 +29,7 @@
|
|
#include <linux/wait.h>
|
|
#include <linux/wait.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/sched.h>
|
|
|
|
+#include <linux/semaphore.h>
|
|
|
|
|
|
#include <linux/hid.h>
|
|
#include <linux/hid.h>
|
|
#include <linux/hiddev.h>
|
|
#include <linux/hiddev.h>
|
|
@@ -1085,16 +1086,25 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
|
struct hid_report *report;
|
|
struct hid_report *report;
|
|
char *buf;
|
|
char *buf;
|
|
unsigned int i;
|
|
unsigned int i;
|
|
- int ret;
|
|
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
- if (!hid || !hid->driver)
|
|
|
|
|
|
+ if (!hid)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
+
|
|
|
|
+ if (down_trylock(&hid->driver_lock))
|
|
|
|
+ return -EBUSY;
|
|
|
|
+
|
|
|
|
+ if (!hid->driver) {
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto unlock;
|
|
|
|
+ }
|
|
report_enum = hid->report_enum + type;
|
|
report_enum = hid->report_enum + type;
|
|
hdrv = hid->driver;
|
|
hdrv = hid->driver;
|
|
|
|
|
|
if (!size) {
|
|
if (!size) {
|
|
dbg_hid("empty report\n");
|
|
dbg_hid("empty report\n");
|
|
- return -1;
|
|
|
|
|
|
+ ret = -1;
|
|
|
|
+ goto unlock;
|
|
}
|
|
}
|
|
|
|
|
|
buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
|
|
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
|
|
nomem:
|
|
nomem:
|
|
report = hid_get_report(report_enum, data);
|
|
report = hid_get_report(report_enum, data);
|
|
|
|
|
|
- if (!report)
|
|
|
|
- return -1;
|
|
|
|
|
|
+ if (!report) {
|
|
|
|
+ ret = -1;
|
|
|
|
+ goto unlock;
|
|
|
|
+ }
|
|
|
|
|
|
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
|
|
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
|
|
ret = hdrv->raw_event(hid, report, data, size);
|
|
ret = hdrv->raw_event(hid, report, data, size);
|
|
- if (ret != 0)
|
|
|
|
- return ret < 0 ? ret : 0;
|
|
|
|
|
|
+ if (ret != 0) {
|
|
|
|
+ ret = ret < 0 ? ret : 0;
|
|
|
|
+ goto unlock;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
hid_report_raw_event(hid, type, data, size, interrupt);
|
|
hid_report_raw_event(hid, type, data, size, interrupt);
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+unlock:
|
|
|
|
+ up(&hid->driver_lock);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(hid_input_report);
|
|
EXPORT_SYMBOL_GPL(hid_input_report);
|
|
|
|
|
|
@@ -1349,6 +1365,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
|
|
{ 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[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
|
|
{ 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[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
|
|
{ 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)
|
|
const struct hid_device_id *id;
|
|
const struct hid_device_id *id;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
|
|
+ if (down_interruptible(&hdev->driver_lock))
|
|
|
|
+ return -EINTR;
|
|
|
|
+
|
|
if (!hdev->driver) {
|
|
if (!hdev->driver) {
|
|
id = hid_match_device(hdev, hdrv);
|
|
id = hid_match_device(hdev, hdrv);
|
|
- if (id == NULL)
|
|
|
|
- return -ENODEV;
|
|
|
|
|
|
+ if (id == NULL) {
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto unlock;
|
|
|
|
+ }
|
|
|
|
|
|
hdev->driver = hdrv;
|
|
hdev->driver = hdrv;
|
|
if (hdrv->probe) {
|
|
if (hdrv->probe) {
|
|
@@ -1647,14 +1679,20 @@ static int hid_device_probe(struct device *dev)
|
|
if (ret)
|
|
if (ret)
|
|
hdev->driver = NULL;
|
|
hdev->driver = NULL;
|
|
}
|
|
}
|
|
|
|
+unlock:
|
|
|
|
+ up(&hdev->driver_lock);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int hid_device_remove(struct device *dev)
|
|
static int hid_device_remove(struct device *dev)
|
|
{
|
|
{
|
|
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
|
|
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
|
|
- struct hid_driver *hdrv = hdev->driver;
|
|
|
|
|
|
+ struct hid_driver *hdrv;
|
|
|
|
+
|
|
|
|
+ if (down_interruptible(&hdev->driver_lock))
|
|
|
|
+ return -EINTR;
|
|
|
|
|
|
|
|
+ hdrv = hdev->driver;
|
|
if (hdrv) {
|
|
if (hdrv) {
|
|
if (hdrv->remove)
|
|
if (hdrv->remove)
|
|
hdrv->remove(hdev);
|
|
hdrv->remove(hdev);
|
|
@@ -1663,6 +1701,7 @@ static int hid_device_remove(struct device *dev)
|
|
hdev->driver = NULL;
|
|
hdev->driver = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ up(&hdev->driver_lock);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1903,6 +1942,12 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) },
|
|
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
|
{ }
|
|
{ }
|
|
@@ -2010,6 +2055,7 @@ struct hid_device *hid_allocate_device(void)
|
|
|
|
|
|
init_waitqueue_head(&hdev->debug_wait);
|
|
init_waitqueue_head(&hdev->debug_wait);
|
|
INIT_LIST_HEAD(&hdev->debug_list);
|
|
INIT_LIST_HEAD(&hdev->debug_list);
|
|
|
|
+ sema_init(&hdev->driver_lock, 1);
|
|
|
|
|
|
return hdev;
|
|
return hdev;
|
|
err:
|
|
err:
|