hid-roccat-koneplus.c revision 5dc0c9835fb96c75c8dbf657393764bd0abbac04
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_USB_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_USB_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_USB_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_USB_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_USB_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_USB_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_USB_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_startup_profile(struct usb_device *usb_dev) 171{ 172 struct koneplus_startup_profile buf; 173 int retval; 174 175 retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, 176 &buf, sizeof(struct koneplus_startup_profile)); 177 178 return retval ? retval : buf.startup_profile; 179} 180 181static int koneplus_set_startup_profile(struct usb_device *usb_dev, 182 int startup_profile) 183{ 184 struct koneplus_startup_profile buf; 185 186 buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE; 187 buf.size = sizeof(struct koneplus_startup_profile); 188 buf.startup_profile = startup_profile; 189 190 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, 191 &buf, sizeof(struct koneplus_profile_buttons)); 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_macro(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_macro), KONEPLUS_USB_COMMAND_MACRO); 249} 250 251static ssize_t koneplus_sysfs_read_sensor(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_read(fp, kobj, buf, off, count, 256 sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); 257} 258 259static ssize_t koneplus_sysfs_write_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_write(fp, kobj, buf, off, count, 264 sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); 265} 266 267static ssize_t koneplus_sysfs_write_tcu(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_tcu), KONEPLUS_USB_COMMAND_TCU); 273} 274 275static ssize_t koneplus_sysfs_read_tcu_image(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_read(fp, kobj, buf, off, count, 280 sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU); 281} 282 283static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, 284 struct kobject *kobj, struct bin_attribute *attr, char *buf, 285 loff_t off, size_t count) 286{ 287 struct device *dev = 288 container_of(kobj, struct device, kobj)->parent->parent; 289 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 290 291 if (off >= sizeof(struct koneplus_profile_settings)) 292 return 0; 293 294 if (off + count > sizeof(struct koneplus_profile_settings)) 295 count = sizeof(struct koneplus_profile_settings) - off; 296 297 mutex_lock(&koneplus->koneplus_lock); 298 memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, 299 count); 300 mutex_unlock(&koneplus->koneplus_lock); 301 302 return count; 303} 304 305static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp, 306 struct kobject *kobj, struct bin_attribute *attr, char *buf, 307 loff_t off, size_t count) 308{ 309 struct device *dev = 310 container_of(kobj, struct device, kobj)->parent->parent; 311 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 312 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 313 int retval = 0; 314 int difference; 315 int profile_number; 316 struct koneplus_profile_settings *profile_settings; 317 318 if (off != 0 || count != sizeof(struct koneplus_profile_settings)) 319 return -EINVAL; 320 321 profile_number = ((struct koneplus_profile_settings const *)buf)->number; 322 profile_settings = &koneplus->profile_settings[profile_number]; 323 324 mutex_lock(&koneplus->koneplus_lock); 325 difference = memcmp(buf, profile_settings, 326 sizeof(struct koneplus_profile_settings)); 327 if (difference) { 328 retval = koneplus_set_profile_settings(usb_dev, 329 (struct koneplus_profile_settings const *)buf); 330 if (!retval) 331 memcpy(profile_settings, buf, 332 sizeof(struct koneplus_profile_settings)); 333 } 334 mutex_unlock(&koneplus->koneplus_lock); 335 336 if (retval) 337 return retval; 338 339 return sizeof(struct koneplus_profile_settings); 340} 341 342static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, 343 struct kobject *kobj, struct bin_attribute *attr, char *buf, 344 loff_t off, size_t count) 345{ 346 struct device *dev = 347 container_of(kobj, struct device, kobj)->parent->parent; 348 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 349 350 if (off >= sizeof(struct koneplus_profile_buttons)) 351 return 0; 352 353 if (off + count > sizeof(struct koneplus_profile_buttons)) 354 count = sizeof(struct koneplus_profile_buttons) - off; 355 356 mutex_lock(&koneplus->koneplus_lock); 357 memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, 358 count); 359 mutex_unlock(&koneplus->koneplus_lock); 360 361 return count; 362} 363 364static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp, 365 struct kobject *kobj, struct bin_attribute *attr, char *buf, 366 loff_t off, size_t count) 367{ 368 struct device *dev = 369 container_of(kobj, struct device, kobj)->parent->parent; 370 struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 371 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 372 int retval = 0; 373 int difference; 374 uint profile_number; 375 struct koneplus_profile_buttons *profile_buttons; 376 377 if (off != 0 || count != sizeof(struct koneplus_profile_buttons)) 378 return -EINVAL; 379 380 profile_number = ((struct koneplus_profile_buttons const *)buf)->number; 381 profile_buttons = &koneplus->profile_buttons[profile_number]; 382 383 mutex_lock(&koneplus->koneplus_lock); 384 difference = memcmp(buf, profile_buttons, 385 sizeof(struct koneplus_profile_buttons)); 386 if (difference) { 387 retval = koneplus_set_profile_buttons(usb_dev, 388 (struct koneplus_profile_buttons const *)buf); 389 if (!retval) 390 memcpy(profile_buttons, buf, 391 sizeof(struct koneplus_profile_buttons)); 392 } 393 mutex_unlock(&koneplus->koneplus_lock); 394 395 if (retval) 396 return retval; 397 398 return sizeof(struct koneplus_profile_buttons); 399} 400 401static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev, 402 struct device_attribute *attr, char *buf) 403{ 404 struct koneplus_device *koneplus = 405 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 406 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile); 407} 408 409static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev, 410 struct device_attribute *attr, char const *buf, size_t size) 411{ 412 struct koneplus_device *koneplus; 413 struct usb_device *usb_dev; 414 unsigned long profile; 415 int retval; 416 417 dev = dev->parent->parent; 418 koneplus = hid_get_drvdata(dev_get_drvdata(dev)); 419 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 420 421 retval = strict_strtoul(buf, 10, &profile); 422 if (retval) 423 return retval; 424 425 mutex_lock(&koneplus->koneplus_lock); 426 retval = koneplus_set_startup_profile(usb_dev, profile); 427 mutex_unlock(&koneplus->koneplus_lock); 428 if (retval) 429 return retval; 430 431 return size; 432} 433 434static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, 435 struct device_attribute *attr, char *buf) 436{ 437 struct koneplus_device *koneplus = 438 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 439 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); 440} 441 442static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, 443 struct device_attribute *attr, char *buf) 444{ 445 struct koneplus_device *koneplus = 446 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 447 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version); 448} 449 450static struct device_attribute koneplus_attributes[] = { 451 __ATTR(startup_profile, 0660, 452 koneplus_sysfs_show_startup_profile, 453 koneplus_sysfs_set_startup_profile), 454 __ATTR(actual_profile, 0440, 455 koneplus_sysfs_show_actual_profile, NULL), 456 __ATTR(firmware_version, 0440, 457 koneplus_sysfs_show_firmware_version, NULL), 458 __ATTR_NULL 459}; 460 461static struct bin_attribute koneplus_bin_attributes[] = { 462 { 463 .attr = { .name = "sensor", .mode = 0220 }, 464 .size = sizeof(struct koneplus_sensor), 465 .read = koneplus_sysfs_read_sensor, 466 .write = koneplus_sysfs_write_sensor 467 }, 468 { 469 .attr = { .name = "tcu", .mode = 0220 }, 470 .size = sizeof(struct koneplus_tcu), 471 .write = koneplus_sysfs_write_tcu 472 }, 473 { 474 .attr = { .name = "tcu_image", .mode = 0440 }, 475 .size = sizeof(struct koneplus_tcu_image), 476 .read = koneplus_sysfs_read_tcu_image 477 }, 478 { 479 .attr = { .name = "profile_settings", .mode = 0220 }, 480 .size = sizeof(struct koneplus_profile_settings), 481 .write = koneplus_sysfs_write_profile_settings 482 }, 483 { 484 .attr = { .name = "profile1_settings", .mode = 0440 }, 485 .size = sizeof(struct koneplus_profile_settings), 486 .read = koneplus_sysfs_read_profilex_settings, 487 .private = &profile_numbers[0] 488 }, 489 { 490 .attr = { .name = "profile2_settings", .mode = 0440 }, 491 .size = sizeof(struct koneplus_profile_settings), 492 .read = koneplus_sysfs_read_profilex_settings, 493 .private = &profile_numbers[1] 494 }, 495 { 496 .attr = { .name = "profile3_settings", .mode = 0440 }, 497 .size = sizeof(struct koneplus_profile_settings), 498 .read = koneplus_sysfs_read_profilex_settings, 499 .private = &profile_numbers[2] 500 }, 501 { 502 .attr = { .name = "profile4_settings", .mode = 0440 }, 503 .size = sizeof(struct koneplus_profile_settings), 504 .read = koneplus_sysfs_read_profilex_settings, 505 .private = &profile_numbers[3] 506 }, 507 { 508 .attr = { .name = "profile5_settings", .mode = 0440 }, 509 .size = sizeof(struct koneplus_profile_settings), 510 .read = koneplus_sysfs_read_profilex_settings, 511 .private = &profile_numbers[4] 512 }, 513 { 514 .attr = { .name = "profile_buttons", .mode = 0220 }, 515 .size = sizeof(struct koneplus_profile_buttons), 516 .write = koneplus_sysfs_write_profile_buttons 517 }, 518 { 519 .attr = { .name = "profile1_buttons", .mode = 0440 }, 520 .size = sizeof(struct koneplus_profile_buttons), 521 .read = koneplus_sysfs_read_profilex_buttons, 522 .private = &profile_numbers[0] 523 }, 524 { 525 .attr = { .name = "profile2_buttons", .mode = 0440 }, 526 .size = sizeof(struct koneplus_profile_buttons), 527 .read = koneplus_sysfs_read_profilex_buttons, 528 .private = &profile_numbers[1] 529 }, 530 { 531 .attr = { .name = "profile3_buttons", .mode = 0440 }, 532 .size = sizeof(struct koneplus_profile_buttons), 533 .read = koneplus_sysfs_read_profilex_buttons, 534 .private = &profile_numbers[2] 535 }, 536 { 537 .attr = { .name = "profile4_buttons", .mode = 0440 }, 538 .size = sizeof(struct koneplus_profile_buttons), 539 .read = koneplus_sysfs_read_profilex_buttons, 540 .private = &profile_numbers[3] 541 }, 542 { 543 .attr = { .name = "profile5_buttons", .mode = 0440 }, 544 .size = sizeof(struct koneplus_profile_buttons), 545 .read = koneplus_sysfs_read_profilex_buttons, 546 .private = &profile_numbers[4] 547 }, 548 { 549 .attr = { .name = "macro", .mode = 0220 }, 550 .size = sizeof(struct koneplus_macro), 551 .write = koneplus_sysfs_write_macro 552 }, 553 __ATTR_NULL 554}; 555 556static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, 557 struct koneplus_device *koneplus) 558{ 559 int retval, i; 560 static uint wait = 100; /* device will freeze with just 60 */ 561 562 mutex_init(&koneplus->koneplus_lock); 563 564 koneplus->startup_profile = koneplus_get_startup_profile(usb_dev); 565 if (koneplus->startup_profile < 0) 566 return koneplus->startup_profile; 567 568 msleep(wait); 569 retval = koneplus_get_info(usb_dev, &koneplus->info); 570 if (retval) 571 return retval; 572 573 for (i = 0; i < 5; ++i) { 574 msleep(wait); 575 retval = koneplus_get_profile_settings(usb_dev, 576 &koneplus->profile_settings[i], i); 577 if (retval) 578 return retval; 579 580 msleep(wait); 581 retval = koneplus_get_profile_buttons(usb_dev, 582 &koneplus->profile_buttons[i], i); 583 if (retval) 584 return retval; 585 } 586 587 koneplus_profile_activated(koneplus, koneplus->startup_profile); 588 589 return 0; 590} 591 592static int koneplus_init_specials(struct hid_device *hdev) 593{ 594 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 595 struct usb_device *usb_dev = interface_to_usbdev(intf); 596 struct koneplus_device *koneplus; 597 int retval; 598 599 if (intf->cur_altsetting->desc.bInterfaceProtocol 600 == USB_INTERFACE_PROTOCOL_MOUSE) { 601 602 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); 603 if (!koneplus) { 604 hid_err(hdev, "can't alloc device descriptor\n"); 605 return -ENOMEM; 606 } 607 hid_set_drvdata(hdev, koneplus); 608 609 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); 610 if (retval) { 611 hid_err(hdev, "couldn't init struct koneplus_device\n"); 612 goto exit_free; 613 } 614 615 retval = roccat_connect(koneplus_class, hdev, 616 sizeof(struct koneplus_roccat_report)); 617 if (retval < 0) { 618 hid_err(hdev, "couldn't init char dev\n"); 619 } else { 620 koneplus->chrdev_minor = retval; 621 koneplus->roccat_claimed = 1; 622 } 623 } else { 624 hid_set_drvdata(hdev, NULL); 625 } 626 627 return 0; 628exit_free: 629 kfree(koneplus); 630 return retval; 631} 632 633static void koneplus_remove_specials(struct hid_device *hdev) 634{ 635 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 636 struct koneplus_device *koneplus; 637 638 if (intf->cur_altsetting->desc.bInterfaceProtocol 639 == USB_INTERFACE_PROTOCOL_MOUSE) { 640 koneplus = hid_get_drvdata(hdev); 641 if (koneplus->roccat_claimed) 642 roccat_disconnect(koneplus->chrdev_minor); 643 kfree(koneplus); 644 } 645} 646 647static int koneplus_probe(struct hid_device *hdev, 648 const struct hid_device_id *id) 649{ 650 int retval; 651 652 retval = hid_parse(hdev); 653 if (retval) { 654 hid_err(hdev, "parse failed\n"); 655 goto exit; 656 } 657 658 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 659 if (retval) { 660 hid_err(hdev, "hw start failed\n"); 661 goto exit; 662 } 663 664 retval = koneplus_init_specials(hdev); 665 if (retval) { 666 hid_err(hdev, "couldn't install mouse\n"); 667 goto exit_stop; 668 } 669 670 return 0; 671 672exit_stop: 673 hid_hw_stop(hdev); 674exit: 675 return retval; 676} 677 678static void koneplus_remove(struct hid_device *hdev) 679{ 680 koneplus_remove_specials(hdev); 681 hid_hw_stop(hdev); 682} 683 684static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, 685 u8 const *data) 686{ 687 struct koneplus_mouse_report_button const *button_report; 688 689 switch (data[0]) { 690 case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: 691 button_report = (struct koneplus_mouse_report_button const *)data; 692 switch (button_report->type) { 693 case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: 694 koneplus_profile_activated(koneplus, button_report->data1 - 1); 695 break; 696 } 697 break; 698 } 699} 700 701static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, 702 u8 const *data) 703{ 704 struct koneplus_roccat_report roccat_report; 705 struct koneplus_mouse_report_button const *button_report; 706 707 if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) 708 return; 709 710 button_report = (struct koneplus_mouse_report_button const *)data; 711 712 if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || 713 button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && 714 button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) 715 return; 716 717 roccat_report.type = button_report->type; 718 roccat_report.data1 = button_report->data1; 719 roccat_report.data2 = button_report->data2; 720 roccat_report.profile = koneplus->actual_profile + 1; 721 roccat_report_event(koneplus->chrdev_minor, 722 (uint8_t const *)&roccat_report); 723} 724 725static int koneplus_raw_event(struct hid_device *hdev, 726 struct hid_report *report, u8 *data, int size) 727{ 728 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 729 struct koneplus_device *koneplus = hid_get_drvdata(hdev); 730 731 if (intf->cur_altsetting->desc.bInterfaceProtocol 732 != USB_INTERFACE_PROTOCOL_MOUSE) 733 return 0; 734 735 koneplus_keep_values_up_to_date(koneplus, data); 736 737 if (koneplus->roccat_claimed) 738 koneplus_report_to_chrdev(koneplus, data); 739 740 return 0; 741} 742 743static const struct hid_device_id koneplus_devices[] = { 744 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 745 { } 746}; 747 748MODULE_DEVICE_TABLE(hid, koneplus_devices); 749 750static struct hid_driver koneplus_driver = { 751 .name = "koneplus", 752 .id_table = koneplus_devices, 753 .probe = koneplus_probe, 754 .remove = koneplus_remove, 755 .raw_event = koneplus_raw_event 756}; 757 758static int __init koneplus_init(void) 759{ 760 int retval; 761 762 /* class name has to be same as driver name */ 763 koneplus_class = class_create(THIS_MODULE, "koneplus"); 764 if (IS_ERR(koneplus_class)) 765 return PTR_ERR(koneplus_class); 766 koneplus_class->dev_attrs = koneplus_attributes; 767 koneplus_class->dev_bin_attrs = koneplus_bin_attributes; 768 769 retval = hid_register_driver(&koneplus_driver); 770 if (retval) 771 class_destroy(koneplus_class); 772 return retval; 773} 774 775static void __exit koneplus_exit(void) 776{ 777 hid_unregister_driver(&koneplus_driver); 778 class_destroy(koneplus_class); 779} 780 781module_init(koneplus_init); 782module_exit(koneplus_exit); 783 784MODULE_AUTHOR("Stefan Achatz"); 785MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); 786MODULE_LICENSE("GPL v2"); 787