forked from drath/libratbag
steelseries: implement cycle struct
This commit is contained in:
committed by
Thomas H. P. Andersen
parent
66fc7b545e
commit
363eab80f0
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user