1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Roccat Kone[+] driver for Linux 4 * 5 * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> 6 */ 7 8 /* 9 */ 10 11 /* 12 * Roccat Kone[+] is an updated/improved version of the Kone with more memory 13 * and functionality and without the non-standard behaviours the Kone had. 14 * KoneXTD has same capabilities but updated sensor. 15 */ 16 17 #include <linux/device.h> 18 #include <linux/input.h> 19 #include <linux/hid.h> 20 #include <linux/module.h> 21 #include <linux/slab.h> 22 #include <linux/hid-roccat.h> 23 #include "hid-ids.h" 24 #include "hid-roccat-common.h" 25 #include "hid-roccat-koneplus.h" 26 27 static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 28 29 static void koneplus_profile_activated(struct koneplus_device *koneplus, 30 uint new_profile) 31 { 32 koneplus->actual_profile = new_profile; 33 } 34 35 static int koneplus_send_control(struct usb_device *usb_dev, uint value, 36 enum koneplus_control_requests request) 37 { 38 struct roccat_common2_control control; 39 40 if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || 41 request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && 42 value > 4) 43 return -EINVAL; 44 45 control.command = ROCCAT_COMMON_COMMAND_CONTROL; 46 control.value = value; 47 control.request = request; 48 49 return roccat_common2_send_with_status(usb_dev, 50 ROCCAT_COMMON_COMMAND_CONTROL, 51 &control, sizeof(struct roccat_common2_control)); 52 } 53 54 55 /* retval is 0-4 on success, < 0 on error */ 56 static int koneplus_get_actual_profile(struct usb_device *usb_dev) 57 { 58 struct koneplus_actual_profile buf; 59 int retval; 60 61 retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, 62 &buf, KONEPLUS_SIZE_ACTUAL_PROFILE); 63 64 return retval ? retval : buf.actual_profile; 65 } 66 67 static int koneplus_set_actual_profile(struct usb_device *usb_dev, 68 int new_profile) 69 { 70 struct koneplus_actual_profile buf; 71 72 buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE; 73 buf.size = KONEPLUS_SIZE_ACTUAL_PROFILE; 74 buf.actual_profile = new_profile; 75 76 return roccat_common2_send_with_status(usb_dev, 77 KONEPLUS_COMMAND_ACTUAL_PROFILE, 78 &buf, KONEPLUS_SIZE_ACTUAL_PROFILE); 79 } 80 81 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, 82 char *buf, loff_t off, size_t count, 83 size_t real_size, uint command) 84 { 85 struct device *dev = kobj_to_dev(kobj)->parent->parent; 86 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 87 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 88 int retval; 89 90 if (off >= real_size) 91 return 0; 92 93 if (off != 0 || count != real_size) 94 return -EINVAL; 95 96 mutex_lock(&koneplus->koneplus_lock); 97 retval = roccat_common2_receive(usb_dev, command, buf, real_size); 98 mutex_unlock(&koneplus->koneplus_lock); 99 100 if (retval) 101 return retval; 102 103 return real_size; 104 } 105 106 static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, 107 void const *buf, loff_t off, size_t count, 108 size_t real_size, uint command) 109 { 110 struct device *dev = kobj_to_dev(kobj)->parent->parent; 111 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 112 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 113 int retval; 114 115 if (off != 0 || count != real_size) 116 return -EINVAL; 117 118 mutex_lock(&koneplus->koneplus_lock); 119 retval = roccat_common2_send_with_status(usb_dev, command, 120 buf, real_size); 121 mutex_unlock(&koneplus->koneplus_lock); 122 123 if (retval) 124 return retval; 125 126 return real_size; 127 } 128 129 #define KONEPLUS_SYSFS_W(thingy, THINGY) \ 130 static ssize_t koneplus_sysfs_write_ ## thingy(struct file *fp, \ 131 struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 132 loff_t off, size_t count) \ 133 { \ 134 return koneplus_sysfs_write(fp, kobj, buf, off, count, \ 135 KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \ 136 } 137 138 #define KONEPLUS_SYSFS_R(thingy, THINGY) \ 139 static ssize_t koneplus_sysfs_read_ ## thingy(struct file *fp, \ 140 struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 141 loff_t off, size_t count) \ 142 { \ 143 return koneplus_sysfs_read(fp, kobj, buf, off, count, \ 144 KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \ 145 } 146 147 #define KONEPLUS_SYSFS_RW(thingy, THINGY) \ 148 KONEPLUS_SYSFS_W(thingy, THINGY) \ 149 KONEPLUS_SYSFS_R(thingy, THINGY) 150 151 #define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 152 KONEPLUS_SYSFS_RW(thingy, THINGY); \ 153 static struct bin_attribute bin_attr_##thingy = { \ 154 .attr = { .name = #thingy, .mode = 0660 }, \ 155 .size = KONEPLUS_SIZE_ ## THINGY, \ 156 .read = koneplus_sysfs_read_ ## thingy, \ 157 .write = koneplus_sysfs_write_ ## thingy \ 158 } 159 160 #define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \ 161 KONEPLUS_SYSFS_R(thingy, THINGY); \ 162 static struct bin_attribute bin_attr_##thingy = { \ 163 .attr = { .name = #thingy, .mode = 0440 }, \ 164 .size = KONEPLUS_SIZE_ ## THINGY, \ 165 .read = koneplus_sysfs_read_ ## thingy, \ 166 } 167 168 #define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \ 169 KONEPLUS_SYSFS_W(thingy, THINGY); \ 170 static struct bin_attribute bin_attr_##thingy = { \ 171 .attr = { .name = #thingy, .mode = 0220 }, \ 172 .size = KONEPLUS_SIZE_ ## THINGY, \ 173 .write = koneplus_sysfs_write_ ## thingy \ 174 } 175 KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL); 176 KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK); 177 KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO); 178 KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE); 179 KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO); 180 KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR); 181 KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU); 182 KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS); 183 KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS); 184 185 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, 186 struct kobject *kobj, struct bin_attribute *attr, char *buf, 187 loff_t off, size_t count) 188 { 189 struct device *dev = kobj_to_dev(kobj)->parent->parent; 190 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 191 ssize_t retval; 192 193 retval = koneplus_send_control(usb_dev, *(uint *)(attr->private), 194 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); 195 if (retval) 196 return retval; 197 198 return koneplus_sysfs_read(fp, kobj, buf, off, count, 199 KONEPLUS_SIZE_PROFILE_SETTINGS, 200 KONEPLUS_COMMAND_PROFILE_SETTINGS); 201 } 202 203 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, 204 struct kobject *kobj, struct bin_attribute *attr, char *buf, 205 loff_t off, size_t count) 206 { 207 struct device *dev = kobj_to_dev(kobj)->parent->parent; 208 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 209 ssize_t retval; 210 211 retval = koneplus_send_control(usb_dev, *(uint *)(attr->private), 212 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); 213 if (retval) 214 return retval; 215 216 return koneplus_sysfs_read(fp, kobj, buf, off, count, 217 KONEPLUS_SIZE_PROFILE_BUTTONS, 218 KONEPLUS_COMMAND_PROFILE_BUTTONS); 219 } 220 221 #define PROFILE_ATTR(number) \ 222 static struct bin_attribute bin_attr_profile##number##_settings = { \ 223 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 224 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \ 225 .read = koneplus_sysfs_read_profilex_settings, \ 226 .private = &profile_numbers[number-1], \ 227 }; \ 228 static struct bin_attribute bin_attr_profile##number##_buttons = { \ 229 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 230 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \ 231 .read = koneplus_sysfs_read_profilex_buttons, \ 232 .private = &profile_numbers[number-1], \ 233 }; 234 PROFILE_ATTR(1); 235 PROFILE_ATTR(2); 236 PROFILE_ATTR(3); 237 PROFILE_ATTR(4); 238 PROFILE_ATTR(5); 239 240 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, 241 struct device_attribute *attr, char *buf) 242 { 243 struct koneplus_device *koneplus = 244 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 245 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); 246 } 247 248 static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, 249 struct device_attribute *attr, char const *buf, size_t size) 250 { 251 struct koneplus_device *koneplus; 252 struct usb_device *usb_dev; 253 unsigned long profile; 254 int retval; 255 struct koneplus_roccat_report roccat_report; 256 257 dev = dev->parent->parent; 258 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 259 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 260 261 retval = kstrtoul(buf, 10, &profile); 262 if (retval) 263 return retval; 264 265 if (profile > 4) 266 return -EINVAL; 267 268 mutex_lock(&koneplus->koneplus_lock); 269 270 retval = koneplus_set_actual_profile(usb_dev, profile); 271 if (retval) { 272 mutex_unlock(&koneplus->koneplus_lock); 273 return retval; 274 } 275 276 koneplus_profile_activated(koneplus, profile); 277 278 roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; 279 roccat_report.data1 = profile + 1; 280 roccat_report.data2 = 0; 281 roccat_report.profile = profile + 1; 282 roccat_report_event(koneplus->chrdev_minor, 283 (uint8_t const *)&roccat_report); 284 285 mutex_unlock(&koneplus->koneplus_lock); 286 287 return size; 288 } 289 static DEVICE_ATTR(actual_profile, 0660, 290 koneplus_sysfs_show_actual_profile, 291 koneplus_sysfs_set_actual_profile); 292 static DEVICE_ATTR(startup_profile, 0660, 293 koneplus_sysfs_show_actual_profile, 294 koneplus_sysfs_set_actual_profile); 295 296 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, 297 struct device_attribute *attr, char *buf) 298 { 299 struct koneplus_device *koneplus; 300 struct usb_device *usb_dev; 301 struct koneplus_info info; 302 303 dev = dev->parent->parent; 304 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 305 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 306 307 mutex_lock(&koneplus->koneplus_lock); 308 roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO, 309 &info, KONEPLUS_SIZE_INFO); 310 mutex_unlock(&koneplus->koneplus_lock); 311 312 return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version); 313 } 314 static DEVICE_ATTR(firmware_version, 0440, 315 koneplus_sysfs_show_firmware_version, NULL); 316 317 static struct attribute *koneplus_attrs[] = { 318 &dev_attr_actual_profile.attr, 319 &dev_attr_startup_profile.attr, 320 &dev_attr_firmware_version.attr, 321 NULL, 322 }; 323 324 static struct bin_attribute *koneplus_bin_attributes[] = { 325 &bin_attr_control, 326 &bin_attr_talk, 327 &bin_attr_macro, 328 &bin_attr_tcu_image, 329 &bin_attr_info, 330 &bin_attr_sensor, 331 &bin_attr_tcu, 332 &bin_attr_profile_settings, 333 &bin_attr_profile_buttons, 334 &bin_attr_profile1_settings, 335 &bin_attr_profile2_settings, 336 &bin_attr_profile3_settings, 337 &bin_attr_profile4_settings, 338 &bin_attr_profile5_settings, 339 &bin_attr_profile1_buttons, 340 &bin_attr_profile2_buttons, 341 &bin_attr_profile3_buttons, 342 &bin_attr_profile4_buttons, 343 &bin_attr_profile5_buttons, 344 NULL, 345 }; 346 347 static const struct attribute_group koneplus_group = { 348 .attrs = koneplus_attrs, 349 .bin_attrs = koneplus_bin_attributes, 350 }; 351 352 static const struct attribute_group *koneplus_groups[] = { 353 &koneplus_group, 354 NULL, 355 }; 356 357 static const struct class koneplus_class = { 358 .name = "koneplus", 359 .dev_groups = koneplus_groups, 360 }; 361 362 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, 363 struct koneplus_device *koneplus) 364 { 365 int retval; 366 367 mutex_init(&koneplus->koneplus_lock); 368 369 retval = koneplus_get_actual_profile(usb_dev); 370 if (retval < 0) 371 return retval; 372 koneplus_profile_activated(koneplus, retval); 373 374 return 0; 375 } 376 377 static int koneplus_init_specials(struct hid_device *hdev) 378 { 379 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 380 struct usb_device *usb_dev = interface_to_usbdev(intf); 381 struct koneplus_device *koneplus; 382 int retval; 383 384 if (intf->cur_altsetting->desc.bInterfaceProtocol 385 == USB_INTERFACE_PROTOCOL_MOUSE) { 386 387 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); 388 if (!koneplus) { 389 hid_err(hdev, "can't alloc device descriptor\n"); 390 return -ENOMEM; 391 } 392 hid_set_drvdata(hdev, koneplus); 393 394 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); 395 if (retval) { 396 hid_err(hdev, "couldn't init struct koneplus_device\n"); 397 goto exit_free; 398 } 399 400 retval = roccat_connect(&koneplus_class, hdev, 401 sizeof(struct koneplus_roccat_report)); 402 if (retval < 0) { 403 hid_err(hdev, "couldn't init char dev\n"); 404 } else { 405 koneplus->chrdev_minor = retval; 406 koneplus->roccat_claimed = 1; 407 } 408 } else { 409 hid_set_drvdata(hdev, NULL); 410 } 411 412 return 0; 413 exit_free: 414 kfree(koneplus); 415 return retval; 416 } 417 418 static void koneplus_remove_specials(struct hid_device *hdev) 419 { 420 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 421 struct koneplus_device *koneplus; 422 423 if (intf->cur_altsetting->desc.bInterfaceProtocol 424 == USB_INTERFACE_PROTOCOL_MOUSE) { 425 koneplus = hid_get_drvdata(hdev); 426 if (koneplus->roccat_claimed) 427 roccat_disconnect(koneplus->chrdev_minor); 428 kfree(koneplus); 429 } 430 } 431 432 static int koneplus_probe(struct hid_device *hdev, 433 const struct hid_device_id *id) 434 { 435 int retval; 436 437 if (!hid_is_usb(hdev)) 438 return -EINVAL; 439 440 retval = hid_parse(hdev); 441 if (retval) { 442 hid_err(hdev, "parse failed\n"); 443 goto exit; 444 } 445 446 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 447 if (retval) { 448 hid_err(hdev, "hw start failed\n"); 449 goto exit; 450 } 451 452 retval = koneplus_init_specials(hdev); 453 if (retval) { 454 hid_err(hdev, "couldn't install mouse\n"); 455 goto exit_stop; 456 } 457 458 return 0; 459 460 exit_stop: 461 hid_hw_stop(hdev); 462 exit: 463 return retval; 464 } 465 466 static void koneplus_remove(struct hid_device *hdev) 467 { 468 koneplus_remove_specials(hdev); 469 hid_hw_stop(hdev); 470 } 471 472 static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, 473 u8 const *data) 474 { 475 struct koneplus_mouse_report_button const *button_report; 476 477 switch (data[0]) { 478 case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: 479 button_report = (struct koneplus_mouse_report_button const *)data; 480 switch (button_report->type) { 481 case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: 482 koneplus_profile_activated(koneplus, button_report->data1 - 1); 483 break; 484 } 485 break; 486 } 487 } 488 489 static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, 490 u8 const *data) 491 { 492 struct koneplus_roccat_report roccat_report; 493 struct koneplus_mouse_report_button const *button_report; 494 495 if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) 496 return; 497 498 button_report = (struct koneplus_mouse_report_button const *)data; 499 500 if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || 501 button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && 502 button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) 503 return; 504 505 roccat_report.type = button_report->type; 506 roccat_report.data1 = button_report->data1; 507 roccat_report.data2 = button_report->data2; 508 roccat_report.profile = koneplus->actual_profile + 1; 509 roccat_report_event(koneplus->chrdev_minor, 510 (uint8_t const *)&roccat_report); 511 } 512 513 static int koneplus_raw_event(struct hid_device *hdev, 514 struct hid_report *report, u8 *data, int size) 515 { 516 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 517 struct koneplus_device *koneplus = hid_get_drvdata(hdev); 518 519 if (intf->cur_altsetting->desc.bInterfaceProtocol 520 != USB_INTERFACE_PROTOCOL_MOUSE) 521 return 0; 522 523 if (koneplus == NULL) 524 return 0; 525 526 koneplus_keep_values_up_to_date(koneplus, data); 527 528 if (koneplus->roccat_claimed) 529 koneplus_report_to_chrdev(koneplus, data); 530 531 return 0; 532 } 533 534 static const struct hid_device_id koneplus_devices[] = { 535 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 536 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) }, 537 { } 538 }; 539 540 MODULE_DEVICE_TABLE(hid, koneplus_devices); 541 542 static struct hid_driver koneplus_driver = { 543 .name = "koneplus", 544 .id_table = koneplus_devices, 545 .probe = koneplus_probe, 546 .remove = koneplus_remove, 547 .raw_event = koneplus_raw_event 548 }; 549 550 static int __init koneplus_init(void) 551 { 552 int retval; 553 554 /* class name has to be same as driver name */ 555 retval = class_register(&koneplus_class); 556 if (retval) 557 return retval; 558 559 retval = hid_register_driver(&koneplus_driver); 560 if (retval) 561 class_unregister(&koneplus_class); 562 return retval; 563 } 564 565 static void __exit koneplus_exit(void) 566 { 567 hid_unregister_driver(&koneplus_driver); 568 class_unregister(&koneplus_class); 569 } 570 571 module_init(koneplus_init); 572 module_exit(koneplus_exit); 573 574 MODULE_AUTHOR("Stefan Achatz"); 575 MODULE_DESCRIPTION("USB Roccat Kone[+]/XTD driver"); 576 MODULE_LICENSE("GPL v2"); 577