From 87113c3bda9245ad758ce75d8cec04ca303faed3 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 19 Jan 2007 16:07:37 +0000 Subject: CreateDevice: initial skeleton --- input/input-service.c | 294 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 223 insertions(+), 71 deletions(-) (limited to 'input/input-service.c') diff --git a/input/input-service.c b/input/input-service.c index 35e5306b..4c2105c4 100644 --- a/input/input-service.c +++ b/input/input-service.c @@ -33,6 +33,7 @@ #include "logging.h" #include "input-service.h" #include "glib-ectomy.h" +#include "textfile.h" #include @@ -49,6 +50,25 @@ static DBusConnection *connection = NULL; +struct input_device { + char addr[18]; +}; + +struct input_device *input_device_new(const char *addr) +{ + struct input_device *idev; + + idev = malloc(sizeof(struct input_device)); + if (!idev) + return NULL; + + memset(idev, 0, sizeof(struct input_device)); + + memcpy(idev->addr, addr, 18); + + return idev; +} + /* * Common D-Bus BlueZ input error functions */ @@ -68,98 +88,60 @@ static DBusHandlerResult err_unknown_method(DBusConnection *conn, DBusMessage *m "Unknown input method")); } -/* - * Input Manager methods - */ -struct input_manager { - GList *paths; -}; - -static DBusHandlerResult manager_create_device(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, + const char *str) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return send_message_and_unref(conn, + dbus_message_new_error(msg, + INPUT_ERROR_INTERFACE ".Failed", str)); } -static DBusHandlerResult manager_remove_device(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusHandlerResult err_already_exists(DBusConnection *conn, + DBusMessage *msg, const char *str) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return send_message_and_unref(conn, + dbus_message_new_error(msg, + INPUT_ERROR_INTERFACE ".AlreadyExists", str)); } -static DBusHandlerResult manager_list_devices(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusHandlerResult err_generic(DBusConnection *conn, DBusMessage *msg, + const char *name, const char *str) { - struct input_manager *mgr = data; - DBusMessageIter iter, iter_array; - DBusMessage *reply; - GList *paths; - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, &iter_array); - - for (paths = mgr->paths; paths != NULL; paths = paths->next) { - const char *ppath = paths->data; - dbus_message_iter_append_basic(&iter_array, - DBUS_TYPE_STRING, &ppath); - } - - dbus_message_iter_close_container(&iter, &iter_array); + return send_message_and_unref(conn, + dbus_message_new_error(msg, name, str)); - return send_message_and_unref(conn, reply); } -static DBusHandlerResult manager_message(DBusConnection *conn, - DBusMessage *msg, void *data) +static inline int create_filename(char *buf, size_t size, + bdaddr_t *bdaddr, const char *name) { - const char *path, *iface, *member; + char addr[18]; - path = dbus_message_get_path(msg); - iface = dbus_message_get_interface(msg); - member = dbus_message_get_member(msg); - - /* Catching fallback paths */ - if (strcmp(INPUT_PATH, path) != 0) - return err_unknown_device(conn, msg); - - /* Accept messages from the input manager interface only */ - if (strcmp(INPUT_MANAGER_INTERFACE, iface)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (strcmp(member, "ListDevices") == 0) - return manager_list_devices(conn, msg, data); + ba2str(bdaddr, addr); - if (strcmp(member, "CreateDevice") == 0) - return manager_create_device(conn, msg, data); - - if (strcmp(member, "RemoveDevice") == 0) - return manager_remove_device(conn, msg, data); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return create_name(buf, size, STORAGEDIR, addr, name); } -static void manager_unregister(DBusConnection *conn, void *data) +static int has_hid_record(const char *local, const char *peer) { - struct input_manager *mgr = data; + char filename[PATH_MAX + 1], *str; - info("Unregistered manager path"); + create_name(filename, PATH_MAX, STORAGEDIR, local, "hidd"); - if (mgr->paths) - g_list_foreach(mgr->paths, (GFunc) free, NULL); + str = textfile_get(filename, peer); + if (!str) + return 0; - free(mgr); + free(str); + return 1; } -/* Virtual table to handle manager object path hierarchy */ -static const DBusObjectPathVTable manager_table = { - .message_function = manager_message, - .unregister_function = manager_unregister, -}; +static int search_request(DBusConnection *conn, + DBusMessage *msg, const char *peer) +{ + info("FIXME: service search"); + return 0; +} /* * Input Device methods @@ -260,14 +242,177 @@ static DBusHandlerResult device_message(DBusConnection *conn, return err_unknown_method(conn, msg); } +static DBusHandlerResult device_message(DBusConnection *conn, + DBusMessage *msg, void *data); /* Virtual table to handle device object path hierarchy */ static const DBusObjectPathVTable device_table = { .message_function = device_message, }; +/* + * Input Manager methods + */ +struct input_manager { + char adapter[18]; + GList *paths; +}; + +static int path_addr_cmp(const char *path, const char *addr) +{ + struct input_device *idev; + + if (!dbus_connection_get_object_path_data(connection, path, + (void *) &idev)) + return -1; + + if (!idev) + return -1; + + return strcasecmp(idev->addr, addr); +} + +static DBusHandlerResult manager_create_device(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct input_manager *mgr = data; + struct input_device *idev; + DBusMessage *reply; + DBusError derr; + const char *addr; + const char *keyb_path = "/org/bluez/input/keyboard0"; + GList *path; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &addr, + DBUS_TYPE_INVALID)) { + err_generic(conn, msg, derr.name, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + path = g_list_find_custom(mgr->paths, addr, + (GCompareFunc) path_addr_cmp); + if (path) + return err_already_exists(conn, msg, "Input Already exists"); + + if (!has_hid_record(mgr->adapter, addr)) { + if (search_request(conn, msg, addr) < 0) + return err_failed(conn, msg, "SDP error"); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + idev = input_device_new(addr); + if (!idev) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + reply = dbus_message_new_method_return(msg); + if (!reply) { + free(idev); + return DBUS_HANDLER_RESULT_NEED_MEMORY; + } + + if (!dbus_connection_register_object_path(conn, + keyb_path, &device_table, idev)) { + error("Input device path registration failed"); + free(idev); + return err_failed(conn, msg, "Path registration failed"); + } + + mgr->paths = g_list_append(mgr->paths, strdup(keyb_path)); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &keyb_path, + DBUS_TYPE_INVALID); + + return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult manager_remove_device(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult manager_list_devices(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct input_manager *mgr = data; + DBusMessageIter iter, iter_array; + DBusMessage *reply; + GList *paths; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &iter_array); + + for (paths = mgr->paths; paths != NULL; paths = paths->next) { + const char *ppath = paths->data; + dbus_message_iter_append_basic(&iter_array, + DBUS_TYPE_STRING, &ppath); + } + + dbus_message_iter_close_container(&iter, &iter_array); + + return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult manager_message(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *path, *iface, *member; + + path = dbus_message_get_path(msg); + iface = dbus_message_get_interface(msg); + member = dbus_message_get_member(msg); + + /* Catching fallback paths */ + if (strcmp(INPUT_PATH, path) != 0) + return err_unknown_device(conn, msg); + + /* Accept messages from the input manager interface only */ + if (strcmp(INPUT_MANAGER_INTERFACE, iface)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strcmp(member, "ListDevices") == 0) + return manager_list_devices(conn, msg, data); + + if (strcmp(member, "CreateDevice") == 0) + return manager_create_device(conn, msg, data); + + if (strcmp(member, "RemoveDevice") == 0) + return manager_remove_device(conn, msg, data); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void manager_unregister(DBusConnection *conn, void *data) +{ + struct input_manager *mgr = data; + + info("Unregistered manager path"); + + if (mgr->paths) + g_list_foreach(mgr->paths, (GFunc) free, NULL); + + free(mgr); +} + +/* Virtual table to handle manager object path hierarchy */ +static const DBusObjectPathVTable manager_table = { + .message_function = manager_message, + .unregister_function = manager_unregister, +}; + int input_dbus_init(void) { struct input_manager *mgr; + bdaddr_t sba; + connection = init_dbus(INPUT_SERVICE, NULL, NULL); if (!connection) return -1; @@ -277,6 +422,13 @@ int input_dbus_init(void) mgr = malloc(sizeof(struct input_manager)); memset(mgr, 0, sizeof(struct input_manager)); + /* Get the local adapter */ + if (hci_devba(0, &sba) < 0) { + error("Can't access local adapter"); + return -1; + } + ba2str(&sba, mgr->adapter); + /* Fallback to catch invalid device path */ if (!dbus_connection_register_fallback(connection, INPUT_PATH, &manager_table, mgr)) { -- cgit