mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 23:23:52 +01:00
steelseries: read settings from device
Open an extra hidraw to read current onboard settings. Initially DPI and static LED color can be read from the rival 310. Other data/devices can be added as the protocol is better understood. The protocol used to extract the data seems to be both device and firmware version specific. To be able to switch on both cases we now store the firmware information in the drv_data. Signed-off-by: Thomas Hindoe Paaboel Andersen <phomes@gmail.com>
This commit is contained in:
committed by
Peter Hutterer
parent
a4e1e1690d
commit
fff3589a20
@@ -37,6 +37,8 @@
|
||||
|
||||
#define STEELSERIES_NUM_PROFILES 1
|
||||
#define STEELSERIES_NUM_DPI 2
|
||||
#define STEELSERIES_INPUT_ENDPOINT 0
|
||||
#define STEELSERIES_INPUT_HIDRAW 1
|
||||
|
||||
/* not sure these two are used for */
|
||||
#define STEELSERIES_REPORT_ID_1 0x01
|
||||
@@ -58,6 +60,8 @@
|
||||
#define STEELSERIES_ID_REPORT_RATE 0x54
|
||||
#define STEELSERIES_ID_LED 0x5b
|
||||
#define STEELSERIES_ID_SAVE 0x59
|
||||
#define STEELSERIES_ID_FIRMWARE 0x90
|
||||
#define STEELSERIES_ID_SETTTINGS 0x92
|
||||
|
||||
#define STEELSERIES_BUTTON_OFF 0x00
|
||||
#define STEELSERIES_BUTTON_RES_CYCLE 0x30
|
||||
@@ -67,6 +71,11 @@
|
||||
#define STEELSERIES_BUTTON_KBD 0x51
|
||||
#define STEELSERIES_BUTTON_CONSUMER 0x61
|
||||
|
||||
struct steelseries_data {
|
||||
int firmware_major;
|
||||
int firmware_minor;
|
||||
};
|
||||
|
||||
static int
|
||||
steelseries_test_hidraw(struct ratbag_device *device)
|
||||
{
|
||||
@@ -122,9 +131,83 @@ button_defaults_for_layout(struct ratbag_button *button, int button_count)
|
||||
ratbag_button_set_action(button, &button_actions[button->index]);
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_get_firmware_version(struct ratbag_device *device)
|
||||
{
|
||||
struct steelseries_data *drv_data = device->drv_data;
|
||||
int device_version = ratbag_device_data_steelseries_get_device_version(device->data);
|
||||
size_t buf_len = STEELSERIES_REPORT_SIZE;
|
||||
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
|
||||
int ret;
|
||||
|
||||
if (device_version == 1)
|
||||
return 0;
|
||||
|
||||
buf[0] = STEELSERIES_ID_FIRMWARE;
|
||||
msleep(10);
|
||||
ret = ratbag_hidraw_output_report(device, buf, buf_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ratbag_hidraw_read_input_report_index(device, buf, buf_len, STEELSERIES_INPUT_HIDRAW);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
drv_data->firmware_major = buf[1];
|
||||
drv_data->firmware_minor = buf[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_read_settings(struct ratbag_device *device)
|
||||
{
|
||||
int device_version = ratbag_device_data_steelseries_get_device_version(device->data);
|
||||
struct ratbag_profile *profile = NULL;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_led *led;
|
||||
|
||||
size_t buf_len = STEELSERIES_REPORT_SIZE;
|
||||
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
|
||||
int ret;
|
||||
unsigned int active_resolution;
|
||||
|
||||
if (device_version == 1)
|
||||
return 0;
|
||||
|
||||
buf[0] = STEELSERIES_ID_SETTTINGS;
|
||||
msleep(10);
|
||||
ret = ratbag_hidraw_output_report(device, buf, buf_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ratbag_hidraw_read_input_report_index(device, buf, buf_len, STEELSERIES_INPUT_HIDRAW);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
active_resolution = buf[1] - 1;
|
||||
ratbag_device_for_each_profile(device, profile) {
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
resolution->is_active = resolution->index == active_resolution;
|
||||
|
||||
resolution->dpi_x = 100 * (1 + buf[2 + resolution->index*2]);
|
||||
resolution->dpi_y = resolution->dpi_x;
|
||||
}
|
||||
|
||||
ratbag_profile_for_each_led(profile, led) {
|
||||
led->color.red = buf[6 + led->index * 3];
|
||||
led->color.green = buf[7 + led->index * 3];
|
||||
led->color.blue = buf[8 + led->index * 3];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_probe(struct ratbag_device *device)
|
||||
{
|
||||
struct steelseries_data *drv_data = NULL;
|
||||
struct ratbag_profile *profile = NULL;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_button *button;
|
||||
@@ -139,6 +222,12 @@ steelseries_probe(struct ratbag_device *device)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = ratbag_open_hidraw_index(device,
|
||||
STEELSERIES_INPUT_ENDPOINT,
|
||||
STEELSERIES_INPUT_HIDRAW);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
device_version = ratbag_device_data_steelseries_get_device_version(device->data);
|
||||
button_count = ratbag_device_data_steelseries_get_button_count(device->data);
|
||||
led_count = ratbag_device_data_steelseries_get_led_count(device->data);
|
||||
@@ -226,6 +315,16 @@ steelseries_probe(struct ratbag_device *device)
|
||||
}
|
||||
}
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
|
||||
steelseries_get_firmware_version(device);
|
||||
log_debug(device->ratbag, "SteelSeries firmware version %d.%d\n",
|
||||
drv_data->firmware_major,
|
||||
drv_data->firmware_minor);
|
||||
|
||||
steelseries_read_settings(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -695,7 +794,9 @@ steelseries_commit(struct ratbag_device *device)
|
||||
static void
|
||||
steelseries_remove(struct ratbag_device *device)
|
||||
{
|
||||
ratbag_close_hidraw(device);
|
||||
ratbag_close_hidraw_index(device, 0);
|
||||
ratbag_close_hidraw_index(device, 1);
|
||||
free(ratbag_get_drv_data(device));
|
||||
}
|
||||
|
||||
struct ratbag_driver steelseries_driver = {
|
||||
|
||||
Reference in New Issue
Block a user