diff --git a/data/devices/logitech-g502-x-plus.device b/data/devices/logitech-g502-x-plus.device new file mode 100644 index 00000000..4fb153b6 --- /dev/null +++ b/data/devices/logitech-g502-x-plus.device @@ -0,0 +1,8 @@ +[Device] +Name=Logitech G502 X PLUS +DeviceMatch=usb:046d:c095 +DeviceType=mouse +Driver=hidpp20 + +[Driver/hidpp20] +Quirk=G502X_PLUS diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index 7c4cfb00..4a9b4c67 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -411,7 +411,13 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat hidpp20_rgb_effects_get_device_info(drv_data->dev, &device_info); cluster_info = drv_data->led_infos.color_leds_8071[led->index]; profile = &drv_data->profiles->profiles[led->profile->index]; - h_led = &profile->leds[led->index]; + if (drv_data->dev->quirk == HIDPP20_QUIRK_G502X_PLUS) { + // On G502X+ the second slot controls the user configurable LED. + // (Note: There is only 1 reported LED, it just happens to use 2nd index though) + h_led = &profile->leds[1]; + } else { + h_led = &profile->leds[led->index]; + } switch (h_led->mode) { case HIDPP20_LED_ON: @@ -689,7 +695,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) { h_profile = &drv_data->profiles->profiles[profile->index]; - h_led = &(h_profile->leds[led->index]); + if (drv_data->dev->quirk == HIDPP20_QUIRK_G502X_PLUS) { + // On G502X+ the second slot controls the user configurable LED. + // (Note: There is only 1 reported LED, it just happens to use 2nd index though) + h_led = &(h_profile->leds[1]); + } else { + h_led = &(h_profile->leds[led->index]); + } } if (!h_led) diff --git a/src/hidpp20.c b/src/hidpp20.c index 83531c0f..221234be 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -110,6 +110,7 @@ hidpp20_get_quirk_string(enum hidpp20_quirk quirk) CASE_RETURN_STRING(HIDPP20_QUIRK_NONE); CASE_RETURN_STRING(HIDPP20_QUIRK_G305); CASE_RETURN_STRING(HIDPP20_QUIRK_G602); + CASE_RETURN_STRING(HIDPP20_QUIRK_G502X_PLUS); } abort(); @@ -1802,6 +1803,7 @@ int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device #define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303 0x02 #define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900 0x03 #define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915 0x04 +#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G502X 0x05 #define HIDPP20_ONBOARD_PROFILES_MACRO_TYPE_G402 0x01 #define HIDPP20_USER_PROFILES_G402 0x0000 @@ -1831,7 +1833,8 @@ union hidpp20_internal_profile { } name; struct hidpp20_internal_led leds[2]; /* G303, g502, g900 only */ struct hidpp20_internal_led alt_leds[2]; - uint8_t free[2]; + uint8_t custom_animation_index; // G502X Plus, G705 + uint8_t free; // unused uint16_t crc; } __attribute__((packed)) profile; }; @@ -2220,7 +2223,8 @@ hidpp20_onboard_profiles_validate(struct hidpp20_device *device, if ((info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402) && (info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303) && (info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900) && - (info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915)) { + (info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915) && + (info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G502X)) { hidpp_log_error(&device->base, "Profile layout not supported: 0x%02x.\n", info->profile_format_id); @@ -2959,6 +2963,18 @@ hidpp20_onboard_profiles_write_profile(struct hidpp20_device *device, memcpy(pdata->profile.name.txt, profile->name, sizeof(profile->name)); + // Mice like G502X can store custom animations onboard. + // ratbag does not support this, so we set it to disable it to ensure + // that the actual lighting matches the user's settings. + if (device->quirk == HIDPP20_QUIRK_G502X_PLUS) + { + // Note(sewer56): There are two known mice which use this field; + // G502X PLUS and G705. [And I only own one of these.] But it's not known how + // prevalent this is elsewhere, so in the interest of defensive programming; + // we're not setting this on unknown mice. + pdata->profile.custom_animation_index = 0x00; + } + rc = hidpp20_onboard_profiles_write_sector(device, sector, sector_size, data, true); if (rc < 0) { hidpp_log_error(&device->base, "failed to write profile\n"); diff --git a/src/hidpp20.h b/src/hidpp20.h index cddf3866..7e14f359 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -55,6 +55,7 @@ enum hidpp20_quirk { HIDPP20_QUIRK_NONE, HIDPP20_QUIRK_G305, HIDPP20_QUIRK_G602, + HIDPP20_QUIRK_G502X_PLUS, // G502X+ uses 2nd LED slot instead of 1st. }; struct hidpp20_device { diff --git a/src/libratbag-data.c b/src/libratbag-data.c index 0eb43c86..cd0f53ed 100644 --- a/src/libratbag-data.c +++ b/src/libratbag-data.c @@ -225,6 +225,8 @@ init_data_hidpp20(struct ratbag *ratbag, data->hidpp20.quirk = HIDPP20_QUIRK_G305; else if(streq(str, "G602")) data->hidpp20.quirk = HIDPP20_QUIRK_G602; + else if(streq(str, "G502X_PLUS")) + data->hidpp20.quirk = HIDPP20_QUIRK_G502X_PLUS; } }