linux/drivers/hid/hid-lg-g15.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  HID driver for gaming keys on Logitech gaming keyboards (such as the G15)
   4 *
   5 *  Copyright (c) 2019 Hans de Goede <hdegoede@redhat.com>
   6 */
   7
   8#include <linux/device.h>
   9#include <linux/hid.h>
  10#include <linux/module.h>
  11#include <linux/random.h>
  12#include <linux/sched.h>
  13#include <linux/usb.h>
  14#include <linux/wait.h>
  15
  16#include "hid-ids.h"
  17
  18#define LG_G15_TRANSFER_BUF_SIZE        20
  19
  20#define LG_G15_FEATURE_REPORT           0x02
  21
  22#define LG_G510_FEATURE_M_KEYS_LEDS     0x04
  23#define LG_G510_FEATURE_BACKLIGHT_RGB   0x05
  24#define LG_G510_FEATURE_POWER_ON_RGB    0x06
  25
  26enum lg_g15_model {
  27        LG_G15,
  28        LG_G15_V2,
  29        LG_G510,
  30        LG_G510_USB_AUDIO,
  31};
  32
  33enum lg_g15_led_type {
  34        LG_G15_KBD_BRIGHTNESS,
  35        LG_G15_LCD_BRIGHTNESS,
  36        LG_G15_BRIGHTNESS_MAX,
  37        LG_G15_MACRO_PRESET1 = 2,
  38        LG_G15_MACRO_PRESET2,
  39        LG_G15_MACRO_PRESET3,
  40        LG_G15_MACRO_RECORD,
  41        LG_G15_LED_MAX
  42};
  43
  44struct lg_g15_led {
  45        struct led_classdev cdev;
  46        enum led_brightness brightness;
  47        enum lg_g15_led_type led;
  48        u8 red, green, blue;
  49};
  50
  51struct lg_g15_data {
  52        /* Must be first for proper dma alignment */
  53        u8 transfer_buf[LG_G15_TRANSFER_BUF_SIZE];
  54        /* Protects the transfer_buf and led brightness */
  55        struct mutex mutex;
  56        struct work_struct work;
  57        struct input_dev *input;
  58        struct hid_device *hdev;
  59        enum lg_g15_model model;
  60        struct lg_g15_led leds[LG_G15_LED_MAX];
  61        bool game_mode_enabled;
  62};
  63
  64/******** G15 and G15 v2 LED functions ********/
  65
  66static int lg_g15_update_led_brightness(struct lg_g15_data *g15)
  67{
  68        int ret;
  69
  70        ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT,
  71                                 g15->transfer_buf, 4,
  72                                 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
  73        if (ret != 4) {
  74                hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
  75                return (ret < 0) ? ret : -EIO;
  76        }
  77
  78        g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = g15->transfer_buf[1];
  79        g15->leds[LG_G15_LCD_BRIGHTNESS].brightness = g15->transfer_buf[2];
  80
  81        g15->leds[LG_G15_MACRO_PRESET1].brightness =
  82                !(g15->transfer_buf[3] & 0x01);
  83        g15->leds[LG_G15_MACRO_PRESET2].brightness =
  84                !(g15->transfer_buf[3] & 0x02);
  85        g15->leds[LG_G15_MACRO_PRESET3].brightness =
  86                !(g15->transfer_buf[3] & 0x04);
  87        g15->leds[LG_G15_MACRO_RECORD].brightness =
  88                !(g15->transfer_buf[3] & 0x08);
  89
  90        return 0;
  91}
  92
  93static enum led_brightness lg_g15_led_get(struct led_classdev *led_cdev)
  94{
  95        struct lg_g15_led *g15_led =
  96                container_of(led_cdev, struct lg_g15_led, cdev);
  97        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
  98        enum led_brightness brightness;
  99
 100        mutex_lock(&g15->mutex);
 101        lg_g15_update_led_brightness(g15);
 102        brightness = g15->leds[g15_led->led].brightness;
 103        mutex_unlock(&g15->mutex);
 104
 105        return brightness;
 106}
 107
 108static int lg_g15_led_set(struct led_classdev *led_cdev,
 109                          enum led_brightness brightness)
 110{
 111        struct lg_g15_led *g15_led =
 112                container_of(led_cdev, struct lg_g15_led, cdev);
 113        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
 114        u8 val, mask = 0;
 115        int i, ret;
 116
 117        /* Ignore LED off on unregister / keyboard unplug */
 118        if (led_cdev->flags & LED_UNREGISTERING)
 119                return 0;
 120
 121        mutex_lock(&g15->mutex);
 122
 123        g15->transfer_buf[0] = LG_G15_FEATURE_REPORT;
 124        g15->transfer_buf[3] = 0;
 125
 126        if (g15_led->led < LG_G15_BRIGHTNESS_MAX) {
 127                g15->transfer_buf[1] = g15_led->led + 1;
 128                g15->transfer_buf[2] = brightness << (g15_led->led * 4);
 129        } else {
 130                for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
 131                        if (i == g15_led->led)
 132                                val = brightness;
 133                        else
 134                                val = g15->leds[i].brightness;
 135
 136                        if (val)
 137                                mask |= 1 << (i - LG_G15_MACRO_PRESET1);
 138                }
 139
 140                g15->transfer_buf[1] = 0x04;
 141                g15->transfer_buf[2] = ~mask;
 142        }
 143
 144        ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT,
 145                                 g15->transfer_buf, 4,
 146                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 147        if (ret == 4) {
 148                /* Success */
 149                g15_led->brightness = brightness;
 150                ret = 0;
 151        } else {
 152                hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
 153                ret = (ret < 0) ? ret : -EIO;
 154        }
 155
 156        mutex_unlock(&g15->mutex);
 157
 158        return ret;
 159}
 160
 161static void lg_g15_leds_changed_work(struct work_struct *work)
 162{
 163        struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
 164        enum led_brightness old_brightness[LG_G15_BRIGHTNESS_MAX];
 165        enum led_brightness brightness[LG_G15_BRIGHTNESS_MAX];
 166        int i, ret;
 167
 168        mutex_lock(&g15->mutex);
 169        for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
 170                old_brightness[i] = g15->leds[i].brightness;
 171
 172        ret = lg_g15_update_led_brightness(g15);
 173
 174        for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
 175                brightness[i] = g15->leds[i].brightness;
 176        mutex_unlock(&g15->mutex);
 177
 178        if (ret)
 179                return;
 180
 181        for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++) {
 182                if (brightness[i] == old_brightness[i])
 183                        continue;
 184
 185                led_classdev_notify_brightness_hw_changed(&g15->leds[i].cdev,
 186                                                          brightness[i]);
 187        }
 188}
 189
 190/******** G510 LED functions ********/
 191
 192static int lg_g510_get_initial_led_brightness(struct lg_g15_data *g15, int i)
 193{
 194        int ret, high;
 195
 196        ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_BACKLIGHT_RGB + i,
 197                                 g15->transfer_buf, 4,
 198                                 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 199        if (ret != 4) {
 200                hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
 201                return (ret < 0) ? ret : -EIO;
 202        }
 203
 204        high = max3(g15->transfer_buf[1], g15->transfer_buf[2],
 205                    g15->transfer_buf[3]);
 206
 207        if (high) {
 208                g15->leds[i].red =
 209                        DIV_ROUND_CLOSEST(g15->transfer_buf[1] * 255, high);
 210                g15->leds[i].green =
 211                        DIV_ROUND_CLOSEST(g15->transfer_buf[2] * 255, high);
 212                g15->leds[i].blue =
 213                        DIV_ROUND_CLOSEST(g15->transfer_buf[3] * 255, high);
 214                g15->leds[i].brightness = high;
 215        } else {
 216                g15->leds[i].red   = 255;
 217                g15->leds[i].green = 255;
 218                g15->leds[i].blue  = 255;
 219                g15->leds[i].brightness = 0;
 220        }
 221
 222        return 0;
 223}
 224
 225/* Must be called with g15->mutex locked */
 226static int lg_g510_kbd_led_write(struct lg_g15_data *g15,
 227                                 struct lg_g15_led *g15_led,
 228                                 enum led_brightness brightness)
 229{
 230        int ret;
 231
 232        g15->transfer_buf[0] = 5 + g15_led->led;
 233        g15->transfer_buf[1] =
 234                DIV_ROUND_CLOSEST(g15_led->red * brightness, 255);
 235        g15->transfer_buf[2] =
 236                DIV_ROUND_CLOSEST(g15_led->green * brightness, 255);
 237        g15->transfer_buf[3] =
 238                DIV_ROUND_CLOSEST(g15_led->blue * brightness, 255);
 239
 240        ret = hid_hw_raw_request(g15->hdev,
 241                                 LG_G510_FEATURE_BACKLIGHT_RGB + g15_led->led,
 242                                 g15->transfer_buf, 4,
 243                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 244        if (ret == 4) {
 245                /* Success */
 246                g15_led->brightness = brightness;
 247                ret = 0;
 248        } else {
 249                hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
 250                ret = (ret < 0) ? ret : -EIO;
 251        }
 252
 253        return ret;
 254}
 255
 256static int lg_g510_kbd_led_set(struct led_classdev *led_cdev,
 257                               enum led_brightness brightness)
 258{
 259        struct lg_g15_led *g15_led =
 260                container_of(led_cdev, struct lg_g15_led, cdev);
 261        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
 262        int ret;
 263
 264        /* Ignore LED off on unregister / keyboard unplug */
 265        if (led_cdev->flags & LED_UNREGISTERING)
 266                return 0;
 267
 268        mutex_lock(&g15->mutex);
 269        ret = lg_g510_kbd_led_write(g15, g15_led, brightness);
 270        mutex_unlock(&g15->mutex);
 271
 272        return ret;
 273}
 274
 275static enum led_brightness lg_g510_kbd_led_get(struct led_classdev *led_cdev)
 276{
 277        struct lg_g15_led *g15_led =
 278                container_of(led_cdev, struct lg_g15_led, cdev);
 279
 280        return g15_led->brightness;
 281}
 282
 283static ssize_t color_store(struct device *dev, struct device_attribute *attr,
 284                           const char *buf, size_t count)
 285{
 286        struct led_classdev *led_cdev = dev_get_drvdata(dev);
 287        struct lg_g15_led *g15_led =
 288                container_of(led_cdev, struct lg_g15_led, cdev);
 289        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
 290        unsigned long value;
 291        int ret;
 292
 293        if (count < 7 || (count == 8 && buf[7] != '\n') || count > 8)
 294                return -EINVAL;
 295
 296        if (buf[0] != '#')
 297                return -EINVAL;
 298
 299        ret = kstrtoul(buf + 1, 16, &value);
 300        if (ret)
 301                return ret;
 302
 303        mutex_lock(&g15->mutex);
 304        g15_led->red   = (value & 0xff0000) >> 16;
 305        g15_led->green = (value & 0x00ff00) >> 8;
 306        g15_led->blue  = (value & 0x0000ff);
 307        ret = lg_g510_kbd_led_write(g15, g15_led, g15_led->brightness);
 308        mutex_unlock(&g15->mutex);
 309
 310        return (ret < 0) ? ret : count;
 311}
 312
 313static ssize_t color_show(struct device *dev, struct device_attribute *attr,
 314                          char *buf)
 315{
 316        struct led_classdev *led_cdev = dev_get_drvdata(dev);
 317        struct lg_g15_led *g15_led =
 318                container_of(led_cdev, struct lg_g15_led, cdev);
 319        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
 320        ssize_t ret;
 321
 322        mutex_lock(&g15->mutex);
 323        ret = sprintf(buf, "#%02x%02x%02x\n",
 324                      g15_led->red, g15_led->green, g15_led->blue);
 325        mutex_unlock(&g15->mutex);
 326
 327        return ret;
 328}
 329
 330static DEVICE_ATTR_RW(color);
 331
 332static struct attribute *lg_g510_kbd_led_attrs[] = {
 333        &dev_attr_color.attr,
 334        NULL,
 335};
 336
 337static const struct attribute_group lg_g510_kbd_led_group = {
 338        .attrs = lg_g510_kbd_led_attrs,
 339};
 340
 341static const struct attribute_group *lg_g510_kbd_led_groups[] = {
 342        &lg_g510_kbd_led_group,
 343        NULL,
 344};
 345
 346static void lg_g510_leds_sync_work(struct work_struct *work)
 347{
 348        struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
 349
 350        mutex_lock(&g15->mutex);
 351        lg_g510_kbd_led_write(g15, &g15->leds[LG_G15_KBD_BRIGHTNESS],
 352                              g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
 353        mutex_unlock(&g15->mutex);
 354}
 355
 356static int lg_g510_update_mkey_led_brightness(struct lg_g15_data *g15)
 357{
 358        int ret;
 359
 360        ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS,
 361                                 g15->transfer_buf, 2,
 362                                 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 363        if (ret != 2) {
 364                hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
 365                ret = (ret < 0) ? ret : -EIO;
 366        }
 367
 368        g15->leds[LG_G15_MACRO_PRESET1].brightness =
 369                !!(g15->transfer_buf[1] & 0x80);
 370        g15->leds[LG_G15_MACRO_PRESET2].brightness =
 371                !!(g15->transfer_buf[1] & 0x40);
 372        g15->leds[LG_G15_MACRO_PRESET3].brightness =
 373                !!(g15->transfer_buf[1] & 0x20);
 374        g15->leds[LG_G15_MACRO_RECORD].brightness =
 375                !!(g15->transfer_buf[1] & 0x10);
 376
 377        return 0;
 378}
 379
 380static enum led_brightness lg_g510_mkey_led_get(struct led_classdev *led_cdev)
 381{
 382        struct lg_g15_led *g15_led =
 383                container_of(led_cdev, struct lg_g15_led, cdev);
 384        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
 385        enum led_brightness brightness;
 386
 387        mutex_lock(&g15->mutex);
 388        lg_g510_update_mkey_led_brightness(g15);
 389        brightness = g15->leds[g15_led->led].brightness;
 390        mutex_unlock(&g15->mutex);
 391
 392        return brightness;
 393}
 394
 395static int lg_g510_mkey_led_set(struct led_classdev *led_cdev,
 396                                enum led_brightness brightness)
 397{
 398        struct lg_g15_led *g15_led =
 399                container_of(led_cdev, struct lg_g15_led, cdev);
 400        struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
 401        u8 val, mask = 0;
 402        int i, ret;
 403
 404        /* Ignore LED off on unregister / keyboard unplug */
 405        if (led_cdev->flags & LED_UNREGISTERING)
 406                return 0;
 407
 408        mutex_lock(&g15->mutex);
 409
 410        for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
 411                if (i == g15_led->led)
 412                        val = brightness;
 413                else
 414                        val = g15->leds[i].brightness;
 415
 416                if (val)
 417                        mask |= 0x80 >> (i - LG_G15_MACRO_PRESET1);
 418        }
 419
 420        g15->transfer_buf[0] = LG_G510_FEATURE_M_KEYS_LEDS;
 421        g15->transfer_buf[1] = mask;
 422
 423        ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS,
 424                                 g15->transfer_buf, 2,
 425                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 426        if (ret == 2) {
 427                /* Success */
 428                g15_led->brightness = brightness;
 429                ret = 0;
 430        } else {
 431                hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
 432                ret = (ret < 0) ? ret : -EIO;
 433        }
 434
 435        mutex_unlock(&g15->mutex);
 436
 437        return ret;
 438}
 439
 440/******** Generic LED functions ********/
 441static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
 442{
 443        int ret;
 444
 445        switch (g15->model) {
 446        case LG_G15:
 447        case LG_G15_V2:
 448                return lg_g15_update_led_brightness(g15);
 449        case LG_G510:
 450        case LG_G510_USB_AUDIO:
 451                ret = lg_g510_get_initial_led_brightness(g15, 0);
 452                if (ret)
 453                        return ret;
 454
 455                ret = lg_g510_get_initial_led_brightness(g15, 1);
 456                if (ret)
 457                        return ret;
 458
 459                return lg_g510_update_mkey_led_brightness(g15);
 460        }
 461        return -EINVAL; /* Never reached */
 462}
 463
 464/******** Input functions ********/
 465
 466/* On the G15 Mark I Logitech has been quite creative with which bit is what */
 467static int lg_g15_event(struct lg_g15_data *g15, u8 *data, int size)
 468{
 469        int i, val;
 470
 471        /* G1 - G6 */
 472        for (i = 0; i < 6; i++) {
 473                val = data[i + 1] & (1 << i);
 474                input_report_key(g15->input, KEY_MACRO1 + i, val);
 475        }
 476        /* G7 - G12 */
 477        for (i = 0; i < 6; i++) {
 478                val = data[i + 2] & (1 << i);
 479                input_report_key(g15->input, KEY_MACRO7 + i, val);
 480        }
 481        /* G13 - G17 */
 482        for (i = 0; i < 5; i++) {
 483                val = data[i + 1] & (4 << i);
 484                input_report_key(g15->input, KEY_MACRO13 + i, val);
 485        }
 486        /* G18 */
 487        input_report_key(g15->input, KEY_MACRO18, data[8] & 0x40);
 488
 489        /* M1 - M3 */
 490        for (i = 0; i < 3; i++) {
 491                val = data[i + 6] & (1 << i);
 492                input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val);
 493        }
 494        /* MR */
 495        input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40);
 496
 497        /* Most left (round) button below the LCD */
 498        input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80);
 499        /* 4 other buttons below the LCD */
 500        for (i = 0; i < 4; i++) {
 501                val = data[i + 2] & 0x80;
 502                input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
 503        }
 504
 505        /* Backlight cycle button pressed? */
 506        if (data[1] & 0x80)
 507                schedule_work(&g15->work);
 508
 509        input_sync(g15->input);
 510        return 0;
 511}
 512
 513static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data, int size)
 514{
 515        int i, val;
 516
 517        /* G1 - G6 */
 518        for (i = 0; i < 6; i++) {
 519                val = data[1] & (1 << i);
 520                input_report_key(g15->input, KEY_MACRO1 + i, val);
 521        }
 522
 523        /* M1 - M3 + MR */
 524        input_report_key(g15->input, KEY_MACRO_PRESET1, data[1] & 0x40);
 525        input_report_key(g15->input, KEY_MACRO_PRESET2, data[1] & 0x80);
 526        input_report_key(g15->input, KEY_MACRO_PRESET3, data[2] & 0x20);
 527        input_report_key(g15->input, KEY_MACRO_RECORD_START, data[2] & 0x40);
 528
 529        /* Round button to the left of the LCD */
 530        input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[2] & 0x80);
 531        /* 4 buttons below the LCD */
 532        for (i = 0; i < 4; i++) {
 533                val = data[2] & (2 << i);
 534                input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
 535        }
 536
 537        /* Backlight cycle button pressed? */
 538        if (data[2] & 0x01)
 539                schedule_work(&g15->work);
 540
 541        input_sync(g15->input);
 542        return 0;
 543}
 544
 545static int lg_g510_event(struct lg_g15_data *g15, u8 *data, int size)
 546{
 547        bool game_mode_enabled;
 548        int i, val;
 549
 550        /* G1 - G18 */
 551        for (i = 0; i < 18; i++) {
 552                val = data[i / 8 + 1] & (1 << (i % 8));
 553                input_report_key(g15->input, KEY_MACRO1 + i, val);
 554        }
 555
 556        /* Game mode on/off slider */
 557        game_mode_enabled = data[3] & 0x04;
 558        if (game_mode_enabled != g15->game_mode_enabled) {
 559                if (game_mode_enabled)
 560                        hid_info(g15->hdev, "Game Mode enabled, Windows (super) key is disabled\n");
 561                else
 562                        hid_info(g15->hdev, "Game Mode disabled\n");
 563                g15->game_mode_enabled = game_mode_enabled;
 564        }
 565
 566        /* M1 - M3 */
 567        for (i = 0; i < 3; i++) {
 568                val = data[3] & (0x10 << i);
 569                input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val);
 570        }
 571        /* MR */
 572        input_report_key(g15->input, KEY_MACRO_RECORD_START, data[3] & 0x80);
 573
 574        /* LCD menu keys */
 575        for (i = 0; i < 5; i++) {
 576                val = data[4] & (1 << i);
 577                input_report_key(g15->input, KEY_KBD_LCD_MENU1 + i, val);
 578        }
 579
 580        /* Headphone Mute */
 581        input_report_key(g15->input, KEY_MUTE, data[4] & 0x20);
 582        /* Microphone Mute */
 583        input_report_key(g15->input, KEY_F20, data[4] & 0x40);
 584
 585        input_sync(g15->input);
 586        return 0;
 587}
 588
 589static int lg_g510_leds_event(struct lg_g15_data *g15, u8 *data, int size)
 590{
 591        bool backlight_disabled;
 592
 593        /*
 594         * The G510 ignores backlight updates when the backlight is turned off
 595         * through the light toggle button on the keyboard, to work around this
 596         * we queue a workitem to sync values when the backlight is turned on.
 597         */
 598        backlight_disabled = data[1] & 0x04;
 599        if (!backlight_disabled)
 600                schedule_work(&g15->work);
 601
 602        return 0;
 603}
 604
 605static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
 606                            u8 *data, int size)
 607{
 608        struct lg_g15_data *g15 = hid_get_drvdata(hdev);
 609
 610        if (!g15)
 611                return 0;
 612
 613        switch (g15->model) {
 614        case LG_G15:
 615                if (data[0] == 0x02 && size == 9)
 616                        return lg_g15_event(g15, data, size);
 617                break;
 618        case LG_G15_V2:
 619                if (data[0] == 0x02 && size == 5)
 620                        return lg_g15_v2_event(g15, data, size);
 621                break;
 622        case LG_G510:
 623        case LG_G510_USB_AUDIO:
 624                if (data[0] == 0x03 && size == 5)
 625                        return lg_g510_event(g15, data, size);
 626                if (data[0] == 0x04 && size == 2)
 627                        return lg_g510_leds_event(g15, data, size);
 628                break;
 629        }
 630
 631        return 0;
 632}
 633
 634static int lg_g15_input_open(struct input_dev *dev)
 635{
 636        struct hid_device *hdev = input_get_drvdata(dev);
 637
 638        return hid_hw_open(hdev);
 639}
 640
 641static void lg_g15_input_close(struct input_dev *dev)
 642{
 643        struct hid_device *hdev = input_get_drvdata(dev);
 644
 645        hid_hw_close(hdev);
 646}
 647
 648static int lg_g15_register_led(struct lg_g15_data *g15, int i)
 649{
 650        static const char * const led_names[] = {
 651                "g15::kbd_backlight",
 652                "g15::lcd_backlight",
 653                "g15::macro_preset1",
 654                "g15::macro_preset2",
 655                "g15::macro_preset3",
 656                "g15::macro_record",
 657        };
 658
 659        g15->leds[i].led = i;
 660        g15->leds[i].cdev.name = led_names[i];
 661
 662        switch (g15->model) {
 663        case LG_G15:
 664        case LG_G15_V2:
 665                g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set;
 666                g15->leds[i].cdev.brightness_get = lg_g15_led_get;
 667                if (i < LG_G15_BRIGHTNESS_MAX) {
 668                        g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED;
 669                        g15->leds[i].cdev.max_brightness = 2;
 670                } else {
 671                        g15->leds[i].cdev.max_brightness = 1;
 672                }
 673                break;
 674        case LG_G510:
 675        case LG_G510_USB_AUDIO:
 676                switch (i) {
 677                case LG_G15_LCD_BRIGHTNESS:
 678                        /*
 679                         * The G510 does not have a separate LCD brightness,
 680                         * but it does have a separate power-on (reset) value.
 681                         */
 682                        g15->leds[i].cdev.name = "g15::power_on_backlight_val";
 683                        fallthrough;
 684                case LG_G15_KBD_BRIGHTNESS:
 685                        g15->leds[i].cdev.brightness_set_blocking =
 686                                lg_g510_kbd_led_set;
 687                        g15->leds[i].cdev.brightness_get =
 688                                lg_g510_kbd_led_get;
 689                        g15->leds[i].cdev.max_brightness = 255;
 690                        g15->leds[i].cdev.groups = lg_g510_kbd_led_groups;
 691                        break;
 692                default:
 693                        g15->leds[i].cdev.brightness_set_blocking =
 694                                lg_g510_mkey_led_set;
 695                        g15->leds[i].cdev.brightness_get =
 696                                lg_g510_mkey_led_get;
 697                        g15->leds[i].cdev.max_brightness = 1;
 698                }
 699                break;
 700        }
 701
 702        return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
 703}
 704
 705static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
 706{
 707        u8 gkeys_settings_output_report = 0;
 708        u8 gkeys_settings_feature_report = 0;
 709        struct hid_report_enum *rep_enum;
 710        unsigned int connect_mask = 0;
 711        bool has_ff000000 = false;
 712        struct lg_g15_data *g15;
 713        struct input_dev *input;
 714        struct hid_report *rep;
 715        int ret, i, gkeys = 0;
 716
 717        hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
 718
 719        ret = hid_parse(hdev);
 720        if (ret)
 721                return ret;
 722
 723        /*
 724         * Some models have multiple interfaces, we want the interface with
 725         * with the f000.0000 application input report.
 726         */
 727        rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
 728        list_for_each_entry(rep, &rep_enum->report_list, list) {
 729                if (rep->application == 0xff000000)
 730                        has_ff000000 = true;
 731        }
 732        if (!has_ff000000)
 733                return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 734
 735        g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL);
 736        if (!g15)
 737                return -ENOMEM;
 738
 739        mutex_init(&g15->mutex);
 740
 741        input = devm_input_allocate_device(&hdev->dev);
 742        if (!input)
 743                return -ENOMEM;
 744
 745        g15->hdev = hdev;
 746        g15->model = id->driver_data;
 747        hid_set_drvdata(hdev, (void *)g15);
 748
 749        switch (g15->model) {
 750        case LG_G15:
 751                INIT_WORK(&g15->work, lg_g15_leds_changed_work);
 752                /*
 753                 * The G15 and G15 v2 use a separate usb-device (on a builtin
 754                 * hub) which emulates a keyboard for the F1 - F12 emulation
 755                 * on the G-keys, which we disable, rendering the emulated kbd
 756                 * non-functional, so we do not let hid-input connect.
 757                 */
 758                connect_mask = HID_CONNECT_HIDRAW;
 759                gkeys_settings_output_report = 0x02;
 760                gkeys = 18;
 761                break;
 762        case LG_G15_V2:
 763                INIT_WORK(&g15->work, lg_g15_leds_changed_work);
 764                connect_mask = HID_CONNECT_HIDRAW;
 765                gkeys_settings_output_report = 0x02;
 766                gkeys = 6;
 767                break;
 768        case LG_G510:
 769        case LG_G510_USB_AUDIO:
 770                INIT_WORK(&g15->work, lg_g510_leds_sync_work);
 771                connect_mask = HID_CONNECT_HIDINPUT | HID_CONNECT_HIDRAW;
 772                gkeys_settings_feature_report = 0x01;
 773                gkeys = 18;
 774                break;
 775        }
 776
 777        ret = hid_hw_start(hdev, connect_mask);
 778        if (ret)
 779                return ret;
 780
 781        /* Tell the keyboard to stop sending F1-F12 + 1-6 for G1 - G18 */
 782        if (gkeys_settings_output_report) {
 783                g15->transfer_buf[0] = gkeys_settings_output_report;
 784                memset(g15->transfer_buf + 1, 0, gkeys);
 785                /*
 786                 * The kbd ignores our output report if we do not queue
 787                 * an URB on the USB input endpoint first...
 788                 */
 789                ret = hid_hw_open(hdev);
 790                if (ret)
 791                        goto error_hw_stop;
 792                ret = hid_hw_output_report(hdev, g15->transfer_buf, gkeys + 1);
 793                hid_hw_close(hdev);
 794        }
 795
 796        if (gkeys_settings_feature_report) {
 797                g15->transfer_buf[0] = gkeys_settings_feature_report;
 798                memset(g15->transfer_buf + 1, 0, gkeys);
 799                ret = hid_hw_raw_request(g15->hdev,
 800                                gkeys_settings_feature_report,
 801                                g15->transfer_buf, gkeys + 1,
 802                                HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 803        }
 804
 805        if (ret < 0) {
 806                hid_err(hdev, "Error %d disabling keyboard emulation for the G-keys, falling back to generic hid-input driver\n",
 807                        ret);
 808                hid_set_drvdata(hdev, NULL);
 809                return 0;
 810        }
 811
 812        /* Get initial brightness levels */
 813        ret = lg_g15_get_initial_led_brightness(g15);
 814        if (ret)
 815                goto error_hw_stop;
 816
 817        /* Setup and register input device */
 818        input->name = "Logitech Gaming Keyboard Gaming Keys";
 819        input->phys = hdev->phys;
 820        input->uniq = hdev->uniq;
 821        input->id.bustype = hdev->bus;
 822        input->id.vendor  = hdev->vendor;
 823        input->id.product = hdev->product;
 824        input->id.version = hdev->version;
 825        input->dev.parent = &hdev->dev;
 826        input->open = lg_g15_input_open;
 827        input->close = lg_g15_input_close;
 828
 829        /* G-keys */
 830        for (i = 0; i < gkeys; i++)
 831                input_set_capability(input, EV_KEY, KEY_MACRO1 + i);
 832
 833        /* M1 - M3 and MR keys */
 834        for (i = 0; i < 3; i++)
 835                input_set_capability(input, EV_KEY, KEY_MACRO_PRESET1 + i);
 836        input_set_capability(input, EV_KEY, KEY_MACRO_RECORD_START);
 837
 838        /* Keys below the LCD, intended for controlling a menu on the LCD */
 839        for (i = 0; i < 5; i++)
 840                input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
 841
 842        /*
 843         * On the G510 only report headphone and mic mute keys when *not* using
 844         * the builtin USB audio device. When the builtin audio is used these
 845         * keys directly toggle mute (and the LEDs) on/off.
 846         */
 847        if (g15->model == LG_G510) {
 848                input_set_capability(input, EV_KEY, KEY_MUTE);
 849                /* Userspace expects F20 for micmute */
 850                input_set_capability(input, EV_KEY, KEY_F20);
 851        }
 852
 853        g15->input = input;
 854        input_set_drvdata(input, hdev);
 855
 856        ret = input_register_device(input);
 857        if (ret)
 858                goto error_hw_stop;
 859
 860        /* Register LED devices */
 861        for (i = 0; i < LG_G15_LED_MAX; i++) {
 862                ret = lg_g15_register_led(g15, i);
 863                if (ret)
 864                        goto error_hw_stop;
 865        }
 866
 867        return 0;
 868
 869error_hw_stop:
 870        hid_hw_stop(hdev);
 871        return ret;
 872}
 873
 874static const struct hid_device_id lg_g15_devices[] = {
 875        /* The G11 is a G15 without the LCD, treat it as a G15 */
 876        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 877                USB_DEVICE_ID_LOGITECH_G11),
 878                .driver_data = LG_G15 },
 879        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 880                         USB_DEVICE_ID_LOGITECH_G15_LCD),
 881                .driver_data = LG_G15 },
 882        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 883                         USB_DEVICE_ID_LOGITECH_G15_V2_LCD),
 884                .driver_data = LG_G15_V2 },
 885        /* G510 without a headset plugged in */
 886        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 887                         USB_DEVICE_ID_LOGITECH_G510),
 888                .driver_data = LG_G510 },
 889        /* G510 with headset plugged in / with extra USB audio interface */
 890        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 891                         USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO),
 892                .driver_data = LG_G510_USB_AUDIO },
 893        { }
 894};
 895MODULE_DEVICE_TABLE(hid, lg_g15_devices);
 896
 897static struct hid_driver lg_g15_driver = {
 898        .name                   = "lg-g15",
 899        .id_table               = lg_g15_devices,
 900        .raw_event              = lg_g15_raw_event,
 901        .probe                  = lg_g15_probe,
 902};
 903module_hid_driver(lg_g15_driver);
 904
 905MODULE_LICENSE("GPL");
 906