Export button mappings over dbus

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer
2016-02-23 14:37:29 +10:00
parent 2fad2e3ccd
commit 8e8d827e00
3 changed files with 652 additions and 1 deletions

View File

@@ -715,6 +715,176 @@ static int show_profile_print_resolutions(struct ratbagctl *ctl,
return 0;
}
static int show_profile_print_button(struct ratbagctl *ctl, const char *path)
{
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
unsigned int prop_index = -1,
prop_btnmap = -1;
unsigned int prop_keymap[20] = {0};
const char *prop_type,
*prop_action_type,
*prop_special;
const char *prop_action_types[20] = {0};
unsigned int idx = 0;
unsigned int modmap = 0;
int r;
r = sd_bus_call_method(ctl->bus,
"org.freedesktop.ratbag1",
path,
"org.freedesktop.DBus.Properties",
"GetAll",
&error,
&reply,
"s",
"org.freedesktop.ratbag1.Button");
if (r < 0)
goto exit;
r = sd_bus_message_enter_container(reply, 'a', "{sv}");
if (r < 0)
goto exit;
while ((r = sd_bus_message_enter_container(reply, 'e', "sv")) > 0) {
const char *property;
r = sd_bus_message_read_basic(reply, 's', &property);
if (r < 0)
goto exit;
if (streq(property, "Index")) {
r = sd_bus_message_read(reply, "v", "u",
&prop_index);
} else if (streq(property, "Type")) {
r = sd_bus_message_read(reply, "v", "s",
&prop_type);
} else if (streq(property, "ButtonMapping")) {
r = sd_bus_message_read(reply, "v", "u",
&prop_btnmap);
} else if (streq(property, "SpecialMapping")) {
r = sd_bus_message_read(reply, "v", "s",
&prop_special);
} else if (streq(property, "KeyMapping")) {
r = sd_bus_message_enter_container(reply, 'v', "au");
if (r < 0)
goto exit;
r = sd_bus_message_enter_container(reply, 'a', "u");
if (r < 0)
goto exit;
idx = 0;
while ((r = sd_bus_message_read_basic(reply, 'u',
&prop_keymap[idx++])) > 0)
;
r = sd_bus_message_exit_container(reply);
if (r < 0)
goto exit;
r = sd_bus_message_exit_container(reply);
if (r < 0)
goto exit;
} else if (streq(property, "ActionType")) {
r = sd_bus_message_read(reply, "v", "s",
&prop_action_type);
} else if (streq(property, "ActionTypes")) {
r = sd_bus_message_enter_container(reply, 'v', "as");
if (r < 0)
goto exit;
r = sd_bus_message_enter_container(reply, 'a', "s");
if (r < 0)
goto exit;
idx = 0;
while ((r = sd_bus_message_read_basic(reply, 's',
&prop_action_types[idx++])) > 0)
;
r = sd_bus_message_exit_container(reply);
if (r < 0)
goto exit;
r = sd_bus_message_exit_container(reply);
if (r < 0)
goto exit;
} else {
r = sd_bus_message_skip(reply, "v");
}
if (r < 0)
goto exit;
r = sd_bus_message_exit_container(reply);
if (r < 0)
goto exit;
}
if (r < 0)
goto exit;
r = sd_bus_message_rewind(reply, 0);
if (r < 0)
goto exit;
printf("button-%u\n", prop_index);
printf("\t Index: %u\n", prop_index);
printf("\t Type: %s\n", prop_type);
printf("\t Action type: %s\n", prop_action_type);
idx = 0;
printf("\t Action types: ");
while ((prop_action_type = prop_action_types[idx++]) != NULL)
printf("%s ", prop_action_type);
printf("\n");
printf("\t Special mapping: %s\n", prop_special);
printf("\t Button mapping: %d\n", prop_btnmap);
printf("\t Key mapping: %d (", prop_keymap[0]);
idx = 1;
if (prop_keymap[1] == 0) {
printf("no modifiers");
} else {
printf("modifiers ");
while ((modmap = prop_keymap[idx++]) != 0)
printf("%d ", modmap);
}
printf(")\n");
exit:
if (r < 0)
fprintf(stderr, "Cannot show button: %s\n",
error.message ? : "Parser error");
return r;
}
static int show_profile_print_buttons(struct ratbagctl *ctl,
sd_bus_message *m)
{
const char *button;
int r;
r = sd_bus_message_enter_container(m, 'v', "ao");
if (r < 0)
return r;
r = sd_bus_message_enter_container(m, 'a', "o");
if (r < 0)
return r;
while ((r = sd_bus_message_read_basic(m, 'o', &button)) > 0)
show_profile_print_button(ctl, button);
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return 0;
}
static int show_profile_print(struct ratbagctl *ctl,
const char *device,
const char *profile)
@@ -795,6 +965,8 @@ static int show_profile_print(struct ratbagctl *ctl,
reply,
prop_active_resolution,
prop_default_resolution);
} else if (streq(property, "Buttons")) {
r = show_profile_print_buttons(ctl, reply);
} else {
r = sd_bus_message_skip(reply, "v");
}

View File

@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include <linux/input.h>
#include "ratbagd.h"
#include "shared-macro.h"
@@ -40,9 +41,453 @@ struct ratbagd_button {
char *path;
};
static int ratbagd_button_get_type(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
const char *type = NULL;
enum ratbag_button_type t;
t = ratbag_button_get_type(button->lib_button);
switch(t) {
default:
log_error("Unknown button type %d\n", t);
/* fallthrough */
case RATBAG_BUTTON_TYPE_UNKNOWN:
type = "unknown";
break;
case RATBAG_BUTTON_TYPE_LEFT:
type = "left";
break;
case RATBAG_BUTTON_TYPE_MIDDLE:
type = "middle";
break;
case RATBAG_BUTTON_TYPE_RIGHT:
type = "right";
break;
case RATBAG_BUTTON_TYPE_THUMB:
type = "thumb";
break;
case RATBAG_BUTTON_TYPE_THUMB2:
type = "thumb2";
break;
case RATBAG_BUTTON_TYPE_THUMB3:
type = "thumb3";
break;
case RATBAG_BUTTON_TYPE_THUMB4:
type = "thumb4";
break;
case RATBAG_BUTTON_TYPE_WHEEL_LEFT:
type = "wheel_left";
break;
case RATBAG_BUTTON_TYPE_WHEEL_RIGHT:
type = "wheel_right";
break;
case RATBAG_BUTTON_TYPE_WHEEL_CLICK:
type = "wheel_click";
break;
case RATBAG_BUTTON_TYPE_WHEEL_UP:
type = "wheel_up";
break;
case RATBAG_BUTTON_TYPE_WHEEL_DOWN:
type = "wheel_down";
break;
case RATBAG_BUTTON_TYPE_WHEEL_RATCHET_MODE_SHIFT:
type = "wheel_ratchet_mode_shift";
break;
case RATBAG_BUTTON_TYPE_EXTRA:
type = "extra";
break;
case RATBAG_BUTTON_TYPE_SIDE:
type = "side";
break;
case RATBAG_BUTTON_TYPE_PINKIE:
type = "pinkie";
break;
case RATBAG_BUTTON_TYPE_PINKIE2:
type = "pinkie2";
break;
case RATBAG_BUTTON_TYPE_RESOLUTION_CYCLE_UP:
type = "resolution_cycle_up";
break;
case RATBAG_BUTTON_TYPE_RESOLUTION_UP:
type = "resolution_up";
break;
case RATBAG_BUTTON_TYPE_RESOLUTION_DOWN:
type = "resolution_down";
break;
case RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP:
type = "profile_cycle_up";
break;
case RATBAG_BUTTON_TYPE_PROFILE_UP:
type = "profile_up";
break;
case RATBAG_BUTTON_TYPE_PROFILE_DOWN:
type = "profile_down";
break;
}
return sd_bus_message_append(reply, "s", type);
}
static int ratbagd_button_get_button(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
unsigned int b;
b = ratbag_button_get_button(button->lib_button);
return sd_bus_message_append(reply, "u", b);
}
static int ratbagd_button_set_button(sd_bus_message *m,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
unsigned int map;
int r;
r = sd_bus_message_read(m, "u", &map);
if (r < 0)
return r;
if (map == 0 || map > 30)
return 0;
r = ratbag_button_set_button(button->lib_button, map);
return sd_bus_reply_method_return(m, "u", r);
}
static int ratbagd_button_get_special(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
const char *type;
enum ratbag_button_action_special special;
special = ratbag_button_get_special(button->lib_button);
switch(special) {
default:
log_error("Unknown special type %d\n", special);
case RATBAG_BUTTON_ACTION_SPECIAL_UNKNOWN:
type = "unknown";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_INVALID:
type = "n/a";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_DOUBLECLICK:
type = "doubleclick";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT:
type = "wheel-left";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT:
type = "wheel-right";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP:
type = "wheel-up";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN:
type = "wheel-down";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_RATCHET_MODE_SWITCH:
type = "ratchet-mode-switch";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP:
type = "resolution-cycle-up";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP:
type = "resolution-up";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN:
type = "resolution-down";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_ALTERNATE:
type = "resolution-alternate";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DEFAULT:
type = "resolution-default";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP:
type = "profile-cycle-up";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_UP:
type = "profile-up";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_DOWN:
type = "profile-down";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_SECOND_MODE:
type = "second-mode";
break;
case RATBAG_BUTTON_ACTION_SPECIAL_BATTERY_LEVEL:
type = "battery-level";
break;
}
return sd_bus_message_append(reply, "s", type);
}
static int ratbagd_button_set_special(sd_bus_message *m,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
const char *s;
enum ratbag_button_action_special special;
int r;
r = sd_bus_message_read(m, "s", &s);
if (r < 0)
return r;
if (streq(s, "doubleclick"))
special = RATBAG_BUTTON_ACTION_SPECIAL_DOUBLECLICK;
else if (streq(s, "wheel-left"))
special = RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT;
else if (streq(s, "wheel-right"))
special = RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT;
else if (streq(s, "wheel-up"))
special = RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP;
else if (streq(s, "wheel-down"))
special = RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN;
else if (streq(s, "ratchet-mode-switch"))
special = RATBAG_BUTTON_ACTION_SPECIAL_RATCHET_MODE_SWITCH;
else if (streq(s, "resolution-cycle-up"))
special = RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP;
else if (streq(s, "resolution-up"))
special = RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP;
else if (streq(s, "resolution-down"))
special = RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN;
else if (streq(s, "resolution-alternate"))
special = RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_ALTERNATE;
else if (streq(s, "resolution-default"))
special = RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DEFAULT;
else if (streq(s, "profile-cycle-up"))
special = RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP;
else if (streq(s, "profile-up"))
special = RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_UP;
else if (streq(s, "profile-down"))
special = RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_DOWN;
else if (streq(s, "second-mode"))
special = RATBAG_BUTTON_ACTION_SPECIAL_SECOND_MODE;
else if (streq(s, "battery-level"))
special = RATBAG_BUTTON_ACTION_SPECIAL_BATTERY_LEVEL;
else {
log_error("Unknown button special action %s\n", s);
return 0;
}
r = ratbag_button_set_special(button->lib_button, special);
return sd_bus_reply_method_return(m, "u", r);
}
static int ratbagd_button_get_key(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
unsigned int key;
unsigned int modifiers[10] = {0};
size_t nmodifiers = ELEMENTSOF(modifiers);
size_t i;
int r;
/* Return an array with the first element the key, the rest
are modifiers (or 0 if unset). If no key is set, the array is
just [0] */
r = sd_bus_message_open_container(reply, 'a', "u");
if (r < 0)
return r;
key = ratbag_button_get_key(button->lib_button,
modifiers,
&nmodifiers);
r = sd_bus_message_append(reply, "u", key);
if (r < 0)
return r;
if (key == 0)
nmodifiers = 0;
for (i = 0; i < nmodifiers; i++) {
r = sd_bus_message_append(reply, "u", modifiers[0]);
if (r < 0)
return r;
}
return sd_bus_message_close_container(reply);
}
static int ratbagd_button_set_key(sd_bus_message *m,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
unsigned int key;
size_t nmodifiers = 10;
unsigned int modifiers[nmodifiers];
int r;
/* Expect an array with the first element the key, the rest
are modifiers (or 0 if unset). */
r = sd_bus_message_enter_container(m, 'a', "u");
if (r < 0)
return r;
r = sd_bus_message_read(m, "u", &key);
if (r < 0)
return r;
nmodifiers = 0;
while ((r = sd_bus_message_read_basic(m, 'u',
&modifiers[nmodifiers++])) > 0)
;
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
r = ratbag_button_set_key(button->lib_button, key, modifiers, nmodifiers);
return sd_bus_reply_method_return(m, "u", r);
}
static int ratbagd_button_get_action_type(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
const char *type;
switch (ratbag_button_get_action_type(button->lib_button)) {
case RATBAG_BUTTON_ACTION_TYPE_NONE:
type = "none";
break;
case RATBAG_BUTTON_ACTION_TYPE_BUTTON:
type = "button";
break;
case RATBAG_BUTTON_ACTION_TYPE_KEY:
type = "key";
break;
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
type = "special";
break;
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
type = "macro";
break;
case RATBAG_BUTTON_ACTION_TYPE_UNKNOWN:
type = "unknown";
break;
}
return sd_bus_message_append(reply, "s", type);
}
static int ratbagd_button_get_action_types(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
const char *types[5] = {NULL};
const char **t;
int idx = 0;
int r;
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
if (ratbag_button_has_action_type(button->lib_button,
RATBAG_BUTTON_ACTION_TYPE_BUTTON))
types[idx++] = "button";
if (ratbag_button_has_action_type(button->lib_button,
RATBAG_BUTTON_ACTION_TYPE_KEY))
types[idx++] = "key";
if (ratbag_button_has_action_type(button->lib_button,
RATBAG_BUTTON_ACTION_TYPE_SPECIAL))
types[idx++] = "special";
if (ratbag_button_has_action_type(button->lib_button,
RATBAG_BUTTON_ACTION_TYPE_MACRO))
types[idx++] = "macro";
t = types;
while (*t) {
r = sd_bus_message_append(reply, "s", *t);
if (r < 0)
return r;
t++;
}
return sd_bus_message_close_container(reply);
}
static int ratbagd_button_disable(sd_bus_message *m,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_button *button = userdata;
int r;
r = sd_bus_message_read(m, "");
if (r < 0)
return r;
r = ratbag_button_disable(button->lib_button);
return sd_bus_reply_method_return(m, "u", r);
}
const sd_bus_vtable ratbagd_button_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_button, index), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Type", "s", ratbagd_button_get_type, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ButtonMapping", "u", ratbagd_button_get_button, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("SpecialMapping", "s", ratbagd_button_get_special, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("KeyMapping", "au", ratbagd_button_get_key, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ActionType", "s", ratbagd_button_get_action_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("ActionTypes", "as", ratbagd_button_get_action_types, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("SetButtonMapping", "u", "u", ratbagd_button_set_button, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetSpecialMapping", "s", "u", ratbagd_button_set_special, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetKeyMapping", "au", "u", ratbagd_button_set_key, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Disable", "", "u", ratbagd_button_disable, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END,
};

View File

@@ -114,6 +114,39 @@ static int ratbagd_profile_get_resolutions(sd_bus *bus,
return sd_bus_message_close_container(reply);
}
static int ratbagd_profile_get_buttons(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_profile *profile = userdata;
struct ratbagd_button *button;
unsigned int i;
int r;
r = sd_bus_message_open_container(reply, 'a', "o");
if (r < 0)
return r;
for (i = 0; i < profile->n_buttons; ++i) {
button = profile->buttons[i];
if (!button)
continue;
r = sd_bus_message_append(reply,
"o",
ratbagd_button_get_path(button));
if (r < 0)
return r;
}
return sd_bus_message_close_container(reply);
}
static int ratbagd_profile_get_active_resolution(sd_bus *bus,
const char *path,
const char *interface,
@@ -239,6 +272,7 @@ const sd_bus_vtable ratbagd_profile_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_profile, index), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Resolutions", "ao", ratbagd_profile_get_resolutions, 0, 0),
SD_BUS_PROPERTY("Buttons", "ao", ratbagd_profile_get_buttons, 0, 0),
SD_BUS_PROPERTY("ActiveResolution", "u", ratbagd_profile_get_active_resolution, 0, 0),
SD_BUS_PROPERTY("DefaultResolution", "u", ratbagd_profile_get_default_resolution, 0, 0),
SD_BUS_METHOD("SetActive", "", "u", ratbagd_profile_set_active, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -482,7 +516,7 @@ int ratbagd_profile_register_buttons(struct sd_bus *bus,
sprintf(index_buffer, "p%u", profile->index);
/* register resolution interfaces */
/* register button interfaces */
r = sd_bus_path_encode_many(&prefix,
"/org/freedesktop/ratbag1/button/%/%",
ratbagd_device_get_name(device),