@@ -34,6 +34,7 @@
#include "lib/sdp.h"
#include "lib/uuid.h"
+#include "btio/btio.h"
#include "src/shared/util.h"
#include "src/shared/att.h"
#include "src/shared/queue.h"
@@ -47,6 +48,28 @@
#include "src/log.h"
#define IPSP_UUID16 0x1820
+#define IPSP_PSM 0x0023
+#define IPSP_MTU 1280
+
+struct ipsp_session {
+ GIOChannel *io;
+ unsigned int id;
+};
+
+static void ipsp_cleanup(struct btd_service *service)
+{
+ struct ipsp_session *session = btd_service_get_user_data(service);
+
+ if (!session)
+ return;
+
+ btd_service_set_user_data(service, NULL);
+
+ if (session->id > 0)
+ g_source_remove(session->id);
+
+ g_io_channel_unref(session->io);
+}
static int ipsp_probe(struct btd_service *service)
{
@@ -64,6 +87,49 @@ static void ipsp_remove(struct btd_service *service)
const char *path = device_get_path(device);
DBG("path %s", path);
+
+ ipsp_cleanup(service);
+}
+
+static gboolean ipsp_session(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ struct btd_service *service = data;
+
+ if (cond & G_IO_NVAL)
+ return FALSE;
+
+ if (cond & (G_IO_HUP | G_IO_ERR)) {
+ DBG("IPSP session disconnected");
+ ipsp_cleanup(service);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void ipsp_connect(GIOChannel *io, GError *err, gpointer user_data)
+{
+ struct btd_service *service = user_data;
+ struct ipsp_session *session = btd_service_get_user_data(service);
+
+ if (err) {
+ DBG("%s", err->message);
+
+ ipsp_cleanup(service);
+
+ btd_service_connecting_complete(service, -EIO);
+ return;
+ }
+
+ session->id = g_io_add_watch(io,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) ipsp_session, service);
+
+ g_io_channel_unref(session->io);
+ session->io = NULL;
+
+ btd_service_connecting_complete(service, 0);
}
static void foreach_ipsp_service(struct gatt_db_attribute *attr,
@@ -77,12 +143,13 @@ static void foreach_ipsp_service(struct gatt_db_attribute *attr,
static int ipsp_accept(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
+ struct btd_adapter *adapter = device_get_adapter(device);
struct gatt_db *db = btd_device_get_gatt_db(device);
- const char *path = device_get_path(device);
bool found = false;
bt_uuid_t ipsp_uuid;
+ struct ipsp_session *session;
- DBG("path %s", path);
+ DBG("path %s", device_get_path(device));
/* Handle the IPSP services */
bt_uuid16_create(&ipsp_uuid, IPSP_UUID16);
@@ -92,7 +159,33 @@ static int ipsp_accept(struct btd_service *service)
return -EINVAL;
}
- btd_service_connecting_complete(service, 0);
+ session = g_new0(struct ipsp_session, 1);
+ if (!session) {
+ error("Unable to allocate IPSP session");
+ return -ENOMEM;
+ }
+
+ /* Connect L2CAP channel */
+ session->io = bt_io_connect(ipsp_connect, service, NULL, NULL,
+ BT_IO_OPT_SOURCE_BDADDR,
+ btd_adapter_get_address(adapter),
+ BT_IO_OPT_SOURCE_TYPE,
+ btd_adapter_get_address_type(adapter),
+ BT_IO_OPT_DEST_BDADDR,
+ device_get_address(device),
+ BT_IO_OPT_DEST_TYPE,
+ btd_device_get_bdaddr_type(device),
+ BT_IO_OPT_PSM, IPSP_PSM,
+ BT_IO_OPT_IMTU, IPSP_MTU,
+ BT_IO_OPT_INVALID);
+ if (!session->io) {
+ error("Unable create IPSP connection");
+ g_free(session);
+ return -EIO;
+ }
+
+ /* Attach session to the service */
+ btd_service_set_user_data(service, session);
return 0;
}
@@ -104,6 +197,8 @@ static int ipsp_disconnect(struct btd_service *service)
DBG("path %s", path);
+ ipsp_cleanup(service);
+
btd_service_disconnecting_complete(service, 0);
return 0;
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> In case the remote device has IPSP service connect attempt to the IPSP L2CAP PSM. --- profiles/network/ipsp.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-)