summaryrefslogtreecommitdiff
path: root/rcm-server-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'rcm-server-main.c')
-rw-r--r--rcm-server-main.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/rcm-server-main.c b/rcm-server-main.c
index 2a3266f..266658f 100644
--- a/rcm-server-main.c
+++ b/rcm-server-main.c
@@ -192,6 +192,245 @@ out:
return sd_bus_error_set_errno(error, r);
}
+static int
+method_setkeymap(sd_bus_message *m, void *userdata, sd_bus_error *error)
+{
+ _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ struct manager *mgr = userdata;
+ struct device *dev;
+ struct keymap *keymap;
+ const char *id;
+ const char *name;
+ const char *description;
+ uint16_t cols, rows;
+ int r;
+
+ dev = find_device_by_path(mgr, sd_bus_message_get_path(m));
+ if (!dev)
+ return sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidDevice", "Sorry, invalid device");
+
+ r = sd_bus_message_read(m, "sssqq", &id, &name, &description, &cols, &rows);
+ if (r < 0) {
+ fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
+ goto out;
+ }
+
+ keymap = find_keymap_by_id(dev, id);
+ if (!keymap)
+ return sd_bus_error_set_const(error, "org.gnome.RemoteControlManager.InvalidKeymap", "Sorry, unknown keymap");
+
+ printf("Asked to update keymap\n");
+ printf("\tID : %s\n", id);
+ printf("\tName: %s\n", name);
+ printf("\tDesc: %s\n", description);
+ printf("\tCols: %u\n", cols);
+ printf("\tRows: %u\n", rows);
+
+ printf("\tKeymap:\n");
+ r = sd_bus_message_enter_container(m, 'a', "a{sv}");
+ if (r < 0)
+ goto out;
+
+ while ((r = sd_bus_message_enter_container(m, 'a', "{sv}")) > 0) {
+ const char *protocol;
+ uint64_t scancode;
+ const char *keycode;
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ const char *name;
+ const char *contents;
+ char type;
+
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, NULL, &contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ goto out;
+
+ if (!strcmp(name, "protocol")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for protocol (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &protocol);
+ if (r < 0)
+ goto out;
+
+ } else if (!strcmp(name, "scancode")) {
+ if (type != SD_BUS_TYPE_UINT64) {
+ printf("Invalid type for scancode (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &scancode);
+ if (r < 0)
+ goto out;
+
+ } else if (!strcmp(name, "keycode")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for keycode (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &keycode);
+ if (r < 0)
+ goto out;
+
+ } else {
+ r = sd_bus_message_skip(reply, contents);
+ if (r < 0)
+ goto out;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ printf("\t\t%s:%" PRIx64 ":%s\n", protocol, scancode, keycode);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ printf("\tLayout:\n");
+ r = sd_bus_message_enter_container(m, 'a', "a{sv}");
+ if (r < 0)
+ goto out;
+
+ while ((r = sd_bus_message_enter_container(m, 'a', "{sv}")) > 0) {
+ bool blank = false;
+ bool button = false;
+ const char *keycode = NULL;
+
+ while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+ const char *name;
+ const char *contents;
+ const char *button_type;
+ char type;
+
+ r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, NULL, &contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ goto out;
+
+ if (!strcmp(name, "type")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for type (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &button_type);
+ if (r < 0)
+ goto out;
+
+ if (!strcasecmp(button_type, "button"))
+ button = true;
+ else if (!strcasecmp(button_type, "blank"))
+ blank = true;
+ else {
+ printf("Invalid button type: %s\n", button_type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ } else if (!strcmp(name, "keycode")) {
+ if (type != SD_BUS_TYPE_STRING) {
+ printf("Invalid type for keycode (%c)\n", type);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = sd_bus_message_read_basic(m, type, &keycode);
+ if (r < 0)
+ goto out;
+
+ } else {
+ r = sd_bus_message_skip(reply, contents);
+ if (r < 0)
+ goto out;
+ }
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ if ((!blank && !button) || (blank && button) || (button && !keycode)) {
+ printf("Invalid layout specification\n");
+ r = -EINVAL;
+ goto out;
+ }
+
+ printf("\t\tButton: %s\n", button ? keycode : "blank");
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+ }
+
+ if (r < 0)
+ goto out;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ goto out;
+
+ /* FIXME: save the result */
+ return sd_bus_reply_method_return(m, NULL);
+
+out:
+ return sd_bus_error_set_errno(error, r);
+}
+
static const sd_bus_vtable device_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("DriverName", "s", property_get, 0, 0),
@@ -199,6 +438,7 @@ static const sd_bus_vtable device_vtable[] = {
SD_BUS_PROPERTY("HardwareType", "s", property_get, 0, 0),
SD_BUS_METHOD("ListKeymaps", NULL, "as", method_listkeymaps, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetKeymap", "s", "ssqqaa{sv}aa{sv}", method_getkeymap, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetKeymap", "sssqqaa{sv}aa{sv}", NULL, method_setkeymap, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("KeyPressed", "s", 0),
SD_BUS_SIGNAL("KeyReleased", "s", 0),
SD_BUS_VTABLE_END