summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2014-08-02 20:39:40 +0200
committerWim Taymans <wtaymans@redhat.com>2014-08-02 20:39:40 +0200
commit2841a3e0963eb8a544e389f02cb5e3f24f2db843 (patch)
tree1fb9ff96066959d3c0fc89c00c64bfbd129a3d3b
parent854f4f6f507b224687b8800d284ce042a4625aba (diff)
implement Transport and call MediaEndpoint
-rwxr-xr-xcompile2
-rw-r--r--make-hsp-ag.c177
2 files changed, 164 insertions, 15 deletions
diff --git a/compile b/compile
index 4159fae..81804ed 100755
--- a/compile
+++ b/compile
@@ -1 +1 @@
-gcc `pkg-config --cflags --libs gio-2.0` -o make-hsp-ag make-hsp-ag.c
+gcc `pkg-config --cflags --libs gio-unix-2.0` -o make-hsp-ag make-hsp-ag.c
diff --git a/make-hsp-ag.c b/make-hsp-ag.c
index f5f4c16..59ac50b 100644
--- a/make-hsp-ag.c
+++ b/make-hsp-ag.c
@@ -18,6 +18,7 @@
*/
#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
#include <errno.h>
#include <sys/types.h>
@@ -48,10 +49,25 @@ static const gchar introspection_xml[] =
" <arg type='a{sv}' name='opts' direction='in'/>"
" </method>"
" </interface>"
+ " <interface name='org.bluez.MediaTransport1'>"
+ " <method name='Release'>"
+ " </method>"
+ " <method name='Acquire'>"
+ " <arg name='fd' direction='out' type='h'/>"
+ " <arg name='mtu_r' direction='out' type='q'/>"
+ " <arg name='mtu_w' direction='out' type='q'/>"
+ " </method>"
+ " <method name='TryAcquire'>"
+ " <arg name='fd' direction='out' type='h'/>"
+ " <arg name='mtu_r' direction='out' type='q'/>"
+ " <arg name='mtu_w' direction='out' type='q'/>"
+ " </method>"
+ " </interface>"
"</node>";
static struct sco_options so;
+#if 0
static gboolean
sco_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
{
@@ -82,10 +98,10 @@ sco_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
}
return TRUE;
}
+#endif
static int
-start_codec_connection (gchar *src_addr,
- gchar *dst_addr)
+transport_acquire (gchar *src_addr, gchar *dst_addr)
{
struct sockaddr_sco addr;
int err, i;
@@ -148,14 +164,15 @@ start_codec_connection (gchar *src_addr,
g_print ("connected: MTU %d\n", so.mtu);
+ /*
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);
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 0;
+ */
+ return sock;
}
static gboolean
@@ -195,7 +212,6 @@ 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);
- start_codec_connection ("FC:F8:AE:4A:3F:D4", "13:11:14:AA:00:B8");
}
else {
write (fd, "\r\nOK\r\n", 5);
@@ -205,14 +221,56 @@ rfcomm_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
}
static void
+transport_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)
+{
+ 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 (
+
+ } else if (g_strcmp0 (method_name, "TryAcquire") == 0) {
+ g_dbus_method_invocation_return_value (invocation, NULL);
+
+ } else if (g_strcmp0 (method_name, "Release") == 0) {
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+}
+
+static const GDBusInterfaceVTable transport_interface_vtable =
+{
+ transport_method_call,
+ NULL,
+ 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)
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
{
if (g_strcmp0 (method_name, "Release") == 0) {
@@ -222,15 +280,19 @@ profile_method_call (GDBusConnection *connection,
} else if (g_strcmp0 (method_name, "RequestDisconnection") == 0) {
g_print ("RequestDisconnection\n");
} else if (g_strcmp0 (method_name, "NewConnection") == 0) {
- gint fd;
+ gint32 fd;
gchar *obj;
GDBusMessage *message;
GUnixFDList * fdlist;
GIOChannel *channel;
+ GVariantIter *props_i;
+ GVariant *value;
gsize written;
+ gchar *key, *transport_name;
+ guint registration_id;
g_variant_get (parameters, "(oha{sv})",
- &obj, &fd, NULL);
+ &obj, &fd, &props_i);
message = g_dbus_method_invocation_get_message (invocation);
fdlist = g_dbus_message_get_unix_fd_list (message);
@@ -238,6 +300,93 @@ profile_method_call (GDBusConnection *connection,
g_print ("NewConnection %s %d\n", obj, fd);
+ /* 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);
+ }
+
+ /* 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);
+ }
+ }
+
+ 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);
+
channel = g_io_channel_unix_new (fd);
g_io_add_watch (channel, G_IO_IN, rfcomm_io_cb, NULL);