linux/drivers/hid/hid-corsair.c
<<
>>
Prefs
   1/*
   2 * HID driver for Corsair devices
   3 *
   4 * Supported devices:
   5 *  - Vengeance K90 Keyboard
   6 *
   7 * Copyright (c) 2015 Clement Vuchener
   8 */
   9
  10/*
  11 * This program is free software; you can redistribute it and/or modify it
  12 * under the terms of the GNU General Public License as published by the Free
  13 * Software Foundation; either version 2 of the License, or (at your option)
  14 * any later version.
  15 */
  16
  17#include <linux/hid.h>
  18#include <linux/module.h>
  19#include <linux/usb.h>
  20#include <linux/leds.h>
  21
  22#include "hid-ids.h"
  23
  24#define CORSAIR_USE_K90_MACRO   (1<<0)
  25#define CORSAIR_USE_K90_BACKLIGHT       (1<<1)
  26
  27struct k90_led {
  28        struct led_classdev cdev;
  29        int brightness;
  30        struct work_struct work;
  31        bool removed;
  32};
  33
  34struct k90_drvdata {
  35        struct k90_led record_led;
  36};
  37
  38struct corsair_drvdata {
  39        unsigned long quirks;
  40        struct k90_drvdata *k90;
  41        struct k90_led *backlight;
  42};
  43
  44#define K90_GKEY_COUNT  18
  45
  46static int corsair_usage_to_gkey(unsigned int usage)
  47{
  48        /* G1 (0xd0) to G16 (0xdf) */
  49        if (usage >= 0xd0 && usage <= 0xdf)
  50                return usage - 0xd0 + 1;
  51        /* G17 (0xe8) to G18 (0xe9) */
  52        if (usage >= 0xe8 && usage <= 0xe9)
  53                return usage - 0xe8 + 17;
  54        return 0;
  55}
  56
  57static unsigned short corsair_gkey_map[K90_GKEY_COUNT] = {
  58        BTN_TRIGGER_HAPPY1,
  59        BTN_TRIGGER_HAPPY2,
  60        BTN_TRIGGER_HAPPY3,
  61        BTN_TRIGGER_HAPPY4,
  62        BTN_TRIGGER_HAPPY5,
  63        BTN_TRIGGER_HAPPY6,
  64        BTN_TRIGGER_HAPPY7,
  65        BTN_TRIGGER_HAPPY8,
  66        BTN_TRIGGER_HAPPY9,
  67        BTN_TRIGGER_HAPPY10,
  68        BTN_TRIGGER_HAPPY11,
  69        BTN_TRIGGER_HAPPY12,
  70        BTN_TRIGGER_HAPPY13,
  71        BTN_TRIGGER_HAPPY14,
  72        BTN_TRIGGER_HAPPY15,
  73        BTN_TRIGGER_HAPPY16,
  74        BTN_TRIGGER_HAPPY17,
  75        BTN_TRIGGER_HAPPY18,
  76};
  77
  78module_param_array_named(gkey_codes, corsair_gkey_map, ushort, NULL, S_IRUGO);
  79MODULE_PARM_DESC(gkey_codes, "Key codes for the G-keys");
  80
  81static unsigned short corsair_record_keycodes[2] = {
  82        BTN_TRIGGER_HAPPY19,
  83        BTN_TRIGGER_HAPPY20
  84};
  85
  86module_param_array_named(recordkey_codes, corsair_record_keycodes, ushort,
  87                         NULL, S_IRUGO);
  88MODULE_PARM_DESC(recordkey_codes, "Key codes for the MR (start and stop record) button");
  89
  90static unsigned short corsair_profile_keycodes[3] = {
  91        BTN_TRIGGER_HAPPY21,
  92        BTN_TRIGGER_HAPPY22,
  93        BTN_TRIGGER_HAPPY23
  94};
  95
  96module_param_array_named(profilekey_codes, corsair_profile_keycodes, ushort,
  97                         NULL, S_IRUGO);
  98MODULE_PARM_DESC(profilekey_codes, "Key codes for the profile buttons");
  99
 100#define CORSAIR_USAGE_SPECIAL_MIN 0xf0
 101#define CORSAIR_USAGE_SPECIAL_MAX 0xff
 102
 103#define CORSAIR_USAGE_MACRO_RECORD_START 0xf6
 104#define CORSAIR_USAGE_MACRO_RECORD_STOP 0xf7
 105
 106#define CORSAIR_USAGE_PROFILE 0xf1
 107#define CORSAIR_USAGE_M1 0xf1
 108#define CORSAIR_USAGE_M2 0xf2
 109#define CORSAIR_USAGE_M3 0xf3
 110#define CORSAIR_USAGE_PROFILE_MAX 0xf3
 111
 112#define CORSAIR_USAGE_META_OFF 0xf4
 113#define CORSAIR_USAGE_META_ON  0xf5
 114
 115#define CORSAIR_USAGE_LIGHT 0xfa
 116#define CORSAIR_USAGE_LIGHT_OFF 0xfa
 117#define CORSAIR_USAGE_LIGHT_DIM 0xfb
 118#define CORSAIR_USAGE_LIGHT_MEDIUM 0xfc
 119#define CORSAIR_USAGE_LIGHT_BRIGHT 0xfd
 120#define CORSAIR_USAGE_LIGHT_MAX 0xfd
 121
 122/* USB control protocol */
 123
 124#define K90_REQUEST_BRIGHTNESS 49
 125#define K90_REQUEST_MACRO_MODE 2
 126#define K90_REQUEST_STATUS 4
 127#define K90_REQUEST_GET_MODE 5
 128#define K90_REQUEST_PROFILE 20
 129
 130#define K90_MACRO_MODE_SW 0x0030
 131#define K90_MACRO_MODE_HW 0x0001
 132
 133#define K90_MACRO_LED_ON  0x0020
 134#define K90_MACRO_LED_OFF 0x0040
 135
 136/*
 137 * LED class devices
 138 */
 139
 140#define K90_BACKLIGHT_LED_SUFFIX "::backlight"
 141#define K90_RECORD_LED_SUFFIX "::record"
 142
 143static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev)
 144{
 145        int ret;
 146        struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
 147        struct device *dev = led->cdev.dev->parent;
 148        struct usb_interface *usbif = to_usb_interface(dev->parent);
 149        struct usb_device *usbdev = interface_to_usbdev(usbif);
 150        int brightness;
 151        char data[8];
 152
 153        ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 154                              K90_REQUEST_STATUS,
 155                              USB_DIR_IN | USB_TYPE_VENDOR |
 156                              USB_RECIP_DEVICE, 0, 0, data, 8,
 157                              USB_CTRL_SET_TIMEOUT);
 158        if (ret < 0) {
 159                dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
 160                         ret);
 161                return -EIO;
 162        }
 163        brightness = data[4];
 164        if (brightness < 0 || brightness > 3) {
 165                dev_warn(dev,
 166                         "Read invalid backlight brightness: %02hhx.\n",
 167                         data[4]);
 168                return -EIO;
 169        }
 170        return brightness;
 171}
 172
 173static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
 174{
 175        struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
 176
 177        return led->brightness;
 178}
 179
 180static void k90_brightness_set(struct led_classdev *led_cdev,
 181                               enum led_brightness brightness)
 182{
 183        struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
 184
 185        led->brightness = brightness;
 186        schedule_work(&led->work);
 187}
 188
 189static void k90_backlight_work(struct work_struct *work)
 190{
 191        int ret;
 192        struct k90_led *led = container_of(work, struct k90_led, work);
 193        struct device *dev;
 194        struct usb_interface *usbif;
 195        struct usb_device *usbdev;
 196
 197        if (led->removed)
 198                return;
 199
 200        dev = led->cdev.dev->parent;
 201        usbif = to_usb_interface(dev->parent);
 202        usbdev = interface_to_usbdev(usbif);
 203
 204        ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
 205                              K90_REQUEST_BRIGHTNESS,
 206                              USB_DIR_OUT | USB_TYPE_VENDOR |
 207                              USB_RECIP_DEVICE, led->brightness, 0,
 208                              NULL, 0, USB_CTRL_SET_TIMEOUT);
 209        if (ret != 0)
 210                dev_warn(dev, "Failed to set backlight brightness (error: %d).\n",
 211                         ret);
 212}
 213
 214static void k90_record_led_work(struct work_struct *work)
 215{
 216        int ret;
 217        struct k90_led *led = container_of(work, struct k90_led, work);
 218        struct device *dev;
 219        struct usb_interface *usbif;
 220        struct usb_device *usbdev;
 221        int value;
 222
 223        if (led->removed)
 224                return;
 225
 226        dev = led->cdev.dev->parent;
 227        usbif = to_usb_interface(dev->parent);
 228        usbdev = interface_to_usbdev(usbif);
 229
 230        if (led->brightness > 0)
 231                value = K90_MACRO_LED_ON;
 232        else
 233                value = K90_MACRO_LED_OFF;
 234
 235        ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
 236                              K90_REQUEST_MACRO_MODE,
 237                              USB_DIR_OUT | USB_TYPE_VENDOR |
 238                              USB_RECIP_DEVICE, value, 0, NULL, 0,
 239                              USB_CTRL_SET_TIMEOUT);
 240        if (ret != 0)
 241                dev_warn(dev, "Failed to set record LED state (error: %d).\n",
 242                         ret);
 243}
 244
 245/*
 246 * Keyboard attributes
 247 */
 248
 249static ssize_t k90_show_macro_mode(struct device *dev,
 250                                   struct device_attribute *attr, char *buf)
 251{
 252        int ret;
 253        struct usb_interface *usbif = to_usb_interface(dev->parent);
 254        struct usb_device *usbdev = interface_to_usbdev(usbif);
 255        const char *macro_mode;
 256        char data[8];
 257
 258        ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 259                              K90_REQUEST_GET_MODE,
 260                              USB_DIR_IN | USB_TYPE_VENDOR |
 261                              USB_RECIP_DEVICE, 0, 0, data, 2,
 262                              USB_CTRL_SET_TIMEOUT);
 263        if (ret < 0) {
 264                dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
 265                         ret);
 266                return -EIO;
 267        }
 268
 269        switch (data[0]) {
 270        case K90_MACRO_MODE_HW:
 271                macro_mode = "HW";
 272                break;
 273
 274        case K90_MACRO_MODE_SW:
 275                macro_mode = "SW";
 276                break;
 277        default:
 278                dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
 279                         data[0]);
 280                return -EIO;
 281        }
 282
 283        return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
 284}
 285
 286static ssize_t k90_store_macro_mode(struct device *dev,
 287                                    struct device_attribute *attr,
 288                                    const char *buf, size_t count)
 289{
 290        int ret;
 291        struct usb_interface *usbif = to_usb_interface(dev->parent);
 292        struct usb_device *usbdev = interface_to_usbdev(usbif);
 293        __u16 value;
 294
 295        if (strncmp(buf, "SW", 2) == 0)
 296                value = K90_MACRO_MODE_SW;
 297        else if (strncmp(buf, "HW", 2) == 0)
 298                value = K90_MACRO_MODE_HW;
 299        else
 300                return -EINVAL;
 301
 302        ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
 303                              K90_REQUEST_MACRO_MODE,
 304                              USB_DIR_OUT | USB_TYPE_VENDOR |
 305                              USB_RECIP_DEVICE, value, 0, NULL, 0,
 306                              USB_CTRL_SET_TIMEOUT);
 307        if (ret != 0) {
 308                dev_warn(dev, "Failed to set macro mode.\n");
 309                return ret;
 310        }
 311
 312        return count;
 313}
 314
 315static ssize_t k90_show_current_profile(struct device *dev,
 316                                        struct device_attribute *attr,
 317                                        char *buf)
 318{
 319        int ret;
 320        struct usb_interface *usbif = to_usb_interface(dev->parent);
 321        struct usb_device *usbdev = interface_to_usbdev(usbif);
 322        int current_profile;
 323        char data[8];
 324
 325        ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 326                              K90_REQUEST_STATUS,
 327                              USB_DIR_IN | USB_TYPE_VENDOR |
 328                              USB_RECIP_DEVICE, 0, 0, data, 8,
 329                              USB_CTRL_SET_TIMEOUT);
 330        if (ret < 0) {
 331                dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
 332                         ret);
 333                return -EIO;
 334        }
 335        current_profile = data[7];
 336        if (current_profile < 1 || current_profile > 3) {
 337                dev_warn(dev, "Read invalid current profile: %02hhx.\n",
 338                         data[7]);
 339                return -EIO;
 340        }
 341
 342        return snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
 343}
 344
 345static ssize_t k90_store_current_profile(struct device *dev,
 346                                         struct device_attribute *attr,
 347                                         const char *buf, size_t count)
 348{
 349        int ret;
 350        struct usb_interface *usbif = to_usb_interface(dev->parent);
 351        struct usb_device *usbdev = interface_to_usbdev(usbif);
 352        int profile;
 353
 354        if (kstrtoint(buf, 10, &profile))
 355                return -EINVAL;
 356        if (profile < 1 || profile > 3)
 357                return -EINVAL;
 358
 359        ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
 360                              K90_REQUEST_PROFILE,
 361                              USB_DIR_OUT | USB_TYPE_VENDOR |
 362                              USB_RECIP_DEVICE, profile, 0, NULL, 0,
 363                              USB_CTRL_SET_TIMEOUT);
 364        if (ret != 0) {
 365                dev_warn(dev, "Failed to change current profile (error %d).\n",
 366                         ret);
 367                return ret;
 368        }
 369
 370        return count;
 371}
 372
 373static DEVICE_ATTR(macro_mode, 0644, k90_show_macro_mode, k90_store_macro_mode);
 374static DEVICE_ATTR(current_profile, 0644, k90_show_current_profile,
 375                   k90_store_current_profile);
 376
 377static struct attribute *k90_attrs[] = {
 378        &dev_attr_macro_mode.attr,
 379        &dev_attr_current_profile.attr,
 380        NULL
 381};
 382
 383static const struct attribute_group k90_attr_group = {
 384        .attrs = k90_attrs,
 385};
 386
 387/*
 388 * Driver functions
 389 */
 390
 391static int k90_init_backlight(struct hid_device *dev)
 392{
 393        int ret;
 394        struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
 395        size_t name_sz;
 396        char *name;
 397
 398        drvdata->backlight = kzalloc(sizeof(struct k90_led), GFP_KERNEL);
 399        if (!drvdata->backlight) {
 400                ret = -ENOMEM;
 401                goto fail_backlight_alloc;
 402        }
 403
 404        name_sz =
 405            strlen(dev_name(&dev->dev)) + sizeof(K90_BACKLIGHT_LED_SUFFIX);
 406        name = kzalloc(name_sz, GFP_KERNEL);
 407        if (!name) {
 408                ret = -ENOMEM;
 409                goto fail_name_alloc;
 410        }
 411        snprintf(name, name_sz, "%s" K90_BACKLIGHT_LED_SUFFIX,
 412                 dev_name(&dev->dev));
 413        drvdata->backlight->removed = false;
 414        drvdata->backlight->cdev.name = name;
 415        drvdata->backlight->cdev.max_brightness = 3;
 416        drvdata->backlight->cdev.brightness_set = k90_brightness_set;
 417        drvdata->backlight->cdev.brightness_get = k90_backlight_get;
 418        INIT_WORK(&drvdata->backlight->work, k90_backlight_work);
 419        ret = led_classdev_register(&dev->dev, &drvdata->backlight->cdev);
 420        if (ret != 0)
 421                goto fail_register_cdev;
 422
 423        return 0;
 424
 425fail_register_cdev:
 426        kfree(drvdata->backlight->cdev.name);
 427fail_name_alloc:
 428        kfree(drvdata->backlight);
 429        drvdata->backlight = NULL;
 430fail_backlight_alloc:
 431        return ret;
 432}
 433
 434static int k90_init_macro_functions(struct hid_device *dev)
 435{
 436        int ret;
 437        struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
 438        struct k90_drvdata *k90;
 439        size_t name_sz;
 440        char *name;
 441
 442        k90 = kzalloc(sizeof(struct k90_drvdata), GFP_KERNEL);
 443        if (!k90) {
 444                ret = -ENOMEM;
 445                goto fail_drvdata;
 446        }
 447        drvdata->k90 = k90;
 448
 449        /* Init LED device for record LED */
 450        name_sz = strlen(dev_name(&dev->dev)) + sizeof(K90_RECORD_LED_SUFFIX);
 451        name = kzalloc(name_sz, GFP_KERNEL);
 452        if (!name) {
 453                ret = -ENOMEM;
 454                goto fail_record_led_alloc;
 455        }
 456        snprintf(name, name_sz, "%s" K90_RECORD_LED_SUFFIX,
 457                 dev_name(&dev->dev));
 458        k90->record_led.removed = false;
 459        k90->record_led.cdev.name = name;
 460        k90->record_led.cdev.max_brightness = 1;
 461        k90->record_led.cdev.brightness_set = k90_brightness_set;
 462        k90->record_led.cdev.brightness_get = k90_record_led_get;
 463        INIT_WORK(&k90->record_led.work, k90_record_led_work);
 464        k90->record_led.brightness = 0;
 465        ret = led_classdev_register(&dev->dev, &k90->record_led.cdev);
 466        if (ret != 0)
 467                goto fail_record_led;
 468
 469        /* Init attributes */
 470        ret = sysfs_create_group(&dev->dev.kobj, &k90_attr_group);
 471        if (ret != 0)
 472                goto fail_sysfs;
 473
 474        return 0;
 475
 476fail_sysfs:
 477        k90->record_led.removed = true;
 478        led_classdev_unregister(&k90->record_led.cdev);
 479        cancel_work_sync(&k90->record_led.work);
 480fail_record_led:
 481        kfree(k90->record_led.cdev.name);
 482fail_record_led_alloc:
 483        kfree(k90);
 484fail_drvdata:
 485        drvdata->k90 = NULL;
 486        return ret;
 487}
 488
 489static void k90_cleanup_backlight(struct hid_device *dev)
 490{
 491        struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
 492
 493        if (drvdata->backlight) {
 494                drvdata->backlight->removed = true;
 495                led_classdev_unregister(&drvdata->backlight->cdev);
 496                cancel_work_sync(&drvdata->backlight->work);
 497                kfree(drvdata->backlight->cdev.name);
 498                kfree(drvdata->backlight);
 499        }
 500}
 501
 502static void k90_cleanup_macro_functions(struct hid_device *dev)
 503{
 504        struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
 505        struct k90_drvdata *k90 = drvdata->k90;
 506
 507        if (k90) {
 508                sysfs_remove_group(&dev->dev.kobj, &k90_attr_group);
 509
 510                k90->record_led.removed = true;
 511                led_classdev_unregister(&k90->record_led.cdev);
 512                cancel_work_sync(&k90->record_led.work);
 513                kfree(k90->record_led.cdev.name);
 514
 515                kfree(k90);
 516        }
 517}
 518
 519static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id)
 520{
 521        int ret;
 522        unsigned long quirks = id->driver_data;
 523        struct corsair_drvdata *drvdata;
 524        struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
 525
 526        drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
 527                               GFP_KERNEL);
 528        if (drvdata == NULL)
 529                return -ENOMEM;
 530        drvdata->quirks = quirks;
 531        hid_set_drvdata(dev, drvdata);
 532
 533        ret = hid_parse(dev);
 534        if (ret != 0) {
 535                hid_err(dev, "parse failed\n");
 536                return ret;
 537        }
 538        ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
 539        if (ret != 0) {
 540                hid_err(dev, "hw start failed\n");
 541                return ret;
 542        }
 543
 544        if (usbif->cur_altsetting->desc.bInterfaceNumber == 0) {
 545                if (quirks & CORSAIR_USE_K90_MACRO) {
 546                        ret = k90_init_macro_functions(dev);
 547                        if (ret != 0)
 548                                hid_warn(dev, "Failed to initialize K90 macro functions.\n");
 549                }
 550                if (quirks & CORSAIR_USE_K90_BACKLIGHT) {
 551                        ret = k90_init_backlight(dev);
 552                        if (ret != 0)
 553                                hid_warn(dev, "Failed to initialize K90 backlight.\n");
 554                }
 555        }
 556
 557        return 0;
 558}
 559
 560static void corsair_remove(struct hid_device *dev)
 561{
 562        k90_cleanup_macro_functions(dev);
 563        k90_cleanup_backlight(dev);
 564
 565        hid_hw_stop(dev);
 566}
 567
 568static int corsair_event(struct hid_device *dev, struct hid_field *field,
 569                         struct hid_usage *usage, __s32 value)
 570{
 571        struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
 572
 573        if (!drvdata->k90)
 574                return 0;
 575
 576        switch (usage->hid & HID_USAGE) {
 577        case CORSAIR_USAGE_MACRO_RECORD_START:
 578                drvdata->k90->record_led.brightness = 1;
 579                break;
 580        case CORSAIR_USAGE_MACRO_RECORD_STOP:
 581                drvdata->k90->record_led.brightness = 0;
 582                break;
 583        default:
 584                break;
 585        }
 586
 587        return 0;
 588}
 589
 590static int corsair_input_mapping(struct hid_device *dev,
 591                                 struct hid_input *input,
 592                                 struct hid_field *field,
 593                                 struct hid_usage *usage, unsigned long **bit,
 594                                 int *max)
 595{
 596        int gkey;
 597
 598        if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD)
 599                return 0;
 600
 601        gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE);
 602        if (gkey != 0) {
 603                hid_map_usage_clear(input, usage, bit, max, EV_KEY,
 604                                    corsair_gkey_map[gkey - 1]);
 605                return 1;
 606        }
 607        if ((usage->hid & HID_USAGE) >= CORSAIR_USAGE_SPECIAL_MIN &&
 608            (usage->hid & HID_USAGE) <= CORSAIR_USAGE_SPECIAL_MAX) {
 609                switch (usage->hid & HID_USAGE) {
 610                case CORSAIR_USAGE_MACRO_RECORD_START:
 611                        hid_map_usage_clear(input, usage, bit, max, EV_KEY,
 612                                            corsair_record_keycodes[0]);
 613                        return 1;
 614
 615                case CORSAIR_USAGE_MACRO_RECORD_STOP:
 616                        hid_map_usage_clear(input, usage, bit, max, EV_KEY,
 617                                            corsair_record_keycodes[1]);
 618                        return 1;
 619
 620                case CORSAIR_USAGE_M1:
 621                        hid_map_usage_clear(input, usage, bit, max, EV_KEY,
 622                                            corsair_profile_keycodes[0]);
 623                        return 1;
 624
 625                case CORSAIR_USAGE_M2:
 626                        hid_map_usage_clear(input, usage, bit, max, EV_KEY,
 627                                            corsair_profile_keycodes[1]);
 628                        return 1;
 629
 630                case CORSAIR_USAGE_M3:
 631                        hid_map_usage_clear(input, usage, bit, max, EV_KEY,
 632                                            corsair_profile_keycodes[2]);
 633                        return 1;
 634
 635                default:
 636                        return -1;
 637                }
 638        }
 639
 640        return 0;
 641}
 642
 643static const struct hid_device_id corsair_devices[] = {
 644        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
 645                .driver_data = CORSAIR_USE_K90_MACRO |
 646                               CORSAIR_USE_K90_BACKLIGHT },
 647        {}
 648};
 649
 650MODULE_DEVICE_TABLE(hid, corsair_devices);
 651
 652static struct hid_driver corsair_driver = {
 653        .name = "corsair",
 654        .id_table = corsair_devices,
 655        .probe = corsair_probe,
 656        .event = corsair_event,
 657        .remove = corsair_remove,
 658        .input_mapping = corsair_input_mapping,
 659};
 660
 661module_hid_driver(corsair_driver);
 662
 663MODULE_LICENSE("GPL");
 664MODULE_AUTHOR("Clement Vuchener");
 665MODULE_DESCRIPTION("HID driver for Corsair devices");
 666