diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-driver-hid-wiimote | 18 | ||||
-rw-r--r-- | drivers/hid/Kconfig | 22 | ||||
-rw-r--r-- | drivers/hid/hid-apple.c | 22 | ||||
-rw-r--r-- | drivers/hid/hid-axff.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 18 | ||||
-rw-r--r-- | drivers/hid/hid-elo.c | 35 | ||||
-rw-r--r-- | drivers/hid/hid-holtek-mouse.c | 4 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 13 | ||||
-rw-r--r-- | drivers/hid/hid-lenovo-tpkbd.c | 50 | ||||
-rw-r--r-- | drivers/hid/hid-lg.c | 138 | ||||
-rw-r--r-- | drivers/hid/hid-lg2ff.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-lg4ff.c | 101 | ||||
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 14 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.c | 27 | ||||
-rw-r--r-- | drivers/hid/hid-sensor-hub.c | 13 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 63 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 117 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote.h | 2 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 4 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/usbtouchscreen.c | 4 |
21 files changed, 562 insertions, 110 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-wiimote b/Documentation/ABI/testing/sysfs-driver-hid-wiimote index ed5dd567d39..39dfa5cb1cc 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-wiimote +++ b/Documentation/ABI/testing/sysfs-driver-hid-wiimote @@ -57,3 +57,21 @@ Description: This attribute is only provided if the device was detected as a Calibration data is already applied by the kernel to all input values but may be used by user-space to perform other transformations. + +What: /sys/bus/hid/drivers/wiimote/<dev>/pro_calib +Date: October 2013 +KernelVersion: 3.13 +Contact: David Herrmann <dh.herrmann@gmail.com> +Description: This attribute is only provided if the device was detected as a + pro-controller. It provides a single line with 4 calibration + values for all 4 analog sticks. Format is: "x1:y1 x2:y2". Data + is prefixed with a +/-. Each value is a signed 16bit number. + Data is encoded as decimal numbers and specifies the offsets of + the analog sticks of the pro-controller. + Calibration data is already applied by the kernel to all input + values but may be used by user-space to perform other + transformations. + Calibration data is detected by the kernel during device setup. + You can write "scan\n" into this file to re-trigger calibration. + You can also write data directly in the form "x1:y1 x2:y2" to + set the calibration values manually. diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index c91d547191d..329fbb9b597 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -242,6 +242,7 @@ config HID_HOLTEK - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 / Zalman ZM-GM1 - SHARKOON DarkGlider Gaming mouse + - LEETGION Hellion Gaming Mouse config HOLTEK_FF bool "Holtek On Line Grip force feedback support" @@ -323,7 +324,7 @@ config HID_LCPOWER config HID_LENOVO_TPKBD tristate "Lenovo ThinkPad USB Keyboard with TrackPoint" - depends on USB_HID + depends on HID select NEW_LEDS select LEDS_CLASS ---help--- @@ -362,19 +363,20 @@ config LOGITECH_FF - Logitech WingMan Force 3D - Logitech Formula Force EX - Logitech WingMan Formula Force GP - - Logitech MOMO Force wheel and if you want to enable force feedback for them. Note: if you say N here, this device will still be supported, but without force feedback. config LOGIRUMBLEPAD2_FF - bool "Logitech RumblePad/Rumblepad 2 force feedback support" + bool "Logitech force feedback support (variant 2)" depends on HID_LOGITECH select INPUT_FF_MEMLESS help - Say Y here if you want to enable force feedback support for Logitech - RumblePad and Rumblepad 2 devices. + Say Y here if you want to enable force feedback support for: + - Logitech RumblePad + - Logitech Rumblepad 2 + - Logitech Formula Vibration Feedback Wheel config LOGIG940_FF bool "Logitech Flight System G940 force feedback support" @@ -437,6 +439,7 @@ config HID_MULTITOUCH - Chunghwa panels - CVTouch panels - Cypress TrueTouch panels + - Elan Microelectronics touch panels - Elo TouchSystems IntelliTouch Plus panels - GeneralTouch 'Sensing Win7-TwoFinger' panels - GoodTouch panels @@ -453,6 +456,7 @@ config HID_MULTITOUCH - Pixcir dual touch panels - Quanta panels - eGalax dual-touch panels, including the Joojoo and Wetab tablets + - SiS multitouch panels - Stantum multitouch panels - Touch International Panels - Unitec Panels @@ -614,6 +618,14 @@ config HID_SONY * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) +config SONY_FF + bool "Sony PS2/3 accessories force feedback support" + depends on HID_SONY + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have a Sony PS2/3 accessory and want to enable force + feedback support for it. + config HID_SPEEDLINK tristate "Speedlink VAD Cezanne mouse support" depends on HID diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 881cf7b4f9a..497558127bb 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -46,6 +46,12 @@ module_param(iso_layout, uint, 0644); MODULE_PARM_DESC(iso_layout, "Enable/Disable hardcoded ISO-layout of the keyboard. " "(0 = disabled, [1] = enabled)"); +static unsigned int swap_opt_cmd; +module_param(swap_opt_cmd, uint, 0644); +MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. " + "(For people who want to keep Windows PC keyboard muscle memory. " + "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)"); + struct apple_sc { unsigned long quirks; unsigned int fn_on; @@ -150,6 +156,14 @@ static const struct apple_key_translation apple_iso_keyboard[] = { { } }; +static const struct apple_key_translation swapped_option_cmd_keys[] = { + { KEY_LEFTALT, KEY_LEFTMETA }, + { KEY_LEFTMETA, KEY_LEFTALT }, + { KEY_RIGHTALT, KEY_RIGHTMETA }, + { KEY_RIGHTMETA,KEY_RIGHTALT }, + { } +}; + static const struct apple_key_translation *apple_find_translation( const struct apple_key_translation *table, u16 from) { @@ -242,6 +256,14 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } } + if (swap_opt_cmd) { + trans = apple_find_translation(swapped_option_cmd_keys, usage->code); + if (trans) { + input_event(input, usage->type, trans->to, value); + return 1; + } + } + return 0; } diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index 64ab94a55aa..a594e478a1e 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c @@ -95,7 +95,7 @@ static int axff_init(struct hid_device *hid) } } - if (field_count < 4) { + if (field_count < 4 && hid->product != 0xf705) { hid_err(hid, "not enough fields in the report: %d\n", field_count); return -ENODEV; @@ -180,6 +180,7 @@ static void ax_remove(struct hid_device *hdev) static const struct hid_device_id ax_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705), }, { } }; MODULE_DEVICE_TABLE(hid, ax_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ec6ba50e745..8c10f274223 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1418,10 +1418,8 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { ret = hdrv->raw_event(hid, report, data, size); - if (ret < 0) { - ret = ret < 0 ? ret : 0; + if (ret < 0) goto unlock; - } } ret = hid_report_raw_event(hid, type, data, size, interrupt); @@ -1605,6 +1603,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, @@ -1716,6 +1715,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, @@ -1754,6 +1754,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, { 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_VIBRATION_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, @@ -1821,6 +1822,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, @@ -2381,15 +2384,6 @@ bool hid_ignore(struct hid_device *hdev) hdev->type == HID_TYPE_USBNONE) return true; break; - case USB_VENDOR_ID_DWAV: - /* These are handled by usbtouchscreen. hdev->type is probably - * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match - * usbtouchscreen. */ - if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER || - hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) && - hdev->type != HID_TYPE_USBMOUSE) - return true; - break; case USB_VENDOR_ID_VELLEMAN: /* These are not HID devices. They are handled by comedi. */ if ((hdev->product >= USB_DEVICE_ID_VELLEMAN_K8055_FIRST && diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c index f042a6cf8b1..4e49462870a 100644 --- a/drivers/hid/hid-elo.c +++ b/drivers/hid/hid-elo.c @@ -181,7 +181,40 @@ fail: */ static bool elo_broken_firmware(struct usb_device *dev) { - return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d; + struct usb_device *hub = dev->parent; + struct usb_device *child = NULL; + u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice); + u16 child_vid, child_pid; + int i; + + if (!use_fw_quirk) + return false; + if (fw_lvl != 0x10d) + return false; + + /* iterate sibling devices of the touch controller */ + usb_hub_for_each_child(hub, i, child) { + child_vid = le16_to_cpu(child->descriptor.idVendor); + child_pid = le16_to_cpu(child->descriptor.idProduct); + + /* + * If one of the devices below is present attached as a sibling of + * the touch controller then this is a newer IBM 4820 monitor that + * does not need the IBM-requested workaround if fw level is + * 0x010d - aka 'M'. + * No other HW can have this combination. + */ + if (child_vid==0x04b3) { + switch (child_pid) { + case 0x4676: /* 4820 21x Video */ + case 0x4677: /* 4820 51x Video */ + case 0x4678: /* 4820 2Lx Video */ + case 0x4679: /* 4820 5Lx Video */ + return false; + } + } + } + return true; } static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c index e696566cde4..0caa676de62 100644 --- a/drivers/hid/hid-holtek-mouse.c +++ b/drivers/hid/hid-holtek-mouse.c @@ -28,6 +28,7 @@ * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200 * and Zalman ZM-GM1 * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse + * - USB ID 04d9:a072, sold as LEETGION Hellion Gaming Mouse */ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, @@ -40,6 +41,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, * 0x2fff, so they don't exceed HID_MAX_USAGES */ switch (hdev->product) { case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067: + case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072: if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f && rdesc[120] == 0xff && rdesc[121] == 0x7f) { hid_info(hdev, "Fixing up report descriptor\n"); @@ -66,6 +68,8 @@ static const struct hid_device_id holtek_mouse_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, { } }; diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 768fafc42c8..76559629568 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -332,6 +332,11 @@ #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101 0x0101 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102 0x0102 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106 0x0106 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 @@ -448,8 +453,9 @@ #define USB_VENDOR_ID_HOLTEK_ALT 0x04d9 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 -#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a +#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 +#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072 0xa072 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081 #define USB_VENDOR_ID_IMATION 0x0718 @@ -571,6 +577,7 @@ #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 #define USB_DEVICE_ID_DINOVO_MINI 0xc71f #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 +#define USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL 0xca04 #define USB_VENDOR_ID_LUMIO 0x202e #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 @@ -748,6 +755,10 @@ #define USB_VENDOR_ID_SIGMATEL 0x066F #define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 +#define USB_VENDOR_ID_SIS2_TOUCH 0x0457 +#define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 +#define USB_DEVICE_ID_SIS817_TOUCH 0x0817 + #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 31cf29a6ba1..2d25b6cbbc0 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -14,11 +14,9 @@ #include <linux/module.h> #include <linux/sysfs.h> #include <linux/device.h> -#include <linux/usb.h> #include <linux/hid.h> #include <linux/input.h> #include <linux/leds.h> -#include "usbhid/usbhid.h" #include "hid-ids.h" @@ -41,10 +39,9 @@ static int tpkbd_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - struct usbhid_device *uhdev; - - uhdev = (struct usbhid_device *) hdev->driver_data; - if (uhdev->ifnum == 1 && usage->hid == (HID_UP_BUTTON | 0x0010)) { + if (usage->hid == (HID_UP_BUTTON | 0x0010)) { + /* mark the device as pointer */ + hid_set_drvdata(hdev, (void *)1); map_key_clear(KEY_MICMUTE); return 1; } @@ -339,7 +336,7 @@ static int tpkbd_probe_tp(struct hid_device *hdev) struct tpkbd_data_pointer *data_pointer; size_t name_sz = strlen(dev_name(dev)) + 16; char *name_mute, *name_micmute; - int i, ret; + int i; /* Validate required reports. */ for (i = 0; i < 4; i++) { @@ -354,7 +351,9 @@ static int tpkbd_probe_tp(struct hid_device *hdev) hid_warn(hdev, "Could not create sysfs group\n"); } - data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL); + data_pointer = devm_kzalloc(&hdev->dev, + sizeof(struct tpkbd_data_pointer), + GFP_KERNEL); if (data_pointer == NULL) { hid_err(hdev, "Could not allocate memory for driver data\n"); return -ENOMEM; @@ -364,20 +363,13 @@ static int tpkbd_probe_tp(struct hid_device *hdev) data_pointer->sensitivity = 0xa0; data_pointer->press_speed = 0x38; - name_mute = kzalloc(name_sz, GFP_KERNEL); - if (name_mute == NULL) { + name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); + name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); + if (name_mute == NULL || name_micmute == NULL) { hid_err(hdev, "Could not allocate memory for led data\n"); - ret = -ENOMEM; - goto err; + return -ENOMEM; } snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); - - name_micmute = kzalloc(name_sz, GFP_KERNEL); - if (name_micmute == NULL) { - hid_err(hdev, "Could not allocate memory for led data\n"); - ret = -ENOMEM; - goto err2; - } snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); hid_set_drvdata(hdev, data_pointer); @@ -397,19 +389,12 @@ static int tpkbd_probe_tp(struct hid_device *hdev) tpkbd_features_set(hdev); return 0; - -err2: - kfree(name_mute); -err: - kfree(data_pointer); - return ret; } static int tpkbd_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; - struct usbhid_device *uhdev; ret = hid_parse(hdev); if (ret) { @@ -423,9 +408,8 @@ static int tpkbd_probe(struct hid_device *hdev, goto err; } - uhdev = (struct usbhid_device *) hdev->driver_data; - - if (uhdev->ifnum == 1) { + if (hid_get_drvdata(hdev)) { + hid_set_drvdata(hdev, NULL); ret = tpkbd_probe_tp(hdev); if (ret) goto err_hid; @@ -449,17 +433,11 @@ static void tpkbd_remove_tp(struct hid_device *hdev) led_classdev_unregister(&data_pointer->led_mute); hid_set_drvdata(hdev, NULL); - kfree(data_pointer->led_micmute.name); - kfree(data_pointer->led_mute.name); - kfree(data_pointer); } static void tpkbd_remove(struct hid_device *hdev) { - struct usbhid_device *uhdev; - - uhdev = (struct usbhid_device *) hdev->driver_data; - if (uhdev->ifnum == 1) + if (hid_get_drvdata(hdev)) tpkbd_remove_tp(hdev); hid_hw_stop(hdev); diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 6f12ecd36c8..06eb45fa633 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -45,7 +45,9 @@ /* Size of the original descriptors of the Driving Force (and Pro) wheels */ #define DF_RDESC_ORIG_SIZE 130 #define DFP_RDESC_ORIG_SIZE 97 +#define FV_RDESC_ORIG_SIZE 130 #define MOMO_RDESC_ORIG_SIZE 87 +#define MOMO2_RDESC_ORIG_SIZE 87 /* Fixed report descriptors for Logitech Driving Force (and Pro) * wheel controllers @@ -170,6 +172,73 @@ static __u8 dfp_rdesc_fixed[] = { 0xC0 /* End Collection */ }; +static __u8 fv_rdesc_fixed[] = { +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x04, /* Usage (Joystik), */ +0xA1, 0x01, /* Collection (Application), */ +0xA1, 0x02, /* Collection (Logical), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x0A, /* Report Size (10), */ +0x15, 0x00, /* Logical Minimum (0), */ +0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ +0x35, 0x00, /* Physical Minimum (0), */ +0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ +0x09, 0x30, /* Usage (X), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x0C, /* Report Count (12), */ +0x75, 0x01, /* Report Size (1), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x05, 0x09, /* Usage Page (Button), */ +0x19, 0x01, /* Usage Minimum (01h), */ +0x29, 0x0C, /* Usage Maximum (0Ch), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x02, /* Report Count (2), */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x01, /* Usage (01h), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x02, /* Usage (02h), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x08, /* Report Size (8), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x25, 0x07, /* Logical Maximum (7), */ +0x46, 0x3B, 0x01, /* Physical Maximum (315), */ +0x75, 0x04, /* Report Size (4), */ +0x65, 0x14, /* Unit (Degrees), */ +0x09, 0x39, /* Usage (Hat Switch), */ +0x81, 0x42, /* Input (Variable, Null State), */ +0x75, 0x01, /* Report Size (1), */ +0x95, 0x04, /* Report Count (4), */ +0x65, 0x00, /* Unit, */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x01, /* Usage (01h), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x08, /* Report Size (8), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x09, 0x31, /* Usage (Y), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x32, /* Usage (Z), */ +0x81, 0x02, /* Input (Variable), */ +0xC0, /* End Collection, */ +0xA1, 0x02, /* Collection (Logical), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x95, 0x07, /* Report Count (7), */ +0x75, 0x08, /* Report Size (8), */ +0x09, 0x03, /* Usage (03h), */ +0x91, 0x02, /* Output (Variable), */ +0xC0, /* End Collection, */ +0xC0 /* End Collection */ +}; + static __u8 momo_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystik), */ @@ -216,6 +285,54 @@ static __u8 momo_rdesc_fixed[] = { 0xC0 /* End Collection */ }; +static __u8 momo2_rdesc_fixed[] = { +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x04, /* Usage (Joystik), */ +0xA1, 0x01, /* Collection (Application), */ +0xA1, 0x02, /* Collection (Logical), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x0A, /* Report Size (10), */ +0x15, 0x00, /* Logical Minimum (0), */ +0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ +0x35, 0x00, /* Physical Minimum (0), */ +0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ +0x09, 0x30, /* Usage (X), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x0A, /* Report Count (10), */ +0x75, 0x01, /* Report Size (1), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x05, 0x09, /* Usage Page (Button), */ +0x19, 0x01, /* Usage Minimum (01h), */ +0x29, 0x0A, /* Usage Maximum (0Ah), */ +0x81, 0x02, /* Input (Variable), */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x00, /* Usage (00h), */ +0x95, 0x04, /* Report Count (4), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x08, /* Report Size (8), */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x09, 0x01, /* Usage (01h), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x31, /* Usage (Y), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x32, /* Usage (Z), */ +0x81, 0x02, /* Input (Variable), */ +0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ +0x09, 0x00, /* Usage (00h), */ +0x81, 0x02, /* Input (Variable), */ +0xC0, /* End Collection, */ +0xA1, 0x02, /* Collection (Logical), */ +0x09, 0x02, /* Usage (02h), */ +0x95, 0x07, /* Report Count (7), */ +0x91, 0x02, /* Output (Variable), */ +0xC0, /* End Collection, */ +0xC0 /* End Collection */ +}; + /* * Certain Logitech keyboards send in report #3 keys which are far * above the logical maximum described in descriptor. This extends @@ -275,6 +392,24 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, } break; + case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: + if (*rsize == MOMO2_RDESC_ORIG_SIZE) { + hid_info(hdev, + "fixing up Logitech Momo Racing Force (Black) report descriptor\n"); + rdesc = momo2_rdesc_fixed; + *rsize = sizeof(momo2_rdesc_fixed); + } + break; + + case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: + if (*rsize == FV_RDESC_ORIG_SIZE) { + hid_info(hdev, + "fixing up Logitech Formula Vibration report descriptor\n"); + rdesc = fv_rdesc_fixed; + *rsize = sizeof(fv_rdesc_fixed); + } + break; + case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: if (*rsize == DFP_RDESC_ORIG_SIZE) { hid_info(hdev, @@ -492,6 +627,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, case USB_DEVICE_ID_LOGITECH_G27_WHEEL: case USB_DEVICE_ID_LOGITECH_WII_WHEEL: case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: + case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL: field->application = HID_GD_MULTIAXIS; break; default: @@ -639,6 +775,8 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_NOGET | LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), .driver_data = LG_FF4 }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL), + .driver_data = LG_FF2 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL), diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index 1a42eaa6ca0..0e3fb1a7e42 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -95,7 +95,7 @@ int lg2ff_init(struct hid_device *hid) hid_hw_request(hid, report, HID_REQ_SET_REPORT); - hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n"); + hid_info(hid, "Force feedback for Logitech variant 2 rumble devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); return 0; } diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 8782fe1aaa0..befe0e33647 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -196,6 +196,21 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e case FF_CONSTANT: x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ CLAMP(x); + + if (x == 0x80) { + /* De-activate force in slot-1*/ + value[0] = 0x13; + value[1] = 0x00; + value[2] = 0x00; + value[3] = 0x00; + value[4] = 0x00; + value[5] = 0x00; + value[6] = 0x00; + + hid_hw_request(hid, report, HID_REQ_SET_REPORT); + return 0; + } + value[0] = 0x11; /* Slot 1 */ value[1] = 0x08; value[2] = x; @@ -218,12 +233,70 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); __s32 *value = report->field[0]->value; + __u32 expand_a, expand_b; + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return; + } + + /* De-activate Auto-Center */ + if (magnitude == 0) { + value[0] = 0xf5; + value[1] = 0x00; + value[2] = 0x00; + value[3] = 0x00; + value[4] = 0x00; + value[5] = 0x00; + value[6] = 0x00; + + hid_hw_request(hid, report, HID_REQ_SET_REPORT); + return; + } + + if (magnitude <= 0xaaaa) { + expand_a = 0x0c * magnitude; + expand_b = 0x80 * magnitude; + } else { + expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa); + expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa); + } + + /* Adjust for non-MOMO wheels */ + switch (entry->product_id) { + case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: + case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: + break; + default: + expand_a = expand_a >> 1; + break; + } value[0] = 0xfe; value[1] = 0x0d; - value[2] = magnitude >> 13; - value[3] = magnitude >> 13; - value[4] = magnitude >> 8; + value[2] = expand_a / 0xaaaa; + value[3] = expand_a / 0xaaaa; + value[4] = expand_b / 0xaaaa; + value[5] = 0x00; + value[6] = 0x00; + + hid_hw_request(hid, report, HID_REQ_SET_REPORT); + + /* Activate Auto-Center */ + value[0] = 0x14; + value[1] = 0x00; + value[2] = 0x00; + value[3] = 0x00; + value[4] = 0x00; value[5] = 0x00; value[6] = 0x00; @@ -540,17 +613,6 @@ int lg4ff_init(struct hid_device *hid) if (error) return error; - /* Check if autocentering is available and - * set the centering force to zero by default */ - if (test_bit(FF_AUTOCENTER, dev->ffbit)) { - if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; - else - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; - - dev->ff->set_autocenter(dev, 0); - } - /* Get private driver data */ drv_data = hid_get_drvdata(hid); if (!drv_data) { |