2014-02-26 01:57:11

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 00/17] Test and fix for cancel discovery

This patch series is to show and fix one single issue found on UPF.
Issue is that cancel discovery does not work as designed when there
is a lot of remote devices in piscan mode.

To write testcase for this scenario, new way of handle inquiry
command has been introduced in btdev.

Also abstraction for timeout has be introduced to give btdev
possibility to schedule "inquiry session"

I'm aware that testcase will have to be rebased after
fixes for android-tester will hit the tree. Hopefully it will
me more stable then as well.

I have not run any other testers than android one, so I don't
know yet how changes in btdev influence on it.

Patches tested with btvirt (mainloop support) and android-tester
(glib support)

Lukasz Rymanowski (17):
monitor: Allow to modify epoll even events are the same
monitor: Use miliseconds instead of seconds in the timeout
shared: Add header for timeout abstraction
shared: Add timeout handling with Glib support
shared: Add timeout handling with mainloop support
emulator: Minor style fix
emulator: Use timeout for sending inquiry results
emulator: Add inquiry cancel
emulator: Add handling inquiry number of responses
emulator: Add handling inquiry_lenght from inquiry command
emulator: Add support to create many remote devices in hciemu
android/tester: Add discovery cancel test
android/tester: Remove not needed hook for inquiry complete
android/tester: Increase timeout for test failure
android: Add tracking for pending confirm name command
android: Cancel all pending confirm name before stop discovery
android: Send confirm name request with mgmt_send

Makefile.tools | 19 ++++--
android/Makefile.am | 2 +
android/android-tester.c | 116 +++++++++++++++++++++++++++++----
android/bluetooth.c | 43 ++++++++++--
emulator/btdev.c | 148 ++++++++++++++++++++++++++++++++++++++----
monitor/mainloop.c | 22 +++----
monitor/mainloop.h | 4 +-
src/shared/hciemu.c | 63 ++++++++++++++++++
src/shared/hciemu.h | 11 ++++
src/shared/timeout-glib.c | 73 +++++++++++++++++++++
src/shared/timeout-mainloop.c | 78 ++++++++++++++++++++++
src/shared/timeout.h | 27 ++++++++
tools/3dsp.c | 2 +-
tools/btinfo.c | 2 +-
14 files changed, 561 insertions(+), 49 deletions(-)
create mode 100644 src/shared/timeout-glib.c
create mode 100644 src/shared/timeout-mainloop.c
create mode 100644 src/shared/timeout.h

--
1.8.4



2014-02-27 17:18:15

by Lukasz Rymanowski

[permalink] [raw]
Subject: Re: [PATCH 14/17] android/tester: Increase timeout for test failure

Hi,

On 26 February 2014 02:57, Lukasz Rymanowski
<[email protected]> wrote:
> Inquiry command is sent with inquiry lenght 10.24 sec. There are
> testcases where that time is needed to end the test, therefore change
> timeout to 12 sec (number choosed based on strong feelings ;))
> ---
> android/android-tester.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/android/android-tester.c b/android/android-tester.c
> index 65516c1..b09834a 100644
> --- a/android/android-tester.c
> +++ b/android/android-tester.c
> @@ -3707,7 +3707,7 @@ static void test_hidhost_get_report(const void *test_data)
> user->test_data = data; \
> tester_add_full(name, data, test_pre_setup, test_setup, \
> test, test_teardown, test_post_teardown, \
> - 3, user, g_free); \
> + 12, user, g_free); \
> } while (0)
>
> int main(int argc, char *argv[])
> --
> 1.8.4
>

Will not need this patch. Will fix it in v2

\Lukasz

2014-02-26 10:32:06

by Lukasz Rymanowski

[permalink] [raw]
Subject: Re: [PATCH 10/17] emulator: Add handling inquiry_lenght from inquiry command

Hi,

On 26 February 2014 02:57, Lukasz Rymanowski
<[email protected]> wrote:
> ---
> emulator/btdev.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/emulator/btdev.c b/emulator/btdev.c
> index c74258b..bf0c9d2 100644
> --- a/emulator/btdev.c
> +++ b/emulator/btdev.c
> @@ -129,8 +129,10 @@ struct btdev {
> struct inquiry_data {
> struct btdev *btdev;
> int num_resp;
> + int max_iter; /* Calculated from inquiry_lenght */
>
> int sent_count;
> + int iter;
> };
>
> #define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */
> @@ -778,8 +780,12 @@ static bool inquiry_callback(void *user_data)
> if (data->num_resp && data->sent_count == data->num_resp)
> goto finish;
>
> + /* Check if we already spent as much time as required */
> + if (data->max_iter && data->iter++ == data->max_iter)
> + goto finish;
> +
> if (i == MAX_BTDEV_ENTRIES) {
> - if (!data->num_resp)
> + if (!data->max_iter && !data->num_resp)
> goto finish;
>
> /* Reset main iterator so we can start iterate btdev_list
> @@ -826,6 +832,7 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
> const struct bt_hci_cmd_inquiry *inq_cmd = cmd;
> struct inquiry_data *data;
> struct bt_hci_evt_inquiry_complete ic;
> + unsigned int inquiry_len_ms = 128 * inq_cmd->length;
>
> if (btdev->inquiry_id)
> return;
> @@ -838,6 +845,9 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
> data->btdev = btdev;
> data->num_resp = inq_cmd->num_resp;
>
> + if (inquiry_len_ms)
> + data->max_iter = inquiry_len_ms / DEFAULT_INQUIRY_INTERVAL;
> +
> btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
> inquiry_callback, data, inquiry_destroy);
> /* Return if success */
> --
> 1.8.4
>

Do not review this one, I will change the approach here

\Lukasz

2014-02-26 01:57:18

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 07/17] emulator: Use timeout for sending inquiry results

With this patch btdev uses timeout to schedule inquiry results
It also allows btdev to receive hci commands during inquiry.
Previously btdev was blocked since all the inquiry result were sent in
single loop
---
Makefile.tools | 19 ++++++++----
android/Makefile.am | 2 ++
emulator/btdev.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 96 insertions(+), 12 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 15d810f..0a41ec3 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -48,6 +48,7 @@ emulator_btvirt_SOURCES = emulator/main.c monitor/bt.h \
monitor/mainloop.h monitor/mainloop.c \
src/shared/util.h src/shared/util.c \
src/shared/crypto.h src/shared/crypto.c \
+ src/sharead/timeout.h src/shared/timeout-mainloop.c \
emulator/server.h emulator/server.c \
emulator/vhci.h emulator/vhci.c \
emulator/btdev.h emulator/btdev.c \
@@ -82,7 +83,8 @@ tools_mgmt_tester_SOURCES = tools/mgmt-tester.c monitor/bt.h \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
- src/shared/tester.h src/shared/tester.c
+ src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c
tools_mgmt_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
@@ -94,7 +96,8 @@ tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
- src/shared/tester.h src/shared/tester.c
+ src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c
tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
@@ -106,7 +109,8 @@ tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
- src/shared/tester.h src/shared/tester.c
+ src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c
tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
@@ -118,7 +122,8 @@ tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
- src/shared/tester.h src/shared/tester.c
+ src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c
tools_smp_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
@@ -128,7 +133,8 @@ tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
src/shared/util.h src/shared/util.c \
src/shared/queue.h src/shared/queue.c \
src/shared/hciemu.h src/shared/hciemu.c \
- src/shared/tester.h src/shared/tester.c
+ src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c
tools_gap_tester_LDADD = lib/libbluetooth-internal.la \
gdbus/libgdbus-internal.la \
@GLIB_LIBS@ @DBUS_LIBS@
@@ -142,7 +148,8 @@ tools_sco_tester_SOURCES = tools/sco-tester.c monitor/bt.h \
src/shared/util.h src/shared/util.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
- src/shared/tester.h src/shared/tester.c
+ src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c
tools_sco_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

tools_hci_tester_SOURCES = tools/hci-tester.c monitor/bt.h \
diff --git a/android/Makefile.am b/android/Makefile.am
index b93b840..036a08b 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -117,6 +117,7 @@ android_android_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c \
monitor/rfcomm.h \
android/hardware/hardware.c \
android/android-tester.c
@@ -139,6 +140,7 @@ android_ipc_tester_SOURCES = emulator/btdev.h emulator/btdev.c \
src/shared/mgmt.h src/shared/mgmt.c \
src/shared/hciemu.h src/shared/hciemu.c \
src/shared/tester.h src/shared/tester.c \
+ src/shared/timeout.h src/shared/timeout-glib.c \
android/hal-utils.h android/hal-utils.c \
android/ipc-tester.c

diff --git a/emulator/btdev.c b/emulator/btdev.c
index c6bf96c..18f7410 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -33,6 +33,7 @@
#include <alloca.h>

#include "src/shared/util.h"
+#include "src/shared/timeout.h"
#include "monitor/bt.h"
#include "btdev.h"

@@ -68,6 +69,8 @@ struct btdev {
btdev_send_func send_handler;
void *send_data;

+ int inquiry_id;
+
struct hook *hook_list[MAX_HOOK_ENTRIES];

uint16_t manufacturer;
@@ -122,8 +125,16 @@ struct btdev {
uint8_t sync_train_service_data;
};

+struct inquiry_data {
+ struct btdev *btdev;
+ int sent_count;
+};
+
+#define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */
+
#define MAX_BTDEV_ENTRIES 16

+
static const uint8_t LINK_KEY_NONE[16] = { 0 };
static const uint8_t LINK_KEY_DUMMY[16] = { 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 0, 1, 2, 3, 4, 5 };
@@ -527,9 +538,13 @@ void btdev_destroy(struct btdev *btdev)
if (!btdev)
return;

+ if (btdev->inquiry_id)
+ timeout_remove(btdev->inquiry_id);
+
del_btdev(btdev);

free(btdev);
+ btdev = NULL;
}

const uint8_t *btdev_get_bdaddr(struct btdev *btdev)
@@ -683,12 +698,22 @@ static void num_completed_packets(struct btdev *btdev)
}
}

-static void inquiry_complete(struct btdev *btdev, uint8_t status)
+static bool inquiry_callback(void *user_data)
{
- struct bt_hci_evt_inquiry_complete ic;
+ struct inquiry_data *data = user_data;
+ struct btdev *btdev = data->btdev;
+ static int j;
+ int sent = data->sent_count;
int i;

- for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
+ if (!btdev)
+ return false;
+
+ for (i = j; i < MAX_BTDEV_ENTRIES; i++, j++) {
+ /*Lets sent 10 inquiry results at once */
+ if (sent + 10 == data->sent_count)
+ break;
+
if (!btdev_list[i] || btdev_list[i] == btdev)
continue;

@@ -710,6 +735,7 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)

send_event(btdev, BT_HCI_EVT_EXT_INQUIRY_RESULT, &ir,
sizeof(ir));
+ data->sent_count++;
continue;
}

@@ -726,6 +752,7 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)

send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI,
&ir, sizeof(ir));
+ data->sent_count++;
} else {
struct bt_hci_evt_inquiry_result ir;

@@ -739,11 +766,59 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)

send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT, &ir,
sizeof(ir));
+ data->sent_count++;
}
- }
+ }
+
+ if (i == MAX_BTDEV_ENTRIES) {
+ struct bt_hci_evt_inquiry_complete ic;
+
+ ic.status = BT_HCI_ERR_SUCCESS;
+ send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
+
+ /* reset */
+ btdev->inquiry_id = 0;
+ j = 0;

- ic.status = status;
+ return false;
+ }
+
+ return true;
+}
+
+static void inquiry_destroy(void *user_data)
+{
+ struct inquiry_data *data = user_data;
+
+ if (data->btdev)
+ data->btdev->inquiry_id = 0;
+
+ free(data);
+}
+
+static void inquiry_cmd(struct btdev *btdev, const void *cmd)
+{
+ struct inquiry_data *data;
+ struct bt_hci_evt_inquiry_complete ic;
+
+ if (btdev->inquiry_id)
+ return;
+
+ data = malloc(sizeof(*data));
+ if (!data)
+ goto error;
+
+ memset(data, 0, sizeof(*data));
+ data->btdev = btdev;
+
+ btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
+ inquiry_callback, data, inquiry_destroy);
+ /* Return if success */
+ if (btdev->inquiry_id)
+ return;

+error:
+ ic.status = BT_HCI_ERR_HARDWARE_FAILURE;
send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
}

@@ -2480,7 +2555,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_INQUIRY:
if (btdev->type == BTDEV_TYPE_LE)
return;
- inquiry_complete(btdev, BT_HCI_ERR_SUCCESS);
+ inquiry_cmd(btdev, data);
break;

case BT_HCI_CMD_CREATE_CONN:
--
1.8.4


2014-02-26 01:57:16

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 05/17] shared: Add timeout handling with mainloop support

---
src/shared/timeout-mainloop.c | 78 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
create mode 100644 src/shared/timeout-mainloop.c

diff --git a/src/shared/timeout-mainloop.c b/src/shared/timeout-mainloop.c
new file mode 100644
index 0000000..bdc527a
--- /dev/null
+++ b/src/shared/timeout-mainloop.c
@@ -0,0 +1,78 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 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.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "timeout.h"
+
+#include "monitor/mainloop.h"
+
+struct timeout_data {
+ int id;
+ timeout_func_t func;
+ timeout_destroy_func_t destroy;
+ unsigned int timeout;
+ void *user_data;
+};
+
+static void timeout_callback(int id, void *user_data)
+{
+ struct timeout_data *data = user_data;
+
+ if (data->func(data->user_data) &&
+ !mainloop_modify_timeout(data->id, data->timeout))
+ return;
+
+ mainloop_remove_timeout(data->id);
+}
+
+static void timeout_destroy(void *user_data)
+{
+ struct timeout_data *data = user_data;
+
+ if (data->destroy)
+ data->destroy(data->user_data);
+
+ free(data);
+}
+
+int timeout_add(unsigned int t, timeout_func_t func, void *user_data,
+ timeout_destroy_func_t destroy)
+{
+ struct timeout_data *data = malloc(sizeof(*data));
+
+ data->func = func;
+ data->user_data = user_data;
+ data->timeout = t;
+
+ data->id = mainloop_add_timeout(t, timeout_callback, data,
+ timeout_destroy);
+ if (!data->id) {
+ free(data);
+ return 0;
+ }
+
+ return data->id;
+}
+
+void timeout_remove(unsigned int id)
+{
+ if (id)
+ mainloop_remove_timeout(id);
+}
--
1.8.4


2014-02-26 01:57:17

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 06/17] emulator: Minor style fix

---
emulator/btdev.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index c7231dd..c6bf96c 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -708,8 +708,8 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
ir.rssi = -60;
memcpy(ir.data, btdev_list[i]->ext_inquiry_rsp, 240);

- send_event(btdev, BT_HCI_EVT_EXT_INQUIRY_RESULT,
- &ir, sizeof(ir));
+ send_event(btdev, BT_HCI_EVT_EXT_INQUIRY_RESULT, &ir,
+ sizeof(ir));
continue;
}

@@ -737,8 +737,8 @@ static void inquiry_complete(struct btdev *btdev, uint8_t status)
memcpy(ir.dev_class, btdev_list[i]->dev_class, 3);
ir.clock_offset = 0x0000;

- send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT,
- &ir, sizeof(ir));
+ send_event(btdev, BT_HCI_EVT_INQUIRY_RESULT, &ir,
+ sizeof(ir));
}
}

--
1.8.4


2014-02-26 01:57:25

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 14/17] android/tester: Increase timeout for test failure

Inquiry command is sent with inquiry lenght 10.24 sec. There are
testcases where that time is needed to end the test, therefore change
timeout to 12 sec (number choosed based on strong feelings ;))
---
android/android-tester.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index 65516c1..b09834a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3707,7 +3707,7 @@ static void test_hidhost_get_report(const void *test_data)
user->test_data = data; \
tester_add_full(name, data, test_pre_setup, test_setup, \
test, test_teardown, test_post_teardown, \
- 3, user, g_free); \
+ 12, user, g_free); \
} while (0)

int main(int argc, char *argv[])
--
1.8.4


2014-02-26 01:57:23

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 12/17] android/tester: Add discovery cancel test

This test a scenario:
1. Start discovery (99 remote devices)
2. Cancel discovery after 11 inquiry results

Test pass if cancel inquiry command hits btdev before all 50 remote
devices is found
---
android/android-tester.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 111 insertions(+)

diff --git a/android/android-tester.c b/android/android-tester.c
index 6d5638e..c6484bf 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -56,6 +56,8 @@ struct generic_data {
bt_callbacks_t expected_hal_cb;
struct priority_property *expected_properties;
uint8_t expected_properties_num;
+ uint8_t set_num_of_remote;
+ int expected_device_found_num;
};

struct socket_data {
@@ -408,6 +410,13 @@ static void index_removed_callback(uint16_t index, uint16_t length,
tester_post_teardown_complete();
}

+static void enable_and_set_discoverable(gpointer data, gpointer user_data)
+{
+ struct bthost *bthost = ((struct remote_dev *)data)->bthost;
+ bthost_start(bthost);
+ bthost_write_scan_enable(bthost, 0x03);
+}
+
static void read_index_list_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -643,6 +652,26 @@ static void discovery_stop_success_cb(bt_discovery_state_t state)
}
}

+static void discovery_cancel_state_changed_cb(bt_discovery_state_t state)
+{
+ struct test_data *data = tester_get_data();
+
+ if (state == BT_DISCOVERY_STARTED) {
+ data->cb_count--;
+ return;
+ }
+
+ if (state == BT_DISCOVERY_STOPPED)
+ data->cb_count--;
+
+ if (data->cb_count) {
+ tester_test_failed();
+ return;
+ }
+
+ tester_test_passed();
+}
+
static void discovery_device_found_state_changed_cb(bt_discovery_state_t state)
{
struct test_data *data = tester_get_data();
@@ -695,6 +724,28 @@ static void discovery_state_changed_cb(bt_discovery_state_t state)
}
}

+static void device_found_cancel_cb(int num_properties,
+ bt_property_t *properties)
+{
+ struct test_data *data = tester_get_data();
+ const struct generic_data *test = data->test_data;
+ static int num_resp;
+ int triger_cancel = 11;
+
+ if (num_resp > test->expected_device_found_num)
+ return;
+
+ /* Increase cb_count if we reach bad amount of found devices*/
+ if (num_resp++ == test->expected_device_found_num)
+ data->cb_count++;
+
+ /* It is time to issue cancel discovery */
+ if (num_resp == triger_cancel) {
+ data->cb_count--;
+ data->if_bluetooth->cancel_discovery();
+ }
+}
+
static void discovery_device_found_cb(int num_properties,
bt_property_t *properties)
{
@@ -1362,6 +1413,16 @@ static const struct generic_data bluetooth_discovery_device_found_test = {
.expected_adapter_status = BT_STATUS_NOT_EXPECTED,
};

+static const struct generic_data bluetooth_discovery_cancel_test = {
+ .expected_hal_cb.discovery_state_changed_cb =
+ discovery_cancel_state_changed_cb,
+ .expected_hal_cb.device_found_cb = device_found_cancel_cb,
+ .set_num_of_remote = 98,
+ .expected_device_found_num = 50,
+ .expected_cb_count = 4,
+ .expected_adapter_status = BT_STATUS_NOT_EXPECTED,
+};
+
static char remote_get_properties_bdname_val[] = "00:AA:01:01:00:00";
static uint32_t remote_get_properties_cod_val = 0;
static bt_device_type_t remote_get_properties_tod_val = BT_DEVICE_DEVTYPE_BREDR;
@@ -2052,6 +2113,25 @@ static void setup_enabled_adapter(const void *test_data)
tester_setup_failed();
}

+static void setup_enable_adapter_add_remote(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct generic_data *test = test_data;
+ GList *l;
+ int i;
+
+ /* Setup some more remote devices if needed */
+ i = hciemu_add_remote_devs(data->hciemu, test->set_num_of_remote);
+ if (i != test->set_num_of_remote)
+ tester_setup_failed();
+
+ tester_print("Created %d remote devices", i);
+ l = hciemu_get_remote_devs(data->hciemu);
+ g_list_foreach(l, enable_and_set_discoverable, NULL);
+
+ setup_enabled_adapter(test_data);
+}
+
static void teardown(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -2406,6 +2486,18 @@ static bool pre_inq_compl_hook(const void *dummy, uint16_t len, void *user_data)
return false;
}

+static bool post_inq_cancel_hook(const void *dummy, uint16_t len,
+ void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ hciemu_del_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
+ BT_HCI_CMD_INQUIRY_CANCEL);
+
+ data->cb_count--;
+ return true;
+}
+
static void test_discovery_stop_success(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -2430,6 +2522,20 @@ static void test_discovery_start_done(const void *test_data)
data->if_bluetooth->start_discovery();
}

+static void test_discovery_device_cancel(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ init_test_conditions(data);
+
+ /* Need this hook to check if inquiry cancel reached btdev */
+ hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
+ BT_HCI_CMD_INQUIRY_CANCEL,
+ post_inq_cancel_hook, data);
+
+ data->if_bluetooth->start_discovery();
+}
+
static void test_discovery_device_found(const void *test_data)
{
struct test_data *data = tester_get_data();
@@ -3764,6 +3870,11 @@ int main(int argc, char *argv[])
setup_enabled_adapter,
test_discovery_device_found, teardown);

+ test_bredrle("Bluetooth BR/EDR Discovery Cancel",
+ &bluetooth_discovery_cancel_test,
+ setup_enable_adapter_add_remote,
+ test_discovery_device_cancel, teardown);
+
test_bredrle("Bluetooth Device Get Props - Success",
&bt_dev_getprops_success_test,
setup_enabled_adapter,
--
1.8.4


2014-02-26 01:57:26

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 15/17] android: Add tracking for pending confirm name command

This is usefull in case we want to cancel discovery during
big inflow on device found events.
---
android/bluetooth.c | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 7f37590..e0bc730 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -96,6 +96,8 @@ struct device {
GSList *uuids;

bool found; /* if device is found in current discovery session */
+ unsigned int confirm_id; /* mgtm command id if command pending */
+
};

struct browse_req {
@@ -315,6 +317,9 @@ static struct device *find_device(const bdaddr_t *bdaddr)

static void free_device(struct device *dev)
{
+ if (dev->confirm_id)
+ mgmt_cancel(mgmt_if, dev->confirm_id);
+
g_free(dev->name);
g_free(dev->friendly_name);
g_slist_free_full(dev->uuids, g_free);
@@ -1020,10 +1025,24 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
HAL_EV_DISCOVERY_STATE_CHANGED, sizeof(cp), &cp);
}

-static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
+static void confirm_device_name_cb(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_confirm_name *rp = param;
+ struct device *dev;
+
+ dev = find_device(&rp->addr.bdaddr);
+ if (!dev)
+ return;
+
+ dev->confirm_id = 0;
+}
+
+static unsigned int confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
bool resolve_name)
{
struct mgmt_cp_confirm_name cp;
+ unsigned int res;

memset(&cp, 0, sizeof(cp));
bacpy(&cp.addr.bdaddr, addr);
@@ -1032,9 +1051,13 @@ static void confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
if (!resolve_name)
cp.name_known = 1;

- if (mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
- sizeof(cp), &cp, NULL, NULL, NULL) == 0)
+ res = mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
+ sizeof(cp), &cp, confirm_device_name_cb,
+ NULL, NULL);
+ if (!res)
error("Failed to send confirm name request");
+
+ return res;
}

static int fill_hal_prop(void *buf, uint8_t type, uint16_t len,
@@ -1204,7 +1227,8 @@ static void update_found_device(const bdaddr_t *bdaddr, uint8_t bdaddr_type,

info("Device %s needs name confirmation (resolve_name=%d)",
addr, resolve_name);
- confirm_device_name(bdaddr, bdaddr_type, resolve_name);
+ dev->confirm_id = confirm_device_name(bdaddr, bdaddr_type,
+ resolve_name);
}
}

--
1.8.4


2014-02-26 01:57:28

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 17/17] android: Send confirm name request with mgmt_send

This patch is needed in scenarios when there is a big inflow of device found
events and we want to cancel discovery. In such case number of confirm
name commands might block mgmt queses and don't let stop discovery to pass
thru.

Even we cancel previous confirm name commands, stop discovery might
still get on the end of line.
---
android/bluetooth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index fb33976..5cb0e78 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1051,7 +1051,7 @@ static unsigned int confirm_device_name(const bdaddr_t *addr, uint8_t addr_type,
if (!resolve_name)
cp.name_known = 1;

- res = mgmt_reply(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
+ res = mgmt_send(mgmt_if, MGMT_OP_CONFIRM_NAME, adapter.index,
sizeof(cp), &cp, confirm_device_name_cb,
NULL, NULL);
if (!res)
--
1.8.4


2014-02-26 01:57:27

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 16/17] android: Cancel all pending confirm name before stop discovery

Make sure there is nothing outstdanign related to discovery before
sending stop discovery.

It is also in order to make sure that stop discovery have a free way to
get the kernel.
---
android/bluetooth.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index e0bc730..fb33976 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -2456,6 +2456,14 @@ static bool start_discovery(void)
return false;
}

+static void cancel_pending_confirm_name(gpointer data, gpointer user_data)
+{
+ struct device *dev = data;
+
+ mgmt_cancel(mgmt_if, dev->confirm_id);
+ dev->confirm_id = 0;
+}
+
static bool stop_discovery(void)
{
struct mgmt_cp_stop_discovery cp;
@@ -2468,6 +2476,9 @@ static bool stop_discovery(void)

DBG("type=0x%x", type);

+ /* Lets drop all confirm name request as we don't need it anymore */
+ g_slist_foreach(cached_devices, cancel_pending_confirm_name, NULL);
+
if (mgmt_send(mgmt_if, MGMT_OP_STOP_DISCOVERY, adapter.index,
sizeof(cp), &cp, NULL, NULL, NULL) > 0)
return true;
--
1.8.4


2014-02-26 01:57:22

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 11/17] emulator: Add support to create many remote devices in hciemu

This patch adds possibility to add more remote devices
---
emulator/btdev.c | 2 +-
src/shared/hciemu.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/shared/hciemu.h | 11 ++++++++++
3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index bf0c9d2..1be3ba1 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -137,7 +137,7 @@ struct inquiry_data {

#define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */

-#define MAX_BTDEV_ENTRIES 16
+#define MAX_BTDEV_ENTRIES 100


static const uint8_t LINK_KEY_NONE[16] = { 0 };
diff --git a/src/shared/hciemu.c b/src/shared/hciemu.c
index 6c93005..c40f71e 100644
--- a/src/shared/hciemu.c
+++ b/src/shared/hciemu.c
@@ -57,6 +57,7 @@ struct hciemu {
guint client_source;
struct queue *post_command_hooks;
char bdaddr_str[18];
+ GList *remote_devs;
};

struct hciemu_command_hook {
@@ -358,6 +359,18 @@ struct hciemu *hciemu_ref(struct hciemu *hciemu)
return hciemu;
}

+static void destroy_remotes(struct remote_dev *r)
+{
+ bthost_stop(r->bthost);
+
+ g_source_remove(r->client_source);
+ g_source_remove(r->host_source);
+
+ bthost_destroy(r->bthost);
+ btdev_destroy(r->btdev);
+ g_free(r);
+}
+
void hciemu_unref(struct hciemu *hciemu)
{
if (!hciemu)
@@ -378,6 +391,8 @@ void hciemu_unref(struct hciemu *hciemu)
btdev_destroy(hciemu->client_dev);
btdev_destroy(hciemu->master_dev);

+ g_list_free_full(hciemu->remote_devs, (GDestroyNotify)destroy_remotes);
+
free(hciemu);
}

@@ -498,3 +513,51 @@ bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,

return btdev_del_hook(hciemu->master_dev, hook_type, opcode);
}
+
+int hciemu_add_remote_devs(struct hciemu *hciemu, int number_of_devices)
+{
+ int i;
+
+ for (i = 0; i < number_of_devices; i++) {
+ struct remote_dev *r;
+ struct btdev *btdev;
+ struct bthost *bthost;
+ int sv[2];
+
+ btdev = btdev_create(hciemu->btdev_type, 0x00);
+ if (!btdev)
+ break;
+
+ bthost = bthost_create();
+ if (!bthost) {
+ btdev_destroy(btdev);
+ break;
+ }
+
+ btdev_set_command_handler(btdev, client_command_callback,
+ hciemu);
+
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK |
+ SOCK_CLOEXEC, 0, sv) < 0) {
+ bthost_destroy(bthost);
+ btdev_destroy(btdev);
+ break;
+ }
+
+ r = g_malloc(sizeof(*r));
+ r->btdev = btdev;
+ r->bthost = bthost;
+
+ r->client_source = create_source_btdev(sv[0], btdev);
+ r->host_source = create_source_bthost(sv[1], bthost);
+
+ hciemu->remote_devs = g_list_prepend(hciemu->remote_devs, r);
+ }
+
+ return i;
+}
+
+GList *hciemu_get_remote_devs(struct hciemu *hciemu)
+{
+ return hciemu->remote_devs;
+}
diff --git a/src/shared/hciemu.h b/src/shared/hciemu.h
index d948867..52dee23 100644
--- a/src/shared/hciemu.h
+++ b/src/shared/hciemu.h
@@ -26,6 +26,13 @@

struct hciemu;

+struct remote_dev {
+ struct btdev *btdev;
+ struct bthost *bthost;
+ guint client_source;
+ guint host_source;
+};
+
enum hciemu_type {
HCIEMU_TYPE_BREDRLE,
HCIEMU_TYPE_BREDR,
@@ -67,3 +74,7 @@ int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,

bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
uint16_t opcode);
+
+int hciemu_add_remote_devs(struct hciemu *hciemu, int number_of_devices);
+
+GList *hciemu_get_remote_devs(struct hciemu *hciemu);
--
1.8.4


2014-02-26 01:57:21

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 10/17] emulator: Add handling inquiry_lenght from inquiry command

---
emulator/btdev.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index c74258b..bf0c9d2 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -129,8 +129,10 @@ struct btdev {
struct inquiry_data {
struct btdev *btdev;
int num_resp;
+ int max_iter; /* Calculated from inquiry_lenght */

int sent_count;
+ int iter;
};

#define DEFAULT_INQUIRY_INTERVAL 2 /* 2 miliseconds */
@@ -778,8 +780,12 @@ static bool inquiry_callback(void *user_data)
if (data->num_resp && data->sent_count == data->num_resp)
goto finish;

+ /* Check if we already spent as much time as required */
+ if (data->max_iter && data->iter++ == data->max_iter)
+ goto finish;
+
if (i == MAX_BTDEV_ENTRIES) {
- if (!data->num_resp)
+ if (!data->max_iter && !data->num_resp)
goto finish;

/* Reset main iterator so we can start iterate btdev_list
@@ -826,6 +832,7 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
const struct bt_hci_cmd_inquiry *inq_cmd = cmd;
struct inquiry_data *data;
struct bt_hci_evt_inquiry_complete ic;
+ unsigned int inquiry_len_ms = 128 * inq_cmd->length;

if (btdev->inquiry_id)
return;
@@ -838,6 +845,9 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)
data->btdev = btdev;
data->num_resp = inq_cmd->num_resp;

+ if (inquiry_len_ms)
+ data->max_iter = inquiry_len_ms / DEFAULT_INQUIRY_INTERVAL;
+
btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
inquiry_callback, data, inquiry_destroy);
/* Return if success */
--
1.8.4


2014-02-26 01:57:24

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 13/17] android/tester: Remove not needed hook for inquiry complete

Inquiry is scheduled with timeout so there is no need to hook
before inquiry complete. It influence those tests cases:
"Bluetooth BR/EDR Discovery Start - Success".
"Bluetooth BR/EDR Discovery Stop - Success".
---
android/android-tester.c | 17 -----------------
1 file changed, 17 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index c6484bf..65516c1 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -2475,17 +2475,6 @@ static void test_discovery_stop_done(const void *test_data)
check_expected_status(status);
}

-static bool pre_inq_compl_hook(const void *dummy, uint16_t len, void *user_data)
-{
- struct test_data *data = tester_get_data();
-
- /* Make sure Inquiry Command Complete is not called */
-
- hciemu_del_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT, BT_HCI_CMD_INQUIRY);
-
- return false;
-}
-
static bool post_inq_cancel_hook(const void *dummy, uint16_t len,
void *user_data)
{
@@ -2504,9 +2493,6 @@ static void test_discovery_stop_success(const void *test_data)

init_test_conditions(data);

- hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT, BT_HCI_CMD_INQUIRY,
- pre_inq_compl_hook, data);
-
data->if_bluetooth->start_discovery();
}

@@ -2516,9 +2502,6 @@ static void test_discovery_start_done(const void *test_data)

init_test_conditions(data);

- hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT, BT_HCI_CMD_INQUIRY,
- pre_inq_compl_hook, data);
-
data->if_bluetooth->start_discovery();
}

--
1.8.4


2014-02-26 01:57:13

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 02/17] monitor: Use miliseconds instead of seconds in the timeout

---
monitor/mainloop.c | 19 ++++++++++---------
monitor/mainloop.h | 4 ++--
tools/3dsp.c | 2 +-
tools/btinfo.c | 2 +-
4 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/monitor/mainloop.c b/monitor/mainloop.c
index 7f97e65..8d4b391 100644
--- a/monitor/mainloop.c
+++ b/monitor/mainloop.c
@@ -287,20 +287,21 @@ static void timeout_callback(int fd, uint32_t events, void *user_data)
data->callback(data->fd, data->user_data);
}

-static inline int timeout_set(int fd, unsigned int seconds)
+static inline int timeout_set(int fd, unsigned int msec)
{
struct itimerspec itimer;
+ unsigned int sec = msec / 1000;

memset(&itimer, 0, sizeof(itimer));
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_nsec = 0;
- itimer.it_value.tv_sec = seconds;
- itimer.it_value.tv_nsec = 0;
+ itimer.it_value.tv_sec = sec;
+ itimer.it_value.tv_nsec = (msec - (sec * 1000)) * 1000;

return timerfd_settime(fd, 0, &itimer, NULL);
}

-int mainloop_add_timeout(unsigned int seconds, mainloop_timeout_func callback,
+int mainloop_add_timeout(unsigned int msec, mainloop_timeout_func callback,
void *user_data, mainloop_destroy_func destroy)
{
struct timeout_data *data;
@@ -323,8 +324,8 @@ int mainloop_add_timeout(unsigned int seconds, mainloop_timeout_func callback,
return -EIO;
}

- if (seconds > 0) {
- if (timeout_set(data->fd, seconds) < 0) {
+ if (msec > 0) {
+ if (timeout_set(data->fd, msec) < 0) {
close(data->fd);
free(data);
return -EIO;
@@ -341,10 +342,10 @@ int mainloop_add_timeout(unsigned int seconds, mainloop_timeout_func callback,
return data->fd;
}

-int mainloop_modify_timeout(int id, unsigned int seconds)
+int mainloop_modify_timeout(int id, unsigned int msec)
{
- if (seconds > 0) {
- if (timeout_set(id, seconds) < 0)
+ if (msec > 0) {
+ if (timeout_set(id, msec) < 0)
return -EIO;
}

diff --git a/monitor/mainloop.h b/monitor/mainloop.h
index d36f5aa..dafec8b 100644
--- a/monitor/mainloop.h
+++ b/monitor/mainloop.h
@@ -40,9 +40,9 @@ int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
int mainloop_modify_fd(int fd, uint32_t events);
int mainloop_remove_fd(int fd);

-int mainloop_add_timeout(unsigned int seconds, mainloop_timeout_func callback,
+int mainloop_add_timeout(unsigned int msec, mainloop_timeout_func callback,
void *user_data, mainloop_destroy_func destroy);
-int mainloop_modify_timeout(int fd, unsigned int seconds);
+int mainloop_modify_timeout(int fd, unsigned int msec);
int mainloop_remove_timeout(int id);

int mainloop_set_signal(sigset_t *mask, mainloop_signal_func callback,
diff --git a/tools/3dsp.c b/tools/3dsp.c
index d1b17f2..fc5c8e6 100644
--- a/tools/3dsp.c
+++ b/tools/3dsp.c
@@ -66,7 +66,7 @@ static void shutdown_device(void)
bt_hci_flush(hci_dev);

if (reset_on_shutdown) {
- id = mainloop_add_timeout(5, shutdown_timeout, NULL, NULL);
+ id = mainloop_add_timeout(5000, shutdown_timeout, NULL, NULL);

bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0,
shutdown_complete, UINT_TO_PTR(id), NULL);
diff --git a/tools/btinfo.c b/tools/btinfo.c
index 7951808..6693132 100644
--- a/tools/btinfo.c
+++ b/tools/btinfo.c
@@ -109,7 +109,7 @@ static void shutdown_device(void)
bt_hci_flush(hci_dev);

if (reset_on_shutdown) {
- id = mainloop_add_timeout(5, shutdown_timeout, NULL, NULL);
+ id = mainloop_add_timeout(5000, shutdown_timeout, NULL, NULL);

bt_hci_send(hci_dev, BT_HCI_CMD_RESET, NULL, 0,
shutdown_complete, UINT_TO_PTR(id), NULL);
--
1.8.4


2014-02-26 01:57:19

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 08/17] emulator: Add inquiry cancel

---
emulator/btdev.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 18f7410..722c312 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -70,6 +70,7 @@ struct btdev {
void *send_data;

int inquiry_id;
+ bool inquiry_cancel;

struct hook *hook_list[MAX_HOOK_ENTRIES];

@@ -789,10 +790,20 @@ static bool inquiry_callback(void *user_data)
static void inquiry_destroy(void *user_data)
{
struct inquiry_data *data = user_data;
+ struct btdev *btdev = data->btdev;
+ uint8_t status = BT_HCI_ERR_SUCCESS;
+
+ if (!btdev)
+ goto finish;
+
+ if (btdev->inquiry_cancel)
+ cmd_complete(btdev, BT_HCI_CMD_INQUIRY_CANCEL, &status,
+ sizeof(status));

- if (data->btdev)
- data->btdev->inquiry_id = 0;
+ btdev->inquiry_cancel = false;
+ btdev->inquiry_id = 0;

+finish:
free(data);
}

@@ -822,6 +833,19 @@ error:
send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
}

+static void inquiry_cancel(struct btdev *btdev)
+{
+ uint8_t status = BT_HCI_ERR_COMMAND_DISALLOWED;
+
+ if (btdev->inquiry_id) {
+ btdev->inquiry_cancel = true;
+ timeout_remove(btdev->inquiry_id);
+ btdev->inquiry_id = 0;
+ return;
+ }
+
+ cmd_complete(btdev, BT_HCI_CMD_INQUIRY_CANCEL, &status, sizeof(status));
+}
static void conn_complete(struct btdev *btdev,
const uint8_t *bdaddr, uint8_t status)
{
@@ -1638,8 +1662,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
case BT_HCI_CMD_INQUIRY_CANCEL:
if (btdev->type == BTDEV_TYPE_LE)
goto unsupported;
- status = BT_HCI_ERR_SUCCESS;
- cmd_complete(btdev, opcode, &status, sizeof(status));
+ inquiry_cancel(btdev);
break;

case BT_HCI_CMD_CREATE_CONN:
--
1.8.4


2014-02-26 01:57:20

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 09/17] emulator: Add handling inquiry number of responses

Conflicts:
emulator/btdev.c

Conflicts:
emulator/btdev.c
---
emulator/btdev.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 722c312..c74258b 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -128,6 +128,8 @@ struct btdev {

struct inquiry_data {
struct btdev *btdev;
+ int num_resp;
+
int sent_count;
};

@@ -703,6 +705,7 @@ static bool inquiry_callback(void *user_data)
{
struct inquiry_data *data = user_data;
struct btdev *btdev = data->btdev;
+ struct bt_hci_evt_inquiry_complete ic;
static int j;
int sent = data->sent_count;
int i;
@@ -771,20 +774,31 @@ static bool inquiry_callback(void *user_data)
}
}

- if (i == MAX_BTDEV_ENTRIES) {
- struct bt_hci_evt_inquiry_complete ic;
+ /* Check if we sent already required amount of responses*/
+ if (data->num_resp && data->sent_count == data->num_resp)
+ goto finish;

- ic.status = BT_HCI_ERR_SUCCESS;
- send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
+ if (i == MAX_BTDEV_ENTRIES) {
+ if (!data->num_resp)
+ goto finish;

- /* reset */
- btdev->inquiry_id = 0;
+ /* Reset main iterator so we can start iterate btdev_list
+ * from the beggining */
j = 0;
-
- return false;
}

return true;
+
+finish:
+ /* Note that destroy will be called */
+ ic.status = BT_HCI_ERR_SUCCESS;
+ send_event(btdev, BT_HCI_EVT_INQUIRY_COMPLETE, &ic, sizeof(ic));
+
+ /* reset */
+ btdev->inquiry_id = 0;
+ j = 0;
+
+ return false;
}

static void inquiry_destroy(void *user_data)
@@ -809,6 +823,7 @@ finish:

static void inquiry_cmd(struct btdev *btdev, const void *cmd)
{
+ const struct bt_hci_cmd_inquiry *inq_cmd = cmd;
struct inquiry_data *data;
struct bt_hci_evt_inquiry_complete ic;

@@ -821,6 +836,7 @@ static void inquiry_cmd(struct btdev *btdev, const void *cmd)

memset(data, 0, sizeof(*data));
data->btdev = btdev;
+ data->num_resp = inq_cmd->num_resp;

btdev->inquiry_id = timeout_add(DEFAULT_INQUIRY_INTERVAL,
inquiry_callback, data, inquiry_destroy);
--
1.8.4


2014-02-26 01:57:14

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 03/17] shared: Add header for timeout abstraction

---
src/shared/timeout.h | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 src/shared/timeout.h

diff --git a/src/shared/timeout.h b/src/shared/timeout.h
new file mode 100644
index 0000000..c13616f
--- /dev/null
+++ b/src/shared/timeout.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 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.
+ *
+ */
+
+#include <stdbool.h>
+
+typedef bool (*timeout_func_t)(void *user_data);
+typedef void (*timeout_destroy_func_t)(void *user_data);
+
+int timeout_add(unsigned int msec, timeout_func_t func, void *user_data,
+ timeout_destroy_func_t destroy);
+void timeout_remove(unsigned int id);
--
1.8.4


2014-02-26 01:57:15

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 04/17] shared: Add timeout handling with Glib support

---
src/shared/timeout-glib.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 src/shared/timeout-glib.c

diff --git a/src/shared/timeout-glib.c b/src/shared/timeout-glib.c
new file mode 100644
index 0000000..c045efc
--- /dev/null
+++ b/src/shared/timeout-glib.c
@@ -0,0 +1,73 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 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.
+ *
+ */
+
+#include "timeout.h"
+
+#include <glib.h>
+
+struct timeout_data {
+ timeout_func_t func;
+ timeout_destroy_func_t destroy;
+ void *user_data;
+};
+
+static gboolean timeout_callback(gpointer user_data)
+{
+ struct timeout_data *data = user_data;
+
+ if (data->func(data->user_data))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void timeout_destroy(gpointer user_data)
+{
+ struct timeout_data *data = user_data;
+
+ if (data->destroy)
+ data->destroy(data->user_data);
+
+ g_free(data);
+}
+
+int timeout_add(unsigned int ms, timeout_func_t func, void *user_data,
+ timeout_destroy_func_t destroy)
+{
+ guint id;
+ struct timeout_data *data = g_malloc0(sizeof(*data));
+
+ data->func = func;
+ data->destroy = destroy;
+ data->user_data = user_data;
+
+ id = g_timeout_add_full(G_PRIORITY_DEFAULT, ms, timeout_callback, data,
+ timeout_destroy);
+ if (!id)
+ g_free(data);
+
+ return id;
+}
+
+void timeout_remove(unsigned int id)
+{
+ GSource *source = g_main_context_find_source_by_id(NULL, id);
+ if (source)
+ g_source_destroy(source);
+}
--
1.8.4


2014-02-26 01:57:12

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 01/17] monitor: Allow to modify epoll even events are the same

This is epsecially needed when we want to modify timer.
---
monitor/mainloop.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/monitor/mainloop.c b/monitor/mainloop.c
index 8c94bfe..7f97e65 100644
--- a/monitor/mainloop.c
+++ b/monitor/mainloop.c
@@ -222,9 +222,6 @@ int mainloop_modify_fd(int fd, uint32_t events)
if (!data)
return -ENXIO;

- if (data->events == events)
- return 0;
-
memset(&ev, 0, sizeof(ev));
ev.events = events;
ev.data.ptr = data;
--
1.8.4