Fix leds getting unset when closing the program

This commit is contained in:
dec05eba
2025-11-08 13:24:40 +01:00
parent f017f04bdc
commit 2506750243
6 changed files with 105 additions and 18 deletions

View File

@@ -1,5 +1,6 @@
#include "keyboard_event.h"
#include "keys.h"
#include "leds.h"
/* C stdlib */
#include <stdio.h>
@@ -716,6 +717,41 @@ bool keyboard_event_init(keyboard_event *self, bool exclusive_grab, keyboard_gra
return true;
}
static void write_led_data_to_device(int fd, uint16_t led, int value) {
struct input_event led_data = {
.type = EV_LED,
.code = led,
.value = value
};
write(fd, &led_data, sizeof(led_data));
struct input_event syn_data = {
.type = EV_SYN,
.code = 0,
.value = 0
};
write(fd, &syn_data, sizeof(syn_data));
}
/* When the device is ungrabbed the leds are unset for some reason. Set them back to their previous brightness */
static void keyboard_event_device_deinit(int fd, event_extra_data *extra_data) {
ggh_leds leds;
const bool got_leds = get_leds(extra_data->dev_input_id, &leds);
ioctl(fd, EVIOCGRAB, 0);
if(got_leds) {
if(leds.scroll_lock_brightness >= 0)
write_led_data_to_device(fd, LED_SCROLLL, leds.scroll_lock_brightness);
if(leds.num_lock_brightness >= 0)
write_led_data_to_device(fd, LED_NUML, leds.num_lock_brightness);
if(leds.caps_lock_brightness >= 0)
write_led_data_to_device(fd, LED_CAPSL, leds.caps_lock_brightness);
}
close(fd);
}
void keyboard_event_deinit(keyboard_event *self) {
self->running = false;
@@ -732,8 +768,10 @@ void keyboard_event_deinit(keyboard_event *self) {
for(int i = 0; i < self->num_event_polls; ++i) {
if(self->event_polls[i].fd > 0) {
ioctl(self->event_polls[i].fd, EVIOCGRAB, 0);
close(self->event_polls[i].fd);
if(self->event_extra_data[i].dev_input_id > 0 && !self->event_extra_data[i].gsr_ui_virtual_keyboard)
keyboard_event_device_deinit(self->event_polls[i].fd, &self->event_extra_data[i]);
else
close(self->event_polls[i].fd);
}
free(self->event_extra_data[i].key_states);
free(self->event_extra_data[i].key_presses_grabbed);

View File

@@ -15,27 +15,37 @@
/* LINUX */
#include <linux/input.h>
static int get_max_brightness(const char *sys_class_path, const char *filename) {
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/%s/max_brightness", sys_class_path, filename);
const int fd = open(path, O_RDONLY);
/* Returns -1 on error */
static int read_int_from_file(const char *filepath) {
const int fd = open(filepath, O_RDONLY);
if(fd == -1) {
fprintf(stderr, "Warning: get_max_brightness open error: %s\n", strerror(errno));
return false;
return -1;
}
bool success = false;
int max_brightness = 0;
int value = 0;
char buffer[32];
const ssize_t num_bytes_read = read(fd, buffer, sizeof(buffer));
if(num_bytes_read > 0) {
buffer[num_bytes_read] = '\0';
success = sscanf(buffer, "%d", &max_brightness) == 1;
success = sscanf(buffer, "%d", &value) == 1;
}
close(fd);
return success;
return success ? value : -1;
}
static int get_max_brightness(const char *sys_class_path, const char *filename) {
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/%s/max_brightness", sys_class_path, filename);
return read_int_from_file(path);
}
static int get_brightness(const char *sys_class_path, const char *filename) {
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/%s/brightness", sys_class_path, filename);
return read_int_from_file(path);
}
static bool string_starts_with(const char *str, const char *sub) {
@@ -137,3 +147,35 @@ bool set_leds(const char *led_name, bool enabled) {
return false;
}
}
bool get_leds(int event_number, ggh_leds *leds) {
leds->scroll_lock_brightness = -1;
leds->num_lock_brightness = -1;
leds->caps_lock_brightness = -1;
char path[PATH_MAX];
snprintf(path, sizeof(path), "/sys/class/input/event%d/device", event_number);
DIR *dir = opendir(path);
if(!dir)
return false;
struct dirent *entry;
while((entry = readdir(dir)) != NULL) {
if(entry->d_name[0] == '.')
continue;
if(!string_starts_with(entry->d_name, "input"))
continue;
if(string_ends_with(entry->d_name, "::scrolllock"))
leds->scroll_lock_brightness = get_brightness(path, entry->d_name);
else if(string_ends_with(entry->d_name, "::numlock"))
leds->num_lock_brightness = get_brightness(path, entry->d_name);
else if(string_ends_with(entry->d_name, "::capslock"))
leds->caps_lock_brightness = get_brightness(path, entry->d_name);
}
closedir(dir);
return true;
}

View File

@@ -4,6 +4,14 @@
/* C stdlib */
#include <stdbool.h>
typedef struct {
/* These are set to -1 if not supported */
int scroll_lock_brightness;
int num_lock_brightness;
int caps_lock_brightness;
} ggh_leds;
bool set_leds(const char *led_name, bool enabled);
bool get_leds(int event_number, ggh_leds *leds);
#endif /* LEDS_H */