root/drivers/hid/hid-roccat-isku.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isku_profile_activated
  2. isku_receive
  3. isku_get_actual_profile
  4. isku_set_actual_profile
  5. isku_sysfs_show_actual_profile
  6. isku_sysfs_set_actual_profile
  7. isku_sysfs_read
  8. isku_sysfs_write
  9. isku_init_isku_device_struct
  10. isku_init_specials
  11. isku_remove_specials
  12. isku_probe
  13. isku_remove
  14. isku_keep_values_up_to_date
  15. isku_report_to_chrdev
  16. isku_raw_event
  17. isku_init
  18. isku_exit

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

/* [<][>][^][v][top][bottom][index][help] */