summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2014-08-04 21:05:29 +0200
committerWim Taymans <wtaymans@redhat.com>2014-08-04 21:05:29 +0200
commitd2f1fd297f35473207ceff3b09c3951568291d1a (patch)
treecabcefd6fbc46b251f9c391602eca627cb133795
parent2841a3e0963eb8a544e389f02cb5e3f24f2db843 (diff)
implement external profile
-rw-r--r--make-hsp-ag.c687
1 files changed, 436 insertions, 251 deletions
diff --git a/make-hsp-ag.c b/make-hsp-ag.c
index 59ac50b..0d963b8 100644
--- a/make-hsp-ag.c
+++ b/make-hsp-ag.c
@@ -28,6 +28,8 @@
#include <bluetooth/sco.h>
+#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb"
+
/* ---------------------------------------------------------------------------------------------------- */
static GDBusNodeInfo *introspection_data = NULL;
@@ -62,117 +64,130 @@ static const gchar introspection_xml[] =
" <arg name='mtu_r' direction='out' type='q'/>"
" <arg name='mtu_w' direction='out' type='q'/>"
" </method>"
+ " <property type='s' name='State' access='read'/>"
" </interface>"
"</node>";
-static struct sco_options so;
+typedef struct {
+ GDBusConnection *conn;
+ GDBusProxy *manager;
-#if 0
-static gboolean
-sco_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
-{
- gchar buf[1024];
- gsize length;
- gint fd = g_io_channel_unix_get_fd (source);
+ gchar *uuid;
+ gchar *name;
+ guint id;
- if (condition & G_IO_IN) {
- length = recv (fd, buf, 1024, 0);
- if (length <= 0)
- perror ("recv()");
- g_print ("-");
- } else if (condition & G_IO_OUT) {
- gint i;
-
- for (i = 0; i < 48; i++)
- buf[i] = g_random_int_range (0, 255);
-
- length = send (fd, buf, 48, 0);
- if (length != 48)
- perror ("send()");
-
- g_print ("+");
- usleep(2500);
- } else if (condition & (G_IO_ERR | G_IO_HUP)) {
- g_print ("got error\n");
- return FALSE;
- }
- return TRUE;
-}
-#endif
+ GHashTable *objs;
+} Profile;
-static int
-transport_acquire (gchar *src_addr, gchar *dst_addr)
-{
- struct sockaddr_sco addr;
- int err, i;
- int sock;
- GIOCondition cond;
- GIOChannel *io;
- bdaddr_t src;
- bdaddr_t dst;
- int voice = 0x60;
- socklen_t len;
+typedef struct {
+ Profile *profile;
- for (i = 5; i >= 0; i--, src_addr += 3)
- src.b[i] = strtol(src_addr, NULL, 16);
- for (i = 5; i >= 0; i--, dst_addr += 3)
- dst.b[i] = strtol(dst_addr, NULL, 16);
+ gchar *obj;
+ gint fd;
+ guint id;
+ gchar *state;
- sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
- if (sock < 0) {
- g_printerr("socket(SEQPACKET, SCO)");
- return -1;
- }
+ GVariantIter *props;
+ gchar *name;
- memset(&addr, 0, sizeof(addr));
- addr.sco_family = AF_BLUETOOTH;
- bacpy(&addr.sco_bdaddr, &src);
+ GIOChannel *channel;
+} MediaTransport;
- if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("bind()");
- return -1;
- }
+static void send_set_configuration_reply (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GError *error = NULL;
+ GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
- if (voice) {
- struct bt_voice opts;
+ g_dbus_connection_call_finish (connection, res, &error);
- /* SCO voice setting */
- memset(&opts, 0, sizeof(opts));
- opts.setting = voice;
- if (setsockopt(sock, SOL_BLUETOOTH, BT_VOICE, &opts, sizeof(opts)) < 0) {
- perror("setsockopt()");
- return -1;
- }
+ if (error) {
+ g_printerr ("error doing SetConfiguration %s", error->message);
+ g_clear_error (&error);
}
+}
- memset(&addr, 0, sizeof(addr));
- addr.sco_family = AF_BLUETOOTH;
- bacpy(&addr.sco_bdaddr, &dst);
+static void send_set_configuration (MediaTransport *t, const gchar *owner, const gchar *spath)
+{
+ /* send transport to endpoint */
+ GVariantBuilder *b;
+ GError *error = NULL;
- g_printerr ("doing connect\n");
- err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
- if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
- perror("connect()");
- return -1;
- }
+ b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (b, "{sv}", "UUID", g_variant_new_string ("0000111f-0000-1000-8000-00805f9b34fb"));
+ g_variant_builder_add (b, "{sv}", "Device", g_variant_new_object_path (t->obj));
+
+ g_dbus_connection_call (t->profile->conn,
+ owner,
+ spath,
+ "org.bluez.MediaEndpoint1",
+ "SetConfiguration",
+ g_variant_new ("(oa{sv})",
+ t->name,
+ b),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ send_set_configuration_reply,
+ t);
+}
- len = sizeof(so);
- if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &so, &len) < 0) {
- perror("getsockopt()");
- return -1;
- }
+static void
+media_transport_configure_endpoint (MediaTransport *t)
+{
+ GVariantIter *props_i = t->props;
+ GVariant *value;
+ gchar *key;
+
+ /* now go over all registered endpoints and inform them about the
+ * new transport object */
+ while (g_variant_iter_next (props_i, "{&sv}", &key, &value)) {
+ g_print (" prop: %s\n", key);
+
+ if (g_str_equal (key, "MediaEndpoints")) {
+ GVariantIter *endpoints_i;
+ gchar *owner;
+ GVariant *oprops;
+
+ g_variant_get (value, "a{sv}", &endpoints_i);
+
+ while (g_variant_iter_next (endpoints_i, "{&sv}", &owner, &oprops)) {
+ GVariantIter *oprops_i;
+ gchar *pname;
+ const gchar *spath;
+ GVariant *pval;
+
+ g_print (" owner: %s\n", owner);
+
+ g_variant_get (oprops, "a{sv}", &oprops_i);
+
+ while (g_variant_iter_next (oprops_i, "{&sv}", &pname, &pval)) {
+ if (g_variant_is_of_type (pval, G_VARIANT_TYPE_OBJECT_PATH)) {
+ spath = g_variant_get_string (pval, NULL);
+ g_print (" key: %s object-path=%s\n", pname, spath);
+ } else if (g_variant_is_of_type (pval, G_VARIANT_TYPE_BYTE)) {
+ g_print (" key: %s byte=%c\n", pname, g_variant_get_byte (pval));
+ } else if (g_variant_is_of_type (pval, G_VARIANT_TYPE_ARRAY)) {
+ g_print (" key: %s array\n", pname);
+ } else if (g_variant_is_of_type (pval, G_VARIANT_TYPE_STRING)) {
+ g_print (" key: %s string=%s\n", pname, g_variant_get_string (pval, NULL));
+ } else {
+ g_print (" key: %s (%s)\n", pname, g_variant_get_type_string (pval));
+ }
- g_print ("connected: MTU %d\n", so.mtu);
+ g_variant_unref (pval);
+ }
- /*
- io = g_io_channel_unix_new (sock);
- g_io_channel_set_close_on_unref(io, TRUE);
- g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
+ send_set_configuration (t, owner, spath);
- cond = G_IO_IN | G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
- g_io_add_watch(io, cond, sco_io_cb, NULL);
- */
- return sock;
+ g_variant_iter_free (oprops_i);
+ g_variant_unref (oprops);
+ }
+ g_variant_iter_free (endpoints_i);
+ }
+ g_variant_unref (value);
+ }
+ g_variant_iter_free (props_i);
}
static gboolean
@@ -180,6 +195,7 @@ rfcomm_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
{
gchar buf[512];
GIOStatus st;
+ MediaTransport *t = data;
g_print ("condition %d\n", condition);
@@ -212,6 +228,7 @@ rfcomm_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
}
else if (g_str_has_prefix (buf, "AT+CMEE=")) {
write (fd, "\r\nOK\r\n", 5);
+ media_transport_configure_endpoint (t);
}
else {
write (fd, "\r\nOK\r\n", 5);
@@ -221,6 +238,137 @@ rfcomm_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
}
static void
+transport_set_state (MediaTransport *t, const gchar *state)
+{
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GError *error;
+
+ error = NULL;
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (builder,
+ "{sv}",
+ "State",
+ g_variant_new_string (state));
+ g_dbus_connection_emit_signal (t->profile->conn,
+ NULL,
+ t->name,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ "org.bluez.MediaTransport1",
+ builder,
+ invalidated_builder),
+ &error);
+ g_assert_no_error (error);
+}
+
+static void
+transport_acquire (MediaTransport *t,
+ gboolean optional,
+ GDBusConnection *connection,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ GUnixFDList *fdlist;
+ GDBusMessage *reply;
+ GError *error;
+ guchar *blob;
+ gsize out_size;
+ struct sockaddr_sco addr;
+ int err, i;
+ GIOCondition cond;
+ GIOChannel *io;
+ bdaddr_t src;
+ bdaddr_t dst;
+ int voice = 0x60;
+ socklen_t len;
+ gchar *src_addr;
+ gchar *dst_addr;
+
+ src_addr = "FC:F8:AE:4A:3F:D4";
+ dst_addr = "13:11:14:AA:00:B8";
+
+ for (i = 5; i >= 0; i--, src_addr += 3)
+ src.b[i] = strtol(src_addr, NULL, 16);
+ for (i = 5; i >= 0; i--, dst_addr += 3)
+ dst.b[i] = strtol(dst_addr, NULL, 16);
+
+ t->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
+ if (t->fd < 0) {
+ g_printerr("socket(SEQPACKET, SCO)");
+ return;
+ }
+
+ g_print ("got fd %d\n", t->fd);
+ transport_set_state (t, "pending");
+
+ fdlist = g_unix_fd_list_new ();
+ g_unix_fd_list_append (fdlist, t->fd, NULL);
+ g_dbus_method_invocation_return_value_with_unix_fd_list (
+ invocation, g_variant_new ("(hqq)", 0, 48, 48), fdlist);
+
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sco_family = AF_BLUETOOTH;
+ bacpy(&addr.sco_bdaddr, &src);
+
+ if (bind(t->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind()");
+ return;
+ }
+
+ if (voice) {
+ struct bt_voice opts;
+
+ /* SCO voice setting */
+ memset(&opts, 0, sizeof(opts));
+ opts.setting = voice;
+ if (setsockopt(t->fd, SOL_BLUETOOTH, BT_VOICE, &opts, sizeof(opts)) < 0) {
+ perror("setsockopt()");
+ return;
+ }
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sco_family = AF_BLUETOOTH;
+ bacpy(&addr.sco_bdaddr, &dst);
+
+ g_printerr ("doing connect\n");
+ err = connect(t->fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
+ perror("connect()");
+ return;
+ }
+
+ g_printerr ("connected\n");
+ t->state = "active";
+
+ transport_set_state (t, "active");
+}
+
+static void
+transport_release (MediaTransport *t,
+ GDBusConnection *connection,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+
+ g_print ("close fd %d\n", t->fd);
+
+ if (t->fd != -1) {
+ shutdown (t->fd, SHUT_RDWR);
+ close (t->fd);
+ }
+ t->fd = -1;
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+
+ transport_set_state (t, "idle");
+}
+
+static void
transport_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
@@ -230,69 +378,105 @@ transport_method_call (GDBusConnection *connection,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
- if (g_strcmp0 (method_name, "Acquire") == 0) {
- gint fd;
- GUnixFDList *fdlist;
-
- fd = transport_acquire ("FC:F8:AE:4A:3F:D4", "13:11:14:AA:00:B8");
-
- g_print ("got fd %d\n", fd);
-
- fdlist = g_unix_fd_list_new ();
- g_unix_fd_list_append (fdlist, fd, NULL);
- fdlist= NULL;
-
- g_dbus_method_invocation_return_value_with_unix_fd_list (
- invocation, g_variant_new ("(hqq)", (gint32) 0, (guint16) 48, (guint16) 48), fdlist);
-
- //g_print ("%s\n", g_dbus_message_print (
+ MediaTransport *t = user_data;
+ if (g_strcmp0 (method_name, "Acquire") == 0) {
+ transport_acquire (t, TRUE, connection, parameters, invocation);
} else if (g_strcmp0 (method_name, "TryAcquire") == 0) {
- g_dbus_method_invocation_return_value (invocation, NULL);
-
+ transport_acquire (t, FALSE, connection, parameters, invocation);
} else if (g_strcmp0 (method_name, "Release") == 0) {
- g_dbus_method_invocation_return_value (invocation, NULL);
+ transport_release (t, connection, parameters, invocation);
+ }
+}
+
+static GVariant *
+transport_get_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ MediaTransport *t = user_data;
+ GVariant *ret;
+
+ ret = NULL;
+ if (g_strcmp0 (property_name, "State") == 0) {
+ ret = g_variant_new_string (t->state);
}
+ return ret;
}
static const GDBusInterfaceVTable transport_interface_vtable =
{
transport_method_call,
- NULL,
+ transport_get_property,
NULL
};
-static void
-profile_method_call (GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *method_name,
- GVariant *parameters,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
+static MediaTransport *
+media_transport_free (MediaTransport *t)
{
+ if (t->id)
+ g_dbus_connection_unregister_object (t->profile->conn, t->id);
+ if (t->channel)
+ g_io_channel_unref (t->channel);
+ g_free (t->obj);
+ g_free (t);
+}
- if (g_strcmp0 (method_name, "Release") == 0) {
- g_print ("Release\n");
- } else if (g_strcmp0 (method_name, "Cancel") == 0) {
- g_print ("Cancel\n");
- } else if (g_strcmp0 (method_name, "RequestDisconnection") == 0) {
- g_print ("RequestDisconnection\n");
- } else if (g_strcmp0 (method_name, "NewConnection") == 0) {
- gint32 fd;
+static MediaTransport *
+media_transport_new (Profile *p, const gchar *obj, gint fd, GVariantIter *props)
+{
+ MediaTransport *t;
+ GError *error = NULL;
+
+ t = g_new0 (MediaTransport, 1);
+ t->profile = p;
+ t->obj = g_strdup (obj);
+ t->fd = fd;
+ t->props = props;
+ t->state = "idle";
+
+ /* make a new transport object to handle the setup of the SCO connection */
+ t->name = g_strdup_printf ("%s/fd%d", obj, fd);
+ t->id = g_dbus_connection_register_object (p->conn,
+ t->name,
+ introspection_data->interfaces[1],
+ &transport_interface_vtable,
+ t,
+ (GDestroyNotify) media_transport_free, /* user_data_free_func */
+ &error); /* GError** */
+ if (t->id == 0) {
+ g_printerr ("error registering object %s\n", error->message);
+ media_transport_free (t);
+ return NULL;
+ }
+
+ t->channel = g_io_channel_unix_new (fd);
+ g_io_channel_set_close_on_unref (t->channel, TRUE);
+ g_io_add_watch (t->channel, G_IO_IN, rfcomm_io_cb, t);
+
+ g_hash_table_insert (p->objs, (gpointer) obj, t);
+
+ return t;
+}
+
+static void
+profile_new_connection (Profile *p,
+ GDBusConnection *connection,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
gchar *obj;
+ gint32 fd;
+ GVariantIter *props;
GDBusMessage *message;
GUnixFDList * fdlist;
- GIOChannel *channel;
- GVariantIter *props_i;
- GVariant *value;
- gsize written;
- gchar *key, *transport_name;
- guint registration_id;
+ MediaTransport *t;
- g_variant_get (parameters, "(oha{sv})",
- &obj, &fd, &props_i);
+ g_variant_get (parameters, "(oha{sv})", &obj, &fd, &props);
message = g_dbus_method_invocation_get_message (invocation);
fdlist = g_dbus_message_get_unix_fd_list (message);
@@ -300,100 +484,77 @@ profile_method_call (GDBusConnection *connection,
g_print ("NewConnection %s %d\n", obj, fd);
+ g_dbus_method_invocation_return_value (invocation, NULL);
+
/* make a new transport object to handle the setup of the SCO connection */
- transport_name = g_strdup_printf ("%s/fd%d", obj, fd);
-
- registration_id = g_dbus_connection_register_object (connection,
- transport_name,
- introspection_data->interfaces[1],
- &transport_interface_vtable,
- NULL,
- NULL, /* user_data_free_func */
- NULL); /* GError** */
- g_assert (registration_id > 0);
-
- /* now go over all registered endpoints and inform them about the
- * new transport object */
- while (g_variant_iter_next (props_i, "{&sv}", &key, &value)) {
- g_print (" prop: %s\n", key);
-
- if (g_str_equal (key, "MediaEndpoints")) {
- GVariantIter *endpoints_i;
- gchar *owner;
- GVariant *oprops;
-
- g_variant_get (value, "a{sv}", &endpoints_i);
-
- while (g_variant_iter_next (endpoints_i, "{&sv}", &owner, &oprops)) {
- GVariantIter *oprops_i;
- gchar *pname;
- const gchar *spath;
- GVariant *pval;
-
- g_print (" owner: %s\n", owner);
-
- g_variant_get (oprops, "a{sv}", &oprops_i);
-
- while (g_variant_iter_next (oprops_i, "{&sv}", &pname, &pval)) {
- if (g_variant_is_of_type (pval, G_VARIANT_TYPE_OBJECT_PATH)) {
- spath = g_variant_get_string (pval, NULL);
- g_print (" key: %s object-path=%s\n", pname, spath);
- } else if (g_variant_is_of_type (pval, G_VARIANT_TYPE_BYTE)) {
- g_print (" key: %s byte=%c\n", pname, g_variant_get_byte (pval));
- } else if (g_variant_is_of_type (pval, G_VARIANT_TYPE_ARRAY)) {
- g_print (" key: %s array\n", pname);
- } else if (g_variant_is_of_type (pval, G_VARIANT_TYPE_STRING)) {
- g_print (" key: %s string=%s\n", pname, g_variant_get_string (pval, NULL));
- } else {
- g_print (" key: %s (%s)\n", pname, g_variant_get_type_string (pval));
- }
-
- g_variant_unref (pval);
- }
+ t = media_transport_new (p, obj, fd, props);
+}
- /* send transport to endpoint */
- {
- GVariantBuilder *b;
- GError *error = NULL;
-
- b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (b, "{sv}", "UUID", g_variant_new_string ("0000111f-0000-1000-8000-00805f9b34fb"));
- g_variant_builder_add (b, "{sv}", "Device", g_variant_new_object_path (obj));
-
- g_dbus_connection_call_sync (connection,
- owner,
- spath,
- "org.bluez.MediaEndpoint1",
- "SetConfiguration",
- g_variant_new ("(oa{sv})",
- transport_name,
- b),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- if (error) {
- g_printerr ("error SetConfiguration %s\n", error->message);
- }
- }
+static void
+profile_request_disconnection (Profile *p,
+ GDBusConnection *connection,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ gchar *obj;
+ MediaTransport *t;
- g_variant_iter_free (oprops_i);
- g_variant_unref (oprops);
- }
- g_variant_iter_free (endpoints_i);
- }
- g_variant_unref (value);
+ g_variant_get (parameters, "(o)", &obj);
+
+ t = g_hash_table_lookup (p->objs, obj);
+ if (t == NULL) {
+ g_warning ("unknown transport object %s", obj);
+ goto done;
}
- g_variant_iter_free (props_i);
- channel = g_io_channel_unix_new (fd);
- g_io_add_watch (channel, G_IO_IN, rfcomm_io_cb, NULL);
+ g_hash_table_remove (p->objs, obj);
+
+ media_transport_free (t);
+
+done:
+ g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static void
+profile_release (Profile *p,
+ GDBusConnection *connection,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static void
+profile_cancel (Profile *p,
+ GDBusConnection *connection,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static void
+profile_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ Profile *p = user_data;
+ if (g_strcmp0 (method_name, "Release") == 0) {
+ profile_release (p, connection, parameters, invocation);
+ } else if (g_strcmp0 (method_name, "Cancel") == 0) {
+ profile_cancel (p, connection, parameters, invocation);
+ } else if (g_strcmp0 (method_name, "RequestDisconnection") == 0) {
+ profile_request_disconnection (p, connection, parameters, invocation);
+ } else if (g_strcmp0 (method_name, "NewConnection") == 0) {
+ profile_new_connection (p, connection, parameters, invocation);
} else
g_print ("Unhandled %s\n", method_name);
-
- g_dbus_method_invocation_return_value (invocation, NULL);
}
static const GDBusInterfaceVTable profile_interface_vtable =
@@ -403,50 +564,63 @@ static const GDBusInterfaceVTable profile_interface_vtable =
NULL
};
+static void profile_free (Profile *p)
+{
+ if (p->id)
+ g_dbus_connection_unregister_object (p->conn, p->id);
+ g_free (p->uuid);
+ g_free (p->name);
+ g_hash_table_unref (p->objs);
+ g_free (p);
+}
-static int
-register_profile (GDBusConnection *connection)
+static Profile *
+register_profile (GDBusConnection *connection, GDBusProxy * manager, const gchar *uuid)
{
GError *error = NULL;
- GDBusProxy *manager;
guint registration_id;
-
- g_print ("making proxy for ProfileManager1\n");
- manager = g_dbus_proxy_new_sync (connection,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL, "org.bluez", "/org/bluez", "org.bluez.ProfileManager1",
- NULL, &error);
- if (error != NULL) {
- g_printerr ("error getting ProfileManager1: %s", error->message);
- return -1;
+ Profile *profile;
+ GVariant *res;
+
+ profile = g_new0 (Profile, 1);
+ profile->conn = connection;
+ profile->manager = manager;
+ profile->name = g_strdup_printf ("/org/test/Profile");
+ profile->uuid = g_strdup (uuid);
+ profile->objs = g_hash_table_new (g_str_hash, g_str_equal);
+
+ profile->id = g_dbus_connection_register_object (connection,
+ profile->name,
+ introspection_data->interfaces[0],
+ &profile_interface_vtable,
+ profile,
+ (GDestroyNotify) profile_free, /* user_data_free_func */
+ &error); /* GError** */
+ if (profile->id == 0) {
+ g_printerr ("error registering object %s\n", error->message);
+ profile_free (profile);
+ return NULL;
}
- registration_id = g_dbus_connection_register_object (connection,
- "/org/test/Profile",
- introspection_data->interfaces[0],
- &profile_interface_vtable,
- NULL,
- NULL, /* user_data_free_func */
- NULL); /* GError** */
- g_assert (registration_id > 0);
-
g_print ("Register profile\n");
- g_dbus_proxy_call_sync (manager,
+ res = g_dbus_proxy_call_sync (manager,
"RegisterProfile",
g_variant_new ("(osa{sv})",
- "/org/test/Profile",
- "0000111f-0000-1000-8000-00805f9b34fb", NULL),
+ profile->name,
+ uuid, NULL),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
- if (error) {
+ if (res == NULL) {
g_printerr ("error registering %s\n", error->message);
- return -1;
+ profile_free (profile);
+ return NULL;
}
g_print ("Profile registered\n");
+ g_variant_unref (res);
- return 0;
+ return profile;
}
int
@@ -456,6 +630,7 @@ main (int argc, char *argv[])
GError *error = NULL;
GMainLoop *loop;
guint registration_id;
+ GDBusProxy *manager;
g_print ("connecting to system bus\n");
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
@@ -467,7 +642,17 @@ main (int argc, char *argv[])
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
g_assert (introspection_data != NULL);
- if (register_profile (connection) < 0)
+ g_print ("making proxy for ProfileManager1\n");
+ manager = g_dbus_proxy_new_sync (connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL, "org.bluez", "/org/bluez", "org.bluez.ProfileManager1",
+ NULL, &error);
+ if (error != NULL) {
+ g_printerr ("error getting ProfileManager1: %s", error->message);
+ return -1;
+ }
+
+ if (register_profile (connection, manager, HFP_AG_UUID) == NULL)
return -1;
g_print ("going into mainloop\n");