Change driver probe() as a flat function

Previously, probe() would call ratbag_init_profiles() which in turn would call
the various function pointers in the driver to fill in profiles, buttons and
leds (the latter while filling in profiles). This made the probe() function
harder to understand than necessary and unreliable because it wasn't always
clear which bits were already set up while some driver function was called and
which ones weren't yet.

This patch switches to a flat probe(). The driver still needs to call
ratbag_init_profiles(), libratbag sets up everything (to default values). Then
the driver can fill in the rest as it wants.

This patch still makes use of the current infrastructure, the drivers
just call the read_profile and read_button functions manually now.

Fixes #370

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer
2017-10-04 19:00:10 +10:00
committed by Benjamin Tissoires
parent e9008eeaba
commit f26de4bb29
9 changed files with 419 additions and 426 deletions

View File

@@ -324,79 +324,6 @@ etekcity_button_to_action(struct ratbag_profile *profile,
return etekcity_raw_to_button_action(data);
}
static void
etekcity_read_profile(struct ratbag_profile *profile, unsigned int index)
{
struct ratbag_device *device = profile->device;
struct etekcity_data *drv_data;
struct ratbag_resolution *resolution;
struct etekcity_settings_report *setting_report;
uint8_t *buf;
unsigned int report_rate;
int dpi_x, dpi_y, hz;
int rc;
assert(index <= ETEKCITY_PROFILE_MAX);
drv_data = ratbag_get_drv_data(device);
setting_report = &drv_data->settings[index];
buf = (uint8_t*)setting_report;
etekcity_set_config_profile(device, index, ETEKCITY_CONFIG_SETTINGS);
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_SETTINGS,
buf, ETEKCITY_REPORT_SIZE_SETTINGS,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (rc < ETEKCITY_REPORT_SIZE_SETTINGS)
return;
/* first retrieve the report rate, it is set per profile */
switch (setting_report->report_rate) {
case 0x00: report_rate = 125; break;
case 0x01: report_rate = 250; break;
case 0x02: report_rate = 500; break;
case 0x03: report_rate = 1000; break;
default:
log_error(device->ratbag,
"error while reading the report rate of the mouse (0x%02x)\n",
buf[26]);
report_rate = 0;
}
ratbag_profile_for_each_resolution(profile, resolution) {
dpi_x = setting_report->xres[resolution->index] * 50;
dpi_y = setting_report->yres[resolution->index] * 50;
hz = report_rate;
if (!(setting_report->dpi_mask & (1 << resolution->index))) {
/* the profile is disabled, overwrite it */
dpi_x = 0;
dpi_y = 0;
hz = 0;
}
ratbag_resolution_set_resolution(resolution, dpi_x, dpi_y, hz);
ratbag_resolution_set_cap(resolution,
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
resolution->is_active = (resolution->index == setting_report->current_dpi);
}
buf = drv_data->profiles[index];
etekcity_set_config_profile(device, index, ETEKCITY_CONFIG_KEY_MAPPING);
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_KEY_MAPPING,
buf, ETEKCITY_REPORT_SIZE_PROFILE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
msleep(10);
if (rc < ETEKCITY_REPORT_SIZE_PROFILE)
return;
log_raw(device->ratbag, "profile: %d %s:%d\n",
buf[2],
__FILE__, __LINE__);
}
static int
etekcity_write_profile(struct ratbag_profile *profile)
{
@@ -491,6 +418,82 @@ etekcity_read_button(struct ratbag_button *button)
}
}
static void
etekcity_read_profile(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct etekcity_data *drv_data;
struct ratbag_resolution *resolution;
struct ratbag_button *button;
struct etekcity_settings_report *setting_report;
uint8_t *buf;
unsigned int report_rate;
int dpi_x, dpi_y, hz;
int rc;
assert(profile->index <= ETEKCITY_PROFILE_MAX);
drv_data = ratbag_get_drv_data(device);
setting_report = &drv_data->settings[profile->index];
buf = (uint8_t*)setting_report;
etekcity_set_config_profile(device, profile->index, ETEKCITY_CONFIG_SETTINGS);
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_SETTINGS,
buf, ETEKCITY_REPORT_SIZE_SETTINGS,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (rc < ETEKCITY_REPORT_SIZE_SETTINGS)
return;
/* first retrieve the report rate, it is set per profile */
switch (setting_report->report_rate) {
case 0x00: report_rate = 125; break;
case 0x01: report_rate = 250; break;
case 0x02: report_rate = 500; break;
case 0x03: report_rate = 1000; break;
default:
log_error(device->ratbag,
"error while reading the report rate of the mouse (0x%02x)\n",
buf[26]);
report_rate = 0;
}
ratbag_profile_for_each_resolution(profile, resolution) {
dpi_x = setting_report->xres[resolution->index] * 50;
dpi_y = setting_report->yres[resolution->index] * 50;
hz = report_rate;
if (!(setting_report->dpi_mask & (1 << resolution->index))) {
/* the profile is disabled, overwrite it */
dpi_x = 0;
dpi_y = 0;
hz = 0;
}
ratbag_resolution_set_resolution(resolution, dpi_x, dpi_y, hz);
ratbag_resolution_set_cap(resolution,
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
resolution->is_active = (resolution->index == setting_report->current_dpi);
}
ratbag_profile_for_each_button(profile, button)
etekcity_read_button(button);
buf = drv_data->profiles[profile->index];
etekcity_set_config_profile(device, profile->index, ETEKCITY_CONFIG_KEY_MAPPING);
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_KEY_MAPPING,
buf, ETEKCITY_REPORT_SIZE_PROFILE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
msleep(10);
if (rc < ETEKCITY_REPORT_SIZE_PROFILE)
return;
log_raw(device->ratbag, "profile: %d %s:%d\n",
buf[2],
__FILE__, __LINE__);
}
static int
etekcity_write_macro(struct ratbag_button *button,
const struct ratbag_button_action *action)
@@ -661,6 +664,9 @@ etekcity_probe(struct ratbag_device *device)
ETEKCITY_BUTTON_MAX + 1,
ETEKCITY_LED);
ratbag_device_for_each_profile(device, profile)
etekcity_read_profile(profile);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
@@ -706,10 +712,8 @@ struct ratbag_driver etekcity_driver = {
.id = "etekcity",
.probe = etekcity_probe,
.remove = etekcity_remove,
.read_profile = etekcity_read_profile,
.write_profile = etekcity_write_profile,
.set_active_profile = etekcity_set_current_profile,
.read_button = etekcity_read_button,
.write_button = etekcity_write_button,
.write_resolution_dpi = etekcity_write_resolution_dpi,
};

View File

@@ -972,67 +972,6 @@ gskill_write_button_macro(struct ratbag_device *device,
return 0;
}
static int
gskill_probe(struct ratbag_device *device)
{
struct gskill_data *drv_data = NULL;
struct ratbag_profile *profile;
unsigned int active_idx;
int ret;
ret = ratbag_open_hidraw(device);
if (ret)
return ret;
drv_data = zalloc(sizeof(*drv_data));
ratbag_set_drv_data(device, drv_data);
ret = gskill_get_firmware_version(device);
if (ret < 0)
goto err;
log_debug(device->ratbag,
"Firmware version: %d\n", ret);
ret = gskill_get_profile_count(device);
if (ret < 0)
goto err;
drv_data->profile_count = ret;
ratbag_device_init_profiles(device, GSKILL_PROFILE_MAX, GSKILL_NUM_DPI,
GSKILL_BUTTON_MAX, GSKILL_NUM_LED);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_QUERY_CONFIGURATION);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_DISABLE_PROFILE);
ret = gskill_get_active_profile_idx(device);
if (ret < 0)
goto err;
active_idx = ret;
list_for_each(profile, &device->profiles, link) {
if (profile->index == active_idx) {
profile->is_active = true;
break;
}
}
return 0;
err:
if (drv_data) {
ratbag_set_drv_data(device, NULL);
free(drv_data);
}
ratbag_close_hidraw(device);
return ret;
}
static void
gskill_read_resolutions(struct ratbag_profile *profile,
struct gskill_profile_report *report)
@@ -1083,7 +1022,7 @@ gskill_read_profile_name(struct ratbag_device *device,
}
static void
gskill_read_profile(struct ratbag_profile *profile, unsigned int index)
gskill_read_profile(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct gskill_data *drv_data = ratbag_get_drv_data(device);
@@ -1092,7 +1031,7 @@ gskill_read_profile(struct ratbag_profile *profile, unsigned int index)
uint8_t checksum;
int rc, retries;
if (index >= drv_data->profile_count) {
if (profile->index >= drv_data->profile_count) {
profile->is_enabled = false;
return;
}
@@ -1106,7 +1045,7 @@ gskill_read_profile(struct ratbag_profile *profile, unsigned int index)
* mouse we're doing something wrong.
*/
for (retries = 0; retries < 3; retries++) {
rc = gskill_select_profile(device, index, false);
rc = gskill_select_profile(device, profile->index, false);
if (rc < 0)
return;
@@ -1124,12 +1063,11 @@ gskill_read_profile(struct ratbag_profile *profile, unsigned int index)
return;
}
if (report->profile_num == index)
if (report->profile_num == profile->index)
break;
log_debug(device->ratbag,
"Mouse send wrong profile %d instead of %d, retrying...\n",
profile->index, index);
"Mouse send wrong profile, retrying...\n");
}
checksum = gskill_calculate_checksum((uint8_t*)report, sizeof(*report));
@@ -1430,6 +1368,73 @@ gskill_update_profile(struct ratbag_profile *profile)
return 0;
}
static int
gskill_probe(struct ratbag_device *device)
{
struct gskill_data *drv_data = NULL;
struct ratbag_profile *profile;
unsigned int active_idx;
int ret;
ret = ratbag_open_hidraw(device);
if (ret)
return ret;
drv_data = zalloc(sizeof(*drv_data));
ratbag_set_drv_data(device, drv_data);
ret = gskill_get_firmware_version(device);
if (ret < 0)
goto err;
log_debug(device->ratbag,
"Firmware version: %d\n", ret);
ret = gskill_get_profile_count(device);
if (ret < 0)
goto err;
drv_data->profile_count = ret;
ratbag_device_init_profiles(device, GSKILL_PROFILE_MAX, GSKILL_NUM_DPI,
GSKILL_BUTTON_MAX, GSKILL_NUM_LED);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_QUERY_CONFIGURATION);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_DISABLE_PROFILE);
ret = gskill_get_active_profile_idx(device);
if (ret < 0)
goto err;
active_idx = ret;
ratbag_device_for_each_profile(device, profile) {
struct ratbag_button *button;
gskill_read_profile(profile);
ratbag_profile_for_each_button(profile, button)
gskill_read_button(button);
if (profile->index == active_idx) {
profile->is_active = true;
break;
}
}
return 0;
err:
if (drv_data) {
ratbag_set_drv_data(device, NULL);
free(drv_data);
}
ratbag_close_hidraw(device);
return ret;
}
static int
gskill_commit(struct ratbag_device *device)
{
@@ -1507,8 +1512,6 @@ struct ratbag_driver gskill_driver = {
.id = "gskill",
.probe = gskill_probe,
.remove = gskill_remove,
.read_profile = gskill_read_profile,
.commit = gskill_commit,
.set_active_profile = gskill_set_active_profile,
.read_button = gskill_read_button,
};

View File

@@ -347,9 +347,10 @@ hidpp10drv_set_current_profile(struct ratbag_device *device, unsigned int index)
}
static void
hidpp10drv_read_profile(struct ratbag_profile *profile, unsigned int index)
hidpp10drv_read_profile(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct ratbag_button *button;
struct hidpp10drv_data *drv_data;
struct hidpp10_device *hidpp10;
struct hidpp10_profile p = {0};
@@ -360,7 +361,7 @@ hidpp10drv_read_profile(struct ratbag_profile *profile, unsigned int index)
drv_data = ratbag_get_drv_data(device);
hidpp10 = drv_data->dev;
rc = hidpp10_get_profile(hidpp10, index, &p);
rc = hidpp10_get_profile(hidpp10, profile->index, &p);
if (rc)
return;
@@ -400,6 +401,9 @@ hidpp10drv_read_profile(struct ratbag_profile *profile, unsigned int index)
max = hidpp10_dpi_table_get_max_dpi(hidpp10);
ratbag_resolution_set_range(res, min, max);
}
ratbag_profile_for_each_button(profile, button)
hidpp10drv_read_button(button);
}
static int
@@ -531,6 +535,7 @@ hidpp10drv_probe(struct ratbag_device *device)
const char *typestr;
int device_idx = HIDPP_WIRED_DEVICE_IDX;
unsigned int profile_count = 1;
struct ratbag_profile *profile;
rc = ratbag_find_hidraw(device, hidpp10drv_test_hidraw);
if (rc)
@@ -618,6 +623,9 @@ hidpp10drv_probe(struct ratbag_device *device)
profile->is_active = true;
}
ratbag_device_for_each_profile(device, profile)
hidpp10drv_read_profile(profile);
return 0;
err:
free(drv_data);
@@ -649,8 +657,6 @@ struct ratbag_driver hidpp10_driver = {
.id = "hidpp10",
.probe = hidpp10drv_probe,
.remove = hidpp10drv_remove,
.read_profile = hidpp10drv_read_profile,
.set_active_profile = hidpp10drv_set_current_profile,
.read_button = hidpp10drv_read_button,
.commit = hidpp10drv_commit,
};

View File

@@ -831,7 +831,7 @@ hidpp20drv_read_leds(struct ratbag_device *device)
}
static void
hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
hidpp20drv_read_profile_8100(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
@@ -839,10 +839,10 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
struct hidpp20_profile *p;
int dpi_index = 0xff;
profile->is_enabled = drv_data->profiles->profiles[index].enabled;
profile->is_enabled = drv_data->profiles->profiles[profile->index].enabled;
profile->is_active = false;
if ((int)index == hidpp20drv_current_profile(device))
if ((int)profile->index == hidpp20drv_current_profile(device))
profile->is_active = true;
if (profile->is_active)
@@ -851,7 +851,7 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
if (dpi_index < 0)
dpi_index = 0xff;
p = &drv_data->profiles->profiles[index];
p = &drv_data->profiles->profiles[profile->index];
ratbag_profile_for_each_resolution(profile, res) {
struct hidpp20_sensor *sensor;
@@ -879,18 +879,27 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
}
static void
hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index)
hidpp20drv_read_profile(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct ratbag_led *led;
struct ratbag_button *button;
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
return hidpp20drv_read_profile_8100(profile, index);
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
hidpp20drv_read_profile_8100(profile);
} else {
hidpp20drv_read_resolution_dpi(profile);
hidpp20drv_read_special_key_mouse(device);
hidpp20drv_read_resolution_dpi(profile);
hidpp20drv_read_special_key_mouse(device);
profile->is_active = (profile->index == 0);
}
profile->is_active = (index == 0);
ratbag_profile_for_each_led(profile, led)
hidpp20drv_read_led(led);
ratbag_profile_for_each_button(profile, button)
hidpp20drv_read_button(button);
}
static int
@@ -1159,6 +1168,22 @@ hidpp20drv_remove(struct ratbag_device *device)
free(drv_data);
}
static void
hidpp20drv_init_device(struct ratbag_device *device,
struct hidpp20drv_data *drv_data)
{
struct ratbag_profile *profile;
ratbag_device_init_profiles(device,
drv_data->num_profiles,
drv_data->num_resolutions,
drv_data->num_buttons,
drv_data->num_leds);
ratbag_device_for_each_profile(device, profile)
hidpp20drv_read_profile(profile);
}
static int
hidpp20drv_probe(struct ratbag_device *device)
{
@@ -1209,11 +1234,7 @@ hidpp20drv_probe(struct ratbag_device *device)
if (rc)
goto err;
ratbag_device_init_profiles(device,
drv_data->num_profiles,
drv_data->num_resolutions,
drv_data->num_buttons,
drv_data->num_leds);
hidpp20drv_init_device(device, drv_data);
return rc;
err:
@@ -1227,8 +1248,5 @@ struct ratbag_driver hidpp20_driver = {
.probe = hidpp20drv_probe,
.remove = hidpp20drv_remove,
.commit = hidpp20drv_commit,
.read_profile = hidpp20drv_read_profile,
.set_active_profile = hidpp20drv_set_current_profile,
.read_button = hidpp20drv_read_button,
.read_led = hidpp20drv_read_led,
};

View File

@@ -289,59 +289,6 @@ logitech_g300_set_current_resolution(struct ratbag_device *device, unsigned int
return ret == sizeof(buf) ? 0 : ret;
}
static void
logitech_g300_read_profile(struct ratbag_profile *profile, unsigned int index)
{
struct ratbag_device *device = profile->device;
struct logitech_g300_data *drv_data = device->drv_data;
struct logitech_g300_profile_data *pdata;
struct logitech_g300_profile_report *report;
struct ratbag_resolution *resolution;
unsigned int hz;
uint8_t report_id;
int rc;
assert(index <= LOGITECH_G300_PROFILE_MAX);
pdata = &drv_data->profile_data[index];
report = &pdata->report;
switch (index) {
case 0: report_id = LOGITECH_G300_REPORT_ID_PROFILE_0; break;
case 1: report_id = LOGITECH_G300_REPORT_ID_PROFILE_1; break;
case 2: report_id = LOGITECH_G300_REPORT_ID_PROFILE_2; break;
}
rc = ratbag_hidraw_raw_request(device, report_id,
(uint8_t*)report,
sizeof(*report),
HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (rc < (int)sizeof(*report)) {
log_error(device->ratbag,
"Error while requesting profile: %d\n", rc);
return;
}
hz = logitech_g300_raw_to_frequency(report->frequency);
ratbag_profile_for_each_resolution(profile, resolution) {
struct logitech_g300_resolution *res =
&report->dpi_levels[resolution->index];
resolution->dpi_x = res->dpi * 250;
resolution->dpi_y = res->dpi * 250;
resolution->hz = hz;
resolution->is_default = res->is_default;
resolution->is_active = res->is_default;
ratbag_resolution_set_range(resolution,
LOGITECH_G300_DPI_MIN,
LOGITECH_G300_DPI_MAX);
}
}
static void
logitech_g300_read_button(struct ratbag_button *button)
{
@@ -397,6 +344,67 @@ logitech_g300_read_led(struct ratbag_led *led)
led->color.blue = profile_report->led_blue * 255;
}
static void
logitech_g300_read_profile(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct logitech_g300_data *drv_data = device->drv_data;
struct logitech_g300_profile_data *pdata;
struct logitech_g300_profile_report *report;
struct ratbag_resolution *resolution;
unsigned int hz;
uint8_t report_id;
int rc;
struct ratbag_button *button;
struct ratbag_led *led;
assert(profile->index <= LOGITECH_G300_PROFILE_MAX);
pdata = &drv_data->profile_data[profile->index];
report = &pdata->report;
switch (profile->index) {
case 0: report_id = LOGITECH_G300_REPORT_ID_PROFILE_0; break;
case 1: report_id = LOGITECH_G300_REPORT_ID_PROFILE_1; break;
case 2: report_id = LOGITECH_G300_REPORT_ID_PROFILE_2; break;
}
rc = ratbag_hidraw_raw_request(device, report_id,
(uint8_t*)report,
sizeof(*report),
HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (rc < (int)sizeof(*report)) {
log_error(device->ratbag,
"Error while requesting profile: %d\n", rc);
return;
}
hz = logitech_g300_raw_to_frequency(report->frequency);
ratbag_profile_for_each_resolution(profile, resolution) {
struct logitech_g300_resolution *res =
&report->dpi_levels[resolution->index];
resolution->dpi_x = res->dpi * 250;
resolution->dpi_y = res->dpi * 250;
resolution->hz = hz;
resolution->is_default = res->is_default;
resolution->is_active = res->is_default;
ratbag_resolution_set_range(resolution,
LOGITECH_G300_DPI_MIN,
LOGITECH_G300_DPI_MAX);
}
ratbag_profile_for_each_button(profile, button)
logitech_g300_read_button(button);
ratbag_profile_for_each_led(profile, led)
logitech_g300_read_led(led);
}
static int
logitech_g300_test_hidraw(struct ratbag_device *device)
{
@@ -409,6 +417,7 @@ logitech_g300_probe(struct ratbag_device *device)
int rc;
struct logitech_g300_data *drv_data = NULL;
int active_idx;
struct ratbag_profile *profile;
rc = ratbag_find_hidraw(device, logitech_g300_test_hidraw);
if (rc)
@@ -424,6 +433,9 @@ logitech_g300_probe(struct ratbag_device *device)
LOGITECH_G300_BUTTON_MAX + 1,
LOGITECH_G300_NUM_LED);
ratbag_device_for_each_profile(device, profile)
logitech_g300_read_profile(profile);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_RESOLUTION);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_PROFILE);
@@ -570,9 +582,6 @@ struct ratbag_driver logitech_g300_driver = {
.id = "logitech_g300",
.probe = logitech_g300_probe,
.remove = logitech_g300_remove,
.read_profile = logitech_g300_read_profile,
.commit = logitech_g300_commit,
.set_active_profile = logitech_g300_set_active_profile,
.read_button = logitech_g300_read_button,
.read_led = logitech_g300_read_led,
};

View File

@@ -391,83 +391,6 @@ roccat_button_to_action(struct ratbag_profile *profile,
return roccat_raw_to_button_action(data);
}
static void
roccat_read_profile(struct ratbag_profile *profile, unsigned int index)
{
struct ratbag_device *device = profile->device;
struct roccat_data *drv_data;
struct ratbag_resolution *resolution;
struct roccat_settings_report *setting_report;
uint8_t *buf;
unsigned int report_rate;
int dpi_x, dpi_y, hz;
int rc;
assert(index <= ROCCAT_PROFILE_MAX);
drv_data = ratbag_get_drv_data(device);
setting_report = &drv_data->settings[index];
buf = (uint8_t*)setting_report;
roccat_set_config_profile(device, index, ROCCAT_CONFIG_SETTINGS);
rc = ratbag_hidraw_raw_request(device, ROCCAT_REPORT_ID_SETTINGS,
buf, ROCCAT_REPORT_SIZE_SETTINGS,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (rc < ROCCAT_REPORT_SIZE_SETTINGS)
return;
/* first retrieve the report rate, it is set per profile */
switch (setting_report->report_rate) {
case 0x00: report_rate = 125; break;
case 0x01: report_rate = 250; break;
case 0x02: report_rate = 500; break;
case 0x03: report_rate = 1000; break;
default:
log_error(device->ratbag,
"error while reading the report rate of the mouse (0x%02x)\n",
buf[26]);
report_rate = 0;
}
ratbag_profile_for_each_resolution(profile, resolution) {
dpi_x = setting_report->xres[resolution->index] * 50;
dpi_y = setting_report->yres[resolution->index] * 50;
hz = report_rate;
if (!(setting_report->dpi_mask & (1 << resolution->index))) {
/* the profile is disabled, overwrite it */
dpi_x = 0;
dpi_y = 0;
hz = 0;
}
ratbag_resolution_set_resolution(resolution, dpi_x, dpi_y, hz);
ratbag_resolution_set_cap(resolution,
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
resolution->is_active = (resolution->index == setting_report->current_dpi);
}
buf = drv_data->profiles[index];
roccat_set_config_profile(device, index, ROCCAT_CONFIG_KEY_MAPPING);
rc = ratbag_hidraw_raw_request(device, ROCCAT_REPORT_ID_KEY_MAPPING,
buf, ROCCAT_REPORT_SIZE_PROFILE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
msleep(10);
if (rc < ROCCAT_REPORT_SIZE_PROFILE)
return;
if (!roccat_crc_is_valid(device, buf, ROCCAT_REPORT_SIZE_PROFILE))
log_error(device->ratbag,
"Error while reading profile %d, continuing...\n",
profile->index);
log_raw(device->ratbag, "profile: %d %s:%d\n",
buf[2],
__FILE__, __LINE__);
}
static int
roccat_write_profile(struct ratbag_profile *profile)
{
@@ -769,6 +692,87 @@ roccat_write_resolution_dpi(struct ratbag_resolution *resolution,
return rc;
}
static void
roccat_read_profile(struct ratbag_profile *profile)
{
struct ratbag_device *device = profile->device;
struct roccat_data *drv_data;
struct ratbag_resolution *resolution;
struct ratbag_button *button;
struct roccat_settings_report *setting_report;
uint8_t *buf;
unsigned int report_rate;
int dpi_x, dpi_y, hz;
int rc;
assert(profile->index <= ROCCAT_PROFILE_MAX);
drv_data = ratbag_get_drv_data(device);
setting_report = &drv_data->settings[profile->index];
buf = (uint8_t*)setting_report;
roccat_set_config_profile(device, profile->index, ROCCAT_CONFIG_SETTINGS);
rc = ratbag_hidraw_raw_request(device, ROCCAT_REPORT_ID_SETTINGS,
buf, ROCCAT_REPORT_SIZE_SETTINGS,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (rc < ROCCAT_REPORT_SIZE_SETTINGS)
return;
/* first retrieve the report rate, it is set per profile */
switch (setting_report->report_rate) {
case 0x00: report_rate = 125; break;
case 0x01: report_rate = 250; break;
case 0x02: report_rate = 500; break;
case 0x03: report_rate = 1000; break;
default:
log_error(device->ratbag,
"error while reading the report rate of the mouse (0x%02x)\n",
buf[26]);
report_rate = 0;
}
ratbag_profile_for_each_resolution(profile, resolution) {
dpi_x = setting_report->xres[resolution->index] * 50;
dpi_y = setting_report->yres[resolution->index] * 50;
hz = report_rate;
if (!(setting_report->dpi_mask & (1 << resolution->index))) {
/* the profile is disabled, overwrite it */
dpi_x = 0;
dpi_y = 0;
hz = 0;
}
ratbag_resolution_set_resolution(resolution, dpi_x, dpi_y, hz);
ratbag_resolution_set_cap(resolution,
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
resolution->is_active = (resolution->index == setting_report->current_dpi);
}
ratbag_profile_for_each_button(profile, button)
roccat_read_button(button);
buf = drv_data->profiles[profile->index];
roccat_set_config_profile(device, profile->index, ROCCAT_CONFIG_KEY_MAPPING);
rc = ratbag_hidraw_raw_request(device, ROCCAT_REPORT_ID_KEY_MAPPING,
buf, ROCCAT_REPORT_SIZE_PROFILE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
msleep(10);
if (rc < ROCCAT_REPORT_SIZE_PROFILE)
return;
if (!roccat_crc_is_valid(device, buf, ROCCAT_REPORT_SIZE_PROFILE))
log_error(device->ratbag,
"Error while reading profile %d, continuing...\n",
profile->index);
log_raw(device->ratbag, "profile: %d %s:%d\n",
buf[2],
__FILE__, __LINE__);
}
static int
roccat_probe(struct ratbag_device *device)
{
@@ -796,6 +800,9 @@ roccat_probe(struct ratbag_device *device)
ROCCAT_BUTTON_MAX + 1,
ROCCAT_LED_MAX);
ratbag_device_for_each_profile(device, profile)
roccat_read_profile(profile);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
@@ -841,10 +848,8 @@ struct ratbag_driver roccat_driver = {
.id = "roccat",
.probe = roccat_probe,
.remove = roccat_remove,
.read_profile = roccat_read_profile,
.write_profile = roccat_write_profile,
.set_active_profile = roccat_set_current_profile,
.read_button = roccat_read_button,
.write_button = roccat_write_button,
.write_resolution_dpi = roccat_write_resolution_dpi,
};

View File

@@ -29,57 +29,6 @@
#include "libratbag-private.h"
#include "libratbag-test.h"
static void
test_read_profile(struct ratbag_profile *profile, unsigned int index)
{
struct ratbag_test_device *d = ratbag_get_drv_data(profile->device);
struct ratbag_test_profile *p;
struct ratbag_test_resolution *r;
unsigned int i;
bool active_set = false;
bool default_set = false;
assert(index < d->num_profiles);
p = &d->profiles[index];
for (i = 0; i < d->num_resolutions; i++) {
_cleanup_resolution_ struct ratbag_resolution *res;
r = &p->resolutions[i];
res = ratbag_profile_get_resolution(profile, i);
assert(res);
ratbag_resolution_set_resolution(res, r->xres, r->yres, r->hz);
res->is_active = r->active;
if (r->active)
active_set = true;
res->is_default = r->dflt;
if (r->dflt)
default_set = true;
ratbag_resolution_set_cap(res, r->caps);
res->hz = r->hz;
}
/* special case triggered by the test suite when num_resolutions is 0 */
if (d->num_resolutions) {
_cleanup_resolution_ struct ratbag_resolution *res;
res = ratbag_profile_get_resolution(profile, 0);
assert(res);
if (!active_set)
res->is_active = true;
if (!default_set)
res->is_default = true;
}
profile->is_active = p->active;
profile->is_enabled = !p->disabled;
for (i = 0; i < ARRAY_LENGTH(p->caps) && p->caps[i]; i++) {
ratbag_profile_set_cap(profile, p->caps[i]);
}
}
static int
test_write_profile(struct ratbag_profile *profile)
{
@@ -215,10 +164,70 @@ test_fake_probe(struct ratbag_device *device)
return -ENODEV;
}
static void
test_read_profile(struct ratbag_profile *profile)
{
struct ratbag_test_device *d = ratbag_get_drv_data(profile->device);
struct ratbag_test_profile *p;
struct ratbag_test_resolution *r;
struct ratbag_button *button;
struct ratbag_led *led;
unsigned int i;
bool active_set = false;
bool default_set = false;
assert(profile->index < d->num_profiles);
p = &d->profiles[profile->index];
for (i = 0; i < d->num_resolutions; i++) {
_cleanup_resolution_ struct ratbag_resolution *res;
r = &p->resolutions[i];
res = ratbag_profile_get_resolution(profile, i);
assert(res);
ratbag_resolution_set_resolution(res, r->xres, r->yres, r->hz);
res->is_active = r->active;
if (r->active)
active_set = true;
res->is_default = r->dflt;
if (r->dflt)
default_set = true;
ratbag_resolution_set_cap(res, r->caps);
res->hz = r->hz;
}
/* special case triggered by the test suite when num_resolutions is 0 */
if (d->num_resolutions) {
_cleanup_resolution_ struct ratbag_resolution *res;
res = ratbag_profile_get_resolution(profile, 0);
assert(res);
if (!active_set)
res->is_active = true;
if (!default_set)
res->is_default = true;
}
ratbag_profile_for_each_button(profile, button)
test_read_button(button);
ratbag_profile_for_each_led(profile, led)
test_read_led(led);
profile->is_active = p->active;
profile->is_enabled = !p->disabled;
for (i = 0; i < ARRAY_LENGTH(p->caps) && p->caps[i]; i++) {
ratbag_profile_set_cap(profile, p->caps[i]);
}
}
static int
test_probe(struct ratbag_device *device, const void *data)
{
struct ratbag_test_device *test_device;
struct ratbag_profile *profile;
test_device = zalloc(sizeof(*test_device));
memcpy(test_device, data, sizeof(*test_device));
@@ -235,6 +244,9 @@ test_probe(struct ratbag_device *device, const void *data)
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_DISABLE_PROFILE);
}
ratbag_device_for_each_profile(device, profile)
test_read_profile(profile);
return 0;
}
@@ -258,11 +270,8 @@ struct ratbag_driver test_driver = {
.test_probe = test_probe,
.remove = test_remove,
.get_svg_name = test_get_svg_name,
.read_profile = test_read_profile,
.write_profile = test_write_profile,
.set_active_profile = test_set_active_profile,
.read_button = test_read_button,
.read_led = test_read_led,
.write_button = test_write_button,
.write_resolution_dpi = NULL,
.write_led = test_write_led,

View File

@@ -174,17 +174,6 @@ struct ratbag_driver {
*/
const char *(*get_svg_name)(const struct ratbag_device *device);
/**
* Callback called when a read profile is requested by the
* caller of the library.
*
* The driver should probe here the device for the requested
* profile and populate the related information.
* There is no need to populate the various struct ratbag_button
* as they are allocated when the user needs it.
*/
void (*read_profile)(struct ratbag_profile *profile, unsigned int index);
/*
* FIXME: This function is deprecated and should be removed. Once
* we've updated all the device drivers to stop using it we'll remove
@@ -200,19 +189,6 @@ struct ratbag_driver {
*/
int (*set_active_profile)(struct ratbag_device *device, unsigned int index);
/**
* For the given button, fill in the struct ratbag_button
* with the available information.
*
* For devices with profiles, profile will not be NULL. For
* device without, profile will be set to NULL.
*
* For devices with profile, there should not be the need to
* actually read the profile from the device. The caller
* should make sure that the profile is up to date.
*/
void (*read_button)(struct ratbag_button *button);
/*
* FIXME: This function is deprecated and should be removed. Once
* we've updated all the device drivers to stop using it we'll remove
@@ -229,12 +205,6 @@ struct ratbag_driver {
int (*write_resolution_dpi)(struct ratbag_resolution *resolution,
int dpi_x, int dpi_y);
/**
* For the given led, fill in the struct ratbag_led
* with the available information.
*/
void (*read_led)(struct ratbag_led *led);
/*
* FIXME: This function is deprecated and should be removed. Once
* we've updated all the device drivers to stop using it we'll remove

View File

@@ -295,6 +295,8 @@ ratbag_sanity_check_device(struct ratbag_device *device)
_cleanup_led_ struct ratbag_led *p0_led = ratbag_profile_get_led(p0, j);
_cleanup_led_ struct ratbag_led *led = ratbag_profile_get_led(p, j);
assert(led->type != RATBAG_LED_TYPE_UNKNOWN);
if (p0_led->type != led->type) {
log_bug_libratbag(ratbag,
"%s: mismatching LED types (profile %d led %d)\n",
@@ -597,19 +599,16 @@ ratbag_unref(struct ratbag *ratbag)
static struct ratbag_button *
ratbag_create_button(struct ratbag_profile *profile, unsigned int index)
{
struct ratbag_device *device = profile->device;
struct ratbag_button *button;
button = zalloc(sizeof(*button));
button->refcount = 0;
button->profile = profile;
button->index = index;
button->type = RATBAG_BUTTON_TYPE_UNKNOWN;
list_insert(&profile->buttons, &button->link);
if (device->driver->read_button)
device->driver->read_button(button);
return button;
}
@@ -630,42 +629,9 @@ ratbag_create_led(struct ratbag_profile *profile, unsigned int index)
list_insert(&profile->leds, &led->link);
/* If you init a LED, you need to provide this function */
assert(device->driver->read_led);
device->driver->read_led(led);
/* The driver must fill this in correctly */
assert(led->type != RATBAG_LED_TYPE_UNKNOWN);
return led;
}
static int
ratbag_profile_init_buttons(struct ratbag_profile *profile, unsigned int count)
{
unsigned int i;
for (i = 0; i < count; i++)
ratbag_create_button(profile, i);
profile->device->num_buttons = count;
return 0;
}
static int
ratbag_profile_init_leds(struct ratbag_profile *profile, unsigned int count)
{
unsigned int i;
for (i = 0; i < count; i++)
ratbag_create_led(profile, i);
profile->device->num_leds = count;
return 0;
}
LIBRATBAG_EXPORT int
ratbag_profile_has_capability(const struct ratbag_profile *profile,
enum ratbag_profile_capability cap)
@@ -715,14 +681,17 @@ ratbag_create_profile(struct ratbag_device *device,
list_init(&profile->leds);
list_init(&profile->resolutions);
profile->device->num_buttons = num_buttons;
profile->device->num_leds = num_leds;
for (i = 0; i < num_resolutions; i++)
ratbag_create_resolution(profile, i);
assert(device->driver->read_profile);
device->driver->read_profile(profile, index);
for (i = 0; i < num_buttons; i++)
ratbag_create_button(profile, i);
ratbag_profile_init_buttons(profile, num_buttons);
ratbag_profile_init_leds(profile, num_leds);
for (i = 0; i < num_leds; i++)
ratbag_create_led(profile, i);
return profile;
}