summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2014-08-06 23:15:41 +0200
committerWim Taymans <wtaymans@redhat.com>2014-08-06 23:15:41 +0200
commit4ca6de134ead2aaa2280429df0ced0681c9ca523 (patch)
tree46d6a920510058e7af606933f7c1563d636d5cc0
parent638eb2e3a0124606200dfa11b185e22d10f20c1d (diff)
listen on RFCOMM
Listen on RFCOMM Rework add/remove of headsets in the manager
-rw-r--r--src/hsd-headset.c52
-rw-r--r--src/hsd-headset.h4
-rw-r--r--src/hsd-manager.c31
-rw-r--r--src/hsd-manager.h8
-rw-r--r--src/hsd-profile.c36
5 files changed, 98 insertions, 33 deletions
diff --git a/src/hsd-headset.c b/src/hsd-headset.c
index b8d536e..1af096c 100644
--- a/src/hsd-headset.c
+++ b/src/hsd-headset.c
@@ -188,9 +188,55 @@ dbus_get_property (GDBusConnection *conn, const gchar *service, const gchar *obj
return result;
}
+static gboolean
+rfcomm_io_cb (GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ gchar buf[512];
+ GIOStatus st;
+ HsdHeadset *h = data;
+
+ g_debug ("condition %d\n", condition);
+
+ if (condition & (G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ if (condition & G_IO_IN) {
+ gint fd = g_io_channel_unix_get_fd (source);
+ gsize length;
+
+ g_io_channel_read_chars (source, buf, 512, &length, NULL);
+ buf[length] = 0;
+ g_message ("%d %s", length, buf);
+
+ if (g_str_has_prefix (buf, "AT+BRSF=")) {
+ write (fd, "\r\n+BRSF:254\r\n", 13);
+ write (fd, "\r\nOK\r\n", 5);
+ }
+ else if (g_str_has_prefix (buf, "AT+CIND=?")) {
+ write (fd, "\r\n+CIND:254\r\n", 13);
+ write (fd, "\r\nOK\r\n", 5);
+ }
+ else if (g_str_has_prefix (buf, "AT+CIND?")) {
+ write (fd, "\r\n+CIND:254\r\n", 13);
+ write (fd, "\r\nOK\r\n", 5);
+ }
+ else if (g_str_has_prefix (buf, "AT+CMER=")) {
+ write (fd, "\r\n+VGM:15\r\n", 11);
+ write (fd, "\r\n+VGS:15\r\n", 11);
+ write (fd, "\r\nOK\r\n", 5);
+ }
+ else if (g_str_has_prefix (buf, "AT+CMEE=")) {
+ write (fd, "\r\nOK\r\n", 5);
+ }
+ else {
+ write (fd, "\r\nOK\r\n", 5);
+ }
+ }
+ return TRUE;
+}
HsdHeadset *
-hsd_headset_new (const gchar *device, GError **error)
+hsd_headset_new (const gchar *device, GIOChannel *rfcomm, GError **error)
{
GDBusConnection *conn = hsd_dbus_connection_get ();
HsdHeadset *headset;
@@ -199,6 +245,7 @@ hsd_headset_new (const gchar *device, GError **error)
headset = g_new0 (HsdHeadset, 1);
headset->device = g_strdup (device);
headset->transports = g_hash_table_new (g_str_hash, g_str_equal);
+ headset->rfcomm = rfcomm;
headset->device_addr = dbus_get_property (conn, "org.bluez", device, "org.bluez.Device1", "Address", error);
if (headset->device_addr == NULL)
@@ -227,6 +274,8 @@ hsd_headset_new (const gchar *device, GError **error)
if (headset->id == 0)
goto cleanup;
+ g_io_add_watch (headset->rfcomm, G_IO_IN | G_IO_ERR | G_IO_HUP, rfcomm_io_cb, headset);
+
return headset;
cleanup:
@@ -248,6 +297,7 @@ hsd_headset_free (HsdHeadset *headset)
g_free (headset->device_addr);
g_free (headset->adapter);
g_free (headset->adapter_addr);
+ g_io_channel_unref (headset->rfcomm);
g_hash_table_unref (headset->transports);
g_free (headset);
}
diff --git a/src/hsd-headset.h b/src/hsd-headset.h
index 5e5f5dd..c739a42 100644
--- a/src/hsd-headset.h
+++ b/src/hsd-headset.h
@@ -25,8 +25,10 @@ struct _HsdHeadset {
gchar *adapter;
gchar *adapter_addr;
+ GIOChannel *rfcomm;
+
GHashTable *transports;
};
-HsdHeadset * hsd_headset_new (const gchar *device, GError **error);
+HsdHeadset * hsd_headset_new (const gchar *device, GIOChannel *rfcomm, GError **error);
void hsd_headset_free (HsdHeadset *headset);
diff --git a/src/hsd-manager.c b/src/hsd-manager.c
index 8e1eee7..7a10264 100644
--- a/src/hsd-manager.c
+++ b/src/hsd-manager.c
@@ -161,17 +161,12 @@ hsd_manager_free (HsdManager *manager)
g_free (manager);
}
-HsdHeadset *
-hsd_manager_add_headset (HsdManager *manager, const gchar *device, GError **error)
+void
+hsd_manager_add_headset (HsdManager *manager, HsdHeadset *headset, GError **error)
{
GDBusConnection *conn = hsd_dbus_connection_get ();
- HsdHeadset *headset;
GError *local_error = NULL;
- headset = hsd_headset_new (device, error);
- if (headset == NULL)
- return NULL;
-
g_hash_table_insert (manager->devices, headset->device, headset);
g_dbus_connection_emit_signal (conn,
@@ -180,31 +175,23 @@ hsd_manager_add_headset (HsdManager *manager, const gchar *device, GError **erro
HSD_MANAGER_INTERFACE_SERVICE,
"DeviceAdded",
g_variant_new ("(oa{sv})",
- device,
+ headset->device,
NULL),
&local_error);
if (local_error != NULL) {
g_warning ("error emiting signal %s", local_error->message);
g_clear_error (&local_error);
}
- return headset;
}
void
-hsd_manager_remove_headset (HsdManager *manager, const gchar *device, GError **error)
+hsd_manager_remove_headset (HsdManager *manager, HsdHeadset *headset, GError **error)
{
GDBusConnection *conn = hsd_dbus_connection_get ();
- HsdHeadset *headset;
GError *local_error = NULL;
- headset = g_hash_table_lookup (manager->devices, device);
- if (headset == NULL) {
- g_warning ("unknown headset device %s", device);
+ if (!g_hash_table_remove (manager->devices, headset->device))
return;
- }
-
- g_hash_table_remove (manager->devices, device);
- hsd_headset_free (headset);
g_dbus_connection_emit_signal (conn,
NULL,
@@ -212,7 +199,7 @@ hsd_manager_remove_headset (HsdManager *manager, const gchar *device, GError **e
HSD_MANAGER_INTERFACE_SERVICE,
"DeviceRemoved",
g_variant_new ("(o)",
- device),
+ headset->device),
&local_error);
if (local_error != NULL) {
g_warning ("error emiting signal %s", local_error->message);
@@ -220,3 +207,9 @@ hsd_manager_remove_headset (HsdManager *manager, const gchar *device, GError **e
}
}
+HsdHeadset *
+hsd_manager_find_headset (HsdManager *manager, const gchar *key)
+{
+ return g_hash_table_lookup (manager->devices, key);
+}
+
diff --git a/src/hsd-manager.h b/src/hsd-manager.h
index 25c9eea..f4f607c 100644
--- a/src/hsd-manager.h
+++ b/src/hsd-manager.h
@@ -29,7 +29,9 @@ struct _HsdManager {
HsdManager * hsd_manager_new (GError **error);
void hsd_manager_free (HsdManager *manager);
-HsdHeadset * hsd_manager_add_headset (HsdManager *manager,
- const gchar *device, GError **error);
+void hsd_manager_add_headset (HsdManager *manager,
+ HsdHeadset *headset, GError **error);
void hsd_manager_remove_headset (HsdManager *manager,
- const gchar *device, GError **error);
+ HsdHeadset *headset, GError **error);
+
+HsdHeadset * hsd_manager_find_headset (HsdManager *manager, const gchar *key);
diff --git a/src/hsd-profile.c b/src/hsd-profile.c
index 3be9b8f..3625a46 100644
--- a/src/hsd-profile.c
+++ b/src/hsd-profile.c
@@ -20,6 +20,7 @@
#include <gio/gio.h>
#include "hsd.h"
+#include "hsd-headset.h"
#include "hsd-profile.h"
typedef struct {
@@ -78,18 +79,33 @@ profile_new_connection (HsdProfile *p,
GDBusMessage *message;
GUnixFDList * fdlist;
GError *error = NULL;
+ HsdHeadset *headset;
+ GIOChannel *rfcomm;
g_variant_get (parameters, "(oha{sv})", &obj, &fd, &props);
- g_debug ("profile NewConnection device=%s, fd=%d", obj, fd);
-
message = g_dbus_method_invocation_get_message (invocation);
fdlist = g_dbus_message_get_unix_fd_list (message);
fd = g_unix_fd_list_get (fdlist, fd, NULL);
+ g_debug ("profile NewConnection device=%s, fd=%d", obj, fd);
+
+ rfcomm = g_io_channel_unix_new (fd);
+ headset = hsd_headset_new (obj, rfcomm, &error);
+ if (headset == NULL)
+ goto failure;
+
+ hsd_manager_add_headset (p->manager, headset);
+
g_dbus_method_invocation_return_value (invocation, NULL);
- hsd_manager_add_headset (p->manager, obj, &error);
+ return;
+
+failure:
+ {
+ g_dbus_method_invocation_take_error (invocation, error);
+ return;
+ }
}
static void
@@ -98,22 +114,24 @@ profile_request_disconnection (HsdProfile *p,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
+ HsdHeadset *headset;
+ GError *error = NULL;
gchar *obj;
- gpointer t;
g_variant_get (parameters, "(o)", &obj);
g_debug ("profile RequestDisconnection device=%s", obj);
- t = g_hash_table_lookup (p->objs, obj);
- if (t == NULL)
- goto unknown_transport;
+ headset = hsd_manager_find_headset (p->manager, obj);
+ if (headset == NULL)
+ goto unknown_headset;
- g_hash_table_remove (p->objs, obj);
+ hsd_manager_remove_headset (p->manager, headset);
+ hsd_headset_free (headset);
g_dbus_method_invocation_return_value (invocation, NULL);
return;
-unknown_transport:
+unknown_headset:
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.freedesktop.Headset.Error.Rejected", "no such transport");