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 29static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 30 31static struct class *koneplus_class; 32 33static void koneplus_profile_activated(struct koneplus_device *koneplus, 34 uint new_profile) 35{ 36 koneplus->actual_profile = new_profile; 37} 38 39static 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 57static 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 89static 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 101static 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 120static 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 127static 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 141static 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 148static 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 162static 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 */ 170static 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 181static 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 194static 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 220static 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 243static 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 251static 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 259static 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 267static 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 275static 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 283static 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 291static 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 313static 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 350static 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 372static 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 409static 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 417static 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 459static 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 467static 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 479static 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 579static 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 614static 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; 650exit_free: 651 kfree(koneplus); 652 return retval; 653} 654 655static 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 669static 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 694exit_stop: 695 hid_hw_stop(hdev); 696exit: 697 return retval; 698} 699 700static void koneplus_remove(struct hid_device *hdev) 701{ 702 koneplus_remove_specials(hdev); 703 hid_hw_stop(hdev); 704} 705 706static 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 723static 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 747static 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 768static const struct hid_device_id koneplus_devices[] = { 769 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 770 { } 771}; 772 773MODULE_DEVICE_TABLE(hid, koneplus_devices); 774 775static 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 783static 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 800static void __exit koneplus_exit(void) 801{ 802 hid_unregister_driver(&koneplus_driver); 803 class_destroy(koneplus_class); 804} 805 806module_init(koneplus_init); 807module_exit(koneplus_exit); 808 809MODULE_AUTHOR("Stefan Achatz"); 810MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); 811MODULE_LICENSE("GPL v2"); 812