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