Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hid: force feedback driver for PantherLord USB/PS2 2in1 Adapter

Add a force feedback driver for PantherLord USB/PS2 2in1 Adapter,
0810:0001. The device identifies itself as "Twin USB Joystick".

Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Anssi Hannula and committed by
Jiri Kosina
20eb1279 5556feae

+144
+8
drivers/usb/input/Kconfig
··· 69 69 Note: if you say N here, this device will still be supported, but without 70 70 force feedback. 71 71 72 + config PANTHERLORD_FF 73 + bool "PantherLord USB/PS2 2in1 Adapter support" 74 + depends on HID_FF 75 + select INPUT_FF_MEMLESS if USB_HID 76 + help 77 + Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want 78 + to enable force feedback support for it. 79 + 72 80 config THRUSTMASTER_FF 73 81 bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" 74 82 depends on HID_FF && EXPERIMENTAL
+3
drivers/usb/input/Makefile
··· 17 17 ifeq ($(CONFIG_LOGITECH_FF),y) 18 18 usbhid-objs += hid-lgff.o 19 19 endif 20 + ifeq ($(CONFIG_PANTHERLORD_FF),y) 21 + usbhid-objs += hid-plff.o 22 + endif 20 23 ifeq ($(CONFIG_THRUSTMASTER_FF),y) 21 24 usbhid-objs += hid-tmff.o 22 25 endif
+3
drivers/usb/input/hid-ff.c
··· 58 58 { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ 59 59 { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ 60 60 #endif 61 + #ifdef CONFIG_PANTHERLORD_FF 62 + { 0x810, 0x0001, hid_plff_init }, 63 + #endif 61 64 #ifdef CONFIG_THRUSTMASTER_FF 62 65 { 0x44f, 0xb304, hid_tmff_init }, 63 66 #endif
+129
drivers/usb/input/hid-plff.c
··· 1 + /* 2 + * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices 3 + * 4 + * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> 5 + */ 6 + 7 + /* 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 + */ 22 + 23 + 24 + /* #define DEBUG */ 25 + 26 + #define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) 27 + 28 + #include <linux/input.h> 29 + #include <linux/usb.h> 30 + #include <linux/hid.h> 31 + #include "usbhid.h" 32 + 33 + struct plff_device { 34 + struct hid_report *report; 35 + }; 36 + 37 + static int hid_plff_play(struct input_dev *dev, void *data, 38 + struct ff_effect *effect) 39 + { 40 + struct hid_device *hid = dev->private; 41 + struct plff_device *plff = data; 42 + int left, right; 43 + 44 + left = effect->u.rumble.strong_magnitude; 45 + right = effect->u.rumble.weak_magnitude; 46 + debug("called with 0x%04x 0x%04x", left, right); 47 + 48 + left = left * 0x7f / 0xffff; 49 + right = right * 0x7f / 0xffff; 50 + 51 + plff->report->field[0]->value[2] = left; 52 + plff->report->field[0]->value[3] = right; 53 + debug("running with 0x%02x 0x%02x", left, right); 54 + usbhid_submit_report(hid, plff->report, USB_DIR_OUT); 55 + 56 + return 0; 57 + } 58 + 59 + int hid_plff_init(struct hid_device *hid) 60 + { 61 + struct plff_device *plff; 62 + struct hid_report *report; 63 + struct hid_input *hidinput; 64 + struct list_head *report_list = 65 + &hid->report_enum[HID_OUTPUT_REPORT].report_list; 66 + struct list_head *report_ptr = report_list; 67 + struct input_dev *dev; 68 + int error; 69 + 70 + /* The device contains 2 output reports (one for each 71 + HID_QUIRK_MULTI_INPUT device), both containing 1 field, which 72 + contains 4 ff00.0002 usages and 4 16bit absolute values. 73 + 74 + The 2 input reports also contain a field which contains 75 + 8 ff00.0001 usages and 8 boolean values. Their meaning is 76 + currently unknown. */ 77 + 78 + if (list_empty(report_list)) { 79 + printk(KERN_ERR "hid-plff: no output reports found\n"); 80 + return -ENODEV; 81 + } 82 + 83 + list_for_each_entry(hidinput, &hid->inputs, list) { 84 + 85 + report_ptr = report_ptr->next; 86 + 87 + if (report_ptr == report_list) { 88 + printk(KERN_ERR "hid-plff: required output report is missing\n"); 89 + return -ENODEV; 90 + } 91 + 92 + report = list_entry(report_ptr, struct hid_report, list); 93 + if (report->maxfield < 1) { 94 + printk(KERN_ERR "hid-plff: no fields in the report\n"); 95 + return -ENODEV; 96 + } 97 + 98 + if (report->field[0]->report_count < 4) { 99 + printk(KERN_ERR "hid-plff: not enough values in the field\n"); 100 + return -ENODEV; 101 + } 102 + 103 + plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); 104 + if (!plff) 105 + return -ENOMEM; 106 + 107 + dev = hidinput->input; 108 + 109 + set_bit(FF_RUMBLE, dev->ffbit); 110 + 111 + error = input_ff_create_memless(dev, plff, hid_plff_play); 112 + if (error) { 113 + kfree(plff); 114 + return error; 115 + } 116 + 117 + plff->report = report; 118 + plff->report->field[0]->value[0] = 0x00; 119 + plff->report->field[0]->value[1] = 0x00; 120 + plff->report->field[0]->value[2] = 0x00; 121 + plff->report->field[0]->value[3] = 0x00; 122 + usbhid_submit_report(hid, plff->report, USB_DIR_OUT); 123 + } 124 + 125 + printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " 126 + "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n"); 127 + 128 + return 0; 129 + }
+1
include/linux/hid.h
··· 504 504 int hid_ff_init(struct hid_device *hid); 505 505 506 506 int hid_lgff_init(struct hid_device *hid); 507 + int hid_plff_init(struct hid_device *hid); 507 508 int hid_tmff_init(struct hid_device *hid); 508 509 int hid_zpff_init(struct hid_device *hid); 509 510 #ifdef CONFIG_HID_PID