1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Roccat Arvo driver for Linux 4 * 5 * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> 6 */ 7 8 /* 9 */ 10 11 /* 12 * Roccat Arvo is a gamer keyboard with 5 macro keys that can be configured in 13 * 5 profiles. 14 */ 15 16 #include <linux/device.h> 17 #include <linux/input.h> 18 #include <linux/hid.h> 19 #include <linux/module.h> 20 #include <linux/slab.h> 21 #include <linux/hid-roccat.h> 22 #include "hid-ids.h" 23 #include "hid-roccat-common.h" 24 #include "hid-roccat-arvo.h" 25 26 static ssize_t arvo_sysfs_show_mode_key(struct device *dev, 27 struct device_attribute *attr, char *buf) 28 { 29 struct arvo_device *arvo = 30 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 31 struct usb_device *usb_dev = 32 interface_to_usbdev(to_usb_interface(dev->parent->parent)); 33 struct arvo_mode_key temp_buf; 34 int retval; 35 36 mutex_lock(&arvo->arvo_lock); 37 retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_MODE_KEY, 38 &temp_buf, sizeof(struct arvo_mode_key)); 39 mutex_unlock(&arvo->arvo_lock); 40 if (retval) 41 return retval; 42 43 return sysfs_emit(buf, "%d\n", temp_buf.state); 44 } 45 46 static ssize_t arvo_sysfs_set_mode_key(struct device *dev, 47 struct device_attribute *attr, char const *buf, size_t size) 48 { 49 struct arvo_device *arvo = 50 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 51 struct usb_device *usb_dev = 52 interface_to_usbdev(to_usb_interface(dev->parent->parent)); 53 struct arvo_mode_key temp_buf; 54 unsigned long state; 55 int retval; 56 57 retval = kstrtoul(buf, 10, &state); 58 if (retval) 59 return retval; 60 61 temp_buf.command = ARVO_COMMAND_MODE_KEY; 62 temp_buf.state = state; 63 64 mutex_lock(&arvo->arvo_lock); 65 retval = roccat_common2_send(usb_dev, ARVO_COMMAND_MODE_KEY, 66 &temp_buf, sizeof(struct arvo_mode_key)); 67 mutex_unlock(&arvo->arvo_lock); 68 if (retval) 69 return retval; 70 71 return size; 72 } 73 static DEVICE_ATTR(mode_key, 0660, 74 arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key); 75 76 static ssize_t arvo_sysfs_show_key_mask(struct device *dev, 77 struct device_attribute *attr, char *buf) 78 { 79 struct arvo_device *arvo = 80 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 81 struct usb_device *usb_dev = 82 interface_to_usbdev(to_usb_interface(dev->parent->parent)); 83 struct arvo_key_mask temp_buf; 84 int retval; 85 86 mutex_lock(&arvo->arvo_lock); 87 retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_KEY_MASK, 88 &temp_buf, sizeof(struct arvo_key_mask)); 89 mutex_unlock(&arvo->arvo_lock); 90 if (retval) 91 return retval; 92 93 return sysfs_emit(buf, "%d\n", temp_buf.key_mask); 94 } 95 96 static ssize_t arvo_sysfs_set_key_mask(struct device *dev, 97 struct device_attribute *attr, char const *buf, size_t size) 98 { 99 struct arvo_device *arvo = 100 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 101 struct usb_device *usb_dev = 102 interface_to_usbdev(to_usb_interface(dev->parent->parent)); 103 struct arvo_key_mask temp_buf; 104 unsigned long key_mask; 105 int retval; 106 107 retval = kstrtoul(buf, 10, &key_mask); 108 if (retval) 109 return retval; 110 111 temp_buf.command = ARVO_COMMAND_KEY_MASK; 112 temp_buf.key_mask = key_mask; 113 114 mutex_lock(&arvo->arvo_lock); 115 retval = roccat_common2_send(usb_dev, ARVO_COMMAND_KEY_MASK, 116 &temp_buf, sizeof(struct arvo_key_mask)); 117 mutex_unlock(&arvo->arvo_lock); 118 if (retval) 119 return retval; 120 121 return size; 122 } 123 static DEVICE_ATTR(key_mask, 0660, 124 arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask); 125 126 /* retval is 1-5 on success, < 0 on error */ 127 static int arvo_get_actual_profile(struct usb_device *usb_dev) 128 { 129 struct arvo_actual_profile temp_buf; 130 int retval; 131 132 retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, 133 &temp_buf, sizeof(struct arvo_actual_profile)); 134 135 if (retval) 136 return retval; 137 138 return temp_buf.actual_profile; 139 } 140 141 static ssize_t arvo_sysfs_show_actual_profile(struct device *dev, 142 struct device_attribute *attr, char *buf) 143 { 144 struct arvo_device *arvo = 145 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 146 147 return sysfs_emit(buf, "%d\n", arvo->actual_profile); 148 } 149 150 static ssize_t arvo_sysfs_set_actual_profile(struct device *dev, 151 struct device_attribute *attr, char const *buf, size_t size) 152 { 153 struct arvo_device *arvo = 154 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 155 struct usb_device *usb_dev = 156 interface_to_usbdev(to_usb_interface(dev->parent->parent)); 157 struct arvo_actual_profile temp_buf; 158 unsigned long profile; 159 int retval; 160 161 retval = kstrtoul(buf, 10, &profile); 162 if (retval) 163 return retval; 164 165 if (profile < 1 || profile > 5) 166 return -EINVAL; 167 168 temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE; 169 temp_buf.actual_profile = profile; 170 171 mutex_lock(&arvo->arvo_lock); 172 retval = roccat_common2_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, 173 &temp_buf, sizeof(struct arvo_actual_profile)); 174 if (!retval) { 175 arvo->actual_profile = profile; 176 retval = size; 177 } 178 mutex_unlock(&arvo->arvo_lock); 179 return retval; 180 } 181 static DEVICE_ATTR(actual_profile, 0660, 182 arvo_sysfs_show_actual_profile, 183 arvo_sysfs_set_actual_profile); 184 185 static ssize_t arvo_sysfs_write(struct file *fp, 186 struct kobject *kobj, void const *buf, 187 loff_t off, size_t count, size_t real_size, uint command) 188 { 189 struct device *dev = kobj_to_dev(kobj)->parent->parent; 190 struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); 191 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 192 int retval; 193 194 if (off != 0 || count != real_size) 195 return -EINVAL; 196 197 mutex_lock(&arvo->arvo_lock); 198 retval = roccat_common2_send(usb_dev, command, buf, real_size); 199 mutex_unlock(&arvo->arvo_lock); 200 201 return (retval ? retval : real_size); 202 } 203 204 static ssize_t arvo_sysfs_read(struct file *fp, 205 struct kobject *kobj, void *buf, loff_t off, 206 size_t count, size_t real_size, uint command) 207 { 208 struct device *dev = kobj_to_dev(kobj)->parent->parent; 209 struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); 210 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 211 int retval; 212 213 if (off >= real_size) 214 return 0; 215 216 if (off != 0 || count != real_size) 217 return -EINVAL; 218 219 mutex_lock(&arvo->arvo_lock); 220 retval = roccat_common2_receive(usb_dev, command, buf, real_size); 221 mutex_unlock(&arvo->arvo_lock); 222 223 return (retval ? retval : real_size); 224 } 225 226 static ssize_t arvo_sysfs_write_button(struct file *fp, 227 struct kobject *kobj, struct bin_attribute *attr, char *buf, 228 loff_t off, size_t count) 229 { 230 return arvo_sysfs_write(fp, kobj, buf, off, count, 231 sizeof(struct arvo_button), ARVO_COMMAND_BUTTON); 232 } 233 static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button, 234 sizeof(struct arvo_button)); 235 236 static ssize_t arvo_sysfs_read_info(struct file *fp, 237 struct kobject *kobj, struct bin_attribute *attr, char *buf, 238 loff_t off, size_t count) 239 { 240 return arvo_sysfs_read(fp, kobj, buf, off, count, 241 sizeof(struct arvo_info), ARVO_COMMAND_INFO); 242 } 243 static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL, 244 sizeof(struct arvo_info)); 245 246 static struct attribute *arvo_attrs[] = { 247 &dev_attr_mode_key.attr, 248 &dev_attr_key_mask.attr, 249 &dev_attr_actual_profile.attr, 250 NULL, 251 }; 252 253 static struct bin_attribute *arvo_bin_attributes[] = { 254 &bin_attr_button, 255 &bin_attr_info, 256 NULL, 257 }; 258 259 static const struct attribute_group arvo_group = { 260 .attrs = arvo_attrs, 261 .bin_attrs = arvo_bin_attributes, 262 }; 263 264 static const struct attribute_group *arvo_groups[] = { 265 &arvo_group, 266 NULL, 267 }; 268 269 static const struct class arvo_class = { 270 .name = "arvo", 271 .dev_groups = arvo_groups, 272 }; 273 274 static int arvo_init_arvo_device_struct(struct usb_device *usb_dev, 275 struct arvo_device *arvo) 276 { 277 int retval; 278 279 mutex_init(&arvo->arvo_lock); 280 281 retval = arvo_get_actual_profile(usb_dev); 282 if (retval < 0) 283 return retval; 284 arvo->actual_profile = retval; 285 286 return 0; 287 } 288 289 static int arvo_init_specials(struct hid_device *hdev) 290 { 291 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 292 struct usb_device *usb_dev = interface_to_usbdev(intf); 293 struct arvo_device *arvo; 294 int retval; 295 296 if (intf->cur_altsetting->desc.bInterfaceProtocol 297 == USB_INTERFACE_PROTOCOL_KEYBOARD) { 298 hid_set_drvdata(hdev, NULL); 299 return 0; 300 } 301 302 arvo = kzalloc(sizeof(*arvo), GFP_KERNEL); 303 if (!arvo) { 304 hid_err(hdev, "can't alloc device descriptor\n"); 305 return -ENOMEM; 306 } 307 hid_set_drvdata(hdev, arvo); 308 309 retval = arvo_init_arvo_device_struct(usb_dev, arvo); 310 if (retval) { 311 hid_err(hdev, "couldn't init struct arvo_device\n"); 312 goto exit_free; 313 } 314 315 retval = roccat_connect(&arvo_class, hdev, 316 sizeof(struct arvo_roccat_report)); 317 if (retval < 0) { 318 hid_err(hdev, "couldn't init char dev\n"); 319 } else { 320 arvo->chrdev_minor = retval; 321 arvo->roccat_claimed = 1; 322 } 323 324 return 0; 325 exit_free: 326 kfree(arvo); 327 return retval; 328 } 329 330 static void arvo_remove_specials(struct hid_device *hdev) 331 { 332 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 333 struct arvo_device *arvo; 334 335 if (intf->cur_altsetting->desc.bInterfaceProtocol 336 == USB_INTERFACE_PROTOCOL_KEYBOARD) 337 return; 338 339 arvo = hid_get_drvdata(hdev); 340 if (arvo->roccat_claimed) 341 roccat_disconnect(arvo->chrdev_minor); 342 kfree(arvo); 343 } 344 345 static int arvo_probe(struct hid_device *hdev, 346 const struct hid_device_id *id) 347 { 348 int retval; 349 350 if (!hid_is_usb(hdev)) 351 return -EINVAL; 352 353 retval = hid_parse(hdev); 354 if (retval) { 355 hid_err(hdev, "parse failed\n"); 356 goto exit; 357 } 358 359 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 360 if (retval) { 361 hid_err(hdev, "hw start failed\n"); 362 goto exit; 363 } 364 365 retval = arvo_init_specials(hdev); 366 if (retval) { 367 hid_err(hdev, "couldn't install keyboard\n"); 368 goto exit_stop; 369 } 370 371 return 0; 372 373 exit_stop: 374 hid_hw_stop(hdev); 375 exit: 376 return retval; 377 } 378 379 static void arvo_remove(struct hid_device *hdev) 380 { 381 arvo_remove_specials(hdev); 382 hid_hw_stop(hdev); 383 } 384 385 static void arvo_report_to_chrdev(struct arvo_device const *arvo, 386 u8 const *data) 387 { 388 struct arvo_special_report const *special_report; 389 struct arvo_roccat_report roccat_report; 390 391 special_report = (struct arvo_special_report const *)data; 392 393 roccat_report.profile = arvo->actual_profile; 394 roccat_report.button = special_report->event & 395 ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON; 396 if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) == 397 ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS) 398 roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS; 399 else 400 roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE; 401 402 roccat_report_event(arvo->chrdev_minor, 403 (uint8_t const *)&roccat_report); 404 } 405 406 static int arvo_raw_event(struct hid_device *hdev, 407 struct hid_report *report, u8 *data, int size) 408 { 409 struct arvo_device *arvo = hid_get_drvdata(hdev); 410 411 if (size != 3) 412 return 0; 413 414 if (arvo && arvo->roccat_claimed) 415 arvo_report_to_chrdev(arvo, data); 416 417 return 0; 418 } 419 420 static const struct hid_device_id arvo_devices[] = { 421 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, 422 { } 423 }; 424 425 MODULE_DEVICE_TABLE(hid, arvo_devices); 426 427 static struct hid_driver arvo_driver = { 428 .name = "arvo", 429 .id_table = arvo_devices, 430 .probe = arvo_probe, 431 .remove = arvo_remove, 432 .raw_event = arvo_raw_event 433 }; 434 435 static int __init arvo_init(void) 436 { 437 int retval; 438 439 retval = class_register(&arvo_class); 440 if (retval) 441 return retval; 442 443 retval = hid_register_driver(&arvo_driver); 444 if (retval) 445 class_unregister(&arvo_class); 446 return retval; 447 } 448 449 static void __exit arvo_exit(void) 450 { 451 hid_unregister_driver(&arvo_driver); 452 class_unregister(&arvo_class); 453 } 454 455 module_init(arvo_init); 456 module_exit(arvo_exit); 457 458 MODULE_AUTHOR("Stefan Achatz"); 459 MODULE_DESCRIPTION("USB Roccat Arvo driver"); 460 MODULE_LICENSE("GPL v2"); 461