diff options
Diffstat (limited to 'drivers/hid/hid-roccat-konepure.c')
| -rw-r--r-- | drivers/hid/hid-roccat-konepure.c | 202 |
1 files changed, 66 insertions, 136 deletions
diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c index c79d0b06c143..027bfc55ef9c 100644 --- a/drivers/hid/hid-roccat-konepure.c +++ b/drivers/hid/hid-roccat-konepure.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Roccat KonePure driver for Linux * @@ -5,16 +6,13 @@ */ /* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. */ /* * Roccat KonePure is a smaller version of KoneXTD with less buttons and lights. */ +#include <linux/types.h> #include <linux/device.h> #include <linux/input.h> #include <linux/hid.h> @@ -23,136 +21,65 @@ #include <linux/hid-roccat.h> #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); \ -} - -#define KONEPURE_SYSFS_RW(thingy, THINGY) \ -KONEPURE_SYSFS_W(thingy, THINGY) \ -KONEPURE_SYSFS_R(thingy, THINGY) - -#define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \ -{ \ - .attr = { .name = #thingy, .mode = 0660 }, \ - .size = KONEPURE_SIZE_ ## THINGY, \ - .read = konepure_sysfs_read_ ## thingy, \ - .write = konepure_sysfs_write_ ## thingy \ -} - -#define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \ -{ \ - .attr = { .name = #thingy, .mode = 0440 }, \ - .size = KONEPURE_SIZE_ ## THINGY, \ - .read = konepure_sysfs_read_ ## thingy, \ -} +enum { + KONEPURE_MOUSE_REPORT_NUMBER_BUTTON = 3, +}; -#define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \ -{ \ - .attr = { .name = #thingy, .mode = 0220 }, \ - .size = KONEPURE_SIZE_ ## 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; + +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 const struct bin_attribute *const 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, + NULL, +}; -KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE) -KONEPURE_SYSFS_W(control, CONTROL) -KONEPURE_SYSFS_RW(info, INFO) -KONEPURE_SYSFS_W(talk, TALK) -KONEPURE_SYSFS_W(macro, MACRO) -KONEPURE_SYSFS_RW(sensor, SENSOR) -KONEPURE_SYSFS_RW(tcu, TCU) -KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE) -KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS) -KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS) - -static struct bin_attribute konepure_bin_attributes[] = { - KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE), - KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL), - KONEPURE_BIN_ATTRIBUTE_RW(info, INFO), - KONEPURE_BIN_ATTRIBUTE_W(talk, TALK), - KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO), - KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR), - KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU), - KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE), - KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), - KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), - __ATTR_NULL +static const struct attribute_group konepure_group = { + .bin_attrs = konepure_bin_attrs, }; -static int konepure_init_konepure_device_struct(struct usb_device *usb_dev, - struct konepure_device *konepure) -{ - mutex_init(&konepure->konepure_lock); +static const struct attribute_group *konepure_groups[] = { + &konepure_group, + NULL, +}; - return 0; -} +static const struct class konepure_class = { + .name = "konepure", + .dev_groups = konepure_groups, +}; 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 @@ -168,14 +95,14 @@ 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; } - retval = roccat_connect(konepure_class, hdev, - sizeof(struct konepure_mouse_report_button)); + retval = roccat_connect(&konepure_class, hdev, + sizeof(struct konepure_mouse_report_button)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -192,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) @@ -209,6 +136,9 @@ static int konepure_probe(struct hid_device *hdev, { int retval; + if (!hid_is_usb(hdev)) + return -EINVAL; + retval = hid_parse(hdev); if (retval) { hid_err(hdev, "parse failed\n"); @@ -245,7 +175,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_get_drvdata(hdev); + struct roccat_common2_device *konepure = hid_get_drvdata(hdev); if (intf->cur_altsetting->desc.bInterfaceProtocol != USB_INTERFACE_PROTOCOL_MOUSE) @@ -262,6 +192,7 @@ static int konepure_raw_event(struct hid_device *hdev, static const struct hid_device_id konepure_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) }, { } }; @@ -279,26 +210,25 @@ static int __init konepure_init(void) { int retval; - konepure_class = class_create(THIS_MODULE, "konepure"); - if (IS_ERR(konepure_class)) - return PTR_ERR(konepure_class); - konepure_class->dev_bin_attrs = konepure_bin_attributes; + retval = class_register(&konepure_class); + if (retval) + return retval; retval = hid_register_driver(&konepure_driver); if (retval) - class_destroy(konepure_class); + class_unregister(&konepure_class); return retval; } static void __exit konepure_exit(void) { hid_unregister_driver(&konepure_driver); - class_destroy(konepure_class); + class_unregister(&konepure_class); } module_init(konepure_init); module_exit(konepure_exit); MODULE_AUTHOR("Stefan Achatz"); -MODULE_DESCRIPTION("USB Roccat KonePure driver"); +MODULE_DESCRIPTION("USB Roccat KonePure/Optical driver"); MODULE_LICENSE("GPL v2"); |
