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 */ 18 19 #include <linux/device.h> 20 #include <linux/input.h> 21 #include <linux/hid.h> 22 #include <linux/module.h> 23 #include <linux/slab.h> 24 #include <linux/hid-roccat.h> 25 #include "hid-ids.h" 26 #include "hid-roccat-common.h" 27 #include "hid-roccat-koneplus.h" 28 29 static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 30 31 static struct class *koneplus_class; 32 33 static void koneplus_profile_activated(struct koneplus_device *koneplus, 34 uint new_profile) 35 { 36 koneplus->actual_profile = new_profile; 37 } 38 39 static int koneplus_send_control(struct usb_device *usb_dev, uint value, 40 enum koneplus_control_requests request) 41 { 42 struct koneplus_control control; 43 44 if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || 45 request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && 46 value > 4) 47 return -EINVAL; 48 49 control.command = KONEPLUS_COMMAND_CONTROL; 50 control.value = value; 51 control.request = request; 52 53 return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL, 54 &control, sizeof(struct koneplus_control)); 55 } 56 57 static int koneplus_receive_control_status(struct usb_device *usb_dev) 58 { 59 int retval; 60 struct koneplus_control control; 61 62 do { 63 retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL, 64 &control, sizeof(struct koneplus_control)); 65 66 /* check if we get a completely wrong answer */ 67 if (retval) 68 return retval; 69 70 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) 71 return 0; 72 73 /* indicates that hardware needs some more time to complete action */ 74 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { 75 msleep(500); /* windows driver uses 1000 */ 76 continue; 77 } 78 79 /* seems to be critical - replug necessary */ 80 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) 81 return -EINVAL; 82 83 hid_err(usb_dev, "koneplus_receive_control_status: " 84 "unknown response value 0x%x\n", control.value); 85 return -EINVAL; 86 } while (1); 87 } 88 89 static int koneplus_send(struct usb_device *usb_dev, uint command, 90 void const *buf, uint size) 91 { 92 int retval; 93 94 retval = roccat_common_send(usb_dev, command, buf, size); 95 if (retval) 96 return retval; 97 98 return koneplus_receive_control_status(usb_dev); 99 } 100 101 static int koneplus_select_profile(struct usb_device *usb_dev, uint number, 102 enum koneplus_control_requests request) 103 { 104 int retval; 105 106 retval = koneplus_send_control(usb_dev, number, request); 107 if (retval) 108 return retval; 109 110 /* allow time to settle things - windows driver uses 500 */ 111 msleep(100); 112 113 retval = koneplus_receive_control_status(usb_dev); 114 if (retval) 115 return retval; 116 117 return 0; 118 } 119 120 static int koneplus_get_info(struct usb_device *usb_dev, 121 struct koneplus_info *buf) 122 { 123 return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO, 124 buf, sizeof(struct koneplus_info)); 125 } 126 127 static int koneplus_get_profile_settings(struct usb_device *usb_dev, 128 struct koneplus_profile_settings *buf, uint number) 129 { 130 int retval; 131 132 retval = koneplus_select_profile(usb_dev, number, 133 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); 134 if (retval) 135 return retval; 136 137 return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, 138 buf, sizeof(struct koneplus_profile_settings)); 139 } 140 141 static int koneplus_set_profile_settings(struct usb_device *usb_dev, 142 struct koneplus_profile_settings const *settings) 143 { 144 return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, 145 settings, sizeof(struct koneplus_profile_settings)); 146 } 147 148 static int koneplus_get_profile_buttons(struct usb_device *usb_dev, 149 struct koneplus_profile_buttons *buf, int number) 150 { 151 int retval; 152 153 retval = koneplus_select_profile(usb_dev, number, 154 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); 155 if (retval) 156 return retval; 157 158 return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, 159 buf, sizeof(struct koneplus_profile_buttons)); 160 } 161 162 static int koneplus_set_profile_buttons(struct usb_device *usb_dev, 163 struct koneplus_profile_buttons const *buttons) 164 { 165 return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, 166 buttons, sizeof(struct koneplus_profile_buttons)); 167 } 168 169 /* retval is 0-4 on success, < 0 on error */ 170 static int koneplus_get_actual_profile(struct usb_device *usb_dev) 171 { 172 struct koneplus_actual_profile buf; 173 int retval; 174 175 retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, 176 &buf, sizeof(struct koneplus_actual_profile)); 177 178 return retval ? retval : buf.actual_profile; 179 } 180 181 static int koneplus_set_actual_profile(struct usb_device *usb_dev, 182 int new_profile) 183 { 184 struct koneplus_actual_profile buf; 185 186 buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE; 187 buf.size = sizeof(struct koneplus_actual_profile); 188 buf.actual_profile = new_profile; 189 190 return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, 191 &buf, sizeof(struct koneplus_actual_profile)); 192 } 193 194 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, 195 char *buf, loff_t off, size_t count, 196 size_t real_size, uint command) 197 { 198 struct device *dev = 199 container_of(kobj, struct device, kobj)->parent->parent; 200 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 201 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 202 int retval; 203 204 if (off >= real_size) 205 return 0; 206 207 if (off != 0 || count != real_size) 208 return -EINVAL; 209 210 mutex_lock(&koneplus->koneplus_lock); 211 retval = roccat_common_receive(usb_dev, command, buf, real_size); 212 mutex_unlock(&koneplus->koneplus_lock); 213 214 if (retval) 215 return retval; 216 217 return real_size; 218 } 219 220 static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, 221 void const *buf, loff_t off, size_t count, 222 size_t real_size, uint command) 223 { 224 struct device *dev = 225 container_of(kobj, struct device, kobj)->parent->parent; 226 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 227 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 228 int retval; 229 230 if (off != 0 || count != real_size) 231 return -EINVAL; 232 233 mutex_lock(&koneplus->koneplus_lock); 234 retval = koneplus_send(usb_dev, command, buf, real_size); 235 mutex_unlock(&koneplus->koneplus_lock); 236 237 if (retval) 238 return retval; 239 240 return real_size; 241 } 242 243 static ssize_t koneplus_sysfs_write_talk(struct file *fp, 244 struct kobject *kobj, struct bin_attribute *attr, char *buf, 245 loff_t off, size_t count) 246 { 247 return koneplus_sysfs_write(fp, kobj, buf, off, count, 248 sizeof(struct koneplus_talk), KONEPLUS_COMMAND_TALK); 249 } 250 251 static ssize_t koneplus_sysfs_write_macro(struct file *fp, 252 struct kobject *kobj, struct bin_attribute *attr, char *buf, 253 loff_t off, size_t count) 254 { 255 return koneplus_sysfs_write(fp, kobj, buf, off, count, 256 sizeof(struct koneplus_macro), KONEPLUS_COMMAND_MACRO); 257 } 258 259 static ssize_t koneplus_sysfs_read_sensor(struct file *fp, 260 struct kobject *kobj, struct bin_attribute *attr, char *buf, 261 loff_t off, size_t count) 262 { 263 return koneplus_sysfs_read(fp, kobj, buf, off, count, 264 sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR); 265 } 266 267 static ssize_t koneplus_sysfs_write_sensor(struct file *fp, 268 struct kobject *kobj, struct bin_attribute *attr, char *buf, 269 loff_t off, size_t count) 270 { 271 return koneplus_sysfs_write(fp, kobj, buf, off, count, 272 sizeof(struct koneplus_sensor), KONEPLUS_COMMAND_SENSOR); 273 } 274 275 static ssize_t koneplus_sysfs_write_tcu(struct file *fp, 276 struct kobject *kobj, struct bin_attribute *attr, char *buf, 277 loff_t off, size_t count) 278 { 279 return koneplus_sysfs_write(fp, kobj, buf, off, count, 280 sizeof(struct koneplus_tcu), KONEPLUS_COMMAND_TCU); 281 } 282 283 static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, 284 struct kobject *kobj, struct bin_attribute *attr, char *buf, 285 loff_t off, size_t count) 286 { 287 return koneplus_sysfs_read(fp, kobj, buf, off, count, 288 sizeof(struct koneplus_tcu_image), KONEPLUS_COMMAND_TCU); 289 } 290 291 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, 292 struct kobject *kobj, struct bin_attribute *attr, char *buf, 293 loff_t off, size_t count) 294 { 295 struct device *dev = 296 container_of(kobj, struct device, kobj)->parent->parent; 297 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 298 299 if (off >= sizeof(struct koneplus_profile_settings)) 300 return 0; 301 302 if (off + count > sizeof(struct koneplus_profile_settings)) 303 count = sizeof(struct koneplus_profile_settings) - off; 304 305 mutex_lock(&koneplus->koneplus_lock); 306 memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, 307 count); 308 mutex_unlock(&koneplus->koneplus_lock); 309 310 return count; 311 } 312 313 static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp, 314 struct kobject *kobj, struct bin_attribute *attr, char *buf, 315 loff_t off, size_t count) 316 { 317 struct device *dev = 318 container_of(kobj, struct device, kobj)->parent->parent; 319 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 320 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 321 int retval = 0; 322 int difference; 323 int profile_number; 324 struct koneplus_profile_settings *profile_settings; 325 326 if (off != 0 || count != sizeof(struct koneplus_profile_settings)) 327 return -EINVAL; 328 329 profile_number = ((struct koneplus_profile_settings const *)buf)->number; 330 profile_settings = &koneplus->profile_settings[profile_number]; 331 332 mutex_lock(&koneplus->koneplus_lock); 333 difference = memcmp(buf, profile_settings, 334 sizeof(struct koneplus_profile_settings)); 335 if (difference) { 336 retval = koneplus_set_profile_settings(usb_dev, 337 (struct koneplus_profile_settings const *)buf); 338 if (!retval) 339 memcpy(profile_settings, buf, 340 sizeof(struct koneplus_profile_settings)); 341 } 342 mutex_unlock(&koneplus->koneplus_lock); 343 344 if (retval) 345 return retval; 346 347 return sizeof(struct koneplus_profile_settings); 348 } 349 350 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, 351 struct kobject *kobj, struct bin_attribute *attr, char *buf, 352 loff_t off, size_t count) 353 { 354 struct device *dev = 355 container_of(kobj, struct device, kobj)->parent->parent; 356 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 357 358 if (off >= sizeof(struct koneplus_profile_buttons)) 359 return 0; 360 361 if (off + count > sizeof(struct koneplus_profile_buttons)) 362 count = sizeof(struct koneplus_profile_buttons) - off; 363 364 mutex_lock(&koneplus->koneplus_lock); 365 memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, 366 count); 367 mutex_unlock(&koneplus->koneplus_lock); 368 369 return count; 370 } 371 372 static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp, 373 struct kobject *kobj, struct bin_attribute *attr, char *buf, 374 loff_t off, size_t count) 375 { 376 struct device *dev = 377 container_of(kobj, struct device, kobj)->parent->parent; 378 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 379 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 380 int retval = 0; 381 int difference; 382 uint profile_number; 383 struct koneplus_profile_buttons *profile_buttons; 384 385 if (off != 0 || count != sizeof(struct koneplus_profile_buttons)) 386 return -EINVAL; 387 388 profile_number = ((struct koneplus_profile_buttons const *)buf)->number; 389 profile_buttons = &koneplus->profile_buttons[profile_number]; 390 391 mutex_lock(&koneplus->koneplus_lock); 392 difference = memcmp(buf, profile_buttons, 393 sizeof(struct koneplus_profile_buttons)); 394 if (difference) { 395 retval = koneplus_set_profile_buttons(usb_dev, 396 (struct koneplus_profile_buttons const *)buf); 397 if (!retval) 398 memcpy(profile_buttons, buf, 399 sizeof(struct koneplus_profile_buttons)); 400 } 401 mutex_unlock(&koneplus->koneplus_lock); 402 403 if (retval) 404 return retval; 405 406 return sizeof(struct koneplus_profile_buttons); 407 } 408 409 static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, 410 struct device_attribute *attr, char *buf) 411 { 412 struct koneplus_device *koneplus = 413 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 414 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); 415 } 416 417 static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, 418 struct device_attribute *attr, char const *buf, size_t size) 419 { 420 struct koneplus_device *koneplus; 421 struct usb_device *usb_dev; 422 unsigned long profile; 423 int retval; 424 struct koneplus_roccat_report roccat_report; 425 426 dev = dev->parent->parent; 427 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 428 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 429 430 retval = strict_strtoul(buf, 10, &profile); 431 if (retval) 432 return retval; 433 434 if (profile > 4) 435 return -EINVAL; 436 437 mutex_lock(&koneplus->koneplus_lock); 438 439 retval = koneplus_set_actual_profile(usb_dev, profile); 440 if (retval) { 441 mutex_unlock(&koneplus->koneplus_lock); 442 return retval; 443 } 444 445 koneplus_profile_activated(koneplus, profile); 446 447 roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; 448 roccat_report.data1 = profile + 1; 449 roccat_report.data2 = 0; 450 roccat_report.profile = profile + 1; 451 roccat_report_event(koneplus->chrdev_minor, 452 (uint8_t const *)&roccat_report); 453 454 mutex_unlock(&koneplus->koneplus_lock); 455 456 return size; 457 } 458 459 static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, 460 struct device_attribute *attr, char *buf) 461 { 462 struct koneplus_device *koneplus = 463 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 464 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version); 465 } 466 467 static struct device_attribute koneplus_attributes[] = { 468 __ATTR(actual_profile, 0660, 469 koneplus_sysfs_show_actual_profile, 470 koneplus_sysfs_set_actual_profile), 471 __ATTR(startup_profile, 0660, 472 koneplus_sysfs_show_actual_profile, 473 koneplus_sysfs_set_actual_profile), 474 __ATTR(firmware_version, 0440, 475 koneplus_sysfs_show_firmware_version, NULL), 476 __ATTR_NULL 477 }; 478 479 static struct bin_attribute koneplus_bin_attributes[] = { 480 { 481 .attr = { .name = "sensor", .mode = 0660 }, 482 .size = sizeof(struct koneplus_sensor), 483 .read = koneplus_sysfs_read_sensor, 484 .write = koneplus_sysfs_write_sensor 485 }, 486 { 487 .attr = { .name = "tcu", .mode = 0220 }, 488 .size = sizeof(struct koneplus_tcu), 489 .write = koneplus_sysfs_write_tcu 490 }, 491 { 492 .attr = { .name = "tcu_image", .mode = 0440 }, 493 .size = sizeof(struct koneplus_tcu_image), 494 .read = koneplus_sysfs_read_tcu_image 495 }, 496 { 497 .attr = { .name = "profile_settings", .mode = 0220 }, 498 .size = sizeof(struct koneplus_profile_settings), 499 .write = koneplus_sysfs_write_profile_settings 500 }, 501 { 502 .attr = { .name = "profile1_settings", .mode = 0440 }, 503 .size = sizeof(struct koneplus_profile_settings), 504 .read = koneplus_sysfs_read_profilex_settings, 505 .private = &profile_numbers[0] 506 }, 507 { 508 .attr = { .name = "profile2_settings", .mode = 0440 }, 509 .size = sizeof(struct koneplus_profile_settings), 510 .read = koneplus_sysfs_read_profilex_settings, 511 .private = &profile_numbers[1] 512 }, 513 { 514 .attr = { .name = "profile3_settings", .mode = 0440 }, 515 .size = sizeof(struct koneplus_profile_settings), 516 .read = koneplus_sysfs_read_profilex_settings, 517 .private = &profile_numbers[2] 518 }, 519 { 520 .attr = { .name = "profile4_settings", .mode = 0440 }, 521 .size = sizeof(struct koneplus_profile_settings), 522 .read = koneplus_sysfs_read_profilex_settings, 523 .private = &profile_numbers[3] 524 }, 525 { 526 .attr = { .name = "profile5_settings", .mode = 0440 }, 527 .size = sizeof(struct koneplus_profile_settings), 528 .read = koneplus_sysfs_read_profilex_settings, 529 .private = &profile_numbers[4] 530 }, 531 { 532 .attr = { .name = "profile_buttons", .mode = 0220 }, 533 .size = sizeof(struct koneplus_profile_buttons), 534 .write = koneplus_sysfs_write_profile_buttons 535 }, 536 { 537 .attr = { .name = "profile1_buttons", .mode = 0440 }, 538 .size = sizeof(struct koneplus_profile_buttons), 539 .read = koneplus_sysfs_read_profilex_buttons, 540 .private = &profile_numbers[0] 541 }, 542 { 543 .attr = { .name = "profile2_buttons", .mode = 0440 }, 544 .size = sizeof(struct koneplus_profile_buttons), 545 .read = koneplus_sysfs_read_profilex_buttons, 546 .private = &profile_numbers[1] 547 }, 548 { 549 .attr = { .name = "profile3_buttons", .mode = 0440 }, 550 .size = sizeof(struct koneplus_profile_buttons), 551 .read = koneplus_sysfs_read_profilex_buttons, 552 .private = &profile_numbers[2] 553 }, 554 { 555 .attr = { .name = "profile4_buttons", .mode = 0440 }, 556 .size = sizeof(struct koneplus_profile_buttons), 557 .read = koneplus_sysfs_read_profilex_buttons, 558 .private = &profile_numbers[3] 559 }, 560 { 561 .attr = { .name = "profile5_buttons", .mode = 0440 }, 562 .size = sizeof(struct koneplus_profile_buttons), 563 .read = koneplus_sysfs_read_profilex_buttons, 564 .private = &profile_numbers[4] 565 }, 566 { 567 .attr = { .name = "macro", .mode = 0220 }, 568 .size = sizeof(struct koneplus_macro), 569 .write = koneplus_sysfs_write_macro 570 }, 571 { 572 .attr = { .name = "talk", .mode = 0220 }, 573 .size = sizeof(struct koneplus_talk), 574 .write = koneplus_sysfs_write_talk 575 }, 576 __ATTR_NULL 577 }; 578 579 static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, 580 struct koneplus_device *koneplus) 581 { 582 int retval, i; 583 static uint wait = 200; 584 585 mutex_init(&koneplus->koneplus_lock); 586 587 retval = koneplus_get_info(usb_dev, &koneplus->info); 588 if (retval) 589 return retval; 590 591 for (i = 0; i < 5; ++i) { 592 msleep(wait); 593 retval = koneplus_get_profile_settings(usb_dev, 594 &koneplus->profile_settings[i], i); 595 if (retval) 596 return retval; 597 598 msleep(wait); 599 retval = koneplus_get_profile_buttons(usb_dev, 600 &koneplus->profile_buttons[i], i); 601 if (retval) 602 return retval; 603 } 604 605 msleep(wait); 606 retval = koneplus_get_actual_profile(usb_dev); 607 if (retval < 0) 608 return retval; 609 koneplus_profile_activated(koneplus, retval); 610 611 return 0; 612 } 613 614 static int koneplus_init_specials(struct hid_device *hdev) 615 { 616 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 617 struct usb_device *usb_dev = interface_to_usbdev(intf); 618 struct koneplus_device *koneplus; 619 int retval; 620 621 if (intf->cur_altsetting->desc.bInterfaceProtocol 622 == USB_INTERFACE_PROTOCOL_MOUSE) { 623 624 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); 625 if (!koneplus) { 626 hid_err(hdev, "can't alloc device descriptor\n"); 627 return -ENOMEM; 628 } 629 hid_set_drvdata(hdev, koneplus); 630 631 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); 632 if (retval) { 633 hid_err(hdev, "couldn't init struct koneplus_device\n"); 634 goto exit_free; 635 } 636 637 retval = roccat_connect(koneplus_class, hdev, 638 sizeof(struct koneplus_roccat_report)); 639 if (retval < 0) { 640 hid_err(hdev, "couldn't init char dev\n"); 641 } else { 642 koneplus->chrdev_minor = retval; 643 koneplus->roccat_claimed = 1; 644 } 645 } else { 646 hid_set_drvdata(hdev, NULL); 647 } 648 649 return 0; 650 exit_free: 651 kfree(koneplus); 652 return retval; 653 } 654 655 static void koneplus_remove_specials(struct hid_device *hdev) 656 { 657 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 658 struct koneplus_device *koneplus; 659 660 if (intf->cur_altsetting->desc.bInterfaceProtocol 661 == USB_INTERFACE_PROTOCOL_MOUSE) { 662 koneplus = hid_get_drvdata(hdev); 663 if (koneplus->roccat_claimed) 664 roccat_disconnect(koneplus->chrdev_minor); 665 kfree(koneplus); 666 } 667 } 668 669 static int koneplus_probe(struct hid_device *hdev, 670 const struct hid_device_id *id) 671 { 672 int retval; 673 674 retval = hid_parse(hdev); 675 if (retval) { 676 hid_err(hdev, "parse failed\n"); 677 goto exit; 678 } 679 680 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 681 if (retval) { 682 hid_err(hdev, "hw start failed\n"); 683 goto exit; 684 } 685 686 retval = koneplus_init_specials(hdev); 687 if (retval) { 688 hid_err(hdev, "couldn't install mouse\n"); 689 goto exit_stop; 690 } 691 692 return 0; 693 694 exit_stop: 695 hid_hw_stop(hdev); 696 exit: 697 return retval; 698 } 699 700 static void koneplus_remove(struct hid_device *hdev) 701 { 702 koneplus_remove_specials(hdev); 703 hid_hw_stop(hdev); 704 } 705 706 static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, 707 u8 const *data) 708 { 709 struct koneplus_mouse_report_button const *button_report; 710 711 switch (data[0]) { 712 case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: 713 button_report = (struct koneplus_mouse_report_button const *)data; 714 switch (button_report->type) { 715 case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: 716 koneplus_profile_activated(koneplus, button_report->data1 - 1); 717 break; 718 } 719 break; 720 } 721 } 722 723 static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, 724 u8 const *data) 725 { 726 struct koneplus_roccat_report roccat_report; 727 struct koneplus_mouse_report_button const *button_report; 728 729 if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) 730 return; 731 732 button_report = (struct koneplus_mouse_report_button const *)data; 733 734 if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || 735 button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && 736 button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) 737 return; 738 739 roccat_report.type = button_report->type; 740 roccat_report.data1 = button_report->data1; 741 roccat_report.data2 = button_report->data2; 742 roccat_report.profile = koneplus->actual_profile + 1; 743 roccat_report_event(koneplus->chrdev_minor, 744 (uint8_t const *)&roccat_report); 745 } 746 747 static int koneplus_raw_event(struct hid_device *hdev, 748 struct hid_report *report, u8 *data, int size) 749 { 750 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 751 struct koneplus_device *koneplus = hid_get_drvdata(hdev); 752 753 if (intf->cur_altsetting->desc.bInterfaceProtocol 754 != USB_INTERFACE_PROTOCOL_MOUSE) 755 return 0; 756 757 if (koneplus == NULL) 758 return 0; 759 760 koneplus_keep_values_up_to_date(koneplus, data); 761 762 if (koneplus->roccat_claimed) 763 koneplus_report_to_chrdev(koneplus, data); 764 765 return 0; 766 } 767 768 static const struct hid_device_id koneplus_devices[] = { 769 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 770 { } 771 }; 772 773 MODULE_DEVICE_TABLE(hid, koneplus_devices); 774 775 static struct hid_driver koneplus_driver = { 776 .name = "koneplus", 777 .id_table = koneplus_devices, 778 .probe = koneplus_probe, 779 .remove = koneplus_remove, 780 .raw_event = koneplus_raw_event 781 }; 782 783 static int __init koneplus_init(void) 784 { 785 int retval; 786 787 /* class name has to be same as driver name */ 788 koneplus_class = class_create(THIS_MODULE, "koneplus"); 789 if (IS_ERR(koneplus_class)) 790 return PTR_ERR(koneplus_class); 791 koneplus_class->dev_attrs = koneplus_attributes; 792 koneplus_class->dev_bin_attrs = koneplus_bin_attributes; 793 794 retval = hid_register_driver(&koneplus_driver); 795 if (retval) 796 class_destroy(koneplus_class); 797 return retval; 798 } 799 800 static void __exit koneplus_exit(void) 801 { 802 hid_unregister_driver(&koneplus_driver); 803 class_destroy(koneplus_class); 804 } 805 806 module_init(koneplus_init); 807 module_exit(koneplus_exit); 808 809 MODULE_AUTHOR("Stefan Achatz"); 810 MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); 811 MODULE_LICENSE("GPL v2"); 812