* [PATCH BlueZ 1/7] shared/io: Add io_recv
@ 2017-10-24 13:24 Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 2/7] shared: Add initial code for 6LoWPAN Luiz Augusto von Dentz
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds io_recv for reading using different buffer pointed by iovec.
---
src/shared/io-glib.c | 20 ++++++++++++++++++++
src/shared/io.h | 1 +
2 files changed, 21 insertions(+)
diff --git a/src/shared/io-glib.c b/src/shared/io-glib.c
index 6687a6b28..3ea68ac4e 100644
--- a/src/shared/io-glib.c
+++ b/src/shared/io-glib.c
@@ -280,6 +280,26 @@ ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)
return ret;
}
+ssize_t io_recv(struct io *io, const struct iovec *iov, int iovcnt)
+{
+ int fd;
+ ssize_t ret;
+
+ if (!io || !io->channel)
+ return -ENOTCONN;
+
+ fd = io_get_fd(io);
+
+ do {
+ ret = readv(fd, iov, iovcnt);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0)
+ return -errno;
+
+ return ret;
+}
+
bool io_shutdown(struct io *io)
{
if (!io || !io->channel)
diff --git a/src/shared/io.h b/src/shared/io.h
index 8bc1111d0..14f0034cf 100644
--- a/src/shared/io.h
+++ b/src/shared/io.h
@@ -35,6 +35,7 @@ int io_get_fd(struct io *io);
bool io_set_close_on_destroy(struct io *io, bool do_close);
ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt);
+ssize_t io_recv(struct io *io, const struct iovec *iov, int iovcnt);
bool io_shutdown(struct io *io);
typedef bool (*io_callback_func_t)(struct io *io, void *user_data);
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 2/7] shared: Add initial code for 6LoWPAN
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
@ 2017-10-24 13:24 ` Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 3/7] unit: Add initial test for bt_6lo Luiz Augusto von Dentz
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This introduces struct bt_6lo to interface with 6LoWPAN kernel
driver.
---
Makefile.am | 2 +-
src/shared/6lo.c | 523 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/shared/6lo.h | 40 +++++
3 files changed, 564 insertions(+), 1 deletion(-)
create mode 100644 src/shared/6lo.c
create mode 100644 src/shared/6lo.h
diff --git a/Makefile.am b/Makefile.am
index 8faabf44b..bb5a77408 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -119,7 +119,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \
src/shared/gatt-server.h src/shared/gatt-server.c \
src/shared/gatt-db.h src/shared/gatt-db.c \
src/shared/gap.h src/shared/gap.c \
- src/shared/tty.h
+ src/shared/tty.h src/shared/6lo.h src/shared/6lo.c
src_libshared_glib_la_SOURCES = $(shared_sources) \
src/shared/io-glib.c \
diff --git a/src/shared/6lo.c b/src/shared/6lo.c
new file mode 100644
index 000000000..3a0bf5678
--- /dev/null
+++ b/src/shared/6lo.c
@@ -0,0 +1,523 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/if_tun.h>
+#include <net/ethernet.h>
+#include <arpa/inet.h>
+#include <netinet/ip6.h>
+
+#include "src/shared/io.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
+#include "src/shared/6lo.h"
+
+#define DEV_6LO "/dev/net/tun"
+#define IFF_6LO 0x0040
+#define IFF_6LO_FLAGS IFF_TAP | IFF_6LO | IFF_NO_PI
+#define IFMTU ETHERMTU /* TUN/TAP doesn't seem to allow changing this */
+
+struct bt_6lo_chan {
+ struct bt_6lo_if *iface;
+ struct ether_addr addr;
+ struct io *io;
+};
+
+struct bt_6lo_if {
+ struct bt_6lo *lo;
+ struct ether_addr addr;
+ char name[IFNAMSIZ];
+ unsigned int index;
+ uint8_t buf[IFMTU];
+ struct io *io;
+ struct queue *channels;
+};
+
+struct bt_6lo {
+ int ref_count;
+ int fd;
+ struct queue *ifs;
+
+ bt_6lo_debug_func_t debug_callback;
+ bt_6lo_destroy_func_t debug_destroy;
+ void *debug_data;
+};
+
+static void chan_free(void *data)
+{
+ struct bt_6lo_chan *chan = data;
+
+ io_destroy(chan->io);
+ free(chan);
+}
+
+static void if_free(void *data)
+{
+ struct bt_6lo_if *iface = data;
+
+ queue_destroy(iface->channels, chan_free);
+ io_destroy(iface->io);
+ free(iface);
+}
+
+static void lo_free(struct bt_6lo *lo)
+{
+ if (lo->fd > 0)
+ close(lo->fd);
+
+ queue_destroy(lo->ifs, if_free);
+ free(lo);
+}
+
+struct bt_6lo *bt_6lo_new_default(void)
+{
+ int fd;
+ unsigned int flags;
+
+ if ((fd = open(DEV_6LO, O_RDWR)) < 0)
+ return NULL;
+
+ /* read back flags to check if IFF_6LO is supported */
+ if (ioctl(fd, TUNGETFEATURES, &flags) < 0 || !(flags & IFF_6LO)) {
+ close(fd);
+ return NULL;
+ }
+
+ return bt_6lo_new(fd);
+}
+
+struct bt_6lo *bt_6lo_new(int fd)
+{
+ struct bt_6lo *lo;
+
+ lo = new0(struct bt_6lo, 1);
+ lo->fd = fd;
+ lo->ifs = queue_new();
+
+ return bt_6lo_ref(lo);
+}
+
+struct bt_6lo *bt_6lo_ref(struct bt_6lo *lo)
+{
+ if (!lo)
+ return NULL;
+
+ __sync_fetch_and_add(&lo->ref_count, 1);
+
+ return lo;
+}
+
+void bt_6lo_unref(struct bt_6lo *lo)
+{
+ if (!lo)
+ return;
+
+ if (__sync_sub_and_fetch(&lo->ref_count, 1))
+ return;
+
+ lo_free(lo);
+}
+
+bool bt_6lo_set_debug(struct bt_6lo *lo, bt_6lo_debug_func_t callback,
+ void *user_data, bt_6lo_destroy_func_t destroy)
+{
+ if (!lo)
+ return false;
+
+ if (lo->debug_destroy)
+ lo->debug_destroy(lo->debug_data);
+
+ lo->debug_callback = callback;
+ lo->debug_destroy = destroy;
+ lo->debug_data = user_data;
+
+ return true;
+}
+
+static inline void memswap(void *dst, const void *src, size_t len)
+{
+ src += len - 1;
+
+ for (; len > 0; len--)
+ *((uint8_t *)dst++) = *((uint8_t *)src--);
+}
+
+static int if_setup(struct bt_6lo_if *iface)
+{
+ struct ifreq ifr = {};
+ int err = 0;
+ unsigned int family = ARPHRD_6LOWPAN;
+
+
+ /* Set ARPHRD_6LOWPAN as link type */
+ if (ioctl(iface->lo->fd, TUNSETLINK, family) < 0)
+ return -errno;
+
+ strcpy(ifr.ifr_name, iface->name);
+ ifr.ifr_hwaddr.sa_family = family;
+ memcpy(&ifr.ifr_hwaddr.sa_data, &iface->addr, sizeof(iface->addr));
+
+ if (ioctl(iface->lo->fd, SIOCSIFHWADDR, &ifr) < 0)
+ err = -errno;
+
+ return err;
+}
+
+static bool find_chan(const void *data, const void *match_data)
+{
+ const struct bt_6lo_chan *chan = data;
+ const struct ether_header *mac = match_data;
+
+ return !memcmp(&chan->addr, mac->ether_dhost, sizeof(chan->addr));
+}
+
+static bool if_read(struct io *io, void *user_data)
+{
+ struct bt_6lo_if *iface = user_data;
+ struct ether_header mac = {};
+ struct bt_6lo_chan *chan;
+ struct iovec iov[2];
+ ssize_t ret;
+
+ iov[0].iov_base = &mac;
+ iov[0].iov_len = sizeof(mac);
+
+ iov[1].iov_base = iface->buf;
+ iov[1].iov_len = sizeof(iface->buf);
+
+ ret = io_recv(io, iov, 2);
+ if (ret < 0 || (size_t) ret < sizeof(mac)) {
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "iface recv %zd", ret);
+ return true;
+ }
+
+ if (queue_length(iface->channels) == 1) {
+ chan = queue_peek_head(iface->channels);
+ goto done;
+ }
+
+ chan = queue_find(iface->channels, find_chan, &mac);
+ if (!chan) {
+ /* MAC doesn't match any of the existing channels? */
+ return true;
+ }
+
+done:
+ /* Update received length */
+ iov[1].iov_len = ret - sizeof(mac);
+
+ ret = io_send(chan->io, &iov[1], 1);
+ if (ret < 0) {
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "chan send %zd", ret);
+ return true;
+ }
+
+ return true;
+}
+
+static bool if_hup(struct io *io, void *user_data)
+{
+ struct bt_6lo_if *iface = user_data;
+
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "iface %s disconnected", iface->name);
+
+ queue_remove(iface->lo->ifs, iface);
+ if_free(iface);
+
+ return false;
+}
+
+int bt_6lo_add(struct bt_6lo *lo, const char *name, const uint8_t *addr)
+{
+ struct bt_6lo_if *iface;
+ struct ifreq ifr = {};
+ int err;
+
+ if (!lo)
+ return -EINVAL;
+
+ ifr.ifr_flags = IFF_6LO_FLAGS;
+ strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
+
+ if (lo->fd == -1) {
+ lo->fd = open(DEV_6LO, O_RDWR);
+ if (lo->fd < 0)
+ return -errno;
+ }
+
+ if (ioctl(lo->fd, TUNSETIFF, &ifr) < 0)
+ return -errno;
+
+ iface = new0(struct bt_6lo_if, 1);
+ iface->lo = lo;
+ memswap(&iface->addr, addr, sizeof(iface->addr));
+ strcpy(iface->name, ifr.ifr_name);
+ iface->index = if_nametoindex(iface->name);
+ iface->channels = queue_new();
+
+ err = if_setup(iface);
+ if (err < 0) {
+ if_free(iface);
+ return err;
+ }
+
+ iface->io = io_new(lo->fd);
+ io_set_close_on_destroy(iface->io, true);
+ io_set_read_handler(iface->io, if_read, iface, NULL);
+ io_set_disconnect_handler(iface->io, if_hup, iface, NULL);
+
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "iface %s added", iface->name);
+
+ lo->fd = -1;
+
+ queue_push_tail(lo->ifs, iface);
+
+ return 0;
+}
+
+static bool find_if_by_name(const void *data, const void *match_data)
+{
+ const struct bt_6lo_if *iface = data;
+ const char *name = match_data;
+
+ return !strcmp(iface->name, name);
+}
+
+static int if_name(struct bt_6lo *lo, const char *name, struct ifreq *ifr)
+{
+ struct bt_6lo_if *iface;
+
+ iface = queue_find(lo->ifs, find_if_by_name, name);
+ if (!iface)
+ return -ENOENT;
+
+ if_indextoname(iface->index, ifr->ifr_name);
+
+ return 0;
+}
+
+static int if_up(struct bt_6lo *lo, const char *name)
+{
+ struct ifreq ifr = {};
+ int fd, err;
+
+ if (!lo || !name)
+ return -EINVAL;
+
+ err = if_name(lo, name, &ifr);
+ if (err < 0)
+ return err;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ err = -errno;
+ goto done;
+ }
+
+ ifr.ifr_flags |= IFF_UP;
+ ifr.ifr_flags |= IFF_MULTICAST;
+
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+ err = -errno;
+ goto done;
+ }
+
+ util_debug(lo->debug_callback, lo->debug_data, "iface %s up",
+ ifr.ifr_name);
+
+done:
+ close(fd);
+
+ return err;
+}
+
+static int if_down(struct bt_6lo *lo, const char *name)
+{
+ struct ifreq ifr = {};
+ int fd, err;
+
+ if (!lo || !name)
+ return -EINVAL;
+
+ err = if_name(lo, name, &ifr);
+ if (err < 0)
+ return err;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ err = -errno;
+ goto done;
+ }
+
+ ifr.ifr_flags &= ~IFF_UP;
+
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+ err = -errno;
+ goto done;
+ }
+
+ util_debug(lo->debug_callback, lo->debug_data, "iface %s down",
+ ifr.ifr_name);
+
+done:
+ close(fd);
+
+ return err;
+}
+
+static bool find_if_by_addr(const void *data, const void *match_data)
+{
+ const struct bt_6lo_if *iface = data;
+ const uint8_t *addr = match_data;
+ struct ether_addr ifaddr;
+
+ memswap(&ifaddr, addr, sizeof(ifaddr));
+
+ return !memcmp(&iface->addr, &ifaddr, sizeof(iface->addr));
+}
+
+int bt_6lo_remove(struct bt_6lo *lo, const uint8_t *addr)
+{
+ struct bt_6lo_if *iface;
+
+ if (!lo)
+ return -EINVAL;
+
+ iface = queue_remove_if(lo->ifs, find_if_by_addr, (void *) addr);
+ if (!iface)
+ return -ENOENT;
+
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "iface %s removed", iface->name);
+
+ if_free(iface);
+
+ return 0;
+}
+
+static bool chan_hup(struct io *io, void *user_data)
+{
+ struct bt_6lo_chan *chan = user_data;
+ struct bt_6lo_if *iface = chan->iface;
+
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "chan %p hup", chan);
+
+ queue_remove(iface->channels, chan);
+ chan_free(chan);
+
+ /* Auto down when last IO is detached */
+ if (queue_isempty(iface->channels))
+ if_down(iface->lo, iface->name);
+
+ return false;
+}
+
+static bool chan_read(struct io *io, void *user_data)
+{
+ struct bt_6lo_chan *chan = user_data;
+ struct bt_6lo_if *iface = chan->iface;
+ struct ether_header mac = {};
+ struct iovec iov[2];
+ ssize_t ret;
+
+ iov[1].iov_base = iface->buf;
+ iov[1].iov_len = sizeof(iface->buf);
+
+ ret = io_recv(io, &iov[1], 1);
+ if (ret < 0) {
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "chan recv %zd", ret);
+ return true;
+ }
+
+ memcpy(&mac.ether_shost, &chan->addr, sizeof(mac.ether_shost));
+ memcpy(&mac.ether_dhost, &iface->addr, sizeof(mac.ether_dhost));
+
+ iov[0].iov_base = &mac;
+ iov[0].iov_len = sizeof(mac);
+
+ iov[1].iov_len = ret;
+
+ ret = io_send(iface->io, iov, 2);
+ if (ret < 0) {
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "iface send %zd", ret);
+ return true;
+ }
+
+ return true;
+}
+
+int bt_6lo_attach(struct bt_6lo *lo, const uint8_t *ifaddr, int fd,
+ const uint8_t *addr)
+{
+ struct bt_6lo_if *iface;
+ struct bt_6lo_chan *chan;
+
+ iface = queue_find(lo->ifs, find_if_by_addr, ifaddr);
+ if (!iface)
+ return -ENOENT;
+
+ chan = new0(struct bt_6lo_chan, 1);
+ chan->iface = iface;
+ memswap(&chan->addr, addr, sizeof(chan->addr));
+ chan->io = io_new(fd);
+ io_set_close_on_destroy(chan->io, true);
+ io_set_read_handler(chan->io, chan_read, chan, NULL);
+ io_set_disconnect_handler(chan->io, chan_hup, chan, NULL);
+
+ /* Auto up when first IO is attached */
+ if (queue_isempty(iface->channels))
+ if_up(lo, iface->name);
+
+ queue_push_tail(iface->channels, chan);
+
+ util_debug(iface->lo->debug_callback, iface->lo->debug_data,
+ "chan %p attached to %s", chan, iface->name);
+
+ return 0;
+}
diff --git a/src/shared/6lo.h b/src/shared/6lo.h
new file mode 100644
index 000000000..4dbe780b2
--- /dev/null
+++ b/src/shared/6lo.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+struct bt_6lo;
+
+struct bt_6lo *bt_6lo_new_default(void);
+struct bt_6lo *bt_6lo_new(int fd);
+
+struct bt_6lo *bt_6lo_ref(struct bt_6lo *lo);
+void bt_6lo_unref(struct bt_6lo *lo);
+
+typedef void (*bt_6lo_destroy_func_t)(void *user_data);
+typedef void (*bt_6lo_debug_func_t)(const char *str, void *user_data);
+bool bt_6lo_set_debug(struct bt_6lo *lo, bt_6lo_debug_func_t callback,
+ void *user_data, bt_6lo_destroy_func_t destroy);
+
+int bt_6lo_add(struct bt_6lo *lo, const char *name, const uint8_t *addr);
+int bt_6lo_remove(struct bt_6lo *lo, const uint8_t *addr);
+
+int bt_6lo_attach(struct bt_6lo *lo, const uint8_t *src, int fd,
+ const uint8_t *dst);
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 3/7] unit: Add initial test for bt_6lo
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 2/7] shared: Add initial code for 6LoWPAN Luiz Augusto von Dentz
@ 2017-10-24 13:24 ` Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 4/7] uuid: Add IPSP UUID Luiz Augusto von Dentz
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
Makefile.am | 6 ++
unit/test-6lo.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 277 insertions(+)
create mode 100644 unit/test-6lo.c
diff --git a/Makefile.am b/Makefile.am
index bb5a77408..3ba1a8dab 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -430,6 +430,12 @@ unit_test_midi_LDADD = src/libshared-glib.la \
@GLIB_LIBS@ @ALSA_LIBS@
endif
+unit_tests += unit/test-6lo
+
+unit_test_6lo_SOURCES = unit/test-6lo.c
+unit_test_6lo_LDADD = src/libshared-glib.la \
+ lib/libbluetooth-internal.la @GLIB_LIBS@
+
if MAINTAINER_MODE
noinst_PROGRAMS += $(unit_tests)
endif
diff --git a/unit/test-6lo.c b/unit/test-6lo.c
new file mode 100644
index 000000000..77f24e795
--- /dev/null
+++ b/unit/test-6lo.c
@@ -0,0 +1,271 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#include "src/shared/6lo.h"
+#include "src/shared/util.h"
+
+#include "src/shared/tester.h"
+
+struct test_pdu {
+ bool valid;
+ const uint8_t *data;
+ size_t size;
+};
+
+struct test_data {
+ char *test_name;
+ struct test_pdu *pdu_list;
+};
+
+struct context {
+ struct bt_6lo *lo;
+ guint source;
+ guint process;
+ int fd;
+ unsigned int pdu_offset;
+ const struct test_data *data;
+};
+
+#define data(args...) ((const unsigned char[]) { args })
+
+#define raw_pdu(args...) \
+ { \
+ .valid = true, \
+ .data = data(args), \
+ .size = sizeof(data(args)), \
+ }
+
+#define define_test(name, function, args...) \
+ do { \
+ const struct test_pdu pdus[] = { \
+ args, { } \
+ }; \
+ static struct test_data data; \
+ data.test_name = g_strdup(name); \
+ data.pdu_list = g_memdup(pdus, sizeof(pdus)); \
+ tester_add(name, &data, NULL, function, NULL); \
+ } while (0)
+
+static const uint8_t src[] = { 0xac, 0x9f, 0xa0, 0xf3, 0x42, 0x42 };
+static const uint8_t dst[] = { 0xac, 0x9f, 0xa0, 0xf3, 0x42, 0x43 };
+
+static void test_debug(const char *str, void *user_data)
+{
+ const char *prefix = user_data;
+
+ tester_debug("%s%s\n", prefix, str);
+}
+
+static void test_free(gconstpointer user_data)
+{
+ const struct test_data *data = user_data;
+
+ g_free(data->test_name);
+ g_free(data->pdu_list);
+}
+
+static void destroy_context(struct context *context)
+{
+ if (context->source > 0)
+ g_source_remove(context->source);
+
+ bt_6lo_unref(context->lo);
+
+ test_free(context->data);
+ g_free(context);
+}
+
+static gboolean context_quit(gpointer user_data)
+{
+ struct context *context = user_data;
+
+ if (context == NULL)
+ return FALSE;
+
+ if (context->process > 0)
+ g_source_remove(context->process);
+
+ destroy_context(context);
+ tester_test_passed();
+
+ return FALSE;
+}
+
+static gboolean send_pdu(gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_pdu *pdu;
+ ssize_t len;
+
+ pdu = &context->data->pdu_list[context->pdu_offset++];
+
+ len = write(context->fd, pdu->data, pdu->size);
+
+ util_hexdump('<', pdu->data, len, test_debug, "6lo: ");
+
+ g_assert_cmpint(len, ==, pdu->size);
+
+ context->process = 0;
+ return FALSE;
+}
+
+static void context_process(struct context *context)
+{
+ if (!context->data->pdu_list[context->pdu_offset].valid) {
+ context_quit(context);
+ return;
+ }
+
+ context->process = g_idle_add(send_pdu, context);
+}
+
+static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
+ gpointer user_data)
+{
+ struct context *context = user_data;
+ const struct test_pdu *pdu;
+ unsigned char buf[1280];
+ ssize_t len;
+ int fd;
+
+ pdu = &context->data->pdu_list[context->pdu_offset++];
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+ context->source = 0;
+ g_print("%s: cond %x\n", __func__, cond);
+ return FALSE;
+ }
+
+ fd = g_io_channel_unix_get_fd(channel);
+
+ len = read(fd, buf, sizeof(buf));
+
+ g_assert(len > 0);
+
+ util_hexdump('>', buf, len, test_debug, "6lo: ");
+
+ g_assert_cmpint(len, ==, pdu->size);
+
+ g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+ context_process(context);
+
+ return TRUE;
+}
+
+static struct context *create_context(gconstpointer data)
+{
+ struct bt_6lo *lo;
+ struct context *context;
+ int err = 0;
+
+ lo = bt_6lo_new_default();
+ if (!lo) {
+ err = -ENOTSUP;
+ goto fail;
+ }
+
+ err = bt_6lo_add(lo, "bt0", src);
+ if (err < 0) {
+ bt_6lo_unref(lo);
+ goto fail;
+ }
+
+ context = g_new0(struct context, 1);
+ context->lo = lo;
+
+ context->data = data;
+
+ return context;
+
+fail:
+ tester_warn("Failed to setup bt_6lo: %s", strerror(-err));
+ return NULL;
+}
+
+static void attach_client(struct context *context)
+{
+ GIOChannel *channel;
+ int err, sv[2];
+
+ err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+ g_assert(err == 0);
+
+ err = bt_6lo_attach(context->lo, src, sv[0], dst);
+ g_assert(err == 0);
+
+ channel = g_io_channel_unix_new(sv[1]);
+
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+
+ context->source = g_io_add_watch(channel,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ test_handler, context);
+ g_assert(context->source > 0);
+
+ g_io_channel_unref(channel);
+
+ context->fd = sv[1];
+}
+
+static void test_run(gconstpointer data)
+{
+ struct context *context = create_context(data);
+
+ if (!context) {
+ tester_test_abort();
+ return;
+ }
+
+ if (!g_str_equal(context->data->test_name, "/6lo/init"))
+ attach_client(context);
+
+ context_quit(context);
+}
+
+int main(int argc, char *argv[])
+{
+ tester_init(&argc, &argv);
+
+ define_test("/6lo/init", test_run, raw_pdu());
+ define_test("/6lo/attach", test_run, raw_pdu());
+
+ return tester_run();
+}
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 4/7] uuid: Add IPSP UUID
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 2/7] shared: Add initial code for 6LoWPAN Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 3/7] unit: Add initial test for bt_6lo Luiz Augusto von Dentz
@ 2017-10-24 13:24 ` Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 5/7] build: Add IPSP plugin Luiz Augusto von Dentz
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds IPSP UUID in string format.
---
lib/uuid.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/uuid.h b/lib/uuid.h
index 2c57a3378..71ed3df3b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -81,6 +81,8 @@ extern "C" {
#define SENSOR_LOCATION_UUID "00002a5d-0000-1000-8000-00805f9b34fb"
#define SC_CONTROL_POINT_UUID "00002a55-0000-1000-8000-00805f9b34fb"
+#define IPSP_UUID "00001820-0000-1000-8000-00805f9b34fb"
+
#define RFCOMM_UUID_STR "00000003-0000-1000-8000-00805f9b34fb"
#define HDP_UUID "00001400-0000-1000-8000-00805f9b34fb"
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 5/7] build: Add IPSP plugin
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
` (2 preceding siblings ...)
2017-10-24 13:24 ` [PATCH BlueZ 4/7] uuid: Add IPSP UUID Luiz Augusto von Dentz
@ 2017-10-24 13:24 ` Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 6/7] ipsp: Connect to IPSP PSM Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 7/7] ipsp: Add support for bt_6lo Luiz Augusto von Dentz
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds the initial plugin structure to handle IPSP profile.
---
Makefile.plugins | 5 ++
configure.ac | 4 ++
profiles/network/ipsp.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 141 insertions(+)
create mode 100644 profiles/network/ipsp.c
diff --git a/Makefile.plugins b/Makefile.plugins
index 73377e532..b5127b697 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -53,6 +53,11 @@ builtin_sources += profiles/network/manager.c \
profiles/network/connection.c
endif
+if IPSP
+builtin_modules += ipsp
+builtin_sources += profiles/network/ipsp.c
+endif
+
if HID
builtin_modules += input
builtin_sources += profiles/input/manager.c \
diff --git a/configure.ac b/configure.ac
index 964101412..24489f7d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -160,6 +160,10 @@ AC_ARG_ENABLE(network, AC_HELP_STRING([--disable-network],
[disable network profiles]), [enable_network=${enableval}])
AM_CONDITIONAL(NETWORK, test "${enable_network}" != "no")
+AC_ARG_ENABLE(ipsp, AC_HELP_STRING([--disable-ipsp],
+ [disable ipsp profile]), [enable_ipsp=${enableval}])
+AM_CONDITIONAL(IPSP, test "${enable_ipsp}" != "no")
+
AC_ARG_ENABLE(hid, AC_HELP_STRING([--disable-hid],
[disable HID profile]), [enable_hid=${enableval}])
AM_CONDITIONAL(HID, test "${enable_hid}" != "no")
diff --git a/profiles/network/ipsp.c b/profiles/network/ipsp.c
new file mode 100644
index 000000000..2645b0598
--- /dev/null
+++ b/profiles/network/ipsp.c
@@ -0,0 +1,132 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/sdp.h"
+#include "lib/uuid.h"
+
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/plugin.h"
+#include "src/adapter.h"
+#include "src/device.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/log.h"
+
+#define IPSP_UUID16 0x1820
+
+static int ipsp_probe(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ const char *path = device_get_path(device);
+
+ DBG("path %s", path);
+
+ return 0;
+}
+
+static void ipsp_remove(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ const char *path = device_get_path(device);
+
+ DBG("path %s", path);
+}
+
+static void foreach_ipsp_service(struct gatt_db_attribute *attr,
+ void *user_data)
+{
+ bool *found = user_data;
+
+ *found = true;
+}
+
+static int ipsp_accept(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ 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;
+
+ DBG("path %s", path);
+
+ /* Handle the IPSP services */
+ bt_uuid16_create(&ipsp_uuid, IPSP_UUID16);
+ gatt_db_foreach_service(db, &ipsp_uuid, foreach_ipsp_service, &found);
+ if (!found) {
+ error("IPSP attribute not found");
+ return -EINVAL;
+ }
+
+ btd_service_connecting_complete(service, 0);
+
+ return 0;
+}
+
+static int ipsp_disconnect(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ const char *path = device_get_path(device);
+
+ DBG("path %s", path);
+
+ btd_service_disconnecting_complete(service, 0);
+
+ return 0;
+}
+
+static struct btd_profile ipsp_profile = {
+ .name = "network-ipsp",
+ .remote_uuid = IPSP_UUID,
+ .device_probe = ipsp_probe,
+ .device_remove = ipsp_remove,
+ .accept = ipsp_accept,
+ .disconnect = ipsp_disconnect,
+};
+
+static int ipsp_init(void)
+{
+ return btd_profile_register(&ipsp_profile);
+}
+
+static void ipsp_exit(void)
+{
+ btd_profile_unregister(&ipsp_profile);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(ipsp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ ipsp_init, ipsp_exit)
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 6/7] ipsp: Connect to IPSP PSM
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
` (3 preceding siblings ...)
2017-10-24 13:24 ` [PATCH BlueZ 5/7] build: Add IPSP plugin Luiz Augusto von Dentz
@ 2017-10-24 13:24 ` Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 7/7] ipsp: Add support for bt_6lo Luiz Augusto von Dentz
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
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(-)
diff --git a/profiles/network/ipsp.c b/profiles/network/ipsp.c
index 2645b0598..28683f4b6 100644
--- a/profiles/network/ipsp.c
+++ b/profiles/network/ipsp.c
@@ -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;
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH BlueZ 7/7] ipsp: Add support for bt_6lo
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
` (4 preceding siblings ...)
2017-10-24 13:24 ` [PATCH BlueZ 6/7] ipsp: Connect to IPSP PSM Luiz Augusto von Dentz
@ 2017-10-24 13:24 ` Luiz Augusto von Dentz
5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2017-10-24 13:24 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This makes use of bt_6lo instance to create interfaces and attach
channels to them.
---
profiles/network/ipsp.c | 131 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 111 insertions(+), 20 deletions(-)
diff --git a/profiles/network/ipsp.c b/profiles/network/ipsp.c
index 28683f4b6..f6bace956 100644
--- a/profiles/network/ipsp.c
+++ b/profiles/network/ipsp.c
@@ -40,6 +40,7 @@
#include "src/shared/queue.h"
#include "src/shared/gatt-db.h"
#include "src/shared/gatt-client.h"
+#include "src/shared/6lo.h"
#include "src/plugin.h"
#include "src/adapter.h"
#include "src/device.h"
@@ -50,8 +51,12 @@
#define IPSP_UUID16 0x1820
#define IPSP_PSM 0x0023
#define IPSP_MTU 1280
+#define IF_PREFIX "bt"
+
+static struct bt_6lo *lo;
struct ipsp_session {
+ int ifindex;
GIOChannel *io;
unsigned int id;
};
@@ -63,36 +68,49 @@ static void ipsp_cleanup(struct btd_service *service)
if (!session)
return;
- btd_service_set_user_data(service, NULL);
-
- if (session->id > 0)
+ if (session->id > 0) {
g_source_remove(session->id);
+ session->id = 0;
+ }
- g_io_channel_unref(session->io);
+ if (session->io) {
+ g_io_channel_unref(session->io);
+ session->io = NULL;
+ }
}
static int ipsp_probe(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
const char *path = device_get_path(device);
+ struct ipsp_session *session;
DBG("path %s", path);
+ session = new0(struct ipsp_session, 1);
+
+ /* Attach session to the service */
+ btd_service_set_user_data(service, session);
+
return 0;
}
static void ipsp_remove(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
+ struct ipsp_session *session = btd_service_get_user_data(service);
const char *path = device_get_path(device);
DBG("path %s", path);
ipsp_cleanup(service);
+
+ btd_service_set_user_data(service, NULL);
+
+ g_free(session);
}
-static gboolean ipsp_session(GIOChannel *chan, GIOCondition cond,
- gpointer data)
+static gboolean ipsp_hup(GIOChannel *chan, GIOCondition cond, gpointer data)
{
struct btd_service *service = data;
@@ -112,19 +130,38 @@ 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);
+ GError *gerr = NULL;
+ bdaddr_t src, dst;
+ int fd;
if (err) {
DBG("%s", err->message);
-
ipsp_cleanup(service);
+ btd_service_connecting_complete(service, -EIO);
+ return;
+ }
+
+ bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (gerr) {
+ error("bt_io_get: %s", gerr->message);
+ g_error_free(gerr);
+ g_io_channel_unref(io);
+ return;
+ }
+
+ fd = g_io_channel_unix_get_fd(io);
+ if (bt_6lo_attach(lo, src.b, fd, dst.b) < 0) {
+ DBG("Unable to attach channel");
+ 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);
+ session->id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) ipsp_hup, service);
g_io_channel_unref(session->io);
session->io = NULL;
@@ -144,10 +181,10 @@ 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 ipsp_session *session = btd_service_get_user_data(service);
struct gatt_db *db = btd_device_get_gatt_db(device);
bool found = false;
bt_uuid_t ipsp_uuid;
- struct ipsp_session *session;
DBG("path %s", device_get_path(device));
@@ -159,11 +196,8 @@ static int ipsp_accept(struct btd_service *service)
return -EINVAL;
}
- session = g_new0(struct ipsp_session, 1);
- if (!session) {
- error("Unable to allocate IPSP session");
- return -ENOMEM;
- }
+ if (session->io)
+ return -EINPROGRESS;
/* Connect L2CAP channel */
session->io = bt_io_connect(ipsp_connect, service, NULL, NULL,
@@ -184,9 +218,6 @@ static int ipsp_accept(struct btd_service *service)
return -EIO;
}
- /* Attach session to the service */
- btd_service_set_user_data(service, session);
-
return 0;
}
@@ -213,14 +244,74 @@ static struct btd_profile ipsp_profile = {
.disconnect = ipsp_disconnect,
};
+static int net_6lo_probe(struct btd_adapter *adapter)
+{
+ uint16_t index = btd_adapter_get_index(adapter);
+ const bdaddr_t *addr = btd_adapter_get_address(adapter);
+ char *ifname;
+ int err;
+
+ DBG("");
+
+ ifname = g_strdup_printf("%s%u", IF_PREFIX, index);
+
+ err = bt_6lo_add(lo, ifname, addr->b);
+
+ g_free(ifname);
+
+ return err;
+}
+
+static void net_6lo_remove(struct btd_adapter *adapter)
+{
+ const bdaddr_t *addr = btd_adapter_get_address(adapter);
+
+ DBG("");
+
+ bt_6lo_remove(lo, addr->b);
+}
+
+static struct btd_adapter_driver net_6lo_driver = {
+ .name = "network-6lo",
+ .probe = net_6lo_probe,
+ .remove = net_6lo_remove,
+};
+
+static void net_6lo_debug(const char *str, void *user_data)
+{
+ DBG("%s", str);
+}
+
static int ipsp_init(void)
{
- return btd_profile_register(&ipsp_profile);
+ int err;
+
+ lo = bt_6lo_new_default();
+ if (!lo)
+ return -ENOTSUP;
+
+ bt_6lo_set_debug(lo, net_6lo_debug, NULL, NULL);
+
+ err = btd_register_adapter_driver(&net_6lo_driver);
+ if (err < 0) {
+ bt_6lo_unref(lo);
+ return err;
+ }
+
+ err = btd_profile_register(&ipsp_profile);
+ if (err < 0) {
+ btd_unregister_adapter_driver(&net_6lo_driver);
+ bt_6lo_unref(lo);
+ }
+
+ return err;
}
static void ipsp_exit(void)
{
btd_profile_unregister(&ipsp_profile);
+ btd_unregister_adapter_driver(&net_6lo_driver);
+ bt_6lo_unref(lo);
}
BLUETOOTH_PLUGIN_DEFINE(ipsp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
--
2.13.6
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-10-24 13:24 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-24 13:24 [PATCH BlueZ 1/7] shared/io: Add io_recv Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 2/7] shared: Add initial code for 6LoWPAN Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 3/7] unit: Add initial test for bt_6lo Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 4/7] uuid: Add IPSP UUID Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 5/7] build: Add IPSP plugin Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 6/7] ipsp: Connect to IPSP PSM Luiz Augusto von Dentz
2017-10-24 13:24 ` [PATCH BlueZ 7/7] ipsp: Add support for bt_6lo Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).