return NULL;
}
+static const struct hid_device_id hid_hiddev_list[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1) },
+ { }
+};
+
+static bool hid_hiddev(struct hid_device *hdev)
+{
+ return !!hid_match_id(hdev, hid_hiddev_list);
+}
+
+int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
+{
+ static const char *types[] = { "Device", "Pointer", "Mouse", "Device",
+ "Joystick", "Gamepad", "Keyboard", "Keypad",
+ "Multi-Axis Controller"
+ };
+ const char *type, *bus;
+ char buf[64];
+ unsigned int i;
+ int len;
+
+ if (hdev->bus != BUS_USB)
+ connect_mask &= ~HID_CONNECT_HIDDEV;
+ if (hid_hiddev(hdev))
+ connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+
+ if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
+ connect_mask & HID_CONNECT_HIDINPUT_FORCE))
+ hdev->claimed |= HID_CLAIMED_INPUT;
+ if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
+ !hdev->hiddev_connect(hdev,
+ connect_mask & HID_CONNECT_HIDDEV_FORCE))
+ hdev->claimed |= HID_CLAIMED_HIDDEV;
+ if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev))
+ hdev->claimed |= HID_CLAIMED_HIDRAW;
+
+ if (!hdev->claimed) {
+ dev_err(&hdev->dev, "claimed by neither input, hiddev nor "
+ "hidraw\n");
+ return -ENODEV;
+ }
+
+ if ((hdev->claimed & HID_CLAIMED_INPUT) &&
+ (connect_mask & HID_CONNECT_FF) && hdev->ff_init)
+ hdev->ff_init(hdev);
+
+ len = 0;
+ if (hdev->claimed & HID_CLAIMED_INPUT)
+ len += sprintf(buf + len, "input");
+ if (hdev->claimed & HID_CLAIMED_HIDDEV)
+ len += sprintf(buf + len, "%shiddev%d", len ? "," : "",
+ hdev->minor);
+ if (hdev->claimed & HID_CLAIMED_HIDRAW)
+ len += sprintf(buf + len, "%shidraw%d", len ? "," : "",
+ ((struct hidraw *)hdev->hidraw)->minor);
+
+ type = "Device";
+ for (i = 0; i < hdev->maxcollection; i++) {
+ struct hid_collection *col = &hdev->collection[i];
+ if (col->type == HID_COLLECTION_APPLICATION &&
+ (col->usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+ (col->usage & 0xffff) < ARRAY_SIZE(types)) {
+ type = types[col->usage & 0xffff];
+ break;
+ }
+ }
+
+ switch (hdev->bus) {
+ case BUS_USB:
+ bus = "USB";
+ break;
+ case BUS_BLUETOOTH:
+ bus = "BLUETOOTH";
+ break;
+ default:
+ bus = "<UNKNOWN>";
+ }
+
+ dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
+ buf, bus, hdev->version >> 8, hdev->version & 0xff,
+ type, hdev->name, hdev->phys);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hid_connect);
+
static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
} else { /* default probe */
ret = hid_parse(hdev);
if (!ret)
- ret = hid_hw_start(hdev);
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
if (ret)
hdev->driver = NULL;
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
request_module("hid-dummy");
}
static DECLARE_WORK(hid_compat_work, hid_compat_load);
+static struct workqueue_struct *hid_compat_wq;
#endif
static int __init hid_init(void)
goto err_bus;
#ifdef CONFIG_HID_COMPAT
- schedule_work(&hid_compat_work);
+ hid_compat_wq = create_workqueue("hid_compat");
+ if (!hid_compat_wq) {
+ hidraw_exit();
+ goto err;
+ }
+ queue_work(hid_compat_wq, &hid_compat_work);
#endif
return 0;
static void __exit hid_exit(void)
{
+#ifdef CONFIG_HID_COMPAT
+ destroy_workqueue(hid_compat_wq);
+#endif
hidraw_exit();
bus_unregister(&hid_bus_type);
}