From 01ab35f14aafbc6e159254f52444895661c2f604 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 11 Sep 2013 22:12:23 +0200 Subject: HID: lenovo-tpkbd: devm conversion We can use the devres API in hid modules, so use it to avoid some kfree and potential leaks. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-lenovo-tpkbd.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 31cf29a6ba17..0d9a276af16a 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -339,7 +339,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 +354,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 +366,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,12 +392,6 @@ 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, @@ -449,9 +438,6 @@ 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) -- cgit v1.2.3 From 0c5218362b429ab9cbf295dfe069ce410d180493 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 11 Sep 2013 22:12:24 +0200 Subject: HID: lenovo-tpkbd: remove usb dependency lenovo tpkbd currently relies on the usb interface number to detect if it is dealing with the touchpad interface or not. As the report descriptors of the interface 0 does not contain the button 3, we can use this to remove the need to check for usb. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 2 +- drivers/hid/hid-lenovo-tpkbd.c | 20 ++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 71b70e3a7a71..53747245d904 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -322,7 +322,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--- diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 0d9a276af16a..2d25b6cbbc05 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -14,11 +14,9 @@ #include #include #include -#include #include #include #include -#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; } @@ -398,7 +395,6 @@ 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) { @@ -412,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; @@ -442,10 +437,7 @@ static void tpkbd_remove_tp(struct hid_device *hdev) 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); -- cgit v1.2.3 From f204828a1150b0f35730556cd493febda011caf1 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 11 Sep 2013 22:12:25 +0200 Subject: HID: sony: use hid_get_raw_report() instead of a direct call to usb The usb packets are exactly the same, but it makes it a little bit more independent of the transport layer. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b18320db5f7d..bc37a1800166 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -419,21 +419,14 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf, */ static int sixaxis_set_operational_usb(struct hid_device *hdev) { - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct usb_device *dev = interface_to_usbdev(intf); - __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber; int ret; char *buf = kmalloc(18, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - HID_REQ_GET_REPORT, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, - (3 << 8) | 0xf2, ifnum, buf, 17, - USB_CTRL_GET_TIMEOUT); + ret = hdev->hid_get_raw_report(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT); + if (ret < 0) hid_err(hdev, "can't set operational mode\n"); -- cgit v1.2.3 From 403cfb53fb450d53751fdc7ee0cd6652419612cf Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 25 Sep 2013 09:42:55 +0200 Subject: HID: hid-elo: some systems cannot stomach work around Some systems although they have firmware class 'M', which usually needs a work around to not crash, must not be subjected to the work around because the work around crashes them. They cannot be told apart by their own device descriptor, but as they are part of compound devices, can be identified by looking at their siblings. Signed-off-by: Oliver Neukum Signed-off-by: Jiri Kosina --- drivers/hid/hid-elo.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c index f042a6cf8b18..4e49462870ab 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) -- cgit v1.2.3 From 7b2262920db2b98fe2cd32cde52141f02fd9eecf Mon Sep 17 00:00:00 2001 From: Luosong Date: Wed, 2 Oct 2013 11:20:00 +0200 Subject: HID: multitouch: Fix GeneralTouch products and add more PIDs GeneralTouch products should use the quirk SLOT_IS_CONTACTID instead of SLOT_IS_CONTACTNUMBER. Adding PIDs 0101,e100,0102,0106,010a from the new products. Tested on new and older products by GeneralTouch engineers. Signed-off-by: Luosong Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 5 +++++ drivers/hid/hid-multitouch.c | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e60e8d530697..9a91dee2cfe9 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 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 5e5fe1b8eebb..cb3250c5a397 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -250,12 +250,12 @@ static struct mt_class mt_classes[] = { { .name = MT_CLS_GENERALTOUCH_TWOFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_VALID_IS_INRANGE | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, + MT_QUIRK_SLOT_IS_CONTACTID, .maxcontacts = 2 }, { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTNUMBER + MT_QUIRK_SLOT_IS_CONTACTID }, { .name = MT_CLS_FLATFROG, @@ -1173,6 +1173,21 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) }, + { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) }, + { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, + MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) }, /* Gametel game controller */ { .driver_data = MT_CLS_NSMU, -- cgit v1.2.3 From bd04363d3990c0727b7512a79a08c68436878bb0 Mon Sep 17 00:00:00 2001 From: Elias Vanderstuyft Date: Mon, 7 Oct 2013 19:48:12 +0300 Subject: HID: logitech - lg2ff: Add IDs for Formula Vibration Feedback Wheel Add USB IDs for Logitech Formula Vibration Feedback Wheel (046d:ca04). The lg2ff force feedback subdriver is used for vibration and HID_GD_MULTIAXIS is set to avoid deadzone like other Logitech wheels. Kconfig description etc are also updated accordingly. Signed-off-by: Elias Vanderstuyft [anssi.hannula@iki.fi: added description and CCs] Signed-off-by: Anssi Hannula Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 8 +++++--- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-lg.c | 3 +++ drivers/hid/hid-lg2ff.c | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index c91d547191dd..46fd27f6f026 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -369,12 +369,14 @@ config LOGITECH_FF 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" diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5a8c01112a23..95d2dff0a7ee 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1753,6 +1753,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) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9cbc7ab07dfa..312d7fd20ee1 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -571,6 +571,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 diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 6f12ecd36c88..c2c7dab7d2c4 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -492,6 +492,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 +640,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 1a42eaa6ca02..0e3fb1a7e421 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 \n"); + hid_info(hid, "Force feedback for Logitech variant 2 rumble devices by Anssi Hannula \n"); return 0; } -- cgit v1.2.3 From 43c831468b3d26dbe8f2e061ccaf1abaf9cc1b8b Mon Sep 17 00:00:00 2001 From: Nanno Langstraat Date: Mon, 14 Oct 2013 16:07:15 +0200 Subject: HID: apple: option to swap the 'Option' ("Alt") and 'Command' ("Flag") keys. Use case: people who use both Apple and PC keyboards regularly, and desire to keep&use their PC muscle memory. A particular use case: an Apple compact external keyboard connected to a PC laptop. (This use case can't be covered well by X.org key remappings etc.) Signed-off-by: Nanno Langstraat Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 881cf7b4f9a4..3b219b9553fb 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 = 0; +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; } -- cgit v1.2.3 From a94c79bdc972f7b3d66756043edbd6d04e8486d6 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 14 Oct 2013 16:07:42 +0200 Subject: HID: apple: swap_opt_cmd is already zero-initialized Global static variable is already zero-initialized. Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 3b219b9553fb..497558127bb3 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -46,7 +46,7 @@ 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 = 0; +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. " -- cgit v1.2.3 From 7f50547059bd55ac6a98c29fd1989421bdc36ec9 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Thu, 10 Oct 2013 08:20:12 -0600 Subject: HID: lg: fix ReportDescriptor for Logitech Formula Vibration By default the Logitech Formula Vibration presents a combined accel/brake axis ('Y'). This patch modifies the HID descriptor to present seperate accel/brake axes ('Y' and 'Z'). Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-lg.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index c2c7dab7d2c4..1bfd292cac8f 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -45,6 +45,7 @@ /* 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 /* Fixed report descriptors for Logitech Driving Force (and Pro) @@ -170,6 +171,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), */ @@ -275,6 +343,15 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, } 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, -- cgit v1.2.3 From 348cbaa800f8161168b20f85f72abb541c145132 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Thu, 10 Oct 2013 08:20:13 -0600 Subject: HID: lg: fix Report Descriptor for Logitech MOMO Force (Black) By default the Logitech MOMO Force (Black) presents a combined accel/brake axis ('Y'). This patch modifies the HID descriptor to present seperate accel/brake axes ('Y' and 'Z'). Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-lg.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 1bfd292cac8f..06eb45fa6331 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -47,6 +47,7 @@ #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 @@ -284,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 @@ -343,6 +392,15 @@ 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, -- cgit v1.2.3 From 362ecc7c38ac3806d2afca92b25094e6063a0f17 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Thu, 10 Oct 2013 08:20:14 -0600 Subject: HID: Correct Kconfig MOMO description Minor correction to the description in Kconfig. The Logitect MOMO wheel is actually handled by the LOGITECH_WHEELS (hid-lg4ff) section, not by the LOGITECH_FF (hid-lgff). Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 46fd27f6f026..aee718269ab3 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -362,7 +362,6 @@ 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 -- cgit v1.2.3 From a6802e008e19845fd9669511b895f7515ef9c48b Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 21 Oct 2013 12:38:49 -0400 Subject: HID: hid-multitouch: add support for SiS panels Add support for SiS multitouch panels. Signed-off-by: Forest Bond Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 2 ++ drivers/hid/hid-ids.h | 4 ++++ drivers/hid/hid-multitouch.c | 8 ++++++++ drivers/hid/usbhid/hid-quirks.c | 2 ++ 5 files changed, 17 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 71b70e3a7a71..eb8c6278cfce 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -452,6 +452,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 diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b8470b1a10fe..825f9c3aadb1 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1814,6 +1814,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) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9a91dee2cfe9..842685a77e4b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -748,6 +748,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-multitouch.c b/drivers/hid/hid-multitouch.c index cb3250c5a397..a2cedb8ae1c0 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1299,6 +1299,14 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, + /* SiS panels */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + USB_DEVICE_ID_SIS9200_TOUCH) }, + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, + USB_DEVICE_ID_SIS817_TOUCH) }, + /* Stantum panels */ { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 07345521f421..ae5c63478b92 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -84,6 +84,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, -- cgit v1.2.3 From f1a4914bd04911fbeaee23445112adae8977144a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=2E=20U=2E=20Ki=C3=A6r?= Date: Mon, 21 Oct 2013 23:42:22 +0200 Subject: HID: add support for LEETGION Hellion Gaming Mouse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added id, bindings and comments for Holtek USB ID 04d9:a072 LEETGION Hellion Gaming mouse to use the same corrections of the report descriptor as Holtek 04d9:a067. As the mouse exceed HID_MAX_USAGES at the same offsets in the reported descriptor. Tested on the hardware. Signed-off-by: Anders F. U. KiƦr Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-holtek-mouse.c | 4 ++++ drivers/hid/hid-ids.h | 3 ++- 4 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index c91d547191dd..d68292a50df5 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" diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e80da62363bc..e8353f331792 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1716,6 +1716,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) }, diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c index e696566cde46..0caa676de622 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"); @@ -65,6 +67,8 @@ static const struct hid_device_id holtek_mouse_devices[] = { USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, { 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 f0296a50be5f..bdebab4e345b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -448,8 +448,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 -- cgit v1.2.3 From 0abda6fa81dced031e3df31ac29bfb253549c2d1 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 28 Oct 2013 17:47:53 +0100 Subject: HID: wiimote: fix inverted pro-controller axes The analog-stick vertical axes are inverted. Fix that! Otherwise, games and other gamepad applications need to carry their own fixups (which they thankfully haven't done, yet). Cc: # 3.11+ Reported-by: Rafael Brune Tested-by: Rafael Brune Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote-modules.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 71adf9e60b13..e30567af42ed 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c @@ -1656,9 +1656,9 @@ static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext) ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8); input_report_abs(wdata->extension.input, ABS_X, lx - 0x800); - input_report_abs(wdata->extension.input, ABS_Y, ly - 0x800); + input_report_abs(wdata->extension.input, ABS_Y, 0x800 - ly); input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800); - input_report_abs(wdata->extension.input, ABS_RY, ry - 0x800); + input_report_abs(wdata->extension.input, ABS_RY, 0x800 - ry); input_report_key(wdata->extension.input, wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT], -- cgit v1.2.3 From 08072dde333c2f09114a01b0bd32be52ecce195b Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 28 Oct 2013 17:49:20 +0100 Subject: HID: wiimote: add pro-controller analog stick calibration The analog sticks of the pro-controller might report slightly off values. To guarantee a uniform setup, we now calibrate analog-stick values during pro-controller setup. Unfortunately, the pro-controller fails during normal EEPROM reads and I couldn't figure out whether there are any calibration values stored on the device. Therefore, we now use the first values reported by the device (iff they are not _way_ off, which would indicate movement) to initialize the calibration values. To allow users to change this calibration data, we provide a pro_calib sysfs attribute. We also change the "flat" values so user-space correctly smoothes our data. It makes slightly off zero-positions less visible while still guaranteeing highly precise movement reports. Note that the pro controller reports zero-positions in a quite huge range (at least: -100 to +100). Reported-by: Rafael Brune Tested-by: Rafael Brune Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote-modules.c | 117 +++++++++++++++++++++++++++++++++++--- drivers/hid/hid-wiimote.h | 2 + 2 files changed, 110 insertions(+), 9 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index e30567af42ed..6b61f01e01e7 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c @@ -1655,10 +1655,39 @@ static void wiimod_pro_in_ext(struct wiimote_data *wdata, const __u8 *ext) ly = (ext[4] & 0xff) | ((ext[5] & 0x0f) << 8); ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8); - input_report_abs(wdata->extension.input, ABS_X, lx - 0x800); - input_report_abs(wdata->extension.input, ABS_Y, 0x800 - ly); - input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800); - input_report_abs(wdata->extension.input, ABS_RY, 0x800 - ry); + /* zero-point offsets */ + lx -= 0x800; + ly = 0x800 - ly; + rx -= 0x800; + ry = 0x800 - ry; + + /* Trivial automatic calibration. We don't know any calibration data + * in the EEPROM so we must use the first report to calibrate the + * null-position of the analog sticks. Users can retrigger calibration + * via sysfs, or set it explicitly. If data is off more than abs(500), + * we skip calibration as the sticks are likely to be moved already. */ + if (!(wdata->state.flags & WIIPROTO_FLAG_PRO_CALIB_DONE)) { + wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE; + if (abs(lx) < 500) + wdata->state.calib_pro_sticks[0] = -lx; + if (abs(ly) < 500) + wdata->state.calib_pro_sticks[1] = -ly; + if (abs(rx) < 500) + wdata->state.calib_pro_sticks[2] = -rx; + if (abs(ry) < 500) + wdata->state.calib_pro_sticks[3] = -ry; + } + + /* apply calibration data */ + lx += wdata->state.calib_pro_sticks[0]; + ly += wdata->state.calib_pro_sticks[1]; + rx += wdata->state.calib_pro_sticks[2]; + ry += wdata->state.calib_pro_sticks[3]; + + input_report_abs(wdata->extension.input, ABS_X, lx); + input_report_abs(wdata->extension.input, ABS_Y, ly); + input_report_abs(wdata->extension.input, ABS_RX, rx); + input_report_abs(wdata->extension.input, ABS_RY, ry); input_report_key(wdata->extension.input, wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT], @@ -1766,12 +1795,70 @@ static int wiimod_pro_play(struct input_dev *dev, void *data, return 0; } +static ssize_t wiimod_pro_calib_show(struct device *dev, + struct device_attribute *attr, + char *out) +{ + struct wiimote_data *wdata = dev_to_wii(dev); + int r; + + r = 0; + r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[0]); + r += sprintf(&out[r], "%+06hd ", wdata->state.calib_pro_sticks[1]); + r += sprintf(&out[r], "%+06hd:", wdata->state.calib_pro_sticks[2]); + r += sprintf(&out[r], "%+06hd\n", wdata->state.calib_pro_sticks[3]); + + return r; +} + +static ssize_t wiimod_pro_calib_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wiimote_data *wdata = dev_to_wii(dev); + int r; + s16 x1, y1, x2, y2; + + if (!strncmp(buf, "scan\n", 5)) { + spin_lock_irq(&wdata->state.lock); + wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE; + spin_unlock_irq(&wdata->state.lock); + } else { + r = sscanf(buf, "%hd:%hd %hd:%hd", &x1, &y1, &x2, &y2); + if (r != 4) + return -EINVAL; + + spin_lock_irq(&wdata->state.lock); + wdata->state.flags |= WIIPROTO_FLAG_PRO_CALIB_DONE; + spin_unlock_irq(&wdata->state.lock); + + wdata->state.calib_pro_sticks[0] = x1; + wdata->state.calib_pro_sticks[1] = y1; + wdata->state.calib_pro_sticks[2] = x2; + wdata->state.calib_pro_sticks[3] = y2; + } + + return strnlen(buf, PAGE_SIZE); +} + +static DEVICE_ATTR(pro_calib, S_IRUGO|S_IWUSR|S_IWGRP, wiimod_pro_calib_show, + wiimod_pro_calib_store); + static int wiimod_pro_probe(const struct wiimod_ops *ops, struct wiimote_data *wdata) { int ret, i; + unsigned long flags; INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); + wdata->state.calib_pro_sticks[0] = 0; + wdata->state.calib_pro_sticks[1] = 0; + wdata->state.calib_pro_sticks[2] = 0; + wdata->state.calib_pro_sticks[3] = 0; + + spin_lock_irqsave(&wdata->state.lock, flags); + wdata->state.flags &= ~WIIPROTO_FLAG_PRO_CALIB_DONE; + spin_unlock_irqrestore(&wdata->state.lock, flags); wdata->extension.input = input_allocate_device(); if (!wdata->extension.input) @@ -1786,6 +1873,13 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops, goto err_free; } + ret = device_create_file(&wdata->hdev->dev, + &dev_attr_pro_calib); + if (ret) { + hid_err(wdata->hdev, "cannot create sysfs attribute\n"); + goto err_free; + } + wdata->extension.input->open = wiimod_pro_open; wdata->extension.input->close = wiimod_pro_close; wdata->extension.input->dev.parent = &wdata->hdev->dev; @@ -1806,20 +1900,23 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops, set_bit(ABS_RX, wdata->extension.input->absbit); set_bit(ABS_RY, wdata->extension.input->absbit); input_set_abs_params(wdata->extension.input, - ABS_X, -0x800, 0x800, 2, 4); + ABS_X, -0x400, 0x400, 4, 100); input_set_abs_params(wdata->extension.input, - ABS_Y, -0x800, 0x800, 2, 4); + ABS_Y, -0x400, 0x400, 4, 100); input_set_abs_params(wdata->extension.input, - ABS_RX, -0x800, 0x800, 2, 4); + ABS_RX, -0x400, 0x400, 4, 100); input_set_abs_params(wdata->extension.input, - ABS_RY, -0x800, 0x800, 2, 4); + ABS_RY, -0x400, 0x400, 4, 100); ret = input_register_device(wdata->extension.input); if (ret) - goto err_free; + goto err_file; return 0; +err_file: + device_remove_file(&wdata->hdev->dev, + &dev_attr_pro_calib); err_free: input_free_device(wdata->extension.input); wdata->extension.input = NULL; @@ -1837,6 +1934,8 @@ static void wiimod_pro_remove(const struct wiimod_ops *ops, input_unregister_device(wdata->extension.input); wdata->extension.input = NULL; cancel_work_sync(&wdata->rumble_worker); + device_remove_file(&wdata->hdev->dev, + &dev_attr_pro_calib); spin_lock_irqsave(&wdata->state.lock, flags); wiiproto_req_rumble(wdata, 0); diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index 75db0c400037..03065f1917fc 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h @@ -46,6 +46,7 @@ #define WIIPROTO_FLAG_DRM_LOCKED 0x8000 #define WIIPROTO_FLAG_BUILTIN_MP 0x010000 #define WIIPROTO_FLAG_NO_MP 0x020000 +#define WIIPROTO_FLAG_PRO_CALIB_DONE 0x040000 #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) @@ -135,6 +136,7 @@ struct wiimote_state { /* calibration/cache data */ __u16 calib_bboard[4][3]; + __s16 calib_pro_sticks[4]; __u8 cache_rumble; }; -- cgit v1.2.3 From 14fc4290df2fb94a28f39dab9ed32feaa5527bef Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Mon, 28 Oct 2013 18:52:03 +0100 Subject: HID: roccat: add new device return value Ryos uses a new return value for critical errors, others have been confirmed. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat-common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index 74f704032627..e84089998900 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c @@ -65,10 +65,11 @@ int roccat_common2_send(struct usb_device *usb_dev, uint report_id, EXPORT_SYMBOL_GPL(roccat_common2_send); enum roccat_common2_control_states { - ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD = 0, + ROCCAT_COMMON_CONTROL_STATUS_CRITICAL = 0, ROCCAT_COMMON_CONTROL_STATUS_OK = 1, ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2, - ROCCAT_COMMON_CONTROL_STATUS_WAIT = 3, + ROCCAT_COMMON_CONTROL_STATUS_BUSY = 3, + ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW = 4, }; static int roccat_common2_receive_control_status(struct usb_device *usb_dev) @@ -88,13 +89,12 @@ static int roccat_common2_receive_control_status(struct usb_device *usb_dev) switch (control.value) { case ROCCAT_COMMON_CONTROL_STATUS_OK: return 0; - case ROCCAT_COMMON_CONTROL_STATUS_WAIT: + case ROCCAT_COMMON_CONTROL_STATUS_BUSY: msleep(500); continue; case ROCCAT_COMMON_CONTROL_STATUS_INVALID: - - case ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD: - /* seems to be critical - replug necessary */ + case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL: + case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW: return -EINVAL; default: dev_err(&usb_dev->dev, -- cgit v1.2.3 From 71304f5a269abc25b9277744dfd6925f3e29e26a Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Mon, 28 Oct 2013 18:52:05 +0100 Subject: HID: roccat: generalize some common code Reduced some duplicate code by moving it to hid-roccat-common. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat-common.c | 53 +++++++++++++ drivers/hid/hid-roccat-common.h | 62 +++++++++++++++ drivers/hid/hid-roccat-konepure.c | 158 +++++++++----------------------------- drivers/hid/hid-roccat-konepure.h | 72 ----------------- drivers/hid/hid-roccat-savu.c | 123 ++++------------------------- drivers/hid/hid-roccat-savu.h | 32 -------- 6 files changed, 167 insertions(+), 333 deletions(-) delete mode 100644 drivers/hid/hid-roccat-konepure.h (limited to 'drivers/hid') diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index e84089998900..02e28e9f4ea7 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c @@ -122,6 +122,59 @@ int roccat_common2_send_with_status(struct usb_device *usb_dev, } EXPORT_SYMBOL_GPL(roccat_common2_send_with_status); +int roccat_common2_device_init_struct(struct usb_device *usb_dev, + struct roccat_common2_device *dev) +{ + mutex_init(&dev->lock); + return 0; +} +EXPORT_SYMBOL_GPL(roccat_common2_device_init_struct); + +ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj, + char *buf, loff_t off, size_t count, + size_t real_size, uint command) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval; + + if (off >= real_size) + return 0; + + if (off != 0 || count != real_size) + return -EINVAL; + + mutex_lock(&roccat_dev->lock); + retval = roccat_common2_receive(usb_dev, command, buf, real_size); + mutex_unlock(&roccat_dev->lock); + + return retval ? retval : real_size; +} +EXPORT_SYMBOL_GPL(roccat_common2_sysfs_read); + +ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj, + void const *buf, loff_t off, size_t count, + size_t real_size, uint command) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval; + + if (off != 0 || count != real_size) + return -EINVAL; + + mutex_lock(&roccat_dev->lock); + retval = roccat_common2_send_with_status(usb_dev, command, buf, real_size); + mutex_unlock(&roccat_dev->lock); + + return retval ? retval : real_size; +} +EXPORT_SYMBOL_GPL(roccat_common2_sysfs_write); + MODULE_AUTHOR("Stefan Achatz"); MODULE_DESCRIPTION("USB Roccat common driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h index a97746a63b70..eaa56eb7d5d1 100644 --- a/drivers/hid/hid-roccat-common.h +++ b/drivers/hid/hid-roccat-common.h @@ -32,4 +32,66 @@ int roccat_common2_send(struct usb_device *usb_dev, uint report_id, int roccat_common2_send_with_status(struct usb_device *usb_dev, uint command, void const *buf, uint size); +struct roccat_common2_device { + int roccat_claimed; + int chrdev_minor; + struct mutex lock; +}; + +int roccat_common2_device_init_struct(struct usb_device *usb_dev, + struct roccat_common2_device *dev); +ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj, + char *buf, loff_t off, size_t count, + size_t real_size, uint command); +ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj, + void const *buf, loff_t off, size_t count, + size_t real_size, uint command); + +#define ROCCAT_COMMON2_SYSFS_W(thingy, COMMAND, SIZE) \ +static ssize_t roccat_common2_sysfs_write_ ## thingy(struct file *fp, \ + struct kobject *kobj, struct bin_attribute *attr, char *buf, \ + loff_t off, size_t count) \ +{ \ + return roccat_common2_sysfs_write(fp, kobj, buf, off, count, \ + SIZE, COMMAND); \ +} + +#define ROCCAT_COMMON2_SYSFS_R(thingy, COMMAND, SIZE) \ +static ssize_t roccat_common2_sysfs_read_ ## thingy(struct file *fp, \ + struct kobject *kobj, struct bin_attribute *attr, char *buf, \ + loff_t off, size_t count) \ +{ \ + return roccat_common2_sysfs_read(fp, kobj, buf, off, count, \ + SIZE, COMMAND); \ +} + +#define ROCCAT_COMMON2_SYSFS_RW(thingy, COMMAND, SIZE) \ +ROCCAT_COMMON2_SYSFS_W(thingy, COMMAND, SIZE) \ +ROCCAT_COMMON2_SYSFS_R(thingy, COMMAND, SIZE) + +#define ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(thingy, COMMAND, SIZE) \ +ROCCAT_COMMON2_SYSFS_RW(thingy, COMMAND, SIZE); \ +static struct bin_attribute bin_attr_ ## thingy = { \ + .attr = { .name = #thingy, .mode = 0660 }, \ + .size = SIZE, \ + .read = roccat_common2_sysfs_read_ ## thingy, \ + .write = roccat_common2_sysfs_write_ ## thingy \ +} + +#define ROCCAT_COMMON2_BIN_ATTRIBUTE_R(thingy, COMMAND, SIZE) \ +ROCCAT_COMMON2_SYSFS_R(thingy, COMMAND, SIZE); \ +static struct bin_attribute bin_attr_ ## thingy = { \ + .attr = { .name = #thingy, .mode = 0440 }, \ + .size = SIZE, \ + .read = roccat_common2_sysfs_read_ ## thingy, \ +} + +#define ROCCAT_COMMON2_BIN_ATTRIBUTE_W(thingy, COMMAND, SIZE) \ +ROCCAT_COMMON2_SYSFS_W(thingy, COMMAND, SIZE); \ +static struct bin_attribute bin_attr_ ## thingy = { \ + .attr = { .name = #thingy, .mode = 0220 }, \ + .size = SIZE, \ + .write = roccat_common2_sysfs_write_ ## thingy \ +} + #endif diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c index 99a605ebb665..07de2f9014c6 100644 --- a/drivers/hid/hid-roccat-konepure.c +++ b/drivers/hid/hid-roccat-konepure.c @@ -15,6 +15,7 @@ * Roccat KonePure is a smaller version of KoneXTD with less buttons and lights. */ +#include #include #include #include @@ -23,128 +24,50 @@ #include #include "hid-ids.h" #include "hid-roccat-common.h" -#include "hid-roccat-konepure.h" -static struct class *konepure_class; - -static ssize_t konepure_sysfs_read(struct file *fp, struct kobject *kobj, - char *buf, loff_t off, size_t count, - size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off >= real_size) - return 0; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&konepure->konepure_lock); - retval = roccat_common2_receive(usb_dev, command, buf, real_size); - mutex_unlock(&konepure->konepure_lock); - - return retval ? retval : real_size; -} - -static ssize_t konepure_sysfs_write(struct file *fp, struct kobject *kobj, - void const *buf, loff_t off, size_t count, - size_t real_size, uint command) -{ - struct device *dev = - container_of(kobj, struct device, kobj)->parent->parent; - struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev)); - struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); - int retval; - - if (off != 0 || count != real_size) - return -EINVAL; - - mutex_lock(&konepure->konepure_lock); - retval = roccat_common2_send_with_status(usb_dev, command, - (void *)buf, real_size); - mutex_unlock(&konepure->konepure_lock); - - return retval ? retval : real_size; -} - -#define KONEPURE_SYSFS_W(thingy, THINGY) \ -static ssize_t konepure_sysfs_write_ ## thingy(struct file *fp, \ - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ - loff_t off, size_t count) \ -{ \ - return konepure_sysfs_write(fp, kobj, buf, off, count, \ - KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \ -} - -#define KONEPURE_SYSFS_R(thingy, THINGY) \ -static ssize_t konepure_sysfs_read_ ## thingy(struct file *fp, \ - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ - loff_t off, size_t count) \ -{ \ - return konepure_sysfs_read(fp, kobj, buf, off, count, \ - KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \ -} +enum { + KONEPURE_MOUSE_REPORT_NUMBER_BUTTON = 3, +}; -#define KONEPURE_SYSFS_RW(thingy, THINGY) \ -KONEPURE_SYSFS_W(thingy, THINGY) \ -KONEPURE_SYSFS_R(thingy, THINGY) - -#define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \ -KONEPURE_SYSFS_RW(thingy, THINGY); \ -static struct bin_attribute bin_attr_##thingy = { \ - .attr = { .name = #thingy, .mode = 0660 }, \ - .size = KONEPURE_SIZE_ ## THINGY, \ - .read = konepure_sysfs_read_ ## thingy, \ - .write = konepure_sysfs_write_ ## thingy \ -} +struct konepure_mouse_report_button { + uint8_t report_number; /* always KONEPURE_MOUSE_REPORT_NUMBER_BUTTON */ + uint8_t zero; + uint8_t type; + uint8_t data1; + uint8_t data2; + uint8_t zero2; + uint8_t unknown[2]; +} __packed; -#define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \ -KONEPURE_SYSFS_R(thingy, THINGY); \ -static struct bin_attribute bin_attr_##thingy = { \ - .attr = { .name = #thingy, .mode = 0440 }, \ - .size = KONEPURE_SIZE_ ## THINGY, \ - .read = konepure_sysfs_read_ ## thingy, \ -} - -#define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \ -KONEPURE_SYSFS_W(thingy, THINGY); \ -static struct bin_attribute bin_attr_##thingy = { \ - .attr = { .name = #thingy, .mode = 0220 }, \ - .size = KONEPURE_SIZE_ ## THINGY, \ - .write = konepure_sysfs_write_ ## thingy \ -} +static struct class *konepure_class; -KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE); -KONEPURE_BIN_ATTRIBUTE_RW(info, INFO); -KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR); -KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU); -KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS); -KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS); -KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL); -KONEPURE_BIN_ATTRIBUTE_W(talk, TALK); -KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO); -KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE); - -static struct bin_attribute *konepure_bin_attributes[] = { +ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x04, 0x03); +ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(actual_profile, 0x05, 0x03); +ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile_settings, 0x06, 0x1f); +ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile_buttons, 0x07, 0x3b); +ROCCAT_COMMON2_BIN_ATTRIBUTE_W(macro, 0x08, 0x0822); +ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(info, 0x09, 0x06); +ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(tcu, 0x0c, 0x04); +ROCCAT_COMMON2_BIN_ATTRIBUTE_R(tcu_image, 0x0c, 0x0404); +ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(sensor, 0x0f, 0x06); +ROCCAT_COMMON2_BIN_ATTRIBUTE_W(talk, 0x10, 0x10); + +static struct bin_attribute *konepure_bin_attrs[] = { &bin_attr_actual_profile, + &bin_attr_control, &bin_attr_info, + &bin_attr_talk, + &bin_attr_macro, &bin_attr_sensor, &bin_attr_tcu, + &bin_attr_tcu_image, &bin_attr_profile_settings, &bin_attr_profile_buttons, - &bin_attr_control, - &bin_attr_talk, - &bin_attr_macro, - &bin_attr_tcu_image, NULL, }; static const struct attribute_group konepure_group = { - .bin_attrs = konepure_bin_attributes, + .bin_attrs = konepure_bin_attrs, }; static const struct attribute_group *konepure_groups[] = { @@ -152,20 +75,11 @@ static const struct attribute_group *konepure_groups[] = { NULL, }; - -static int konepure_init_konepure_device_struct(struct usb_device *usb_dev, - struct konepure_device *konepure) -{ - mutex_init(&konepure->konepure_lock); - - return 0; -} - static int konepure_init_specials(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); struct usb_device *usb_dev = interface_to_usbdev(intf); - struct konepure_device *konepure; + struct roccat_common2_device *konepure; int retval; if (intf->cur_altsetting->desc.bInterfaceProtocol @@ -181,9 +95,9 @@ static int konepure_init_specials(struct hid_device *hdev) } hid_set_drvdata(hdev, konepure); - retval = konepure_init_konepure_device_struct(usb_dev, konepure); + retval = roccat_common2_device_init_struct(usb_dev, konepure); if (retval) { - hid_err(hdev, "couldn't init struct konepure_device\n"); + hid_err(hdev, "couldn't init KonePure device\n"); goto exit_free; } @@ -205,7 +119,7 @@ exit_free: static void konepure_remove_specials(struct hid_device *hdev) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct konepure_device *konepure; + struct roccat_common2_device *konepure; if (intf->cur_altsetting->desc.bInterfaceProtocol != USB_INTERFACE_PROTOCOL_MOUSE) @@ -258,7 +172,7 @@ static int konepure_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - struct konepure_device *konepure = hid_ge