forked from drath/libratbag
data: add LedTypes keyword argument to the device files
At least on HID++ 2.0, the LED types appear to be random and don't match the protocol specs. Other protocols don't even have those bits, so let's make this a generic entry. This is pre-filled for all LEDs but drivers can override it where required. Fixes #377 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
@@ -62,9 +62,20 @@ def check_match_str(string):
|
||||
assert(pid == '{:04x}'.format(int(pid, 16)))
|
||||
|
||||
|
||||
def check_ledtypes_str(string):
|
||||
permitted_types = ['logo', 'side', 'battery', 'dpi']
|
||||
|
||||
types = string.split(';')
|
||||
for t in types:
|
||||
if not t: # emtpy string if trailing ;
|
||||
continue
|
||||
|
||||
assert(t in permitted_types)
|
||||
|
||||
|
||||
def check_section_device(section):
|
||||
required_keys = ['Name', 'Driver', 'DeviceMatch']
|
||||
permitted_keys = required_keys + ['Svg']
|
||||
permitted_keys = required_keys + ['Svg', 'LedTypes']
|
||||
|
||||
for key in section.keys():
|
||||
assert(key in permitted_keys)
|
||||
@@ -77,6 +88,11 @@ def check_section_device(section):
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
check_ledtypes_str(section['LedTypes'])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
check_match_str(section['DeviceMatch'])
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ Svg=logitech-example.svg
|
||||
# The libratbag driver backend
|
||||
Driver=hidpp10
|
||||
|
||||
# The types of the LEDs, in the indexed order they appear in, separated by a
|
||||
# semicolon.
|
||||
# Allowed values: logo, side, battery, dpi
|
||||
LedTypes=logo;side
|
||||
|
||||
# Only one group of driver-specific properties is permitted and it must be
|
||||
# [Driver/<drivername>]. It is a bug do have any other [Driver/foo] group in
|
||||
# a device file, but this example file lists all.
|
||||
|
||||
@@ -4,3 +4,4 @@ Name=Logitech Gaming Mouse G303
|
||||
DeviceMatch=usb:046d:c080
|
||||
Svg=logitech-g303.svg
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side;
|
||||
|
||||
@@ -322,7 +322,10 @@ hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
||||
led->mode = RATBAG_LED_OFF;
|
||||
break;
|
||||
}
|
||||
led->type = hidpp20_8070_get_location_mapping(led_info->location);
|
||||
|
||||
/* pre-filled, only override if unknown */
|
||||
if (led->type == RATBAG_LED_TYPE_UNKNOWN)
|
||||
led->type = hidpp20_8070_get_location_mapping(led_info->location);
|
||||
led->color.red = h_led->color.red;
|
||||
led->color.green = h_led->color.green;
|
||||
led->color.blue = h_led->color.blue;
|
||||
|
||||
@@ -75,6 +75,9 @@ struct ratbag_device_data {
|
||||
struct data_hidpp20 hidpp20;
|
||||
struct data_hidpp10 hidpp10;
|
||||
};
|
||||
|
||||
enum ratbag_led_type led_types[20];
|
||||
size_t nled_types;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -178,6 +181,15 @@ ratbag_device_data_get_svg(const struct ratbag_device_data *data)
|
||||
return data->svg;
|
||||
}
|
||||
|
||||
enum ratbag_led_type
|
||||
ratbag_device_data_get_led_type(const struct ratbag_device_data *data,
|
||||
unsigned int index)
|
||||
{
|
||||
assert(index < ARRAY_LENGTH(data->led_types));
|
||||
|
||||
return data->led_types[index];
|
||||
}
|
||||
|
||||
struct ratbag_device_data *
|
||||
ratbag_device_data_ref(struct ratbag_device_data *data)
|
||||
{
|
||||
@@ -218,6 +230,40 @@ ratbag_device_data_unref(struct ratbag_device_data *data)
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbag_device_data *, ratbag_device_data_unref);
|
||||
|
||||
static int
|
||||
parse_ledtypes(char **strv, enum ratbag_led_type *types, size_t ntypes)
|
||||
{
|
||||
unsigned int i;
|
||||
int count = 0;
|
||||
|
||||
for (i = 0; i < ntypes; i++)
|
||||
types[i] = RATBAG_LED_TYPE_UNKNOWN;
|
||||
|
||||
if (!strv)
|
||||
return count;
|
||||
|
||||
i = 0;
|
||||
while(strv[i]) {
|
||||
const char *s = strv[i];
|
||||
|
||||
if (streq(s, "logo"))
|
||||
types[i] = RATBAG_LED_TYPE_LOGO;
|
||||
else if (streq(s, "side"))
|
||||
types[i] = RATBAG_LED_TYPE_SIDE;
|
||||
else if (streq(s, "dpi"))
|
||||
types[i] = RATBAG_LED_TYPE_SIDE;
|
||||
else if (streq(s, "battery"))
|
||||
types[i] = RATBAG_LED_TYPE_SIDE;
|
||||
else
|
||||
return -1;
|
||||
|
||||
count++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool
|
||||
match(const struct input_id *id, char **strv)
|
||||
{
|
||||
@@ -250,7 +296,8 @@ file_data_matches(struct ratbag *ratbag,
|
||||
{
|
||||
_cleanup_(g_key_file_freep) GKeyFile *keyfile = NULL;
|
||||
_cleanup_(g_error_freep) GError *error = NULL;
|
||||
_cleanup_(g_strfreevp) char **strv = NULL;
|
||||
_cleanup_(g_strfreevp) char **match_strv = NULL;
|
||||
_cleanup_(g_strfreevp) char **ledtypes_strv = NULL;
|
||||
_cleanup_(ratbag_device_data_unrefp) struct ratbag_device_data *data = NULL;
|
||||
int rc;
|
||||
|
||||
@@ -261,13 +308,13 @@ file_data_matches(struct ratbag *ratbag,
|
||||
return false;
|
||||
}
|
||||
|
||||
strv = g_key_file_get_string_list(keyfile, GROUP_DEVICE, "DeviceMatch", NULL, NULL);
|
||||
if (!strv) {
|
||||
match_strv = g_key_file_get_string_list(keyfile, GROUP_DEVICE, "DeviceMatch", NULL, NULL);
|
||||
if (!match_strv) {
|
||||
log_error(ratbag, "Missing DeviceMatch in %s\n", basename(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!match(id, strv))
|
||||
if (!match(id, match_strv))
|
||||
return false;
|
||||
|
||||
data = zalloc(sizeof(*data));
|
||||
@@ -303,6 +350,12 @@ file_data_matches(struct ratbag *ratbag,
|
||||
|
||||
data->svg = g_key_file_get_string(keyfile, GROUP_DEVICE, "Svg", NULL);
|
||||
|
||||
ledtypes_strv = g_key_file_get_string_list(keyfile, GROUP_DEVICE, "LedTypes", NULL, NULL);
|
||||
if (parse_ledtypes(ledtypes_strv, data->led_types, ARRAY_LENGTH(data->led_types)) < 0) {
|
||||
log_error(ratbag, "Invalid LedTypes string in '%s'\n", basename(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
*data_out = data;
|
||||
data = NULL;
|
||||
|
||||
|
||||
@@ -42,6 +42,9 @@ const char *
|
||||
ratbag_device_data_get_name(const struct ratbag_device_data *data);
|
||||
const char *
|
||||
ratbag_device_data_get_svg(const struct ratbag_device_data *data);
|
||||
enum ratbag_led_type
|
||||
ratbag_device_data_get_led_type(const struct ratbag_device_data *data,
|
||||
unsigned int index);
|
||||
|
||||
/* HID++ 1.0 */
|
||||
/**
|
||||
|
||||
@@ -623,6 +623,8 @@ ratbag_create_led(struct ratbag_profile *profile, unsigned int index)
|
||||
led->index = index;
|
||||
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
||||
led->type = RATBAG_LED_TYPE_UNKNOWN;
|
||||
if (device->data)
|
||||
led->type = ratbag_device_data_get_led_type(device->data, led->index);
|
||||
|
||||
list_insert(&profile->leds, &led->link);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user