2015-03-12 17:07:27

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 0/6] Create bneptest tool

v4:
- Fix error returning in bnep server add
- Reorganize bnep service comparing (by uuid, by string),
- Fixed pointed by Szymon commit message typo,
- Add support for sending general bnep frames by bneptest,
- bneptest now require bridge and iface name (it was optional-def. names were
set)
- Update PTS results and test instructions.
v5:
- Fix converting uuids (16 to 128),
- Extend bneptest with frames retransmission parameters,
- Update PTS results and test instructions.

Grzegorz Kolodziejczyk (6):
profiles/network: Remove unneded bnep_uuid function from bnep code
profiles/network: Remove not needed get name by bnep id function
profiles/network: Move disconn cb setting to bnep connect method
tools/bneptest: Add initial support for bneptest tool
tools/bneptest: Add generic connect/listen functionality
android/pts: Add BNEP PTS 6.0 results for android 5.0

.gitignore | 1 +
Makefile.tools | 12 +-
android/Android.mk | 35 ++
android/Makefile.am | 5 +-
android/pan.c | 5 +-
android/pics-bnep.txt | 26 ++
android/pixit-bnep.txt | 30 ++
android/pts-bnep.txt | 48 +++
profiles/network/bnep.c | 53 +--
profiles/network/bnep.h | 9 +-
profiles/network/connection.c | 23 +-
profiles/network/server.c | 36 +-
tools/bneptest.c | 777 ++++++++++++++++++++++++++++++++++++++++++
13 files changed, 985 insertions(+), 75 deletions(-)
create mode 100644 android/pics-bnep.txt
create mode 100644 android/pixit-bnep.txt
create mode 100644 android/pts-bnep.txt
create mode 100644 tools/bneptest.c

--
2.1.0



2015-03-12 22:34:13

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v5 0/6] Create bneptest tool

Hi Grzegorz,

On Thursday 12 March 2015 18:07:27 Grzegorz Kolodziejczyk wrote:
> v4:
> - Fix error returning in bnep server add
> - Reorganize bnep service comparing (by uuid, by string),
> - Fixed pointed by Szymon commit message typo,
> - Add support for sending general bnep frames by bneptest,
> - bneptest now require bridge and iface name (it was optional-def. names
> were set)
> - Update PTS results and test instructions.
> v5:
> - Fix converting uuids (16 to 128),
> - Extend bneptest with frames retransmission parameters,
> - Update PTS results and test instructions.
>
> Grzegorz Kolodziejczyk (6):
> profiles/network: Remove unneded bnep_uuid function from bnep code
> profiles/network: Remove not needed get name by bnep id function
> profiles/network: Move disconn cb setting to bnep connect method
> tools/bneptest: Add initial support for bneptest tool
> tools/bneptest: Add generic connect/listen functionality
> android/pts: Add BNEP PTS 6.0 results for android 5.0
>
> .gitignore | 1 +
> Makefile.tools | 12 +-
> android/Android.mk | 35 ++
> android/Makefile.am | 5 +-
> android/pan.c | 5 +-
> android/pics-bnep.txt | 26 ++
> android/pixit-bnep.txt | 30 ++
> android/pts-bnep.txt | 48 +++
> profiles/network/bnep.c | 53 +--
> profiles/network/bnep.h | 9 +-
> profiles/network/connection.c | 23 +-
> profiles/network/server.c | 36 +-
> tools/bneptest.c | 777
> ++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 985
> insertions(+), 75 deletions(-)
> create mode 100644 android/pics-bnep.txt
> create mode 100644 android/pixit-bnep.txt
> create mode 100644 android/pts-bnep.txt
> create mode 100644 tools/bneptest.c

Patches 1-3 are now applied (after fixing some typos in commit messages),
thanks.

--
Szymon K. Janc
[email protected]

2015-03-12 22:17:12

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v5 4/6] tools/bneptest: Add initial support for bneptest tool

Hi Grzegorz,

On Thursday 12 March 2015 18:07:31 Grzegorz Kolodziejczyk wrote:
> This tool should be designed to help testing bnep on Bluez.

BlueZ :-)

> ---
> .gitignore | 1 +
> Makefile.tools | 12 ++++++---
> android/Android.mk | 35 ++++++++++++++++++++++++++
> tools/bneptest.c | 74
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119
> insertions(+), 3 deletions(-)
> create mode 100644 tools/bneptest.c
>
> diff --git a/.gitignore b/.gitignore
> index a207a0f..a4f06dc 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -82,6 +82,7 @@ tools/gatt-service
> tools/btgatt-client
> tools/btgatt-server
> tools/mcaptest
> +tools/bneptest
> test/sap_client.pyc
> test/bluezutils.pyc
> unit/test-ringbuf
> diff --git a/Makefile.tools b/Makefile.tools
> index e28f3cb..1aafb28 100644
> --- a/Makefile.tools
> +++ b/Makefile.tools
> @@ -223,9 +223,9 @@ noinst_PROGRAMS += tools/bdaddr tools/avinfo
> tools/avtest \ tools/hcieventmask tools/hcisecfilter \
> tools/btmgmt tools/btinfo tools/btattach \
> tools/btsnoop tools/btproxy \
> - tools/btiotest tools/mcaptest tools/cltest \
> - tools/oobtest tools/seq2bseq tools/ibeacon \
> - tools/btgatt-client tools/btgatt-server
> + tools/btiotest tools/bneptest tools/mcaptest \

double space

> + tools/cltest tools/oobtest tools/seq2bseq \
> + tools/ibeacon tools/btgatt-client tools/btgatt-server
>
> tools_bdaddr_SOURCES = tools/bdaddr.c src/oui.h src/oui.c
> tools_bdaddr_LDADD = lib/libbluetooth-internal.la @UDEV_LIBS@
> @@ -267,6 +267,12 @@ tools_mcaptest_SOURCES = tools/mcaptest.c \
> profiles/health/mcap.h profiles/health/mcap.c
> tools_mcaptest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
>
> +tools_bneptest_SOURCES = tools/bneptest.c \
> + btio/btio.h btio/btio.c \
> + src/log.c src/log.h \

nitpick: header first

> + profiles/network/bnep.h profiles/network/bnep.c
> +tools_bneptest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
> +
> tools_cltest_SOURCES = tools/cltest.c
> tools_cltest_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la
>
> diff --git a/android/Android.mk b/android/Android.mk
> index 6c0eda8..f218805 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -256,6 +256,41 @@ LOCAL_MODULE := mcaptest
> include $(BUILD_EXECUTABLE)
>
> #
> +# bneptest
> +#
> +
> +include $(CLEAR_VARS)
> +
> +LOCAL_SRC_FILES := \
> + bluez/src/log.c \
> + bluez/btio/btio.c \
> + bluez/lib/bluetooth.c \
> + bluez/lib/hci.c \
> + bluez/profiles/network/bnep.c \
> + bluez/tools/bneptest.c \
> +
> +LOCAL_C_INCLUDES := \
> + $(call include-path-for, glib) \
> + $(call include-path-for, glib)/glib \
> +
> +LOCAL_C_INCLUDES += \
> + $(LOCAL_PATH)/bluez \
> +
> +LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
> +
> +LOCAL_SHARED_LIBRARIES := \
> + libglib \
> +
> +LOCAL_STATIC_LIBRARIES := \
> + bluetooth-headers \
> +
> +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
> +LOCAL_MODULE_TAGS := debug
> +LOCAL_MODULE := bneptest
> +
> +include $(BUILD_EXECUTABLE)
> +
> +#
> # avdtptest
> #
>
> diff --git a/tools/bneptest.c b/tools/bneptest.c
> new file mode 100644
> index 0000000..619427b
> --- /dev/null
> +++ b/tools/bneptest.c
> @@ -0,0 +1,74 @@
> +/*
> + *
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2015 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 <stdio.h>
> +#include <stdlib.h>
> +#include <getopt.h>
> +
> +#include <glib.h>
> +
> +#include "src/log.h"
> +
> +static GMainLoop *mloop;
> +
> +static void usage(void)
> +{
> + printf("bneptest - BNEP testing ver %s\n", VERSION);
> + printf("Usage:\n"
> + "\tbneptest [options]\n");
> +}
> +
> +static struct option main_options[] = {
> + { "help", 0, 0, 'h' },
> + { 0, 0, 0, 0 }
> +};
> +
> +int main(int argc, char *argv[])
> +{
> + int opt;
> +
> + DBG("");
> +
> + mloop = g_main_loop_new(NULL, FALSE);
> + if (!mloop) {
> + printf("cannot create main loop\n");
> +
> + exit(1);
> + }
> +
> + while ((opt = getopt_long(argc, argv, "h", main_options, NULL))
> + != EOF) {
> + switch (opt) {
> + case 'h':
> + default:
> + usage();
> + exit(0);
> + }
> + }
> +
> + return 0;
> +}

--
Szymon K. Janc
[email protected]

2015-03-12 22:13:33

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v5 5/6] tools/bneptest: Add generic connect/listen functionality

Hi Grzegorz,

On Thursday 12 March 2015 18:07:32 Grzegorz Kolodziejczyk wrote:
> This patch adds general functionality of bnep connect and listen.
> ---
> tools/bneptest.c | 711
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 707
> insertions(+), 4 deletions(-)
>
> diff --git a/tools/bneptest.c b/tools/bneptest.c
> index 619427b..b694055 100644
> --- a/tools/bneptest.c
> +++ b/tools/bneptest.c
> @@ -26,33 +26,570 @@
> #endif
>
> #include <stdio.h>
> +#include <signal.h>
> #include <stdlib.h>
> #include <getopt.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <sys/ioctl.h>
> +#include <net/if.h>
> +#include <linux/sockios.h>
> +#include <netinet/in.h>
> +#include <linux/if_bridge.h>
> +
> +#include <bluetooth/bluetooth.h>
> +#include <bluetooth/hci.h>
> +#include <bluetooth/hci_lib.h>
>
> #include <glib.h>
>
> #include "src/log.h"
> +#include "btio/btio.h"
> +#include "lib/bnep.h"
> +#include "profiles/network/bnep.h"
> +
> +enum {
> + MODE_NONE,
> + MODE_CONNECT,
> + MODE_LISTEN,

just connect/listen mode should be enough

> +};
>
> static GMainLoop *mloop;
> +static GIOChannel *bnep_io;
> +
> +static int mode;
> +static bool no_close_after_disconn;
> +static int send_frame_timeout;
> +
> +static bdaddr_t src_addr, dst_addr;
> +static char iface[16];
> +static char bridge[16];
> +static bool send_ctrl_msg_type_set;
> +static uint8_t ctrl_msg_type;
> +static bool send_bnep_msg_type_set;
> +static uint8_t bnep_msg_type;
> +static int ctrl_msg_retransmition_nb;
> +static int bnep_msg_retransmission_nb;
> +static uint16_t local_role = BNEP_SVC_PANU;
> +static uint16_t remote_role = BNEP_SVC_NAP;
> +static uint16_t ntw_proto_down_range;
> +static uint16_t ntw_proto_up_range = 0xdc05;
> +static uint16_t ntw_proto_type;
> +static uint8_t mcast_addr_down_range[6];
> +static uint8_t mcast_addr_up_range[6] = { 0xff, 0xff, 0xff, 0xff, 0xff,
> 0xff }; +static uint8_t src_hw_addr[6];
> +static uint8_t dst_hw_addr[6];
> +static uint8_t general_frame_payload[] = "abcdef0123456789_bnep_test_data";
> +static struct bnep *session;

statics should be explicitly initialized to zero/null as well (not really
needed but we have this convention in userspace code).

> +
> +
> +static int set_forward_delay(int sk)
> +{
> + unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0, 0, 0 };
> + struct ifreq ifr;
> +
> + memset(&ifr, 0, sizeof(ifr));
> + strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
> + ifr.ifr_data = (char *) args;
> +
> + if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
> + error("setting forward delay failed: %d (%s)",
> + errno, strerror(errno));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int nap_create_bridge(void)
> +{
> + int sk, err;
> +
> + sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
> + if (sk < 0)
> + return -EOPNOTSUPP;
> +
> + if (ioctl(sk, SIOCBRADDBR, bridge) < 0) {
> + err = -errno;
> + if (err != -EEXIST) {

just check errno here.

> + close(sk);
> + return -EOPNOTSUPP;
> + }
> + }
> +
> + err = set_forward_delay(sk);
> + if (err < 0) {
> + printf("failed to set forward delay\n");
> + ioctl(sk, SIOCBRDELBR, bridge);
> + }
> +
> + close(sk);
> +
> + return err;
> +}
> +
> +static int cleanup(void)
> +{
> + bnep_cleanup();
> +
> + if (mode == MODE_LISTEN)
> + bnep_server_delete(bridge, iface, &dst_addr);
> +
> + if (bnep_io) {
> + g_io_channel_shutdown(bnep_io, TRUE, NULL);
> + g_io_channel_unref(bnep_io);

bnep_io = NULL here to avoid dangling pointer.

> + }
> +
> + return 0;
> +}
> +
> +static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
> + gpointer user_data)
> +{
> + printf("%s\n", __func__);
> +
> + if (no_close_after_disconn)
> + return FALSE;
> +
> + /* Cleanup since it's called when disconnected l2cap */
> + if (cleanup() < 0) {
> + printf("cleanup went wrong...\n");
> + return FALSE;
> + }
> +
> + g_main_loop_quit(mloop);
> + return FALSE;
> +}
> +
> +static ssize_t send_compressed_frame(int sk, uint8_t type)
> +{
> + uint8_t frame[100];
> +
> + printf("%s\n", __func__);
> +
> + if (send_frame_timeout > 0) {
> + printf("waiting %d seconds before sending msg\n",
> + send_frame_timeout);
> + sleep(send_frame_timeout);
> + }
> +
> + frame[0] = type;
> + memcpy(&frame[1], dst_hw_addr, sizeof(dst_hw_addr));
> + memcpy(&frame[7], src_hw_addr, sizeof(src_hw_addr));
> + frame[13] = ntw_proto_type & 0xff;
> + frame[14] = (ntw_proto_type >> 8);
> + memcpy(&frame[15], general_frame_payload,
> + sizeof(general_frame_payload));
> +
> + /* TODO - set frame payload by user */
> + return send(sk, frame, 15 + sizeof(general_frame_payload), 0);
> +}
> +
> +static ssize_t send_general_frame(int sk)
> +{
> + uint8_t frame[100];
> +
> + printf("%s\n", __func__);
> +
> + if (send_frame_timeout > 0) {
> + printf("waiting %d seconds before sending msg\n",
> + send_frame_timeout);
> + sleep(send_frame_timeout);
> + }
> +
> + frame[0] = BNEP_GENERAL;
> + memcpy(&frame[1], dst_hw_addr, sizeof(dst_hw_addr));
> + memcpy(&frame[7], src_hw_addr, sizeof(src_hw_addr));
> + frame[13] = ntw_proto_type & 0xff;
> + frame[14] = (ntw_proto_type >> 8);
> + memcpy(&frame[15], general_frame_payload,
> + sizeof(general_frame_payload));
> +
> + /* TODO - set frame payload by user */
> + return send(sk, frame, 15 + sizeof(general_frame_payload), 0);
> +}
> +
> +static ssize_t send_ctrl_frame(int sk)
> +{
> + /* Max buff size = type(1byte) + ctrl(1byte) + len(2byte) +
> + * mcast_addr_down(6byte) + mcast_addr_up(6byte) */

/*
* foo
* bar
*/

> + uint8_t buff[16];
> + int err;
> +
> + printf("%s\n", __func__);
> +
> + if (send_frame_timeout > 0) {
> + printf("waiting %d seconds before sending msg\n",
> + send_frame_timeout);
> + sleep(send_frame_timeout);
> + }
> +
> + switch (ctrl_msg_type) {
> + case BNEP_FILTER_NET_TYPE_SET: {
> + struct bnep_set_filter_req *frame = (void *)buff;

just move struct bnep_set_filter_req *frame = (void *)buff;
to the top of function. Also there should be space after (void *)

> +
> + frame->type = BNEP_CONTROL;
> + frame->ctrl = ctrl_msg_type;
> + frame->len = htons(sizeof(ntw_proto_down_range) +
> + sizeof(ntw_proto_up_range));
> + memcpy(frame->list, &ntw_proto_down_range,
> + sizeof(ntw_proto_down_range));
> + memcpy(frame->list + sizeof(ntw_proto_down_range),
> + &ntw_proto_up_range, sizeof(ntw_proto_up_range));
> +
> + err = send(sk, frame, sizeof(*frame) +
> + sizeof(ntw_proto_down_range) +
> + sizeof(ntw_proto_up_range), 0);
> +
> + break;
> +
> + }
> + case BNEP_FILTER_MULT_ADDR_SET: {
> + struct bnep_set_filter_req *frame = (void *)buff;
> +
> + frame->type = BNEP_CONTROL;
> + frame->ctrl = ctrl_msg_type;
> + frame->len = htons(sizeof(mcast_addr_down_range) +
> + sizeof(mcast_addr_up_range));
> + memcpy(frame->list, mcast_addr_down_range,
> + sizeof(mcast_addr_down_range));
> + memcpy(frame->list + sizeof(mcast_addr_down_range),
> + mcast_addr_up_range, sizeof(mcast_addr_up_range));
> +
> + err = send(sk, frame, sizeof(*frame) +
> + sizeof(mcast_addr_down_range) +
> + sizeof(mcast_addr_up_range), 0);
> +
> + break;
> +
> + }
> + default:
> + err = -1;
> + }
> +
> + return err;
> +}
> +
> +static int send_bnep_frame(int sk)
> +{
> + int err = 0;

just set err in default case.

> +
> + switch (bnep_msg_type) {
> + case BNEP_GENERAL:
> + err = send_general_frame(sk);
> +

those empty lines are not needed.

> + break;
> +
> + case BNEP_COMPRESSED:
> + err = send_compressed_frame(sk, BNEP_COMPRESSED);
> +
> + break;
> +
> + case BNEP_COMPRESSED_SRC_ONLY:
> + err = send_compressed_frame(sk,
> + BNEP_COMPRESSED_SRC_ONLY);
> +
> + break;
> +
> + case BNEP_COMPRESSED_DST_ONLY:
> + err = send_compressed_frame(sk,
> + BNEP_COMPRESSED_DST_ONLY);
> +
> + break;
> +
> + default:
> + printf("wrong bnep_msg_type 0x%02x\n", bnep_msg_type);
> + }
> +
> + return err;
> +}
> +
> +static void handle_bnep_msg_send(int sk)
> +{
> + if (send_ctrl_msg_type_set) {
> + do {
> + if (send_ctrl_frame(sk) < 0)
> + printf("sending ctrl frame error: %s (%d)\n",
> + strerror(errno), errno);
> + } while (!ctrl_msg_retransmition_nb--);

This ! seems bogus.

> + }
> +
> + if (send_bnep_msg_type_set) {
> + do {
> + if (send_bnep_frame(sk) < 0)
> + printf("sending bnep frame error: %s (%d)\n",
> + strerror(errno), errno);
> + } while (!bnep_msg_retransmission_nb--);

ditto.

> + }
> +}
> +
> +static gboolean setup_bnep_cb(GIOChannel *chan, GIOCondition cond,
> + gpointer user_data)
> +{
> + uint8_t packet[BNEP_MTU];
> + int sk, n, err;
> +
> + printf("%s\n", __func__);
> +
> + if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
> + error("hangup or error or inval on BNEP socket");
> + return FALSE;
> + }
> +
> + sk = g_io_channel_unix_get_fd(chan);
> +
> + /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
> + n = read(sk, packet, sizeof(packet));
> + if (n < 0) {

double space before <

> + error("read(): %s(%d)", strerror(errno), errno);
> + return FALSE;
> + }
> +
> + err = nap_create_bridge();
> + if (err < 0) {
> + error("failed to create bridge: %s (%d)", strerror(-err), err);
> + return FALSE;
> + }
> +
> + if (bnep_server_add(sk, (err < 0) ? NULL : bridge, iface, &dst_addr,
> + packet, n) < 0) {
> + printf("server_connadd failed\n");
> + cleanup();
> + return FALSE;
> + }
> +
> + g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL, bnep_watchdog_cb,
> + NULL);
> +
> + handle_bnep_msg_send(sk);
> +
> + g_io_channel_unref(bnep_io);
> + bnep_io = NULL;
> +
> + return FALSE;
> +}
> +
> +static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
> +{
> + printf("%s\n", __func__);
> +
> + if (err) {
> + error("%s", err->message);
> + return;
> + }
> +
> + g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> + setup_bnep_cb, NULL);
> +}
> +
> +static void connected_client_cb(char *iface, int err, void *data)
> +{
> + int sk = *((int *)data);

Use PTR_TO_INT macro instead.

> +
> + printf("%s\n", __func__);
> +
> + free(data);
> +
> + handle_bnep_msg_send(sk);
> +}
> +
> +static void disconnected_client_cb(void *data)
> +{
> + printf("%s\n", __func__);
> +
> + if (no_close_after_disconn)
> + return;
> +
> + /* Cleanup since it's called when disconnected l2cap */
> + if (cleanup() < 0) {
> + printf("cleanup went wrong...\n");
> + return;
> + }
> +
> + g_main_loop_quit(mloop);
> +}
> +
> +static void connect_client_cb(GIOChannel *chan, GError *err, gpointer
> user_data) +{
> + int perr;
> + int *sk;
> +
> + sk = malloc(sizeof(*sk));

just use INT_TO_PTR to pass this as userdata.

> +
> + *sk = g_io_channel_unix_get_fd(bnep_io);
> +
> + session = bnep_new(*sk, local_role, remote_role, bridge);
> + if (!session) {
> + printf("cannot create bnep session\n");
> + free(sk);
> + return;
> + }
> +
> + perr = bnep_connect(session, connected_client_cb,
> + disconnected_client_cb, sk, NULL);
> + if (perr < 0)
> + printf("cannot initiate bnep connection\n");
> +}
> +
> +static void confirm_cb(GIOChannel *chan, gpointer data)
> +{
> + GError *err = NULL;
> + char address[18];
> +
> + printf("%s\n", __func__);
> +
> + bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst_addr, BT_IO_OPT_DEST,
> + address, BT_IO_OPT_INVALID);
> + if (err) {
> + error("%s", err->message);
> + g_error_free(err);
> + return;
> + }
> +
> + printf("incoming connection from: %s\n", address);
> +
> + bnep_io = g_io_channel_ref(chan);
> + g_io_channel_set_close_on_unref(bnep_io, TRUE);
> +
> + if (!bt_io_accept(bnep_io, connect_cb, NULL, NULL, &err)) {
> + error("bt_io_accept: %s", err->message);
> + g_error_free(err);

missing bnep_io unref?

> + }

or you can just return on error and ref bnep_io here ?

> +}
> +
> +static int bnep_server_listen(void)
> +{
> + GError *gerr = NULL;
> +
> + printf("%s\n", __func__);
> +
> + bnep_io = bt_io_listen(NULL, confirm_cb, NULL, NULL, &gerr,
> + BT_IO_OPT_SOURCE_BDADDR, &src_addr,
> + BT_IO_OPT_PSM, BNEP_PSM,
> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> + BT_IO_OPT_OMTU, BNEP_MTU,
> + BT_IO_OPT_IMTU, BNEP_MTU,
> + BT_IO_OPT_INVALID);
> +
> + if (!bnep_io) {
> + printf("can't start server listening: err %s\n", gerr->message);
> + g_error_free(gerr);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int bnep_client_connect(void)
> +{
> + GError *gerr = NULL;
> + char *dst_addr_str = batostr(&dst_addr);

use ba2str and stack variable.

> +
> + printf("%s\n", __func__);
> +
> + printf("connecting %s\n", dst_addr_str);
> + free(dst_addr_str);
> +
> + bnep_io = bt_io_connect(connect_client_cb, NULL, NULL, &gerr,
> + BT_IO_OPT_SOURCE_BDADDR, &src_addr,
> + BT_IO_OPT_DEST_BDADDR, &dst_addr,
> + BT_IO_OPT_PSM, BNEP_PSM,
> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
> + BT_IO_OPT_OMTU, BNEP_MTU,
> + BT_IO_OPT_IMTU, BNEP_MTU,
> + BT_IO_OPT_INVALID);
> +
> + if (!bnep_io) {
> + printf("cannot connect: err %s\n", gerr->message);
> + g_error_free(gerr);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static void exit_handler(int sig)
> +{
> + printf("got sig = %d, cleaning up...\n", sig);
> +
> + if (cleanup() < 0)
> + printf("cleanup failure...\n");
> + else
> + printf("cleanup successful - exit\n");
> +
> + exit(0);
> +}
>
> static void usage(void)
> {
> printf("bneptest - BNEP testing ver %s\n", VERSION);
> printf("Usage:\n"
> - "\tbneptest [options]\n");
> + "\tbneptest [-i] -b <bridge name> -n <iface name>"
> + " <connection mode> [send_ctrl_cmd] [options]\n"
> + "\t-i hci dev number <hci number>, def. 0\n"
> + "\t-b bridge name <string>\n"
> + "\t-n interface name <string>\n");
> + printf("Connect Mode:\n"
> + "\t-c connect <dst_addr>\n"
> + "\t-r remote role <16 bit svc value>\n"
> + "\t-l local role <16 bit svc valu>\n");
> + printf("Listen Mode:\n"
> + "\t-s start server listening\n");
> + printf("Send control command:\n"
> + "\t-t send message type <control msg type>, def. 0\n"
> + "\t-e start network protocol type range <16 bit val>, def. 0\n"
> + "\t-d end network protocol type range <16 bit val>, def. 1500\n"
> + "\t-g start multicast addr range <xx:xx:xx:xx:xx:xx>, def. 0\n"
> + "\t-j end multicast addr range <xx:xx:xx:xx:xx:xx>, def. f\n"
> + "\t-y number of ctrl frame retransmission <integer>, def. 0\n"
> + "\t-u number of bnep frame retransmission <integer>, def. 0\n");
> + printf("Send bnep generic frame:\n"
> + "\t-w send bnep generic frame <bnep generic type>, def. 0\n"
> + "\t-k set src mac addr <xx:xx:xx:xx:xx:xx>, def. 0\n"
> + "\t-f set dst mac addr <xx:xx:xx:xx:xx:xx>, def. 0\n");
> + printf("Options:\n"
> + "\t-T send message timeout after setup <seconds>\n"
> + "\t-N don't close bneptest after disconnect\n");
> }
>
> static struct option main_options[] = {
> - { "help", 0, 0, 'h' },
> + { "device", 1, 0, 'i' },
> + { "listen", 0, 0, 's' },
> + { "connect", 1, 0, 'c' },
> + { "snd_ctrl_msg_type", 1, 0, 't' },
> + { "snd_bnep_msg_type", 1, 0, 'w' },
> + { "src_hw_addr", 1, 0, 'k' },
> + { "dst_hw_addr", 1, 0, 'f' },
> + { "send_timeout", 1, 0, 'T' },
> + { "ntw_proto_down_range", 1, 0, 'd' },
> + { "ntw_proto_up_range", 1, 0, 'e' },
> + { "mcast_addr_down_range", 1, 0, 'g' },
> + { "mcast_addr_up_range", 1, 0, 'j' },
> + { "local_role", 1, 0, 'l' },
> + { "remote_role", 1, 0, 'r' },
> + { "bridge name", 1, 0, 'b' },
> + { "iface name", 1, 0, 'n' },
> + { "no_close", 0, 0, 'N' },
> + { "retrans_ctrl_nb", 0, 0, 'y' },
> + { "retrans_bnep_nb", 0, 0, 'u' },
> + { "help", 0, 0, 'h' },
> { 0, 0, 0, 0 }
> };
>
> int main(int argc, char *argv[])
> {
> int opt;
> + int err;
> + bool is_set_b_name = false, is_set_i_name = false;
>
> DBG("");
>
> + signal(SIGINT, exit_handler);
> +
> + hci_devba(0, &src_addr);
> + bacpy(&src_addr, BDADDR_ANY);
> +
> mloop = g_main_loop_new(NULL, FALSE);
> if (!mloop) {
> printf("cannot create main loop\n");
> @@ -60,9 +597,133 @@ int main(int argc, char *argv[])
> exit(1);
> }
>
> - while ((opt = getopt_long(argc, argv, "h", main_options, NULL))
> - != EOF) {
> + while ((opt = getopt_long(argc, argv,
> + "+i:c:b:n:t:T:d:e:g:j:k:f:w:l:r:y:u:Nsh",
> + main_options, NULL)) != EOF) {
> switch (opt) {
> + case 'i':
> + if (!strncmp(optarg, "hci", 3))
> + hci_devba(atoi(optarg + 3), &src_addr);
> + else
> + str2ba(optarg, &src_addr);
> +
> + break;
> +

Those empty lines are not needed.

> + case 's':
> + mode = MODE_LISTEN;
> + break;
> +
> + case 'c':
> + str2ba(optarg, &dst_addr);
> + mode = MODE_CONNECT;
> +
> + break;
> +
> + case 't':
> + send_ctrl_msg_type_set = true;
> + ctrl_msg_type = atoi(optarg);
> +
> + break;
> +
> + case 'w':
> + send_bnep_msg_type_set = true;
> + bnep_msg_type = atoi(optarg);
> +
> + break;
> +
> + case 'k': {
> + int i = 0;

declare it at the top

> +
> + for (; i <= 5; i++, optarg += 3)

initialize i in for loop.
for (i = 0; ...)

> + src_hw_addr[i] = strtol(optarg, NULL, 16);
> +
> + break;
> + }
> +
> + case 'f': {
> + int i = 0;

ditto.

> +
> + for (; i <= 5; i++, optarg += 3)
> + dst_hw_addr[i] = strtol(optarg, NULL, 16);
> +
> + break;
> + }
> +
> + case 'T':
> + send_frame_timeout = atoi(optarg);
> +
> + break;
> +
> + case 'd':
> + ntw_proto_down_range = htons(atoi(optarg));
> +
> + break;
> +
> + case 'e':
> + ntw_proto_up_range = htons(atoi(optarg));
> +
> + break;
> +
> + case 'g': {
> + int i = 0;
> +

ditto.

> + for (i = 5; i >= 0; i--, optarg += 3)
> + mcast_addr_down_range[i] =
> + strtol(optarg, NULL, 16);
> +
> + break;
> + }
> +
> + case 'j': {
> + int i = 0;

ditto.

> +
> + for (i = 5; i >= 0; i--, optarg += 3)
> + mcast_addr_up_range[i] =
> + strtol(optarg, NULL, 16);
> +
> + break;
> + }
> +
> + case 'l':
> + local_role = atoi(optarg);
> +
> + break;
> +
> + case 'r':
> + remote_role = atoi(optarg);
> +
> + break;
> +
> + case 'b':
> + strncpy(bridge, optarg, 16);
> + bridge[15] = '\0';
> + is_set_b_name = true;
> +
> + break;
> +
> + case 'n':
> + strncpy(iface, optarg, 14);
> + strcat(iface, "\%d");
> + iface[15] = '\0';
> + is_set_i_name = true;
> +
> + break;
> +
> + case 'N':
> + no_close_after_disconn = true;
> +
> + break;
> +
> + case 'y':
> + ctrl_msg_retransmition_nb = atoi(optarg);
> +
> + break;
> +
> + case 'u':
> + bnep_msg_retransmission_nb = atoi(optarg);
> +
> + break;
> +
> case 'h':
> default:
> usage();
> @@ -70,5 +731,47 @@ int main(int argc, char *argv[])
> }
> }
>
> + if (!is_set_b_name || !is_set_i_name) {
> + printf("bridge, interface name must be set!\n");
> + exit(1);
> + }
> +
> + switch (mode) {
> + case MODE_CONNECT:
> + err = bnep_init();
> + if (err < 0) {
> + printf("cannot initialize bnep\n");
> + exit(1);
> + }
> + err = bnep_client_connect();
> + if (err < 0)
> + exit(1);
> +
> + break;
> +
> + case MODE_LISTEN:
> + err = bnep_init();
> + if (err < 0) {
> + printf("cannot initialize bnep\n");
> + exit(1);
> + }
> + err = bnep_server_listen();
> + if (err < 0)
> + exit(1);
> +
> + break;
> +
> + case MODE_NONE:
> + default:
> + printf("connect/listen mode not set, exit...\n");
> + exit(1);
> + }
> +
> + g_main_loop_run(mloop);
> +
> + printf("Done\n");
> +
> + g_main_loop_unref(mloop);
> +
> return 0;
> }

--
Szymon K. Janc
[email protected]

2015-03-12 17:07:32

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 5/6] tools/bneptest: Add generic connect/listen functionality

This patch adds general functionality of bnep connect and listen.
---
tools/bneptest.c | 711 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 707 insertions(+), 4 deletions(-)

diff --git a/tools/bneptest.c b/tools/bneptest.c
index 619427b..b694055 100644
--- a/tools/bneptest.c
+++ b/tools/bneptest.c
@@ -26,33 +26,570 @@
#endif

#include <stdio.h>
+#include <signal.h>
#include <stdlib.h>
#include <getopt.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <netinet/in.h>
+#include <linux/if_bridge.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>

#include <glib.h>

#include "src/log.h"
+#include "btio/btio.h"
+#include "lib/bnep.h"
+#include "profiles/network/bnep.h"
+
+enum {
+ MODE_NONE,
+ MODE_CONNECT,
+ MODE_LISTEN,
+};

static GMainLoop *mloop;
+static GIOChannel *bnep_io;
+
+static int mode;
+static bool no_close_after_disconn;
+static int send_frame_timeout;
+
+static bdaddr_t src_addr, dst_addr;
+static char iface[16];
+static char bridge[16];
+static bool send_ctrl_msg_type_set;
+static uint8_t ctrl_msg_type;
+static bool send_bnep_msg_type_set;
+static uint8_t bnep_msg_type;
+static int ctrl_msg_retransmition_nb;
+static int bnep_msg_retransmission_nb;
+static uint16_t local_role = BNEP_SVC_PANU;
+static uint16_t remote_role = BNEP_SVC_NAP;
+static uint16_t ntw_proto_down_range;
+static uint16_t ntw_proto_up_range = 0xdc05;
+static uint16_t ntw_proto_type;
+static uint8_t mcast_addr_down_range[6];
+static uint8_t mcast_addr_up_range[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+static uint8_t src_hw_addr[6];
+static uint8_t dst_hw_addr[6];
+static uint8_t general_frame_payload[] = "abcdef0123456789_bnep_test_data";
+static struct bnep *session;
+
+
+static int set_forward_delay(int sk)
+{
+ unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0, 0, 0 };
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
+ ifr.ifr_data = (char *) args;
+
+ if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
+ error("setting forward delay failed: %d (%s)",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int nap_create_bridge(void)
+{
+ int sk, err;
+
+ sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return -EOPNOTSUPP;
+
+ if (ioctl(sk, SIOCBRADDBR, bridge) < 0) {
+ err = -errno;
+ if (err != -EEXIST) {
+ close(sk);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ err = set_forward_delay(sk);
+ if (err < 0) {
+ printf("failed to set forward delay\n");
+ ioctl(sk, SIOCBRDELBR, bridge);
+ }
+
+ close(sk);
+
+ return err;
+}
+
+static int cleanup(void)
+{
+ bnep_cleanup();
+
+ if (mode == MODE_LISTEN)
+ bnep_server_delete(bridge, iface, &dst_addr);
+
+ if (bnep_io) {
+ g_io_channel_shutdown(bnep_io, TRUE, NULL);
+ g_io_channel_unref(bnep_io);
+ }
+
+ return 0;
+}
+
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ printf("%s\n", __func__);
+
+ if (no_close_after_disconn)
+ return FALSE;
+
+ /* Cleanup since it's called when disconnected l2cap */
+ if (cleanup() < 0) {
+ printf("cleanup went wrong...\n");
+ return FALSE;
+ }
+
+ g_main_loop_quit(mloop);
+ return FALSE;
+}
+
+static ssize_t send_compressed_frame(int sk, uint8_t type)
+{
+ uint8_t frame[100];
+
+ printf("%s\n", __func__);
+
+ if (send_frame_timeout > 0) {
+ printf("waiting %d seconds before sending msg\n",
+ send_frame_timeout);
+ sleep(send_frame_timeout);
+ }
+
+ frame[0] = type;
+ memcpy(&frame[1], dst_hw_addr, sizeof(dst_hw_addr));
+ memcpy(&frame[7], src_hw_addr, sizeof(src_hw_addr));
+ frame[13] = ntw_proto_type & 0xff;
+ frame[14] = (ntw_proto_type >> 8);
+ memcpy(&frame[15], general_frame_payload,
+ sizeof(general_frame_payload));
+
+ /* TODO - set frame payload by user */
+ return send(sk, frame, 15 + sizeof(general_frame_payload), 0);
+}
+
+static ssize_t send_general_frame(int sk)
+{
+ uint8_t frame[100];
+
+ printf("%s\n", __func__);
+
+ if (send_frame_timeout > 0) {
+ printf("waiting %d seconds before sending msg\n",
+ send_frame_timeout);
+ sleep(send_frame_timeout);
+ }
+
+ frame[0] = BNEP_GENERAL;
+ memcpy(&frame[1], dst_hw_addr, sizeof(dst_hw_addr));
+ memcpy(&frame[7], src_hw_addr, sizeof(src_hw_addr));
+ frame[13] = ntw_proto_type & 0xff;
+ frame[14] = (ntw_proto_type >> 8);
+ memcpy(&frame[15], general_frame_payload,
+ sizeof(general_frame_payload));
+
+ /* TODO - set frame payload by user */
+ return send(sk, frame, 15 + sizeof(general_frame_payload), 0);
+}
+
+static ssize_t send_ctrl_frame(int sk)
+{
+ /* Max buff size = type(1byte) + ctrl(1byte) + len(2byte) +
+ * mcast_addr_down(6byte) + mcast_addr_up(6byte) */
+ uint8_t buff[16];
+ int err;
+
+ printf("%s\n", __func__);
+
+ if (send_frame_timeout > 0) {
+ printf("waiting %d seconds before sending msg\n",
+ send_frame_timeout);
+ sleep(send_frame_timeout);
+ }
+
+ switch (ctrl_msg_type) {
+ case BNEP_FILTER_NET_TYPE_SET: {
+ struct bnep_set_filter_req *frame = (void *)buff;
+
+ frame->type = BNEP_CONTROL;
+ frame->ctrl = ctrl_msg_type;
+ frame->len = htons(sizeof(ntw_proto_down_range) +
+ sizeof(ntw_proto_up_range));
+ memcpy(frame->list, &ntw_proto_down_range,
+ sizeof(ntw_proto_down_range));
+ memcpy(frame->list + sizeof(ntw_proto_down_range),
+ &ntw_proto_up_range, sizeof(ntw_proto_up_range));
+
+ err = send(sk, frame, sizeof(*frame) +
+ sizeof(ntw_proto_down_range) +
+ sizeof(ntw_proto_up_range), 0);
+
+ break;
+
+ }
+ case BNEP_FILTER_MULT_ADDR_SET: {
+ struct bnep_set_filter_req *frame = (void *)buff;
+
+ frame->type = BNEP_CONTROL;
+ frame->ctrl = ctrl_msg_type;
+ frame->len = htons(sizeof(mcast_addr_down_range) +
+ sizeof(mcast_addr_up_range));
+ memcpy(frame->list, mcast_addr_down_range,
+ sizeof(mcast_addr_down_range));
+ memcpy(frame->list + sizeof(mcast_addr_down_range),
+ mcast_addr_up_range, sizeof(mcast_addr_up_range));
+
+ err = send(sk, frame, sizeof(*frame) +
+ sizeof(mcast_addr_down_range) +
+ sizeof(mcast_addr_up_range), 0);
+
+ break;
+
+ }
+ default:
+ err = -1;
+ }
+
+ return err;
+}
+
+static int send_bnep_frame(int sk)
+{
+ int err = 0;
+
+ switch (bnep_msg_type) {
+ case BNEP_GENERAL:
+ err = send_general_frame(sk);
+
+ break;
+
+ case BNEP_COMPRESSED:
+ err = send_compressed_frame(sk, BNEP_COMPRESSED);
+
+ break;
+
+ case BNEP_COMPRESSED_SRC_ONLY:
+ err = send_compressed_frame(sk,
+ BNEP_COMPRESSED_SRC_ONLY);
+
+ break;
+
+ case BNEP_COMPRESSED_DST_ONLY:
+ err = send_compressed_frame(sk,
+ BNEP_COMPRESSED_DST_ONLY);
+
+ break;
+
+ default:
+ printf("wrong bnep_msg_type 0x%02x\n", bnep_msg_type);
+ }
+
+ return err;
+}
+
+static void handle_bnep_msg_send(int sk)
+{
+ if (send_ctrl_msg_type_set) {
+ do {
+ if (send_ctrl_frame(sk) < 0)
+ printf("sending ctrl frame error: %s (%d)\n",
+ strerror(errno), errno);
+ } while (!ctrl_msg_retransmition_nb--);
+ }
+
+ if (send_bnep_msg_type_set) {
+ do {
+ if (send_bnep_frame(sk) < 0)
+ printf("sending bnep frame error: %s (%d)\n",
+ strerror(errno), errno);
+ } while (!bnep_msg_retransmission_nb--);
+ }
+}
+
+static gboolean setup_bnep_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ uint8_t packet[BNEP_MTU];
+ int sk, n, err;
+
+ printf("%s\n", __func__);
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+ error("hangup or error or inval on BNEP socket");
+ return FALSE;
+ }
+
+ sk = g_io_channel_unix_get_fd(chan);
+
+ /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
+ n = read(sk, packet, sizeof(packet));
+ if (n < 0) {
+ error("read(): %s(%d)", strerror(errno), errno);
+ return FALSE;
+ }
+
+ err = nap_create_bridge();
+ if (err < 0) {
+ error("failed to create bridge: %s (%d)", strerror(-err), err);
+ return FALSE;
+ }
+
+ if (bnep_server_add(sk, (err < 0) ? NULL : bridge, iface, &dst_addr,
+ packet, n) < 0) {
+ printf("server_connadd failed\n");
+ cleanup();
+ return FALSE;
+ }
+
+ g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL, bnep_watchdog_cb,
+ NULL);
+
+ handle_bnep_msg_send(sk);
+
+ g_io_channel_unref(bnep_io);
+ bnep_io = NULL;
+
+ return FALSE;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ printf("%s\n", __func__);
+
+ if (err) {
+ error("%s", err->message);
+ return;
+ }
+
+ g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_bnep_cb, NULL);
+}
+
+static void connected_client_cb(char *iface, int err, void *data)
+{
+ int sk = *((int *)data);
+
+ printf("%s\n", __func__);
+
+ free(data);
+
+ handle_bnep_msg_send(sk);
+}
+
+static void disconnected_client_cb(void *data)
+{
+ printf("%s\n", __func__);
+
+ if (no_close_after_disconn)
+ return;
+
+ /* Cleanup since it's called when disconnected l2cap */
+ if (cleanup() < 0) {
+ printf("cleanup went wrong...\n");
+ return;
+ }
+
+ g_main_loop_quit(mloop);
+}
+
+static void connect_client_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ int perr;
+ int *sk;
+
+ sk = malloc(sizeof(*sk));
+
+ *sk = g_io_channel_unix_get_fd(bnep_io);
+
+ session = bnep_new(*sk, local_role, remote_role, bridge);
+ if (!session) {
+ printf("cannot create bnep session\n");
+ free(sk);
+ return;
+ }
+
+ perr = bnep_connect(session, connected_client_cb,
+ disconnected_client_cb, sk, NULL);
+ if (perr < 0)
+ printf("cannot initiate bnep connection\n");
+}
+
+static void confirm_cb(GIOChannel *chan, gpointer data)
+{
+ GError *err = NULL;
+ char address[18];
+
+ printf("%s\n", __func__);
+
+ bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst_addr, BT_IO_OPT_DEST,
+ address, BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ return;
+ }
+
+ printf("incoming connection from: %s\n", address);
+
+ bnep_io = g_io_channel_ref(chan);
+ g_io_channel_set_close_on_unref(bnep_io, TRUE);
+
+ if (!bt_io_accept(bnep_io, connect_cb, NULL, NULL, &err)) {
+ error("bt_io_accept: %s", err->message);
+ g_error_free(err);
+ }
+}
+
+static int bnep_server_listen(void)
+{
+ GError *gerr = NULL;
+
+ printf("%s\n", __func__);
+
+ bnep_io = bt_io_listen(NULL, confirm_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &src_addr,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+
+ if (!bnep_io) {
+ printf("can't start server listening: err %s\n", gerr->message);
+ g_error_free(gerr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bnep_client_connect(void)
+{
+ GError *gerr = NULL;
+ char *dst_addr_str = batostr(&dst_addr);
+
+ printf("%s\n", __func__);
+
+ printf("connecting %s\n", dst_addr_str);
+ free(dst_addr_str);
+
+ bnep_io = bt_io_connect(connect_client_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &src_addr,
+ BT_IO_OPT_DEST_BDADDR, &dst_addr,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+
+ if (!bnep_io) {
+ printf("cannot connect: err %s\n", gerr->message);
+ g_error_free(gerr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void exit_handler(int sig)
+{
+ printf("got sig = %d, cleaning up...\n", sig);
+
+ if (cleanup() < 0)
+ printf("cleanup failure...\n");
+ else
+ printf("cleanup successful - exit\n");
+
+ exit(0);
+}

static void usage(void)
{
printf("bneptest - BNEP testing ver %s\n", VERSION);
printf("Usage:\n"
- "\tbneptest [options]\n");
+ "\tbneptest [-i] -b <bridge name> -n <iface name>"
+ " <connection mode> [send_ctrl_cmd] [options]\n"
+ "\t-i hci dev number <hci number>, def. 0\n"
+ "\t-b bridge name <string>\n"
+ "\t-n interface name <string>\n");
+ printf("Connect Mode:\n"
+ "\t-c connect <dst_addr>\n"
+ "\t-r remote role <16 bit svc value>\n"
+ "\t-l local role <16 bit svc valu>\n");
+ printf("Listen Mode:\n"
+ "\t-s start server listening\n");
+ printf("Send control command:\n"
+ "\t-t send message type <control msg type>, def. 0\n"
+ "\t-e start network protocol type range <16 bit val>, def. 0\n"
+ "\t-d end network protocol type range <16 bit val>, def. 1500\n"
+ "\t-g start multicast addr range <xx:xx:xx:xx:xx:xx>, def. 0\n"
+ "\t-j end multicast addr range <xx:xx:xx:xx:xx:xx>, def. f\n"
+ "\t-y number of ctrl frame retransmission <integer>, def. 0\n"
+ "\t-u number of bnep frame retransmission <integer>, def. 0\n");
+ printf("Send bnep generic frame:\n"
+ "\t-w send bnep generic frame <bnep generic type>, def. 0\n"
+ "\t-k set src mac addr <xx:xx:xx:xx:xx:xx>, def. 0\n"
+ "\t-f set dst mac addr <xx:xx:xx:xx:xx:xx>, def. 0\n");
+ printf("Options:\n"
+ "\t-T send message timeout after setup <seconds>\n"
+ "\t-N don't close bneptest after disconnect\n");
}

static struct option main_options[] = {
- { "help", 0, 0, 'h' },
+ { "device", 1, 0, 'i' },
+ { "listen", 0, 0, 's' },
+ { "connect", 1, 0, 'c' },
+ { "snd_ctrl_msg_type", 1, 0, 't' },
+ { "snd_bnep_msg_type", 1, 0, 'w' },
+ { "src_hw_addr", 1, 0, 'k' },
+ { "dst_hw_addr", 1, 0, 'f' },
+ { "send_timeout", 1, 0, 'T' },
+ { "ntw_proto_down_range", 1, 0, 'd' },
+ { "ntw_proto_up_range", 1, 0, 'e' },
+ { "mcast_addr_down_range", 1, 0, 'g' },
+ { "mcast_addr_up_range", 1, 0, 'j' },
+ { "local_role", 1, 0, 'l' },
+ { "remote_role", 1, 0, 'r' },
+ { "bridge name", 1, 0, 'b' },
+ { "iface name", 1, 0, 'n' },
+ { "no_close", 0, 0, 'N' },
+ { "retrans_ctrl_nb", 0, 0, 'y' },
+ { "retrans_bnep_nb", 0, 0, 'u' },
+ { "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};

int main(int argc, char *argv[])
{
int opt;
+ int err;
+ bool is_set_b_name = false, is_set_i_name = false;

DBG("");

+ signal(SIGINT, exit_handler);
+
+ hci_devba(0, &src_addr);
+ bacpy(&src_addr, BDADDR_ANY);
+
mloop = g_main_loop_new(NULL, FALSE);
if (!mloop) {
printf("cannot create main loop\n");
@@ -60,9 +597,133 @@ int main(int argc, char *argv[])
exit(1);
}

- while ((opt = getopt_long(argc, argv, "h", main_options, NULL))
- != EOF) {
+ while ((opt = getopt_long(argc, argv,
+ "+i:c:b:n:t:T:d:e:g:j:k:f:w:l:r:y:u:Nsh",
+ main_options, NULL)) != EOF) {
switch (opt) {
+ case 'i':
+ if (!strncmp(optarg, "hci", 3))
+ hci_devba(atoi(optarg + 3), &src_addr);
+ else
+ str2ba(optarg, &src_addr);
+
+ break;
+
+ case 's':
+ mode = MODE_LISTEN;
+ break;
+
+ case 'c':
+ str2ba(optarg, &dst_addr);
+ mode = MODE_CONNECT;
+
+ break;
+
+ case 't':
+ send_ctrl_msg_type_set = true;
+ ctrl_msg_type = atoi(optarg);
+
+ break;
+
+ case 'w':
+ send_bnep_msg_type_set = true;
+ bnep_msg_type = atoi(optarg);
+
+ break;
+
+ case 'k': {
+ int i = 0;
+
+ for (; i <= 5; i++, optarg += 3)
+ src_hw_addr[i] = strtol(optarg, NULL, 16);
+
+ break;
+ }
+
+ case 'f': {
+ int i = 0;
+
+ for (; i <= 5; i++, optarg += 3)
+ dst_hw_addr[i] = strtol(optarg, NULL, 16);
+
+ break;
+ }
+
+ case 'T':
+ send_frame_timeout = atoi(optarg);
+
+ break;
+
+ case 'd':
+ ntw_proto_down_range = htons(atoi(optarg));
+
+ break;
+
+ case 'e':
+ ntw_proto_up_range = htons(atoi(optarg));
+
+ break;
+
+ case 'g': {
+ int i = 0;
+
+ for (i = 5; i >= 0; i--, optarg += 3)
+ mcast_addr_down_range[i] =
+ strtol(optarg, NULL, 16);
+
+ break;
+ }
+
+ case 'j': {
+ int i = 0;
+
+ for (i = 5; i >= 0; i--, optarg += 3)
+ mcast_addr_up_range[i] =
+ strtol(optarg, NULL, 16);
+
+ break;
+ }
+
+ case 'l':
+ local_role = atoi(optarg);
+
+ break;
+
+ case 'r':
+ remote_role = atoi(optarg);
+
+ break;
+
+ case 'b':
+ strncpy(bridge, optarg, 16);
+ bridge[15] = '\0';
+ is_set_b_name = true;
+
+ break;
+
+ case 'n':
+ strncpy(iface, optarg, 14);
+ strcat(iface, "\%d");
+ iface[15] = '\0';
+ is_set_i_name = true;
+
+ break;
+
+ case 'N':
+ no_close_after_disconn = true;
+
+ break;
+
+ case 'y':
+ ctrl_msg_retransmition_nb = atoi(optarg);
+
+ break;
+
+ case 'u':
+ bnep_msg_retransmission_nb = atoi(optarg);
+
+ break;
+
case 'h':
default:
usage();
@@ -70,5 +731,47 @@ int main(int argc, char *argv[])
}
}

+ if (!is_set_b_name || !is_set_i_name) {
+ printf("bridge, interface name must be set!\n");
+ exit(1);
+ }
+
+ switch (mode) {
+ case MODE_CONNECT:
+ err = bnep_init();
+ if (err < 0) {
+ printf("cannot initialize bnep\n");
+ exit(1);
+ }
+ err = bnep_client_connect();
+ if (err < 0)
+ exit(1);
+
+ break;
+
+ case MODE_LISTEN:
+ err = bnep_init();
+ if (err < 0) {
+ printf("cannot initialize bnep\n");
+ exit(1);
+ }
+ err = bnep_server_listen();
+ if (err < 0)
+ exit(1);
+
+ break;
+
+ case MODE_NONE:
+ default:
+ printf("connect/listen mode not set, exit...\n");
+ exit(1);
+ }
+
+ g_main_loop_run(mloop);
+
+ printf("Done\n");
+
+ g_main_loop_unref(mloop);
+
return 0;
}
--
2.1.0


2015-03-12 17:07:33

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 6/6] android/pts: Add BNEP PTS 6.0 results for android 5.0

This patch adds test case list and results for BNEP profile against
android 5.0
---
android/Makefile.am | 5 ++++-
android/pics-bnep.txt | 26 ++++++++++++++++++++++++++
android/pixit-bnep.txt | 30 ++++++++++++++++++++++++++++++
android/pts-bnep.txt | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 108 insertions(+), 1 deletion(-)
create mode 100644 android/pics-bnep.txt
create mode 100644 android/pixit-bnep.txt
create mode 100644 android/pts-bnep.txt

diff --git a/android/Makefile.am b/android/Makefile.am
index 7eb6440..cb32bc3 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -258,6 +258,7 @@ EXTRA_DIST += android/Android.mk android/README \
android/pics-dis.txt \
android/pics-avdtp.txt \
android/pics-gavdp.txt \
+ android/pics-bnep.txt \
android/pixit-l2cap.txt \
android/pixit-gap.txt \
android/pixit-did.txt \
@@ -285,6 +286,7 @@ EXTRA_DIST += android/Android.mk android/README \
android/pixit-avdtp.txt \
android/pixit-gavdp.txt \
android/pixit-sdp.txt \
+ android/pixit-bnep.txt \
android/pts-rfcomm.txt \
android/pts-spp.txt \
android/pts-l2cap.txt \
@@ -311,4 +313,5 @@ EXTRA_DIST += android/Android.mk android/README \
android/pts-dis.txt \
android/pts-avdtp.txt \
android/pts-gavdp.txt \
- android/pts-sdp.txt
+ android/pts-sdp.txt \
+ android/pts-bnep.txt
diff --git a/android/pics-bnep.txt b/android/pics-bnep.txt
new file mode 100644
index 0000000..4aba68e
--- /dev/null
+++ b/android/pics-bnep.txt
@@ -0,0 +1,26 @@
+BNEP PICS for the PTS tool.
+
+PTS version: 6.0
+
+* - different than PTS defaults
+# - not yet implemented/supported
+
+M - mandatory if such role selected
+O - optional
+
+ Profile Version
+-------------------------------------------------------------------------------
+Parameter Name Selected Description
+-------------------------------------------------------------------------------
+TSPC_BNEP_1_1 True BNEP Connection Setup (M)
+TSPC_BNEP_1_2 True BNEP Data Packet Reception (M)
+TSPC_BNEP_1_3 True BNEP Data Packet Transmission (M)
+TSPC_BNEP_1_3a True BNEP Compressed Packet Transmission (O)
+TSPC_BNEP_1_3b True BNEP Compressed Packet Transmission Source Only
+ (O)
+TSPC_BNEP_1_4 True BNEP Control Message Processing (M)
+TSPC_BNEP_1_5 True BNEP Extension Header Processing (M)
+TSPC_BNEP_1_6 True Network Protocol Filter Message Transmission (O)
+TSPC_BNEP_1_7 True Multicast Address Filter Message Transmission
+ (O)
+-------------------------------------------------------------------------------
diff --git a/android/pixit-bnep.txt b/android/pixit-bnep.txt
new file mode 100644
index 0000000..9a26cd2
--- /dev/null
+++ b/android/pixit-bnep.txt
@@ -0,0 +1,30 @@
+BNEP PIXIT for the PTS tool.
+
+PTS version: 6.0
+
+* - different than PTS defaults
+& - should be set to IUT Bluetooth address
+# - should be set to PTS's bin/audio folder
+
+Required PIXIT settings
+-------------------------------------------------------------------------------
+Parameter Name Value
+-------------------------------------------------------------------------------
+TSPX_class_of_device 04041C
+TSPX_security_control_data
+TSPX_content_protection_data
+TSPX_bd_addr_iut 112233445566 (*&)
+TSPX_delete_link_key FALSE
+TSPX_pin_code 1234
+TSPX_security_enabled FALSE
+TSPX_time_guard 300000
+TSPX_use_implicit_send TRUE
+TSPX_auth_password 0000
+TSPX_auth_user_id PTS
+TSPX_l2cap_psm 000F
+TSPX_rfcomm_channel 8
+TSPX_no_confirmations FALSE
+TSPX_UUID_dest_address 1116
+TSPX_UUID_source_address 1115
+TSPX_MAC_dest_address 000000000000 (*&)
+TSPX_MAC_source_address 000000000000 (*&)
diff --git a/android/pts-bnep.txt b/android/pts-bnep.txt
new file mode 100644
index 0000000..1915590
--- /dev/null
+++ b/android/pts-bnep.txt
@@ -0,0 +1,48 @@
+PTS test results for BNEP
+
+PTS version: 6.0
+Tested: 12-March-2015
+Android version: 5.0
+Kernel version: 3.20
+
+Results:
+PASS test passed
+FAIL test failed
+INC test is inconclusive
+N/A test is disabled due to PICS setup
+
+--------------------------------------------------------------------------------
+Test Name Result Notes
+--------------------------------------------------------------------------------
+TC_CTRL_BV_01_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_02_C PASS bneptest -c <PTS addr> -b <bridge> -n <iface>
+TC_CTRL_BV_03_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_04_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_05_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_06_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_07_C PASS bneptest -c <PTS addr> -b <bridge> -n <iface>
+ -t 3 -d 0 -e 1500 -y 1
+TC_CTRL_BV_08_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_09_C PASS PTS issue #13170
+ bneptest -c <PTS addr> -b <bridge> -n <iface>
+ -t 5 -g 00:00:00:00:00:00
+ -j ff:ff:ff:ff:ff:ff -y 1
+TC_CTRL_BV_10_C PASS bneptest -s -b <bridge> -n <iface>
+TC_CTRL_BV_19_C INC Jira issue #BA-343
+ bneptest -s -b <bridge> -n <iface>
+TC_RX_TYPE_0_BV_11_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_C_BV_12_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_C_S_BV_13_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_C_S_BV_14_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_TYPE_0_BV_15_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_TYPE_0_BV_16_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_TYPE_0_BV_17_C PASS bneptest -s -b <bridge> -n <iface>
+TC_RX_TYPE_0_BV_18_C PASS bneptest -s -b <bridge> -n <iface>
+TC_TX_TYPE_0_BV_20_C PASS bneptest -c <PTS addr> -b <bridge> -n <iface>
+ -w 0 -k <src hw addr> -f <dst hw addr>
+TC_TX_C_BV_21_C PASS bneptest -c <PTS addr> -b <bridge> -n <iface>
+ -w 2 -k <src hw addr> -f <dst hw addr>
+TC_TX_C_S_BV_22_C PASS bneptest -c <PTS addr> -b <bridge> -n <iface>
+ -w 3 -k <src hw addr> -f <dst hw addr>
+TC_TX_C_D_BV_23_C PASS bneptest -c <PTS addr> -b <bridge> -n <iface>
+ -w 4 -k <src hw addr> -f <dst hw addr>
--
2.1.0


2015-03-12 17:07:31

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 4/6] tools/bneptest: Add initial support for bneptest tool

This tool should be designed to help testing bnep on Bluez.
---
.gitignore | 1 +
Makefile.tools | 12 ++++++---
android/Android.mk | 35 ++++++++++++++++++++++++++
tools/bneptest.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 119 insertions(+), 3 deletions(-)
create mode 100644 tools/bneptest.c

diff --git a/.gitignore b/.gitignore
index a207a0f..a4f06dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,6 +82,7 @@ tools/gatt-service
tools/btgatt-client
tools/btgatt-server
tools/mcaptest
+tools/bneptest
test/sap_client.pyc
test/bluezutils.pyc
unit/test-ringbuf
diff --git a/Makefile.tools b/Makefile.tools
index e28f3cb..1aafb28 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -223,9 +223,9 @@ noinst_PROGRAMS += tools/bdaddr tools/avinfo tools/avtest \
tools/hcieventmask tools/hcisecfilter \
tools/btmgmt tools/btinfo tools/btattach \
tools/btsnoop tools/btproxy \
- tools/btiotest tools/mcaptest tools/cltest \
- tools/oobtest tools/seq2bseq tools/ibeacon \
- tools/btgatt-client tools/btgatt-server
+ tools/btiotest tools/bneptest tools/mcaptest \
+ tools/cltest tools/oobtest tools/seq2bseq \
+ tools/ibeacon tools/btgatt-client tools/btgatt-server

tools_bdaddr_SOURCES = tools/bdaddr.c src/oui.h src/oui.c
tools_bdaddr_LDADD = lib/libbluetooth-internal.la @UDEV_LIBS@
@@ -267,6 +267,12 @@ tools_mcaptest_SOURCES = tools/mcaptest.c \
profiles/health/mcap.h profiles/health/mcap.c
tools_mcaptest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

+tools_bneptest_SOURCES = tools/bneptest.c \
+ btio/btio.h btio/btio.c \
+ src/log.c src/log.h \
+ profiles/network/bnep.h profiles/network/bnep.c
+tools_bneptest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
tools_cltest_SOURCES = tools/cltest.c
tools_cltest_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la

diff --git a/android/Android.mk b/android/Android.mk
index 6c0eda8..f218805 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -256,6 +256,41 @@ LOCAL_MODULE := mcaptest
include $(BUILD_EXECUTABLE)

#
+# bneptest
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ bluez/src/log.c \
+ bluez/btio/btio.c \
+ bluez/lib/bluetooth.c \
+ bluez/lib/hci.c \
+ bluez/profiles/network/bnep.c \
+ bluez/tools/bneptest.c \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/bluez \
+
+LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libglib \
+
+LOCAL_STATIC_LIBRARIES := \
+ bluetooth-headers \
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := bneptest
+
+include $(BUILD_EXECUTABLE)
+
+#
# avdtptest
#

diff --git a/tools/bneptest.c b/tools/bneptest.c
new file mode 100644
index 0000000..619427b
--- /dev/null
+++ b/tools/bneptest.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2015 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 <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <glib.h>
+
+#include "src/log.h"
+
+static GMainLoop *mloop;
+
+static void usage(void)
+{
+ printf("bneptest - BNEP testing ver %s\n", VERSION);
+ printf("Usage:\n"
+ "\tbneptest [options]\n");
+}
+
+static struct option main_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+ int opt;
+
+ DBG("");
+
+ mloop = g_main_loop_new(NULL, FALSE);
+ if (!mloop) {
+ printf("cannot create main loop\n");
+
+ exit(1);
+ }
+
+ while ((opt = getopt_long(argc, argv, "h", main_options, NULL))
+ != EOF) {
+ switch (opt) {
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ }
+ }
+
+ return 0;
+}
--
2.1.0


2015-03-12 17:07:30

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 3/6] profiles/network: Move disconn cb setting to bnep connect method

Disconnect callback can be set while connececting bnep. In previous
implementation there was separated method to setting up the disconnect
callback and it was always called immediately after calling connect -
this method was redundand.
---
android/pan.c | 5 ++---
profiles/network/bnep.c | 22 +++++++---------------
profiles/network/bnep.h | 6 +++---
profiles/network/connection.c | 4 +---
4 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index a14ed84..6c9815b 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -324,14 +324,13 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
if (!dev->session)
goto fail;

- perr = bnep_connect(dev->session, bnep_conn_cb, dev);
+ perr = bnep_connect(dev->session, bnep_conn_cb, bnep_disconn_cb, dev,
+ dev);
if (perr < 0) {
error("bnep connect req failed: %s", strerror(-perr));
goto fail;
}

- bnep_set_disconnect(dev->session, bnep_disconn_cb, dev);
-
if (dev->io) {
g_io_channel_unref(dev->io);
dev->io = NULL;
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 9dbdb7a..e325b72 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -369,17 +369,21 @@ void bnep_free(struct bnep *session)
g_free(session);
}

-int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb, void *data)
+int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb,
+ bnep_disconnect_cb disconn_cb,
+ void *conn_data, void *disconn_data)
{
GError *gerr = NULL;
int err;

- if (!session || !conn_cb)
+ if (!session || !conn_cb || !disconn_cb)
return -EINVAL;

session->attempts = 0;
session->conn_cb = conn_cb;
- session->conn_data = data;
+ session->disconn_cb = disconn_cb;
+ session->conn_data = conn_data;
+ session->disconn_data = disconn_data;

bt_io_get(session->io, &gerr, BT_IO_OPT_DEST_BDADDR, &session->dst_addr,
BT_IO_OPT_INVALID);
@@ -417,18 +421,6 @@ void bnep_disconnect(struct bnep *session)
bnep_conndel(&session->dst_addr);
}

-void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
- void *data)
-{
- if (!session || !disconn_cb)
- return;
-
- if (!session->disconn_cb && !session->disconn_data) {
- session->disconn_cb = disconn_cb;
- session->disconn_data = data;
- }
-}
-
static int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index da706ac..e9f4c1c 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -31,10 +31,10 @@ struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
void bnep_free(struct bnep *session);

typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
-int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb, void *data);
typedef void (*bnep_disconnect_cb) (void *data);
-void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
- void *data);
+int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb,
+ bnep_disconnect_cb disconn_cb,
+ void *conn_data, void *disconn_data);
void bnep_disconnect(struct bnep *session);

int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 9439d34..2b07771 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -258,14 +258,12 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
if (!nc->session)
goto failed;

- perr = bnep_connect(nc->session, bnep_conn_cb, nc);
+ perr = bnep_connect(nc->session, bnep_conn_cb, bnep_disconn_cb, nc, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
}

- bnep_set_disconnect(nc->session, bnep_disconn_cb, nc);
-
if (nc->io) {
g_io_channel_unref(nc->io);
nc->io = NULL;
--
2.1.0


2015-03-12 17:07:28

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 1/6] profiles/network: Remove unneded bnep_uuid function from bnep code

This function is no longer needed since connection and server can handle
this funcionality by itself.
---
profiles/network/bnep.c | 10 ----------
profiles/network/bnep.h | 1 -
profiles/network/connection.c | 19 ++++++++++++-------
profiles/network/server.c | 36 ++++++++++++++++++++++++++++++------
4 files changed, 42 insertions(+), 24 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 779c5fb..7280149 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -85,16 +85,6 @@ struct bnep {
void *disconn_data;
};

-const char *bnep_uuid(uint16_t id)
-{
- int i;
-
- for (i = 0; __svc[i].uuid128; i++)
- if (__svc[i].id == id)
- return __svc[i].uuid128;
- return NULL;
-}
-
const char *bnep_name(uint16_t id)
{
int i;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 31579f9..811ea14 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -26,7 +26,6 @@ struct bnep;
int bnep_init(void);
int bnep_cleanup(void);

-const char *bnep_uuid(uint16_t id);
const char *bnep_name(uint16_t id);

struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 4311cc9..9439d34 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -284,21 +284,23 @@ static DBusMessage *local_connect(DBusConnection *conn,
struct btd_service *service;
struct network_conn *nc;
const char *svc;
- const char *uuid;
uint16_t id;
int err;
+ char uuid_str[MAX_LEN_UUID_STR];
+ bt_uuid_t uuid16, uuid128;

if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,
DBUS_TYPE_INVALID) == FALSE)
return btd_error_invalid_args(msg);

id = get_pan_srv_id(svc);
- uuid = bnep_uuid(id);
+ bt_uuid16_create(&uuid16, id);
+ bt_uuid_to_uuid128(&uuid128, &uuid16);

- if (uuid == NULL)
+ if (bt_uuid_to_string(&uuid128, uuid_str, MAX_LEN_UUID_STR) < 0)
return btd_error_invalid_args(msg);

- service = btd_device_get_service(peer->device, uuid);
+ service = btd_device_get_service(peer->device, uuid_str);
if (service == NULL)
return btd_error_not_supported(msg);

@@ -439,15 +441,18 @@ static gboolean network_property_get_uuid(const GDBusPropertyTable *property,
{
struct network_peer *peer = data;
struct network_conn *nc;
- const char *uuid;
+ char uuid_str[MAX_LEN_UUID_STR];
+ bt_uuid_t uuid16, uuid128;

nc = find_connection_by_state(peer->connections, CONNECTED);
if (nc == NULL)
return FALSE;

- uuid = bnep_uuid(nc->id);
+ bt_uuid16_create(&uuid16, nc->id);
+ bt_uuid_to_uuid128(&uuid128, &uuid16);
+ bt_uuid_to_string(&uuid128, uuid_str, MAX_LEN_UUID_STR);

- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid_str);

return TRUE;
}
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 9caabb0..32aafc3 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -114,14 +114,38 @@ static struct network_server *find_server(GSList *list, uint16_t id)
static struct network_server *find_server_by_uuid(GSList *list,
const char *uuid)
{
- for (; list; list = list->next) {
- struct network_server *ns = list->data;
+ bt_uuid_t srv_uuid, bnep_uuid;

- if (strcasecmp(uuid, bnep_uuid(ns->id)) == 0)
- return ns;
+ if (!bt_string_to_uuid(&srv_uuid, uuid)) {
+ for (; list; list = list->next) {
+ struct network_server *ns = list->data;

- if (strcasecmp(uuid, bnep_name(ns->id)) == 0)
- return ns;
+ bt_uuid16_create(&bnep_uuid, ns->id);
+
+ /* UUID value compare */
+ if (!bt_uuid_cmp(&srv_uuid, &bnep_uuid))
+ return ns;
+ }
+ } else {
+ for (; list; list = list->next) {
+ struct network_server *ns = list->data;
+
+ /* String value compare */
+ switch (ns->id) {
+ case BNEP_SVC_PANU:
+ if (!strcasecmp(uuid, "panu"))
+ return ns;
+ break;
+ case BNEP_SVC_NAP:
+ if (!strcasecmp(uuid, "nap"))
+ return ns;
+ break;
+ case BNEP_SVC_GN:
+ if (!strcasecmp(uuid, "gn"))
+ return ns;
+ break;
+ }
+ }
}

return NULL;
--
2.1.0


2015-03-12 17:07:29

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v5 2/6] profiles/network: Remove not needed get name by bnep id function

This function and service structure declaration is no longer needed
since related code was distracted.
---
profiles/network/bnep.c | 21 ---------------------
profiles/network/bnep.h | 2 --
2 files changed, 23 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 7280149..9dbdb7a 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -54,17 +54,6 @@

static int ctl;

-static struct {
- const char *name; /* Friendly name */
- const char *uuid128; /* UUID 128 */
- uint16_t id; /* Service class identifier */
-} __svc[] = {
- { "panu", PANU_UUID, BNEP_SVC_PANU },
- { "gn", GN_UUID, BNEP_SVC_GN },
- { "nap", NAP_UUID, BNEP_SVC_NAP },
- { NULL }
-};
-
struct __service_16 {
uint16_t dst;
uint16_t src;
@@ -85,16 +74,6 @@ struct bnep {
void *disconn_data;
};

-const char *bnep_name(uint16_t id)
-{
- int i;
-
- for (i = 0; __svc[i].name; i++)
- if (__svc[i].id == id)
- return __svc[i].name;
- return NULL;
-}
-
int bnep_init(void)
{
ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 811ea14..da706ac 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -26,8 +26,6 @@ struct bnep;
int bnep_init(void);
int bnep_cleanup(void);

-const char *bnep_name(uint16_t id);
-
struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
char *iface);
void bnep_free(struct bnep *session);
--
2.1.0