1 /* 2 * Roccat Isku driver for Linux 3 * 4 * Copyright (c) 2011 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 Isku is a gamer keyboard with macro keys that can be configured in 16 * 5 profiles. 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-isku.h" 28 29 static struct class *isku_class; 30 31 static void isku_profile_activated(struct isku_device *isku, uint new_profile) 32 { 33 isku->actual_profile = new_profile; 34 } 35 36 static int isku_receive(struct usb_device *usb_dev, uint command, 37 void *buf, uint size) 38 { 39 return roccat_common_receive(usb_dev, command, buf, size); 40 } 41 42 static int isku_receive_control_status(struct usb_device *usb_dev) 43 { 44 int retval; 45 struct isku_control control; 46 47 do { 48 msleep(50); 49 retval = isku_receive(usb_dev, ISKU_COMMAND_CONTROL, 50 &control, sizeof(struct isku_control)); 51 52 if (retval) 53 return retval; 54 55 switch (control.value) { 56 case ISKU_CONTROL_VALUE_STATUS_OK: 57 return 0; 58 case ISKU_CONTROL_VALUE_STATUS_WAIT: 59 continue; 60 case ISKU_CONTROL_VALUE_STATUS_INVALID: 61 /* seems to be critical - replug necessary */ 62 case ISKU_CONTROL_VALUE_STATUS_OVERLOAD: 63 return -EINVAL; 64 default: 65 hid_err(usb_dev, "isku_receive_control_status: " 66 "unknown response value 0x%x\n", 67 control.value); 68 return -EINVAL; 69 } 70 71 } while (1); 72 } 73 74 static int isku_send(struct usb_device *usb_dev, uint command, 75 void const *buf, uint size) 76 { 77 int retval; 78 79 retval = roccat_common_send(usb_dev, command, buf, size); 80 if (retval) 81 return retval; 82 83 return isku_receive_control_status(usb_dev); 84 } 85 86 static int isku_get_actual_profile(struct usb_device *usb_dev) 87 { 88 struct isku_actual_profile buf; 89 int retval; 90 91 retval = isku_receive(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, 92 &buf, sizeof(struct isku_actual_profile)); 93 return retval ? retval : buf.actual_profile; 94 } 95 96 static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile) 97 { 98 struct isku_actual_profile buf; 99 100 buf.command = ISKU_COMMAND_ACTUAL_PROFILE; 101 buf.size = sizeof(struct isku_actual_profile); 102 buf.actual_profile = new_profile; 103 return isku_send(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, &buf, 104 sizeof(struct isku_actual_profile)); 105 } 106 107 static ssize_t isku_sysfs_show_actual_profile(struct device *dev, 108 struct device_attribute *attr, char *buf) 109 { 110 struct isku_device *isku = 111 hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); 112 return snprintf(buf, PAGE_SIZE, "%d\n", isku->actual_profile); 113 } 114 115 static ssize_t isku_sysfs_set_actual_profile(struct device *dev, 116 struct device_attribute *attr, char const *buf, size_t size) 117 { 118 struct isku_device *isku; 119 struct usb_device *usb_dev; 120 unsigned long profile; 121 int retval; 122 struct isku_roccat_report roccat_report; 123 124 dev = dev->parent->parent; 125 isku = hid_get_drvdata(dev_get_drvdata(dev)); 126 usb_dev = interface_to_usbdev(to_usb_interface(dev)); 127 128 retval = strict_strtoul(buf, 10, &profile); 129 if (retval) 130 return retval; 131 132 if (profile > 4) 133 return -EINVAL; 134 135 mutex_lock(&isku->isku_lock); 136 137 retval = isku_set_actual_profile(usb_dev, profile); 138 if (retval) { 139 mutex_unlock(&isku->isku_lock); 140 return retval; 141 } 142 143 isku_profile_activated(isku, profile); 144 145 roccat_report.event = ISKU_REPORT_BUTTON_EVENT_PROFILE; 146 roccat_report.data1 = profile + 1; 147 roccat_report.data2 = 0; 148 roccat_report.profile = profile + 1; 149 roccat_report_event(isku->chrdev_minor, (uint8_t const *)&roccat_report); 150 151 mutex_unlock(&isku->isku_lock); 152 153 return size; 154 } 155 156 static struct device_attribute isku_attributes[] = { 157 __ATTR(actual_profile, 0660, 158 isku_sysfs_show_actual_profile, 159 isku_sysfs_set_actual_profile), 160 __ATTR_NULL 161 }; 162 163 static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, 164 char *buf, loff_t off, size_t count, 165 size_t real_size, uint command) 166 { 167 struct device *dev = 168 container_of(kobj, struct device, kobj)->parent->parent; 169 struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); 170 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 171 int retval; 172 173 if (off >= real_size) 174 return 0; 175 176 if (off != 0 || count != real_size) 177 return -EINVAL; 178 179 mutex_lock(&isku->isku_lock); 180 retval = isku_receive(usb_dev, command, buf, real_size); 181 mutex_unlock(&isku->isku_lock); 182 183 return retval ? retval : real_size; 184 } 185 186 static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj, 187 void const *buf, loff_t off, size_t count, 188 size_t real_size, uint command) 189 { 190 struct device *dev = 191 container_of(kobj, struct device, kobj)->parent->parent; 192 struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); 193 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 194 int retval; 195 196 if (off != 0 || count != real_size) 197 return -EINVAL; 198 199 mutex_lock(&isku->isku_lock); 200 retval = isku_send(usb_dev, command, (void *)buf, real_size); 201 mutex_unlock(&isku->isku_lock); 202 203 return retval ? retval : real_size; 204 } 205 206 #define ISKU_SYSFS_W(thingy, THINGY) \ 207 static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj, \ 208 struct bin_attribute *attr, char *buf, \ 209 loff_t off, size_t count) \ 210 { \ 211 return isku_sysfs_write(fp, kobj, buf, off, count, \ 212 sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ 213 } 214 215 #define ISKU_SYSFS_R(thingy, THINGY) \ 216 static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, \ 217 struct bin_attribute *attr, char *buf, \ 218 loff_t off, size_t count) \ 219 { \ 220 return isku_sysfs_read(fp, kobj, buf, off, count, \ 221 sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ 222 } 223 224 #define ISKU_SYSFS_RW(thingy, THINGY) \ 225 ISKU_SYSFS_R(thingy, THINGY) \ 226 ISKU_SYSFS_W(thingy, THINGY) 227 228 #define ISKU_BIN_ATTR_RW(thingy) \ 229 { \ 230 .attr = { .name = #thingy, .mode = 0660 }, \ 231 .size = sizeof(struct isku_ ## thingy), \ 232 .read = isku_sysfs_read_ ## thingy, \ 233 .write = isku_sysfs_write_ ## thingy \ 234 } 235 236 #define ISKU_BIN_ATTR_R(thingy) \ 237 { \ 238 .attr = { .name = #thingy, .mode = 0440 }, \ 239 .size = sizeof(struct isku_ ## thingy), \ 240 .read = isku_sysfs_read_ ## thingy, \ 241 } 242 243 #define ISKU_BIN_ATTR_W(thingy) \ 244 { \ 245 .attr = { .name = #thingy, .mode = 0220 }, \ 246 .size = sizeof(struct isku_ ## thingy), \ 247 .write = isku_sysfs_write_ ## thingy \ 248 } 249 250 ISKU_SYSFS_RW(macro, MACRO) 251 ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION) 252 ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE) 253 ISKU_SYSFS_RW(keys_media, KEYS_MEDIA) 254 ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER) 255 ISKU_SYSFS_RW(keys_macro, KEYS_MACRO) 256 ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK) 257 ISKU_SYSFS_RW(light, LIGHT) 258 ISKU_SYSFS_RW(key_mask, KEY_MASK) 259 ISKU_SYSFS_RW(last_set, LAST_SET) 260 ISKU_SYSFS_W(talk, TALK) 261 ISKU_SYSFS_R(info, INFO) 262 ISKU_SYSFS_W(control, CONTROL) 263 264 static struct bin_attribute isku_bin_attributes[] = { 265 ISKU_BIN_ATTR_RW(macro), 266 ISKU_BIN_ATTR_RW(keys_function), 267 ISKU_BIN_ATTR_RW(keys_easyzone), 268 ISKU_BIN_ATTR_RW(keys_media), 269 ISKU_BIN_ATTR_RW(keys_thumbster), 270 ISKU_BIN_ATTR_RW(keys_macro), 271 ISKU_BIN_ATTR_RW(keys_capslock), 272 ISKU_BIN_ATTR_RW(light), 273 ISKU_BIN_ATTR_RW(key_mask), 274 ISKU_BIN_ATTR_RW(last_set), 275 ISKU_BIN_ATTR_W(talk), 276 ISKU_BIN_ATTR_R(info), 277 ISKU_BIN_ATTR_W(control), 278 __ATTR_NULL 279 }; 280 281 static int isku_init_isku_device_struct(struct usb_device *usb_dev, 282 struct isku_device *isku) 283 { 284 int retval; 285 286 mutex_init(&isku->isku_lock); 287 288 retval = isku_get_actual_profile(usb_dev); 289 if (retval < 0) 290 return retval; 291 isku_profile_activated(isku, retval); 292 293 return 0; 294 } 295 296 static int isku_init_specials(struct hid_device *hdev) 297 { 298 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 299 struct usb_device *usb_dev = interface_to_usbdev(intf); 300 struct isku_device *isku; 301 int retval; 302 303 if (intf->cur_altsetting->desc.bInterfaceProtocol 304 != ISKU_USB_INTERFACE_PROTOCOL) { 305 hid_set_drvdata(hdev, NULL); 306 return 0; 307 } 308 309 isku = kzalloc(sizeof(*isku), GFP_KERNEL); 310 if (!isku) { 311 hid_err(hdev, "can't alloc device descriptor\n"); 312 return -ENOMEM; 313 } 314 hid_set_drvdata(hdev, isku); 315 316 retval = isku_init_isku_device_struct(usb_dev, isku); 317 if (retval) { 318 hid_err(hdev, "couldn't init struct isku_device\n"); 319 goto exit_free; 320 } 321 322 retval = roccat_connect(isku_class, hdev, 323 sizeof(struct isku_roccat_report)); 324 if (retval < 0) { 325 hid_err(hdev, "couldn't init char dev\n"); 326 } else { 327 isku->chrdev_minor = retval; 328 isku->roccat_claimed = 1; 329 } 330 331 return 0; 332 exit_free: 333 kfree(isku); 334 return retval; 335 } 336 337 static void isku_remove_specials(struct hid_device *hdev) 338 { 339 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 340 struct isku_device *isku; 341 342 if (intf->cur_altsetting->desc.bInterfaceProtocol 343 != ISKU_USB_INTERFACE_PROTOCOL) 344 return; 345 346 isku = hid_get_drvdata(hdev); 347 if (isku->roccat_claimed) 348 roccat_disconnect(isku->chrdev_minor); 349 kfree(isku); 350 } 351 352 static int isku_probe(struct hid_device *hdev, 353 const struct hid_device_id *id) 354 { 355 int retval; 356 357 retval = hid_parse(hdev); 358 if (retval) { 359 hid_err(hdev, "parse failed\n"); 360 goto exit; 361 } 362 363 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 364 if (retval) { 365 hid_err(hdev, "hw start failed\n"); 366 goto exit; 367 } 368 369 retval = isku_init_specials(hdev); 370 if (retval) { 371 hid_err(hdev, "couldn't install keyboard\n"); 372 goto exit_stop; 373 } 374 375 return 0; 376 377 exit_stop: 378 hid_hw_stop(hdev); 379 exit: 380 return retval; 381 } 382 383 static void isku_remove(struct hid_device *hdev) 384 { 385 isku_remove_specials(hdev); 386 hid_hw_stop(hdev); 387 } 388 389 static void isku_keep_values_up_to_date(struct isku_device *isku, 390 u8 const *data) 391 { 392 struct isku_report_button const *button_report; 393 394 switch (data[0]) { 395 case ISKU_REPORT_NUMBER_BUTTON: 396 button_report = (struct isku_report_button const *)data; 397 switch (button_report->event) { 398 case ISKU_REPORT_BUTTON_EVENT_PROFILE: 399 isku_profile_activated(isku, button_report->data1 - 1); 400 break; 401 } 402 break; 403 } 404 } 405 406 static void isku_report_to_chrdev(struct isku_device const *isku, 407 u8 const *data) 408 { 409 struct isku_roccat_report roccat_report; 410 struct isku_report_button const *button_report; 411 412 if (data[0] != ISKU_REPORT_NUMBER_BUTTON) 413 return; 414 415 button_report = (struct isku_report_button const *)data; 416 417 roccat_report.event = button_report->event; 418 roccat_report.data1 = button_report->data1; 419 roccat_report.data2 = button_report->data2; 420 roccat_report.profile = isku->actual_profile + 1; 421 roccat_report_event(isku->chrdev_minor, 422 (uint8_t const *)&roccat_report); 423 } 424 425 static int isku_raw_event(struct hid_device *hdev, 426 struct hid_report *report, u8 *data, int size) 427 { 428 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 429 struct isku_device *isku = hid_get_drvdata(hdev); 430 431 if (intf->cur_altsetting->desc.bInterfaceProtocol 432 != ISKU_USB_INTERFACE_PROTOCOL) 433 return 0; 434 435 if (isku == NULL) 436 return 0; 437 438 isku_keep_values_up_to_date(isku, data); 439 440 if (isku->roccat_claimed) 441 isku_report_to_chrdev(isku, data); 442 443 return 0; 444 } 445 446 static const struct hid_device_id isku_devices[] = { 447 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, 448 { } 449 }; 450 451 MODULE_DEVICE_TABLE(hid, isku_devices); 452 453 static struct hid_driver isku_driver = { 454 .name = "isku", 455 .id_table = isku_devices, 456 .probe = isku_probe, 457 .remove = isku_remove, 458 .raw_event = isku_raw_event 459 }; 460 461 static int __init isku_init(void) 462 { 463 int retval; 464 isku_class = class_create(THIS_MODULE, "isku"); 465 if (IS_ERR(isku_class)) 466 return PTR_ERR(isku_class); 467 isku_class->dev_attrs = isku_attributes; 468 isku_class->dev_bin_attrs = isku_bin_attributes; 469 470 retval = hid_register_driver(&isku_driver); 471 if (retval) 472 class_destroy(isku_class); 473 return retval; 474 } 475 476 static void __exit isku_exit(void) 477 { 478 hid_unregister_driver(&isku_driver); 479 class_destroy(isku_class); 480 } 481 482 module_init(isku_init); 483 module_exit(isku_exit); 484 485 MODULE_AUTHOR("Stefan Achatz"); 486 MODULE_DESCRIPTION("USB Roccat Isku driver"); 487 MODULE_LICENSE("GPL v2"); 488