1
0
forked from drath/libratbag

steelseries: implement cycle struct

This commit is contained in:
FFY00
2018-08-07 22:36:34 +01:00
committed by Thomas H. P. Andersen
parent 66fc7b545e
commit 363eab80f0

View File

@@ -76,6 +76,21 @@ struct steelseries_data {
int firmware_minor;
};
struct steelseries_point {
struct list link;
struct ratbag_color color; /* point color */
uint8_t pos; /* relative position in the cycle */
};
struct steelseries_led_cycle {
uint8_t led_id; /* led id */
uint16_t duration; /* cycle duration */
bool repeat; /* if the cycle restarts automatically */
uint8_t trigger_buttons; /* trigger button combination */
struct list points; /* colors in the cycle */
};
static int
steelseries_test_hidraw(struct ratbag_device *device)
{
@@ -571,103 +586,134 @@ steelseries_write_led_v1(struct ratbag_led *led)
return 0;
}
static void
create_cycle(struct steelseries_led_cycle *cycle)
{
cycle->led_id = 0x00;
cycle->duration = 5000;
cycle->repeat = true;
cycle->trigger_buttons = 0x00;
list_init(&cycle->points);
}
static void
construct_cycle_buffer(struct steelseries_led_cycle *cycle, uint8_t *buf, uint8_t buf_size)
{
struct steelseries_point *point;
uint16_t duration;
uint8_t npoints = 0;
uint16_t cycle_size = 0;
buf[0] = STEELSERIES_ID_LED;
buf[2] = cycle->led_id;
if (!cycle->repeat)
buf[19] = 0x01;
buf[23] = cycle->trigger_buttons;
list_for_each(point, &cycle->points, link) {
if(npoints == 0){
/* this is not a mistake,
we need to write the first
point to 28,29,30 */
buf[28] = point->color.red;
buf[29] = point->color.green;
buf[30] = point->color.blue;
}
cycle_size += point->pos;
assert(cycle_size < 256);
assert(34 + npoints*4 <= buf_size);
buf[31 + npoints*4] = point->color.red;
buf[32 + npoints*4] = point->color.green;
buf[33 + npoints*4] = point->color.blue;
buf[34 + npoints*4] = point->pos;
npoints++;
}
buf[27] = npoints;
/* this seems to be the minimum allowed */
duration = max(buf[27] * 330, cycle->duration);
hidpp_set_unaligned_le_u16(&buf[3], duration);
}
static int
steelseries_write_led_v2(struct ratbag_led *led)
{
struct ratbag_device *device = led->profile->device;
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
uint16_t duration, min_duration;
int ret;
buf[0] = STEELSERIES_ID_LED;
buf[2] = led->index;
struct steelseries_led_cycle cycle;
struct steelseries_point point[4];
/* not sure if these two are needed */
buf[15] = 0x01;
buf[17] = 0x01;
const struct ratbag_color black = { 0x00 };
const struct ratbag_color red = { 0xFF, 0x00, 0x00 };
const struct ratbag_color green = { 0x00, 0xFF, 0x00 };
const struct ratbag_color blue = { 0x00, 0x00, 0xFF };
create_cycle(&cycle);
cycle.led_id = led->index;
switch(led->mode) {
case RATBAG_LED_OFF:
buf[19] = 0x01;
buf[27] = 0x01;
buf[28] = buf[31] = 0x00;
buf[29] = buf[32] = 0x00;
buf[30] = buf[33] = 0x00;
/* not sure why the duration is set for the steady color or why
it is different for the two LEDs */
duration = led->index == 0 ? 10000 : 5000; /* 0x1027 or 0x8813 */
point[0].color = black;
point[0].pos = 0x00;
list_append(&cycle.points, &point[0].link);
break;
case RATBAG_LED_ON:
buf[19] = 0x01;
buf[27] = 0x01;
buf[28] = buf[31] = led->color.red;
buf[29] = buf[32] = led->color.green;
buf[30] = buf[33] = led->color.blue;
point[0].color = led->color;
/* not sure why the duration is set for the steady color or why
it is different for the two LEDs */
duration = led->index == 0 ? 10000 : 5000; /* 0x1027 or 0x8813 */
list_append(&cycle.points, &point[0].link);
break;
case RATBAG_LED_CYCLE:
buf[27] = 0x04; /* number of steps in cycle */
case RATBAG_LED_CYCLE:
point[0].color = red;
point[0].pos = 0x00;
/* start color */
buf[28] = buf[31] = 0xFF;
buf[29] = buf[32] = 0x00;
buf[30] = buf[33] = 0x00;
point[1].color = green;
point[1].pos = 0x55;
/* Cycle to green */
buf[35] = 0x00;
buf[36] = 0xFF;
buf[37] = 0x00;
buf[38] = 0x54; /* normalized time share of animation */
point[2].color = blue;
point[2].pos = 0x55;
/* Cycle to blue */
buf[39] = 0x00;
buf[40] = 0x00;
buf[41] = 0xFF;
buf[42] = 0x54; /* normalized time share of animation */
point[3].color = red;
point[3].pos = 0x55;
/* Cycle to red */
buf[43] = 0xFF;
buf[44] = 0x00;
buf[45] = 0x00;
buf[46] = 0x56; /* normalized time share of animation */
list_append(&cycle.points, &point[0].link);
list_append(&cycle.points, &point[1].link);
list_append(&cycle.points, &point[2].link);
list_append(&cycle.points, &point[3].link);
duration = led->ms;
cycle.duration = led->ms;
break;
case RATBAG_LED_BREATHING:
buf[27] = 0x03; /* number of steps in cycle */
point[0].color = black;
point[0].pos = 0x00;
/* start color */
buf[28] = buf[31] = led->color.red;
buf[29] = buf[32] = led->color.green;
buf[30] = buf[33] = led->color.blue;
point[1].color = led->color;
point[1].pos = 0x7F;
/* Cycle to black */
buf[35] = 0x00;
buf[36] = 0x00;
buf[37] = 0x00;
buf[38] = 0x7F; /* normalized time share of animation */
point[2].color = black;
point[2].pos = 0x7F;
list_append(&cycle.points, &point[0].link);
list_append(&cycle.points, &point[1].link);
list_append(&cycle.points, &point[2].link);
/* Cycle to selected color */
buf[39] = led->color.red;
buf[40] = led->color.green;
buf[41] = led->color.blue;
buf[42] = 0x7F; /* normalized time share of animation */
duration = led->ms;
cycle.duration = led->ms;
break;
default:
return -EINVAL;
}
/* this seems to be the minimum allowed */
min_duration = buf[27] * 330;
if (duration < min_duration)
duration = min_duration;
hidpp_set_unaligned_le_u16(&buf[3], duration);
construct_cycle_buffer(&cycle, buf, sizeof(buf));
msleep(10);
ret = ratbag_hidraw_output_report(device, buf, sizeof(buf));