From: "Frédéric Danis" <frederic.danis@linux.intel.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH v15 11/14] audio: Add DUN GW to org.bluez.Telephony
Date: Thu, 26 Jul 2012 10:45:21 +0200 [thread overview]
Message-ID: <1343292324-959-12-git-send-email-frederic.danis@linux.intel.com> (raw)
In-Reply-To: <1343292324-959-1-git-send-email-frederic.danis@linux.intel.com>
---
audio/telephony.c | 298 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 292 insertions(+), 6 deletions(-)
diff --git a/audio/telephony.c b/audio/telephony.c
index 99c2bbf..6581ff3 100644
--- a/audio/telephony.c
+++ b/audio/telephony.c
@@ -39,6 +39,7 @@
#include "btio.h"
#include "../src/adapter.h"
+#include "../src/manager.h"
#include "../src/device.h"
#include "log.h"
@@ -56,6 +57,7 @@
#define AUDIO_TELEPHONY_INTERFACE "org.bluez.Telephony"
#define AUDIO_TELEPHONY_AGENT_INTERFACE "org.bluez.TelephonyAgent"
+#define DEFAULT_DUN_GW_CHANNEL 1
#define DEFAULT_HS_HS_CHANNEL 6
#define DEFAULT_HS_AG_CHANNEL 12
#define DEFAULT_HF_HS_CHANNEL 7
@@ -123,7 +125,8 @@ struct telephony_device {
struct profile_config *config; /* default configuration */
char *name; /* agent DBus bus id */
char *path; /* agent object path */
- struct audio_device *au_dev; /* Audio device for HSP/HFP */
+ struct audio_device *au_dev; /* Audio device for HSP/HFP
+ * or NULL for DUN/SAP */
uint16_t version; /* remote profile version */
uint16_t features; /* remote supported features */
GIOChannel *rfcomm; /* connected RFCOMM channel */
@@ -132,6 +135,21 @@ struct telephony_device {
DBusPendingCall *call; /* D-Bus pending call */
};
+/*
+ * Connecting device
+ *
+ * Used for DUN and SAP gateway profiles in place of the audio device structure
+ * to store informations during connection phase, from device connection up to
+ * authentication completion.
+ */
+struct connecting_device {
+ const char *uuid;
+ struct btd_device *btd_dev;
+ bdaddr_t src, dst;
+ GIOChannel *rfcomm;
+ guint preauth_id;
+};
+
static DBusConnection *connection = NULL;
static GSList *agents = NULL; /* server list */
@@ -296,6 +314,198 @@ static gboolean agent_sendfd(struct telephony_device *tel_dev, int fd,
return TRUE;
}
+static void rfcomm_channel_close(GIOChannel *chan)
+{
+ int sock;
+
+ sock = g_io_channel_unix_get_fd(chan);
+ shutdown(sock, SHUT_RDWR);
+
+ g_io_channel_shutdown(chan, TRUE, NULL);
+ g_io_channel_unref(chan);
+}
+
+static gboolean client_dev_disconnect_cb(GIOChannel *chan,
+ GIOCondition cond,
+ struct telephony_device *tel_dev)
+{
+ if (cond & G_IO_NVAL)
+ return FALSE;
+
+ rfcomm_channel_close(tel_dev->rfcomm);
+ tel_dev->rfcomm = NULL;
+ telephony_device_disconnect(tel_dev);
+
+ return FALSE;
+}
+
+static void client_newconnection_reply(DBusPendingCall *call,
+ void *user_data)
+{
+ struct telephony_device *tel_dev = user_data;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ DBusError derr;
+
+ dbus_error_init(&derr);
+ if (!dbus_set_error_from_message(&derr, reply)) {
+ DBG("Agent reply: file descriptor passed successfully");
+ g_io_add_watch(tel_dev->rfcomm, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) client_dev_disconnect_cb, tel_dev);
+ goto done;
+ }
+
+ DBG("Agent reply: %s", derr.message);
+
+ dbus_error_free(&derr);
+ rfcomm_channel_close(tel_dev->rfcomm);
+ tel_dev->rfcomm = NULL;
+ telephony_device_disconnect(tel_dev);
+
+done:
+ dbus_pending_call_unref(tel_dev->call);
+ tel_dev->call = NULL;
+ dbus_message_unref(reply);
+}
+
+static void client_connect_cb(GIOChannel *chan, GError *err,
+ gpointer user_data)
+{
+ struct connecting_device *client = user_data;
+ struct telephony_device *tel_dev;
+ char hs_address[18];
+
+ if (err) {
+ error("%s", err->message);
+ rfcomm_channel_close(client->rfcomm);
+ goto done;
+ }
+
+ ba2str(&client->dst, hs_address);
+
+ tel_dev = telephony_device_connecting(chan, client->btd_dev, NULL,
+ client->uuid);
+ if (tel_dev == NULL) {
+ rfcomm_channel_close(client->rfcomm);
+ goto done;
+ }
+
+ DBG("%s: Connected to %s", device_get_path(client->btd_dev),
+ hs_address);
+
+done:
+ g_free(client);
+
+ return;
+}
+
+static void client_auth_cb(DBusError *derr, void *user_data)
+{
+ struct connecting_device *client = user_data;
+ GError *err = NULL;
+
+ if (client->preauth_id) {
+ g_source_remove(client->preauth_id);
+ client->preauth_id = 0;
+ }
+
+ if (derr && dbus_error_is_set(derr)) {
+ error("Access denied: %s", derr->message);
+ goto failed;
+ }
+
+ if (!bt_io_accept(client->rfcomm, client_connect_cb, client, NULL,
+ &err)) {
+ error("bt_io_accept: %s", err->message);
+ g_error_free(err);
+ goto failed;
+ }
+
+ return;
+
+failed:
+ rfcomm_channel_close(client->rfcomm);
+ g_free(client);
+}
+
+static gboolean client_preauth_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ struct connecting_device *client = user_data;
+
+ DBG("Client for %s disconnected during authorization", client->uuid);
+
+ btd_cancel_authorization(&client->src, &client->dst);
+
+ rfcomm_channel_close(client->rfcomm);
+ g_free(client);
+
+ return FALSE;
+}
+
+static void client_confirm(GIOChannel *chan, gpointer data)
+{
+ struct telephony_agent *agent = data;
+ struct connecting_device *client;
+ struct btd_adapter *adapter;
+ struct btd_device *btd_dev;
+ char addr[18];
+ int perr;
+ GError *err = NULL;
+ uint8_t ch;
+
+ client = g_new0(struct connecting_device, 1);
+ client->rfcomm = g_io_channel_ref(chan);
+
+ bt_io_get(chan, BT_IO_RFCOMM, &err,
+ BT_IO_OPT_SOURCE_BDADDR, &client->src,
+ BT_IO_OPT_DEST_BDADDR, &client->dst,
+ BT_IO_OPT_CHANNEL, &ch,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ ba2str(&client->src, addr);
+
+ adapter = manager_find_adapter(&client->src);
+ if (!adapter) {
+ error("Unable to get a btd_adapter object for %s", addr);
+ goto drop;
+ }
+
+ ba2str(&client->dst, addr);
+
+ btd_dev = adapter_get_device(connection, adapter, addr);
+ if (!btd_dev) {
+ error("Unable to get btd_device object for %s", addr);
+ goto drop;
+ }
+
+ client->uuid = agent->config->uuid;
+ client->btd_dev = btd_dev;
+
+ perr = btd_request_authorization(&client->src, &client->dst,
+ agent->config->uuid,
+ client_auth_cb, client);
+ if (perr < 0) {
+ DBG("Authorization denied: %s", strerror(-perr));
+ goto drop;
+ }
+
+ client->preauth_id = g_io_add_watch(chan,
+ G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+ client_preauth_cb, client);
+
+ return;
+
+drop:
+ rfcomm_channel_close(client->rfcomm);
+
+ g_free(client);
+}
+
static gboolean hs_dev_disconnect_cb(GIOChannel *chan, GIOCondition cond,
struct telephony_device *tel_dev)
{
@@ -443,7 +653,8 @@ struct telephony_device *telephony_device_connecting(GIOChannel *io,
struct telephony_agent *agent;
struct telephony_device *tel_dev;
uuid_t r_uuid;
- int err;
+ int sk;
+ int err = 0;
adapter = device_get_adapter(btd_dev);
agent = find_agent(adapter, NULL, NULL, uuid);
@@ -459,15 +670,28 @@ struct telephony_device *telephony_device_connecting(GIOChannel *io,
tel_dev->rfcomm = io;
tel_dev->features = 0xFFFF;
- sdp_uuid16_create(&r_uuid, tel_dev->config->r_class);
+ if (tel_dev->config->r_class == 0) {
+ sk = g_io_channel_unix_get_fd(tel_dev->rfcomm);
+
+ if (agent_sendfd(tel_dev, sk, tel_dev->config->connection_reply)
+ == FALSE) {
+ error("Failed to send RFComm socket to agent %s," \
+ " path %s", tel_dev->name, tel_dev->path);
+ err = -1;
+ }
+ } else {
+ sdp_uuid16_create(&r_uuid, tel_dev->config->r_class);
+
+ err = bt_search_service(&au_dev->src, &au_dev->dst, &r_uuid,
+ get_record_cb, tel_dev, NULL);
+ if (!err)
+ tel_dev->pending_sdp = TRUE;
+ }
- err = bt_search_service(&au_dev->src, &au_dev->dst, &r_uuid,
- get_record_cb, tel_dev, NULL);
if (err < 0) {
telephony_device_disconnect(tel_dev);
return NULL;
}
- tel_dev->pending_sdp = TRUE;
return tel_dev;
}
@@ -501,6 +725,60 @@ const char *telephony_get_agent_name(struct telephony_device *device)
return device->name;
}
+static sdp_record_t *dun_gw_record(struct telephony_agent *agent)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, svclass_uuid;
+ uuid_t l2cap_uuid, rfcomm_uuid;
+ sdp_profile_desc_t profile;
+ sdp_list_t *aproto, *proto[2];
+ sdp_record_t *record;
+ sdp_data_t *channel;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(0, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&svclass_uuid, DIALUP_NET_SVCLASS_ID);
+ svclass_id = sdp_list_append(0, &svclass_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
+ profile.version = agent->version;
+ pfseq = sdp_list_append(0, &profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto[0] = sdp_list_append(0, &l2cap_uuid);
+ apseq = sdp_list_append(0, proto[0]);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[1] = sdp_list_append(0, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &agent->config->channel);
+ proto[1] = sdp_list_append(proto[1], channel);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(0, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sdp_set_info_attr(record, "Dial-up Networking", 0, 0);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], 0);
+ sdp_list_free(proto[1], 0);
+ sdp_list_free(apseq, 0);
+ sdp_list_free(pfseq, 0);
+ sdp_list_free(aproto, 0);
+ sdp_list_free(root, 0);
+ sdp_list_free(svclass_id, 0);
+
+ return record;
+}
+
static sdp_record_t *hfp_hs_record(struct telephony_agent *agent)
{
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
@@ -917,6 +1195,14 @@ drop:
}
static struct profile_config default_configs[] = {
+ { DUN_GW_UUID,
+ DEFAULT_DUN_GW_CHANNEL,
+ NULL,
+ 0,
+ 0,
+ dun_gw_record,
+ client_confirm,
+ client_newconnection_reply },
{ HSP_AG_UUID,
DEFAULT_HS_AG_CHANNEL,
HSP_HS_UUID,
--
1.7.9.5
next prev parent reply other threads:[~2012-07-26 8:45 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-26 8:45 [PATCH v15 00/14] Add org.bluez.Telephony interface Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 01/14] doc: Add telephony interface documents Frédéric Danis
2012-07-27 7:52 ` Mikel Astiz
2012-07-27 8:30 ` Frederic Danis
2012-07-26 8:45 ` [PATCH v15 02/14] audio: Move telephony drivers to D-Bus interface Frédéric Danis
2012-07-27 8:25 ` Mikel Astiz
2012-07-27 9:33 ` Frederic Danis
2012-07-30 7:58 ` Johan Hedberg
2012-07-26 8:45 ` [PATCH v15 03/14] audio: Simplify org.bluez.Headset Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 04/14] audio: Remove dummy telephony driver Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 05/14] audio: Remove maemo5 " Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 06/14] audio: Remove maemo6 " Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 07/14] audio: Remove oFono " Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 08/14] audio: Move HFP/HSP AG servers to telephony.c Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 09/14] audio: Send transport path to telephony agent Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 10/14] audio: Move HFP HF server to telephony.c Frédéric Danis
2012-07-27 8:50 ` Mikel Astiz
2012-07-27 12:44 ` Frederic Danis
2012-07-26 8:45 ` Frédéric Danis [this message]
2012-07-26 8:45 ` [PATCH v15 12/14] audio: Add SAP GW to org.bluez.Telephony Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 13/14] adapter: Add API to get fast connectable mode Frédéric Danis
2012-07-26 8:45 ` [PATCH v15 14/14] audio: Add fast connectable to telephony interface Frédéric Danis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1343292324-959-12-git-send-email-frederic.danis@linux.intel.com \
--to=frederic.danis@linux.intel.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.