HID: move pantherlord FF processing
[safe/jmp/linux-2.6] / drivers / hid / hid-core.c
index ea5f8bc..48a76e7 100644 (file)
@@ -1131,6 +1131,93 @@ static const struct hid_device_id *hid_match_id(struct hid_device *hdev,
        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) },
@@ -1188,6 +1275,13 @@ static const struct hid_device_id hid_blacklist[] = {
        { 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) },
@@ -1238,7 +1332,7 @@ static int hid_device_probe(struct device *dev)
                } 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;
@@ -1317,6 +1411,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { 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) },
@@ -1332,6 +1427,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { 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) },
@@ -1400,8 +1496,6 @@ static const struct hid_device_id hid_ignore_list[] = {
        { 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) },
@@ -1420,6 +1514,8 @@ static const struct hid_device_id hid_ignore_list[] = {
        { 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) },
@@ -1563,6 +1659,7 @@ static void hid_compat_load(struct work_struct *ws)
        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)
@@ -1580,7 +1677,12 @@ 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;
@@ -1592,6 +1694,9 @@ err:
 
 static void __exit hid_exit(void)
 {
+#ifdef CONFIG_HID_COMPAT
+       destroy_workqueue(hid_compat_wq);
+#endif
        hidraw_exit();
        bus_unregister(&hid_bus_type);
 }