diff --git a/src/driver-etekcity.c b/src/driver-etekcity.c index 012ecd58..efd6af51 100644 --- a/src/driver-etekcity.c +++ b/src/driver-etekcity.c @@ -430,6 +430,7 @@ etekcity_read_button(struct ratbag_button *button) { const struct ratbag_button_action *action; struct ratbag_device *device; + struct ratbag_button_macro *m; struct etekcity_macro *macro; struct etekcity_data *drv_data; uint8_t *buf; @@ -464,7 +465,7 @@ etekcity_read_button(struct ratbag_button *button) button->index, button->profile->index, rc < 0 ? strerror(-rc) : "not read enough", rc); } else { - ratbag_button_set_macro(button, macro->name); + m = ratbag_button_macro_new(macro->name); log_raw(device->ratbag, "macro on button %d of profile %d is named '%s', and contains %d events:\n", button->index, button->profile->index, @@ -472,7 +473,7 @@ etekcity_read_button(struct ratbag_button *button) for (j = 0; j < macro->length; j++) { unsigned int keycode = ratbag_hidraw_get_keycode_from_keyboard_usage(device, macro->keys[j].keycode); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, j, macro->keys[j].flag & 0x80 ? RATBAG_MACRO_EVENT_KEY_RELEASED : RATBAG_MACRO_EVENT_KEY_PRESSED, keycode); @@ -481,6 +482,8 @@ etekcity_read_button(struct ratbag_button *button) libevdev_event_code_get_name(EV_KEY, keycode), macro->keys[j].flag & 0x80 ? "released" : "pressed"); } + ratbag_button_copy_macro(button, m); + ratbag_button_macro_unref(m); } msleep(10); } diff --git a/src/driver-hidpp10.c b/src/driver-hidpp10.c index 59a6c823..0dfd8afc 100644 --- a/src/driver-hidpp10.c +++ b/src/driver-hidpp10.c @@ -76,6 +76,7 @@ hidpp10drv_read_macro(struct ratbag_button *button, union hidpp10_button *binding) { struct ratbag_device *device = button->profile->device; + struct ratbag_button_macro *m; const char *name; union hidpp10_macro_data *macro; unsigned int i, keycode; @@ -84,13 +85,13 @@ hidpp10drv_read_macro(struct ratbag_button *button, macro = profile->macros[binding->macro.address]; name = binding->macro.address > 1 ? (const char *)profile->macro_names[binding->macro.address - 2] : ""; - ratbag_button_set_macro(button, name); i = 0; + m = ratbag_button_macro_new(name); while (macro && macro->any.type != HIDPP10_MACRO_END && i < MAX_MACRO_EVENTS) { switch (macro->any.type) { case HIDPP10_MACRO_DELAY: - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, macro->delay.time); @@ -99,11 +100,11 @@ hidpp10drv_read_macro(struct ratbag_button *button, case HIDPP10_MACRO_KEY_PRESS: keycode = ratbag_hidraw_get_keycode_from_keyboard_usage(device, macro->key.key); if (!delay) - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, 1); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_KEY_PRESSED, keycode); @@ -112,11 +113,11 @@ hidpp10drv_read_macro(struct ratbag_button *button, case HIDPP10_MACRO_KEY_RELEASE: keycode = ratbag_hidraw_get_keycode_from_keyboard_usage(device, macro->key.key); if (!delay) - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, 1); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_KEY_RELEASED, keycode); @@ -125,11 +126,11 @@ hidpp10drv_read_macro(struct ratbag_button *button, case HIDPP10_MACRO_MOD_PRESS: keycode = hidpp10drv_read_macro_modifier(device, macro); if (!delay) - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, 1); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_KEY_PRESSED, keycode); @@ -138,11 +139,11 @@ hidpp10drv_read_macro(struct ratbag_button *button, case HIDPP10_MACRO_MOD_RELEASE: keycode = hidpp10drv_read_macro_modifier(device, macro); if (!delay) - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, 1); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_KEY_RELEASED, keycode); @@ -151,6 +152,9 @@ hidpp10drv_read_macro(struct ratbag_button *button, } macro++; } + + ratbag_button_copy_macro(button, m); + ratbag_button_macro_unref(m); } static void diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index 3598d7c1..ba333cb2 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -123,32 +123,34 @@ hidpp20drv_read_macro_8100(struct ratbag_button *button, union hidpp20_button_binding *binding) { struct ratbag_device *device = button->profile->device; + struct ratbag_button_macro *m; union hidpp20_macro_data *macro; unsigned int i, keycode; bool delay = true; macro = profile->macros[binding->macro.page]; - ratbag_button_set_macro(button, "macro"); i = 0; + m = ratbag_button_macro_new("macro"); + while (macro && macro->any.type != HIDPP20_MACRO_END && i < MAX_MACRO_EVENTS) { switch (macro->any.type) { case HIDPP20_MACRO_DELAY: - ratbag_button_set_macro_event(button, - i++, - RATBAG_MACRO_EVENT_WAIT, - macro->delay.time); + ratbag_button_macro_set_event(m, + i++, + RATBAG_MACRO_EVENT_WAIT, + macro->delay.time); delay = true; break; case HIDPP20_MACRO_KEY_PRESS: keycode = hidpp20drv_read_macro_key_8100(device, macro); if (!delay) - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, 1); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_KEY_PRESSED, keycode); @@ -157,11 +159,11 @@ hidpp20drv_read_macro_8100(struct ratbag_button *button, case HIDPP20_MACRO_KEY_RELEASE: keycode = hidpp20drv_read_macro_key_8100(device, macro); if (!delay) - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_WAIT, 1); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i++, RATBAG_MACRO_EVENT_KEY_RELEASED, keycode); @@ -170,6 +172,9 @@ hidpp20drv_read_macro_8100(struct ratbag_button *button, } macro++; } + + ratbag_button_copy_macro(button, m); + ratbag_button_macro_unref(m); } static void diff --git a/src/driver-roccat.c b/src/driver-roccat.c index ef563265..ec702a0e 100644 --- a/src/driver-roccat.c +++ b/src/driver-roccat.c @@ -532,6 +532,7 @@ roccat_read_button(struct ratbag_button *button) ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO); if (action && action->type == RATBAG_BUTTON_ACTION_TYPE_MACRO) { + struct ratbag_button_macro *m = NULL; roccat_set_config_profile(device, button->profile->index, @@ -566,7 +567,7 @@ roccat_read_button(struct ratbag_button *button) goto out_macro; } - ratbag_button_set_macro(button, macro->name); + m = ratbag_button_macro_new(macro->name); log_raw(device->ratbag, "macro on button %d of profile %d is named '%s', and contains %d events:\n", button->index, button->profile->index, @@ -574,7 +575,7 @@ roccat_read_button(struct ratbag_button *button) for (j = 0; j < macro->length; j++) { unsigned int keycode = ratbag_hidraw_get_keycode_from_keyboard_usage(device, macro->keys[j].keycode); - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, j * 2, macro->keys[j].flag & 0x01 ? RATBAG_MACRO_EVENT_KEY_PRESSED : RATBAG_MACRO_EVENT_KEY_RELEASED, keycode); @@ -582,7 +583,7 @@ roccat_read_button(struct ratbag_button *button) time = macro->keys[j].time; else time = macro->keys[j].flag & 0x01 ? 10 : 50; - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, j * 2 + 1, RATBAG_MACRO_EVENT_WAIT, time); @@ -592,9 +593,11 @@ roccat_read_button(struct ratbag_button *button) libevdev_event_code_get_name(EV_KEY, keycode), macro->keys[j].flag & 0x80 ? "released" : "pressed"); } + ratbag_button_copy_macro(button, m); } out_macro: msleep(10); + ratbag_button_macro_unref(m); } } diff --git a/src/libratbag-private.h b/src/libratbag-private.h index a72d7077..041a8e68 100644 --- a/src/libratbag-private.h +++ b/src/libratbag-private.h @@ -250,6 +250,11 @@ struct ratbag_macro { struct ratbag_macro_event events[MAX_MACRO_EVENTS]; }; +struct ratbag_button_macro { + int refcount; + struct ratbag_macro macro; +}; + struct ratbag_button_action { enum ratbag_button_action_type type; union ratbag_btn_action { @@ -424,13 +429,17 @@ const char * ratbag_device_get_udev_property(const struct ratbag_device* device, const char *name); -struct ratbag_driver * -ratbag_find_driver(struct ratbag_device *device, - const struct input_id *dev_id, - struct ratbag_test_device *test_device); +bool +ratbag_assign_driver(struct ratbag_device *device, + const struct input_id *dev_id, + struct ratbag_test_device *test_device); void ratbag_register_driver(struct ratbag *ratbag, struct ratbag_driver *driver); +void +ratbag_button_copy_macro(struct ratbag_button *button, + const struct ratbag_button_macro *macro); + #endif /* LIBRATBAG_PRIVATE_H */ diff --git a/src/libratbag-test.c b/src/libratbag-test.c index 5660e23a..79393054 100644 --- a/src/libratbag-test.c +++ b/src/libratbag-test.c @@ -71,7 +71,7 @@ ratbag_device_new_test_device(struct ratbag *ratbag, device = ratbag_device_new(ratbag, NULL, "Test device", &id); - if (!ratbag_find_driver(device, &device->ids, test_device)) { + if (!ratbag_assign_driver(device, &device->ids, test_device)) { ratbag_device_destroy(device); return NULL; } diff --git a/src/libratbag.c b/src/libratbag.c index c8929f70..b62038cb 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -37,6 +37,23 @@ #include "libratbag-private.h" #include "libratbag-util.h" +static enum ratbag_error_code +error_code(enum ratbag_error_code code) +{ + switch(code) { + case RATBAG_SUCCESS: + case RATBAG_ERROR_DEVICE: + case RATBAG_ERROR_CAPABILITY: + case RATBAG_ERROR_VALUE: + case RATBAG_ERROR_SYSTEM: + case RATBAG_ERROR_IMPLEMENTATION: + break; + default: + assert(!"Invalid error code. This is a library bug."); + } + return code; +} + static void ratbag_profile_destroy(struct ratbag_profile *profile); static void @@ -266,10 +283,10 @@ out: return rc; } -struct ratbag_driver * -ratbag_find_driver(struct ratbag_device *device, - const struct input_id *dev_id, - struct ratbag_test_device *test_device) +bool +ratbag_assign_driver(struct ratbag_device *device, + const struct input_id *dev_id, + struct ratbag_test_device *test_device) { struct ratbag *ratbag = device->ratbag; struct ratbag_driver *driver; @@ -279,7 +296,7 @@ ratbag_find_driver(struct ratbag_device *device, if (!test_device) { driver_name = udev_prop_value(device->udev_device, "RATBAG_DRIVER"); if (!driver_name) - return NULL; + return false; } else { driver_name = "test_driver"; } @@ -294,7 +311,7 @@ ratbag_find_driver(struct ratbag_device *device, if (!device->driver) { log_error(ratbag, "%s: driver '%s' does not exist\n", device->name, driver_name); - return NULL; + return false; } if (test_device) @@ -303,21 +320,19 @@ ratbag_find_driver(struct ratbag_device *device, rc = device->driver->probe(device); if (rc == 0) { if (!ratbag_sanity_check_device(device)) { - return NULL; + return false; } else { log_debug(ratbag, "driver match found: %s\n", driver->name); - return device->driver; + return true; } } device->driver = NULL; - if (rc == -ENODEV) { + if (rc == -ENODEV) log_error(ratbag, "%s: no hidraw device found\n", device->name); - return NULL; - } - return NULL; + return false; } static inline char* @@ -353,52 +368,44 @@ get_product_id(struct udev_device *device, struct input_id *id) return 0; } -LIBRATBAG_EXPORT struct ratbag_device* +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_device_new_from_udev_device(struct ratbag *ratbag, - struct udev_device *udev_device) + struct udev_device *udev_device, + struct ratbag_device **device_out) { struct ratbag_device *device = NULL; - struct ratbag_driver *driver; - char *name = NULL; + enum ratbag_error_code error = RATBAG_ERROR_DEVICE; + _cleanup_free_ char *name = NULL; struct input_id id; - if (!ratbag) { - fprintf(stderr, "ratbag is NULL\n"); - return NULL; - } - - if (!udev_device) { - log_bug_client(ratbag, "udev device is NULL.\n"); - return NULL; - } + assert(ratbag != NULL); + assert(udev_device != NULL); + assert(device_out != NULL); if (get_product_id(udev_device, &id) != 0) goto out_err; name = get_device_name(udev_device); - if (!name) { - errno = ENOMEM; + if (!name) goto out_err; - } device = ratbag_device_new(ratbag, udev_device, name, &id); - free(name); - if (!device) goto out_err; - driver = ratbag_find_driver(device, &device->ids, NULL); - if (!driver) { - errno = ENOTSUP; + if (!ratbag_assign_driver(device, &device->ids, NULL)) goto out_err; - } - return device; + error = RATBAG_SUCCESS; out_err: - ratbag_device_destroy(device); - return NULL; + if (error != RATBAG_SUCCESS) + ratbag_device_destroy(device); + else + *device_out = device; + + return error_code(error); } LIBRATBAG_EXPORT struct ratbag_device * @@ -464,10 +471,9 @@ ratbag_create_context(const struct ratbag_interface *interface, { struct ratbag *ratbag; - if (interface == NULL || - interface->open_restricted == NULL || - interface->close_restricted == NULL) - return NULL; + assert(interface != NULL); + assert(interface->open_restricted != NULL); + assert(interface->close_restricted != NULL); ratbag = zalloc(sizeof(*ratbag)); ratbag->refcount = 1; @@ -653,8 +659,10 @@ ratbag_device_get_profile(struct ratbag_device *device, unsigned int index) { struct ratbag_profile *profile; - if (index >= ratbag_device_get_num_profiles(device)) + if (index >= ratbag_device_get_num_profiles(device)) { + log_bug_client(device->ratbag, "Requested invalid profile %d\n", index); return NULL; + } list_for_each(profile, &device->profiles, link) { if (profile->index == index) @@ -701,31 +709,31 @@ ratbag_device_has_capability(const struct ratbag_device *device, return !!(device->capabilities & (1UL << cap)); } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_profile_set_active(struct ratbag_profile *profile) { struct ratbag_device *device = profile->device; struct ratbag_profile *p; int rc; + if (!ratbag_device_has_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE)) + return RATBAG_ERROR_CAPABILITY; + assert(device->driver->write_profile); rc = device->driver->write_profile(profile); if (rc) - return rc; - - if (ratbag_device_has_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE)) { - assert(device->driver->set_active_profile); - rc = device->driver->set_active_profile(device, profile->index); - } + return RATBAG_ERROR_DEVICE; + assert(device->driver->set_active_profile); + rc = device->driver->set_active_profile(device, profile->index); if (rc) - return rc; + return RATBAG_ERROR_DEVICE; list_for_each(p, &device->profiles, link) p->is_active = false; profile->is_active = true; - return rc; + return RATBAG_SUCCESS; } LIBRATBAG_EXPORT unsigned int @@ -740,8 +748,11 @@ ratbag_profile_get_resolution(struct ratbag_profile *profile, unsigned int idx) struct ratbag_resolution *res; unsigned max = ratbag_profile_get_num_resolutions(profile); - if (idx >= max) + if (idx >= max) { + log_bug_client(profile->device->ratbag, + "Requested invalid resolution %d\n", idx); return NULL; + } res = &profile->resolution.modes[idx]; @@ -787,42 +798,48 @@ ratbag_resolution_has_capability(struct ratbag_resolution *resolution, return !!(resolution->capabilities & (1 << cap)); } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_resolution_set_dpi(struct ratbag_resolution *resolution, unsigned int dpi) { struct ratbag_profile *profile = resolution->profile; + int rc; + resolution->dpi_x = dpi; resolution->dpi_y = dpi; assert(profile->device->driver->write_resolution_dpi); - return profile->device->driver->write_resolution_dpi(resolution, dpi, dpi); + rc = profile->device->driver->write_resolution_dpi(resolution, dpi, dpi); + + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_resolution_set_dpi_xy(struct ratbag_resolution *resolution, unsigned int x, unsigned int y) { struct ratbag_profile *profile = resolution->profile; + int rc; if (!ratbag_resolution_has_capability(resolution, RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION)) - return -1; + return RATBAG_ERROR_CAPABILITY; if ((x == 0 && y != 0) || (x != 0 && y == 0)) - return -1; + return RATBAG_ERROR_VALUE; assert(profile->device->driver->write_resolution_dpi); - return profile->device->driver->write_resolution_dpi(resolution, x, y); + rc = profile->device->driver->write_resolution_dpi(resolution, x, y); + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_resolution_set_report_rate(struct ratbag_resolution *resolution, unsigned int hz) { resolution->hz = hz; /* FIXME: call into the driver */ - return 0; + return RATBAG_ERROR_IMPLEMENTATION; } LIBRATBAG_EXPORT int @@ -855,12 +872,12 @@ ratbag_resolution_is_active(const struct ratbag_resolution *resolution) return resolution->is_active; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_resolution_set_active(struct ratbag_resolution *resolution) { resolution->is_active = true; /* FIXME: call into the driver */ - return 0; + return RATBAG_ERROR_IMPLEMENTATION; } @@ -870,12 +887,12 @@ ratbag_resolution_is_default(const struct ratbag_resolution *resolution) return resolution->is_default; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_resolution_set_default(struct ratbag_resolution *resolution) { resolution->is_default = true; /* FIXME: call into the driver */ - return 0; + return RATBAG_ERROR_IMPLEMENTATION; } LIBRATBAG_EXPORT struct ratbag_button* @@ -885,8 +902,10 @@ ratbag_profile_get_button(struct ratbag_profile *profile, struct ratbag_device *device = profile->device; struct ratbag_button *button; - if (index >= ratbag_device_get_num_buttons(device)) + if (index >= ratbag_device_get_num_buttons(device)) { + log_bug_client(device->ratbag, "Requested invalid button %d\n", index); return NULL; + } list_for_each(button, &profile->buttons, link) { if (button->index == index) @@ -937,14 +956,14 @@ ratbag_button_get_button(struct ratbag_button *button) return button->action.action.button; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_button_set_button(struct ratbag_button *button, unsigned int btn) { struct ratbag_button_action action; int rc; if (!button->profile->device->driver->write_button) - return -ENOTSUP; + return RATBAG_ERROR_CAPABILITY; action.type = RATBAG_BUTTON_ACTION_TYPE_BUTTON; action.action.button = btn; @@ -954,7 +973,7 @@ ratbag_button_set_button(struct ratbag_button *button, unsigned int btn) if (rc == 0) button->action = action; - return rc; + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; } LIBRATBAG_EXPORT enum ratbag_button_action_special @@ -966,7 +985,7 @@ ratbag_button_get_special(struct ratbag_button *button) return button->action.action.special; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_button_set_special(struct ratbag_button *button, enum ratbag_button_action_special act) { @@ -976,7 +995,7 @@ ratbag_button_set_special(struct ratbag_button *button, /* FIXME: range checks */ if (!button->profile->device->driver->write_button) - return -1; + return RATBAG_ERROR_CAPABILITY; action.type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL; action.action.special = act; @@ -986,7 +1005,7 @@ ratbag_button_set_special(struct ratbag_button *button, if (rc == 0) button->action = action; - return rc; + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; } LIBRATBAG_EXPORT unsigned int @@ -1002,7 +1021,7 @@ ratbag_button_get_key(struct ratbag_button *button, return button->action.action.key.key; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_button_set_key(struct ratbag_button *button, unsigned int key, unsigned int *modifiers, @@ -1014,7 +1033,7 @@ ratbag_button_set_key(struct ratbag_button *button, /* FIXME: range checks */ if (!button->profile->device->driver->write_button) - return -1; + return RATBAG_ERROR_CAPABILITY; /* FIXME: modifiers */ @@ -1025,17 +1044,17 @@ ratbag_button_set_key(struct ratbag_button *button, if (rc == 0) button->action = action; - return rc; + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; } -LIBRATBAG_EXPORT int +LIBRATBAG_EXPORT enum ratbag_error_code ratbag_button_disable(struct ratbag_button *button) { struct ratbag_button_action action; int rc; if (!button->profile->device->driver->write_button) - return -1; + return RATBAG_ERROR_CAPABILITY; action.type = RATBAG_BUTTON_ACTION_TYPE_NONE; rc = button->profile->device->driver->write_button(button, &action); @@ -1043,7 +1062,7 @@ ratbag_button_disable(struct ratbag_button *button) if (rc == 0) button->action = action; - return rc; + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; } LIBRATBAG_EXPORT struct ratbag_button * @@ -1142,8 +1161,25 @@ ratbag_resolution_get_user_data(const struct ratbag_resolution *ratbag_resolutio return ratbag_resolution->userdata; } -LIBRATBAG_EXPORT int -ratbag_button_set_macro(struct ratbag_button *button, const char *name) +LIBRATBAG_EXPORT struct ratbag_button_macro * +ratbag_button_get_macro(struct ratbag_button *button) +{ + struct ratbag_button_macro *macro; + + if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO) + return NULL; + + macro = ratbag_button_macro_new(button->action.macro->name); + memcpy(macro->macro.events, + button->action.macro->events, + sizeof(macro->macro.events)); + + return macro; +} + +void +ratbag_button_copy_macro(struct ratbag_button *button, + const struct ratbag_button_macro *macro) { if (!button->action.macro) button->action.macro = zalloc(sizeof(struct ratbag_macro)); @@ -1154,24 +1190,36 @@ ratbag_button_set_macro(struct ratbag_button *button, const char *name) } button->action.type = RATBAG_BUTTON_ACTION_TYPE_MACRO; - button->action.macro->name = strdup_safe(name); - - return 0; + memcpy(button->action.macro->events, + macro->macro.events, + sizeof(macro->macro.events)); + button->action.macro->name = strdup_safe(macro->macro.name); + button->action.macro->group = strdup_safe(macro->macro.group); } -LIBRATBAG_EXPORT int -ratbag_button_set_macro_event(struct ratbag_button *button, +LIBRATBAG_EXPORT enum ratbag_error_code +ratbag_button_set_macro(struct ratbag_button *button, + const struct ratbag_button_macro *macro) +{ + int rc; + + ratbag_button_copy_macro(button, macro); + + rc = button->profile->device->driver->write_button(button, &button->action); + + return rc == 0 ? RATBAG_SUCCESS : RATBAG_ERROR_DEVICE; +} + +LIBRATBAG_EXPORT enum ratbag_error_code +ratbag_button_macro_set_event(struct ratbag_button_macro *m, unsigned int index, enum ratbag_macro_event_type type, unsigned int data) { - struct ratbag_macro *macro; + struct ratbag_macro *macro = &m->macro; - if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO || - index >= MAX_MACRO_EVENTS) - return -EINVAL; - - macro = button->action.macro; + if (index >= MAX_MACRO_EVENTS) + return RATBAG_ERROR_VALUE; switch (type) { case RATBAG_MACRO_EVENT_KEY_PRESSED: @@ -1187,39 +1235,28 @@ ratbag_button_set_macro_event(struct ratbag_button *button, macro->events[index].type = type; break; default: - return -EINVAL; + return RATBAG_ERROR_VALUE; } return 0; } -LIBRATBAG_EXPORT int -ratbag_button_write_macro(struct ratbag_button *button) -{ - return button->profile->device->driver->write_button(button, &button->action); - -} - LIBRATBAG_EXPORT enum ratbag_macro_event_type -ratbag_button_get_macro_event_type(struct ratbag_button *button, unsigned int index) +ratbag_button_macro_get_event_type(struct ratbag_button_macro *macro, unsigned int index) { - if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO || - index >= MAX_MACRO_EVENTS) + if (index >= MAX_MACRO_EVENTS) return RATBAG_MACRO_EVENT_INVALID; - return button->action.macro->events[index].type; + return macro->macro.events[index].type; } LIBRATBAG_EXPORT int -ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int index) +ratbag_button_macro_get_event_key(struct ratbag_button_macro *m, unsigned int index) { - struct ratbag_macro *macro; + struct ratbag_macro *macro = &m->macro; - if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO || - index >= MAX_MACRO_EVENTS) - return -EINVAL; - - macro = button->action.macro; + if (index >= MAX_MACRO_EVENTS) + return 0; if (macro->events[index].type != RATBAG_MACRO_EVENT_KEY_PRESSED && macro->events[index].type != RATBAG_MACRO_EVENT_KEY_RELEASED) @@ -1229,27 +1266,72 @@ ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int ind } LIBRATBAG_EXPORT int -ratbag_button_get_macro_event_timeout(struct ratbag_button *button, unsigned int index) +ratbag_button_macro_get_event_timeout(struct ratbag_button_macro *m, + unsigned int index) { - struct ratbag_macro *macro; + struct ratbag_macro *macro = &m->macro; - if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO || - index >= MAX_MACRO_EVENTS) - return -EINVAL; - - macro = button->action.macro; + if (index >= MAX_MACRO_EVENTS) + return 0; if (macro->events[index].type != RATBAG_MACRO_EVENT_WAIT) - return -EINVAL; + return 0; return macro->events[index].event.timeout; } -LIBRATBAG_EXPORT const char * -ratbag_button_get_macro_name(struct ratbag_button *button) +LIBRATBAG_EXPORT unsigned int +ratbag_button_macro_get_num_events(struct ratbag_button_macro *macro) { - if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO) + return MAX_MACRO_EVENTS; +} + +LIBRATBAG_EXPORT const char * +ratbag_button_macro_get_name(struct ratbag_button_macro *macro) +{ + return macro->macro.name; +} + +static void +ratbag_button_macro_destroy(struct ratbag_button_macro *macro) +{ + assert(macro->refcount == 0); + free(macro->macro.name); + free(macro->macro.group); + free(macro); +} + +LIBRATBAG_EXPORT struct ratbag_button_macro * +ratbag_button_macro_ref(struct ratbag_button_macro *macro) +{ + assert(macro->refcount < INT_MAX); + + macro->refcount++; + return macro; +} + +LIBRATBAG_EXPORT struct ratbag_button_macro * +ratbag_button_macro_unref(struct ratbag_button_macro *macro) +{ + if (macro == NULL) return NULL; - return button->action.macro->name; + assert(macro->refcount > 0); + macro->refcount--; + if (macro->refcount == 0) + ratbag_button_macro_destroy(macro); + + return NULL; +} + +LIBRATBAG_EXPORT struct ratbag_button_macro * +ratbag_button_macro_new(const char *name) +{ + struct ratbag_button_macro *macro; + + macro = zalloc(sizeof *macro); + macro->refcount = 1; + macro->macro.name = strdup_safe(name); + + return macro; } diff --git a/src/libratbag.h b/src/libratbag.h index 2606288e..21f4b122 100644 --- a/src/libratbag.h +++ b/src/libratbag.h @@ -125,6 +125,59 @@ struct ratbag_button; */ struct ratbag_resolution; +/** + * @ingroup button + * @struct ratbag_macro + * + * Represents a macro that can be assigned to a button. + * + * This struct is refcounted, use ratbag_button_macro_ref() and + * ratbag_button_macro_unref(). + */ +struct ratbag_button_macro; + +/** + * @ingroup base + * + * Error codes used by libratbag. + */ +enum ratbag_error_code { + RATBAG_SUCCESS = 0, + + /** + * An error occured on the device. Either the device is not a + * libratbag device or communication with the device failed. + */ + RATBAG_ERROR_DEVICE = -1000, + + /** + * Insufficient capabilities. This error occurs when a requestd change is + * beyond the device's capabilities. + */ + RATBAG_ERROR_CAPABILITY = -1001, + + /** + * Invalid value or value range. The provided value or value range + * is outside of the legal or supported range. + */ + RATBAG_ERROR_VALUE = -1002, + + /** + * A low-level system error has occured, e.g. a failure to access + * files that should be there. This error is usually unrecoverable + * and libratbag will print a log message with details about the + * error. + */ + RATBAG_ERROR_SYSTEM = -1003, + + /** + * Implementation bug, either in libratbag or in the caller. This + * error is usually unrecoverable and libratbag will print a log + * message with details about the + * error. + */ + RATBAG_ERROR_IMPLEMENTATION = -1004, +}; /** * @ingroup base @@ -325,12 +378,18 @@ ratbag_unref(struct ratbag *ratbag); * The device is refcounted with an initial value of at least 1. * Use ratbag_device_unref() to release the device. * - * @return A new device based on the udev device, or NULL in case of - * failure. + * @param ratbag A previously initialized ratbag context + * @param udev_device The udev device that points at the device + * @param device Set to a new device based on the udev device. + * + * @return 0 on success or the error. + * @retval RATBAG_ERROR_DEVICE The given device does not exist or is not + * supported by libratbag. */ -struct ratbag_device* +enum ratbag_error_code ratbag_device_new_from_udev_device(struct ratbag *ratbag, - struct udev_device *device); + struct udev_device *udev_device, + struct ratbag_device **device); /** * @ingroup device @@ -600,9 +659,9 @@ ratbag_profile_is_active(struct ratbag_profile *profile); * * @param profile The profile to make the active profile. * - * @return 0 on success or nonzero otherwise. + * @return 0 on success or an error code otherwise */ -int +enum ratbag_error_code ratbag_profile_set_active(struct ratbag_profile *profile); /** @@ -740,9 +799,9 @@ ratbag_resolution_has_capability(struct ratbag_resolution *resolution, * @param resolution A previously initialized ratbag resolution * @param dpi Set to the resolution in dpi, 0 to disable * - * @return zero on success, non-zero otherwise + * @return zero on success or an error code on failure */ -int +enum ratbag_error_code ratbag_resolution_set_dpi(struct ratbag_resolution *resolution, unsigned int dpi); @@ -766,9 +825,9 @@ ratbag_resolution_set_dpi(struct ratbag_resolution *resolution, * @param x The x resolution in dpi * @param y The y resolution in dpi * - * @return zero on success, non-zero otherwise + * @return zero on success or an error code on failure */ -int +enum ratbag_error_code ratbag_resolution_set_dpi_xy(struct ratbag_resolution *resolution, unsigned int x, unsigned int y); @@ -836,9 +895,9 @@ ratbag_resolution_get_dpi_y(struct ratbag_resolution *resolution); * @param resolution A previously initialized ratbag resolution * @param hz Set to the report rate in Hz, may be 0 * - * @return zero on success, non-zero otherwise + * @return zero on success or an error code on failure */ -int +enum ratbag_error_code ratbag_resolution_set_report_rate(struct ratbag_resolution *resolution, unsigned int hz); @@ -856,7 +915,7 @@ ratbag_resolution_set_report_rate(struct ratbag_resolution *resolution, * * @param resolution A previously initialized ratbag resolution * - * @return zero on success, non-zero otherwise + * @return The report rate for this resolution in Hz */ int ratbag_resolution_get_report_rate(struct ratbag_resolution *resolution); @@ -872,9 +931,9 @@ ratbag_resolution_get_report_rate(struct ratbag_resolution *resolution); * * @param resolution A previously initialized ratbag resolution * - * @return zero on success, non-zero otherwise + * @return zero on success or an error code on failure */ -int +enum ratbag_error_code ratbag_resolution_set_active(struct ratbag_resolution *resolution); /** @@ -906,9 +965,9 @@ ratbag_resolution_is_active(const struct ratbag_resolution *resolution); * * @param resolution A previously initialized ratbag resolution * - * @return zero on success, non-zero otherwise + * @return zero on success or an error code on failure */ -int +enum ratbag_error_code ratbag_resolution_set_default(struct ratbag_resolution *resolution); /** @@ -1165,12 +1224,12 @@ ratbag_button_get_button(struct ratbag_button *button); * * @param button A previously initialized ratbag button * @param btn The logical button number to assign to this button. - * @return 0 on success or nonzero otherwise. On success, the button's + * @return 0 on success or an error code otherwise. On success, the button's * action is set to @ref RATBAG_BUTTON_ACTION_TYPE_BUTTON. * * @see ratbag_button_get_button */ -int +enum ratbag_error_code ratbag_button_set_button(struct ratbag_button *button, unsigned int btn); @@ -1197,12 +1256,12 @@ ratbag_button_get_special(struct ratbag_button *button); * * @param button A previously initialized ratbag button * @param action The special action to assign to this button. - * @return 0 on success or nonzero otherwise. On success, the button's + * @return 0 on success or an error code otherwise. On success, the button's * action is set to @ref RATBAG_BUTTON_ACTION_TYPE_SPECIAL. * * @see ratbag_button_get_button */ -int +enum ratbag_error_code ratbag_button_set_special(struct ratbag_button *button, enum ratbag_button_action_special action); @@ -1243,10 +1302,10 @@ ratbag_button_get_key(struct ratbag_button *button, * @param sz The size of the modifiers array. sz may be 0 if no modifiers * are required. * - * @return 0 on success or nonzero otherwise. On success, the button's + * @return 0 on success or an error code otherwise. On success, the button's * action is set to @ref RATBAG_BUTTON_ACTION_TYPE_KEY. */ -int +enum ratbag_error_code ratbag_button_set_key(struct ratbag_button *button, unsigned int key, unsigned int *modifiers, @@ -1257,10 +1316,10 @@ ratbag_button_set_key(struct ratbag_button *button, * * @param button A previously initialized ratbag button * - * @return 0 on success or nonzero otherwise. On success, the button's + * @return 0 on success or an error code otherwise. On success, the button's * action is set to @ref RATBAG_BUTTON_ACTION_TYPE_NONE. */ -int +enum ratbag_error_code ratbag_button_disable(struct ratbag_button *button); /** @@ -1279,101 +1338,175 @@ enum ratbag_macro_event_type { /** * @ingroup button * - * If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, - * this function returns the macro name. + * @param macro A previously initialized ratbag button macro * - * If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, - * this function returns NULL. - * - * @param button A previously initialized ratbag button - * - * @return The name of the macro associated to the button. + * @return The name of the macro */ const char * -ratbag_button_get_macro_name(struct ratbag_button *button); +ratbag_button_macro_get_name(struct ratbag_button_macro *macro); /** * @ingroup button * - * If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, - * this function returns the macro event type configured for the event at the + * @param macro A previously initialized ratbag button macro + * + * @return The maximum number of events that can be assigned to this macro + */ +unsigned int +ratbag_button_macro_get_num_events(struct ratbag_button_macro *macro); + +/** + * @ingroup button + * + * Returns the macro event type configured for the event at the * given index. * - * If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, - * this function returns @ref RATBAG_MACRO_EVENT_INVALID. + * The behavior of this function for an index equal to or greater than the + * return value of ratbag_button_macro_get_num_events() is undefined. * - * @param button A previously initialized ratbag button + * @param macro A previously initialized ratbag button macro * @param index An index of the event within the macro we are interested in. * * @return The type of the event at the given index */ enum ratbag_macro_event_type -ratbag_button_get_macro_event_type(struct ratbag_button *button, unsigned int index); +ratbag_button_macro_get_event_type(struct ratbag_button_macro *macro, + unsigned int index); /** * @ingroup button * - * If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, and if the - * event stored at the given index is @ref RATBAG_MACRO_EVENT_KEY_PRESSED or - * @ref RATBAG_MACRO_EVENT_KEY_RELEASED, this function returns the key code - * configured for the event at the given index. + * If the event stored at the given index is @ref + * RATBAG_MACRO_EVENT_KEY_PRESSED or @ref RATBAG_MACRO_EVENT_KEY_RELEASED, + * this function returns the key code configured for the event at the given + * index. * - * If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, - * or if the event stored at the given index is not - * @ref RATBAG_MACRO_EVENT_KEY_PRESSED or @ref RATBAG_MACRO_EVENT_KEY_RELEASED, - * this function returns -EINVAL. + * The behavior of this function for an index equal to or greater than the + * return value of ratbag_button_macro_get_num_events() is undefined. * - * @param button A previously initialized ratbag button + * @param macro A previously initialized ratbag button macro * @param index An index of the event within the macro we are interested in. * * @return The key of the event at the given index */ int -ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int index); +ratbag_button_macro_get_event_key(struct ratbag_button_macro*macro, + unsigned int index); /** * @ingroup button * - * If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, and if the - * event stored at the given index is @ref RATBAG_MACRO_EVENT_WAIT, this - * function returns the timeout configured for the event at the given index. + * If the event stored at the given index is @ref RATBAG_MACRO_EVENT_WAIT, + * this function returns the timeout configured for the event at the given + * index. * - * If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, - * or if the event stored at the given index is not - * @ref RATBAG_MACRO_EVENT_WAIT, this function returns -EINVAL. + * The behavior of this function for an index equal to or greater than the + * return value of ratbag_button_macro_get_num_events() is undefined. * - * @param button A previously initialized ratbag button + * @param macro A previously initialized ratbag button macro * @param index An index of the event within the macro we are interested in. * * @return The timeout of the event at the given index */ int -ratbag_button_get_macro_event_timeout(struct ratbag_button *button, unsigned int index); +ratbag_button_macro_get_event_timeout(struct ratbag_button_macro *macro, + unsigned int index); /** * @ingroup button * * Sets the button's action to @ref RATBAG_BUTTON_ACTION_TYPE_MACRO and - * allocates the required memory to store the macro. + * assigns the given macro to this button. + * + * libratbag does not use the macro struct passed in, it extracts the + * required information from the struct. Changes to the macro after a call + * to ratbag_button_set_macro() are not reflected in the device until a + * subsequent call to ratbag_button_set_macro(). + * + * @param button A previously intialized ratbag button + * @param macro A fully initialized macro + * + * @return 0 on success or nonzero otherwise */ -int -ratbag_button_set_macro(struct ratbag_button *button, const char *name); +enum ratbag_error_code +ratbag_button_set_macro(struct ratbag_button *button, + const struct ratbag_button_macro *macro); -int -ratbag_button_write_macro(struct ratbag_button *button); +/** + * @ingroup button + * + * Initialize a new button macro. + * + * The macro is refcounted with an initial value of at least 1. + * Use ratbag_button_macro_unref() to release the macro. + * + * Note that some devices have limited storage for the macro names. + * libratbag silently shortens macro names to the longest string the device + * is capable of storing. + * + * @param name The name to assign to this macro. + * + * @return An "empty" button macro + */ +struct ratbag_button_macro * +ratbag_button_macro_new(const char *name); + +/** + * @ingroup button + * + * If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, + * this function returns the current button macro. The macro is a copy of + * the one used on the device, changes to the macro are not reflected on the + * device until a subsequent call to ratbag_button_set_macro(). + * + * If a button's action is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, + * this function returns NULL. + * + * @param button A previously initialized ratbag button + */ +struct ratbag_button_macro * +ratbag_button_get_macro(struct ratbag_button *button); /** * @ingroup button * * Sets the macro's event at the given index to the given type with the * key code or timeout given. + * + * The behavior of this function for an index equal to or greater than the + * return value of ratbag_button_macro_get_num_events() is undefined. */ -int -ratbag_button_set_macro_event(struct ratbag_button *button, +enum ratbag_error_code +ratbag_button_macro_set_event(struct ratbag_button_macro *macro, unsigned int index, enum ratbag_macro_event_type type, unsigned int data); +/** + * @ingroup button + * + * Add a reference to the macro. A macro is destroyed whenever the + * reference count reaches 0. See @ref ratbag_button_macro_unref. + * + * @param macro A previously initialized valid ratbag button macro + * @return The passed ratbag macro + */ +struct ratbag_button_macro * +ratbag_button_macro_ref(struct ratbag_button_macro *macro); + +/** + * @ingroup button + * + * Dereference the ratbag button macro. When the internal refcount reaches + * zero, all resources associated with this object are released. The object + * must be considered invalid once unref is called. + * + * @param macro A previously initialized ratbag button macro + * @return Always NULL + */ +struct ratbag_button_macro * +ratbag_button_macro_unref(struct ratbag_button_macro *macro); + /** * @ingroup button * diff --git a/src/libratbag.sym b/src/libratbag.sym index 604a86ad..b076bae8 100644 --- a/src/libratbag.sym +++ b/src/libratbag.sym @@ -1,6 +1,6 @@ /* in alphabetical order! */ -LIBRATBAG_0.2.0 { +LIBRATBAG_0.3.0 { global: ratbag_create_context; ratbag_button_disable; @@ -8,22 +8,26 @@ global: ratbag_button_get_type; ratbag_button_get_button; ratbag_button_get_key; - ratbag_button_get_macro_event_type; - ratbag_button_get_macro_event_key; - ratbag_button_get_macro_event_timeout; - ratbag_button_get_macro_name; + ratbag_button_get_macro; ratbag_button_get_special; ratbag_button_get_user_data; ratbag_button_has_action_type; + ratbag_button_macro_get_event_key; + ratbag_button_macro_get_event_timeout; + ratbag_button_macro_get_event_type; + ratbag_button_macro_get_name; + ratbag_button_macro_get_num_events; + ratbag_button_macro_new; + ratbag_button_macro_ref; + ratbag_button_macro_set_event; + ratbag_button_macro_unref; ratbag_button_ref; ratbag_button_set_button; ratbag_button_set_key; ratbag_button_set_macro; - ratbag_button_set_macro_event; ratbag_button_set_special; ratbag_button_set_user_data; ratbag_button_unref; - ratbag_button_write_macro; ratbag_device_get_name; ratbag_device_get_num_buttons; ratbag_device_get_num_profiles; diff --git a/test/test-context.c b/test/test-context.c index 6f98d3c7..d3392e3d 100644 --- a/test/test-context.c +++ b/test/test-context.c @@ -26,12 +26,16 @@ #include #include #include +#include +#include #include #include #include #include "libratbag.h" +#define _unused_ __attribute__ ((unused)) + static int open_restricted(const char *path, int flags, void *user_data) { @@ -65,23 +69,40 @@ END_TEST START_TEST(context_init_bad_iface) { - struct ratbag *lr; + struct ratbag *lr _unused_; struct ratbag_interface iface = { .open_restricted = NULL, .close_restricted = NULL, }; lr = ratbag_create_context(&iface, NULL); - ck_assert(lr == NULL); + /* abort */ +} +END_TEST - iface.open_restricted = open_restricted; - lr = ratbag_create_context(&iface, NULL); - ck_assert(lr == NULL); +START_TEST(context_init_bad_iface_open) +{ + struct ratbag *lr _unused_; + struct ratbag_interface iface = { + .open_restricted = open_restricted, + .close_restricted = NULL, + }; - iface.open_restricted = NULL; - iface.close_restricted = close_restricted; lr = ratbag_create_context(&iface, NULL); - ck_assert(lr == NULL); + /* abort */ +} +END_TEST + +START_TEST(context_init_bad_iface_close) +{ + struct ratbag *lr _unused_; + struct ratbag_interface iface = { + .open_restricted = NULL, + .close_restricted = close_restricted, + }; + + lr = ratbag_create_context(&iface, NULL); + /* abort */ } END_TEST @@ -115,15 +136,19 @@ START_TEST(context_ref) END_TEST static Suite * -test_context_suite(void) +test_context_suite(bool using_valgrind) { TCase *tc; Suite *s; s = suite_create("context"); tc = tcase_create("init"); - tcase_add_test(tc, context_init_NULL); - tcase_add_test(tc, context_init_bad_iface); + if (!using_valgrind) { + tcase_add_test_raise_signal(tc, context_init_NULL, SIGABRT); + tcase_add_test_raise_signal(tc, context_init_bad_iface, SIGABRT); + tcase_add_test_raise_signal(tc, context_init_bad_iface_open, SIGABRT); + tcase_add_test_raise_signal(tc, context_init_bad_iface_close, SIGABRT); + } tcase_add_test(tc, context_init); tcase_add_test(tc, context_ref); suite_add_tcase(s, tc); @@ -136,9 +161,14 @@ int main(void) int nfailed; Suite *s; SRunner *sr; + bool using_valgrind; - s = test_context_suite(); - sr = srunner_create(s); + /* when running under valgrind we're using nofork mode, so a + * signal raised by a test will fail in valgrind */ + using_valgrind = !!getenv("USING_VALGRIND"); + + s = test_context_suite(using_valgrind); + sr = srunner_create(s); srunner_run_all(sr, CK_ENV); nfailed = srunner_ntests_failed(sr); diff --git a/tools/ratbag-command.c b/tools/ratbag-command.c index 5c850d68..f780bb42 100644 --- a/tools/ratbag-command.c +++ b/tools/ratbag-command.c @@ -556,6 +556,7 @@ ratbag_cmd_change_button(const struct ratbag_cmd *cmd, struct ratbag_device *device; struct ratbag_button *button = NULL; struct ratbag_profile *profile = NULL; + struct ratbag_button_macro *m = NULL; int button_index; enum ratbag_button_action_type action_type; int rc = ERR_DEVICE; @@ -630,17 +631,18 @@ ratbag_cmd_change_button(const struct ratbag_cmd *cmd, rc = ratbag_button_set_special(button, special); break; case RATBAG_BUTTON_ACTION_TYPE_MACRO: - rc = ratbag_button_set_macro(button, macro.name); + m = ratbag_button_macro_new(macro.name); for (i = 0; i < ARRAY_LENGTH(macro.events); i++) { if (macro.events[i].type == RATBAG_MACRO_EVENT_NONE) break; - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i, macro.events[i].type, macro.events[i].data); } - rc = ratbag_button_write_macro(button); + rc = ratbag_button_set_macro(button, m); + ratbag_button_macro_unref(m); break; default: error("well, that shouldn't have happened\n"); @@ -1265,6 +1267,7 @@ ratbag_cmd_button_set_macro(const struct ratbag_cmd *cmd, { struct ratbag_device *device; struct ratbag_button *button; + struct ratbag_button_macro *m; struct macro macro = {0}; int rc; int i; @@ -1289,17 +1292,18 @@ ratbag_cmd_button_set_macro(const struct ratbag_cmd *cmd, return ERR_UNSUPPORTED; button = options->button; - rc = ratbag_button_set_macro(button, macro.name); + m = ratbag_button_macro_new(macro.name); for (i = 0; i < ARRAY_LENGTH(macro.events); i++) { if (macro.events[i].type == RATBAG_MACRO_EVENT_NONE) break; - ratbag_button_set_macro_event(button, + ratbag_button_macro_set_event(m, i, macro.events[i].type, macro.events[i].data); } - rc = ratbag_button_write_macro(button); + rc = ratbag_button_set_macro(button, m); + ratbag_button_macro_unref(m); if (rc != 0) return ERR_DEVICE; diff --git a/tools/shared.c b/tools/shared.c index 9ac94d66..4a110e09 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -174,18 +174,20 @@ static const char *strip_ev_key(int key) char * button_action_macro_to_str(struct ratbag_button *button) { + struct ratbag_button_macro *macro; char str[4096] = {0}; const char *name; int offset; unsigned int i; - name = ratbag_button_get_macro_name(button); + macro = ratbag_button_get_macro(button); + name = ratbag_button_macro_get_name(macro); offset = snprintf(str, sizeof(str), "macro \"%s\":", name ? name : "UNKNOWN"); for (i = 0; i < MAX_MACRO_EVENTS; i++) { - enum ratbag_macro_event_type type = ratbag_button_get_macro_event_type(button, i); - int key = ratbag_button_get_macro_event_key(button, i); - int timeout = ratbag_button_get_macro_event_timeout(button, i); + enum ratbag_macro_event_type type = ratbag_button_macro_get_event_type(macro, i); + int key = ratbag_button_macro_get_event_key(macro, i); + int timeout = ratbag_button_macro_get_event_timeout(macro, i); if (type == RATBAG_MACRO_EVENT_NONE) break; @@ -205,6 +207,8 @@ button_action_macro_to_str(struct ratbag_button *button) } } + ratbag_button_macro_unref(macro); + return strdup_safe(str); } @@ -236,13 +240,17 @@ ratbag_cmd_open_device(struct ratbag *ratbag, const char *path) struct ratbag_device *device; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL; + enum ratbag_error_code error; udev = udev_new(); udev_device = udev_device_from_path(udev, path); if (!udev_device) return NULL; - device = ratbag_device_new_from_udev_device(ratbag, udev_device); + error = ratbag_device_new_from_udev_device(ratbag, udev_device, + &device); + if (error != RATBAG_SUCCESS) + return NULL; return device; }