diff options
| -rw-r--r-- | serial/manager.c | 100 | 
1 files changed, 99 insertions, 1 deletions
| diff --git a/serial/manager.c b/serial/manager.c index 15d23a30..c15d102e 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -34,7 +34,10 @@  #include <stdlib.h>  #include <string.h>  #include <unistd.h> +#include <arpa/inet.h>  #include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h>  #include <glib.h> @@ -99,6 +102,7 @@ static struct {  static DBusConnection *connection = NULL;  static GSList *pending_connects = NULL; +static GSList *proxies_paths = NULL;  static int rfcomm_ctl = -1;  static void pending_connect_free(struct pending_connect *pc) @@ -891,10 +895,97 @@ static DBusHandlerResult remove_port(DBusConnection *conn,  	return DBUS_HANDLER_RESULT_HANDLED;  } +static int str2uuid(uuid_t *uuid, const char *string) +{ +	uint16_t data1, data2, data3, data5; +	uint32_t data0, data4; + +	if (strlen(string) == 36 && +			string[8] == '-' && +			string[13] == '-' && +			string[18] == '-' && +			string[23] == '-' && +			sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx", +				&data0, &data1, &data2, &data3, &data4, &data5) == 6) { +		uint8_t val[16]; + +		data0 = htonl(data0); +		data1 = htons(data1); +		data2 = htons(data2); +		data3 = htons(data3); +		data4 = htonl(data4); +		data5 = htons(data5); + +		memcpy(&val[0], &data0, 4); +		memcpy(&val[4], &data1, 2); +		memcpy(&val[6], &data2, 2); +		memcpy(&val[8], &data3, 2); +		memcpy(&val[10], &data4, 4); +		memcpy(&val[14], &data5, 2); + +		sdp_uuid128_create(uuid, val); + +		return 0; +	} + +	return -1; +} +  static DBusHandlerResult create_proxy(DBusConnection *conn,  				DBusMessage *msg, void *data)  { -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	char path[MAX_PATH_LENGTH]; +	const char *uuidstr, *tty, *ppath = path; +	DBusMessage *reply; +	GSList *l; +	DBusError derr; +	struct stat st; +	uuid_t uuid; +	int pos = 0; + +	dbus_error_init(&derr); +	if (!dbus_message_get_args(msg, &derr, +				DBUS_TYPE_STRING, &uuidstr, +				DBUS_TYPE_STRING, &tty, +				DBUS_TYPE_INVALID)) { +		err_invalid_args(conn, msg, derr.message); +		dbus_error_free(&derr); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	if (str2uuid(&uuid, uuidstr) < 0) +		return err_invalid_args(conn, msg, "Invalid UUID"); + +	sscanf(tty, "/dev/%n", &pos); +	if (!pos || stat(tty, &st) < 0) +		return err_invalid_args(conn, msg, "Invalid TTY"); + +	snprintf(path, MAX_PATH_LENGTH - 1, +			"/org/bluez/serial/proxy%s", tty + pos); + +	l = g_slist_find_custom(proxies_paths, path, (GCompareFunc) strcmp); +	if (l) +		return err_already_exists(conn, msg, "Proxy already exists"); + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	/* FIXME: Register the proxy object */ +	/* FIXME: persistent storage */ + +	proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); + +	dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, +			SERIAL_MANAGER_INTERFACE, "ProxyCreated", +			DBUS_TYPE_STRING, &ppath, +			DBUS_TYPE_INVALID); + +	dbus_message_append_args(reply, +			DBUS_TYPE_STRING, &ppath, +			DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply);  }  static DBusHandlerResult list_proxies(DBusConnection *conn, @@ -1086,6 +1177,13 @@ static void manager_unregister(DBusConnection *conn, void *data)  		pending_connects = NULL;  	} +	if (proxies_paths) { +		g_slist_foreach(proxies_paths, +				(GFunc) g_free, NULL); +		g_slist_free(proxies_paths); +		proxies_paths = NULL; +	} +  	/* Unregister all paths in serial hierarchy */  	if (!dbus_connection_list_registered(conn, SERIAL_MANAGER_PATH, &dev))  		return; | 
