Lines Matching +full:kbd +full:- +full:led +full:- +full:backlight
1 // SPDX-License-Identifier: GPL-2.0+
16 #include "hid-ids.h"
47 enum lg_g15_led_type led; member
54 /* Protects the transfer_buf and led brightness */
64 /******** G15 and G15 v2 LED functions ********/
70 ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT, in lg_g15_update_led_brightness()
71 g15->transfer_buf, 4, in lg_g15_update_led_brightness()
74 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret); in lg_g15_update_led_brightness()
75 return (ret < 0) ? ret : -EIO; in lg_g15_update_led_brightness()
78 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = g15->transfer_buf[1]; in lg_g15_update_led_brightness()
79 g15->leds[LG_G15_LCD_BRIGHTNESS].brightness = g15->transfer_buf[2]; in lg_g15_update_led_brightness()
81 g15->leds[LG_G15_MACRO_PRESET1].brightness = in lg_g15_update_led_brightness()
82 !(g15->transfer_buf[3] & 0x01); in lg_g15_update_led_brightness()
83 g15->leds[LG_G15_MACRO_PRESET2].brightness = in lg_g15_update_led_brightness()
84 !(g15->transfer_buf[3] & 0x02); in lg_g15_update_led_brightness()
85 g15->leds[LG_G15_MACRO_PRESET3].brightness = in lg_g15_update_led_brightness()
86 !(g15->transfer_buf[3] & 0x04); in lg_g15_update_led_brightness()
87 g15->leds[LG_G15_MACRO_RECORD].brightness = in lg_g15_update_led_brightness()
88 !(g15->transfer_buf[3] & 0x08); in lg_g15_update_led_brightness()
97 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g15_led_get()
100 mutex_lock(&g15->mutex); in lg_g15_led_get()
102 brightness = g15->leds[g15_led->led].brightness; in lg_g15_led_get()
103 mutex_unlock(&g15->mutex); in lg_g15_led_get()
113 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g15_led_set()
117 /* Ignore LED off on unregister / keyboard unplug */ in lg_g15_led_set()
118 if (led_cdev->flags & LED_UNREGISTERING) in lg_g15_led_set()
121 mutex_lock(&g15->mutex); in lg_g15_led_set()
123 g15->transfer_buf[0] = LG_G15_FEATURE_REPORT; in lg_g15_led_set()
124 g15->transfer_buf[3] = 0; in lg_g15_led_set()
126 if (g15_led->led < LG_G15_BRIGHTNESS_MAX) { in lg_g15_led_set()
127 g15->transfer_buf[1] = g15_led->led + 1; in lg_g15_led_set()
128 g15->transfer_buf[2] = brightness << (g15_led->led * 4); in lg_g15_led_set()
131 if (i == g15_led->led) in lg_g15_led_set()
134 val = g15->leds[i].brightness; in lg_g15_led_set()
137 mask |= 1 << (i - LG_G15_MACRO_PRESET1); in lg_g15_led_set()
140 g15->transfer_buf[1] = 0x04; in lg_g15_led_set()
141 g15->transfer_buf[2] = ~mask; in lg_g15_led_set()
144 ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT, in lg_g15_led_set()
145 g15->transfer_buf, 4, in lg_g15_led_set()
149 g15_led->brightness = brightness; in lg_g15_led_set()
152 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret); in lg_g15_led_set()
153 ret = (ret < 0) ? ret : -EIO; in lg_g15_led_set()
156 mutex_unlock(&g15->mutex); in lg_g15_led_set()
168 mutex_lock(&g15->mutex); in lg_g15_leds_changed_work()
170 old_brightness[i] = g15->leds[i].brightness; in lg_g15_leds_changed_work()
175 brightness[i] = g15->leds[i].brightness; in lg_g15_leds_changed_work()
176 mutex_unlock(&g15->mutex); in lg_g15_leds_changed_work()
185 led_classdev_notify_brightness_hw_changed(&g15->leds[i].cdev, in lg_g15_leds_changed_work()
190 /******** G510 LED functions ********/
196 ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_BACKLIGHT_RGB + i, in lg_g510_get_initial_led_brightness()
197 g15->transfer_buf, 4, in lg_g510_get_initial_led_brightness()
200 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret); in lg_g510_get_initial_led_brightness()
201 return (ret < 0) ? ret : -EIO; in lg_g510_get_initial_led_brightness()
204 high = max3(g15->transfer_buf[1], g15->transfer_buf[2], in lg_g510_get_initial_led_brightness()
205 g15->transfer_buf[3]); in lg_g510_get_initial_led_brightness()
208 g15->leds[i].red = in lg_g510_get_initial_led_brightness()
209 DIV_ROUND_CLOSEST(g15->transfer_buf[1] * 255, high); in lg_g510_get_initial_led_brightness()
210 g15->leds[i].green = in lg_g510_get_initial_led_brightness()
211 DIV_ROUND_CLOSEST(g15->transfer_buf[2] * 255, high); in lg_g510_get_initial_led_brightness()
212 g15->leds[i].blue = in lg_g510_get_initial_led_brightness()
213 DIV_ROUND_CLOSEST(g15->transfer_buf[3] * 255, high); in lg_g510_get_initial_led_brightness()
214 g15->leds[i].brightness = high; in lg_g510_get_initial_led_brightness()
216 g15->leds[i].red = 255; in lg_g510_get_initial_led_brightness()
217 g15->leds[i].green = 255; in lg_g510_get_initial_led_brightness()
218 g15->leds[i].blue = 255; in lg_g510_get_initial_led_brightness()
219 g15->leds[i].brightness = 0; in lg_g510_get_initial_led_brightness()
225 /* Must be called with g15->mutex locked */
232 g15->transfer_buf[0] = 5 + g15_led->led; in lg_g510_kbd_led_write()
233 g15->transfer_buf[1] = in lg_g510_kbd_led_write()
234 DIV_ROUND_CLOSEST(g15_led->red * brightness, 255); in lg_g510_kbd_led_write()
235 g15->transfer_buf[2] = in lg_g510_kbd_led_write()
236 DIV_ROUND_CLOSEST(g15_led->green * brightness, 255); in lg_g510_kbd_led_write()
237 g15->transfer_buf[3] = in lg_g510_kbd_led_write()
238 DIV_ROUND_CLOSEST(g15_led->blue * brightness, 255); in lg_g510_kbd_led_write()
240 ret = hid_hw_raw_request(g15->hdev, in lg_g510_kbd_led_write()
241 LG_G510_FEATURE_BACKLIGHT_RGB + g15_led->led, in lg_g510_kbd_led_write()
242 g15->transfer_buf, 4, in lg_g510_kbd_led_write()
246 g15_led->brightness = brightness; in lg_g510_kbd_led_write()
249 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret); in lg_g510_kbd_led_write()
250 ret = (ret < 0) ? ret : -EIO; in lg_g510_kbd_led_write()
261 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g510_kbd_led_set()
264 /* Ignore LED off on unregister / keyboard unplug */ in lg_g510_kbd_led_set()
265 if (led_cdev->flags & LED_UNREGISTERING) in lg_g510_kbd_led_set()
268 mutex_lock(&g15->mutex); in lg_g510_kbd_led_set()
270 mutex_unlock(&g15->mutex); in lg_g510_kbd_led_set()
280 return g15_led->brightness; in lg_g510_kbd_led_get()
289 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in color_store()
294 return -EINVAL; in color_store()
297 return -EINVAL; in color_store()
303 mutex_lock(&g15->mutex); in color_store()
304 g15_led->red = (value & 0xff0000) >> 16; in color_store()
305 g15_led->green = (value & 0x00ff00) >> 8; in color_store()
306 g15_led->blue = (value & 0x0000ff); in color_store()
307 ret = lg_g510_kbd_led_write(g15, g15_led, g15_led->brightness); in color_store()
308 mutex_unlock(&g15->mutex); in color_store()
319 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in color_show()
322 mutex_lock(&g15->mutex); in color_show()
324 g15_led->red, g15_led->green, g15_led->blue); in color_show()
325 mutex_unlock(&g15->mutex); in color_show()
350 mutex_lock(&g15->mutex); in lg_g510_leds_sync_work()
351 lg_g510_kbd_led_write(g15, &g15->leds[LG_G15_KBD_BRIGHTNESS], in lg_g510_leds_sync_work()
352 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness); in lg_g510_leds_sync_work()
353 mutex_unlock(&g15->mutex); in lg_g510_leds_sync_work()
360 ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS, in lg_g510_update_mkey_led_brightness()
361 g15->transfer_buf, 2, in lg_g510_update_mkey_led_brightness()
364 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret); in lg_g510_update_mkey_led_brightness()
365 ret = (ret < 0) ? ret : -EIO; in lg_g510_update_mkey_led_brightness()
368 g15->leds[LG_G15_MACRO_PRESET1].brightness = in lg_g510_update_mkey_led_brightness()
369 !!(g15->transfer_buf[1] & 0x80); in lg_g510_update_mkey_led_brightness()
370 g15->leds[LG_G15_MACRO_PRESET2].brightness = in lg_g510_update_mkey_led_brightness()
371 !!(g15->transfer_buf[1] & 0x40); in lg_g510_update_mkey_led_brightness()
372 g15->leds[LG_G15_MACRO_PRESET3].brightness = in lg_g510_update_mkey_led_brightness()
373 !!(g15->transfer_buf[1] & 0x20); in lg_g510_update_mkey_led_brightness()
374 g15->leds[LG_G15_MACRO_RECORD].brightness = in lg_g510_update_mkey_led_brightness()
375 !!(g15->transfer_buf[1] & 0x10); in lg_g510_update_mkey_led_brightness()
384 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g510_mkey_led_get()
387 mutex_lock(&g15->mutex); in lg_g510_mkey_led_get()
389 brightness = g15->leds[g15_led->led].brightness; in lg_g510_mkey_led_get()
390 mutex_unlock(&g15->mutex); in lg_g510_mkey_led_get()
400 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g510_mkey_led_set()
404 /* Ignore LED off on unregister / keyboard unplug */ in lg_g510_mkey_led_set()
405 if (led_cdev->flags & LED_UNREGISTERING) in lg_g510_mkey_led_set()
408 mutex_lock(&g15->mutex); in lg_g510_mkey_led_set()
411 if (i == g15_led->led) in lg_g510_mkey_led_set()
414 val = g15->leds[i].brightness; in lg_g510_mkey_led_set()
417 mask |= 0x80 >> (i - LG_G15_MACRO_PRESET1); in lg_g510_mkey_led_set()
420 g15->transfer_buf[0] = LG_G510_FEATURE_M_KEYS_LEDS; in lg_g510_mkey_led_set()
421 g15->transfer_buf[1] = mask; in lg_g510_mkey_led_set()
423 ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS, in lg_g510_mkey_led_set()
424 g15->transfer_buf, 2, in lg_g510_mkey_led_set()
428 g15_led->brightness = brightness; in lg_g510_mkey_led_set()
431 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret); in lg_g510_mkey_led_set()
432 ret = (ret < 0) ? ret : -EIO; in lg_g510_mkey_led_set()
435 mutex_unlock(&g15->mutex); in lg_g510_mkey_led_set()
440 /******** Generic LED functions ********/
445 switch (g15->model) { in lg_g15_get_initial_led_brightness()
461 return -EINVAL; /* Never reached */ in lg_g15_get_initial_led_brightness()
471 /* G1 - G6 */ in lg_g15_event()
474 input_report_key(g15->input, KEY_MACRO1 + i, val); in lg_g15_event()
476 /* G7 - G12 */ in lg_g15_event()
479 input_report_key(g15->input, KEY_MACRO7 + i, val); in lg_g15_event()
481 /* G13 - G17 */ in lg_g15_event()
484 input_report_key(g15->input, KEY_MACRO13 + i, val); in lg_g15_event()
487 input_report_key(g15->input, KEY_MACRO18, data[8] & 0x40); in lg_g15_event()
489 /* M1 - M3 */ in lg_g15_event()
492 input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val); in lg_g15_event()
495 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40); in lg_g15_event()
498 input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80); in lg_g15_event()
502 input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val); in lg_g15_event()
505 /* Backlight cycle button pressed? */ in lg_g15_event()
507 schedule_work(&g15->work); in lg_g15_event()
509 input_sync(g15->input); in lg_g15_event()
517 /* G1 - G6 */ in lg_g15_v2_event()
520 input_report_key(g15->input, KEY_MACRO1 + i, val); in lg_g15_v2_event()
523 /* M1 - M3 + MR */ in lg_g15_v2_event()
524 input_report_key(g15->input, KEY_MACRO_PRESET1, data[1] & 0x40); in lg_g15_v2_event()
525 input_report_key(g15->input, KEY_MACRO_PRESET2, data[1] & 0x80); in lg_g15_v2_event()
526 input_report_key(g15->input, KEY_MACRO_PRESET3, data[2] & 0x20); in lg_g15_v2_event()
527 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[2] & 0x40); in lg_g15_v2_event()
530 input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[2] & 0x80); in lg_g15_v2_event()
534 input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val); in lg_g15_v2_event()
537 /* Backlight cycle button pressed? */ in lg_g15_v2_event()
539 schedule_work(&g15->work); in lg_g15_v2_event()
541 input_sync(g15->input); in lg_g15_v2_event()
550 /* G1 - G18 */ in lg_g510_event()
553 input_report_key(g15->input, KEY_MACRO1 + i, val); in lg_g510_event()
558 if (game_mode_enabled != g15->game_mode_enabled) { in lg_g510_event()
560 hid_info(g15->hdev, "Game Mode enabled, Windows (super) key is disabled\n"); in lg_g510_event()
562 hid_info(g15->hdev, "Game Mode disabled\n"); in lg_g510_event()
563 g15->game_mode_enabled = game_mode_enabled; in lg_g510_event()
566 /* M1 - M3 */ in lg_g510_event()
569 input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val); in lg_g510_event()
572 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[3] & 0x80); in lg_g510_event()
577 input_report_key(g15->input, KEY_KBD_LCD_MENU1 + i, val); in lg_g510_event()
581 input_report_key(g15->input, KEY_MUTE, data[4] & 0x20); in lg_g510_event()
583 input_report_key(g15->input, KEY_F20, data[4] & 0x40); in lg_g510_event()
585 input_sync(g15->input); in lg_g510_event()
594 * The G510 ignores backlight updates when the backlight is turned off in lg_g510_leds_event()
596 * we queue a workitem to sync values when the backlight is turned on. in lg_g510_leds_event()
600 schedule_work(&g15->work); in lg_g510_leds_event()
613 switch (g15->model) { in lg_g15_raw_event()
659 g15->leds[i].led = i; in lg_g15_register_led()
660 g15->leds[i].cdev.name = led_names[i]; in lg_g15_register_led()
662 switch (g15->model) { in lg_g15_register_led()
665 g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set; in lg_g15_register_led()
666 g15->leds[i].cdev.brightness_get = lg_g15_led_get; in lg_g15_register_led()
668 g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED; in lg_g15_register_led()
669 g15->leds[i].cdev.max_brightness = 2; in lg_g15_register_led()
671 g15->leds[i].cdev.max_brightness = 1; in lg_g15_register_led()
680 * but it does have a separate power-on (reset) value. in lg_g15_register_led()
682 g15->leds[i].cdev.name = "g15::power_on_backlight_val"; in lg_g15_register_led()
685 g15->leds[i].cdev.brightness_set_blocking = in lg_g15_register_led()
687 g15->leds[i].cdev.brightness_get = in lg_g15_register_led()
689 g15->leds[i].cdev.max_brightness = 255; in lg_g15_register_led()
690 g15->leds[i].cdev.groups = lg_g510_kbd_led_groups; in lg_g15_register_led()
693 g15->leds[i].cdev.brightness_set_blocking = in lg_g15_register_led()
695 g15->leds[i].cdev.brightness_get = in lg_g15_register_led()
697 g15->leds[i].cdev.max_brightness = 1; in lg_g15_register_led()
702 return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev); in lg_g15_register_led()
717 hdev->quirks |= HID_QUIRK_INPUT_PER_APP; in lg_g15_probe()
727 rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; in lg_g15_probe()
728 list_for_each_entry(rep, &rep_enum->report_list, list) { in lg_g15_probe()
729 if (rep->application == 0xff000000) in lg_g15_probe()
735 g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL); in lg_g15_probe()
737 return -ENOMEM; in lg_g15_probe()
739 mutex_init(&g15->mutex); in lg_g15_probe()
741 input = devm_input_allocate_device(&hdev->dev); in lg_g15_probe()
743 return -ENOMEM; in lg_g15_probe()
745 g15->hdev = hdev; in lg_g15_probe()
746 g15->model = id->driver_data; in lg_g15_probe()
749 switch (g15->model) { in lg_g15_probe()
751 INIT_WORK(&g15->work, lg_g15_leds_changed_work); in lg_g15_probe()
753 * The G15 and G15 v2 use a separate usb-device (on a builtin in lg_g15_probe()
754 * hub) which emulates a keyboard for the F1 - F12 emulation in lg_g15_probe()
755 * on the G-keys, which we disable, rendering the emulated kbd in lg_g15_probe()
756 * non-functional, so we do not let hid-input connect. in lg_g15_probe()
763 INIT_WORK(&g15->work, lg_g15_leds_changed_work); in lg_g15_probe()
770 INIT_WORK(&g15->work, lg_g510_leds_sync_work); in lg_g15_probe()
781 /* Tell the keyboard to stop sending F1-F12 + 1-6 for G1 - G18 */ in lg_g15_probe()
783 g15->transfer_buf[0] = gkeys_settings_output_report; in lg_g15_probe()
784 memset(g15->transfer_buf + 1, 0, gkeys); in lg_g15_probe()
786 * The kbd ignores our output report if we do not queue in lg_g15_probe()
792 ret = hid_hw_output_report(hdev, g15->transfer_buf, gkeys + 1); in lg_g15_probe()
797 g15->transfer_buf[0] = gkeys_settings_feature_report; in lg_g15_probe()
798 memset(g15->transfer_buf + 1, 0, gkeys); in lg_g15_probe()
799 ret = hid_hw_raw_request(g15->hdev, in lg_g15_probe()
801 g15->transfer_buf, gkeys + 1, in lg_g15_probe()
806 …hid_err(hdev, "Error %d disabling keyboard emulation for the G-keys, falling back to generic hid-i… in lg_g15_probe()
818 input->name = "Logitech Gaming Keyboard Gaming Keys"; in lg_g15_probe()
819 input->phys = hdev->phys; in lg_g15_probe()
820 input->uniq = hdev->uniq; in lg_g15_probe()
821 input->id.bustype = hdev->bus; in lg_g15_probe()
822 input->id.vendor = hdev->vendor; in lg_g15_probe()
823 input->id.product = hdev->product; in lg_g15_probe()
824 input->id.version = hdev->version; in lg_g15_probe()
825 input->dev.parent = &hdev->dev; in lg_g15_probe()
826 input->open = lg_g15_input_open; in lg_g15_probe()
827 input->close = lg_g15_input_close; in lg_g15_probe()
829 /* G-keys */ in lg_g15_probe()
833 /* M1 - M3 and MR keys */ in lg_g15_probe()
847 if (g15->model == LG_G510) { in lg_g15_probe()
853 g15->input = input; in lg_g15_probe()
860 /* Register LED devices */ in lg_g15_probe()
898 .name = "lg-g15",