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/leds.h>
11#include <linux/led-class-multicolor.h>
12#include <linux/module.h>
13#include <linux/random.h>
14#include <linux/sched.h>
15#include <linux/usb.h>
16#include <linux/wait.h>
17#include <dt-bindings/leds/common.h>
18
19#include "hid-ids.h"
20
21#define LG_G15_TRANSFER_BUF_SIZE 20
22
23#define LG_G15_FEATURE_REPORT 0x02
24
25#define LG_G510_FEATURE_M_KEYS_LEDS 0x04
26#define LG_G510_FEATURE_BACKLIGHT_RGB 0x05
27#define LG_G510_FEATURE_POWER_ON_RGB 0x06
28
29#define LG_G510_INPUT_MACRO_KEYS 0x03
30#define LG_G510_INPUT_KBD_BACKLIGHT 0x04
31
32#define LG_G13_INPUT_REPORT 0x01
33#define LG_G13_FEATURE_M_KEYS_LEDS 0x05
34#define LG_G13_FEATURE_BACKLIGHT_RGB 0x07
35#define LG_G13_BACKLIGHT_HW_ON_BIT 23
36
37/**
38 * g13_input_report.keybits[] is not 32-bit aligned, so we can't use the bitops macros.
39 *
40 * @ary: Pointer to array of u8s
41 * @b: Bit index into ary, LSB first. Not range checked.
42 */
43#define TEST_BIT(ary, b) ((1 << ((b) & 7)) & (ary)[(b) >> 3])
44
45enum lg_g15_model {
46 LG_G13,
47 LG_G15,
48 LG_G15_V2,
49 LG_G510,
50 LG_G510_USB_AUDIO,
51 LG_Z10,
52};
53
54enum lg_g15_led_type {
55 LG_G15_KBD_BRIGHTNESS,
56 LG_G15_LCD_BRIGHTNESS,
57 LG_G15_BRIGHTNESS_MAX,
58 LG_G15_MACRO_PRESET1 = 2,
59 LG_G15_MACRO_PRESET2,
60 LG_G15_MACRO_PRESET3,
61 LG_G15_MACRO_RECORD,
62 LG_G15_LED_MAX
63};
64
65struct g13_input_report {
66 u8 report_id; /* Report ID is always set to 1. */
67 u8 joy_x, joy_y;
68 u8 keybits[5];
69};
70
71struct lg_g15_led {
72 union {
73 struct led_classdev cdev;
74 struct led_classdev_mc mcdev;
75 };
76 enum led_brightness brightness;
77 enum lg_g15_led_type led;
78 /* Used to store initial color intensities before subled_info is allocated */
79 u8 red, green, blue;
80};
81
82struct lg_g15_data {
83 /* Must be first for proper dma alignment */
84 u8 transfer_buf[LG_G15_TRANSFER_BUF_SIZE];
85 /* Protects the transfer_buf and led brightness */
86 struct mutex mutex;
87 struct work_struct work;
88 struct input_dev *input;
89 struct input_dev *input_js; /* Separate joystick device for G13. */
90 struct hid_device *hdev;
91 enum lg_g15_model model;
92 struct lg_g15_led leds[LG_G15_LED_MAX];
93 bool game_mode_enabled;
94 bool backlight_disabled; /* true == HW backlight toggled *OFF* */
95};
96
97/********* G13 LED functions ***********/
98/*
99 * G13 retains no state across power cycles, and always powers up with the backlight on,
100 * color #5AFF6E, all macro key LEDs off.
101 */
102static int lg_g13_get_leds_state(struct lg_g15_data *g15)
103{
104 u8 * const tbuf = g15->transfer_buf;
105 int ret, high;
106
107 /* RGB backlight. */
108 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G13_FEATURE_BACKLIGHT_RGB,
109 buf: tbuf, len: 5,
110 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT);
111 if (ret != 5) {
112 hid_err(g15->hdev, "Error getting backlight brightness: %d\n", ret);
113 return (ret < 0) ? ret : -EIO;
114 }
115
116 /* Normalize RGB intensities against the highest component. */
117 high = max3(tbuf[1], tbuf[2], tbuf[3]);
118 if (high) {
119 g15->leds[LG_G15_KBD_BRIGHTNESS].red =
120 DIV_ROUND_CLOSEST(tbuf[1] * 255, high);
121 g15->leds[LG_G15_KBD_BRIGHTNESS].green =
122 DIV_ROUND_CLOSEST(tbuf[2] * 255, high);
123 g15->leds[LG_G15_KBD_BRIGHTNESS].blue =
124 DIV_ROUND_CLOSEST(tbuf[3] * 255, high);
125 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = high;
126 } else {
127 g15->leds[LG_G15_KBD_BRIGHTNESS].red = 255;
128 g15->leds[LG_G15_KBD_BRIGHTNESS].green = 255;
129 g15->leds[LG_G15_KBD_BRIGHTNESS].blue = 255;
130 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = 0;
131 }
132
133 /* Macro LEDs. */
134 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G13_FEATURE_M_KEYS_LEDS,
135 buf: tbuf, len: 5,
136 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT);
137 if (ret != 5) {
138 hid_err(g15->hdev, "Error getting macro LED brightness: %d\n", ret);
139 return (ret < 0) ? ret : -EIO;
140 }
141
142 for (int i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; ++i)
143 g15->leds[i].brightness = !!(tbuf[1] & (1 << (i - LG_G15_MACRO_PRESET1)));
144
145 /*
146 * Bit 23 of g13_input_report.keybits[] contains the backlight's
147 * current HW toggle state. Retrieve it from the device.
148 */
149 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G13_INPUT_REPORT,
150 buf: tbuf, len: sizeof(struct g13_input_report),
151 rtype: HID_INPUT_REPORT, reqtype: HID_REQ_GET_REPORT);
152 if (ret != sizeof(struct g13_input_report)) {
153 hid_err(g15->hdev, "Error getting backlight on/off state: %d\n", ret);
154 return (ret < 0) ? ret : -EIO;
155 }
156 g15->backlight_disabled =
157 !TEST_BIT(((struct g13_input_report *) tbuf)->keybits,
158 LG_G13_BACKLIGHT_HW_ON_BIT);
159
160 return 0;
161}
162
163static int lg_g13_kbd_led_write(struct lg_g15_data *g15,
164 struct lg_g15_led *g15_led,
165 enum led_brightness brightness)
166{
167 struct mc_subled const * const subleds = g15_led->mcdev.subled_info;
168 u8 * const tbuf = g15->transfer_buf;
169 int ret;
170
171 guard(mutex)(T: &g15->mutex);
172
173 led_mc_calc_color_components(mcled_cdev: &g15_led->mcdev, brightness);
174
175 tbuf[0] = 5;
176 tbuf[1] = subleds[0].brightness;
177 tbuf[2] = subleds[1].brightness;
178 tbuf[3] = subleds[2].brightness;
179 tbuf[4] = 0;
180
181 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G13_FEATURE_BACKLIGHT_RGB,
182 buf: tbuf, len: 5,
183 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT);
184 if (ret != 5) {
185 hid_err(g15->hdev, "Error setting backlight brightness: %d\n", ret);
186 return (ret < 0) ? ret : -EIO;
187 }
188
189 g15_led->brightness = brightness;
190 return 0;
191}
192
193static int lg_g13_kbd_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
194{
195 struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
196 struct lg_g15_led *g15_led =
197 container_of(mc, struct lg_g15_led, mcdev);
198 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
199
200 /* Ignore LED off on unregister / keyboard unplug */
201 if (led_cdev->flags & LED_UNREGISTERING)
202 return 0;
203
204 return lg_g13_kbd_led_write(g15, g15_led, brightness);
205}
206
207static enum led_brightness lg_g13_kbd_led_get(struct led_classdev *led_cdev)
208{
209 struct led_classdev_mc const * const mc = lcdev_to_mccdev(led_cdev);
210 struct lg_g15_led const *g15_led =
211 container_of(mc, struct lg_g15_led, mcdev);
212
213 return g15_led->brightness;
214}
215
216static int lg_g13_mkey_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
217{
218 struct lg_g15_led *g15_led =
219 container_of(led_cdev, struct lg_g15_led, cdev);
220 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
221 int i, ret;
222 u8 * const tbuf = g15->transfer_buf;
223 u8 val, mask = 0;
224
225 /* Ignore LED off on unregister / keyboard unplug */
226 if (led_cdev->flags & LED_UNREGISTERING)
227 return 0;
228
229 guard(mutex)(T: &g15->mutex);
230
231 for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; ++i) {
232 if (i == g15_led->led)
233 val = brightness;
234 else
235 val = g15->leds[i].brightness;
236
237 if (val)
238 mask |= 1 << (i - LG_G15_MACRO_PRESET1);
239 }
240
241 tbuf[0] = 5;
242 tbuf[1] = mask;
243 tbuf[2] = 0;
244 tbuf[3] = 0;
245 tbuf[4] = 0;
246
247 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G13_FEATURE_M_KEYS_LEDS,
248 buf: tbuf, len: 5,
249 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT);
250 if (ret != 5) {
251 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
252 return (ret < 0) ? ret : -EIO;
253 }
254
255 g15_led->brightness = brightness;
256 return 0;
257}
258
259static enum led_brightness lg_g13_mkey_led_get(struct led_classdev *led_cdev)
260{
261 /*
262 * G13 doesn't change macro key LEDs behind our back, so they're
263 * whatever we last set them to.
264 */
265 struct lg_g15_led *g15_led =
266 container_of(led_cdev, struct lg_g15_led, cdev);
267
268 return g15_led->brightness;
269}
270
271/******** G15 and G15 v2 LED functions ********/
272
273static int lg_g15_update_led_brightness(struct lg_g15_data *g15)
274{
275 int ret;
276
277 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G15_FEATURE_REPORT,
278 buf: g15->transfer_buf, len: 4,
279 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT);
280 if (ret != 4) {
281 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
282 return (ret < 0) ? ret : -EIO;
283 }
284
285 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = g15->transfer_buf[1];
286 g15->leds[LG_G15_LCD_BRIGHTNESS].brightness = g15->transfer_buf[2];
287
288 g15->leds[LG_G15_MACRO_PRESET1].brightness =
289 !(g15->transfer_buf[3] & 0x01);
290 g15->leds[LG_G15_MACRO_PRESET2].brightness =
291 !(g15->transfer_buf[3] & 0x02);
292 g15->leds[LG_G15_MACRO_PRESET3].brightness =
293 !(g15->transfer_buf[3] & 0x04);
294 g15->leds[LG_G15_MACRO_RECORD].brightness =
295 !(g15->transfer_buf[3] & 0x08);
296
297 return 0;
298}
299
300static enum led_brightness lg_g15_led_get(struct led_classdev *led_cdev)
301{
302 struct lg_g15_led *g15_led =
303 container_of(led_cdev, struct lg_g15_led, cdev);
304 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
305 enum led_brightness brightness;
306
307 mutex_lock(&g15->mutex);
308 lg_g15_update_led_brightness(g15);
309 brightness = g15->leds[g15_led->led].brightness;
310 mutex_unlock(lock: &g15->mutex);
311
312 return brightness;
313}
314
315static int lg_g15_led_set(struct led_classdev *led_cdev,
316 enum led_brightness brightness)
317{
318 struct lg_g15_led *g15_led =
319 container_of(led_cdev, struct lg_g15_led, cdev);
320 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
321 u8 val, mask = 0;
322 int i, ret;
323
324 /* Ignore LED off on unregister / keyboard unplug */
325 if (led_cdev->flags & LED_UNREGISTERING)
326 return 0;
327
328 mutex_lock(&g15->mutex);
329
330 g15->transfer_buf[0] = LG_G15_FEATURE_REPORT;
331 g15->transfer_buf[3] = 0;
332
333 if (g15_led->led < LG_G15_BRIGHTNESS_MAX) {
334 g15->transfer_buf[1] = g15_led->led + 1;
335 g15->transfer_buf[2] = brightness << (g15_led->led * 4);
336 } else {
337 for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
338 if (i == g15_led->led)
339 val = brightness;
340 else
341 val = g15->leds[i].brightness;
342
343 if (val)
344 mask |= 1 << (i - LG_G15_MACRO_PRESET1);
345 }
346
347 g15->transfer_buf[1] = 0x04;
348 g15->transfer_buf[2] = ~mask;
349 }
350
351 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G15_FEATURE_REPORT,
352 buf: g15->transfer_buf, len: 4,
353 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT);
354 if (ret == 4) {
355 /* Success */
356 g15_led->brightness = brightness;
357 ret = 0;
358 } else {
359 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
360 ret = (ret < 0) ? ret : -EIO;
361 }
362
363 mutex_unlock(lock: &g15->mutex);
364
365 return ret;
366}
367
368static void lg_g15_leds_changed_work(struct work_struct *work)
369{
370 struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
371 enum led_brightness old_brightness[LG_G15_BRIGHTNESS_MAX];
372 enum led_brightness brightness[LG_G15_BRIGHTNESS_MAX];
373 int i, ret;
374
375 mutex_lock(&g15->mutex);
376 for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
377 old_brightness[i] = g15->leds[i].brightness;
378
379 ret = lg_g15_update_led_brightness(g15);
380
381 for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++)
382 brightness[i] = g15->leds[i].brightness;
383 mutex_unlock(lock: &g15->mutex);
384
385 if (ret)
386 return;
387
388 for (i = 0; i < LG_G15_BRIGHTNESS_MAX; i++) {
389 if (brightness[i] == old_brightness[i])
390 continue;
391
392 led_classdev_notify_brightness_hw_changed(led_cdev: &g15->leds[i].cdev,
393 brightness: brightness[i]);
394 }
395}
396
397/******** G510 LED functions ********/
398
399static int lg_g510_get_initial_led_brightness(struct lg_g15_data *g15, int i)
400{
401 int ret, high;
402
403 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G510_FEATURE_BACKLIGHT_RGB + i,
404 buf: g15->transfer_buf, len: 4,
405 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT);
406 if (ret != 4) {
407 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
408 return (ret < 0) ? ret : -EIO;
409 }
410
411 high = max3(g15->transfer_buf[1], g15->transfer_buf[2],
412 g15->transfer_buf[3]);
413
414 if (high) {
415 g15->leds[i].red =
416 DIV_ROUND_CLOSEST(g15->transfer_buf[1] * 255, high);
417 g15->leds[i].green =
418 DIV_ROUND_CLOSEST(g15->transfer_buf[2] * 255, high);
419 g15->leds[i].blue =
420 DIV_ROUND_CLOSEST(g15->transfer_buf[3] * 255, high);
421 g15->leds[i].brightness = high;
422 } else {
423 g15->leds[i].red = 255;
424 g15->leds[i].green = 255;
425 g15->leds[i].blue = 255;
426 g15->leds[i].brightness = 0;
427 }
428
429 if (i)
430 return 0;
431
432 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G510_INPUT_KBD_BACKLIGHT,
433 buf: g15->transfer_buf, len: 2,
434 rtype: HID_INPUT_REPORT, reqtype: HID_REQ_GET_REPORT);
435 if (ret != 2) {
436 /* This can happen when a KVM switch is used, so only warn. */
437 hid_warn(g15->hdev, "Error getting backlight state: %d\n", ret);
438 return 0;
439 }
440
441 g15->backlight_disabled = g15->transfer_buf[1] & 0x04;
442
443 return 0;
444}
445
446/* Must be called with g15->mutex locked */
447static int lg_g510_kbd_led_write(struct lg_g15_data *g15,
448 struct lg_g15_led *g15_led,
449 enum led_brightness brightness)
450{
451 struct mc_subled *subleds = g15_led->mcdev.subled_info;
452 int ret;
453
454 led_mc_calc_color_components(mcled_cdev: &g15_led->mcdev, brightness);
455
456 g15->transfer_buf[0] = 5 + g15_led->led;
457 g15->transfer_buf[1] = subleds[0].brightness;
458 g15->transfer_buf[2] = subleds[1].brightness;
459 g15->transfer_buf[3] = subleds[2].brightness;
460
461 ret = hid_hw_raw_request(hdev: g15->hdev,
462 LG_G510_FEATURE_BACKLIGHT_RGB + g15_led->led,
463 buf: g15->transfer_buf, len: 4,
464 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT);
465 if (ret == 4) {
466 /* Success */
467 g15_led->brightness = brightness;
468 ret = 0;
469 } else {
470 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
471 ret = (ret < 0) ? ret : -EIO;
472 }
473
474 return ret;
475}
476
477static int lg_g510_kbd_led_set(struct led_classdev *led_cdev,
478 enum led_brightness brightness)
479{
480 struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
481 struct lg_g15_led *g15_led =
482 container_of(mc, struct lg_g15_led, mcdev);
483 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
484 int ret;
485
486 /* Ignore LED off on unregister / keyboard unplug */
487 if (led_cdev->flags & LED_UNREGISTERING)
488 return 0;
489
490 mutex_lock(&g15->mutex);
491 ret = lg_g510_kbd_led_write(g15, g15_led, brightness);
492 mutex_unlock(lock: &g15->mutex);
493
494 return ret;
495}
496
497static enum led_brightness lg_g510_kbd_led_get(struct led_classdev *led_cdev)
498{
499 struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
500 struct lg_g15_led *g15_led =
501 container_of(mc, struct lg_g15_led, mcdev);
502
503 return g15_led->brightness;
504}
505
506static void lg_g510_leds_sync_work(struct work_struct *work)
507{
508 struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
509 struct lg_g15_led *g15_led = &g15->leds[LG_G15_KBD_BRIGHTNESS];
510
511 mutex_lock(&g15->mutex);
512 lg_g510_kbd_led_write(g15, g15_led, brightness: g15_led->brightness);
513 mutex_unlock(lock: &g15->mutex);
514}
515
516static int lg_g510_update_mkey_led_brightness(struct lg_g15_data *g15)
517{
518 int ret;
519
520 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS,
521 buf: g15->transfer_buf, len: 2,
522 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT);
523 if (ret != 2) {
524 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret);
525 ret = (ret < 0) ? ret : -EIO;
526 }
527
528 g15->leds[LG_G15_MACRO_PRESET1].brightness =
529 !!(g15->transfer_buf[1] & 0x80);
530 g15->leds[LG_G15_MACRO_PRESET2].brightness =
531 !!(g15->transfer_buf[1] & 0x40);
532 g15->leds[LG_G15_MACRO_PRESET3].brightness =
533 !!(g15->transfer_buf[1] & 0x20);
534 g15->leds[LG_G15_MACRO_RECORD].brightness =
535 !!(g15->transfer_buf[1] & 0x10);
536
537 return 0;
538}
539
540static enum led_brightness lg_g510_mkey_led_get(struct led_classdev *led_cdev)
541{
542 struct lg_g15_led *g15_led =
543 container_of(led_cdev, struct lg_g15_led, cdev);
544 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
545 enum led_brightness brightness;
546
547 mutex_lock(&g15->mutex);
548 lg_g510_update_mkey_led_brightness(g15);
549 brightness = g15->leds[g15_led->led].brightness;
550 mutex_unlock(lock: &g15->mutex);
551
552 return brightness;
553}
554
555static int lg_g510_mkey_led_set(struct led_classdev *led_cdev,
556 enum led_brightness brightness)
557{
558 struct lg_g15_led *g15_led =
559 container_of(led_cdev, struct lg_g15_led, cdev);
560 struct lg_g15_data *g15 = dev_get_drvdata(dev: led_cdev->dev->parent);
561 u8 val, mask = 0;
562 int i, ret;
563
564 /* Ignore LED off on unregister / keyboard unplug */
565 if (led_cdev->flags & LED_UNREGISTERING)
566 return 0;
567
568 mutex_lock(&g15->mutex);
569
570 for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; i++) {
571 if (i == g15_led->led)
572 val = brightness;
573 else
574 val = g15->leds[i].brightness;
575
576 if (val)
577 mask |= 0x80 >> (i - LG_G15_MACRO_PRESET1);
578 }
579
580 g15->transfer_buf[0] = LG_G510_FEATURE_M_KEYS_LEDS;
581 g15->transfer_buf[1] = mask;
582
583 ret = hid_hw_raw_request(hdev: g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS,
584 buf: g15->transfer_buf, len: 2,
585 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT);
586 if (ret == 2) {
587 /* Success */
588 g15_led->brightness = brightness;
589 ret = 0;
590 } else {
591 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
592 ret = (ret < 0) ? ret : -EIO;
593 }
594
595 mutex_unlock(lock: &g15->mutex);
596
597 return ret;
598}
599
600/******** Generic LED functions ********/
601static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
602{
603 int ret;
604
605 switch (g15->model) {
606 case LG_G13:
607 return lg_g13_get_leds_state(g15);
608 case LG_G15:
609 case LG_G15_V2:
610 return lg_g15_update_led_brightness(g15);
611 case LG_G510:
612 case LG_G510_USB_AUDIO:
613 ret = lg_g510_get_initial_led_brightness(g15, i: 0);
614 if (ret)
615 return ret;
616
617 ret = lg_g510_get_initial_led_brightness(g15, i: 1);
618 if (ret)
619 return ret;
620
621 return lg_g510_update_mkey_led_brightness(g15);
622 case LG_Z10:
623 /*
624 * Getting the LCD backlight brightness is not supported.
625 * Reading Feature(2) fails with -EPIPE and this crashes
626 * the LCD and touch keys part of the speakers.
627 */
628 return 0;
629 }
630 return -EINVAL; /* Never reached */
631}
632
633/******** Input functions ********/
634
635/* Table mapping keybits[] bit positions to event codes. */
636/* Note: Indices are discontinuous to aid readability. */
637static const u16 g13_keys_for_bits[] = {
638 /* Main keypad - keys G1 - G22 */
639 [0] = KEY_MACRO1,
640 [1] = KEY_MACRO2,
641 [2] = KEY_MACRO3,
642 [3] = KEY_MACRO4,
643 [4] = KEY_MACRO5,
644 [5] = KEY_MACRO6,
645 [6] = KEY_MACRO7,
646 [7] = KEY_MACRO8,
647 [8] = KEY_MACRO9,
648 [9] = KEY_MACRO10,
649 [10] = KEY_MACRO11,
650 [11] = KEY_MACRO12,
651 [12] = KEY_MACRO13,
652 [13] = KEY_MACRO14,
653 [14] = KEY_MACRO15,
654 [15] = KEY_MACRO16,
655 [16] = KEY_MACRO17,
656 [17] = KEY_MACRO18,
657 [18] = KEY_MACRO19,
658 [19] = KEY_MACRO20,
659 [20] = KEY_MACRO21,
660 [21] = KEY_MACRO22,
661
662 /* LCD menu buttons. */
663 [24] = KEY_KBD_LCD_MENU5, /* "Next page" button */
664 [25] = KEY_KBD_LCD_MENU1, /* Left-most */
665 [26] = KEY_KBD_LCD_MENU2,
666 [27] = KEY_KBD_LCD_MENU3,
667 [28] = KEY_KBD_LCD_MENU4, /* Right-most */
668
669 /* Macro preset and record buttons; have red LEDs under them. */
670 [29] = KEY_MACRO_PRESET1,
671 [30] = KEY_MACRO_PRESET2,
672 [31] = KEY_MACRO_PRESET3,
673 [32] = KEY_MACRO_RECORD_START,
674
675 /* 33-35 handled by joystick device. */
676
677 /* Backlight toggle. */
678 [37] = KEY_LIGHTS_TOGGLE,
679};
680
681#define G13_JS_KEYBITS_OFFSET 33
682
683static const u16 g13_keys_for_bits_js[] = {
684 /* Joystick buttons */
685 /* These keybits are at bit indices 33, 34, and 35. */
686 BTN_BASE, /* Left side */
687 BTN_BASE2, /* Bottom side */
688 BTN_THUMB, /* Stick depress */
689};
690
691static int lg_g13_event(struct lg_g15_data *g15, u8 const *data)
692{
693 struct g13_input_report const * const rep = (struct g13_input_report *) data;
694 int i, val;
695 bool backlight_disabled;
696
697 /*
698 * Main macropad and menu keys.
699 * Emit key events defined for each bit position.
700 */
701 for (i = 0; i < ARRAY_SIZE(g13_keys_for_bits); ++i) {
702 if (g13_keys_for_bits[i]) {
703 val = TEST_BIT(rep->keybits, i);
704 input_report_key(dev: g15->input, code: g13_keys_for_bits[i], value: val);
705 }
706 }
707 input_sync(dev: g15->input);
708
709 /*
710 * Joystick.
711 * Emit button and deflection events.
712 */
713 for (i = 0; i < ARRAY_SIZE(g13_keys_for_bits_js); ++i) {
714 val = TEST_BIT(rep->keybits, i + G13_JS_KEYBITS_OFFSET);
715 input_report_key(dev: g15->input_js, code: g13_keys_for_bits_js[i], value: val);
716 }
717 input_report_abs(dev: g15->input_js, ABS_X, value: rep->joy_x);
718 input_report_abs(dev: g15->input_js, ABS_Y, value: rep->joy_y);
719 input_sync(dev: g15->input_js);
720
721 /*
722 * Bit 23 of keybits[] reports the current backlight on/off state. If
723 * it has changed from the last cached value, apply an update.
724 */
725 backlight_disabled = !TEST_BIT(rep->keybits, LG_G13_BACKLIGHT_HW_ON_BIT);
726 if (backlight_disabled ^ g15->backlight_disabled) {
727 led_classdev_notify_brightness_hw_changed(
728 led_cdev: &g15->leds[LG_G15_KBD_BRIGHTNESS].mcdev.led_cdev,
729 brightness: backlight_disabled
730 ? 0 : g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
731 g15->backlight_disabled = backlight_disabled;
732 }
733
734 return 0;
735}
736
737/* On the G15 Mark I Logitech has been quite creative with which bit is what */
738static void lg_g15_handle_lcd_menu_keys(struct lg_g15_data *g15, u8 *data)
739{
740 int i, val;
741
742 /* Most left (round/display) button below the LCD */
743 input_report_key(dev: g15->input, KEY_KBD_LCD_MENU1, value: data[8] & 0x80);
744 /* 4 other buttons below the LCD */
745 for (i = 0; i < 4; i++) {
746 val = data[i + 2] & 0x80;
747 input_report_key(dev: g15->input, KEY_KBD_LCD_MENU2 + i, value: val);
748 }
749}
750
751static int lg_g15_event(struct lg_g15_data *g15, u8 *data)
752{
753 int i, val;
754
755 /* G1 - G6 */
756 for (i = 0; i < 6; i++) {
757 val = data[i + 1] & (1 << i);
758 input_report_key(dev: g15->input, KEY_MACRO1 + i, value: val);
759 }
760 /* G7 - G12 */
761 for (i = 0; i < 6; i++) {
762 val = data[i + 2] & (1 << i);
763 input_report_key(dev: g15->input, KEY_MACRO7 + i, value: val);
764 }
765 /* G13 - G17 */
766 for (i = 0; i < 5; i++) {
767 val = data[i + 1] & (4 << i);
768 input_report_key(dev: g15->input, KEY_MACRO13 + i, value: val);
769 }
770 /* G18 */
771 input_report_key(dev: g15->input, KEY_MACRO18, value: data[8] & 0x40);
772
773 /* M1 - M3 */
774 for (i = 0; i < 3; i++) {
775 val = data[i + 6] & (1 << i);
776 input_report_key(dev: g15->input, KEY_MACRO_PRESET1 + i, value: val);
777 }
778 /* MR */
779 input_report_key(dev: g15->input, KEY_MACRO_RECORD_START, value: data[7] & 0x40);
780
781 lg_g15_handle_lcd_menu_keys(g15, data);
782
783 /* Backlight cycle button pressed? */
784 if (data[1] & 0x80)
785 schedule_work(work: &g15->work);
786
787 input_sync(dev: g15->input);
788 return 0;
789}
790
791static int lg_g15_v2_event(struct lg_g15_data *g15, u8 *data)
792{
793 int i, val;
794
795 /* G1 - G6 */
796 for (i = 0; i < 6; i++) {
797 val = data[1] & (1 << i);
798 input_report_key(dev: g15->input, KEY_MACRO1 + i, value: val);
799 }
800
801 /* M1 - M3 + MR */
802 input_report_key(dev: g15->input, KEY_MACRO_PRESET1, value: data[1] & 0x40);
803 input_report_key(dev: g15->input, KEY_MACRO_PRESET2, value: data[1] & 0x80);
804 input_report_key(dev: g15->input, KEY_MACRO_PRESET3, value: data[2] & 0x20);
805 input_report_key(dev: g15->input, KEY_MACRO_RECORD_START, value: data[2] & 0x40);
806
807 /* Round button to the left of the LCD */
808 input_report_key(dev: g15->input, KEY_KBD_LCD_MENU1, value: data[2] & 0x80);
809 /* 4 buttons below the LCD */
810 for (i = 0; i < 4; i++) {
811 val = data[2] & (2 << i);
812 input_report_key(dev: g15->input, KEY_KBD_LCD_MENU2 + i, value: val);
813 }
814
815 /* Backlight cycle button pressed? */
816 if (data[2] & 0x01)
817 schedule_work(work: &g15->work);
818
819 input_sync(dev: g15->input);
820 return 0;
821}
822
823static int lg_g510_event(struct lg_g15_data *g15, u8 *data)
824{
825 bool game_mode_enabled;
826 int i, val;
827
828 /* G1 - G18 */
829 for (i = 0; i < 18; i++) {
830 val = data[i / 8 + 1] & (1 << (i % 8));
831 input_report_key(dev: g15->input, KEY_MACRO1 + i, value: val);
832 }
833
834 /* Game mode on/off slider */
835 game_mode_enabled = data[3] & 0x04;
836 if (game_mode_enabled != g15->game_mode_enabled) {
837 if (game_mode_enabled)
838 hid_info(g15->hdev, "Game Mode enabled, Windows (super) key is disabled\n");
839 else
840 hid_info(g15->hdev, "Game Mode disabled\n");
841 g15->game_mode_enabled = game_mode_enabled;
842 }
843
844 /* M1 - M3 */
845 for (i = 0; i < 3; i++) {
846 val = data[3] & (0x10 << i);
847 input_report_key(dev: g15->input, KEY_MACRO_PRESET1 + i, value: val);
848 }
849 /* MR */
850 input_report_key(dev: g15->input, KEY_MACRO_RECORD_START, value: data[3] & 0x80);
851
852 /* LCD menu keys */
853 for (i = 0; i < 5; i++) {
854 val = data[4] & (1 << i);
855 input_report_key(dev: g15->input, KEY_KBD_LCD_MENU1 + i, value: val);
856 }
857
858 /* Headphone Mute */
859 input_report_key(dev: g15->input, KEY_MUTE, value: data[4] & 0x20);
860 /* Microphone Mute */
861 input_report_key(dev: g15->input, KEY_F20, value: data[4] & 0x40);
862
863 input_sync(dev: g15->input);
864 return 0;
865}
866
867static int lg_g510_leds_event(struct lg_g15_data *g15, u8 *data)
868{
869 struct lg_g15_led *g15_led = &g15->leds[LG_G15_KBD_BRIGHTNESS];
870 bool backlight_disabled;
871
872 backlight_disabled = data[1] & 0x04;
873 if (backlight_disabled == g15->backlight_disabled)
874 return 0;
875
876 led_classdev_notify_brightness_hw_changed(
877 led_cdev: &g15_led->mcdev.led_cdev,
878 brightness: backlight_disabled ? 0 : g15_led->brightness);
879
880 g15->backlight_disabled = backlight_disabled;
881
882 /*
883 * The G510 ignores backlight updates when the backlight is turned off
884 * through the light toggle button on the keyboard, to work around this
885 * we queue a workitem to sync values when the backlight is turned on.
886 */
887 if (!backlight_disabled)
888 schedule_work(work: &g15->work);
889
890 return 0;
891}
892
893static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
894 u8 *data, int size)
895{
896 struct lg_g15_data *g15 = hid_get_drvdata(hdev);
897
898 if (!g15)
899 return 0;
900
901 switch (g15->model) {
902 case LG_G13:
903 if (data[0] == 0x01 && size == sizeof(struct g13_input_report))
904 return lg_g13_event(g15, data);
905 break;
906 case LG_G15:
907 if (data[0] == 0x02 && size == 9)
908 return lg_g15_event(g15, data);
909 break;
910 case LG_G15_V2:
911 if (data[0] == 0x02 && size == 5)
912 return lg_g15_v2_event(g15, data);
913 break;
914 case LG_Z10:
915 if (data[0] == 0x02 && size == 9) {
916 lg_g15_handle_lcd_menu_keys(g15, data);
917 input_sync(dev: g15->input);
918 }
919 break;
920 case LG_G510:
921 case LG_G510_USB_AUDIO:
922 if (data[0] == LG_G510_INPUT_MACRO_KEYS && size == 5)
923 return lg_g510_event(g15, data);
924 if (data[0] == LG_G510_INPUT_KBD_BACKLIGHT && size == 2)
925 return lg_g510_leds_event(g15, data);
926 break;
927 }
928
929 return 0;
930}
931
932static int lg_g15_input_open(struct input_dev *dev)
933{
934 struct hid_device *hdev = input_get_drvdata(dev);
935
936 return hid_hw_open(hdev);
937}
938
939static void lg_g15_input_close(struct input_dev *dev)
940{
941 struct hid_device *hdev = input_get_drvdata(dev);
942
943 hid_hw_close(hdev);
944}
945
946static void lg_g15_setup_led_rgb(struct lg_g15_data *g15, int index)
947{
948 int i;
949 struct mc_subled *subled_info;
950 struct lg_g15_led * const gled = &g15->leds[index];
951
952 if (g15->model == LG_G13) {
953 gled->mcdev.led_cdev.brightness_set_blocking =
954 lg_g13_kbd_led_set;
955 gled->mcdev.led_cdev.brightness_get =
956 lg_g13_kbd_led_get;
957 gled->mcdev.led_cdev.flags = LED_BRIGHT_HW_CHANGED;
958 } else {
959 gled->mcdev.led_cdev.brightness_set_blocking =
960 lg_g510_kbd_led_set;
961 gled->mcdev.led_cdev.brightness_get =
962 lg_g510_kbd_led_get;
963 if (index == LG_G15_KBD_BRIGHTNESS)
964 g15->leds[index].mcdev.led_cdev.flags = LED_BRIGHT_HW_CHANGED;
965 }
966 gled->mcdev.led_cdev.max_brightness = 255;
967 gled->mcdev.num_colors = 3;
968
969 subled_info = devm_kcalloc(dev: &g15->hdev->dev, n: 3, size: sizeof(*subled_info), GFP_KERNEL);
970 if (!subled_info)
971 return;
972
973 for (i = 0; i < 3; i++) {
974 switch (i + 1) {
975 case LED_COLOR_ID_RED:
976 subled_info[i].color_index = LED_COLOR_ID_RED;
977 subled_info[i].intensity = gled->red;
978 break;
979 case LED_COLOR_ID_GREEN:
980 subled_info[i].color_index = LED_COLOR_ID_GREEN;
981 subled_info[i].intensity = gled->green;
982 break;
983 case LED_COLOR_ID_BLUE:
984 subled_info[i].color_index = LED_COLOR_ID_BLUE;
985 subled_info[i].intensity = gled->blue;
986 break;
987 }
988 subled_info[i].channel = i;
989 }
990 gled->mcdev.subled_info = subled_info;
991}
992
993static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
994{
995 int ret;
996
997 g15->leds[i].led = i;
998 g15->leds[i].cdev.name = name;
999
1000 switch (g15->model) {
1001 case LG_G13:
1002 if (i < LG_G15_BRIGHTNESS_MAX) {
1003 /* RGB backlight. */
1004 lg_g15_setup_led_rgb(g15, index: i);
1005 ret = devm_led_classdev_multicolor_register_ext(parent: &g15->hdev->dev,
1006 mcled_cdev: &g15->leds[i].mcdev,
1007 NULL);
1008 } else {
1009 /* Macro keys */
1010 g15->leds[i].cdev.brightness_set_blocking = lg_g13_mkey_led_set;
1011 g15->leds[i].cdev.brightness_get = lg_g13_mkey_led_get;
1012 g15->leds[i].cdev.max_brightness = 1;
1013
1014 ret = devm_led_classdev_register(parent: &g15->hdev->dev,
1015 led_cdev: &g15->leds[i].cdev);
1016 }
1017 break;
1018 case LG_G15:
1019 case LG_G15_V2:
1020 g15->leds[i].cdev.brightness_get = lg_g15_led_get;
1021 fallthrough;
1022 case LG_Z10:
1023 g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set;
1024 if (i < LG_G15_BRIGHTNESS_MAX) {
1025 g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED;
1026 g15->leds[i].cdev.max_brightness = 2;
1027 } else {
1028 g15->leds[i].cdev.max_brightness = 1;
1029 }
1030 ret = devm_led_classdev_register(parent: &g15->hdev->dev, led_cdev: &g15->leds[i].cdev);
1031 break;
1032 case LG_G510:
1033 case LG_G510_USB_AUDIO:
1034 switch (i) {
1035 case LG_G15_LCD_BRIGHTNESS:
1036 /*
1037 * The G510 does not have a separate LCD brightness,
1038 * but it does have a separate power-on (reset) value.
1039 */
1040 g15->leds[i].cdev.name = "g15::power_on_backlight_val";
1041 fallthrough;
1042 case LG_G15_KBD_BRIGHTNESS:
1043 /* register multicolor LED */
1044 lg_g15_setup_led_rgb(g15, index: i);
1045 ret = devm_led_classdev_multicolor_register_ext(parent: &g15->hdev->dev,
1046 mcled_cdev: &g15->leds[i].mcdev,
1047 NULL);
1048 break;
1049 default:
1050 g15->leds[i].cdev.brightness_set_blocking =
1051 lg_g510_mkey_led_set;
1052 g15->leds[i].cdev.brightness_get =
1053 lg_g510_mkey_led_get;
1054 g15->leds[i].cdev.max_brightness = 1;
1055 ret = devm_led_classdev_register(parent: &g15->hdev->dev, led_cdev: &g15->leds[i].cdev);
1056 }
1057 break;
1058 }
1059
1060 return ret;
1061}
1062
1063/* Common input device init code shared between keyboards and Z-10 speaker handling */
1064static void lg_g15_init_input_dev_core(struct hid_device *hdev, struct input_dev *input,
1065 char const *name)
1066{
1067 input->name = name;
1068 input->phys = hdev->phys;
1069 input->uniq = hdev->uniq;
1070 input->id.bustype = hdev->bus;
1071 input->id.vendor = hdev->vendor;
1072 input->id.product = hdev->product;
1073 input->id.version = hdev->version;
1074 input->dev.parent = &hdev->dev;
1075 input->open = lg_g15_input_open;
1076 input->close = lg_g15_input_close;
1077}
1078
1079static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
1080 const char *name)
1081{
1082 int i;
1083
1084 lg_g15_init_input_dev_core(hdev, input, name);
1085
1086 /* Keys below the LCD, intended for controlling a menu on the LCD */
1087 for (i = 0; i < 5; i++)
1088 input_set_capability(dev: input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
1089}
1090
1091static void lg_g13_init_input_dev(struct hid_device *hdev,
1092 struct input_dev *input, const char *name,
1093 struct input_dev *input_js, const char *name_js)
1094{
1095 /* Macropad. */
1096 lg_g15_init_input_dev_core(hdev, input, name);
1097 for (int i = 0; i < ARRAY_SIZE(g13_keys_for_bits); ++i) {
1098 if (g13_keys_for_bits[i])
1099 input_set_capability(dev: input, EV_KEY, code: g13_keys_for_bits[i]);
1100 }
1101
1102 /* OBTW, we're a joystick, too... */
1103 lg_g15_init_input_dev_core(hdev, input: input_js, name: name_js);
1104 for (int i = 0; i < ARRAY_SIZE(g13_keys_for_bits_js); ++i)
1105 input_set_capability(dev: input_js, EV_KEY, code: g13_keys_for_bits_js[i]);
1106
1107 input_set_capability(dev: input_js, EV_ABS, ABS_X);
1108 input_set_abs_params(dev: input_js, ABS_X, min: 0, max: 255, fuzz: 0, flat: 0);
1109 input_set_capability(dev: input_js, EV_ABS, ABS_Y);
1110 input_set_abs_params(dev: input_js, ABS_Y, min: 0, max: 255, fuzz: 0, flat: 0);
1111}
1112
1113static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
1114{
1115 static const char * const led_names[] = {
1116 "g15::kbd_backlight",
1117 "g15::lcd_backlight",
1118 "g15::macro_preset1",
1119 "g15::macro_preset2",
1120 "g15::macro_preset3",
1121 "g15::macro_record",
1122 };
1123 u8 gkeys_settings_output_report = 0;
1124 u8 gkeys_settings_feature_report = 0;
1125 struct hid_report_enum *rep_enum;
1126 unsigned int connect_mask = 0;
1127 bool has_ff000000 = false;
1128 struct lg_g15_data *g15;
1129 struct input_dev *input, *input_js;
1130 struct hid_report *rep;
1131 int ret, i, gkeys = 0;
1132
1133 hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
1134
1135 ret = hid_parse(hdev);
1136 if (ret)
1137 return ret;
1138
1139 /*
1140 * Some models have multiple interfaces, we want the interface with
1141 * the f000.0000 application input report.
1142 */
1143 rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
1144 list_for_each_entry(rep, &rep_enum->report_list, list) {
1145 if (rep->application == 0xff000000)
1146 has_ff000000 = true;
1147 }
1148 if (!has_ff000000)
1149 return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
1150
1151 g15 = devm_kzalloc(dev: &hdev->dev, size: sizeof(*g15), GFP_KERNEL);
1152 if (!g15)
1153 return -ENOMEM;
1154
1155 mutex_init(&g15->mutex);
1156
1157 input = devm_input_allocate_device(&hdev->dev);
1158 if (!input)
1159 return -ENOMEM;
1160
1161 g15->hdev = hdev;
1162 g15->model = id->driver_data;
1163 g15->input = input;
1164 input_set_drvdata(dev: input, data: hdev);
1165 hid_set_drvdata(hdev, data: (void *)g15);
1166
1167 switch (g15->model) {
1168 case LG_G13:
1169 /*
1170 * The G13 has an analog thumbstick with nearby buttons. Some
1171 * libraries and applications are known to ignore devices that
1172 * don't "look like" a joystick, and a device with two ABS axes
1173 * and 25+ macro keys would confuse them.
1174 *
1175 * Create an additional input device dedicated to appear as a
1176 * simplified joystick (two ABS axes, three BTN buttons).
1177 */
1178 input_js = devm_input_allocate_device(&hdev->dev);
1179 if (!input_js)
1180 return -ENOMEM;
1181 g15->input_js = input_js;
1182 input_set_drvdata(dev: input_js, data: hdev);
1183
1184 connect_mask = HID_CONNECT_HIDRAW;
1185 gkeys = 25;
1186 break;
1187 case LG_G15:
1188 INIT_WORK(&g15->work, lg_g15_leds_changed_work);
1189 /*
1190 * The G15 and G15 v2 use a separate usb-device (on a builtin
1191 * hub) which emulates a keyboard for the F1 - F12 emulation
1192 * on the G-keys, which we disable, rendering the emulated kbd
1193 * non-functional, so we do not let hid-input connect.
1194 */
1195 connect_mask = HID_CONNECT_HIDRAW;
1196 gkeys_settings_output_report = 0x02;
1197 gkeys = 18;
1198 break;
1199 case LG_G15_V2:
1200 INIT_WORK(&g15->work, lg_g15_leds_changed_work);
1201 connect_mask = HID_CONNECT_HIDRAW;
1202 gkeys_settings_output_report = 0x02;
1203 gkeys = 6;
1204 break;
1205 case LG_G510:
1206 case LG_G510_USB_AUDIO:
1207 INIT_WORK(&g15->work, lg_g510_leds_sync_work);
1208 connect_mask = HID_CONNECT_HIDINPUT | HID_CONNECT_HIDRAW;
1209 gkeys_settings_feature_report = 0x01;
1210 gkeys = 18;
1211 break;
1212 case LG_Z10:
1213 connect_mask = HID_CONNECT_HIDRAW;
1214 break;
1215 }
1216
1217 ret = hid_hw_start(hdev, connect_mask);
1218 if (ret)
1219 return ret;
1220
1221 /* Tell the keyboard to stop sending F1-F12 + 1-6 for G1 - G18 */
1222 if (gkeys_settings_output_report) {
1223 g15->transfer_buf[0] = gkeys_settings_output_report;
1224 memset(g15->transfer_buf + 1, 0, gkeys);
1225 /*
1226 * The kbd ignores our output report if we do not queue
1227 * an URB on the USB input endpoint first...
1228 */
1229 ret = hid_hw_open(hdev);
1230 if (ret)
1231 goto error_hw_stop;
1232 ret = hid_hw_output_report(hdev, buf: g15->transfer_buf, len: gkeys + 1);
1233 hid_hw_close(hdev);
1234 }
1235
1236 if (gkeys_settings_feature_report) {
1237 g15->transfer_buf[0] = gkeys_settings_feature_report;
1238 memset(g15->transfer_buf + 1, 0, gkeys);
1239 ret = hid_hw_raw_request(hdev: g15->hdev,
1240 reportnum: gkeys_settings_feature_report,
1241 buf: g15->transfer_buf, len: gkeys + 1,
1242 rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT);
1243 }
1244
1245 if (ret < 0) {
1246 hid_err(hdev, "Error %d disabling keyboard emulation for the G-keys, falling back to generic hid-input driver\n",
1247 ret);
1248 hid_set_drvdata(hdev, NULL);
1249 return 0;
1250 }
1251
1252 /* Get initial brightness levels */
1253 ret = lg_g15_get_initial_led_brightness(g15);
1254 if (ret)
1255 goto error_hw_stop;
1256
1257 if (g15->model == LG_Z10) {
1258 lg_g15_init_input_dev(hdev, input: g15->input, name: "Logitech Z-10 LCD Menu Keys");
1259 ret = input_register_device(g15->input);
1260 if (ret)
1261 goto error_hw_stop;
1262
1263 ret = lg_g15_register_led(g15, i: 1, name: "z-10::lcd_backlight");
1264 if (ret)
1265 goto error_hw_stop;
1266
1267 return 0; /* All done */
1268 } else if (g15->model == LG_G13) {
1269 static char const * const g13_led_names[] = {
1270 /* Backlight is shared between LCD and keys. */
1271 "g13:rgb:kbd_backlight",
1272 NULL, /* Keep in sync with led_type enum */
1273 "g13:red:macro_preset_1",
1274 "g13:red:macro_preset_2",
1275 "g13:red:macro_preset_3",
1276 "g13:red:macro_record",
1277 };
1278 lg_g13_init_input_dev(hdev,
1279 input, name: "Logitech G13 Gaming Keypad",
1280 input_js, name_js: "Logitech G13 Thumbstick");
1281 ret = input_register_device(input);
1282 if (ret)
1283 goto error_hw_stop;
1284 ret = input_register_device(input_js);
1285 if (ret)
1286 goto error_hw_stop;
1287
1288 for (i = 0; i < ARRAY_SIZE(g13_led_names); ++i) {
1289 if (g13_led_names[i]) {
1290 ret = lg_g15_register_led(g15, i, name: g13_led_names[i]);
1291 if (ret)
1292 goto error_hw_stop;
1293 }
1294 }
1295 led_classdev_notify_brightness_hw_changed(
1296 led_cdev: &g15->leds[LG_G15_KBD_BRIGHTNESS].mcdev.led_cdev,
1297 brightness: g15->backlight_disabled
1298 ? 0 : g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
1299 return 0;
1300 }
1301
1302 /* Setup and register input device */
1303 lg_g15_init_input_dev(hdev, input, name: "Logitech Gaming Keyboard Gaming Keys");
1304
1305 /* G-keys */
1306 for (i = 0; i < gkeys; i++)
1307 input_set_capability(dev: input, EV_KEY, KEY_MACRO1 + i);
1308
1309 /* M1 - M3 and MR keys */
1310 for (i = 0; i < 3; i++)
1311 input_set_capability(dev: input, EV_KEY, KEY_MACRO_PRESET1 + i);
1312 input_set_capability(dev: input, EV_KEY, KEY_MACRO_RECORD_START);
1313
1314 /*
1315 * On the G510 only report headphone and mic mute keys when *not* using
1316 * the builtin USB audio device. When the builtin audio is used these
1317 * keys directly toggle mute (and the LEDs) on/off.
1318 */
1319 if (g15->model == LG_G510) {
1320 input_set_capability(dev: input, EV_KEY, KEY_MUTE);
1321 /* Userspace expects F20 for micmute */
1322 input_set_capability(dev: input, EV_KEY, KEY_F20);
1323 }
1324
1325 ret = input_register_device(input);
1326 if (ret)
1327 goto error_hw_stop;
1328
1329 /* Register LED devices */
1330 for (i = 0; i < LG_G15_LED_MAX; i++) {
1331 ret = lg_g15_register_led(g15, i, name: led_names[i]);
1332 if (ret)
1333 goto error_hw_stop;
1334 }
1335
1336 return 0;
1337
1338error_hw_stop:
1339 hid_hw_stop(hdev);
1340 return ret;
1341}
1342
1343static const struct hid_device_id lg_g15_devices[] = {
1344 /*
1345 * The G13 is a macropad-only device with an LCD, LED backlighing,
1346 * and joystick.
1347 */
1348 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1349 USB_DEVICE_ID_LOGITECH_G13),
1350 .driver_data = LG_G13 },
1351 /* The G11 is a G15 without the LCD, treat it as a G15 */
1352 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1353 USB_DEVICE_ID_LOGITECH_G11),
1354 .driver_data = LG_G15 },
1355 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1356 USB_DEVICE_ID_LOGITECH_G15_LCD),
1357 .driver_data = LG_G15 },
1358 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1359 USB_DEVICE_ID_LOGITECH_G15_V2_LCD),
1360 .driver_data = LG_G15_V2 },
1361 /* G510 without a headset plugged in */
1362 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1363 USB_DEVICE_ID_LOGITECH_G510),
1364 .driver_data = LG_G510 },
1365 /* G510 with headset plugged in / with extra USB audio interface */
1366 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1367 USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO),
1368 .driver_data = LG_G510_USB_AUDIO },
1369 /* Z-10 speakers */
1370 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
1371 USB_DEVICE_ID_LOGITECH_Z_10_SPK),
1372 .driver_data = LG_Z10 },
1373 { }
1374};
1375MODULE_DEVICE_TABLE(hid, lg_g15_devices);
1376
1377static struct hid_driver lg_g15_driver = {
1378 .name = "lg-g15",
1379 .id_table = lg_g15_devices,
1380 .raw_event = lg_g15_raw_event,
1381 .probe = lg_g15_probe,
1382};
1383module_hid_driver(lg_g15_driver);
1384
1385MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
1386MODULE_DESCRIPTION("HID driver for gaming keys on Logitech gaming keyboards");
1387MODULE_LICENSE("GPL");
1388

source code of linux/drivers/hid/hid-lg-g15.c