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