hid-roccat-pyra.c (16571B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Roccat Pyra driver for Linux 4 * 5 * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> 6 */ 7 8/* 9 */ 10 11/* 12 * Roccat Pyra is a mobile gamer mouse which comes in wired and wireless 13 * variant. Wireless variant is not tested. 14 * Userland tools can be found at http://sourceforge.net/projects/roccat 15 */ 16 17#include <linux/device.h> 18#include <linux/input.h> 19#include <linux/hid.h> 20#include <linux/module.h> 21#include <linux/slab.h> 22#include <linux/hid-roccat.h> 23#include "hid-ids.h" 24#include "hid-roccat-common.h" 25#include "hid-roccat-pyra.h" 26 27static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 28 29/* pyra_class is used for creating sysfs attributes via roccat char device */ 30static struct class *pyra_class; 31 32static void profile_activated(struct pyra_device *pyra, 33 unsigned int new_profile) 34{ 35 if (new_profile >= ARRAY_SIZE(pyra->profile_settings)) 36 return; 37 pyra->actual_profile = new_profile; 38 pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; 39} 40 41static int pyra_send_control(struct usb_device *usb_dev, int value, 42 enum pyra_control_requests request) 43{ 44 struct roccat_common2_control control; 45 46 if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || 47 request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && 48 (value < 0 || value > 4)) 49 return -EINVAL; 50 51 control.command = ROCCAT_COMMON_COMMAND_CONTROL; 52 control.value = value; 53 control.request = request; 54 55 return roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL, 56 &control, sizeof(struct roccat_common2_control)); 57} 58 59static int pyra_get_profile_settings(struct usb_device *usb_dev, 60 struct pyra_profile_settings *buf, int number) 61{ 62 int retval; 63 retval = pyra_send_control(usb_dev, number, 64 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); 65 if (retval) 66 return retval; 67 return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, 68 buf, PYRA_SIZE_PROFILE_SETTINGS); 69} 70 71static int pyra_get_settings(struct usb_device *usb_dev, 72 struct pyra_settings *buf) 73{ 74 return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS, 75 buf, PYRA_SIZE_SETTINGS); 76} 77 78static int pyra_set_settings(struct usb_device *usb_dev, 79 struct pyra_settings const *settings) 80{ 81 return roccat_common2_send_with_status(usb_dev, 82 PYRA_COMMAND_SETTINGS, settings, 83 PYRA_SIZE_SETTINGS); 84} 85 86static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj, 87 char *buf, loff_t off, size_t count, 88 size_t real_size, uint command) 89{ 90 struct device *dev = kobj_to_dev(kobj)->parent->parent; 91 struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); 92 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 93 int retval; 94 95 if (off >= real_size) 96 return 0; 97 98 if (off != 0 || count != real_size) 99 return -EINVAL; 100 101 mutex_lock(&pyra->pyra_lock); 102 retval = roccat_common2_receive(usb_dev, command, buf, real_size); 103 mutex_unlock(&pyra->pyra_lock); 104 105 if (retval) 106 return retval; 107 108 return real_size; 109} 110 111static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj, 112 void const *buf, loff_t off, size_t count, 113 size_t real_size, uint command) 114{ 115 struct device *dev = kobj_to_dev(kobj)->parent->parent; 116 struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); 117 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 118 int retval; 119 120 if (off != 0 || count != real_size) 121 return -EINVAL; 122 123 mutex_lock(&pyra->pyra_lock); 124 retval = roccat_common2_send_with_status(usb_dev, command, (void *)buf, real_size); 125 mutex_unlock(&pyra->pyra_lock); 126 127 if (retval) 128 return retval; 129 130 return real_size; 131} 132 133#define PYRA_SYSFS_W(thingy, THINGY) \ 134static ssize_t pyra_sysfs_write_ ## thingy(struct file *fp, \ 135 struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 136 loff_t off, size_t count) \ 137{ \ 138 return pyra_sysfs_write(fp, kobj, buf, off, count, \ 139 PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \ 140} 141 142#define PYRA_SYSFS_R(thingy, THINGY) \ 143static ssize_t pyra_sysfs_read_ ## thingy(struct file *fp, \ 144 struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 145 loff_t off, size_t count) \ 146{ \ 147 return pyra_sysfs_read(fp, kobj, buf, off, count, \ 148 PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \ 149} 150 151#define PYRA_SYSFS_RW(thingy, THINGY) \ 152PYRA_SYSFS_W(thingy, THINGY) \ 153PYRA_SYSFS_R(thingy, THINGY) 154 155#define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 156PYRA_SYSFS_RW(thingy, THINGY); \ 157static struct bin_attribute bin_attr_##thingy = { \ 158 .attr = { .name = #thingy, .mode = 0660 }, \ 159 .size = PYRA_SIZE_ ## THINGY, \ 160 .read = pyra_sysfs_read_ ## thingy, \ 161 .write = pyra_sysfs_write_ ## thingy \ 162} 163 164#define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \ 165PYRA_SYSFS_R(thingy, THINGY); \ 166static struct bin_attribute bin_attr_##thingy = { \ 167 .attr = { .name = #thingy, .mode = 0440 }, \ 168 .size = PYRA_SIZE_ ## THINGY, \ 169 .read = pyra_sysfs_read_ ## thingy, \ 170} 171 172#define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \ 173PYRA_SYSFS_W(thingy, THINGY); \ 174static struct bin_attribute bin_attr_##thingy = { \ 175 .attr = { .name = #thingy, .mode = 0220 }, \ 176 .size = PYRA_SIZE_ ## THINGY, \ 177 .write = pyra_sysfs_write_ ## thingy \ 178} 179 180PYRA_BIN_ATTRIBUTE_W(control, CONTROL); 181PYRA_BIN_ATTRIBUTE_RW(info, INFO); 182PYRA_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS); 183PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS); 184 185static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, 186 struct kobject *kobj, struct bin_attribute *attr, char *buf, 187 loff_t off, size_t count) 188{ 189 struct device *dev = kobj_to_dev(kobj)->parent->parent; 190 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 191 ssize_t retval; 192 193 retval = pyra_send_control(usb_dev, *(uint *)(attr->private), 194 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); 195 if (retval) 196 return retval; 197 198 return pyra_sysfs_read(fp, kobj, buf, off, count, 199 PYRA_SIZE_PROFILE_SETTINGS, 200 PYRA_COMMAND_PROFILE_SETTINGS); 201} 202 203static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, 204 struct kobject *kobj, struct bin_attribute *attr, char *buf, 205 loff_t off, size_t count) 206{ 207 struct device *dev = kobj_to_dev(kobj)->parent->parent; 208 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 209 ssize_t retval; 210 211 retval = pyra_send_control(usb_dev, *(uint *)(attr->private), 212 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); 213 if (retval) 214 return retval; 215 216 return pyra_sysfs_read(fp, kobj, buf, off, count, 217 PYRA_SIZE_PROFILE_BUTTONS, 218 PYRA_COMMAND_PROFILE_BUTTONS); 219} 220 221#define PROFILE_ATTR(number) \ 222static struct bin_attribute bin_attr_profile##number##_settings = { \ 223 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 224 .size = PYRA_SIZE_PROFILE_SETTINGS, \ 225 .read = pyra_sysfs_read_profilex_settings, \ 226 .private = &profile_numbers[number-1], \ 227}; \ 228static struct bin_attribute bin_attr_profile##number##_buttons = { \ 229 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 230 .size = PYRA_SIZE_PROFILE_BUTTONS, \ 231 .read = pyra_sysfs_read_profilex_buttons, \ 232 .private = &profile_numbers[number-1], \ 233}; 234PROFILE_ATTR(1); 235PROFILE_ATTR(2); 236PROFILE_ATTR(3); 237PROFILE_ATTR(4); 238PROFILE_ATTR(5); 239 240static ssize_t pyra_sysfs_write_settings(struct file *fp, 241 struct kobject *kobj, struct bin_attribute *attr, char *buf, 242 loff_t off, size_t count) 243{ 244 struct device *dev = kobj_to_dev(kobj)->parent->parent; 245 struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); 246 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 247 int retval = 0; 248 struct pyra_roccat_report roccat_report; 249 struct pyra_settings const *settings; 250 251 if (off != 0 || count != PYRA_SIZE_SETTINGS) 252 return -EINVAL; 253 254 settings = (struct pyra_settings const *)buf; 255 if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings)) 256 return -EINVAL; 257 258 mutex_lock(&pyra->pyra_lock); 259 260 retval = pyra_set_settings(usb_dev, settings); 261 if (retval) { 262 mutex_unlock(&pyra->pyra_lock); 263 return retval; 264 } 265 266 profile_activated(pyra, settings->startup_profile); 267 268 roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2; 269 roccat_report.value = settings->startup_profile + 1; 270 roccat_report.key = 0; 271 roccat_report_event(pyra->chrdev_minor, 272 (uint8_t const *)&roccat_report); 273 274 mutex_unlock(&pyra->pyra_lock); 275 return PYRA_SIZE_SETTINGS; 276} 277 278PYRA_SYSFS_R(settings, SETTINGS); 279static struct bin_attribute bin_attr_settings = 280 __BIN_ATTR(settings, (S_IWUSR | S_IRUGO), 281 pyra_sysfs_read_settings, pyra_sysfs_write_settings, 282 PYRA_SIZE_SETTINGS); 283 284static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev, 285 struct device_attribute *attr, char *buf) 286{ 287 struct pyra_device *pyra = 288 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 289 return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); 290} 291static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL); 292 293static ssize_t pyra_sysfs_show_actual_profile(struct device *dev, 294 struct device_attribute *attr, char *buf) 295{ 296 struct pyra_device *pyra = 297 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 298 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 299 struct pyra_settings settings; 300 301 mutex_lock(&pyra->pyra_lock); 302 roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS, 303 &settings, PYRA_SIZE_SETTINGS); 304 mutex_unlock(&pyra->pyra_lock); 305 306 return snprintf(buf, PAGE_SIZE, "%d\n", settings.startup_profile); 307} 308static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL); 309static DEVICE_ATTR(startup_profile, 0440, pyra_sysfs_show_actual_profile, NULL); 310 311static ssize_t pyra_sysfs_show_firmware_version(struct device *dev, 312 struct device_attribute *attr, char *buf) 313{ 314 struct pyra_device *pyra; 315 struct usb_device *usb_dev; 316 struct pyra_info info; 317 318 dev = dev->parent->parent; 319 pyra = hid_get_drvdata(dev_get_drvdata(dev)); 320 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 321 322 mutex_lock(&pyra->pyra_lock); 323 roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO, 324 &info, PYRA_SIZE_INFO); 325 mutex_unlock(&pyra->pyra_lock); 326 327 return snprintf(buf, PAGE_SIZE, "%d\n", info.firmware_version); 328} 329static DEVICE_ATTR(firmware_version, 0440, pyra_sysfs_show_firmware_version, 330 NULL); 331 332static struct attribute *pyra_attrs[] = { 333 &dev_attr_actual_cpi.attr, 334 &dev_attr_actual_profile.attr, 335 &dev_attr_firmware_version.attr, 336 &dev_attr_startup_profile.attr, 337 NULL, 338}; 339 340static struct bin_attribute *pyra_bin_attributes[] = { 341 &bin_attr_control, 342 &bin_attr_info, 343 &bin_attr_profile_settings, 344 &bin_attr_profile_buttons, 345 &bin_attr_settings, 346 &bin_attr_profile1_settings, 347 &bin_attr_profile2_settings, 348 &bin_attr_profile3_settings, 349 &bin_attr_profile4_settings, 350 &bin_attr_profile5_settings, 351 &bin_attr_profile1_buttons, 352 &bin_attr_profile2_buttons, 353 &bin_attr_profile3_buttons, 354 &bin_attr_profile4_buttons, 355 &bin_attr_profile5_buttons, 356 NULL, 357}; 358 359static const struct attribute_group pyra_group = { 360 .attrs = pyra_attrs, 361 .bin_attrs = pyra_bin_attributes, 362}; 363 364static const struct attribute_group *pyra_groups[] = { 365 &pyra_group, 366 NULL, 367}; 368 369static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, 370 struct pyra_device *pyra) 371{ 372 struct pyra_settings settings; 373 int retval, i; 374 375 mutex_init(&pyra->pyra_lock); 376 377 retval = pyra_get_settings(usb_dev, &settings); 378 if (retval) 379 return retval; 380 381 for (i = 0; i < 5; ++i) { 382 retval = pyra_get_profile_settings(usb_dev, 383 &pyra->profile_settings[i], i); 384 if (retval) 385 return retval; 386 } 387 388 profile_activated(pyra, settings.startup_profile); 389 390 return 0; 391} 392 393static int pyra_init_specials(struct hid_device *hdev) 394{ 395 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 396 struct usb_device *usb_dev = interface_to_usbdev(intf); 397 struct pyra_device *pyra; 398 int retval; 399 400 if (intf->cur_altsetting->desc.bInterfaceProtocol 401 == USB_INTERFACE_PROTOCOL_MOUSE) { 402 403 pyra = kzalloc(sizeof(*pyra), GFP_KERNEL); 404 if (!pyra) { 405 hid_err(hdev, "can't alloc device descriptor\n"); 406 return -ENOMEM; 407 } 408 hid_set_drvdata(hdev, pyra); 409 410 retval = pyra_init_pyra_device_struct(usb_dev, pyra); 411 if (retval) { 412 hid_err(hdev, "couldn't init struct pyra_device\n"); 413 goto exit_free; 414 } 415 416 retval = roccat_connect(pyra_class, hdev, 417 sizeof(struct pyra_roccat_report)); 418 if (retval < 0) { 419 hid_err(hdev, "couldn't init char dev\n"); 420 } else { 421 pyra->chrdev_minor = retval; 422 pyra->roccat_claimed = 1; 423 } 424 } else { 425 hid_set_drvdata(hdev, NULL); 426 } 427 428 return 0; 429exit_free: 430 kfree(pyra); 431 return retval; 432} 433 434static void pyra_remove_specials(struct hid_device *hdev) 435{ 436 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 437 struct pyra_device *pyra; 438 439 if (intf->cur_altsetting->desc.bInterfaceProtocol 440 == USB_INTERFACE_PROTOCOL_MOUSE) { 441 pyra = hid_get_drvdata(hdev); 442 if (pyra->roccat_claimed) 443 roccat_disconnect(pyra->chrdev_minor); 444 kfree(hid_get_drvdata(hdev)); 445 } 446} 447 448static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) 449{ 450 int retval; 451 452 if (!hid_is_usb(hdev)) 453 return -EINVAL; 454 455 retval = hid_parse(hdev); 456 if (retval) { 457 hid_err(hdev, "parse failed\n"); 458 goto exit; 459 } 460 461 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 462 if (retval) { 463 hid_err(hdev, "hw start failed\n"); 464 goto exit; 465 } 466 467 retval = pyra_init_specials(hdev); 468 if (retval) { 469 hid_err(hdev, "couldn't install mouse\n"); 470 goto exit_stop; 471 } 472 return 0; 473 474exit_stop: 475 hid_hw_stop(hdev); 476exit: 477 return retval; 478} 479 480static void pyra_remove(struct hid_device *hdev) 481{ 482 pyra_remove_specials(hdev); 483 hid_hw_stop(hdev); 484} 485 486static void pyra_keep_values_up_to_date(struct pyra_device *pyra, 487 u8 const *data) 488{ 489 struct pyra_mouse_event_button const *button_event; 490 491 switch (data[0]) { 492 case PYRA_MOUSE_REPORT_NUMBER_BUTTON: 493 button_event = (struct pyra_mouse_event_button const *)data; 494 switch (button_event->type) { 495 case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: 496 profile_activated(pyra, button_event->data1 - 1); 497 break; 498 case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: 499 pyra->actual_cpi = button_event->data1; 500 break; 501 } 502 break; 503 } 504} 505 506static void pyra_report_to_chrdev(struct pyra_device const *pyra, 507 u8 const *data) 508{ 509 struct pyra_roccat_report roccat_report; 510 struct pyra_mouse_event_button const *button_event; 511 512 if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON) 513 return; 514 515 button_event = (struct pyra_mouse_event_button const *)data; 516 517 switch (button_event->type) { 518 case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: 519 case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: 520 roccat_report.type = button_event->type; 521 roccat_report.value = button_event->data1; 522 roccat_report.key = 0; 523 roccat_report_event(pyra->chrdev_minor, 524 (uint8_t const *)&roccat_report); 525 break; 526 case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: 527 case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: 528 case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH: 529 if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) { 530 roccat_report.type = button_event->type; 531 roccat_report.key = button_event->data1; 532 /* 533 * pyra reports profile numbers with range 1-5. 534 * Keeping this behaviour. 535 */ 536 roccat_report.value = pyra->actual_profile + 1; 537 roccat_report_event(pyra->chrdev_minor, 538 (uint8_t const *)&roccat_report); 539 } 540 break; 541 } 542} 543 544static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, 545 u8 *data, int size) 546{ 547 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 548 struct pyra_device *pyra = hid_get_drvdata(hdev); 549 550 if (intf->cur_altsetting->desc.bInterfaceProtocol 551 != USB_INTERFACE_PROTOCOL_MOUSE) 552 return 0; 553 554 if (pyra == NULL) 555 return 0; 556 557 pyra_keep_values_up_to_date(pyra, data); 558 559 if (pyra->roccat_claimed) 560 pyra_report_to_chrdev(pyra, data); 561 562 return 0; 563} 564 565static const struct hid_device_id pyra_devices[] = { 566 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, 567 USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, 568 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, 569 USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, 570 { } 571}; 572 573MODULE_DEVICE_TABLE(hid, pyra_devices); 574 575static struct hid_driver pyra_driver = { 576 .name = "pyra", 577 .id_table = pyra_devices, 578 .probe = pyra_probe, 579 .remove = pyra_remove, 580 .raw_event = pyra_raw_event 581}; 582 583static int __init pyra_init(void) 584{ 585 int retval; 586 587 /* class name has to be same as driver name */ 588 pyra_class = class_create(THIS_MODULE, "pyra"); 589 if (IS_ERR(pyra_class)) 590 return PTR_ERR(pyra_class); 591 pyra_class->dev_groups = pyra_groups; 592 593 retval = hid_register_driver(&pyra_driver); 594 if (retval) 595 class_destroy(pyra_class); 596 return retval; 597} 598 599static void __exit pyra_exit(void) 600{ 601 hid_unregister_driver(&pyra_driver); 602 class_destroy(pyra_class); 603} 604 605module_init(pyra_init); 606module_exit(pyra_exit); 607 608MODULE_AUTHOR("Stefan Achatz"); 609MODULE_DESCRIPTION("USB Roccat Pyra driver"); 610MODULE_LICENSE("GPL v2");