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