Return-Path: From: Szymon Janc To: linux-bluetooth@vger.kernel.org Subject: Re: [PATCH] tools: Add initial User Channel tester Date: Mon, 18 May 2015 22:08:08 +0200 Message-ID: <2235784.nv5OG9emlI@leonov> In-Reply-To: <1430834137-19064-2-git-send-email-szymon.janc@tieto.com> References: <1430834137-19064-1-git-send-email-szymon.janc@tieto.com> <1430834137-19064-2-git-send-email-szymon.janc@tieto.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Sender: linux-bluetooth-owner@vger.kernel.org List-ID: On Tuesday 05 of May 2015 15:55:37 Szymon Janc wrote: > This adds basic tests only. > --- > .gitignore | 1 + > Makefile.tools | 11 +- > tools/userchannel-tester.c | 333 > +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 344 > insertions(+), 1 deletion(-) > create mode 100644 tools/userchannel-tester.c > > diff --git a/.gitignore b/.gitignore > index 08eabac..c350f49 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -109,6 +109,7 @@ tools/smp-tester > tools/gap-tester > tools/rfcomm-tester > tools/bnep-tester > +tools/userchannel-tester > tools/btattach > tools/btmgmt > tools/btsnoop > diff --git a/Makefile.tools b/Makefile.tools > index 6020b01..9abe07d 100644 > --- a/Makefile.tools > +++ b/Makefile.tools > @@ -43,7 +43,8 @@ noinst_PROGRAMS += emulator/btvirt emulator/b1ee > emulator/hfp \ tools/mgmt-tester tools/gap-tester \ > tools/l2cap-tester tools/sco-tester \ > tools/smp-tester tools/hci-tester \ > - tools/rfcomm-tester tools/bnep-tester > + tools/rfcomm-tester tools/bnep-tester \ > + tools/userchannel-tester > > emulator_btvirt_SOURCES = emulator/main.c monitor/bt.h \ > emulator/serial.h emulator/serial.c \ > @@ -135,6 +136,14 @@ tools_sco_tester_LDADD = lib/libbluetooth-internal.la \ > > tools_hci_tester_SOURCES = tools/hci-tester.c monitor/bt.h > tools_hci_tester_LDADD = src/libshared-glib.la @GLIB_LIBS@ > + > +tools_userchannel_tester_SOURCES = tools/userchannel-tester.c monitor/bt.h > \ + emulator/hciemu.h emulator/hciemu.c \ > + emulator/btdev.h emulator/btdev.c \ > + emulator/bthost.h emulator/bthost.c \ > + emulator/smp.c > +tools_userchannel_tester_LDADD = lib/libbluetooth-internal.la \ > + src/libshared-glib.la @GLIB_LIBS@ > endif > > if TOOLS > diff --git a/tools/userchannel-tester.c b/tools/userchannel-tester.c > new file mode 100644 > index 0000000..ec5dffd > --- /dev/null > +++ b/tools/userchannel-tester.c > @@ -0,0 +1,333 @@ > +/* > + * > + * BlueZ - Bluetooth protocol stack for Linux > + * > + * Copyright (C) 2014-2015 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 > +#endif > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include "lib/bluetooth.h" > +#include "lib/hci.h" > +#include "lib/mgmt.h" > + > +#include "monitor/bt.h" > +#include "emulator/bthost.h" > +#include "emulator/hciemu.h" > + > +#include "src/shared/tester.h" > +#include "src/shared/mgmt.h" > +#include "src/shared/hci.h" > +#include "src/shared/util.h" > + > +struct test_data { > + struct mgmt *mgmt; > + uint16_t mgmt_index; > + struct hciemu *hciemu; > + enum hciemu_type hciemu_type; > + const void *test_data; > + unsigned int remove_id; > +}; > + > +static void mgmt_debug(const char *str, void *user_data) > +{ > + const char *prefix = user_data; > + > + tester_print("%s%s", prefix, str); > +} > + > +static void read_info_callback(uint8_t status, uint16_t length, > + const void *param, void *user_data) > +{ > + struct test_data *data = tester_get_data(); > + const struct mgmt_rp_read_info *rp = param; > + char addr[18]; > + uint16_t manufacturer; > + uint32_t supported_settings, current_settings; > + > + tester_print("Read Info callback"); > + tester_print(" Status: 0x%02x", status); > + > + if (status || !param) { > + tester_pre_setup_failed(); > + return; > + } > + > + ba2str(&rp->bdaddr, addr); > + manufacturer = btohs(rp->manufacturer); > + supported_settings = btohl(rp->supported_settings); > + current_settings = btohl(rp->current_settings); > + > + tester_print(" Address: %s", addr); > + tester_print(" Version: 0x%02x", rp->version); > + tester_print(" Manufacturer: 0x%04x", manufacturer); > + tester_print(" Supported settings: 0x%08x", supported_settings); > + tester_print(" Current settings: 0x%08x", current_settings); > + tester_print(" Class: 0x%02x%02x%02x", > + rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]); > + tester_print(" Name: %s", rp->name); > + tester_print(" Short name: %s", rp->short_name); > + > + if (strcmp(hciemu_get_address(data->hciemu), addr)) { > + tester_pre_setup_failed(); > + return; > + } > + > + tester_pre_setup_complete(); > +} > + > +static void index_added_callback(uint16_t index, uint16_t length, > + const void *param, void *user_data) > +{ > + struct test_data *data = tester_get_data(); > + > + tester_print("Index Added callback"); > + tester_print(" Index: 0x%04x", index); > + > + if (data->mgmt_index != MGMT_INDEX_NONE) > + return; > + > + data->mgmt_index = index; > + > + mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL, > + read_info_callback, NULL, NULL); > +} > + > +static void index_removed_callback(uint16_t index, uint16_t length, > + const void *param, void *user_data) > +{ > + struct test_data *data = tester_get_data(); > + > + tester_print("Index Removed callback"); > + tester_print(" Index: 0x%04x", index); > + > + if (index != data->mgmt_index) > + return; > + > + if (data->remove_id) { > + mgmt_unregister(data->mgmt, data->remove_id); > + data->remove_id = 0; > + tester_test_passed(); > + return; > + } > + > + mgmt_unregister_index(data->mgmt, data->mgmt_index); > + > + mgmt_unref(data->mgmt); > + data->mgmt = NULL; > + > + tester_post_teardown_complete(); > +} > + > +static void read_index_list_callback(uint8_t status, uint16_t length, > + const void *param, void *user_data) > +{ > + struct test_data *data = tester_get_data(); > + > + tester_print("Read Index List callback"); > + tester_print(" Status: 0x%02x", status); > + > + if (status || !param) { > + tester_pre_setup_failed(); > + return; > + } > + > + mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE, > + index_added_callback, NULL, NULL); > + > + data->hciemu = hciemu_new(data->hciemu_type); > + if (!data->hciemu) { > + tester_warn("Failed to setup HCI emulation"); > + tester_pre_setup_failed(); > + } > + > + tester_print("New hciemu instance created"); > +} > + > +static void test_pre_setup(const void *test_data) > +{ > + struct test_data *data = tester_get_data(); > + > + data->mgmt = mgmt_new_default(); > + if (!data->mgmt) { > + tester_warn("Failed to setup management interface"); > + tester_pre_setup_failed(); > + return; > + } > + > + if (tester_use_debug()) > + mgmt_set_debug(data->mgmt, mgmt_debug, "mgmt: ", NULL); > + > + mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL, > + read_index_list_callback, NULL, NULL); > +} > + > +static void test_post_teardown(const void *test_data) > +{ > + struct test_data *data = tester_get_data(); > + > + mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, data->mgmt_index, > + index_removed_callback, > + NULL, NULL); > + > + hciemu_unref(data->hciemu); > + data->hciemu = NULL; > +} > + > +static void test_data_free(void *test_data) > +{ > + struct test_data *data = test_data; > + > + free(data); > +} > + > +static void setup_powered_client_callback(uint8_t status, uint16_t length, > + const void *param, void *user_data) > +{ > + if (status != MGMT_STATUS_SUCCESS) { > + tester_setup_failed(); > + return; > + } > + > + tester_print("Controller powered on"); > + > + tester_setup_complete(); > +} > + > +static void setup_powered(const void *test_data) > +{ > + struct test_data *data = tester_get_data(); > + unsigned char param[] = { 0x01 }; > + > + tester_print("Powering on controller"); > + > + mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, > + sizeof(param), param, setup_powered_client_callback, > + NULL, NULL); > +} > + > +static void toggle_powered(const void *test_data); > + > +static void toggle_powered_client_callback(uint8_t status, uint16_t length, > + const void *param, void *user_data) > +{ > + bool power = PTR_TO_INT(user_data); > + > + if (status != MGMT_STATUS_SUCCESS) { > + tester_setup_failed(); > + return; > + } > + > + tester_print("Controller powered %s", power ? "on" : "off"); > + > + if (power) > + toggle_powered(false); > + else > + tester_setup_complete(); > +} > + > +static void toggle_powered(const void *test_data) > +{ > + struct test_data *data = tester_get_data(); > + bool power = PTR_TO_INT(test_data); > + unsigned char param[1]; > + > + param[0] = power ? 0x01 : 0x00; > + > + tester_print("Powering %s controller", power ? "on" : "off"); > + > + mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index, > + sizeof(param), param, toggle_powered_client_callback, > + INT_TO_PTR(power), NULL); > +} > + > +static void test_open_success(const void *test_data) > +{ > + struct test_data *data = tester_get_data(); > + struct bt_hci *hci; > + > + data->remove_id = mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, > + data->mgmt_index, > + index_removed_callback, > + NULL, NULL); > + > + hci = bt_hci_new_user_channel(data->mgmt_index); > + if (hci) { > + bt_hci_unref(hci); > + return; > + } > + > + mgmt_unregister(data->mgmt, data->remove_id); > + data->remove_id = 0; > + > + tester_test_failed(); > +} > + > +static void test_open_failed(const void *test_data) > +{ > + struct test_data *data = tester_get_data(); > + struct bt_hci *hci; > + > + hci = bt_hci_new_user_channel(data->mgmt_index); > + if (!hci) { > + tester_test_passed(); > + return; > + } > + > + bt_hci_unref(hci); > + tester_test_failed(); > +} > + > +#define test_user(name, data, setup, func) \ > + do { \ > + struct test_data *user; \ > + user = malloc(sizeof(struct test_data)); \ > + if (!user) \ > + break; \ > + user->hciemu_type = HCIEMU_TYPE_BREDR; \ > + user->mgmt_index = MGMT_INDEX_NONE; \ > + user->test_data = data; \ > + tester_add_full(name, data, \ > + test_pre_setup, setup, func, NULL, \ > + test_post_teardown, 2, user, test_data_free); \ > + } while (0) > + > +int main(int argc, char *argv[]) > +{ > + tester_init(&argc, &argv); > + > + test_user("User channel open - Success", NULL, > + NULL, test_open_success); > + test_user("User channel open - Failed", NULL, > + setup_powered, test_open_failed); > + test_user("User channel open - Power Toggle Success", INT_TO_PTR(true), > + toggle_powered, test_open_success); > + > + return tester_run(); > +} Applied. -- BR Szymon Janc