summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/apps/blestress
diff options
context:
space:
mode:
authorJF <jf@codingfield.com>2020-04-26 10:25:59 +0200
committerJF <jf@codingfield.com>2020-04-26 10:25:59 +0200
commitbdc10744fb338ae197692713a0b48a7ccc36f566 (patch)
treeaf7a8f2f16ddd2e5483758effec15c7683f6c453 /src/libs/mynewt-nimble/apps/blestress
parent032fad094c6411ad3ff4321ad61ceed95d7dc4ff (diff)
Add Nimble in libs directory
Diffstat (limited to 'src/libs/mynewt-nimble/apps/blestress')
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/README.md201
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/pkg.yml39
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/main.c99
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/misc.c224
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/misc.h54
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c1471
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/rx_stress.h53
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/stress.c389
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/stress.h375
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.c155
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.h54
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c1671
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/src/tx_stress.h49
-rw-r--r--src/libs/mynewt-nimble/apps/blestress/syscfg.yml74
14 files changed, 4908 insertions, 0 deletions
diff --git a/src/libs/mynewt-nimble/apps/blestress/README.md b/src/libs/mynewt-nimble/apps/blestress/README.md
new file mode 100644
index 00000000..8524397a
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/README.md
@@ -0,0 +1,201 @@
+BLE Stress Tests
+
+******************************************************************************
+ QUICK TIPS:
+ You need 2 controllers supported by MyNewt. One will become TX device,
+ the other will become RX device.
+
+ 1. Set role (TX=0, RX=1) for current device in syscfg.yml
+ BLE_STRESS_TEST_ROLE: 1
+
+ The RX has LED2 turned on.
+
+ 2. Set (in syscfg.yml) number of times to repeat each tested action
+ in use case, e.g. do 1000 times connect/disconnect to complete use case.
+ RX_STRESS_REPEAT: 1000
+
+ 3. To perform only specific test, go to rx_stress.c,
+ find definition of rx_stress_main_task_fn(void *arg) and in place of
+ for-loop just paste function rx_stress_start(i), where i is id of test.
+
+******************************************************************************
+
+No | Use case
+-----------------------------------------------------------------------------
+ 1 | Stress Connect -> Connect Cancel - repeat 1000
+ | RX: Nothing
+ | TX: Connect/Connect cancel
+ |
+ 2 | Stress Connect/Disconnect legacy - repeat 1000
+ | RX: Advertise legacy
+ | TX: Connect/Disconnect
+ |
+ 3 | Stress Connect/Disconnect ext adv - repeat 1000
+ | RX: Advertise Ext
+ | TX: Connect/Disconnect
+ |
+ 4 | Stress connection params update (TX) - (1000)
+ | RX: Advertise
+ | TX: Connect/Connect param update
+ |
+ 5 | Stress connection params update (RX) - (1000)
+ | RX: Advertise/Connect param update
+ | TX: Connect
+ |
+ 6 | Stress Scan
+ | RX: Advertise a known data pattern
+ | TX: Scan and check received data with pattern
+ |
+ 7 | Stress PHY Update (TX) - (1000)
+ | RX: Advertise
+ | TX: Connect/Phy update
+ |
+ 8 | Stress PHY update (RX) - (1000)
+ | RX: Advertise/Phy update
+ | TX: Connect
+ |
+ 9 | Stress multi connection
+ | RX: Advertise Ext
+ | TX: Establish and maintain as many instances as possible
+ |
+10 | Stress L2CAP send
+ | RX: Send 64kB of data with L2CAP
+ | TX: Measure bit rate and max received data MTU
+ |
+11 | Stress Advertise/Connect/Continue Adv/Disconnect
+ | RX: Advertise Ext/Continue same advertise after connect
+ | TX: Connect
+ |
+12 | Stress GATT indicating
+ | RX: Indicate
+ | TX: Receive indication. Measure average time of indicating.
+ |
+13 | Stress GATT notification
+ | RX: Notify. Measure average time of notifying.
+ | TX: Count the number of received notification.
+ |
+14 | Stress GATT Subscribe/Notify/Unsubscribe
+ | RX: Notify on subscribe
+ | TX: Measure the average time from sending a subscription request
+ | to receiving a notification.
+ |
+15 | Stress Connect/Send/Disconnect
+ | RX: Advertise/Send via ATT/Disconnect
+ | TX: Receive notification. Measure time of notifying.
+
+******************************************************************************
+ Concept:
+ The RX device advertises data containing a UUID128 of test use case that
+ should be performed. The TX device scan for known UUIDs, when it finds,
+ adapts to the advertised use case and runs a test.
+
+ Stress Task vs Semaphore:
+ The rx_stress_start_auto function starts main stress test task that runs
+ all stress tests one by one. The tests are based on event handling, so to
+ synchronize main task with events, a semaphore is used. On use case start
+ there is 0 tokens for semaphore. After main task starts one of use cases,
+ it comes across a semaphore and has to wait. When use case is completed,
+ 1 token is released, so main task can use it to pass through semaphore.
+ The tx_stress_start_auto function works analogically.
+
+
+ Newt target set example:
+ rymek@rymek:~/projects/bletiny_proj$ newt target show bletest_tx
+ targets/bletest_tx
+ app=@apache-mynewt-nimble/apps/blestress
+ bsp=@apache-mynewt-core/hw/bsp/nordic_pca10056
+ build_profile=debug
+ syscfg=BLE_STRESS_TEST_ROLE=0
+ rymek@rymek:~/projects/bletiny_proj$ newt target show bletest_rx
+ targets/bletest_rx
+ app=@apache-mynewt-nimble/apps/blestress
+ bsp=@apache-mynewt-core/hw/bsp/nordic_pca10056
+ build_profile=debug
+ syscfg=BLE_STRESS_TEST_ROLE=1
+
+
+ Example of expected logs on TX side(LOG_LEVEL > 1):
+ Start test num 1
+ >>>>>>>>>>>>>>>>>>>> Stress test 1 completed
+ Start scan for test
+ Start test num 2
+ >>>>>>>>>>>>>>>>>>>> Stress test 2 completed
+ Start scan for test
+ Start test num 3
+ >>>>>>>>>>>>>>>>>>>> Stress test 3 completed
+ Start scan for test
+ Start test num 4
+ >>>>>>>>>>>>>>>>>>>> Stress test 4 completed
+ Start scan for test
+ Start test num 5
+ >>>>>>>>>>>>>>>>>>>> Stress test 5 completed
+ Start scan for test
+ Start test num 6
+ >>>>>>>>>>>>>>>>>>>> Stress test 6 completed
+ Start scan for test
+ Start test num 7
+ >>>>>>>>>>>>>>>>>>>> Stress test 7 completed
+ Start scan for test
+ Start test num 8
+ >>>>>>>>>>>>>>>>>>>> Stress test 8 completed
+ All tests completed
+ Tests results:
+ Use case 1 - Stress Connect -> Connect Cancel:
+ Con attempts = 20
+ Con success = 0
+ Use case 2 - Stress Connect/Disconnect legacy:
+ Con attempts = 20
+ Con success = 20
+ Use case 3 - Stress Connect/Disconnect ext adv:
+ Con attempts = 20
+ Con success = 20
+ Use case 4 - Stress connection params update (TX):
+ Params updates = 20
+ Use case 5 - Stress connection params update (RX):
+ Params updates = 20
+ Use case 6 - Stress Scan:
+ Received first packets = 20
+ Received all packets = 20
+ Use case 7 - Stress PHY Update (TX):
+ PHY updates = 20
+ Use case 8 - Stress Connect -> Connect Cancel:
+ PHY updates = 20
+
+
+ Example of expected logs on RX side(LOG_LEVEL > 1):
+ Start test num 2
+ >>>>>>>>>>>>>>>>>>>> Stress test 2 completed
+ Start test num 3
+ >>>>>>>>>>>>>>>>>>>> Stress test 3 completed
+ Start test num 4
+ >>>>>>>>>>>>>>>>>>>> Stress test 4 completed
+ Start test num 5
+ >>>>>>>>>>>>>>>>>>>> Stress test 5 completed
+ Start test num 6
+ Received signal to switch test
+ Start test num 7
+ >>>>>>>>>>>>>>>>>>>> Stress test 7 completed
+ Start test num 8
+ >>>>>>>>>>>>>>>>>>>> Stress test 8 completed
+ All tests completed
+ Tests results:
+ Use case 1 - Stress Connect -> Connect Cancel:
+ Con attempts = 0
+ Con success = 0
+ Use case 2 - Stress Connect/Disconnect legacy:
+ Con attempts = 20
+ Con success = 20
+ Use case 3 - Stress Connect/Disconnect ext adv:
+ Con attempts = 20
+ Con success = 20
+ Use case 4 - Stress connection params update (TX):
+ Params updates = 20
+ Use case 5 - Stress connection params update (RX):
+ Params updates = 20
+ Use case 6 - Stress Scan:
+ Received first packets = 0
+ Received all packets = 0
+ Use case 7 - Stress PHY Update (TX):
+ PHY updates = 20
+ Use case 8 - Stress Connect -> Connect Cancel:
+ PHY updates = 20
diff --git a/src/libs/mynewt-nimble/apps/blestress/pkg.yml b/src/libs/mynewt-nimble/apps/blestress/pkg.yml
new file mode 100644
index 00000000..da23ecb0
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/pkg.yml
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: "apps/blestress"
+pkg.type: app
+pkg.description: "Stress tests sample application."
+pkg.keywords:
+
+pkg.deps:
+ - "@mcuboot/boot/bootutil"
+ - "@apache-mynewt-core/sys/log/modlog"
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/sys/console/full"
+ - "@apache-mynewt-core/sys/log/full"
+ - "@apache-mynewt-core/sys/stats/full"
+ - "@apache-mynewt-core/sys/id"
+ - "@apache-mynewt-nimble/nimble/controller"
+ - "@apache-mynewt-nimble/nimble/host"
+ - "@apache-mynewt-nimble/nimble/host/util"
+ - "@apache-mynewt-nimble/nimble/host/services/gap"
+ - "@apache-mynewt-nimble/nimble/host/services/gatt"
+ - "@apache-mynewt-nimble/nimble/host/store/ram"
+ - "@apache-mynewt-nimble/nimble/transport/ram"
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/main.c b/src/libs/mynewt-nimble/apps/blestress/src/main.c
new file mode 100644
index 00000000..ec28ed8a
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/main.c
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include "os/mynewt.h"
+#include "config/config.h"
+#include "bsp.h"
+#include "hal/hal_gpio.h"
+
+/* BLE */
+#include "nimble/ble.h"
+#include "host/ble_hs.h"
+#include "host/util/util.h"
+#include "services/gap/ble_svc_gap.h"
+
+/* Application-specified header. */
+#include "rx_stress.h"
+#include "tx_stress.h"
+#include "stress_gatt.h"
+
+static void
+stress_test_on_reset(int reason)
+{
+ MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
+}
+
+static void
+stress_test_on_sync(void)
+{
+ int rc;
+
+ /* Make sure we have proper identity address set (public preferred) */
+ rc = ble_hs_util_ensure_addr(1);
+ assert(rc == 0);
+
+#if MYNEWT_VAL(BLE_STRESS_TEST_ROLE)
+ rx_stress_start_auto();
+#else
+ tx_stress_start_auto();
+#endif
+}
+
+/**
+ * main
+ *
+ * The main task for the project. This function initializes the packages,
+ * then starts serving events from default event queue.
+ *
+ * @return int NOTE: this function should never return!
+ */
+int
+main(void)
+{
+ int rc;
+
+ sysinit();
+
+ ble_hs_cfg.reset_cb = stress_test_on_reset;
+ ble_hs_cfg.sync_cb = stress_test_on_sync;
+ ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+ /* Please do not change name. Otherwise some tests could fail. */
+ rc = ble_svc_gap_device_name_set("STRESS");
+ assert(rc == 0);
+
+ conf_load();
+
+ rc = gatt_svr_init();
+ assert(rc == 0);
+
+#if MYNEWT_VAL(BLE_STRESS_TEST_ROLE)
+ /* RX device */
+ ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
+ hal_gpio_init_out(LED_2, 1);
+ hal_gpio_toggle(LED_2);
+#endif
+
+ while (1) {
+ os_eventq_run(os_eventq_dflt_get());
+ }
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/misc.c b/src/libs/mynewt-nimble/apps/blestress/src/misc.c
new file mode 100644
index 00000000..bd71a871
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/misc.c
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "misc.h"
+
+void
+rand_bytes(uint8_t *data, int len) {
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ data[i] = (uint8_t) rand() % UINT8_MAX;
+ }
+}
+
+/**
+ * Utility function to log an array of bytes.
+ */
+void
+print_bytes(const uint8_t *bytes, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ MODLOG_DFLT(DEBUG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
+ }
+}
+
+void
+print_addr(const void *addr)
+{
+ const uint8_t *u8p;
+
+ u8p = addr;
+ MODLOG_DFLT(DEBUG, "%02x:%02x:%02x:%02x:%02x:%02x",
+ u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
+}
+
+void
+print_mbuf(const struct os_mbuf *om)
+{
+ while (om != NULL) {
+ print_bytes(om->om_data, om->om_len);
+ om = SLIST_NEXT(om, om_next);
+
+ if(om == NULL) {
+ return;
+ }
+
+ /* Separate buf fields with colon to maintain continuity */
+ MODLOG_DFLT(DEBUG, ":");
+ }
+}
+
+char *
+addr_str(const void *addr)
+{
+ /* 6 bytes of MAC address * 2 signs for each byte in string + 5 colons to
+ * separate bytes + 1 byte for null-character appended by sprintf
+ */
+ static char buf[6 * 2 + 5 + 1];
+ const uint8_t *u8p;
+
+ u8p = addr;
+ sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
+
+ return buf;
+}
+
+void
+print_uuid(const ble_uuid_t *uuid)
+{
+ char buf[BLE_UUID_STR_LEN];
+
+ MODLOG_DFLT(DEBUG, "%s", ble_uuid_to_str(uuid, buf));
+}
+
+/**
+ * Logs information about a connection to the console.
+ */
+void
+print_conn_desc(const struct ble_gap_conn_desc *desc)
+{
+ MODLOG_DFLT(DEBUG, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ",
+ desc->conn_handle, desc->our_ota_addr.type,
+ addr_str(desc->our_ota_addr.val));
+ MODLOG_DFLT(DEBUG, "our_id_addr_type=%d our_id_addr=%s ",
+ desc->our_id_addr.type, addr_str(desc->our_id_addr.val));
+ MODLOG_DFLT(DEBUG, "peer_ota_addr_type=%d peer_ota_addr=%s ",
+ desc->peer_ota_addr.type, addr_str(desc->peer_ota_addr.val));
+ MODLOG_DFLT(DEBUG, "peer_id_addr_type=%d peer_id_addr=%s ",
+ desc->peer_id_addr.type, addr_str(desc->peer_id_addr.val));
+ MODLOG_DFLT(DEBUG, "conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+ "encrypted=%d authenticated=%d bonded=%d",
+ desc->conn_itvl, desc->conn_latency,
+ desc->supervision_timeout,
+ desc->sec_state.encrypted,
+ desc->sec_state.authenticated,
+ desc->sec_state.bonded);
+}
+
+void
+print_adv_fields(const struct ble_hs_adv_fields *fields)
+{
+ char s[BLE_HS_ADV_MAX_SZ];
+ const uint8_t *u8p;
+ int i;
+
+ if (fields->flags != 0) {
+ MODLOG_DFLT(DEBUG, " flags=0x%02x\n", fields->flags);
+ }
+
+ if (fields->uuids16 != NULL) {
+ MODLOG_DFLT(DEBUG, " uuids16(%scomplete)=",
+ fields->uuids16_is_complete ? "" : "in");
+ for (i = 0; i < fields->num_uuids16; i++) {
+ print_uuid(&fields->uuids16[i].u);
+ MODLOG_DFLT(DEBUG, " ");
+ }
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->uuids32 != NULL) {
+ MODLOG_DFLT(DEBUG, " uuids32(%scomplete)=",
+ fields->uuids32_is_complete ? "" : "in");
+ for (i = 0; i < fields->num_uuids32; i++) {
+ print_uuid(&fields->uuids32[i].u);
+ MODLOG_DFLT(DEBUG, " ");
+ }
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->uuids128 != NULL) {
+ MODLOG_DFLT(DEBUG, " uuids128(%scomplete)=",
+ fields->uuids128_is_complete ? "" : "in");
+ for (i = 0; i < fields->num_uuids128; i++) {
+ print_uuid(&fields->uuids128[i].u);
+ MODLOG_DFLT(DEBUG, " ");
+ }
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->name != NULL) {
+ assert(fields->name_len < sizeof s - 1);
+ memcpy(s, fields->name, fields->name_len);
+ s[fields->name_len] = '\0';
+ MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
+ fields->name_is_complete ? "" : "in", s);
+ }
+
+ if (fields->tx_pwr_lvl_is_present) {
+ MODLOG_DFLT(DEBUG, " tx_pwr_lvl=%d\n", fields->tx_pwr_lvl);
+ }
+
+ if (fields->slave_itvl_range != NULL) {
+ MODLOG_DFLT(DEBUG, " slave_itvl_range=");
+ print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->svc_data_uuid16 != NULL) {
+ MODLOG_DFLT(DEBUG, " svc_data_uuid16=");
+ print_bytes(fields->svc_data_uuid16, fields->svc_data_uuid16_len);
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->public_tgt_addr != NULL) {
+ MODLOG_DFLT(DEBUG, " public_tgt_addr=");
+ u8p = fields->public_tgt_addr;
+ for (i = 0; i < fields->num_public_tgt_addrs; i++) {
+ MODLOG_DFLT(DEBUG, "public_tgt_addr=%s ", addr_str(u8p));
+ u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
+ }
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->appearance_is_present) {
+ MODLOG_DFLT(DEBUG, " appearance=0x%04x\n", fields->appearance);
+ }
+
+ if (fields->adv_itvl_is_present) {
+ MODLOG_DFLT(DEBUG, " adv_itvl=0x%04x\n", fields->adv_itvl);
+ }
+
+ if (fields->svc_data_uuid32 != NULL) {
+ MODLOG_DFLT(DEBUG, " svc_data_uuid32=");
+ print_bytes(fields->svc_data_uuid32, fields->svc_data_uuid32_len);
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->svc_data_uuid128 != NULL) {
+ MODLOG_DFLT(DEBUG, " svc_data_uuid128=");
+ print_bytes(fields->svc_data_uuid128, fields->svc_data_uuid128_len);
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->uri != NULL) {
+ MODLOG_DFLT(DEBUG, " uri=");
+ print_bytes(fields->uri, fields->uri_len);
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+
+ if (fields->mfg_data != NULL) {
+ MODLOG_DFLT(DEBUG, " mfg_data=");
+ print_bytes(fields->mfg_data, fields->mfg_data_len);
+ MODLOG_DFLT(DEBUG, "\n");
+ }
+}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/misc.h b/src/libs/mynewt-nimble/apps/blestress/src/misc.h
new file mode 100644
index 00000000..39e5e737
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/misc.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef BLE_TGT_MISC_H
+#define BLE_TGT_MISC_H
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "host/ble_hs_adv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void rand_bytes(uint8_t *data, int len);
+
+void print_bytes(const uint8_t *bytes, int len);
+
+void print_addr(const void *addr);
+
+void print_mbuf(const struct os_mbuf *om);
+
+char *addr_str(const void *addr);
+
+void print_uuid(const ble_uuid_t *uuid);
+
+void print_conn_desc(const struct ble_gap_conn_desc *desc);
+
+void print_adv_fields(const struct ble_hs_adv_fields *fields);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //BLE_TGT_MISC_H
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c
new file mode 100644
index 00000000..a4253ce6
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c
@@ -0,0 +1,1471 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <host/ble_gap.h>
+#include "rx_stress.h"
+
+/* UUID128 of stress test use cases*/
+static uint8_t rx_stress_uuid128[STRESS_UUIDS_NUM][16];
+
+static struct com_stress_test_ctx rx_stress_ctxD = {
+ .conn_handle = 0xffff,
+ .cur_test_id = 0,
+ .s6_rcv_adv_first = 0,
+ .s6_rcv_adv_suc = 0,
+};
+
+static struct com_stress_test_ctx *rx_stress_ctx = &rx_stress_ctxD;
+
+#define EXTENDED_ADVERT 0
+#define LEGACY_ADVERT 1
+/* Advertising instances ids */
+#define SWITCHER_INSTANCE 0
+#define TEST_INSTANCE 1
+/* Main test task priority. Set a high value so that the task does not
+ * interfere with event handling */
+#define RX_STRESS_MAIN_TASK_PRIO 0xf0
+
+/* Advertising settings */
+struct rx_stress_adv_set {
+ uint8_t instance;
+ uint8_t *instance_uuid128;
+ uint8_t legacy_pdu;
+ ble_gap_event_fn *cb;
+ const uint8_t *pattern_data;
+ int pattern_len;
+};
+
+/* Define task stack and task object */
+#define RX_STRESS_MAIN_TASK_STACK_SIZE (2000)
+static struct os_task rx_stress_main_task;
+static os_stack_t rx_stress_main_task_stack[RX_STRESS_MAIN_TASK_STACK_SIZE];
+static struct os_sem rx_stress_main_sem;
+
+static void
+rx_stress_on_test_finish(int test_num)
+{
+ console_printf("\033[0;32m\nStress test %d completed\033[0m\n", test_num);
+ os_sem_release(&rx_stress_main_sem);
+}
+
+static int
+rx_stress_adv_start(uint8_t instance)
+{
+ int rc;
+
+ /* Resume advertising earlier configured instance */
+ rc = ble_gap_ext_adv_start(instance, 0, 0);
+ assert (rc == 0 || rc == 2);
+ MODLOG_DFLT(INFO, "Instance %d started; rc: %d\n", instance, rc);
+ return rc;
+}
+
+static int
+rx_stress_adv_start_with_rand_addr(uint8_t instance)
+{
+ int rc;
+ ble_addr_t addr;
+
+ ble_gap_ext_adv_stop(instance);
+
+ rc = ble_hs_id_gen_rnd(1, &addr);
+ assert (rc == 0);
+
+ /* Set random address for advertising instance */
+ rc = ble_gap_ext_adv_set_addr(instance, &addr);
+ assert (rc == 0);
+
+ return rx_stress_adv_start(instance);
+}
+
+static void
+rx_stress_simple_adv(struct rx_stress_adv_set *adv_set)
+{
+ uint8_t own_addr_type;
+ struct ble_gap_ext_adv_params params;
+ struct ble_hs_adv_fields fields;
+ struct os_mbuf *adv_data;
+ ble_addr_t addr;
+ const char *name;
+ int rc;
+ int pattern_len;
+
+ /* Determine own address type */
+ rc = ble_hs_id_infer_auto(0, &own_addr_type);
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "\033[0;31mError determining own address type; "
+ "rc=%d\033[0m\n", rc);
+ return;
+ }
+
+ /* Use defaults for non-set fields */
+ memset(&fields, 0, sizeof fields);
+ /* General Discoverable and BrEdrNotSupported */
+ fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
+ /* Set device name as instance name */
+ name = ble_svc_gap_device_name();
+ fields.name = (uint8_t *) name;
+ fields.name_len = strlen(name);
+ fields.name_is_complete = 1;
+ /* Set UUID 128 data service */
+ fields.svc_data_uuid128 = adv_set->instance_uuid128;
+ fields.svc_data_uuid128_len = 16;
+
+ /* Use defaults for non-set params */
+ memset(&params, 0, sizeof(params));
+ /* Set adv mode */
+ if (adv_set->legacy_pdu == 1) {
+ params.connectable = 1;
+ params.scannable = 1;
+ } else if (adv_set->pattern_len < 255) {
+ params.connectable = 1;
+ }
+
+ params.own_addr_type = own_addr_type;
+ params.primary_phy = BLE_HCI_LE_PHY_1M;
+ /* If legacy, this param will be lowered by API */
+ params.secondary_phy = BLE_HCI_LE_PHY_2M;
+ params.sid = adv_set->instance;
+ params.legacy_pdu = adv_set->legacy_pdu;
+
+ ble_gap_set_prefered_default_le_phy(TX_PHY_MASK, RX_PHY_MASK);
+
+ rc = ble_gap_ext_adv_remove(adv_set->instance);
+ assert(rc == 0 || rc == BLE_HS_EALREADY);
+
+ /* Configure instance with the params set */
+ rc = ble_gap_ext_adv_configure(adv_set->instance, &params,
+ NULL, adv_set->cb, NULL);
+ assert (rc == 0);
+
+ if (own_addr_type == 0) {
+ memcpy(addr.val, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), 6);
+ } else {
+ rc = ble_hs_id_gen_rnd(1, &addr);
+ assert (rc == 0);
+
+ /* Set random address for advertising instance */
+ rc = ble_gap_ext_adv_set_addr(adv_set->instance, &addr);
+ assert (rc == 0);
+ }
+
+ /* Get mbuf for adv data */
+ adv_data = os_msys_get_pkthdr(16, 0);
+ assert(adv_data != NULL);
+
+ /* Fill mbuf with adv fields - structured data */
+ rc = ble_hs_adv_set_fields_mbuf(&fields, adv_data);
+
+ if (rc) {
+ os_mbuf_free_chain(adv_data);
+ assert(0);
+ }
+
+ pattern_len = min(adv_set->pattern_len,
+ MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) - adv_data->om_len);
+
+ /* Append to mbuf pattern data - raw data */
+ rc = os_mbuf_append(adv_data, adv_set->pattern_data, pattern_len);
+
+ if (rc) {
+ os_mbuf_free_chain(adv_data);
+ assert(0);
+ }
+
+ /* Include mbuf data in advertisement */
+ rc = ble_gap_ext_adv_set_data(adv_set->instance, adv_data);
+ assert (rc == 0);
+
+ /* Start advertising */
+ rc = ble_gap_ext_adv_start(adv_set->instance, 0, 0);
+ assert (rc == 0);
+
+ MODLOG_DFLT(INFO, "instance %u started\n", adv_set->instance);
+}
+
+static int
+rx_stress_0_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[0].num);
+
+ /* Stop test advert */
+ ble_gap_ext_adv_stop(TEST_INSTANCE);
+ ble_gap_terminate(event->connect.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ } else {
+ /* Connection failed; resume advertising */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ }
+ return 0;
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32mReceived signal to switch test\033[0m\n");
+ /* Add token to semaphore. Main task will start next test. */
+ os_sem_release(&rx_stress_main_sem);
+
+ return 0;
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_2_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[2].attempts_num;
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[2].num);
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+ if (rx_stress_ctx->con_stat[2].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(2);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_3_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[3].attempts_num;
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[3].num);
+ } else {
+ /* Connection failed; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+ if (rx_stress_ctx->con_stat[3].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(3);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_4_gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[4].attempts_num;
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Connection established; status=%d; num=%d",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[4].num);
+
+ /* Remember connection handler */
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ if (rx_stress_ctx->con_stat[4].prms_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(4);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ if (event->conn_update.status != 0) {
+ MODLOG_DFLT(INFO, "Connection update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "Connection updated; num=%d\n",
+ ++rx_stress_ctx->con_stat[4].prms_upd_num);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (rx_stress_ctx->con_stat[4].prms_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Test completed. */
+ ble_gap_terminate(rx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_5_con_update(void)
+{
+ int rc;
+
+ /* With every next update at least one param must change. Otherwise no
+ * event occurs and test will not be continued */
+ struct ble_gap_upd_params params = {
+ .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN,
+ .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX,
+ .latency = BLE_GAP_INITIAL_CONN_LATENCY,
+ /* So let's change e.g. timeout value. Put ...% 2 ? 1 : 2 to make sure
+ * that value won't grow significantly and will be different with every
+ * iteration. */
+ .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT +
+ (rx_stress_ctx->con_stat[5].prms_upd_num % 2 ?
+ 1 : 2),
+ .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN,
+ .max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN,
+ };
+
+ rc = ble_gap_update_params(rx_stress_ctx->conn_handle, &params);
+
+ if (rc == BLE_HS_ENOTCONN) {
+ MODLOG_DFLT(INFO, "Device disconnected. Connection update failed\n");
+ assert(0);
+ }
+
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "\033[0;31mError during connection update; "
+ "rc=%d\033[0m\n", rc);
+ assert(0);
+ }
+
+ return rc;
+}
+
+static int
+rx_stress_5_gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[5].attempts_num;
+
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Connection established; status=%d; num=%d",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[5].num);
+
+ /* Remember connection handler */
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ /* Update connection. */
+ rc = rx_stress_5_con_update();
+ assert(rc == 0);
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ if (rx_stress_ctx->con_stat[5].prms_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(5);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ if (event->conn_update.status != 0) {
+ MODLOG_DFLT(INFO, "Connection update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "Connection updated; num=%d\n",
+ ++rx_stress_ctx->con_stat[5].prms_upd_num);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (rx_stress_ctx->con_stat[5].prms_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Test completed. */
+ ble_gap_terminate(rx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ } else {
+ /* Update connection. */
+ rc = rx_stress_5_con_update();
+ assert(rc == 0);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_6_gap_event(struct ble_gap_event *event, void *arg)
+{
+ MODLOG_DFLT(INFO, "Event occurs=%d\n", event->type);
+ return 0;
+}
+
+static int
+rx_stress_7_gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[7].attempts_num;
+
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Connection established; status=%d; num=%d",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[7].num);
+
+ /* Remember connection handler */
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ if (rx_stress_ctx->con_stat[7].phy_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(7);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
+ if (event->phy_updated.status != 0) {
+ MODLOG_DFLT(INFO, "PHY update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "PHY updated; num=%d\n",
+ ++rx_stress_ctx->con_stat[7].phy_upd_num);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (rx_stress_ctx->con_stat[7].phy_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Test completed. */
+ ble_gap_terminate(rx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_8_con_update(void)
+{
+ int rc;
+ uint8_t tx_phys_mask;
+ uint8_t rx_phys_mask;
+
+ ble_gap_read_le_phy(rx_stress_ctx->conn_handle, &tx_phys_mask,
+ &rx_phys_mask);
+
+ /* With every next update at least one param must change */
+ switch (rx_phys_mask) {
+ case BLE_GAP_LE_PHY_1M_MASK:
+ rx_phys_mask = BLE_GAP_LE_PHY_2M_MASK;
+ break;
+ case BLE_GAP_LE_PHY_2M_MASK:
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ rx_phys_mask = BLE_GAP_LE_PHY_CODED_MASK;
+ break;
+ case BLE_GAP_LE_PHY_CODED_MASK:
+#endif
+ rx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ default:
+ rx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ }
+
+ switch (tx_phys_mask) {
+ case BLE_GAP_LE_PHY_1M_MASK:
+ tx_phys_mask = BLE_GAP_LE_PHY_2M_MASK;
+ break;
+ case BLE_GAP_LE_PHY_2M_MASK:
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ tx_phys_mask = BLE_GAP_LE_PHY_CODED_MASK;
+ break;
+ case BLE_GAP_LE_PHY_CODED_MASK:
+#endif
+ tx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ default:
+ tx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ }
+
+ rc = ble_gap_set_prefered_le_phy(rx_stress_ctx->conn_handle,
+ tx_phys_mask, rx_phys_mask, 0);
+
+ if (rc == BLE_HS_ENOTCONN) {
+ MODLOG_DFLT(INFO, "Device disconnected. Connection update failed\n");
+ return rc;
+ }
+
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "\033[0;31mError during PHY update; "
+ "rc=%d\033[0m\n", rc);
+ }
+
+ return rc;
+}
+
+static int
+rx_stress_8_gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[8].attempts_num;
+
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Connection established; status=%d; num=%d",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[8].num);
+
+ /* Remember connection handler */
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ /* Update connection. */
+ rc = rx_stress_8_con_update();
+ assert(rc == 0);
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ if (rx_stress_ctx->con_stat[8].phy_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(8);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
+ if (event->phy_updated.status != 0) {
+ MODLOG_DFLT(INFO, "PHY update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "PHY updated; num=%d; rx:%d, tx:%d\n",
+ ++rx_stress_ctx->con_stat[8].phy_upd_num,
+ event->phy_updated.rx_phy, event->phy_updated.tx_phy);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (rx_stress_ctx->con_stat[8].phy_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Test completed. */
+ ble_gap_terminate(rx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ } else {
+ /* Update connection. */
+ rc = rx_stress_8_con_update();
+ assert(rc == 0);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_9_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[9].attempts_num;
+
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Connection established; status=%d; num=%d",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[9].num);
+ console_printf("\033[0;32m>\033[0m");
+
+ /* Remember max number of established connections */
+ if (rx_stress_ctx->con_stat[9].num >
+ rx_stress_ctx->con_stat[9].max_num) {
+ rx_stress_ctx->con_stat[9].max_num = rx_stress_ctx->con_stat[9].num;
+ }
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ console_printf("\033[0;31mX\033[0m");
+ MODLOG_DFLT(INFO, "Connections num: %d\n",
+ --rx_stress_ctx->con_stat[9].num);
+
+ if (rx_stress_ctx->con_stat[9].num != 0 &&
+ rx_stress_ctx->con_stat[9].num <
+ MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1) {
+ rx_stress_adv_start_with_rand_addr(TEST_INSTANCE);
+ } else {
+ /* When TX device has terminated all connections, stop advertising. */
+ ble_gap_ext_adv_stop(TEST_INSTANCE);
+ rx_stress_on_test_finish(9);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_ADV_COMPLETE:
+ /* Stop test when TX device has terminated all connections or
+ * number of connections has reached the max possible value. */
+ if (rx_stress_ctx->con_stat[9].num != 0 &&
+ rx_stress_ctx->con_stat[9].num <
+ MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1) {
+ rx_stress_adv_start_with_rand_addr(TEST_INSTANCE);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ }
+ return 0;
+}
+
+static void
+tx_stress_10_l2cap_update_event(uint16_t conn_handle, int status, void *arg)
+{
+ if (status == 0) {
+ MODLOG_DFLT(INFO, "L2CAP params updated\n");
+ } else {
+ MODLOG_DFLT(INFO, "L2CAP params update failed; rc=%d\n", status);
+ assert(0);
+ }
+}
+
+static int
+rx_stress_10_l2cap_event(struct ble_l2cap_event *event, void *arg)
+{
+ int rc;
+ struct os_mbuf *data_buf;
+ static int data_len = 1000;
+ static int send_cnt = 0;
+ static bool stalled = false;
+ struct ble_l2cap_chan_info chan_info;
+
+ switch (event->type) {
+ case BLE_L2CAP_EVENT_COC_CONNECTED:
+ if (event->connect.status) {
+ MODLOG_DFLT(INFO, "LE COC error: %d\n", event->connect.status);
+ return 0;
+ }
+
+ ble_l2cap_get_chan_info(event->connect.chan, &chan_info);
+
+ MODLOG_DFLT(INFO,
+ "LE COC connected, conn: %d, chan: 0x%08lx, scid: 0x%04x, "
+ "dcid: 0x%04x, our_mtu: 0x%04x, peer_mtu: 0x%04x\n",
+ event->connect.conn_handle,
+ (uint32_t) event->connect.chan,
+ chan_info.scid,
+ chan_info.dcid,
+ chan_info.our_l2cap_mtu,
+ chan_info.peer_l2cap_mtu);
+
+ struct ble_l2cap_sig_update_params params = {
+ .itvl_min = 0x0006,//BLE_GAP_INITIAL_CONN_ITVL_MIN
+ .itvl_max = 0x0006,//BLE_GAP_INITIAL_CONN_ITVL_MIN
+ .slave_latency = 0x0000,
+ .timeout_multiplier = 0x0100,
+ };
+
+ rc = ble_l2cap_sig_update(event->connect.conn_handle, &params,
+ &tx_stress_10_l2cap_update_event, NULL);
+ assert(rc == 0);
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_DISCONNECTED:
+ MODLOG_DFLT(INFO, "LE CoC disconnected, chan: 0x%08lx\n",
+ (uint32_t) event->disconnect.chan);
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_ACCEPT:
+ stress_l2cap_coc_accept(event->accept.peer_sdu_size,
+ event->accept.chan);
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
+ stress_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx);
+
+ MODLOG_DFLT(INFO, "L2CAP server received data; num=%d\n",
+ ++rx_stress_ctx->rcv_num);
+ rx_stress_ctx->chan = event->receive.chan;
+
+ /* In this use case, receiving any data by RX device L2CAP server means
+ * request from TX device to send data. */
+
+ /* Do not send if stalled on the last sending. */
+ if (stalled) {
+ return 0;
+ }
+ break;
+
+ case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
+ MODLOG_DFLT(INFO, "L2CAP unstalled event\n");
+
+ stalled = false;
+
+ /* Send if was stalled on the last request to send. */
+ if (rx_stress_ctx->rcv_num > send_cnt) {
+ break;
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other L2CAP event occurs: %d\n", event->type);
+ return 0;
+ }
+
+ /* Send pattern data */
+
+ /* Get mbuf for adv data */
+ data_buf = os_msys_get_pkthdr(data_len, 0);
+
+ MODLOG_DFLT(INFO, "Data buf %s\n", data_buf ? "OK" : "NOK");
+ assert(data_buf != NULL);
+
+ /* The first 2 bytes of data is the size of appended pattern data. */
+ rc = os_mbuf_append(data_buf, (uint8_t[]) {data_len >> 8, data_len},
+ 2);
+ if (rc) {
+ os_mbuf_free_chain(data_buf);
+ assert(0);
+ }
+
+ /* Fill mbuf with the pattern */
+ stress_fill_mbuf_with_pattern(data_buf, data_len);
+
+ /* Send data */
+ rc = ble_l2cap_send(rx_stress_ctx->chan, data_buf);
+ MODLOG_DFLT(INFO, "Return code=%d\n", rc);
+ if (rc) {
+ MODLOG_DFLT(INFO, "L2CAP stalled - waiting\n");
+ stalled = true;
+ }
+
+ MODLOG_DFLT(INFO, " %d, %d\n", ++send_cnt, data_len);
+ data_len += 500;
+
+ return 0;
+}
+
+static int
+rx_stress_10_gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc out_desc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[10].attempts_num;
+
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Connection established; status=%d; num=%d",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[10].num);
+
+ ble_gap_conn_find(event->connect.conn_handle, &out_desc);
+ MODLOG_DFLT(INFO, "Address %s",
+ addr_str(out_desc.peer_id_addr.val));
+ } else {
+ /* Connection failed; resume advertising. */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ rx_stress_ctx->completed[10] = true;
+ rx_stress_on_test_finish(10);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_11_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[11].attempts_num;
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[11].num);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ }
+
+ ble_gap_terminate(event->connect.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+ if (rx_stress_ctx->con_stat[11].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(11);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_12_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int om_len = 10000;
+ struct os_mbuf *om;
+ int64_t us = 0;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[12].num);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ break;
+ } else {
+ /* Connection failed; resume advertising */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+
+ rx_stress_ctx->s12_notif_time = rx_stress_ctx->time_sum /
+ rx_stress_ctx->send_num;
+
+ MODLOG_DFLT(INFO, "Average time: %d us\n",
+ rx_stress_ctx->s12_notif_time);
+
+ rx_stress_on_test_finish(12);
+ return 0;
+
+ case BLE_GAP_EVENT_NOTIFY_TX:
+ rx_stress_ctx->end_us = os_get_uptime_usec();
+ MODLOG_DFLT(INFO, "Notify TX event\n");
+
+ if (!event->notify_tx.status) {
+ /* Send next only after previous indication is done */
+ return 0;
+ }
+ assert(event->notify_tx.status == BLE_HS_EDONE);
+
+ if (rx_stress_ctx->send_num++ >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ ble_gap_terminate(event->notify_tx.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ return 0;
+ }
+
+ /* Time of data sending */
+ us = rx_stress_ctx->end_us - rx_stress_ctx->begin_us;
+ console_printf("Indication time: %lld\n", us);
+ rx_stress_ctx->time_sum += us;
+ console_printf("\033[0;32m>\033[0m");
+ break;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+
+ /* Indicate data pattern */
+ rx_stress_ctx->begin_us = os_get_uptime_usec();
+ om = os_msys_get_pkthdr(om_len, 0);
+ stress_fill_mbuf_with_pattern(om, om_len);
+ rc = ble_gattc_indicate_custom(rx_stress_ctx->conn_handle, hrs_hrm_handle,
+ om);
+ assert(rc == 0);
+ return 0;
+}
+
+static int
+rx_stress_13_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+ struct os_mbuf *om = NULL;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[13].num);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ rx_stress_ctx->begin_us = os_get_uptime_usec();
+ break;
+ } else {
+ /* Connection failed; resume advertising */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ assert(0);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+
+ rx_stress_ctx->time_sum = rx_stress_ctx->end_us -
+ rx_stress_ctx->begin_us;
+
+ rx_stress_ctx->s13_notif_time = rx_stress_ctx->time_sum /
+ rx_stress_ctx->send_num;
+
+ MODLOG_DFLT(INFO, "Average time: %lld us\n",
+ rx_stress_ctx->s13_notif_time);
+ rx_stress_on_test_finish(13);
+ return 0;
+
+ case BLE_GAP_EVENT_NOTIFY_TX:
+ MODLOG_DFLT(INFO, "Notify TX event; num=%d\n",
+ ++rx_stress_ctx->send_num);
+ assert(event->notify_tx.status == 0);
+
+ if (rx_stress_ctx->send_num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_ctx->end_us = os_get_uptime_usec();
+ ble_gap_terminate(event->connect.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ return 0;
+ }
+ break;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+
+ om = ble_hs_mbuf_from_flat(test_6_pattern, 10);
+ rc = ble_gattc_notify_custom(rx_stress_ctx->conn_handle,
+ hrs_hrm_handle, om);
+ assert(rc == 0);
+ return 0;
+}
+
+static int
+rx_stress_14_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int bytes_num = 10000;
+ static struct os_mbuf *om = NULL;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[14].num);
+ rx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ /* Connection failed; resume advertising */
+ MODLOG_DFLT(INFO, "Connection failed; status=%d ",
+ event->connect.status);
+ assert(0);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+
+ rx_stress_ctx->s14_notif_time = rx_stress_ctx->time_sum /
+ rx_stress_ctx->send_num;
+
+ MODLOG_DFLT(INFO, "Average time: %d us\n",
+ rx_stress_ctx->s14_notif_time);
+
+ rx_stress_on_test_finish(14);
+ return 0;
+
+ case BLE_GAP_EVENT_NOTIFY_TX:
+ MODLOG_DFLT(INFO, "Notify TX event\n");
+ assert(event->notify_tx.status == 0);
+ return 0;
+
+ case BLE_GAP_EVENT_SUBSCRIBE:
+ MODLOG_DFLT(INFO, "Subscribe event\n");
+
+ if (event->subscribe.cur_notify) {
+ MODLOG_DFLT(INFO, "Notification subscribed\n");
+
+ ++rx_stress_ctx->send_num;
+
+ /* Notify data pattern */
+ om = ble_hs_mbuf_from_flat(test_6_pattern, bytes_num);
+
+ rc = ble_gattc_notify_custom(rx_stress_ctx->conn_handle,
+ hrs_hrm_handle, om);
+ assert(rc == 0);
+
+ console_printf("\033[0;32m>\033[0m");
+ } else if (event->subscribe.prev_notify) {
+ MODLOG_DFLT(INFO, "Notification unsubscribed\n");
+ } else {
+ MODLOG_DFLT(INFO, "Other subscription\n");
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+rx_stress_15_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++rx_stress_ctx->con_stat[15].attempts_num;
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "\nConnection established; status=%d; num=%d\n",
+ event->connect.status,
+ ++rx_stress_ctx->con_stat[15].num);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ assert(0);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+ if (rx_stress_ctx->con_stat[15].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rx_stress_on_test_finish(15);
+ } else {
+ /* Connection terminated; resume advertising. */
+ rx_stress_adv_start(TEST_INSTANCE);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+/* Advert settings for each test. */
+static struct rx_stress_adv_set rx_stress_adv_sets[] = {
+ {
+ .instance = SWITCHER_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[0],
+ .legacy_pdu = LEGACY_ADVERT,
+ .cb = rx_stress_0_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = SWITCHER_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[0],
+ .legacy_pdu = LEGACY_ADVERT,
+ .cb = rx_stress_0_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[2],
+ .legacy_pdu = LEGACY_ADVERT,
+ .cb = rx_stress_2_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[3],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_3_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[4],
+ .legacy_pdu = LEGACY_ADVERT,
+ .cb = rx_stress_4_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[5],
+ .legacy_pdu = LEGACY_ADVERT,
+ .cb = rx_stress_5_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[6],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_6_gap_event,
+ .pattern_data = test_6_pattern,
+ .pattern_len = 1640,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[7],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_7_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[8],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_8_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[9],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_9_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[10],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_10_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[11],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_11_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[12],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_12_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[13],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_13_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[14],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_14_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+ {
+ .instance = TEST_INSTANCE,
+ .instance_uuid128 = rx_stress_uuid128[15],
+ .legacy_pdu = EXTENDED_ADVERT,
+ .cb = rx_stress_15_gap_event,
+ .pattern_data = NULL,
+ .pattern_len = 0,
+ },
+};
+
+static void
+rx_stress_start(int test_num)
+{
+ int rc;
+
+ /* Init semaphore with 0 tokens. */
+ os_sem_init(&rx_stress_main_sem, 0);
+
+ console_printf("\033[1;36mStart test num %d - ", test_num);
+
+ /* Start test. */
+ switch (test_num) {
+ case 2:
+ console_printf("Stress Connect/Disconnect legacy\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[2]);
+ break;
+ case 3:
+ console_printf("Stress Connect/Disconnect ext adv\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[3]);
+ break;
+ case 4:
+ console_printf("Stress connection params update (TX)\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[4]);
+ break;
+ case 5:
+ console_printf("Stress connection params update (RX)\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[5]);
+ break;
+ case 6:
+ /* Start SWITCHER advert that gives possibility to remotely start
+ * next test advert */
+ console_printf("Stress Scan\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[0]);
+ rx_stress_simple_adv(&rx_stress_adv_sets[6]);
+ break;
+ case 7:
+ console_printf("Stress PHY Update (TX)\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[7]);
+ break;
+ case 8:
+ console_printf("Stress PHY Update (RX)\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[8]);
+ break;
+ case 9:
+ console_printf("Stress multi connection\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[9]);
+ break;
+ case 10:
+ console_printf("Stress L2CAP send\033[0m\n");
+ rc = ble_l2cap_create_server(1, STRESS_COC_MTU,
+ rx_stress_10_l2cap_event, NULL);
+ assert(rc == 0);
+ rx_stress_simple_adv(&rx_stress_adv_sets[10]);
+ break;
+ case 11:
+ console_printf("Stress Advertise/Connect/Disconnect\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[11]);
+ break;
+ case 12:
+ console_printf("Stress GATT indication\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[12]);
+ break;
+ case 13:
+ console_printf("Stress GATT notification\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[13]);
+ break;
+ case 14:
+ console_printf("Stress GATT Subscribe/Notify/Unsubscribe\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[14]);
+ break;
+ case 15:
+ console_printf("Stress Connect/Send/Disconnect\033[0m\n");
+ rx_stress_simple_adv(&rx_stress_adv_sets[15]);
+ break;
+ default:
+ console_printf("\033[0;31mFound test, but do not know how to perform."
+ "\033[0m\n");
+ assert(0);
+ }
+
+ /* Wait for the test to finish. Then 1 token will be released
+ * allowing to pass through semaphore. */
+ os_sem_pend(&rx_stress_main_sem, OS_TIMEOUT_NEVER);
+
+ ble_gap_ext_adv_stop(SWITCHER_INSTANCE);
+
+ stress_clear_ctx_reusable_var(rx_stress_ctx);
+}
+
+static void
+stress_uuid_init()
+{
+ uint8_t i;
+
+ for (i = 0; i < STRESS_UUIDS_NUM; ++i) {
+ /* Fill all 16 bytes of UUID128 */
+ rx_stress_uuid128[i][0] = 0xC0;
+ rx_stress_uuid128[i][1] = 0xDE;
+ rx_stress_uuid128[i][2] = i;
+ memcpy(&rx_stress_uuid128[i][3], MYNEWT_VAL(BLE_STRESS_UUID_BASE), 13);
+ }
+}
+
+static void
+rx_stress_read_command_cb(void)
+{
+ console_printf("Start testing\n");
+ os_sem_release(&rx_stress_main_sem);
+}
+
+static void
+rx_stress_main_task_fn(void *arg)
+{
+ int i;
+
+ stress_uuid_init();
+
+ console_printf("\033[1;36mRX device\033[0m\n");
+ console_printf("Press ENTER to start: \n");
+ console_init(&rx_stress_read_command_cb);
+
+ /* Waite for pressing ENTER in console */
+ os_sem_pend(&rx_stress_main_sem, OS_TIMEOUT_NEVER);
+
+ /* Standard tests perform */
+ for (i = 11; i < STRESS_UUIDS_NUM; ++i) {
+ if (i == 7 || i == 8 || i == 13) {
+ /* 7,8: PHY update tests cause that the device during the next test
+ * will stuck somewhere and will reset. Skip them for now.
+ * 13: Should work after fixing ble_gattc_notify_custom (nimble issue on GitHub)*/
+ continue;
+ }
+ /* Start test. */
+ rx_stress_start(i);
+ }
+
+ /* Print tests results */
+ com_stress_print_report(rx_stress_ctx);
+
+ /* Task should never return */
+ while (1) {
+ }
+}
+
+void
+rx_stress_start_auto()
+{
+ /* Start task that will run all stress tests one by one. */
+ os_task_init(&rx_stress_main_task, "rx_stress_main_task",
+ rx_stress_main_task_fn, NULL, RX_STRESS_MAIN_TASK_PRIO,
+ OS_WAIT_FOREVER, rx_stress_main_task_stack,
+ RX_STRESS_MAIN_TASK_STACK_SIZE);
+}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.h b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.h
new file mode 100644
index 00000000..62f84117
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _BLE_STRESS_RX_H
+#define _BLE_STRESS_RX_H
+
+#include <assert.h>
+#include <string.h>
+#include <console/console.h>
+#include <errno.h>
+#include <nrfx/hal/nrf_aar.h>
+
+/* BLE */
+#include "nimble/ble.h"
+#include "host/ble_hs.h"
+#include "services/gap/ble_svc_gap.h"
+#include "host/ble_gap.h"
+#include <host/ble_l2cap.h>
+
+#include "misc.h"
+#include "stress.h"
+#include "stress_gatt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Executes stress tests one by one.
+ */
+void rx_stress_start_auto();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_BLE_STRESS_RX_H
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress.c b/src/libs/mynewt-nimble/apps/blestress/src/stress.c
new file mode 100644
index 00000000..6f5badf0
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/stress.c
@@ -0,0 +1,389 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "stress.h"
+
+void
+com_stress_print_report(const struct com_stress_test_ctx *test_ctxs)
+{
+ console_printf("\033[0;32mAll tests completed\033[0m\n");
+ console_printf("Tests results:\n");
+
+ console_printf(
+ "\033[0;33mUse case 1 - Stress Connect -> Connect Cancel: \n\033[0m");
+ console_printf("Con attempts = %d\n", test_ctxs->con_stat[1].attempts_num);
+ console_printf("Con success = %d\n", test_ctxs->con_stat[1].num);
+
+ console_printf(
+ "\033[0;33mUse case 2 - Stress Connect/Disconnect legacy: \n\033[0m");
+ console_printf("Con attempts = %d\n", test_ctxs->con_stat[2].attempts_num);
+ console_printf("Con success = %d\n", test_ctxs->con_stat[2].num);
+
+ console_printf(
+ "\033[0;33mUse case 3 - Stress Connect/Disconnect ext adv: \n\033[0m");
+ console_printf("Con attempts = %d\n", test_ctxs->con_stat[3].attempts_num);
+ console_printf("Con success = %d\n", test_ctxs->con_stat[3].num);
+
+ console_printf(
+ "\033[0;33mUse case 4 - Stress connection params update (TX): \n\033[0m");
+ console_printf("Params updates = %d\n",
+ test_ctxs->con_stat[4].prms_upd_num);
+
+ console_printf(
+ "\033[0;33mUse case 5 - Stress connection params update (RX): \n\033[0m");
+ console_printf("Params updates = %d\n",
+ test_ctxs->con_stat[5].prms_upd_num);
+
+ console_printf("\033[0;33mUse case 6 - Stress Scan: \n\033[0m");
+ console_printf("Received first packets = %d\n",
+ test_ctxs->s6_rcv_adv_first);
+ console_printf("Received all packets = %d\n", test_ctxs->s6_rcv_adv_suc);
+
+ console_printf("\033[0;33mUse case 7 - Stress PHY Update (TX): \n\033[0m");
+ console_printf("PHY updates = %d\n", test_ctxs->con_stat[7].phy_upd_num);
+
+ console_printf("\033[0;33mUse case 8 - Stress PHY Update (RX): \n\033[0m");
+ console_printf("PHY updates = %d\n", test_ctxs->con_stat[8].phy_upd_num);
+
+ console_printf(
+ "\033[0;33mUse case 9 - Stress multi connection: \n\033[0m");
+ console_printf("Max reached num of connections = %d\n",
+ test_ctxs->con_stat[9].max_num);
+
+ console_printf("\033[0;33mUse case 10 - Stress L2CAP send: \n\033[0m");
+ console_printf("Average bit rate = %d\n", test_ctxs->s10_bit_rate);
+ console_printf("Max received MTU = %lld\n", test_ctxs->s10_max_mtu);
+
+ console_printf("\033[0;33mUse case 11 - "
+ "Stress Advertise/Connect/Continue adv \n\033[0m");
+// console_printf(" = %d\n",);
+
+ console_printf("\033[0;33mUse case 12 - "
+ "Stress GATT indication: \n\033[0m");
+ console_printf("Average bit rate = %d\n", test_ctxs->s12_notif_time);
+
+ console_printf("\033[0;33mUse case 13 - "
+ "Stress GATT notification: \n\033[0m");
+ console_printf("Average time = %d\n", test_ctxs->s13_notif_time);
+
+ console_printf("\033[0;33mUse case 14 - "
+ "Stress GATT Subscribe/Notify/Unsubscribe: \n\033[0m");
+ console_printf("Average time = %d\n", test_ctxs->s14_notif_time);
+
+ console_printf("\033[0;33mUse case 15 - "
+ "Stress Connect/Send/Disconnect: \n\033[0m");
+ console_printf("Con num = %d\n", test_ctxs->con_stat[15].num);
+}
+
+void
+stress_clear_ctx_reusable_var(struct com_stress_test_ctx *ctx)
+{
+ ctx->cur_test_id = 0;
+ ctx->dev_addr.type = 0;
+ ctx->dev_addr.type = 0;
+ ctx->conn_handle = 0;
+ ctx->chan = 0;
+ ctx->rcv_data_bytes = 0;
+ ctx->rcv_num = 0;
+ ctx->send_num = 0;
+ ctx->begin_us = 0;
+ ctx->end_us = 0;
+ ctx->time_sum = 0;
+ ctx->bytes_sum = 0;
+ ctx->timeout_flag = 0;
+ ctx->rcv_data_flag = 0;
+}
+
+int
+stress_fill_mbuf_with_pattern(struct os_mbuf *om, uint16_t len)
+{
+ int rc, i, mul, rest;
+
+ mul = len / STRESS_PAT_LEN;
+ rest = len % STRESS_PAT_LEN;
+
+ for (i = 0; i < mul; ++i) {
+ rc = os_mbuf_append(om, &test_6_pattern[29], STRESS_PAT_LEN);
+
+ if (rc) {
+ os_mbuf_free_chain(om);
+ assert(0);
+ }
+ }
+
+ rc = os_mbuf_append(om, &test_6_pattern[29], rest);
+
+ if (rc) {
+ os_mbuf_free_chain(om);
+ assert(0);
+ }
+
+ return rc;
+}
+
+void
+stress_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
+{
+ int rc;
+ console_printf("LE CoC SDU received, chan: 0x%08lx, data len %d\n",
+ (uint32_t) chan, OS_MBUF_PKTLEN(sdu));
+
+ rc = os_mbuf_free_chain(sdu);
+ assert(rc == 0);
+
+ /* Get buffer for data chain */
+ sdu = os_msys_get_pkthdr(STRESS_COC_MTU, 0);
+ assert(sdu != NULL);
+
+ /* Receive data chain */
+ rc = ble_l2cap_recv_ready(chan, sdu);
+ assert(rc == 0);
+}
+
+void
+stress_l2cap_coc_accept(uint16_t peer_mtu, struct ble_l2cap_chan *chan)
+{
+ struct os_mbuf *sdu_rx;
+ int rc;
+
+ console_printf("LE CoC accepting, chan: 0x%08lx, peer_mtu %d\n",
+ (uint32_t) chan, peer_mtu);
+
+ sdu_rx = os_msys_get_pkthdr(STRESS_COC_MTU, 0);
+ assert(sdu_rx != NULL);
+
+ rc = ble_l2cap_recv_ready(chan, sdu_rx);
+ assert(rc == 0);
+}
+
+void
+stress_start_timer(uint32_t timeout_ms, os_event_fn *ev_cb)
+{
+ int rc;
+ os_callout_stop(&stress_timer_callout);
+
+ os_callout_init(&stress_timer_callout, os_eventq_dflt_get(), ev_cb, NULL);
+
+ rc = os_callout_reset(&stress_timer_callout,
+ os_time_ms_to_ticks32(timeout_ms));
+
+ assert(rc == 0);
+}
+
+int64_t
+stress_calc_bit_rate(int64_t us, int64_t bytes_num)
+{
+ int bit_rate;
+
+ /* Multiply by 1000000 so you don't lose accuracy */
+ bit_rate = 1000000 * bytes_num / us;
+
+ return bit_rate;
+}
+
+static int
+stress_disc_dsc_fn(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ uint16_t chr_val_handle,
+ const struct ble_gatt_dsc *dsc,
+ void *arg)
+{
+ struct stress_gatt_search_ctx *search_ctx;
+ static bool found = false;
+
+ search_ctx = (struct stress_gatt_search_ctx *) arg;
+
+ if (error->status == 0) {
+ if (!ble_uuid_cmp(&dsc->uuid.u, &search_ctx->dsc_uuid.u) && !found) {
+ MODLOG_DFLT(INFO, "Found chr descriptor\n");
+ search_ctx->dsc_handle = dsc->handle;
+ MODLOG_DFLT(INFO, "uuid=%#06x; handle=%#06x", dsc->uuid.u16.value,
+ dsc->handle);
+ found = true;
+ }
+ return 0;
+ }
+
+ if (error->status == BLE_HS_EDONE) {
+ MODLOG_DFLT(INFO, "Done descriptor discovery\n");
+
+ if (found) {
+ found = false;
+ search_ctx->disc_end_fn(search_ctx);
+ return 0;
+ }
+
+ MODLOG_DFLT(ERROR, "\033[0;31mDid not find particular descriptor"
+ "\033[0m\n");
+ return 0;
+ }
+
+ MODLOG_DFLT(ERROR, "\033[0;31mError during descriptor discovery"
+ "\033[0m\n");
+ assert(0);
+ return 0;
+}
+
+static int
+stress_disc_chr_fn(uint16_t conn_handle,
+ const struct ble_gatt_error *error,
+ const struct ble_gatt_chr *chr, void *arg)
+{
+ int rc;
+ struct stress_gatt_search_ctx *search_ctx;
+ static bool found = false;
+
+ search_ctx = (struct stress_gatt_search_ctx *) arg;
+
+ if (error->status == 0) {
+ MODLOG_DFLT(INFO, "Found characteristic\n");
+ search_ctx->chr_start_handle = chr->val_handle;
+ found = true;
+ return 0;
+ }
+
+ if (error->status == BLE_HS_EDONE) {
+ MODLOG_DFLT(INFO, "Done characteristic discovery\n");
+
+ if (found) {
+ found = false;
+
+ if (search_ctx->search_goal == STRESS_FIND_CHR) {
+ search_ctx->disc_end_fn(search_ctx);
+ return 0;
+ }
+
+ rc = ble_gattc_disc_all_dscs(conn_handle,
+ search_ctx->chr_start_handle,
+ search_ctx->srv_end_handle,
+ &stress_disc_dsc_fn, search_ctx);
+ assert(rc == 0);
+ return 0;
+ }
+
+ MODLOG_DFLT(ERROR, "\033[0;31mDid not find particular "
+ "characteristic\033[0m\n");
+ return 0;
+ }
+
+ MODLOG_DFLT(ERROR,
+ "\033[0;31mError during characteristic discovery\033[0m\n");
+ assert(0);
+ return 0;
+}
+
+static int
+stress_disc_svc_fn(uint16_t conn_handle, const struct ble_gatt_error *error,
+ const struct ble_gatt_svc *service, void *arg)
+{
+ int rc;
+ struct stress_gatt_search_ctx *search_ctx = NULL;
+ static bool found = false;
+
+ search_ctx = (struct stress_gatt_search_ctx *) arg;
+
+ if (error->status == 0) {
+ MODLOG_DFLT(INFO, "Found service\n");
+ search_ctx->srv_start_handle = service->start_handle;
+ search_ctx->srv_end_handle = service->end_handle;
+ found = true;
+ return 0;
+ }
+
+ if (error->status == BLE_HS_EDONE) {
+ MODLOG_DFLT(INFO, "Done service discovery\n");
+
+ if (found) {
+ found = false;
+ if (search_ctx->search_goal == STRESS_FIND_SRV) {
+ search_ctx->disc_end_fn(search_ctx);
+ return 0;
+ }
+
+ rc = ble_gattc_disc_chrs_by_uuid(conn_handle,
+ search_ctx->srv_start_handle,
+ search_ctx->srv_end_handle,
+ &search_ctx->chr_uuid.u,
+ &stress_disc_chr_fn,
+ search_ctx);
+ MODLOG_DFLT(INFO, "rc=%d\n", rc);
+ assert(rc == 0);
+ return 0;
+ }
+
+ MODLOG_DFLT(ERROR,
+ "\033[0;31mDid not find particular service\033[0m\n");
+ return 0;
+ }
+
+ MODLOG_DFLT(ERROR, "\033[0;31mError during service discovery\033[0m\n");
+ assert(0);
+ return 0;
+}
+
+static void
+stress_gatt_find_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ const ble_uuid_t *chr_uuid, const ble_uuid_t *dsc_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn,
+ uint8_t search_goal)
+{
+ static struct stress_gatt_search_ctx search_ctx;
+ int rc;
+
+ search_ctx.conn_handle = conn_handle;
+ ble_uuid_copy((ble_uuid_any_t *) &search_ctx.srv_uuid, srv_uuid);
+ ble_uuid_copy((ble_uuid_any_t *) &search_ctx.chr_uuid, chr_uuid);
+ ble_uuid_copy((ble_uuid_any_t *) &search_ctx.dsc_uuid, dsc_uuid);
+ search_ctx.disc_end_fn = disc_end_fn;
+ search_ctx.search_goal = search_goal;
+ search_ctx.srv_start_handle = 0;
+ search_ctx.srv_end_handle = 0;
+ search_ctx.chr_start_handle = 0;
+ search_ctx.dsc_handle = 0;
+
+ rc = ble_gattc_disc_svc_by_uuid(conn_handle, srv_uuid, &stress_disc_svc_fn,
+ &search_ctx);
+ assert(rc == 0);
+}
+
+void
+stress_find_svc_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn)
+{
+ stress_gatt_find_handle(conn_handle, srv_uuid, NULL, NULL, disc_end_fn,
+ STRESS_FIND_SRV);
+}
+
+void
+stress_find_chr_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ const ble_uuid_t *chr_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn)
+{
+ stress_gatt_find_handle(conn_handle, srv_uuid, chr_uuid, NULL, disc_end_fn,
+ STRESS_FIND_CHR);
+}
+
+void
+stress_find_dsc_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ const ble_uuid_t *chr_uuid, const ble_uuid_t *dsc_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn)
+{
+ stress_gatt_find_handle(conn_handle, srv_uuid, chr_uuid, dsc_uuid,
+ disc_end_fn, STRESS_FIND_DSC);
+}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress.h b/src/libs/mynewt-nimble/apps/blestress/src/stress.h
new file mode 100644
index 00000000..91ab4f47
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/stress.h
@@ -0,0 +1,375 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef BLE_TGT_STRESS_H
+#define BLE_TGT_STRESS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nimble/ble.h>
+#include <modlog/modlog.h>
+#include <os/mynewt.h>
+#include <console/console.h>
+#include <host/ble_l2cap.h>
+#include <host/ble_gatt.h>
+#include <host/ble_gap.h>
+#include <assert.h>
+
+#define STRESS_UUIDS_NUM (16)
+
+/* No preferred PHY */
+#define TX_PHY_MASK 0
+#define RX_PHY_MASK 0
+/* L2CAP SDU */
+#define STRESS_COC_MTU (64000)
+
+#define STRESS_FIND_SRV 1
+#define STRESS_FIND_CHR 2
+#define STRESS_FIND_DSC 3
+
+struct os_callout stress_timer_callout;
+struct stress_gatt_search_ctx;
+typedef void stress_gatt_disc_end_fn(struct stress_gatt_search_ctx *search_ctx);
+
+struct stress_gatt_search_ctx {
+ /* Connection handle */
+ uint16_t conn_handle;
+
+ /* Wanted service uuid */
+ ble_uuid16_t srv_uuid;
+
+ /* Wanted characteristic uuid */
+ ble_uuid16_t chr_uuid;
+
+ /* Wanted descriptor uuid */
+ ble_uuid16_t dsc_uuid;
+
+ /* Search goal: 1 - service, 2 - characteristic, 3 - descriptor */
+ uint8_t search_goal;
+
+ /* Callback after reaching the goal */
+ stress_gatt_disc_end_fn *disc_end_fn;
+
+ /* Service start handle */
+ uint16_t srv_start_handle;
+
+ /* Service end handle */
+ uint16_t srv_end_handle;
+
+ /* Characteristic start handle */
+ uint16_t chr_start_handle;
+
+ /* Descriptor handle */
+ uint16_t dsc_handle;
+};
+
+struct stress_con_stat {
+ /* Number of successful connection attempts */
+ int num;
+
+ /* Max number of established connections */
+ int max_num;
+
+ /* Number connection attempts */
+ int attempts_num;
+
+ /* Number of params updates */
+ int prms_upd_num;
+
+ /* Number of PHY updates */
+ int phy_upd_num;
+};
+
+/* Common stress test context.
+ * (Reusable) - auxiliary variable
+ * (Stress x) - variable contains result of x stress test */
+struct com_stress_test_ctx {
+ /* Which of tests are completed already. Each element for different
+ * stress test. */
+ bool completed[STRESS_UUIDS_NUM];
+
+ /* Connection stats. Each element for different stress test. */
+ struct stress_con_stat con_stat[STRESS_UUIDS_NUM];
+
+/* Reusable variables */
+
+ /* Stress test number */
+ int cur_test_id;
+
+ /* Instance address */
+ ble_addr_t dev_addr;
+
+ /* Connection handler */
+ uint16_t conn_handle;
+
+ /* L2CAP channel (Reusable) */
+ struct ble_l2cap_chan * chan;
+
+ /* Size of received data */
+ int64_t rcv_data_bytes;
+
+ /* Number of received packages */
+ int rcv_num;
+
+ /* Number of send actions */
+ int send_num;
+
+ /* Variables for bit rate measurement */
+ int64_t begin_us;
+ int64_t end_us;
+ int64_t time_sum;
+ int64_t bytes_sum;
+
+ /* Timeout flag */
+ bool timeout_flag;
+
+ /* Data received flag */
+ bool rcv_data_flag;
+
+ uint16_t start_handle;
+ uint16_t end_handle;
+ uint16_t dsc_handle;
+
+/* Variables for test results */
+ /* Reached timeout of scanning for test */
+ bool scan_timeout;
+
+ /* Number of received first packets of adverts */
+ int s6_rcv_adv_first;
+
+ /* Number of full received adverts */
+ int s6_rcv_adv_suc;
+
+ /* L2CAP Send Bit Rate */
+ int s10_bit_rate;
+
+ /* Average indication time */
+ int s12_notif_time;
+
+ /* Average notification time */
+ int s13_notif_time;
+
+ /* Average notification time */
+ int s14_notif_time;
+
+ /* Max size of received MTU */
+ int64_t s10_max_mtu;
+};
+
+#define STRESS_PAT_LEN 1650
+
+static const uint8_t test_6_pattern[STRESS_PAT_LEN] = {
+ /* Random data */
+ 0x00, 0x02, 0x00, 0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0a,
+ 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x12, 0x00, 0x14,
+ 0x00, 0x16, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x1c, 0x00, 0x1e,
+ 0x00, 0x20, 0x00, 0x22, 0x00, 0x24, 0x00, 0x26, 0x00, 0x28,
+ 0x00, 0x2a, 0x00, 0x2c, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x32,
+ 0x00, 0x34, 0x00, 0x36, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c,
+ 0x00, 0x3e, 0x00, 0x40, 0x00, 0x42, 0x00, 0x44, 0x00, 0x46,
+ 0x00, 0x48, 0x00, 0x4a, 0x00, 0x4c, 0x00, 0x4e, 0x00, 0x50,
+ 0x00, 0x52, 0x00, 0x54, 0x00, 0x56, 0x00, 0x58, 0x00, 0x5a,
+ 0x00, 0x5c, 0x00, 0x5e, 0x00, 0x60, 0x00, 0x62, 0x00, 0x64,
+ 0x00, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, 0x6c, 0x00, 0x6e,
+ 0x00, 0x70, 0x00, 0x72, 0x00, 0x74, 0x00, 0x76, 0x00, 0x78,
+ 0x00, 0x7a, 0x00, 0x7c, 0x00, 0x7e, 0x00, 0x80, 0x00, 0x82,
+ 0x00, 0x84, 0x00, 0x86, 0x00, 0x88, 0x00, 0x8a, 0x00, 0x8c,
+ 0x00, 0x8e, 0x00, 0x90, 0x00, 0x92, 0x00, 0x94, 0x00, 0x96,
+ 0x00, 0x98, 0x00, 0x9a, 0x00, 0x9c, 0x00, 0x9e, 0x00, 0xa0,
+ 0x00, 0xa2, 0x00, 0xa4, 0x00, 0xa6, 0x00, 0xa8, 0x00, 0xaa,
+ 0x00, 0xac, 0x00, 0xae, 0x00, 0xb0, 0x00, 0xb2, 0x00, 0xb4,
+ 0x00, 0xb6, 0x00, 0xb8, 0x00, 0xba, 0x00, 0xbc, 0x00, 0xbe,
+ 0x00, 0xc0, 0x00, 0xc2, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xc8,
+ 0x00, 0xca, 0x00, 0xcc, 0x00, 0xce, 0x00, 0xd0, 0x00, 0xd2,
+ 0x00, 0xd4, 0x00, 0xd6, 0x00, 0xd8, 0x00, 0xda, 0x00, 0xdc,
+ 0x00, 0xde, 0x00, 0xe0, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6,
+ 0x00, 0xe8, 0x00, 0xea, 0x00, 0xec, 0x00, 0xee, 0x00, 0xf0,
+ 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, 0xf8, 0x00, 0xfa,
+ 0x00, 0xfc, 0x00, 0xfe, 0x01, 0x01, 0x01, 0x03, 0x01, 0x05,
+ 0x01, 0x07, 0x01, 0x09, 0x01, 0x0b, 0x01, 0x0d, 0x01, 0x0f,
+ 0x01, 0x11, 0x01, 0x13, 0x01, 0x15, 0x01, 0x17, 0x01, 0x19,
+ 0x01, 0x1b, 0x01, 0x1d, 0x01, 0x1f, 0x01, 0x21, 0x01, 0x23,
+ 0x01, 0x25, 0x01, 0x27, 0x01, 0x29, 0x01, 0x2b, 0x01, 0x2d,
+ 0x01, 0x2f, 0x01, 0x31, 0x01, 0x33, 0x01, 0x35, 0x01, 0x37,
+ 0x01, 0x39, 0x01, 0x3b, 0x01, 0x3d, 0x01, 0x3f, 0x01, 0x41,
+ 0x01, 0x43, 0x01, 0x45, 0x01, 0x47, 0x01, 0x49, 0x01, 0x4b,
+ 0x01, 0x4d, 0x01, 0x4f, 0x01, 0x51, 0x01, 0x53, 0x01, 0x55,
+ 0x01, 0x57, 0x01, 0x59, 0x01, 0x5b, 0x01, 0x5d, 0x01, 0x5f,
+ 0x01, 0x61, 0x01, 0x63, 0x01, 0x65, 0x01, 0x67, 0x01, 0x69,
+ 0x01, 0x6b, 0x01, 0x6d, 0x01, 0x6f, 0x01, 0x71, 0x01, 0x73,
+ 0x01, 0x75, 0x01, 0x77, 0x01, 0x79, 0x01, 0x7b, 0x01, 0x7d,
+ 0x01, 0x7f, 0x01, 0x81, 0x01, 0x83, 0x01, 0x85, 0x01, 0x87,
+ 0x01, 0x89, 0x01, 0x8b, 0x01, 0x8d, 0x01, 0x8f, 0x01, 0x91,
+ 0x01, 0x93, 0x01, 0x95, 0x01, 0x97, 0x01, 0x99, 0x01, 0x9b,
+ 0x01, 0x9d, 0x01, 0x9f, 0x01, 0xa1, 0x01, 0xa3, 0x01, 0xa5,
+ 0x01, 0xa7, 0x01, 0xa9, 0x01, 0xab, 0x01, 0xad, 0x01, 0xaf,
+ 0x01, 0xb1, 0x01, 0xb3, 0x01, 0xb5, 0x01, 0xb7, 0x01, 0xb9,
+ 0x01, 0xbb, 0x01, 0xbd, 0x01, 0xbf, 0x01, 0xc1, 0x01, 0xc3,
+ 0x01, 0xc5, 0x01, 0xc7, 0x01, 0xc9, 0x01, 0xcb, 0x01, 0xcd,
+ 0x01, 0xcf, 0x01, 0xd1, 0x01, 0xd3, 0x01, 0xd5, 0x01, 0xd7,
+ 0x01, 0xd9, 0x01, 0xdb, 0x01, 0xdd, 0x01, 0xdf, 0x01, 0xe1,
+ 0x01, 0xe3, 0x01, 0xe5, 0x01, 0xe7, 0x01, 0xe9, 0x01, 0xeb,
+ 0x01, 0xed, 0x01, 0xef, 0x01, 0xf1, 0x01, 0xf3, 0x01, 0xf5,
+ 0x01, 0xf7, 0x01, 0xf9, 0x01, 0xfb, 0x01, 0xfd, 0x02, 0x00,
+ 0x02, 0x02, 0x02, 0x04, 0x02, 0x06, 0x02, 0x08, 0x02, 0x0a,
+ 0x02, 0x0c, 0x02, 0x0e, 0x02, 0x10, 0x02, 0x12, 0x02, 0x14,
+ 0x02, 0x16, 0x02, 0x18, 0x02, 0x1a, 0x02, 0x1c, 0x02, 0x1e,
+ 0x02, 0x20, 0x02, 0x22, 0x02, 0x24, 0x02, 0x26, 0x02, 0x28,
+ 0x02, 0x2a, 0x02, 0x2c, 0x02, 0x2e, 0x02, 0x30, 0x02, 0x32,
+ 0x02, 0x34, 0x02, 0x36, 0x02, 0x38, 0x02, 0x3a, 0x02, 0x3c,
+ 0x02, 0x3e, 0x02, 0x40, 0x02, 0x42, 0x02, 0x44, 0x02, 0x46,
+ 0x02, 0x48, 0x02, 0x4a, 0x02, 0x4c, 0x02, 0x4e, 0x02, 0x50,
+ 0x02, 0x52, 0x02, 0x54, 0x02, 0x56, 0x02, 0x58, 0x02, 0x5a,
+ 0x02, 0x5c, 0x02, 0x5e, 0x02, 0x60, 0x02, 0x62, 0x02, 0x64,
+ 0x02, 0x66, 0x02, 0x68, 0x02, 0x6a, 0x02, 0x6c, 0x02, 0x6e,
+ 0x02, 0x70, 0x02, 0x72, 0x02, 0x74, 0x02, 0x76, 0x02, 0x78,
+ 0x02, 0x7a, 0x02, 0x7c, 0x02, 0x7e, 0x02, 0x80, 0x02, 0x82,
+ 0x02, 0x84, 0x02, 0x86, 0x02, 0x88, 0x02, 0x8a, 0x02, 0x8c,
+ 0x02, 0x8e, 0x02, 0x90, 0x02, 0x92, 0x02, 0x94, 0x02, 0x96,
+ 0x02, 0x98, 0x02, 0x9a, 0x02, 0x9c, 0x02, 0x9e, 0x02, 0xa0,
+ 0x02, 0xa2, 0x02, 0xa4, 0x02, 0xa6, 0x02, 0xa8, 0x02, 0xaa,
+ 0x02, 0xac, 0x02, 0xae, 0x02, 0xb0, 0x02, 0xb2, 0x02, 0xb4,
+ 0x02, 0xb6, 0x02, 0xb8, 0x02, 0xba, 0x02, 0xbc, 0x02, 0xbe,
+ 0x02, 0xc0, 0x02, 0xc2, 0x02, 0xc4, 0x02, 0xc6, 0x02, 0xc8,
+ 0x02, 0xca, 0x02, 0xcc, 0x02, 0xce, 0x02, 0xd0, 0x02, 0xd2,
+ 0x02, 0xd4, 0x02, 0xd6, 0x02, 0xd8, 0x02, 0xda, 0x02, 0xdc,
+ 0x02, 0xde, 0x02, 0xe0, 0x02, 0xe2, 0x02, 0xe4, 0x02, 0xe6,
+ 0x02, 0xe8, 0x02, 0xea, 0x02, 0xec, 0x02, 0xee, 0x02, 0xf0,
+ 0x02, 0xf2, 0x02, 0xf4, 0x02, 0xf6, 0x02, 0xf8, 0x02, 0xfa,
+ 0x02, 0xfc, 0x02, 0xfe, 0x03, 0x01, 0x03, 0x03, 0x03, 0x05,
+ 0x03, 0x07, 0x03, 0x09, 0x03, 0x0b, 0x03, 0x0d, 0x03, 0x0f,
+ 0x03, 0x11, 0x03, 0x13, 0x03, 0x15, 0x03, 0x17, 0x03, 0x19,
+ 0x03, 0x1b, 0x03, 0x1d, 0x03, 0x1f, 0x03, 0x21, 0x03, 0x23,
+ 0x03, 0x25, 0x03, 0x27, 0x03, 0x29, 0x03, 0x2b, 0x03, 0x2d,
+ 0x03, 0x2f, 0x03, 0x31, 0x03, 0x33, 0x03, 0x35, 0x03, 0x37,
+ 0x03, 0x39, 0x03, 0x3b, 0x03, 0x3d, 0x03, 0x3f, 0x03, 0x41,
+ 0x03, 0x43, 0x03, 0x45, 0x03, 0x47, 0x03, 0x49, 0x03, 0x4b,
+ 0x03, 0x4d, 0x03, 0x4f, 0x03, 0x51, 0x03, 0x53, 0x03, 0x55,
+ 0x03, 0x57, 0x03, 0x59, 0x03, 0x5b, 0x03, 0x5d, 0x03, 0x5f,
+ 0x03, 0x61, 0x03, 0x63, 0x03, 0x65, 0x03, 0x67, 0x03, 0x69,
+ 0x03, 0x6b, 0x03, 0x6d, 0x03, 0x6f, 0x03, 0x71, 0x03, 0x73,
+ 0x03, 0x75, 0x03, 0x77, 0x03, 0x79, 0x03, 0x7b, 0x03, 0x7d,
+ 0x03, 0x7f, 0x03, 0x81, 0x03, 0x83, 0x03, 0x85, 0x03, 0x87,
+ 0x03, 0x89, 0x03, 0x8b, 0x03, 0x8d, 0x03, 0x8f, 0x03, 0x91,
+ 0x03, 0x93, 0x03, 0x95, 0x03, 0x97, 0x03, 0x99, 0x03, 0x9b,
+ 0x03, 0x9d, 0x03, 0x9f, 0x03, 0xa1, 0x03, 0xa3, 0x03, 0xa5,
+ 0x03, 0xa7, 0x03, 0xa9, 0x03, 0xab, 0x03, 0xad, 0x03, 0xaf,
+ 0x03, 0xb1, 0x03, 0xb3, 0x03, 0xb5, 0x03, 0xb7, 0x03, 0xb9,
+ 0x03, 0xbb, 0x03, 0xbd, 0x03, 0xbf, 0x03, 0xc1, 0x03, 0xc3,
+ 0x03, 0xc5, 0x03, 0xc7, 0x03, 0xc9, 0x03, 0xcb, 0x03, 0xcd,
+ 0x03, 0xcf, 0x03, 0xd1, 0x03, 0xd3, 0x03, 0xd5, 0x03, 0xd7,
+ 0x03, 0xd9, 0x03, 0xdb, 0x03, 0xdd, 0x03, 0xdf, 0x03, 0xe1,
+ 0x03, 0xe3, 0x03, 0xe5, 0x03, 0xe7, 0x03, 0xe9, 0x03, 0xeb,
+ 0x03, 0xed, 0x03, 0xef, 0x03, 0xf1, 0x03, 0xf3, 0x03, 0xf5,
+ 0x03, 0xf7, 0x03, 0xf9, 0x03, 0xfb, 0x03, 0xfd, 0x04, 0x00,
+ 0x04, 0x02, 0x04, 0x04, 0x04, 0x06, 0x04, 0x08, 0x04, 0x0a,
+ 0x04, 0x0c, 0x04, 0x0e, 0x04, 0x10, 0x04, 0x12, 0x04, 0x14,
+ 0x04, 0x16, 0x04, 0x18, 0x04, 0x1a, 0x04, 0x1c, 0x04, 0x1e,
+ 0x04, 0x20, 0x04, 0x22, 0x04, 0x24, 0x04, 0x26, 0x04, 0x28,
+ 0x04, 0x2a, 0x04, 0x2c, 0x04, 0x2e, 0x04, 0x30, 0x04, 0x32,
+ 0x04, 0x34, 0x04, 0x36, 0x04, 0x38, 0x04, 0x3a, 0x04, 0x3c,
+ 0x04, 0x3e, 0x04, 0x40, 0x04, 0x42, 0x04, 0x44, 0x04, 0x46,
+ 0x04, 0x48, 0x04, 0x4a, 0x04, 0x4c, 0x04, 0x4e, 0x04, 0x50,
+ 0x04, 0x52, 0x04, 0x54, 0x04, 0x56, 0x04, 0x58, 0x04, 0x5a,
+ 0x04, 0x5c, 0x04, 0x5e, 0x04, 0x60, 0x04, 0x62, 0x04, 0x64,
+ 0x04, 0x66, 0x04, 0x68, 0x04, 0x6a, 0x04, 0x6c, 0x04, 0x6e,
+ 0x04, 0x70, 0x04, 0x72, 0x04, 0x74, 0x04, 0x76, 0x04, 0x78,
+ 0x04, 0x7a, 0x04, 0x7c, 0x04, 0x7e, 0x04, 0x80, 0x04, 0x82,
+ 0x04, 0x84, 0x04, 0x86, 0x04, 0x88, 0x04, 0x8a, 0x04, 0x8c,
+ 0x04, 0x8e, 0x04, 0x90, 0x04, 0x92, 0x04, 0x94, 0x04, 0x96,
+ 0x04, 0x98, 0x04, 0x9a, 0x04, 0x9c, 0x04, 0x9e, 0x04, 0xa0,
+ 0x04, 0xa2, 0x04, 0xa4, 0x04, 0xa6, 0x04, 0xa8, 0x04, 0xaa,
+ 0x04, 0xac, 0x04, 0xae, 0x04, 0xb0, 0x04, 0xb2, 0x04, 0xb4,
+ 0x04, 0xb6, 0x04, 0xb8, 0x04, 0xba, 0x04, 0xbc, 0x04, 0xbe,
+ 0x04, 0xc0, 0x04, 0xc2, 0x04, 0xc4, 0x04, 0xc6, 0x04, 0xc8,
+ 0x04, 0xca, 0x04, 0xcc, 0x04, 0xce, 0x04, 0xd0, 0x04, 0xd2,
+ 0x04, 0xd4, 0x04, 0xd6, 0x04, 0xd8, 0x04, 0xda, 0x04, 0xdc,
+ 0x04, 0xde, 0x04, 0xe0, 0x04, 0xe2, 0x04, 0xe4, 0x04, 0xe6,
+ 0x04, 0xe8, 0x04, 0xea, 0x04, 0xec, 0x04, 0xee, 0x04, 0xf0,
+ 0x04, 0xf2, 0x04, 0xf4, 0x04, 0xf6, 0x04, 0xf8, 0x04, 0xfa,
+ 0x04, 0xfc, 0x04, 0xfe, 0x05, 0x01, 0x05, 0x03, 0x05, 0x05,
+ 0x05, 0x07, 0x05, 0x09, 0x05, 0x0b, 0x05, 0x0d, 0x05, 0x0f,
+ 0x05, 0x11, 0x05, 0x13, 0x05, 0x15, 0x05, 0x17, 0x05, 0x19,
+ 0x05, 0x1b, 0x05, 0x1d, 0x05, 0x1f, 0x05, 0x21, 0x05, 0x23,
+ 0x05, 0x25, 0x05, 0x27, 0x05, 0x29, 0x05, 0x2b, 0x05, 0x2d,
+ 0x05, 0x2f, 0x05, 0x31, 0x05, 0x33, 0x05, 0x35, 0x05, 0x37,
+ 0x05, 0x39, 0x05, 0x3b, 0x05, 0x3d, 0x05, 0x3f, 0x05, 0x41,
+ 0x05, 0x43, 0x05, 0x45, 0x05, 0x47, 0x05, 0x49, 0x05, 0x4b,
+ 0x05, 0x4d, 0x05, 0x4f, 0x05, 0x51, 0x05, 0x53, 0x05, 0x55,
+ 0x05, 0x57, 0x05, 0x59, 0x05, 0x5b, 0x05, 0x5d, 0x05, 0x5f,
+ 0x05, 0x61, 0x05, 0x63, 0x05, 0x65, 0x05, 0x67, 0x05, 0x69,
+ 0x05, 0x6b, 0x05, 0x6d, 0x05, 0x6f, 0x05, 0x71, 0x05, 0x73,
+ 0x05, 0x75, 0x05, 0x77, 0x05, 0x79, 0x05, 0x7b, 0x05, 0x7d,
+ 0x05, 0x7f, 0x05, 0x81, 0x05, 0x83, 0x05, 0x85, 0x05, 0x87,
+ 0x05, 0x89, 0x05, 0x8b, 0x05, 0x8d, 0x05, 0x8f, 0x05, 0x91,
+ 0x05, 0x93, 0x05, 0x95, 0x05, 0x97, 0x05, 0x99, 0x05, 0x9b,
+ 0x05, 0x9d, 0x05, 0x9f, 0x05, 0xa1, 0x05, 0xa3, 0x05, 0xa5,
+ 0x05, 0xa7, 0x05, 0xa9, 0x05, 0xab, 0x05, 0xad, 0x05, 0xaf,
+ 0x05, 0xb1, 0x05, 0xb3, 0x05, 0xb5, 0x05, 0xb7, 0x05, 0xb9,
+ 0x05, 0xbb, 0x05, 0xbd, 0x05, 0xbf, 0x05, 0xc1, 0x05, 0xc3,
+ 0x05, 0xc5, 0x05, 0xc7, 0x05, 0xc9, 0x05, 0xcb, 0x05, 0xcd,
+ 0x05, 0xcf, 0x05, 0xd1, 0x05, 0xd3, 0x05, 0xd5, 0x05, 0xd7,
+ 0x05, 0xd9, 0x05, 0xdb, 0x05, 0xdd, 0x05, 0xdf, 0x05, 0xe1,
+ 0x05, 0xe3, 0x05, 0xe5, 0x05, 0xe7, 0x05, 0xe9, 0x05, 0xeb,
+ 0x05, 0xed, 0x05, 0xef, 0x05, 0xf1, 0x05, 0xf3, 0x05, 0xf5,
+ 0x05, 0xf7, 0x05, 0xf9, 0x05, 0xfb, 0x05, 0xfd, 0x06, 0x00,
+ 0x06, 0x02, 0x06, 0x04, 0x06, 0x06, 0x06, 0x08, 0x06, 0x0a,
+ 0x06, 0x0c, 0x06, 0x0e, 0x06, 0x10, 0x06, 0x12, 0x06, 0x14,
+ 0x06, 0x16, 0x06, 0x18, 0x06, 0x1a, 0x06, 0x1c, 0x06, 0x1e,
+ 0x06, 0x20, 0x06, 0x22, 0x06, 0x24, 0x06, 0x26, 0x06, 0x28,
+ 0x06, 0x2a, 0x06, 0x2c, 0x06, 0x2e, 0x06, 0x30, 0x06, 0x32,
+ 0x06, 0x34, 0x06, 0x36, 0x06, 0x38, 0x06, 0x3a, 0x06, 0x3c,
+ 0x06, 0x3e, 0x06, 0x40, 0x06, 0x42, 0x06, 0x44, 0x06, 0x46,
+ 0x06, 0x48, 0x06, 0x4a, 0x06, 0x4c, 0x06, 0x4e, 0x06, 0x50,
+ 0x06, 0x52, 0x06, 0x54, 0x06, 0x56, 0x06, 0x58, 0x06, 0x5a,
+ 0x06, 0x5c, 0x06, 0x5e, 0x06, 0x60, 0x06, 0x62, 0x06, 0x64,
+ 0x06, 0x66, 0x06, 0x68, 0x06, 0x6a, 0x06, 0x6c, 0x06, 0x6e,
+ 0x06, 0x70, 0x06, 0x72, 0x06, 0x74, 0x06, 0x76, 0x06, 0x78,
+};
+
+void stress_clear_ctx_reusable_var(struct com_stress_test_ctx *ctx);
+
+void com_stress_print_report(const struct com_stress_test_ctx test_ctxs[]);
+
+int stress_fill_mbuf_with_pattern(struct os_mbuf *om, uint16_t len);
+
+void stress_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu);
+
+void stress_l2cap_coc_accept(uint16_t peer_mtu, struct ble_l2cap_chan *chan);
+
+void stress_start_timer(uint32_t timeout_ms, os_event_fn *ev_cb);
+
+int64_t stress_calc_bit_rate(int64_t us, int64_t bytes_num);
+
+void stress_find_svc_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn);
+void stress_find_chr_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ const ble_uuid_t *chr_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn);
+
+void stress_find_dsc_handle(uint16_t conn_handle, const ble_uuid_t *srv_uuid,
+ const ble_uuid_t *chr_uuid, const ble_uuid_t *dsc_uuid,
+ stress_gatt_disc_end_fn *disc_end_fn);
+#ifdef __cplusplus
+}
+#endif
+
+#endif //BLE_TGT_STRESS_H
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.c b/src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.c
new file mode 100644
index 00000000..a6d845c5
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.c
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "stress_gatt.h"
+
+uint16_t hrs_hrm_handle = 0xffff;
+
+static int
+stress_gatt_access_cb(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
+ {
+ /* Service: Heart-rate */
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = BLE_UUID16_DECLARE(STRESS_GATT_UUID),
+ .characteristics = (struct ble_gatt_chr_def[]) {
+ {
+ /* Characteristic: read test */
+ .uuid = BLE_UUID16_DECLARE(STRESS_GATT_READ_UUID),
+ .access_cb = stress_gatt_access_cb,
+ .val_handle = &hrs_hrm_handle,
+ .flags = BLE_GATT_CHR_F_READ,
+ },
+ {
+ /* Characteristic: write test */
+ .uuid = BLE_UUID16_DECLARE(STRESS_GATT_WRITE_UUID),
+ .access_cb = stress_gatt_access_cb,
+ .val_handle = &hrs_hrm_handle,
+ .flags = BLE_GATT_CHR_F_WRITE,
+ },
+ {
+ /* Characteristic: notify test */
+ .uuid = BLE_UUID16_DECLARE(STRESS_GATT_NOTIFY_UUID),
+ .access_cb = stress_gatt_access_cb,
+ .val_handle = &hrs_hrm_handle,
+ .flags = BLE_GATT_CHR_F_NOTIFY,
+ },
+ {
+ /* Characteristic: indicate test */
+ .uuid = BLE_UUID16_DECLARE(STRESS_GATT_INDICATE_UUID),
+ .access_cb = stress_gatt_access_cb,
+ .val_handle = &hrs_hrm_handle,
+ .flags = BLE_GATT_CHR_F_INDICATE,
+ },
+ {
+ 0, /* No more characteristics in this service */
+ },}
+ },
+ {
+ 0, /* No more services */
+ },
+};
+
+static int
+stress_gatt_access_cb(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+ /* Sensor location, set to "Chest" */
+ static uint8_t chr_value[] = "Hello";
+ uint16_t uuid;
+ int rc;
+
+ //chr_value = (uint8_t)rand() % 256;
+ uuid = ble_uuid_u16(ctxt->chr->uuid);
+
+ switch(uuid){
+ case STRESS_GATT_READ_UUID:
+ MODLOG_DFLT(INFO, "GATT Read event\n");
+ rc = os_mbuf_append(ctxt->om, &chr_value, sizeof(chr_value));
+ assert(rc == 0);
+ //return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+ return 0;
+ case STRESS_GATT_WRITE_UUID:
+ MODLOG_DFLT(INFO, "GATT Write event\n");
+ print_mbuf(ctxt->om);
+ return 0;
+ case STRESS_GATT_NOTIFY_UUID:
+ MODLOG_DFLT(INFO, "GATT Notify event\n");
+ return 0;
+ case STRESS_GATT_INDICATE_UUID:
+ MODLOG_DFLT(INFO, "GATT Indicate event\n");
+ return 0;
+ default:
+ MODLOG_DFLT(ERROR, "GATT UUID does not exist\n");
+ assert(0);
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+void
+gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+ char buf[BLE_UUID_STR_LEN];
+
+ switch (ctxt->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
+ ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+ ctxt->svc.handle);
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ MODLOG_DFLT(DEBUG, "registering characteristic %s with "
+ "def_handle=%d val_handle=%d\n",
+ ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+ ctxt->chr.def_handle,
+ ctxt->chr.val_handle);
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
+ ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+ ctxt->dsc.handle);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+int
+gatt_svr_init(void)
+{
+ int rc;
+
+ rc = ble_gatts_count_cfg(gatt_svr_svcs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_gatts_add_svcs(gatt_svr_svcs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.h b/src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.h
new file mode 100644
index 00000000..3344fe2d
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/stress_gatt.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef BLE_TGT_STRESS_GATT_H
+#define BLE_TGT_STRESS_GATT_H
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "nimble/ble.h"
+#include "modlog/modlog.h"
+#include "misc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint16_t hrs_hrm_handle;
+
+/* Heart-rate configuration */
+#define STRESS_GATT_UUID 0xC0DE
+#define STRESS_GATT_READ_UUID 0xC1DE
+#define STRESS_GATT_WRITE_UUID 0xC2DE
+#define STRESS_GATT_INDICATE_UUID 0xC3DE
+#define STRESS_GATT_NOTIFY_UUID 0xC4DE
+
+int gatt_svr_init(void);
+
+void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //BLE_TGT_STRESS_GATT_H
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c
new file mode 100644
index 00000000..b73adc8a
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c
@@ -0,0 +1,1671 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <host/ble_gap.h>
+#include <console/console.h>
+#include <host/util/util.h>
+#include <host/ble_l2cap.h>
+#include "tx_stress.h"
+
+/* Main test task priority. Set a high value so that the task does not
+ * interfere with event handling */
+#define TX_STRESS_MAIN_TASK_PRIO 0xf0
+#define BASE_UUID_LEN 13
+
+/* Contexts for stress tests. */
+static struct com_stress_test_ctx tx_stress_ctxD = {
+ .conn_handle = 0xffff,
+ .cur_test_id = 0,
+};
+
+static struct com_stress_test_ctx *tx_stress_ctx;
+
+/* Define stack, object and semaphore for test main task. */
+#define TX_STRESS_MAIN_TASK_STACK_SIZE (500)
+static struct os_task tx_stress_main_task;
+static os_stack_t tx_stress_main_task_stack[TX_STRESS_MAIN_TASK_STACK_SIZE];
+static struct os_sem tx_stress_main_sem;
+/* Test use case and address of test advertiser. */
+static int tx_stress_use_case;
+static int completed_tests = 0;
+
+static void
+tx_stress_on_test_finish(int test_num)
+{
+ console_printf("\033[0;32m\nStress test %d completed\033[0m\n", test_num);
+ ++completed_tests;
+ tx_stress_ctx->completed[test_num] = true;
+ os_sem_release(&tx_stress_main_sem);
+}
+
+static void
+tx_stress_simple_scan(ble_gap_event_fn *cb, uint16_t duration)
+{
+ uint8_t own_addr_type;
+ struct ble_gap_ext_disc_params params = {0};
+ int rc;
+
+ /* Figure out address to use while scanning. */
+ rc = ble_hs_id_infer_auto(0, &own_addr_type);
+ if (rc != 0) {
+ console_printf("\033[0;31mError determining own address type; "
+ "rc=%d\033[0m\n", rc);
+ assert(0);
+ }
+
+ params.itvl = BLE_GAP_SCAN_FAST_INTERVAL_MAX;
+ params.passive = 1;
+ params.window = BLE_GAP_SCAN_FAST_WINDOW;
+
+ rc = ble_gap_ext_disc(own_addr_type, duration, 0, 1, 0, 0, &params, NULL,
+ cb, NULL);
+
+ if (rc != 0) {
+ console_printf("\033[0;31mError initiating GAP discovery procedure"
+ "; rc=%d\033[0m\n", rc);
+ }
+}
+
+static int
+tx_stress_simple_connect(ble_gap_event_fn *cb, int test_num)
+{
+ uint8_t own_addr_type;
+ int rc;
+
+ /* Set so any PHY mask allowed. */
+ ble_gap_set_prefered_default_le_phy(TX_PHY_MASK, RX_PHY_MASK);
+
+ /* Figure out address to use while connecting. */
+ rc = ble_hs_id_infer_auto(0, &own_addr_type);
+ if (rc != 0) {
+ MODLOG_DFLT(INFO, "\033[0;31mError determining own address type; "
+ "rc=%d\033[0m\n", rc);
+ return rc;
+ }
+
+ MODLOG_DFLT(INFO, "Connection attempt: %d\n",
+ ++tx_stress_ctx->con_stat[test_num].attempts_num);
+
+ rc = ble_gap_ext_connect(own_addr_type, &tx_stress_ctx->dev_addr,
+ 10000,
+ BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK,
+ NULL, NULL, NULL, cb, NULL);
+
+ if (rc != 0) {
+ MODLOG_DFLT(INFO, "\033[0;31mError during connection; rc=%d\033[0m\n",
+ rc);
+ }
+
+ return rc;
+}
+
+static int
+tx_stress_find_test(struct ble_gap_ext_disc_desc *ext_disc)
+{
+ struct ble_hs_adv_fields fields;
+ int data_len;
+ int rc;
+
+ /* Parser refuses greater length data than 31. But known UUID128 will be
+ * in first 31 bytes of adv data first packet. */
+ if (ext_disc->length_data > 31) {
+ data_len = 31;
+ } else {
+ data_len = ext_disc->length_data;
+ }
+
+ /* Parse part of adv data. */
+ ble_hs_adv_parse_fields(&fields, ext_disc->data, data_len);
+ print_adv_fields(&fields);
+
+ /* UUID128 service data of stress test advert includes only UUID128. */
+ if (fields.svc_data_uuid128_len != 16) {
+ return -1;
+ }
+
+ /* Check if service data include known UUID128. */
+ rc = memcmp(fields.svc_data_uuid128, (uint8_t[]) {0xC0, 0xDE}, 2);
+ if (rc) {
+ return -1;
+ }
+
+ rc = memcmp(fields.svc_data_uuid128 + 3, MYNEWT_VAL(BLE_STRESS_UUID_BASE),
+ BASE_UUID_LEN);
+
+ if (rc != 0) {
+ return -1;
+ }
+
+ /* This UUID 128 byte indicates the stress test ID to be executed. */
+ return fields.svc_data_uuid128[2];
+}
+
+static int
+tx_stress_switcher_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ return 0;
+ } else if (event->connect.status == BLE_HS_ETIMEOUT_HCI) {
+ MODLOG_DFLT(INFO, "Connection timeout\n");
+ } else {
+ MODLOG_DFLT(INFO, "Error: connection attempt failed; status=%d\n",
+ event->connect.status);
+ }
+ /* Connect to rx device just to give it a signal to switch test. */
+ tx_stress_simple_connect(tx_stress_switcher_gap_event,
+ tx_stress_ctx->cur_test_id);
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ os_sem_release(&tx_stress_main_sem);
+ return 0;
+
+ case BLE_GAP_EVENT_EXT_DISC:
+ /* Check if caught advert contains known UUID128. The UUID128
+ * contains the ID of test use case to be executed. */
+ rc = tx_stress_find_test(&event->ext_disc);
+ if (rc == 0) {
+ tx_stress_ctx->dev_addr = event->ext_disc.addr;
+ /* Stop scanning. */
+ ble_gap_disc_cancel();
+ /* Add token to semaphore. Main task will start the test. */
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISC_COMPLETE:
+ MODLOG_DFLT(INFO, "Discovery complete; reason=%d\n",
+ event->disc_complete.reason);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static void
+tx_stress_switch_test()
+{
+ tx_stress_simple_scan(tx_stress_switcher_gap_event, 0);
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+
+ tx_stress_simple_connect(tx_stress_switcher_gap_event, 0);
+}
+
+static int
+tx_stress_1_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ MODLOG_DFLT(INFO, "Connection %s; status=%d ",
+ event->connect.status == 0 ? "established" : "failed",
+ event->connect.status);
+
+ if (event->connect.status == 0) {
+ /* Connection successfully established. In this use case
+ * it is error of 'Connect cancel'. Stress test failed. */
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ ++tx_stress_ctx->con_stat[1].num;
+
+ ble_gap_terminate(event->connect.conn_handle, BLE_ERR_NO_PAIRING);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static void
+tx_stress_1_test()
+{
+ int rc;
+ uint8_t own_addr_type;
+ ble_addr_t rnd_rx_addr;
+ int delay_time;
+
+ rc = ble_gap_disc_active();
+ assert(rc == 0);
+
+ /* Figure out address to use while advertising. */
+ rc = ble_hs_id_infer_auto(0, &own_addr_type);
+ if (rc != 0) {
+ MODLOG_DFLT(INFO, "\033[0;31mError determining own address type; "
+ "rc=%d\033[0m\n", rc);
+ os_sem_release(&tx_stress_main_sem);
+ return;
+ }
+
+ while (tx_stress_ctx->con_stat[1].attempts_num <
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Rand ble address to connect*/
+ rc = ble_hs_id_gen_rnd(1, &rnd_rx_addr);
+ assert (rc == 0);
+
+ MODLOG_DFLT(INFO, "Connection attempt; num=%d\n",
+ ++tx_stress_ctx->con_stat[1].attempts_num);
+
+ rc = ble_gap_connect(own_addr_type, &rnd_rx_addr, 10000, NULL,
+ tx_stress_1_gap_event, NULL);
+
+ if (rc != 0) {
+ MODLOG_DFLT(INFO, "\033[0;31mConnection error; rc=%d\033[0m\n",
+ rc);
+ os_sem_release(&tx_stress_main_sem);
+ return;
+ }
+
+ MODLOG_DFLT(INFO, "Connect cancel\n");
+ ble_gap_conn_cancel();
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ console_printf(
+ "\033[0;32m\nFirst part of test completed\nStart second part: "
+ "Connect->random delay->cancel\n\033[0m");
+
+ while (tx_stress_ctx->con_stat[1].attempts_num <
+ 2 * MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Rand ble address to connect*/
+ rc = ble_hs_id_gen_rnd(1, &rnd_rx_addr);
+ assert (rc == 0);
+
+ MODLOG_DFLT(INFO, "Connection attempt; num=%d\n",
+ ++tx_stress_ctx->con_stat[1].attempts_num);
+
+ delay_time = rand() % 1000;
+
+ MODLOG_DFLT(INFO, "Time to delay=%d\n", delay_time);
+
+ rc = ble_gap_connect(own_addr_type, &rnd_rx_addr, 10000, NULL,
+ tx_stress_1_gap_event, NULL);
+
+ if (rc != 0) {
+ MODLOG_DFLT(INFO, "\033[0;31mConnection error; rc=%d\033[0m\n",
+ rc);
+ os_sem_release(&tx_stress_main_sem);
+ return;
+ }
+
+ os_time_delay(os_time_ms_to_ticks32(delay_time));
+
+ MODLOG_DFLT(INFO, "Connect cancel\n");
+ ble_gap_conn_cancel();
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ tx_stress_on_test_finish(1);
+}
+
+static int
+tx_stress_2_gap_event(struct ble_gap_event *event, void *arg)
+{
+ struct ble_gap_conn_desc desc;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+
+ ++tx_stress_ctx->con_stat[2].num;
+ rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+ assert(rc == 0);
+
+ tx_stress_ctx->conn_handle = desc.conn_handle;
+
+ ble_gap_terminate(event->connect.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+
+ if (tx_stress_ctx->con_stat[2].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ tx_stress_on_test_finish(2);
+ return 0;
+ }
+ tx_stress_simple_connect(tx_stress_2_gap_event,
+ tx_stress_ctx->cur_test_id);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_3_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ ++tx_stress_ctx->con_stat[3].num;
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+
+ rc = ble_gap_terminate(event->connect.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+
+ MODLOG_DFLT(INFO, "rc=%d\n", rc);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+
+ if (tx_stress_ctx->con_stat[3].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ tx_stress_on_test_finish(3);
+ return 0;
+ }
+ tx_stress_simple_connect(tx_stress_3_gap_event,
+ tx_stress_ctx->cur_test_id);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_4_con_update(void)
+{
+ int rc;
+
+ /* With every next update at least one param must change. Otherwise no
+ * event occurs and test will not be continued */
+ struct ble_gap_upd_params params = {
+ .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN,
+ .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX,
+ .latency = BLE_GAP_INITIAL_CONN_LATENCY,
+ /* So let's change e.g. timeout value. Put ...% 2 ? 1 : 2 to make sure
+ * that value won't grow significantly and will be different with every
+ * iteration. */
+ .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT +
+ (tx_stress_ctx->con_stat[4].prms_upd_num % 2 ?
+ 1 : 2),
+ .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN,
+ .max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN,
+ };
+
+ rc = ble_gap_update_params(tx_stress_ctx->conn_handle, &params);
+
+ if (rc == BLE_HS_ENOTCONN) {
+ MODLOG_DFLT(INFO, "Device disconnected. Connection update failed\n");
+ assert(0);
+ }
+
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "\033[0;31mError during connection update; "
+ "rc=%d\033[0m\n", rc);
+ assert(0);
+ }
+
+ return rc;
+}
+
+static int
+tx_stress_4_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ ++tx_stress_ctx->con_stat[4].attempts_num;
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+
+ ++tx_stress_ctx->con_stat[4].num;
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ tx_stress_4_con_update();
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ tx_stress_on_test_finish(4);
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ if (event->conn_update.status != 0) {
+ MODLOG_DFLT(INFO, "Connection update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "Connection updated; num=%d\n",
+ ++tx_stress_ctx->con_stat[4].prms_upd_num);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (tx_stress_ctx->con_stat[4].prms_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ ble_gap_terminate(tx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ } else {
+ /* Update connection. */
+ rc = tx_stress_4_con_update();
+
+ if (rc != 0) {
+ MODLOG_DFLT(INFO, "\033[0;31mError: update fail; "
+ "rc=%d\033[0m\n", rc);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ MODLOG_DFLT(INFO, "Connection update request\n");
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_5_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+
+ ++tx_stress_ctx->con_stat[5].num;
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ console_printf("\033[0;31mError: Update fail; "
+ "status=%d\033[0m\n", event->connect.status);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ tx_stress_on_test_finish(5);
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ if (event->conn_update.status != 0) {
+ MODLOG_DFLT(INFO, "Connection update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "Connection updated; num=%d\n",
+ ++tx_stress_ctx->con_stat[5].prms_upd_num);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (tx_stress_ctx->con_stat[5].prms_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ ble_gap_terminate(tx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ MODLOG_DFLT(INFO, "Connection update request\n");
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_6_gap_event(struct ble_gap_event *event, void *arg)
+{
+ static int start_id = 0;
+ int use_case = 0;
+ int adv_pattern_len;
+ const uint8_t *adv_pattern;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_EXT_DISC:
+
+ /* Instance 0 reserved for SWITCH advert. */
+ if (event->ext_disc.sid == 0) {
+ return 0;
+ }
+
+ /* Check if advertiser is known rx device. */
+ if (memcmp(tx_stress_ctx->dev_addr.val,
+ event->ext_disc.addr.val, 6) != 0) {
+ return 0;
+ }
+
+ /* Return -1 if not first package of advert. */
+ use_case = tx_stress_find_test(&event->ext_disc);
+
+ if (use_case > 0) {
+ /* If first package of advert */
+ ++tx_stress_ctx->s6_rcv_adv_first;
+ start_id = 0;
+ adv_pattern = &event->ext_disc.data[29];
+ adv_pattern_len = event->ext_disc.length_data - 29;
+ } else {
+ if (start_id == 0) {
+ return 0;
+ }
+ /* If not first package of advert */
+ adv_pattern = event->ext_disc.data;
+ adv_pattern_len = event->ext_disc.length_data;
+ }
+
+ /* Check data pattern */
+ if (memcmp(adv_pattern, test_6_pattern + start_id,
+ adv_pattern_len) != 0) {
+ /* Pattern does not match. May lost some data or package.
+ * Reset data pattern index. */
+ start_id = 0;
+ return 0;
+ }
+
+ /* At the next adv data package, start comparing from this index.*/
+ start_id += adv_pattern_len;
+
+ /* Check if last packet of advert. */
+ if (event->ext_disc.data_status ==
+ BLE_GAP_EXT_ADV_DATA_STATUS_COMPLETE) {
+ /* Got all packets of advert. */
+ ++tx_stress_ctx->s6_rcv_adv_suc;
+ MODLOG_DFLT(INFO, "Got all packets of advert. num=%d\n",
+ tx_stress_ctx->s6_rcv_adv_suc);
+ console_printf("\033[0;32m>\033[0m");
+ start_id = 0;
+
+ if (tx_stress_ctx->s6_rcv_adv_suc >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ /* Stop scanning. */
+ ble_gap_disc_cancel();
+ tx_stress_on_test_finish(6);
+ }
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISC_COMPLETE:
+ MODLOG_DFLT(INFO, "Discovery complete; reason=%d\n",
+ event->disc_complete.reason);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static void
+tx_stress_6_perform(void)
+{
+ tx_stress_simple_scan(tx_stress_6_gap_event, 0);
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+ tx_stress_switch_test();
+}
+
+static int
+tx_stress_7_phy_update(void)
+{
+ int rc;
+ uint8_t tx_phys_mask;
+ uint8_t rx_phys_mask;
+
+ ble_gap_read_le_phy(tx_stress_ctx->conn_handle, &tx_phys_mask,
+ &rx_phys_mask);
+
+
+ /* With every next update at least one param must change */
+ switch (rx_phys_mask) {
+ case BLE_GAP_LE_PHY_1M_MASK:
+ rx_phys_mask = BLE_GAP_LE_PHY_2M_MASK;
+ break;
+ case BLE_GAP_LE_PHY_2M_MASK:
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ rx_phys_mask = BLE_GAP_LE_PHY_CODED_MASK;
+ break;
+ case BLE_GAP_LE_PHY_CODED_MASK:
+#endif
+ rx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ default:
+ rx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ }
+
+ switch (tx_phys_mask) {
+ case BLE_GAP_LE_PHY_1M_MASK:
+ tx_phys_mask = BLE_GAP_LE_PHY_2M_MASK;
+ break;
+ case BLE_GAP_LE_PHY_2M_MASK:
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
+ tx_phys_mask = BLE_GAP_LE_PHY_CODED_MASK;
+ break;
+ case BLE_GAP_LE_PHY_CODED_MASK:
+#endif
+ tx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ default:
+ tx_phys_mask = BLE_GAP_LE_PHY_1M_MASK;
+ break;
+ }
+
+ rc = ble_gap_set_prefered_le_phy(tx_stress_ctx->conn_handle,
+ tx_phys_mask, rx_phys_mask, 0);
+
+ if (rc == BLE_HS_ENOTCONN) {
+ MODLOG_DFLT(INFO, "Device disconnected. Connection update failed\n");
+ return rc;
+ }
+
+ if (rc != 0) {
+ MODLOG_DFLT(ERROR, "\033[0;31mError during PHY update; "
+ "rc=%d\033[0m\n", rc);
+ }
+
+ return rc;
+}
+
+static int
+tx_stress_7_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+
+ ++tx_stress_ctx->con_stat[7].num;
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ tx_stress_7_phy_update();
+ } else {
+ console_printf("\033[0;31mError: Update fail; "
+ "status=%d\033[0m\n", event->connect.status);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ tx_stress_on_test_finish(7);
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ MODLOG_DFLT(INFO, "Connection updated\n");
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ MODLOG_DFLT(INFO, "Connection update request\n");
+ return 0;
+
+ case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
+ if (event->phy_updated.status != 0) {
+ MODLOG_DFLT(INFO, "PHY update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "PHY updated; num=%d; rx:%d, tx:%d\n",
+ ++tx_stress_ctx->con_stat[7].phy_upd_num,
+ event->phy_updated.rx_phy, event->phy_updated.tx_phy);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (tx_stress_ctx->con_stat[7].phy_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ ble_gap_terminate(tx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ } else {
+ /* Update connection. */
+ rc = tx_stress_7_phy_update();
+ if (rc != 0) {
+ console_printf("\033[0;31mError: PHPY update fail; "
+ "rc=%d\033[0m\n", event->phy_updated.status);
+ assert(0);
+ }
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_8_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+
+ ++tx_stress_ctx->con_stat[8].num;
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ tx_stress_on_test_finish(8);
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ if (event->conn_update.status != 0) {
+ MODLOG_DFLT(INFO, "Connection update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "Connection updated; num=%d\n",
+ ++tx_stress_ctx->con_stat[8].prms_upd_num);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ MODLOG_DFLT(INFO, "Connection update request\n");
+ return 0;
+
+ case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
+ if (event->phy_updated.status != 0) {
+ MODLOG_DFLT(INFO, "PHY update failed\n");
+ } else {
+ MODLOG_DFLT(INFO, "PHY updated; num=%d\n",
+ ++tx_stress_ctx->con_stat[8].phy_upd_num);
+ console_printf("\033[0;32m>\033[0m");
+ }
+
+ if (tx_stress_ctx->con_stat[8].phy_upd_num >=
+ MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ ble_gap_terminate(tx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ }
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_9_gap_event(struct ble_gap_event *event, void *arg)
+{
+ ble_addr_t addr;
+ int test;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_EXT_DISC:
+ /* Looking for next instance of test 9 advert. */
+ test = tx_stress_find_test(&event->ext_disc);
+ /* To avoid messing by rest of test 9 events in queue, check if handle
+ * filled */
+ if (test == 9 && tx_stress_ctx->conn_handle == 0xffff) {
+ tx_stress_ctx->conn_handle = 0;
+ ble_gap_disc_cancel();
+ tx_stress_ctx->dev_addr = event->ext_disc.addr;
+ tx_stress_simple_connect(tx_stress_9_gap_event,
+ tx_stress_ctx->cur_test_id);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISC_COMPLETE:
+ if (event->disc_complete.reason == 0 && !tx_stress_ctx->completed[9]) {
+ console_printf("\033[0;31mScanning timeout\033[0m");
+ tx_stress_ctx->completed[9] = true;
+ os_sem_release(&tx_stress_main_sem);
+ return 0;
+ }
+ break;
+
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ MODLOG_DFLT(INFO, "Connections num: %d\n",
+ ++tx_stress_ctx->con_stat[9].num);
+ console_printf("\033[0;32m>\033[0m");
+ /* Remember max number of handled connections */
+ if (tx_stress_ctx->con_stat[9].num >
+ tx_stress_ctx->con_stat[9].max_num) {
+ tx_stress_ctx->con_stat[9].max_num = tx_stress_ctx->con_stat[9].num;
+ }
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ }
+ break;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d ", event->disconnect.reason);
+ console_printf("\033[0;31mX\033[0m");
+ MODLOG_DFLT(INFO, "Connections num: %d\n",
+ --tx_stress_ctx->con_stat[9].num);
+
+ if (tx_stress_ctx->con_stat[9].num == 0) {
+ os_sem_release(&tx_stress_main_sem);
+ return 0;
+ }
+ break;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+
+ if (tx_stress_ctx->completed[9]) {
+ return 0;
+ }
+
+ /* End use case after specified number of scan times or max config number
+ * of connections */
+ if (tx_stress_ctx->con_stat[9].attempts_num <
+ MYNEWT_VAL(BLE_STRESS_REPEAT) &&
+ tx_stress_ctx->con_stat[9].max_num < MYNEWT_VAL(BLE_MAX_CONNECTIONS)) {
+ if (ble_gap_disc_active() == 0) {
+ /* Generate and set new random address */
+ ble_hs_id_gen_rnd(0, &addr);
+ ble_hs_id_set_rnd(addr.val);
+ tx_stress_ctx->conn_handle = 0xffff;
+ /* Scan for next instance of the test. */
+ tx_stress_simple_scan(tx_stress_9_gap_event, 2000);
+ }
+ } else {
+ tx_stress_ctx->completed[9] = true;
+ os_sem_release(&tx_stress_main_sem);
+ }
+ return 0;
+}
+
+static void
+tx_stress_9_perform()
+{
+ int i, rc;
+
+ /* Scan for next instance of the test. */
+ tx_stress_simple_scan(tx_stress_9_gap_event, 2000);
+
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+
+ /* On use case finishing terminate all handled connections */
+ for (i = 0; i <= MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) {
+ rc = ble_gap_conn_find(i, NULL);
+ if (rc == 0) {
+ MODLOG_DFLT(INFO, "Terminating...\n");
+ ble_gap_terminate(i, BLE_ERR_REM_USER_CONN_TERM);
+ }
+ }
+
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+ tx_stress_on_test_finish(9);
+}
+
+static int
+tx_stress_10_l2cap_send(struct ble_l2cap_chan *chan, uint8_t *data,
+ int data_len)
+{
+ struct os_mbuf *data_buf;
+ int rc;
+
+ /* Get mbuf for adv data */
+ data_buf = os_msys_get_pkthdr(data_len, 0);
+ assert(data != NULL);
+
+ /* Fill mbuf with pattern data */
+ rc = os_mbuf_append(data_buf, data, data_len);
+
+ if (rc) {
+ os_mbuf_free_chain(data_buf);
+ assert(0);
+ }
+
+ /* Send data with L2CAP */
+ rc = ble_l2cap_send(chan, data_buf);
+
+ return rc;
+}
+
+void tx_stress_10_timer_ev_cb(struct os_event *ev)
+{
+ assert(ev != NULL);
+
+ if (tx_stress_ctx->rcv_data_flag) {
+ return;
+ }
+
+ tx_stress_ctx->timeout_flag = true;
+ MODLOG_DFLT(INFO, "L2CAP receiving timeout\n");
+ ble_gap_terminate(tx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+}
+
+static void
+tx_stress_10_l2cap_send_req()
+{
+ int rc;
+ /* Send a request to the RX device */
+
+ MODLOG_DFLT(INFO, "L2CAP sending request\n");
+ tx_stress_ctx->timeout_flag = false;
+ tx_stress_ctx->rcv_data_flag = false;
+ stress_start_timer(7000, tx_stress_10_timer_ev_cb);
+
+ /* Get the sending begin time */
+ tx_stress_ctx->begin_us = os_get_uptime_usec();
+
+ /* Send anything just to give a signal to start sending data
+ * by RX device */
+ rc = tx_stress_10_l2cap_send(tx_stress_ctx->chan, (uint8_t *) "S",
+ sizeof("S"));
+ assert(rc == 0);
+}
+
+static int
+tx_stress_10_l2cap_event(struct ble_l2cap_event *event, void *arg)
+{
+ static int i = 0;
+ int64_t us = 0;
+ struct ble_l2cap_chan_info chan_info;
+
+ switch (event->type) {
+ case BLE_L2CAP_EVENT_COC_CONNECTED:
+ /* A new L2CAP connection was established. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Established L2CAP connection\n");
+ tx_stress_ctx->chan = event->connect.chan;
+
+ ble_l2cap_get_chan_info(event->connect.chan, &chan_info);
+
+ MODLOG_DFLT(INFO,
+ "LE COC connected, conn: %d, chan: 0x%08lx, scid: 0x%04x, "
+ "dcid: 0x%04x, our_mtu: 0x%04x, peer_mtu: 0x%04x\n",
+ event->connect.conn_handle,
+ (uint32_t) event->connect.chan,
+ chan_info.scid,
+ chan_info.dcid,
+ chan_info.our_l2cap_mtu,
+ chan_info.peer_l2cap_mtu);
+
+ tx_stress_10_l2cap_send_req();
+ }
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_DISCONNECTED:
+ MODLOG_DFLT(INFO, "Remote device disconnected from L2CAP server\n");
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_ACCEPT:
+ stress_l2cap_coc_accept(event->accept.peer_sdu_size,
+ event->accept.chan);
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
+ /* Get the time of data receive */
+ tx_stress_ctx->end_us = os_get_uptime_usec();
+
+ /* And test after timeout */
+ if (tx_stress_ctx->timeout_flag) {
+ ble_gap_terminate(tx_stress_ctx->conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ return 0;
+ }
+
+ tx_stress_ctx->rcv_data_flag = true;
+
+ stress_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx);
+
+ /* Time of data sending */
+ us = tx_stress_ctx->end_us - tx_stress_ctx->begin_us;
+ MODLOG_DFLT(INFO, "Time of receiving L2CAP data: %ld \n",
+ tx_stress_ctx->end_us);
+
+ /* Remember size of entire mbuf chain */
+ tx_stress_ctx->rcv_data_bytes = OS_MBUF_PKTLEN(
+ event->receive.sdu_rx);
+ MODLOG_DFLT(INFO, "Num of received bytes: %lld\n",
+ tx_stress_ctx->rcv_data_bytes);
+
+ /* Calculate the bit rate of this send */
+ tx_stress_ctx->s10_bit_rate =
+ stress_calc_bit_rate(us, tx_stress_ctx->rcv_data_bytes);
+ MODLOG_DFLT(INFO, "Bit rate: %d B/s\n", tx_stress_ctx->s10_bit_rate);
+
+ /* Remember the sum of bytes and the time to calculate the average
+ * bit rate. */
+ tx_stress_ctx->bytes_sum += tx_stress_ctx->rcv_data_bytes;
+ tx_stress_ctx->time_sum += us;
+
+ /* Remember max received MTU */
+ if (tx_stress_ctx->s10_max_mtu < tx_stress_ctx->rcv_data_bytes) {
+ tx_stress_ctx->s10_max_mtu = tx_stress_ctx->rcv_data_bytes;
+ }
+ console_printf("\033[0;32m>\033[0m");
+ MODLOG_DFLT(INFO, "Loop nr: %d\n", ++i);
+
+ tx_stress_10_l2cap_send_req();
+ return 0;
+
+ case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
+ MODLOG_DFLT(INFO, "L2CAP event unstalled\n");
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other L2CAP event occurs; rc=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_10_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int rc;
+ struct os_mbuf *sdu_rx;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device; num: %d\n",
+ ++tx_stress_ctx->con_stat[10].num);
+
+ sdu_rx = os_msys_get_pkthdr(STRESS_COC_MTU, 0);
+ assert(sdu_rx != NULL);
+
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+ rc = ble_l2cap_connect(event->connect.conn_handle, 1,
+ STRESS_COC_MTU, sdu_rx,
+ tx_stress_10_l2cap_event, NULL);
+ assert(rc == 0);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ tx_stress_ctx->s10_bit_rate = 1000000 * tx_stress_ctx->bytes_sum /
+ tx_stress_ctx->time_sum;
+
+ MODLOG_DFLT(INFO, "Average bit rate: %d B/s\n",
+ tx_stress_ctx->s10_bit_rate);
+ tx_stress_on_test_finish(10);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_11_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int test;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_EXT_DISC:
+ /* Looking for next instance of test 9 advert. */
+ test = tx_stress_find_test(&event->ext_disc);
+
+ /* To avoid messing by rest of test 9 events in queue, check if handle
+ * filled */
+ if (test == 11 && tx_stress_ctx->conn_handle == 0xffff) {
+ tx_stress_ctx->conn_handle = 0;
+ ble_gap_disc_cancel();
+ tx_stress_ctx->dev_addr = event->ext_disc.addr;
+ tx_stress_simple_connect(tx_stress_11_gap_event,
+ tx_stress_ctx->cur_test_id);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ ++tx_stress_ctx->con_stat[11].num;
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ break;
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ console_printf("\033[0;32m>\033[0m");
+
+ if (tx_stress_ctx->con_stat[11].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ tx_stress_on_test_finish(11);
+ return 0;
+ }
+ break;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+
+ tx_stress_ctx->conn_handle = 0xffff;
+
+ /* Scan for next instance of the test. */
+ tx_stress_simple_scan(tx_stress_11_gap_event, 750);
+
+ return 0;
+}
+
+static int
+tx_stress_12_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ ++tx_stress_ctx->con_stat[12].num;
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ /* Finish test after first disconnection */
+ tx_stress_on_test_finish(12);
+ return 0;
+
+ case BLE_GAP_EVENT_NOTIFY_RX:
+ /* Received indication */
+ MODLOG_DFLT(INFO, "Notify RX event\n");
+ console_printf("\033[0;32m>\033[0m");
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_13_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ ++tx_stress_ctx->con_stat[13].num;
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ assert(0);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ /* Finish test after disconnection */
+ tx_stress_on_test_finish(13);
+ return 0;
+
+ case BLE_GAP_EVENT_NOTIFY_RX:
+ MODLOG_DFLT(INFO, "Notify RX event\n");
+ console_printf("\033[0;32m>\033[0m");
+ os_mbuf_free_chain(event->notify_rx.om);
+ ++tx_stress_ctx->rcv_num;
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_14_subs_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr, void *arg)
+{
+ struct os_mbuf *om;
+ bool *sub;
+ int rc;
+
+ assert(error->status == 0);
+
+ /* If the first subscription after finding cccd */
+ if(arg == NULL) {
+ return 0;
+ }
+
+ sub = (bool*)arg;
+
+ /* Enable notifications */
+ if(*sub == 0) {
+ *sub = true;
+ om = ble_hs_mbuf_from_flat(
+ (uint8_t[]) {0x01, 0x00}, 2);
+
+ tx_stress_ctx->begin_us = tx_stress_ctx->end_us;
+
+ rc = ble_gattc_write(tx_stress_ctx->conn_handle,
+ tx_stress_ctx->dsc_handle, om,
+ tx_stress_14_subs_cb, arg);
+ assert(rc == 0);
+ }
+
+ return 0;
+}
+
+static void
+tx_stress_14_disc_cccd_fn(struct stress_gatt_search_ctx *search_ctx)
+{
+ int rc;
+ struct os_mbuf *om;
+ MODLOG_DFLT(INFO, "CCCD found\n");
+
+ /* Enable notifications */
+ om = ble_hs_mbuf_from_flat((uint8_t[]) {0x01, 0x00}, 2);
+ tx_stress_ctx->begin_us = os_get_uptime_usec();
+ tx_stress_ctx->dsc_handle = search_ctx->dsc_handle;
+
+ rc = ble_gattc_write(tx_stress_ctx->conn_handle,
+ tx_stress_ctx->dsc_handle, om,
+ tx_stress_14_subs_cb, NULL);
+ assert(rc == 0);
+}
+
+static int
+tx_stress_14_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int64_t us = 0;
+ struct os_mbuf *om;
+ int rc;
+ static bool subscribed = true;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ ++tx_stress_ctx->con_stat[14].num;
+ MODLOG_DFLT(INFO, "Success to connect to device\n");
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ /* Find CCCD handle (with default UUID16 = 0x2902) */
+ stress_find_dsc_handle(event->connect.conn_handle,
+ BLE_UUID16_DECLARE(STRESS_GATT_UUID),
+ BLE_UUID16_DECLARE(STRESS_GATT_NOTIFY_UUID),
+ BLE_UUID16_DECLARE(0x2902),
+ &tx_stress_14_disc_cccd_fn);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ assert(0);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ MODLOG_DFLT(INFO, "Disconnect; reason=%d \n",
+ event->disconnect.reason);
+ /* Calc average notifying time */
+ if (tx_stress_ctx->rcv_num > 0) {
+ tx_stress_ctx->s14_notif_time = tx_stress_ctx->time_sum /
+ tx_stress_ctx->rcv_num;
+ }
+ MODLOG_DFLT(INFO, "Average notification time: %d\n",
+ tx_stress_ctx->s14_notif_time);
+ /* Finish test after first disconnection */
+ tx_stress_on_test_finish(14);
+ return 0;
+
+ case BLE_GAP_EVENT_NOTIFY_RX:
+ tx_stress_ctx->end_us = os_get_uptime_usec();
+ MODLOG_DFLT(INFO, "Notify RX event\n");
+
+ /* Time of data sending */
+ us = tx_stress_ctx->end_us - tx_stress_ctx->begin_us;
+ MODLOG_DFLT(INFO, "Notification time: %lld\n us", us);
+
+ tx_stress_ctx->time_sum += us;
+ console_printf("\033[0;32m>\033[0m");
+
+ /* Perform use case specified number of times */
+ if (++tx_stress_ctx->rcv_num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ rc = ble_gap_terminate(event->notify_rx.conn_handle,
+ BLE_ERR_REM_USER_CONN_TERM);
+ MODLOG_DFLT(INFO, "rc=%d\n");
+ assert(rc == 0);
+ return 0;
+ }
+
+ /* Disable notifications */
+ subscribed = false;
+ om = ble_hs_mbuf_from_flat(
+ (uint8_t[]) {0x00, 0x00}, 2);
+
+ rc = ble_gattc_write(tx_stress_ctx->conn_handle,
+ tx_stress_ctx->dsc_handle, om,
+ tx_stress_14_subs_cb, &subscribed);
+ assert(rc == 0);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+tx_stress_15_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
+ struct ble_gatt_attr *attr, void *arg)
+{
+ /* Disconnect */
+ ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
+ console_printf("\033[0;32m>\033[0m");
+ return 0;
+}
+
+static void
+tx_stress_15_disc_chr_fn(struct stress_gatt_search_ctx *search_ctx)
+{
+ int rc;
+ struct os_mbuf *om;
+
+ /* Send some data */
+ MODLOG_DFLT(INFO, "Write to chr\n");
+ om = ble_hs_mbuf_from_flat(test_6_pattern, 20);
+
+ rc = ble_gattc_write(tx_stress_ctx->conn_handle,
+ search_ctx->chr_start_handle, om,
+ tx_stress_15_write_cb, NULL);
+ assert(rc == 0);
+}
+
+static int
+tx_stress_15_gap_event(struct ble_gap_event *event, void *arg)
+{
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ /* A new connection was established or a connection attempt failed. */
+ if (event->connect.status == 0) {
+ MODLOG_DFLT(INFO, "Success to connect to device; num: %d\n",
+ ++tx_stress_ctx->con_stat[15].num);
+ tx_stress_ctx->conn_handle = event->connect.conn_handle;
+
+ /* Find characteristic handle */
+ stress_find_chr_handle(event->connect.conn_handle,
+ BLE_UUID16_DECLARE(STRESS_GATT_UUID),
+ BLE_UUID16_DECLARE(STRESS_GATT_WRITE_UUID),
+ &tx_stress_15_disc_chr_fn);
+ } else {
+ MODLOG_DFLT(INFO, "\033[0;31mError: connection attempt failed; "
+ "status=%d\033[0m\n", event->connect.status);
+ assert(0);
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ /* Perform use case specified number of times */
+ if(tx_stress_ctx->con_stat[15].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
+ tx_stress_on_test_finish(15);
+ return 0;
+ }
+ /* Reconnect */
+ tx_stress_simple_connect(tx_stress_15_gap_event, 15);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static int
+scan_for_test_gap_event(struct ble_gap_event *event, void *arg)
+{
+ int use_case;
+ int rc;
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_EXT_DISC:
+ /* Check if caught advert contains known UUID128. The UUID128
+ * contains the ID of test use case to be executed. */
+ use_case = tx_stress_find_test(&event->ext_disc);
+ if (use_case > 0) {
+ rc = ble_gap_disc_cancel();
+ tx_stress_ctx->dev_addr = event->ext_disc.addr;
+
+ /* After discovery cancel there are still some events in queue. */
+ if (rc == 0) {
+ tx_stress_use_case = use_case;
+ /* Add token to semaphore. Main task will start the test. */
+ os_sem_release(&tx_stress_main_sem);
+ }
+ }
+ return 0;
+
+ case BLE_GAP_EVENT_DISC_COMPLETE:
+ /* On timeout */
+ tx_stress_ctx->scan_timeout = true;
+ console_printf("\033[1;36mDiscover complete\033[0m\n");
+ os_sem_release(&tx_stress_main_sem);
+ return 0;
+
+ default:
+ MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type);
+ return 0;
+ }
+}
+
+static void
+tx_stress_test_perform(int test_num)
+{
+ /* Perform every test only once */
+// if (test_num <= 0 || tx_stress_ctx->completed[test_num] == true) {
+// return;
+// }
+
+ tx_stress_ctx->cur_test_id = test_num;
+ tx_stress_ctx->completed[test_num] = false;
+ tx_stress_ctx->conn_handle = 0xffff;
+
+ console_printf("\033[1;36mStart test num %d - ", test_num);
+
+ /* Start test */
+ switch (test_num) {
+ case 0:
+ return;
+ case 1:
+ console_printf("Stress Connect -> Connect Cancel\033[0m\n");
+ tx_stress_1_test();
+ break;
+ case 2:
+ console_printf("Stress Connect/Disconnect legacy\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_2_gap_event, 2);
+ break;
+ case 3:
+ console_printf("Stress Connect/Disconnect ext adv\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_3_gap_event, 3);
+ break;
+ case 4:
+ console_printf("Stress connection params update (TX)\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_4_gap_event, 4);
+ break;
+ case 5:
+ console_printf("Stress connection params update (RX)\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_5_gap_event, 5);
+ break;
+ case 6:
+ console_printf("Stress Scan\033[0m\n");
+ tx_stress_6_perform();
+ break;
+ case 7:
+ console_printf("Stress PHY Update (TX)\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_7_gap_event, 7);
+ break;
+ case 8:
+ console_printf("Stress PHY Update (RX)\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_8_gap_event, 8);
+ break;
+ case 9:
+ console_printf("Stress multi connection\033[0m\n");
+ tx_stress_9_perform();
+ break;
+ case 10:
+ console_printf("Stress L2CAP send\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_10_gap_event, 10);
+ break;
+ case 11:
+ console_printf("Stress Advertise/Connect/Disconnect\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_11_gap_event, 11);
+ break;
+ case 12:
+ console_printf("Stress GATT indication\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_12_gap_event, 12);
+ break;
+ case 13:
+ console_printf("Stress GATT notification\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_13_gap_event, 13);
+ break;
+ case 14:
+ console_printf("Stress GATT Subscribe/Notify/Unsubscribe\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_14_gap_event, 14);
+ break;
+ case 15:
+ console_printf("Stress Connect/Send/Disconnect\033[0m\n");
+ tx_stress_simple_connect(&tx_stress_15_gap_event, 15);
+ break;
+ default:
+ console_printf("\033[0;31mFound test, but do not know how to perform."
+ "\033[0m\n");
+ assert(0);
+ }
+
+ /* Wait for the test to finish. Then 1 token will be released
+ * allowing to pass through semaphore. */
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+
+ stress_clear_ctx_reusable_var(tx_stress_ctx);
+}
+
+static void
+tx_stress_read_command_cb(void) {
+ console_printf("Start testing\n");
+ os_sem_release(&tx_stress_main_sem);
+}
+
+static void
+tx_stress_main_task_fn(void *arg)
+{
+ int rc;
+
+ tx_stress_ctx = &tx_stress_ctxD;
+
+ console_printf("\033[1;36mTX device\033[0m\n");
+ console_printf("Press ENTER to start: \n");
+ console_init(&tx_stress_read_command_cb);
+
+ /* Waite for pressing ENTER in console */
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+
+ /* Init semaphore with 0 tokens. */
+ rc = os_sem_init(&tx_stress_main_sem, 0);
+ assert(rc == 0);
+
+ /* Start test 1 - Connect/Connect cancel */
+ //tx_stress_test_perform(1);
+
+ while (1) {
+ console_printf("\033[0;36mStart scan for test\033[0m\n");
+
+ /* Scan for known UUID128 of one of the stress tests. */
+ tx_stress_simple_scan(scan_for_test_gap_event, 2000);
+
+ /* Wait for the scan to find the test. Then 1 token will be
+ * released allowing to pass through semaphore. */
+ os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
+ if(tx_stress_ctx->scan_timeout) {
+ break;
+ }
+
+ /* Start test. */
+ tx_stress_test_perform(tx_stress_use_case);
+ tx_stress_use_case = -1;
+ }
+
+ /* Print tests results */
+ com_stress_print_report(tx_stress_ctx);
+
+ /* Task should never return */
+ while (1) {
+ /* Delay used only to prevent watchdog to reset the device. */
+ os_time_delay(os_time_ms_to_ticks32(2000));
+ }
+}
+
+void tx_stress_start_auto()
+{
+ /* Start task that will run all stress tests one by one. */
+ os_task_init(&tx_stress_main_task, "tx_stress_main_task",
+ tx_stress_main_task_fn, NULL, TX_STRESS_MAIN_TASK_PRIO,
+ OS_WAIT_FOREVER, tx_stress_main_task_stack,
+ TX_STRESS_MAIN_TASK_STACK_SIZE);
+}
diff --git a/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.h b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.h
new file mode 100644
index 00000000..83ed3020
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _BLE_STRESS_TX_H
+#define _BLE_STRESS_TX_H
+
+#include <assert.h>
+#include <string.h>
+#include <host/ble_gap.h>
+#include <stdlib.h>
+
+/* BLE */
+#include "nimble/ble.h"
+#include "host/ble_hs.h"
+
+#include "misc.h"
+#include "stress.h"
+#include "stress_gatt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Scan and execute tests one by one.
+ */
+void tx_stress_start_auto();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_BLE_STRESS_TX_H
diff --git a/src/libs/mynewt-nimble/apps/blestress/syscfg.yml b/src/libs/mynewt-nimble/apps/blestress/syscfg.yml
new file mode 100644
index 00000000..344466ce
--- /dev/null
+++ b/src/libs/mynewt-nimble/apps/blestress/syscfg.yml
@@ -0,0 +1,74 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Settings this app defines.
+syscfg.defs:
+ BLE_STRESS_TEST_ROLE:
+ description: 0 - TX device, 1 - RX device
+ value: 0
+
+ BLE_STRESS_REPEAT:
+ description: Number of times to repeat each stress test use case
+ value: 50
+
+ BLE_STRESS_UUID_BASE:
+ description: Part of the test UUID that is specific to the current
+ device couple.
+ value: ((uint8_t[13]){0xA5, 0x4A, 0xB4, 0x44, 0xC3, 0xBF, 0xB5,
+ 0xF8, 0xF9, 0x42, 0x83, 0xA1, 0xDA})
+
+# Settings this app overrides.
+syscfg.vals:
+ # Change these settings:
+
+ # Set 0 to print all debug logs, but keep in mind that plenty of
+ # adv packets will be lost during scan tests.
+ LOG_LEVEL: 1
+
+ # The maximum number of concurrent connections. For some devices, this
+ # value will need to be reduced due to the RAM capacity.
+ BLE_MAX_CONNECTIONS: 50
+
+ # Should not change these settings:
+
+ # Enable Extended Advertising
+ BLE_EXT_ADV: 1
+
+ # Max advertising data size
+ BLE_EXT_ADV_MAX_SIZE: 1650
+
+ # Number of multi-advertising instances. Note that due
+ # to historical reasons total number of advertising
+ # instances is BLE_MULTI_ADV_INSTANCES + 1 as instance
+ # 0 is always available
+ BLE_MULTI_ADV_INSTANCES: 2
+
+ # Controller uses msys pool for storing advertising data and scan responses.
+ # Since we advertise a lot of data (~4k in total) at the same time we need
+ # to increase block count.
+ MSYS_1_BLOCK_COUNT: 50
+
+ #
+ BLE_L2CAP_COC_MAX_NUM: 2
+
+ # Enable 2M PHY
+ BLE_LL_CFG_FEAT_LE_2M_PHY: 1
+
+ # Enable CODED PHY
+ BLE_LL_CFG_FEAT_LE_CODED_PHY: 1