diff options
Diffstat (limited to 'drivers/hid/hid-roccat-kone.c')
| -rw-r--r-- | drivers/hid/hid-roccat-kone.c | 236 |
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) |
