diff --git a/src/driver-etekcity.c b/src/driver-etekcity.c index 877ac73b..e9af6fbd 100644 --- a/src/driver-etekcity.c +++ b/src/driver-etekcity.c @@ -250,24 +250,6 @@ etekcity_button_action_to_raw(const struct ratbag_button_action *action) return 0; } -static int -etekcity_has_capability(const struct ratbag_device *device, - enum ratbag_device_capability cap) -{ - switch (cap) { - case RATBAG_DEVICE_CAP_NONE: - return 0; - case RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION: - case RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE: - case RATBAG_DEVICE_CAP_BUTTON_KEY: - case RATBAG_DEVICE_CAP_BUTTON_MACROS: - return 1; - case RATBAG_DEVICE_CAP_DEFAULT_PROFILE: - return 0; - } - return 0; -} - static int etekcity_current_profile(struct ratbag_device *device) { @@ -387,9 +369,7 @@ etekcity_read_profile(struct ratbag_profile *profile, unsigned int index) report_rate = 0; } - profile->resolution.num_modes = ETEKCITY_NUM_DPI; - - for (i = 0; i < ETEKCITY_NUM_DPI; i++) { + for (i = 0; i < profile->resolution.num_modes; i++) { dpi_x = setting_report->xres[i] * 50; dpi_y = setting_report->yres[i] * 50; hz = report_rate; @@ -682,7 +662,12 @@ etekcity_probe(struct ratbag_device *device) log_debug(device->ratbag, "device is at %d ms of latency\n", drv_data->speed_setting[2]); /* profiles are 0-indexed */ - ratbag_device_init_profiles(device, ETEKCITY_PROFILE_MAX + 1, ETEKCITY_BUTTON_MAX + 1); + ratbag_device_init_profiles(device, + ETEKCITY_PROFILE_MAX + 1, + ETEKCITY_NUM_DPI, + ETEKCITY_BUTTON_MAX + 1); + + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS); active_idx = etekcity_current_profile(device); if (active_idx < 0) { @@ -730,7 +715,6 @@ struct ratbag_driver etekcity_driver = { .write_profile = etekcity_write_profile, .set_active_profile = etekcity_set_current_profile, .set_default_profile = etekcity_set_default_profile, - .has_capability = etekcity_has_capability, .read_button = etekcity_read_button, .write_button = etekcity_write_button, .write_resolution_dpi = etekcity_write_resolution_dpi, diff --git a/src/driver-hidpp10.c b/src/driver-hidpp10.c index 0454304c..5fa93dc8 100644 --- a/src/driver-hidpp10.c +++ b/src/driver-hidpp10.c @@ -317,28 +317,6 @@ hidpp10drv_write_button(struct ratbag_button *button, return hidpp10_set_profile(drv_data->dev, button->profile->index, &profile); } -static int -hidpp10drv_has_capability(const struct ratbag_device *device, - enum ratbag_device_capability cap) -{ - /* we force a non const device to shut up a warning, but we won't change anything */ - struct hidpp10drv_data *drv_data = ratbag_get_drv_data((struct ratbag_device *)device); - struct hidpp10_device *hidpp10 = drv_data->dev; - - switch (cap) { - case RATBAG_DEVICE_CAP_NONE: - abort(); - break; - case RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE: - case RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION: - case RATBAG_DEVICE_CAP_BUTTON_KEY: - case RATBAG_DEVICE_CAP_BUTTON_MACROS: - case RATBAG_DEVICE_CAP_DEFAULT_PROFILE: - return (hidpp10->profile_type != HIDPP10_PROFILE_UNKNOWN); - } - return 0; -} - static int hidpp10drv_set_current_profile(struct ratbag_device *device, unsigned int index) { @@ -381,8 +359,7 @@ hidpp10drv_read_profile(struct ratbag_profile *profile, unsigned int index) if (rc) xres = 0xffff; - profile->resolution.num_modes = p.num_dpi_modes; - for (i = 0; i < p.num_dpi_modes; i++) { + for (i = 0; i < profile->resolution.num_modes; i++) { res = ratbag_resolution_init(profile, i, p.dpi_modes[i].xres, p.dpi_modes[i].yres, @@ -467,7 +444,13 @@ hidpp10drv_fill_from_profile(struct ratbag_device *device, struct hidpp10_device if (rc) return rc; - ratbag_device_init_profiles(device, count, profile.num_buttons); + ratbag_device_init_profiles(device, + count, + profile.num_dpi_modes, + profile.num_buttons); + + if (dev->profile_type != HIDPP10_PROFILE_UNKNOWN) + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS); return 0; } @@ -588,7 +571,7 @@ hidpp10drv_probe(struct ratbag_device *device) /* Fall back to something that every mouse has */ struct ratbag_profile *profile; - ratbag_device_init_profiles(device, 1, 3); + ratbag_device_init_profiles(device, 1, 1, 3); profile = ratbag_device_get_profile(device, 0); profile->is_active = true; profile->is_default = true; @@ -630,7 +613,6 @@ struct ratbag_driver hidpp10_driver = { .write_profile = hidpp10drv_write_profile, .set_active_profile = hidpp10drv_set_current_profile, .set_default_profile = hidpp10drv_set_default_profile, - .has_capability = hidpp10drv_has_capability, .read_button = hidpp10drv_read_button, .write_button = hidpp10drv_write_button, .write_resolution_dpi = hidpp10drv_write_resolution_dpi, diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index f2d8db5a..1ac3ca4f 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -56,12 +56,15 @@ struct hidpp20drv_data { struct hidpp20_device *dev; unsigned long capabilities; - unsigned long exported_capabilities; unsigned num_sensors; struct hidpp20_sensor *sensors; unsigned num_controls; struct hidpp20_control_id *controls; struct hidpp20_profiles *profiles; + + unsigned int num_profiles; + unsigned int num_resolutions; + unsigned int num_buttons; }; static void @@ -327,31 +330,6 @@ hidpp20drv_write_button(struct ratbag_button *button, return -ENOTSUP; } -static int -hidpp20drv_has_capability(const struct ratbag_device *device, - enum ratbag_device_capability cap) -{ - /* - * We need to force the non const, but we will not change anything, - * promise! - */ - struct hidpp20drv_data *drv_data = ratbag_get_drv_data((struct ratbag_device *)device); - - if (cap == RATBAG_DEVICE_CAP_NONE) - abort(); - - return !!(drv_data->exported_capabilities & (1UL << cap)); -} - -static inline void -hidpp20drv_set_exported_capability(const struct ratbag_device *device, - enum ratbag_device_capability cap) -{ - struct hidpp20drv_data *drv_data = ratbag_get_drv_data((struct ratbag_device *)device); - - drv_data->exported_capabilities |= (1UL << cap); -} - static int hidpp20drv_current_profile(struct ratbag_device *device) { @@ -378,7 +356,7 @@ hidpp20drv_set_current_profile(struct ratbag_device *device, unsigned int index) if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) return 0; - if (index >= drv_data->profiles->num_profiles) + if (index >= drv_data->num_profiles) return -EINVAL; h_profile = &drv_data->profiles->profiles[index]; @@ -397,6 +375,38 @@ hidpp20drv_set_default_profile(struct ratbag_device *device, unsigned int index) return -ENOTSUP; } +static int +hidpp20drv_read_resolution_dpi_2201(struct ratbag_device *device) +{ + struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); + struct ratbag *ratbag = device->ratbag; + int rc; + + free(drv_data->sensors); + drv_data->sensors = NULL; + drv_data->num_sensors = 0; + rc = hidpp20_adjustable_dpi_get_sensors(drv_data->dev, &drv_data->sensors); + if (rc < 0) { + log_error(ratbag, + "Error while requesting resolution: %s (%d)\n", + strerror(-rc), rc); + return rc; + } else if (rc == 0) { + log_error(ratbag, "Error, no compatible sensors found.\n"); + return -ENODEV; + } + log_debug(ratbag, + "device is at %d dpi (variable between %d and %d).\n", + drv_data->sensors[0].dpi, + drv_data->sensors[0].dpi_min, + drv_data->sensors[0].dpi_max); + + drv_data->num_sensors = rc; + drv_data->num_resolutions = drv_data->num_sensors; + + return 0; +} + static int hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile) { @@ -411,7 +421,6 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile) uint16_t resolution; uint8_t flags; - profile->resolution.num_modes = 1; rc = hidpp20_mousepointer_get_mousepointer_info(drv_data->dev, &resolution, &flags); if (rc) { log_error(ratbag, @@ -424,28 +433,9 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile) } if (drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201) { - free(drv_data->sensors); - drv_data->sensors = NULL; - drv_data->num_sensors = 0; - rc = hidpp20_adjustable_dpi_get_sensors(drv_data->dev, &drv_data->sensors); - if (rc < 0) { - log_error(ratbag, - "Error while requesting resolution: %s (%d)\n", - strerror(-rc), rc); + rc = hidpp20drv_read_resolution_dpi_2201(device); + if (rc < 0) return rc; - } else if (rc == 0) { - log_error(ratbag, "Error, no compatible sensors found.\n"); - return -ENODEV; - } - log_debug(ratbag, - "device is at %d dpi (variable between %d and %d).\n", - drv_data->sensors[0].dpi, - drv_data->sensors[0].dpi_min, - drv_data->sensors[0].dpi_max); - drv_data->num_sensors = rc; - if (drv_data->num_sensors > MAX_RESOLUTIONS) - drv_data->num_sensors = MAX_RESOLUTIONS; - profile->resolution.num_modes = drv_data->num_sensors; for (i = 0; i < profile->resolution.num_modes; i++) { int dpi = drv_data->sensors[i].dpi; /* FIXME: retrieve the refresh rate */ @@ -581,14 +571,6 @@ hidpp20drv_read_onboard_profile(struct ratbag_device *device, unsigned index) if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) return 0; - if (!drv_data->profiles) { - rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles); - if (rc < 0) - return rc; - - device->num_buttons = drv_data->profiles->num_buttons; - } - rc = hidpp20_onboard_profiles_read(drv_data->dev, index, drv_data->profiles); if (rc < 0) return rc; @@ -597,30 +579,25 @@ hidpp20drv_read_onboard_profile(struct ratbag_device *device, unsigned index) } static void -hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index) +hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index) { struct ratbag_device *device = profile->device; struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct ratbag_resolution *res; + struct hidpp20_profile *p; unsigned i, dpi; - hidpp20drv_read_resolution_dpi(profile); - hidpp20drv_read_special_key_mouse(device); hidpp20drv_read_onboard_profile(device, profile->index); profile->is_active = false; if ((int)index == hidpp20drv_current_profile(device)) profile->is_active = true; - if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) - return; - dpi = ratbag_resolution_get_dpi(profile->resolution.modes); - profile->resolution.num_modes = drv_data->profiles->num_modes; - for (i = 0; i < drv_data->profiles->num_modes; i++) { - struct hidpp20_profile *p = &drv_data->profiles->profiles[index]; + p = &drv_data->profiles->profiles[index]; + for (i = 0; i < profile->resolution.num_modes; i++) { res = ratbag_resolution_init(profile, i, p->dpi[i], p->dpi[i], @@ -634,6 +611,21 @@ hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index) } } +static void +hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index) +{ + struct ratbag_device *device = profile->device; + struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); + + if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) + return hidpp20drv_read_profile_8100(profile, index); + + hidpp20drv_read_resolution_dpi(profile); + hidpp20drv_read_special_key_mouse(device); + + profile->is_active = (index == 0); +} + static int hidpp20drv_write_profile(struct ratbag_profile *profile) { @@ -665,14 +657,19 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature) } case HIDPP_PAGE_ADJUSTABLE_DPI: { log_debug(ratbag, "device has adjustable dpi\n"); - hidpp20drv_set_exported_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION); + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION); drv_data->capabilities |= HIDPP_CAP_SWITCHABLE_RESOLUTION_2201; + /* we read the profile once to get the correct number of + * supported resolutions. */ + rc = hidpp20drv_read_resolution_dpi_2201(device); + if (rc < 0) + return rc; break; } case HIDPP_PAGE_SPECIAL_KEYS_BUTTONS: { log_debug(ratbag, "device has programmable keys/buttons\n"); drv_data->capabilities |= HIDPP_CAP_BUTTON_KEY_1b04; - hidpp20drv_set_exported_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY); + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY); /* we read the profile once to get the correct number of * supported buttons. */ if (!hidpp20drv_read_special_key_mouse(device)) @@ -715,12 +712,15 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature) case HIDPP_PAGE_ONBOARD_PROFILES: { log_debug(ratbag, "device has onboard profiles\n"); drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100; - hidpp20drv_set_exported_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY); - hidpp20drv_set_exported_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION); - hidpp20drv_set_exported_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE); - /* we read the profiles once with an incorect profile index - * to get the correct number of supported profiles. */ - hidpp20drv_read_onboard_profile(device, 0xffffff); + + rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles); + if (rc < 0) + return rc; + + drv_data->num_profiles = drv_data->profiles->num_profiles; + drv_data->num_resolutions = drv_data->profiles->num_modes; + drv_data->num_buttons = drv_data->profiles->num_buttons; + break; } case HIDPP_PAGE_MOUSE_BUTTON_SPY: { @@ -807,14 +807,21 @@ hidpp20drv_probe(struct ratbag_device *device) log_debug(device->ratbag, "'%s' is using protocol v%d.%d\n", ratbag_device_get_name(device), dev->proto_major, dev->proto_minor); + /* add some defaults that will be overwritten by the device */ + drv_data->num_profiles = 1; + drv_data->num_resolutions = 1; + drv_data->num_buttons = 8; + if (dev->proto_major >= 2) { rc = hidpp20drv_20_probe(device); if (rc) goto err; } - ratbag_device_init_profiles(device, drv_data->profiles ? drv_data->profiles->num_profiles : 1, - device->num_buttons ? device->num_buttons : 8); + ratbag_device_init_profiles(device, + drv_data->num_profiles, + drv_data->num_resolutions, + drv_data->num_buttons); return rc; err: @@ -848,7 +855,6 @@ struct ratbag_driver hidpp20_driver = { .write_profile = hidpp20drv_write_profile, .set_active_profile = hidpp20drv_set_current_profile, .set_default_profile = hidpp20drv_set_default_profile, - .has_capability = hidpp20drv_has_capability, .read_button = hidpp20drv_read_button, .write_button = hidpp20drv_write_button, .write_resolution_dpi = hidpp20drv_write_resolution_dpi, diff --git a/src/driver-roccat.c b/src/driver-roccat.c index 2a00c864..ef563265 100644 --- a/src/driver-roccat.c +++ b/src/driver-roccat.c @@ -307,23 +307,6 @@ roccat_wait_ready(struct ratbag_device *device) return -ETIMEDOUT; } -static int -roccat_has_capability(const struct ratbag_device *device, - enum ratbag_device_capability cap) -{ - switch (cap) { - case RATBAG_DEVICE_CAP_NONE: - case RATBAG_DEVICE_CAP_DEFAULT_PROFILE: - return 0; - case RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION: - case RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE: - case RATBAG_DEVICE_CAP_BUTTON_KEY: - case RATBAG_DEVICE_CAP_BUTTON_MACROS: - return 1; - } - return 0; -} - static int roccat_current_profile(struct ratbag_device *device) { @@ -446,9 +429,7 @@ roccat_read_profile(struct ratbag_profile *profile, unsigned int index) report_rate = 0; } - profile->resolution.num_modes = ROCCAT_NUM_DPI; - - for (i = 0; i < ROCCAT_NUM_DPI; i++) { + for (i = 0; i < profile->resolution.num_modes; i++) { dpi_x = setting_report->xres[i] * 50; dpi_y = setting_report->yres[i] * 50; hz = report_rate; @@ -813,7 +794,12 @@ roccat_probe(struct ratbag_device *device) ratbag_set_drv_data(device, drv_data); /* profiles are 0-indexed */ - ratbag_device_init_profiles(device, ROCCAT_PROFILE_MAX + 1, ROCCAT_BUTTON_MAX + 1); + ratbag_device_init_profiles(device, + ROCCAT_PROFILE_MAX + 1, + ROCCAT_NUM_DPI, + ROCCAT_BUTTON_MAX + 1); + + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS); active_idx = roccat_current_profile(device); if (active_idx < 0) { @@ -860,7 +846,6 @@ struct ratbag_driver roccat_driver = { .read_profile = roccat_read_profile, .write_profile = roccat_write_profile, .set_active_profile = roccat_set_current_profile, - .has_capability = roccat_has_capability, .read_button = roccat_read_button, .write_button = roccat_write_button, .write_resolution_dpi = roccat_write_resolution_dpi, diff --git a/src/driver-test.c b/src/driver-test.c index 91a30e47..7447e8a5 100644 --- a/src/driver-test.c +++ b/src/driver-test.c @@ -28,24 +28,6 @@ #include "libratbag-private.h" #include "libratbag-test.h" -static int -test_has_capability(const struct ratbag_device *device, - enum ratbag_device_capability cap) -{ - switch (cap) { - case RATBAG_DEVICE_CAP_NONE: - abort(); - break; - case RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION: - case RATBAG_DEVICE_CAP_BUTTON_KEY: - case RATBAG_DEVICE_CAP_BUTTON_MACROS: - return (device->num_profiles > 1); - default: - return 0; - } - return 0; -} - static void test_read_profile(struct ratbag_profile *profile, unsigned int index) { @@ -57,8 +39,7 @@ test_read_profile(struct ratbag_profile *profile, unsigned int index) assert(index < d->num_profiles); p = &d->profiles[index]; - profile->resolution.num_modes = p->num_resolutions; - for (i = 0; i < p->num_resolutions; i++) { + for (i = 0; i < d->num_resolutions; i++) { struct ratbag_resolution *res; r = &p->resolutions[i]; @@ -82,6 +63,17 @@ test_write_profile(struct ratbag_profile *profile) return 0; } +static int +test_set_active_profile(struct ratbag_device *device, unsigned int index) +{ + struct ratbag_test_device *d = ratbag_get_drv_data(device); + + /* check if the device is still valid */ + assert(d != NULL); + assert(index < d->num_profiles); + return 0; +} + static int test_fake_probe(struct ratbag_device *device) { @@ -96,7 +88,11 @@ test_probe(struct ratbag_device *device, void *data) ratbag_set_drv_data(device, test_device); ratbag_device_init_profiles(device, test_device->num_profiles, + test_device->num_resolutions, test_device->num_buttons); + if (test_device->num_profiles > 1) + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS); + return 0; } @@ -120,8 +116,7 @@ struct ratbag_driver test_driver = { .remove = test_remove, .read_profile = test_read_profile, .write_profile = test_write_profile, - .set_active_profile = NULL, - .has_capability = test_has_capability, + .set_active_profile = test_set_active_profile, .read_button = NULL, .write_button = NULL, .write_resolution_dpi = NULL, diff --git a/src/libratbag-private.h b/src/libratbag-private.h index 2eff7321..c6e5b9ca 100644 --- a/src/libratbag-private.h +++ b/src/libratbag-private.h @@ -89,6 +89,7 @@ struct ratbag_device { struct input_id ids; struct ratbag_driver *driver; struct ratbag *ratbag; + unsigned long capabilities; unsigned num_profiles; struct list profiles; @@ -162,17 +163,6 @@ struct ratbag_driver { */ int (*set_default_profile)(struct ratbag_device *device, unsigned int index); - /** - * This should return a boolean whether or not the device - * supports the given capability. - * - * In most cases, the .probe() should store a list of capabilities - * for each device, but most of the time, it can be statically - * stored. - */ - int (*has_capability)(const struct ratbag_device *device, - enum ratbag_device_capability cap); - /** * For the given button, fill in the struct ratbag_button * with the available information. @@ -208,7 +198,6 @@ struct ratbag_driver { struct list link; }; -#define MAX_RESOLUTIONS 10 struct ratbag_resolution{ struct ratbag_profile *profile; int refcount; @@ -232,7 +221,7 @@ struct ratbag_profile { void *drv_data; void *user_data; struct { - struct ratbag_resolution modes[MAX_RESOLUTIONS]; + struct ratbag_resolution *modes; unsigned int num_modes; } resolution; @@ -332,8 +321,13 @@ ratbag_get_drv_data(struct ratbag_device *device) int ratbag_device_init_profiles(struct ratbag_device *device, unsigned int num_profiles, + unsigned int num_resolutions, unsigned int num_buttons); +void +ratbag_device_set_capability(struct ratbag_device *device, + enum ratbag_device_capability cap); + static inline void ratbag_profile_set_drv_data(struct ratbag_profile *profile, void *drv_data) { diff --git a/src/libratbag-test.h b/src/libratbag-test.h index a5573917..3dbd1ffd 100644 --- a/src/libratbag-test.h +++ b/src/libratbag-test.h @@ -43,7 +43,6 @@ struct ratbag_test_resolution { }; struct ratbag_test_profile { - unsigned int num_resolutions; struct ratbag_test_button buttons[RATBAG_TEST_MAX_BUTTONS]; struct ratbag_test_resolution resolutions[RATBAG_TEST_MAX_RESOLUTIONS]; bool active; @@ -52,6 +51,7 @@ struct ratbag_test_profile { struct ratbag_test_device { unsigned int num_profiles; + unsigned int num_resolutions; unsigned int num_buttons; struct ratbag_test_profile profiles[RATBAG_TEST_MAX_PROFILES]; void (*destroyed)(struct ratbag_device *device, void *data); diff --git a/src/libratbag.c b/src/libratbag.c index c4c27f2c..bfd7068b 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -564,6 +564,7 @@ ratbag_profile_init_buttons(struct ratbag_profile *profile, unsigned int count) static struct ratbag_profile * ratbag_create_profile(struct ratbag_device *device, unsigned int index, + unsigned int num_resolutions, unsigned int num_buttons) { struct ratbag_profile *profile; @@ -573,13 +574,15 @@ ratbag_create_profile(struct ratbag_device *device, profile->refcount = 0; profile->device = device; profile->index = index; + profile->resolution.modes = zalloc(num_resolutions * + sizeof(*profile->resolution.modes)); + profile->resolution.num_modes = num_resolutions; list_insert(&device->profiles, &profile->link); list_init(&profile->buttons); - for (i = 0; i < MAX_RESOLUTIONS; i++) + for (i = 0; i < num_resolutions; i++) ratbag_resolution_init(profile, i, 0, 0, 0); - profile->resolution.num_modes = 1; assert(device->driver->read_profile); device->driver->read_profile(profile, index); @@ -592,16 +595,28 @@ ratbag_create_profile(struct ratbag_device *device, int ratbag_device_init_profiles(struct ratbag_device *device, unsigned int num_profiles, + unsigned int num_resolutions, unsigned int num_buttons) { unsigned int i; for (i = 0; i < num_profiles; i++) { - ratbag_create_profile(device, i, num_buttons); + ratbag_create_profile(device, i, num_resolutions, num_buttons); } device->num_profiles = num_profiles; + if (num_profiles > 1) { + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE); + + /* having more than one profile means we can remap the buttons + * at least */ + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY); + } + + if (num_resolutions > 1) + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION); + return 0; } @@ -626,7 +641,7 @@ ratbag_profile_destroy(struct ratbag_profile *profile) list_for_each_safe(button, next, &profile->buttons, link) ratbag_button_destroy(button); - /* Resolution is a fixed list of structs, no freeing required */ + free(profile->resolution.modes); list_remove(&profile->link); free(profile); @@ -690,12 +705,21 @@ ratbag_device_get_num_buttons(struct ratbag_device *device) return device->num_buttons; } +void +ratbag_device_set_capability(struct ratbag_device *device, + enum ratbag_device_capability cap) +{ + device->capabilities |= (1UL << cap); +} + LIBRATBAG_EXPORT int ratbag_device_has_capability(const struct ratbag_device *device, enum ratbag_device_capability cap) { - assert(device->driver->has_capability); - return device->driver->has_capability(device, cap); + if (cap == RATBAG_DEVICE_CAP_NONE) + abort(); + + return !!(device->capabilities & (1UL << cap)); } LIBRATBAG_EXPORT int diff --git a/test/test-device.c b/test/test-device.c index 455e8906..776dc15e 100644 --- a/test/test-device.c +++ b/test/test-device.c @@ -51,10 +51,10 @@ device_destroyed(struct ratbag_device *device, void *data) */ const struct ratbag_test_device sane_device = { .num_profiles = 3, + .num_resolutions = 3, .num_buttons = 1, .profiles = { { - .num_resolutions = 3, .resolutions = { { .xres = 100, .yres = 200, .hz = 1000 }, { .xres = 200, .yres = 300, .hz = 1000 }, @@ -64,7 +64,6 @@ const struct ratbag_test_device sane_device = { .dflt = false, }, { - .num_resolutions = 3, .resolutions = { { .xres = 1100, .yres = 1200, .hz = 2000 }, { .xres = 1200, .yres = 1300, .hz = 2000 }, @@ -74,7 +73,6 @@ const struct ratbag_test_device sane_device = { .dflt = true, }, { - .num_resolutions = 3, .resolutions = { { .xres = 2100, .yres = 2200, .hz = 3000 }, { .xres = 2200, .yres = 2300, .hz = 3000 }, @@ -330,10 +328,10 @@ START_TEST(device_resolutions) struct ratbag_test_device td = { .num_profiles = 3, + .num_resolutions = 3, .num_buttons = 1, .profiles = { { - .num_resolutions = 3, .resolutions = { { .xres = 100, .yres = 200, .hz = 1000 }, { .xres = 200, .yres = 300, .hz = 1000, .active = true }, @@ -342,7 +340,6 @@ START_TEST(device_resolutions) .active = true, }, { - .num_resolutions = 3, .resolutions = { { .xres = 1100, .yres = 1200, .hz = 2000 }, { .xres = 1200, .yres = 1300, .hz = 2000, .active = true }, @@ -350,7 +347,6 @@ START_TEST(device_resolutions) }, }, { - .num_resolutions = 3, .resolutions = { { .xres = 2100, .yres = 2200, .hz = 3000 }, { .xres = 2200, .yres = 2300, .hz = 3000, .active = true }, @@ -429,9 +425,9 @@ START_TEST(device_resolutions_num_0) struct ratbag_test_device td = { .num_profiles = 1, .num_buttons = 1, + .num_resolutions = 0, /* failure trigger */ .profiles = { { - .num_resolutions = 0, /* failure trigger */ .active = true, }, },