| /* |
| * 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(¶ms, 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, ¶ms, |
| NULL, adv_set->cb, NULL); |
| assert (rc == 0); |
| |
| if (own_addr_type == 0) { |
| rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL); |
| assert (rc == 0); |
| } 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, ¶ms); |
| |
| 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, ¶ms, |
| &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); |
| |
| /* 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) { |
| if (rc == BLE_HS_ESTALLED) { |
| MODLOG_DFLT(INFO, "L2CAP stalled - waiting\n"); |
| stalled = true; |
| } else { |
| MODLOG_DFLT(INFO, "Sending data via L2CAP failed with error " |
| "code %d\n", rc); |
| } |
| } |
| |
| 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_gatts_indicate_custom(rx_stress_ctx->conn_handle, hrs_hrm_handle, |
| om); |
| assert(rc == 0); |
| return 0; |
| } |
| |
| static struct ble_npl_event rx_stress_13_notify_ev; |
| |
| static void |
| rx_stress_13_notify_ev_func(struct ble_npl_event *ev) |
| { |
| struct os_mbuf *om; |
| int rc; |
| |
| om = ble_hs_mbuf_from_flat(test_6_pattern, 10); |
| rc = ble_gatts_notify_custom(rx_stress_ctx->conn_handle, |
| hrs_hrm_handle, om); |
| assert(rc == 0); |
| |
| } |
| |
| static int |
| rx_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) { |
| 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(); |
| |
| ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(), |
| &rx_stress_13_notify_ev); |
| 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: %d 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; |
| } |
| |
| ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(), |
| &rx_stress_13_notify_ev); |
| break; |
| |
| default: |
| MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type); |
| return 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_gatts_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[1], |
| .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 0: |
| return; |
| case 1: |
| console_printf("Nothing to do"); |
| rx_stress_simple_adv(&rx_stress_adv_sets[1]); |
| return; |
| 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(TEST_PSM, 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"); |
| ble_npl_event_init(&rx_stress_13_notify_ev, |
| rx_stress_13_notify_ev_func, NULL); |
| 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 = 1; i < STRESS_UUIDS_NUM; ++i) { |
| /* 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); |
| } |