diff options
Diffstat (limited to 'rcm-server-main.c')
-rw-r--r-- | rcm-server-main.c | 240 |
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 |