driver-hidpp20: add feature discovery for 0x1300

fix #325

Signed-off-by: Ogier Bouvier <obouvier@logitech.com>
This commit is contained in:
Ogier Bouvier
2017-09-20 16:52:12 +02:00
committed by Peter Hutterer
parent a47492e62c
commit 835a694c4b
2 changed files with 171 additions and 16 deletions

View File

@@ -54,7 +54,7 @@
#define HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00 (1 << 4)
#define HIDPP_CAP_COLOR_LED_EFFECTS_8070 (1 << 5)
#define HIDPP_CAP_ONBOARD_PROFILES_8100 (1 << 6)
#define HIDPP_CAP_LED_SW_CONTROL (1 << 7)
#define HIDPP_CAP_LED_SW_CONTROL_1300 (1 << 7)
struct hidpp20drv_data {
struct hidpp20_device *dev;
@@ -247,17 +247,63 @@ hidpp20drv_read_button(struct ratbag_button *button)
}
static void
hidpp20drv_read_led(struct ratbag_led *led)
hidpp20drv_read_led_1300(struct ratbag_led *led, struct hidpp20drv_data* data)
{
struct ratbag_device *device = led->profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct hidpp20_profile *profile;
struct hidpp20_color_led_zone_info *led_info;
struct hidpp20_led *h_led;
struct hidpp20_led_sw_ctrl_led_state state;
struct hidpp20_led_sw_ctrl_led_info *info;
int rc;
if (!(drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070))
info = &data->led_infos.leds[led->index];
rc = hidpp20_led_sw_control_get_led_state(data->dev, led->index, &state);
if (rc != 0)
return;
led->colordepth = RATBAG_LED_COLORDEPTH_MONOCHROME;
switch (info->type)
{
case HIDPP20_LED_TYPE_LOGO:
led->type = RATBAG_LED_TYPE_LOGO;
break;
case HIDPP20_LED_TYPE_BATTERY:
led->type = RATBAG_LED_TYPE_BATTERY;
break;
case HIDPP20_LED_TYPE_DPI:
led->type = RATBAG_LED_TYPE_DPI;
break;
case HIDPP20_LED_TYPE_PROFILE:
case HIDPP20_LED_TYPE_COSMETIC:
led->type = RATBAG_LED_TYPE_SIDE;
break;
}
switch (state.mode)
{
case HIDPP20_LED_MODE_OFF:
led->mode = RATBAG_LED_OFF;
break;
case HIDPP20_LED_MODE_ON:
led->mode = RATBAG_LED_ON;
break;
case HIDPP20_LED_MODE_BREATHING:
led->mode = RATBAG_LED_BREATHING;
led->hz = state.breathing.period;
led->brightness = state.breathing.brightness;
break;
default:
led->mode = RATBAG_LED_ON;
}
}
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_color_led_zone_info* led_info;
led_info = &drv_data->led_infos.color_leds[led->index];
profile = &drv_data->profiles->profiles[led->profile->index];
h_led = &profile->leds[led->index];
@@ -285,6 +331,18 @@ hidpp20drv_read_led(struct ratbag_led *led)
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
}
static void
hidpp20drv_read_led(struct ratbag_led *led)
{
struct ratbag_device *device = led->profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070)
hidpp20drv_read_led_8070(led, drv_data);
else if (drv_data->capabilities & HIDPP_CAP_LED_SW_CONTROL_1300)
hidpp20drv_read_led_1300(led, drv_data);
}
static int
hidpp20drv_write_button_1b04(struct ratbag_button *button,
const struct ratbag_button_action *action)
@@ -389,17 +447,61 @@ hidpp20drv_update_button(struct ratbag_button *button,
}
static int
hidpp20drv_update_led(struct ratbag_led *led)
hidpp20drv_update_led_1300(struct ratbag_led *led, struct hidpp20drv_data *data)
{
const uint16_t led_caps = data->led_infos.leds[led->index].caps;
struct hidpp20_led_sw_ctrl_led_state h_led;
int rc;
h_led.index = led->index;
switch(led->mode)
{
case RATBAG_LED_BREATHING:
h_led.mode = HIDPP20_LED_MODE_BREATHING;
h_led.breathing.brightness = led->brightness;
h_led.breathing.period = led->hz;
h_led.breathing.timeout = 300;
break;
case RATBAG_LED_OFF:
h_led.mode = HIDPP20_LED_MODE_OFF;
h_led.on.index = HIDPP20_LED_SW_CONTROL_LED_INDEX_ALL;
break;
case RATBAG_LED_ON:
h_led.mode = HIDPP20_LED_MODE_ON;
h_led.on.index = HIDPP20_LED_SW_CONTROL_LED_INDEX_ALL;
break;
case RATBAG_LED_CYCLE:
return -ENOTSUP;
}
if (!(h_led.mode & led_caps)) {
hidpp_log_error(&data->dev->base, "LED %d does not support effect %s(%04x), supports %04x\n",
led->index, hidpp20_sw_led_control_get_mode_string(h_led.mode),
h_led.mode, led_caps);
return -ENOTSUP;
}
if (!hidpp20_led_sw_control_get_sw_ctrl(data->dev)) {
rc = hidpp20_led_sw_control_set_sw_ctrl(data->dev, true);
if (rc)
return rc;
}
rc = hidpp20_led_sw_control_set_led_state(data->dev, &h_led);
if (rc)
return rc;
return RATBAG_SUCCESS;
}
static int
hidpp20drv_update_led_8070(struct ratbag_led *led, struct ratbag_profile* profile,
struct hidpp20drv_data *drv_data)
{
struct ratbag_profile *profile = led->profile;
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct hidpp20_profile *h_profile;
struct hidpp20_led *h_led;
if (!(drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070))
return -ENOTSUP;
h_profile = &drv_data->profiles->profiles[profile->index];
h_led = &(h_profile->leds[led->index]);
@@ -430,6 +532,22 @@ hidpp20drv_update_led(struct ratbag_led *led)
return RATBAG_SUCCESS;
}
static int
hidpp20drv_update_led(struct ratbag_led *led)
{
struct ratbag_profile *profile = led->profile;
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070)
return hidpp20drv_update_led_8070(led, profile, drv_data);
if (drv_data->capabilities & HIDPP_CAP_LED_SW_CONTROL_1300)
return hidpp20drv_update_led_1300(led, drv_data);
return RATBAG_ERROR_CAPABILITY;
}
static int
hidpp20drv_current_profile(struct ratbag_device *device)
{
@@ -692,6 +810,27 @@ hidpp20drv_read_color_leds(struct ratbag_device *device)
return rc;
}
static int
hidpp20drv_read_leds(struct ratbag_device *device)
{
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
int rc;
if (!(drv_data->capabilities & HIDPP_CAP_LED_SW_CONTROL_1300))
return 0;
free(drv_data->led_infos.leds);
drv_data->led_infos.leds = NULL;
rc = hidpp20_led_sw_control_read_leds(drv_data->dev, &drv_data->led_infos.leds);
if (rc > 0) {
drv_data->num_leds = rc;
rc = 0;
}
return rc;
}
static void
hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
{
@@ -847,6 +986,20 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
device->num_leds = drv_data->num_leds;
break;
}
case HIDPP_PAGE_LED_SW_CONTROL: {
log_debug(ratbag, "device has non-rgb leds\n");
drv_data->capabilities |= HIDPP_CAP_LED_SW_CONTROL_1300;
if (drv_data->capabilities & HIDPP_PAGE_COLOR_LED_EFFECTS)
return 0;
if (hidpp20drv_read_leds(device))
return 0;
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_LED);
device->num_leds = drv_data->num_leds;
break;
}
case HIDPP_PAGE_ONBOARD_PROFILES: {
log_debug(ratbag, "device has onboard profiles\n");
drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100;

View File

@@ -1460,7 +1460,9 @@ enum ratbag_led_mode {
enum ratbag_led_type {
RATBAG_LED_TYPE_UNKNOWN = -1,
RATBAG_LED_TYPE_LOGO = 0,
RATBAG_LED_TYPE_SIDE
RATBAG_LED_TYPE_SIDE,
RATBAG_LED_TYPE_BATTERY,
RATBAG_LED_TYPE_DPI,
};
/**