diff options
author | Wim Taymans <wtaymans@redhat.com> | 2014-08-06 23:15:41 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2014-08-06 23:15:41 +0200 |
commit | 4ca6de134ead2aaa2280429df0ced0681c9ca523 (patch) | |
tree | 46d6a920510058e7af606933f7c1563d636d5cc0 /src | |
parent | 638eb2e3a0124606200dfa11b185e22d10f20c1d (diff) |
listen on RFCOMM
Listen on RFCOMM
Rework add/remove of headsets in the manager
Diffstat (limited to 'src')
-rw-r--r-- | src/hsd-headset.c | 52 | ||||
-rw-r--r-- | src/hsd-headset.h | 4 | ||||
-rw-r--r-- | src/hsd-manager.c | 31 | ||||
-rw-r--r-- | src/hsd-manager.h | 8 | ||||
-rw-r--r-- | src/hsd-profile.c | 36 |
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"); |