diff --git a/src/hidpp20.c b/src/hidpp20.c index 1cbbaf8b..cd4c1735 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -1289,6 +1289,7 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device, profiles->num_rom_profiles = info->profile_count_oob; profiles->num_buttons = msg.msg.parameters[5] <= 16 ? msg.msg.parameters[5] : 16; profiles->num_modes = HIDPP20_DPI_COUNT; + profiles->num_leds = HIDPP20_LED_COUNT; profiles->has_g_shift = (info->mechanical_layout & 0x03) == 2; profiles->has_dpi_shift = ((info->mechanical_layout & 0x0c) >> 2) == 2; switch(info->various_info & 0x07) { @@ -1776,6 +1777,30 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile, } } +static void +hidpp20_onboard_profile_read_led(struct hidpp20_led *led, + struct hidpp20_internal_led internal_led) +{ + uint16_t rate = 0; + uint8_t brightness = 0; + + switch (internal_led.mode) { + case HIDPP20_LED_CYCLE: + rate = internal_led.effect.cycle.rate; + brightness = internal_led.effect.cycle.brightness; + break; + case HIDPP20_LED_BREATHING: + rate = internal_led.effect.breath.rate; + brightness = internal_led.effect.breath.brightness; + break; + } + + led->mode = (enum hidpp20_led_mode)internal_led.mode; + led->color = internal_led.color; + led->rate = rate; + led->brightness = brightness; +} + int hidpp20_onboard_profiles_read(struct hidpp20_device *device, unsigned int index, struct hidpp20_profiles *profiles_list) @@ -1804,6 +1829,9 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, profile->dpi[i] = hidpp_get_unaligned_le_u16(&data[2 * i + 3]); } + for (i = 0; i < profiles_list->num_leds; i++) + hidpp20_onboard_profile_read_led(&profile->leds[i], pdata.profile.leds[i]); + hidpp20_buttons_to_cpu(device, profile, pdata.profile.buttons, profiles_list->num_buttons); memcpy(profile->name, pdata.profile.name.txt, sizeof(profile->name)); @@ -1821,6 +1849,33 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, return 0; } +static void +hidpp20_onboard_write_profile_led(struct hidpp20_internal_led *internal_led, + struct hidpp20_led *led) +{ + uint16_t rate = led->rate; + uint8_t brightness = led->brightness; + + internal_led->mode = (uint8_t)led->mode; + internal_led->color.red = led->color.red; + internal_led->color.blue = led->color.blue; + internal_led->color.green = led->color.green; + + switch (led->mode) { + case HIDPP20_LED_CYCLE: + internal_led->effect.cycle.rate = rate; + internal_led->effect.cycle.brightness = brightness; + break; + case HIDPP20_LED_BREATHING: + internal_led->effect.breath.rate = rate; + internal_led->effect.breath.brightness = brightness; + break; + case HIDPP20_LED_ON: + case HIDPP20_LED_OFF: + break; + } +} + int hidpp20_onboard_profiles_write(struct hidpp20_device *device, unsigned int index, struct hidpp20_profiles *profiles_list) @@ -1853,6 +1908,9 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device, pdata.profile.dpi[i] = hidpp_cpu_to_le_u16(profile->dpi[i]); } + for (i = 0; i < profiles_list->num_leds; i++) + hidpp20_onboard_write_profile_led(&pdata.profile.leds[i], &profile->leds[i]); + hidpp20_buttons_from_cpu(profile, pdata.profile.buttons, profiles_list->num_buttons); memcpy(pdata.profile.name.txt, profile->name, sizeof(profile->name)); diff --git a/src/hidpp20.h b/src/hidpp20.h index e54ba234..b4f9addb 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -117,6 +117,13 @@ enum hidpp20_battery_status { BATTERY_STATUS_INVALID, }; +enum hidpp20_led_mode { + HIDPP20_LED_OFF = 0x00, + HIDPP20_LED_ON = 0x01, + HIDPP20_LED_CYCLE = 0x03, + HIDPP20_LED_BREATHING = 0x0a, +}; + /** * Retrieves the battery level status. * @@ -276,6 +283,7 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device, #define HIDPP20_MODIFIER_KEY_SHIFT 0x02 #define HIDPP20_DPI_COUNT 5 +#define HIDPP20_LED_COUNT 2 union hidpp20_button_binding { struct { @@ -324,6 +332,12 @@ struct hidpp20_color { } __attribute__((packed)); _Static_assert(sizeof(struct hidpp20_color) == 3, "Invalid size"); +enum hidpp20_led_type { + HIDPP20_LED_UNKNOWN = -1, + HIDPP20_LED_LOGO = 0, + HIDPP20_LED_SIDE, +}; + struct hidpp20_internal_led { uint8_t mode; /* 00 - off; 01 - on; 03 - cycle; 0a - breath */ struct hidpp20_color color; @@ -347,6 +361,15 @@ _Static_assert(sizeof(struct hidpp20_led_cycle) == 7, "Invalid size"); _Static_assert(sizeof(struct hidpp20_led_breath) == 7, "Invalid size"); _Static_assert(sizeof(struct hidpp20_internal_led) == 11, "Invalid size"); +typedef uint8_t percent_t; + +struct hidpp20_led { + enum hidpp20_led_mode mode; + struct hidpp20_color color; + uint16_t rate; + percent_t brightness; +}; + #define HIDPP20_MACRO_NOOP 0x01 #define HIDPP20_MACRO_DELAY 0x40 #define HIDPP20_MACRO_KEY_PRESS 0x43 @@ -388,6 +411,7 @@ struct hidpp20_profile { uint16_t dpi[HIDPP20_DPI_COUNT]; union hidpp20_button_binding buttons[32]; union hidpp20_macro_data *macros[32]; + struct hidpp20_led leds[32]; }; struct hidpp20_profiles { @@ -395,6 +419,7 @@ struct hidpp20_profiles { uint8_t num_rom_profiles; uint8_t num_buttons; uint8_t num_modes; + uint8_t num_leds; uint8_t has_g_shift; uint8_t has_dpi_shift; uint8_t corded;