Re: [PATCH] bluetooth: Add bluetooth server support (based on Zhenhua code)
Hi Fred, > Add bluetooth_ref()/bluetooth_unref() to support reference count in > bluetooth utils. didn't you had this as separate patch already? I think we should keep that as a separate patch. > --- > Makefile.am |2 +- > plugins/bluetooth.c | 396 -- > plugins/bluetooth.h | 11 ++ > 3 files changed, 392 insertions(+), 17 deletions(-) > > diff --git a/Makefile.am b/Makefile.am > index da59be7..fb3f750 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -312,7 +312,7 @@ builtin_sources += plugins/nokiacdma.c > > if BLUETOOTH > builtin_modules += bluetooth > -builtin_sources += plugins/bluetooth.c plugins/bluetooth.h > +builtin_sources += $(btio_sources) plugins/bluetooth.c plugins/bluetooth.h > > builtin_modules += hfp > builtin_sources += plugins/hfp.c plugins/bluetooth.h Please do it like this: builtin_sources += $(btio_sources) builtin_cflags += @BLUEZ_CFLAGS@ builtin_libadd += @BLUEZ_LIBS@ > +struct client { > + GIOChannel *io; > + guint watch; > +}; Why do you need both. Normally only the watch is enough? > +struct server { > + gchar *name; Don't bother with gchar. Just use char. > + guint8 channel; > + gchar *sdp_record; > + GIOChannel *io; > + gchar *adapter; > + guint handle; > + ConnectFunc connect_cb; > + gpointeruser_data; > + > + struct client client; Is it not simpler to just fold client_watch directly into it? > +}; > > void bluetooth_create_path(const char *dev_addr, const char *adapter_addr, > char *buf, int size) > @@ -370,6 +393,246 @@ static gboolean property_changed(DBusConnection > *connection, DBusMessage *msg, > return TRUE; > } > > +static void disconnect(struct server *server) > +{ > + struct client *client = &server->client; > + > + if (!client->io) > + return; > + > + g_io_channel_unref(client->io); > + client->io = NULL; > + > + if (client->watch > 0) { > + g_source_remove(client->watch); > + client->watch = 0; > + } > + > + return; Don't bother with return for functions returning void. > +} > + > +static void server_stop(gpointer data, gpointer user_data) > +{ > + struct server *server = data; > + > + disconnect(server); > + > + if (server->handle) { We do prefer service->handle > 0 for these cases. > + DBusMessage *msg; > + > + msg = dbus_message_new_method_call(BLUEZ_SERVICE, > + server->adapter, > + BLUEZ_SERVICE_INTERFACE, > + "RemoveRecord"); > + dbus_message_append_args(msg, DBUS_TYPE_UINT32, &server->handle, > + DBUS_TYPE_INVALID); > + g_dbus_send_message(connection, msg); > + > + server->handle = 0; > + } > + > + if (server->io) { And here please do server->io != NULL. > + g_io_channel_shutdown(server->io, TRUE, NULL); > + g_io_channel_unref(server->io); > + server->io = NULL; > + } > + > + g_free(server->adapter); > + server->adapter = NULL; > +} > + > +static gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer > data) > +{ > + struct server *server = data; > + > + disconnect(server); > + > + return FALSE; > +} > + > +static void cancel_authorization(struct server *server) > +{ > + DBusMessage *msg; > + > + if (!server->adapter) > + return; > + > + msg = dbus_message_new_method_call(BLUEZ_SERVICE, server->adapter, > + BLUEZ_SERVICE_INTERFACE, > + "CancelAuthorization"); Check that msg allocation succeeded before calling send. > + > + g_dbus_send_message(connection, msg); > +} > + > +static void auth_cb(DBusPendingCall *call, gpointer user_data) > +{ > + struct server *server = user_data; > + struct client *client = &server->client; > + GIOChannel *io = client->io; > + DBusMessage *reply = dbus_pending_call_steal_reply(call); > + DBusError derr; > + GError *err = NULL; > + > + dbus_error_init(&derr); > + > + if (dbus_set_error_from_message(&derr, reply)) { > + ofono_error("RequestAuthorization error: %s, %s", > + derr.name, derr.message); > + > + if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) > + cancel_authorization(server); > + > + dbus_error_free(&derr); > + goto failed; > + } > + > + ofono_info("RequestAuthorization succeeded"); > + > + if (!bt_io_accept(io, server->connect_cb, server->user_data, > + NULL, &err)) { > +
[PATCH] bluetooth: Add bluetooth server support (based on Zhenhua code)
It watches Bluetooth adapter property changes and adds SDP record to listen client connection request (refactored to support both DUN and HFP GW servers). Add bluetooth_ref()/bluetooth_unref() to support reference count in bluetooth utils. --- Makefile.am |2 +- plugins/bluetooth.c | 396 -- plugins/bluetooth.h | 11 ++ 3 files changed, 392 insertions(+), 17 deletions(-) diff --git a/Makefile.am b/Makefile.am index da59be7..fb3f750 100644 --- a/Makefile.am +++ b/Makefile.am @@ -312,7 +312,7 @@ builtin_sources += plugins/nokiacdma.c if BLUETOOTH builtin_modules += bluetooth -builtin_sources += plugins/bluetooth.c plugins/bluetooth.h +builtin_sources += $(btio_sources) plugins/bluetooth.c plugins/bluetooth.h builtin_modules += hfp builtin_sources += plugins/hfp.c plugins/bluetooth.h diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index 602c6da..fd6f541 100644 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -35,11 +35,34 @@ #include +#include #include "bluetooth.h" static DBusConnection *connection; static GHashTable *uuid_hash = NULL; static GHashTable *adapter_address_hash = NULL; +static GSList *server_list = NULL; +static gint ref_count; + +#define TIMEOUT (60*1000) /* Timeout for user response (miliseconds) */ + +struct client { + GIOChannel *io; + guint watch; +}; + +struct server { + gchar *name; + guint8 channel; + gchar *sdp_record; + GIOChannel *io; + gchar *adapter; + guint handle; + ConnectFunc connect_cb; + gpointeruser_data; + + struct client client; +}; void bluetooth_create_path(const char *dev_addr, const char *adapter_addr, char *buf, int size) @@ -370,6 +393,246 @@ static gboolean property_changed(DBusConnection *connection, DBusMessage *msg, return TRUE; } +static void disconnect(struct server *server) +{ + struct client *client = &server->client; + + if (!client->io) + return; + + g_io_channel_unref(client->io); + client->io = NULL; + + if (client->watch > 0) { + g_source_remove(client->watch); + client->watch = 0; + } + + return; +} + +static void server_stop(gpointer data, gpointer user_data) +{ + struct server *server = data; + + disconnect(server); + + if (server->handle) { + DBusMessage *msg; + + msg = dbus_message_new_method_call(BLUEZ_SERVICE, + server->adapter, + BLUEZ_SERVICE_INTERFACE, + "RemoveRecord"); + dbus_message_append_args(msg, DBUS_TYPE_UINT32, &server->handle, + DBUS_TYPE_INVALID); + g_dbus_send_message(connection, msg); + + server->handle = 0; + } + + if (server->io) { + g_io_channel_shutdown(server->io, TRUE, NULL); + g_io_channel_unref(server->io); + server->io = NULL; + } + + g_free(server->adapter); + server->adapter = NULL; +} + +static gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer data) +{ + struct server *server = data; + + disconnect(server); + + return FALSE; +} + +static void cancel_authorization(struct server *server) +{ + DBusMessage *msg; + + if (!server->adapter) + return; + + msg = dbus_message_new_method_call(BLUEZ_SERVICE, server->adapter, + BLUEZ_SERVICE_INTERFACE, + "CancelAuthorization"); + + g_dbus_send_message(connection, msg); +} + +static void auth_cb(DBusPendingCall *call, gpointer user_data) +{ + struct server *server = user_data; + struct client *client = &server->client; + GIOChannel *io = client->io; + DBusMessage *reply = dbus_pending_call_steal_reply(call); + DBusError derr; + GError *err = NULL; + + dbus_error_init(&derr); + + if (dbus_set_error_from_message(&derr, reply)) { + ofono_error("RequestAuthorization error: %s, %s", + derr.name, derr.message); + + if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY)) + cancel_authorization(server); + + dbus_error_free(&derr); + goto failed; + } + + ofono_info("RequestAuthorization succeeded"); + + if (!bt_io_accept(io, server->connect_cb, server->user_data, + NULL, &err)) { + ofono_error("%s", err->message); + g_error_free(err); + goto failed; + } + +