From 558f59b52c88e36d235a030c1d2bfa9b939cac7a Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 13 Oct 2017 11:19:54 +0200 Subject: [PATCH] tools: replace ratbag-command.c with ratbag-command.py Let the .c file die, and try to maintain the python version only. Signed-off-by: Benjamin Tissoires --- meson.build | 44 +- tools/ratbag-command.c | 2198 -------------------------------------- tools/ratbag-command.man | 144 --- 3 files changed, 14 insertions(+), 2372 deletions(-) delete mode 100644 tools/ratbag-command.c delete mode 100644 tools/ratbag-command.man diff --git a/meson.build b/meson.build index 9d695322..61eef95a 100644 --- a/meson.build +++ b/meson.build @@ -190,33 +190,6 @@ lib_libshared = static_library('shared', ) dep_libshared = declare_dependency(link_with: lib_libshared) -#### ratbag-command #### -src_ratbag_command = [ 'tools/ratbag-command.c' ] -deps_ratbag_command = [ - dep_libshared, - dep_libratbag, - dep_libevdev -] - -executable('ratbag-command', - src_ratbag_command, - dependencies : deps_ratbag_command, - include_directories : include_directories('src'), - install : false, -) - -man_config = configuration_data() - -man_config.set('version', meson.project_version()) - -man_ratbag_command = configure_file ( - input: 'tools/ratbag-command.man', - output: 'ratbag-command.1', - configuration: man_config, - install : false, - install_dir : join_paths(get_option('mandir'), 'man1') -) - #### hidpp10-dump-page #### src_hidpp10_dump_page = [ 'tools/hidpp10-dump-page.c' ] executable('hidpp10-dump-page', @@ -253,6 +226,10 @@ executable('lur-command', install : true, ) +man_config = configuration_data() + +man_config.set('version', meson.project_version()) + man_lur_command = configure_file ( input: 'tools/lur-command.man', output: 'lur-command.1', @@ -515,7 +492,14 @@ custom_target('ratbagctl', '--version', meson.project_version()], install: true, install_dir: get_option('bindir')) -install_man('tools/ratbagctl.1') + +man_ratbagctl = configure_file ( + input: 'tools/ratbagctl.1', + output: 'ratbagctl.1', + configuration: man_config, + install : true, + install_dir : join_paths(get_option('mandir'), 'man1') +) config_ratbagctl_devel = configuration_data() config_ratbagctl_devel.set('ratbagd_sha', ratbagd_sha) @@ -573,8 +557,8 @@ shared_library( ) -custom_target('ratbag-command.py', - output : 'ratbag-command.py', +custom_target('ratbag-command', + output : 'ratbag-command', input : ['tools/ratbagctl.in', 'tools/ratbagc.py'], build_by_default : true, command : [py3, join_paths(meson.source_root(), 'tools', 'merge_ratbagd.py'), diff --git a/tools/ratbag-command.c b/tools/ratbag-command.c deleted file mode 100644 index 4cb08403..00000000 --- a/tools/ratbag-command.c +++ /dev/null @@ -1,2198 +0,0 @@ -/* - * Copyright © 2015 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libratbag-version.h" -#include "shared.h" - -#include -#include - -enum options { - OPT_VERSION, - OPT_VERBOSE, - OPT_HELP, -}; - -enum errors { - SUCCESS = 0, - ERR_UNSUPPORTED = 1, /* device doesn't support function, or - an index exceeds the device */ - ERR_USAGE = 2, /* invalid commandline */ - ERR_DEVICE = 3, /* invalid/missing device or command failed */ -}; - -enum cmd_flags { - FLAG_VERBOSE = 1 << 0, - FLAG_VERBOSE_RAW = 1 << 1, - - /* flags used in ratbag_cmd */ - FLAG_NEED_DEVICE = 1 << 10, - FLAG_NEED_PROFILE = 1 << 11, - FLAG_NEED_RESOLUTION = 1 << 12, - FLAG_NEED_BUTTON = 1 << 13, - FLAG_NEED_LED = 1 << 14, -}; - -struct ratbag_cmd_options { - enum cmd_flags flags; - struct ratbag_device *device; - struct ratbag_profile *profile; - struct ratbag_resolution *resolution; - struct ratbag_button *button; - struct ratbag_led *led; -}; - -struct ratbag_cmd { - const char *name; - int (*cmd)(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv); - uint32_t flags; - const struct ratbag_cmd *subcommands[]; -}; - -static const struct ratbag_cmd *ratbag_commands; - -static void -usage(void) -{ - printf("%s [OPTIONS] {COMMAND} ... /path/to/device\n" - "\n" - "Query or change a device's settings:\n" - "\n" - "Options:\n" - " --verbose Print debugging output\n" - " --verbose=raw Print debugging output with protocol output.\n" - " --help Print this help.\n" - "\n" - "General Commands:\n" - " list List supported devices (does not take a device argument)\n" - "\n" - "Device Commands:\n" - " info Print information about a device \n" - "\n" - "Profile Commands:\n" - " profile active get Print the currently active profile\n" - " profile active set N Set profile N as to the active profile\n" - " profile N enable Enable profile N\n" - " profile N disable Disable profile N\n" - " profile N {COMMAND} Use profile N for COMMAND\n" - "\n" - "Resolution Commands\n" - " Resolution commands work on the given profile, or on the\n" - " active profile if none is given.\n" - "\n" - " resolution active get Print the currently active resolution\n" - " resolution active set N Set resolution N as the active resolution\n" - " resolution N {COMMAND} Use resolution N for COMMAND\n" - "\n" - "DPI Commands:\n" - " DPI commands work on the given profile and resolution, or on the\n" - " active resolution of the active profile if none are given.\n" - "\n" - " dpi get Print the dpi value\n" - " dpi set N Set the dpi value to N\n" - " rate get Print the report rate in Hz\n" - " rate set N Set the report rate in N Hz\n" - "\n" - "Button Commands:\n" - " Button commands work on the given profile, or on the\n" - " active profile if none is given.\n" - "\n" - " button count Print the number of buttons\n" - " button N action get Print the button action\n" - " button N action set button B Set the button action to button B\n" - " button N action set special S Set the button action to special action S\n" - " button N action set macro ... Set the button action to the given macro \n" - "\n" - " Macro syntax:\n" - " A macro is a series of key events or waiting periods.\n" - " Keys must be specified in linux/input.h key names.\n" - " KEY_A Press and release 'a'\n" - " +KEY_A Press 'a'\n" - " -KEY_A Release 'a'\n" - " t300 Wait 300ms\n" - "\n" - "LED Commands:\n" - " LED commands work on the given profile, or on the\n" - " active profile if none is given.\n" - "\n" - " led N {COMMAND}\n" - " get print the LED properties\n" - " set {COMMAND} ... sets LED properties (one or more)\n" - " mode [on|off|cycle|breathing] sets LED mode\n" - " color COLOR sets LED's color in hex format\n" - " rate N sets LED's effect rate in Hz\n" - " brightness N sets LED's effect brightness\n" - "\n" - "Special Commands:\n" - "These commands are for testing purposes and may be removed without notice\n" - "\n" - " switch-etekcity Switch the Etekcity mouse active profile\n" - "\n" - "Examples:\n" - " %s profile active get\n" - " %s profile 0 resolution active set 4\n" - " %s profile 0 resolution 1 dpi get\n" - " %s resolution 4 rate get\n" - " %s dpi set 800\n" - " %s profile 0 led 0 set mode on\n" - " %s profile 0 led 0 set color ff00ff\n" - " %s profile 0 led 0 set rate 20\n" - "\n" - "Exit codes:\n" - " 0 Success\n" - " 1 Unsupported feature or index out of available range\n" - " 2 Commandline arguments are invalid\n" - " 3 Invalid device or a command failed on the device\n" - "\n", - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name, - program_invocation_short_name); -} - -static void -version(void) -{ - printf("%s\n", LIBRATBAG_VERSION); -} - -static inline int -ratbag_cmd_device_from_arg(struct ratbag *ratbag, - int *argc, char **argv, - struct ratbag_device **device_out) -{ - struct ratbag_device *device; - const char *path; - - if (*argc == 0) { - error("Missing device path.\n"); - return ERR_USAGE; - } - - path = argv[*argc - 1]; - device = ratbag_cmd_open_device(ratbag, path); - if (!device) { - error("Device '%s' is not supported\n", path); - return ERR_DEVICE; - } - - (*argc)--; - *device_out = device; - - return SUCCESS; -} - -static inline struct ratbag_profile * -ratbag_cmd_get_active_profile(struct ratbag_device *device) -{ - struct ratbag_profile *profile = NULL; - - for (unsigned int i = 0; i < ratbag_device_get_num_profiles(device); i++) { - profile = ratbag_device_get_profile(device, i); - if (ratbag_profile_is_active(profile)) - return profile; - - ratbag_profile_unref(profile); - profile = NULL; - } - - if (!profile) - error("Failed to retrieve the active profile\n"); - - return NULL; -} - -static inline struct ratbag_resolution * -ratbag_cmd_get_active_resolution(struct ratbag_profile *profile) -{ - struct ratbag_resolution *resolution = NULL; - - for (unsigned int i = 0; i < ratbag_profile_get_num_resolutions(profile); i++) { - resolution = ratbag_profile_get_resolution(profile, i); - if (ratbag_resolution_is_active(resolution)) - return resolution; - - ratbag_resolution_unref(resolution); - resolution = NULL; - } - - if (!resolution) - error("Failed to retrieve the active resolution\n"); - - return NULL; -} - -static inline int -fill_options(struct ratbag *ratbag, - struct ratbag_cmd_options *options, - uint32_t flags, - int *argc, char **argv) -{ - struct ratbag_device *device = options->device; - struct ratbag_profile *profile = options->profile; - struct ratbag_resolution *resolution = options->resolution; - struct ratbag_button *button = options->button; - int rc; - - if ((flags & (FLAG_NEED_DEVICE|FLAG_NEED_PROFILE|FLAG_NEED_RESOLUTION|FLAG_NEED_LED)) && - device == NULL) { - rc = ratbag_cmd_device_from_arg(ratbag, argc, argv, - &device); - if (rc != SUCCESS) - return rc; - options->device = device; - } - - if ((flags & (FLAG_NEED_PROFILE|FLAG_NEED_RESOLUTION|FLAG_NEED_LED)) && - profile == NULL) { - profile = ratbag_cmd_get_active_profile(device); - if (!profile) - return ERR_DEVICE; - options->profile = profile; - } - - if (flags & FLAG_NEED_RESOLUTION && resolution == NULL) { - resolution = ratbag_cmd_get_active_resolution(profile); - if (!resolution) - return ERR_DEVICE; - options->resolution = resolution; - } - - if (flags & FLAG_NEED_BUTTON && button == NULL) { - error("Missing button identifier\n"); - return ERR_USAGE; - } - - return SUCCESS; -} - -static int -run_subcommand(const char *command, - const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - const struct ratbag_cmd *sub = cmd->subcommands[0]; - int i = 0; - int rc; - - while (sub) { - if (streq(command, sub->name)) { - rc = fill_options(ratbag, options, - sub->flags, - &argc, - argv); - if (rc != SUCCESS) - return rc; - - argc--; - argv++; - return sub->cmd(sub, ratbag, options, argc, argv); - } - sub = cmd->subcommands[i++]; - } - - error("Invalid subcommand '%s'\n", command); - return ERR_USAGE; -} - -static int -ratbag_printf_led(struct ratbag_led *led, const char *prefix_format, ...) -{ - va_list arg; - enum ratbag_led_mode mode; - struct ratbag_color color; - int hz; - int brightness; - enum ratbag_led_type type; - - type = ratbag_led_get_type(led); - mode = ratbag_led_get_mode(led); - color = ratbag_led_get_color(led); - hz = ratbag_led_get_effect_rate(led); - brightness = ratbag_led_get_brightness(led); - - va_start(arg, prefix_format); - vprintf(prefix_format, arg); - va_end(arg); - switch (mode) { - case RATBAG_LED_OFF: - printf("type: %s, mode: %s\n", - led_type_to_str(type), - led_mode_to_str(mode)); - break; - case RATBAG_LED_ON: - printf("type: %s, mode: %s, color: %02x%02x%02x\n", - led_type_to_str(type), - led_mode_to_str(mode), - color.red, color.green, color.blue); - break; - case RATBAG_LED_CYCLE: - printf("type: %s, mode: %s, rate: %d, brightness: %d\n", - led_type_to_str(type), - led_mode_to_str(mode), - hz, brightness); - break; - case RATBAG_LED_BREATHING: - printf("type: %s, mode: %s, color: %02x%02x%02x, rate: %d, brightness: %d\n", - led_type_to_str(type), - led_mode_to_str(mode), - color.red, color.green, color.blue, - hz, brightness); - break; - } - - return SUCCESS; -} - -static int -ratbag_cmd_info(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - int num_profiles, num_buttons, num_leds; - int b, l; - - device = options->device; - - printf("Device '%s'\n", ratbag_device_get_name(device)); - - printf("Capabilities:"); - if (ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION)) - printf(" res"); - if (ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE)) - printf(" profile"); - if (ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_BUTTON_KEY)) - printf(" btn-key"); - if (ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_BUTTON_MACROS)) - printf(" btn-macros"); - if (ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_LED)) - printf(" led"); - printf("\n"); - - num_buttons = ratbag_device_get_num_buttons(device); - printf("Number of buttons: %d\n", num_buttons); - - num_leds = ratbag_device_get_num_leds(device); - printf("Number of leds: %d\n", num_leds); - - num_profiles = ratbag_device_get_num_profiles(device); - printf("Profiles supported: %d\n", num_profiles); - - for (int i = 0; i < num_profiles; i++) { - _cleanup_profile_ struct ratbag_profile *profile = NULL; - _cleanup_resolution_ struct ratbag_resolution *res0 = NULL; - int dpi, rate; - unsigned int dpis[300]; - int ndpis = ARRAY_LENGTH(dpis); - - profile = ratbag_device_get_profile(device, i); - if (!profile) - continue; - - printf(" Profile %d (%s)%s\n", i, - ratbag_profile_is_enabled(profile) ? "enabled" : "disabled", - ratbag_profile_is_active(profile) ? " (active)" : ""); - if (!ratbag_profile_is_enabled(profile)) - continue; - - printf(" Resolutions:\n"); - - res0 = ratbag_profile_get_resolution(profile, 0); - ndpis = ratbag_resolution_get_dpi_list(res0, dpis, ndpis); - printf(" Range: [%d, %d]\n", dpis[0], dpis[ndpis - 1]); - - for (unsigned int j = 0; j < ratbag_profile_get_num_resolutions(profile); j++) { - _cleanup_resolution_ struct ratbag_resolution *res = NULL; - - res = ratbag_profile_get_resolution(profile, j); - dpi = ratbag_resolution_get_dpi(res); - rate = ratbag_resolution_get_report_rate(res); - if (dpi == 0) - printf(" %d: \n", j); - else if (ratbag_resolution_has_capability(res, - RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION)) - printf(" %d: %dx%ddpi @ %dHz%s%s\n", j, - ratbag_resolution_get_dpi_x(res), - ratbag_resolution_get_dpi_y(res), - rate, - ratbag_resolution_is_active(res) ? " (active)" : "", - ratbag_resolution_is_default(res) ? " (default)" : ""); - else - printf(" %d: %ddpi @ %dHz%s%s\n", j, dpi, rate, - ratbag_resolution_is_active(res) ? " (active)" : "", - ratbag_resolution_is_default(res) ? " (default)" : ""); - } - - for (b = 0; b < num_buttons; b++) { - _cleanup_button_ struct ratbag_button *button = NULL; - _cleanup_free_ char *action = NULL; - enum ratbag_button_type type; - - button = ratbag_profile_get_button(profile, b); - type = ratbag_button_get_type(button); - action = button_action_to_str(button); - printf(" Button: %d type %s is mapped to '%s'\n", - b, button_type_to_str(type), action); - } - - for (l = 0; l < num_leds; l++) { - _cleanup_led_ struct ratbag_led *led = NULL; - - led = ratbag_profile_get_led(profile, l); - ratbag_printf_led(led, " LED: %d ", l); - } - } - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_info = { - .name = "info", - .cmd = ratbag_cmd_info, - .flags = FLAG_NEED_DEVICE, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_switch_etekcity(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_button *button_6, *button_7; - struct ratbag_profile *profile = NULL; - int commit = 0; - unsigned int modifiers[10]; - size_t modifiers_sz = 10; - - device = options->device; - profile = options->profile; - - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE)) { - error("Device '%s' has no switchable profiles\n", - ratbag_device_get_name(device)); - return ERR_UNSUPPORTED; - } - - button_6 = ratbag_profile_get_button(profile, 6); - button_7 = ratbag_profile_get_button(profile, 7); - - if (ratbag_button_get_key(button_6, modifiers, &modifiers_sz) == KEY_VOLUMEUP && - ratbag_button_get_key(button_7, modifiers, &modifiers_sz) == KEY_VOLUMEDOWN) { - ratbag_button_disable(button_6); - ratbag_button_disable(button_7); - commit = 1; - } else if (ratbag_button_get_action_type(button_6) == RATBAG_BUTTON_ACTION_TYPE_NONE && - ratbag_button_get_action_type(button_7) == RATBAG_BUTTON_ACTION_TYPE_NONE) { - ratbag_button_set_key(button_6, KEY_VOLUMEUP, modifiers, 0); - ratbag_button_set_key(button_7, KEY_VOLUMEDOWN, modifiers, 0); - commit = 2; - } - - ratbag_button_unref(button_6); - ratbag_button_unref(button_7); - - printf("Switched the current profile of '%s' to %sreport the volume keys\n", - ratbag_device_get_name(device), - commit == 1 ? "not " : ""); - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_switch_etekcity = { - .name = "switch-etekcity", - .cmd = ratbag_cmd_switch_etekcity, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { NULL }, -}; - -struct macro { - const char *name; - struct { - enum ratbag_macro_event_type type; - unsigned data; - } events[64]; -}; - -static int -str_to_macro(const char *action_arg, struct macro *m) -{ - char *str, *s; - enum ratbag_macro_event_type type; - int code; - unsigned int idx = 0; - int rc = ERR_USAGE; - - /* FIXME: handle per-device maximum lengths of macros */ - - if (!action_arg) - return -EINVAL; - - str = strdup_safe(action_arg); - s = str; - - m->name = ""; - - while (idx < ARRAY_LENGTH(m->events)) { - char *token; - - token = strsep(&s, " "); - if (!token) - break; - if (strlen(token) == 0) - continue; - - switch(token[0]) { - case '+': - type = RATBAG_MACRO_EVENT_KEY_PRESSED; - token++; - break; - case '-': - type = RATBAG_MACRO_EVENT_KEY_RELEASED; - token++; - break; - case 't': - type = RATBAG_MACRO_EVENT_WAIT; - token++; - break; - default: - type = RATBAG_MACRO_EVENT_NONE; - break; - } - - if (type == RATBAG_MACRO_EVENT_WAIT) { - char *endptr; - code = strtol(token, &endptr, 10); - if (*endptr != '\0') { - error("Invalid token name: %s\n", token); - goto out; - } - } else { - code = libevdev_event_code_from_name(EV_KEY, token); - if (code == -1) { - error("Invalid token name: %s\n", token); - goto out; - } - } - - if (type == RATBAG_MACRO_EVENT_NONE) { - m->events[idx].type = RATBAG_MACRO_EVENT_KEY_PRESSED; - m->events[idx].data = code; - type = RATBAG_MACRO_EVENT_KEY_RELEASED; - idx++; - } - m->events[idx].data = code; - m->events[idx].type = type; - idx++; - } - - rc = SUCCESS; - -out: - free(str); - - return rc; -} - -static int -ratbag_cmd_change_button(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - const char *action_str, *action_arg; - 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; - unsigned int btnkey = 0; - enum ratbag_button_action_special special; - struct macro macro = {0}; - - if (argc != 3) - return ERR_USAGE; - - button_index = atoi(argv[0]); - action_str = argv[1]; - action_arg = argv[2]; - - argc -= 3; - argv += 3; - - (void)argc; - (void)argv; - - if (streq(action_str, "button")) { - action_type = RATBAG_BUTTON_ACTION_TYPE_BUTTON; - btnkey = atoi(action_arg); - } else if (streq(action_str, "key")) { - action_type = RATBAG_BUTTON_ACTION_TYPE_KEY; - btnkey = libevdev_event_code_from_name(EV_KEY, action_arg); - if (!btnkey) { - error("Failed to resolve key %s\n", action_arg); - return ERR_USAGE; - } - } else if (streq(action_str, "special")) { - action_type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL; - special = str_to_special_action(action_arg); - if (special == RATBAG_BUTTON_ACTION_SPECIAL_INVALID) { - error("Invalid special command '%s'\n", action_arg); - return ERR_USAGE; - } - } else if (streq(action_str, "macro")) { - action_type = RATBAG_BUTTON_ACTION_TYPE_MACRO; - if (str_to_macro(action_arg, ¯o)) { - error("Invalid special command '%s'\n", action_arg); - return ERR_USAGE; - } - } else { - return ERR_USAGE; - } - - device = options->device; - profile = options->profile; - - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_BUTTON_KEY)) { - error("Device '%s' has no programmable buttons\n", - ratbag_device_get_name(device)); - rc = ERR_UNSUPPORTED; - goto out; - } - - button = ratbag_profile_get_button(profile, button_index); - if (!button) { - error("Invalid button number %d\n", button_index); - rc = ERR_UNSUPPORTED; - goto out; - } - - switch (action_type) { - case RATBAG_BUTTON_ACTION_TYPE_BUTTON: - rc = ratbag_button_set_button(button, btnkey); - break; - case RATBAG_BUTTON_ACTION_TYPE_KEY: - rc = ratbag_button_set_key(button, btnkey, NULL, 0); - break; - case RATBAG_BUTTON_ACTION_TYPE_SPECIAL: - rc = ratbag_button_set_special(button, special); - break; - case RATBAG_BUTTON_ACTION_TYPE_MACRO: - m = ratbag_button_macro_new(macro.name); - for (size_t i = 0; i < ARRAY_LENGTH(macro.events); i++) { - if (macro.events[i].type == RATBAG_MACRO_EVENT_NONE) - break; - - ratbag_button_macro_set_event(m, - i, - macro.events[i].type, - macro.events[i].data); - } - rc = ratbag_button_set_macro(button, m); - ratbag_button_macro_unref(m); - break; - default: - error("well, that shouldn't have happened\n"); - abort(); - break; - } - if (rc) { - error("Unable to perform button %d mapping %s %s\n", - button_index, - action_str, - action_arg); - rc = ERR_UNSUPPORTED; - goto out; - } - - rc = ratbag_profile_set_active(profile); - if (rc) { - error("Unable to apply the current profile: %s (%d)\n", - strerror(-rc), - rc); - rc = ERR_DEVICE; - goto out; - } - -out: - ratbag_button_unref(button); - - return rc; -} - -static const struct ratbag_cmd cmd_change_button = { - .name = "change-button", - .cmd = ratbag_cmd_change_button, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { NULL }, -}; - -static int -filter_event_node(const struct dirent *input_entry) -{ - return strneq(input_entry->d_name, "event", 5); -} - -static int -ratbag_cmd_list_supported_devices(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct dirent **input_list; - struct ratbag_device *device; - char path[256]; - int n, i; - int supported = 0; - - if (argc != 0) - return ERR_USAGE; - - n = scandir("/dev/input", &input_list, filter_event_node, alphasort); - if (n < 0) - return SUCCESS; - - i = -1; - while (++i < n) { - sprintf_safe(path, "/dev/input/%s", input_list[i]->d_name); - device = ratbag_cmd_open_device(ratbag, path); - if (device) { - printf("%s:\t%s\n", path, ratbag_device_get_name(device)); - ratbag_device_unref(device); - supported++; - } - free(input_list[i]); - } - free(input_list); - - if (!supported) - printf("No supported devices found\n"); - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_list = { - .name = "list", - .cmd = ratbag_cmd_list_supported_devices, - .flags = 0, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_active_set(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_profile *profile = options->profile; - struct ratbag_resolution *resolution = NULL; - int num_resolutions, index; - int rc = SUCCESS; - - index = atoi(argv[0]); - - argc--; - argv++; - - num_resolutions = ratbag_profile_get_num_resolutions(profile); - if (index >= num_resolutions) { - error("'%d' is not a valid resolution\n", index); - rc = ERR_USAGE; - goto out; - } - - resolution = ratbag_profile_get_resolution(profile, index); - if (ratbag_resolution_is_active(resolution)) { - rc = SUCCESS; - goto out; - } - - rc = ratbag_resolution_set_active(resolution); - - if (rc != 0) { - error("Failed to to set resolution as active\n"); - return ERR_DEVICE; - } - -out: - ratbag_resolution_unref(resolution); - - return rc; -} - -static const struct ratbag_cmd cmd_resolution_active_set = { - .name = "set", - .cmd = ratbag_cmd_resolution_active_set, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_active_get(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_profile *profile; - struct ratbag_resolution *resolution = NULL; - int num_resolutions; - int active_resolution = -1; - int i; - int rc = SUCCESS; - - profile = options->profile; - - num_resolutions = ratbag_profile_get_num_resolutions(profile); - - for (i = 0; i < num_resolutions && active_resolution < 0; i++) { - resolution = ratbag_profile_get_resolution(profile, i); - if (ratbag_resolution_is_active(resolution)) - active_resolution = i; - - ratbag_resolution_unref(resolution); - } - - if (active_resolution < 0) { - error("BUG: Unable to find active resolution\n"); - rc = ERR_DEVICE; - } - - if (rc == SUCCESS) - printf("%d\n", active_resolution); - - return rc; -} - -static const struct ratbag_cmd cmd_resolution_active_get = { - .name = "get", - .cmd = ratbag_cmd_resolution_active_get, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_active(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - if (argc < 1) - return ERR_USAGE; - - return run_subcommand(argv[0], - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_resolution_active = { - .name = "active", - .cmd = ratbag_cmd_resolution_active, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { - &cmd_resolution_active_get, - &cmd_resolution_active_set, - NULL, - }, -}; - -static int -ratbag_cmd_resolution_dpi_get(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_resolution *resolution; - int dpi; - - resolution = options->resolution; - dpi = ratbag_resolution_get_dpi(resolution); - printf("%ddpi\n", dpi); - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_resolution_dpi_get = { - .name = "get", - .cmd = ratbag_cmd_resolution_dpi_get, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_RESOLUTION, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_dpi_set(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_resolution *resolution; - int rc = SUCCESS; - int dpi; - - if (argc != 1) - return ERR_USAGE; - - dpi = atoi(argv[0]); - - argc--; - argv++; - - device = options->device; - resolution = options->resolution; - - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION)) { - error("Device '%s' has no switchable resolution\n", - ratbag_device_get_name(device)); - rc = ERR_UNSUPPORTED; - goto out; - } - - rc = ratbag_resolution_set_dpi(resolution, dpi); - if (rc) { - error("Failed to change the dpi: %s (%d)\n", - strerror(-rc), - rc); - rc = ERR_DEVICE; - } -out: - return rc; -} - -static const struct ratbag_cmd cmd_resolution_dpi_set = { - .name = "set", - .cmd = ratbag_cmd_resolution_dpi_set, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE| FLAG_NEED_RESOLUTION, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_dpi(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - if (argc < 1) - return ERR_USAGE; - - return run_subcommand(argv[0], - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_resolution_dpi = { - .name = "dpi", - .cmd = ratbag_cmd_resolution_dpi, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE| FLAG_NEED_RESOLUTION, - .subcommands = { - &cmd_resolution_dpi_get, - &cmd_resolution_dpi_set, - NULL, - }, -}; - -static int -ratbag_cmd_resolution_rate_get(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_resolution *resolution; - int rate; - - resolution = options->resolution; - rate = ratbag_resolution_get_report_rate(resolution); - printf("%d\n", rate); - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_resolution_rate_get = { - .name = "get", - .cmd = ratbag_cmd_resolution_rate_get, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_RESOLUTION, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_rate_set(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_resolution *resolution; - int rc = SUCCESS; - int rate; - - if (argc != 1) - return ERR_USAGE; - - rate = atoi(argv[0]); - - argc--; - argv++; - - device = options->device; - resolution = options->resolution; - - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION)) { - error("Device '%s' has no switchable resolution\n", - ratbag_device_get_name(device)); - rc = ERR_UNSUPPORTED; - goto out; - } - - rc = ratbag_resolution_set_report_rate(resolution, rate); - if (rc) { - error("Failed to change the rate: %s (%d)\n", - strerror(-rc), - rc); - rc = ERR_DEVICE; - } -out: - return rc; -} - -static const struct ratbag_cmd cmd_resolution_rate_set = { - .name = "set", - .cmd = ratbag_cmd_resolution_rate_set, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE| FLAG_NEED_RESOLUTION, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_resolution_rate(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - if (argc < 1) - return ERR_USAGE; - - return run_subcommand(argv[0], - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_resolution_rate = { - .name = "rate", - .cmd = ratbag_cmd_resolution_rate, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE| FLAG_NEED_RESOLUTION, - .subcommands = { - &cmd_resolution_rate_get, - &cmd_resolution_rate_set, - NULL, - }, -}; - -static int -ratbag_cmd_resolution(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_profile *profile; - struct ratbag_resolution *resolution; - const char *command; - int resolution_idx = 0; - char *endp; - - if (argc < 1) - return ERR_USAGE; - - command = argv[0]; - - profile = options->profile; - - resolution_idx = strtol(command, &endp, 10); - if (command != endp && *endp == '\0') { - resolution = ratbag_profile_get_resolution(profile, - resolution_idx); - - if (!resolution) { - error("Unable to retrieve resolution %d\n", - resolution_idx); - return ERR_UNSUPPORTED; - } - argc--; - argv++; - command = argv[0]; - } else { - resolution = ratbag_cmd_get_active_resolution(profile); - if (!resolution) - return ERR_DEVICE; - } - - options->resolution = resolution; - - return run_subcommand(command, - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_resolution = { - .name = "resolution", - .cmd = ratbag_cmd_resolution, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { - &cmd_resolution_active, - &cmd_resolution_dpi, - &cmd_resolution_rate, - NULL, - }, -}; - -static int -ratbag_cmd_button_count(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - int num_buttons; - - device = options->device; - num_buttons = ratbag_device_get_num_buttons(device); - printf("%d\n", num_buttons); - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_button_count = { - .name = "count", - .cmd = ratbag_cmd_button_count, - .flags = FLAG_NEED_DEVICE, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_button_get(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_button *button; - enum ratbag_button_type type; - const char *action; - - button = options->button; - - type = ratbag_button_get_type(button); - action = button_action_to_str(button); - printf("type %s to %s\n", - button_type_to_str(type), action); - - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_button_get = { - .name = "get", - .cmd = ratbag_cmd_button_get, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_button_set_button(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_button *button; - char *str, *endptr; - int b; - int rc; - - if (argc < 1) - return ERR_USAGE; - - str = argv[0]; - b = strtol(str, &endptr, 10); - if (*endptr != '\0') - return ERR_USAGE; - - device = options->device; - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_BUTTON_KEY)) - return ERR_UNSUPPORTED; - - - button = options->button; - rc = ratbag_button_set_button(button, b); - if (rc != 0) - return ERR_DEVICE; - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_button_set_button = { - .name = "button", - .cmd = ratbag_cmd_button_set_button, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_button_set_key(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_button *button; - int keycode; - char *str; - int rc; - - if (argc < 1) - return ERR_USAGE; - - str = argv[0]; - keycode = libevdev_event_code_from_name(EV_KEY, str); - if (keycode == -1) { - error("Failed to resolve keycode '%s'\n", str); - return ERR_USAGE; - } - - device = options->device; - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_BUTTON_KEY)) - return ERR_UNSUPPORTED; - - button = options->button; - rc = ratbag_button_set_key(button, keycode, NULL, 0); - if (rc != 0) - return ERR_DEVICE; - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_button_set_key = { - .name = "key", - .cmd = ratbag_cmd_button_set_key, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_button_set_special(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_button *button; - enum ratbag_button_action_special special; - char *str; - int rc; - - if (argc < 1) - return ERR_USAGE; - - str = argv[0]; - special = str_to_special_action(str); - if (special == RATBAG_BUTTON_ACTION_SPECIAL_INVALID) { - error("Invalid special identifier '%s'\n", str); - return ERR_USAGE; - } - - button = options->button; - rc = ratbag_button_set_special(button, special); - if (rc != 0) - return ERR_DEVICE; - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_button_set_special = { - .name = "special", - .cmd = ratbag_cmd_button_set_special, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_button_set_macro(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_button *button; - struct ratbag_button_macro *m; - struct macro macro = {0}; - int rc; - char macro_str[PATH_MAX] = {0}; - - if (argc < 1) - return ERR_USAGE; - - for (int i = 0; i < argc; i++) { - strncat(macro_str, argv[i], sizeof(macro_str) - strlen(macro_str) - 1); - strcat(macro_str, " "); - } - - if (str_to_macro(macro_str, ¯o) != 0) { - error("Invalid macro string '%s'\n", macro_str); - return ERR_USAGE; - } - - device = options->device; - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_BUTTON_MACROS)) - return ERR_UNSUPPORTED; - - button = options->button; - m = ratbag_button_macro_new(macro.name); - for (size_t i = 0; i < ARRAY_LENGTH(macro.events); i++) { - if (macro.events[i].type == RATBAG_MACRO_EVENT_NONE) - break; - - ratbag_button_macro_set_event(m, - i, - macro.events[i].type, - macro.events[i].data); - } - rc = ratbag_button_set_macro(button, m); - ratbag_button_macro_unref(m); - if (rc != 0) - return ERR_DEVICE; - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_button_set_macro = { - .name = "macro", - .cmd = ratbag_cmd_button_set_macro, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_button_set(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - const char *command; - - if (argc < 1) - return ERR_USAGE; - - command = argv[0]; - - return run_subcommand(command, - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_button_set = { - .name = "set", - .cmd = ratbag_cmd_button_set, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - &cmd_button_set_button, - &cmd_button_set_key, - &cmd_button_set_special, - &cmd_button_set_macro, - NULL, - }, -}; - -static int -ratbag_cmd_button_action(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - const char *command; - - if (argc < 1) - return ERR_USAGE; - - command = argv[0]; - - return run_subcommand(command, - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_button_action = { - .name = "action", - .cmd = ratbag_cmd_button_action, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_BUTTON, - .subcommands = { - &cmd_button_get, - &cmd_button_set, - NULL, - }, -}; - -static int -ratbag_cmd_button(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_profile *profile; - struct ratbag_button *button; - const char *command; - int button_idx = 0; - char *endp; - - if (argc < 1) - return ERR_USAGE; - - profile = options->profile; - - command = argv[0]; - - button_idx = strtol(command, &endp, 10); - if (command != endp && *endp == '\0') { - button = ratbag_profile_get_button(profile, - button_idx); - if (!button) { - error("Invalid button %d\n", button_idx); - return ERR_UNSUPPORTED; - } - options->button = button; - argc--; - argv++; - command = argv[0]; - } - - return run_subcommand(command, - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_button = { - .name = "button", - .cmd = ratbag_cmd_button, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { - &cmd_button_count, - &cmd_button_action, - NULL, - }, -}; - -static int -ratbag_cmd_led_set_brightness(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_led *led; - int brightness; - int rc; - - if (argc < 1) - return ERR_USAGE; - - led = options->led; - brightness = atoi(argv[0]); - - rc = ratbag_led_set_brightness(led, brightness); - if (rc != 0) - return ERR_DEVICE; - - if (argc == 1) - return SUCCESS; - - return run_subcommand(argv[1], cmd, ratbag, options, - argc - 1, argv + 1); -} - -static const struct ratbag_cmd cmd_led_set_color; -static const struct ratbag_cmd cmd_led_set_effect_rate; - -static const struct ratbag_cmd cmd_led_set_brightness = { - .name = "brightness", - .cmd = ratbag_cmd_led_set_brightness, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED, - .subcommands = { - &cmd_led_set_color, - &cmd_led_set_effect_rate, - NULL, - }, -}; - -static int -ratbag_cmd_led_set_effect_rate(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - - struct ratbag_led *led; - char *str, *endptr; - int hz; - int rc; - - if (argc < 1) - return ERR_USAGE; - - led = options->led; - str = argv[0]; - hz = strtoul(str, &endptr, 10); - if (*endptr != '\0') - return ERR_USAGE; - - rc = ratbag_led_set_effect_rate(led, hz); - if (rc != 0) - return ERR_DEVICE; - - if (argc == 1) - return SUCCESS; - - return run_subcommand(argv[1], cmd, ratbag, options, - argc - 1, argv + 1); -} - -static const struct ratbag_cmd cmd_led_set_effect_rate = { - .name = "rate", - .cmd = ratbag_cmd_led_set_effect_rate, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED, - .subcommands = { - &cmd_led_set_color, - &cmd_led_set_brightness, - NULL, - }, -}; - -static int -ratbag_cmd_led_set_color(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_led *led; - struct ratbag_color color; - int rc; - char red[3], green[3], blue[3]; - char *p; - - if (argc < 1) - return ERR_USAGE; - - led = options->led; - - sscanf(argv[0], "%2s%2s%2s", red, green, blue); - - color.red = strtoul(red, &p, 16); - color.green = strtoul(green, &p, 16); - color.blue = strtoul(blue, &p, 16); - - rc = ratbag_led_set_color(led, color); - if (rc != 0) - return ERR_DEVICE; - - if (argc == 1) - return SUCCESS; - - return run_subcommand(argv[1], cmd, ratbag, options, - argc - 1, argv + 1); -} - -static const struct ratbag_cmd cmd_led_set_color = { - .name = "color", - .cmd = ratbag_cmd_led_set_color, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED, - .subcommands = { - &cmd_led_set_effect_rate, - &cmd_led_set_brightness, - NULL, - }, -}; - -static int -ratbag_cmd_led_set_mode(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_led *led; - struct ratbag_color color; - enum ratbag_led_mode mode; - char *str; - int rc; - - if (argc < 1) - return ERR_USAGE; - - led = options->led; - str = argv[0]; - - if (streq(str, "off")) - mode = RATBAG_LED_OFF; - else if (streq(str, "on")) - mode = RATBAG_LED_ON; - else if (streq(str, "cycle")) - mode = RATBAG_LED_CYCLE; - else if (streq(str, "breathing")) - mode = RATBAG_LED_BREATHING; - else { - usage(); - return ERR_USAGE; - } - - /* set default rate and brightness */ - switch (mode) { - case RATBAG_LED_ON: - color.red = 255; - color.green = 255; - color.blue = 255; - ratbag_led_set_color(led, color); - break; - case RATBAG_LED_CYCLE: - case RATBAG_LED_BREATHING: - ratbag_led_set_effect_rate(led, 20); - ratbag_led_set_brightness(led, 100); - break; - case RATBAG_LED_OFF: - break; - } - - rc = ratbag_led_set_mode(led, mode); - if (rc != 0) - return ERR_DEVICE; - - if (argc == 1) - return SUCCESS; - - return run_subcommand(argv[1], cmd, ratbag, options, - argc - 1, argv + 1); -} - -static const struct ratbag_cmd cmd_led_set_mode = { - .name = "mode", - .cmd = ratbag_cmd_led_set_mode, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED, - .subcommands = { - &cmd_led_set_color, - &cmd_led_set_effect_rate, - &cmd_led_set_brightness, - NULL, - }, -}; - -static int -ratbag_cmd_led_set(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - if (argc < 1) - return ERR_USAGE; - - return run_subcommand(argv[0], cmd, ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_led_set = { - .name = "set", - .cmd = ratbag_cmd_led_set, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED, - .subcommands = { - &cmd_led_set_mode, - &cmd_led_set_color, - &cmd_led_set_effect_rate, - &cmd_led_set_brightness, - NULL, - }, -}; - -static int -ratbag_cmd_led_get(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_led *led = options->led; - - ratbag_printf_led(led, ""); - - return SUCCESS; -} - -static const struct ratbag_cmd cmd_led_get = { - .name = "get", - .cmd = ratbag_cmd_led_get, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_led(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_profile *profile; - struct ratbag_led *led; - int rc, index; - - if (argc < 1) - return ERR_USAGE; - - profile = options->profile; - - index = atoi(argv[0]); - - led = ratbag_profile_get_led(profile, index); - if (!led) { - error("Invalid led %d\n", index); - return ERR_UNSUPPORTED; - } - options->led = led; - argc--; - argv++; - - rc = run_subcommand(argv[0], cmd, ratbag, options, - argc, argv); - - return rc; -} - -static const struct ratbag_cmd cmd_led = { - .name = "led", - .cmd = ratbag_cmd_led, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { - &cmd_led_get, - &cmd_led_set, - NULL, - }, -}; - -static int -ratbag_cmd_profile_active_set(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_profile *profile = NULL; - int num_profiles, index; - int rc = ERR_UNSUPPORTED; - - if (argc != 1) - return ERR_USAGE; - - index = atoi(argv[0]); - - argc--; - argv++; - - device = options->device; - - if (!ratbag_device_has_capability(device, - RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE)) { - error("Device '%s' has no switchable profiles\n", - ratbag_device_get_name(device)); - goto out; - } - - num_profiles = ratbag_device_get_num_profiles(device); - if (index >= num_profiles) { - error("'%d' is not a valid profile\n", index); - goto out; - } - - profile = ratbag_device_get_profile(device, index); - if (ratbag_profile_is_active(profile)) { - rc = SUCCESS; - goto out; - } - - rc = ratbag_profile_set_active(profile); - if (rc == 0) { - printf("Switched '%s' to profile '%d'\n", - ratbag_device_get_name(device), index); - rc = SUCCESS; - } else { - rc = ERR_DEVICE; - } - -out: - ratbag_profile_unref(profile); - - return rc; -} - -static const struct ratbag_cmd cmd_profile_active_set = { - .name = "set", - .cmd = ratbag_cmd_profile_active_set, - .flags = FLAG_NEED_DEVICE, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_profile_active_get(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_device *device; - struct ratbag_profile *profile = NULL; - int i; - int rc = SUCCESS; - int active_profile = -1; - int num_profiles = 0; - - device = options->device; - - num_profiles = ratbag_device_get_num_profiles(device); - - for (i = 0; i < num_profiles && active_profile < 0; i++) { - profile = ratbag_device_get_profile(device, i); - if (ratbag_profile_is_active(profile)) - active_profile = i; - - ratbag_profile_unref(profile); - } - - if (active_profile < 0) { - error("BUG: Unable to find active profile.\n"); - rc = ERR_DEVICE; - } - - if (rc == SUCCESS) - printf("%d\n", active_profile); - - return rc; -} - -static const struct ratbag_cmd cmd_profile_active_get = { - .name = "get", - .cmd = ratbag_cmd_profile_active_get, - .flags = FLAG_NEED_DEVICE, - .subcommands = { NULL }, -}; - -static int -ratbag_cmd_profile_active(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - if (argc < 1) - return ERR_USAGE; - - return run_subcommand(argv[0], - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_profile_active = { - .name = "active", - .cmd = ratbag_cmd_profile_active, - .flags = FLAG_NEED_DEVICE, - .subcommands = { - &cmd_profile_active_get, - &cmd_profile_active_set, - NULL, - }, -}; - -static int -ratbag_cmd_profile_enable(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - int rc; - - if (!ratbag_device_has_capability(options->device, - RATBAG_DEVICE_CAP_DISABLE_PROFILE)) - return ERR_UNSUPPORTED; - - ratbag_profile_set_enabled(options->profile, true); - rc = ratbag_device_commit(options->device); - - return rc ? ERR_DEVICE : SUCCESS; -} - -static const struct ratbag_cmd cmd_profile_enable = { - .name = "enable", - .cmd = ratbag_cmd_profile_enable, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_profile_disable(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - int rc; - - if (!ratbag_device_has_capability(options->device, - RATBAG_DEVICE_CAP_DISABLE_PROFILE)) - return ERR_UNSUPPORTED; - - ratbag_profile_set_enabled(options->profile, false); - rc = ratbag_device_commit(options->device); - - return rc ? ERR_DEVICE : SUCCESS; -} - -static const struct ratbag_cmd cmd_profile_disable = { - .name = "disable", - .cmd = ratbag_cmd_profile_disable, - .flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE, - .subcommands = { - NULL, - }, -}; - -static int -ratbag_cmd_profile(const struct ratbag_cmd *cmd, - struct ratbag *ratbag, - struct ratbag_cmd_options *options, - int argc, char **argv) -{ - struct ratbag_profile *profile; - struct ratbag_device *device; - const char *command; - int profile_idx = 0; - char *endp; - - device = options->device; - - if (argc < 1) - return ERR_USAGE; - - command = argv[0]; - - profile_idx = strtol(command, &endp, 10); - if (command != endp && *endp == '\0') { - profile = ratbag_device_get_profile(device, - profile_idx); - if (!profile) { - error("Unable to find profile %d\n", profile_idx); - return ERR_UNSUPPORTED; - } - - argc--; - argv++; - command = argv[0]; - } else { - profile = ratbag_cmd_get_active_profile(device); - if (!profile) - return ERR_DEVICE; - } - - options->profile = profile; - - return run_subcommand(command, - cmd, - ratbag, options, - argc, argv); -} - -static const struct ratbag_cmd cmd_profile = { - .name = "profile", - .cmd = ratbag_cmd_profile, - .flags = FLAG_NEED_DEVICE, - .subcommands = { - &cmd_profile_active, - &cmd_profile_enable, - &cmd_profile_disable, - &cmd_resolution, - &cmd_button, - &cmd_led, - NULL, - }, -}; - -static const struct ratbag_cmd top_level_commands = { - .name = "ratbag-command", - .cmd = NULL, - .subcommands = { - &cmd_info, - &cmd_list, - &cmd_change_button, - &cmd_switch_etekcity, - &cmd_button, - &cmd_resolution, - &cmd_profile, - &cmd_resolution_dpi, - &cmd_resolution_rate, - &cmd_led, - NULL, - }, -}; - -static const struct ratbag_cmd *ratbag_commands = &top_level_commands; - -int -main(int argc, char **argv) -{ - struct ratbag *ratbag; - const char *command; - int rc = SUCCESS; - struct ratbag_cmd_options options = {0}; - - ratbag = ratbag_create_context(&interface, NULL); - if (!ratbag) { - rc = ERR_DEVICE; - error("Failed to initialize ratbag\n"); - goto out; - } - - options.flags = 0; - - while (1) { - int c; - int option_index = 0; - static struct option opts[] = { - { "verbose", optional_argument, 0, OPT_VERBOSE }, - { "version", no_argument, 0, OPT_VERSION }, - { "help", no_argument, 0, OPT_HELP }, - { 0, 0, 0, 0 }, - }; - - c = getopt_long(argc, argv, "+h", opts, &option_index); - if (c == -1) - break; - switch(c) { - case 'h': - case OPT_HELP: - usage(); - goto out; - case OPT_VERSION: - version(); - goto out; - case OPT_VERBOSE: - if (optarg && streq(optarg, "raw")) - options.flags |= FLAG_VERBOSE_RAW; - else - options.flags |= FLAG_VERBOSE; - break; - default: - goto out; - } - } - - if (optind >= argc) { - rc = ERR_USAGE; - goto out; - } - - if (options.flags & FLAG_VERBOSE_RAW) - ratbag_log_set_priority(ratbag, RATBAG_LOG_PRIORITY_RAW); - else if (options.flags & FLAG_VERBOSE) - ratbag_log_set_priority(ratbag, RATBAG_LOG_PRIORITY_DEBUG); - - argc -= optind; - argv += optind; - - command = argv[0]; - rc = run_subcommand(command, - ratbag_commands, - ratbag, - &options, - argc, argv); - - if (options.device) - rc = ratbag_device_commit(options.device); - -out: - ratbag_resolution_unref(options.resolution); - ratbag_button_unref(options.button); - ratbag_led_unref(options.led); - ratbag_profile_unref(options.profile); - ratbag_device_unref(options.device); - ratbag_unref(ratbag); - - if (rc == ERR_USAGE) - usage(); - - return rc; -} diff --git a/tools/ratbag-command.man b/tools/ratbag-command.man deleted file mode 100644 index 2c83961d..00000000 --- a/tools/ratbag-command.man +++ /dev/null @@ -1,144 +0,0 @@ -.TH RATBAG_COMMAND "1" "@version@" -.SH NAME -ratbag\-command \- query or change a device's settings -.SH SYNOPSIS -.B ratbag\-command [OPTIONS] {COMMAND} ... /path/to/device -.SH DESCRIPTION -.PP -The -.I ratbag\-command -tool queries or changes a device's settings. -.PP -This tool usually needs to be run as root to have access to the -/dev/input/eventX nodes. -.SH OPTIONS -.TP 8 -.B \-\-verbose -Print debugging output. -.TP 8 -.B \-\-verbose=raw -Print debugging output with protocol output. No guarantees are given regarding -the output format when this flag is on. -.TP 8 -.B \-\-version -Print the tool's version. -.TP 8 -.B \-\-help -Print the help. -.SH General Commands -.TP 8 -.B list -List supported devices (does not take a device argument) -.SH Device Commands -.TP 8 -.B info -Print information about a device -.SH Profile Commands -.TP 8 -.B profile active get -Print the currently active profile -.TP 8 -.B profile active set N -Set profile N as to the active profile -.TP 8 -.B profile N {COMMAND} -Use profile N for COMMAND -.SH Resolution Commands -Resolution commands work on the given profile, or on the active profile if none -is given. -.TP 8 -.B resolution active get -Print the currently active resolution -.TP 8 -.B resolution active set N -Set resolution N as the active resolution -.TP 8 -.B resolution N {COMMAND} -Use resolution N for COMMAND -.SH DPI Commands -DPI commands work on the given profile and resolution, or on the active -resolution of the active profile if none are given. -.TP 8 -.B dpi get -Print the dpi value -.TP 8 -.B dpi set N -Set the dpi value to N -.TP 8 -.B rate get -Print the report rate in Hz -.TP 8 -.B rate set N -Set the report rate in N Hz -.SH Button Commands -Button commands work on the given profile, or on the active profile if none is -given. -.TP 8 -.B button count -Print the number of buttons -.TP 8 -.B button N action get -Print the button action -.TP 8 -.B button N action set button B -Set the button action to button B -.TP 8 -.B button N action set special S -Set the button action to special action S -.TP 8 -.B button N action set macro ... -Set the button action to the given macro -.PP -.B Macro syntax: -.HP 8 -A macro is a series of key events or waiting periods. Keys must be specified -in linux/input.h key names. -.RS -.TP 8 -.B KEY_A -Press and release 'a' -.TP 8 -.B +KEY_A -Press 'a' -.TP 8 -.B \-KEY_A -Release 'a' -.TP 8 -.B t300 -Wait 300ms -.RE -.SH Special Commands -These commands are for testing purposes and may be removed without notice -.TP 8 -.B switch\-etekcity -Switch the Etekcity mouse active profile -.SH Examples -.TP 8 -ratbag\-command profile active get -.TP 8 -ratbag\-command profile 0 resolution active set 4 -.TP 8 -ratbag\-command profile 0 resolution 1 dpi get -.TP 8 -ratbag\-command resolution 4 rate get -.TP 8 -ratbag\-command dpi set 800 -.SH Exit codes -.TP 8 -.B 0 -Success -.TP 8 -.B 1 -Unsupported feature or index out of available range -.TP 8 -.B 2 -Commandline arguments are invalid -.TP 8 -.B 3 -Invalid device or a command failed on the device -.SH NOTES -.PP -There is currently no guarantees that the output format of -.B ratbag\-command -will not change in the future. There should be some stability with the commands -mentioned in this man page, but do not expect it to stay the same.