From b76fcdadde0c3c03326349c40888ace1a7668243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Thu, 23 Jan 2020 20:37:56 +0000 Subject: [PATCH] hidpp20: enable 0x8070 (ColorLedEffects) standalone use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0x8071 is still missing but as of now we don't have any device that needs it. Signed-off-by: Filipe LaĆ­ns --- src/driver-hidpp20.c | 47 ++++++++++++++++----------- src/hidpp20.c | 76 ++++++++++++++++++++++++++++++++++++++++++-- src/hidpp20.h | 20 ++++++++++++ 3 files changed, 123 insertions(+), 20 deletions(-) diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index bf1f09be..369ead43 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -69,6 +69,7 @@ struct hidpp20drv_data { unsigned num_controls; struct hidpp20_control_id *controls; struct hidpp20_profiles *profiles; + struct hidpp20_led *leds; union hidpp20_generic_led_zone_info led_infos; unsigned int report_rates[4]; @@ -334,14 +335,20 @@ static void hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_data) { struct hidpp20_profile *profile; - struct hidpp20_led *h_led; + struct hidpp20_led h_led_val; + struct hidpp20_led *h_led = &h_led_val; struct hidpp20_color_led_zone_info* led_info; struct hidpp20_color_led_info info; int rc; led_info = &drv_data->led_infos.color_leds_8070[led->index]; - profile = &drv_data->profiles->profiles[led->profile->index]; - h_led = &profile->leds[led->index]; + + if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) { + profile = &drv_data->profiles->profiles[led->profile->index]; + h_led = &profile->leds[led->index]; + } else { + hidpp20_color_led_effects_get_zone_effect(drv_data->dev, led->index, h_led); + } switch (h_led->mode) { case HIDPP20_LED_ON: @@ -691,11 +698,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p struct hidpp20drv_data *drv_data) { struct hidpp20_profile *h_profile; - struct hidpp20_led *h_led; + struct hidpp20_led h_led_val; + struct hidpp20_led *h_led = &h_led_val; - h_profile = &drv_data->profiles->profiles[profile->index]; - - h_led = &(h_profile->leds[led->index]); + 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 (!h_led) return -EINVAL; @@ -720,6 +729,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p h_led->period = led->ms; h_led->brightness = led->brightness * 100 / 255; + if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) { + if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070) + hidpp20_color_led_effects_set_zone_effect(drv_data->dev, + led->index, + h_led_val); + } + return RATBAG_SUCCESS; } @@ -1237,17 +1253,11 @@ hidpp20drv_init_leds_8070_8071(struct ratbag_device *device) struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct ratbag *ratbag = device->ratbag; - /* we only support 0x8070/0x8071 via 0x8100 */ - if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) { - if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070) { - log_debug(ratbag, "disabling 0x8070 (Color Leds Effects) feature because the device doesn't have 0x8100 (Onboard Memory Profiles)\n"); - drv_data->capabilities &= ~HIDPP_CAP_COLOR_LED_EFFECTS_8070; - } - - if (drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) { - log_debug(ratbag, "disabling 0x8071 (RGB Effects) feature because the device doesn't have 0x8100 (Onboard Memory Profiles)\n"); - drv_data->capabilities &= ~HIDPP_CAP_RGB_EFFECTS_8071; - } + /* we only support 0x8071 via 0x8100 */ + if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) && + drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) { + log_debug(ratbag, "disabling 0x8071 (RGB Effects) feature because the device doesn't have 0x8100 (Onboard Memory Profiles)\n"); + drv_data->capabilities &= ~HIDPP_CAP_RGB_EFFECTS_8071; } if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070 || @@ -1612,6 +1622,7 @@ hidpp20drv_remove(struct ratbag_device *device) free(drv_data->led_infos.color_leds_8070); free(drv_data->controls); free(drv_data->sensors); + free(drv_data->leds); if (drv_data->dev) hidpp20_device_destroy(drv_data->dev); free(drv_data); diff --git a/src/hidpp20.c b/src/hidpp20.c index d4ea49a1..42f25e7a 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -868,6 +868,8 @@ err: #define CMD_COLOR_LED_EFFECTS_GET_INFO 0x00 #define CMD_COLOR_LED_EFFECTS_GET_ZONE_INFO 0x10 #define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT_INFO 0x20 +#define CMD_COLOR_LED_EFFECTS_SET_ZONE_EFFECT 0x30 +#define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT 0xe0 int hidpp20_color_led_effects_get_info(struct hidpp20_device *device, @@ -1012,6 +1014,76 @@ hidpp20_color_led_effect_get_zone_effect_info(struct hidpp20_device *device, return 0; } +int +hidpp20_color_led_effects_set_zone_effect(struct hidpp20_device *device, + uint8_t zone_index, + struct hidpp20_led led) +{ + uint8_t feature_index; + union hidpp20_message msg = { + .msg.report_id = REPORT_ID_SHORT, + .msg.address = CMD_COLOR_LED_EFFECTS_SET_ZONE_EFFECT, + .msg.device_idx = device->index, + .msg.parameters[0] = zone_index, + .msg.parameters[12] = 1, /* write to RAM and flash */ + }; + int rc; + struct hidpp20_internal_led *internal_led = (struct hidpp20_internal_led*) &msg.msg.parameters[1]; + + hidpp20_onboard_profiles_write_led(internal_led, &led); + + feature_index = hidpp_root_get_feature_idx(device, + HIDPP_PAGE_COLOR_LED_EFFECTS); + if (feature_index == 0) + return -ENOTSUP; + + msg.msg.sub_id = feature_index; + + rc = hidpp20_request_command(device, &msg); + if (rc) + return rc; + + return 0; +} + +int +hidpp20_color_led_effects_get_zone_effect(struct hidpp20_device *device, + uint8_t zone_index, + struct hidpp20_led *led) +{ + uint8_t feature_index; + union hidpp20_message msg = { + .msg.report_id = REPORT_ID_SHORT, + .msg.address = CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT, + .msg.device_idx = device->index, + .msg.parameters[0] = zone_index, + }; + struct hidpp20_internal_led *internal_led; + int rc; + + feature_index = hidpp_root_get_feature_idx(device, + HIDPP_PAGE_COLOR_LED_EFFECTS); + if (feature_index == 0) + return -ENOTSUP; + + msg.msg.sub_id = feature_index; + + rc = hidpp20_request_command(device, &msg); + if (rc) + return rc; + + if (msg.msg.parameters[0] != zone_index) + return -EPROTO; + + internal_led = (struct hidpp20_internal_led*) &msg.msg.parameters[1]; + + hidpp20_onboard_profiles_read_led(led, *internal_led); + + hidpp_log_debug(&device->base, "zone %u has effect %u\n", zone_index, led->mode); + + return 0; +} + /* -------------------------------------------------------------------------- */ /* 0x8071: RGB Effects */ /* -------------------------------------------------------------------------- */ @@ -2566,7 +2638,7 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile, } } -static void +void hidpp20_onboard_profiles_read_led(struct hidpp20_led *led, struct hidpp20_internal_led internal_led) { @@ -2769,7 +2841,7 @@ read_profiles: return profiles->num_profiles; } -static void +void hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led, struct hidpp20_led *led) { diff --git a/src/hidpp20.h b/src/hidpp20.h index 61a60f52..ffe37102 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -501,6 +501,18 @@ hidpp20_rgb_effects_get_effect_info(struct hidpp20_device *device, uint8_t effect_index, struct hidpp20_rgb_effect_info *info); +struct hidpp20_led; + +int +hidpp20_color_led_effects_set_zone_effect(struct hidpp20_device *device, + uint8_t zone_index, + struct hidpp20_led led); + +int +hidpp20_color_led_effects_get_zone_effect(struct hidpp20_device *device, + uint8_t zone_index, + struct hidpp20_led *led); + enum hidpp20_color_led_location { HIDPP20_COLOR_LED_LOCATION_UNDEFINED = 0, HIDPP20_COLOR_LED_LOCATION_PRIMARY, @@ -925,6 +937,14 @@ hidpp20_onboard_profiles_allocate_sector(struct hidpp20_profiles *profiles) return zalloc(profiles->sector_size); } +void +hidpp20_onboard_profiles_read_led(struct hidpp20_led *led, + struct hidpp20_internal_led internal_led); + +void +hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led, + struct hidpp20_led *led); + /* -------------------------------------------------------------------------- */ /* 0x8110 - Mouse Button Spy */ /* -------------------------------------------------------------------------- */