aboutsummaryrefslogtreecommitdiff
path: root/drivers/hid/hid-roccat-kone.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-roccat-kone.c')
-rw-r--r--drivers/hid/hid-roccat-kone.c236
1 files changed, 144 insertions, 92 deletions
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index a57838d1526..6101816a7dd 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -37,6 +37,60 @@
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+static void kone_profile_activated(struct kone_device *kone, uint new_profile)
+{
+ kone->actual_profile = new_profile;
+ kone->actual_dpi = kone->profiles[new_profile - 1].startup_dpi;
+}
+
+static void kone_profile_report(struct kone_device *kone, uint new_profile)
+{
+ struct kone_roccat_report roccat_report;
+ roccat_report.event = kone_mouse_event_switch_profile;
+ roccat_report.value = new_profile;
+ roccat_report.key = 0;
+ roccat_report_event(kone->chrdev_minor, (uint8_t *)&roccat_report);
+}
+
+static int kone_receive(struct usb_device *usb_dev, uint usb_command,
+ void *data, uint size)
+{
+ char *buf;
+ int len;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+ usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+ memcpy(data, buf, size);
+ kfree(buf);
+ return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+
+static int kone_send(struct usb_device *usb_dev, uint usb_command,
+ void const *data, uint size)
+{
+ char *buf;
+ int len;
+
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+ HID_REQ_SET_REPORT,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+ kfree(buf);
+ return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+
/* kone_class is used for creating sysfs attributes via roccat char device */
static struct class *kone_class;
@@ -68,7 +122,7 @@ static int kone_check_write(struct usb_device *usb_dev)
*/
msleep(80);
- retval = roccat_common_receive(usb_dev,
+ retval = kone_receive(usb_dev,
kone_command_confirm_write, &data, 1);
if (retval)
return retval;
@@ -84,7 +138,7 @@ static int kone_check_write(struct usb_device *usb_dev)
return 0;
/* unknown answer */
- hid_err(usb_dev, "got retval %d when checking write\n", data);
+ dev_err(&usb_dev->dev, "got retval %d when checking write\n", data);
return -EIO;
}
@@ -96,7 +150,7 @@ static int kone_check_write(struct usb_device *usb_dev)
static int kone_get_settings(struct usb_device *usb_dev,
struct kone_settings *buf)
{
- return roccat_common_receive(usb_dev, kone_command_settings, buf,
+ return kone_receive(usb_dev, kone_command_settings, buf,
sizeof(struct kone_settings));
}
@@ -109,7 +163,7 @@ static int kone_set_settings(struct usb_device *usb_dev,
struct kone_settings const *settings)
{
int retval;
- retval = roccat_common_send(usb_dev, kone_command_settings,
+ retval = kone_send(usb_dev, kone_command_settings,
settings, sizeof(struct kone_settings));
if (retval)
return retval;
@@ -182,7 +236,7 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result)
int retval;
uint8_t data;
- retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
+ retval = kone_receive(usb_dev, kone_command_weight, &data, 1);
if (retval)
return retval;
@@ -201,7 +255,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
int retval;
uint16_t data;
- retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
+ retval = kone_receive(usb_dev, kone_command_firmware_version,
&data, 2);
if (retval)
return retval;
@@ -242,7 +296,7 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
container_of(kobj, struct device, kobj)->parent->parent;
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
- int retval = 0, difference;
+ int retval = 0, difference, old_profile;
/* I need to get my data in one piece */
if (off != 0 || count != sizeof(struct kone_settings))
@@ -253,24 +307,25 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
if (difference) {
retval = kone_set_settings(usb_dev,
(struct kone_settings const *)buf);
- if (!retval)
- memcpy(&kone->settings, buf,
- sizeof(struct kone_settings));
- }
- mutex_unlock(&kone->kone_lock);
+ if (retval) {
+ mutex_unlock(&kone->kone_lock);
+ return retval;
+ }
- if (retval)
- return retval;
+ old_profile = kone->settings.startup_profile;
+ memcpy(&kone->settings, buf, sizeof(struct kone_settings));
- /*
- * If we get here, treat settings as okay and update actual values
- * according to startup_profile
- */
- kone->actual_profile = kone->settings.startup_profile;
- kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+ kone_profile_activated(kone, kone->settings.startup_profile);
+
+ if (kone->settings.startup_profile != old_profile)
+ kone_profile_report(kone, kone->settings.startup_profile);
+ }
+ mutex_unlock(&kone->kone_lock);
return sizeof(struct kone_settings);
}
+static BIN_ATTR(settings, 0660, kone_sysfs_read_settings,
+ kone_sysfs_write_settings, sizeof(struct kone_settings));
static ssize_t kone_sysfs_read_profilex(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr,
@@ -325,6 +380,19 @@ static ssize_t kone_sysfs_write_profilex(struct file *fp,
return sizeof(struct kone_profile);
}
+#define PROFILE_ATTR(number) \
+static struct bin_attribute bin_attr_profile##number = { \
+ .attr = { .name = "profile" #number, .mode = 0660 }, \
+ .size = sizeof(struct kone_profile), \
+ .read = kone_sysfs_read_profilex, \
+ .write = kone_sysfs_write_profilex, \
+ .private = &profile_numbers[number-1], \
+};
+PROFILE_ATTR(1);
+PROFILE_ATTR(2);
+PROFILE_ATTR(3);
+PROFILE_ATTR(4);
+PROFILE_ATTR(5);
static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -333,6 +401,7 @@ static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
}
+static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -341,6 +410,7 @@ static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
}
+static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
/* weight is read each time, since we don't get informed when it's changed */
static ssize_t kone_sysfs_show_weight(struct device *dev,
@@ -363,6 +433,7 @@ static ssize_t kone_sysfs_show_weight(struct device *dev,
return retval;
return snprintf(buf, PAGE_SIZE, "%d\n", weight);
}
+static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -371,6 +442,8 @@ static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
}
+static DEVICE_ATTR(firmware_version, 0440, kone_sysfs_show_firmware_version,
+ NULL);
static ssize_t kone_sysfs_show_tcu(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -384,7 +457,7 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number)
{
unsigned char value;
value = number;
- return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
+ return kone_send(usb_dev, kone_command_calibrate, &value, 1);
}
/*
@@ -403,7 +476,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
kone = hid_get_drvdata(dev_get_drvdata(dev));
usb_dev = interface_to_usbdev(to_usb_interface(dev));
- retval = strict_strtoul(buf, 10, &state);
+ retval = kstrtoul(buf, 10, &state);
if (retval)
return retval;
@@ -450,7 +523,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
retval = kone_set_settings(usb_dev, &kone->settings);
if (retval) {
- hid_err(usb_dev, "couldn't set tcu state\n");
+ dev_err(&usb_dev->dev, "couldn't set tcu state\n");
/*
* try to reread valid settings into buffer overwriting
* first error code
@@ -460,15 +533,18 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
goto exit_no_settings;
goto exit_unlock;
}
+ /* calibration resets profile */
+ kone_profile_activated(kone, kone->settings.startup_profile);
}
retval = size;
exit_no_settings:
- hid_err(usb_dev, "couldn't read settings\n");
+ dev_err(&usb_dev->dev, "couldn't read settings\n");
exit_unlock:
mutex_unlock(&kone->kone_lock);
return retval;
}
+static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -490,7 +566,7 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
kone = hid_get_drvdata(dev_get_drvdata(dev));
usb_dev = interface_to_usbdev(to_usb_interface(dev));
- retval = strict_strtoul(buf, 10, &new_startup_profile);
+ retval = kstrtoul(buf, 10, &new_startup_profile);
if (retval)
return retval;
@@ -503,27 +579,29 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
kone_set_settings_checksum(&kone->settings);
retval = kone_set_settings(usb_dev, &kone->settings);
-
- mutex_unlock(&kone->kone_lock);
-
- if (retval)
+ if (retval) {
+ mutex_unlock(&kone->kone_lock);
return retval;
+ }
/* changing the startup profile immediately activates this profile */
- kone->actual_profile = new_startup_profile;
- kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
+ kone_profile_activated(kone, new_startup_profile);
+ kone_profile_report(kone, new_startup_profile);
+ mutex_unlock(&kone->kone_lock);
return size;
}
+static DEVICE_ATTR(startup_profile, 0660, kone_sysfs_show_startup_profile,
+ kone_sysfs_set_startup_profile);
-static struct device_attribute kone_attributes[] = {
+static struct attribute *kone_attrs[] = {
/*
* Read actual dpi settings.
* Returns raw value for further processing. Refer to enum
* kone_polling_rates to get real value.
*/
- __ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL),
- __ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL),
+ &dev_attr_actual_dpi.attr,
+ &dev_attr_actual_profile.attr,
/*
* The mouse can be equipped with one of four supplied weights from 5
@@ -532,7 +610,7 @@ static struct device_attribute kone_attributes[] = {
* by software. Refer to enum kone_weights to get corresponding real
* weight.
*/
- __ATTR(weight, 0440, kone_sysfs_show_weight, NULL),
+ &dev_attr_weight.attr,
/*
* Prints firmware version stored in mouse as integer.
@@ -540,66 +618,38 @@ static struct device_attribute kone_attributes[] = {
* to get the real version number the decimal point has to be shifted 2
* positions to the left. E.g. a value of 138 means 1.38.
*/
- __ATTR(firmware_version, 0440,
- kone_sysfs_show_firmware_version, NULL),
+ &dev_attr_firmware_version.attr,
/*
* Prints state of Tracking Control Unit as number where 0 = off and
* 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and
* activates the tcu
*/
- __ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu),
+ &dev_attr_tcu.attr,
/* Prints and takes the number of the profile the mouse starts with */
- __ATTR(startup_profile, 0660,
- kone_sysfs_show_startup_profile,
- kone_sysfs_set_startup_profile),
- __ATTR_NULL
+ &dev_attr_startup_profile.attr,
+ NULL,
+};
+
+static struct bin_attribute *kone_bin_attributes[] = {
+ &bin_attr_settings,
+ &bin_attr_profile1,
+ &bin_attr_profile2,
+ &bin_attr_profile3,
+ &bin_attr_profile4,
+ &bin_attr_profile5,
+ NULL,
};
-static struct bin_attribute kone_bin_attributes[] = {
- {
- .attr = { .name = "settings", .mode = 0660 },
- .size = sizeof(struct kone_settings),
- .read = kone_sysfs_read_settings,
- .write = kone_sysfs_write_settings
- },
- {
- .attr = { .name = "profile1", .mode = 0660 },
- .size = sizeof(struct kone_profile),
- .read = kone_sysfs_read_profilex,
- .write = kone_sysfs_write_profilex,
- .private = &profile_numbers[0]
- },
- {
- .attr = { .name = "profile2", .mode = 0660 },
- .size = sizeof(struct kone_profile),
- .read = kone_sysfs_read_profilex,
- .write = kone_sysfs_write_profilex,
- .private = &profile_numbers[1]
- },
- {
- .attr = { .name = "profile3", .mode = 0660 },
- .size = sizeof(struct kone_profile),
- .read = kone_sysfs_read_profilex,
- .write = kone_sysfs_write_profilex,
- .private = &profile_numbers[2]
- },
- {
- .attr = { .name = "profile4", .mode = 0660 },
- .size = sizeof(struct kone_profile),
- .read = kone_sysfs_read_profilex,
- .write = kone_sysfs_write_profilex,
- .private = &profile_numbers[3]
- },
- {
- .attr = { .name = "profile5", .mode = 0660 },
- .size = sizeof(struct kone_profile),
- .read = kone_sysfs_read_profilex,
- .write = kone_sysfs_write_profilex,
- .private = &profile_numbers[4]
- },
- __ATTR_NULL
+static const struct attribute_group kone_group = {
+ .attrs = kone_attrs,
+ .bin_attrs = kone_bin_attributes,
+};
+
+static const struct attribute_group *kone_groups[] = {
+ &kone_group,
+ NULL,
};
static int kone_init_kone_device_struct(struct usb_device *usb_dev,
@@ -624,8 +674,7 @@ static int kone_init_kone_device_struct(struct usb_device *usb_dev,
if (retval)
return retval;
- kone->actual_profile = kone->settings.startup_profile;
- kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
+ kone_profile_activated(kone, kone->settings.startup_profile);
return 0;
}
@@ -735,10 +784,10 @@ static void kone_keep_values_up_to_date(struct kone_device *kone,
{
switch (event->event) {
case kone_mouse_event_switch_profile:
+ kone->actual_dpi = kone->profiles[event->value - 1].
+ startup_dpi;
case kone_mouse_event_osd_profile:
kone->actual_profile = event->value;
- kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
- startup_dpi;
break;
case kone_mouse_event_switch_dpi:
case kone_mouse_event_osd_dpi:
@@ -764,8 +813,9 @@ static void kone_report_to_chrdev(struct kone_device const *kone,
(uint8_t *)&roccat_report);
break;
case kone_mouse_event_call_overlong_macro:
+ case kone_mouse_event_multimedia:
if (event->value == kone_keystroke_action_press) {
- roccat_report.event = kone_mouse_event_call_overlong_macro;
+ roccat_report.event = event->event;
roccat_report.value = kone->actual_profile;
roccat_report.key = event->macro_key;
roccat_report_event(kone->chrdev_minor,
@@ -791,6 +841,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
if (size != sizeof(struct kone_mouse_event))
return 0;
+ if (kone == NULL)
+ return 0;
+
/*
* Firmware 1.38 introduced new behaviour for tilt and special buttons.
* Pressed button is reported in each movement event.
@@ -833,8 +886,7 @@ static int __init kone_init(void)
kone_class = class_create(THIS_MODULE, "kone");
if (IS_ERR(kone_class))
return PTR_ERR(kone_class);
- kone_class->dev_attrs = kone_attributes;
- kone_class->dev_bin_attrs = kone_bin_attributes;
+ kone_class->dev_groups = kone_groups;
retval = hid_register_driver(&kone_driver);
if (retval)