xref: /openbmc/linux/drivers/hid/hid-lg-g15.c (revision dfc53baa)
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 
26 enum lg_g15_model {
27 	LG_G15,
28 	LG_G15_V2,
29 	LG_G510,
30 	LG_G510_USB_AUDIO,
31 };
32 
33 enum 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 
44 struct 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 
51 struct 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 
66 static 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 
93 static 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 
108 static 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 
161 static 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 
192 static 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 */
226 static 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 
256 static 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 
275 static 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 
283 static 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 
313 static 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 
330 static DEVICE_ATTR_RW(color);
331 
332 static struct attribute *lg_g510_kbd_led_attrs[] = {
333 	&dev_attr_color.attr,
334 	NULL,
335 };
336 
337 static const struct attribute_group lg_g510_kbd_led_group = {
338 	.attrs = lg_g510_kbd_led_attrs,
339 };
340 
341 static const struct attribute_group *lg_g510_kbd_led_groups[] = {
342 	&lg_g510_kbd_led_group,
343 	NULL,
344 };
345 
346 static 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 
356 static 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 
380 static 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 
395 static 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 ********/
441 static 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 */
467 static 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 
513 static 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 
545 static 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 
589 static 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 
605 static 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 
634 static 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 
641 static 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 
648 static int lg_g15_register_led(struct lg_g15_data *g15, int i)
649 {
650 	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 
705 static 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 
869 error_hw_stop:
870 	hid_hw_stop(hdev);
871 	return ret;
872 }
873 
874 static 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 };
895 MODULE_DEVICE_TABLE(hid, lg_g15_devices);
896 
897 static 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 };
903 module_hid_driver(lg_g15_driver);
904 
905 MODULE_LICENSE("GPL");
906