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:
Peter Hutterer
2017-10-09 08:39:26 +10:00
parent c8929b50fa
commit 1c85d77d56
7 changed files with 89 additions and 6 deletions

View File

@@ -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'])

View File

@@ -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.

View File

@@ -4,3 +4,4 @@ Name=Logitech Gaming Mouse G303
DeviceMatch=usb:046d:c080
Svg=logitech-g303.svg
Driver=hidpp20
LedTypes=logo;side;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */
/**

View File

@@ -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);