15f022298SJiri Slaby /* 25f022298SJiri Slaby * Force feedback support for PantherLord/GreenAsia based devices 35f022298SJiri Slaby * 45f022298SJiri Slaby * The devices are distributed under various names and the same USB device ID 55f022298SJiri Slaby * can be used in both adapters and actual game controllers. 65f022298SJiri Slaby * 75f022298SJiri Slaby * 0810:0001 "Twin USB Joystick" 85f022298SJiri Slaby * - tested with PantherLord USB/PS2 2in1 Adapter 95f022298SJiri Slaby * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) 105f022298SJiri Slaby * 115f022298SJiri Slaby * 0e8f:0003 "GreenAsia Inc. USB Joystick " 1227a9c179SAnssi Hannula * - tested with K�nig Gaming gamepad 135f022298SJiri Slaby * 1427a9c179SAnssi Hannula * 0e8f:0003 "GASIA USB Gamepad" 1527a9c179SAnssi Hannula * - another version of the K�nig gamepad 1627a9c179SAnssi Hannula * 1727a9c179SAnssi Hannula * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com> 185f022298SJiri Slaby */ 195f022298SJiri Slaby 205f022298SJiri Slaby /* 215f022298SJiri Slaby * This program is free software; you can redistribute it and/or modify 225f022298SJiri Slaby * it under the terms of the GNU General Public License as published by 235f022298SJiri Slaby * the Free Software Foundation; either version 2 of the License, or 245f022298SJiri Slaby * (at your option) any later version. 255f022298SJiri Slaby * 265f022298SJiri Slaby * This program is distributed in the hope that it will be useful, 275f022298SJiri Slaby * but WITHOUT ANY WARRANTY; without even the implied warranty of 285f022298SJiri Slaby * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 295f022298SJiri Slaby * GNU General Public License for more details. 305f022298SJiri Slaby * 315f022298SJiri Slaby * You should have received a copy of the GNU General Public License 325f022298SJiri Slaby * along with this program; if not, write to the Free Software 335f022298SJiri Slaby * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 345f022298SJiri Slaby */ 355f022298SJiri Slaby 365f022298SJiri Slaby 375f022298SJiri Slaby /* #define DEBUG */ 385f022298SJiri Slaby 395f022298SJiri Slaby #define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) 405f022298SJiri Slaby 415f022298SJiri Slaby #include <linux/input.h> 425a0e3ad6STejun Heo #include <linux/slab.h> 43*8f86a2c3SPaul Gortmaker #include <linux/module.h> 445f022298SJiri Slaby #include <linux/usb.h> 455f022298SJiri Slaby #include <linux/hid.h> 465f022298SJiri Slaby 475f022298SJiri Slaby #include "hid-ids.h" 485f022298SJiri Slaby 495f022298SJiri Slaby #ifdef CONFIG_PANTHERLORD_FF 505f022298SJiri Slaby #include "usbhid/usbhid.h" 515f022298SJiri Slaby 525f022298SJiri Slaby struct plff_device { 535f022298SJiri Slaby struct hid_report *report; 5427a9c179SAnssi Hannula s32 *strong; 5527a9c179SAnssi Hannula s32 *weak; 565f022298SJiri Slaby }; 575f022298SJiri Slaby 585f022298SJiri Slaby static int hid_plff_play(struct input_dev *dev, void *data, 595f022298SJiri Slaby struct ff_effect *effect) 605f022298SJiri Slaby { 615f022298SJiri Slaby struct hid_device *hid = input_get_drvdata(dev); 625f022298SJiri Slaby struct plff_device *plff = data; 635f022298SJiri Slaby int left, right; 645f022298SJiri Slaby 655f022298SJiri Slaby left = effect->u.rumble.strong_magnitude; 665f022298SJiri Slaby right = effect->u.rumble.weak_magnitude; 675f022298SJiri Slaby debug("called with 0x%04x 0x%04x", left, right); 685f022298SJiri Slaby 695f022298SJiri Slaby left = left * 0x7f / 0xffff; 705f022298SJiri Slaby right = right * 0x7f / 0xffff; 715f022298SJiri Slaby 7227a9c179SAnssi Hannula *plff->strong = left; 7327a9c179SAnssi Hannula *plff->weak = right; 745f022298SJiri Slaby debug("running with 0x%02x 0x%02x", left, right); 755f022298SJiri Slaby usbhid_submit_report(hid, plff->report, USB_DIR_OUT); 765f022298SJiri Slaby 775f022298SJiri Slaby return 0; 785f022298SJiri Slaby } 795f022298SJiri Slaby 805f022298SJiri Slaby static int plff_init(struct hid_device *hid) 815f022298SJiri Slaby { 825f022298SJiri Slaby struct plff_device *plff; 835f022298SJiri Slaby struct hid_report *report; 845f022298SJiri Slaby struct hid_input *hidinput; 855f022298SJiri Slaby struct list_head *report_list = 865f022298SJiri Slaby &hid->report_enum[HID_OUTPUT_REPORT].report_list; 875f022298SJiri Slaby struct list_head *report_ptr = report_list; 885f022298SJiri Slaby struct input_dev *dev; 895f022298SJiri Slaby int error; 9027a9c179SAnssi Hannula s32 *strong; 9127a9c179SAnssi Hannula s32 *weak; 925f022298SJiri Slaby 935f022298SJiri Slaby /* The device contains one output report per physical device, all 945f022298SJiri Slaby containing 1 field, which contains 4 ff00.0002 usages and 4 16bit 955f022298SJiri Slaby absolute values. 965f022298SJiri Slaby 975f022298SJiri Slaby The input reports also contain a field which contains 985f022298SJiri Slaby 8 ff00.0001 usages and 8 boolean values. Their meaning is 9927a9c179SAnssi Hannula currently unknown. 10027a9c179SAnssi Hannula 10127a9c179SAnssi Hannula A version of the 0e8f:0003 exists that has all the values in 10227a9c179SAnssi Hannula separate fields and misses the extra input field, thus resembling 10327a9c179SAnssi Hannula Zeroplus (hid-zpff) devices. 10427a9c179SAnssi Hannula */ 1055f022298SJiri Slaby 1065f022298SJiri Slaby if (list_empty(report_list)) { 1074291ee30SJoe Perches hid_err(hid, "no output reports found\n"); 1085f022298SJiri Slaby return -ENODEV; 1095f022298SJiri Slaby } 1105f022298SJiri Slaby 1115f022298SJiri Slaby list_for_each_entry(hidinput, &hid->inputs, list) { 1125f022298SJiri Slaby 1135f022298SJiri Slaby report_ptr = report_ptr->next; 1145f022298SJiri Slaby 1155f022298SJiri Slaby if (report_ptr == report_list) { 1164291ee30SJoe Perches hid_err(hid, "required output report is missing\n"); 1175f022298SJiri Slaby return -ENODEV; 1185f022298SJiri Slaby } 1195f022298SJiri Slaby 1205f022298SJiri Slaby report = list_entry(report_ptr, struct hid_report, list); 1215f022298SJiri Slaby if (report->maxfield < 1) { 1224291ee30SJoe Perches hid_err(hid, "no fields in the report\n"); 1235f022298SJiri Slaby return -ENODEV; 1245f022298SJiri Slaby } 1255f022298SJiri Slaby 12627a9c179SAnssi Hannula if (report->field[0]->report_count >= 4) { 12727a9c179SAnssi Hannula report->field[0]->value[0] = 0x00; 12827a9c179SAnssi Hannula report->field[0]->value[1] = 0x00; 12927a9c179SAnssi Hannula strong = &report->field[0]->value[2]; 13027a9c179SAnssi Hannula weak = &report->field[0]->value[3]; 13127a9c179SAnssi Hannula debug("detected single-field device"); 13227a9c179SAnssi Hannula } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && 13327a9c179SAnssi Hannula report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { 13427a9c179SAnssi Hannula report->field[0]->value[0] = 0x00; 13527a9c179SAnssi Hannula report->field[1]->value[0] = 0x00; 13627a9c179SAnssi Hannula strong = &report->field[2]->value[0]; 13727a9c179SAnssi Hannula weak = &report->field[3]->value[0]; 13827a9c179SAnssi Hannula debug("detected 4-field device"); 13927a9c179SAnssi Hannula } else { 1404291ee30SJoe Perches hid_err(hid, "not enough fields or values\n"); 1415f022298SJiri Slaby return -ENODEV; 1425f022298SJiri Slaby } 1435f022298SJiri Slaby 1445f022298SJiri Slaby plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); 1455f022298SJiri Slaby if (!plff) 1465f022298SJiri Slaby return -ENOMEM; 1475f022298SJiri Slaby 1485f022298SJiri Slaby dev = hidinput->input; 1495f022298SJiri Slaby 1505f022298SJiri Slaby set_bit(FF_RUMBLE, dev->ffbit); 1515f022298SJiri Slaby 1525f022298SJiri Slaby error = input_ff_create_memless(dev, plff, hid_plff_play); 1535f022298SJiri Slaby if (error) { 1545f022298SJiri Slaby kfree(plff); 1555f022298SJiri Slaby return error; 1565f022298SJiri Slaby } 1575f022298SJiri Slaby 1585f022298SJiri Slaby plff->report = report; 15927a9c179SAnssi Hannula plff->strong = strong; 16027a9c179SAnssi Hannula plff->weak = weak; 16127a9c179SAnssi Hannula 16227a9c179SAnssi Hannula *strong = 0x00; 16327a9c179SAnssi Hannula *weak = 0x00; 1645f022298SJiri Slaby usbhid_submit_report(hid, plff->report, USB_DIR_OUT); 1655f022298SJiri Slaby } 1665f022298SJiri Slaby 1674291ee30SJoe Perches hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); 1685f022298SJiri Slaby 1695f022298SJiri Slaby return 0; 1705f022298SJiri Slaby } 1715f022298SJiri Slaby #else 1725f022298SJiri Slaby static inline int plff_init(struct hid_device *hid) 1735f022298SJiri Slaby { 1745f022298SJiri Slaby return 0; 1755f022298SJiri Slaby } 1765f022298SJiri Slaby #endif 1775f022298SJiri Slaby 1785f022298SJiri Slaby static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) 1795f022298SJiri Slaby { 1805f022298SJiri Slaby int ret; 1815f022298SJiri Slaby 1825f022298SJiri Slaby if (id->driver_data) 1835f022298SJiri Slaby hdev->quirks |= HID_QUIRK_MULTI_INPUT; 1845f022298SJiri Slaby 1855f022298SJiri Slaby ret = hid_parse(hdev); 1865f022298SJiri Slaby if (ret) { 1874291ee30SJoe Perches hid_err(hdev, "parse failed\n"); 1885f022298SJiri Slaby goto err; 1895f022298SJiri Slaby } 1905f022298SJiri Slaby 1915f022298SJiri Slaby ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); 1925f022298SJiri Slaby if (ret) { 1934291ee30SJoe Perches hid_err(hdev, "hw start failed\n"); 1945f022298SJiri Slaby goto err; 1955f022298SJiri Slaby } 1965f022298SJiri Slaby 1975f022298SJiri Slaby plff_init(hdev); 1985f022298SJiri Slaby 1995f022298SJiri Slaby return 0; 2005f022298SJiri Slaby err: 2015f022298SJiri Slaby return ret; 2025f022298SJiri Slaby } 2035f022298SJiri Slaby 2045f022298SJiri Slaby static const struct hid_device_id pl_devices[] = { 2055f022298SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR), 2065f022298SJiri Slaby .driver_data = 1 }, /* Twin USB Joystick */ 207578f3a35SJiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR), 208578f3a35SJiri Kosina .driver_data = 1 }, /* Twin USB Joystick */ 20927a9c179SAnssi Hannula { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, 2105f022298SJiri Slaby { } 2115f022298SJiri Slaby }; 2125f022298SJiri Slaby MODULE_DEVICE_TABLE(hid, pl_devices); 2135f022298SJiri Slaby 2145f022298SJiri Slaby static struct hid_driver pl_driver = { 2155f022298SJiri Slaby .name = "pantherlord", 2165f022298SJiri Slaby .id_table = pl_devices, 2175f022298SJiri Slaby .probe = pl_probe, 2185f022298SJiri Slaby }; 2195f022298SJiri Slaby 220a24f423bSPeter Huewe static int __init pl_init(void) 2215f022298SJiri Slaby { 2225f022298SJiri Slaby return hid_register_driver(&pl_driver); 2235f022298SJiri Slaby } 2245f022298SJiri Slaby 225a24f423bSPeter Huewe static void __exit pl_exit(void) 2265f022298SJiri Slaby { 2275f022298SJiri Slaby hid_unregister_driver(&pl_driver); 2285f022298SJiri Slaby } 2295f022298SJiri Slaby 2305f022298SJiri Slaby module_init(pl_init); 2315f022298SJiri Slaby module_exit(pl_exit); 2325f022298SJiri Slaby MODULE_LICENSE("GPL"); 233