From be94d76f2545a897c31cb14cd76b7125b6d100eb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 01:25:50 +0000 Subject: Add serial subdirectory --- serial/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 serial/Makefile.am (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am new file mode 100644 index 00000000..02742923 --- /dev/null +++ b/serial/Makefile.am @@ -0,0 +1,2 @@ + +MAINTAINERCLEANFILES = Makefile.in -- cgit From e6fe40e5e92a6942869a2fc7e7cb210d18da3929 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Feb 2007 00:15:27 +0000 Subject: Add skeleton for serial port service --- serial/Makefile.am | 11 ++++++++++ serial/main.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 serial/main.c (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 02742923..7cb86842 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -1,2 +1,13 @@ +noinst_PROGRAMS = bluetoothd-service-serial + +bluetoothd_service_serial_SOURCES = main.c + +LDADD = $(top_builddir)/common/libhelper.a \ + @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ + +AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ + +INCLUDES = -I$(top_srcdir)/common + MAINTAINERCLEANFILES = Makefile.in diff --git a/serial/main.c b/serial/main.c new file mode 100644 index 00000000..b6f52d46 --- /dev/null +++ b/serial/main.c @@ -0,0 +1,60 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "logging.h" + +static void sig_term(int sig) +{ +} + +int main(int argc, char *argv[]) +{ + struct sigaction sa; + + start_logging("serial", "Bluetooth Serial Port daemon"); + + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_NOCLDSTOP; + sa.sa_handler = sig_term; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + + enable_debug(); + + info("Exit"); + + stop_logging(); + + return 0; +} -- cgit From 6dc594dbea588a7285dff7eac35d1c0c3fca206d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 23 Apr 2007 17:12:00 +0000 Subject: Add skeleton for manager interface --- serial/Makefile.am | 2 +- serial/main.c | 2 ++ serial/manager.c | 26 ++++++++++++++++++++++++++ serial/manager.h | 22 ++++++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 serial/manager.c create mode 100644 serial/manager.h (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 7cb86842..e8fd392c 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -1,7 +1,7 @@ noinst_PROGRAMS = bluetoothd-service-serial -bluetoothd_service_serial_SOURCES = main.c +bluetoothd_service_serial_SOURCES = main.c manager.h manager.c LDADD = $(top_builddir)/common/libhelper.a \ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ diff --git a/serial/main.c b/serial/main.c index b6f52d46..d249e672 100644 --- a/serial/main.c +++ b/serial/main.c @@ -30,6 +30,8 @@ #include "logging.h" +#include "manager.h" + static void sig_term(int sig) { } diff --git a/serial/manager.c b/serial/manager.c new file mode 100644 index 00000000..2f4ab59e --- /dev/null +++ b/serial/manager.c @@ -0,0 +1,26 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif diff --git a/serial/manager.h b/serial/manager.h new file mode 100644 index 00000000..e87dd676 --- /dev/null +++ b/serial/manager.h @@ -0,0 +1,22 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ -- cgit From 712a6619937ca6109be36f3b764da6c388a0b487 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 23 Apr 2007 17:16:10 +0000 Subject: Add API description file --- serial/Makefile.am | 2 ++ serial/serial-api.txt | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 serial/serial-api.txt (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index e8fd392c..24506088 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -10,4 +10,6 @@ AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ INCLUDES = -I$(top_srcdir)/common +EXTRA_DIST = serial-api.txt + MAINTAINERCLEANFILES = Makefile.in diff --git a/serial/serial-api.txt b/serial/serial-api.txt new file mode 100644 index 00000000..d85acf2d --- /dev/null +++ b/serial/serial-api.txt @@ -0,0 +1,12 @@ +Bluetooth serial service API description +**************************************** + +Copyright (C) 2006-2007 Marcel Holtmann + + +Manager hierarchy +================= + +Service org.bluez.serial +Interface org.bluez.serial.Manager +Object path /org/bluez/serial -- cgit From cdb1b7c3435688bc6f30a3953f1152247ec51b95 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 11:23:55 +0000 Subject: serial: added main loop integration --- serial/main.c | 32 ++++++++++++++++++++++++++++++++ serial/manager.c | 19 +++++++++++++++++++ serial/manager.h | 3 +++ 3 files changed, 54 insertions(+) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index d249e672..5bacd121 100644 --- a/serial/main.c +++ b/serial/main.c @@ -25,19 +25,26 @@ #include #endif +#include #include #include +#include #include "logging.h" +#include "dbus.h" #include "manager.h" +static GMainLoop *main_loop; + static void sig_term(int sig) { + g_main_loop_quit(main_loop); } int main(int argc, char *argv[]) { + DBusConnection *conn; struct sigaction sa; start_logging("serial", "Bluetooth Serial Port daemon"); @@ -54,6 +61,31 @@ int main(int argc, char *argv[]) enable_debug(); + main_loop = g_main_loop_new(NULL, FALSE); + + conn = dbus_bus_system_setup_with_main_loop(NULL, NULL, NULL); + if (!conn) { + g_main_loop_unref(main_loop); + exit(EXIT_FAILURE); + } + + if (serial_init(conn) < 0) { + dbus_connection_unref(conn); + g_main_loop_unref(main_loop); + exit(EXIT_FAILURE); + } + + if (argc > 1 && !strcmp(argv[1], "-s")) + register_external_service(conn, "serial", "Serial service", ""); + + g_main_loop_run(main_loop); + + serial_exit(); + + dbus_connection_unref(conn); + + g_main_loop_unref(main_loop); + info("Exit"); stop_logging(); diff --git a/serial/manager.c b/serial/manager.c index 2f4ab59e..79601624 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -24,3 +24,22 @@ #ifdef HAVE_CONFIG_H #include #endif + +#include "dbus.h" + +#include "manager.h" + +static DBusConnection *connection = NULL; + +int serial_init(DBusConnection *conn) +{ + connection = dbus_connection_ref(conn); + + return 0; +} + +void serial_exit(void) +{ + dbus_connection_unref(connection); + connection = NULL; +} diff --git a/serial/manager.h b/serial/manager.h index e87dd676..f09aa294 100644 --- a/serial/manager.h +++ b/serial/manager.h @@ -20,3 +20,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + +int serial_init(DBusConnection *conn); +void serial_exit(void); -- cgit From 7c21f8711c39949419c35aba60b007d1b9d2b1d5 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 11:50:48 +0000 Subject: serial: added manager methods skeleton --- serial/manager.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 79601624..ee250b37 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -25,21 +25,107 @@ #include #endif +#include +#include + #include "dbus.h" +#include "logging.h" #include "manager.h" +#define SERIAL_PATH "/org/bluez/serial" +#define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" +#define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" + static DBusConnection *connection = NULL; +DBusHandlerResult err_unknown_port(DBusConnection *conn, DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".UnknownPort", + "Unknown port path")); +} + +static DBusHandlerResult create_port(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult remove_port(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult list_ports(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +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(SERIAL_PATH, path) != 0) + return err_unknown_port(conn, msg); + + /* Accept messages from the manager interface only */ + if (strcmp(SERIAL_MANAGER_INTERFACE, iface)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strcmp(member, "CreatePort") == 0) + return create_port(conn, msg, data); + + if (strcmp(member, "RemovePort") == 0) + return remove_port(conn, msg, data); + + if (strcmp(member, "ListPorts") == 0) + return list_ports(conn, msg, data); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void manager_unregister(DBusConnection *conn, void *data) +{ +} + +/* Virtual table to handle manager object path hierarchy */ +static const DBusObjectPathVTable manager_table = { + .message_function = manager_message, + .unregister_function = manager_unregister, +}; + int serial_init(DBusConnection *conn) { connection = dbus_connection_ref(conn); + /* Fallback to catch invalid serial path */ + if (dbus_connection_register_fallback(connection, SERIAL_PATH, + &manager_table, NULL) == FALSE) { + error("D-Bus failed to register %s path", SERIAL_PATH); + dbus_connection_unref(connection); + + return -1; + } + + info("Registered manager path:%s", SERIAL_PATH); + return 0; } void serial_exit(void) { + dbus_connection_unregister_object_path(connection, SERIAL_PATH); + dbus_connection_unref(connection); connection = NULL; } -- cgit From 701245f0971feee4f41ef8ec03a4f03265c3c9d9 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 13:56:28 +0000 Subject: serial: added port methods skeleton --- serial/manager.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 155 insertions(+), 10 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index ee250b37..b93069e2 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -26,20 +26,60 @@ #endif #include +#include +#include #include +#include #include "dbus.h" #include "logging.h" #include "manager.h" -#define SERIAL_PATH "/org/bluez/serial" +#define SERIAL_MANAGER_PATH "/org/bluez/serial" +#define SERIAL_PORT_PATH "/org/bluez/serial/port" #define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" +#define SERIAL_PORT_INTERFACE "org.bluez.serial.Port" #define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" +#define PATH_LENGTH 32 + static DBusConnection *connection = NULL; +static GSList *port_paths = NULL; +static unsigned int next_id = 0; + +struct serial_port { + char *owner; + int16_t id; /* Device id */ +}; + +static void serial_port_free(struct serial_port *sp) +{ + if (!sp) + return; + if (sp->owner) + g_free(sp->owner); + g_free(sp); +} + +DBusHandlerResult err_failed(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".Failed", str)); +} -DBusHandlerResult err_unknown_port(DBusConnection *conn, DBusMessage *msg) +static DBusHandlerResult err_invalid_args(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); +} + +static DBusHandlerResult err_unknown_port(DBusConnection *conn, + DBusMessage *msg) { return send_message_and_unref(conn, dbus_message_new_error(msg, @@ -47,12 +87,117 @@ DBusHandlerResult err_unknown_port(DBusConnection *conn, DBusMessage *msg) "Unknown port path")); } -static DBusHandlerResult create_port(DBusConnection *conn, +static DBusHandlerResult port_connect(DBusConnection *conn, DBusMessage *msg, void *data) { return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } +static DBusHandlerResult port_disconnect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult port_message(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *iface, *member; + + iface = dbus_message_get_interface(msg); + member = dbus_message_get_member(msg); + + /* Accept messages from the port interface only */ + if (strcmp(SERIAL_PORT_INTERFACE, iface)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strcmp(member, "Connect") == 0) + return port_connect(conn, msg, data); + + if (strcmp(member, "Disconnect") == 0) + return port_disconnect(conn, msg, data); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void port_unregister(DBusConnection *conn, void *data) +{ + serial_port_free(data); +} + +/* Virtual table to handle port object path hierarchy */ +static const DBusObjectPathVTable port_table = { + .message_function = port_message, + .unregister_function = port_unregister, +}; + +static int port_register(DBusConnection *conn, + const char *path, const char *owner) +{ + struct serial_port *sp; + + if (!conn) + return -1; + + sp = g_new0(struct serial_port, 1); + + /* FIXME: Create the RFCOMM device node */ + sp->id = -1; + sp->owner = g_strdup(owner); + + /* Register path */ + if (!dbus_connection_register_object_path(conn, path, + &port_table, sp)) { + serial_port_free(sp); + return -1; + } + + info("Registered serial port path:%s", path); + + return 0; +} + +static DBusHandlerResult create_port(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + char port_path[PATH_LENGTH]; + DBusMessage *reply; + DBusError derr; + const char *addr; + const char *pattern; + + /* FIXME: Check if it already exist */ + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &addr, + DBUS_TYPE_STRING, &pattern, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + /* Pattern can be a service or a channel */ + + /* FIXME: Missing SDP search */ + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + snprintf(port_path, PATH_LENGTH, SERIAL_PORT_PATH"%d", next_id++); + + if (port_register(conn, port_path, dbus_message_get_sender(msg)) < 0) { + dbus_message_unref(reply); + return err_failed(conn, msg, "D-Bus path registration failed"); + } + + port_paths = g_slist_append(port_paths, g_strdup(port_path)); + + return send_message_and_unref(conn, reply); +} + static DBusHandlerResult remove_port(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -75,7 +220,7 @@ static DBusHandlerResult manager_message(DBusConnection *conn, member = dbus_message_get_member(msg); /* Catching fallback paths */ - if (strcmp(SERIAL_PATH, path) != 0) + if (strcmp(SERIAL_MANAGER_PATH, path) != 0) return err_unknown_port(conn, msg); /* Accept messages from the manager interface only */ @@ -100,8 +245,8 @@ static void manager_unregister(DBusConnection *conn, void *data) /* Virtual table to handle manager object path hierarchy */ static const DBusObjectPathVTable manager_table = { - .message_function = manager_message, - .unregister_function = manager_unregister, + .message_function = manager_message, + .unregister_function = manager_unregister, }; int serial_init(DBusConnection *conn) @@ -109,22 +254,22 @@ int serial_init(DBusConnection *conn) connection = dbus_connection_ref(conn); /* Fallback to catch invalid serial path */ - if (dbus_connection_register_fallback(connection, SERIAL_PATH, + if (dbus_connection_register_fallback(connection, SERIAL_MANAGER_PATH, &manager_table, NULL) == FALSE) { - error("D-Bus failed to register %s path", SERIAL_PATH); + error("D-Bus failed to register %s path", SERIAL_MANAGER_PATH); dbus_connection_unref(connection); return -1; } - info("Registered manager path:%s", SERIAL_PATH); + info("Registered manager path:%s", SERIAL_MANAGER_PATH); return 0; } void serial_exit(void) { - dbus_connection_unregister_object_path(connection, SERIAL_PATH); + dbus_connection_unregister_object_path(connection, SERIAL_MANAGER_PATH); dbus_connection_unref(connection); connection = NULL; -- cgit From d9b667c2cae88ead3efa166fef6580170dc8936d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 16:35:58 +0000 Subject: serial: added RemovePort --- serial/manager.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index b93069e2..6b10c13d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -62,7 +62,16 @@ static void serial_port_free(struct serial_port *sp) g_free(sp); } -DBusHandlerResult err_failed(DBusConnection *conn, +static DBusHandlerResult err_does_not_exist(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".DoesNotExist", + "Port doesn't exist")); +} + +static DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, const char *str) { return send_message_and_unref(conn, @@ -120,15 +129,16 @@ static DBusHandlerResult port_message(DBusConnection *conn, return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static void port_unregister(DBusConnection *conn, void *data) +static void port_handler_unregister(DBusConnection *conn, void *data) { + /* FIXME: Disconnect if applied */ serial_port_free(data); } /* Virtual table to handle port object path hierarchy */ static const DBusObjectPathVTable port_table = { .message_function = port_message, - .unregister_function = port_unregister, + .unregister_function = port_handler_unregister, }; static int port_register(DBusConnection *conn, @@ -136,8 +146,8 @@ static int port_register(DBusConnection *conn, { struct serial_port *sp; - if (!conn) - return -1; + if (!conn || !owner) + return -EINVAL; sp = g_new0(struct serial_port, 1); @@ -157,6 +167,27 @@ static int port_register(DBusConnection *conn, return 0; } +static int port_unregister(DBusConnection *conn, + const char *path, const char *owner) +{ + struct serial_port *sp; + + if (!conn || !owner) + return -EINVAL; + + if (!dbus_connection_get_object_path_data(conn, path, (void *) &sp) || !sp) + return -ENOENT; + + if (strcmp(sp->owner, owner) != 0) + return -EACCES; + + /* FIXME: If it is connected return EPERM or disconnect */ + + dbus_connection_unregister_object_path(conn, path); + + return 0; +} + static DBusHandlerResult create_port(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -165,6 +196,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, DBusError derr; const char *addr; const char *pattern; + const char *ppath = port_path; /* FIXME: Check if it already exist */ @@ -188,6 +220,8 @@ static DBusHandlerResult create_port(DBusConnection *conn, snprintf(port_path, PATH_LENGTH, SERIAL_PORT_PATH"%d", next_id++); + /* FIXME: Send signal */ + if (port_register(conn, port_path, dbus_message_get_sender(msg)) < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "D-Bus path registration failed"); @@ -195,13 +229,49 @@ static DBusHandlerResult create_port(DBusConnection *conn, port_paths = g_slist_append(port_paths, g_strdup(port_path)); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + return send_message_and_unref(conn, reply); } static DBusHandlerResult remove_port(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessage *reply; + DBusError derr; + const char *path; + GSList *l; + int err; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + l = g_slist_find_custom(port_paths, path, (GCompareFunc) strcmp); + if (!l) + return err_does_not_exist(conn, msg); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + err = port_unregister(conn, path, dbus_message_get_sender(msg)); + if (err < 0) { + dbus_message_unref(reply); + return err_failed(conn, msg, strerror(-err)); + } + + g_free(l->data); + port_paths = g_slist_remove(port_paths, l->data); + + return send_message_and_unref(conn, reply); } static DBusHandlerResult list_ports(DBusConnection *conn, -- cgit From 66570ffe00f40c03ea3ae4fa7e62eea5697a7262 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 16:55:37 +0000 Subject: serial: added PortCreated signal --- serial/manager.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 6b10c13d..cbd1ea21 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -145,6 +145,7 @@ static int port_register(DBusConnection *conn, const char *path, const char *owner) { struct serial_port *sp; + DBusMessage *signal; if (!conn || !owner) return -EINVAL; @@ -162,6 +163,15 @@ static int port_register(DBusConnection *conn, return -1; } + signal = dbus_message_new_signal(SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortCreated"); + + dbus_message_append_args(signal, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + + send_message_and_unref(conn, signal); + info("Registered serial port path:%s", path); return 0; @@ -220,8 +230,6 @@ static DBusHandlerResult create_port(DBusConnection *conn, snprintf(port_path, PATH_LENGTH, SERIAL_PORT_PATH"%d", next_id++); - /* FIXME: Send signal */ - if (port_register(conn, port_path, dbus_message_get_sender(msg)) < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "D-Bus path registration failed"); -- cgit From f05b9d3834fb8f587987026f8ffde549fa6497d3 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 17:36:54 +0000 Subject: serial: Added ListPorts --- serial/manager.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index cbd1ea21..9c920a2f 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -285,7 +285,27 @@ static DBusHandlerResult remove_port(DBusConnection *conn, static DBusHandlerResult list_ports(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter array_iter; + GSList *l; + + 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, &array_iter); + + for (l = port_paths; l; l= l->next) { + dbus_message_iter_append_basic(&array_iter, + DBUS_TYPE_STRING, &l->data); + } + + dbus_message_iter_close_container(&iter, &array_iter); + + return send_message_and_unref(conn, reply); } static DBusHandlerResult manager_message(DBusConnection *conn, -- cgit From 3c157186641a97c2d37d122b391dc0d6b258735b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 18:07:12 +0000 Subject: serial: Added initial API description --- serial/serial-api.txt | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index d85acf2d..9ae947db 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -4,9 +4,54 @@ Bluetooth serial service API description Copyright (C) 2006-2007 Marcel Holtmann -Manager hierarchy +Manager hierarchy (experimental) ================= - -Service org.bluez.serial Interface org.bluez.serial.Manager Object path /org/bluez/serial + +Methods string CreatePort(string address, string pattern) + + Creates a serial port object. + + Possible errors:org.bluez.serial.Error.AlreadyExists + org.bluez.serial.Error.NotSupported + org.bluez.serial.Error.ConnectionAttemptFailed + org.bluez.serial.Error.Failed + + void RemovePort(string path) + Removes the serial port object for given path. + + Possible errors:org.bluez.serial.Error.DoesNotExist + org.bluez.serial.Error.Failed + + array{string} ListPorts() + + Returns an array of available serial port paths. + +Signals + + void PortCreated(string path) + + void PortRemoved(string path) + +Port hierarchy (experimental) +======================================= + +Interface org.bluez.serial.Port +Object path /org/bluez/serial/port* + +Methods string GetAddress() + Returns the Bluetooth address of the ending point. + + string Connect() + + Connects to remote device associated to the port object. + + Possible errors:org.bluez.serial.Error.ConnectionAttemptFailed + org.bluez.serial.Error.Failed + + void Disconnect() + + Disconnects from remote device. + + Possible errors:org.bluez.serial.Error.Failed -- cgit From 9aaae3b234e219d5770a972858d9ea3e9783e12e Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 19:07:49 +0000 Subject: serial: added PortRemoved signal --- serial/manager.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 9c920a2f..caacdd05 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -181,6 +181,7 @@ static int port_unregister(DBusConnection *conn, const char *path, const char *owner) { struct serial_port *sp; + DBusMessage *signal; if (!conn || !owner) return -EINVAL; @@ -195,6 +196,17 @@ static int port_unregister(DBusConnection *conn, dbus_connection_unregister_object_path(conn, path); + signal = dbus_message_new_signal(SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortRemoved"); + + dbus_message_append_args(signal, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + + send_message_and_unref(conn, signal); + + info("Unregistered serial port path:%s", path); + return 0; } -- cgit From d8cd184883cc2233db0bde0218201a2756aa7c16 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 1 May 2007 19:13:39 +0000 Subject: serial: free port_paths and unregister the D-Bus path when the daemon exits --- serial/manager.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index caacdd05..4f7efdb4 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -351,6 +351,14 @@ static DBusHandlerResult manager_message(DBusConnection *conn, static void manager_unregister(DBusConnection *conn, void *data) { + GSList *l; + + for (l = port_paths; l; l = l->next) + dbus_connection_unregister_object_path(conn, l->data); + + g_slist_foreach(port_paths, (GFunc) g_free, NULL); + g_slist_free(port_paths); + port_paths = NULL; } /* Virtual table to handle manager object path hierarchy */ -- cgit From a13e1f4616b578fc49e7320f09d32f451b1a09b9 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 14:27:51 +0000 Subject: serial: service refactory - Added skeleton --- serial/manager.c | 280 +++++-------------------------------------------------- 1 file changed, 21 insertions(+), 259 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 4f7efdb4..fb4aaf5e 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -36,48 +36,13 @@ #include "manager.h" -#define SERIAL_MANAGER_PATH "/org/bluez/serial" -#define SERIAL_PORT_PATH "/org/bluez/serial/port" -#define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" -#define SERIAL_PORT_INTERFACE "org.bluez.serial.Port" -#define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" +#define SERIAL_MANAGER_PATH "/org/bluez/serial" +#define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" +#define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" #define PATH_LENGTH 32 static DBusConnection *connection = NULL; -static GSList *port_paths = NULL; -static unsigned int next_id = 0; - -struct serial_port { - char *owner; - int16_t id; /* Device id */ -}; - -static void serial_port_free(struct serial_port *sp) -{ - if (!sp) - return; - if (sp->owner) - g_free(sp->owner); - g_free(sp); -} - -static DBusHandlerResult err_does_not_exist(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".DoesNotExist", - "Port doesn't exist")); -} - -static DBusHandlerResult err_failed(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".Failed", str)); -} static DBusHandlerResult err_invalid_args(DBusConnection *conn, DBusMessage *msg, const char *str) @@ -87,140 +52,15 @@ static DBusHandlerResult err_invalid_args(DBusConnection *conn, SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); } -static DBusHandlerResult err_unknown_port(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".UnknownPort", - "Unknown port path")); -} - -static DBusHandlerResult port_connect(DBusConnection *conn, +static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult port_disconnect(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult port_message(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *iface, *member; - - iface = dbus_message_get_interface(msg); - member = dbus_message_get_member(msg); - - /* Accept messages from the port interface only */ - if (strcmp(SERIAL_PORT_INTERFACE, iface)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (strcmp(member, "Connect") == 0) - return port_connect(conn, msg, data); - - if (strcmp(member, "Disconnect") == 0) - return port_disconnect(conn, msg, data); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static void port_handler_unregister(DBusConnection *conn, void *data) -{ - /* FIXME: Disconnect if applied */ - serial_port_free(data); -} - -/* Virtual table to handle port object path hierarchy */ -static const DBusObjectPathVTable port_table = { - .message_function = port_message, - .unregister_function = port_handler_unregister, -}; - -static int port_register(DBusConnection *conn, - const char *path, const char *owner) -{ - struct serial_port *sp; - DBusMessage *signal; - - if (!conn || !owner) - return -EINVAL; - - sp = g_new0(struct serial_port, 1); - - /* FIXME: Create the RFCOMM device node */ - sp->id = -1; - sp->owner = g_strdup(owner); - - /* Register path */ - if (!dbus_connection_register_object_path(conn, path, - &port_table, sp)) { - serial_port_free(sp); - return -1; - } - - signal = dbus_message_new_signal(SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortCreated"); - - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - - send_message_and_unref(conn, signal); - - info("Registered serial port path:%s", path); - - return 0; -} - -static int port_unregister(DBusConnection *conn, - const char *path, const char *owner) -{ - struct serial_port *sp; - DBusMessage *signal; - - if (!conn || !owner) - return -EINVAL; - - if (!dbus_connection_get_object_path_data(conn, path, (void *) &sp) || !sp) - return -ENOENT; - - if (strcmp(sp->owner, owner) != 0) - return -EACCES; - - /* FIXME: If it is connected return EPERM or disconnect */ - - dbus_connection_unregister_object_path(conn, path); - - signal = dbus_message_new_signal(SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortRemoved"); - - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - - send_message_and_unref(conn, signal); - - info("Unregistered serial port path:%s", path); - - return 0; -} - -static DBusHandlerResult create_port(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - char port_path[PATH_LENGTH]; DBusMessage *reply; DBusError derr; const char *addr; const char *pattern; - const char *ppath = port_path; - /* FIXME: Check if it already exist */ + /* FIXME: Check if it already exist or if there is pending connect */ dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -232,7 +72,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - /* Pattern can be a service or a channel */ + /* Pattern can be a UUID128, handle or a channel */ /* FIXME: Missing SDP search */ @@ -240,125 +80,48 @@ static DBusHandlerResult create_port(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - snprintf(port_path, PATH_LENGTH, SERIAL_PORT_PATH"%d", next_id++); - - if (port_register(conn, port_path, dbus_message_get_sender(msg)) < 0) { - dbus_message_unref(reply); - return err_failed(conn, msg, "D-Bus path registration failed"); - } - - port_paths = g_slist_append(port_paths, g_strdup(port_path)); - - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); } -static DBusHandlerResult remove_port(DBusConnection *conn, +static DBusHandlerResult disconnect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessage *reply; - DBusError derr; - const char *path; - GSList *l; - int err; - - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } - - l = g_slist_find_custom(port_paths, path, (GCompareFunc) strcmp); - if (!l) - return err_does_not_exist(conn, msg); - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - err = port_unregister(conn, path, dbus_message_get_sender(msg)); - if (err < 0) { - dbus_message_unref(reply); - return err_failed(conn, msg, strerror(-err)); - } - - g_free(l->data); - port_paths = g_slist_remove(port_paths, l->data); - - return send_message_and_unref(conn, reply); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult list_ports(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusHandlerResult cancel_connect_service(DBusConnection *conn, + DBusMessage *msg, void *data) { - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter array_iter; - GSList *l; - - 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, &array_iter); - - for (l = port_paths; l; l= l->next) { - dbus_message_iter_append_basic(&array_iter, - DBUS_TYPE_STRING, &l->data); - } - - dbus_message_iter_close_container(&iter, &array_iter); - - return send_message_and_unref(conn, reply); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static DBusHandlerResult manager_message(DBusConnection *conn, - DBusMessage *msg, void *data) + DBusMessage *msg, void *data) { - const char *path, *iface, *member; + const char *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(SERIAL_MANAGER_PATH, path) != 0) - return err_unknown_port(conn, msg); - /* Accept messages from the manager interface only */ if (strcmp(SERIAL_MANAGER_INTERFACE, iface)) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (strcmp(member, "CreatePort") == 0) - return create_port(conn, msg, data); + if (strcmp(member, "ConnectService") == 0) + return connect_service(conn, msg, data); - if (strcmp(member, "RemovePort") == 0) - return remove_port(conn, msg, data); + if (strcmp(member, "DisconnectService") == 0) + return disconnect_service(conn, msg, data); - if (strcmp(member, "ListPorts") == 0) - return list_ports(conn, msg, data); + if (strcmp(member, "CancelConnectService") == 0) + return cancel_connect_service(conn, msg, data); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static void manager_unregister(DBusConnection *conn, void *data) { - GSList *l; - - for (l = port_paths; l; l = l->next) - dbus_connection_unregister_object_path(conn, l->data); - g_slist_foreach(port_paths, (GFunc) g_free, NULL); - g_slist_free(port_paths); - port_paths = NULL; } /* Virtual table to handle manager object path hierarchy */ @@ -371,9 +134,8 @@ int serial_init(DBusConnection *conn) { connection = dbus_connection_ref(conn); - /* Fallback to catch invalid serial path */ - if (dbus_connection_register_fallback(connection, SERIAL_MANAGER_PATH, - &manager_table, NULL) == FALSE) { + if (dbus_connection_register_object_path(connection, + SERIAL_MANAGER_PATH, &manager_table, NULL) == FALSE) { error("D-Bus failed to register %s path", SERIAL_MANAGER_PATH); dbus_connection_unref(connection); -- cgit From 71da6f84e448a6e08ef252f21e4404d602ef1096 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 17:20:57 +0000 Subject: serial: added pattern validation for ConnectService --- serial/manager.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index fb4aaf5e..b16c4f72 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,7 @@ #define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" #define PATH_LENGTH 32 +#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" static DBusConnection *connection = NULL; @@ -55,10 +57,10 @@ static DBusHandlerResult err_invalid_args(DBusConnection *conn, static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessage *reply; DBusError derr; - const char *addr; - const char *pattern; + const char *addr, *pattern; + char *endptr; + long val; /* FIXME: Check if it already exist or if there is pending connect */ @@ -72,15 +74,43 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - /* Pattern can be a UUID128, handle or a channel */ + /* UUID 128*/ + if (strlen(pattern) == 36) { + char tmp[37]; - /* FIXME: Missing SDP search */ + strcpy(tmp, pattern); + tmp[4] = '0'; + tmp[5] = '0'; + tmp[6] = '0'; + tmp[7] = '0'; - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + if (strcasecmp(BASE_UUID, tmp) != 0) + return err_invalid_args(conn, msg, "invalid UUID"); - return send_message_and_unref(conn, reply); + /* FIXME: Retrieve the handle/record */ + + return DBUS_HANDLER_RESULT_HANDLED; + } + + errno = 0; + val = strtol(pattern, &endptr, 0); + if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || + (errno != 0 && val == 0) || (pattern == endptr)) + return err_invalid_args(conn, msg, "Invalid pattern"); + + if (val < 0x100) { + /* RFCOMM Channel range: 0x00 - 0xff */ + info("Connecting to channel: 0x%x", val); + /* FIXME: Connect */ + } else { + /* Service record handle must be > 0x0000ffff */ + if (val < 0x10000) + return err_invalid_args(conn, msg, + "invalid record handle"); + /* FIXME: retrieve the record */ + } + + return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult disconnect_service(DBusConnection *conn, -- cgit From 500a7637d7eae204fbb74a6602afa3f08a040d17 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 18:00:05 +0000 Subject: serial: fixed record handle and channel values validation --- serial/manager.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index b16c4f72..30380d9d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -98,18 +98,23 @@ static DBusHandlerResult connect_service(DBusConnection *conn, (errno != 0 && val == 0) || (pattern == endptr)) return err_invalid_args(conn, msg, "Invalid pattern"); - if (val < 0x100) { - /* RFCOMM Channel range: 0x00 - 0xff */ - info("Connecting to channel: 0x%x", val); - /* FIXME: Connect */ - } else { - /* Service record handle must be > 0x0000ffff */ + /* Record handle: starts at 0x10000 */ + if (strncasecmp("0x", pattern, 2) == 0) { if (val < 0x10000) return err_invalid_args(conn, msg, "invalid record handle"); /* FIXME: retrieve the record */ + return DBUS_HANDLER_RESULT_HANDLED; } + /* RFCOMM Channel range: 1 - 30 */ + if (val < 1 || val > 30) + return err_invalid_args(conn, msg, + "invalid RFCOMM channel"); + + /* FIXME: Connect */ + info("Connecting to channel: %d", val); + return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From 7026c4f01e50040d2539a6ca7f80cb533210e8dd Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 18:08:13 +0000 Subject: serial: get the default adapter address --- serial/manager.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 30380d9d..36711c1a 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -32,6 +32,10 @@ #include #include +#include +#include +#include + #include "dbus.h" #include "logging.h" @@ -54,13 +58,23 @@ static DBusHandlerResult err_invalid_args(DBusConnection *conn, SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); } +static DBusHandlerResult err_failed(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".Failed", str)); +} + static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { DBusError derr; + bdaddr_t src; const char *addr, *pattern; char *endptr; long val; + int dev_id; /* FIXME: Check if it already exist or if there is pending connect */ @@ -74,6 +88,10 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } + dev_id = hci_get_route(NULL); + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) + return err_failed(conn, msg, "Adapter not available"); + /* UUID 128*/ if (strlen(pattern) == 36) { char tmp[37]; -- cgit From 4a653936cf357c3266777e176da15508e08d7271 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 19:06:44 +0000 Subject: serial: added get_handles and pending_connection struct --- serial/manager.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 7 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 36711c1a..6e46bc51 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -48,14 +48,34 @@ #define PATH_LENGTH 32 #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" +struct pending_connection { + DBusConnection *conn; + DBusMessage *msg; + bdaddr_t src; /* Source address */ + char *addr; /* Destination address */ + char *adapter_path; /* Adapter D-Bus path */ +}; + static DBusConnection *connection = NULL; -static DBusHandlerResult err_invalid_args(DBusConnection *conn, +static void pending_connection_free(struct pending_connection *pc) +{ + if (pc->conn) + dbus_connection_unref(pc->conn); + if (pc->msg) + dbus_message_unref(pc->msg); + if (pc->addr) + g_free(pc->addr); + if (pc->adapter_path) + g_free(pc->adapter_path); +} + +static DBusHandlerResult err_connection_failed(DBusConnection *conn, DBusMessage *msg, const char *str) { return send_message_and_unref(conn, dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); + SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); } static DBusHandlerResult err_failed(DBusConnection *conn, @@ -66,11 +86,100 @@ static DBusHandlerResult err_failed(DBusConnection *conn, SERIAL_ERROR_INTERFACE ".Failed", str)); } +static DBusHandlerResult err_invalid_args(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); +} + +static DBusHandlerResult err_not_supported(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".NotSupported", + "The service is not supported by the remote device")); +} + +static void handles_reply(DBusPendingCall *call, void *data) +{ + struct pending_connection *pc = data; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + DBusError derr; + uint32_t *phandle; + int len; + + dbus_error_init(&derr); + if (dbus_set_error_from_message(&derr, reply)) { + if (dbus_error_has_name(&derr, + "org.bluez.Error.ConnectionAttemptFailed")) + err_connection_failed(pc->conn, pc->msg, derr.message); + else + err_not_supported(pc->conn, pc->msg); + + error("GetRemoteServiceHandles: %s(%s)", + derr.name, derr.message); + goto fail; + } + + if (!dbus_message_get_args(reply, &derr, + DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, + &len, DBUS_TYPE_INVALID)) { + err_not_supported(pc->conn, pc->msg); + error("%s: %s", derr.name, derr.message); + goto fail; + } + + if (len == 0) { + err_not_supported(pc->conn, pc->msg); + goto fail; + } + + /* FIXME: Get the record */ + dbus_message_unref(reply); + return; +fail: + dbus_message_unref(reply); + dbus_error_free(&derr); + pending_connection_free(pc); +} + +static int get_handles(struct pending_connection *pc, const char *uuid, + DBusPendingCallNotifyFunction cb) +{ + DBusMessage *msg; + DBusPendingCall *pending; + + msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, + "org.bluez.Adapter", "GetRemoteServiceHandles"); + if (!msg) + return -1; + + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &pc->addr, + DBUS_TYPE_STRING, &uuid, + DBUS_TYPE_INVALID); + + if (dbus_connection_send_with_reply(pc->conn, msg, &pending, -1) == FALSE) { + error("Can't send D-Bus message."); + return -1; + } + + dbus_pending_call_set_notify(pending, cb, pc, NULL); + dbus_message_unref(msg); + dbus_pending_call_unref(pending); + + return 0; +} + static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { DBusError derr; bdaddr_t src; + struct pending_connection *pc; const char *addr, *pattern; char *endptr; long val; @@ -92,6 +201,14 @@ static DBusHandlerResult connect_service(DBusConnection *conn, if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) return err_failed(conn, msg, "Adapter not available"); + pc = g_new0(struct pending_connection, 1); + pc->conn = dbus_connection_ref(conn); + pc->msg = dbus_message_ref(msg); + bacpy(&pc->src, &src); + pc->addr = g_strdup(addr); + pc->adapter_path = g_malloc0(16); + snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); + /* UUID 128*/ if (strlen(pattern) == 36) { char tmp[37]; @@ -102,10 +219,15 @@ static DBusHandlerResult connect_service(DBusConnection *conn, tmp[6] = '0'; tmp[7] = '0'; - if (strcasecmp(BASE_UUID, tmp) != 0) + if (strcasecmp(BASE_UUID, tmp) != 0) { + pending_connection_free(pc); return err_invalid_args(conn, msg, "invalid UUID"); + } - /* FIXME: Retrieve the handle/record */ + if (get_handles(pc, pattern, handles_reply) < 0) { + pending_connection_free(pc); + return err_not_supported(conn, msg); + } return DBUS_HANDLER_RESULT_HANDLED; } @@ -113,22 +235,28 @@ static DBusHandlerResult connect_service(DBusConnection *conn, errno = 0; val = strtol(pattern, &endptr, 0); if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || - (errno != 0 && val == 0) || (pattern == endptr)) + (errno != 0 && val == 0) || (pattern == endptr)) { + pending_connection_free(pc); return err_invalid_args(conn, msg, "Invalid pattern"); + } /* Record handle: starts at 0x10000 */ if (strncasecmp("0x", pattern, 2) == 0) { - if (val < 0x10000) + if (val < 0x10000) { + pending_connection_free(pc); return err_invalid_args(conn, msg, "invalid record handle"); + } /* FIXME: retrieve the record */ return DBUS_HANDLER_RESULT_HANDLED; } /* RFCOMM Channel range: 1 - 30 */ - if (val < 1 || val > 30) + if (val < 1 || val > 30) { + pending_connection_free(pc); return err_invalid_args(conn, msg, "invalid RFCOMM channel"); + } /* FIXME: Connect */ info("Connecting to channel: %d", val); -- cgit From 6b1cc18f00d0dd894a5293de7fff7e85b1a00294 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 19:20:20 +0000 Subject: serial: added get_record --- serial/manager.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 6e46bc51..2fa8faba 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -103,6 +103,60 @@ static DBusHandlerResult err_not_supported(DBusConnection *conn, "The service is not supported by the remote device")); } +static void record_reply(DBusPendingCall *call, void *data) +{ + struct pending_connection *pc = data; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + DBusError derr; + + dbus_error_init(&derr); + if (dbus_set_error_from_message(&derr, reply)) { + if (dbus_error_has_name(&derr, + "org.bluez.Error.ConnectionAttemptFailed")) + err_connection_failed(pc->conn, pc->msg, derr.message); + else + err_not_supported(pc->conn, pc->msg); + + error("GetRemoteServiceRecord: %s(%s)", + derr.name, derr.message); + goto fail; + } + + /* FIXME: extract the record */ +fail: + dbus_message_unref(reply); + dbus_error_free(&derr); + pending_connection_free(pc); +} + +static int get_record(struct pending_connection *pc, uint32_t handle, + DBusPendingCallNotifyFunction cb) +{ + DBusMessage *msg; + DBusPendingCall *pending; + + msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, + "org.bluez.Adapter", "GetRemoteServiceRecord"); + if (!msg) + return -1; + + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &pc->addr, + DBUS_TYPE_UINT32, &handle, + DBUS_TYPE_INVALID); + + if (dbus_connection_send_with_reply(pc->conn, msg, &pending, -1) == FALSE) { + error("Can't send D-Bus message."); + return -1; + } + + dbus_pending_call_set_notify(pending, cb, pc, NULL); + dbus_message_unref(msg); + dbus_pending_call_unref(pending); + + return 0; +} + static void handles_reply(DBusPendingCall *call, void *data) { struct pending_connection *pc = data; @@ -137,7 +191,11 @@ static void handles_reply(DBusPendingCall *call, void *data) goto fail; } - /* FIXME: Get the record */ + if (get_record(pc, *phandle, record_reply) < 0) { + err_not_supported(pc->conn, pc->msg); + goto fail; + } + dbus_message_unref(reply); return; fail: @@ -247,7 +305,12 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return err_invalid_args(conn, msg, "invalid record handle"); } - /* FIXME: retrieve the record */ + + if (get_record(pc, val, record_reply) < 0) { + pending_connection_free(pc); + return err_not_supported(conn, msg); + + } return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From fa6159b9a4d2e54d94d56e215474ea07155366a1 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 7 May 2007 20:30:15 +0000 Subject: serial: added code to extract the channel --- serial/manager.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 2fa8faba..0b35f6e6 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "dbus.h" #include "logging.h" @@ -107,7 +109,11 @@ static void record_reply(DBusPendingCall *call, void *data) { struct pending_connection *pc = data; DBusMessage *reply = dbus_pending_call_steal_reply(call); + sdp_record_t *rec; + const uint8_t *rec_bin; + sdp_list_t *protos; DBusError derr; + int len, scanned, ch; dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { @@ -122,7 +128,45 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - /* FIXME: extract the record */ + if (!dbus_message_get_args(reply, &derr, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len, + DBUS_TYPE_INVALID)) { + err_not_supported(pc->conn, pc->msg); + error("%s: %s", derr.name, derr.message); + goto fail; + } + + if (len == 0) { + err_not_supported(pc->conn, pc->msg); + error("Invalid service record length"); + goto fail; + } + + rec = sdp_extract_pdu(rec_bin, &scanned); + if (!rec) { + error("Can't extract SDP record."); + err_not_supported(pc->conn, pc->msg); + goto fail; + } + + if (len != scanned || (sdp_get_access_protos(rec, &protos) < 0)) { + sdp_record_free(rec); + err_not_supported(pc->conn, pc->msg); + goto fail; + } + + ch = sdp_get_proto_port(protos, RFCOMM_UUID); + sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); + sdp_list_free(protos, NULL); + + if (ch < 1 || ch > 30) { + error("Channel out of range: %d", ch); + sdp_record_free(rec); + err_not_supported(pc->conn, pc->msg); + } + + /* FIXME: Check if there is a pending connection */ + fail: dbus_message_unref(reply); dbus_error_free(&derr); -- cgit From 5d9f545ef534d3d2f4861c336de8d4f6321dd011 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 8 May 2007 11:30:35 +0000 Subject: serial: added rfcomm_connect --- serial/manager.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 129 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 0b35f6e6..795b9b36 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include + #include #include @@ -37,6 +40,7 @@ #include #include #include +#include #include "dbus.h" #include "logging.h" @@ -53,9 +57,10 @@ struct pending_connection { DBusConnection *conn; DBusMessage *msg; - bdaddr_t src; /* Source address */ char *addr; /* Destination address */ char *adapter_path; /* Adapter D-Bus path */ + bdaddr_t src; + uint8_t channel; }; static DBusConnection *connection = NULL; @@ -105,6 +110,108 @@ static DBusHandlerResult err_not_supported(DBusConnection *conn, "The service is not supported by the remote device")); } +static gboolean rfcomm_connect_cb(GIOChannel *chan, + GIOCondition cond, struct pending_connection *pc) +{ + DBusMessage *reply; + char node_name[16]; + const char *pname = node_name; + struct rfcomm_dev_req req; + int sk, ret, err, id; + socklen_t len; + + /* FIXME: Check if it was canceled */ + + sk = g_io_channel_unix_get_fd(chan); + + len = sizeof(ret); + if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { + err = errno; + error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err); + goto fail; + } + + if (ret != 0) { + error("connect(): %s (%d)", strerror(ret), ret); + goto fail; + } + + debug("rfcomm_connect_cb: connected"); + + memset(&req, 0, sizeof(req)); + req.dev_id = -1; + req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP); + bacpy(&req.src, &pc->src); + str2ba(pc->addr, &req.dst); + req.channel = pc->channel; + + id = ioctl(sk, RFCOMMCREATEDEV, &req); + if (id < 0) { + err = errno; + error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(err), err); + err_connection_failed(pc->conn, pc->msg, strerror(err)); + goto fail; + } + + snprintf(node_name, 16, "/dev/rfcomm%d", id); + reply = dbus_message_new_method_return(pc->msg); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &pname, + DBUS_TYPE_INVALID); + send_message_and_unref(pc->conn, reply); +fail: + pending_connection_free(pc); + /* FIXME: Remote from the pending connects list */ + return FALSE; +} + +static int rfcomm_connect(struct pending_connection *pc) +{ + struct sockaddr_rc addr; + GIOChannel *io; + int sk, err = 0; + + sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (sk < 0) + return -errno; + + addr.rc_family = AF_BLUETOOTH; + bacpy(&addr.rc_bdaddr, &pc->src); + addr.rc_channel = 0; + + if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) + return -errno; + + if (set_nonblocking(sk) < 0) + return -errno; + + io = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(io, TRUE); + + addr.rc_family = AF_BLUETOOTH; + str2ba(pc->addr, &addr.rc_bdaddr); + addr.rc_channel = pc->channel; + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + /* BlueZ returns EAGAIN eventhough it should return EINPROGRESS */ + if (!(errno == EAGAIN || errno == EINPROGRESS)) { + err = errno; + error("connect() failed: %s (%d)", strerror(err), err); + goto fail; + } + + debug("Connect in progress"); + g_io_add_watch(io, G_IO_OUT, (GIOFunc) rfcomm_connect_cb, pc); + /* FIXME: Control the pending connects */ + } else { + debug("Connect succeeded with first try"); + (void) rfcomm_connect_cb(io, G_IO_OUT, pc); + } +fail: + g_io_channel_unref(io); + return -err; +} + static void record_reply(DBusPendingCall *call, void *data) { struct pending_connection *pc = data; @@ -113,7 +220,7 @@ static void record_reply(DBusPendingCall *call, void *data) const uint8_t *rec_bin; sdp_list_t *protos; DBusError derr; - int len, scanned, ch; + int len, scanned, ch, err; dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { @@ -163,10 +270,21 @@ static void record_reply(DBusPendingCall *call, void *data) error("Channel out of range: %d", ch); sdp_record_free(rec); err_not_supported(pc->conn, pc->msg); + goto fail; } - /* FIXME: Check if there is a pending connection */ + /* FIXME: Check if there is a pending connection or if it was canceled */ + + pc->channel = ch; + err = rfcomm_connect(pc); + if (err < 0) { + error("RFCOMM connection failed"); + err_connection_failed(pc->conn, pc->msg, strerror(-err)); + goto fail; + } + dbus_message_unref(reply); + return; fail: dbus_message_unref(reply); dbus_error_free(&derr); @@ -285,7 +403,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, const char *addr, *pattern; char *endptr; long val; - int dev_id; + int dev_id, err; /* FIXME: Check if it already exist or if there is pending connect */ @@ -330,7 +448,6 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pending_connection_free(pc); return err_not_supported(conn, msg); } - return DBUS_HANDLER_RESULT_HANDLED; } @@ -353,7 +470,6 @@ static DBusHandlerResult connect_service(DBusConnection *conn, if (get_record(pc, val, record_reply) < 0) { pending_connection_free(pc); return err_not_supported(conn, msg); - } return DBUS_HANDLER_RESULT_HANDLED; } @@ -365,9 +481,13 @@ static DBusHandlerResult connect_service(DBusConnection *conn, "invalid RFCOMM channel"); } - /* FIXME: Connect */ - info("Connecting to channel: %d", val); - + pc->channel = val; + err = rfcomm_connect(pc); + if (err < 0) { + const char *strerr = strerror(-err); + error("RFCOMM connect failed: %s(%d)", strerr, -err); + err_connection_failed(conn, msg, strerr); + } return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From 331abb4c83b5c6690093ec0807d01823e4548865 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 May 2007 12:52:54 +0000 Subject: Allow configuration of serial service --- serial/Makefile.am | 14 ++++++++++++-- serial/serial.service | 5 +++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 serial/serial.service (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 24506088..240429a6 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -1,15 +1,25 @@ -noinst_PROGRAMS = bluetoothd-service-serial +if SERIALSERVICE +if CONFIGFILES +confdir = $(sysconfdir)/bluetooth + +conf_DATA = serial.service +endif + +servicedir = $(libdir)/bluetooth + +service_PROGRAMS = bluetoothd-service-serial bluetoothd_service_serial_SOURCES = main.c manager.h manager.c LDADD = $(top_builddir)/common/libhelper.a \ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ +endif AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ INCLUDES = -I$(top_srcdir)/common -EXTRA_DIST = serial-api.txt +EXTRA_DIST = serial.service serial-api.txt MAINTAINERCLEANFILES = Makefile.in diff --git a/serial/serial.service b/serial/serial.service new file mode 100644 index 00000000..926e5064 --- /dev/null +++ b/serial/serial.service @@ -0,0 +1,5 @@ +[Bluetooth Service] +Identifier=serial +Name=Serial service +Description=Bluetooth Serial Port service +Autostart=false -- cgit From fcba5ddbba50277ab533ac9efc8414f8b839ec8e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 May 2007 14:08:54 +0000 Subject: Add service test scripts --- serial/Makefile.am | 2 +- serial/test-serial | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100755 serial/test-serial (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 240429a6..9d47f2db 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -20,6 +20,6 @@ AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ INCLUDES = -I$(top_srcdir)/common -EXTRA_DIST = serial.service serial-api.txt +EXTRA_DIST = serial.service serial-api.txt test-serial MAINTAINERCLEANFILES = Makefile.in diff --git a/serial/test-serial b/serial/test-serial new file mode 100755 index 00000000..06e5da55 --- /dev/null +++ b/serial/test-serial @@ -0,0 +1,48 @@ +#!/usr/bin/python + +import sys +import time +import dbus + +bus = dbus.SystemBus() + +manager = dbus.Interface(bus.get_object('org.bluez', '/org/bluez'), + 'org.bluez.Manager') + +conn = manager.ActivateService('serial') + +serial = dbus.Interface(bus.get_object(conn, '/org/bluez/serial'), + 'org.bluez.serial.Manager') + +if (len(sys.argv) < 2): + print "Usage: %s
[service]" % (sys.argv[0]) + sys.exit(1) + +address = sys.argv[1] + +if (len(sys.argv) < 3): + service = "spp" +else: + service = sys.argv[2] + +uuidbase = "-0000-1000-8000-00805F9B34FB" + +if (service == "spp"): + service = "00001101" + uuidbase + +if (service == "dun"): + service = "00001103" + uuidbase + +device = serial.ConnectService(address, service) + +print "Connected %s to %s" % (device, address) + +print "Press CTRL-C to disconnect" + +try: + time.sleep(1000) + print "Terminating connection" +except: + pass + +serial.DisconnectService(device) -- cgit From c4c2b3b842d89e0dc5b585f34ad0692156b55eb6 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 8 May 2007 15:06:43 +0000 Subject: serial: added name listener --- serial/manager.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 5 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 795b9b36..80dfa225 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -54,6 +55,18 @@ #define PATH_LENGTH 32 #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" +/* Waiting for udev to create the device node */ +#define MAX_OPEN_TRIES 5 +#define OPEN_WAIT 300 /* ms */ + +struct rfcomm_node { + int16_t id; /* RFCOMM device id */ + DBusConnection *conn; /* for name listener handling */ + char *owner; /* Bus name */ + GIOChannel *io; /* Connected node IO Channel */ + guint io_id; /* IO Channel ID */ +}; + struct pending_connection { DBusConnection *conn; DBusMessage *msg; @@ -61,9 +74,12 @@ struct pending_connection { char *adapter_path; /* Adapter D-Bus path */ bdaddr_t src; uint8_t channel; + int id; /* RFCOMM device id */ + int ntries; /* Open attempts */ }; static DBusConnection *connection = NULL; +static GSList *connected_nodes = NULL; static void pending_connection_free(struct pending_connection *pc) { @@ -75,6 +91,20 @@ static void pending_connection_free(struct pending_connection *pc) g_free(pc->addr); if (pc->adapter_path) g_free(pc->adapter_path); + g_free(pc); +} + +static void rfcomm_node_free(struct rfcomm_node *node) +{ + if (node->conn) + dbus_connection_unref(node->conn); + if (node->owner) + g_free(node->owner); + if (node->io) { + g_source_remove(node->io_id); + g_io_channel_unref(node->io); + } + g_free(node); } static DBusHandlerResult err_connection_failed(DBusConnection *conn, @@ -110,6 +140,87 @@ static DBusHandlerResult err_not_supported(DBusConnection *conn, "The service is not supported by the remote device")); } +static void connect_service_exited(const char *name, struct rfcomm_node *node) +{ + debug("Connect requestor %s exited. Releasing /dev/rfcomm%d node", + name, node->id); + connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); +} + +static gboolean rfcomm_disconnect_cb(GIOChannel *io, + GIOCondition cond, struct rfcomm_node *node) +{ + debug("RFCOMM node /dev/rfcomm%d was disconnected", node->id); + name_listener_remove(node->conn, node->owner, + (name_cb_t) connect_service_exited, node); + /* FIXME: send the Disconnected signal */ + connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); + return FALSE; +} + +static int add_rfcomm_node(GIOChannel *io, int id, DBusConnection *conn, const char *owner) +{ + struct rfcomm_node *node; + + node = g_new0(struct rfcomm_node, 1); + node->id = id; + node->conn = dbus_connection_ref(conn); + node->owner = g_strdup(owner); + node->io = io; + + /* FIXME: send the Connected signal */ + + g_io_channel_set_close_on_unref(io, TRUE); + node->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP, + (GIOFunc) rfcomm_disconnect_cb, node); + + return name_listener_add(node->conn, owner, (name_cb_t) connect_service_exited, node); +} + +static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) +{ + const char *owner = dbus_message_get_sender(pc->msg); + DBusMessage *reply; + char node_name[16]; + const char *pname = node_name; + int fd; + + /* FIXME: Check if it was canceled */ + + /* Check if the caller is still present */ + if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { + error("Connect requestor %s exited", owner); + pending_connection_free(pc); + return FALSE; + } + + snprintf(node_name, sizeof(node_name), "/dev/rfcomm%d", pc->id); + fd = open(node_name, O_RDONLY | O_NOCTTY); + if (fd < 0) { + int err = errno; + error("Could not open %s: %s (%d)", + node_name, strerror(err), err); + if (++pc->ntries >= MAX_OPEN_TRIES) { + err_connection_failed(pc->conn, pc->msg, strerror(err)); + pending_connection_free(pc); + return FALSE; + } + return TRUE; + } + + add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, pc->conn, owner); + reply = dbus_message_new_method_return(pc->msg); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &pname, + DBUS_TYPE_INVALID); + send_message_and_unref(pc->conn, reply); + pending_connection_free(pc); + + return FALSE; +} + static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct pending_connection *pc) { @@ -117,7 +228,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, char node_name[16]; const char *pname = node_name; struct rfcomm_dev_req req; - int sk, ret, err, id; + int sk, ret, err, fd; socklen_t len; /* FIXME: Check if it was canceled */ @@ -145,15 +256,27 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, str2ba(pc->addr, &req.dst); req.channel = pc->channel; - id = ioctl(sk, RFCOMMCREATEDEV, &req); - if (id < 0) { + pc->id = ioctl(sk, RFCOMMCREATEDEV, &req); + if (pc->id < 0) { err = errno; error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(err), err); err_connection_failed(pc->conn, pc->msg, strerror(err)); goto fail; } - snprintf(node_name, 16, "/dev/rfcomm%d", id); + + snprintf(node_name, sizeof(node_name), "/dev/rfcomm%d", pc->id); + + fd = open(node_name, O_RDONLY | O_NOCTTY); + if (fd < 0) { + g_timeout_add(OPEN_WAIT, + (GSourceFunc) rfcomm_connect_cb_continue, pc); + return FALSE; + } + + add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, + pc->conn, dbus_message_get_sender(pc->msg)); + reply = dbus_message_new_method_return(pc->msg); dbus_message_append_args(reply, DBUS_TYPE_STRING, &pname, @@ -529,7 +652,12 @@ static DBusHandlerResult manager_message(DBusConnection *conn, static void manager_unregister(DBusConnection *conn, void *data) { - + if (connected_nodes) { + g_slist_foreach(connected_nodes, + (GFunc) rfcomm_node_free, NULL); + g_slist_free(connected_nodes); + connected_nodes = NULL; + } } /* Virtual table to handle manager object path hierarchy */ -- cgit From c80c810165dd8274681f4b22312b9c3c9654fcdb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 May 2007 17:59:19 +0000 Subject: Update API description --- serial/serial-api.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 9ae947db..f3c39e22 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -28,12 +28,31 @@ Methods string CreatePort(string address, string pattern) Returns an array of available serial port paths. + string ConnectService(string address, string pattern) + + Connects to a specific RFCOMM based service on a + remote device and then creates a RFCOMM TTY + device for it. The RFCOMM TTY device is returned. + + void CancelConnectService(string address, string pattern) + + Cancel a previous ConnectService method call. + + void DisconnectService(string device) + + Disconnect a RFCOMM TTY device that has been + created via the ConnectService method. + Signals void PortCreated(string path) void PortRemoved(string path) + void ServiceConnected(string device, string adddress, string pattern) + + void ServiceDisconnected(string device) + Port hierarchy (experimental) ======================================= -- cgit From 0416abb5d66e9f362f868ab44757728b445f9a0f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 8 May 2007 18:05:52 +0000 Subject: Make port hierarchy as experimental --- serial/serial-api.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index f3c39e22..75369da2 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -4,12 +4,13 @@ Bluetooth serial service API description Copyright (C) 2006-2007 Marcel Holtmann -Manager hierarchy (experimental) +Manager hierarchy ================= + Interface org.bluez.serial.Manager Object path /org/bluez/serial -Methods string CreatePort(string address, string pattern) +Methods string CreatePort(string address, string pattern) [experimental] Creates a serial port object. @@ -18,13 +19,14 @@ Methods string CreatePort(string address, string pattern) org.bluez.serial.Error.ConnectionAttemptFailed org.bluez.serial.Error.Failed - void RemovePort(string path) + void RemovePort(string path) [experimental] + Removes the serial port object for given path. Possible errors:org.bluez.serial.Error.DoesNotExist org.bluez.serial.Error.Failed - array{string} ListPorts() + array{string} ListPorts() [experimental] Returns an array of available serial port paths. @@ -43,18 +45,16 @@ Methods string CreatePort(string address, string pattern) Disconnect a RFCOMM TTY device that has been created via the ConnectService method. -Signals - - void PortCreated(string path) +Signals void PortCreated(string path) [experimental] - void PortRemoved(string path) + void PortRemoved(string path) [experimental] void ServiceConnected(string device, string adddress, string pattern) void ServiceDisconnected(string device) Port hierarchy (experimental) -======================================= +============================= Interface org.bluez.serial.Port Object path /org/bluez/serial/port* -- cgit From bbd9569c25a9f29f48242930661c3968c4bc06f1 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 8 May 2007 18:36:29 +0000 Subject: serial: added ServiceConnected/ServiceDisconnected signals --- serial/manager.c | 59 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 12 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 80dfa225..6d18be2d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -61,6 +61,7 @@ struct rfcomm_node { int16_t id; /* RFCOMM device id */ + char *name; /* RFCOMM device name */ DBusConnection *conn; /* for name listener handling */ char *owner; /* Bus name */ GIOChannel *io; /* Connected node IO Channel */ @@ -96,6 +97,8 @@ static void pending_connection_free(struct pending_connection *pc) static void rfcomm_node_free(struct rfcomm_node *node) { + if (node->name) + g_free(node->name); if (node->conn) dbus_connection_unref(node->conn); if (node->owner) @@ -140,10 +143,26 @@ static DBusHandlerResult err_not_supported(DBusConnection *conn, "The service is not supported by the remote device")); } +static void send_signal(DBusConnection *conn, + const char *sname, const char *node_name) +{ + DBusMessage *signal; + + signal = dbus_message_new_signal(SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, sname); + dbus_message_append_args(signal, + DBUS_TYPE_STRING, &node_name, + DBUS_TYPE_INVALID); + send_message_and_unref(conn, signal); +} + static void connect_service_exited(const char *name, struct rfcomm_node *node) -{ - debug("Connect requestor %s exited. Releasing /dev/rfcomm%d node", - name, node->id); +{ + debug("Connect requestor %s exited. Releasing %s node", + name, node->name); + + send_signal(node->conn, "ServiceDisconnected", node->name); + connected_nodes = g_slist_remove(connected_nodes, node); rfcomm_node_free(node); } @@ -151,32 +170,37 @@ static void connect_service_exited(const char *name, struct rfcomm_node *node) static gboolean rfcomm_disconnect_cb(GIOChannel *io, GIOCondition cond, struct rfcomm_node *node) { - debug("RFCOMM node /dev/rfcomm%d was disconnected", node->id); + debug("RFCOMM node %s was disconnected", node->name); + name_listener_remove(node->conn, node->owner, (name_cb_t) connect_service_exited, node); - /* FIXME: send the Disconnected signal */ + + send_signal(node->conn, "ServiceDisconnected", node->name); + connected_nodes = g_slist_remove(connected_nodes, node); - rfcomm_node_free(node); + rfcomm_node_free(node); + return FALSE; } -static int add_rfcomm_node(GIOChannel *io, int id, DBusConnection *conn, const char *owner) +static int add_rfcomm_node(GIOChannel *io, int id, const char *name, + DBusConnection *conn, const char *owner) { struct rfcomm_node *node; node = g_new0(struct rfcomm_node, 1); node->id = id; + node->name = g_strdup(name); node->conn = dbus_connection_ref(conn); node->owner = g_strdup(owner); node->io = io; - /* FIXME: send the Connected signal */ - g_io_channel_set_close_on_unref(io, TRUE); node->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP, (GIOFunc) rfcomm_disconnect_cb, node); - return name_listener_add(node->conn, owner, (name_cb_t) connect_service_exited, node); + return name_listener_add(node->conn, owner, + (name_cb_t) connect_service_exited, node); } static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) @@ -210,12 +234,19 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) return TRUE; } - add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, pc->conn, owner); + add_rfcomm_node(g_io_channel_unix_new(fd), + pc->id, node_name, pc->conn, owner); + + /* Reply to the requestor */ reply = dbus_message_new_method_return(pc->msg); dbus_message_append_args(reply, DBUS_TYPE_STRING, &pname, DBUS_TYPE_INVALID); send_message_and_unref(pc->conn, reply); + + /* Send the D-Bus signal */ + send_signal(pc->conn, "ServiceConnected", node_name); + pending_connection_free(pc); return FALSE; @@ -274,14 +305,18 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, return FALSE; } - add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, + add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, node_name, pc->conn, dbus_message_get_sender(pc->msg)); + /* Reply to the requestor */ reply = dbus_message_new_method_return(pc->msg); dbus_message_append_args(reply, DBUS_TYPE_STRING, &pname, DBUS_TYPE_INVALID); send_message_and_unref(pc->conn, reply); + + /* Send the D-Bus signal */ + send_signal(pc->conn, "ServiceConnected", node_name); fail: pending_connection_free(pc); /* FIXME: Remote from the pending connects list */ -- cgit From 49cf828b678259deb691b6b9cc5741c0ff4a2e3c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 8 May 2007 20:30:09 +0000 Subject: serial: added friendly service name support for ConnectService --- serial/manager.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 6d18be2d..795e5a45 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -79,6 +79,25 @@ struct pending_connection { int ntries; /* Open attempts */ }; +/* FIXME: Common file required */ +static struct { + const char *name; + uint16_t class; +} serial_services[] = { + { "vcp", VIDEO_CONF_SVCLASS_ID }, + { "pbap", PBAP_SVCLASS_ID }, + { "sap", SAP_SVCLASS_ID }, + { "ftp", OBEX_FILETRANS_SVCLASS_ID }, + { "bpp", BASIC_PRINTING_SVCLASS_ID }, + { "bip", IMAGING_SVCLASS_ID }, + { "synch", IRMC_SYNC_SVCLASS_ID }, + { "dun", DIALUP_NET_SVCLASS_ID }, + { "opp", OBEX_OBJPUSH_SVCLASS_ID }, + { "fax", FAX_SVCLASS_ID }, + { "spp", SERIAL_PORT_SVCLASS_ID }, + { NULL } +}; + static DBusConnection *connection = NULL; static GSList *connected_nodes = NULL; @@ -110,6 +129,18 @@ static void rfcomm_node_free(struct rfcomm_node *node) g_free(node); } +static uint16_t str2class(const char *pattern) +{ + int i; + + for (i = 0; serial_services[i].name; i++) { + if (strcasecmp(serial_services[i].name, pattern) == 0) + return serial_services[i].class; + } + + return 0; +} + static DBusHandlerResult err_connection_failed(DBusConnection *conn, DBusMessage *msg, const char *str) { @@ -270,11 +301,13 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { err = errno; error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err); + err_connection_failed(pc->conn, pc->msg, strerror(err)); goto fail; } if (ret != 0) { error("connect(): %s (%d)", strerror(ret), ret); + err_connection_failed(pc->conn, pc->msg, strerror(ret)); goto fail; } @@ -562,6 +595,8 @@ static DBusHandlerResult connect_service(DBusConnection *conn, char *endptr; long val; int dev_id, err; + uint16_t cls; + char tmp[37]; /* FIXME: Check if it already exist or if there is pending connect */ @@ -587,10 +622,27 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); + memset(tmp, 0, sizeof(tmp)); + + /* Friendly name */ + cls = str2class(pattern); + if (cls) { + uuid_t uuid16, uuid128; + + sdp_uuid16_create(&uuid16, cls); + sdp_uuid16_to_uuid128(&uuid128, &uuid16); + sdp_uuid2strn(&uuid128, tmp, sizeof(tmp)); + + if (get_handles(pc, tmp, handles_reply) < 0) { + pending_connection_free(pc); + return err_not_supported(conn, msg); + } + + return DBUS_HANDLER_RESULT_HANDLED; + } + /* UUID 128*/ if (strlen(pattern) == 36) { - char tmp[37]; - strcpy(tmp, pattern); tmp[4] = '0'; tmp[5] = '0'; -- cgit From 2580e81792ef920b58055d69afb0315d21749165 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 8 May 2007 21:22:12 +0000 Subject: serial: added disconnect service --- serial/manager.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 795e5a45..e4a7c82b 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -100,6 +100,7 @@ static struct { static DBusConnection *connection = NULL; static GSList *connected_nodes = NULL; +static int rfcomm_ctl = -1; static void pending_connection_free(struct pending_connection *pc) { @@ -129,6 +130,11 @@ static void rfcomm_node_free(struct rfcomm_node *node) g_free(node); } +static int node_cmp_by_name(struct rfcomm_node *node, const char *name) +{ + return strcmp(node->name, name); +} + static uint16_t str2class(const char *pattern) { int i; @@ -149,6 +155,14 @@ static DBusHandlerResult err_connection_failed(DBusConnection *conn, SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); } +static DBusHandlerResult err_does_not_exist(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".DoesNotExist", str)); +} + static DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, const char *str) { @@ -165,6 +179,15 @@ static DBusHandlerResult err_invalid_args(DBusConnection *conn, SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); } +static DBusHandlerResult err_not_authorized(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".NotAuthorized", + "Owner not allowed")); +} + static DBusHandlerResult err_not_supported(DBusConnection *conn, DBusMessage *msg) { @@ -174,6 +197,32 @@ static DBusHandlerResult err_not_supported(DBusConnection *conn, "The service is not supported by the remote device")); } +static int rfcomm_release(int16_t id) +{ + struct rfcomm_dev_req req; + + memset(&req, 0, sizeof(req)); + req.dev_id = id; + +#if 0 + /* + * We are hitting a kernel bug inside RFCOMM code when + * RFCOMM_HANGUP_NOW bit is set on request's flags passed to + * ioctl(RFCOMMRELEASEDEV)! + */ + req.flags = (1 << RFCOMM_HANGUP_NOW); +#endif + + if (ioctl(rfcomm_ctl, RFCOMMRELEASEDEV, &req) < 0) { + int err = errno; + error("Can't release device %d: %s (%d)", + id, strerror(err), err); + return -err; + } + + return 0; +} + static void send_signal(DBusConnection *conn, const char *sname, const char *node_name) { @@ -192,6 +241,8 @@ static void connect_service_exited(const char *name, struct rfcomm_node *node) debug("Connect requestor %s exited. Releasing %s node", name, node->name); + rfcomm_release(node->id); + send_signal(node->conn, "ServiceDisconnected", node->name); connected_nodes = g_slist_remove(connected_nodes, node); @@ -230,6 +281,8 @@ static int add_rfcomm_node(GIOChannel *io, int id, const char *name, node->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP, (GIOFunc) rfcomm_disconnect_cb, node); + connected_nodes = g_slist_append(connected_nodes, node); + return name_listener_add(node->conn, owner, (name_cb_t) connect_service_exited, node); } @@ -247,6 +300,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) /* Check if the caller is still present */ if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { error("Connect requestor %s exited", owner); + rfcomm_release(pc->id); pending_connection_free(pc); return FALSE; } @@ -258,6 +312,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) error("Could not open %s: %s (%d)", node_name, strerror(err), err); if (++pc->ntries >= MAX_OPEN_TRIES) { + rfcomm_release(pc->id); err_connection_failed(pc->conn, pc->msg, strerror(err)); pending_connection_free(pc); return FALSE; @@ -704,7 +759,47 @@ static DBusHandlerResult connect_service(DBusConnection *conn, static DBusHandlerResult disconnect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessage *reply; + DBusError derr; + struct rfcomm_node *node; + const char *name; + GSList *l; + int err; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + l = g_slist_find_custom(connected_nodes, name, (GCompareFunc) node_cmp_by_name); + if (!l) + return err_does_not_exist(conn, msg, "Invalid node"); + + node = l->data; + + if (strcmp(node->owner, dbus_message_get_sender(msg)) != 0) + return err_not_authorized(conn, msg); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + err = rfcomm_release(node->id); + if (err < 0) { + dbus_message_unref(reply); + return err_failed(conn, msg, strerror(err)); + } + + name_listener_remove(node->conn, node->owner, + (name_cb_t) connect_service_exited, node); + connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); + + return send_message_and_unref(conn, reply); } static DBusHandlerResult cancel_connect_service(DBusConnection *conn, @@ -755,6 +850,13 @@ static const DBusObjectPathVTable manager_table = { int serial_init(DBusConnection *conn) { + + if (rfcomm_ctl < 0) { + rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM); + if (rfcomm_ctl < 0) + return -errno; + } + connection = dbus_connection_ref(conn); if (dbus_connection_register_object_path(connection, @@ -776,4 +878,7 @@ void serial_exit(void) dbus_connection_unref(connection); connection = NULL; + + if (rfcomm_ctl >= 0) + close(rfcomm_ctl); } -- cgit From 2349a0b07a08587f017cca9ae5cd9065c49db051 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 8 May 2007 21:51:08 +0000 Subject: serial: small code cleanup --- serial/manager.c | 54 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index e4a7c82b..458a71a2 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -68,7 +68,7 @@ struct rfcomm_node { guint io_id; /* IO Channel ID */ }; -struct pending_connection { +struct pending_connect { DBusConnection *conn; DBusMessage *msg; char *addr; /* Destination address */ @@ -102,7 +102,7 @@ static DBusConnection *connection = NULL; static GSList *connected_nodes = NULL; static int rfcomm_ctl = -1; -static void pending_connection_free(struct pending_connection *pc) +static void pending_connect_free(struct pending_connect *pc) { if (pc->conn) dbus_connection_unref(pc->conn); @@ -287,7 +287,7 @@ static int add_rfcomm_node(GIOChannel *io, int id, const char *name, (name_cb_t) connect_service_exited, node); } -static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) +static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) { const char *owner = dbus_message_get_sender(pc->msg); DBusMessage *reply; @@ -301,7 +301,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { error("Connect requestor %s exited", owner); rfcomm_release(pc->id); - pending_connection_free(pc); + pending_connect_free(pc); return FALSE; } @@ -314,7 +314,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) if (++pc->ntries >= MAX_OPEN_TRIES) { rfcomm_release(pc->id); err_connection_failed(pc->conn, pc->msg, strerror(err)); - pending_connection_free(pc); + pending_connect_free(pc); return FALSE; } return TRUE; @@ -333,13 +333,13 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connection *pc) /* Send the D-Bus signal */ send_signal(pc->conn, "ServiceConnected", node_name); - pending_connection_free(pc); + pending_connect_free(pc); return FALSE; } static gboolean rfcomm_connect_cb(GIOChannel *chan, - GIOCondition cond, struct pending_connection *pc) + GIOCondition cond, struct pending_connect *pc) { DBusMessage *reply; char node_name[16]; @@ -406,12 +406,12 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, /* Send the D-Bus signal */ send_signal(pc->conn, "ServiceConnected", node_name); fail: - pending_connection_free(pc); + pending_connect_free(pc); /* FIXME: Remote from the pending connects list */ return FALSE; } -static int rfcomm_connect(struct pending_connection *pc) +static int rfcomm_connect(struct pending_connect *pc) { struct sockaddr_rc addr; GIOChannel *io; @@ -421,6 +421,7 @@ static int rfcomm_connect(struct pending_connection *pc) if (sk < 0) return -errno; + memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; bacpy(&addr.rc_bdaddr, &pc->src); addr.rc_channel = 0; @@ -460,7 +461,7 @@ fail: static void record_reply(DBusPendingCall *call, void *data) { - struct pending_connection *pc = data; + struct pending_connect *pc = data; DBusMessage *reply = dbus_pending_call_steal_reply(call); sdp_record_t *rec; const uint8_t *rec_bin; @@ -534,10 +535,10 @@ static void record_reply(DBusPendingCall *call, void *data) fail: dbus_message_unref(reply); dbus_error_free(&derr); - pending_connection_free(pc); + pending_connect_free(pc); } -static int get_record(struct pending_connection *pc, uint32_t handle, +static int get_record(struct pending_connect *pc, uint32_t handle, DBusPendingCallNotifyFunction cb) { DBusMessage *msg; @@ -567,7 +568,7 @@ static int get_record(struct pending_connection *pc, uint32_t handle, static void handles_reply(DBusPendingCall *call, void *data) { - struct pending_connection *pc = data; + struct pending_connect *pc = data; DBusMessage *reply = dbus_pending_call_steal_reply(call); DBusError derr; uint32_t *phandle; @@ -609,10 +610,10 @@ static void handles_reply(DBusPendingCall *call, void *data) fail: dbus_message_unref(reply); dbus_error_free(&derr); - pending_connection_free(pc); + pending_connect_free(pc); } -static int get_handles(struct pending_connection *pc, const char *uuid, +static int get_handles(struct pending_connect *pc, const char *uuid, DBusPendingCallNotifyFunction cb) { DBusMessage *msg; @@ -645,7 +646,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, { DBusError derr; bdaddr_t src; - struct pending_connection *pc; + struct pending_connect *pc; const char *addr, *pattern; char *endptr; long val; @@ -669,10 +670,10 @@ static DBusHandlerResult connect_service(DBusConnection *conn, if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) return err_failed(conn, msg, "Adapter not available"); - pc = g_new0(struct pending_connection, 1); + pc = g_new0(struct pending_connect, 1); + bacpy(&pc->src, &src); pc->conn = dbus_connection_ref(conn); pc->msg = dbus_message_ref(msg); - bacpy(&pc->src, &src); pc->addr = g_strdup(addr); pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); @@ -689,7 +690,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, sdp_uuid2strn(&uuid128, tmp, sizeof(tmp)); if (get_handles(pc, tmp, handles_reply) < 0) { - pending_connection_free(pc); + pending_connect_free(pc); return err_not_supported(conn, msg); } @@ -705,12 +706,12 @@ static DBusHandlerResult connect_service(DBusConnection *conn, tmp[7] = '0'; if (strcasecmp(BASE_UUID, tmp) != 0) { - pending_connection_free(pc); + pending_connect_free(pc); return err_invalid_args(conn, msg, "invalid UUID"); } if (get_handles(pc, pattern, handles_reply) < 0) { - pending_connection_free(pc); + pending_connect_free(pc); return err_not_supported(conn, msg); } return DBUS_HANDLER_RESULT_HANDLED; @@ -720,20 +721,20 @@ static DBusHandlerResult connect_service(DBusConnection *conn, val = strtol(pattern, &endptr, 0); if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0) || (pattern == endptr)) { - pending_connection_free(pc); + pending_connect_free(pc); return err_invalid_args(conn, msg, "Invalid pattern"); } /* Record handle: starts at 0x10000 */ if (strncasecmp("0x", pattern, 2) == 0) { if (val < 0x10000) { - pending_connection_free(pc); + pending_connect_free(pc); return err_invalid_args(conn, msg, "invalid record handle"); } if (get_record(pc, val, record_reply) < 0) { - pending_connection_free(pc); + pending_connect_free(pc); return err_not_supported(conn, msg); } return DBUS_HANDLER_RESULT_HANDLED; @@ -741,7 +742,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, /* RFCOMM Channel range: 1 - 30 */ if (val < 1 || val > 30) { - pending_connection_free(pc); + pending_connect_free(pc); return err_invalid_args(conn, msg, "invalid RFCOMM channel"); } @@ -775,7 +776,8 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - l = g_slist_find_custom(connected_nodes, name, (GCompareFunc) node_cmp_by_name); + l = g_slist_find_custom(connected_nodes, name, + (GCompareFunc) node_cmp_by_name); if (!l) return err_does_not_exist(conn, msg, "Invalid node"); -- cgit From 1bd19f3b6236ec87d225589108339086c0b2e8f8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 9 May 2007 10:14:05 +0000 Subject: Update serial service test script --- serial/test-serial | 8 -------- 1 file changed, 8 deletions(-) (limited to 'serial') diff --git a/serial/test-serial b/serial/test-serial index 06e5da55..aec728d4 100755 --- a/serial/test-serial +++ b/serial/test-serial @@ -25,14 +25,6 @@ if (len(sys.argv) < 3): else: service = sys.argv[2] -uuidbase = "-0000-1000-8000-00805F9B34FB" - -if (service == "spp"): - service = "00001101" + uuidbase - -if (service == "dun"): - service = "00001103" + uuidbase - device = serial.ConnectService(address, service) print "Connected %s to %s" % (device, address) -- cgit From d57f86fa59d10c46e82b1b9217387523d77d395a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 12:15:39 +0000 Subject: serial: added verification for pending connects --- serial/manager.c | 81 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 18 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 458a71a2..83f08884 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -100,6 +100,7 @@ static struct { static DBusConnection *connection = NULL; static GSList *connected_nodes = NULL; +static GSList *pending_connects = NULL; static int rfcomm_ctl = -1; static void pending_connect_free(struct pending_connect *pc) @@ -130,9 +131,32 @@ static void rfcomm_node_free(struct rfcomm_node *node) g_free(node); } -static int node_cmp_by_name(struct rfcomm_node *node, const char *name) +static struct rfcomm_node *find_node_by_name(const char *name) { - return strcmp(node->name, name); + GSList *l; + + for (l = connected_nodes; l != NULL; l = l->next) { + struct rfcomm_node *node = l->data; + if (!strcmp(node->name, name)) + return node; + } + + return NULL; +} + +static struct pending_connect *find_pending_connect_by_channel(const char *bda, + uint8_t ch) +{ + GSList *l; + + for (l = pending_connects; l != NULL; l = l->next) { + struct pending_connect *pending = l->data; + if (!strcasecmp(bda, pending->addr) && + pending->channel == ch) + return pending; + } + + return NULL; } static uint16_t str2class(const char *pattern) @@ -155,6 +179,15 @@ static DBusHandlerResult err_connection_failed(DBusConnection *conn, SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); } +static DBusHandlerResult err_connection_in_progress(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionInProgress", + "Connection creation in progress")); +} + static DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg, const char *str) { @@ -301,8 +334,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { error("Connect requestor %s exited", owner); rfcomm_release(pc->id); - pending_connect_free(pc); - return FALSE; + goto fail; } snprintf(node_name, sizeof(node_name), "/dev/rfcomm%d", pc->id); @@ -314,8 +346,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) if (++pc->ntries >= MAX_OPEN_TRIES) { rfcomm_release(pc->id); err_connection_failed(pc->conn, pc->msg, strerror(err)); - pending_connect_free(pc); - return FALSE; + goto fail; } return TRUE; } @@ -332,7 +363,8 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) /* Send the D-Bus signal */ send_signal(pc->conn, "ServiceConnected", node_name); - +fail: + pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); return FALSE; @@ -406,8 +438,9 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, /* Send the D-Bus signal */ send_signal(pc->conn, "ServiceConnected", node_name); fail: + pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); - /* FIXME: Remote from the pending connects list */ + return FALSE; } @@ -449,7 +482,8 @@ static int rfcomm_connect(struct pending_connect *pc) debug("Connect in progress"); g_io_add_watch(io, G_IO_OUT, (GIOFunc) rfcomm_connect_cb, pc); - /* FIXME: Control the pending connects */ + + pending_connects = g_slist_append(pending_connects, pc); } else { debug("Connect succeeded with first try"); (void) rfcomm_connect_cb(io, G_IO_OUT, pc); @@ -461,7 +495,7 @@ fail: static void record_reply(DBusPendingCall *call, void *data) { - struct pending_connect *pc = data; + struct pending_connect *pending, *pc = data; DBusMessage *reply = dbus_pending_call_steal_reply(call); sdp_record_t *rec; const uint8_t *rec_bin; @@ -520,7 +554,11 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - /* FIXME: Check if there is a pending connection or if it was canceled */ + pending = find_pending_connect_by_channel(pc->addr, ch); + if (pending) { + err_connection_in_progress(pc->conn, pc->msg); + goto fail; + } pc->channel = ch; err = rfcomm_connect(pc); @@ -535,6 +573,7 @@ static void record_reply(DBusPendingCall *call, void *data) fail: dbus_message_unref(reply); dbus_error_free(&derr); + pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); } @@ -610,6 +649,7 @@ static void handles_reply(DBusPendingCall *call, void *data) fail: dbus_message_unref(reply); dbus_error_free(&derr); + pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); } @@ -646,7 +686,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, { DBusError derr; bdaddr_t src; - struct pending_connect *pc; + struct pending_connect *pending, *pc; const char *addr, *pattern; char *endptr; long val; @@ -747,11 +787,20 @@ static DBusHandlerResult connect_service(DBusConnection *conn, "invalid RFCOMM channel"); } + /* FIXME: Check if it is already connected */ + + pending = find_pending_connect_by_channel(addr, val); + if (pending) { + pending_connect_free(pc); + return err_connection_in_progress(conn, msg); + } + pc->channel = val; err = rfcomm_connect(pc); if (err < 0) { const char *strerr = strerror(-err); error("RFCOMM connect failed: %s(%d)", strerr, -err); + pending_connect_free(pc); err_connection_failed(conn, msg, strerr); } return DBUS_HANDLER_RESULT_HANDLED; @@ -764,7 +813,6 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, DBusError derr; struct rfcomm_node *node; const char *name; - GSList *l; int err; dbus_error_init(&derr); @@ -776,13 +824,10 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - l = g_slist_find_custom(connected_nodes, name, - (GCompareFunc) node_cmp_by_name); - if (!l) + node = find_node_by_name(name); + if (!node) return err_does_not_exist(conn, msg, "Invalid node"); - node = l->data; - if (strcmp(node->owner, dbus_message_get_sender(msg)) != 0) return err_not_authorized(conn, msg); -- cgit From 3789ae5c5cf7a872c60ea3ffbdcb7071fa63a81e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 9 May 2007 12:22:27 +0000 Subject: Update serial API documentation --- serial/serial-api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 75369da2..cbd8e667 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -49,7 +49,7 @@ Signals void PortCreated(string path) [experimental] void PortRemoved(string path) [experimental] - void ServiceConnected(string device, string adddress, string pattern) + void ServiceConnected(string device) void ServiceDisconnected(string device) -- cgit From 6f6bdcb3ae048fafa7d711d164757f2c05cbe40f Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 13:09:06 +0000 Subject: serial: missing free the pending_connects list and small code cleanup --- serial/manager.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 83f08884..9fbf1f39 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -71,7 +71,7 @@ struct rfcomm_node { struct pending_connect { DBusConnection *conn; DBusMessage *msg; - char *addr; /* Destination address */ + char *bda; /* Destination address */ char *adapter_path; /* Adapter D-Bus path */ bdaddr_t src; uint8_t channel; @@ -109,8 +109,8 @@ static void pending_connect_free(struct pending_connect *pc) dbus_connection_unref(pc->conn); if (pc->msg) dbus_message_unref(pc->msg); - if (pc->addr) - g_free(pc->addr); + if (pc->bda) + g_free(pc->bda); if (pc->adapter_path) g_free(pc->adapter_path); g_free(pc); @@ -151,7 +151,7 @@ static struct pending_connect *find_pending_connect_by_channel(const char *bda, for (l = pending_connects; l != NULL; l = l->next) { struct pending_connect *pending = l->data; - if (!strcasecmp(bda, pending->addr) && + if (!strcasecmp(bda, pending->bda) && pending->channel == ch) return pending; } @@ -351,8 +351,8 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) return TRUE; } - add_rfcomm_node(g_io_channel_unix_new(fd), - pc->id, node_name, pc->conn, owner); + add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, + node_name, pc->conn, owner); /* Reply to the requestor */ reply = dbus_message_new_method_return(pc->msg); @@ -404,7 +404,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, req.dev_id = -1; req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP); bacpy(&req.src, &pc->src); - str2ba(pc->addr, &req.dst); + str2ba(pc->bda, &req.dst); req.channel = pc->channel; pc->id = ioctl(sk, RFCOMMCREATEDEV, &req); @@ -426,7 +426,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, } add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, node_name, - pc->conn, dbus_message_get_sender(pc->msg)); + pc->conn, dbus_message_get_sender(pc->msg)); /* Reply to the requestor */ reply = dbus_message_new_method_return(pc->msg); @@ -469,7 +469,7 @@ static int rfcomm_connect(struct pending_connect *pc) g_io_channel_set_close_on_unref(io, TRUE); addr.rc_family = AF_BLUETOOTH; - str2ba(pc->addr, &addr.rc_bdaddr); + str2ba(pc->bda, &addr.rc_bdaddr); addr.rc_channel = pc->channel; if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { @@ -554,7 +554,7 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - pending = find_pending_connect_by_channel(pc->addr, ch); + pending = find_pending_connect_by_channel(pc->bda, ch); if (pending) { err_connection_in_progress(pc->conn, pc->msg); goto fail; @@ -589,7 +589,7 @@ static int get_record(struct pending_connect *pc, uint32_t handle, return -1; dbus_message_append_args(msg, - DBUS_TYPE_STRING, &pc->addr, + DBUS_TYPE_STRING, &pc->bda, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID); @@ -665,7 +665,7 @@ static int get_handles(struct pending_connect *pc, const char *uuid, return -1; dbus_message_append_args(msg, - DBUS_TYPE_STRING, &pc->addr, + DBUS_TYPE_STRING, &pc->bda, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); @@ -684,21 +684,19 @@ static int get_handles(struct pending_connect *pc, const char *uuid, static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { + struct pending_connect *pending, *pc; DBusError derr; bdaddr_t src; - struct pending_connect *pending, *pc; - const char *addr, *pattern; + const char *bda, *pattern; char *endptr; long val; int dev_id, err; uint16_t cls; char tmp[37]; - /* FIXME: Check if it already exist or if there is pending connect */ - dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &addr, + DBUS_TYPE_STRING, &bda, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { err_invalid_args(conn, msg, derr.message); @@ -714,7 +712,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, bacpy(&pc->src, &src); pc->conn = dbus_connection_ref(conn); pc->msg = dbus_message_ref(msg); - pc->addr = g_strdup(addr); + pc->bda = g_strdup(bda); pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); @@ -787,9 +785,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, "invalid RFCOMM channel"); } - /* FIXME: Check if it is already connected */ - - pending = find_pending_connect_by_channel(addr, val); + pending = find_pending_connect_by_channel(bda, val); if (pending) { pending_connect_free(pc); return err_connection_in_progress(conn, msg); @@ -887,6 +883,13 @@ static void manager_unregister(DBusConnection *conn, void *data) g_slist_free(connected_nodes); connected_nodes = NULL; } + + if (pending_connects) { + g_slist_foreach(pending_connects, + (GFunc) pending_connect_free, NULL); + g_slist_free(pending_connects); + pending_connects = NULL; + } } /* Virtual table to handle manager object path hierarchy */ -- cgit From f0f6c6e23591320ce33f748ecbde483d431df46c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 14:02:11 +0000 Subject: serial: added CancelConnectService --- serial/manager.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 9fbf1f39..0032a995 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -71,12 +71,14 @@ struct rfcomm_node { struct pending_connect { DBusConnection *conn; DBusMessage *msg; - char *bda; /* Destination address */ - char *adapter_path; /* Adapter D-Bus path */ + char *bda; /* Destination address */ + char *adapter_path; /* Adapter D-Bus path */ + char *pattern; /* Connection request pattern */ bdaddr_t src; uint8_t channel; int id; /* RFCOMM device id */ int ntries; /* Open attempts */ + int canceled; /* Operation canceled */ }; /* FIXME: Common file required */ @@ -111,6 +113,8 @@ static void pending_connect_free(struct pending_connect *pc) dbus_message_unref(pc->msg); if (pc->bda) g_free(pc->bda); + if (pc->pattern) + g_free(pc->pattern); if (pc->adapter_path) g_free(pc->adapter_path); g_free(pc); @@ -159,6 +163,22 @@ static struct pending_connect *find_pending_connect_by_channel(const char *bda, return NULL; } +static struct pending_connect *find_pending_connect_by_pattern(const char *bda, + const char *pattern) +{ + GSList *l; + + /* Pattern can be friendly name, uuid128, record handle or channel */ + for (l = pending_connects; l != NULL; l = l->next) { + struct pending_connect *pending = l->data; + if (!strcasecmp(pending->bda, bda) && + !strcasecmp(pending->pattern, pattern)) + return pending; + } + + return NULL; +} + static uint16_t str2class(const char *pattern) { int i; @@ -179,6 +199,15 @@ static DBusHandlerResult err_connection_failed(DBusConnection *conn, SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); } +static DBusHandlerResult err_connection_canceled(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionCanceled", + "Connection creation canceled")); +} + static DBusHandlerResult err_connection_in_progress(DBusConnection *conn, DBusMessage *msg) { @@ -188,6 +217,15 @@ static DBusHandlerResult err_connection_in_progress(DBusConnection *conn, "Connection creation in progress")); } +static DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionNotInProgress", + "Connection creation not in progress")); +} + static DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg, const char *str) { @@ -328,7 +366,11 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) const char *pname = node_name; int fd; - /* FIXME: Check if it was canceled */ + if (pc->canceled) { + rfcomm_release(pc->id); + err_connection_canceled(pc->conn, pc->msg); + goto fail; + } /* Check if the caller is still present */ if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { @@ -380,7 +422,10 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, int sk, ret, err, fd; socklen_t len; - /* FIXME: Check if it was canceled */ + if (pc->canceled) { + err_connection_canceled(pc->conn, pc->msg); + goto fail; + } sk = g_io_channel_unix_get_fd(chan); @@ -503,6 +548,11 @@ static void record_reply(DBusPendingCall *call, void *data) DBusError derr; int len, scanned, ch, err; + if (pc->canceled) { + err_connection_canceled(pc->conn, pc->msg); + goto fail; + } + dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { if (dbus_error_has_name(&derr, @@ -613,6 +663,11 @@ static void handles_reply(DBusPendingCall *call, void *data) uint32_t *phandle; int len; + if (pc->canceled) { + err_connection_canceled(pc->conn, pc->msg); + goto fail; + } + dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { if (dbus_error_has_name(&derr, @@ -713,6 +768,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pc->conn = dbus_connection_ref(conn); pc->msg = dbus_message_ref(msg); pc->bda = g_strdup(bda); + pc->pattern = g_strdup(pattern); pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); @@ -731,7 +787,6 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pending_connect_free(pc); return err_not_supported(conn, msg); } - return DBUS_HANDLER_RESULT_HANDLED; } @@ -848,7 +903,32 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, static DBusHandlerResult cancel_connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + struct pending_connect *pending; + DBusMessage *reply; + DBusError derr; + const char *bda, *pattern; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &pattern, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + pending = find_pending_connect_by_pattern(bda, pattern); + if (!pending) + return err_connection_not_in_progress(conn, msg); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + pending->canceled = 1; + + return send_message_and_unref(conn, reply); } static DBusHandlerResult manager_message(DBusConnection *conn, -- cgit From 98d1e9d7b34c631ded87ae360a3b122b7171079d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 9 May 2007 15:01:49 +0000 Subject: Convert to using generic dbus message dispatching --- serial/manager.c | 61 +++++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 0032a995..becd4476 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -44,6 +44,7 @@ #include #include "dbus.h" +#include "dbus-helper.h" #include "logging.h" #include "manager.h" @@ -931,30 +932,6 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, return send_message_and_unref(conn, reply); } -static DBusHandlerResult manager_message(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *iface, *member; - - iface = dbus_message_get_interface(msg); - member = dbus_message_get_member(msg); - - /* Accept messages from the manager interface only */ - if (strcmp(SERIAL_MANAGER_INTERFACE, iface)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (strcmp(member, "ConnectService") == 0) - return connect_service(conn, msg, data); - - if (strcmp(member, "DisconnectService") == 0) - return disconnect_service(conn, msg, data); - - if (strcmp(member, "CancelConnectService") == 0) - return cancel_connect_service(conn, msg, data); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - static void manager_unregister(DBusConnection *conn, void *data) { if (connected_nodes) { @@ -972,10 +949,17 @@ static void manager_unregister(DBusConnection *conn, void *data) } } -/* Virtual table to handle manager object path hierarchy */ -static const DBusObjectPathVTable manager_table = { - .message_function = manager_message, - .unregister_function = manager_unregister, +static DBusMethodVTable manager_methods[] = { + { "ConnectService", connect_service, "ss", "s" }, + { "DisconnectService", disconnect_service, "s", "" }, + { "CancelConnectService", cancel_connect_service, "ss", "" }, + { NULL, NULL, NULL, NULL }, +}; + +static DBusSignalVTable manager_signals[] = { + { "ServiceConnected", "s" }, + { "ServiceDisconnected", "s" }, + { NULL, NULL } }; int serial_init(DBusConnection *conn) @@ -987,16 +971,25 @@ int serial_init(DBusConnection *conn) return -errno; } - connection = dbus_connection_ref(conn); - - if (dbus_connection_register_object_path(connection, - SERIAL_MANAGER_PATH, &manager_table, NULL) == FALSE) { + if (!dbus_connection_create_object_path(conn, SERIAL_MANAGER_PATH, + NULL, manager_unregister)) { error("D-Bus failed to register %s path", SERIAL_MANAGER_PATH); - dbus_connection_unref(connection); + return -1; + } + if (!dbus_connection_register_interface(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, + manager_methods, + manager_signals, NULL)) { + error("Failed to register %s interface to %s", + SERIAL_MANAGER_INTERFACE, SERIAL_MANAGER_PATH); + dbus_connection_destroy_object_path(connection, + SERIAL_MANAGER_PATH); return -1; } + connection = dbus_connection_ref(conn); + info("Registered manager path:%s", SERIAL_MANAGER_PATH); return 0; @@ -1004,7 +997,7 @@ int serial_init(DBusConnection *conn) void serial_exit(void) { - dbus_connection_unregister_object_path(connection, SERIAL_MANAGER_PATH); + dbus_connection_destroy_object_path(connection, SERIAL_MANAGER_PATH); dbus_connection_unref(connection); connection = NULL; -- cgit From 366b8792a7fde8056ad8f12484d5e87239441b1d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 17:07:48 +0000 Subject: serial: service record leak and small pending connect fix --- serial/manager.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index becd4476..d9162873 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -53,7 +53,6 @@ #define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" #define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" -#define PATH_LENGTH 32 #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" /* Waiting for udev to create the device node */ @@ -528,7 +527,6 @@ static int rfcomm_connect(struct pending_connect *pc) debug("Connect in progress"); g_io_add_watch(io, G_IO_OUT, (GIOFunc) rfcomm_connect_cb, pc); - pending_connects = g_slist_append(pending_connects, pc); } else { debug("Connect succeeded with first try"); @@ -564,6 +562,7 @@ static void record_reply(DBusPendingCall *call, void *data) error("GetRemoteServiceRecord: %s(%s)", derr.name, derr.message); + dbus_error_free(&derr); goto fail; } @@ -572,6 +571,7 @@ static void record_reply(DBusPendingCall *call, void *data) DBUS_TYPE_INVALID)) { err_not_supported(pc->conn, pc->msg); error("%s: %s", derr.name, derr.message); + dbus_error_free(&derr); goto fail; } @@ -598,9 +598,10 @@ static void record_reply(DBusPendingCall *call, void *data) sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); + sdp_record_free(rec); + if (ch < 1 || ch > 30) { error("Channel out of range: %d", ch); - sdp_record_free(rec); err_not_supported(pc->conn, pc->msg); goto fail; } @@ -623,7 +624,6 @@ static void record_reply(DBusPendingCall *call, void *data) return; fail: dbus_message_unref(reply); - dbus_error_free(&derr); pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); } @@ -679,6 +679,7 @@ static void handles_reply(DBusPendingCall *call, void *data) error("GetRemoteServiceHandles: %s(%s)", derr.name, derr.message); + dbus_error_free(&derr); goto fail; } @@ -687,6 +688,7 @@ static void handles_reply(DBusPendingCall *call, void *data) &len, DBUS_TYPE_INVALID)) { err_not_supported(pc->conn, pc->msg); error("%s: %s", derr.name, derr.message); + dbus_error_free(&derr); goto fail; } @@ -704,7 +706,6 @@ static void handles_reply(DBusPendingCall *call, void *data) return; fail: dbus_message_unref(reply); - dbus_error_free(&derr); pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); } @@ -760,6 +761,10 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } + pending = find_pending_connect_by_pattern(bda, pattern); + if (pending) + return err_connection_in_progress(conn, msg); + dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) return err_failed(conn, msg, "Adapter not available"); @@ -788,6 +793,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pending_connect_free(pc); return err_not_supported(conn, msg); } + pending_connects = g_slist_append(pending_connects, pc); return DBUS_HANDLER_RESULT_HANDLED; } @@ -808,6 +814,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pending_connect_free(pc); return err_not_supported(conn, msg); } + pending_connects = g_slist_append(pending_connects, pc); return DBUS_HANDLER_RESULT_HANDLED; } @@ -831,6 +838,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pending_connect_free(pc); return err_not_supported(conn, msg); } + pending_connects = g_slist_append(pending_connects, pc); return DBUS_HANDLER_RESULT_HANDLED; } @@ -841,19 +849,13 @@ static DBusHandlerResult connect_service(DBusConnection *conn, "invalid RFCOMM channel"); } - pending = find_pending_connect_by_channel(bda, val); - if (pending) { - pending_connect_free(pc); - return err_connection_in_progress(conn, msg); - } - pc->channel = val; err = rfcomm_connect(pc); if (err < 0) { const char *strerr = strerror(-err); error("RFCOMM connect failed: %s(%d)", strerr, -err); pending_connect_free(pc); - err_connection_failed(conn, msg, strerr); + return err_connection_failed(conn, msg, strerr); } return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From a7fb39b7fec5bf46bc486fc3a1a693271185113f Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 17:37:24 +0000 Subject: serial: using dbus_connection_emit_signal --- serial/manager.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index d9162873..c4d29b45 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -294,19 +294,6 @@ static int rfcomm_release(int16_t id) return 0; } -static void send_signal(DBusConnection *conn, - const char *sname, const char *node_name) -{ - DBusMessage *signal; - - signal = dbus_message_new_signal(SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, sname); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &node_name, - DBUS_TYPE_INVALID); - send_message_and_unref(conn, signal); -} - static void connect_service_exited(const char *name, struct rfcomm_node *node) { debug("Connect requestor %s exited. Releasing %s node", @@ -314,7 +301,10 @@ static void connect_service_exited(const char *name, struct rfcomm_node *node) rfcomm_release(node->id); - send_signal(node->conn, "ServiceDisconnected", node->name); + dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , + DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_INVALID); connected_nodes = g_slist_remove(connected_nodes, node); rfcomm_node_free(node); @@ -328,7 +318,10 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, name_listener_remove(node->conn, node->owner, (name_cb_t) connect_service_exited, node); - send_signal(node->conn, "ServiceDisconnected", node->name); + dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , + DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_INVALID); connected_nodes = g_slist_remove(connected_nodes, node); rfcomm_node_free(node); @@ -404,7 +397,11 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) send_message_and_unref(pc->conn, reply); /* Send the D-Bus signal */ - send_signal(pc->conn, "ServiceConnected", node_name); + dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceConnected" , + DBUS_TYPE_STRING, &pname, + DBUS_TYPE_INVALID); + fail: pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); @@ -481,7 +478,11 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, send_message_and_unref(pc->conn, reply); /* Send the D-Bus signal */ - send_signal(pc->conn, "ServiceConnected", node_name); + dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceConnected" , + DBUS_TYPE_STRING, &pname, + DBUS_TYPE_INVALID); + fail: pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); @@ -895,6 +896,11 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, return err_failed(conn, msg, strerror(err)); } + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , + DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_INVALID); + name_listener_remove(node->conn, node->owner, (name_cb_t) connect_service_exited, node); connected_nodes = g_slist_remove(connected_nodes, node); -- cgit From 1dd87340fa57eb1a6b32f3cb78cc3a309e076b09 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 19:14:12 +0000 Subject: serial: let the kernel handle device busy --- serial/manager.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index c4d29b45..4de3ce87 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -148,21 +148,6 @@ static struct rfcomm_node *find_node_by_name(const char *name) return NULL; } -static struct pending_connect *find_pending_connect_by_channel(const char *bda, - uint8_t ch) -{ - GSList *l; - - for (l = pending_connects; l != NULL; l = l->next) { - struct pending_connect *pending = l->data; - if (!strcasecmp(bda, pending->bda) && - pending->channel == ch) - return pending; - } - - return NULL; -} - static struct pending_connect *find_pending_connect_by_pattern(const char *bda, const char *pattern) { @@ -540,7 +525,7 @@ fail: static void record_reply(DBusPendingCall *call, void *data) { - struct pending_connect *pending, *pc = data; + struct pending_connect *pc = data; DBusMessage *reply = dbus_pending_call_steal_reply(call); sdp_record_t *rec; const uint8_t *rec_bin; @@ -607,12 +592,6 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - pending = find_pending_connect_by_channel(pc->bda, ch); - if (pending) { - err_connection_in_progress(pc->conn, pc->msg); - goto fail; - } - pc->channel = ch; err = rfcomm_connect(pc); if (err < 0) { -- cgit From 9e824dd2ce0e935616074a7242eab1a57fa8b86f Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 19:33:49 +0000 Subject: serial: handle the pending connects list properly when connect() in the first try happens --- serial/manager.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 4de3ce87..f4480404 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -513,7 +513,6 @@ static int rfcomm_connect(struct pending_connect *pc) debug("Connect in progress"); g_io_add_watch(io, G_IO_OUT, (GIOFunc) rfcomm_connect_cb, pc); - pending_connects = g_slist_append(pending_connects, pc); } else { debug("Connect succeeded with first try"); (void) rfcomm_connect_cb(io, G_IO_OUT, pc); @@ -829,11 +828,15 @@ static DBusHandlerResult connect_service(DBusConnection *conn, "invalid RFCOMM channel"); } + /* Add here since connect() in the first try can happen */ + pending_connects = g_slist_append(pending_connects, pc); + pc->channel = val; err = rfcomm_connect(pc); if (err < 0) { const char *strerr = strerror(-err); error("RFCOMM connect failed: %s(%d)", strerr, -err); + pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); return err_connection_failed(conn, msg, strerr); } -- cgit From c7ff83efffd73e9ca82aa29990faaa38c90bd826 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 21:28:22 +0000 Subject: serial: handle socket errors properly - timeout waiting linkkey or other errors can happen --- serial/manager.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index f4480404..90637123 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -404,6 +404,12 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, int sk, ret, err, fd; socklen_t len; + if (cond & (G_IO_ERR | G_IO_HUP)) { + error("Hangup or error on rfcomm socket"); + err_connection_canceled(pc->conn, pc->msg); + goto fail; + } + if (pc->canceled) { err_connection_canceled(pc->conn, pc->msg); goto fail; @@ -512,7 +518,8 @@ static int rfcomm_connect(struct pending_connect *pc) } debug("Connect in progress"); - g_io_add_watch(io, G_IO_OUT, (GIOFunc) rfcomm_connect_cb, pc); + g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP, + (GIOFunc) rfcomm_connect_cb, pc); } else { debug("Connect succeeded with first try"); (void) rfcomm_connect_cb(io, G_IO_OUT, pc); -- cgit From d997f1912250982b6b7e4eae7516245c9be291b7 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 May 2007 22:38:56 +0000 Subject: serial: handle connection refused error and others SO_ERROR properly --- serial/manager.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 90637123..0c2baba9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -401,14 +401,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, char node_name[16]; const char *pname = node_name; struct rfcomm_dev_req req; - int sk, ret, err, fd; - socklen_t len; - - if (cond & (G_IO_ERR | G_IO_HUP)) { - error("Hangup or error on rfcomm socket"); - err_connection_canceled(pc->conn, pc->msg); - goto fail; - } + int sk, err, fd; if (pc->canceled) { err_connection_canceled(pc->conn, pc->msg); @@ -417,17 +410,28 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, sk = g_io_channel_unix_get_fd(chan); - len = sizeof(ret); - if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { - err = errno; - error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err); - err_connection_failed(pc->conn, pc->msg, strerror(err)); - goto fail; - } + if (cond & (G_IO_ERR | G_IO_HUP)) { + socklen_t len; + int ret; + + len = sizeof(ret); + if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { + err = errno; + error("getsockopt(SO_ERROR): %s (%d)", + strerror(err), err); + err_connection_failed(pc->conn, + pc->msg, strerror(err)); + goto fail; + } - if (ret != 0) { - error("connect(): %s (%d)", strerror(ret), ret); - err_connection_failed(pc->conn, pc->msg, strerror(ret)); + if (ret != 0) { + error("connect(): %s (%d)", strerror(ret), ret); + err_connection_failed(pc->conn, pc->msg, strerror(ret)); + goto fail; + } + + error("Hangup on rfcomm socket"); + err_connection_canceled(pc->conn, pc->msg); goto fail; } -- cgit From 07958fc3612225ceeffcbbcbae320a2bedcd774d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 May 2007 08:45:28 +0000 Subject: Update API descriptions --- serial/serial-api.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index cbd8e667..9b1c67a3 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -53,6 +53,7 @@ Signals void PortCreated(string path) [experimental] void ServiceDisconnected(string device) + Port hierarchy (experimental) ============================= @@ -60,11 +61,13 @@ Interface org.bluez.serial.Port Object path /org/bluez/serial/port* Methods string GetAddress() + Returns the Bluetooth address of the ending point. string Connect() - Connects to remote device associated to the port object. + Connects to remote device associated to the port + object. Possible errors:org.bluez.serial.Error.ConnectionAttemptFailed org.bluez.serial.Error.Failed -- cgit From 8ee70afdcabbe9a105869a1b488a7c59fab4cc5c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 10 May 2007 13:23:32 +0000 Subject: serial API: updated possible errors --- serial/serial-api.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 9b1c67a3..bff9248c 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -36,15 +36,27 @@ Methods string CreatePort(string address, string pattern) [experimental] remote device and then creates a RFCOMM TTY device for it. The RFCOMM TTY device is returned. + Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.ConnectionInProgress + org.bluez.serial.Error.NotSupported + org.bluez.serial.Error.ConnectionAttemptFailed + void CancelConnectService(string address, string pattern) Cancel a previous ConnectService method call. + Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.ConnectionNotInProgress + void DisconnectService(string device) Disconnect a RFCOMM TTY device that has been created via the ConnectService method. + Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.NotAuthorized + org.bluez.serial.Error.Failed + Signals void PortCreated(string path) [experimental] void PortRemoved(string path) [experimental] -- cgit From e26377ac2dec7905881b1c062795b7057de91c18 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 10 May 2007 13:37:51 +0000 Subject: serial: fixed returned error value for DisconnectService --- serial/manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 0c2baba9..5f6ad065 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -886,7 +886,7 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, err = rfcomm_release(node->id); if (err < 0) { dbus_message_unref(reply); - return err_failed(conn, msg, strerror(err)); + return err_failed(conn, msg, strerror(-err)); } dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, -- cgit From f32fbc4028fd7677674b3c15b324b053c0f5ca91 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 10 May 2007 16:52:34 +0000 Subject: serial API: added experimental tag for "Port" methods --- serial/serial-api.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index bff9248c..dc2a2eba 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -72,11 +72,11 @@ Port hierarchy (experimental) Interface org.bluez.serial.Port Object path /org/bluez/serial/port* -Methods string GetAddress() +Methods string GetAddress() [experimental] Returns the Bluetooth address of the ending point. - string Connect() + string Connect() [experimental] Connects to remote device associated to the port object. @@ -84,7 +84,7 @@ Methods string GetAddress() Possible errors:org.bluez.serial.Error.ConnectionAttemptFailed org.bluez.serial.Error.Failed - void Disconnect() + void Disconnect() [experimental] Disconnects from remote device. -- cgit From daea1f31faccd8e5f154a81e7812b4afb4f000b0 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 14 May 2007 21:05:45 +0000 Subject: serial: added G_IO_NVAL flag to fix potential busy loop --- serial/manager.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 5f6ad065..2c797191 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -300,6 +300,9 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, { debug("RFCOMM node %s was disconnected", node->name); + if (cond & (G_IO_ERR | G_IO_HUP)) + g_io_channel_close(io); + name_listener_remove(node->conn, node->owner, (name_cb_t) connect_service_exited, node); @@ -326,9 +329,8 @@ static int add_rfcomm_node(GIOChannel *io, int id, const char *name, node->owner = g_strdup(owner); node->io = io; - g_io_channel_set_close_on_unref(io, TRUE); - node->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP, - (GIOFunc) rfcomm_disconnect_cb, node); + node->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc) rfcomm_disconnect_cb, node); connected_nodes = g_slist_append(connected_nodes, node); @@ -401,7 +403,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, char node_name[16]; const char *pname = node_name; struct rfcomm_dev_req req; - int sk, err, fd; + int sk, err, fd, close_chan = 1; if (pc->canceled) { err_connection_canceled(pc->conn, pc->msg); @@ -410,6 +412,13 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, sk = g_io_channel_unix_get_fd(chan); + if (cond & G_IO_NVAL) { + close_chan = 0; + err_connection_failed(pc->conn, pc->msg, + "File descriptor is not open"); + goto fail; + } + if (cond & (G_IO_ERR | G_IO_HUP)) { socklen_t len; int ret; @@ -459,6 +468,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, if (fd < 0) { g_timeout_add(OPEN_WAIT, (GSourceFunc) rfcomm_connect_cb_continue, pc); + g_io_channel_close(chan); return FALSE; } @@ -482,6 +492,9 @@ fail: pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); + if (close_chan) + g_io_channel_close(chan); + return FALSE; } @@ -507,7 +520,6 @@ static int rfcomm_connect(struct pending_connect *pc) return -errno; io = g_io_channel_unix_new(sk); - g_io_channel_set_close_on_unref(io, TRUE); addr.rc_family = AF_BLUETOOTH; str2ba(pc->bda, &addr.rc_bdaddr); @@ -522,8 +534,8 @@ static int rfcomm_connect(struct pending_connect *pc) } debug("Connect in progress"); - g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP, - (GIOFunc) rfcomm_connect_cb, pc); + g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc) rfcomm_connect_cb, pc); } else { debug("Connect succeeded with first try"); (void) rfcomm_connect_cb(io, G_IO_OUT, pc); -- cgit From e5d465b5adb59f2b199819793939d781376b7d75 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 15 May 2007 14:15:52 +0000 Subject: Add new file skeletons --- serial/Makefile.am | 4 +++- serial/error.c | 28 ++++++++++++++++++++++++++++ serial/error.h | 22 ++++++++++++++++++++++ serial/port.c | 28 ++++++++++++++++++++++++++++ serial/port.h | 22 ++++++++++++++++++++++ serial/storage.c | 28 ++++++++++++++++++++++++++++ serial/storage.h | 22 ++++++++++++++++++++++ 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 serial/error.c create mode 100644 serial/error.h create mode 100644 serial/port.c create mode 100644 serial/port.h create mode 100644 serial/storage.c create mode 100644 serial/storage.h (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 9d47f2db..75f50b80 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -10,7 +10,9 @@ servicedir = $(libdir)/bluetooth service_PROGRAMS = bluetoothd-service-serial -bluetoothd_service_serial_SOURCES = main.c manager.h manager.c +bluetoothd_service_serial_SOURCES = main.c \ + manager.h manager.c port.h port.c \ + error.h error.c storage.h storage.c LDADD = $(top_builddir)/common/libhelper.a \ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ diff --git a/serial/error.c b/serial/error.c new file mode 100644 index 00000000..55c459da --- /dev/null +++ b/serial/error.c @@ -0,0 +1,28 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "error.h" diff --git a/serial/error.h b/serial/error.h new file mode 100644 index 00000000..e87dd676 --- /dev/null +++ b/serial/error.h @@ -0,0 +1,22 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ diff --git a/serial/port.c b/serial/port.c new file mode 100644 index 00000000..80e3c6df --- /dev/null +++ b/serial/port.c @@ -0,0 +1,28 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "port.h" diff --git a/serial/port.h b/serial/port.h new file mode 100644 index 00000000..e87dd676 --- /dev/null +++ b/serial/port.h @@ -0,0 +1,22 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ diff --git a/serial/storage.c b/serial/storage.c new file mode 100644 index 00000000..bf885407 --- /dev/null +++ b/serial/storage.c @@ -0,0 +1,28 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "storage.h" diff --git a/serial/storage.h b/serial/storage.h new file mode 100644 index 00000000..e87dd676 --- /dev/null +++ b/serial/storage.h @@ -0,0 +1,22 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2007 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ -- cgit From ceeb274a3bc8f4fda2a08c1a831a1ffbfb2f85a8 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 15 May 2007 16:59:41 +0000 Subject: serial: moving error functions to error.c --- serial/error.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ serial/error.h | 21 +++++++++++++++ serial/manager.c | 79 +------------------------------------------------------- 3 files changed, 101 insertions(+), 78 deletions(-) (limited to 'serial') diff --git a/serial/error.c b/serial/error.c index 55c459da..c3ec9144 100644 --- a/serial/error.c +++ b/serial/error.c @@ -26,3 +26,82 @@ #endif #include "error.h" + +#define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" + +DBusHandlerResult err_connection_canceled(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionCanceled", + "Connection creation canceled")); +} + +DBusHandlerResult err_connection_failed(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); +} + +DBusHandlerResult err_connection_in_progress(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionInProgress", + "Connection creation in progress")); +} + +DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE".ConnectionNotInProgress", + "Connection creation not in progress")); +} + +DBusHandlerResult err_does_not_exist(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".DoesNotExist", str)); +} + +DBusHandlerResult err_failed(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".Failed", str)); +} + +DBusHandlerResult err_invalid_args(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); +} + +DBusHandlerResult err_not_authorized(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".NotAuthorized", + "Owner not allowed")); +} + +DBusHandlerResult err_not_supported(DBusConnection *conn, + DBusMessage *msg) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".NotSupported", + "The service is not supported by the remote device")); +} diff --git a/serial/error.h b/serial/error.h index e87dd676..d43d87ca 100644 --- a/serial/error.h +++ b/serial/error.h @@ -20,3 +20,24 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + +#include + +DBusHandlerResult err_connection_canceled(DBusConnection *conn, + DBusMessage *msg); +DBusHandlerResult err_connection_failed(DBusConnection *conn, + DBusMessage *msg, const char *str); +DBusHandlerResult err_connection_in_progress(DBusConnection *conn, + DBusMessage *msg); +DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, + DBusMessage *msg); +DBusHandlerResult err_does_not_exist(DBusConnection *conn, + DBusMessage *msg, const char *str); +DBusHandlerResult err_failed(DBusConnection *conn, + DBusMessage *msg, const char *str); +DBusHandlerResult err_invalid_args(DBusConnection *conn, + DBusMessage *msg, const char *str); +DBusHandlerResult err_not_authorized(DBusConnection *conn, + DBusMessage *msg); +DBusHandlerResult err_not_supported(DBusConnection *conn, + DBusMessage *msg); diff --git a/serial/manager.c b/serial/manager.c index 2c797191..58263721 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -47,11 +47,11 @@ #include "dbus-helper.h" #include "logging.h" +#include "error.h" #include "manager.h" #define SERIAL_MANAGER_PATH "/org/bluez/serial" #define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" -#define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" @@ -176,83 +176,6 @@ static uint16_t str2class(const char *pattern) return 0; } -static DBusHandlerResult err_connection_failed(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); -} - -static DBusHandlerResult err_connection_canceled(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionCanceled", - "Connection creation canceled")); -} - -static DBusHandlerResult err_connection_in_progress(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionInProgress", - "Connection creation in progress")); -} - -static DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionNotInProgress", - "Connection creation not in progress")); -} - -static DBusHandlerResult err_does_not_exist(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".DoesNotExist", str)); -} - -static DBusHandlerResult err_failed(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".Failed", str)); -} - -static DBusHandlerResult err_invalid_args(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); -} - -static DBusHandlerResult err_not_authorized(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".NotAuthorized", - "Owner not allowed")); -} - -static DBusHandlerResult err_not_supported(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".NotSupported", - "The service is not supported by the remote device")); -} - static int rfcomm_release(int16_t id) { struct rfcomm_dev_req req; -- cgit From 2ebe2befb56e62e81ec42f81450118a8721724e0 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 15 May 2007 17:07:22 +0000 Subject: serial: Added CreatePort, ListPorts and RemovePort declaration --- serial/manager.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 58263721..b5ced583 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -663,6 +663,24 @@ static int get_handles(struct pending_connect *pc, const char *uuid, return 0; } +static DBusHandlerResult create_port(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult list_ports(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult remove_port(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -886,6 +904,9 @@ static void manager_unregister(DBusConnection *conn, void *data) } static DBusMethodVTable manager_methods[] = { + { "CreatePort", create_port, "ss", "s" }, + { "ListPorts", list_ports, "", "as" }, + { "RemovePort", remove_port, "s", "" }, { "ConnectService", connect_service, "ss", "s" }, { "DisconnectService", disconnect_service, "s", "" }, { "CancelConnectService", cancel_connect_service, "ss", "" }, -- cgit From 5caf7e18f9534e9cd16264026169016ccbcdb1fa Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 16 May 2007 21:04:12 +0000 Subject: serial: moving functions to port.c and added port methods declaration --- serial/manager.c | 493 +++++++++++++++++++++++++++++-------------------------- serial/manager.h | 6 + serial/port.c | 258 +++++++++++++++++++++++++++++ serial/port.h | 11 ++ 4 files changed, 535 insertions(+), 233 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index b5ced583..c33f51cb 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -48,26 +48,11 @@ #include "logging.h" #include "error.h" +#include "port.h" #include "manager.h" -#define SERIAL_MANAGER_PATH "/org/bluez/serial" -#define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" - #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" -/* Waiting for udev to create the device node */ -#define MAX_OPEN_TRIES 5 -#define OPEN_WAIT 300 /* ms */ - -struct rfcomm_node { - int16_t id; /* RFCOMM device id */ - char *name; /* RFCOMM device name */ - DBusConnection *conn; /* for name listener handling */ - char *owner; /* Bus name */ - GIOChannel *io; /* Connected node IO Channel */ - guint io_id; /* IO Channel ID */ -}; - struct pending_connect { DBusConnection *conn; DBusMessage *msg; @@ -101,7 +86,6 @@ static struct { }; static DBusConnection *connection = NULL; -static GSList *connected_nodes = NULL; static GSList *pending_connects = NULL; static int rfcomm_ctl = -1; @@ -120,32 +104,10 @@ static void pending_connect_free(struct pending_connect *pc) g_free(pc); } -static void rfcomm_node_free(struct rfcomm_node *node) -{ - if (node->name) - g_free(node->name); - if (node->conn) - dbus_connection_unref(node->conn); - if (node->owner) - g_free(node->owner); - if (node->io) { - g_source_remove(node->io_id); - g_io_channel_unref(node->io); - } - g_free(node); -} - -static struct rfcomm_node *find_node_by_name(const char *name) +static void pending_connect_remove(struct pending_connect *pc) { - GSList *l; - - for (l = connected_nodes; l != NULL; l = l->next) { - struct rfcomm_node *node = l->data; - if (!strcmp(node->name, name)) - return node; - } - - return NULL; + pending_connects = g_slist_remove(pending_connects, pc); + pending_connect_free(pc); } static struct pending_connect *find_pending_connect_by_pattern(const char *bda, @@ -176,7 +138,7 @@ static uint16_t str2class(const char *pattern) return 0; } -static int rfcomm_release(int16_t id) +int rfcomm_release(int16_t id) { struct rfcomm_dev_req req; @@ -202,102 +164,59 @@ static int rfcomm_release(int16_t id) return 0; } -static void connect_service_exited(const char *name, struct rfcomm_node *node) -{ - debug("Connect requestor %s exited. Releasing %s node", - name, node->name); - - rfcomm_release(node->id); - - dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , - DBUS_TYPE_STRING, &node->name, - DBUS_TYPE_INVALID); - - connected_nodes = g_slist_remove(connected_nodes, node); - rfcomm_node_free(node); -} - -static gboolean rfcomm_disconnect_cb(GIOChannel *io, - GIOCondition cond, struct rfcomm_node *node) -{ - debug("RFCOMM node %s was disconnected", node->name); - - if (cond & (G_IO_ERR | G_IO_HUP)) - g_io_channel_close(io); - - name_listener_remove(node->conn, node->owner, - (name_cb_t) connect_service_exited, node); - - dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , - DBUS_TYPE_STRING, &node->name, - DBUS_TYPE_INVALID); - - connected_nodes = g_slist_remove(connected_nodes, node); - rfcomm_node_free(node); - - return FALSE; -} - -static int add_rfcomm_node(GIOChannel *io, int id, const char *name, - DBusConnection *conn, const char *owner) +static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, uint8_t ch) { - struct rfcomm_node *node; - - node = g_new0(struct rfcomm_node, 1); - node->id = id; - node->name = g_strdup(name); - node->conn = dbus_connection_ref(conn); - node->owner = g_strdup(owner); - node->io = io; + struct rfcomm_dev_req req; + int id; - node->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_NVAL | G_IO_HUP, - (GIOFunc) rfcomm_disconnect_cb, node); + memset(&req, 0, sizeof(req)); + req.dev_id = -1; + req.flags = 0; + bacpy(&req.src, src); + bacpy(&req.dst, dst); + req.channel = ch; - connected_nodes = g_slist_append(connected_nodes, node); + id = ioctl(rfcomm_ctl, RFCOMMCREATEDEV, &req); + if (id < 0) { + int err = errno; + error("RFCOMMCREATEDEV failed: %s (%d)", strerror(err), err); + return -err; + } - return name_listener_add(node->conn, owner, - (name_cb_t) connect_service_exited, node); + return id; } -static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) +static void open_notify(int fd, int err, void *data) { - const char *owner = dbus_message_get_sender(pc->msg); + char port_name[16]; + char path[MAX_PATH_LENGTH]; + const char *pname = port_name; + const char *ppath = path; + const char *owner; DBusMessage *reply; - char node_name[16]; - const char *pname = node_name; - int fd; + struct pending_connect *pc = data; + + if (err) { + /* Max tries exceeded */ + err_connection_failed(pc->conn, pc->msg, strerror(err)); + return; + } if (pc->canceled) { rfcomm_release(pc->id); err_connection_canceled(pc->conn, pc->msg); - goto fail; + return; } /* Check if the caller is still present */ + owner = dbus_message_get_sender(pc->msg); if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { error("Connect requestor %s exited", owner); rfcomm_release(pc->id); - goto fail; - } - - snprintf(node_name, sizeof(node_name), "/dev/rfcomm%d", pc->id); - fd = open(node_name, O_RDONLY | O_NOCTTY); - if (fd < 0) { - int err = errno; - error("Could not open %s: %s (%d)", - node_name, strerror(err), err); - if (++pc->ntries >= MAX_OPEN_TRIES) { - rfcomm_release(pc->id); - err_connection_failed(pc->conn, pc->msg, strerror(err)); - goto fail; - } - return TRUE; + return; } - add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, - node_name, pc->conn, owner); + snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", pc->id); /* Reply to the requestor */ reply = dbus_message_new_method_return(pc->msg); @@ -307,24 +226,23 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc) send_message_and_unref(pc->conn, reply); /* Send the D-Bus signal */ + port_register(pc->conn, pc->id, fd, pname, owner, path); + dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortCreated" , + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceConnected" , DBUS_TYPE_STRING, &pname, - DBUS_TYPE_INVALID); - -fail: - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); + DBUS_TYPE_INVALID); - return FALSE; } static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct pending_connect *pc) { - DBusMessage *reply; - char node_name[16]; - const char *pname = node_name; + char port_name[16]; struct rfcomm_dev_req req; int sk, err, fd, close_chan = 1; @@ -384,37 +302,20 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, goto fail; } - - snprintf(node_name, sizeof(node_name), "/dev/rfcomm%d", pc->id); - - fd = open(node_name, O_RDONLY | O_NOCTTY); + snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", pc->id); + /* Addressing connect port */ + fd = port_open(port_name, open_notify, pc, + (udata_free_t) pending_connect_remove); if (fd < 0) { - g_timeout_add(OPEN_WAIT, - (GSourceFunc) rfcomm_connect_cb_continue, pc); g_io_channel_close(chan); + /* Open in progress: Wait the callback */ return FALSE; } - add_rfcomm_node(g_io_channel_unix_new(fd), pc->id, node_name, - pc->conn, dbus_message_get_sender(pc->msg)); - - /* Reply to the requestor */ - reply = dbus_message_new_method_return(pc->msg); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &pname, - DBUS_TYPE_INVALID); - send_message_and_unref(pc->conn, reply); - - /* Send the D-Bus signal */ - dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ServiceConnected" , - DBUS_TYPE_STRING, &pname, - DBUS_TYPE_INVALID); - + open_notify(fd, 0, pc); fail: pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); - if (close_chan) g_io_channel_close(chan); @@ -537,16 +438,48 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - pc->channel = ch; - err = rfcomm_connect(pc); - if (err < 0) { - error("RFCOMM connection failed"); - err_connection_failed(pc->conn, pc->msg, strerror(-err)); - goto fail; + if (dbus_message_has_member(pc->msg, "CreatePort")) { + char path[MAX_PATH_LENGTH]; + char port_name[16]; + const char *ppath = path; + DBusMessage *reply; + bdaddr_t dst; + + str2ba(pc->bda, &dst); + err = rfcomm_bind(&pc->src, &dst, ch); + if (err < 0) { + err_failed(pc->conn, pc->msg, strerror(-err)); + goto fail; + } + + snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); + port_register(pc->conn, err, -1, port_name, NULL, path); + + reply = dbus_message_new_method_return(pc->msg); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + send_message_and_unref(pc->conn, reply); + + dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortCreated" , + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + } else { + /* ConnectService */ + pc->channel = ch; + err = rfcomm_connect(pc); + if (err < 0) { + error("RFCOMM connection failed"); + err_connection_failed(pc->conn, pc->msg, strerror(-err)); + goto fail; + } + + /* Wait the connect callback */ + dbus_message_unref(reply); + return; } - dbus_message_unref(reply); - return; fail: dbus_message_unref(reply); pending_connects = g_slist_remove(pending_connects, pc); @@ -663,10 +596,153 @@ static int get_handles(struct pending_connect *pc, const char *uuid, return 0; } +static int pattern2uuid128(const char *pattern, char *uuid, size_t size) +{ + uint16_t cls; + + /* Friendly name */ + cls = str2class(pattern); + if (cls) { + uuid_t uuid16, uuid128; + + sdp_uuid16_create(&uuid16, cls); + sdp_uuid16_to_uuid128(&uuid128, &uuid16); + sdp_uuid2strn(&uuid128, uuid, size); + return 0; + } + + /* UUID 128*/ + if ((strlen(pattern) == 36) && + (strncasecmp(BASE_UUID, pattern, 3) == 0) && + (strncasecmp(BASE_UUID + 8, pattern + 8, 28) == 0)) { + + strncpy(uuid, pattern, size); + return 0; + } + + return -EINVAL; +} + +static int pattern2long(const char *pattern, long *pval) +{ + char *endptr; + long val; + + errno = 0; + val = strtol(pattern, &endptr, 0); + if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || + (errno != 0 && val == 0) || (pattern == endptr)) { + return -EINVAL; + } + + *pval = val; + + return 0; +} + static DBusHandlerResult create_port(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + struct pending_connect *pending, *pc; + DBusMessage *reply; + DBusError derr; + bdaddr_t src, dst; + char path[MAX_PATH_LENGTH]; + const char *bda, *pattern, *ppath = path; + long val; + int dev_id, err; + char port_name[16]; + char uuid[37]; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &pattern, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + pending = find_pending_connect_by_pattern(bda, pattern); + if (pending) + return err_connection_in_progress(conn, msg); + + dev_id = hci_get_route(NULL); + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) + return err_failed(conn, msg, "Adapter not available"); + + pc = g_new0(struct pending_connect, 1); + bacpy(&pc->src, &src); + pc->conn = dbus_connection_ref(conn); + pc->msg = dbus_message_ref(msg); + pc->bda = g_strdup(bda); + pc->pattern = g_strdup(pattern); + pc->adapter_path = g_malloc0(16); + snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); + + memset(uuid, 0, sizeof(uuid)); + + /* Friendly name or uuid128 */ + if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) { + if (get_handles(pc, uuid, handles_reply) < 0) { + pending_connect_free(pc); + return err_not_supported(conn, msg); + } + pending_connects = g_slist_append(pending_connects, pc); + return DBUS_HANDLER_RESULT_HANDLED; + } + + /* Record handle or channel */ + err = pattern2long(pattern, &val); + if (err < 0) { + pending_connect_free(pc); + return err_invalid_args(conn, msg, "invalid pattern"); + } + + /* Record handle: starts at 0x10000 */ + if (strncasecmp("0x", pattern, 2) == 0) { + if (val < 0x10000) { + pending_connect_free(pc); + return err_invalid_args(conn, msg, + "invalid record handle"); + } + + if (get_record(pc, val, record_reply) < 0) { + pending_connect_free(pc); + return err_not_supported(conn, msg); + } + pending_connects = g_slist_append(pending_connects, pc); + return DBUS_HANDLER_RESULT_HANDLED; + } + + pending_connect_free(pc); + /* RFCOMM Channel range: 1 - 30 */ + if (val < 1 || val > 30) + return err_invalid_args(conn, msg, + "invalid RFCOMM channel"); + + str2ba(bda, &dst); + err = rfcomm_bind(&src, &dst, val); + if (err < 0) + return err_failed(conn, msg, strerror(-err)); + + snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); + port_register(conn, err, -1, port_name, NULL, path); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + send_message_and_unref(conn, reply); + + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortCreated" , + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult list_ports(DBusConnection *conn, @@ -688,11 +764,9 @@ static DBusHandlerResult connect_service(DBusConnection *conn, DBusError derr; bdaddr_t src; const char *bda, *pattern; - char *endptr; long val; int dev_id, err; - uint16_t cls; - char tmp[37]; + char uuid[37]; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -721,39 +795,11 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); - memset(tmp, 0, sizeof(tmp)); - - /* Friendly name */ - cls = str2class(pattern); - if (cls) { - uuid_t uuid16, uuid128; - - sdp_uuid16_create(&uuid16, cls); - sdp_uuid16_to_uuid128(&uuid128, &uuid16); - sdp_uuid2strn(&uuid128, tmp, sizeof(tmp)); - - if (get_handles(pc, tmp, handles_reply) < 0) { - pending_connect_free(pc); - return err_not_supported(conn, msg); - } - pending_connects = g_slist_append(pending_connects, pc); - return DBUS_HANDLER_RESULT_HANDLED; - } + memset(uuid, 0, sizeof(uuid)); - /* UUID 128*/ - if (strlen(pattern) == 36) { - strcpy(tmp, pattern); - tmp[4] = '0'; - tmp[5] = '0'; - tmp[6] = '0'; - tmp[7] = '0'; - - if (strcasecmp(BASE_UUID, tmp) != 0) { - pending_connect_free(pc); - return err_invalid_args(conn, msg, "invalid UUID"); - } - - if (get_handles(pc, pattern, handles_reply) < 0) { + /* Friendly name or uuid128 */ + if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) { + if (get_handles(pc, uuid, handles_reply) < 0) { pending_connect_free(pc); return err_not_supported(conn, msg); } @@ -761,12 +807,11 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - errno = 0; - val = strtol(pattern, &endptr, 0); - if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || - (errno != 0 && val == 0) || (pattern == endptr)) { + /* Record handle or channel */ + err = pattern2long(pattern, &val); + if (err < 0) { pending_connect_free(pc); - return err_invalid_args(conn, msg, "Invalid pattern"); + return err_invalid_args(conn, msg, "invalid pattern"); } /* Record handle: starts at 0x10000 */ @@ -810,11 +855,10 @@ static DBusHandlerResult connect_service(DBusConnection *conn, static DBusHandlerResult disconnect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessage *reply; DBusError derr; - struct rfcomm_node *node; - const char *name; + const char *name, *owner; int err; + int id; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -825,34 +869,22 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - node = find_node_by_name(name); - if (!node) - return err_does_not_exist(conn, msg, "Invalid node"); + if (sscanf(name, "/dev/rfcomm%d", &id) != 1) + return err_invalid_args(conn, msg, "invalid RFCOMM node"); - if (strcmp(node->owner, dbus_message_get_sender(msg)) != 0) - return err_not_authorized(conn, msg); + owner = port_get_owner(conn, id); + if (!owner) + return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + if (strcmp(owner, dbus_message_get_sender(msg)) != 0) + return err_not_authorized(conn, msg); - err = rfcomm_release(node->id); - if (err < 0) { - dbus_message_unref(reply); + err = rfcomm_release(id); + if (err < 0) return err_failed(conn, msg, strerror(-err)); - } - - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , - DBUS_TYPE_STRING, &node->name, - DBUS_TYPE_INVALID); - - name_listener_remove(node->conn, node->owner, - (name_cb_t) connect_service_exited, node); - connected_nodes = g_slist_remove(connected_nodes, node); - rfcomm_node_free(node); - return send_message_and_unref(conn, reply); + return send_message_and_unref(conn, + dbus_message_new_method_return(msg)); } static DBusHandlerResult cancel_connect_service(DBusConnection *conn, @@ -888,13 +920,6 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, static void manager_unregister(DBusConnection *conn, void *data) { - if (connected_nodes) { - g_slist_foreach(connected_nodes, - (GFunc) rfcomm_node_free, NULL); - g_slist_free(connected_nodes); - connected_nodes = NULL; - } - if (pending_connects) { g_slist_foreach(pending_connects, (GFunc) pending_connect_free, NULL); @@ -916,6 +941,8 @@ static DBusMethodVTable manager_methods[] = { static DBusSignalVTable manager_signals[] = { { "ServiceConnected", "s" }, { "ServiceDisconnected", "s" }, + { "PortCreated", "s" }, + { "PortRemoved", "s" }, { NULL, NULL } }; diff --git a/serial/manager.h b/serial/manager.h index f09aa294..4004d81e 100644 --- a/serial/manager.h +++ b/serial/manager.h @@ -21,5 +21,11 @@ * */ +#define SERIAL_MANAGER_PATH "/org/bluez/serial" +#define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" + +#define MAX_PATH_LENGTH 32 + int serial_init(DBusConnection *conn); void serial_exit(void); +int rfcomm_release(int16_t id); diff --git a/serial/port.c b/serial/port.c index 80e3c6df..7d3b95c8 100644 --- a/serial/port.c +++ b/serial/port.c @@ -25,4 +25,262 @@ #include #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "dbus.h" +#include "dbus-helper.h" +#include "logging.h" + +#include "error.h" +#include "manager.h" #include "port.h" + +#define SERIAL_PORT_INTERFACE "org.bluez.serial.Port" + +/* Waiting for udev to create the device node */ +#define MAX_OPEN_TRIES 5 +#define OPEN_WAIT 300 /* ms */ + +struct rfcomm_node { + int16_t id; /* RFCOMM device id */ + char *name; /* RFCOMM device name */ + DBusConnection *conn; /* for name listener handling */ + char *owner; /* Bus name */ + GIOChannel *io; /* Connected node IO Channel */ + guint io_id; /* IO Channel ID */ +}; + +struct open_context { + char *dev; + open_notify_t notify; + udata_free_t ufree; + void *udata; + int ntries; +}; + +static GSList *connected_nodes = NULL; + +static DBusHandlerResult port_connect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + /* FIXME: call port_open() */ + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult port_disconnect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult port_get_address(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusMethodVTable port_methods[] = { + { "Connect", port_connect, "", "" }, + { "Disconnect", port_disconnect, "", "" }, + { "GetAddress", port_get_address, "", "s" }, + { NULL, NULL, NULL, NULL }, +}; + +static DBusSignalVTable port_signals[] = { + { NULL, NULL } +}; + +static void rfcomm_node_free(struct rfcomm_node *node) +{ + if (node->name) + g_free(node->name); + if (node->conn) + dbus_connection_unref(node->conn); + if (node->owner) + g_free(node->owner); + if (node->io) { + g_source_remove(node->io_id); + g_io_channel_unref(node->io); + } + g_free(node); +} + +static void connection_owner_exited(const char *name, struct rfcomm_node *node) +{ + char path[MAX_PATH_LENGTH]; + + debug("Connect requestor %s exited. Releasing %s node", + name, node->name); + + snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, node->id); + rfcomm_release(node->id); + dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , + DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_INVALID); + + connected_nodes = g_slist_remove(connected_nodes, node); + dbus_connection_destroy_object_path(node->conn, path); +} + +static gboolean rfcomm_disconnect_cb(GIOChannel *io, + GIOCondition cond, struct rfcomm_node *node) +{ + debug("RFCOMM node %s was disconnected", node->name); + + if (cond & (G_IO_ERR | G_IO_HUP)) + g_io_channel_close(io); + + name_listener_remove(node->conn, node->owner, + (name_cb_t) connection_owner_exited, node); + + dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , + DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_INVALID); + + connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); + + return FALSE; +} + +static void port_unregister(DBusConnection *conn, void *data) +{ + struct rfcomm_node *node = data; + + debug("Unregistered serial port: %s", node->name); + + rfcomm_node_free(node); +} + +int port_register(DBusConnection *conn, int id, int fd, + const char *name, const char *owner, char *ppath) +{ + char path[MAX_PATH_LENGTH]; + struct rfcomm_node *node; + + node = g_new0(struct rfcomm_node, 1); + node->id = id; + node->name = g_strdup(name); + node->conn = dbus_connection_ref(conn); + + snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, id); + + if (!dbus_connection_create_object_path(conn, path, node, + port_unregister)) { + error("D-Bus failed to register %s path", path); + rfcomm_node_free(node); + return -1; + } + + if (!dbus_connection_register_interface(conn, path, + SERIAL_PORT_INTERFACE, + port_methods, + port_signals, NULL)) { + error("D-Bus failed to register %s interface", + SERIAL_PORT_INTERFACE); + dbus_connection_destroy_object_path(conn, path); + return -1; + } + + info("Registered RFCOMM:%s, path:%s owner:%s", name, path, owner); + + if (ppath) + strcpy(ppath, path); + + if (fd < 0) + return 0; + + node->owner = g_strdup(owner); + node->io = g_io_channel_unix_new(fd); + node->io_id = g_io_add_watch(node->io, G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc) rfcomm_disconnect_cb, node); + + connected_nodes = g_slist_append(connected_nodes, node); + + /* Serial port connection listener */ + return name_listener_add(node->conn, owner, + (name_cb_t) connection_owner_exited, node); +} + +const char *port_get_owner(DBusConnection *conn, int16_t id) +{ + struct rfcomm_node *node; + static char path[MAX_PATH_LENGTH]; + + snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, id); + + if (!dbus_connection_get_object_user_data(conn, path, (void *) &node) + || !node) { + errno = ENOENT; + return NULL; + } + + return node->owner; +} + +static gboolean open_continue(struct open_context *oc) +{ + int fd; + + fd = open(oc->dev, O_RDONLY | O_NOCTTY); + if (fd < 0) { + int err = errno; + error("Could not open %s: %s (%d)", + oc->dev, strerror(err), err); + if (++oc->ntries >= MAX_OPEN_TRIES) { + /* Reporting error */ + oc->notify(fd, err, oc->udata); + return FALSE; + } + return TRUE; + } + /* Connection succeeded */ + oc->notify(fd, 0, oc->udata); + return FALSE; +} + +static void open_context_free(void *data) +{ + struct open_context *oc = data; + + if (oc->ufree) + oc->ufree(oc->udata); + g_free(oc->dev); + g_free(oc); +} + +int port_open(const char *dev, open_notify_t notify, void *udata, udata_free_t ufree) +{ + int fd; + + fd = open(dev, O_RDONLY | O_NOCTTY); + if (fd < 0) { + struct open_context *oc; + oc = g_new0(struct open_context, 1); + oc->dev = g_strdup(dev); + oc->notify = notify; + oc->ufree = ufree; + oc->udata = udata; + g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, OPEN_WAIT, + (GSourceFunc) open_continue, oc, open_context_free); + return -EINPROGRESS; + } + + return fd; +} diff --git a/serial/port.h b/serial/port.h index e87dd676..9cab2847 100644 --- a/serial/port.h +++ b/serial/port.h @@ -20,3 +20,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + +typedef void (*open_notify_t) (int fd, int err, void *data); +typedef void (*udata_free_t) (void *data); + +int port_register(DBusConnection *conn, int id, int fd, + const char *name, const char *owner, char *path); + +const char *port_get_owner(DBusConnection *conn, int16_t id); + +int port_open(const char *dev, open_notify_t notify, + void *data, udata_free_t ufree); -- cgit From 3a3580f78fbe363f357abec73bacd89416e4f8f0 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 13:12:05 +0000 Subject: serial: Removed PortCreated signal when calling ConnectService --- serial/manager.c | 33 ++++++++++++++++++++++----------- serial/port.c | 42 +++++++++++++++++++++++++----------------- serial/port.h | 6 ++++-- 3 files changed, 51 insertions(+), 30 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index c33f51cb..538931a9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -189,9 +189,7 @@ static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, uint8_t ch) static void open_notify(int fd, int err, void *data) { char port_name[16]; - char path[MAX_PATH_LENGTH]; const char *pname = port_name; - const char *ppath = path; const char *owner; DBusMessage *reply; struct pending_connect *pc = data; @@ -208,7 +206,7 @@ static void open_notify(int fd, int err, void *data) return; } - /* Check if the caller is still present */ + /* FIXME: it must be a per request listener */ owner = dbus_message_get_sender(pc->msg); if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { error("Connect requestor %s exited", owner); @@ -226,17 +224,12 @@ static void open_notify(int fd, int err, void *data) send_message_and_unref(pc->conn, reply); /* Send the D-Bus signal */ - port_register(pc->conn, pc->id, fd, pname, owner, path); - dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortCreated" , - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceConnected" , DBUS_TYPE_STRING, &pname, DBUS_TYPE_INVALID); + port_add_listener(pc->conn, pc->id, fd, port_name, owner); } static gboolean rfcomm_connect_cb(GIOChannel *chan, @@ -453,7 +446,7 @@ static void record_reply(DBusPendingCall *call, void *data) } snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); - port_register(pc->conn, err, -1, port_name, NULL, path); + port_register(pc->conn, err, port_name, path); reply = dbus_message_new_method_return(pc->msg); dbus_message_append_args(reply, @@ -728,7 +721,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, return err_failed(conn, msg, strerror(-err)); snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); - port_register(conn, err, -1, port_name, NULL, path); + port_register(conn, err, port_name, path); reply = dbus_message_new_method_return(msg); if (!reply) @@ -920,12 +913,30 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, static void manager_unregister(DBusConnection *conn, void *data) { + char **dev; + int i; + if (pending_connects) { g_slist_foreach(pending_connects, (GFunc) pending_connect_free, NULL); g_slist_free(pending_connects); pending_connects = NULL; } + + /* Unregister all paths in serial hierarchy */ + if (!dbus_connection_list_registered(conn, SERIAL_MANAGER_PATH, &dev)) + return; + + for (i = 0; dev[i]; i++) { + char dev_path[MAX_PATH_LENGTH]; + + snprintf(dev_path, sizeof(dev_path), "%s/%s", SERIAL_MANAGER_PATH, + dev[i]); + + dbus_connection_destroy_object_path(conn, dev_path); + } + + dbus_free_string_array(dev); } static DBusMethodVTable manager_methods[] = { diff --git a/serial/port.c b/serial/port.c index 7d3b95c8..5bd217b7 100644 --- a/serial/port.c +++ b/serial/port.c @@ -134,7 +134,6 @@ static void connection_owner_exited(const char *name, struct rfcomm_node *node) DBUS_TYPE_INVALID); connected_nodes = g_slist_remove(connected_nodes, node); - dbus_connection_destroy_object_path(node->conn, path); } static gboolean rfcomm_disconnect_cb(GIOChannel *io, @@ -168,8 +167,29 @@ static void port_unregister(DBusConnection *conn, void *data) rfcomm_node_free(node); } -int port_register(DBusConnection *conn, int id, int fd, - const char *name, const char *owner, char *ppath) +int port_add_listener(DBusConnection *conn, int id, int fd, + const char *name, const char *owner) +{ + struct rfcomm_node *node; + + node = g_new0(struct rfcomm_node, 1); + node->id = id; + node->name = g_strdup(name); + node->conn = dbus_connection_ref(conn); + node->owner = g_strdup(owner); + node->io = g_io_channel_unix_new(fd); + node->io_id = g_io_add_watch(node->io, G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc) rfcomm_disconnect_cb, node); + + connected_nodes = g_slist_append(connected_nodes, node); + + /* Serial port connection listener */ + return name_listener_add(conn, owner, + (name_cb_t) connection_owner_exited, node); + +} + +int port_register(DBusConnection *conn, int id, const char *name, char *ppath) { char path[MAX_PATH_LENGTH]; struct rfcomm_node *node; @@ -198,24 +218,12 @@ int port_register(DBusConnection *conn, int id, int fd, return -1; } - info("Registered RFCOMM:%s, path:%s owner:%s", name, path, owner); + info("Registered RFCOMM:%s, path:%s", name, path); if (ppath) strcpy(ppath, path); - if (fd < 0) - return 0; - - node->owner = g_strdup(owner); - node->io = g_io_channel_unix_new(fd); - node->io_id = g_io_add_watch(node->io, G_IO_ERR | G_IO_NVAL | G_IO_HUP, - (GIOFunc) rfcomm_disconnect_cb, node); - - connected_nodes = g_slist_append(connected_nodes, node); - - /* Serial port connection listener */ - return name_listener_add(node->conn, owner, - (name_cb_t) connection_owner_exited, node); + return 0; } const char *port_get_owner(DBusConnection *conn, int16_t id) diff --git a/serial/port.h b/serial/port.h index 9cab2847..1b17fb66 100644 --- a/serial/port.h +++ b/serial/port.h @@ -24,8 +24,10 @@ typedef void (*open_notify_t) (int fd, int err, void *data); typedef void (*udata_free_t) (void *data); -int port_register(DBusConnection *conn, int id, int fd, - const char *name, const char *owner, char *path); +int port_add_listener(DBusConnection *conn, int id, int fd, + const char *name, const char *owner); + +int port_register(DBusConnection *conn, int id, const char *name, char *ppath); const char *port_get_owner(DBusConnection *conn, int16_t id); -- cgit From 1dc1880aa31a8577272841e085a06ac88df37e48 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 16:16:06 +0000 Subject: serial: added ListPorts --- serial/manager.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 538931a9..cf247a0f 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -741,7 +741,37 @@ static DBusHandlerResult create_port(DBusConnection *conn, static DBusHandlerResult list_ports(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessage *reply; + DBusMessageIter iter, iter_array; + char **dev; + int i; + + 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); + + if (!dbus_connection_list_registered(conn, SERIAL_MANAGER_PATH, &dev)) + goto done; + + for (i = 0; dev[i]; i++) { + char dev_path[MAX_PATH_LENGTH]; + const char *ppath = dev_path; + + snprintf(dev_path, sizeof(dev_path), "%s/%s", + SERIAL_MANAGER_PATH, dev[i]); + dbus_message_iter_append_basic(&iter_array, + DBUS_TYPE_STRING, &ppath); + } + + dbus_free_string_array(dev); +done: + dbus_message_iter_close_container(&iter, &iter_array); + + return send_message_and_unref(conn, reply); } static DBusHandlerResult remove_port(DBusConnection *conn, @@ -865,6 +895,7 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, if (sscanf(name, "/dev/rfcomm%d", &id) != 1) return err_invalid_args(conn, msg, "invalid RFCOMM node"); + /* FIXME: Remove the listener */ owner = port_get_owner(conn, id); if (!owner) return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); @@ -876,6 +907,8 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, if (err < 0) return err_failed(conn, msg, strerror(-err)); + /* FIXME: Remove the node from the list */ + return send_message_and_unref(conn, dbus_message_new_method_return(msg)); } -- cgit From 8bd6348b59d94d40ad4e85e3561cbbf2b7a02cdd Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 16:51:30 +0000 Subject: serial: release the node when the daemon exits --- serial/port.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index 5bd217b7..1ff26714 100644 --- a/serial/port.c +++ b/serial/port.c @@ -112,6 +112,8 @@ static void rfcomm_node_free(struct rfcomm_node *node) dbus_connection_unref(node->conn); if (node->owner) g_free(node->owner); + if (node->id) + rfcomm_release(node->id); if (node->io) { g_source_remove(node->io_id); g_io_channel_unref(node->io); @@ -121,19 +123,16 @@ static void rfcomm_node_free(struct rfcomm_node *node) static void connection_owner_exited(const char *name, struct rfcomm_node *node) { - char path[MAX_PATH_LENGTH]; - debug("Connect requestor %s exited. Releasing %s node", name, node->name); - snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, node->id); - rfcomm_release(node->id); dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , DBUS_TYPE_STRING, &node->name, DBUS_TYPE_INVALID); connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); } static gboolean rfcomm_disconnect_cb(GIOChannel *io, @@ -183,10 +182,9 @@ int port_add_listener(DBusConnection *conn, int id, int fd, connected_nodes = g_slist_append(connected_nodes, node); - /* Serial port connection listener */ + /* Service connection listener */ return name_listener_add(conn, owner, (name_cb_t) connection_owner_exited, node); - } int port_register(DBusConnection *conn, int id, const char *name, char *ppath) @@ -233,6 +231,7 @@ const char *port_get_owner(DBusConnection *conn, int16_t id) snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, id); + /* FIXME: Ports related to services connection doesn't have a path/object */ if (!dbus_connection_get_object_user_data(conn, path, (void *) &node) || !node) { errno = ENOENT; -- cgit From 23a6e61e8ceeb719a88788292390ad062712034d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 18:09:14 +0000 Subject: serial: fixed DisconnectService and added port_remove_listener --- serial/manager.c | 24 ++++++++++++------------ serial/port.c | 32 ++++++++++++++++++++++++++++++++ serial/port.h | 2 ++ 3 files changed, 46 insertions(+), 12 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index cf247a0f..6bce2d69 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -879,9 +879,8 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, DBusMessage *msg, void *data) { DBusError derr; - const char *name, *owner; - int err; - int id; + const char *name; + int err, id; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -895,22 +894,23 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, if (sscanf(name, "/dev/rfcomm%d", &id) != 1) return err_invalid_args(conn, msg, "invalid RFCOMM node"); - /* FIXME: Remove the listener */ - owner = port_get_owner(conn, id); - if (!owner) + err = port_remove_listener(dbus_message_get_sender(msg), name); + if (err < 0) return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); - if (strcmp(owner, dbus_message_get_sender(msg)) != 0) - return err_not_authorized(conn, msg); - err = rfcomm_release(id); if (err < 0) return err_failed(conn, msg, strerror(-err)); - /* FIXME: Remove the node from the list */ - - return send_message_and_unref(conn, + send_message_and_unref(conn, dbus_message_new_method_return(msg)); + + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); + + return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult cancel_connect_service(DBusConnection *conn, diff --git a/serial/port.c b/serial/port.c index 1ff26714..00bddab1 100644 --- a/serial/port.c +++ b/serial/port.c @@ -73,6 +73,19 @@ struct open_context { static GSList *connected_nodes = NULL; +static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *name) +{ + GSList *l; + + for (l = nodes; l != NULL; l = l->next) { + struct rfcomm_node *node = l->data; + if (!strcmp(node->name, name)) + return node; + } + + return NULL; +} + static DBusHandlerResult port_connect(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -187,6 +200,25 @@ int port_add_listener(DBusConnection *conn, int id, int fd, (name_cb_t) connection_owner_exited, node); } +int port_remove_listener(const char *owner, const char *name) +{ + struct rfcomm_node *node; + + node = find_node_by_name(connected_nodes, name); + if (!node) + return -ENOENT; + if (strcmp(node->owner, owner) != 0) + return -EPERM; + + name_listener_remove(node->conn, owner, + (name_cb_t) connection_owner_exited, node); + + connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); + + return 0; +} + int port_register(DBusConnection *conn, int id, const char *name, char *ppath) { char path[MAX_PATH_LENGTH]; diff --git a/serial/port.h b/serial/port.h index 1b17fb66..cb2ecf65 100644 --- a/serial/port.h +++ b/serial/port.h @@ -27,6 +27,8 @@ typedef void (*udata_free_t) (void *data); int port_add_listener(DBusConnection *conn, int id, int fd, const char *name, const char *owner); +int port_remove_listener(const char *owner, const char *name); + int port_register(DBusConnection *conn, int id, const char *name, char *ppath); const char *port_get_owner(DBusConnection *conn, int16_t id); -- cgit From 01cb453b85b7cf26ee9e5f848717d82ce455070a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 19:08:16 +0000 Subject: serial: added RemovePort and bonded node list --- serial/manager.c | 18 +++++++++++++++++- serial/port.c | 27 +++++++++++++++++++++++++-- serial/port.h | 2 ++ 3 files changed, 44 insertions(+), 3 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 6bce2d69..9a6972da 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -777,7 +777,23 @@ done: static DBusHandlerResult remove_port(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusError derr; + const char *path; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (port_unregister(path) < 0) + return err_does_not_exist(conn, msg, "path doesn't exist"); + + return send_message_and_unref(conn, + dbus_message_new_method_return(msg)); } static DBusHandlerResult connect_service(DBusConnection *conn, diff --git a/serial/port.c b/serial/port.c index 00bddab1..76e00e01 100644 --- a/serial/port.c +++ b/serial/port.c @@ -72,6 +72,7 @@ struct open_context { }; static GSList *connected_nodes = NULL; +static GSList *bound_nodes = NULL; static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *name) { @@ -170,12 +171,13 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, return FALSE; } -static void port_unregister(DBusConnection *conn, void *data) +static void port_handler_unregister(DBusConnection *conn, void *data) { struct rfcomm_node *node = data; debug("Unregistered serial port: %s", node->name); + bound_nodes = g_slist_remove(bound_nodes, node); rfcomm_node_free(node); } @@ -232,7 +234,7 @@ int port_register(DBusConnection *conn, int id, const char *name, char *ppath) snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, id); if (!dbus_connection_create_object_path(conn, path, node, - port_unregister)) { + port_handler_unregister)) { error("D-Bus failed to register %s path", path); rfcomm_node_free(node); return -1; @@ -253,6 +255,27 @@ int port_register(DBusConnection *conn, int id, const char *name, char *ppath) if (ppath) strcpy(ppath, path); + bound_nodes = g_slist_append(bound_nodes, node); + + return 0; +} + +int port_unregister(const char *path) +{ + struct rfcomm_node *node; + char name[16]; + int id; + + if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%d", &id) != 1) + return -ENOENT; + + snprintf(name, sizeof(name), "/dev/rfcomm%d", id); + node = find_node_by_name(bound_nodes, name); + if (!node) + return -ENOENT; + + dbus_connection_destroy_object_path(node->conn, path); + return 0; } diff --git a/serial/port.h b/serial/port.h index cb2ecf65..c6a74548 100644 --- a/serial/port.h +++ b/serial/port.h @@ -31,6 +31,8 @@ int port_remove_listener(const char *owner, const char *name); int port_register(DBusConnection *conn, int id, const char *name, char *ppath); +int port_unregister(const char *path); + const char *port_get_owner(DBusConnection *conn, int16_t id); int port_open(const char *dev, open_notify_t notify, -- cgit From 2fbfb83dae49fb9de541869986bc719e06b6cf12 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 19:37:49 +0000 Subject: serial: added port GetAddress --- serial/manager.c | 8 +++++--- serial/port.c | 32 +++++++++++++++++++++++++------- serial/port.h | 7 ++++--- 3 files changed, 34 insertions(+), 13 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 9a6972da..c6c35131 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -193,6 +193,7 @@ static void open_notify(int fd, int err, void *data) const char *owner; DBusMessage *reply; struct pending_connect *pc = data; + bdaddr_t dst; if (err) { /* Max tries exceeded */ @@ -229,7 +230,8 @@ static void open_notify(int fd, int err, void *data) DBUS_TYPE_STRING, &pname, DBUS_TYPE_INVALID); - port_add_listener(pc->conn, pc->id, fd, port_name, owner); + str2ba(pc->bda, &dst); + port_add_listener(pc->conn, pc->id, &dst, fd, port_name, owner); } static gboolean rfcomm_connect_cb(GIOChannel *chan, @@ -446,7 +448,7 @@ static void record_reply(DBusPendingCall *call, void *data) } snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); - port_register(pc->conn, err, port_name, path); + port_register(pc->conn, err, &dst, port_name, path); reply = dbus_message_new_method_return(pc->msg); dbus_message_append_args(reply, @@ -721,7 +723,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, return err_failed(conn, msg, strerror(-err)); snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); - port_register(conn, err, port_name, path); + port_register(conn, err, &dst, port_name, path); reply = dbus_message_new_method_return(msg); if (!reply) diff --git a/serial/port.c b/serial/port.c index 76e00e01..ce339a20 100644 --- a/serial/port.c +++ b/serial/port.c @@ -52,15 +52,16 @@ /* Waiting for udev to create the device node */ #define MAX_OPEN_TRIES 5 -#define OPEN_WAIT 300 /* ms */ +#define OPEN_WAIT 300 /* ms */ struct rfcomm_node { int16_t id; /* RFCOMM device id */ + bdaddr_t dst; /* Destination address */ char *name; /* RFCOMM device name */ - DBusConnection *conn; /* for name listener handling */ + DBusConnection *conn; /* for name listener handling */ char *owner; /* Bus name */ GIOChannel *io; /* Connected node IO Channel */ - guint io_id; /* IO Channel ID */ + guint io_id; /* IO Channel ID */ }; struct open_context { @@ -104,7 +105,21 @@ static DBusHandlerResult port_disconnect(DBusConnection *conn, static DBusHandlerResult port_get_address(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + struct rfcomm_node *node = data; + DBusMessage *reply; + char bda[18]; + const char *pbda = bda; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + ba2str(&node->dst, bda); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &pbda, + DBUS_TYPE_INVALID); + return send_message_and_unref(conn, reply); + } static DBusMethodVTable port_methods[] = { @@ -181,12 +196,13 @@ static void port_handler_unregister(DBusConnection *conn, void *data) rfcomm_node_free(node); } -int port_add_listener(DBusConnection *conn, int id, int fd, - const char *name, const char *owner) +int port_add_listener(DBusConnection *conn, int id, bdaddr_t *dst, + int fd, const char *name, const char *owner) { struct rfcomm_node *node; node = g_new0(struct rfcomm_node, 1); + bacpy(&node->dst, dst); node->id = id; node->name = g_strdup(name); node->conn = dbus_connection_ref(conn); @@ -221,12 +237,14 @@ int port_remove_listener(const char *owner, const char *name) return 0; } -int port_register(DBusConnection *conn, int id, const char *name, char *ppath) +int port_register(DBusConnection *conn, int id, bdaddr_t *dst, + const char *name, char *ppath) { char path[MAX_PATH_LENGTH]; struct rfcomm_node *node; node = g_new0(struct rfcomm_node, 1); + bacpy(&node->dst, dst); node->id = id; node->name = g_strdup(name); node->conn = dbus_connection_ref(conn); diff --git a/serial/port.h b/serial/port.h index c6a74548..2907647b 100644 --- a/serial/port.h +++ b/serial/port.h @@ -24,12 +24,13 @@ typedef void (*open_notify_t) (int fd, int err, void *data); typedef void (*udata_free_t) (void *data); -int port_add_listener(DBusConnection *conn, int id, int fd, - const char *name, const char *owner); +int port_add_listener(DBusConnection *conn, int id, bdaddr_t *dst, + int fd, const char *name, const char *owner); int port_remove_listener(const char *owner, const char *name); -int port_register(DBusConnection *conn, int id, const char *name, char *ppath); +int port_register(DBusConnection *conn, int id, bdaddr_t *dst, + const char *name, char *ppath); int port_unregister(const char *path); -- cgit From b779724baafa371f98d0429b973d432d83a2510d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 17 May 2007 19:47:07 +0000 Subject: serial: enabled RFCOMM_HANGUP_NOW bit when releasing the node --- serial/manager.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index c6c35131..73485382 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -145,14 +145,12 @@ int rfcomm_release(int16_t id) memset(&req, 0, sizeof(req)); req.dev_id = id; -#if 0 /* * We are hitting a kernel bug inside RFCOMM code when * RFCOMM_HANGUP_NOW bit is set on request's flags passed to * ioctl(RFCOMMRELEASEDEV)! */ req.flags = (1 << RFCOMM_HANGUP_NOW); -#endif if (ioctl(rfcomm_ctl, RFCOMMRELEASEDEV, &req) < 0) { int err = errno; -- cgit From 2180c8458b3347f5c83fb483bcc70ec8dd5fe924 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 12:20:15 +0000 Subject: serial: added port persistent storage --- serial/manager.c | 31 ++++++++++++++++++++++--------- serial/storage.c | 40 ++++++++++++++++++++++++++++++++++++++++ serial/storage.h | 3 +++ 3 files changed, 65 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 73485382..86f5255f 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -49,6 +49,7 @@ #include "error.h" #include "port.h" +#include "storage.h" #include "manager.h" #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" @@ -366,7 +367,7 @@ static void record_reply(DBusPendingCall *call, void *data) { struct pending_connect *pc = data; DBusMessage *reply = dbus_pending_call_steal_reply(call); - sdp_record_t *rec; + sdp_record_t *rec = NULL; const uint8_t *rec_bin; sdp_list_t *protos; DBusError derr; @@ -414,7 +415,6 @@ static void record_reply(DBusPendingCall *call, void *data) } if (len != scanned || (sdp_get_access_protos(rec, &protos) < 0)) { - sdp_record_free(rec); err_not_supported(pc->conn, pc->msg); goto fail; } @@ -423,18 +423,17 @@ static void record_reply(DBusPendingCall *call, void *data) sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); - sdp_record_free(rec); - if (ch < 1 || ch > 30) { error("Channel out of range: %d", ch); err_not_supported(pc->conn, pc->msg); goto fail; } - if (dbus_message_has_member(pc->msg, "CreatePort")) { char path[MAX_PATH_LENGTH]; char port_name[16]; const char *ppath = path; + sdp_data_t *d; + char *svcname = NULL; DBusMessage *reply; bdaddr_t dst; @@ -444,8 +443,19 @@ static void record_reply(DBusPendingCall *call, void *data) err_failed(pc->conn, pc->msg, strerror(-err)); goto fail; } - snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); + + d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); + if (d) { + svcname = g_new0(char, d->unitSize); + snprintf(svcname, d->unitSize, "%.*s", + d->unitSize, d->val.str); + } + + port_store(&pc->src, &dst, err, ch, svcname); + if (svcname) + g_free(svcname); + port_register(pc->conn, err, &dst, port_name, path); reply = dbus_message_new_method_return(pc->msg); @@ -469,14 +479,16 @@ static void record_reply(DBusPendingCall *call, void *data) } /* Wait the connect callback */ - dbus_message_unref(reply); - return; + goto done; } fail: - dbus_message_unref(reply); pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); +done: + if (rec) + sdp_record_free(rec); + dbus_message_unref(reply); } static int get_record(struct pending_connect *pc, uint32_t handle, @@ -721,6 +733,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, return err_failed(conn, msg, strerror(-err)); snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); + port_store(&src, &dst, err, val, NULL); port_register(conn, err, &dst, port_name, path); reply = dbus_message_new_method_return(msg); diff --git a/serial/storage.c b/serial/storage.c index bf885407..0b599247 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -25,4 +25,44 @@ #include #endif +#include +#include + +#include + +#include + +#include "logging.h" +#include "textfile.h" + #include "storage.h" + +int port_store(bdaddr_t *src, bdaddr_t *dst, int id, + uint8_t ch, const char *svcname) +{ + char filename[PATH_MAX + 1]; + char src_addr[18], dst_addr[18]; + char key[32]; + char *value; + int size, err; + + if (!svcname) + svcname = "Bluetooth RFCOMM port"; + + ba2str(src, src_addr); + ba2str(dst, dst_addr); + + create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "serial"); + create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + size = strlen(svcname) + 3; + value = g_malloc0(size); + + snprintf(key, 32, "%s#%d", dst_addr, id); + snprintf(value, size, "%d:%s", ch, svcname); + + err = textfile_put(filename, key, value); + g_free(value); + + return err; +} diff --git a/serial/storage.h b/serial/storage.h index e87dd676..82512c90 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -20,3 +20,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ + +int port_store(bdaddr_t *src, bdaddr_t *dst, int id, + uint8_t ch, const char *svcname); -- cgit From 0b9f4f5015bae61751330b02c0e6591643216565 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 13:44:10 +0000 Subject: serial: added function to register/bind stored ports --- serial/manager.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 86f5255f..6b60423d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -25,6 +25,8 @@ #include #endif +#include +#include #include #include #include @@ -46,6 +48,7 @@ #include "dbus.h" #include "dbus-helper.h" #include "logging.h" +#include "textfile.h" #include "error.h" #include "port.h" @@ -163,13 +166,13 @@ int rfcomm_release(int16_t id) return 0; } -static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, uint8_t ch) +static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, int16_t dev_id, uint8_t ch) { struct rfcomm_dev_req req; int id; memset(&req, 0, sizeof(req)); - req.dev_id = -1; + req.dev_id = dev_id; req.flags = 0; bacpy(&req.src, src); bacpy(&req.dst, dst); @@ -438,7 +441,7 @@ static void record_reply(DBusPendingCall *call, void *data) bdaddr_t dst; str2ba(pc->bda, &dst); - err = rfcomm_bind(&pc->src, &dst, ch); + err = rfcomm_bind(&pc->src, &dst, -1, ch); if (err < 0) { err_failed(pc->conn, pc->msg, strerror(-err)); goto fail; @@ -728,7 +731,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, "invalid RFCOMM channel"); str2ba(bda, &dst); - err = rfcomm_bind(&src, &dst, val); + err = rfcomm_bind(&src, &dst, -1, val); if (err < 0) return err_failed(conn, msg, strerror(-err)); @@ -1019,6 +1022,61 @@ static DBusSignalVTable manager_signals[] = { { NULL, NULL } }; +static void parse_port(char *key, char *value, void *data) +{ + char path[MAX_PATH_LENGTH], port_name[16], dst_addr[18]; + const char *ppath = path; + char *src_addr = data; + bdaddr_t dst, src; + int ch, id; + + memset(dst_addr, 0, sizeof(dst_addr)); + if (sscanf(key,"%17s#%d", dst_addr, &id) != 2) + return; + + if (sscanf(value,"%d:", &ch) != 1) + return; + + str2ba(dst_addr, &dst); + str2ba(src_addr, &src); + + if (rfcomm_bind(&src, &dst, id, ch) < 0) + return; + + snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", id); + + port_register(connection, id, &dst, port_name, path); + + dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortCreated" , + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + +} + +static void register_stored_ports(void) +{ + char filename[PATH_MAX + 1]; + struct dirent *de; + DIR *dir; + + snprintf(filename, PATH_MAX, "%s", STORAGEDIR); + + dir = opendir(filename); + if (!dir) + return; + + while ((de = readdir(dir)) != NULL) { + if (!isdigit(de->d_name[0])) + continue; + snprintf(filename, PATH_MAX, "%s/%s/serial", STORAGEDIR, de->d_name); + + textfile_foreach(filename, parse_port, de->d_name); + } + + closedir(dir); +} + int serial_init(DBusConnection *conn) { @@ -1049,6 +1107,8 @@ int serial_init(DBusConnection *conn) info("Registered manager path:%s", SERIAL_MANAGER_PATH); + register_stored_ports(); + return 0; } -- cgit From b418fa69a7733bb5dcd108ee1582908532f2f8a3 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 14:00:30 +0000 Subject: serial: zero is a valid node id, missing node release. --- serial/port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index ce339a20..a433e319 100644 --- a/serial/port.c +++ b/serial/port.c @@ -141,8 +141,7 @@ static void rfcomm_node_free(struct rfcomm_node *node) dbus_connection_unref(node->conn); if (node->owner) g_free(node->owner); - if (node->id) - rfcomm_release(node->id); + rfcomm_release(node->id); if (node->io) { g_source_remove(node->io_id); g_io_channel_unref(node->io); -- cgit From 098b83ac08ad6c1a92a59f6cfbbf61de3ec8b643 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 14:23:01 +0000 Subject: serial API: removed Connect/Disconnect and added GetInfo --- serial/serial-api.txt | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index dc2a2eba..fef95d6a 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -76,16 +76,6 @@ Methods string GetAddress() [experimental] Returns the Bluetooth address of the ending point. - string Connect() [experimental] + string GetInfo() [experimental] - Connects to remote device associated to the port - object. - - Possible errors:org.bluez.serial.Error.ConnectionAttemptFailed - org.bluez.serial.Error.Failed - - void Disconnect() [experimental] - - Disconnects from remote device. - - Possible errors:org.bluez.serial.Error.Failed + Returns the port properties. -- cgit From 09e244622737c52bb7b9a06420f5c1fc5e7bf446 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 14:49:45 +0000 Subject: serial: removed Connected/Disconnected and added GetInfo --- serial/port.c | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index a433e319..44879ecc 100644 --- a/serial/port.c +++ b/serial/port.c @@ -88,25 +88,32 @@ static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *name) return NULL; } -static DBusHandlerResult port_connect(DBusConnection *conn, +static DBusHandlerResult port_get_address(DBusConnection *conn, DBusMessage *msg, void *data) { - /* FIXME: call port_open() */ + struct rfcomm_node *node = data; + DBusMessage *reply; + char bda[18]; + const char *pbda = bda; - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + ba2str(&node->dst, bda); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &pbda, + DBUS_TYPE_INVALID); + return send_message_and_unref(conn, reply); -static DBusHandlerResult port_disconnect(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static DBusHandlerResult port_get_address(DBusConnection *conn, +static DBusHandlerResult port_get_info(DBusConnection *conn, DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; + DBusMessageIter iter, dict; char bda[18]; const char *pbda = bda; @@ -114,18 +121,31 @@ static DBusHandlerResult port_get_address(DBusConnection *conn, 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_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + dbus_message_iter_append_dict_entry(&dict, "name", + DBUS_TYPE_STRING, &node->name); + ba2str(&node->dst, bda); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &pbda, - DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); + dbus_message_iter_append_dict_entry(&dict, "address", + DBUS_TYPE_STRING, &pbda); + dbus_message_iter_append_dict_entry(&dict, "dev_id", + DBUS_TYPE_INT16, &node->id); + + dbus_message_iter_close_container(&iter, &dict); + + return send_message_and_unref(conn, reply); } static DBusMethodVTable port_methods[] = { - { "Connect", port_connect, "", "" }, - { "Disconnect", port_disconnect, "", "" }, { "GetAddress", port_get_address, "", "s" }, + { "GetInfo", port_get_info, "", "{sv}" }, { NULL, NULL, NULL, NULL }, }; -- cgit From d0b45fbc214a16bcc0b13f4e37c37a8bfa96b904 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 14:58:00 +0000 Subject: serial: removed unused function(port_get_owner) --- serial/port.c | 17 ----------------- serial/port.h | 2 -- 2 files changed, 19 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index 44879ecc..3866076a 100644 --- a/serial/port.c +++ b/serial/port.c @@ -316,23 +316,6 @@ int port_unregister(const char *path) return 0; } -const char *port_get_owner(DBusConnection *conn, int16_t id) -{ - struct rfcomm_node *node; - static char path[MAX_PATH_LENGTH]; - - snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, id); - - /* FIXME: Ports related to services connection doesn't have a path/object */ - if (!dbus_connection_get_object_user_data(conn, path, (void *) &node) - || !node) { - errno = ENOENT; - return NULL; - } - - return node->owner; -} - static gboolean open_continue(struct open_context *oc) { int fd; diff --git a/serial/port.h b/serial/port.h index 2907647b..4e719363 100644 --- a/serial/port.h +++ b/serial/port.h @@ -34,7 +34,5 @@ int port_register(DBusConnection *conn, int id, bdaddr_t *dst, int port_unregister(const char *path); -const char *port_get_owner(DBusConnection *conn, int16_t id); - int port_open(const char *dev, open_notify_t notify, void *data, udata_free_t ufree); -- cgit From f7544168a7628f67f98da7a7d6db63678a3d9be3 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 15:16:21 +0000 Subject: serial: keep port_open static since Connect will not be implemented --- serial/manager.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ serial/port.c | 63 ----------------------------------------------------- serial/port.h | 6 ------ 3 files changed, 66 insertions(+), 69 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 6b60423d..bd0362df 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -57,6 +57,10 @@ #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" +/* Waiting for udev to create the device node */ +#define MAX_OPEN_TRIES 5 +#define OPEN_WAIT 300 /* ms */ + struct pending_connect { DBusConnection *conn; DBusMessage *msg; @@ -89,6 +93,16 @@ static struct { { NULL } }; +typedef void (*open_notify_t) (int fd, int err, void *data); +typedef void (*udata_free_t) (void *data); +struct open_context { + char *dev; + open_notify_t notify; + udata_free_t ufree; + void *udata; + int ntries; +}; + static DBusConnection *connection = NULL; static GSList *pending_connects = NULL; static int rfcomm_ctl = -1; @@ -130,6 +144,58 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda, return NULL; } +static gboolean open_continue(struct open_context *oc) +{ + int fd; + + fd = open(oc->dev, O_RDONLY | O_NOCTTY); + if (fd < 0) { + int err = errno; + error("Could not open %s: %s (%d)", + oc->dev, strerror(err), err); + if (++oc->ntries >= MAX_OPEN_TRIES) { + /* Reporting error */ + oc->notify(fd, err, oc->udata); + return FALSE; + } + return TRUE; + } + /* Connection succeeded */ + oc->notify(fd, 0, oc->udata); + return FALSE; +} + +static void open_context_free(void *data) +{ + struct open_context *oc = data; + + if (oc->ufree) + oc->ufree(oc->udata); + g_free(oc->dev); + g_free(oc); +} + +int port_open(const char *dev, open_notify_t notify, + void *udata, udata_free_t ufree) +{ + int fd; + + fd = open(dev, O_RDONLY | O_NOCTTY); + if (fd < 0) { + struct open_context *oc; + oc = g_new0(struct open_context, 1); + oc->dev = g_strdup(dev); + oc->notify = notify; + oc->ufree = ufree; + oc->udata = udata; + g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, OPEN_WAIT, + (GSourceFunc) open_continue, oc, open_context_free); + return -EINPROGRESS; + } + + return fd; +} + static uint16_t str2class(const char *pattern) { int i; diff --git a/serial/port.c b/serial/port.c index 3866076a..3c6980ce 100644 --- a/serial/port.c +++ b/serial/port.c @@ -50,10 +50,6 @@ #define SERIAL_PORT_INTERFACE "org.bluez.serial.Port" -/* Waiting for udev to create the device node */ -#define MAX_OPEN_TRIES 5 -#define OPEN_WAIT 300 /* ms */ - struct rfcomm_node { int16_t id; /* RFCOMM device id */ bdaddr_t dst; /* Destination address */ @@ -64,14 +60,6 @@ struct rfcomm_node { guint io_id; /* IO Channel ID */ }; -struct open_context { - char *dev; - open_notify_t notify; - udata_free_t ufree; - void *udata; - int ntries; -}; - static GSList *connected_nodes = NULL; static GSList *bound_nodes = NULL; @@ -315,54 +303,3 @@ int port_unregister(const char *path) return 0; } - -static gboolean open_continue(struct open_context *oc) -{ - int fd; - - fd = open(oc->dev, O_RDONLY | O_NOCTTY); - if (fd < 0) { - int err = errno; - error("Could not open %s: %s (%d)", - oc->dev, strerror(err), err); - if (++oc->ntries >= MAX_OPEN_TRIES) { - /* Reporting error */ - oc->notify(fd, err, oc->udata); - return FALSE; - } - return TRUE; - } - /* Connection succeeded */ - oc->notify(fd, 0, oc->udata); - return FALSE; -} - -static void open_context_free(void *data) -{ - struct open_context *oc = data; - - if (oc->ufree) - oc->ufree(oc->udata); - g_free(oc->dev); - g_free(oc); -} - -int port_open(const char *dev, open_notify_t notify, void *udata, udata_free_t ufree) -{ - int fd; - - fd = open(dev, O_RDONLY | O_NOCTTY); - if (fd < 0) { - struct open_context *oc; - oc = g_new0(struct open_context, 1); - oc->dev = g_strdup(dev); - oc->notify = notify; - oc->ufree = ufree; - oc->udata = udata; - g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, OPEN_WAIT, - (GSourceFunc) open_continue, oc, open_context_free); - return -EINPROGRESS; - } - - return fd; -} diff --git a/serial/port.h b/serial/port.h index 4e719363..026ba242 100644 --- a/serial/port.h +++ b/serial/port.h @@ -21,9 +21,6 @@ * */ -typedef void (*open_notify_t) (int fd, int err, void *data); -typedef void (*udata_free_t) (void *data); - int port_add_listener(DBusConnection *conn, int id, bdaddr_t *dst, int fd, const char *name, const char *owner); @@ -33,6 +30,3 @@ int port_register(DBusConnection *conn, int id, bdaddr_t *dst, const char *name, char *ppath); int port_unregister(const char *path); - -int port_open(const char *dev, open_notify_t notify, - void *data, udata_free_t ufree); -- cgit From d421185c6b67a294980425dd24d8142956bb7124 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 16:00:34 +0000 Subject: serial: eglib build was broken --- serial/manager.c | 25 +++++++++++++------------ serial/storage.c | 1 + 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index bd0362df..b860659d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -144,6 +144,16 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda, return NULL; } +static void open_context_free(void *data) +{ + struct open_context *oc = data; + + if (oc->ufree) + oc->ufree(oc->udata); + g_free(oc->dev); + g_free(oc); +} + static gboolean open_continue(struct open_context *oc) { int fd; @@ -156,25 +166,17 @@ static gboolean open_continue(struct open_context *oc) if (++oc->ntries >= MAX_OPEN_TRIES) { /* Reporting error */ oc->notify(fd, err, oc->udata); + open_context_free(oc); return FALSE; } return TRUE; } /* Connection succeeded */ oc->notify(fd, 0, oc->udata); + open_context_free(oc); return FALSE; } -static void open_context_free(void *data) -{ - struct open_context *oc = data; - - if (oc->ufree) - oc->ufree(oc->udata); - g_free(oc->dev); - g_free(oc); -} - int port_open(const char *dev, open_notify_t notify, void *udata, udata_free_t ufree) { @@ -188,8 +190,7 @@ int port_open(const char *dev, open_notify_t notify, oc->notify = notify; oc->ufree = ufree; oc->udata = udata; - g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, OPEN_WAIT, - (GSourceFunc) open_continue, oc, open_context_free); + g_timeout_add(OPEN_WAIT, (GSourceFunc) open_continue, oc); return -EINPROGRESS; } diff --git a/serial/storage.c b/serial/storage.c index 0b599247..89d156e5 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -27,6 +27,7 @@ #include #include +#include #include -- cgit From aab0210d3c33296381cff7f988a30f75f058ae8c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 19:19:49 +0000 Subject: serial: remove the entry from the persistent storage when RemovePort is called --- serial/manager.c | 12 +++++++++++- serial/port.c | 14 +++++++++++--- serial/storage.c | 15 +++++++++++++++ serial/storage.h | 1 + 4 files changed, 38 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index b860659d..0cf46a3d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -860,8 +860,10 @@ done: static DBusHandlerResult remove_port(DBusConnection *conn, DBusMessage *msg, void *data) { + struct rfcomm_dev_info di; DBusError derr; const char *path; + int16_t id; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -872,8 +874,16 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } + if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%hd", &id) != 1) + return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); + + di.id = id; + if (ioctl(rfcomm_ctl, RFCOMMGETDEVINFO, &di) < 0) + return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); + port_delete(&di.src, &di.dst, id); + if (port_unregister(path) < 0) - return err_does_not_exist(conn, msg, "path doesn't exist"); + return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); return send_message_and_unref(conn, dbus_message_new_method_return(msg)); diff --git a/serial/port.c b/serial/port.c index 3c6980ce..fac0d5f7 100644 --- a/serial/port.c +++ b/serial/port.c @@ -196,9 +196,17 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, static void port_handler_unregister(DBusConnection *conn, void *data) { struct rfcomm_node *node = data; + char path[MAX_PATH_LENGTH]; + const char *ppath = path; debug("Unregistered serial port: %s", node->name); + snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, node->id); + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortRemoved" , + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + bound_nodes = g_slist_remove(bound_nodes, node); rfcomm_node_free(node); } @@ -289,12 +297,12 @@ int port_unregister(const char *path) { struct rfcomm_node *node; char name[16]; - int id; + int16_t id; - if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%d", &id) != 1) + if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%hd", &id) != 1) return -ENOENT; - snprintf(name, sizeof(name), "/dev/rfcomm%d", id); + snprintf(name, sizeof(name), "/dev/rfcomm%hd", id); node = find_node_by_name(bound_nodes, name); if (!node) return -ENOENT; diff --git a/serial/storage.c b/serial/storage.c index 89d156e5..e6d73827 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -38,6 +38,21 @@ #include "storage.h" +int port_delete(bdaddr_t *src, bdaddr_t *dst, int id) +{ + char filename[PATH_MAX + 1]; + char src_addr[18], dst_addr[18]; + char key[32]; + + ba2str(src, src_addr); + ba2str(dst, dst_addr); + + create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "serial"); + snprintf(key, sizeof(key), "%s#%d", dst_addr, id); + + return textfile_del(filename, key); +} + int port_store(bdaddr_t *src, bdaddr_t *dst, int id, uint8_t ch, const char *svcname) { diff --git a/serial/storage.h b/serial/storage.h index 82512c90..2abdf0ce 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -21,5 +21,6 @@ * */ +int port_delete(bdaddr_t *src, bdaddr_t *dst, int id); int port_store(bdaddr_t *src, bdaddr_t *dst, int id, uint8_t ch, const char *svcname); -- cgit From 68f208cc3b17f8e26318ba411a0974d9489249c9 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 20:39:10 +0000 Subject: serial: code standard - use int16_t for dev_id --- serial/port.c | 9 +++++---- serial/port.h | 4 ++-- serial/storage.c | 8 ++++---- serial/storage.h | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index fac0d5f7..49042785 100644 --- a/serial/port.c +++ b/serial/port.c @@ -201,7 +201,8 @@ static void port_handler_unregister(DBusConnection *conn, void *data) debug("Unregistered serial port: %s", node->name); - snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, node->id); + snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%hd", SERIAL_MANAGER_PATH, node->id); + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortRemoved" , DBUS_TYPE_STRING, &ppath, @@ -211,7 +212,7 @@ static void port_handler_unregister(DBusConnection *conn, void *data) rfcomm_node_free(node); } -int port_add_listener(DBusConnection *conn, int id, bdaddr_t *dst, +int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, int fd, const char *name, const char *owner) { struct rfcomm_node *node; @@ -252,7 +253,7 @@ int port_remove_listener(const char *owner, const char *name) return 0; } -int port_register(DBusConnection *conn, int id, bdaddr_t *dst, +int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, const char *name, char *ppath) { char path[MAX_PATH_LENGTH]; @@ -264,7 +265,7 @@ int port_register(DBusConnection *conn, int id, bdaddr_t *dst, node->name = g_strdup(name); node->conn = dbus_connection_ref(conn); - snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%d", SERIAL_MANAGER_PATH, id); + snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%hd", SERIAL_MANAGER_PATH, id); if (!dbus_connection_create_object_path(conn, path, node, port_handler_unregister)) { diff --git a/serial/port.h b/serial/port.h index 026ba242..27077925 100644 --- a/serial/port.h +++ b/serial/port.h @@ -21,12 +21,12 @@ * */ -int port_add_listener(DBusConnection *conn, int id, bdaddr_t *dst, +int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, int fd, const char *name, const char *owner); int port_remove_listener(const char *owner, const char *name); -int port_register(DBusConnection *conn, int id, bdaddr_t *dst, +int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, const char *name, char *ppath); int port_unregister(const char *path); diff --git a/serial/storage.c b/serial/storage.c index e6d73827..46e63f5d 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -38,7 +38,7 @@ #include "storage.h" -int port_delete(bdaddr_t *src, bdaddr_t *dst, int id) +int port_delete(bdaddr_t *src, bdaddr_t *dst, int16_t id) { char filename[PATH_MAX + 1]; char src_addr[18], dst_addr[18]; @@ -48,12 +48,12 @@ int port_delete(bdaddr_t *src, bdaddr_t *dst, int id) ba2str(dst, dst_addr); create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "serial"); - snprintf(key, sizeof(key), "%s#%d", dst_addr, id); + snprintf(key, sizeof(key), "%s#%hd", dst_addr, id); return textfile_del(filename, key); } -int port_store(bdaddr_t *src, bdaddr_t *dst, int id, +int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, uint8_t ch, const char *svcname) { char filename[PATH_MAX + 1]; @@ -74,7 +74,7 @@ int port_store(bdaddr_t *src, bdaddr_t *dst, int id, size = strlen(svcname) + 3; value = g_malloc0(size); - snprintf(key, 32, "%s#%d", dst_addr, id); + snprintf(key, 32, "%s#%hd", dst_addr, id); snprintf(value, size, "%d:%s", ch, svcname); err = textfile_put(filename, key, value); diff --git a/serial/storage.h b/serial/storage.h index 2abdf0ce..1f92f521 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -21,6 +21,6 @@ * */ -int port_delete(bdaddr_t *src, bdaddr_t *dst, int id); -int port_store(bdaddr_t *src, bdaddr_t *dst, int id, +int port_delete(bdaddr_t *src, bdaddr_t *dst, int16_t id); +int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, uint8_t ch, const char *svcname); -- cgit From e9e6822e7e4cfb2825ba06b74cbcfb200e546fe6 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 20:50:32 +0000 Subject: serial: send PortRemoved signal for RemovePort calls only --- serial/manager.c | 9 ++++++++- serial/port.c | 9 --------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 0cf46a3d..3a64549d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -885,8 +885,15 @@ static DBusHandlerResult remove_port(DBusConnection *conn, if (port_unregister(path) < 0) return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); - return send_message_and_unref(conn, + send_message_and_unref(conn, dbus_message_new_method_return(msg)); + + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortRemoved" , + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + + return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult connect_service(DBusConnection *conn, diff --git a/serial/port.c b/serial/port.c index 49042785..64a72ff9 100644 --- a/serial/port.c +++ b/serial/port.c @@ -196,18 +196,9 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, static void port_handler_unregister(DBusConnection *conn, void *data) { struct rfcomm_node *node = data; - char path[MAX_PATH_LENGTH]; - const char *ppath = path; debug("Unregistered serial port: %s", node->name); - snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%hd", SERIAL_MANAGER_PATH, node->id); - - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortRemoved" , - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - bound_nodes = g_slist_remove(bound_nodes, node); rfcomm_node_free(node); } -- cgit From 3ef17a4e93c33657c59df092f06057b014adfabd Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 20:57:09 +0000 Subject: serial: removed dev_id from GetInfo --- serial/port.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index 64a72ff9..22fc0129 100644 --- a/serial/port.c +++ b/serial/port.c @@ -123,9 +123,6 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, dbus_message_iter_append_dict_entry(&dict, "address", DBUS_TYPE_STRING, &pbda); - dbus_message_iter_append_dict_entry(&dict, "dev_id", - DBUS_TYPE_INT16, &node->id); - dbus_message_iter_close_container(&iter, &dict); return send_message_and_unref(conn, reply); -- cgit From bd94212baf00fdeca29a8899a47f1b280fd54bd7 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 21:27:11 +0000 Subject: serial: minor code cleanup --- serial/manager.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 3a64549d..528954a9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -258,10 +258,9 @@ static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, int16_t dev_id, uint8_t ch) static void open_notify(int fd, int err, void *data) { char port_name[16]; - const char *pname = port_name; - const char *owner; - DBusMessage *reply; + const char *owner, *pname = port_name; struct pending_connect *pc = data; + DBusMessage *reply; bdaddr_t dst; if (err) { @@ -499,8 +498,7 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } if (dbus_message_has_member(pc->msg, "CreatePort")) { - char path[MAX_PATH_LENGTH]; - char port_name[16]; + char path[MAX_PATH_LENGTH], port_name[16]; const char *ppath = path; sdp_data_t *d; char *svcname = NULL; @@ -722,12 +720,10 @@ static DBusHandlerResult create_port(DBusConnection *conn, DBusMessage *reply; DBusError derr; bdaddr_t src, dst; - char path[MAX_PATH_LENGTH]; + char path[MAX_PATH_LENGTH], port_name[16], uuid[37]; const char *bda, *pattern, *ppath = path; long val; int dev_id, err; - char port_name[16]; - char uuid[37]; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -1129,13 +1125,15 @@ static void parse_port(char *key, char *value, void *data) snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", id); - port_register(connection, id, &dst, port_name, path); + if (port_register(connection, id, &dst, port_name, path) < 0) { + rfcomm_release(id); + return; + } dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortCreated" , DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); - } static void register_stored_ports(void) -- cgit From 9b0bd8e682be29a265a57645e96ed810d5473ad7 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 18 May 2007 21:35:09 +0000 Subject: serial: removed PortCreated signal when the daemon starts --- serial/manager.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 528954a9..8eb1b906 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1104,8 +1104,7 @@ static DBusSignalVTable manager_signals[] = { static void parse_port(char *key, char *value, void *data) { - char path[MAX_PATH_LENGTH], port_name[16], dst_addr[18]; - const char *ppath = path; + char port_name[16], dst_addr[18]; char *src_addr = data; bdaddr_t dst, src; int ch, id; @@ -1125,15 +1124,10 @@ static void parse_port(char *key, char *value, void *data) snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", id); - if (port_register(connection, id, &dst, port_name, path) < 0) { + if (port_register(connection, id, &dst, port_name, NULL) < 0) { rfcomm_release(id); return; } - - dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortCreated" , - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); } static void register_stored_ports(void) -- cgit From bb4707cb8caef490cb3ceb329269f8491d01cc6b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Sat, 19 May 2007 02:19:14 +0000 Subject: serial API: updated port path and possible errors --- serial/serial-api.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index fef95d6a..8f319d20 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -14,9 +14,10 @@ Methods string CreatePort(string address, string pattern) [experimental] Creates a serial port object. - Possible errors:org.bluez.serial.Error.AlreadyExists - org.bluez.serial.Error.NotSupported + Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.ConnectionInProgress org.bluez.serial.Error.ConnectionAttemptFailed + org.bluez.serial.Error.NotSupported org.bluez.serial.Error.Failed void RemovePort(string path) [experimental] @@ -24,7 +25,6 @@ Methods string CreatePort(string address, string pattern) [experimental] Removes the serial port object for given path. Possible errors:org.bluez.serial.Error.DoesNotExist - org.bluez.serial.Error.Failed array{string} ListPorts() [experimental] @@ -38,8 +38,9 @@ Methods string CreatePort(string address, string pattern) [experimental] Possible errors:org.bluez.serial.Error.InvalidArguments org.bluez.serial.Error.ConnectionInProgress - org.bluez.serial.Error.NotSupported org.bluez.serial.Error.ConnectionAttemptFailed + org.bluez.serial.Error.NotSupported + org.bluez.serial.Error.Failed void CancelConnectService(string address, string pattern) @@ -54,7 +55,7 @@ Methods string CreatePort(string address, string pattern) [experimental] created via the ConnectService method. Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.Error.NotAuthorized + org.bluez.serial.Error.DoesNotExist org.bluez.serial.Error.Failed Signals void PortCreated(string path) [experimental] @@ -70,7 +71,7 @@ Port hierarchy (experimental) ============================= Interface org.bluez.serial.Port -Object path /org/bluez/serial/port* +Object path /org/bluez/serial/rfcomm* Methods string GetAddress() [experimental] -- cgit From dc2fadfce2466c28e87f701d995fda91ffda1e67 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Sat, 19 May 2007 02:19:57 +0000 Subject: serial: removed unused error(NotAuthorized) --- serial/error.c | 9 --------- serial/error.h | 2 -- 2 files changed, 11 deletions(-) (limited to 'serial') diff --git a/serial/error.c b/serial/error.c index c3ec9144..22be2b1e 100644 --- a/serial/error.c +++ b/serial/error.c @@ -88,15 +88,6 @@ DBusHandlerResult err_invalid_args(DBusConnection *conn, SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); } -DBusHandlerResult err_not_authorized(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".NotAuthorized", - "Owner not allowed")); -} - DBusHandlerResult err_not_supported(DBusConnection *conn, DBusMessage *msg) { diff --git a/serial/error.h b/serial/error.h index d43d87ca..14301e95 100644 --- a/serial/error.h +++ b/serial/error.h @@ -37,7 +37,5 @@ DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, const char *str); DBusHandlerResult err_invalid_args(DBusConnection *conn, DBusMessage *msg, const char *str); -DBusHandlerResult err_not_authorized(DBusConnection *conn, - DBusMessage *msg); DBusHandlerResult err_not_supported(DBusConnection *conn, DBusMessage *msg); -- cgit From dcc91e3ea4d987dc45b1d6451a8278d857c58d1d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 24 May 2007 09:06:21 +0000 Subject: add name listener support --- serial/manager.c | 103 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 34 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 8eb1b906..8d7af3f9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -64,11 +64,13 @@ struct pending_connect { DBusConnection *conn; DBusMessage *msg; + DBusPendingCall *pcall; /* Pending get handles/records */ char *bda; /* Destination address */ char *adapter_path; /* Adapter D-Bus path */ char *pattern; /* Connection request pattern */ bdaddr_t src; uint8_t channel; + guint io_id; /* GIOChannel watch id */ int id; /* RFCOMM device id */ int ntries; /* Open attempts */ int canceled; /* Operation canceled */ @@ -119,15 +121,11 @@ static void pending_connect_free(struct pending_connect *pc) g_free(pc->pattern); if (pc->adapter_path) g_free(pc->adapter_path); + if (pc->pcall) + dbus_pending_call_unref(pc->pcall); g_free(pc); } -static void pending_connect_remove(struct pending_connect *pc) -{ - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); -} - static struct pending_connect *find_pending_connect_by_pattern(const char *bda, const char *pattern) { @@ -258,7 +256,7 @@ static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, int16_t dev_id, uint8_t ch) static void open_notify(int fd, int err, void *data) { char port_name[16]; - const char *owner, *pname = port_name; + const char *pname = port_name; struct pending_connect *pc = data; DBusMessage *reply; bdaddr_t dst; @@ -275,14 +273,6 @@ static void open_notify(int fd, int err, void *data) return; } - /* FIXME: it must be a per request listener */ - owner = dbus_message_get_sender(pc->msg); - if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) { - error("Connect requestor %s exited", owner); - rfcomm_release(pc->id); - return; - } - snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", pc->id); /* Reply to the requestor */ @@ -299,7 +289,49 @@ static void open_notify(int fd, int err, void *data) DBUS_TYPE_INVALID); str2ba(pc->bda, &dst); - port_add_listener(pc->conn, pc->id, &dst, fd, port_name, owner); + + /* Add the RFCOMM connection listener */ + port_add_listener(pc->conn, pc->id, &dst, fd, + port_name, dbus_message_get_sender(pc->msg)); +} + +static void transaction_owner_exited(const char *name, void *data) +{ + GSList *l, *tmp = NULL; + debug("transaction owner %s exited", name); + + /* Clean all pending calls that belongs to this owner */ + for (l = pending_connects; l != NULL; l = l->next) { + struct pending_connect *pc = l->data; + if (strcmp(name, dbus_message_get_sender(pc->msg)) != 0) { + tmp = g_slist_append(tmp, pc); + continue; + } + + if (pc->pcall) + dbus_pending_call_cancel(pc->pcall); + + if (pc->io_id > 0) + g_source_remove(pc->io_id); + + if (pc->id >= 0) + rfcomm_release(pc->id); + + pending_connect_free(pc); + } + + g_slist_free(pending_connects); + pending_connects = tmp; +} + +static void pending_connect_remove(struct pending_connect *pc) +{ + /* Remove the connection request owner */ + name_listener_remove(pc->conn, dbus_message_get_sender(pc->msg), + (name_cb_t) transaction_owner_exited, NULL); + + pending_connects = g_slist_remove(pending_connects, pc); + pending_connect_free(pc); } static gboolean rfcomm_connect_cb(GIOChannel *chan, @@ -377,8 +409,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, open_notify(fd, 0, pc); fail: - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); + pending_connect_remove(pc); if (close_chan) g_io_channel_close(chan); @@ -421,8 +452,8 @@ static int rfcomm_connect(struct pending_connect *pc) } debug("Connect in progress"); - g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_NVAL | G_IO_HUP, - (GIOFunc) rfcomm_connect_cb, pc); + pc->io_id = g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc) rfcomm_connect_cb, pc); } else { debug("Connect succeeded with first try"); (void) rfcomm_connect_cb(io, G_IO_OUT, pc); @@ -551,8 +582,7 @@ static void record_reply(DBusPendingCall *call, void *data) } fail: - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); + pending_connect_remove(pc); done: if (rec) sdp_record_free(rec); @@ -563,7 +593,6 @@ static int get_record(struct pending_connect *pc, uint32_t handle, DBusPendingCallNotifyFunction cb) { DBusMessage *msg; - DBusPendingCall *pending; msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, "org.bluez.Adapter", "GetRemoteServiceRecord"); @@ -575,14 +604,13 @@ static int get_record(struct pending_connect *pc, uint32_t handle, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(pc->conn, msg, &pending, -1) == FALSE) { + if (dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1) == FALSE) { error("Can't send D-Bus message."); return -1; } - dbus_pending_call_set_notify(pending, cb, pc, NULL); + dbus_pending_call_set_notify(pc->pcall, cb, pc, NULL); dbus_message_unref(msg); - dbus_pending_call_unref(pending); return 0; } @@ -637,15 +665,13 @@ static void handles_reply(DBusPendingCall *call, void *data) return; fail: dbus_message_unref(reply); - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); + pending_connect_remove(pc); } static int get_handles(struct pending_connect *pc, const char *uuid, DBusPendingCallNotifyFunction cb) { DBusMessage *msg; - DBusPendingCall *pending; msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, "org.bluez.Adapter", "GetRemoteServiceHandles"); @@ -657,14 +683,13 @@ static int get_handles(struct pending_connect *pc, const char *uuid, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(pc->conn, msg, &pending, -1) == FALSE) { + if (dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1) == FALSE) { error("Can't send D-Bus message."); return -1; } - dbus_pending_call_set_notify(pending, cb, pc, NULL); + dbus_pending_call_set_notify(pc->pcall, cb, pc, NULL); dbus_message_unref(msg); - dbus_pending_call_unref(pending); return 0; } @@ -748,6 +773,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, pc->conn = dbus_connection_ref(conn); pc->msg = dbus_message_ref(msg); pc->bda = g_strdup(bda); + pc->id = -1; pc->pattern = g_strdup(pattern); pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); @@ -761,6 +787,8 @@ static DBusHandlerResult create_port(DBusConnection *conn, return err_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); + name_listener_add(conn, dbus_message_get_sender(msg), + (name_cb_t) transaction_owner_exited, NULL); return DBUS_HANDLER_RESULT_HANDLED; } @@ -784,6 +812,8 @@ static DBusHandlerResult create_port(DBusConnection *conn, return err_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); + name_listener_add(conn, dbus_message_get_sender(msg), + (name_cb_t) transaction_owner_exited, NULL); return DBUS_HANDLER_RESULT_HANDLED; } @@ -926,6 +956,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pc->conn = dbus_connection_ref(conn); pc->msg = dbus_message_ref(msg); pc->bda = g_strdup(bda); + pc->id = -1; pc->pattern = g_strdup(pattern); pc->adapter_path = g_malloc0(16); snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); @@ -939,7 +970,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return err_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); - return DBUS_HANDLER_RESULT_HANDLED; + goto done; } /* Record handle or channel */ @@ -962,7 +993,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return err_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); - return DBUS_HANDLER_RESULT_HANDLED; + goto done; } /* RFCOMM Channel range: 1 - 30 */ @@ -984,6 +1015,10 @@ static DBusHandlerResult connect_service(DBusConnection *conn, pending_connect_free(pc); return err_connection_failed(conn, msg, strerr); } +done: + name_listener_add(conn, dbus_message_get_sender(msg), + (name_cb_t) transaction_owner_exited, NULL); + return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From 7e0db39d85c0540d683231c13b61b8bdc8ca6d4d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 24 May 2007 13:17:00 +0000 Subject: serial: close the file descriptor before release the RFCOMM device --- serial/port.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index 22fc0129..c220110c 100644 --- a/serial/port.c +++ b/serial/port.c @@ -146,11 +146,12 @@ static void rfcomm_node_free(struct rfcomm_node *node) dbus_connection_unref(node->conn); if (node->owner) g_free(node->owner); - rfcomm_release(node->id); if (node->io) { g_source_remove(node->io_id); + g_io_channel_close(node->io); g_io_channel_unref(node->io); } + rfcomm_release(node->id); g_free(node); } @@ -173,9 +174,6 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, { debug("RFCOMM node %s was disconnected", node->name); - if (cond & (G_IO_ERR | G_IO_HUP)) - g_io_channel_close(io); - name_listener_remove(node->conn, node->owner, (name_cb_t) connection_owner_exited, node); -- cgit From 683ab9d3287f80091036b0c73a56457ca022f47e Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 24 May 2007 17:08:19 +0000 Subject: serial: release node called twice --- serial/manager.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 8d7af3f9..c57e5eb1 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1045,10 +1045,6 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, if (err < 0) return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); - err = rfcomm_release(id); - if (err < 0) - return err_failed(conn, msg, strerror(-err)); - send_message_and_unref(conn, dbus_message_new_method_return(msg)); -- cgit From d69525e2deed68c332c2dcfaf21c23baeab73755 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 24 May 2007 17:09:37 +0000 Subject: serial: Failed error is not returned by DisconnectService --- serial/serial-api.txt | 1 - 1 file changed, 1 deletion(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 8f319d20..6df4a318 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -56,7 +56,6 @@ Methods string CreatePort(string address, string pattern) [experimental] Possible errors:org.bluez.serial.Error.InvalidArguments org.bluez.serial.Error.DoesNotExist - org.bluez.serial.Error.Failed Signals void PortCreated(string path) [experimental] -- cgit From ac3d15d1a358618400b6cdc15d5abf354e374971 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 24 May 2007 20:21:16 +0000 Subject: serial: release the node when device open fails --- serial/manager.c | 1 + 1 file changed, 1 insertion(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index c57e5eb1..cafe8590 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -263,6 +263,7 @@ static void open_notify(int fd, int err, void *data) if (err) { /* Max tries exceeded */ + rfcomm_release(pc->id); err_connection_failed(pc->conn, pc->msg, strerror(err)); return; } -- cgit From c7449f91c86f368d32f4c40d1f10e12448164029 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 24 May 2007 21:38:06 +0000 Subject: serial: timeout leak removed, open_context struct removed --- serial/manager.c | 282 ++++++++++++++++++++++++------------------------------- 1 file changed, 122 insertions(+), 160 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index cafe8590..1f7d7373 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -71,6 +71,8 @@ struct pending_connect { bdaddr_t src; uint8_t channel; guint io_id; /* GIOChannel watch id */ + GIOChannel *io; /* GIOChannel for RFCOMM connect */ + char *dev; /* tty device name */ int id; /* RFCOMM device id */ int ntries; /* Open attempts */ int canceled; /* Operation canceled */ @@ -95,16 +97,6 @@ static struct { { NULL } }; -typedef void (*open_notify_t) (int fd, int err, void *data); -typedef void (*udata_free_t) (void *data); -struct open_context { - char *dev; - open_notify_t notify; - udata_free_t ufree; - void *udata; - int ntries; -}; - static DBusConnection *connection = NULL; static GSList *pending_connects = NULL; static int rfcomm_ctl = -1; @@ -123,6 +115,14 @@ static void pending_connect_free(struct pending_connect *pc) g_free(pc->adapter_path); if (pc->pcall) dbus_pending_call_unref(pc->pcall); + if (pc->dev) + g_free(pc->dev); + if (pc->io_id > 0) + g_source_remove(pc->io_id); + if (pc->io) { + g_io_channel_close(pc->io); + g_io_channel_unref(pc->io); + } g_free(pc); } @@ -142,53 +142,113 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda, return NULL; } -static void open_context_free(void *data) +static void transaction_owner_exited(const char *name, void *data) { - struct open_context *oc = data; + GSList *l, *tmp = NULL; + debug("transaction owner %s exited", name); + + /* Clean all pending calls that belongs to this owner */ + for (l = pending_connects; l != NULL; l = l->next) { + struct pending_connect *pc = l->data; + if (strcmp(name, dbus_message_get_sender(pc->msg)) != 0) { + tmp = g_slist_append(tmp, pc); + continue; + } + + if (pc->pcall) + dbus_pending_call_cancel(pc->pcall); + + if (pc->id >= 0) + rfcomm_release(pc->id); + + pending_connect_free(pc); + } + + g_slist_free(pending_connects); + pending_connects = tmp; +} + +static void pending_connect_remove(struct pending_connect *pc) +{ + /* Remove the connection request owner */ + name_listener_remove(pc->conn, dbus_message_get_sender(pc->msg), + (name_cb_t) transaction_owner_exited, NULL); + + pending_connects = g_slist_remove(pending_connects, pc); + pending_connect_free(pc); +} + +static void open_notify(int fd, int err, struct pending_connect *pc) +{ + DBusMessage *reply; + bdaddr_t dst; - if (oc->ufree) - oc->ufree(oc->udata); - g_free(oc->dev); - g_free(oc); + if (err) { + /* Max tries exceeded */ + rfcomm_release(pc->id); + err_connection_failed(pc->conn, pc->msg, strerror(err)); + return; + } + + if (pc->canceled) { + rfcomm_release(pc->id); + err_connection_canceled(pc->conn, pc->msg); + return; + } + + /* Reply to the requestor */ + reply = dbus_message_new_method_return(pc->msg); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &pc->dev, + DBUS_TYPE_INVALID); + send_message_and_unref(pc->conn, reply); + + /* Send the D-Bus signal */ + dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ServiceConnected" , + DBUS_TYPE_STRING, &pc->dev, + DBUS_TYPE_INVALID); + + str2ba(pc->bda, &dst); + + /* Add the RFCOMM connection listener */ + port_add_listener(pc->conn, pc->id, &dst, fd, + pc->dev, dbus_message_get_sender(pc->msg)); } -static gboolean open_continue(struct open_context *oc) +static gboolean open_continue(struct pending_connect *pc) { int fd; - fd = open(oc->dev, O_RDONLY | O_NOCTTY); + if (!g_slist_find(pending_connects, pc)) + return FALSE; /* Owner exited */ + + fd = open(pc->dev, O_RDONLY | O_NOCTTY); if (fd < 0) { int err = errno; error("Could not open %s: %s (%d)", - oc->dev, strerror(err), err); - if (++oc->ntries >= MAX_OPEN_TRIES) { + pc->dev, strerror(err), err); + if (++pc->ntries >= MAX_OPEN_TRIES) { /* Reporting error */ - oc->notify(fd, err, oc->udata); - open_context_free(oc); + open_notify(fd, err, pc); + pending_connect_remove(pc); return FALSE; } return TRUE; } /* Connection succeeded */ - oc->notify(fd, 0, oc->udata); - open_context_free(oc); + open_notify(fd, 0, pc); + pending_connect_remove(pc); return FALSE; } -int port_open(const char *dev, open_notify_t notify, - void *udata, udata_free_t ufree) +int port_open(struct pending_connect *pc) { int fd; - fd = open(dev, O_RDONLY | O_NOCTTY); + fd = open(pc->dev, O_RDONLY | O_NOCTTY); if (fd < 0) { - struct open_context *oc; - oc = g_new0(struct open_context, 1); - oc->dev = g_strdup(dev); - oc->notify = notify; - oc->ufree = ufree; - oc->udata = udata; - g_timeout_add(OPEN_WAIT, (GSourceFunc) open_continue, oc); + g_timeout_add(OPEN_WAIT, (GSourceFunc) open_continue, pc); return -EINPROGRESS; } @@ -253,131 +313,40 @@ static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, int16_t dev_id, uint8_t ch) return id; } -static void open_notify(int fd, int err, void *data) -{ - char port_name[16]; - const char *pname = port_name; - struct pending_connect *pc = data; - DBusMessage *reply; - bdaddr_t dst; - - if (err) { - /* Max tries exceeded */ - rfcomm_release(pc->id); - err_connection_failed(pc->conn, pc->msg, strerror(err)); - return; - } - - if (pc->canceled) { - rfcomm_release(pc->id); - err_connection_canceled(pc->conn, pc->msg); - return; - } - - snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", pc->id); - - /* Reply to the requestor */ - reply = dbus_message_new_method_return(pc->msg); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &pname, - DBUS_TYPE_INVALID); - send_message_and_unref(pc->conn, reply); - - /* Send the D-Bus signal */ - dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ServiceConnected" , - DBUS_TYPE_STRING, &pname, - DBUS_TYPE_INVALID); - - str2ba(pc->bda, &dst); - - /* Add the RFCOMM connection listener */ - port_add_listener(pc->conn, pc->id, &dst, fd, - port_name, dbus_message_get_sender(pc->msg)); -} - -static void transaction_owner_exited(const char *name, void *data) -{ - GSList *l, *tmp = NULL; - debug("transaction owner %s exited", name); - - /* Clean all pending calls that belongs to this owner */ - for (l = pending_connects; l != NULL; l = l->next) { - struct pending_connect *pc = l->data; - if (strcmp(name, dbus_message_get_sender(pc->msg)) != 0) { - tmp = g_slist_append(tmp, pc); - continue; - } - - if (pc->pcall) - dbus_pending_call_cancel(pc->pcall); - - if (pc->io_id > 0) - g_source_remove(pc->io_id); - - if (pc->id >= 0) - rfcomm_release(pc->id); - - pending_connect_free(pc); - } - - g_slist_free(pending_connects); - pending_connects = tmp; -} - -static void pending_connect_remove(struct pending_connect *pc) -{ - /* Remove the connection request owner */ - name_listener_remove(pc->conn, dbus_message_get_sender(pc->msg), - (name_cb_t) transaction_owner_exited, NULL); - - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); -} - static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond, struct pending_connect *pc) { - char port_name[16]; struct rfcomm_dev_req req; - int sk, err, fd, close_chan = 1; + int sk, err, fd, ret; + socklen_t len; if (pc->canceled) { err_connection_canceled(pc->conn, pc->msg); goto fail; } - sk = g_io_channel_unix_get_fd(chan); - if (cond & G_IO_NVAL) { - close_chan = 0; - err_connection_failed(pc->conn, pc->msg, - "File descriptor is not open"); + /* Avoid close invalid file descriptor */ + g_io_channel_unref(pc->io); + pc->io = NULL; + err_connection_canceled(pc->conn, pc->msg); goto fail; } - if (cond & (G_IO_ERR | G_IO_HUP)) { - socklen_t len; - int ret; - - len = sizeof(ret); - if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { - err = errno; - error("getsockopt(SO_ERROR): %s (%d)", - strerror(err), err); - err_connection_failed(pc->conn, - pc->msg, strerror(err)); - goto fail; - } - - if (ret != 0) { - error("connect(): %s (%d)", strerror(ret), ret); - err_connection_failed(pc->conn, pc->msg, strerror(ret)); - goto fail; - } + sk = g_io_channel_unix_get_fd(chan); + len = sizeof(ret); + if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { + err = errno; + error("getsockopt(SO_ERROR): %s (%d)", + strerror(err), err); + err_connection_failed(pc->conn, + pc->msg, strerror(err)); + goto fail; + } - error("Hangup on rfcomm socket"); - err_connection_canceled(pc->conn, pc->msg); + if (ret != 0) { + error("connect(): %s (%d)", strerror(ret), ret); + err_connection_failed(pc->conn, pc->msg, strerror(ret)); goto fail; } @@ -397,30 +366,24 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, err_connection_failed(pc->conn, pc->msg, strerror(err)); goto fail; } + pc->dev = g_new0(char, 16); + snprintf(pc->dev, 16, "/dev/rfcomm%d", pc->id); - snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", pc->id); /* Addressing connect port */ - fd = port_open(port_name, open_notify, pc, - (udata_free_t) pending_connect_remove); - if (fd < 0) { - g_io_channel_close(chan); + fd = port_open(pc); + if (fd < 0) /* Open in progress: Wait the callback */ return FALSE; - } open_notify(fd, 0, pc); fail: pending_connect_remove(pc); - if (close_chan) - g_io_channel_close(chan); - return FALSE; } static int rfcomm_connect(struct pending_connect *pc) { struct sockaddr_rc addr; - GIOChannel *io; int sk, err = 0; sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); @@ -438,8 +401,7 @@ static int rfcomm_connect(struct pending_connect *pc) if (set_nonblocking(sk) < 0) return -errno; - io = g_io_channel_unix_new(sk); - + pc->io = g_io_channel_unix_new(sk); addr.rc_family = AF_BLUETOOTH; str2ba(pc->bda, &addr.rc_bdaddr); addr.rc_channel = pc->channel; @@ -453,14 +415,14 @@ static int rfcomm_connect(struct pending_connect *pc) } debug("Connect in progress"); - pc->io_id = g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_NVAL | G_IO_HUP, - (GIOFunc) rfcomm_connect_cb, pc); + pc->io_id = g_io_add_watch(pc->io, + G_IO_OUT | G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc) rfcomm_connect_cb, pc); } else { debug("Connect succeeded with first try"); - (void) rfcomm_connect_cb(io, G_IO_OUT, pc); + (void) rfcomm_connect_cb(pc->io, G_IO_OUT, pc); } fail: - g_io_channel_unref(io); return -err; } -- cgit From 99fe5d4bd60337b53beb4da797ea77f2717ce014 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 24 May 2007 21:51:22 +0000 Subject: serial API: missing ConnectionCanceled error --- serial/serial-api.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 6df4a318..84512973 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -15,6 +15,7 @@ Methods string CreatePort(string address, string pattern) [experimental] Creates a serial port object. Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.ConnectionCanceled org.bluez.serial.Error.ConnectionInProgress org.bluez.serial.Error.ConnectionAttemptFailed org.bluez.serial.Error.NotSupported @@ -37,6 +38,7 @@ Methods string CreatePort(string address, string pattern) [experimental] device for it. The RFCOMM TTY device is returned. Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.ConnectionCanceled org.bluez.serial.Error.ConnectionInProgress org.bluez.serial.Error.ConnectionAttemptFailed org.bluez.serial.Error.NotSupported -- cgit From a74aceecae93b2b4274318ec3efe6ff2100c55af Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 25 May 2007 20:18:11 +0000 Subject: serial: missing close the RFCOMM socket --- serial/manager.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 1f7d7373..e847f550 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -384,7 +384,7 @@ fail: static int rfcomm_connect(struct pending_connect *pc) { struct sockaddr_rc addr; - int sk, err = 0; + int sk, err; sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sk < 0) @@ -396,10 +396,10 @@ static int rfcomm_connect(struct pending_connect *pc) addr.rc_channel = 0; if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) - return -errno; + goto fail; if (set_nonblocking(sk) < 0) - return -errno; + goto fail; pc->io = g_io_channel_unix_new(sk); addr.rc_family = AF_BLUETOOTH; @@ -409,8 +409,8 @@ static int rfcomm_connect(struct pending_connect *pc) if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { /* BlueZ returns EAGAIN eventhough it should return EINPROGRESS */ if (!(errno == EAGAIN || errno == EINPROGRESS)) { - err = errno; - error("connect() failed: %s (%d)", strerror(err), err); + error("connect() failed: %s (%d)", + strerror(errno), errno); goto fail; } @@ -422,7 +422,13 @@ static int rfcomm_connect(struct pending_connect *pc) debug("Connect succeeded with first try"); (void) rfcomm_connect_cb(pc->io, G_IO_OUT, pc); } + + return 0; fail: + err = errno; + close(sk); + errno = err; + return -err; } -- cgit From d195a1ef061b12e04ae23cf644ea22d29178f590 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 18:10:26 +0000 Subject: serial-api: added serial port proxy --- serial/serial-api.txt | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 84512973..b02786e7 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -10,7 +10,21 @@ Manager hierarchy Interface org.bluez.serial.Manager Object path /org/bluez/serial -Methods string CreatePort(string address, string pattern) [experimental] +Methods string CreateProxy(string uuid, string tty) + + Creates a serial port proxy object. + + Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.NotAvailable + org.bluez.serial.Failed + + void RemoveProxy(string path) [experimental] + + Removes the serial port proxy object for given path. + + Possible errors:org.bluez.serial.Error.DoesNotExist + + string CreatePort(string address, string pattern) [experimental] Creates a serial port object. @@ -31,6 +45,10 @@ Methods string CreatePort(string address, string pattern) [experimental] Returns an array of available serial port paths. + array{string} ListProxies() [experimental] + + Returns an array of available serial port proxy paths. + string ConnectService(string address, string pattern) Connects to a specific RFCOMM based service on a @@ -63,6 +81,10 @@ Signals void PortCreated(string path) [experimental] void PortRemoved(string path) [experimental] + void ProxyCreated(string path) [experimental] + + void ProxyRemoved(string path) [experimental] + void ServiceConnected(string device) void ServiceDisconnected(string device) @@ -81,3 +103,20 @@ Methods string GetAddress() [experimental] string GetInfo() [experimental] Returns the port properties. + +Proxy hierarchy (experimental) +============================= +Interface org.bluez.serial.Proxy +Object path /org/bluez/serial/rfcomm* + +Methods: string Enable() [experimental] + + Register the serial proxy service record and start + listenning on the specified adapter/channel. + + string Disable() [experimental] + + Unregister the service record and stop listenning. + + String GetInfo() [experimental] + Returns the proxy properties -- cgit From 152ee1375cd30d6efa61b52b46682e9d187155ed Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 18:34:52 +0000 Subject: serial: Added CreateProxy, ListProxies and RemoveProxy skeleton --- serial/manager.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index e847f550..15d23a30 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -891,6 +891,24 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } +static DBusHandlerResult create_proxy(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult list_proxies(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult remove_proxy(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1088,6 +1106,9 @@ static DBusMethodVTable manager_methods[] = { { "CreatePort", create_port, "ss", "s" }, { "ListPorts", list_ports, "", "as" }, { "RemovePort", remove_port, "s", "" }, + { "CreateProxy", create_proxy, "ss", "s" }, + { "ListProxies", list_proxies, "", "as" }, + { "RemoveProxy", remove_proxy, "s", "" }, { "ConnectService", connect_service, "ss", "s" }, { "DisconnectService", disconnect_service, "s", "" }, { "CancelConnectService", cancel_connect_service, "ss", "" }, @@ -1095,10 +1116,12 @@ static DBusMethodVTable manager_methods[] = { }; static DBusSignalVTable manager_signals[] = { - { "ServiceConnected", "s" }, - { "ServiceDisconnected", "s" }, { "PortCreated", "s" }, { "PortRemoved", "s" }, + { "ProxyCreated", "s" }, + { "ProxyRemoved", "s" }, + { "ServiceConnected", "s" }, + { "ServiceDisconnected", "s" }, { NULL, NULL } }; -- cgit From 3d9624ac1513b724eea443c01e655e24636c5153 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 18:50:13 +0000 Subject: serial: added new error - AlreadyExists --- serial/error.c | 8 ++++++++ serial/error.h | 2 ++ 2 files changed, 10 insertions(+) (limited to 'serial') diff --git a/serial/error.c b/serial/error.c index 22be2b1e..ba894992 100644 --- a/serial/error.c +++ b/serial/error.c @@ -64,6 +64,14 @@ DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, "Connection creation not in progress")); } +DBusHandlerResult err_already_exists(DBusConnection *conn, + DBusMessage *msg, const char *str) +{ + return send_message_and_unref(conn, + dbus_message_new_error(msg, + SERIAL_ERROR_INTERFACE ".AlreadyExists", str)); +} + DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg, const char *str) { diff --git a/serial/error.h b/serial/error.h index 14301e95..f12602fb 100644 --- a/serial/error.h +++ b/serial/error.h @@ -31,6 +31,8 @@ DBusHandlerResult err_connection_in_progress(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, DBusMessage *msg); +DBusHandlerResult err_already_exists(DBusConnection *conn, + DBusMessage *msg, const char *str); DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg, const char *str); DBusHandlerResult err_failed(DBusConnection *conn, -- cgit From 89d79b500b8559e11af44fe11dc01432eafa9541 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 19:01:52 +0000 Subject: serial: CreateProxy - added arguments validation and CreateProxy signal emission --- serial/manager.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) (limited to 'serial') 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 #include #include +#include #include +#include +#include #include @@ -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; -- cgit From 71d64082d40bcf1ce620fd3303494667ae1e4771 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 19:49:57 +0000 Subject: serial: added proxy registration function --- serial/manager.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index c15d102e..bdad9b32 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -59,6 +59,7 @@ #include "manager.h" #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" +#define SERIAL_PROXY_INTERFACE "org.bluez.serial.Proxy" /* Waiting for udev to create the device node */ #define MAX_OPEN_TRIES 5 @@ -100,11 +101,25 @@ static struct { { NULL } }; +struct proxy { + bdaddr_t src; + bdaddr_t dst; + uuid_t uuid; + char *tty; +}; + static DBusConnection *connection = NULL; static GSList *pending_connects = NULL; static GSList *proxies_paths = NULL; static int rfcomm_ctl = -1; +static void proxy_free(struct proxy *prx) +{ + if (prx->tty) + g_free(prx->tty); + g_free(prx); +} + static void pending_connect_free(struct pending_connect *pc) { if (pc->conn) @@ -895,6 +910,69 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } +static DBusHandlerResult proxy_enable(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult proxy_disable(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult proxy_get_info(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusMethodVTable proxy_methods[] = { + { "Enable", proxy_enable, "", "" }, + { "Disable", proxy_disable, "", "" }, + { "GetInfo", proxy_get_info, "", "{sv}" }, + { NULL, NULL, NULL, NULL }, +}; + +static void proxy_handler_unregister(DBusConnection *conn, void *data) +{ + struct proxy *prx = data; + + info("Unregistered proxy: %s", prx->tty); + + /* FIXME: Unregister the service record */ + + proxy_free(prx); +} + +static int proxy_register(DBusConnection *conn, + const char *path, uuid_t *uuid, const char *tty) +{ + struct proxy *prx; + + prx = g_new0(struct proxy, 1); + prx->tty = g_strdup(tty); + memcpy(&prx->uuid, uuid, sizeof(uuid_t)); + bacpy(&prx->src, BDADDR_ANY); + + if (!dbus_connection_create_object_path(conn, path, prx, + proxy_handler_unregister)) { + proxy_free(prx); + return -1; + } + + if (!dbus_connection_register_interface(conn, path, + SERIAL_PROXY_INTERFACE, + proxy_methods, + NULL, NULL)) { + dbus_connection_destroy_object_path(conn, path); + return -1; + } + + return 0; +} + static int str2uuid(uuid_t *uuid, const char *string) { uint16_t data1, data2, data3, data5; @@ -971,7 +1049,10 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - /* FIXME: Register the proxy object */ + if (proxy_register(conn, path, &uuid, tty) < 0) { + dbus_message_unref(reply); + return err_failed(conn, msg, "Create object path failed"); + } /* FIXME: persistent storage */ proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); -- cgit From ef00bdddbc2a37b1e0b8d0b4ad8430352d45c21b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 19:55:44 +0000 Subject: serial: ListProxies implementation --- serial/manager.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index bdad9b32..913ea540 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1072,7 +1072,28 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, static DBusHandlerResult list_proxies(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessageIter iter, iter_array; + DBusMessage *reply; + GSList *l; + const char *path; + + 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 (l = proxies_paths; l; l = l->next) { + path = l->data; + dbus_message_iter_append_basic(&iter_array, + DBUS_TYPE_STRING, &path); + } + + dbus_message_iter_close_container(&iter, &iter_array); + + return send_message_and_unref(conn, reply); } static DBusHandlerResult remove_proxy(DBusConnection *conn, -- cgit From 609a9e3c7876e30ba9538cbc406ca17b3addc806 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 20:18:21 +0000 Subject: serial: RemoveProxy implementation --- serial/manager.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 913ea540..072457e4 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1099,7 +1099,35 @@ static DBusHandlerResult list_proxies(DBusConnection *conn, static DBusHandlerResult remove_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + const char *path; + GSList *l; + DBusError derr; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + l = g_slist_find_custom(proxies_paths, path, (GCompareFunc) strcmp); + if (!l) + return err_does_not_exist(conn, msg, "Invalid proxy path"); + + g_free(l->data); + proxies_paths = g_slist_remove(proxies_paths, l->data); + + dbus_connection_destroy_object_path(conn, path); + + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ProxyRemoved", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + + return send_message_and_unref(conn, + dbus_message_new_method_return(msg)); } static DBusHandlerResult connect_service(DBusConnection *conn, -- cgit From 62f6b0087df91a19383d3f467c278e71e49e4c1a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 10 Aug 2007 20:47:16 +0000 Subject: serial: Proxy.Enable initial implementation --- serial/manager.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 072457e4..52b28c6f 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -106,6 +106,9 @@ struct proxy { bdaddr_t dst; uuid_t uuid; char *tty; + uint8_t channel; + uint32_t record_id; + guint listen_watch; }; static DBusConnection *connection = NULL; @@ -910,10 +913,63 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } +static int rfcomm_listen(bdaddr_t *src, uint8_t *channel) +{ + return 0; +} + +static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) +{ + return 0; +} + +static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) +{ + return 0; +} + +static gboolean connect_event(GIOChannel *chan, + GIOCondition cond, gpointer data) +{ + return FALSE; +} + static DBusHandlerResult proxy_enable(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + struct proxy *prx = data; + GIOChannel *io; + sdp_buf_t buf; + int sk; + + /* Listen */ + sk = rfcomm_listen(&prx->src, &prx->channel); + if (sk < 0) { + const char *strerr = strerror(errno); + error("RFCOMM listen socket failed: %s(%d)", strerr, errno); + return err_failed(conn, msg, strerr); + } + + /* Create the record */ + create_proxy_record(&buf, &prx->uuid, prx->channel); + + /* Register the record */ + prx->record_id = add_proxy_record(conn, &buf); + if (!prx->record_id) { + close(sk); + return err_failed(conn, msg, "Service registration failed"); + } + + /* Add incomming connection watch */ + io = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(io, TRUE); + prx->listen_watch = g_io_add_watch(io, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + connect_event, prx); + g_io_channel_unref(io); + + return send_message_and_unref(conn, + dbus_message_new_method_return(msg)); } static DBusHandlerResult proxy_disable(DBusConnection *conn, -- cgit From 807ba1a5ce67fb1b6c99675ea3c203ce9549d971 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 13:52:41 +0000 Subject: serial: added proxy rfcomm_listen implementation --- serial/manager.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 52b28c6f..d6a6cbb5 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -913,9 +913,45 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static int rfcomm_listen(bdaddr_t *src, uint8_t *channel) +static int rfcomm_listen(bdaddr_t *src, uint8_t *channel, int opts) { - return 0; + struct sockaddr_rc laddr; + socklen_t alen; + int err, sk; + + sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (sk < 0) + return -errno; + + if (setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opts, sizeof(opts)) < 0) + goto fail; + + memset(&laddr, 0, sizeof(laddr)); + laddr.rc_family = AF_BLUETOOTH; + bacpy(&laddr.rc_bdaddr, src); + laddr.rc_channel = 0; + + alen = sizeof(laddr); + if (bind(sk, (struct sockaddr *) &laddr, alen) < 0) + goto fail; + + if (listen(sk, 1) < 0) + goto fail; + + memset(&laddr, 0, sizeof(laddr)); + if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) + goto fail; + + *channel = laddr.rc_channel; + + return sk; + +fail: + err = errno; + close(sk); + errno = err; + + return -err; } static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) @@ -943,7 +979,8 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, int sk; /* Listen */ - sk = rfcomm_listen(&prx->src, &prx->channel); + /* FIXME: missing options */ + sk = rfcomm_listen(&prx->src, &prx->channel, 0); if (sk < 0) { const char *strerr = strerror(errno); error("RFCOMM listen socket failed: %s(%d)", strerr, errno); -- cgit From 88d221eba96e8283b32f6d0e3ef74bd5c6fa667d Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 14:28:30 +0000 Subject: serial: added create_proxy_record implementation --- serial/manager.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index d6a6cbb5..47b078ce 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -954,9 +954,74 @@ fail: return -err; } +static void add_lang_attr(sdp_record_t *r) +{ + sdp_lang_attr_t base_lang; + sdp_list_t *langs = 0; + + /* UTF-8 MIBenum (http://www.iana.org/assignments/character-sets) */ + base_lang.code_ISO639 = (0x65 << 8) | 0x6e; + base_lang.encoding = 106; + base_lang.base_offset = SDP_PRIMARY_LANG_BASE; + langs = sdp_list_append(0, &base_lang); + sdp_set_lang_attr(r, langs); + sdp_list_free(langs, 0); +} + static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) { - return 0; + sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; + uuid_t root_uuid, l2cap, rfcomm; + sdp_profile_desc_t profile; + sdp_record_t record; + sdp_data_t *ch; + int ret; + + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + sdp_list_free(root, NULL); + + svclass_id = sdp_list_append(NULL, uuid); + sdp_set_service_classes(&record, svclass_id); + sdp_list_free(svclass_id, NULL); + + sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); + profile.version = 0x0100; + profiles = sdp_list_append(NULL, &profile); + sdp_set_profile_descs(&record, profiles); + sdp_list_free(profiles, NULL); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(NULL, &l2cap); + apseq = sdp_list_append(NULL, proto[0]); + + sdp_uuid16_create(&rfcomm, RFCOMM_UUID); + proto[1] = sdp_list_append(NULL, &rfcomm); + ch = sdp_data_alloc(SDP_UINT8, &channel); + proto[1] = sdp_list_append(proto[1], ch); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(NULL, apseq); + sdp_set_access_protos(&record, aproto); + + add_lang_attr(&record); + + sdp_set_info_attr(&record, "Port Proxy Entity", + NULL, "Port Proxy Entity"); + + ret = sdp_gen_record_pdu(&record, buf); + + sdp_data_free(ch); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + + return ret; + } static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) -- cgit From b42813af874cd3347bd199d82eeec8b2cc780aba Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 14:56:14 +0000 Subject: serial: added add_proxy_record implementation --- serial/manager.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 47b078ce..679c6d4b 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1026,7 +1026,50 @@ static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) { - return 0; + DBusMessage *msg, *reply; + DBusError derr; + dbus_uint32_t rec_id; + + msg = dbus_message_new_method_call("org.bluez", "/org/bluez", + "org.bluez.Database", "AddServiceRecord"); + if (!msg) { + error("Can't allocate new method call"); + return 0; + } + + dbus_message_append_args(msg, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, + &buf->data, buf->data_size, + DBUS_TYPE_INVALID); + + dbus_error_init(&derr); + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); + + free(buf->data); + dbus_message_unref(msg); + + if (dbus_error_is_set(&derr) || + dbus_set_error_from_message(&derr, reply)) { + error("Adding service record failed: %s", derr.message); + dbus_error_free(&derr); + return 0; + } + + dbus_message_get_args(reply, &derr, + DBUS_TYPE_UINT32, &rec_id, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&derr)) { + error("Invalid arguments to AddServiceRecord reply: %s", + derr.message); + dbus_message_unref(reply); + dbus_error_free(&derr); + return 0; + } + + dbus_message_unref(reply); + + return rec_id; } static gboolean connect_event(GIOChannel *chan, -- cgit From 6d48df39064d820d101653714211ea4eb2aa6282 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 17:15:51 +0000 Subject: serial: proxy - accept incomming connections and forward data --- serial/manager.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 679c6d4b..96f9182d 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -60,6 +60,7 @@ #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" #define SERIAL_PROXY_INTERFACE "org.bluez.serial.Proxy" +#define BUF_SIZE 1024 /* Waiting for udev to create the device node */ #define MAX_OPEN_TRIES 5 @@ -109,6 +110,8 @@ struct proxy { uint8_t channel; uint32_t record_id; guint listen_watch; + guint rfcomm_watch; + guint tty_watch; }; static DBusConnection *connection = NULL; @@ -1024,6 +1027,41 @@ static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) } +static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + char buf[BUF_SIZE]; + GIOChannel *dest = data; + GIOError err; + gsize rbytes, wbytes, written; + + if (cond & G_IO_NVAL) + return FALSE; + + if (cond & (G_IO_HUP | G_IO_ERR)) { + g_io_channel_close(dest); + return FALSE; + } + + memset(buf, 0, sizeof(buf)); + rbytes = wbytes = written = 0; + + err = g_io_channel_read(chan, buf, sizeof(buf) - 1, &rbytes); + if (err != G_IO_ERROR_NONE) + return TRUE; + + while (wbytes < rbytes) { + err = g_io_channel_write(dest, + buf + wbytes, + rbytes - wbytes, + &written); + if (err != G_IO_ERROR_NONE) + break; + wbytes += written; + } + + return TRUE; +} + static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) { DBusMessage *msg, *reply; @@ -1075,7 +1113,56 @@ static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) static gboolean connect_event(GIOChannel *chan, GIOCondition cond, gpointer data) { - return FALSE; + struct proxy *prx = data; + struct sockaddr_rc raddr; + GIOChannel *node_io, *tty_io; + socklen_t alen; + int sk, nsk, tty_sk; + + if (cond & G_IO_NVAL) + return FALSE; + + if (cond & (G_IO_ERR | G_IO_HUP)) { + g_io_channel_close(chan); + return FALSE; + } + + sk = g_io_channel_unix_get_fd(chan); + + memset(&raddr, 0, sizeof(raddr)); + alen = sizeof(raddr); + nsk = accept(sk, (struct sockaddr *) &raddr, &alen); + if (nsk < 0) + return TRUE; + + bacpy(&prx->dst, &raddr.rc_bdaddr); + + /* TTY copen */ + tty_sk = open(prx->tty, O_RDWR | O_NOCTTY); + if (tty_sk < 0) { + error("Unable to open %s: %s(%d)", + prx->tty, strerror(errno), errno); + close(nsk); + return TRUE; + } + + node_io = g_io_channel_unix_new(nsk); + g_io_channel_set_close_on_unref(node_io, TRUE); + tty_io = g_io_channel_unix_new(tty_sk); + g_io_channel_set_close_on_unref(tty_io, TRUE); + + prx->rfcomm_watch = g_io_add_watch(node_io, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + forward_data, tty_io); + + prx->tty_watch = g_io_add_watch(tty_io, + G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, + forward_data, node_io); + + g_io_channel_unref(node_io); + g_io_channel_unref(tty_io); + + return TRUE; } static DBusHandlerResult proxy_enable(DBusConnection *conn, -- cgit From 7a085c5eeb65bbde0fee0561de9e0ee283c50566 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 17:35:15 +0000 Subject: serial: added Proxy.Disable implementation --- serial/manager.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 96f9182d..a6c6fe94 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1204,10 +1204,69 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, dbus_message_new_method_return(msg)); } +static int remove_proxy_record(DBusConnection *conn, uint32_t rec_id) +{ + DBusMessage *msg, *reply; + DBusError derr; + + msg = dbus_message_new_method_call("org.bluez", "/org/bluez", + "org.bluez.Database", "RemoveServiceRecord"); + if (!msg) { + error("Can't allocate new method call"); + return -ENOMEM; + } + + dbus_message_append_args(msg, + DBUS_TYPE_UINT32, &rec_id, + DBUS_TYPE_INVALID); + + dbus_error_init(&derr); + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); + + dbus_message_unref(msg); + + if (dbus_error_is_set(&derr)) { + error("Removing service record 0x%x failed: %s", + rec_id, derr.message); + dbus_error_free(&derr); + return -1; + } + + dbus_message_unref(reply); + + return 0; +} + static DBusHandlerResult proxy_disable(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + struct proxy *prx = data; + + /* Unregister the record */ + if (prx->record_id) { + remove_proxy_record(conn, prx->record_id); + prx->record_id = 0; + } + + /* Stop listen */ + if (prx->listen_watch) { + g_source_remove(prx->listen_watch); + prx->listen_watch = 0; + } + + /* Remove watches */ + if (prx->rfcomm_watch) { + g_source_remove(prx->rfcomm_watch); + prx->rfcomm_watch = 0; + } + + if (prx->tty_watch) { + g_source_remove(prx->tty_watch); + prx->tty_watch = 0; + } + + return send_message_and_unref(conn, + dbus_message_new_method_return(msg)); } static DBusHandlerResult proxy_get_info(DBusConnection *conn, -- cgit From d9b79bb83ad9255dfcf2102cb10c3da26c4e3155 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 18:06:48 +0000 Subject: serial: handle already enabled error for Proxy.Enable and not enabled error for Proxy.Disable --- serial/manager.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index a6c6fe94..cd83bfe2 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1173,6 +1173,9 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, sdp_buf_t buf; int sk; + if (prx->listen_watch) + return err_failed(conn, msg, "Already enabled"); + /* Listen */ /* FIXME: missing options */ sk = rfcomm_listen(&prx->src, &prx->channel, 0); @@ -1242,19 +1245,13 @@ static DBusHandlerResult proxy_disable(DBusConnection *conn, { struct proxy *prx = data; - /* Unregister the record */ - if (prx->record_id) { - remove_proxy_record(conn, prx->record_id); - prx->record_id = 0; - } - - /* Stop listen */ - if (prx->listen_watch) { - g_source_remove(prx->listen_watch); - prx->listen_watch = 0; - } + if (!prx->listen_watch) + return err_failed(conn, msg, "Not enabled"); /* Remove watches */ + g_source_remove(prx->listen_watch); + prx->listen_watch = 0; + if (prx->rfcomm_watch) { g_source_remove(prx->rfcomm_watch); prx->rfcomm_watch = 0; @@ -1265,6 +1262,10 @@ static DBusHandlerResult proxy_disable(DBusConnection *conn, prx->tty_watch = 0; } + /* Unregister the record */ + remove_proxy_record(conn, prx->record_id); + prx->record_id = 0; + return send_message_and_unref(conn, dbus_message_new_method_return(msg)); } -- cgit From e375ab2250d99fcb1d188541001fc4fb8c5aa4c7 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 13 Aug 2007 19:07:02 +0000 Subject: serial: added proxy GetInfo implementation --- serial/manager.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index cd83bfe2..39da4ab5 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1273,7 +1273,56 @@ static DBusHandlerResult proxy_disable(DBusConnection *conn, static DBusHandlerResult proxy_get_info(DBusConnection *conn, DBusMessage *msg, void *data) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + struct proxy *prx = data; + DBusMessage *reply; + DBusMessageIter iter, dict; + dbus_bool_t boolean; + char uuid_str[MAX_LEN_UUID_STR]; + char bda[18]; + const char *pstr; + + 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_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + sdp_uuid2strn(&prx->uuid, uuid_str, MAX_LEN_UUID_STR); + pstr = uuid_str; + dbus_message_iter_append_dict_entry(&dict, "uuid", + DBUS_TYPE_STRING, &pstr); + + dbus_message_iter_append_dict_entry(&dict, "tty", + DBUS_TYPE_STRING, &prx->tty); + + if (prx->channel) + dbus_message_iter_append_dict_entry(&dict, "channel", + DBUS_TYPE_BYTE, &prx->channel); + + boolean = (prx->listen_watch ? TRUE : FALSE); + dbus_message_iter_append_dict_entry(&dict, "enabled", + DBUS_TYPE_BOOLEAN, &boolean); + + boolean = (prx->rfcomm_watch ? TRUE : FALSE); + dbus_message_iter_append_dict_entry(&dict, "connected", + DBUS_TYPE_BOOLEAN, &boolean); + + /* If connected: append the remote address */ + if (boolean) { + ba2str(&prx->dst, bda); + pstr = bda; + dbus_message_iter_append_dict_entry(&dict, "address", + DBUS_TYPE_STRING, &pstr); + } + + dbus_message_iter_close_container(&iter, &dict); + + return send_message_and_unref(conn, reply); } static DBusMethodVTable proxy_methods[] = { -- cgit From d7815ff6eede329a957f57053f4e712274388ccb Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 14 Aug 2007 14:55:32 +0000 Subject: serial: fixed ListPorts - proxies paths should not be included --- serial/manager.c | 76 +++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 40 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 39da4ab5..e5b07997 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -116,6 +116,7 @@ struct proxy { static DBusConnection *connection = NULL; static GSList *pending_connects = NULL; +static GSList *ports_paths = NULL; static GSList *proxies_paths = NULL; static int rfcomm_ctl = -1; @@ -550,6 +551,7 @@ static void record_reply(DBusPendingCall *call, void *data) g_free(svcname); port_register(pc->conn, err, &dst, port_name, path); + ports_paths = g_slist_append(ports_paths, g_strdup(path)); reply = dbus_message_new_method_return(pc->msg); dbus_message_append_args(reply, @@ -825,6 +827,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); port_store(&src, &dst, err, val, NULL); port_register(conn, err, &dst, port_name, path); + ports_paths = g_slist_append(ports_paths, g_strdup(path)); reply = dbus_message_new_method_return(msg); if (!reply) @@ -841,38 +844,35 @@ static DBusHandlerResult create_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static DBusHandlerResult list_ports(DBusConnection *conn, - DBusMessage *msg, void *data) +static void message_append_paths(DBusMessage *msg, const GSList *list) { - DBusMessage *reply; + const GSList *l; + const char *path; DBusMessageIter iter, iter_array; - char **dev; - int i; - 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_init_append(msg, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &iter_array); - if (!dbus_connection_list_registered(conn, SERIAL_MANAGER_PATH, &dev)) - goto done; - - for (i = 0; dev[i]; i++) { - char dev_path[MAX_PATH_LENGTH]; - const char *ppath = dev_path; - - snprintf(dev_path, sizeof(dev_path), "%s/%s", - SERIAL_MANAGER_PATH, dev[i]); + for (l = list; l; l = l->next) { + path = l->data; dbus_message_iter_append_basic(&iter_array, - DBUS_TYPE_STRING, &ppath); + DBUS_TYPE_STRING, &path); } - dbus_free_string_array(dev); -done: dbus_message_iter_close_container(&iter, &iter_array); +} + +static DBusHandlerResult list_ports(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusMessage *reply; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + message_append_paths(reply, ports_paths); return send_message_and_unref(conn, reply); } @@ -906,7 +906,7 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + dbus_message_new_method_return(msg)); dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortRemoved" , @@ -1137,7 +1137,7 @@ static gboolean connect_event(GIOChannel *chan, bacpy(&prx->dst, &raddr.rc_bdaddr); - /* TTY copen */ + /* TTY open */ tty_sk = open(prx->tty, O_RDWR | O_NOCTTY); if (tty_sk < 0) { error("Unable to open %s: %s(%d)", @@ -1469,26 +1469,13 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, static DBusHandlerResult list_proxies(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessageIter iter, iter_array; DBusMessage *reply; - GSList *l; - const char *path; 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 (l = proxies_paths; l; l = l->next) { - path = l->data; - dbus_message_iter_append_basic(&iter_array, - DBUS_TYPE_STRING, &path); - } - - dbus_message_iter_close_container(&iter, &iter_array); + message_append_paths(reply, proxies_paths); return send_message_and_unref(conn, reply); } @@ -1711,6 +1698,13 @@ static void manager_unregister(DBusConnection *conn, void *data) proxies_paths = NULL; } + if (ports_paths) { + g_slist_foreach(ports_paths, + (GFunc) g_free, NULL); + g_slist_free(ports_paths); + ports_paths = NULL; + } + /* Unregister all paths in serial hierarchy */ if (!dbus_connection_list_registered(conn, SERIAL_MANAGER_PATH, &dev)) return; @@ -1752,7 +1746,7 @@ static DBusSignalVTable manager_signals[] = { static void parse_port(char *key, char *value, void *data) { - char port_name[16], dst_addr[18]; + char path[MAX_PATH_LENGTH], port_name[16], dst_addr[18]; char *src_addr = data; bdaddr_t dst, src; int ch, id; @@ -1772,10 +1766,12 @@ static void parse_port(char *key, char *value, void *data) snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", id); - if (port_register(connection, id, &dst, port_name, NULL) < 0) { + if (port_register(connection, id, &dst, port_name, path) < 0) { rfcomm_release(id); return; } + + ports_paths = g_slist_append(ports_paths, g_strdup(path)); } static void register_stored_ports(void) -- cgit From e98f93aa5bc0ca18e0544c448690ad7b9a0df6e1 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 14 Aug 2007 16:51:31 +0000 Subject: serial: close the rfcomm/tty sockets and unreg the record when the proxy is removed --- serial/manager.c | 110 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 52 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index e5b07997..19df7379 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1110,6 +1110,39 @@ static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) return rec_id; } +static int remove_proxy_record(DBusConnection *conn, uint32_t rec_id) +{ + DBusMessage *msg, *reply; + DBusError derr; + + msg = dbus_message_new_method_call("org.bluez", "/org/bluez", + "org.bluez.Database", "RemoveServiceRecord"); + if (!msg) { + error("Can't allocate new method call"); + return -ENOMEM; + } + + dbus_message_append_args(msg, + DBUS_TYPE_UINT32, &rec_id, + DBUS_TYPE_INVALID); + + dbus_error_init(&derr); + reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); + + dbus_message_unref(msg); + + if (dbus_error_is_set(&derr)) { + error("Removing service record 0x%x failed: %s", + rec_id, derr.message); + dbus_error_free(&derr); + return -1; + } + + dbus_message_unref(reply); + + return 0; +} + static gboolean connect_event(GIOChannel *chan, GIOCondition cond, gpointer data) { @@ -1165,6 +1198,26 @@ static gboolean connect_event(GIOChannel *chan, return TRUE; } +static void listen_watch_notify(gpointer data) +{ + struct proxy *prx = data; + + prx->listen_watch = 0; + + if (prx->rfcomm_watch) { + g_source_remove(prx->rfcomm_watch); + prx->rfcomm_watch = 0; + } + + if (prx->tty_watch) { + g_source_remove(prx->tty_watch); + prx->tty_watch = 0; + } + + remove_proxy_record(connection, prx->record_id); + prx->record_id = 0; +} + static DBusHandlerResult proxy_enable(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1198,48 +1251,15 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, /* Add incomming connection watch */ io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); - prx->listen_watch = g_io_add_watch(io, + prx->listen_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connect_event, prx); + connect_event, prx, listen_watch_notify); g_io_channel_unref(io); return send_message_and_unref(conn, dbus_message_new_method_return(msg)); } -static int remove_proxy_record(DBusConnection *conn, uint32_t rec_id) -{ - DBusMessage *msg, *reply; - DBusError derr; - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "RemoveServiceRecord"); - if (!msg) { - error("Can't allocate new method call"); - return -ENOMEM; - } - - dbus_message_append_args(msg, - DBUS_TYPE_UINT32, &rec_id, - DBUS_TYPE_INVALID); - - dbus_error_init(&derr); - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); - - dbus_message_unref(msg); - - if (dbus_error_is_set(&derr)) { - error("Removing service record 0x%x failed: %s", - rec_id, derr.message); - dbus_error_free(&derr); - return -1; - } - - dbus_message_unref(reply); - - return 0; -} - static DBusHandlerResult proxy_disable(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1248,23 +1268,8 @@ static DBusHandlerResult proxy_disable(DBusConnection *conn, if (!prx->listen_watch) return err_failed(conn, msg, "Not enabled"); - /* Remove watches */ + /* Remove the watches and unregister the record: see watch notify */ g_source_remove(prx->listen_watch); - prx->listen_watch = 0; - - if (prx->rfcomm_watch) { - g_source_remove(prx->rfcomm_watch); - prx->rfcomm_watch = 0; - } - - if (prx->tty_watch) { - g_source_remove(prx->tty_watch); - prx->tty_watch = 0; - } - - /* Unregister the record */ - remove_proxy_record(conn, prx->record_id); - prx->record_id = 0; return send_message_and_unref(conn, dbus_message_new_method_return(msg)); @@ -1338,7 +1343,8 @@ static void proxy_handler_unregister(DBusConnection *conn, void *data) info("Unregistered proxy: %s", prx->tty); - /* FIXME: Unregister the service record */ + if (prx->listen_watch) + g_source_remove(prx->listen_watch); proxy_free(prx); } -- cgit From b8769c4814ad301b9ee409847b9df12085e69f59 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 15 Aug 2007 13:16:41 +0000 Subject: serial: initial proxy storage implementation --- serial/manager.c | 50 ++++++++++++++++++++++++++++++++++++-------------- serial/storage.c | 36 ++++++++++++++++++++++++++++++++++++ serial/storage.h | 2 ++ 3 files changed, 74 insertions(+), 14 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 19df7379..8703606a 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -105,13 +106,15 @@ static struct { struct proxy { bdaddr_t src; bdaddr_t dst; - uuid_t uuid; - char *tty; - uint8_t channel; - uint32_t record_id; - guint listen_watch; - guint rfcomm_watch; - guint tty_watch; + uuid_t uuid; /* UUID 128 */ + char *tty; /* TTY name */ + struct termios sys_ti; /* Default TTY setting */ + struct termios proxy_ti; /* Proxy TTY settings */ + uint8_t channel; /* RFCOMM channel */ + uint32_t record_id; /* Service record id */ + guint listen_watch; /* Server listen watch */ + guint rfcomm_watch; /* RFCOMM connection watch */ + guint tty_watch; /* Openned TTY watch */ }; static DBusConnection *connection = NULL; @@ -1349,15 +1352,17 @@ static void proxy_handler_unregister(DBusConnection *conn, void *data) proxy_free(prx); } -static int proxy_register(DBusConnection *conn, - const char *path, uuid_t *uuid, const char *tty) +static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, + uuid_t *uuid, const char *tty, struct termios *ti) { struct proxy *prx; prx = g_new0(struct proxy, 1); prx->tty = g_strdup(tty); memcpy(&prx->uuid, uuid, sizeof(uuid_t)); - bacpy(&prx->src, BDADDR_ANY); + bacpy(&prx->src, src); + memcpy(&prx->sys_ti, ti, sizeof(*ti)); + memcpy(&prx->proxy_ti, ti, sizeof(*ti)); if (!dbus_connection_create_object_path(conn, path, prx, proxy_handler_unregister)) { @@ -1417,12 +1422,14 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, { char path[MAX_PATH_LENGTH]; const char *uuidstr, *tty, *ppath = path; + struct termios ti; DBusMessage *reply; GSList *l; DBusError derr; struct stat st; + bdaddr_t src; uuid_t uuid; - int pos = 0; + int sk, dev_id, pos = 0; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -1441,6 +1448,14 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!pos || stat(tty, &st) < 0) return err_invalid_args(conn, msg, "Invalid TTY"); + /* Get the current setting to restore later */ + sk = open(tty, O_RDWR | O_NOCTTY); + if (sk < 0) + return err_invalid_args(conn, msg, "Can't open TTY"); + + tcgetattr(sk, &ti); + close(sk); + snprintf(path, MAX_PATH_LENGTH - 1, "/org/bluez/serial/proxy%s", tty + pos); @@ -1448,18 +1463,25 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (l) return err_already_exists(conn, msg, "Proxy already exists"); + dev_id = hci_get_route(NULL); + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) { + error("Adapter not available"); + return err_failed(conn, msg, "Adapter not available"); + } + reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (proxy_register(conn, path, &uuid, tty) < 0) { + if (proxy_register(conn, &src, path, &uuid, tty, &ti) < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "Create object path failed"); } - /* FIXME: persistent storage */ proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); + proxy_store(&src, uuidstr, tty, NULL, 0, 0, &ti); + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ProxyCreated", DBUS_TYPE_STRING, &ppath, @@ -1546,7 +1568,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return err_connection_in_progress(conn, msg); dev_id = hci_get_route(NULL); - if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) return err_failed(conn, msg, "Adapter not available"); pc = g_new0(struct pending_connect, 1); diff --git a/serial/storage.c b/serial/storage.c index 46e63f5d..1a867307 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -25,11 +25,15 @@ #include #endif +#include +#include #include #include #include #include +#include +#include #include @@ -82,3 +86,35 @@ int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, return err; } + +int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, + const char *name, uint8_t ch, int opts, struct termios *ti) +{ + char filename[PATH_MAX + 1], key[32], src_addr[18], *value; + int i, pos, size, err; + uint8_t *pti; + + ba2str(src, src_addr); + + create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "proxy"); + create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + if (!name) + name = "Port Proxy Entity"; + + size = MAX_LEN_UUID_STR + 16 + strlen(name) + sizeof(struct termios) * 2; + value = g_malloc0(size); + + snprintf(key, 32, "%s", tty); + + /* tty uuid 00 0x0000 name:termios */ + pos = snprintf(value, size, "%s %d 0x%04X %s:", tty, ch, opts, name); + + for (i = 0, pti = (uint8_t *) ti; i < sizeof(struct termios); i++, pti++) + sprintf(value + pos + (i * 2), "%2.2X", *pti); + + err = textfile_put(filename, key, value); + g_free(value); + + return err; +} diff --git a/serial/storage.h b/serial/storage.h index 1f92f521..300976b9 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -24,3 +24,5 @@ int port_delete(bdaddr_t *src, bdaddr_t *dst, int16_t id); int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, uint8_t ch, const char *svcname); +int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, + const char *name, uint8_t ch, int opts, struct termios *ti); -- cgit From 74e5259eb027bd0eaef50004ffe62de28d77e77b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 15 Aug 2007 14:02:10 +0000 Subject: serial: restore the initial TTY configuration when the proxy is unregistered --- serial/manager.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 8703606a..1cf4e083 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1343,9 +1343,17 @@ static DBusMethodVTable proxy_methods[] = { static void proxy_handler_unregister(DBusConnection *conn, void *data) { struct proxy *prx = data; + int sk; info("Unregistered proxy: %s", prx->tty); + /* Restore the initial TTY configuration */ + sk = open(prx->tty, O_RDWR | O_NOCTTY); + if (sk) { + tcsetattr(sk, TCSAFLUSH, &prx->sys_ti); + close(sk); + } + if (prx->listen_watch) g_source_remove(prx->listen_watch); -- cgit From 773651ca6b577e822c2bc096c4a5dec4f9645054 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 15 Aug 2007 20:23:01 +0000 Subject: serial: proxy_store - replaced tty by uuid --- serial/storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/storage.c b/serial/storage.c index 1a867307..f3c070d3 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -108,7 +108,7 @@ int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, snprintf(key, 32, "%s", tty); /* tty uuid 00 0x0000 name:termios */ - pos = snprintf(value, size, "%s %d 0x%04X %s:", tty, ch, opts, name); + pos = snprintf(value, size, "%s %d 0x%04X %s:", uuid, ch, opts, name); for (i = 0, pti = (uint8_t *) ti; i < sizeof(struct termios); i++, pti++) sprintf(value + pos + (i * 2), "%2.2X", *pti); -- cgit From 6fae334c9cca415a6520f258ee850bb0268fe597 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 15 Aug 2007 20:27:20 +0000 Subject: serial: added parsing function for stored proxies --- serial/manager.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 1cf4e083..5ccbce7a 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1386,6 +1386,8 @@ static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, return -1; } + info("Registered proxy:%s path:%s", tty, path); + return 0; } @@ -1810,7 +1812,61 @@ static void parse_port(char *key, char *value, void *data) ports_paths = g_slist_append(ports_paths, g_strdup(path)); } -static void register_stored_ports(void) +static void parse_proxy(char *key, char *value, void *data) +{ + char path[MAX_PATH_LENGTH], uuid_str[MAX_LEN_UUID_STR], tmp[3], *pvalue; + struct termios ti; + int ch, opts, pos = 0; + bdaddr_t *src = data; + uuid_t uuid; + uint8_t *pti; + + memset(uuid_str, 0, sizeof(uuid_str)); + if (sscanf(value,"%s %d 0x%04X %n", uuid_str, &ch, &opts, &pos) != 3) + return; + + /* UUID format valid? */ + if (str2uuid(&uuid, uuid_str) < 0) + return; + + /* Extracting name */ + value += pos; + pvalue = strchr(value, ':'); + if (!pvalue) + return; + + /* FIXME: currently name is not used */ + *pvalue = '\0'; + + /* Extracting termios */ + pvalue++; + if (strlen(pvalue) != (2 * sizeof(ti))) + return; + + memset(&ti, 0, sizeof(ti)); + memset(tmp, 0, sizeof(tmp)); + + /* Converting to termios struct */ + pti = (uint8_t *) &ti; + for (pos = 0; pos < sizeof(ti); pos++, pvalue += 2, pti++) { + memcpy(tmp, pvalue, 2); + *pti = (uint8_t) strtol(tmp, NULL, 16); + } + + pos = 0; + sscanf(key, "/dev/%n", &pos); + if (!pos) + return; + + snprintf(path, MAX_PATH_LENGTH - 1, + "/org/bluez/serial/proxy%s", key + pos); + + proxy_register(connection, src, path, &uuid, key, &ti); + + proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); +} + +static void register_stored(void) { char filename[PATH_MAX + 1]; struct dirent *de; @@ -1825,9 +1881,12 @@ static void register_stored_ports(void) while ((de = readdir(dir)) != NULL) { if (!isdigit(de->d_name[0])) continue; - snprintf(filename, PATH_MAX, "%s/%s/serial", STORAGEDIR, de->d_name); + snprintf(filename, PATH_MAX, "%s/%s/serial", STORAGEDIR, de->d_name); textfile_foreach(filename, parse_port, de->d_name); + + snprintf(filename, PATH_MAX, "%s/%s/proxy", STORAGEDIR, de->d_name); + textfile_foreach(filename, parse_proxy, de->d_name); } closedir(dir); @@ -1863,7 +1922,7 @@ int serial_init(DBusConnection *conn) info("Registered manager path:%s", SERIAL_MANAGER_PATH); - register_stored_ports(); + register_stored(); return 0; } -- cgit From 97650b3f8187b0f8cf8d6f3dfa1c3d6752ef5ca2 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 15 Aug 2007 20:33:34 +0000 Subject: serial: fixed missing ProxyCreated signal for stored proxies --- serial/manager.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 5ccbce7a..f9532ff6 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1386,6 +1386,11 @@ static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, return -1; } + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ProxyCreated", + DBUS_TYPE_STRING, &path, + DBUS_TYPE_INVALID); + info("Registered proxy:%s path:%s", tty, path); return 0; @@ -1492,11 +1497,6 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, proxy_store(&src, uuidstr, tty, NULL, 0, 0, &ti); - 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); -- cgit From fb2bb3f2dcc78b19fb77d9bebf71021c54704e96 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 15 Aug 2007 20:51:30 +0000 Subject: serial: only use automatic assigned channels when it is not provided by the user --- serial/manager.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index f9532ff6..4dd98469 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -935,7 +935,7 @@ static int rfcomm_listen(bdaddr_t *src, uint8_t *channel, int opts) memset(&laddr, 0, sizeof(laddr)); laddr.rc_family = AF_BLUETOOTH; bacpy(&laddr.rc_bdaddr, src); - laddr.rc_channel = 0; + laddr.rc_channel = (channel ? *channel : 0); alen = sizeof(laddr); if (bind(sk, (struct sockaddr *) &laddr, alen) < 0) @@ -944,6 +944,9 @@ static int rfcomm_listen(bdaddr_t *src, uint8_t *channel, int opts) if (listen(sk, 1) < 0) goto fail; + if (!channel) + return sk; + memset(&laddr, 0, sizeof(laddr)); if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) goto fail; @@ -1233,7 +1236,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, return err_failed(conn, msg, "Already enabled"); /* Listen */ - /* FIXME: missing options */ + /* FIXME: missing options, update the stored channel */ sk = rfcomm_listen(&prx->src, &prx->channel, 0); if (sk < 0) { const char *strerr = strerror(errno); -- cgit From 57c2796d829c4b0078db7b59025e3cecdf85b2f0 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 16 Aug 2007 13:10:42 +0000 Subject: serial: proxy storage parsing - fixed Bluetooth source address --- serial/manager.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 4dd98469..1c913351 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1818,9 +1818,10 @@ static void parse_port(char *key, char *value, void *data) static void parse_proxy(char *key, char *value, void *data) { char path[MAX_PATH_LENGTH], uuid_str[MAX_LEN_UUID_STR], tmp[3], *pvalue; + char *src_addr = data; struct termios ti; int ch, opts, pos = 0; - bdaddr_t *src = data; + bdaddr_t src; uuid_t uuid; uint8_t *pti; @@ -1864,7 +1865,8 @@ static void parse_proxy(char *key, char *value, void *data) snprintf(path, MAX_PATH_LENGTH - 1, "/org/bluez/serial/proxy%s", key + pos); - proxy_register(connection, src, path, &uuid, key, &ti); + str2ba(src_addr, &src); + proxy_register(connection, &src, path, &uuid, key, &ti); proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); } -- cgit From 7f0afa058ede87359b3104ffa72874ed59f68432 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 16 Aug 2007 13:15:46 +0000 Subject: serial: RemoveProxy - remove the entry from the storage --- serial/manager.c | 6 ++++++ serial/storage.c | 11 +++++++++++ serial/storage.h | 1 + 3 files changed, 18 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 1c913351..eee5d1aa 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1524,6 +1524,7 @@ static DBusHandlerResult list_proxies(DBusConnection *conn, static DBusHandlerResult remove_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { + struct proxy *prx = NULL; const char *path; GSList *l; DBusError derr; @@ -1541,6 +1542,11 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn, if (!l) return err_does_not_exist(conn, msg, "Invalid proxy path"); + /* Remove from storage */ + if (dbus_connection_get_object_user_data(conn, + path, (void *) &prx) && prx) + proxy_delete(&prx->src, prx->tty); + g_free(l->data); proxies_paths = g_slist_remove(proxies_paths, l->data); diff --git a/serial/storage.c b/serial/storage.c index f3c070d3..641ca1e8 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -87,6 +87,17 @@ int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, return err; } +int proxy_delete(bdaddr_t *src, const char *tty) +{ + char filename[PATH_MAX + 1], src_addr[18]; + + ba2str(src, src_addr); + + create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "proxy"); + + return textfile_del(filename, tty); +} + int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, const char *name, uint8_t ch, int opts, struct termios *ti) { diff --git a/serial/storage.h b/serial/storage.h index 300976b9..4a24bdf7 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -24,5 +24,6 @@ int port_delete(bdaddr_t *src, bdaddr_t *dst, int16_t id); int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, uint8_t ch, const char *svcname); +int proxy_delete(bdaddr_t *src, const char *tty); int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, const char *name, uint8_t ch, int opts, struct termios *ti); -- cgit From 60bef734ae800110dfdba8d88c33dc023498b18b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 16 Aug 2007 15:04:29 +0000 Subject: serial: fixed TTY settings control on proxy creation and daemon startup --- serial/manager.c | 62 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 16 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index eee5d1aa..db5a9d12 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1366,21 +1366,43 @@ static void proxy_handler_unregister(DBusConnection *conn, void *data) static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, uuid_t *uuid, const char *tty, struct termios *ti) { + struct termios sys_ti; struct proxy *prx; + int sk; + + sk = open(tty, O_RDWR | O_NOCTTY); + if (sk < 0) { + error("Cant open TTY: %s(%d)", strerror(errno), errno); + return -EINVAL; + } prx = g_new0(struct proxy, 1); prx->tty = g_strdup(tty); memcpy(&prx->uuid, uuid, sizeof(uuid_t)); bacpy(&prx->src, src); - memcpy(&prx->sys_ti, ti, sizeof(*ti)); - memcpy(&prx->proxy_ti, ti, sizeof(*ti)); if (!dbus_connection_create_object_path(conn, path, prx, proxy_handler_unregister)) { proxy_free(prx); + close(sk); return -1; } + /* Current TTY settings */ + memset(&sys_ti, 0, sizeof(sys_ti)); + tcgetattr(sk, &sys_ti); + memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti)); + if (!ti) { + /* Keep the current settings */ + memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti)); + } else { + /* New TTY settings: user provided */ + memcpy(&prx->proxy_ti, ti, sizeof(*ti)); + tcsetattr(sk, TCSANOW, ti); + } + + close(sk); + if (!dbus_connection_register_interface(conn, path, SERIAL_PROXY_INTERFACE, proxy_methods, @@ -1440,14 +1462,13 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, { char path[MAX_PATH_LENGTH]; const char *uuidstr, *tty, *ppath = path; - struct termios ti; DBusMessage *reply; GSList *l; DBusError derr; struct stat st; bdaddr_t src; uuid_t uuid; - int sk, dev_id, pos = 0; + int dev_id, pos = 0; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -1466,14 +1487,6 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!pos || stat(tty, &st) < 0) return err_invalid_args(conn, msg, "Invalid TTY"); - /* Get the current setting to restore later */ - sk = open(tty, O_RDWR | O_NOCTTY); - if (sk < 0) - return err_invalid_args(conn, msg, "Can't open TTY"); - - tcgetattr(sk, &ti); - close(sk); - snprintf(path, MAX_PATH_LENGTH - 1, "/org/bluez/serial/proxy%s", tty + pos); @@ -1491,15 +1504,13 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (proxy_register(conn, &src, path, &uuid, tty, &ti) < 0) { + if (proxy_register(conn, &src, path, &uuid, tty, NULL) < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "Create object path failed"); } proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); - proxy_store(&src, uuidstr, tty, NULL, 0, 0, &ti); - dbus_message_append_args(reply, DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); @@ -1726,6 +1737,25 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, return send_message_and_unref(conn, reply); } +static void proxy_path_free(gpointer data, gpointer udata) +{ + DBusConnection *conn = udata; + const char *path = data; + struct proxy *prx = NULL; + + /* Store/Update the proxy entries before exit */ + if (dbus_connection_get_object_user_data(conn, + path, (void *) &prx) && prx) { + char uuid_str[MAX_LEN_UUID_STR]; + + sdp_uuid2strn(&prx->uuid, uuid_str, MAX_LEN_UUID_STR); + proxy_store(&prx->src, uuid_str, prx->tty, NULL, + prx->channel, 0, &prx->proxy_ti); + } + + g_free(data); +} + static void manager_unregister(DBusConnection *conn, void *data) { char **dev; @@ -1740,7 +1770,7 @@ static void manager_unregister(DBusConnection *conn, void *data) if (proxies_paths) { g_slist_foreach(proxies_paths, - (GFunc) g_free, NULL); + proxy_path_free, conn); g_slist_free(proxies_paths); proxies_paths = NULL; } -- cgit From 768cffb8e0bb3f9d062441b06db486a63d1f8a5c Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 16 Aug 2007 16:50:11 +0000 Subject: serial: proxy - use uuid128 string instead of uuid_t --- serial/manager.c | 137 ++++++++++++++++++++++++++----------------------------- 1 file changed, 64 insertions(+), 73 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index db5a9d12..498e2846 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -106,7 +106,7 @@ static struct { struct proxy { bdaddr_t src; bdaddr_t dst; - uuid_t uuid; /* UUID 128 */ + char *uuid128; /* UUID 128 */ char *tty; /* TTY name */ struct termios sys_ti; /* Default TTY setting */ struct termios proxy_ti; /* Proxy TTY settings */ @@ -127,6 +127,8 @@ static void proxy_free(struct proxy *prx) { if (prx->tty) g_free(prx->tty); + if (prx->uuid128) + g_free(prx->uuid128); g_free(prx); } @@ -744,7 +746,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, DBusMessage *reply; DBusError derr; bdaddr_t src, dst; - char path[MAX_PATH_LENGTH], port_name[16], uuid[37]; + char path[MAX_PATH_LENGTH], port_name[16], uuid[MAX_LEN_UUID_STR]; const char *bda, *pattern, *ppath = path; long val; int dev_id, err; @@ -977,10 +979,46 @@ static void add_lang_attr(sdp_record_t *r) sdp_list_free(langs, 0); } -static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) +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 int create_proxy_record(sdp_buf_t *buf, const char *uuid128, uint8_t channel) { sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; - uuid_t root_uuid, l2cap, rfcomm; + uuid_t uuid, root_uuid, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_record_t record; sdp_data_t *ch; @@ -993,7 +1031,8 @@ static int create_proxy_record(sdp_buf_t *buf, uuid_t *uuid, uint8_t channel) sdp_set_browse_groups(&record, root); sdp_list_free(root, NULL); - svclass_id = sdp_list_append(NULL, uuid); + str2uuid(&uuid, uuid128); + svclass_id = sdp_list_append(NULL, &uuid); sdp_set_service_classes(&record, svclass_id); sdp_list_free(svclass_id, NULL); @@ -1236,7 +1275,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, return err_failed(conn, msg, "Already enabled"); /* Listen */ - /* FIXME: missing options, update the stored channel */ + /* FIXME: missing options */ sk = rfcomm_listen(&prx->src, &prx->channel, 0); if (sk < 0) { const char *strerr = strerror(errno); @@ -1245,7 +1284,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, } /* Create the record */ - create_proxy_record(&buf, &prx->uuid, prx->channel); + create_proxy_record(&buf, prx->uuid128, prx->channel); /* Register the record */ prx->record_id = add_proxy_record(conn, &buf); @@ -1288,9 +1327,6 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, DBusMessage *reply; DBusMessageIter iter, dict; dbus_bool_t boolean; - char uuid_str[MAX_LEN_UUID_STR]; - char bda[18]; - const char *pstr; reply = dbus_message_new_method_return(msg); if (!reply) @@ -1303,10 +1339,8 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - sdp_uuid2strn(&prx->uuid, uuid_str, MAX_LEN_UUID_STR); - pstr = uuid_str; dbus_message_iter_append_dict_entry(&dict, "uuid", - DBUS_TYPE_STRING, &pstr); + DBUS_TYPE_STRING, &prx->uuid128); dbus_message_iter_append_dict_entry(&dict, "tty", DBUS_TYPE_STRING, &prx->tty); @@ -1325,8 +1359,10 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, /* If connected: append the remote address */ if (boolean) { + char bda[18]; + const char *pstr = bda; + ba2str(&prx->dst, bda); - pstr = bda; dbus_message_iter_append_dict_entry(&dict, "address", DBUS_TYPE_STRING, &pstr); } @@ -1364,7 +1400,7 @@ static void proxy_handler_unregister(DBusConnection *conn, void *data) } static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, - uuid_t *uuid, const char *tty, struct termios *ti) + const char *uuid128, const char *tty, struct termios *ti) { struct termios sys_ti; struct proxy *prx; @@ -1378,7 +1414,7 @@ static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, prx = g_new0(struct proxy, 1); prx->tty = g_strdup(tty); - memcpy(&prx->uuid, uuid, sizeof(uuid_t)); + prx->uuid128 = g_strdup(uuid128); bacpy(&prx->src, src); if (!dbus_connection_create_object_path(conn, path, prx, @@ -1421,47 +1457,11 @@ static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, return 0; } -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) { char path[MAX_PATH_LENGTH]; - const char *uuidstr, *tty, *ppath = path; + const char *uuid128, *tty, *ppath = path; DBusMessage *reply; GSList *l; DBusError derr; @@ -1472,7 +1472,7 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &uuidstr, + DBUS_TYPE_STRING, &uuid128, DBUS_TYPE_STRING, &tty, DBUS_TYPE_INVALID)) { err_invalid_args(conn, msg, derr.message); @@ -1480,7 +1480,7 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - if (str2uuid(&uuid, uuidstr) < 0) + if (str2uuid(&uuid, uuid128) < 0) return err_invalid_args(conn, msg, "Invalid UUID"); sscanf(tty, "/dev/%n", &pos); @@ -1504,7 +1504,7 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (proxy_register(conn, &src, path, &uuid, tty, NULL) < 0) { + if (proxy_register(conn, &src, path, uuid128, tty, NULL) < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "Create object path failed"); } @@ -1581,7 +1581,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, const char *bda, *pattern; long val; int dev_id, err; - char uuid[37]; + char uuid[MAX_LEN_UUID_STR]; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -1745,13 +1745,9 @@ static void proxy_path_free(gpointer data, gpointer udata) /* Store/Update the proxy entries before exit */ if (dbus_connection_get_object_user_data(conn, - path, (void *) &prx) && prx) { - char uuid_str[MAX_LEN_UUID_STR]; - - sdp_uuid2strn(&prx->uuid, uuid_str, MAX_LEN_UUID_STR); - proxy_store(&prx->src, uuid_str, prx->tty, NULL, + path, (void *) &prx) && prx) + proxy_store(&prx->src, prx->uuid128, prx->tty, NULL, prx->channel, 0, &prx->proxy_ti); - } g_free(data); } @@ -1853,20 +1849,15 @@ static void parse_port(char *key, char *value, void *data) static void parse_proxy(char *key, char *value, void *data) { - char path[MAX_PATH_LENGTH], uuid_str[MAX_LEN_UUID_STR], tmp[3], *pvalue; - char *src_addr = data; + char path[MAX_PATH_LENGTH], uuid128[MAX_LEN_UUID_STR], tmp[3]; + char *pvalue, *src_addr = data; struct termios ti; int ch, opts, pos = 0; bdaddr_t src; - uuid_t uuid; uint8_t *pti; - memset(uuid_str, 0, sizeof(uuid_str)); - if (sscanf(value,"%s %d 0x%04X %n", uuid_str, &ch, &opts, &pos) != 3) - return; - - /* UUID format valid? */ - if (str2uuid(&uuid, uuid_str) < 0) + memset(uuid128, 0, sizeof(uuid128)); + if (sscanf(value,"%s %d 0x%04X %n", uuid128, &ch, &opts, &pos) != 3) return; /* Extracting name */ @@ -1902,7 +1893,7 @@ static void parse_proxy(char *key, char *value, void *data) "/org/bluez/serial/proxy%s", key + pos); str2ba(src_addr, &src); - proxy_register(connection, &src, path, &uuid, key, &ti); + proxy_register(connection, &src, path, uuid128, key, &ti); proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); } -- cgit From 09e64106ebaa80ad5e275bb287809d3ecc33a554 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 16 Aug 2007 17:25:25 +0000 Subject: serial: proxy service record - fixed memory leak --- serial/manager.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 498e2846..9f3fe8d9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1063,10 +1063,12 @@ static int create_proxy_record(sdp_buf_t *buf, const char *uuid128, uint8_t chan ret = sdp_gen_record_pdu(&record, buf); sdp_data_free(ch); - sdp_list_free(proto[0], 0); - sdp_list_free(proto[1], 0); - sdp_list_free(apseq, 0); - sdp_list_free(aproto, 0); + sdp_list_free(proto[0], NULL); + sdp_list_free(proto[1], NULL); + sdp_list_free(apseq, NULL); + sdp_list_free(aproto, NULL); + sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free); + sdp_list_free(record.pattern, free); return ret; -- cgit From 193d3073f6a6a69810c23dd17cd12d3f0504d4be Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 16 Aug 2007 18:06:18 +0000 Subject: Small header cleanup --- serial/error.c | 3 +++ serial/error.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/error.c b/serial/error.c index ba894992..7db33086 100644 --- a/serial/error.c +++ b/serial/error.c @@ -25,6 +25,9 @@ #include #endif +#include + +#include "dbus.h" #include "error.h" #define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" diff --git a/serial/error.h b/serial/error.h index f12602fb..5bb02bd0 100644 --- a/serial/error.h +++ b/serial/error.h @@ -21,8 +21,6 @@ * */ -#include - DBusHandlerResult err_connection_canceled(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult err_connection_failed(DBusConnection *conn, -- cgit From bcd8170e936963a81df3115558bf4a16962dc70b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 16 Aug 2007 22:00:50 +0000 Subject: serial: added Proxy.SetSerialParams --- serial/manager.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++- serial/serial-api.txt | 11 +++- 2 files changed, 160 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 9f3fe8d9..9043cc0c 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1226,6 +1226,10 @@ static gboolean connect_event(GIOChannel *chan, return TRUE; } + if (tcsetattr(tty_sk, TCSANOW, &prx->proxy_ti) < 0) + error("Can't change serial settings: %s(%d)", + strerror(errno), errno); + node_io = g_io_channel_unix_new(nsk); g_io_channel_set_close_on_unref(node_io, TRUE); tty_io = g_io_channel_unix_new(tty_sk); @@ -1374,10 +1378,153 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, return send_message_and_unref(conn, reply); } +static struct { + const char *str; + speed_t speed; +} supported_speed[] = { + {"50", B50 }, + {"300", B300 }, + {"600", B600 }, + {"1200", B1200 }, + {"1800", B1800 }, + {"2400", B2400 }, + {"4800", B4800 }, + {"9600", B9600 }, + {"19200", B19200 }, + {"38400", B38400 }, + {"57600", B57600 }, + {"115200", B115200 }, + { NULL, B0 } +}; + +static speed_t str2speed(const char *str, speed_t *speed) +{ + int i; + + for (i = 0; supported_speed[i].str; i++) { + if (strcmp(supported_speed[i].str, str) != 0) + continue; + + if (speed) + *speed = supported_speed[i].speed; + + return supported_speed[i].speed; + } + + return B0; +} + +static int set_parity(const char *str, tcflag_t *ctrl) +{ + if (strcasecmp("even", str) == 0) { + *ctrl |= PARENB; + *ctrl &= ~PARODD; + } else if (strcasecmp("odd", str) == 0) { + *ctrl |= PARENB; + *ctrl |= PARODD; + } else if (strcasecmp("mark", str) == 0) + *ctrl |= PARENB; + else if ((strcasecmp("none", str) == 0) || + (strcasecmp("space", str) == 0)) + *ctrl &= ~PARENB; + else + return -1; + + return 0; +} + +static int set_databits(uint8_t databits, tcflag_t *ctrl) +{ + if (databits < 5 || databits > 8) + return -EINVAL; + + *ctrl &= ~CSIZE; + switch (databits) { + case 5: + *ctrl |= CS5; + break; + case 6: + *ctrl |= CS6; + break; + case 7: + *ctrl |= CS7; + break; + case 8: + *ctrl |= CS8; + break; + } + + return 0; +} + +static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl) +{ + /* 1.5 will not be allowed */ + switch (stopbits) { + case 1: + *ctrl &= ~CSTOPB; + return 0; + case 2: + *ctrl |= CSTOPB; + return 0; + } + + return -EINVAL; +} + +static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusError derr; + struct proxy *prx = data; + const char *ratestr, *paritystr; + uint8_t databits, stopbits; + tcflag_t ctrl; /* Control mode flags */ + speed_t speed = B0; /* In/Out speed */ + + /* Don't allow change TTY settings if it is open */ + if (prx->tty_watch) + return err_failed(conn, msg, "Not allowed"); + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &ratestr, + DBUS_TYPE_BYTE, &databits, + DBUS_TYPE_BYTE, &stopbits, + DBUS_TYPE_STRING, &paritystr, + DBUS_TYPE_INVALID)) { + err_invalid_args(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (str2speed(ratestr, &speed) == B0) + return err_invalid_args(conn, msg, "Invalid baud rate"); + + ctrl = prx->proxy_ti.c_cflag; + if (set_databits(databits, &ctrl) < 0) + return err_invalid_args(conn, msg, "Invalid data bits"); + + if (set_stopbits(stopbits, &ctrl) < 0) + return err_invalid_args(conn, msg, "Invalid stop bits"); + + if (set_parity(paritystr, &ctrl) < 0) + return err_invalid_args(conn, msg, "Invalid parity"); + + prx->proxy_ti.c_cflag = ctrl; + prx->proxy_ti.c_cflag |= (CLOCAL | CREAD); + cfsetispeed(&prx->proxy_ti, speed); + cfsetospeed(&prx->proxy_ti, speed); + + return send_message_and_unref(conn, + dbus_message_new_method_return(msg)); +} + static DBusMethodVTable proxy_methods[] = { - { "Enable", proxy_enable, "", "" }, - { "Disable", proxy_disable, "", "" }, - { "GetInfo", proxy_get_info, "", "{sv}" }, + { "Enable", proxy_enable, "", "" }, + { "Disable", proxy_disable, "", "" }, + { "GetInfo", proxy_get_info, "", "{sv}" }, + { "SetSerialParams", proxy_set_serial_params, "syys", "" }, { NULL, NULL, NULL, NULL }, }; diff --git a/serial/serial-api.txt b/serial/serial-api.txt index b02786e7..70e8983f 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -118,5 +118,14 @@ Methods: string Enable() [experimental] Unregister the service record and stop listenning. - String GetInfo() [experimental] + string GetInfo() [experimental] Returns the proxy properties + + void SetSerialParams(string rate, byte databits, + byte stopbits, string parity) [experimental] + + Change the TTY settings. Available rates: "50", "300", + "600", "1200", "1800", "2400", "4800", "9600", "19200", + "38400", "57600" and "115200". Available data bits: 5, + 6, 7 and 8. Available stop bits: 1 and 2. Available + parity: "even", "odd", "mark", "space" and "none". -- cgit From 1f42e9d93329e035215b9ec1394941599318528a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 17 Aug 2007 14:21:32 +0000 Subject: serial: proxy cleanup - it is not necessary apply the TTY settings at proxy registration --- serial/manager.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 9043cc0c..15e0fca8 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1577,16 +1577,14 @@ static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, memset(&sys_ti, 0, sizeof(sys_ti)); tcgetattr(sk, &sys_ti); memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti)); - if (!ti) { - /* Keep the current settings */ + close(sk); + + if (!ti) + /* Use current settings */ memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti)); - } else { + else /* New TTY settings: user provided */ memcpy(&prx->proxy_ti, ti, sizeof(*ti)); - tcsetattr(sk, TCSANOW, ti); - } - - close(sk); if (!dbus_connection_register_interface(conn, path, SERIAL_PROXY_INTERFACE, -- cgit From 26c787542c3949e2b64564ce84c3f52761b275d1 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 22 Aug 2007 15:01:52 +0000 Subject: serial: added proxy for unix sockets --- serial/manager.c | 374 +++++++++++++++++++++++++++++++++++--------------- serial/serial-api.txt | 8 +- serial/storage.c | 4 + 3 files changed, 273 insertions(+), 113 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 15e0fca8..ace402b5 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -103,18 +104,25 @@ static struct { { NULL } }; +typedef enum { + TTY_PROXY, + UNIX_SOCKET_PROXY, + UNKNOWN_PROXY_TYPE = 0xFF +} proxy_type_t; + struct proxy { bdaddr_t src; bdaddr_t dst; char *uuid128; /* UUID 128 */ - char *tty; /* TTY name */ + char *address; /* TTY or Unix socket name */ + proxy_type_t type; /* TTY or Unix socket */ struct termios sys_ti; /* Default TTY setting */ struct termios proxy_ti; /* Proxy TTY settings */ uint8_t channel; /* RFCOMM channel */ uint32_t record_id; /* Service record id */ guint listen_watch; /* Server listen watch */ - guint rfcomm_watch; /* RFCOMM connection watch */ - guint tty_watch; /* Openned TTY watch */ + guint rfcomm_watch; /* RFCOMM watch: Remote */ + guint local_watch; /* Local watch: TTY or Unix socket */ }; static DBusConnection *connection = NULL; @@ -122,13 +130,12 @@ static GSList *pending_connects = NULL; static GSList *ports_paths = NULL; static GSList *proxies_paths = NULL; static int rfcomm_ctl = -1; +static int sk_counter = 0; static void proxy_free(struct proxy *prx) { - if (prx->tty) - g_free(prx->tty); - if (prx->uuid128) - g_free(prx->uuid128); + g_free(prx->address); + g_free(prx->uuid128); g_free(prx); } @@ -1190,14 +1197,76 @@ static int remove_proxy_record(DBusConnection *conn, uint32_t rec_id) return 0; } +static inline int unix_socket_connect(const char *address) +{ + struct sockaddr_un addr; + int err, sk; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = PF_UNIX; + + if (strncmp("x00", address, 3) == 0) { + /* + * Abstract namespace: first byte NULL, x00 + * must be removed from the original address. + */ + strcpy(addr.sun_path + 1, address + 3); + } else { + /* Filesystem address */ + strcpy(addr.sun_path, address); + } + + /* Unix socket */ + sk = socket(AF_UNIX, SOCK_STREAM, 0); + if (sk < 0) { + err = errno; + error("Can't create socket %s: %s(%d)", + address, strerror(err), err); + return -err; + } + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + error("Unable to connect %s(%d)", strerror(err), err); + close(sk); + errno = err; + return -err; + } + + return sk; +} + +static inline int tty_open(const char *tty, struct termios *ti) +{ + int err, sk; + + sk = open(tty, O_RDWR | O_NOCTTY); + if (sk < 0) { + err = errno; + error("Can't open TTY %s: %s(%d)", tty, strerror(err), err); + return -err; + } + + if (ti && tcsetattr(sk, TCSANOW, ti) < 0) { + err = errno; + error("Can't change serial settings: %s(%d)", + strerror(err), err); + close(sk); + errno = err; + return -err; + } + + return sk; +} + static gboolean connect_event(GIOChannel *chan, GIOCondition cond, gpointer data) { struct proxy *prx = data; struct sockaddr_rc raddr; - GIOChannel *node_io, *tty_io; + GIOChannel *rio, *lio; socklen_t alen; - int sk, nsk, tty_sk; + int sk, rsk, lsk; if (cond & G_IO_NVAL) return FALSE; @@ -1211,40 +1280,37 @@ static gboolean connect_event(GIOChannel *chan, memset(&raddr, 0, sizeof(raddr)); alen = sizeof(raddr); - nsk = accept(sk, (struct sockaddr *) &raddr, &alen); - if (nsk < 0) + rsk = accept(sk, (struct sockaddr *) &raddr, &alen); + if (rsk < 0) return TRUE; bacpy(&prx->dst, &raddr.rc_bdaddr); - /* TTY open */ - tty_sk = open(prx->tty, O_RDWR | O_NOCTTY); - if (tty_sk < 0) { - error("Unable to open %s: %s(%d)", - prx->tty, strerror(errno), errno); - close(nsk); + if (prx->type == UNIX_SOCKET_PROXY) + lsk = unix_socket_connect(prx->address); + else + lsk = tty_open(prx->address, &prx->proxy_ti); + + if (lsk < 0) { + close(rsk); return TRUE; } - if (tcsetattr(tty_sk, TCSANOW, &prx->proxy_ti) < 0) - error("Can't change serial settings: %s(%d)", - strerror(errno), errno); + rio = g_io_channel_unix_new(rsk); + g_io_channel_set_close_on_unref(rio, TRUE); + lio = g_io_channel_unix_new(lsk); + g_io_channel_set_close_on_unref(lio, TRUE); - node_io = g_io_channel_unix_new(nsk); - g_io_channel_set_close_on_unref(node_io, TRUE); - tty_io = g_io_channel_unix_new(tty_sk); - g_io_channel_set_close_on_unref(tty_io, TRUE); - - prx->rfcomm_watch = g_io_add_watch(node_io, + prx->rfcomm_watch = g_io_add_watch(rio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - forward_data, tty_io); + forward_data, lio); - prx->tty_watch = g_io_add_watch(tty_io, + prx->local_watch = g_io_add_watch(lio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - forward_data, node_io); + forward_data, rio); - g_io_channel_unref(node_io); - g_io_channel_unref(tty_io); + g_io_channel_unref(rio); + g_io_channel_unref(lio); return TRUE; } @@ -1260,9 +1326,9 @@ static void listen_watch_notify(gpointer data) prx->rfcomm_watch = 0; } - if (prx->tty_watch) { - g_source_remove(prx->tty_watch); - prx->tty_watch = 0; + if (prx->local_watch) { + g_source_remove(prx->local_watch); + prx->local_watch = 0; } remove_proxy_record(connection, prx->record_id); @@ -1348,8 +1414,8 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, dbus_message_iter_append_dict_entry(&dict, "uuid", DBUS_TYPE_STRING, &prx->uuid128); - dbus_message_iter_append_dict_entry(&dict, "tty", - DBUS_TYPE_STRING, &prx->tty); + dbus_message_iter_append_dict_entry(&dict, "address", + DBUS_TYPE_STRING, &prx->address); if (prx->channel) dbus_message_iter_append_dict_entry(&dict, "channel", @@ -1483,7 +1549,7 @@ static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, speed_t speed = B0; /* In/Out speed */ /* Don't allow change TTY settings if it is open */ - if (prx->tty_watch) + if (prx->local_watch) return err_failed(conn, msg, "Not allowed"); dbus_error_init(&derr); @@ -1533,94 +1599,169 @@ static void proxy_handler_unregister(DBusConnection *conn, void *data) struct proxy *prx = data; int sk; - info("Unregistered proxy: %s", prx->tty); + info("Unregistered proxy: %s", prx->address); + + if (prx->type != TTY_PROXY) + goto done; /* Restore the initial TTY configuration */ - sk = open(prx->tty, O_RDWR | O_NOCTTY); + sk = open(prx->address, O_RDWR | O_NOCTTY); if (sk) { tcsetattr(sk, TCSAFLUSH, &prx->sys_ti); close(sk); } +done: if (prx->listen_watch) g_source_remove(prx->listen_watch); proxy_free(prx); } -static int proxy_register(DBusConnection *conn, bdaddr_t *src, const char *path, - const char *uuid128, const char *tty, struct termios *ti) +static int register_proxy_object(struct proxy *prx, char *outpath, size_t size) +{ + char path[MAX_PATH_LENGTH + 1]; + const char *ppath = path; + + snprintf(path, MAX_PATH_LENGTH, "/org/bluez/serial/proxy%d", + sk_counter++); + + if (!dbus_connection_create_object_path(connection, path, prx, + proxy_handler_unregister)) { + error("D-Bus failed to register %s path", path); + return -1; + } + + dbus_connection_register_interface(connection, path, + SERIAL_PROXY_INTERFACE, proxy_methods, NULL, NULL); + + dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "ProxyCreated", + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + + proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); + + if (outpath) + strncpy(outpath, path, size); + + info("Registered proxy:%s", path); + + return 0; +} + +static int proxy_tty_register(bdaddr_t *src, const char *uuid128, + const char *address, struct termios *ti, char *outpath, size_t size) { struct termios sys_ti; struct proxy *prx; - int sk; + int sk, ret; - sk = open(tty, O_RDWR | O_NOCTTY); + sk = open(address, O_RDONLY | O_NOCTTY); if (sk < 0) { error("Cant open TTY: %s(%d)", strerror(errno), errno); return -EINVAL; } prx = g_new0(struct proxy, 1); - prx->tty = g_strdup(tty); + prx->address = g_strdup(address); prx->uuid128 = g_strdup(uuid128); + prx->type = TTY_PROXY; bacpy(&prx->src, src); - if (!dbus_connection_create_object_path(conn, path, prx, - proxy_handler_unregister)) { - proxy_free(prx); - close(sk); - return -1; - } - /* Current TTY settings */ memset(&sys_ti, 0, sizeof(sys_ti)); tcgetattr(sk, &sys_ti); memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti)); close(sk); - if (!ti) + if (!ti) { /* Use current settings */ memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti)); - else + } else { /* New TTY settings: user provided */ memcpy(&prx->proxy_ti, ti, sizeof(*ti)); + } - if (!dbus_connection_register_interface(conn, path, - SERIAL_PROXY_INTERFACE, - proxy_methods, - NULL, NULL)) { - dbus_connection_destroy_object_path(conn, path); - return -1; + ret = register_proxy_object(prx, outpath, size); + if (ret < 0) + proxy_free(prx); + + return ret; +} + +static int proxy_socket_register(bdaddr_t *src, const char *uuid128, + const char *address, char *outpath, size_t size) +{ + struct proxy *prx; + int ret; + + prx = g_new0(struct proxy, 1); + prx->address = g_strdup(address); + prx->uuid128 = g_strdup(uuid128); + prx->type = UNIX_SOCKET_PROXY; + bacpy(&prx->src, src); + + ret = register_proxy_object(prx, outpath, size); + if (ret < 0) + proxy_free(prx); + + return ret; +} + +static proxy_type_t addr2type(const char *address) +{ + struct stat st; + + if (stat(address, &st) < 0) { + /* + * Unix socket: if the sun_path starts with null byte + * it refers to abstract namespace. 'x00' will be used + * to represent the null byte. + */ + if (strncmp("x00", address, 3) != 0) + return UNKNOWN_PROXY_TYPE; + else + return UNIX_SOCKET_PROXY; + } else { + /* Filesystem: char device or unix socket */ + if (S_ISCHR(st.st_mode) && strncmp("/dev/", address, 4) == 0) + return TTY_PROXY; + else if (S_ISSOCK(st.st_mode)) + return UNIX_SOCKET_PROXY; + else + return UNKNOWN_PROXY_TYPE; } +} - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ProxyCreated", - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); +static int proxycmp(const char *path, const char *address) +{ + struct proxy *prx = NULL; - info("Registered proxy:%s path:%s", tty, path); + if (!dbus_connection_get_object_user_data(connection, + path, (void *) &prx) || !prx) + return -1; - return 0; + return strcmp(prx->address, address); } static DBusHandlerResult create_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { - char path[MAX_PATH_LENGTH]; - const char *uuid128, *tty, *ppath = path; + char path[MAX_PATH_LENGTH + 1]; + const char *uuid128, *address, *ppath = path; DBusMessage *reply; + proxy_type_t type; GSList *l; DBusError derr; - struct stat st; bdaddr_t src; uuid_t uuid; - int dev_id, pos = 0; + int dev_id, ret; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &uuid128, - DBUS_TYPE_STRING, &tty, + DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) { err_invalid_args(conn, msg, derr.message); dbus_error_free(&derr); @@ -1630,14 +1771,12 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (str2uuid(&uuid, uuid128) < 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); + type = addr2type(address); + if (type == UNKNOWN_PROXY_TYPE) + return err_invalid_args(conn, msg, "Invalid address"); - l = g_slist_find_custom(proxies_paths, path, (GCompareFunc) strcmp); + /* Only one proxy per address(TTY or unix socket) is allowed */ + l = g_slist_find_custom(proxies_paths, address, (GCompareFunc) proxycmp); if (l) return err_already_exists(conn, msg, "Proxy already exists"); @@ -1651,13 +1790,18 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (proxy_register(conn, &src, path, uuid128, tty, NULL) < 0) { + if (type != TTY_PROXY) + ret = proxy_socket_register(&src, uuid128, + address, path, sizeof(path)); + else + ret = proxy_tty_register(&src, uuid128, + address, NULL, path, sizeof(path)); + + if (ret < 0) { dbus_message_unref(reply); return err_failed(conn, msg, "Create object path failed"); } - proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); - dbus_message_append_args(reply, DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); @@ -1703,7 +1847,7 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn, /* Remove from storage */ if (dbus_connection_get_object_user_data(conn, path, (void *) &prx) && prx) - proxy_delete(&prx->src, prx->tty); + proxy_delete(&prx->src, prx->address); g_free(l->data); proxies_paths = g_slist_remove(proxies_paths, l->data); @@ -1892,9 +2036,13 @@ static void proxy_path_free(gpointer data, gpointer udata) /* Store/Update the proxy entries before exit */ if (dbus_connection_get_object_user_data(conn, - path, (void *) &prx) && prx) - proxy_store(&prx->src, prx->uuid128, prx->tty, NULL, - prx->channel, 0, &prx->proxy_ti); + path, (void *) &prx) && prx) { + struct termios *ti; + + ti = (prx->type == TTY_PROXY ? &prx->proxy_ti : NULL); + proxy_store(&prx->src, prx->uuid128, prx->address, NULL, + prx->channel, 0, ti); + } g_free(data); } @@ -1996,14 +2144,16 @@ static void parse_port(char *key, char *value, void *data) static void parse_proxy(char *key, char *value, void *data) { - char path[MAX_PATH_LENGTH], uuid128[MAX_LEN_UUID_STR], tmp[3]; + char uuid128[MAX_LEN_UUID_STR], tmp[3]; char *pvalue, *src_addr = data; - struct termios ti; - int ch, opts, pos = 0; + proxy_type_t type; + int ch, opts, pos; bdaddr_t src; + struct termios ti; uint8_t *pti; memset(uuid128, 0, sizeof(uuid128)); + ch = opts = pos = 0; if (sscanf(value,"%s %d 0x%04X %n", uuid128, &ch, &opts, &pos) != 3) return; @@ -2016,33 +2166,33 @@ static void parse_proxy(char *key, char *value, void *data) /* FIXME: currently name is not used */ *pvalue = '\0'; - /* Extracting termios */ - pvalue++; - if (strlen(pvalue) != (2 * sizeof(ti))) - return; - - memset(&ti, 0, sizeof(ti)); - memset(tmp, 0, sizeof(tmp)); - - /* Converting to termios struct */ - pti = (uint8_t *) &ti; - for (pos = 0; pos < sizeof(ti); pos++, pvalue += 2, pti++) { - memcpy(tmp, pvalue, 2); - *pti = (uint8_t) strtol(tmp, NULL, 16); - } - - pos = 0; - sscanf(key, "/dev/%n", &pos); - if (!pos) - return; - - snprintf(path, MAX_PATH_LENGTH - 1, - "/org/bluez/serial/proxy%s", key + pos); - str2ba(src_addr, &src); - proxy_register(connection, &src, path, uuid128, key, &ti); + type = addr2type(key); + switch (type) { + case TTY_PROXY: + /* Extracting termios */ + pvalue++; + if (!pvalue || strlen(pvalue) != (2 * sizeof(ti))) + return; + + memset(&ti, 0, sizeof(ti)); + memset(tmp, 0, sizeof(tmp)); + + /* Converting to termios struct */ + pti = (uint8_t *) &ti; + for (pos = 0; pos < sizeof(ti); pos++, pvalue += 2, pti++) { + memcpy(tmp, pvalue, 2); + *pti = (uint8_t) strtol(tmp, NULL, 16); + } - proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); + proxy_tty_register(&src, uuid128, key, &ti, NULL, 0); + break; + case UNIX_SOCKET_PROXY: + proxy_socket_register(&src, uuid128, key, NULL, 0); + break; + default: + return; + } } static void register_stored(void) diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 70e8983f..ab0a4a35 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -10,10 +10,16 @@ Manager hierarchy Interface org.bluez.serial.Manager Object path /org/bluez/serial -Methods string CreateProxy(string uuid, string tty) +Methods string CreateProxy(string uuid, string address) Creates a serial port proxy object. + Service identifier must be provided in the uuid 128 + format. Addresses can be TTY char devices or unix + socket address. Abstract namespace can be informed + replacing the null byte by 'x00'. eg: "/dev/ttyS0", + "/tmp/gps-data", "x00/org/bluez/echo". + Possible errors:org.bluez.serial.Error.InvalidArguments org.bluez.serial.NotAvailable org.bluez.serial.Failed diff --git a/serial/storage.c b/serial/storage.c index 641ca1e8..8b66354f 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -121,9 +121,13 @@ int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, /* tty uuid 00 0x0000 name:termios */ pos = snprintf(value, size, "%s %d 0x%04X %s:", uuid, ch, opts, name); + if (!ti) + goto done; + for (i = 0, pti = (uint8_t *) ti; i < sizeof(struct termios); i++, pti++) sprintf(value + pos + (i * 2), "%2.2X", *pti); +done: err = textfile_put(filename, key, value); g_free(value); -- cgit From a3dcbd3ab5d172c2537932ef1e2968140139d176 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 23 Aug 2007 08:25:46 +0000 Subject: Add Port.GetDevice method Rename 'name' dict key to 'device --- serial/port.c | 76 +++++++++++++++++++++++++++++++-------------------- serial/port.h | 6 ++-- serial/serial-api.txt | 4 +++ 3 files changed, 54 insertions(+), 32 deletions(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index c220110c..e4048256 100644 --- a/serial/port.c +++ b/serial/port.c @@ -51,25 +51,25 @@ #define SERIAL_PORT_INTERFACE "org.bluez.serial.Port" struct rfcomm_node { - int16_t id; /* RFCOMM device id */ - bdaddr_t dst; /* Destination address */ - char *name; /* RFCOMM device name */ - DBusConnection *conn; /* for name listener handling */ - char *owner; /* Bus name */ - GIOChannel *io; /* Connected node IO Channel */ - guint io_id; /* IO Channel ID */ + int16_t id; /* RFCOMM device id */ + bdaddr_t dst; /* Destination address */ + char *device; /* RFCOMM device name */ + DBusConnection *conn; /* for name listener handling */ + char *owner; /* Bus name */ + GIOChannel *io; /* Connected node IO Channel */ + guint io_id; /* IO Channel ID */ }; static GSList *connected_nodes = NULL; static GSList *bound_nodes = NULL; -static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *name) +static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *dev) { GSList *l; for (l = nodes; l != NULL; l = l->next) { struct rfcomm_node *node = l->data; - if (!strcmp(node->name, name)) + if (!strcmp(node->device, dev)) return node; } @@ -77,7 +77,7 @@ static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *name) } static DBusHandlerResult port_get_address(DBusConnection *conn, - DBusMessage *msg, void *data) + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; @@ -96,6 +96,23 @@ static DBusHandlerResult port_get_address(DBusConnection *conn, } +static DBusHandlerResult port_get_device(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct rfcomm_node *node = data; + DBusMessage *reply; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &node->device, + DBUS_TYPE_INVALID); + return send_message_and_unref(conn, reply); + +} + static DBusHandlerResult port_get_info(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -116,8 +133,8 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - dbus_message_iter_append_dict_entry(&dict, "name", - DBUS_TYPE_STRING, &node->name); + dbus_message_iter_append_dict_entry(&dict, "device", + DBUS_TYPE_STRING, &node->device); ba2str(&node->dst, bda); dbus_message_iter_append_dict_entry(&dict, "address", @@ -130,6 +147,7 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, static DBusMethodVTable port_methods[] = { { "GetAddress", port_get_address, "", "s" }, + { "GetDevice", port_get_device, "", "s" }, { "GetInfo", port_get_info, "", "{sv}" }, { NULL, NULL, NULL, NULL }, }; @@ -140,8 +158,8 @@ static DBusSignalVTable port_signals[] = { static void rfcomm_node_free(struct rfcomm_node *node) { - if (node->name) - g_free(node->name); + if (node->device) + g_free(node->device); if (node->conn) dbus_connection_unref(node->conn); if (node->owner) @@ -158,11 +176,11 @@ static void rfcomm_node_free(struct rfcomm_node *node) static void connection_owner_exited(const char *name, struct rfcomm_node *node) { debug("Connect requestor %s exited. Releasing %s node", - name, node->name); + name, node->device); dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , - DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_STRING, &node->device, DBUS_TYPE_INVALID); connected_nodes = g_slist_remove(connected_nodes, node); @@ -172,14 +190,14 @@ static void connection_owner_exited(const char *name, struct rfcomm_node *node) static gboolean rfcomm_disconnect_cb(GIOChannel *io, GIOCondition cond, struct rfcomm_node *node) { - debug("RFCOMM node %s was disconnected", node->name); + debug("RFCOMM node %s was disconnected", node->device); name_listener_remove(node->conn, node->owner, (name_cb_t) connection_owner_exited, node); dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , - DBUS_TYPE_STRING, &node->name, + DBUS_TYPE_STRING, &node->device, DBUS_TYPE_INVALID); connected_nodes = g_slist_remove(connected_nodes, node); @@ -192,21 +210,21 @@ static void port_handler_unregister(DBusConnection *conn, void *data) { struct rfcomm_node *node = data; - debug("Unregistered serial port: %s", node->name); + debug("Unregistered serial port: %s", node->device); bound_nodes = g_slist_remove(bound_nodes, node); rfcomm_node_free(node); } int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, - int fd, const char *name, const char *owner) + int fd, const char *dev, const char *owner) { struct rfcomm_node *node; node = g_new0(struct rfcomm_node, 1); bacpy(&node->dst, dst); node->id = id; - node->name = g_strdup(name); + node->device = g_strdup(dev); node->conn = dbus_connection_ref(conn); node->owner = g_strdup(owner); node->io = g_io_channel_unix_new(fd); @@ -220,11 +238,11 @@ int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, (name_cb_t) connection_owner_exited, node); } -int port_remove_listener(const char *owner, const char *name) +int port_remove_listener(const char *owner, const char *dev) { struct rfcomm_node *node; - node = find_node_by_name(connected_nodes, name); + node = find_node_by_name(connected_nodes, dev); if (!node) return -ENOENT; if (strcmp(node->owner, owner) != 0) @@ -240,7 +258,7 @@ int port_remove_listener(const char *owner, const char *name) } int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, - const char *name, char *ppath) + const char *dev, char *ppath) { char path[MAX_PATH_LENGTH]; struct rfcomm_node *node; @@ -248,7 +266,7 @@ int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, node = g_new0(struct rfcomm_node, 1); bacpy(&node->dst, dst); node->id = id; - node->name = g_strdup(name); + node->device = g_strdup(dev); node->conn = dbus_connection_ref(conn); snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%hd", SERIAL_MANAGER_PATH, id); @@ -270,7 +288,7 @@ int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, return -1; } - info("Registered RFCOMM:%s, path:%s", name, path); + info("Registered RFCOMM:%s, path:%s", dev, path); if (ppath) strcpy(ppath, path); @@ -283,14 +301,14 @@ int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, int port_unregister(const char *path) { struct rfcomm_node *node; - char name[16]; + char dev[16]; int16_t id; if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%hd", &id) != 1) return -ENOENT; - snprintf(name, sizeof(name), "/dev/rfcomm%hd", id); - node = find_node_by_name(bound_nodes, name); + snprintf(dev, sizeof(dev), "/dev/rfcomm%hd", id); + node = find_node_by_name(bound_nodes, dev); if (!node) return -ENOENT; diff --git a/serial/port.h b/serial/port.h index 27077925..c0b9073d 100644 --- a/serial/port.h +++ b/serial/port.h @@ -22,11 +22,11 @@ */ int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, - int fd, const char *name, const char *owner); + int fd, const char *dev, const char *owner); -int port_remove_listener(const char *owner, const char *name); +int port_remove_listener(const char *owner, const char *dev); int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, - const char *name, char *ppath); + const char *dev, char *ppath); int port_unregister(const char *path); diff --git a/serial/serial-api.txt b/serial/serial-api.txt index ab0a4a35..f73a6b83 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -106,6 +106,10 @@ Methods string GetAddress() [experimental] Returns the Bluetooth address of the ending point. + string GetDevice() [experimental] + + Returns the TTY device node name + string GetInfo() [experimental] Returns the port properties. -- cgit From 780fdf762ea90956b668d8fd3daff35973a06de7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 23 Aug 2007 08:29:21 +0000 Subject: Rename SetSerialParams to SetSerialParameters --- serial/manager.c | 2 +- serial/serial-api.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index ace402b5..965f1653 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1590,7 +1590,7 @@ static DBusMethodVTable proxy_methods[] = { { "Enable", proxy_enable, "", "" }, { "Disable", proxy_disable, "", "" }, { "GetInfo", proxy_get_info, "", "{sv}" }, - { "SetSerialParams", proxy_set_serial_params, "syys", "" }, + { "SetSerialParameters", proxy_set_serial_params, "syys", "" }, { NULL, NULL, NULL, NULL }, }; diff --git a/serial/serial-api.txt b/serial/serial-api.txt index f73a6b83..5ac7091a 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -131,7 +131,7 @@ Methods: string Enable() [experimental] string GetInfo() [experimental] Returns the proxy properties - void SetSerialParams(string rate, byte databits, + void SetSerialParameters(string rate, byte databits, byte stopbits, string parity) [experimental] Change the TTY settings. Available rates: "50", "300", -- cgit From 8231df5273b8ddca457d08809b6e96ed9df1cf62 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 23 Aug 2007 09:06:05 +0000 Subject: Plug minor memory leak --- serial/manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 965f1653..056ecf5f 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -612,7 +612,7 @@ static int get_record(struct pending_connect *pc, uint32_t handle, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1) == FALSE) { + if (!dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1)) { error("Can't send D-Bus message."); return -1; } @@ -693,6 +693,7 @@ static int get_handles(struct pending_connect *pc, const char *uuid, if (dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1) == FALSE) { error("Can't send D-Bus message."); + dbus_message_unref(msg); return -1; } -- cgit From d4b3c37d8dc33d144559a10fdd826b853b6d11a0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 23 Aug 2007 09:11:35 +0000 Subject: Plug another minor memory leak --- serial/manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 056ecf5f..ee1a7924 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -614,6 +614,7 @@ static int get_record(struct pending_connect *pc, uint32_t handle, if (!dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1)) { error("Can't send D-Bus message."); + dbus_message_unref(msg); return -1; } @@ -691,7 +692,7 @@ static int get_handles(struct pending_connect *pc, const char *uuid, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); - if (dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1) == FALSE) { + if (!dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1)) { error("Can't send D-Bus message."); dbus_message_unref(msg); return -1; -- cgit From b7b6b704e9bef49402fa5df84d5193fc7f64c3af Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 23 Aug 2007 14:54:16 +0000 Subject: serial: forward remaining data when the HUP is received from the source --- serial/manager.c | 59 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index ee1a7924..637a9603 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1080,7 +1080,29 @@ static int create_proxy_record(sdp_buf_t *buf, const char *uuid128, uint8_t chan sdp_list_free(record.pattern, free); return ret; +} + +static GIOError channel_write(GIOChannel *chan, char *buf, size_t size) +{ + GIOError err = G_IO_ERROR_NONE; + gsize wbytes, written; + wbytes = written = 0; + while (wbytes < size) { + err = g_io_channel_write(chan, + buf + wbytes, + size - wbytes, + &written); + + if (err != G_IO_ERROR_NONE) + return err; + + wbytes += written; + } + + g_io_channel_flush(chan, NULL); + + return err; } static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data) @@ -1088,32 +1110,34 @@ static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data) char buf[BUF_SIZE]; GIOChannel *dest = data; GIOError err; - gsize rbytes, wbytes, written; + size_t rbytes; if (cond & G_IO_NVAL) return FALSE; if (cond & (G_IO_HUP | G_IO_ERR)) { + /* Try forward remaining data */ + do { + rbytes = 0; + err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes); + if (err != G_IO_ERROR_NONE || rbytes == 0) + break; + + err = channel_write(dest, buf, rbytes); + } while (err == G_IO_ERROR_NONE); + g_io_channel_close(dest); return FALSE; } - memset(buf, 0, sizeof(buf)); - rbytes = wbytes = written = 0; - - err = g_io_channel_read(chan, buf, sizeof(buf) - 1, &rbytes); + rbytes = 0; + err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes); if (err != G_IO_ERROR_NONE) - return TRUE; + return FALSE; - while (wbytes < rbytes) { - err = g_io_channel_write(dest, - buf + wbytes, - rbytes - wbytes, - &written); - if (err != G_IO_ERROR_NONE) - break; - wbytes += written; - } + err = channel_write(dest, buf, rbytes); + if (err != G_IO_ERROR_NONE) + return FALSE; return TRUE; } @@ -1222,14 +1246,15 @@ static inline int unix_socket_connect(const char *address) sk = socket(AF_UNIX, SOCK_STREAM, 0); if (sk < 0) { err = errno; - error("Can't create socket %s: %s(%d)", + error("Unix socket(%s) create failed: %s(%d)", address, strerror(err), err); return -err; } if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { err = errno; - error("Unable to connect %s(%d)", strerror(err), err); + error("Unix socket(%s) connect failed: %s(%d)", + address, strerror(err), err); close(sk); errno = err; return -err; -- cgit From 22e31062ad9458a148a4e4203fb3aed43e65dfa4 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 27 Aug 2007 13:34:47 +0000 Subject: serial: don't send ProxyCreated signal when the daemon starts --- serial/manager.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 637a9603..7a489c7f 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1648,7 +1648,6 @@ done: static int register_proxy_object(struct proxy *prx, char *outpath, size_t size) { char path[MAX_PATH_LENGTH + 1]; - const char *ppath = path; snprintf(path, MAX_PATH_LENGTH, "/org/bluez/serial/proxy%d", sk_counter++); @@ -1661,12 +1660,6 @@ static int register_proxy_object(struct proxy *prx, char *outpath, size_t size) dbus_connection_register_interface(connection, path, SERIAL_PROXY_INTERFACE, proxy_methods, NULL, NULL); - - dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "ProxyCreated", - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); if (outpath) @@ -1829,6 +1822,11 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, return err_failed(conn, msg, "Create object path failed"); } + dbus_connection_emit_signal(connection, 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); -- cgit From 6d146609b5f7e47d312c5b4edfd8db55e8f2aa55 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 27 Aug 2007 21:58:09 +0000 Subject: serial: removed useless call and it is not implemented on eglib --- serial/manager.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 7a489c7f..bb46d35c 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1100,8 +1100,6 @@ static GIOError channel_write(GIOChannel *chan, char *buf, size_t size) wbytes += written; } - g_io_channel_flush(chan, NULL); - return err; } -- cgit From 176c7e84d9db737cb58a381449799b13ef7b3fb4 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 24 Sep 2007 23:36:21 +0000 Subject: serial - RemovePort: remove path from ports_paths --- serial/manager.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index bb46d35c..36af5523 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -897,6 +897,7 @@ static DBusHandlerResult remove_port(DBusConnection *conn, struct rfcomm_dev_info di; DBusError derr; const char *path; + GSList *l; int16_t id; dbus_error_init(&derr); @@ -927,6 +928,12 @@ static DBusHandlerResult remove_port(DBusConnection *conn, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); + l = g_slist_find_custom(ports_paths, path, (GCompareFunc) strcmp); + if (l) { + g_free(l->data); + ports_paths = g_slist_remove(ports_paths, l->data); + } + return DBUS_HANDLER_RESULT_HANDLED; } -- cgit From 09200aea99bdd29fb0f75b67162fbd958ef5df99 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 24 Sep 2007 23:43:32 +0000 Subject: serial - allow up to 3 digits channel number --- serial/storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/storage.c b/serial/storage.c index 8b66354f..110d8de7 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -75,7 +75,7 @@ int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "serial"); create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - size = strlen(svcname) + 3; + size = strlen(svcname) + 5; value = g_malloc0(size); snprintf(key, 32, "%s#%hd", dst_addr, id); -- cgit From 4c18c3e4ffbd0bb6eeb7d0933acadc2f8200587b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 26 Sep 2007 13:58:19 +0000 Subject: serial: Added GetName and GetAdapter --- serial/manager.c | 6 +++--- serial/port.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++--- serial/port.h | 4 ++-- serial/serial-api.txt | 10 ++++++++- serial/storage.c | 35 ++++++++++++++++++++++++++++++ serial/storage.h | 1 + 6 files changed, 106 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 36af5523..371c8a95 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -562,7 +562,7 @@ static void record_reply(DBusPendingCall *call, void *data) if (svcname) g_free(svcname); - port_register(pc->conn, err, &dst, port_name, path); + port_register(pc->conn, err, &pc->src, &dst, port_name, path); ports_paths = g_slist_append(ports_paths, g_strdup(path)); reply = dbus_message_new_method_return(pc->msg); @@ -840,7 +840,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); port_store(&src, &dst, err, val, NULL); - port_register(conn, err, &dst, port_name, path); + port_register(conn, err, &src, &dst, port_name, path); ports_paths = g_slist_append(ports_paths, g_strdup(path)); reply = dbus_message_new_method_return(msg); @@ -2164,7 +2164,7 @@ static void parse_port(char *key, char *value, void *data) snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", id); - if (port_register(connection, id, &dst, port_name, path) < 0) { + if (port_register(connection, id, &src, &dst, port_name, path) < 0) { rfcomm_release(id); return; } diff --git a/serial/port.c b/serial/port.c index e4048256..70e0afb4 100644 --- a/serial/port.c +++ b/serial/port.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -46,12 +47,13 @@ #include "error.h" #include "manager.h" -#include "port.h" +#include "storage.h" #define SERIAL_PORT_INTERFACE "org.bluez.serial.Port" struct rfcomm_node { int16_t id; /* RFCOMM device id */ + bdaddr_t src; /* Source (local) address */ bdaddr_t dst; /* Destination address */ char *device; /* RFCOMM device name */ DBusConnection *conn; /* for name listener handling */ @@ -113,6 +115,54 @@ static DBusHandlerResult port_get_device(DBusConnection *conn, } +static DBusHandlerResult port_get_adapter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct rfcomm_node *node = data; + DBusMessage *reply; + char addr[18]; + const char *paddr = addr; + + ba2str(&node->src, addr); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &paddr, + DBUS_TYPE_INVALID); + + return send_message_and_unref(conn, reply); +} + + +static DBusHandlerResult port_get_name(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct rfcomm_node *node = data; + DBusMessage *reply; + const char *pname; + char *name = NULL; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + read_device_name(&node->src, &node->dst, &name); + + pname = (name ? name : ""); + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &pname, + DBUS_TYPE_INVALID); + + if (name) + g_free(name); + + return send_message_and_unref(conn, reply); +} + + static DBusHandlerResult port_get_info(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -148,6 +198,8 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, static DBusMethodVTable port_methods[] = { { "GetAddress", port_get_address, "", "s" }, { "GetDevice", port_get_device, "", "s" }, + { "GetAdapter", port_get_adapter, "", "s" }, + { "GetName", port_get_name, "", "s" }, { "GetInfo", port_get_info, "", "{sv}" }, { NULL, NULL, NULL, NULL }, }; @@ -257,14 +309,15 @@ int port_remove_listener(const char *owner, const char *dev) return 0; } -int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, - const char *dev, char *ppath) +int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, + bdaddr_t *dst, const char *dev, char *ppath) { char path[MAX_PATH_LENGTH]; struct rfcomm_node *node; node = g_new0(struct rfcomm_node, 1); bacpy(&node->dst, dst); + bacpy(&node->src, src); node->id = id; node->device = g_strdup(dev); node->conn = dbus_connection_ref(conn); diff --git a/serial/port.h b/serial/port.h index c0b9073d..5935bef3 100644 --- a/serial/port.h +++ b/serial/port.h @@ -26,7 +26,7 @@ int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, int port_remove_listener(const char *owner, const char *dev); -int port_register(DBusConnection *conn, int16_t id, bdaddr_t *dst, - const char *dev, char *ppath); +int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, + bdaddr_t *dst, const char *dev, char *ppath); int port_unregister(const char *path); diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 5ac7091a..20a94e51 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -102,7 +102,11 @@ Port hierarchy (experimental) Interface org.bluez.serial.Port Object path /org/bluez/serial/rfcomm* -Methods string GetAddress() [experimental] +Methods string GetAdapter() [experimental] + + Returns the adapter address. + + string GetAddress() [experimental] Returns the Bluetooth address of the ending point. @@ -114,6 +118,10 @@ Methods string GetAddress() [experimental] Returns the port properties. + string GetName() + + Returns the name of the remote device. + Proxy hierarchy (experimental) ============================= Interface org.bluez.serial.Proxy diff --git a/serial/storage.c b/serial/storage.c index 110d8de7..6ea3eb41 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -25,6 +25,7 @@ #include #endif +#include #include #include #include @@ -133,3 +134,37 @@ done: return err; } + +int read_device_name(bdaddr_t *src, bdaddr_t *dst, char **name) +{ + char filename[PATH_MAX + 1], *str; + char src_addr[18], dst_addr[18]; + int len; + + ba2str(src, src_addr); + ba2str(dst, dst_addr); + + create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "names"); + + str = textfile_get(filename, dst_addr); + if (!str) + return -ENOENT; + + len = strlen(str); + + /* Max remote device name */ + if (len < 248) { + *name = str; + return 0; + } + + *name = g_try_malloc0(248); + if (!*name) + return -ENOMEM; + + snprintf(*name, 248, "%s", str); + + free(str); + + return 0; +} diff --git a/serial/storage.h b/serial/storage.h index 4a24bdf7..271ae722 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -27,3 +27,4 @@ int port_store(bdaddr_t *src, bdaddr_t *dst, int16_t id, int proxy_delete(bdaddr_t *src, const char *tty); int proxy_store(bdaddr_t *src, const char *uuid, const char *tty, const char *name, uint8_t ch, int opts, struct termios *ti); +int read_device_name(bdaddr_t *src, bdaddr_t *dst, char **name); -- cgit From ff57b7e4bafc2437d7ef147044b24835f3a4f4d2 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 26 Sep 2007 15:05:37 +0000 Subject: serial: Added GetServiceName --- serial/manager.c | 15 +++++++++++---- serial/port.c | 32 ++++++++++++++++++++++++++------ serial/port.h | 2 +- serial/serial-api.txt | 5 +++++ 4 files changed, 43 insertions(+), 11 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 371c8a95..378434e4 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -559,10 +559,12 @@ static void record_reply(DBusPendingCall *call, void *data) } port_store(&pc->src, &dst, err, ch, svcname); + + port_register(pc->conn, err, &pc->src, &dst, port_name, + path, svcname); if (svcname) g_free(svcname); - port_register(pc->conn, err, &pc->src, &dst, port_name, path); ports_paths = g_slist_append(ports_paths, g_strdup(path)); reply = dbus_message_new_method_return(pc->msg); @@ -840,7 +842,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); port_store(&src, &dst, err, val, NULL); - port_register(conn, err, &src, &dst, port_name, path); + port_register(conn, err, &src, &dst, port_name, path, NULL); ports_paths = g_slist_append(ports_paths, g_strdup(path)); reply = dbus_message_new_method_return(msg); @@ -2144,7 +2146,7 @@ static DBusSignalVTable manager_signals[] = { static void parse_port(char *key, char *value, void *data) { - char path[MAX_PATH_LENGTH], port_name[16], dst_addr[18]; + char path[MAX_PATH_LENGTH], port_name[16], dst_addr[18], *svc; char *src_addr = data; bdaddr_t dst, src; int ch, id; @@ -2156,6 +2158,10 @@ static void parse_port(char *key, char *value, void *data) if (sscanf(value,"%d:", &ch) != 1) return; + svc = strchr(value, ':'); + if (svc && *svc) + svc++; + str2ba(dst_addr, &dst); str2ba(src_addr, &src); @@ -2164,7 +2170,8 @@ static void parse_port(char *key, char *value, void *data) snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", id); - if (port_register(connection, id, &src, &dst, port_name, path) < 0) { + if (port_register(connection, id, &src, &dst, + port_name, path, svc) < 0) { rfcomm_release(id); return; } diff --git a/serial/port.c b/serial/port.c index 70e0afb4..30b1412e 100644 --- a/serial/port.c +++ b/serial/port.c @@ -55,6 +55,7 @@ struct rfcomm_node { int16_t id; /* RFCOMM device id */ bdaddr_t src; /* Source (local) address */ bdaddr_t dst; /* Destination address */ + char *svcname; /* RFCOMM service name */ char *device; /* RFCOMM device name */ DBusConnection *conn; /* for name listener handling */ char *owner; /* Bus name */ @@ -162,6 +163,21 @@ static DBusHandlerResult port_get_name(DBusConnection *conn, return send_message_and_unref(conn, reply); } +static DBusHandlerResult port_get_service_name(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct rfcomm_node *node = data; + DBusMessage *reply; + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &node->svcname, + DBUS_TYPE_INVALID); + return send_message_and_unref(conn, reply); +} static DBusHandlerResult port_get_info(DBusConnection *conn, DBusMessage *msg, void *data) @@ -196,11 +212,12 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, } static DBusMethodVTable port_methods[] = { - { "GetAddress", port_get_address, "", "s" }, - { "GetDevice", port_get_device, "", "s" }, - { "GetAdapter", port_get_adapter, "", "s" }, - { "GetName", port_get_name, "", "s" }, - { "GetInfo", port_get_info, "", "{sv}" }, + { "GetAddress", port_get_address, "", "s" }, + { "GetDevice", port_get_device, "", "s" }, + { "GetAdapter", port_get_adapter, "", "s" }, + { "GetName", port_get_name, "", "s" }, + { "GetServiceName", port_get_service_name, "", "s" }, + { "GetInfo", port_get_info, "", "{sv}" }, { NULL, NULL, NULL, NULL }, }; @@ -216,6 +233,8 @@ static void rfcomm_node_free(struct rfcomm_node *node) dbus_connection_unref(node->conn); if (node->owner) g_free(node->owner); + if (node->svcname) + g_free(node->svcname); if (node->io) { g_source_remove(node->io_id); g_io_channel_close(node->io); @@ -310,7 +329,7 @@ int port_remove_listener(const char *owner, const char *dev) } int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, - bdaddr_t *dst, const char *dev, char *ppath) + bdaddr_t *dst, const char *dev, char *ppath, const char *svc) { char path[MAX_PATH_LENGTH]; struct rfcomm_node *node; @@ -321,6 +340,7 @@ int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, node->id = id; node->device = g_strdup(dev); node->conn = dbus_connection_ref(conn); + node->svcname = g_strdup(svc?:"Bluetooth RFCOMM port"); snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%hd", SERIAL_MANAGER_PATH, id); diff --git a/serial/port.h b/serial/port.h index 5935bef3..ad6f4fa8 100644 --- a/serial/port.h +++ b/serial/port.h @@ -27,6 +27,6 @@ int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, int port_remove_listener(const char *owner, const char *dev); int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, - bdaddr_t *dst, const char *dev, char *ppath); + bdaddr_t *dst, const char *dev, char *ppath, const char *svc); int port_unregister(const char *path); diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 20a94e51..e8431ded 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -122,6 +122,11 @@ Methods string GetAdapter() [experimental] Returns the name of the remote device. + string GetServiceName() + + Returns the name of the remote service. + e.g.: "Dial-up networking Gateway" + Proxy hierarchy (experimental) ============================= Interface org.bluez.serial.Proxy -- cgit From 76a68c90d5d03c4e037ef00562e0fa907fdccf92 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 1 Oct 2007 11:49:40 +0000 Subject: serial: fixed get_handles pending call leak --- serial/manager.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 378434e4..ec06ac0e 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -614,6 +614,12 @@ static int get_record(struct pending_connect *pc, uint32_t handle, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID); + /* Unref get_handles pending call */ + if (pc->pcall) { + dbus_pending_call_unref(pc->pcall); + pc->pcall = NULL; + } + if (!dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1)) { error("Can't send D-Bus message."); dbus_message_unref(msg); -- cgit From cb274f87d6246eb943cd388965e3afe371ed612b Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 1 Oct 2007 13:40:04 +0000 Subject: serial: removed invalid fd warning --- serial/manager.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index ec06ac0e..ba9ef112 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -449,6 +449,8 @@ static int rfcomm_connect(struct pending_connect *pc) if (!(errno == EAGAIN || errno == EINPROGRESS)) { error("connect() failed: %s (%d)", strerror(errno), errno); + g_io_channel_unref(pc->io); + pc->io = NULL; goto fail; } -- cgit From 70f0f80c49b989f346bd3932f26bffcbdb7f75db Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 3 Oct 2007 18:49:14 +0000 Subject: Fix dict signatures. --- serial/manager.c | 2 +- serial/port.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index ba9ef112..3d1f3629 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1631,7 +1631,7 @@ static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, static DBusMethodVTable proxy_methods[] = { { "Enable", proxy_enable, "", "" }, { "Disable", proxy_disable, "", "" }, - { "GetInfo", proxy_get_info, "", "{sv}" }, + { "GetInfo", proxy_get_info, "", "a{sv}" }, { "SetSerialParameters", proxy_set_serial_params, "syys", "" }, { NULL, NULL, NULL, NULL }, }; diff --git a/serial/port.c b/serial/port.c index 30b1412e..b12a2645 100644 --- a/serial/port.c +++ b/serial/port.c @@ -217,7 +217,7 @@ static DBusMethodVTable port_methods[] = { { "GetAdapter", port_get_adapter, "", "s" }, { "GetName", port_get_name, "", "s" }, { "GetServiceName", port_get_service_name, "", "s" }, - { "GetInfo", port_get_info, "", "{sv}" }, + { "GetInfo", port_get_info, "", "a{sv}" }, { NULL, NULL, NULL, NULL }, }; -- cgit From dd4096f6174e4d116796ae05230543e6846efd78 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Sun, 21 Oct 2007 22:29:28 +0000 Subject: serial: fixed API description --- serial/serial-api.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index e8431ded..5ff1dfd2 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -114,7 +114,7 @@ Methods string GetAdapter() [experimental] Returns the TTY device node name - string GetInfo() [experimental] + dict GetInfo() [experimental] Returns the port properties. @@ -132,16 +132,20 @@ Proxy hierarchy (experimental) Interface org.bluez.serial.Proxy Object path /org/bluez/serial/rfcomm* -Methods: string Enable() [experimental] +Methods: void Enable() [experimental] Register the serial proxy service record and start listenning on the specified adapter/channel. - string Disable() [experimental] + Possible errors:org.bluez.serial.Error.Failed + + void Disable() [experimental] Unregister the service record and stop listenning. + + Possible errors:org.bluez.serial.Error.Failed - string GetInfo() [experimental] + dict GetInfo() [experimental] Returns the proxy properties void SetSerialParameters(string rate, byte databits, @@ -152,3 +156,6 @@ Methods: string Enable() [experimental] "38400", "57600" and "115200". Available data bits: 5, 6, 7 and 8. Available stop bits: 1 and 2. Available parity: "even", "odd", "mark", "space" and "none". + + Possible errors:org.bluez.serial.Error.InvalidArguments + org.bluez.serial.Error.Failed -- cgit From e347206fff8ff056189f574651f07015ea9b51ce Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 23 Nov 2007 14:30:17 +0000 Subject: serial: removed pending call ref --- serial/manager.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 3d1f3629..8a6466e9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -71,7 +71,6 @@ struct pending_connect { DBusConnection *conn; DBusMessage *msg; - DBusPendingCall *pcall; /* Pending get handles/records */ char *bda; /* Destination address */ char *adapter_path; /* Adapter D-Bus path */ char *pattern; /* Connection request pattern */ @@ -151,8 +150,6 @@ static void pending_connect_free(struct pending_connect *pc) g_free(pc->pattern); if (pc->adapter_path) g_free(pc->adapter_path); - if (pc->pcall) - dbus_pending_call_unref(pc->pcall); if (pc->dev) g_free(pc->dev); if (pc->io_id > 0) @@ -185,7 +182,7 @@ static void transaction_owner_exited(const char *name, void *data) GSList *l, *tmp = NULL; debug("transaction owner %s exited", name); - /* Clean all pending calls that belongs to this owner */ + /* Remove all pending calls that belongs to this owner */ for (l = pending_connects; l != NULL; l = l->next) { struct pending_connect *pc = l->data; if (strcmp(name, dbus_message_get_sender(pc->msg)) != 0) { @@ -193,9 +190,6 @@ static void transaction_owner_exited(const char *name, void *data) continue; } - if (pc->pcall) - dbus_pending_call_cancel(pc->pcall); - if (pc->id >= 0) rfcomm_release(pc->id); @@ -474,7 +468,7 @@ fail: static void record_reply(DBusPendingCall *call, void *data) { - struct pending_connect *pc = data; + struct pending_connect *pc; DBusMessage *reply = dbus_pending_call_steal_reply(call); sdp_record_t *rec = NULL; const uint8_t *rec_bin; @@ -482,6 +476,13 @@ static void record_reply(DBusPendingCall *call, void *data) DBusError derr; int len, scanned, ch, err; + /* Owner exited? */ + if (!g_slist_find(pending_connects, data)) { + dbus_message_unref(reply); + return; + } + + pc = data; if (pc->canceled) { err_connection_canceled(pc->conn, pc->msg); goto fail; @@ -605,6 +606,7 @@ static int get_record(struct pending_connect *pc, uint32_t handle, DBusPendingCallNotifyFunction cb) { DBusMessage *msg; + DBusPendingCall *call; msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, "org.bluez.Adapter", "GetRemoteServiceRecord"); @@ -616,19 +618,14 @@ static int get_record(struct pending_connect *pc, uint32_t handle, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID); - /* Unref get_handles pending call */ - if (pc->pcall) { - dbus_pending_call_unref(pc->pcall); - pc->pcall = NULL; - } - - if (!dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1)) { + if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) { error("Can't send D-Bus message."); dbus_message_unref(msg); return -1; } - dbus_pending_call_set_notify(pc->pcall, cb, pc, NULL); + dbus_pending_call_set_notify(call, cb, pc, NULL); + dbus_pending_call_unref(call); dbus_message_unref(msg); return 0; @@ -636,12 +633,19 @@ static int get_record(struct pending_connect *pc, uint32_t handle, static void handles_reply(DBusPendingCall *call, void *data) { - struct pending_connect *pc = data; + struct pending_connect *pc; DBusMessage *reply = dbus_pending_call_steal_reply(call); DBusError derr; uint32_t *phandle; int len; + /* Owner exited? */ + if (!g_slist_find(pending_connects, data)) { + dbus_message_unref(reply); + return; + } + + pc = data; if (pc->canceled) { err_connection_canceled(pc->conn, pc->msg); goto fail; @@ -691,6 +695,7 @@ static int get_handles(struct pending_connect *pc, const char *uuid, DBusPendingCallNotifyFunction cb) { DBusMessage *msg; + DBusPendingCall *call; msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, "org.bluez.Adapter", "GetRemoteServiceHandles"); @@ -702,13 +707,14 @@ static int get_handles(struct pending_connect *pc, const char *uuid, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); - if (!dbus_connection_send_with_reply(pc->conn, msg, &pc->pcall, -1)) { + if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) { error("Can't send D-Bus message."); dbus_message_unref(msg); return -1; } - dbus_pending_call_set_notify(pc->pcall, cb, pc, NULL); + dbus_pending_call_set_notify(call, cb, pc, NULL); + dbus_pending_call_unref(call); dbus_message_unref(msg); return 0; -- cgit From 6e49d2d6ab859761671b51b10a40b5750551e152 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 23 Nov 2007 14:51:52 +0000 Subject: serial: minor cleanup --- serial/manager.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 8a6466e9..ed46a1d6 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -767,12 +766,12 @@ static int pattern2long(const char *pattern, long *pval) static DBusHandlerResult create_port(DBusConnection *conn, DBusMessage *msg, void *data) { + char path[MAX_PATH_LENGTH], port_name[16], uuid[MAX_LEN_UUID_STR]; + const char *bda, *pattern, *ppath = path; struct pending_connect *pending, *pc; DBusMessage *reply; DBusError derr; bdaddr_t src, dst; - char path[MAX_PATH_LENGTH], port_name[16], uuid[MAX_LEN_UUID_STR]; - const char *bda, *pattern, *ppath = path; long val; int dev_id, err; @@ -1793,7 +1792,6 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, const char *uuid128, *address, *ppath = path; DBusMessage *reply; proxy_type_t type; - GSList *l; DBusError derr; bdaddr_t src; uuid_t uuid; @@ -1817,8 +1815,8 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, return err_invalid_args(conn, msg, "Invalid address"); /* Only one proxy per address(TTY or unix socket) is allowed */ - l = g_slist_find_custom(proxies_paths, address, (GCompareFunc) proxycmp); - if (l) + if (g_slist_find_custom(proxies_paths, + address, (GCompareFunc) proxycmp)) return err_already_exists(conn, msg, "Proxy already exists"); dev_id = hci_get_route(NULL); -- cgit From 4392fbd3d96e2eea0d91f0eb9fd059ab38255986 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 26 Nov 2007 13:41:36 +0000 Subject: Update API descriptions to match new error codes --- serial/serial-api.txt | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 5ff1dfd2..4730e6a5 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -20,32 +20,32 @@ Methods string CreateProxy(string uuid, string address) replacing the null byte by 'x00'. eg: "/dev/ttyS0", "/tmp/gps-data", "x00/org/bluez/echo". - Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.NotAvailable - org.bluez.serial.Failed + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.NotAvailable + org.bluez.Error.Failed void RemoveProxy(string path) [experimental] Removes the serial port proxy object for given path. - Possible errors:org.bluez.serial.Error.DoesNotExist + Possible errors:org.bluez.Error.DoesNotExist string CreatePort(string address, string pattern) [experimental] Creates a serial port object. - Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.Error.ConnectionCanceled - org.bluez.serial.Error.ConnectionInProgress - org.bluez.serial.Error.ConnectionAttemptFailed - org.bluez.serial.Error.NotSupported - org.bluez.serial.Error.Failed + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.Canceled + org.bluez.Error.InProgress + org.bluez.Error.ConnectionAttemptFailed + org.bluez.Error.NotSupported + org.bluez.Error.Failed void RemovePort(string path) [experimental] Removes the serial port object for given path. - Possible errors:org.bluez.serial.Error.DoesNotExist + Possible errors:org.bluez.Error.DoesNotExist array{string} ListPorts() [experimental] @@ -61,27 +61,26 @@ Methods string CreateProxy(string uuid, string address) remote device and then creates a RFCOMM TTY device for it. The RFCOMM TTY device is returned. - Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.Error.ConnectionCanceled - org.bluez.serial.Error.ConnectionInProgress - org.bluez.serial.Error.ConnectionAttemptFailed - org.bluez.serial.Error.NotSupported - org.bluez.serial.Error.Failed + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.Canceled + org.bluez.Error.InProgress + org.bluez.Error.ConnectionAttemptFailed + org.bluez.Error.NotSupported + org.bluez.Error.Failed void CancelConnectService(string address, string pattern) Cancel a previous ConnectService method call. - Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.Error.ConnectionNotInProgress + Possible errors:org.bluez.serial.InvalidArguments void DisconnectService(string device) Disconnect a RFCOMM TTY device that has been created via the ConnectService method. - Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.Error.DoesNotExist + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.DoesNotExist Signals void PortCreated(string path) [experimental] @@ -137,13 +136,13 @@ Methods: void Enable() [experimental] Register the serial proxy service record and start listenning on the specified adapter/channel. - Possible errors:org.bluez.serial.Error.Failed + Possible errors:org.bluez.Error.Failed void Disable() [experimental] Unregister the service record and stop listenning. - Possible errors:org.bluez.serial.Error.Failed + Possible errors:org.bluez.Error.Failed dict GetInfo() [experimental] Returns the proxy properties @@ -157,5 +156,5 @@ Methods: void Enable() [experimental] 6, 7 and 8. Available stop bits: 1 and 2. Available parity: "even", "odd", "mark", "space" and "none". - Possible errors:org.bluez.serial.Error.InvalidArguments - org.bluez.serial.Error.Failed + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.Failed -- cgit From 7e88afe4f8307c092172ff3c3b76c2f95ab00293 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 26 Nov 2007 13:43:17 +0000 Subject: Update services to new error codes and helper functions --- serial/Makefile.am | 2 +- serial/error.c | 109 ---------------------------------------- serial/error.h | 41 --------------- serial/manager.c | 143 +++++++++++++++++++++++++++-------------------------- 4 files changed, 75 insertions(+), 220 deletions(-) delete mode 100644 serial/error.c delete mode 100644 serial/error.h (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 75f50b80..46039bea 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -12,7 +12,7 @@ service_PROGRAMS = bluetoothd-service-serial bluetoothd_service_serial_SOURCES = main.c \ manager.h manager.c port.h port.c \ - error.h error.c storage.h storage.c + storage.h storage.c LDADD = $(top_builddir)/common/libhelper.a \ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ diff --git a/serial/error.c b/serial/error.c deleted file mode 100644 index 7db33086..00000000 --- a/serial/error.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2007 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "dbus.h" -#include "error.h" - -#define SERIAL_ERROR_INTERFACE "org.bluez.serial.Error" - -DBusHandlerResult err_connection_canceled(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionCanceled", - "Connection creation canceled")); -} - -DBusHandlerResult err_connection_failed(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str)); -} - -DBusHandlerResult err_connection_in_progress(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionInProgress", - "Connection creation in progress")); -} - -DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE".ConnectionNotInProgress", - "Connection creation not in progress")); -} - -DBusHandlerResult err_already_exists(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".AlreadyExists", str)); -} - -DBusHandlerResult err_does_not_exist(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".DoesNotExist", str)); -} - -DBusHandlerResult err_failed(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".Failed", str)); -} - -DBusHandlerResult err_invalid_args(DBusConnection *conn, - DBusMessage *msg, const char *str) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); -} - -DBusHandlerResult err_not_supported(DBusConnection *conn, - DBusMessage *msg) -{ - return send_message_and_unref(conn, - dbus_message_new_error(msg, - SERIAL_ERROR_INTERFACE ".NotSupported", - "The service is not supported by the remote device")); -} diff --git a/serial/error.h b/serial/error.h deleted file mode 100644 index 5bb02bd0..00000000 --- a/serial/error.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2007 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -DBusHandlerResult err_connection_canceled(DBusConnection *conn, - DBusMessage *msg); -DBusHandlerResult err_connection_failed(DBusConnection *conn, - DBusMessage *msg, const char *str); -DBusHandlerResult err_connection_in_progress(DBusConnection *conn, - DBusMessage *msg); -DBusHandlerResult err_connection_not_in_progress(DBusConnection *conn, - DBusMessage *msg); -DBusHandlerResult err_already_exists(DBusConnection *conn, - DBusMessage *msg, const char *str); -DBusHandlerResult err_does_not_exist(DBusConnection *conn, - DBusMessage *msg, const char *str); -DBusHandlerResult err_failed(DBusConnection *conn, - DBusMessage *msg, const char *str); -DBusHandlerResult err_invalid_args(DBusConnection *conn, - DBusMessage *msg, const char *str); -DBusHandlerResult err_not_supported(DBusConnection *conn, - DBusMessage *msg); diff --git a/serial/manager.c b/serial/manager.c index ed46a1d6..b45958b9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -217,13 +217,13 @@ static void open_notify(int fd, int err, struct pending_connect *pc) if (err) { /* Max tries exceeded */ rfcomm_release(pc->id); - err_connection_failed(pc->conn, pc->msg, strerror(err)); + error_connection_attempt_failed(pc->conn, pc->msg, err); return; } if (pc->canceled) { rfcomm_release(pc->id); - err_connection_canceled(pc->conn, pc->msg); + error_canceled(pc->conn, pc->msg, "Connection canceled"); return; } @@ -352,7 +352,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, socklen_t len; if (pc->canceled) { - err_connection_canceled(pc->conn, pc->msg); + error_canceled(pc->conn, pc->msg, "Connection canceled"); goto fail; } @@ -360,7 +360,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, /* Avoid close invalid file descriptor */ g_io_channel_unref(pc->io); pc->io = NULL; - err_connection_canceled(pc->conn, pc->msg); + error_canceled(pc->conn, pc->msg, "Connection canceled"); goto fail; } @@ -370,14 +370,13 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, err = errno; error("getsockopt(SO_ERROR): %s (%d)", strerror(err), err); - err_connection_failed(pc->conn, - pc->msg, strerror(err)); + error_connection_attempt_failed(pc->conn, pc->msg, err); goto fail; } if (ret != 0) { error("connect(): %s (%d)", strerror(ret), ret); - err_connection_failed(pc->conn, pc->msg, strerror(ret)); + error_connection_attempt_failed(pc->conn, pc->msg, ret); goto fail; } @@ -394,7 +393,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, if (pc->id < 0) { err = errno; error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(err), err); - err_connection_failed(pc->conn, pc->msg, strerror(err)); + error_connection_attempt_failed(pc->conn, pc->msg, err); goto fail; } pc->dev = g_new0(char, 16); @@ -483,17 +482,19 @@ static void record_reply(DBusPendingCall *call, void *data) pc = data; if (pc->canceled) { - err_connection_canceled(pc->conn, pc->msg); + error_canceled(pc->conn, pc->msg, "Connection canceled"); goto fail; } dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { + /* FIXME : forward error as is */ if (dbus_error_has_name(&derr, "org.bluez.Error.ConnectionAttemptFailed")) - err_connection_failed(pc->conn, pc->msg, derr.message); + error_connection_attempt_failed(pc->conn, pc->msg, + EIO); else - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); error("GetRemoteServiceRecord: %s(%s)", derr.name, derr.message); @@ -504,14 +505,14 @@ static void record_reply(DBusPendingCall *call, void *data) if (!dbus_message_get_args(reply, &derr, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len, DBUS_TYPE_INVALID)) { - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); error("%s: %s", derr.name, derr.message); dbus_error_free(&derr); goto fail; } if (len == 0) { - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); error("Invalid service record length"); goto fail; } @@ -519,12 +520,12 @@ static void record_reply(DBusPendingCall *call, void *data) rec = sdp_extract_pdu(rec_bin, &scanned); if (!rec) { error("Can't extract SDP record."); - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); goto fail; } if (len != scanned || (sdp_get_access_protos(rec, &protos) < 0)) { - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); goto fail; } @@ -534,7 +535,7 @@ static void record_reply(DBusPendingCall *call, void *data) if (ch < 1 || ch > 30) { error("Channel out of range: %d", ch); - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); goto fail; } if (dbus_message_has_member(pc->msg, "CreatePort")) { @@ -548,7 +549,7 @@ static void record_reply(DBusPendingCall *call, void *data) str2ba(pc->bda, &dst); err = rfcomm_bind(&pc->src, &dst, -1, ch); if (err < 0) { - err_failed(pc->conn, pc->msg, strerror(-err)); + error_failed_errno(pc->conn, pc->msg, -err); goto fail; } snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); @@ -585,7 +586,8 @@ static void record_reply(DBusPendingCall *call, void *data) err = rfcomm_connect(pc); if (err < 0) { error("RFCOMM connection failed"); - err_connection_failed(pc->conn, pc->msg, strerror(-err)); + error_connection_attempt_failed(pc->conn, + pc->msg, -err); goto fail; } @@ -646,17 +648,19 @@ static void handles_reply(DBusPendingCall *call, void *data) pc = data; if (pc->canceled) { - err_connection_canceled(pc->conn, pc->msg); + error_canceled(pc->conn, pc->msg, "Connection canceled"); goto fail; } dbus_error_init(&derr); if (dbus_set_error_from_message(&derr, reply)) { + /* FIXME : forward error as is */ if (dbus_error_has_name(&derr, "org.bluez.Error.ConnectionAttemptFailed")) - err_connection_failed(pc->conn, pc->msg, derr.message); + error_connection_attempt_failed(pc->conn, + pc->msg, EIO); else - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); error("GetRemoteServiceHandles: %s(%s)", derr.name, derr.message); @@ -667,19 +671,19 @@ static void handles_reply(DBusPendingCall *call, void *data) if (!dbus_message_get_args(reply, &derr, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len, DBUS_TYPE_INVALID)) { - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); error("%s: %s", derr.name, derr.message); dbus_error_free(&derr); goto fail; } if (len == 0) { - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); goto fail; } if (get_record(pc, *phandle, record_reply) < 0) { - err_not_supported(pc->conn, pc->msg); + error_not_supported(pc->conn, pc->msg); goto fail; } @@ -780,18 +784,18 @@ static DBusHandlerResult create_port(DBusConnection *conn, DBUS_TYPE_STRING, &bda, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } pending = find_pending_connect_by_pattern(bda, pattern); if (pending) - return err_connection_in_progress(conn, msg); + return error_in_progress(conn, msg, "Connection in progress"); dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) - return err_failed(conn, msg, "Adapter not available"); + return error_failed(conn, msg, "Adapter not available"); pc = g_new0(struct pending_connect, 1); bacpy(&pc->src, &src); @@ -809,7 +813,7 @@ static DBusHandlerResult create_port(DBusConnection *conn, if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) { if (get_handles(pc, uuid, handles_reply) < 0) { pending_connect_free(pc); - return err_not_supported(conn, msg); + return error_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); name_listener_add(conn, dbus_message_get_sender(msg), @@ -821,20 +825,20 @@ static DBusHandlerResult create_port(DBusConnection *conn, err = pattern2long(pattern, &val); if (err < 0) { pending_connect_free(pc); - return err_invalid_args(conn, msg, "invalid pattern"); + return error_invalid_arguments(conn, msg, "invalid pattern"); } /* Record handle: starts at 0x10000 */ if (strncasecmp("0x", pattern, 2) == 0) { if (val < 0x10000) { pending_connect_free(pc); - return err_invalid_args(conn, msg, + return error_invalid_arguments(conn, msg, "invalid record handle"); } if (get_record(pc, val, record_reply) < 0) { pending_connect_free(pc); - return err_not_supported(conn, msg); + return error_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); name_listener_add(conn, dbus_message_get_sender(msg), @@ -845,13 +849,13 @@ static DBusHandlerResult create_port(DBusConnection *conn, pending_connect_free(pc); /* RFCOMM Channel range: 1 - 30 */ if (val < 1 || val > 30) - return err_invalid_args(conn, msg, + return error_invalid_arguments(conn, msg, "invalid RFCOMM channel"); str2ba(bda, &dst); err = rfcomm_bind(&src, &dst, -1, val); if (err < 0) - return err_failed(conn, msg, strerror(-err)); + return error_failed_errno(conn, msg, -err); snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); port_store(&src, &dst, err, val, NULL); @@ -919,21 +923,21 @@ static DBusHandlerResult remove_port(DBusConnection *conn, if (!dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%hd", &id) != 1) - return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); + return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); di.id = id; if (ioctl(rfcomm_ctl, RFCOMMGETDEVINFO, &di) < 0) - return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); + return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); port_delete(&di.src, &di.dst, id); if (port_unregister(path) < 0) - return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); + return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); send_message_and_unref(conn, dbus_message_new_method_return(msg)); @@ -1391,7 +1395,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, int sk; if (prx->listen_watch) - return err_failed(conn, msg, "Already enabled"); + return error_failed(conn, msg, "Already enabled"); /* Listen */ /* FIXME: missing options */ @@ -1399,7 +1403,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, if (sk < 0) { const char *strerr = strerror(errno); error("RFCOMM listen socket failed: %s(%d)", strerr, errno); - return err_failed(conn, msg, strerr); + return error_failed(conn, msg, strerr); } /* Create the record */ @@ -1409,7 +1413,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, prx->record_id = add_proxy_record(conn, &buf); if (!prx->record_id) { close(sk); - return err_failed(conn, msg, "Service registration failed"); + return error_failed(conn, msg, "Service registration failed"); } /* Add incomming connection watch */ @@ -1430,7 +1434,7 @@ static DBusHandlerResult proxy_disable(DBusConnection *conn, struct proxy *prx = data; if (!prx->listen_watch) - return err_failed(conn, msg, "Not enabled"); + return error_failed(conn, msg, "Not enabled"); /* Remove the watches and unregister the record: see watch notify */ g_source_remove(prx->listen_watch); @@ -1597,7 +1601,7 @@ static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, /* Don't allow change TTY settings if it is open */ if (prx->local_watch) - return err_failed(conn, msg, "Not allowed"); + return error_failed(conn, msg, "Not allowed"); dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, @@ -1606,23 +1610,23 @@ static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, DBUS_TYPE_BYTE, &stopbits, DBUS_TYPE_STRING, &paritystr, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } if (str2speed(ratestr, &speed) == B0) - return err_invalid_args(conn, msg, "Invalid baud rate"); + return error_invalid_arguments(conn, msg, "Invalid baud rate"); ctrl = prx->proxy_ti.c_cflag; if (set_databits(databits, &ctrl) < 0) - return err_invalid_args(conn, msg, "Invalid data bits"); + return error_invalid_arguments(conn, msg, "Invalid data bits"); if (set_stopbits(stopbits, &ctrl) < 0) - return err_invalid_args(conn, msg, "Invalid stop bits"); + return error_invalid_arguments(conn, msg, "Invalid stop bits"); if (set_parity(paritystr, &ctrl) < 0) - return err_invalid_args(conn, msg, "Invalid parity"); + return error_invalid_arguments(conn, msg, "Invalid parity"); prx->proxy_ti.c_cflag = ctrl; prx->proxy_ti.c_cflag |= (CLOCAL | CREAD); @@ -1802,27 +1806,27 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, DBUS_TYPE_STRING, &uuid128, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } if (str2uuid(&uuid, uuid128) < 0) - return err_invalid_args(conn, msg, "Invalid UUID"); + return error_invalid_arguments(conn, msg, "Invalid UUID"); type = addr2type(address); if (type == UNKNOWN_PROXY_TYPE) - return err_invalid_args(conn, msg, "Invalid address"); + return error_invalid_arguments(conn, msg, "Invalid address"); /* Only one proxy per address(TTY or unix socket) is allowed */ if (g_slist_find_custom(proxies_paths, address, (GCompareFunc) proxycmp)) - return err_already_exists(conn, msg, "Proxy already exists"); + return error_already_exists(conn, msg, "Proxy already exists"); dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) { error("Adapter not available"); - return err_failed(conn, msg, "Adapter not available"); + return error_failed(conn, msg, "Adapter not available"); } reply = dbus_message_new_method_return(msg); @@ -1838,7 +1842,7 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (ret < 0) { dbus_message_unref(reply); - return err_failed(conn, msg, "Create object path failed"); + return error_failed(conn, msg, "Create object path failed"); } dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, @@ -1879,14 +1883,14 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn, if (!dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } l = g_slist_find_custom(proxies_paths, path, (GCompareFunc) strcmp); if (!l) - return err_does_not_exist(conn, msg, "Invalid proxy path"); + return error_does_not_exist(conn, msg, "Invalid proxy path"); /* Remove from storage */ if (dbus_connection_get_object_user_data(conn, @@ -1923,18 +1927,18 @@ static DBusHandlerResult connect_service(DBusConnection *conn, DBUS_TYPE_STRING, &bda, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } pending = find_pending_connect_by_pattern(bda, pattern); if (pending) - return err_connection_in_progress(conn, msg); + return error_in_progress(conn, msg, "Connection in progress"); dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) - return err_failed(conn, msg, "Adapter not available"); + return error_failed(conn, msg, "Adapter not available"); pc = g_new0(struct pending_connect, 1); bacpy(&pc->src, &src); @@ -1952,7 +1956,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) { if (get_handles(pc, uuid, handles_reply) < 0) { pending_connect_free(pc); - return err_not_supported(conn, msg); + return error_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); goto done; @@ -1962,20 +1966,20 @@ static DBusHandlerResult connect_service(DBusConnection *conn, err = pattern2long(pattern, &val); if (err < 0) { pending_connect_free(pc); - return err_invalid_args(conn, msg, "invalid pattern"); + return error_invalid_arguments(conn, msg, "invalid pattern"); } /* Record handle: starts at 0x10000 */ if (strncasecmp("0x", pattern, 2) == 0) { if (val < 0x10000) { pending_connect_free(pc); - return err_invalid_args(conn, msg, + return error_invalid_arguments(conn, msg, "invalid record handle"); } if (get_record(pc, val, record_reply) < 0) { pending_connect_free(pc); - return err_not_supported(conn, msg); + return error_not_supported(conn, msg); } pending_connects = g_slist_append(pending_connects, pc); goto done; @@ -1984,7 +1988,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, /* RFCOMM Channel range: 1 - 30 */ if (val < 1 || val > 30) { pending_connect_free(pc); - return err_invalid_args(conn, msg, + return error_invalid_arguments(conn, msg, "invalid RFCOMM channel"); } @@ -1998,7 +2002,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn, error("RFCOMM connect failed: %s(%d)", strerr, -err); pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); - return err_connection_failed(conn, msg, strerr); + return error_connection_attempt_failed(conn, msg, -err); } done: name_listener_add(conn, dbus_message_get_sender(msg), @@ -2018,17 +2022,17 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn, if (!dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } if (sscanf(name, "/dev/rfcomm%d", &id) != 1) - return err_invalid_args(conn, msg, "invalid RFCOMM node"); + return error_invalid_arguments(conn, msg, "invalid RFCOMM node"); err = port_remove_listener(dbus_message_get_sender(msg), name); if (err < 0) - return err_does_not_exist(conn, msg, "Invalid RFCOMM node"); + return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); send_message_and_unref(conn, dbus_message_new_method_return(msg)); @@ -2054,14 +2058,15 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, DBUS_TYPE_STRING, &bda, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { - err_invalid_args(conn, msg, derr.message); + error_invalid_arguments(conn, msg, derr.message); dbus_error_free(&derr); return DBUS_HANDLER_RESULT_HANDLED; } pending = find_pending_connect_by_pattern(bda, pattern); if (!pending) - return err_connection_not_in_progress(conn, msg); + return error_does_not_exist(conn, msg, + "No such connection request"); reply = dbus_message_new_method_return(msg); if (!reply) -- cgit From 0a377c514a6d0d5eb3b723977007c682748d1baf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 13 Dec 2007 19:07:36 +0000 Subject: Add TCP connection support for serial proxy --- serial/manager.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 11 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index b45958b9..9c9827d4 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -105,6 +105,7 @@ static struct { typedef enum { TTY_PROXY, UNIX_SOCKET_PROXY, + TCP_SOCKET_PROXY, UNKNOWN_PROXY_TYPE = 0xFF } proxy_type_t; @@ -113,6 +114,7 @@ struct proxy { bdaddr_t dst; char *uuid128; /* UUID 128 */ char *address; /* TTY or Unix socket name */ + short int port; /* TCP port */ proxy_type_t type; /* TTY or Unix socket */ struct termios sys_ti; /* Default TTY setting */ struct termios proxy_ti; /* Proxy TTY settings */ @@ -586,7 +588,7 @@ static void record_reply(DBusPendingCall *call, void *data) err = rfcomm_connect(pc); if (err < 0) { error("RFCOMM connection failed"); - error_connection_attempt_failed(pc->conn, + error_connection_attempt_failed(pc->conn, pc->msg, -err); goto fail; } @@ -657,7 +659,7 @@ static void handles_reply(DBusPendingCall *call, void *data) /* FIXME : forward error as is */ if (dbus_error_has_name(&derr, "org.bluez.Error.ConnectionAttemptFailed")) - error_connection_attempt_failed(pc->conn, + error_connection_attempt_failed(pc->conn, pc->msg, EIO); else error_not_supported(pc->conn, pc->msg); @@ -667,7 +669,7 @@ static void handles_reply(DBusPendingCall *call, void *data) dbus_error_free(&derr); goto fail; } - + if (!dbus_message_get_args(reply, &derr, DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len, DBUS_TYPE_INVALID)) { @@ -1287,6 +1289,45 @@ static inline int unix_socket_connect(const char *address) return sk; } +static int tcp_socket_connect(const char *address) +{ + struct sockaddr_in addr; + int err, sk; + unsigned short int port; + + memset(&addr, 0, sizeof(addr)); + + if (strncmp(address, "localhost", 9) != 0) { + error("Address should have the form localhost:port."); + return -1; + } + port = atoi(strchr(address, ':') + 1); + if (port <= 0) { + error("Invalid port '%d'.", port); + return -1; + } + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = htons(port); + + sk = socket(PF_INET, SOCK_STREAM, 0); + if (sk < 0) { + err = errno; + error("TCP socket(%s) create failed %s(%d)", address, + strerror(err), err); + return -err; + } + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + error("TCP socket(%s) connect failed: %s(%d)", + address, strerror(err), err); + close(sk); + errno = err; + return -err; + } + return sk; +} + static inline int tty_open(const char *tty, struct termios *ti) { int err, sk; @@ -1337,10 +1378,19 @@ static gboolean connect_event(GIOChannel *chan, bacpy(&prx->dst, &raddr.rc_bdaddr); - if (prx->type == UNIX_SOCKET_PROXY) + switch (prx->type) { + case UNIX_SOCKET_PROXY: lsk = unix_socket_connect(prx->address); - else + break; + case TTY_PROXY: lsk = tty_open(prx->address, &prx->proxy_ti); + break; + case TCP_SOCKET_PROXY: + lsk = tcp_socket_connect(prx->address); + break; + default: + lsk = -1; + } if (lsk < 0) { close(rsk); @@ -1753,6 +1803,25 @@ static int proxy_socket_register(bdaddr_t *src, const char *uuid128, return ret; } +static int proxy_tcp_register(bdaddr_t *src, const char *uuid128, + const char *address, char *outpath, size_t size) +{ + struct proxy *prx; + int ret; + + prx = g_new0(struct proxy, 1); + prx->address = g_strdup(address); + prx->uuid128 = g_strdup(uuid128); + prx->type = TCP_SOCKET_PROXY; + bacpy(&prx->src, src); + + ret = register_proxy_object(prx, outpath, size); + if (ret < 0) + proxy_free(prx); + + return ret; +} + static proxy_type_t addr2type(const char *address) { struct stat st; @@ -1763,6 +1832,8 @@ static proxy_type_t addr2type(const char *address) * it refers to abstract namespace. 'x00' will be used * to represent the null byte. */ + if (strncmp("localhost:", address, 10) == 0) + return TCP_SOCKET_PROXY; if (strncmp("x00", address, 3) != 0) return UNKNOWN_PROXY_TYPE; else @@ -1833,13 +1904,22 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (type != TTY_PROXY) + switch (type) { + case UNIX_SOCKET_PROXY: ret = proxy_socket_register(&src, uuid128, - address, path, sizeof(path)); - else + address, path, sizeof(path)); + break; + case TTY_PROXY: ret = proxy_tty_register(&src, uuid128, address, NULL, path, sizeof(path)); - + break; + case TCP_SOCKET_PROXY: + ret = proxy_tcp_register(&src, uuid128, address, + path, sizeof(path)); + break; + default: + ret = -1; + } if (ret < 0) { dbus_message_unref(reply); return error_failed(conn, msg, "Create object path failed"); @@ -2065,7 +2145,7 @@ static DBusHandlerResult cancel_connect_service(DBusConnection *conn, pending = find_pending_connect_by_pattern(bda, pattern); if (!pending) - return error_does_not_exist(conn, msg, + return error_does_not_exist(conn, msg, "No such connection request"); reply = dbus_message_new_method_return(msg); @@ -2087,7 +2167,7 @@ static void proxy_path_free(gpointer data, gpointer udata) if (dbus_connection_get_object_user_data(conn, path, (void *) &prx) && prx) { struct termios *ti; - + ti = (prx->type == TTY_PROXY ? &prx->proxy_ti : NULL); proxy_store(&prx->src, prx->uuid128, prx->address, NULL, prx->channel, 0, ti); @@ -2244,6 +2324,9 @@ static void parse_proxy(char *key, char *value, void *data) case UNIX_SOCKET_PROXY: proxy_socket_register(&src, uuid128, key, NULL, 0); break; + case TCP_SOCKET_PROXY: + proxy_tcp_register(&src, uuid128, key, NULL, 0); + break; default: return; } -- cgit From c7aaa489d0509469fcbc712c49967c9e106f2773 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 21 Dec 2007 20:02:33 +0000 Subject: serial-api: CreatePort - added localhost port proxy --- serial/serial-api.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 4730e6a5..7d194673 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -15,10 +15,11 @@ Methods string CreateProxy(string uuid, string address) Creates a serial port proxy object. Service identifier must be provided in the uuid 128 - format. Addresses can be TTY char devices or unix - socket address. Abstract namespace can be informed - replacing the null byte by 'x00'. eg: "/dev/ttyS0", - "/tmp/gps-data", "x00/org/bluez/echo". + format. Addresses can be either TTY char devices, + unix socket address or a local TCP port. Abstract + namespace can be informed replacing the null byte + by 'x00'. eg: "/dev/ttyS0", "/tmp/gps-data", + "x00/org/bluez/echo", "localhost:2947". Possible errors:org.bluez.Error.InvalidArguments org.bluez.Error.NotAvailable -- cgit From 3950c140757d7ff35366f7d3e1d6aa81c74a5ca8 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Fri, 21 Dec 2007 20:39:35 +0000 Subject: serial: added ConnectServiceFromAdapter --- serial/manager.c | 84 ++++++++++++++++++++++++++++++++++++--------------- serial/serial-api.txt | 15 +++++++++ 2 files changed, 74 insertions(+), 25 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 9c9827d4..b33e30ac 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1991,32 +1991,20 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn, dbus_message_new_method_return(msg)); } -static DBusHandlerResult connect_service(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusHandlerResult connect_service_from_devid(DBusConnection *conn, + DBusMessage *msg, void *data, int dev_id, + const char *bda, const char *pattern) { struct pending_connect *pending, *pc; - DBusError derr; bdaddr_t src; - const char *bda, *pattern; long val; - int dev_id, err; + int err; char uuid[MAX_LEN_UUID_STR]; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &bda, - DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } - pending = find_pending_connect_by_pattern(bda, pattern); if (pending) return error_in_progress(conn, msg, "Connection in progress"); - dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) return error_failed(conn, msg, "Adapter not available"); @@ -2091,6 +2079,51 @@ done: return DBUS_HANDLER_RESULT_HANDLED; } +static DBusHandlerResult connect_service(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusError derr; + const char *bda, *pattern; + int devid; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &pattern, + DBUS_TYPE_INVALID)) { + error_invalid_arguments(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + devid = hci_get_route(NULL); + + return connect_service_from_devid(conn, msg, data, devid, bda, pattern); +} + +static DBusHandlerResult connect_service_from_adapter(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + DBusError derr; + const char *adapter, *bda, *pattern; + int devid; + + dbus_error_init(&derr); + if (!dbus_message_get_args(msg, &derr, + DBUS_TYPE_STRING, &adapter, + DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &pattern, + DBUS_TYPE_INVALID)) { + error_invalid_arguments(conn, msg, derr.message); + dbus_error_free(&derr); + return DBUS_HANDLER_RESULT_HANDLED; + } + + devid = hci_devid(adapter); + + return connect_service_from_devid(conn, msg, data, devid, bda, pattern); +} + static DBusHandlerResult disconnect_service(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -2219,15 +2252,16 @@ static void manager_unregister(DBusConnection *conn, void *data) } static DBusMethodVTable manager_methods[] = { - { "CreatePort", create_port, "ss", "s" }, - { "ListPorts", list_ports, "", "as" }, - { "RemovePort", remove_port, "s", "" }, - { "CreateProxy", create_proxy, "ss", "s" }, - { "ListProxies", list_proxies, "", "as" }, - { "RemoveProxy", remove_proxy, "s", "" }, - { "ConnectService", connect_service, "ss", "s" }, - { "DisconnectService", disconnect_service, "s", "" }, - { "CancelConnectService", cancel_connect_service, "ss", "" }, + { "CreatePort", create_port, "ss", "s" }, + { "ListPorts", list_ports, "", "as" }, + { "RemovePort", remove_port, "s", "" }, + { "CreateProxy", create_proxy, "ss", "s" }, + { "ListProxies", list_proxies, "", "as" }, + { "RemoveProxy", remove_proxy, "s", "" }, + { "ConnectService", connect_service, "ss", "s" }, + { "ConnectServiceFromAdapter", connect_service_from_adapter, "sss", "s" }, + { "DisconnectService", disconnect_service, "s", "" }, + { "CancelConnectService", cancel_connect_service, "ss", "" }, { NULL, NULL, NULL, NULL }, }; diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 7d194673..96b5d684 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -69,6 +69,21 @@ Methods string CreateProxy(string uuid, string address) org.bluez.Error.NotSupported org.bluez.Error.Failed + string ConnectServiceFromAdapter(string adapter, + string address, string pattern) [experimental] + + Use the given adapter to connect to a specific RFCOMM + based service on a remote device and then creates a + RFCOMM TTY device for it. The RFCOMM TTY device is + returned. + + Possible errors:org.bluez.Error.InvalidArguments + org.bluez.Error.Canceled + org.bluez.Error.InProgress + org.bluez.Error.ConnectionAttemptFailed + org.bluez.Error.NotSupported + org.bluez.Error.Failed + void CancelConnectService(string address, string pattern) Cancel a previous ConnectService method call. -- cgit From ba255beb79afb9c00ae5b71821f84f911aa8d1fe Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 28 Jan 2008 10:38:40 +0000 Subject: Whitespace cleanup --- serial/manager.c | 8 ++++---- serial/port.c | 2 +- serial/serial-api.txt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index b33e30ac..2bbb5999 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -64,7 +64,7 @@ #define BUF_SIZE 1024 /* Waiting for udev to create the device node */ -#define MAX_OPEN_TRIES 5 +#define MAX_OPEN_TRIES 5 #define OPEN_WAIT 300 /* ms */ struct pending_connect { @@ -80,7 +80,7 @@ struct pending_connect { char *dev; /* tty device name */ int id; /* RFCOMM device id */ int ntries; /* Open attempts */ - int canceled; /* Operation canceled */ + int canceled; /* Operation canceled */ }; /* FIXME: Common file required */ @@ -1646,7 +1646,7 @@ static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, struct proxy *prx = data; const char *ratestr, *paritystr; uint8_t databits, stopbits; - tcflag_t ctrl; /* Control mode flags */ + tcflag_t ctrl; /* Control mode flags */ speed_t speed = B0; /* In/Out speed */ /* Don't allow change TTY settings if it is open */ @@ -1691,7 +1691,7 @@ static DBusMethodVTable proxy_methods[] = { { "Enable", proxy_enable, "", "" }, { "Disable", proxy_disable, "", "" }, { "GetInfo", proxy_get_info, "", "a{sv}" }, - { "SetSerialParameters", proxy_set_serial_params, "syys", "" }, + { "SetSerialParameters", proxy_set_serial_params, "syys", "" }, { NULL, NULL, NULL, NULL }, }; diff --git a/serial/port.c b/serial/port.c index b12a2645..6d82c632 100644 --- a/serial/port.c +++ b/serial/port.c @@ -145,7 +145,7 @@ static DBusHandlerResult port_get_name(DBusConnection *conn, DBusMessage *reply; const char *pname; char *name = NULL; - + reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; diff --git a/serial/serial-api.txt b/serial/serial-api.txt index 96b5d684..7e17b86e 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -157,7 +157,7 @@ Methods: void Enable() [experimental] void Disable() [experimental] Unregister the service record and stop listenning. - + Possible errors:org.bluez.Error.Failed dict GetInfo() [experimental] -- cgit From e823c15e43a6f924779e466d434c51157002d9ee Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: Update copyright information --- serial/main.c | 2 +- serial/manager.c | 2 +- serial/manager.h | 2 +- serial/port.c | 2 +- serial/port.h | 2 +- serial/storage.c | 2 +- serial/storage.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 5bacd121..3554eeeb 100644 --- a/serial/main.c +++ b/serial/main.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/serial/manager.c b/serial/manager.c index 2bbb5999..bf9b0d24 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/serial/manager.h b/serial/manager.h index 4004d81e..cf55adab 100644 --- a/serial/manager.h +++ b/serial/manager.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/serial/port.c b/serial/port.c index 6d82c632..c090ebd4 100644 --- a/serial/port.c +++ b/serial/port.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/serial/port.h b/serial/port.h index ad6f4fa8..88bcb200 100644 --- a/serial/port.h +++ b/serial/port.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/serial/storage.c b/serial/storage.c index 6ea3eb41..98cd5b84 100644 --- a/serial/storage.c +++ b/serial/storage.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify diff --git a/serial/storage.h b/serial/storage.h index 271ae722..32b04a03 100644 --- a/serial/storage.h +++ b/serial/storage.h @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From d78b22fe007467b1e5129e6e7f0f5752fac85efe Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 22 Mar 2008 16:07:37 +0000 Subject: Convert serial service to a plugin --- serial/Makefile.am | 20 ++++++-------- serial/main.c | 73 +++++++++++++++------------------------------------ serial/manager.c | 4 +-- serial/manager.h | 4 +-- serial/serial.service | 5 ---- 5 files changed, 33 insertions(+), 73 deletions(-) delete mode 100644 serial/serial.service (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 46039bea..705ccef4 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -1,27 +1,23 @@ if SERIALSERVICE -if CONFIGFILES -confdir = $(sysconfdir)/bluetooth +plugindir = $(libdir)/bluetooth/plugins -conf_DATA = serial.service -endif - -servicedir = $(libdir)/bluetooth +plugin_LTLIBRARIES = libserial.la -service_PROGRAMS = bluetoothd-service-serial - -bluetoothd_service_serial_SOURCES = main.c \ +libserial_la_SOURCES = main.c \ manager.h manager.c port.h port.c \ storage.h storage.c LDADD = $(top_builddir)/common/libhelper.a \ - @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ + @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ endif +AM_LDFLAGS = -module -avoid-version -export-symbols-regex bluetooth_plugin_desc + AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ -INCLUDES = -I$(top_srcdir)/common +INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/hcid -EXTRA_DIST = serial.service serial-api.txt test-serial +EXTRA_DIST = serial-api.txt test-serial MAINTAINERCLEANFILES = Makefile.in diff --git a/serial/main.c b/serial/main.c index 3554eeeb..466ee883 100644 --- a/serial/main.c +++ b/serial/main.c @@ -25,70 +25,39 @@ #include #endif -#include -#include -#include -#include -#include "logging.h" -#include "dbus.h" +#include +#include -#include "manager.h" +#include -static GMainLoop *main_loop; +#include "plugin.h" +#include "dbus.h" +#include "manager.h" -static void sig_term(int sig) -{ - g_main_loop_quit(main_loop); -} +static DBusConnection *conn; -int main(int argc, char *argv[]) +static int serial_init(void) { - DBusConnection *conn; - struct sigaction sa; - - start_logging("serial", "Bluetooth Serial Port daemon"); - - memset(&sa, 0, sizeof(sa)); - sa.sa_flags = SA_NOCLDSTOP; - sa.sa_handler = sig_term; - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - - enable_debug(); - - main_loop = g_main_loop_new(NULL, FALSE); + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); + if (conn == NULL) + return -EIO; - conn = dbus_bus_system_setup_with_main_loop(NULL, NULL, NULL); - if (!conn) { - g_main_loop_unref(main_loop); - exit(EXIT_FAILURE); - } - - if (serial_init(conn) < 0) { + if (serial_manager_init(conn) < 0) { dbus_connection_unref(conn); - g_main_loop_unref(main_loop); - exit(EXIT_FAILURE); + return -EIO; } - if (argc > 1 && !strcmp(argv[1], "-s")) - register_external_service(conn, "serial", "Serial service", ""); + register_external_service(conn, "serial", "Serial service", ""); - g_main_loop_run(main_loop); + return 0; +} - serial_exit(); +static void serial_exit(void) +{ + serial_manager_exit(); dbus_connection_unref(conn); - - g_main_loop_unref(main_loop); - - info("Exit"); - - stop_logging(); - - return 0; } + +BLUETOOTH_PLUGIN_DEFINE("serial", serial_init, serial_exit) diff --git a/serial/manager.c b/serial/manager.c index bf9b0d24..349e5cdc 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -2392,7 +2392,7 @@ static void register_stored(void) closedir(dir); } -int serial_init(DBusConnection *conn) +int serial_manager_init(DBusConnection *conn) { if (rfcomm_ctl < 0) { @@ -2427,7 +2427,7 @@ int serial_init(DBusConnection *conn) return 0; } -void serial_exit(void) +void serial_manager_exit(void) { dbus_connection_destroy_object_path(connection, SERIAL_MANAGER_PATH); diff --git a/serial/manager.h b/serial/manager.h index cf55adab..8a870101 100644 --- a/serial/manager.h +++ b/serial/manager.h @@ -26,6 +26,6 @@ #define MAX_PATH_LENGTH 32 -int serial_init(DBusConnection *conn); -void serial_exit(void); +int serial_manager_init(DBusConnection *conn); +void serial_manager_exit(void); int rfcomm_release(int16_t id); diff --git a/serial/serial.service b/serial/serial.service deleted file mode 100644 index 926e5064..00000000 --- a/serial/serial.service +++ /dev/null @@ -1,5 +0,0 @@ -[Bluetooth Service] -Identifier=serial -Name=Serial service -Description=Bluetooth Serial Port service -Autostart=false -- cgit From dad48dfed4d105d6afbdc6471af33484fac3ce03 Mon Sep 17 00:00:00 2001 From: Cidorvan Leite Date: Thu, 27 Mar 2008 18:12:33 +0000 Subject: Add/Remove records directly instead of use D-Bus messages --- serial/Makefile.am | 2 +- serial/manager.c | 130 +++++++++++------------------------------------------ 2 files changed, 27 insertions(+), 105 deletions(-) (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 705ccef4..226ba030 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -16,7 +16,7 @@ AM_LDFLAGS = -module -avoid-version -export-symbols-regex bluetooth_plugin_desc AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ -INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/hcid +INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/hcid -I$(top_srcdir)/sdpd EXTRA_DIST = serial-api.txt test-serial diff --git a/serial/manager.c b/serial/manager.c index 349e5cdc..6ee27ccf 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -58,6 +58,7 @@ #include "port.h" #include "storage.h" #include "manager.h" +#include "sdpd.h" #define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" #define SERIAL_PROXY_INTERFACE "org.bluez.serial.Proxy" @@ -1052,31 +1053,32 @@ static int str2uuid(uuid_t *uuid, const char *string) return -1; } -static int create_proxy_record(sdp_buf_t *buf, const char *uuid128, uint8_t channel) +static sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel) { sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; uuid_t uuid, root_uuid, l2cap, rfcomm; sdp_profile_desc_t profile; - sdp_record_t record; + sdp_record_t *record; sdp_data_t *ch; - int ret; - memset(&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + record = sdp_record_alloc(); + if (!record) + return NULL; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); - sdp_set_browse_groups(&record, root); + sdp_set_browse_groups(record, root); sdp_list_free(root, NULL); str2uuid(&uuid, uuid128); svclass_id = sdp_list_append(NULL, &uuid); - sdp_set_service_classes(&record, svclass_id); + sdp_set_service_classes(record, svclass_id); sdp_list_free(svclass_id, NULL); sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profiles = sdp_list_append(NULL, &profile); - sdp_set_profile_descs(&record, profiles); + sdp_set_profile_descs(record, profiles); sdp_list_free(profiles, NULL); sdp_uuid16_create(&l2cap, L2CAP_UUID); @@ -1090,24 +1092,20 @@ static int create_proxy_record(sdp_buf_t *buf, const char *uuid128, uint8_t chan apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(NULL, apseq); - sdp_set_access_protos(&record, aproto); + sdp_set_access_protos(record, aproto); - add_lang_attr(&record); + add_lang_attr(record); - sdp_set_info_attr(&record, "Port Proxy Entity", + sdp_set_info_attr(record, "Port Proxy Entity", NULL, "Port Proxy Entity"); - ret = sdp_gen_record_pdu(&record, buf); - sdp_data_free(ch); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(apseq, NULL); sdp_list_free(aproto, NULL); - sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free); - sdp_list_free(record.pattern, free); - return ret; + return record; } static GIOError channel_write(GIOChannel *chan, char *buf, size_t size) @@ -1168,87 +1166,6 @@ static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data) return TRUE; } -static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf) -{ - DBusMessage *msg, *reply; - DBusError derr; - dbus_uint32_t rec_id; - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "AddServiceRecord"); - if (!msg) { - error("Can't allocate new method call"); - return 0; - } - - dbus_message_append_args(msg, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &buf->data, buf->data_size, - DBUS_TYPE_INVALID); - - dbus_error_init(&derr); - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); - - free(buf->data); - dbus_message_unref(msg); - - if (dbus_error_is_set(&derr) || - dbus_set_error_from_message(&derr, reply)) { - error("Adding service record failed: %s", derr.message); - dbus_error_free(&derr); - return 0; - } - - dbus_message_get_args(reply, &derr, - DBUS_TYPE_UINT32, &rec_id, - DBUS_TYPE_INVALID); - - if (dbus_error_is_set(&derr)) { - error("Invalid arguments to AddServiceRecord reply: %s", - derr.message); - dbus_message_unref(reply); - dbus_error_free(&derr); - return 0; - } - - dbus_message_unref(reply); - - return rec_id; -} - -static int remove_proxy_record(DBusConnection *conn, uint32_t rec_id) -{ - DBusMessage *msg, *reply; - DBusError derr; - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "RemoveServiceRecord"); - if (!msg) { - error("Can't allocate new method call"); - return -ENOMEM; - } - - dbus_message_append_args(msg, - DBUS_TYPE_UINT32, &rec_id, - DBUS_TYPE_INVALID); - - dbus_error_init(&derr); - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr); - - dbus_message_unref(msg); - - if (dbus_error_is_set(&derr)) { - error("Removing service record 0x%x failed: %s", - rec_id, derr.message); - dbus_error_free(&derr); - return -1; - } - - dbus_message_unref(reply); - - return 0; -} - static inline int unix_socket_connect(const char *address) { struct sockaddr_un addr; @@ -1432,7 +1349,7 @@ static void listen_watch_notify(gpointer data) prx->local_watch = 0; } - remove_proxy_record(connection, prx->record_id); + remove_record_from_server(prx->record_id); prx->record_id = 0; } @@ -1441,7 +1358,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, { struct proxy *prx = data; GIOChannel *io; - sdp_buf_t buf; + sdp_record_t *record; int sk; if (prx->listen_watch) @@ -1456,16 +1373,21 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, return error_failed(conn, msg, strerr); } - /* Create the record */ - create_proxy_record(&buf, prx->uuid128, prx->channel); + record = proxy_record_new(prx->uuid128, prx->channel); + if (!record) { + close(sk); + return error_failed(conn, msg, + "Unable to allocate new service record"); + } - /* Register the record */ - prx->record_id = add_proxy_record(conn, &buf); - if (!prx->record_id) { + if (add_record_to_server(&prx->src, record) < 0) { close(sk); + sdp_record_free(record); return error_failed(conn, msg, "Service registration failed"); } + prx->record_id = record->handle; + /* Add incomming connection watch */ io = g_io_channel_unix_new(sk); g_io_channel_set_close_on_unref(io, TRUE); -- cgit From 60202f31c998cc68c14f57c91e4b40d2c39f95f2 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 9 Apr 2008 22:00:34 +0000 Subject: Broken build: missing headers --- serial/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 466ee883..9d094123 100644 --- a/serial/main.c +++ b/serial/main.c @@ -29,6 +29,7 @@ #include #include +#include #include #include "plugin.h" -- cgit From 68fb0b7fc9dc88e8b7dc412f80a3a0ed04ffd020 Mon Sep 17 00:00:00 2001 From: Cidorvan Leite Date: Tue, 15 Apr 2008 22:16:56 +0000 Subject: Added support for non-Bluetooth UUIDs --- serial/manager.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 6ee27ccf..be8cfa5c 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -60,7 +60,6 @@ #include "manager.h" #include "sdpd.h" -#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" #define SERIAL_PROXY_INTERFACE "org.bluez.serial.Proxy" #define BUF_SIZE 1024 @@ -729,6 +728,7 @@ static int get_handles(struct pending_connect *pc, const char *uuid, static int pattern2uuid128(const char *pattern, char *uuid, size_t size) { uint16_t cls; + int i; /* Friendly name */ cls = str2class(pattern); @@ -742,15 +742,20 @@ static int pattern2uuid128(const char *pattern, char *uuid, size_t size) } /* UUID 128*/ - if ((strlen(pattern) == 36) && - (strncasecmp(BASE_UUID, pattern, 3) == 0) && - (strncasecmp(BASE_UUID + 8, pattern + 8, 28) == 0)) { + if (strlen(pattern) != 36) + return -EINVAL; - strncpy(uuid, pattern, size); - return 0; + for (i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (pattern[i] != '-') + return -EINVAL; + + } else if (!g_ascii_isxdigit(pattern[i])) + return -EINVAL; } - return -EINVAL; + strncpy(uuid, pattern, size); + return 0; } static int pattern2long(const char *pattern, long *pval) -- cgit From 18da7d861808385a5e8c74213beac74599520348 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Tue, 29 Apr 2008 21:02:19 +0000 Subject: serial: using bt_rfcomm_connect function --- serial/manager.c | 106 +++++++++++-------------------------------------------- 1 file changed, 21 insertions(+), 85 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index be8cfa5c..dd776ac8 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -59,6 +59,7 @@ #include "storage.h" #include "manager.h" #include "sdpd.h" +#include "glib-helper.h" #define SERIAL_PROXY_INTERFACE "org.bluez.serial.Proxy" #define BUF_SIZE 1024 @@ -346,39 +347,20 @@ static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, int16_t dev_id, uint8_t ch) return id; } -static gboolean rfcomm_connect_cb(GIOChannel *chan, - GIOCondition cond, struct pending_connect *pc) +static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) { + struct pending_connect *pc = user_data; struct rfcomm_dev_req req; - int sk, err, fd, ret; - socklen_t len; + int sk, err, fd; if (pc->canceled) { error_canceled(pc->conn, pc->msg, "Connection canceled"); goto fail; } - if (cond & G_IO_NVAL) { - /* Avoid close invalid file descriptor */ - g_io_channel_unref(pc->io); - pc->io = NULL; - error_canceled(pc->conn, pc->msg, "Connection canceled"); - goto fail; - } - - sk = g_io_channel_unix_get_fd(chan); - len = sizeof(ret); - if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { - err = errno; - error("getsockopt(SO_ERROR): %s (%d)", - strerror(err), err); - error_connection_attempt_failed(pc->conn, pc->msg, err); - goto fail; - } - - if (ret != 0) { - error("connect(): %s (%d)", strerror(ret), ret); - error_connection_attempt_failed(pc->conn, pc->msg, ret); + if (err_cb < 0) { + error("connect(): %s (%d)", strerror(err_cb), err_cb); + error_connection_attempt_failed(pc->conn, pc->msg, err_cb); goto fail; } @@ -391,6 +373,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, str2ba(pc->bda, &req.dst); req.channel = pc->channel; + sk = g_io_channel_unix_get_fd(chan); pc->id = ioctl(sk, RFCOMMCREATEDEV, &req); if (pc->id < 0) { err = errno; @@ -405,65 +388,11 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, fd = port_open(pc); if (fd < 0) /* Open in progress: Wait the callback */ - return FALSE; + return; open_notify(fd, 0, pc); fail: pending_connect_remove(pc); - return FALSE; -} - -static int rfcomm_connect(struct pending_connect *pc) -{ - struct sockaddr_rc addr; - int sk, err; - - sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) - return -errno; - - memset(&addr, 0, sizeof(addr)); - addr.rc_family = AF_BLUETOOTH; - bacpy(&addr.rc_bdaddr, &pc->src); - addr.rc_channel = 0; - - if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) - goto fail; - - if (set_nonblocking(sk) < 0) - goto fail; - - pc->io = g_io_channel_unix_new(sk); - addr.rc_family = AF_BLUETOOTH; - str2ba(pc->bda, &addr.rc_bdaddr); - addr.rc_channel = pc->channel; - - if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - /* BlueZ returns EAGAIN eventhough it should return EINPROGRESS */ - if (!(errno == EAGAIN || errno == EINPROGRESS)) { - error("connect() failed: %s (%d)", - strerror(errno), errno); - g_io_channel_unref(pc->io); - pc->io = NULL; - goto fail; - } - - debug("Connect in progress"); - pc->io_id = g_io_add_watch(pc->io, - G_IO_OUT | G_IO_ERR | G_IO_NVAL | G_IO_HUP, - (GIOFunc) rfcomm_connect_cb, pc); - } else { - debug("Connect succeeded with first try"); - (void) rfcomm_connect_cb(pc->io, G_IO_OUT, pc); - } - - return 0; -fail: - err = errno; - close(sk); - errno = err; - - return -err; } static void record_reply(DBusPendingCall *call, void *data) @@ -475,6 +404,7 @@ static void record_reply(DBusPendingCall *call, void *data) sdp_list_t *protos; DBusError derr; int len, scanned, ch, err; + bdaddr_t dst; /* Owner exited? */ if (!g_slist_find(pending_connects, data)) { @@ -540,15 +470,16 @@ static void record_reply(DBusPendingCall *call, void *data) error_not_supported(pc->conn, pc->msg); goto fail; } + + str2ba(pc->bda, &dst); + if (dbus_message_has_member(pc->msg, "CreatePort")) { char path[MAX_PATH_LENGTH], port_name[16]; const char *ppath = path; sdp_data_t *d; char *svcname = NULL; DBusMessage *reply; - bdaddr_t dst; - str2ba(pc->bda, &dst); err = rfcomm_bind(&pc->src, &dst, -1, ch); if (err < 0) { error_failed_errno(pc->conn, pc->msg, -err); @@ -585,7 +516,8 @@ static void record_reply(DBusPendingCall *call, void *data) } else { /* ConnectService */ pc->channel = ch; - err = rfcomm_connect(pc); + + err = bt_rfcomm_connect(&pc->src, &dst, ch, rfcomm_connect_cb, pc); if (err < 0) { error("RFCOMM connection failed"); error_connection_attempt_failed(pc->conn, @@ -1923,7 +1855,7 @@ static DBusHandlerResult connect_service_from_devid(DBusConnection *conn, const char *bda, const char *pattern) { struct pending_connect *pending, *pc; - bdaddr_t src; + bdaddr_t src, dst; long val; int err; char uuid[MAX_LEN_UUID_STR]; @@ -1991,7 +1923,11 @@ static DBusHandlerResult connect_service_from_devid(DBusConnection *conn, pending_connects = g_slist_append(pending_connects, pc); pc->channel = val; - err = rfcomm_connect(pc); + + str2ba(pc->bda, &dst); + + err = bt_rfcomm_connect(&pc->src, &dst, val, rfcomm_connect_cb, pc); + if (err < 0) { const char *strerr = strerror(-err); error("RFCOMM connect failed: %s(%d)", strerr, -err); -- cgit From e5efdf9f53353ad7b8e704c4b7ed42d1052ece82 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 5 May 2008 13:09:03 +0000 Subject: serial: missing channel unref --- serial/manager.c | 1 + 1 file changed, 1 insertion(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index dd776ac8..eb49f8e9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -375,6 +375,7 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) sk = g_io_channel_unix_get_fd(chan); pc->id = ioctl(sk, RFCOMMCREATEDEV, &req); + g_io_channel_unref(chan); if (pc->id < 0) { err = errno; error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(err), err); -- cgit From d584577564a1c05ce938493f342ec5dc74a7bca6 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 5 May 2008 13:12:28 +0000 Subject: serial: fixed wrong error value --- serial/manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index eb49f8e9..e03e9b01 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -359,8 +359,8 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) } if (err_cb < 0) { - error("connect(): %s (%d)", strerror(err_cb), err_cb); - error_connection_attempt_failed(pc->conn, pc->msg, err_cb); + error("connect(): %s (%d)", strerror(-err_cb), -err_cb); + error_connection_attempt_failed(pc->conn, pc->msg, -err_cb); goto fail; } -- cgit From 4c169b8a996bf50ed843c8ddc926a5e1530923be Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 5 May 2008 21:07:41 +0000 Subject: serial: cleanup --- serial/manager.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index e03e9b01..dc612b12 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -76,8 +76,6 @@ struct pending_connect { char *pattern; /* Connection request pattern */ bdaddr_t src; uint8_t channel; - guint io_id; /* GIOChannel watch id */ - GIOChannel *io; /* GIOChannel for RFCOMM connect */ char *dev; /* tty device name */ int id; /* RFCOMM device id */ int ntries; /* Open attempts */ @@ -154,12 +152,6 @@ static void pending_connect_free(struct pending_connect *pc) g_free(pc->adapter_path); if (pc->dev) g_free(pc->dev); - if (pc->io_id > 0) - g_source_remove(pc->io_id); - if (pc->io) { - g_io_channel_close(pc->io); - g_io_channel_unref(pc->io); - } g_free(pc); } -- cgit From 71c8ceab961dffc52b7dd4c814529083aede9c48 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 5 May 2008 21:09:51 +0000 Subject: serial: remove RFCOMM_RELEASE_ONHUP flag and close the channel --- serial/manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index dc612b12..631158c9 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -360,13 +360,14 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) memset(&req, 0, sizeof(req)); req.dev_id = -1; - req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP); + req.flags = (1 << RFCOMM_REUSE_DLC); bacpy(&req.src, &pc->src); str2ba(pc->bda, &req.dst); req.channel = pc->channel; sk = g_io_channel_unix_get_fd(chan); pc->id = ioctl(sk, RFCOMMCREATEDEV, &req); + g_io_channel_close(chan); g_io_channel_unref(chan); if (pc->id < 0) { err = errno; -- cgit From d78c8f2dce3e97c62e71e07a5f78f1289db1dd58 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 5 May 2008 21:17:30 +0000 Subject: serial: check if the owner exited in the RFCOMM connect callback --- serial/manager.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 631158c9..2bb1ce84 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -345,6 +345,10 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) struct rfcomm_dev_req req; int sk, err, fd; + /* Owner exited? */ + if (!g_slist_find(pending_connects, pc)) + return; + if (pc->canceled) { error_canceled(pc->conn, pc->msg, "Connection canceled"); goto fail; -- cgit From 6dd473cb823393b9dbfc370d64a039411664372d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 6 May 2008 01:20:42 +0000 Subject: Remove all serial ports on shutdown --- serial/manager.c | 2 ++ serial/port.c | 13 +++++++++++++ serial/port.h | 2 ++ 3 files changed, 17 insertions(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 2bb1ce84..d0a21ce6 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -2295,6 +2295,8 @@ void serial_manager_exit(void) dbus_connection_unref(connection); connection = NULL; + port_release_all(); + if (rfcomm_ctl >= 0) close(rfcomm_ctl); } diff --git a/serial/port.c b/serial/port.c index c090ebd4..f2c0eb61 100644 --- a/serial/port.c +++ b/serial/port.c @@ -328,6 +328,19 @@ int port_remove_listener(const char *owner, const char *dev) return 0; } +void port_release_all(void) +{ + struct rfcomm_node *node; + GSList *l; + + for (l = connected_nodes; l; l = l->next) { + node = l->data; + + connected_nodes = g_slist_remove(connected_nodes, node); + rfcomm_node_free(node); + } +} + int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, bdaddr_t *dst, const char *dev, char *ppath, const char *svc) { diff --git a/serial/port.h b/serial/port.h index 88bcb200..5471525b 100644 --- a/serial/port.h +++ b/serial/port.h @@ -26,6 +26,8 @@ int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, int port_remove_listener(const char *owner, const char *dev); +void port_release_all(void); + int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, bdaddr_t *dst, const char *dev, char *ppath, const char *svc); -- cgit From 319f3d5167907dcd1bdc27653ac889424455e42a Mon Sep 17 00:00:00 2001 From: Cidorvan Leite Date: Wed, 7 May 2008 18:34:24 +0000 Subject: g_ascii_isxdigit replaced to isxdigit function for eglib compatibility. --- serial/manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index d0a21ce6..54e052da 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -680,7 +680,7 @@ static int pattern2uuid128(const char *pattern, char *uuid, size_t size) if (pattern[i] != '-') return -EINVAL; - } else if (!g_ascii_isxdigit(pattern[i])) + } else if (!isxdigit(pattern[i])) return -EINVAL; } -- cgit From 2af3c3a7ddc43577c067892cdfdc06dc4e63386c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 17:24:48 +0000 Subject: Remove service daemon activation handling --- serial/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 9d094123..0916f760 100644 --- a/serial/main.c +++ b/serial/main.c @@ -34,6 +34,7 @@ #include "plugin.h" #include "dbus.h" +#include "dbus-service.h" #include "manager.h" static DBusConnection *conn; @@ -49,13 +50,15 @@ static int serial_init(void) return -EIO; } - register_external_service(conn, "serial", "Serial service", ""); + register_service("serial"); return 0; } static void serial_exit(void) { + unregister_service("serial"); + serial_manager_exit(); dbus_connection_unref(conn); -- cgit From b5514e6c7f0258da455bbde02482fbcdb29d4442 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 18:37:09 +0000 Subject: Register service and UUIDs in one step --- serial/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 0916f760..57a65f88 100644 --- a/serial/main.c +++ b/serial/main.c @@ -50,7 +50,7 @@ static int serial_init(void) return -EIO; } - register_service("serial"); + register_service("serial", NULL); return 0; } -- cgit From e7d668ac9e813bc9922ee7d771848bd8822d5d1f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 20:23:45 +0000 Subject: Move D-Bus watch functions into libgdbus --- serial/Makefile.am | 4 ++-- serial/main.c | 3 ++- serial/manager.c | 7 ++++--- serial/port.c | 7 ++++--- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 226ba030..2f2286bf 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -9,12 +9,12 @@ libserial_la_SOURCES = main.c \ storage.h storage.c LDADD = $(top_builddir)/common/libhelper.a \ - @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ + @GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ endif AM_LDFLAGS = -module -avoid-version -export-symbols-regex bluetooth_plugin_desc -AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ +AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@ INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/hcid -I$(top_srcdir)/sdpd diff --git a/serial/main.c b/serial/main.c index 57a65f88..b4533a01 100644 --- a/serial/main.c +++ b/serial/main.c @@ -30,10 +30,11 @@ #include #include + +#include #include #include "plugin.h" -#include "dbus.h" #include "dbus-service.h" #include "manager.h" diff --git a/serial/manager.c b/serial/manager.c index 54e052da..a10e1631 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -40,8 +40,6 @@ #include #include -#include - #include #include #include @@ -49,7 +47,10 @@ #include #include -#include "dbus.h" +#include + +#include + #include "dbus-helper.h" #include "logging.h" #include "textfile.h" diff --git a/serial/port.c b/serial/port.c index f2c0eb61..98b751be 100644 --- a/serial/port.c +++ b/serial/port.c @@ -36,12 +36,13 @@ #include #include -#include - #include #include -#include "dbus.h" +#include + +#include + #include "dbus-helper.h" #include "logging.h" -- cgit From 15ea15b3a752f0487bc50d0ea04925f1b9d33dcb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 8 May 2008 22:19:14 +0000 Subject: Move D-Bus object and interface helpers into libgdbus --- serial/manager.c | 2 -- serial/port.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index a10e1631..aa05b8f3 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -48,10 +48,8 @@ #include #include - #include -#include "dbus-helper.h" #include "logging.h" #include "textfile.h" diff --git a/serial/port.c b/serial/port.c index 98b751be..215dc62b 100644 --- a/serial/port.c +++ b/serial/port.c @@ -40,10 +40,8 @@ #include #include - #include -#include "dbus-helper.h" #include "logging.h" #include "error.h" -- cgit From f3c0a1a49b0b505b8543b5b3405bd62126be1a24 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 May 2008 09:16:32 +0000 Subject: Use -no-undefined for linking plugins --- serial/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index 2f2286bf..effb7c6f 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -12,7 +12,8 @@ LDADD = $(top_builddir)/common/libhelper.a \ @GDBUS_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ endif -AM_LDFLAGS = -module -avoid-version -export-symbols-regex bluetooth_plugin_desc +AM_LDFLAGS = -module -avoid-version -no-undefined \ + -export-symbols-regex bluetooth_plugin_desc AM_CFLAGS = @BLUEZ_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @GDBUS_CFLAGS@ -- cgit From 8cf2f361bf51ee608db71057843cd9dbdf66ff70 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 9 May 2008 21:00:02 +0000 Subject: Cleanup and removal of dbus internal calls. --- serial/manager.c | 629 +++++++++++++++++++------------------------------------ 1 file changed, 218 insertions(+), 411 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index aa05b8f3..2ad0655c 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -70,10 +70,9 @@ struct pending_connect { DBusConnection *conn; DBusMessage *msg; - char *bda; /* Destination address */ - char *adapter_path; /* Adapter D-Bus path */ + char *adapter; /* Adapter address */ + char *address; /* Destination address */ char *pattern; /* Connection request pattern */ - bdaddr_t src; uint8_t channel; char *dev; /* tty device name */ int id; /* RFCOMM device id */ @@ -143,12 +142,12 @@ static void pending_connect_free(struct pending_connect *pc) dbus_connection_unref(pc->conn); if (pc->msg) dbus_message_unref(pc->msg); - if (pc->bda) - g_free(pc->bda); + if (pc->adapter) + g_free(pc->adapter); + if (pc->address) + g_free(pc->address); if (pc->pattern) g_free(pc->pattern); - if (pc->adapter_path) - g_free(pc->adapter_path); if (pc->dev) g_free(pc->dev); g_free(pc); @@ -162,7 +161,7 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda, /* Pattern can be friendly name, uuid128, record handle or channel */ for (l = pending_connects; l != NULL; l = l->next) { struct pending_connect *pending = l->data; - if (!strcasecmp(pending->bda, bda) && + if (!strcasecmp(pending->address, bda) && !strcasecmp(pending->pattern, pattern)) return pending; } @@ -234,7 +233,7 @@ static void open_notify(int fd, int err, struct pending_connect *pc) DBUS_TYPE_STRING, &pc->dev, DBUS_TYPE_INVALID); - str2ba(pc->bda, &dst); + str2ba(pc->address, &dst); /* Add the RFCOMM connection listener */ port_add_listener(pc->conn, pc->id, &dst, fd, @@ -364,8 +363,8 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) memset(&req, 0, sizeof(req)); req.dev_id = -1; req.flags = (1 << RFCOMM_REUSE_DLC); - bacpy(&req.src, &pc->src); - str2ba(pc->bda, &req.dst); + str2ba(pc->adapter, &req.src); + str2ba(pc->address, &req.dst); req.channel = pc->channel; sk = g_io_channel_unix_get_fd(chan); @@ -392,22 +391,87 @@ fail: pending_connect_remove(pc); } -static void record_reply(DBusPendingCall *call, void *data) +static DBusHandlerResult create_channel_port(DBusConnection *conn, + DBusMessage *msg, const char *adapter, + const char *address, const char *name, + long channel, void *data) +{ + char path[MAX_PATH_LENGTH], port_name[16]; + const char *ppath = path; + DBusMessage *reply; + int err; + bdaddr_t src, dst; + + if (channel < 1 || channel > 30) + return error_invalid_arguments(conn, msg, + "invalid RFCOMM channel"); + + str2ba(adapter, &src); + str2ba(address, &dst); + err = rfcomm_bind(&src, &dst, -1, channel); + if (err < 0) + return error_failed_errno(conn, msg, -err); + + snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); + port_store(&src, &dst, err, channel, name); + port_register(conn, err, &src, &dst, port_name, path, name); + ports_paths = g_slist_append(ports_paths, g_strdup(path)); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + send_message_and_unref(conn, reply); + + dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, "PortCreated" , + DBUS_TYPE_STRING, &ppath, + DBUS_TYPE_INVALID); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult connect_pending(DBusConnection *conn, DBusMessage *msg, + struct pending_connect *pc) +{ + int err; + bdaddr_t src, dst; + + if (!g_slist_find(pending_connects, pc)) { + pending_connects = g_slist_append(pending_connects, pc); + name_listener_add(conn, dbus_message_get_sender(msg), + (name_cb_t) transaction_owner_exited, NULL); + } + + str2ba(pc->adapter, &src); + str2ba(pc->address, &dst); + + err = bt_rfcomm_connect(&src, &dst, pc->channel, rfcomm_connect_cb, pc); + if (err < 0) { + const char *strerr = strerror(-err); + error("RFCOMM connect failed: %s(%d)", strerr, -err); + pending_connects = g_slist_remove(pending_connects, pc); + pending_connect_free(pc); + return error_connection_attempt_failed(conn, msg, -err); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void record_cb(sdp_list_t *recs, int err, gpointer data) { struct pending_connect *pc; - DBusMessage *reply = dbus_pending_call_steal_reply(call); sdp_record_t *rec = NULL; - const uint8_t *rec_bin; sdp_list_t *protos; - DBusError derr; - int len, scanned, ch, err; + int ch; bdaddr_t dst; /* Owner exited? */ - if (!g_slist_find(pending_connects, data)) { - dbus_message_unref(reply); + if (!g_slist_find(pending_connects, data)) return; - } pc = data; if (pc->canceled) { @@ -415,45 +479,19 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - dbus_error_init(&derr); - if (dbus_set_error_from_message(&derr, reply)) { - /* FIXME : forward error as is */ - if (dbus_error_has_name(&derr, - "org.bluez.Error.ConnectionAttemptFailed")) - error_connection_attempt_failed(pc->conn, pc->msg, - EIO); - else - error_not_supported(pc->conn, pc->msg); - - error("GetRemoteServiceRecord: %s(%s)", - derr.name, derr.message); - dbus_error_free(&derr); - goto fail; - } - - if (!dbus_message_get_args(reply, &derr, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len, - DBUS_TYPE_INVALID)) { - error_not_supported(pc->conn, pc->msg); - error("%s: %s", derr.name, derr.message); - dbus_error_free(&derr); + if (err < 0) { + error_connection_attempt_failed(pc->conn, pc->msg, -err); goto fail; } - if (len == 0) { + if (!recs || !recs->data) { error_not_supported(pc->conn, pc->msg); error("Invalid service record length"); goto fail; } - rec = sdp_extract_pdu(rec_bin, &scanned); - if (!rec) { - error("Can't extract SDP record."); - error_not_supported(pc->conn, pc->msg); - goto fail; - } - - if (len != scanned || (sdp_get_access_protos(rec, &protos) < 0)) { + rec = recs->data; + if (sdp_get_access_protos(rec, &protos) < 0) { error_not_supported(pc->conn, pc->msg); goto fail; } @@ -468,21 +506,11 @@ static void record_reply(DBusPendingCall *call, void *data) goto fail; } - str2ba(pc->bda, &dst); + str2ba(pc->address, &dst); if (dbus_message_has_member(pc->msg, "CreatePort")) { - char path[MAX_PATH_LENGTH], port_name[16]; - const char *ppath = path; sdp_data_t *d; char *svcname = NULL; - DBusMessage *reply; - - err = rfcomm_bind(&pc->src, &dst, -1, ch); - if (err < 0) { - error_failed_errno(pc->conn, pc->msg, -err); - goto fail; - } - snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); if (d) { @@ -491,36 +519,16 @@ static void record_reply(DBusPendingCall *call, void *data) d->unitSize, d->val.str); } - port_store(&pc->src, &dst, err, ch, svcname); + create_channel_port(pc->conn, pc->msg, pc->adapter, + pc->address, svcname, ch, data); - port_register(pc->conn, err, &pc->src, &dst, port_name, - path, svcname); if (svcname) g_free(svcname); - - ports_paths = g_slist_append(ports_paths, g_strdup(path)); - - reply = dbus_message_new_method_return(pc->msg); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - send_message_and_unref(pc->conn, reply); - - dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortCreated" , - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); } else { /* ConnectService */ pc->channel = ch; - err = bt_rfcomm_connect(&pc->src, &dst, ch, rfcomm_connect_cb, pc); - if (err < 0) { - error("RFCOMM connection failed"); - error_connection_attempt_failed(pc->conn, - pc->msg, -err); - goto fail; - } + connect_pending(pc->conn, pc->msg, pc); /* Wait the connect callback */ goto done; @@ -529,132 +537,47 @@ static void record_reply(DBusPendingCall *call, void *data) fail: pending_connect_remove(pc); done: - if (rec) - sdp_record_free(rec); - dbus_message_unref(reply); + if (recs) + sdp_list_free(recs, (sdp_free_func_t) sdp_record_free); } -static int get_record(struct pending_connect *pc, uint32_t handle, - DBusPendingCallNotifyFunction cb) -{ - DBusMessage *msg; - DBusPendingCall *call; - - msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, - "org.bluez.Adapter", "GetRemoteServiceRecord"); - if (!msg) - return -1; - - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &pc->bda, - DBUS_TYPE_UINT32, &handle, - DBUS_TYPE_INVALID); - - if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) { - error("Can't send D-Bus message."); - dbus_message_unref(msg); - return -1; - } - - dbus_pending_call_set_notify(call, cb, pc, NULL); - dbus_pending_call_unref(call); - dbus_message_unref(msg); - - return 0; -} - -static void handles_reply(DBusPendingCall *call, void *data) +static int str2uuid(uuid_t *uuid, const char *string) { - struct pending_connect *pc; - DBusMessage *reply = dbus_pending_call_steal_reply(call); - DBusError derr; - uint32_t *phandle; - int len; - - /* Owner exited? */ - if (!g_slist_find(pending_connects, data)) { - dbus_message_unref(reply); - return; - } - - pc = data; - if (pc->canceled) { - error_canceled(pc->conn, pc->msg, "Connection canceled"); - goto fail; - } - - dbus_error_init(&derr); - if (dbus_set_error_from_message(&derr, reply)) { - /* FIXME : forward error as is */ - if (dbus_error_has_name(&derr, - "org.bluez.Error.ConnectionAttemptFailed")) - error_connection_attempt_failed(pc->conn, - pc->msg, EIO); - else - error_not_supported(pc->conn, pc->msg); - - error("GetRemoteServiceHandles: %s(%s)", - derr.name, derr.message); - dbus_error_free(&derr); - goto fail; - } - - if (!dbus_message_get_args(reply, &derr, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, - &len, DBUS_TYPE_INVALID)) { - error_not_supported(pc->conn, pc->msg); - error("%s: %s", derr.name, derr.message); - dbus_error_free(&derr); - goto fail; - } - - if (len == 0) { - error_not_supported(pc->conn, pc->msg); - goto fail; - } - - if (get_record(pc, *phandle, record_reply) < 0) { - error_not_supported(pc->conn, pc->msg); - goto fail; - } + uint16_t data1, data2, data3, data5; + uint32_t data0, data4; - dbus_message_unref(reply); - return; -fail: - dbus_message_unref(reply); - pending_connect_remove(pc); -} + 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]; -static int get_handles(struct pending_connect *pc, const char *uuid, - DBusPendingCallNotifyFunction cb) -{ - DBusMessage *msg; - DBusPendingCall *call; + data0 = htonl(data0); + data1 = htons(data1); + data2 = htons(data2); + data3 = htons(data3); + data4 = htonl(data4); + data5 = htons(data5); - msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, - "org.bluez.Adapter", "GetRemoteServiceHandles"); - if (!msg) - return -1; + 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); - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &pc->bda, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INVALID); + sdp_uuid128_create(uuid, val); - if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) { - error("Can't send D-Bus message."); - dbus_message_unref(msg); - return -1; + return 0; } - dbus_pending_call_set_notify(call, cb, pc, NULL); - dbus_pending_call_unref(call); - dbus_message_unref(msg); - - return 0; + return -1; } -static int pattern2uuid128(const char *pattern, char *uuid, size_t size) +static int pattern2uuid(const char *pattern, uuid_t *uuid) { uint16_t cls; int i; @@ -662,11 +585,7 @@ static int pattern2uuid128(const char *pattern, char *uuid, size_t size) /* Friendly name */ cls = str2class(pattern); if (cls) { - uuid_t uuid16, uuid128; - - sdp_uuid16_create(&uuid16, cls); - sdp_uuid16_to_uuid128(&uuid128, &uuid16); - sdp_uuid2strn(&uuid128, uuid, size); + sdp_uuid16_create(uuid, cls); return 0; } @@ -683,7 +602,7 @@ static int pattern2uuid128(const char *pattern, char *uuid, size_t size) return -EINVAL; } - strncpy(uuid, pattern, size); + str2uuid(uuid, pattern); return 0; } @@ -704,21 +623,53 @@ static int pattern2long(const char *pattern, long *pval) return 0; } +static DBusHandlerResult search_uuid(DBusConnection *conn, DBusMessage *msg, + const char *adapter, const char *address, + const char *pattern, uuid_t *uuid, void *data) +{ + struct pending_connect *pc; + int err; + bdaddr_t src, dst; + + pc = g_new0(struct pending_connect, 1); + pc->conn = dbus_connection_ref(conn); + pc->msg = dbus_message_ref(msg); + pc->adapter = g_strdup(adapter); + pc->address = g_strdup(address); + pc->id = -1; + pc->pattern = g_strdup(pattern); + + str2ba(adapter, &src); + str2ba(address, &dst); + + err = bt_search_service(&src, &dst, uuid, record_cb, pc, NULL); + if (err < 0) { + pending_connect_free(pc); + return error_not_supported(conn, msg); + } + + pending_connects = g_slist_append(pending_connects, pc); + name_listener_add(conn, dbus_message_get_sender(msg), + (name_cb_t) transaction_owner_exited, NULL); + + return DBUS_HANDLER_RESULT_HANDLED; +} + static DBusHandlerResult create_port(DBusConnection *conn, DBusMessage *msg, void *data) { - char path[MAX_PATH_LENGTH], port_name[16], uuid[MAX_LEN_UUID_STR]; - const char *bda, *pattern, *ppath = path; - struct pending_connect *pending, *pc; - DBusMessage *reply; + const char *address, *pattern; + struct pending_connect *pending; DBusError derr; - bdaddr_t src, dst; long val; - int dev_id, err; + uuid_t uuid; + char adp[18]; + int dev_id; + bdaddr_t src; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { error_invalid_arguments(conn, msg, derr.message); @@ -726,92 +677,27 @@ static DBusHandlerResult create_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - pending = find_pending_connect_by_pattern(bda, pattern); - if (pending) - return error_in_progress(conn, msg, "Connection in progress"); - dev_id = hci_get_route(NULL); - if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) return error_failed(conn, msg, "Adapter not available"); - pc = g_new0(struct pending_connect, 1); - bacpy(&pc->src, &src); - pc->conn = dbus_connection_ref(conn); - pc->msg = dbus_message_ref(msg); - pc->bda = g_strdup(bda); - pc->id = -1; - pc->pattern = g_strdup(pattern); - pc->adapter_path = g_malloc0(16); - snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); + pending = find_pending_connect_by_pattern(address, pattern); + if (pending) + return error_in_progress(conn, msg, "Connection in progress"); - memset(uuid, 0, sizeof(uuid)); + ba2str(&src, adp); /* Friendly name or uuid128 */ - if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) { - if (get_handles(pc, uuid, handles_reply) < 0) { - pending_connect_free(pc); - return error_not_supported(conn, msg); - } - pending_connects = g_slist_append(pending_connects, pc); - name_listener_add(conn, dbus_message_get_sender(msg), - (name_cb_t) transaction_owner_exited, NULL); - return DBUS_HANDLER_RESULT_HANDLED; - } + if (pattern2uuid(pattern, &uuid) == 0) + return search_uuid(conn, msg, adp, address, pattern, &uuid, + data); - /* Record handle or channel */ - err = pattern2long(pattern, &val); - if (err < 0) { - pending_connect_free(pc); - return error_invalid_arguments(conn, msg, "invalid pattern"); - } - - /* Record handle: starts at 0x10000 */ - if (strncasecmp("0x", pattern, 2) == 0) { - if (val < 0x10000) { - pending_connect_free(pc); - return error_invalid_arguments(conn, msg, - "invalid record handle"); - } + /* RFCOMM Channel */ + if (pattern2long(pattern, &val) == 0) + return create_channel_port(conn, msg, adp, address, pattern, + val, data); - if (get_record(pc, val, record_reply) < 0) { - pending_connect_free(pc); - return error_not_supported(conn, msg); - } - pending_connects = g_slist_append(pending_connects, pc); - name_listener_add(conn, dbus_message_get_sender(msg), - (name_cb_t) transaction_owner_exited, NULL); - return DBUS_HANDLER_RESULT_HANDLED; - } - - pending_connect_free(pc); - /* RFCOMM Channel range: 1 - 30 */ - if (val < 1 || val > 30) - return error_invalid_arguments(conn, msg, - "invalid RFCOMM channel"); - - str2ba(bda, &dst); - err = rfcomm_bind(&src, &dst, -1, val); - if (err < 0) - return error_failed_errno(conn, msg, -err); - - snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); - port_store(&src, &dst, err, val, NULL); - port_register(conn, err, &src, &dst, port_name, path, NULL); - ports_paths = g_slist_append(ports_paths, g_strdup(path)); - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - send_message_and_unref(conn, reply); - - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, "PortCreated" , - DBUS_TYPE_STRING, &ppath, - DBUS_TYPE_INVALID); - return DBUS_HANDLER_RESULT_HANDLED; + return error_invalid_arguments(conn, msg, "invalid pattern"); } static void message_append_paths(DBusMessage *msg, const GSList *list) @@ -951,42 +837,6 @@ static void add_lang_attr(sdp_record_t *r) sdp_list_free(langs, 0); } -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 sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel) { sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; @@ -1847,108 +1697,70 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn, dbus_message_new_method_return(msg)); } -static DBusHandlerResult connect_service_from_devid(DBusConnection *conn, - DBusMessage *msg, void *data, int dev_id, - const char *bda, const char *pattern) +static DBusHandlerResult connect_channel(DBusConnection *conn, DBusMessage *msg, + const char *adapter, const char *address, + const char *pattern, long channel, void *data) { - struct pending_connect *pending, *pc; - bdaddr_t src, dst; - long val; - int err; - char uuid[MAX_LEN_UUID_STR]; - - pending = find_pending_connect_by_pattern(bda, pattern); - if (pending) - return error_in_progress(conn, msg, "Connection in progress"); + struct pending_connect *pc; - if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) - return error_failed(conn, msg, "Adapter not available"); + if (channel < 1 || channel > 30) + return error_invalid_arguments(conn, msg, + "invalid RFCOMM channel"); pc = g_new0(struct pending_connect, 1); - bacpy(&pc->src, &src); pc->conn = dbus_connection_ref(conn); pc->msg = dbus_message_ref(msg); - pc->bda = g_strdup(bda); + pc->adapter = g_strdup(adapter); + pc->address = g_strdup(address); pc->id = -1; pc->pattern = g_strdup(pattern); - pc->adapter_path = g_malloc0(16); - snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); - - memset(uuid, 0, sizeof(uuid)); - - /* Friendly name or uuid128 */ - if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) { - if (get_handles(pc, uuid, handles_reply) < 0) { - pending_connect_free(pc); - return error_not_supported(conn, msg); - } - pending_connects = g_slist_append(pending_connects, pc); - goto done; - } - - /* Record handle or channel */ - err = pattern2long(pattern, &val); - if (err < 0) { - pending_connect_free(pc); - return error_invalid_arguments(conn, msg, "invalid pattern"); - } + pc->channel = channel; - /* Record handle: starts at 0x10000 */ - if (strncasecmp("0x", pattern, 2) == 0) { - if (val < 0x10000) { - pending_connect_free(pc); - return error_invalid_arguments(conn, msg, - "invalid record handle"); - } - - if (get_record(pc, val, record_reply) < 0) { - pending_connect_free(pc); - return error_not_supported(conn, msg); - } - pending_connects = g_slist_append(pending_connects, pc); - goto done; - } + return connect_pending(conn, msg, pc); +} - /* RFCOMM Channel range: 1 - 30 */ - if (val < 1 || val > 30) { - pending_connect_free(pc); - return error_invalid_arguments(conn, msg, - "invalid RFCOMM channel"); - } +static DBusHandlerResult service_connect(DBusConnection *conn, DBusMessage *msg, + const char *adapter, const char *address, + const char *pattern, void *data) +{ + int dev_id; + bdaddr_t src; + char adp[18]; + uuid_t uuid; + long val; - /* Add here since connect() in the first try can happen */ - pending_connects = g_slist_append(pending_connects, pc); + if (!adapter) + dev_id = hci_get_route(NULL); + else + dev_id = hci_devid(adapter); - pc->channel = val; + if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) + return error_failed(conn, msg, "Adapter not available"); - str2ba(pc->bda, &dst); + ba2str(&src, adp); - err = bt_rfcomm_connect(&pc->src, &dst, val, rfcomm_connect_cb, pc); + /* Friendly name or uuid128 */ + if (pattern2uuid(pattern, &uuid) == 0) + return search_uuid(conn, msg, adp, address, pattern, &uuid, + data); - if (err < 0) { - const char *strerr = strerror(-err); - error("RFCOMM connect failed: %s(%d)", strerr, -err); - pending_connects = g_slist_remove(pending_connects, pc); - pending_connect_free(pc); - return error_connection_attempt_failed(conn, msg, -err); - } -done: - name_listener_add(conn, dbus_message_get_sender(msg), - (name_cb_t) transaction_owner_exited, NULL); + /* RFCOMM Channel */ + if (pattern2long(pattern, &val) == 0) + return connect_channel(conn, msg, adp, address, pattern, + val, data); - return DBUS_HANDLER_RESULT_HANDLED; + return error_invalid_arguments(conn, msg, "invalid pattern"); } static DBusHandlerResult connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { DBusError derr; - const char *bda, *pattern; - int devid; + const char *address, *pattern; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, - DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { error_invalid_arguments(conn, msg, derr.message); @@ -1956,22 +1768,19 @@ static DBusHandlerResult connect_service(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - devid = hci_get_route(NULL); - - return connect_service_from_devid(conn, msg, data, devid, bda, pattern); + return service_connect(conn, msg, NULL, address, pattern, data); } static DBusHandlerResult connect_service_from_adapter(DBusConnection *conn, DBusMessage *msg, void *data) { DBusError derr; - const char *adapter, *bda, *pattern; - int devid; + const char *adapter, *address, *pattern; dbus_error_init(&derr); if (!dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &adapter, - DBUS_TYPE_STRING, &bda, + DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { error_invalid_arguments(conn, msg, derr.message); @@ -1979,9 +1788,7 @@ static DBusHandlerResult connect_service_from_adapter(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - devid = hci_devid(adapter); - - return connect_service_from_devid(conn, msg, data, devid, bda, pattern); + return service_connect(conn, msg, adapter, address, pattern, data); } static DBusHandlerResult disconnect_service(DBusConnection *conn, -- cgit From 0094809955895c974fbe95f2d3ed13f420a6a6ed Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 14 May 2008 22:16:16 +0000 Subject: Make bt_io_callback_t to take both source and destination. --- serial/manager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 2ad0655c..f67a6f89 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -337,7 +337,8 @@ static int rfcomm_bind(bdaddr_t *src, bdaddr_t *dst, int16_t dev_id, uint8_t ch) return id; } -static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data) +static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, const bdaddr_t *src, + const bdaddr_t *dst, gpointer user_data) { struct pending_connect *pc = user_data; struct rfcomm_dev_req req; -- cgit From 624ddeeb67145cdb8cc2b0dc0c7410e76aaa9fa9 Mon Sep 17 00:00:00 2001 From: Cidorvan Leite Date: Thu, 15 May 2008 13:36:26 +0000 Subject: str2uuid function moved to common --- serial/manager.c | 42 +++--------------------------------------- 1 file changed, 3 insertions(+), 39 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index f67a6f89..88160021 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -542,42 +542,6 @@ done: sdp_list_free(recs, (sdp_free_func_t) sdp_record_free); } -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 int pattern2uuid(const char *pattern, uuid_t *uuid) { uint16_t cls; @@ -603,7 +567,7 @@ static int pattern2uuid(const char *pattern, uuid_t *uuid) return -EINVAL; } - str2uuid(uuid, pattern); + bt_string2uuid(uuid, pattern); return 0; } @@ -855,7 +819,7 @@ static sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel) sdp_set_browse_groups(record, root); sdp_list_free(root, NULL); - str2uuid(&uuid, uuid128); + bt_string2uuid(&uuid, uuid128); svclass_id = sdp_list_append(NULL, &uuid); sdp_set_service_classes(record, svclass_id); sdp_list_free(svclass_id, NULL); @@ -1589,7 +1553,7 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - if (str2uuid(&uuid, uuid128) < 0) + if (bt_string2uuid(&uuid, uuid128) < 0) return error_invalid_arguments(conn, msg, "Invalid UUID"); type = addr2type(address); -- cgit From e9f3959fb8c5e4ac323410348013d7c7041146a7 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 16 May 2008 22:29:53 +0000 Subject: Make serial service to use bt_rfcomm_listen_allocate. --- serial/manager.c | 97 ++++++++++++-------------------------------------------- 1 file changed, 20 insertions(+), 77 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 88160021..2a8fc619 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -744,50 +744,6 @@ static DBusHandlerResult remove_port(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } -static int rfcomm_listen(bdaddr_t *src, uint8_t *channel, int opts) -{ - struct sockaddr_rc laddr; - socklen_t alen; - int err, sk; - - sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) - return -errno; - - if (setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opts, sizeof(opts)) < 0) - goto fail; - - memset(&laddr, 0, sizeof(laddr)); - laddr.rc_family = AF_BLUETOOTH; - bacpy(&laddr.rc_bdaddr, src); - laddr.rc_channel = (channel ? *channel : 0); - - alen = sizeof(laddr); - if (bind(sk, (struct sockaddr *) &laddr, alen) < 0) - goto fail; - - if (listen(sk, 1) < 0) - goto fail; - - if (!channel) - return sk; - - memset(&laddr, 0, sizeof(laddr)); - if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) - goto fail; - - *channel = laddr.rc_channel; - - return sk; - -fail: - err = errno; - close(sk); - errno = err; - - return -err; -} - static void add_lang_attr(sdp_record_t *r) { sdp_lang_attr_t base_lang; @@ -1017,32 +973,21 @@ static inline int tty_open(const char *tty, struct termios *ti) return sk; } -static gboolean connect_event(GIOChannel *chan, - GIOCondition cond, gpointer data) +static void connect_event_cb(GIOChannel *chan, int err, const bdaddr_t *src, + const bdaddr_t *dst, gpointer data) { struct proxy *prx = data; - struct sockaddr_rc raddr; GIOChannel *rio, *lio; - socklen_t alen; - int sk, rsk, lsk; + int rsk, lsk; - if (cond & G_IO_NVAL) - return FALSE; - - if (cond & (G_IO_ERR | G_IO_HUP)) { - g_io_channel_close(chan); - return FALSE; + if (err < 0) { + error("accept: %s (%d)", strerror(-err), -err); + return; } - sk = g_io_channel_unix_get_fd(chan); - - memset(&raddr, 0, sizeof(raddr)); - alen = sizeof(raddr); - rsk = accept(sk, (struct sockaddr *) &raddr, &alen); - if (rsk < 0) - return TRUE; + rsk = g_io_channel_unix_get_fd(chan); - bacpy(&prx->dst, &raddr.rc_bdaddr); + bacpy(&prx->dst, dst); switch (prx->type) { case UNIX_SOCKET_PROXY: @@ -1059,8 +1004,8 @@ static gboolean connect_event(GIOChannel *chan, } if (lsk < 0) { - close(rsk); - return TRUE; + g_io_channel_unref(chan); + return; } rio = g_io_channel_unix_new(rsk); @@ -1079,7 +1024,7 @@ static gboolean connect_event(GIOChannel *chan, g_io_channel_unref(rio); g_io_channel_unref(lio); - return TRUE; + return; } static void listen_watch_notify(gpointer data) @@ -1108,42 +1053,40 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, struct proxy *prx = data; GIOChannel *io; sdp_record_t *record; - int sk; if (prx->listen_watch) return error_failed(conn, msg, "Already enabled"); /* Listen */ - /* FIXME: missing options */ - sk = rfcomm_listen(&prx->src, &prx->channel, 0); - if (sk < 0) { + io = bt_rfcomm_listen_allocate(&prx->src, &prx->channel, 0, + connect_event_cb, prx); + if (!io) { const char *strerr = strerror(errno); error("RFCOMM listen socket failed: %s(%d)", strerr, errno); return error_failed(conn, msg, strerr); } + g_io_channel_set_close_on_unref(io, TRUE); + record = proxy_record_new(prx->uuid128, prx->channel); if (!record) { - close(sk); + g_io_channel_unref(io); return error_failed(conn, msg, "Unable to allocate new service record"); } if (add_record_to_server(&prx->src, record) < 0) { - close(sk); sdp_record_free(record); + g_io_channel_unref(io); return error_failed(conn, msg, "Service registration failed"); } prx->record_id = record->handle; /* Add incomming connection watch */ - io = g_io_channel_unix_new(sk); - g_io_channel_set_close_on_unref(io, TRUE); prx->listen_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - connect_event, prx, listen_watch_notify); - g_io_channel_unref(io); + G_IO_HUP | G_IO_ERR | G_IO_NVAL, + NULL, prx, listen_watch_notify); return send_message_and_unref(conn, dbus_message_new_method_return(msg)); -- cgit From 30751fe0c0430e0757c018de4f8e6bceee5e85f7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 20 May 2008 21:54:12 +0000 Subject: Fix issues with missing include for PATH_MAX --- serial/manager.c | 1 + 1 file changed, 1 insertion(+) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 2a8fc619..388ed473 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include -- cgit From d1baca10987d6cb192bc24324571e7b308dc0fec Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 22 May 2008 14:38:27 +0000 Subject: Fix memory leak on proxy disable and some code cleanups. --- serial/manager.c | 104 ++++++++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 58 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 388ed473..eb1be7ff 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -118,7 +118,7 @@ struct proxy { struct termios proxy_ti; /* Proxy TTY settings */ uint8_t channel; /* RFCOMM channel */ uint32_t record_id; /* Service record id */ - guint listen_watch; /* Server listen watch */ + GIOChannel *io; /* Server listen */ guint rfcomm_watch; /* RFCOMM watch: Remote */ guint local_watch; /* Local watch: TTY or Unix socket */ }; @@ -130,6 +130,25 @@ static GSList *proxies_paths = NULL; static int rfcomm_ctl = -1; static int sk_counter = 0; +static void disable_proxy(struct proxy *prx) +{ + if (prx->rfcomm_watch) { + g_source_remove(prx->rfcomm_watch); + prx->rfcomm_watch = 0; + } + + if (prx->local_watch) { + g_source_remove(prx->local_watch); + prx->local_watch = 0; + } + + remove_record_from_server(prx->record_id); + prx->record_id = 0; + + g_io_channel_unref(prx->io); + prx->io = NULL; +} + static void proxy_free(struct proxy *prx) { g_free(prx->address); @@ -978,117 +997,88 @@ static void connect_event_cb(GIOChannel *chan, int err, const bdaddr_t *src, const bdaddr_t *dst, gpointer data) { struct proxy *prx = data; - GIOChannel *rio, *lio; - int rsk, lsk; + GIOChannel *io; + int sk; if (err < 0) { error("accept: %s (%d)", strerror(-err), -err); return; } - rsk = g_io_channel_unix_get_fd(chan); - bacpy(&prx->dst, dst); switch (prx->type) { case UNIX_SOCKET_PROXY: - lsk = unix_socket_connect(prx->address); + sk = unix_socket_connect(prx->address); break; case TTY_PROXY: - lsk = tty_open(prx->address, &prx->proxy_ti); + sk = tty_open(prx->address, &prx->proxy_ti); break; case TCP_SOCKET_PROXY: - lsk = tcp_socket_connect(prx->address); + sk = tcp_socket_connect(prx->address); break; default: - lsk = -1; + sk = -1; } - if (lsk < 0) { + if (sk < 0) { g_io_channel_unref(chan); return; } - rio = g_io_channel_unix_new(rsk); - g_io_channel_set_close_on_unref(rio, TRUE); - lio = g_io_channel_unix_new(lsk); - g_io_channel_set_close_on_unref(lio, TRUE); + g_io_channel_set_close_on_unref(chan, TRUE); + io = g_io_channel_unix_new(sk); + g_io_channel_set_close_on_unref(io, TRUE); - prx->rfcomm_watch = g_io_add_watch(rio, + prx->rfcomm_watch = g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - forward_data, lio); + forward_data, io); - prx->local_watch = g_io_add_watch(lio, + prx->local_watch = g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - forward_data, rio); + forward_data, chan); - g_io_channel_unref(rio); - g_io_channel_unref(lio); + g_io_channel_unref(chan); + g_io_channel_unref(io); return; } -static void listen_watch_notify(gpointer data) -{ - struct proxy *prx = data; - - prx->listen_watch = 0; - - if (prx->rfcomm_watch) { - g_source_remove(prx->rfcomm_watch); - prx->rfcomm_watch = 0; - } - - if (prx->local_watch) { - g_source_remove(prx->local_watch); - prx->local_watch = 0; - } - - remove_record_from_server(prx->record_id); - prx->record_id = 0; -} - static DBusHandlerResult proxy_enable(DBusConnection *conn, DBusMessage *msg, void *data) { struct proxy *prx = data; - GIOChannel *io; sdp_record_t *record; - if (prx->listen_watch) + if (prx->io) return error_failed(conn, msg, "Already enabled"); /* Listen */ - io = bt_rfcomm_listen_allocate(&prx->src, &prx->channel, 0, + prx->io = bt_rfcomm_listen_allocate(&prx->src, &prx->channel, 0, connect_event_cb, prx); - if (!io) { + if (!prx->io) { const char *strerr = strerror(errno); error("RFCOMM listen socket failed: %s(%d)", strerr, errno); return error_failed(conn, msg, strerr); } - g_io_channel_set_close_on_unref(io, TRUE); + g_io_channel_set_close_on_unref(prx->io, TRUE); record = proxy_record_new(prx->uuid128, prx->channel); if (!record) { - g_io_channel_unref(io); + g_io_channel_unref(prx->io); return error_failed(conn, msg, "Unable to allocate new service record"); } if (add_record_to_server(&prx->src, record) < 0) { sdp_record_free(record); - g_io_channel_unref(io); + g_io_channel_unref(prx->io); return error_failed(conn, msg, "Service registration failed"); } prx->record_id = record->handle; - /* Add incomming connection watch */ - prx->listen_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT, - G_IO_HUP | G_IO_ERR | G_IO_NVAL, - NULL, prx, listen_watch_notify); - return send_message_and_unref(conn, dbus_message_new_method_return(msg)); } @@ -1098,11 +1088,11 @@ static DBusHandlerResult proxy_disable(DBusConnection *conn, { struct proxy *prx = data; - if (!prx->listen_watch) + if (!prx->io) return error_failed(conn, msg, "Not enabled"); - /* Remove the watches and unregister the record: see watch notify */ - g_source_remove(prx->listen_watch); + /* Remove the watches and unregister the record */ + disable_proxy(prx); return send_message_and_unref(conn, dbus_message_new_method_return(msg)); @@ -1137,7 +1127,7 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, dbus_message_iter_append_dict_entry(&dict, "channel", DBUS_TYPE_BYTE, &prx->channel); - boolean = (prx->listen_watch ? TRUE : FALSE); + boolean = (prx->io ? TRUE : FALSE); dbus_message_iter_append_dict_entry(&dict, "enabled", DBUS_TYPE_BOOLEAN, &boolean); @@ -1328,8 +1318,6 @@ static void proxy_handler_unregister(DBusConnection *conn, void *data) } done: - if (prx->listen_watch) - g_source_remove(prx->listen_watch); proxy_free(prx); } -- cgit From 649448818704cd93136d55d33676ad80cb463224 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 27 May 2008 21:31:12 +0000 Subject: Use guint identifier for all name_listener operations --- serial/manager.c | 2 +- serial/port.c | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index eb1be7ff..095abf6b 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -257,7 +257,7 @@ static void open_notify(int fd, int err, struct pending_connect *pc) /* Add the RFCOMM connection listener */ port_add_listener(pc->conn, pc->id, &dst, fd, - pc->dev, dbus_message_get_sender(pc->msg)); + pc->dev, dbus_message_get_sender(pc->msg)); } static gboolean open_continue(struct pending_connect *pc) diff --git a/serial/port.c b/serial/port.c index 215dc62b..0e2ad200 100644 --- a/serial/port.c +++ b/serial/port.c @@ -60,6 +60,7 @@ struct rfcomm_node { char *owner; /* Bus name */ GIOChannel *io; /* Connected node IO Channel */ guint io_id; /* IO Channel ID */ + guint listener_id; }; static GSList *connected_nodes = NULL; @@ -243,8 +244,10 @@ static void rfcomm_node_free(struct rfcomm_node *node) g_free(node); } -static void connection_owner_exited(const char *name, struct rfcomm_node *node) +static void connection_owner_exited(const char *name, void *user_data) { + struct rfcomm_node *node = user_data; + debug("Connect requestor %s exited. Releasing %s node", name, node->device); @@ -262,8 +265,7 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, { debug("RFCOMM node %s was disconnected", node->device); - name_listener_remove(node->conn, node->owner, - (name_cb_t) connection_owner_exited, node); + name_listener_id_remove(node->listener_id); dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , @@ -286,7 +288,7 @@ static void port_handler_unregister(DBusConnection *conn, void *data) rfcomm_node_free(node); } -int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, +void port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, int fd, const char *dev, const char *owner) { struct rfcomm_node *node; @@ -304,8 +306,8 @@ int port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, connected_nodes = g_slist_append(connected_nodes, node); /* Service connection listener */ - return name_listener_add(conn, owner, - (name_cb_t) connection_owner_exited, node); + node->listener_id = name_listener_add(conn, owner, + connection_owner_exited, node); } int port_remove_listener(const char *owner, const char *dev) @@ -318,8 +320,7 @@ int port_remove_listener(const char *owner, const char *dev) if (strcmp(node->owner, owner) != 0) return -EPERM; - name_listener_remove(node->conn, owner, - (name_cb_t) connection_owner_exited, node); + name_listener_id_remove(node->listener_id); connected_nodes = g_slist_remove(connected_nodes, node); rfcomm_node_free(node); -- cgit From 24cce397c3479e95f3e525da9285234fbafd2984 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 May 2008 13:11:05 +0000 Subject: Add first skeletion of device driver integration --- serial/main.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index b4533a01..24de70a5 100644 --- a/serial/main.c +++ b/serial/main.c @@ -35,11 +35,32 @@ #include #include "plugin.h" +#include "device.h" +#include "logging.h" #include "dbus-service.h" #include "manager.h" static DBusConnection *conn; +static int serial_probe(const char *path) +{ + debug("path %s", path); + + return 0; +} + +static void serial_remove(const char *path) +{ + debug("path %s", path); +} + +static struct btd_device_driver serial_driver = { + .name = "serial", + .uuids = BTD_UUIDS("spp", "dun"), + .probe = serial_probe, + .remove = serial_remove, +}; + static int serial_init(void) { conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); @@ -53,11 +74,15 @@ static int serial_init(void) register_service("serial", NULL); + btd_register_device_driver(&serial_driver); + return 0; } static void serial_exit(void) { + btd_unregister_device_driver(&serial_driver); + unregister_service("serial"); serial_manager_exit(); -- cgit From a1a1a2637ec9090c021dd83ed7707aabf5a8c0f4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 May 2008 13:22:23 +0000 Subject: Add basic D-Bus skeleton --- serial/main.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 24de70a5..fcff75f5 100644 --- a/serial/main.c +++ b/serial/main.c @@ -31,8 +31,7 @@ #include -#include -#include +#include #include "plugin.h" #include "device.h" @@ -40,18 +39,54 @@ #include "dbus-service.h" #include "manager.h" +#define SERIAL_INTERFACE "org.bluez.Serial" + +static DBusMessage *serial_connect(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + const char *target, *device = "/dev/rfcomm0"; + + if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &target, + DBUS_TYPE_INVALID) == FALSE) + return NULL; + + return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &device, + DBUS_TYPE_INVALID); +} + +static DBusMessage *serial_disconnect(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + const char *device; + + if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &device, + DBUS_TYPE_INVALID) == FALSE) + return NULL; + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); +} + +static GDBusMethodTable serial_methods[] = { + { "Connect", "s", "s", serial_connect }, + { "Disconnect", "s", "", serial_disconnect }, + { } +}; + static DBusConnection *conn; static int serial_probe(const char *path) { debug("path %s", path); - return 0; + return g_dbus_register_interface(conn, path, SERIAL_INTERFACE, + serial_methods, NULL, NULL, NULL, NULL); } static void serial_remove(const char *path) { debug("path %s", path); + + g_dbus_unregister_interface(conn, path, SERIAL_INTERFACE); } static struct btd_device_driver serial_driver = { -- cgit From de29b2ff1d8531fd0583e49e4b8840198681ffe8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 29 May 2008 07:39:11 +0000 Subject: Handle the service UUID mapping via device driver --- serial/main.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index fcff75f5..d0d24982 100644 --- a/serial/main.c +++ b/serial/main.c @@ -36,7 +36,6 @@ #include "plugin.h" #include "device.h" #include "logging.h" -#include "dbus-service.h" #include "manager.h" #define SERIAL_INTERFACE "org.bluez.Serial" @@ -107,8 +106,6 @@ static int serial_init(void) return -EIO; } - register_service("serial", NULL); - btd_register_device_driver(&serial_driver); return 0; @@ -118,8 +115,6 @@ static void serial_exit(void) { btd_unregister_device_driver(&serial_driver); - unregister_service("serial"); - serial_manager_exit(); dbus_connection_unref(conn); -- cgit From cc0f97ec2cb298bde87cd3753fd96f11ce41ff64 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 29 May 2008 14:43:27 +0000 Subject: Change name_listener API to libgdbus watch API --- serial/manager.c | 40 ++++++++++++++++------------------------ serial/port.c | 17 +++++++++-------- 2 files changed, 25 insertions(+), 32 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 095abf6b..3d5b6e88 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -79,6 +79,7 @@ struct pending_connect { int id; /* RFCOMM device id */ int ntries; /* Open attempts */ int canceled; /* Operation canceled */ + guint listener_id; }; /* FIXME: Common file required */ @@ -189,35 +190,23 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda, return NULL; } -static void transaction_owner_exited(const char *name, void *data) +static void transaction_owner_exited(void *data) { - GSList *l, *tmp = NULL; - debug("transaction owner %s exited", name); + struct pending_connect *pc = data; - /* Remove all pending calls that belongs to this owner */ - for (l = pending_connects; l != NULL; l = l->next) { - struct pending_connect *pc = l->data; - if (strcmp(name, dbus_message_get_sender(pc->msg)) != 0) { - tmp = g_slist_append(tmp, pc); - continue; - } + debug("transaction owner exited"); - if (pc->id >= 0) - rfcomm_release(pc->id); + if (pc->id >= 0) + rfcomm_release(pc->id); - pending_connect_free(pc); - } + pending_connects = g_slist_remove(pending_connects, pc); - g_slist_free(pending_connects); - pending_connects = tmp; + pending_connect_free(pc); } static void pending_connect_remove(struct pending_connect *pc) { - /* Remove the connection request owner */ - name_listener_remove(pc->conn, dbus_message_get_sender(pc->msg), - (name_cb_t) transaction_owner_exited, NULL); - + g_dbus_remove_watch(pc->conn, pc->listener_id); pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); } @@ -463,8 +452,10 @@ static DBusHandlerResult connect_pending(DBusConnection *conn, DBusMessage *msg, if (!g_slist_find(pending_connects, pc)) { pending_connects = g_slist_append(pending_connects, pc); - name_listener_add(conn, dbus_message_get_sender(msg), - (name_cb_t) transaction_owner_exited, NULL); + pc->listener_id = g_dbus_add_disconnect_watch(conn, + dbus_message_get_sender(msg), + transaction_owner_exited, pc, + NULL); } str2ba(pc->adapter, &src); @@ -634,8 +625,9 @@ static DBusHandlerResult search_uuid(DBusConnection *conn, DBusMessage *msg, } pending_connects = g_slist_append(pending_connects, pc); - name_listener_add(conn, dbus_message_get_sender(msg), - (name_cb_t) transaction_owner_exited, NULL); + pc->listener_id = g_dbus_add_disconnect_watch(conn, + dbus_message_get_sender(msg), + transaction_owner_exited, pc, NULL); return DBUS_HANDLER_RESULT_HANDLED; } diff --git a/serial/port.c b/serial/port.c index 0e2ad200..bacf093c 100644 --- a/serial/port.c +++ b/serial/port.c @@ -244,12 +244,12 @@ static void rfcomm_node_free(struct rfcomm_node *node) g_free(node); } -static void connection_owner_exited(const char *name, void *user_data) +static void connection_owner_exited(void *user_data) { struct rfcomm_node *node = user_data; - debug("Connect requestor %s exited. Releasing %s node", - name, node->device); + debug("Connect requestor exited. Releasing %s node", + node->device); dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , @@ -265,7 +265,7 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, { debug("RFCOMM node %s was disconnected", node->device); - name_listener_id_remove(node->listener_id); + g_dbus_remove_watch(node->conn, node->listener_id); dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , @@ -299,15 +299,16 @@ void port_add_listener(DBusConnection *conn, int16_t id, bdaddr_t *dst, node->device = g_strdup(dev); node->conn = dbus_connection_ref(conn); node->owner = g_strdup(owner); - node->io = g_io_channel_unix_new(fd); + node->io = g_io_channel_unix_new(fd); node->io_id = g_io_add_watch(node->io, G_IO_ERR | G_IO_NVAL | G_IO_HUP, (GIOFunc) rfcomm_disconnect_cb, node); connected_nodes = g_slist_append(connected_nodes, node); /* Service connection listener */ - node->listener_id = name_listener_add(conn, owner, - connection_owner_exited, node); + node->listener_id = g_dbus_add_disconnect_watch(conn, owner, + connection_owner_exited, node, + NULL); } int port_remove_listener(const char *owner, const char *dev) @@ -320,7 +321,7 @@ int port_remove_listener(const char *owner, const char *dev) if (strcmp(node->owner, owner) != 0) return -EPERM; - name_listener_id_remove(node->listener_id); + g_dbus_remove_watch(node->conn, node->listener_id); connected_nodes = g_slist_remove(connected_nodes, node); rfcomm_node_free(node); -- cgit From 724e5713bca3cccf001524fe1859c1dc66f24f54 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 3 Jun 2008 10:37:11 +0000 Subject: Make serial to use libgdbus functions. --- serial/manager.c | 365 ++++++++++++++++++++++++------------------------------- serial/port.c | 82 ++++++------- 2 files changed, 201 insertions(+), 246 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 3d5b6e88..2b610a3e 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -401,7 +401,27 @@ fail: pending_connect_remove(pc); } -static DBusHandlerResult create_channel_port(DBusConnection *conn, +static inline DBusMessage *does_not_exist(DBusMessage *msg, + const char *description) +{ + return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", + description); +} + +static inline DBusMessage *invalid_arguments(DBusMessage *msg, + const char *description) +{ + return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments", + description); +} + +static inline DBusMessage *failed(DBusMessage *msg, const char *description) +{ + return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", + description); +} + +static DBusMessage *create_channel_port(DBusConnection *conn, DBusMessage *msg, const char *adapter, const char *address, const char *name, long channel, void *data) @@ -413,14 +433,13 @@ static DBusHandlerResult create_channel_port(DBusConnection *conn, bdaddr_t src, dst; if (channel < 1 || channel > 30) - return error_invalid_arguments(conn, msg, - "invalid RFCOMM channel"); + return invalid_arguments(msg, "Invalid RFCOMM channel"); str2ba(adapter, &src); str2ba(address, &dst); err = rfcomm_bind(&src, &dst, -1, channel); if (err < 0) - return error_failed_errno(conn, msg, -err); + return failed(msg, strerror(-err)); snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err); port_store(&src, &dst, err, channel, name); @@ -429,7 +448,7 @@ static DBusHandlerResult create_channel_port(DBusConnection *conn, reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; dbus_message_append_args(reply, DBUS_TYPE_STRING, &ppath, @@ -441,10 +460,10 @@ static DBusHandlerResult create_channel_port(DBusConnection *conn, DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); - return DBUS_HANDLER_RESULT_HANDLED; + return NULL; } -static DBusHandlerResult connect_pending(DBusConnection *conn, DBusMessage *msg, +static DBusMessage *connect_pending(DBusConnection *conn, DBusMessage *msg, struct pending_connect *pc) { int err; @@ -467,10 +486,12 @@ static DBusHandlerResult connect_pending(DBusConnection *conn, DBusMessage *msg, error("RFCOMM connect failed: %s(%d)", strerr, -err); pending_connects = g_slist_remove(pending_connects, pc); pending_connect_free(pc); - return error_connection_attempt_failed(conn, msg, -err); + return g_dbus_create_error(msg, ERROR_INTERFACE + ".ConnectionAttemptFailed", + "%s", strerror(-err)); } - return DBUS_HANDLER_RESULT_HANDLED; + return NULL; } static void record_cb(sdp_list_t *recs, int err, gpointer data) @@ -599,7 +620,7 @@ static int pattern2long(const char *pattern, long *pval) return 0; } -static DBusHandlerResult search_uuid(DBusConnection *conn, DBusMessage *msg, +static DBusMessage *search_uuid(DBusConnection *conn, DBusMessage *msg, const char *adapter, const char *address, const char *pattern, uuid_t *uuid, void *data) { @@ -621,7 +642,8 @@ static DBusHandlerResult search_uuid(DBusConnection *conn, DBusMessage *msg, err = bt_search_service(&src, &dst, uuid, record_cb, pc, NULL); if (err < 0) { pending_connect_free(pc); - return error_not_supported(conn, msg); + return g_dbus_create_error(msg, ERROR_INTERFACE ".NotSuppported", + "Not Supported"); } pending_connects = g_slist_append(pending_connects, pc); @@ -629,38 +651,35 @@ static DBusHandlerResult search_uuid(DBusConnection *conn, DBusMessage *msg, dbus_message_get_sender(msg), transaction_owner_exited, pc, NULL); - return DBUS_HANDLER_RESULT_HANDLED; + return NULL; } -static DBusHandlerResult create_port(DBusConnection *conn, +static DBusMessage *create_port(DBusConnection *conn, DBusMessage *msg, void *data) { const char *address, *pattern; struct pending_connect *pending; - DBusError derr; long val; uuid_t uuid; char adp[18]; int dev_id; bdaddr_t src; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) - return error_failed(conn, msg, "Adapter not available"); + return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable", + "Adapter not Available"); pending = find_pending_connect_by_pattern(address, pattern); if (pending) - return error_in_progress(conn, msg, "Connection in progress"); + return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress", + "Connection in Progress"); ba2str(&src, adp); @@ -674,7 +693,8 @@ static DBusHandlerResult create_port(DBusConnection *conn, return create_channel_port(conn, msg, adp, address, pattern, val, data); - return error_invalid_arguments(conn, msg, "invalid pattern"); + return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArgument", + "Invalid pattern"); } static void message_append_paths(DBusMessage *msg, const GSList *list) @@ -696,51 +716,43 @@ static void message_append_paths(DBusMessage *msg, const GSList *list) dbus_message_iter_close_container(&iter, &iter_array); } -static DBusHandlerResult list_ports(DBusConnection *conn, +static DBusMessage *list_ports(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; message_append_paths(reply, ports_paths); - return send_message_and_unref(conn, reply); + return reply; } -static DBusHandlerResult remove_port(DBusConnection *conn, +static DBusMessage *remove_port(DBusConnection *conn, DBusMessage *msg, void *data) { struct rfcomm_dev_info di; - DBusError derr; const char *path; GSList *l; int16_t id; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%hd", &id) != 1) - return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); + return does_not_exist(msg, "Invalid RFCOMM node"); di.id = id; if (ioctl(rfcomm_ctl, RFCOMMGETDEVINFO, &di) < 0) - return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); + return does_not_exist(msg, "Invalid RFCOMM node"); port_delete(&di.src, &di.dst, id); if (port_unregister(path) < 0) - return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); - - send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + return does_not_exist(msg, "Invalid RFCOMM node"); dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortRemoved" , @@ -753,7 +765,7 @@ static DBusHandlerResult remove_port(DBusConnection *conn, ports_paths = g_slist_remove(ports_paths, l->data); } - return DBUS_HANDLER_RESULT_HANDLED; + return dbus_message_new_method_return(msg); } static void add_lang_attr(sdp_record_t *r) @@ -1036,14 +1048,14 @@ static void connect_event_cb(GIOChannel *chan, int err, const bdaddr_t *src, return; } -static DBusHandlerResult proxy_enable(DBusConnection *conn, +static DBusMessage *proxy_enable(DBusConnection *conn, DBusMessage *msg, void *data) { struct proxy *prx = data; sdp_record_t *record; if (prx->io) - return error_failed(conn, msg, "Already enabled"); + return failed(msg, "Already enabled"); /* Listen */ prx->io = bt_rfcomm_listen_allocate(&prx->src, &prx->channel, 0, @@ -1051,7 +1063,7 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, if (!prx->io) { const char *strerr = strerror(errno); error("RFCOMM listen socket failed: %s(%d)", strerr, errno); - return error_failed(conn, msg, strerr); + return failed(msg, strerr); } g_io_channel_set_close_on_unref(prx->io, TRUE); @@ -1059,38 +1071,35 @@ static DBusHandlerResult proxy_enable(DBusConnection *conn, record = proxy_record_new(prx->uuid128, prx->channel); if (!record) { g_io_channel_unref(prx->io); - return error_failed(conn, msg, - "Unable to allocate new service record"); + return failed(msg, "Unable to allocate new service record"); } if (add_record_to_server(&prx->src, record) < 0) { sdp_record_free(record); g_io_channel_unref(prx->io); - return error_failed(conn, msg, "Service registration failed"); + return failed(msg, "Service registration failed"); } prx->record_id = record->handle; - return send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + return dbus_message_new_method_return(msg); } -static DBusHandlerResult proxy_disable(DBusConnection *conn, +static DBusMessage *proxy_disable(DBusConnection *conn, DBusMessage *msg, void *data) { struct proxy *prx = data; if (!prx->io) - return error_failed(conn, msg, "Not enabled"); + return failed(msg, "Not enabled"); /* Remove the watches and unregister the record */ disable_proxy(prx); - return send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + return dbus_message_new_method_return(msg); } -static DBusHandlerResult proxy_get_info(DBusConnection *conn, +static DBusMessage *proxy_get_info(DBusConnection *conn, DBusMessage *msg, void *data) { struct proxy *prx = data; @@ -1100,7 +1109,7 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; dbus_message_iter_init_append(reply, &iter); @@ -1139,7 +1148,7 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn, dbus_message_iter_close_container(&iter, &dict); - return send_message_and_unref(conn, reply); + return reply; } static struct { @@ -1236,10 +1245,9 @@ static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl) return -EINVAL; } -static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, +static DBusMessage *proxy_set_serial_params(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusError derr; struct proxy *prx = data; const char *ratestr, *paritystr; uint8_t databits, stopbits; @@ -1248,51 +1256,46 @@ static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, /* Don't allow change TTY settings if it is open */ if (prx->local_watch) - return error_failed(conn, msg, "Not allowed"); + return failed(msg, "Not allowed"); - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ratestr, DBUS_TYPE_BYTE, &databits, DBUS_TYPE_BYTE, &stopbits, DBUS_TYPE_STRING, &paritystr, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; if (str2speed(ratestr, &speed) == B0) - return error_invalid_arguments(conn, msg, "Invalid baud rate"); + return invalid_arguments(msg, "Invalid baud rate"); ctrl = prx->proxy_ti.c_cflag; if (set_databits(databits, &ctrl) < 0) - return error_invalid_arguments(conn, msg, "Invalid data bits"); + return invalid_arguments(msg, "Invalid data bits"); if (set_stopbits(stopbits, &ctrl) < 0) - return error_invalid_arguments(conn, msg, "Invalid stop bits"); + return invalid_arguments(msg, "Invalid stop bits"); if (set_parity(paritystr, &ctrl) < 0) - return error_invalid_arguments(conn, msg, "Invalid parity"); + return invalid_arguments(msg, "Invalid parity"); prx->proxy_ti.c_cflag = ctrl; prx->proxy_ti.c_cflag |= (CLOCAL | CREAD); cfsetispeed(&prx->proxy_ti, speed); cfsetospeed(&prx->proxy_ti, speed); - return send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + return dbus_message_new_method_return(msg); } -static DBusMethodVTable proxy_methods[] = { - { "Enable", proxy_enable, "", "" }, - { "Disable", proxy_disable, "", "" }, - { "GetInfo", proxy_get_info, "", "a{sv}" }, - { "SetSerialParameters", proxy_set_serial_params, "syys", "" }, - { NULL, NULL, NULL, NULL }, +static GDBusMethodTable proxy_methods[] = { + { "Enable", "", "", proxy_enable }, + { "Disable", "", "", proxy_disable }, + { "GetInfo", "", "a{sv}",proxy_get_info }, + { "SetSerialParameters", "syys", "", proxy_set_serial_params }, + { }, }; -static void proxy_handler_unregister(DBusConnection *conn, void *data) +static void proxy_handler_unregister(void *data) { struct proxy *prx = data; int sk; @@ -1321,14 +1324,14 @@ static int register_proxy_object(struct proxy *prx, char *outpath, size_t size) snprintf(path, MAX_PATH_LENGTH, "/org/bluez/serial/proxy%d", sk_counter++); - if (!dbus_connection_create_object_path(connection, path, prx, - proxy_handler_unregister)) { + if (!g_dbus_register_interface(connection, path, + SERIAL_PROXY_INTERFACE, + proxy_methods, NULL, NULL, + prx, proxy_handler_unregister)) { error("D-Bus failed to register %s path", path); return -1; } - dbus_connection_register_interface(connection, path, - SERIAL_PROXY_INTERFACE, proxy_methods, NULL, NULL); proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); if (outpath) @@ -1455,49 +1458,45 @@ static int proxycmp(const char *path, const char *address) return strcmp(prx->address, address); } -static DBusHandlerResult create_proxy(DBusConnection *conn, +static DBusMessage *create_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { char path[MAX_PATH_LENGTH + 1]; const char *uuid128, *address, *ppath = path; DBusMessage *reply; proxy_type_t type; - DBusError derr; bdaddr_t src; uuid_t uuid; int dev_id, ret; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &uuid128, DBUS_TYPE_STRING, &address, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; if (bt_string2uuid(&uuid, uuid128) < 0) - return error_invalid_arguments(conn, msg, "Invalid UUID"); + return invalid_arguments(msg, "Invalid UUID"); type = addr2type(address); if (type == UNKNOWN_PROXY_TYPE) - return error_invalid_arguments(conn, msg, "Invalid address"); + return invalid_arguments(msg, "Invalid address"); /* Only one proxy per address(TTY or unix socket) is allowed */ if (g_slist_find_custom(proxies_paths, address, (GCompareFunc) proxycmp)) - return error_already_exists(conn, msg, "Proxy already exists"); + return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExist", + "Proxy already exists"); dev_id = hci_get_route(NULL); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) { error("Adapter not available"); - return error_failed(conn, msg, "Adapter not available"); + return failed(msg, "Adapter no available"); } reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; switch (type) { case UNIX_SOCKET_PROXY: @@ -1517,7 +1516,7 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, } if (ret < 0) { dbus_message_unref(reply); - return error_failed(conn, msg, "Create object path failed"); + return failed(msg, "Create object path failed"); } dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, @@ -1529,43 +1528,38 @@ static DBusHandlerResult create_proxy(DBusConnection *conn, DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); + return reply; } -static DBusHandlerResult list_proxies(DBusConnection *conn, +static DBusMessage *list_proxies(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; message_append_paths(reply, proxies_paths); - return send_message_and_unref(conn, reply); + return reply; } -static DBusHandlerResult remove_proxy(DBusConnection *conn, +static DBusMessage *remove_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { struct proxy *prx = NULL; const char *path; GSList *l; - DBusError derr; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; l = g_slist_find_custom(proxies_paths, path, (GCompareFunc) strcmp); if (!l) - return error_does_not_exist(conn, msg, "Invalid proxy path"); + return does_not_exist(msg, "Invalid proxy path"); /* Remove from storage */ if (dbus_connection_get_object_user_data(conn, @@ -1582,19 +1576,17 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); - return send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + return dbus_message_new_method_return(msg); } -static DBusHandlerResult connect_channel(DBusConnection *conn, DBusMessage *msg, +static DBusMessage *connect_channel(DBusConnection *conn, DBusMessage *msg, const char *adapter, const char *address, const char *pattern, long channel, void *data) { struct pending_connect *pc; if (channel < 1 || channel > 30) - return error_invalid_arguments(conn, msg, - "invalid RFCOMM channel"); + return invalid_arguments(msg, "Invalid RFCOMM channel"); pc = g_new0(struct pending_connect, 1); pc->conn = dbus_connection_ref(conn); @@ -1608,7 +1600,7 @@ static DBusHandlerResult connect_channel(DBusConnection *conn, DBusMessage *msg, return connect_pending(conn, msg, pc); } -static DBusHandlerResult service_connect(DBusConnection *conn, DBusMessage *msg, +static DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg, const char *adapter, const char *address, const char *pattern, void *data) { @@ -1624,7 +1616,7 @@ static DBusHandlerResult service_connect(DBusConnection *conn, DBusMessage *msg, dev_id = hci_devid(adapter); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) - return error_failed(conn, msg, "Adapter not available"); + return failed(msg, "Adapter not Available"); ba2str(&src, adp); @@ -1638,112 +1630,83 @@ static DBusHandlerResult service_connect(DBusConnection *conn, DBusMessage *msg, return connect_channel(conn, msg, adp, address, pattern, val, data); - return error_invalid_arguments(conn, msg, "invalid pattern"); + return invalid_arguments(msg, "Invalid Pattern"); } -static DBusHandlerResult connect_service(DBusConnection *conn, +static DBusMessage *connect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusError derr; const char *address, *pattern; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; return service_connect(conn, msg, NULL, address, pattern, data); } -static DBusHandlerResult connect_service_from_adapter(DBusConnection *conn, +static DBusMessage *connect_service_from_adapter(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusError derr; const char *adapter, *address, *pattern; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &adapter, DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; return service_connect(conn, msg, adapter, address, pattern, data); } -static DBusHandlerResult disconnect_service(DBusConnection *conn, +static DBusMessage *disconnect_service(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusError derr; const char *name; int err, id; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; if (sscanf(name, "/dev/rfcomm%d", &id) != 1) - return error_invalid_arguments(conn, msg, "invalid RFCOMM node"); + return invalid_arguments(msg, "Invalid RFCOMM node"); err = port_remove_listener(dbus_message_get_sender(msg), name); if (err < 0) - return error_does_not_exist(conn, msg, "Invalid RFCOMM node"); - - send_message_and_unref(conn, - dbus_message_new_method_return(msg)); + return does_not_exist(msg, "Invalid RFCOMM node"); dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); - return DBUS_HANDLER_RESULT_HANDLED; + return dbus_message_new_method_return(msg); } -static DBusHandlerResult cancel_connect_service(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *cancel_connect_service(DBusConnection *conn, + DBusMessage *msg, void *data) { struct pending_connect *pending; - DBusMessage *reply; - DBusError derr; const char *bda, *pattern; - dbus_error_init(&derr); - if (!dbus_message_get_args(msg, &derr, + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &bda, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID)) { - error_invalid_arguments(conn, msg, derr.message); - dbus_error_free(&derr); - return DBUS_HANDLER_RESULT_HANDLED; - } + DBUS_TYPE_INVALID)) + return NULL; pending = find_pending_connect_by_pattern(bda, pattern); if (!pending) - return error_does_not_exist(conn, msg, - "No such connection request"); - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return does_not_exist(msg, "No such connection request"); pending->canceled = 1; - return send_message_and_unref(conn, reply); + return dbus_message_new_method_return(msg); } static void proxy_path_free(gpointer data, gpointer udata) @@ -1765,7 +1728,7 @@ static void proxy_path_free(gpointer data, gpointer udata) g_free(data); } -static void manager_unregister(DBusConnection *conn, void *data) +static void manager_unregister(void *data) { char **dev; int i; @@ -1779,7 +1742,7 @@ static void manager_unregister(DBusConnection *conn, void *data) if (proxies_paths) { g_slist_foreach(proxies_paths, - proxy_path_free, conn); + proxy_path_free, connection); g_slist_free(proxies_paths); proxies_paths = NULL; } @@ -1792,7 +1755,8 @@ static void manager_unregister(DBusConnection *conn, void *data) } /* Unregister all paths in serial hierarchy */ - if (!dbus_connection_list_registered(conn, SERIAL_MANAGER_PATH, &dev)) + if (!dbus_connection_list_registered(connection, SERIAL_MANAGER_PATH, + &dev)) return; for (i = 0; dev[i]; i++) { @@ -1801,34 +1765,37 @@ static void manager_unregister(DBusConnection *conn, void *data) snprintf(dev_path, sizeof(dev_path), "%s/%s", SERIAL_MANAGER_PATH, dev[i]); - dbus_connection_destroy_object_path(conn, dev_path); + dbus_connection_destroy_object_path(connection, dev_path); } dbus_free_string_array(dev); } -static DBusMethodVTable manager_methods[] = { - { "CreatePort", create_port, "ss", "s" }, - { "ListPorts", list_ports, "", "as" }, - { "RemovePort", remove_port, "s", "" }, - { "CreateProxy", create_proxy, "ss", "s" }, - { "ListProxies", list_proxies, "", "as" }, - { "RemoveProxy", remove_proxy, "s", "" }, - { "ConnectService", connect_service, "ss", "s" }, - { "ConnectServiceFromAdapter", connect_service_from_adapter, "sss", "s" }, - { "DisconnectService", disconnect_service, "s", "" }, - { "CancelConnectService", cancel_connect_service, "ss", "" }, - { NULL, NULL, NULL, NULL }, +static GDBusMethodTable manager_methods[] = { + { "CreatePort", "ss", "s", create_port, + G_DBUS_METHOD_FLAG_ASYNC }, + { "ListPorts", "", "as", list_ports }, + { "RemovePort", "s", "", remove_port }, + { "CreateProxy", "ss", "s", create_proxy }, + { "ListProxies", "", "as", list_proxies }, + { "RemoveProxy", "s", "", remove_proxy }, + { "ConnectService", "ss", "s", connect_service, + G_DBUS_METHOD_FLAG_ASYNC }, + { "ConnectServiceFromAdapter", "sss", "s", connect_service_from_adapter, + G_DBUS_METHOD_FLAG_ASYNC }, + { "DisconnectService", "s", "", disconnect_service }, + { "CancelConnectService", "ss", "", cancel_connect_service }, + { }, }; -static DBusSignalVTable manager_signals[] = { +static GDBusSignalTable manager_signals[] = { { "PortCreated", "s" }, { "PortRemoved", "s" }, { "ProxyCreated", "s" }, { "ProxyRemoved", "s" }, { "ServiceConnected", "s" }, { "ServiceDisconnected", "s" }, - { NULL, NULL } + { } }; static void parse_port(char *key, char *value, void *data) @@ -1957,20 +1924,12 @@ int serial_manager_init(DBusConnection *conn) return -errno; } - if (!dbus_connection_create_object_path(conn, SERIAL_MANAGER_PATH, - NULL, manager_unregister)) { - error("D-Bus failed to register %s path", SERIAL_MANAGER_PATH); - return -1; - } - - if (!dbus_connection_register_interface(conn, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE, - manager_methods, - manager_signals, NULL)) { + if (!g_dbus_register_interface(conn, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE, + manager_methods, manager_signals, NULL, + NULL, manager_unregister)) { error("Failed to register %s interface to %s", SERIAL_MANAGER_INTERFACE, SERIAL_MANAGER_PATH); - dbus_connection_destroy_object_path(connection, - SERIAL_MANAGER_PATH); return -1; } diff --git a/serial/port.c b/serial/port.c index bacf093c..311d38f0 100644 --- a/serial/port.c +++ b/serial/port.c @@ -79,8 +79,8 @@ static struct rfcomm_node *find_node_by_name(GSList *nodes, const char *dev) return NULL; } -static DBusHandlerResult port_get_address(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *port_get_address(DBusConnection *conn, + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; @@ -89,35 +89,36 @@ static DBusHandlerResult port_get_address(DBusConnection *conn, reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; ba2str(&node->dst, bda); dbus_message_append_args(reply, DBUS_TYPE_STRING, &pbda, DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); + return reply; } -static DBusHandlerResult port_get_device(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *port_get_device(DBusConnection *conn, + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; dbus_message_append_args(reply, DBUS_TYPE_STRING, &node->device, DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); + + return reply; } -static DBusHandlerResult port_get_adapter(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *port_get_adapter(DBusConnection *conn, + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; @@ -128,18 +129,18 @@ static DBusHandlerResult port_get_adapter(DBusConnection *conn, reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; dbus_message_append_args(reply, DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); + return reply; } -static DBusHandlerResult port_get_name(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *port_get_name(DBusConnection *conn, + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; @@ -148,7 +149,7 @@ static DBusHandlerResult port_get_name(DBusConnection *conn, reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; read_device_name(&node->src, &node->dst, &name); @@ -160,27 +161,28 @@ static DBusHandlerResult port_get_name(DBusConnection *conn, if (name) g_free(name); - return send_message_and_unref(conn, reply); + return reply; } -static DBusHandlerResult port_get_service_name(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *port_get_service_name(DBusConnection *conn, + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; dbus_message_append_args(reply, DBUS_TYPE_STRING, &node->svcname, DBUS_TYPE_INVALID); - return send_message_and_unref(conn, reply); + + return reply; } -static DBusHandlerResult port_get_info(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusMessage *port_get_info(DBusConnection *conn, + DBusMessage *msg, void *data) { struct rfcomm_node *node = data; DBusMessage *reply; @@ -190,7 +192,7 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, reply = dbus_message_new_method_return(msg); if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return NULL; dbus_message_iter_init_append(reply, &iter); @@ -208,20 +210,20 @@ static DBusHandlerResult port_get_info(DBusConnection *conn, dbus_message_iter_close_container(&iter, &dict); - return send_message_and_unref(conn, reply); + return reply; } -static DBusMethodVTable port_methods[] = { - { "GetAddress", port_get_address, "", "s" }, - { "GetDevice", port_get_device, "", "s" }, - { "GetAdapter", port_get_adapter, "", "s" }, - { "GetName", port_get_name, "", "s" }, - { "GetServiceName", port_get_service_name, "", "s" }, - { "GetInfo", port_get_info, "", "a{sv}" }, +static GDBusMethodTable port_methods[] = { + { "GetAddress", "", "s", port_get_address }, + { "GetDevice", "", "s", port_get_device }, + { "GetAdapter", "", "s", port_get_adapter }, + { "GetName", "", "s", port_get_name }, + { "GetServiceName", "", "s", port_get_service_name }, + { "GetInfo", "", "a{sv}",port_get_info }, { NULL, NULL, NULL, NULL }, }; -static DBusSignalVTable port_signals[] = { +static GDBusSignalTable port_signals[] = { { NULL, NULL } }; @@ -278,7 +280,7 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, return FALSE; } -static void port_handler_unregister(DBusConnection *conn, void *data) +static void port_handler_unregister(void *data) { struct rfcomm_node *node = data; @@ -358,20 +360,14 @@ int port_register(DBusConnection *conn, int16_t id, bdaddr_t *src, snprintf(path, MAX_PATH_LENGTH, "%s/rfcomm%hd", SERIAL_MANAGER_PATH, id); - if (!dbus_connection_create_object_path(conn, path, node, - port_handler_unregister)) { - error("D-Bus failed to register %s path", path); - rfcomm_node_free(node); - return -1; - } - if (!dbus_connection_register_interface(conn, path, + if (!g_dbus_register_interface(conn, path, SERIAL_PORT_INTERFACE, - port_methods, - port_signals, NULL)) { + port_methods, port_signals, NULL, + node, port_handler_unregister)) { error("D-Bus failed to register %s interface", SERIAL_PORT_INTERFACE); - dbus_connection_destroy_object_path(conn, path); + rfcomm_node_free(node); return -1; } -- cgit From 00f4c9a6e1e5cc7e3fed0651d61a1278c93c2984 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jun 2008 15:00:06 +0000 Subject: Replace destroy method with proper unregister version --- serial/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/port.c b/serial/port.c index 311d38f0..c722dde4 100644 --- a/serial/port.c +++ b/serial/port.c @@ -395,7 +395,7 @@ int port_unregister(const char *path) if (!node) return -ENOENT; - dbus_connection_destroy_object_path(node->conn, path); + g_dbus_unregister_interface(node->conn, path, SERIAL_PORT_INTERFACE); return 0; } -- cgit From 842d3d53c6c3ae712c9d3a585a638ac4da343efa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jun 2008 15:03:17 +0000 Subject: Use proper unregister method for the serial proxy --- serial/manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 2b610a3e..111995c8 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1569,7 +1569,7 @@ static DBusMessage *remove_proxy(DBusConnection *conn, g_free(l->data); proxies_paths = g_slist_remove(proxies_paths, l->data); - dbus_connection_destroy_object_path(conn, path); + g_dbus_unregister_interface(conn, path, SERIAL_PROXY_INTERFACE); dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ProxyRemoved", -- cgit From 79c4527aa8bfbed3a35c2a6ad179f2c498dead16 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jun 2008 15:08:15 +0000 Subject: Only unregister the manager path --- serial/manager.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 111995c8..ae9d90d5 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1731,7 +1731,6 @@ static void proxy_path_free(gpointer data, gpointer udata) static void manager_unregister(void *data) { char **dev; - int i; if (pending_connects) { g_slist_foreach(pending_connects, @@ -1754,19 +1753,8 @@ static void manager_unregister(void *data) ports_paths = NULL; } - /* Unregister all paths in serial hierarchy */ - if (!dbus_connection_list_registered(connection, SERIAL_MANAGER_PATH, - &dev)) - return; - - for (i = 0; dev[i]; i++) { - char dev_path[MAX_PATH_LENGTH]; - - snprintf(dev_path, sizeof(dev_path), "%s/%s", SERIAL_MANAGER_PATH, - dev[i]); - - dbus_connection_destroy_object_path(connection, dev_path); - } + g_dbus_unregister_interface(connection, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE); dbus_free_string_array(dev); } -- cgit From 390070876fc0b10daab553faf183a86243c6802b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jun 2008 15:17:07 +0000 Subject: Fix manager unregistration --- serial/manager.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index ae9d90d5..a9bc0968 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1730,8 +1730,6 @@ static void proxy_path_free(gpointer data, gpointer udata) static void manager_unregister(void *data) { - char **dev; - if (pending_connects) { g_slist_foreach(pending_connects, (GFunc) pending_connect_free, NULL); @@ -1752,11 +1750,6 @@ static void manager_unregister(void *data) g_slist_free(ports_paths); ports_paths = NULL; } - - g_dbus_unregister_interface(connection, SERIAL_MANAGER_PATH, - SERIAL_MANAGER_INTERFACE); - - dbus_free_string_array(dev); } static GDBusMethodTable manager_methods[] = { @@ -1932,7 +1925,8 @@ int serial_manager_init(DBusConnection *conn) void serial_manager_exit(void) { - dbus_connection_destroy_object_path(connection, SERIAL_MANAGER_PATH); + g_dbus_unregister_interface(connection, SERIAL_MANAGER_PATH, + SERIAL_MANAGER_INTERFACE); dbus_connection_unref(connection); connection = NULL; -- cgit From 2aab870f593da0b3ec83095e5ded93b900e4b600 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jun 2008 20:07:34 +0000 Subject: Update autoconf/automake options --- serial/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index effb7c6f..df246cf0 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -1,5 +1,5 @@ -if SERIALSERVICE +if SERIALPLUGIN plugindir = $(libdir)/bluetooth/plugins plugin_LTLIBRARIES = libserial.la -- cgit From f269e27ce7e39e6484cf02a137dcda7458a7fd85 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 Jun 2008 10:20:21 +0000 Subject: Fix the last remains of sending helpers --- serial/manager.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index a9bc0968..64f2203a 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -234,7 +234,8 @@ static void open_notify(int fd, int err, struct pending_connect *pc) dbus_message_append_args(reply, DBUS_TYPE_STRING, &pc->dev, DBUS_TYPE_INVALID); - send_message_and_unref(pc->conn, reply); + dbus_connection_send(pc->conn, reply, NULL); + dbus_message_unref(reply); /* Send the D-Bus signal */ dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, @@ -453,7 +454,8 @@ static DBusMessage *create_channel_port(DBusConnection *conn, dbus_message_append_args(reply, DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); - send_message_and_unref(conn, reply); + dbus_connection_send(conn, reply, NULL); + dbus_message_unref(reply); dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortCreated" , -- cgit From d1683035d36462b5b336169c1bbfd3a86249e2a5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 7 Jun 2008 08:51:44 +0000 Subject: Fix invalid read and get rid of using object path user data --- serial/manager.c | 135 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 61 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index 64f2203a..d285eeda 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -113,6 +113,7 @@ struct proxy { bdaddr_t dst; char *uuid128; /* UUID 128 */ char *address; /* TTY or Unix socket name */ + char *path; /* D-Bus path */ short int port; /* TCP port */ proxy_type_t type; /* TTY or Unix socket */ struct termios sys_ti; /* Default TTY setting */ @@ -127,7 +128,7 @@ struct proxy { static DBusConnection *connection = NULL; static GSList *pending_connects = NULL; static GSList *ports_paths = NULL; -static GSList *proxies_paths = NULL; +static GSList *proxies = NULL; static int rfcomm_ctl = -1; static int sk_counter = 0; @@ -1286,6 +1287,9 @@ static DBusMessage *proxy_set_serial_params(DBusConnection *conn, cfsetispeed(&prx->proxy_ti, speed); cfsetospeed(&prx->proxy_ti, speed); + proxy_store(&prx->src, prx->uuid128, prx->address, NULL, + prx->channel, 0, &prx->proxy_ti); + return dbus_message_new_method_return(msg); } @@ -1297,7 +1301,7 @@ static GDBusMethodTable proxy_methods[] = { { }, }; -static void proxy_handler_unregister(void *data) +static void proxy_unregister(gpointer data) { struct proxy *prx = data; int sk; @@ -1313,7 +1317,6 @@ static void proxy_handler_unregister(void *data) tcsetattr(sk, TCSAFLUSH, &prx->sys_ti); close(sk); } - done: proxy_free(prx); @@ -1329,12 +1332,13 @@ static int register_proxy_object(struct proxy *prx, char *outpath, size_t size) if (!g_dbus_register_interface(connection, path, SERIAL_PROXY_INTERFACE, proxy_methods, NULL, NULL, - prx, proxy_handler_unregister)) { + prx, proxy_unregister)) { error("D-Bus failed to register %s path", path); return -1; } - proxies_paths = g_slist_append(proxies_paths, g_strdup(path)); + prx->path = g_strdup(path); + proxies = g_slist_append(proxies, prx); if (outpath) strncpy(outpath, path, size); @@ -1345,7 +1349,8 @@ static int register_proxy_object(struct proxy *prx, char *outpath, size_t size) } static int proxy_tty_register(bdaddr_t *src, const char *uuid128, - const char *address, struct termios *ti, char *outpath, size_t size) + const char *address, struct termios *ti, + char *outpath, size_t size, gboolean save) { struct termios sys_ti; struct proxy *prx; @@ -1381,11 +1386,16 @@ static int proxy_tty_register(bdaddr_t *src, const char *uuid128, if (ret < 0) proxy_free(prx); + if (save) + proxy_store(src, uuid128, address, NULL, + prx->channel, 0, &prx->proxy_ti); + return ret; } static int proxy_socket_register(bdaddr_t *src, const char *uuid128, - const char *address, char *outpath, size_t size) + const char *address, char *outpath, + size_t size, gboolean save) { struct proxy *prx; int ret; @@ -1400,11 +1410,16 @@ static int proxy_socket_register(bdaddr_t *src, const char *uuid128, if (ret < 0) proxy_free(prx); + if (save) + proxy_store(src, uuid128, address, NULL, + prx->channel, 0, NULL); + return ret; } static int proxy_tcp_register(bdaddr_t *src, const char *uuid128, - const char *address, char *outpath, size_t size) + const char *address, char *outpath, + size_t size, gboolean save) { struct proxy *prx; int ret; @@ -1419,6 +1434,10 @@ static int proxy_tcp_register(bdaddr_t *src, const char *uuid128, if (ret < 0) proxy_free(prx); + if (save) + proxy_store(src, uuid128, address, NULL, + prx->channel, 0, NULL); + return ret; } @@ -1449,17 +1468,22 @@ static proxy_type_t addr2type(const char *address) } } -static int proxycmp(const char *path, const char *address) +static int proxy_addrcmp(gconstpointer proxy, gconstpointer addr) { - struct proxy *prx = NULL; - - if (!dbus_connection_get_object_user_data(connection, - path, (void *) &prx) || !prx) - return -1; + const struct proxy *prx = proxy; + const char *address = addr; return strcmp(prx->address, address); } +static int proxy_pathcmp(gconstpointer proxy, gconstpointer p) +{ + const struct proxy *prx = proxy; + const char *path = p; + + return strcmp(prx->path, path); +} + static DBusMessage *create_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -1485,8 +1509,7 @@ static DBusMessage *create_proxy(DBusConnection *conn, return invalid_arguments(msg, "Invalid address"); /* Only one proxy per address(TTY or unix socket) is allowed */ - if (g_slist_find_custom(proxies_paths, - address, (GCompareFunc) proxycmp)) + if (g_slist_find_custom(proxies, address, proxy_addrcmp)) return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExist", "Proxy already exists"); @@ -1502,16 +1525,16 @@ static DBusMessage *create_proxy(DBusConnection *conn, switch (type) { case UNIX_SOCKET_PROXY: - ret = proxy_socket_register(&src, uuid128, - address, path, sizeof(path)); + ret = proxy_socket_register(&src, uuid128, address, + path, sizeof(path), TRUE); break; case TTY_PROXY: - ret = proxy_tty_register(&src, uuid128, - address, NULL, path, sizeof(path)); + ret = proxy_tty_register(&src, uuid128, address, + NULL, path, sizeof(path), TRUE); break; case TCP_SOCKET_PROXY: ret = proxy_tcp_register(&src, uuid128, address, - path, sizeof(path)); + path, sizeof(path), TRUE); break; default: ret = -1; @@ -1536,13 +1559,26 @@ static DBusMessage *create_proxy(DBusConnection *conn, static DBusMessage *list_proxies(DBusConnection *conn, DBusMessage *msg, void *data) { + struct proxy *prx; + const GSList *l; DBusMessage *reply; + DBusMessageIter iter, iter_array; reply = dbus_message_new_method_return(msg); if (!reply) return NULL; - message_append_paths(reply, proxies_paths); + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &iter_array); + + for (l = proxies; l; l = l->next) { + prx = l->data; + dbus_message_iter_append_basic(&iter_array, + DBUS_TYPE_STRING, &prx->path); + } + + dbus_message_iter_close_container(&iter, &iter_array); return reply; } @@ -1550,7 +1586,7 @@ static DBusMessage *list_proxies(DBusConnection *conn, static DBusMessage *remove_proxy(DBusConnection *conn, DBusMessage *msg, void *data) { - struct proxy *prx = NULL; + struct proxy *prx; const char *path; GSList *l; @@ -1559,25 +1595,21 @@ static DBusMessage *remove_proxy(DBusConnection *conn, DBUS_TYPE_INVALID)) return NULL; - l = g_slist_find_custom(proxies_paths, path, (GCompareFunc) strcmp); + l = g_slist_find_custom(proxies, path, proxy_pathcmp); if (!l) return does_not_exist(msg, "Invalid proxy path"); - /* Remove from storage */ - if (dbus_connection_get_object_user_data(conn, - path, (void *) &prx) && prx) - proxy_delete(&prx->src, prx->address); - - g_free(l->data); - proxies_paths = g_slist_remove(proxies_paths, l->data); - - g_dbus_unregister_interface(conn, path, SERIAL_PROXY_INTERFACE); - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ProxyRemoved", DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); + prx = l->data; + proxy_delete(&prx->src, prx->address); + proxies = g_slist_remove(proxies, prx); + + g_dbus_unregister_interface(conn, path, SERIAL_PROXY_INTERFACE); + return dbus_message_new_method_return(msg); } @@ -1711,25 +1743,6 @@ static DBusMessage *cancel_connect_service(DBusConnection *conn, return dbus_message_new_method_return(msg); } -static void proxy_path_free(gpointer data, gpointer udata) -{ - DBusConnection *conn = udata; - const char *path = data; - struct proxy *prx = NULL; - - /* Store/Update the proxy entries before exit */ - if (dbus_connection_get_object_user_data(conn, - path, (void *) &prx) && prx) { - struct termios *ti; - - ti = (prx->type == TTY_PROXY ? &prx->proxy_ti : NULL); - proxy_store(&prx->src, prx->uuid128, prx->address, NULL, - prx->channel, 0, ti); - } - - g_free(data); -} - static void manager_unregister(void *data) { if (pending_connects) { @@ -1739,11 +1752,11 @@ static void manager_unregister(void *data) pending_connects = NULL; } - if (proxies_paths) { - g_slist_foreach(proxies_paths, - proxy_path_free, connection); - g_slist_free(proxies_paths); - proxies_paths = NULL; + if (proxies) { + g_slist_foreach(proxies, + (GFunc) proxy_unregister, NULL); + g_slist_free(proxies); + proxies = NULL; } if (ports_paths) { @@ -1859,13 +1872,13 @@ static void parse_proxy(char *key, char *value, void *data) *pti = (uint8_t) strtol(tmp, NULL, 16); } - proxy_tty_register(&src, uuid128, key, &ti, NULL, 0); + proxy_tty_register(&src, uuid128, key, &ti, NULL, 0, FALSE); break; case UNIX_SOCKET_PROXY: - proxy_socket_register(&src, uuid128, key, NULL, 0); + proxy_socket_register(&src, uuid128, key, NULL, 0, FALSE); break; case TCP_SOCKET_PROXY: - proxy_tcp_register(&src, uuid128, key, NULL, 0); + proxy_tcp_register(&src, uuid128, key, NULL, 0, FALSE); break; default: return; -- cgit From f80a7215275b229a597cf8d2bbc7e4e208af522c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 7 Jun 2008 19:30:24 +0000 Subject: Use g_dbus_emit_signal for sending D-Bus signals --- serial/manager.c | 12 ++++++------ serial/port.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index d285eeda..cad09e7e 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -239,7 +239,7 @@ static void open_notify(int fd, int err, struct pending_connect *pc) dbus_message_unref(reply); /* Send the D-Bus signal */ - dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(pc->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceConnected" , DBUS_TYPE_STRING, &pc->dev, DBUS_TYPE_INVALID); @@ -458,7 +458,7 @@ static DBusMessage *create_channel_port(DBusConnection *conn, dbus_connection_send(conn, reply, NULL); dbus_message_unref(reply); - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortCreated" , DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); @@ -757,7 +757,7 @@ static DBusMessage *remove_port(DBusConnection *conn, if (port_unregister(path) < 0) return does_not_exist(msg, "Invalid RFCOMM node"); - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "PortRemoved" , DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); @@ -1544,7 +1544,7 @@ static DBusMessage *create_proxy(DBusConnection *conn, return failed(msg, "Create object path failed"); } - dbus_connection_emit_signal(connection, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(connection, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ProxyCreated", DBUS_TYPE_STRING, &ppath, DBUS_TYPE_INVALID); @@ -1599,7 +1599,7 @@ static DBusMessage *remove_proxy(DBusConnection *conn, if (!l) return does_not_exist(msg, "Invalid proxy path"); - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ProxyRemoved", DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); @@ -1714,7 +1714,7 @@ static DBusMessage *disconnect_service(DBusConnection *conn, if (err < 0) return does_not_exist(msg, "Invalid RFCOMM node"); - dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); diff --git a/serial/port.c b/serial/port.c index c722dde4..522f7c01 100644 --- a/serial/port.c +++ b/serial/port.c @@ -253,7 +253,7 @@ static void connection_owner_exited(void *user_data) debug("Connect requestor exited. Releasing %s node", node->device); - dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , DBUS_TYPE_STRING, &node->device, DBUS_TYPE_INVALID); @@ -269,7 +269,7 @@ static gboolean rfcomm_disconnect_cb(GIOChannel *io, g_dbus_remove_watch(node->conn, node->listener_id); - dbus_connection_emit_signal(node->conn, SERIAL_MANAGER_PATH, + g_dbus_emit_signal(node->conn, SERIAL_MANAGER_PATH, SERIAL_MANAGER_INTERFACE, "ServiceDisconnected" , DBUS_TYPE_STRING, &node->device, DBUS_TYPE_INVALID); -- cgit From 22ec945f109d9d1e21a8cfbc6e2dec3dd4b88c8e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 7 Jun 2008 20:09:25 +0000 Subject: Move some D-Bus helpers around --- serial/manager.c | 2 ++ serial/manager.h | 2 -- serial/port.c | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/manager.c b/serial/manager.c index cad09e7e..f097b330 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -51,6 +51,8 @@ #include #include +#include "../hcid/dbus-common.h" + #include "logging.h" #include "textfile.h" diff --git a/serial/manager.h b/serial/manager.h index 8a870101..b25c2686 100644 --- a/serial/manager.h +++ b/serial/manager.h @@ -24,8 +24,6 @@ #define SERIAL_MANAGER_PATH "/org/bluez/serial" #define SERIAL_MANAGER_INTERFACE "org.bluez.serial.Manager" -#define MAX_PATH_LENGTH 32 - int serial_manager_init(DBusConnection *conn); void serial_manager_exit(void); int rfcomm_release(int16_t id); diff --git a/serial/port.c b/serial/port.c index 522f7c01..f0563244 100644 --- a/serial/port.c +++ b/serial/port.c @@ -38,10 +38,13 @@ #include #include +#include #include #include +#include "../hcid/dbus-common.h" + #include "logging.h" #include "error.h" -- cgit From 03b145d3945ccce2855d7a09944c81c9badf798a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Jun 2008 17:16:28 +0000 Subject: Fix up the serial UUIDs --- serial/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index d0d24982..3c69642c 100644 --- a/serial/main.c +++ b/serial/main.c @@ -40,6 +40,9 @@ #define SERIAL_INTERFACE "org.bluez.Serial" +#define SERIAL_PORT_UUID "00001101-0000-1000-8000-00805F9B34FB" +#define DIALUP_NET_UUID "00001103-0000-1000-8000-00805F9B34FB" + static DBusMessage *serial_connect(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -90,7 +93,7 @@ static void serial_remove(const char *path) static struct btd_device_driver serial_driver = { .name = "serial", - .uuids = BTD_UUIDS("spp", "dun"), + .uuids = BTD_UUIDS(SERIAL_PORT_UUID, DIALUP_NET_UUID), .probe = serial_probe, .remove = serial_remove, }; -- cgit From 8bf636881f152a97727774f4f9ea2504c72dfb23 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Jun 2008 20:54:55 +0000 Subject: Use DBG in plugin to show function names --- serial/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 3c69642c..ee1cb9f9 100644 --- a/serial/main.c +++ b/serial/main.c @@ -78,7 +78,7 @@ static DBusConnection *conn; static int serial_probe(const char *path) { - debug("path %s", path); + DBG("path %s", path); return g_dbus_register_interface(conn, path, SERIAL_INTERFACE, serial_methods, NULL, NULL, NULL, NULL); @@ -86,7 +86,7 @@ static int serial_probe(const char *path) static void serial_remove(const char *path) { - debug("path %s", path); + DBG("path %s", path); g_dbus_unregister_interface(conn, path, SERIAL_INTERFACE); } -- cgit From 0f62b72c8564608f849b3bbe54bf48db07c45015 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Jun 2008 21:21:54 +0000 Subject: Update plugin interface registration --- serial/main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index ee1cb9f9..b042e2e7 100644 --- a/serial/main.c +++ b/serial/main.c @@ -38,11 +38,11 @@ #include "logging.h" #include "manager.h" -#define SERIAL_INTERFACE "org.bluez.Serial" - #define SERIAL_PORT_UUID "00001101-0000-1000-8000-00805F9B34FB" #define DIALUP_NET_UUID "00001103-0000-1000-8000-00805F9B34FB" +#define SERIAL_INTERFACE "org.bluez.Serial" + static DBusMessage *serial_connect(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -80,8 +80,12 @@ static int serial_probe(const char *path) { DBG("path %s", path); - return g_dbus_register_interface(conn, path, SERIAL_INTERFACE, - serial_methods, NULL, NULL, NULL, NULL); + if (g_dbus_register_interface(conn, path, SERIAL_INTERFACE, + serial_methods, NULL, NULL, + NULL, NULL) == FALSE) + return -1; + + return 0; } static void serial_remove(const char *path) -- cgit From 5243ac4fd278b0176ece84cbcec537a92a9c7290 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Jun 2008 22:57:11 +0000 Subject: Update probe/remove callback and implement serial API --- serial/main.c | 46 +++++++++++++++++++++++++++++++++------------- serial/manager.c | 19 ++++++++++--------- serial/manager.h | 5 +++++ 3 files changed, 48 insertions(+), 22 deletions(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index b042e2e7..60ce9d45 100644 --- a/serial/main.c +++ b/serial/main.c @@ -35,64 +35,84 @@ #include "plugin.h" #include "device.h" +#include "adapter.h" #include "logging.h" #include "manager.h" +#include "port.h" #define SERIAL_PORT_UUID "00001101-0000-1000-8000-00805F9B34FB" #define DIALUP_NET_UUID "00001103-0000-1000-8000-00805F9B34FB" -#define SERIAL_INTERFACE "org.bluez.Serial" +#define SERIAL_INTERFACE "org.bluez.Serial" +#define ERROR_INVALID_ARGS "org.bluez.Error.InvalidArguments" +#define ERROR_DOES_NOT_EXIST "org.bluez.Error.DoesNotExist" static DBusMessage *serial_connect(DBusConnection *conn, DBusMessage *msg, void *user_data) { - const char *target, *device = "/dev/rfcomm0"; + struct btd_device *device = user_data; + const char *target; + char src[18], dst[18]; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &target, DBUS_TYPE_INVALID) == FALSE) return NULL; - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &device, - DBUS_TYPE_INVALID); + ba2str(&device->src, src); + ba2str(&device->dst, dst); + + service_connect(conn, msg, src, dst, target); + + return NULL; } static DBusMessage *serial_disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data) { - const char *device; + const char *device, *sender; + int err, id; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID) == FALSE) return NULL; + sender = dbus_message_get_sender(msg); + + if (sscanf(device, "/dev/rfcomm%d", &id) != 1) + return g_dbus_create_error(msg, ERROR_INVALID_ARGS, NULL); + + err = port_remove_listener(sender, device); + if (err < 0) + return g_dbus_create_error(msg, ERROR_DOES_NOT_EXIST, NULL); + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } static GDBusMethodTable serial_methods[] = { - { "Connect", "s", "s", serial_connect }, + { "Connect", "s", "s", serial_connect, G_DBUS_METHOD_FLAG_ASYNC }, { "Disconnect", "s", "", serial_disconnect }, { } }; static DBusConnection *conn; -static int serial_probe(const char *path) +static int serial_probe(struct btd_device *device) { - DBG("path %s", path); + DBG("path %s", device->path); - if (g_dbus_register_interface(conn, path, SERIAL_INTERFACE, + if (g_dbus_register_interface(conn, device->path, SERIAL_INTERFACE, serial_methods, NULL, NULL, - NULL, NULL) == FALSE) + device, NULL) == FALSE) return -1; return 0; } -static void serial_remove(const char *path) +static void serial_remove(struct btd_device *device) { - DBG("path %s", path); + DBG("path %s", device->path); - g_dbus_unregister_interface(conn, path, SERIAL_INTERFACE); + g_dbus_unregister_interface(conn, device->path, SERIAL_INTERFACE); } static struct btd_device_driver serial_driver = { diff --git a/serial/manager.c b/serial/manager.c index f097b330..442c386e 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1636,9 +1636,10 @@ static DBusMessage *connect_channel(DBusConnection *conn, DBusMessage *msg, return connect_pending(conn, msg, pc); } -static DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg, - const char *adapter, const char *address, - const char *pattern, void *data) +DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg, + const char *adapter, + const char *address, + const char *pattern) { int dev_id; bdaddr_t src; @@ -1658,13 +1659,13 @@ static DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg, /* Friendly name or uuid128 */ if (pattern2uuid(pattern, &uuid) == 0) - return search_uuid(conn, msg, adp, address, pattern, &uuid, - data); + return search_uuid(conn, msg, adp, address, + pattern, &uuid, NULL); /* RFCOMM Channel */ if (pattern2long(pattern, &val) == 0) - return connect_channel(conn, msg, adp, address, pattern, - val, data); + return connect_channel(conn, msg, adp, address, + pattern, val, NULL); return invalid_arguments(msg, "Invalid Pattern"); } @@ -1680,7 +1681,7 @@ static DBusMessage *connect_service(DBusConnection *conn, DBUS_TYPE_INVALID)) return NULL; - return service_connect(conn, msg, NULL, address, pattern, data); + return service_connect(conn, msg, NULL, address, pattern); } static DBusMessage *connect_service_from_adapter(DBusConnection *conn, @@ -1695,7 +1696,7 @@ static DBusMessage *connect_service_from_adapter(DBusConnection *conn, DBUS_TYPE_INVALID)) return NULL; - return service_connect(conn, msg, adapter, address, pattern, data); + return service_connect(conn, msg, adapter, address, pattern); } static DBusMessage *disconnect_service(DBusConnection *conn, diff --git a/serial/manager.h b/serial/manager.h index b25c2686..fdcc8ab9 100644 --- a/serial/manager.h +++ b/serial/manager.h @@ -27,3 +27,8 @@ int serial_manager_init(DBusConnection *conn); void serial_manager_exit(void); int rfcomm_release(int16_t id); + +DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg, + const char *adapter, + const char *address, + const char *pattern); -- cgit From 64f8405b60509908b8668a4160d3ebe120f7b67f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Jun 2008 22:59:14 +0000 Subject: Remove empty line --- serial/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 60ce9d45..0de87da3 100644 --- a/serial/main.c +++ b/serial/main.c @@ -25,7 +25,6 @@ #include #endif - #include #include -- cgit From a22a088109b664efdee397affed55b039cb0999b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 30 Jun 2008 05:47:13 +0000 Subject: Don't use lib prefix for plugins --- serial/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'serial') diff --git a/serial/Makefile.am b/serial/Makefile.am index df246cf0..0e6c47f7 100644 --- a/serial/Makefile.am +++ b/serial/Makefile.am @@ -2,9 +2,9 @@ if SERIALPLUGIN plugindir = $(libdir)/bluetooth/plugins -plugin_LTLIBRARIES = libserial.la +plugin_LTLIBRARIES = serial.la -libserial_la_SOURCES = main.c \ +serial_la_SOURCES = main.c \ manager.h manager.c port.h port.c \ storage.h storage.c -- cgit From c4139033616c53b1f790fe165d1a22fcce292e74 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 30 Jun 2008 17:35:47 +0000 Subject: Fixed missing include --- serial/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'serial') diff --git a/serial/main.c b/serial/main.c index 0de87da3..20aea93a 100644 --- a/serial/main.c +++ b/serial/main.c @@ -29,6 +29,7 @@ #include #include +#include #include -- cgit