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 30 static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 31 32 static struct class *koneplus_class; 33 34 static void koneplus_profile_activated(struct koneplus_device *koneplus, 35 uint new_profile) 36 { 37 koneplus->actual_profile = new_profile; 38 } 39 40 static 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 */ 61 static 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 72 static 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 86 static 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 112 static 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) \ 137 static 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) \ 146 static 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) \ 155 KONEPLUS_SYSFS_W(thingy, THINGY) \ 156 KONEPLUS_SYSFS_R(thingy, THINGY) 157 158 #define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 159 { \ 160 .attr = { .name = #thingy, .mode = 0660 }, \ 161 .size = KONEPLUS_SIZE_ ## THINGY, \ 162 .read = koneplus_sysfs_read_ ## thingy, \ 163 .write = koneplus_sysfs_write_ ## thingy \ 164 } 165 166 #define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \ 167 { \ 168 .attr = { .name = #thingy, .mode = 0440 }, \ 169 .size = KONEPLUS_SIZE_ ## THINGY, \ 170 .read = koneplus_sysfs_read_ ## thingy, \ 171 } 172 173 #define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \ 174 { \ 175 .attr = { .name = #thingy, .mode = 0220 }, \ 176 .size = KONEPLUS_SIZE_ ## THINGY, \ 177 .write = koneplus_sysfs_write_ ## thingy \ 178 } 179 180 KONEPLUS_SYSFS_W(control, CONTROL) 181 KONEPLUS_SYSFS_RW(info, INFO) 182 KONEPLUS_SYSFS_W(talk, TALK) 183 KONEPLUS_SYSFS_W(macro, MACRO) 184 KONEPLUS_SYSFS_RW(sensor, SENSOR) 185 KONEPLUS_SYSFS_RW(tcu, TCU) 186 KONEPLUS_SYSFS_R(tcu_image, TCU_IMAGE) 187 KONEPLUS_SYSFS_RW(profile_settings, PROFILE_SETTINGS) 188 KONEPLUS_SYSFS_RW(profile_buttons, PROFILE_BUTTONS) 189 190 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, 191 struct kobject *kobj, struct bin_attribute *attr, char *buf, 192 loff_t off, size_t count) 193 { 194 struct device *dev = 195 container_of(kobj, struct device, kobj)->parent->parent; 196 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 197 ssize_t retval; 198 199 retval = koneplus_send_control(usb_dev, *(uint *)(attr->private), 200 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); 201 if (retval) 202 return retval; 203 204 return koneplus_sysfs_read(fp, kobj, buf, off, count, 205 KONEPLUS_SIZE_PROFILE_SETTINGS, 206 KONEPLUS_COMMAND_PROFILE_SETTINGS); 207 } 208 209 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, 210 struct kobject *kobj, struct bin_attribute *attr, char *buf, 211 loff_t off, size_t count) 212 { 213 struct device *dev = 214 container_of(kobj, struct device, kobj)->parent->parent; 215 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 216 ssize_t retval; 217 218 retval = koneplus_send_control(usb_dev, *(uint *)(attr->private), 219 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); 220 if (retval) 221 return retval; 222 223 return koneplus_sysfs_read(fp, kobj, buf, off, count, 224 KONEPLUS_SIZE_PROFILE_BUTTONS, 225 KONEPLUS_COMMAND_PROFILE_BUTTONS); 226 } 227 228 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, 229 struct device_attribute *attr, char *buf) 230 { 231 struct koneplus_device *koneplus = 232 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 233 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); 234 } 235 236 static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, 237 struct device_attribute *attr, char const *buf, size_t size) 238 { 239 struct koneplus_device *koneplus; 240 struct usb_device *usb_dev; 241 unsigned long profile; 242 int retval; 243 struct koneplus_roccat_report roccat_report; 244 245 dev = dev->parent->parent; 246 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 247 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 248 249 retval = strict_strtoul(buf, 10, &profile); 250 if (retval) 251 return retval; 252 253 if (profile > 4) 254 return -EINVAL; 255 256 mutex_lock(&koneplus->koneplus_lock); 257 258 retval = koneplus_set_actual_profile(usb_dev, profile); 259 if (retval) { 260 mutex_unlock(&koneplus->koneplus_lock); 261 return retval; 262 } 263 264 koneplus_profile_activated(koneplus, profile); 265 266 roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; 267 roccat_report.data1 = profile + 1; 268 roccat_report.data2 = 0; 269 roccat_report.profile = profile + 1; 270 roccat_report_event(koneplus->chrdev_minor, 271 (uint8_t const *)&roccat_report); 272 273 mutex_unlock(&koneplus->koneplus_lock); 274 275 return size; 276 } 277 278 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, 279 struct device_attribute *attr, char *buf) 280 { 281 struct koneplus_device *koneplus; 282 struct usb_device *usb_dev; 283 struct koneplus_info info; 284 285 dev = dev->parent->parent; 286 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 287 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 288 289 mutex_lock(&koneplus->koneplus_lock); 290 roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO, 291 &info, KONEPLUS_SIZE_INFO); 292 mutex_unlock(&koneplus->koneplus_lock); 293 294 return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version); 295 } 296 297 static struct device_attribute koneplus_attributes[] = { 298 __ATTR(actual_profile, 0660, 299 koneplus_sysfs_show_actual_profile, 300 koneplus_sysfs_set_actual_profile), 301 __ATTR(startup_profile, 0660, 302 koneplus_sysfs_show_actual_profile, 303 koneplus_sysfs_set_actual_profile), 304 __ATTR(firmware_version, 0440, 305 koneplus_sysfs_show_firmware_version, NULL), 306 __ATTR_NULL 307 }; 308 309 static struct bin_attribute koneplus_bin_attributes[] = { 310 KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL), 311 KONEPLUS_BIN_ATTRIBUTE_RW(info, INFO), 312 KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK), 313 KONEPLUS_BIN_ATTRIBUTE_W(macro, MACRO), 314 KONEPLUS_BIN_ATTRIBUTE_RW(sensor, SENSOR), 315 KONEPLUS_BIN_ATTRIBUTE_RW(tcu, TCU), 316 KONEPLUS_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE), 317 KONEPLUS_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), 318 KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), 319 { 320 .attr = { .name = "profile1_settings", .mode = 0440 }, 321 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, 322 .read = koneplus_sysfs_read_profilex_settings, 323 .private = &profile_numbers[0] 324 }, 325 { 326 .attr = { .name = "profile2_settings", .mode = 0440 }, 327 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, 328 .read = koneplus_sysfs_read_profilex_settings, 329 .private = &profile_numbers[1] 330 }, 331 { 332 .attr = { .name = "profile3_settings", .mode = 0440 }, 333 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, 334 .read = koneplus_sysfs_read_profilex_settings, 335 .private = &profile_numbers[2] 336 }, 337 { 338 .attr = { .name = "profile4_settings", .mode = 0440 }, 339 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, 340 .read = koneplus_sysfs_read_profilex_settings, 341 .private = &profile_numbers[3] 342 }, 343 { 344 .attr = { .name = "profile5_settings", .mode = 0440 }, 345 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, 346 .read = koneplus_sysfs_read_profilex_settings, 347 .private = &profile_numbers[4] 348 }, 349 { 350 .attr = { .name = "profile1_buttons", .mode = 0440 }, 351 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, 352 .read = koneplus_sysfs_read_profilex_buttons, 353 .private = &profile_numbers[0] 354 }, 355 { 356 .attr = { .name = "profile2_buttons", .mode = 0440 }, 357 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, 358 .read = koneplus_sysfs_read_profilex_buttons, 359 .private = &profile_numbers[1] 360 }, 361 { 362 .attr = { .name = "profile3_buttons", .mode = 0440 }, 363 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, 364 .read = koneplus_sysfs_read_profilex_buttons, 365 .private = &profile_numbers[2] 366 }, 367 { 368 .attr = { .name = "profile4_buttons", .mode = 0440 }, 369 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, 370 .read = koneplus_sysfs_read_profilex_buttons, 371 .private = &profile_numbers[3] 372 }, 373 { 374 .attr = { .name = "profile5_buttons", .mode = 0440 }, 375 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, 376 .read = koneplus_sysfs_read_profilex_buttons, 377 .private = &profile_numbers[4] 378 }, 379 __ATTR_NULL 380 }; 381 382 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, 383 struct koneplus_device *koneplus) 384 { 385 int retval; 386 387 mutex_init(&koneplus->koneplus_lock); 388 389 retval = koneplus_get_actual_profile(usb_dev); 390 if (retval < 0) 391 return retval; 392 koneplus_profile_activated(koneplus, retval); 393 394 return 0; 395 } 396 397 static int koneplus_init_specials(struct hid_device *hdev) 398 { 399 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 400 struct usb_device *usb_dev = interface_to_usbdev(intf); 401 struct koneplus_device *koneplus; 402 int retval; 403 404 if (intf->cur_altsetting->desc.bInterfaceProtocol 405 == USB_INTERFACE_PROTOCOL_MOUSE) { 406 407 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); 408 if (!koneplus) { 409 hid_err(hdev, "can't alloc device descriptor\n"); 410 return -ENOMEM; 411 } 412 hid_set_drvdata(hdev, koneplus); 413 414 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); 415 if (retval) { 416 hid_err(hdev, "couldn't init struct koneplus_device\n"); 417 goto exit_free; 418 } 419 420 retval = roccat_connect(koneplus_class, hdev, 421 sizeof(struct koneplus_roccat_report)); 422 if (retval < 0) { 423 hid_err(hdev, "couldn't init char dev\n"); 424 } else { 425 koneplus->chrdev_minor = retval; 426 koneplus->roccat_claimed = 1; 427 } 428 } else { 429 hid_set_drvdata(hdev, NULL); 430 } 431 432 return 0; 433 exit_free: 434 kfree(koneplus); 435 return retval; 436 } 437 438 static void koneplus_remove_specials(struct hid_device *hdev) 439 { 440 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 441 struct koneplus_device *koneplus; 442 443 if (intf->cur_altsetting->desc.bInterfaceProtocol 444 == USB_INTERFACE_PROTOCOL_MOUSE) { 445 koneplus = hid_get_drvdata(hdev); 446 if (koneplus->roccat_claimed) 447 roccat_disconnect(koneplus->chrdev_minor); 448 kfree(koneplus); 449 } 450 } 451 452 static int koneplus_probe(struct hid_device *hdev, 453 const struct hid_device_id *id) 454 { 455 int retval; 456 457 retval = hid_parse(hdev); 458 if (retval) { 459 hid_err(hdev, "parse failed\n"); 460 goto exit; 461 } 462 463 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 464 if (retval) { 465 hid_err(hdev, "hw start failed\n"); 466 goto exit; 467 } 468 469 retval = koneplus_init_specials(hdev); 470 if (retval) { 471 hid_err(hdev, "couldn't install mouse\n"); 472 goto exit_stop; 473 } 474 475 return 0; 476 477 exit_stop: 478 hid_hw_stop(hdev); 479 exit: 480 return retval; 481 } 482 483 static void koneplus_remove(struct hid_device *hdev) 484 { 485 koneplus_remove_specials(hdev); 486 hid_hw_stop(hdev); 487 } 488 489 static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, 490 u8 const *data) 491 { 492 struct koneplus_mouse_report_button const *button_report; 493 494 switch (data[0]) { 495 case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: 496 button_report = (struct koneplus_mouse_report_button const *)data; 497 switch (button_report->type) { 498 case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: 499 koneplus_profile_activated(koneplus, button_report->data1 - 1); 500 break; 501 } 502 break; 503 } 504 } 505 506 static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, 507 u8 const *data) 508 { 509 struct koneplus_roccat_report roccat_report; 510 struct koneplus_mouse_report_button const *button_report; 511 512 if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) 513 return; 514 515 button_report = (struct koneplus_mouse_report_button const *)data; 516 517 if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || 518 button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && 519 button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) 520 return; 521 522 roccat_report.type = button_report->type; 523 roccat_report.data1 = button_report->data1; 524 roccat_report.data2 = button_report->data2; 525 roccat_report.profile = koneplus->actual_profile + 1; 526 roccat_report_event(koneplus->chrdev_minor, 527 (uint8_t const *)&roccat_report); 528 } 529 530 static int koneplus_raw_event(struct hid_device *hdev, 531 struct hid_report *report, u8 *data, int size) 532 { 533 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 534 struct koneplus_device *koneplus = hid_get_drvdata(hdev); 535 536 if (intf->cur_altsetting->desc.bInterfaceProtocol 537 != USB_INTERFACE_PROTOCOL_MOUSE) 538 return 0; 539 540 if (koneplus == NULL) 541 return 0; 542 543 koneplus_keep_values_up_to_date(koneplus, data); 544 545 if (koneplus->roccat_claimed) 546 koneplus_report_to_chrdev(koneplus, data); 547 548 return 0; 549 } 550 551 static const struct hid_device_id koneplus_devices[] = { 552 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 553 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) }, 554 { } 555 }; 556 557 MODULE_DEVICE_TABLE(hid, koneplus_devices); 558 559 static struct hid_driver koneplus_driver = { 560 .name = "koneplus", 561 .id_table = koneplus_devices, 562 .probe = koneplus_probe, 563 .remove = koneplus_remove, 564 .raw_event = koneplus_raw_event 565 }; 566 567 static int __init koneplus_init(void) 568 { 569 int retval; 570 571 /* class name has to be same as driver name */ 572 koneplus_class = class_create(THIS_MODULE, "koneplus"); 573 if (IS_ERR(koneplus_class)) 574 return PTR_ERR(koneplus_class); 575 koneplus_class->dev_attrs = koneplus_attributes; 576 koneplus_class->dev_bin_attrs = koneplus_bin_attributes; 577 578 retval = hid_register_driver(&koneplus_driver); 579 if (retval) 580 class_destroy(koneplus_class); 581 return retval; 582 } 583 584 static void __exit koneplus_exit(void) 585 { 586 hid_unregister_driver(&koneplus_driver); 587 class_destroy(koneplus_class); 588 } 589 590 module_init(koneplus_init); 591 module_exit(koneplus_exit); 592 593 MODULE_AUTHOR("Stefan Achatz"); 594 MODULE_DESCRIPTION("USB Roccat Kone[+]/XTD driver"); 595 MODULE_LICENSE("GPL v2"); 596