hid-roccat-koneplus.c revision 6d1dec85afa7306e66fff633689ff06195ad079a
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_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_USB_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_USB_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_USB_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_USB_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_USB_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_USB_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_USB_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_USB_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 mutex_lock(&koneplus->koneplus_lock); 435 436 retval = koneplus_set_actual_profile(usb_dev, profile); 437 if (retval) { 438 mutex_unlock(&koneplus->koneplus_lock); 439 return retval; 440 } 441 442 koneplus->actual_profile = profile; 443 444 roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; 445 roccat_report.data1 = profile + 1; 446 roccat_report.data2 = 0; 447 roccat_report.profile = profile + 1; 448 roccat_report_event(koneplus->chrdev_minor, 449 (uint8_t const *)&roccat_report); 450 451 mutex_unlock(&koneplus->koneplus_lock); 452 453 return size; 454} 455 456static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, 457 struct device_attribute *attr, char *buf) 458{ 459 struct koneplus_device *koneplus = 460 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 461 return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version); 462} 463 464static struct device_attribute koneplus_attributes[] = { 465 __ATTR(actual_profile, 0660, 466 koneplus_sysfs_show_actual_profile, 467 koneplus_sysfs_set_actual_profile), 468 __ATTR(startup_profile, 0660, 469 koneplus_sysfs_show_actual_profile, 470 koneplus_sysfs_set_actual_profile), 471 __ATTR(firmware_version, 0440, 472 koneplus_sysfs_show_firmware_version, NULL), 473 __ATTR_NULL 474}; 475 476static struct bin_attribute koneplus_bin_attributes[] = { 477 { 478 .attr = { .name = "sensor", .mode = 0660 }, 479 .size = sizeof(struct koneplus_sensor), 480 .read = koneplus_sysfs_read_sensor, 481 .write = koneplus_sysfs_write_sensor 482 }, 483 { 484 .attr = { .name = "tcu", .mode = 0220 }, 485 .size = sizeof(struct koneplus_tcu), 486 .write = koneplus_sysfs_write_tcu 487 }, 488 { 489 .attr = { .name = "tcu_image", .mode = 0440 }, 490 .size = sizeof(struct koneplus_tcu_image), 491 .read = koneplus_sysfs_read_tcu_image 492 }, 493 { 494 .attr = { .name = "profile_settings", .mode = 0220 }, 495 .size = sizeof(struct koneplus_profile_settings), 496 .write = koneplus_sysfs_write_profile_settings 497 }, 498 { 499 .attr = { .name = "profile1_settings", .mode = 0440 }, 500 .size = sizeof(struct koneplus_profile_settings), 501 .read = koneplus_sysfs_read_profilex_settings, 502 .private = &profile_numbers[0] 503 }, 504 { 505 .attr = { .name = "profile2_settings", .mode = 0440 }, 506 .size = sizeof(struct koneplus_profile_settings), 507 .read = koneplus_sysfs_read_profilex_settings, 508 .private = &profile_numbers[1] 509 }, 510 { 511 .attr = { .name = "profile3_settings", .mode = 0440 }, 512 .size = sizeof(struct koneplus_profile_settings), 513 .read = koneplus_sysfs_read_profilex_settings, 514 .private = &profile_numbers[2] 515 }, 516 { 517 .attr = { .name = "profile4_settings", .mode = 0440 }, 518 .size = sizeof(struct koneplus_profile_settings), 519 .read = koneplus_sysfs_read_profilex_settings, 520 .private = &profile_numbers[3] 521 }, 522 { 523 .attr = { .name = "profile5_settings", .mode = 0440 }, 524 .size = sizeof(struct koneplus_profile_settings), 525 .read = koneplus_sysfs_read_profilex_settings, 526 .private = &profile_numbers[4] 527 }, 528 { 529 .attr = { .name = "profile_buttons", .mode = 0220 }, 530 .size = sizeof(struct koneplus_profile_buttons), 531 .write = koneplus_sysfs_write_profile_buttons 532 }, 533 { 534 .attr = { .name = "profile1_buttons", .mode = 0440 }, 535 .size = sizeof(struct koneplus_profile_buttons), 536 .read = koneplus_sysfs_read_profilex_buttons, 537 .private = &profile_numbers[0] 538 }, 539 { 540 .attr = { .name = "profile2_buttons", .mode = 0440 }, 541 .size = sizeof(struct koneplus_profile_buttons), 542 .read = koneplus_sysfs_read_profilex_buttons, 543 .private = &profile_numbers[1] 544 }, 545 { 546 .attr = { .name = "profile3_buttons", .mode = 0440 }, 547 .size = sizeof(struct koneplus_profile_buttons), 548 .read = koneplus_sysfs_read_profilex_buttons, 549 .private = &profile_numbers[2] 550 }, 551 { 552 .attr = { .name = "profile4_buttons", .mode = 0440 }, 553 .size = sizeof(struct koneplus_profile_buttons), 554 .read = koneplus_sysfs_read_profilex_buttons, 555 .private = &profile_numbers[3] 556 }, 557 { 558 .attr = { .name = "profile5_buttons", .mode = 0440 }, 559 .size = sizeof(struct koneplus_profile_buttons), 560 .read = koneplus_sysfs_read_profilex_buttons, 561 .private = &profile_numbers[4] 562 }, 563 { 564 .attr = { .name = "macro", .mode = 0220 }, 565 .size = sizeof(struct koneplus_macro), 566 .write = koneplus_sysfs_write_macro 567 }, 568 { 569 .attr = { .name = "talk", .mode = 0220 }, 570 .size = sizeof(struct koneplus_talk), 571 .write = koneplus_sysfs_write_talk 572 }, 573 __ATTR_NULL 574}; 575 576static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, 577 struct koneplus_device *koneplus) 578{ 579 int retval, i; 580 static uint wait = 200; 581 582 mutex_init(&koneplus->koneplus_lock); 583 584 retval = koneplus_get_info(usb_dev, &koneplus->info); 585 if (retval) 586 return retval; 587 588 for (i = 0; i < 5; ++i) { 589 msleep(wait); 590 retval = koneplus_get_profile_settings(usb_dev, 591 &koneplus->profile_settings[i], i); 592 if (retval) 593 return retval; 594 595 msleep(wait); 596 retval = koneplus_get_profile_buttons(usb_dev, 597 &koneplus->profile_buttons[i], i); 598 if (retval) 599 return retval; 600 } 601 602 msleep(wait); 603 retval = koneplus_get_actual_profile(usb_dev); 604 if (retval < 0) 605 return retval; 606 koneplus_profile_activated(koneplus, retval); 607 608 return 0; 609} 610 611static int koneplus_init_specials(struct hid_device *hdev) 612{ 613 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 614 struct usb_device *usb_dev = interface_to_usbdev(intf); 615 struct koneplus_device *koneplus; 616 int retval; 617 618 if (intf->cur_altsetting->desc.bInterfaceProtocol 619 == USB_INTERFACE_PROTOCOL_MOUSE) { 620 621 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); 622 if (!koneplus) { 623 hid_err(hdev, "can't alloc device descriptor\n"); 624 return -ENOMEM; 625 } 626 hid_set_drvdata(hdev, koneplus); 627 628 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); 629 if (retval) { 630 hid_err(hdev, "couldn't init struct koneplus_device\n"); 631 goto exit_free; 632 } 633 634 retval = roccat_connect(koneplus_class, hdev, 635 sizeof(struct koneplus_roccat_report)); 636 if (retval < 0) { 637 hid_err(hdev, "couldn't init char dev\n"); 638 } else { 639 koneplus->chrdev_minor = retval; 640 koneplus->roccat_claimed = 1; 641 } 642 } else { 643 hid_set_drvdata(hdev, NULL); 644 } 645 646 return 0; 647exit_free: 648 kfree(koneplus); 649 return retval; 650} 651 652static void koneplus_remove_specials(struct hid_device *hdev) 653{ 654 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 655 struct koneplus_device *koneplus; 656 657 if (intf->cur_altsetting->desc.bInterfaceProtocol 658 == USB_INTERFACE_PROTOCOL_MOUSE) { 659 koneplus = hid_get_drvdata(hdev); 660 if (koneplus->roccat_claimed) 661 roccat_disconnect(koneplus->chrdev_minor); 662 kfree(koneplus); 663 } 664} 665 666static int koneplus_probe(struct hid_device *hdev, 667 const struct hid_device_id *id) 668{ 669 int retval; 670 671 retval = hid_parse(hdev); 672 if (retval) { 673 hid_err(hdev, "parse failed\n"); 674 goto exit; 675 } 676 677 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 678 if (retval) { 679 hid_err(hdev, "hw start failed\n"); 680 goto exit; 681 } 682 683 retval = koneplus_init_specials(hdev); 684 if (retval) { 685 hid_err(hdev, "couldn't install mouse\n"); 686 goto exit_stop; 687 } 688 689 return 0; 690 691exit_stop: 692 hid_hw_stop(hdev); 693exit: 694 return retval; 695} 696 697static void koneplus_remove(struct hid_device *hdev) 698{ 699 koneplus_remove_specials(hdev); 700 hid_hw_stop(hdev); 701} 702 703static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, 704 u8 const *data) 705{ 706 struct koneplus_mouse_report_button const *button_report; 707 708 switch (data[0]) { 709 case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: 710 button_report = (struct koneplus_mouse_report_button const *)data; 711 switch (button_report->type) { 712 case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: 713 koneplus_profile_activated(koneplus, button_report->data1 - 1); 714 break; 715 } 716 break; 717 } 718} 719 720static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, 721 u8 const *data) 722{ 723 struct koneplus_roccat_report roccat_report; 724 struct koneplus_mouse_report_button const *button_report; 725 726 if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) 727 return; 728 729 button_report = (struct koneplus_mouse_report_button const *)data; 730 731 if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || 732 button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && 733 button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) 734 return; 735 736 roccat_report.type = button_report->type; 737 roccat_report.data1 = button_report->data1; 738 roccat_report.data2 = button_report->data2; 739 roccat_report.profile = koneplus->actual_profile + 1; 740 roccat_report_event(koneplus->chrdev_minor, 741 (uint8_t const *)&roccat_report); 742} 743 744static int koneplus_raw_event(struct hid_device *hdev, 745 struct hid_report *report, u8 *data, int size) 746{ 747 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 748 struct koneplus_device *koneplus = hid_get_drvdata(hdev); 749 750 if (intf->cur_altsetting->desc.bInterfaceProtocol 751 != USB_INTERFACE_PROTOCOL_MOUSE) 752 return 0; 753 754 koneplus_keep_values_up_to_date(koneplus, data); 755 756 if (koneplus->roccat_claimed) 757 koneplus_report_to_chrdev(koneplus, data); 758 759 return 0; 760} 761 762static const struct hid_device_id koneplus_devices[] = { 763 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 764 { } 765}; 766 767MODULE_DEVICE_TABLE(hid, koneplus_devices); 768 769static struct hid_driver koneplus_driver = { 770 .name = "koneplus", 771 .id_table = koneplus_devices, 772 .probe = koneplus_probe, 773 .remove = koneplus_remove, 774 .raw_event = koneplus_raw_event 775}; 776 777static int __init koneplus_init(void) 778{ 779 int retval; 780 781 /* class name has to be same as driver name */ 782 koneplus_class = class_create(THIS_MODULE, "koneplus"); 783 if (IS_ERR(koneplus_class)) 784 return PTR_ERR(koneplus_class); 785 koneplus_class->dev_attrs = koneplus_attributes; 786 koneplus_class->dev_bin_attrs = koneplus_bin_attributes; 787 788 retval = hid_register_driver(&koneplus_driver); 789 if (retval) 790 class_destroy(koneplus_class); 791 return retval; 792} 793 794static void __exit koneplus_exit(void) 795{ 796 hid_unregister_driver(&koneplus_driver); 797 class_destroy(koneplus_class); 798} 799 800module_init(koneplus_init); 801module_exit(koneplus_exit); 802 803MODULE_AUTHOR("Stefan Achatz"); 804MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); 805MODULE_LICENSE("GPL v2"); 806