1 // SPDX-License-Identifier: GPL-2.0+
3 * HID driver for gaming keys on Logitech gaming keyboards (such as the G15)
5 * Copyright (c) 2019 Hans de Goede <hdegoede@redhat.com>
8 #include <linux/device.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>
18 #define LG_G15_TRANSFER_BUF_SIZE 20
20 #define LG_G15_FEATURE_REPORT 0x02
29 enum lg_g15_led_type {
30 LG_G15_KBD_BRIGHTNESS,
31 LG_G15_LCD_BRIGHTNESS,
32 LG_G15_BRIGHTNESS_MAX,
33 LG_G15_MACRO_PRESET1 = 2,
41 struct led_classdev cdev;
42 enum led_brightness brightness;
43 enum lg_g15_led_type led;
47 /* Must be first for proper dma alignment */
48 u8 transfer_buf[LG_G15_TRANSFER_BUF_SIZE];
49 /* Protects the transfer_buf and led brightness */
51 struct work_struct work;
52 struct input_dev *input;
53 struct hid_device *hdev;
54 enum lg_g15_model model;
55 struct lg_g15_led leds[LG_G15_LED_MAX];
56 bool game_mode_enabled;
59 static int lg_g15_update_led_brightness(struct lg_g15_data *g15)
63 if (g15->model == LG_G510 || g15->model == LG_G510_USB_AUDIO)
66 ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT,
68 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
70 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
71 return (ret < 0) ? ret : -EIO;
74 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = g15->transfer_buf[1];
75 g15->leds[LG_G15_LCD_BRIGHTNESS].brightness = g15->transfer_buf[2];
77 g15->leds[LG_G15_MACRO_PRESET1].brightness =
78 !(g15->transfer_buf[3] & 0x01);
79 g15->leds[LG_G15_MACRO_PRESET2].brightness =
80 !(g15->transfer_buf[3] & 0x02);
81 g15->leds[LG_G15_MACRO_PRESET3].brightness =
82 !(g15->transfer_buf[3] & 0x04);
83 g15->leds[LG_G15_MACRO_RECORD].brightness =
84 !(g15->transfer_buf[3] & 0x08);
89 static enum led_brightness lg_g15_led_get(struct led_classdev *led_cdev)
91 struct lg_g15_led *g15_led =
92 container_of(led_cdev, struct lg_g15_led, cdev);
93 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
94 enum led_brightness brightness;
96 mutex_lock(&g15->mutex);
97 lg_g15_update_led_brightness(g15);
98 brightness = g15->leds[g15_led->led].brightness;
99 mutex_unlock(&g15->mutex);
104 static int lg_g15_led_set(struct led_classdev *led_cdev,
105 enum led_brightness brightness)
107 struct lg_g15_led *g15_led =
108 container_of(led_cdev, struct lg_g15_led, cdev);
109 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
113 /* Ignore LED off on unregister / keyboard unplug */
114 if (led_cdev->flags & LED_UNREGISTERING)
117 mutex_lock(&g15->mutex);
119 g15->transfer_buf[0] = LG_G15_FEATURE_REPORT;
120 g15->transfer_buf[3] = 0;
122 if (g15_led->led < LG_G15_BRIGHTNESS_MAX) {
123 g15->transfer_buf[1] = g15_led->led + 1;
124 g15->transfer_buf[2] = brightness << (g15_led->led * 4);
126 for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
127 if (i == g15_led->led)
130 val = g15->leds[i].brightness;
133 mask |= 1 << (i - LG_G15_MACRO_PRESET1);
136 g15->transfer_buf[1] = 0x04;
137 g15->transfer_buf[2] = ~mask;
140 ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT,
141 g15->transfer_buf, 4,
142 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
145 g15_led->brightness = brightness;
148 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
149 ret = (ret < 0) ? ret : -EIO;
152 mutex_unlock(&g15->mutex);
157 static void lg_g15_leds_changed_work(struct work_struct *work)
159 struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
160 enum led_brightness old_brightness[LG_G15_BRIGHTNESS_MAX];
161 enum led_brightness brightness[LG_G15_BRIGHTNESS_MAX];
164 mutex_lock(&g15->mutex);
165 for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
166 old_brightness[i] = g15->leds[i].brightness;
168 ret = lg_g15_update_led_brightness(g15);
170 for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
171 brightness[i] = g15->leds[i].brightness;
172 mutex_unlock(&g15->mutex);
177 for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++) {
178 if (brightness[i] == old_brightness[i])
181 led_classdev_notify_brightness_hw_changed(&g15->leds[i].cdev,
186 /* On the G15 Mark I Logitech has been quite creative with which bit is what */
187 static int lg_g15_event(struct lg_g15_data *g15, u8 *data, int size)
192 for (i = 0; i < 6; i++) {
193 val = data[i + 1] & (1 << i);
194 input_report_key(g15->input, KEY_MACRO1 + i, val);
197 for (i = 0; i < 6; i++) {
198 val = data[i + 2] & (1 << i);
199 input_report_key(g15->input, KEY_MACRO7 + i, val);
202 for (i = 0; i < 5; i++) {
203 val = data[i + 1] & (4 << i);
204 input_report_key(g15->input, KEY_MACRO13 + i, val);
207 input_report_key(g15->input, KEY_MACRO18, data[8] & 0x40);
210 for (i = 0; i < 3; i++) {
211 val = data[i + 6] & (1 << i);
212 input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val);
215 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40);
217 /* Most left (round) button below the LCD */
218 input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80);
219 /* 4 other buttons below the LCD */
220 for (i = 0; i < 4; i++) {
221 val = data[i + 2] & 0x80;
222 input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
225 /* Backlight cycle button pressed? */
227 schedule_work(&g15->work);
229 input_sync(g15->input);
233 static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data, int size)
238 for (i = 0; i < 6; i++) {
239 val = data[1] & (1 << i);
240 input_report_key(g15->input, KEY_MACRO1 + i, val);
244 input_report_key(g15->input, KEY_MACRO_PRESET1, data[1] & 0x40);
245 input_report_key(g15->input, KEY_MACRO_PRESET2, data[1] & 0x80);
246 input_report_key(g15->input, KEY_MACRO_PRESET3, data[2] & 0x20);
247 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[2] & 0x40);
249 /* Round button to the left of the LCD */
250 input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[2] & 0x80);
251 /* 4 buttons below the LCD */
252 for (i = 0; i < 4; i++) {
253 val = data[2] & (2 << i);
254 input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val);
257 /* Backlight cycle button pressed? */
259 schedule_work(&g15->work);
261 input_sync(g15->input);
265 static int lg_g510_event(struct lg_g15_data *g15, u8 *data, int size)
267 bool game_mode_enabled;
271 for (i = 0; i < 18; i++) {
272 val = data[i / 8 + 1] & (1 << (i % 8));
273 input_report_key(g15->input, KEY_MACRO1 + i, val);
276 /* Game mode on/off slider */
277 game_mode_enabled = data[3] & 0x04;
278 if (game_mode_enabled != g15->game_mode_enabled) {
279 if (game_mode_enabled)
280 hid_info(g15->hdev, "Game Mode enabled, Windows (super) key is disabled\n");
282 hid_info(g15->hdev, "Game Mode disabled\n");
283 g15->game_mode_enabled = game_mode_enabled;
287 for (i = 0; i < 3; i++) {
288 val = data[3] & (0x10 << i);
289 input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val);
292 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[3] & 0x80);
295 for (i = 0; i < 5; i++) {
296 val = data[4] & (1 << i);
297 input_report_key(g15->input, KEY_KBD_LCD_MENU1 + i, val);
301 input_report_key(g15->input, KEY_MUTE, data[4] & 0x20);
302 /* Microphone Mute */
303 input_report_key(g15->input, KEY_F20, data[4] & 0x40);
305 input_sync(g15->input);
309 static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
312 struct lg_g15_data *g15 = hid_get_drvdata(hdev);
317 switch (g15->model) {
319 if (data[0] == 0x02 && size == 9)
320 return lg_g15_event(g15, data, size);
323 if (data[0] == 0x02 && size == 5)
324 return lg_g15_v2_event(g15, data, size);
327 case LG_G510_USB_AUDIO:
328 if (data[0] == 0x03 && size == 5)
329 return lg_g510_event(g15, data, size);
336 static int lg_g15_input_open(struct input_dev *dev)
338 struct hid_device *hdev = input_get_drvdata(dev);
340 return hid_hw_open(hdev);
343 static void lg_g15_input_close(struct input_dev *dev)
345 struct hid_device *hdev = input_get_drvdata(dev);
350 static int lg_g15_register_led(struct lg_g15_data *g15, int i)
352 const char * const led_names[] = {
353 "g15::kbd_backlight",
354 "g15::lcd_backlight",
355 "g15::macro_preset1",
356 "g15::macro_preset2",
357 "g15::macro_preset3",
361 g15->leds[i].led = i;
362 g15->leds[i].cdev.name = led_names[i];
363 g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set;
364 g15->leds[i].cdev.brightness_get = lg_g15_led_get;
365 if (i < LG_G15_BRIGHTNESS_MAX) {
366 g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED;
367 g15->leds[i].cdev.max_brightness = 2;
369 g15->leds[i].cdev.max_brightness = 1;
372 return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
375 static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
377 u8 gkeys_settings_output_report = 0;
378 u8 gkeys_settings_feature_report = 0;
379 struct hid_report_enum *rep_enum;
380 unsigned int connect_mask = 0;
381 bool has_ff000000 = false;
382 struct lg_g15_data *g15;
383 struct input_dev *input;
384 struct hid_report *rep;
385 int ret, i, gkeys = 0;
387 hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
389 ret = hid_parse(hdev);
394 * Some models have multiple interfaces, we want the interface with
395 * with the f000.0000 application input report.
397 rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
398 list_for_each_entry(rep, &rep_enum->report_list, list) {
399 if (rep->application == 0xff000000)
403 return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
405 g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL);
409 mutex_init(&g15->mutex);
411 input = devm_input_allocate_device(&hdev->dev);
416 g15->model = id->driver_data;
417 INIT_WORK(&g15->work, lg_g15_leds_changed_work);
418 hid_set_drvdata(hdev, (void *)g15);
420 switch (g15->model) {
423 * The G15 and G15 v2 use a separate usb-device (on a builtin
424 * hub) which emulates a keyboard for the F1 - F12 emulation
425 * on the G-keys, which we disable, rendering the emulated kbd
426 * non-functional, so we do not let hid-input connect.
428 connect_mask = HID_CONNECT_HIDRAW;
429 gkeys_settings_output_report = 0x02;
433 connect_mask = HID_CONNECT_HIDRAW;
434 gkeys_settings_output_report = 0x02;
438 case LG_G510_USB_AUDIO:
439 connect_mask = HID_CONNECT_HIDINPUT | HID_CONNECT_HIDRAW;
440 gkeys_settings_feature_report = 0x01;
445 ret = hid_hw_start(hdev, connect_mask);
449 /* Tell the keyboard to stop sending F1-F12 + 1-6 for G1 - G18 */
450 if (gkeys_settings_output_report) {
451 g15->transfer_buf[0] = gkeys_settings_output_report;
452 memset(g15->transfer_buf + 1, 0, gkeys);
454 * The kbd ignores our output report if we do not queue
455 * an URB on the USB input endpoint first...
457 ret = hid_hw_open(hdev);
460 ret = hid_hw_output_report(hdev, g15->transfer_buf, gkeys + 1);
464 if (gkeys_settings_feature_report) {
465 g15->transfer_buf[0] = gkeys_settings_feature_report;
466 memset(g15->transfer_buf + 1, 0, gkeys);
467 ret = hid_hw_raw_request(g15->hdev,
468 gkeys_settings_feature_report,
469 g15->transfer_buf, gkeys + 1,
470 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
474 hid_err(hdev, "Error disabling keyboard emulation for the G-keys\n");
478 /* Get initial brightness levels */
479 ret = lg_g15_update_led_brightness(g15);
483 /* Setup and register input device */
484 input->name = "Logitech Gaming Keyboard Gaming Keys";
485 input->phys = hdev->phys;
486 input->uniq = hdev->uniq;
487 input->id.bustype = hdev->bus;
488 input->id.vendor = hdev->vendor;
489 input->id.product = hdev->product;
490 input->id.version = hdev->version;
491 input->dev.parent = &hdev->dev;
492 input->open = lg_g15_input_open;
493 input->close = lg_g15_input_close;
496 for (i = 0; i < gkeys; i++)
497 input_set_capability(input, EV_KEY, KEY_MACRO1 + i);
499 /* M1 - M3 and MR keys */
500 for (i = 0; i < 3; i++)
501 input_set_capability(input, EV_KEY, KEY_MACRO_PRESET1 + i);
502 input_set_capability(input, EV_KEY, KEY_MACRO_RECORD_START);
504 /* Keys below the LCD, intended for controlling a menu on the LCD */
505 for (i = 0; i < 5; i++)
506 input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
509 * On the G510 only report headphone and mic mute keys when *not* using
510 * the builtin USB audio device. When the builtin audio is used these
511 * keys directly toggle mute (and the LEDs) on/off.
513 if (g15->model == LG_G510) {
514 input_set_capability(input, EV_KEY, KEY_MUTE);
515 /* Userspace expects F20 for micmute */
516 input_set_capability(input, EV_KEY, KEY_F20);
520 input_set_drvdata(input, hdev);
522 ret = input_register_device(input);
526 if (g15->model == LG_G510 || g15->model == LG_G510_USB_AUDIO)
529 /* Register LED devices */
530 for (i = 0; i < LG_G15_LED_MAX; i++) {
531 ret = lg_g15_register_led(g15, i);
543 static const struct hid_device_id lg_g15_devices[] = {
544 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
545 USB_DEVICE_ID_LOGITECH_G15_LCD),
546 .driver_data = LG_G15 },
547 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
548 USB_DEVICE_ID_LOGITECH_G15_V2_LCD),
549 .driver_data = LG_G15_V2 },
550 /* G510 without a headset plugged in */
551 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
552 USB_DEVICE_ID_LOGITECH_G510),
553 .driver_data = LG_G510 },
554 /* G510 with headset plugged in / with extra USB audio interface */
555 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
556 USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO),
557 .driver_data = LG_G510_USB_AUDIO },
560 MODULE_DEVICE_TABLE(hid, lg_g15_devices);
562 static struct hid_driver lg_g15_driver = {
564 .id_table = lg_g15_devices,
565 .raw_event = lg_g15_raw_event,
566 .probe = lg_g15_probe,
568 module_hid_driver(lg_g15_driver);
570 MODULE_LICENSE("GPL");