http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/libs/os/test/src/sem_test.c ---------------------------------------------------------------------- diff --cc libs/os/test/src/sem_test.c index ec79185,0000000..6b40069 mode 100644,000000..100644 --- a/libs/os/test/src/sem_test.c +++ b/libs/os/test/src/sem_test.c @@@ -1,401 -1,0 +1,401 @@@ +/** + * 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 <stdio.h> +#include <string.h> +#include "testutil/testutil.h" +#include "os/os.h" +#include "os/os_cfg.h" +#include "os/os_sem.h" +#include "os_test_priv.h" + +#ifdef ARCH_sim +#define SEM_TEST_STACK_SIZE 1024 +#else +#define SEM_TEST_STACK_SIZE 512 +#endif + +struct os_task task1; +os_stack_t stack1[OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)]; + +struct os_task task2; +os_stack_t stack2[OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)]; + +struct os_task task3; +os_stack_t stack3[OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)]; + +struct os_task task4; +os_stack_t stack4[OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)]; + +#define TASK1_PRIO (1) +#define TASK2_PRIO (2) +#define TASK3_PRIO (3) +#define TASK4_PRIO (4) + +struct os_sem g_sem1; + +/* + * TEST NUMBERS: + * 10: In this test we have the highest priority task getting the semaphore + * then sleeping. Two lower priority tasks then wake up and attempt to get + * the semaphore. They are blocked until the higher priority task releases + * the semaphore, at which point the lower priority tasks should wake up in + * order, get the semaphore, then release it and go back to sleep. + * + */ + +/** + * sem test disp sem + * + * Display semaphore contents + * + * @param sem + */ +static const char * +sem_test_sem_to_s(const struct os_sem *sem) +{ + static char buf[128]; + + snprintf(buf, sizeof buf, "\tSemaphore: tokens=%u head=%p", + sem->sem_tokens, SLIST_FIRST(&sem->sem_head)); + + return buf; +} + +static void +sem_test_sleep_task_handler(void *arg) +{ + struct os_task *t; + + t = os_sched_get_current_task(); + TEST_ASSERT(t->t_func == sem_test_sleep_task_handler); + - os_time_delay(2000); ++ os_time_delay(2 * OS_TICKS_PER_SEC); + os_test_restart(); +} + +static void +sem_test_pend_release_loop(int delay, int timeout, int itvl) +{ + os_error_t err; + + os_time_delay(delay); + + while (1) { + err = os_sem_pend(&g_sem1, timeout); + TEST_ASSERT((err == OS_OK) || (err == OS_TIMEOUT)); + + err = os_sem_release(&g_sem1); + TEST_ASSERT(err == OS_OK); + + os_time_delay(itvl); + } +} + +/** + * sem test basic + * + * Basic semaphore tests + * + * @return int + */ +static void +sem_test_basic_handler(void *arg) +{ + struct os_task *t; + struct os_sem *sem; + os_error_t err; + + sem = &g_sem1; + t = os_sched_get_current_task(); + + /* Test some error cases */ + TEST_ASSERT(os_sem_init(NULL, 1) == OS_INVALID_PARM); + TEST_ASSERT(os_sem_release(NULL) == OS_INVALID_PARM); + TEST_ASSERT(os_sem_pend(NULL, 1) == OS_INVALID_PARM); + + /* Get the semaphore */ + err = os_sem_pend(sem, 0); + TEST_ASSERT(err == 0, + "Did not get free semaphore immediately (err=%d)", err); + + /* Check semaphore internals */ + TEST_ASSERT(sem->sem_tokens == 0 && SLIST_EMPTY(&sem->sem_head), + "Semaphore internals wrong after getting semaphore\n" + "%s\n" + "Task: task=%p prio=%u", sem_test_sem_to_s(sem), t, t->t_prio); + + /* Get the semaphore again; should fail */ + err = os_sem_pend(sem, 0); + TEST_ASSERT(err == OS_TIMEOUT, + "Did not time out waiting for semaphore (err=%d)", err); + + /* Check semaphore internals */ + TEST_ASSERT(sem->sem_tokens == 0 && SLIST_EMPTY(&sem->sem_head), + "Semaphore internals wrong after getting semaphore\n" + "%s\n" + "Task: task=%p prio=%u\n", sem_test_sem_to_s(sem), t, + t->t_prio); + + /* Release semaphore */ + err = os_sem_release(sem); + TEST_ASSERT(err == 0, + "Could not release semaphore I own (err=%d)", err); + + /* Check semaphore internals */ + TEST_ASSERT(sem->sem_tokens == 1 && SLIST_EMPTY(&sem->sem_head), + "Semaphore internals wrong after releasing semaphore\n" + "%s\n" + "Task: task=%p prio=%u\n", sem_test_sem_to_s(sem), t, + t->t_prio); + + /* Release it again */ + err = os_sem_release(sem); + TEST_ASSERT(err == 0, + "Could not release semaphore again (err=%d)\n", err); + + /* Check semaphore internals */ + TEST_ASSERT(sem->sem_tokens == 2 && SLIST_EMPTY(&sem->sem_head), + "Semaphore internals wrong after releasing semaphore\n" + "%s\n" + "Task: task=%p prio=%u\n", sem_test_sem_to_s(sem), t, + t->t_prio); + + os_test_restart(); +} + +static void +sem_test_1_task1_handler(void *arg) +{ + os_error_t err; + struct os_task *t; + int i;; + + for (i = 0; i < 3; i++) { + t = os_sched_get_current_task(); + TEST_ASSERT(t->t_func == sem_test_1_task1_handler); + + + err = os_sem_pend(&g_sem1, 0); + TEST_ASSERT(err == OS_OK); + + /* Sleep to let other tasks run */ - os_time_delay(100); ++ os_time_delay(OS_TICKS_PER_SEC / 10); + + /* Release the semaphore */ + err = os_sem_release(&g_sem1); + TEST_ASSERT(err == OS_OK); + + /* Sleep to let other tasks run */ - os_time_delay(100); ++ os_time_delay(OS_TICKS_PER_SEC / 10); + } + + os_test_restart(); +} + +TEST_CASE(os_sem_test_basic) +{ + os_error_t err; + + os_init(); + + err = os_sem_init(&g_sem1, 1); + TEST_ASSERT(err == OS_OK); + + os_task_init(&task1, "task1", sem_test_basic_handler, NULL, TASK1_PRIO, + OS_WAIT_FOREVER, stack1, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_start(); +} + +static void +sem_test_1_task2_handler(void *arg) +{ - sem_test_pend_release_loop(0, 100, 100); ++ sem_test_pend_release_loop(0, OS_TICKS_PER_SEC / 10, OS_TICKS_PER_SEC / 10); +} + +static void +sem_test_1_task3_handler(void *arg) +{ - sem_test_pend_release_loop(0, OS_TIMEOUT_NEVER, 2000); ++ sem_test_pend_release_loop(0, OS_TIMEOUT_NEVER, OS_TICKS_PER_SEC * 2); +} + +TEST_CASE(os_sem_test_case_1) +{ + os_error_t err; + + os_init(); + + err = os_sem_init(&g_sem1, 1); + TEST_ASSERT(err == OS_OK); + + os_task_init(&task1, "task1", sem_test_1_task1_handler, NULL, + TASK1_PRIO, OS_WAIT_FOREVER, stack1, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task2, "task2", sem_test_1_task2_handler, NULL, + TASK2_PRIO, OS_WAIT_FOREVER, stack2, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task3, "task3", sem_test_1_task3_handler, NULL, TASK3_PRIO, + OS_WAIT_FOREVER, stack3, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_start(); +} + +static void +sem_test_2_task2_handler(void *arg) +{ + sem_test_pend_release_loop(0, 2000, 2000); +} + +static void +sem_test_2_task3_handler(void *arg) +{ + sem_test_pend_release_loop(0, OS_TIMEOUT_NEVER, 2000); +} + +static void +sem_test_2_task4_handler(void *arg) +{ + sem_test_pend_release_loop(0, 2000, 2000); +} + +TEST_CASE(os_sem_test_case_2) +{ + os_error_t err; + + os_init(); + + err = os_sem_init(&g_sem1, 1); + TEST_ASSERT(err == OS_OK); + + os_task_init(&task1, "task1", sem_test_sleep_task_handler, NULL, + TASK1_PRIO, OS_WAIT_FOREVER, stack1, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task2, "task2", sem_test_2_task2_handler, NULL, + TASK2_PRIO, OS_WAIT_FOREVER, stack2, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task3, "task3", sem_test_2_task3_handler, NULL, TASK3_PRIO, + OS_WAIT_FOREVER, stack3, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task4, "task4", sem_test_2_task4_handler, NULL, TASK4_PRIO, + OS_WAIT_FOREVER, stack4, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_start(); +} + +static void +sem_test_3_task2_handler(void *arg) +{ + sem_test_pend_release_loop(100, 2000, 2000); +} + +static void +sem_test_3_task3_handler(void *arg) +{ + sem_test_pend_release_loop(150, 2000, 2000); +} + +static void +sem_test_3_task4_handler(void *arg) +{ + sem_test_pend_release_loop(0, 2000, 2000); +} + +TEST_CASE(os_sem_test_case_3) +{ + os_error_t err; + + os_init(); + + err = os_sem_init(&g_sem1, 1); + TEST_ASSERT(err == OS_OK); + + os_task_init(&task1, "task1", sem_test_sleep_task_handler, NULL, + TASK1_PRIO, OS_WAIT_FOREVER, stack1, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task2, "task2", sem_test_3_task2_handler, NULL, + TASK2_PRIO, OS_WAIT_FOREVER, stack2, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task3, "task3", sem_test_3_task3_handler, NULL, TASK3_PRIO, + OS_WAIT_FOREVER, stack3, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task4, "task4", sem_test_3_task4_handler, NULL, TASK4_PRIO, + OS_WAIT_FOREVER, stack4, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_start(); +} + +static void +sem_test_4_task2_handler(void *arg) +{ + sem_test_pend_release_loop(60, 2000, 2000); +} + +static void +sem_test_4_task3_handler(void *arg) +{ + sem_test_pend_release_loop(60, 2000, 2000); +} + +static void +sem_test_4_task4_handler(void *arg) +{ + sem_test_pend_release_loop(0, 2000, 2000); +} + + +TEST_CASE(os_sem_test_case_4) +{ + os_error_t err; + + os_init(); + + err = os_sem_init(&g_sem1, 1); + TEST_ASSERT(err == OS_OK); + + os_task_init(&task1, "task1", sem_test_sleep_task_handler, NULL, + TASK1_PRIO, OS_WAIT_FOREVER, stack1, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task2, "task2", sem_test_4_task2_handler, NULL, + TASK2_PRIO, OS_WAIT_FOREVER, stack2, + OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task3, "task3", sem_test_4_task3_handler, NULL, TASK3_PRIO, + OS_WAIT_FOREVER, stack3, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_task_init(&task4, "task4", sem_test_4_task4_handler, NULL, TASK4_PRIO, + OS_WAIT_FOREVER, stack4, OS_STACK_ALIGN(SEM_TEST_STACK_SIZE)); + + os_start(); +} + +TEST_SUITE(os_sem_test_suite) +{ + os_sem_test_basic(); + os_sem_test_case_1(); + os_sem_test_case_2(); + os_sem_test_case_3(); + os_sem_test_case_4(); +}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/libs/shell/include/shell/shell.h ---------------------------------------------------------------------- diff --cc libs/shell/include/shell/shell.h index 6b89740,1d98148..48351a0 --- a/libs/shell/include/shell/shell.h +++ b/libs/shell/include/shell/shell.h @@@ -40,6 -40,10 +40,9 @@@ int shell_nlip_input_register(shell_nli int shell_nlip_output(struct os_mbuf *m); void shell_console_rx_cb(void); -int shell_task_init(uint8_t prio, os_stack_t *stack, uint16_t stack_size, - int max_input_length); +void shell_init(void); + int shell_cmd_list_lock(void); + int shell_cmd_list_unlock(void); + #endif /* __SHELL_H__ */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/libs/shell/src/shell.c ---------------------------------------------------------------------- diff --cc libs/shell/src/shell.c index 7fe15e5,8c904ec..18f040a --- a/libs/shell/src/shell.c +++ b/libs/shell/src/shell.c @@@ -17,22 -17,23 +17,20 @@@ * under the License. */ -#include <os/os.h> - -#include <console/console.h> -#include <console/prompt.h> - -#include "shell/shell.h" -#include "shell_priv.h" -#include "shell/shell_prompt.h" - -#include <os/endian.h> -#include <util/base64.h> -#include <util/crc16.h> -- #include <stdio.h> #include <string.h> #include <assert.h> - #include <errno.h> +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "console/console.h" +#include "os/os.h" +#include "os/endian.h" +#include "util/base64.h" +#include "util/crc16.h" +#include "shell/shell.h" +#include "shell_priv.h" + static shell_nlip_input_func_t g_shell_nlip_in_func; static void *g_shell_nlip_in_arg; @@@ -42,10 -43,9 +40,11 @@@ static struct os_mqueue g_shell_nlip_mq #define SHELL_HELP_PER_LINE 6 #define SHELL_MAX_ARGS 20 +static os_stack_t shell_stack[OS_STACK_ALIGN(MYNEWT_VAL(SHELL_STACK_SIZE))]; + static int shell_echo_cmd(int argc, char **argv); static int shell_help_cmd(int argc, char **argv); + int shell_prompt_cmd(int argc, char **argv); static struct shell_cmd g_shell_echo_cmd = { .sc_cmd = "echo", @@@ -530,30 -539,50 +537,35 @@@ shell_init(void int rc; free(shell_line); + shell_line = NULL; - if (max_input_length > 0) { - shell_line = malloc(max_input_length); - if (shell_line == NULL) { - rc = OS_ENOMEM; - goto err; - } - } - shell_line_capacity = max_input_length; +#if MYNEWT_VAL(SHELL_MAX_INPUT_LEN) > 0 + shell_line = malloc(MYNEWT_VAL(SHELL_MAX_INPUT_LEN)); + SYSINIT_PANIC_ASSERT(shell_line != NULL); +#endif rc = os_mutex_init(&g_shell_cmd_list_lock); - if (rc != 0) { - goto err; - } + SYSINIT_PANIC_ASSERT(rc == 0); rc = shell_cmd_register(&g_shell_echo_cmd); - if (rc != 0) { - goto err; - } + SYSINIT_PANIC_ASSERT(rc == 0); rc = shell_cmd_register(&g_shell_help_cmd); - if (rc != 0) { - goto err; - } + SYSINIT_PANIC_ASSERT(rc == 0); + rc = shell_cmd_register(&g_shell_prompt_cmd); + if (rc != 0) { + goto err; + } + rc = shell_cmd_register(&g_shell_os_tasks_display_cmd); - if (rc != 0) { - goto err; - } + SYSINIT_PANIC_ASSERT(rc == 0); rc = shell_cmd_register(&g_shell_os_mpool_display_cmd); - if (rc != 0) { - goto err; - } + SYSINIT_PANIC_ASSERT(rc == 0); rc = shell_cmd_register(&g_shell_os_date_cmd); - if (rc != 0) { - goto err; - } + SYSINIT_PANIC_ASSERT(rc == 0); os_eventq_init(&shell_evq); os_mqueue_init(&g_shell_nlip_mq, NULL); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/libs/util/test/src/util_test.c ---------------------------------------------------------------------- diff --cc libs/util/test/src/util_test.c index d528568,0000000..4e21a9a mode 100644,000000..100644 --- a/libs/util/test/src/util_test.c +++ b/libs/util/test/src/util_test.c @@@ -1,46 -1,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. + */ + +#include <assert.h> +#include <stddef.h> +#include "syscfg/syscfg.h" +#include "testutil/testutil.h" +#include "util_test_priv.h" + +int +util_test_all(void) +{ + cbmem_test_suite(); + return tu_case_failed; +} + ++int ++hex_fmt_test_all(void) ++{ ++ hex_fmt_test_suite(); ++ return tu_case_failed; ++} ++ +#if MYNEWT_VAL(SELFTEST) + +int +main(int argc, char **argv) +{ + tu_config.tc_print_results = 1; + tu_init(); + + util_test_all(); - ++ hex_fmt_test_all(); + return tu_any_failed; +} + +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/libs/util/test/src/util_test_priv.h ---------------------------------------------------------------------- diff --cc libs/util/test/src/util_test_priv.h index cc5533d,0000000..c82df29 mode 100644,000000..100644 --- a/libs/util/test/src/util_test_priv.h +++ b/libs/util/test/src/util_test_priv.h @@@ -1,25 -1,0 +1,26 @@@ +/** + * 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 __UTIL_TEST_PRIV_ +#define __UTIL_TEST_PRIV_ + +int cbmem_test_suite(void); ++int hex_fmt_test_suite(void); + +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/libs/wifi_mgmt/src/wifi_cli.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/include/controller/ble_ll.h ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_adv.c ---------------------------------------------------------------------- diff --cc net/nimble/controller/src/ble_ll_adv.c index 01de299,3e2ce1f..64f5e23 --- a/net/nimble/controller/src/ble_ll_adv.c +++ b/net/nimble/controller/src/ble_ll_adv.c @@@ -121,7 -122,24 +123,24 @@@ struct ble_ll_adv_sm g_ble_ll_adv_sm #define BLE_LL_ADV_DIRECT_SCHED_MAX_USECS (502) -#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) + /** + * Called to change advertisers ADVA and INITA (for directed advertisements) + * as an advertiser needs to adhere to the resolvable private address generation + * timer. + * + * NOTE: the resolvable private address code uses its own timer to regenerate + * local resolvable private addresses. The advertising code uses its own + * timer to reset the INITA (for directed advertisements). This code also sets + * the appropriate txadd and rxadd bits that will go into the advertisement. + * + * Another thing to note: it is possible that an IRK is all zeroes in the + * resolving list. That is why we need to check if the generated address is + * in fact a RPA as a resolving list entry with all zeroes will use the + * identity address (which may be a private address or public). + * + * @param advsm + */ void ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm) { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_conn.c ---------------------------------------------------------------------- diff --cc net/nimble/controller/src/ble_ll_conn.c index 8ec6bca,43944a8..ba8fbc4 --- a/net/nimble/controller/src/ble_ll_conn.c +++ b/net/nimble/controller/src/ble_ll_conn.c @@@ -212,7 -215,25 +216,25 @@@ STATS_NAME_START(ble_ll_conn_stats STATS_NAME(ble_ll_conn_stats, mic_failures) STATS_NAME_END(ble_ll_conn_stats) + /** + * Get the event buffer allocated to send the connection complete event + * when we are initiating. + * + * @return uint8_t* + */ + static uint8_t * + ble_ll_init_get_conn_comp_ev(void) + { + uint8_t *evbuf; + + evbuf = g_ble_ll_conn_comp_ev; + assert(evbuf != NULL); + g_ble_ll_conn_comp_ev = NULL; + + return evbuf; + } + -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) /** * Called to determine if the received PDU is an empty PDU or not. */ @@@ -593,13 -620,11 +621,11 @@@ ble_ll_conn_wait_txend(void *arg { struct ble_ll_conn_sm *connsm; - ble_ll_conn_current_sm_over(); - connsm = (struct ble_ll_conn_sm *)arg; - ble_ll_event_send(&connsm->conn_ev_end); + ble_ll_conn_current_sm_over(connsm); } -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) static void ble_ll_conn_start_rx_encrypt(void *arg) { @@@ -2681,10 -2737,10 +2738,10 @@@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, */ hdr_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; conn_nesn = connsm->next_exp_seqnum; - if ((hdr_sn && conn_nesn) || (!hdr_sn && !conn_nesn)) { + if (rxpdu && ((hdr_sn && conn_nesn) || (!hdr_sn && !conn_nesn))) { connsm->next_exp_seqnum ^= 1; -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) - if (CONN_F_ENCRYPTED(connsm) && !ble_ll_conn_is_empty_pdu(rxbuf)) { +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) + if (CONN_F_ENCRYPTED(connsm) && !ble_ll_conn_is_empty_pdu(rxpdu)) { ++connsm->enc_data.rx_pkt_cntr; } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_conn_hci.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_conn_priv.h ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_hci.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_hci_ev.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_resolv.c ---------------------------------------------------------------------- diff --cc net/nimble/controller/src/ble_ll_resolv.c index 608da8c,903c95f..a507d19 --- a/net/nimble/controller/src/ble_ll_resolv.c +++ b/net/nimble/controller/src/ble_ll_resolv.c @@@ -31,15 -30,18 +31,18 @@@ #include "controller/ble_hw.h" #include "ble_ll_conn_priv.h" -#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) - - /* Flag denoting whether or not address translation is enabled. */ - uint8_t g_ble_ll_addr_res_enabled; - uint8_t g_ble_ll_resolv_list_size; - uint8_t g_ble_ll_resolv_list_cnt; - uint32_t g_ble_ll_resolv_rpa_tmo; + struct ble_ll_resolv_data + { + uint8_t addr_res_enabled; + uint8_t rl_size; + uint8_t rl_cnt; + uint32_t rpa_tmo; + struct os_callout_func rpa_timer; + }; + struct ble_ll_resolv_data g_ble_ll_resolv_data; -struct ble_ll_resolv_entry g_ble_ll_resolv_list[NIMBLE_OPT_LL_RESOLV_LIST_SIZE]; +struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)]; /** * Called to determine if a change is allowed to the resolving list at this @@@ -455,15 -553,19 +554,19 @@@ ble_ll_resolv_init(void uint8_t hw_size; /* Default is 15 minutes */ - g_ble_ll_resolv_rpa_tmo = 15 * 60 * OS_TICKS_PER_SEC; + g_ble_ll_resolv_data.rpa_tmo = 15 * 60 * OS_TICKS_PER_SEC; hw_size = ble_hw_resolv_list_size(); - if (hw_size > NIMBLE_OPT_LL_RESOLV_LIST_SIZE) { - hw_size = NIMBLE_OPT_LL_RESOLV_LIST_SIZE; + if (hw_size > MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) { + hw_size = MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE); } - g_ble_ll_resolv_list_size = hw_size; + g_ble_ll_resolv_data.rl_size = hw_size; + os_callout_func_init(&g_ble_ll_resolv_data.rpa_timer, + &g_ble_ll_data.ll_evq, + ble_ll_resolv_rpa_timer_cb, + NULL); } -#endif /* if BLE_LL_CFG_FEAT_LL_PRIVACY == 1 */ +#endif /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1 */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/controller/src/ble_ll_scan.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/drivers/native/src/ble_phy.c ---------------------------------------------------------------------- diff --cc net/nimble/drivers/native/src/ble_phy.c index d19e54b,ff195fc..0f1ef5a --- a/net/nimble/drivers/native/src/ble_phy.c +++ b/net/nimble/drivers/native/src/ble_phy.c @@@ -18,10 -18,12 +18,13 @@@ */ #include <stdint.h> + #include <string.h> #include <assert.h> +#include "syscfg/syscfg.h" #include "os/os.h" - #include "nimble/ble.h" /* XXX: needed for ble mbuf header.*/ + #include "ble/xcvr.h" + #include "nimble/ble.h" + #include "nimble/nimble_opt.h" #include "controller/ble_phy.h" #include "controller/ble_ll.h" http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/drivers/nrf51/src/ble_phy.c ---------------------------------------------------------------------- diff --cc net/nimble/drivers/nrf51/src/ble_phy.c index db6618f,a24a434..b8d2f6b --- a/net/nimble/drivers/nrf51/src/ble_phy.c +++ b/net/nimble/drivers/nrf51/src/ble_phy.c @@@ -27,13 -26,8 +27,8 @@@ #include "nimble/nimble_opt.h" #include "controller/ble_phy.h" #include "controller/ble_ll.h" -#include "mcu/nrf51_bitfields.h" +#include "nrf51_bitfields.h" - /* - * XXX: need to make the copy from mbuf into the PHY data structures 32-bit - * copies or we are screwed. - */ - /* XXX: 4) Make sure RF is higher priority interrupt than schedule */ /* @@@ -93,9 -88,10 +89,10 @@@ struct ble_phy_obj g_ble_phy_data /* XXX: if 27 byte packets desired we can make this smaller */ /* Global transmit/receive buffer */ - static uint32_t g_ble_phy_txrx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) /* Make sure word-aligned for faster copies */ static uint32_t g_ble_phy_enc_buf[(NRF_ENC_BUF_SIZE + 3) / 4]; #endif @@@ -242,11 -284,16 +285,16 @@@ nrf_wait_disabled(void static void ble_phy_rx_xcvr_setup(void) { - #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) + uint8_t *dptr; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) ++#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (g_ble_phy_data.phy_encrypted) { + dptr += 3; NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->OUTPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_CCM->OUTPTR = (uint32_t)dptr; NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; NRF_CCM->MODE = CCM_MODE_MODE_Decryption; NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; @@@ -255,14 -302,16 +303,16 @@@ NRF_CCM->EVENTS_ENDCRYPT = 0; NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk; } else { - NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_RADIO->PACKETPTR = (uint32_t)dptr; } #else - NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_RADIO->PACKETPTR = (uint32_t)dptr; #endif - #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) -#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) ++#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (g_ble_phy_data.phy_privacy) { + dptr += 3; + NRF_RADIO->PACKETPTR = (uint32_t)dptr; NRF_RADIO->PCNF0 = (6 << RADIO_PCNF0_LFLEN_Pos) | (2 << RADIO_PCNF0_S1LEN_Pos) | (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); @@@ -411,7 -464,7 +465,7 @@@ ble_phy_rx_end_isr(void } else { STATS_INC(ble_phy_stats, rx_valid); ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; - #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) ++#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (g_ble_phy_data.phy_encrypted) { /* Only set MIC failure flag if frame is not zero length */ if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { @@@ -442,11 -495,7 +496,7 @@@ #endif } - /* Call Link Layer receive payload function */ - rxpdu = g_ble_phy_data.rxpdu; - g_ble_phy_data.rxpdu = NULL; - - #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) || (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) || (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) ++#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (g_ble_phy_data.phy_encrypted || g_ble_phy_data.phy_privacy) { /* * XXX: This is a horrible ugly hack to deal with the RAM S1 byte. http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/drivers/nrf52/src/ble_phy.c ---------------------------------------------------------------------- diff --cc net/nimble/drivers/nrf52/src/ble_phy.c index 46bb39a,2e34669..6498a06 --- a/net/nimble/drivers/nrf52/src/ble_phy.c +++ b/net/nimble/drivers/nrf52/src/ble_phy.c @@@ -28,13 -27,8 +28,8 @@@ #include "nimble/nimble_opt.h" #include "controller/ble_phy.h" #include "controller/ble_ll.h" -#include "mcu/nrf52_bitfields.h" +#include "nrf52_bitfields.h" - /* - * XXX: need to make the copy from mbuf into the PHY data structures 32-bit - * copies or we are screwed. - */ - /* XXX: 4) Make sure RF is higher priority interrupt than schedule */ /* @@@ -88,9 -82,10 +83,10 @@@ struct ble_phy_obj g_ble_phy_data /* XXX: if 27 byte packets desired we can make this smaller */ /* Global transmit/receive buffer */ - static uint32_t g_ble_phy_txrx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) /* Make sure word-aligned for faster copies */ static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; #endif @@@ -244,7 -285,12 +286,12 @@@ nrf_wait_disabled(void static void ble_phy_rx_xcvr_setup(void) { - #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) + uint8_t *dptr; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + dptr += 3; + -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) ++#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (g_ble_phy_data.phy_encrypted) { NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; @@@ -257,13 -303,13 +304,13 @@@ NRF_CCM->EVENTS_ENDCRYPT = 0; NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk; } else { - NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_RADIO->PACKETPTR = (uint32_t)dptr; } #else - NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_RADIO->PACKETPTR = (uint32_t)dptr; #endif -#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) if (g_ble_phy_data.phy_privacy) { NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; @@@ -827,12 -870,14 +871,14 @@@ ble_phy_tx(struct os_mbuf *txpdu, uint8 ble_hdr = BLE_MBUF_HDR_PTR(txpdu); payload_len = ble_hdr->txinfo.pyld_len; -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) if (g_ble_phy_data.phy_encrypted) { dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; + ++dptr; + pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; NRF_CCM->SHORTS = 1; - NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->OUTPTR = (uint32_t)&g_ble_phy_txrx_buf[0]; + NRF_CCM->INPTR = (uint32_t)dptr; + NRF_CCM->OUTPTR = (uint32_t)pktptr; NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; NRF_CCM->EVENTS_ERROR = 0; NRF_CCM->MODE = CCM_MODE_LENGTH_Msk; @@@ -844,13 -889,17 +890,17 @@@ NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; #endif - dptr = (uint8_t *)&g_ble_phy_txrx_buf[0]; + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + ++dptr; + pktptr = dptr; } #else -#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) +#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; #endif - dptr = (uint8_t *)&g_ble_phy_txrx_buf[0]; + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + ++dptr; + pktptr = dptr; #endif /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/services/gap/include/services/gap/ble_svc_gap.h ---------------------------------------------------------------------- diff --cc net/nimble/host/services/gap/include/services/gap/ble_svc_gap.h index 0000000,95d4226..dcc2712 mode 000000,100644..100644 --- a/net/nimble/host/services/gap/include/services/gap/ble_svc_gap.h +++ b/net/nimble/host/services/gap/include/services/gap/ble_svc_gap.h @@@ -1,0 -1,39 +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. + */ + + #ifndef H_BLE_SVC_GAP_ + #define H_BLE_SVC_GAP_ + + struct ble_hs_cfg; + + #define BLE_SVC_GAP_UUID16 0x1800 + #define BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME 0x2a00 + #define BLE_SVC_GAP_CHR_UUID16_APPEARANCE 0x2a01 + #define BLE_SVC_GAP_CHR_UUID16_PERIPH_PRIV_FLAG 0x2a02 + #define BLE_SVC_GAP_CHR_UUID16_RECONNECT_ADDR 0x2a03 + #define BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS 0x2a04 + + #define BLE_SVC_GAP_APPEARANCE_GEN_COMPUTER 128 + + const char *ble_svc_gap_device_name(void); + int ble_svc_gap_device_name_set(const char *name); + -int ble_svc_gap_init(struct ble_hs_cfg *cfg); ++int ble_svc_gap_init(void); + + #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/services/gap/src/ble_svc_gap.c ---------------------------------------------------------------------- diff --cc net/nimble/host/services/gap/src/ble_svc_gap.c index 0000000,1a2e8a4..eb67b6c mode 000000,100644..100644 --- a/net/nimble/host/services/gap/src/ble_svc_gap.c +++ b/net/nimble/host/services/gap/src/ble_svc_gap.c @@@ -1,0 -1,167 +1,167 @@@ + /** + * 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 <string.h> + #include "host/ble_hs.h" + #include "services/gap/ble_svc_gap.h" + + /* XXX: This should be configurable. */ + #define BLE_SVC_GAP_NAME_MAX_LEN 31 + + static char ble_svc_gap_name[BLE_SVC_GAP_NAME_MAX_LEN + 1] = "nimble"; + static uint16_t ble_svc_gap_appearance; + static uint8_t ble_svc_gap_privacy_flag; + static uint8_t ble_svc_gap_reconnect_addr[6]; + static uint8_t ble_svc_gap_pref_conn_params[8]; + + static int + ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + + static const struct ble_gatt_svc_def ble_svc_gap_defs[] = { + { + /*** Service: GAP. */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(BLE_SVC_GAP_UUID16), + .characteristics = (struct ble_gatt_chr_def[]) { { + /*** Characteristic: Device Name. */ + .uuid128 = BLE_UUID16(BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME), + .access_cb = ble_svc_gap_access, + .flags = BLE_GATT_CHR_F_READ, + }, { + /*** Characteristic: Appearance. */ + .uuid128 = BLE_UUID16(BLE_SVC_GAP_CHR_UUID16_APPEARANCE), + .access_cb = ble_svc_gap_access, + .flags = BLE_GATT_CHR_F_READ, + }, { + /*** Characteristic: Peripheral Privacy Flag. */ + .uuid128 = BLE_UUID16(BLE_SVC_GAP_CHR_UUID16_PERIPH_PRIV_FLAG), + .access_cb = ble_svc_gap_access, + .flags = BLE_GATT_CHR_F_READ, + }, { + /*** Characteristic: Reconnection Address. */ + .uuid128 = BLE_UUID16(BLE_SVC_GAP_CHR_UUID16_RECONNECT_ADDR), + .access_cb = ble_svc_gap_access, + .flags = BLE_GATT_CHR_F_WRITE, + }, { + /*** Characteristic: Peripheral Preferred Connection Parameters. */ + .uuid128 = + BLE_UUID16(BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS), + .access_cb = ble_svc_gap_access, + .flags = BLE_GATT_CHR_F_READ, + }, { + 0, /* No more characteristics in this service. */ + } }, + }, + + { + 0, /* No more services. */ + }, + }; + + static int + ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) + { + uint16_t uuid16; + int rc; + + uuid16 = ble_uuid_128_to_16(ctxt->chr->uuid128); + assert(uuid16 != 0); + + switch (uuid16) { + case BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = os_mbuf_append(ctxt->om, ble_svc_gap_name, + strlen(ble_svc_gap_name)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + + case BLE_SVC_GAP_CHR_UUID16_APPEARANCE: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = os_mbuf_append(ctxt->om, &ble_svc_gap_appearance, + sizeof ble_svc_gap_appearance); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + + case BLE_SVC_GAP_CHR_UUID16_PERIPH_PRIV_FLAG: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = os_mbuf_append(ctxt->om, &ble_svc_gap_privacy_flag, + sizeof ble_svc_gap_privacy_flag); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + + case BLE_SVC_GAP_CHR_UUID16_RECONNECT_ADDR: + assert(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR); + if (OS_MBUF_PKTLEN(ctxt->om) != sizeof ble_svc_gap_reconnect_addr) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + ble_hs_mbuf_to_flat(ctxt->om, ble_svc_gap_reconnect_addr, + sizeof ble_svc_gap_reconnect_addr, NULL); + return 0; + + case BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = os_mbuf_append(ctxt->om, &ble_svc_gap_pref_conn_params, + sizeof ble_svc_gap_pref_conn_params); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + + default: + assert(0); + return BLE_ATT_ERR_UNLIKELY; + } + } + + const char * + ble_svc_gap_device_name(void) + { + return ble_svc_gap_name; + } + + int + ble_svc_gap_device_name_set(const char *name) + { + int len; + + len = strlen(name); + if (len > BLE_SVC_GAP_NAME_MAX_LEN) { + return BLE_HS_EINVAL; + } + + memcpy(ble_svc_gap_name, name, len); + ble_svc_gap_name[len] = '\0'; + + return 0; + } + + int -ble_svc_gap_init(struct ble_hs_cfg *cfg) ++ble_svc_gap_init(void) + { + int rc; + - rc = ble_gatts_count_cfg(ble_svc_gap_defs, cfg); ++ rc = ble_gatts_count_cfg(ble_svc_gap_defs); + if (rc != 0) { + return rc; + } + + rc = ble_gatts_add_svcs(ble_svc_gap_defs); + if (rc != 0) { + return rc; + } + + return 0; + } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/services/gatt/pkg.yml ---------------------------------------------------------------------- diff --cc net/nimble/host/services/gatt/pkg.yml index 0000000,b8fdabe..54343bd mode 000000,100644..100644 --- a/net/nimble/host/services/gatt/pkg.yml +++ b/net/nimble/host/services/gatt/pkg.yml @@@ -1,0 -1,31 +1,34 @@@ + # + # 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: net/nimble/host/services/gatt + pkg.description: Implements the GATT service. + pkg.author: "Apache Mynewt <d...@mynewt.incubator.apache.org>" + pkg.homepage: "http://mynewt.apache.org/" + pkg.keywords: + - ble + - bluetooth + - nimble + - gatt + + pkg.deps: + - net/nimble/host ++ ++pkg.init_function: ble_svc_mandatory_pkg_init ++pkg.init_stage: 3 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/services/gatt/src/ble_svc_gatt.c ---------------------------------------------------------------------- diff --cc net/nimble/host/services/gatt/src/ble_svc_gatt.c index 0000000,74d3ac9..c6426f0 mode 000000,100644..100644 --- a/net/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/net/nimble/host/services/gatt/src/ble_svc_gatt.c @@@ -1,0 -1,90 +1,90 @@@ + /** + * 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 "host/ble_hs.h" + #include "services/gatt/ble_svc_gatt.h" + + static int + ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + + static const struct ble_gatt_svc_def ble_svc_gatt_defs[] = { + { + /*** Service: GATT */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(BLE_GATT_SVC_UUID16), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16), + .access_cb = ble_svc_gatt_access, + .flags = BLE_GATT_CHR_F_INDICATE, + }, { + 0, /* No more characteristics in this service. */ + } }, + }, + + { + 0, /* No more services. */ + }, + }; + + static int + ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) + { + uint8_t *u8; + + /* The only operation allowed for this characteristic is indicate. This + * access callback gets called by the stack when it needs to read the + * characteristic value to populate the outgoing indication command. + * Therefore, this callback should only get called during an attempt to + * read the characteristic. + */ + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + assert(ctxt->chr == &ble_svc_gatt_defs[0].characteristics[0]); + + /* XXX: For now, always respond with 0 (unchanged). */ + u8 = os_mbuf_extend(ctxt->om, 1); + if (u8 == NULL) { + return BLE_ATT_ERR_INSUFFICIENT_RES; + } + + *u8 = 0; + + return 0; + } + + int -ble_svc_gatt_init(struct ble_hs_cfg *cfg) ++ble_svc_gatt_init(void) + { + int rc; + - rc = ble_gatts_count_cfg(ble_svc_gatt_defs, cfg); ++ rc = ble_gatts_count_cfg(ble_svc_gatt_defs); + if (rc != 0) { + return rc; + } + + rc = ble_gatts_add_svcs(ble_svc_gatt_defs); + if (rc != 0) { + return rc; + } + + return 0; + } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_att_clt.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_att_priv.h ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_att_svr.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_gap.c ---------------------------------------------------------------------- diff --cc net/nimble/host/src/ble_gap.c index 81be873,2699e72..5014a86 --- a/net/nimble/host/src/ble_gap.c +++ b/net/nimble/host/src/ble_gap.c @@@ -770,8 -897,12 +895,13 @@@ ble_gap_rx_update_complete(struct hci_l return; #endif ++ struct ble_gap_update_entry *entry; + struct ble_l2cap_sig_update_params l2cap_params; struct ble_gap_event event; struct ble_hs_conn *conn; + int cb_status; + int call_cb; + int rc; STATS_INC(ble_gap_stats, rx_update_complete); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_gattc.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_gatts.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_hs.c ---------------------------------------------------------------------- diff --cc net/nimble/host/src/ble_hs.c index 84a69a6,1899a74..85b524b --- a/net/nimble/host/src/ble_hs.c +++ b/net/nimble/host/src/ble_hs.c @@@ -60,13 -50,15 +60,15 @@@ static struct os_event ble_hs_event_res uint8_t ble_hs_sync_state; static int ble_hs_reset_reason; -#if MYNEWT_SELFTEST -/** Use a higher frequency timer to allow tests to run faster. */ -#define BLE_HS_HEARTBEAT_OS_TICKS (OS_TICKS_PER_SEC / 10) -#else -#define BLE_HS_HEARTBEAT_OS_TICKS OS_TICKS_PER_SEC -#endif +#define BLE_HS_HEARTBEAT_OS_TICKS \ + (MYNEWT_VAL(BLE_HS_HEARTBEAT_FREQ) * OS_TICKS_PER_SEC / 1000) + +#define BLE_HS_SYNC_RETRY_RATE (OS_TICKS_PER_SEC / 10) + +static struct os_task *ble_hs_parent_task; + #define BLE_HS_SYNC_RETRY_RATE (OS_TICKS_PER_SEC / 10) + /** * Handles unresponsive timeouts and periodic retries in case of resource * shortage. @@@ -406,25 -394,25 +409,41 @@@ voi ble_hs_event_enqueue(struct os_event *ev) { os_eventq_put(&ble_hs_evq, ev); - os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev); + os_eventq_put(ble_hs_cfg.parent_evq, &ble_hs_event_co.cf_c.c_ev); +} + +void +ble_hs_enqueue_hci_event(uint8_t *hci_evt) +{ + struct os_event *ev; + + ev = os_memblock_get(&ble_hs_hci_ev_pool); + if (ev == NULL) { + ble_hci_trans_buf_free(ev->ev_arg); + } else { + ev->ev_queued = 0; + ev->ev_type = BLE_HOST_HCI_EVENT_CTLR_EVENT; + ev->ev_arg = hci_evt; + ble_hs_event_enqueue(ev); + } } + void + ble_hs_enqueue_hci_event(uint8_t *hci_evt) + { + struct os_event *ev; + + ev = os_memblock_get(&ble_hs_hci_ev_pool); + if (ev == NULL) { + ble_hci_trans_buf_free(hci_evt); + } else { + ev->ev_queued = 0; + ev->ev_type = BLE_HOST_HCI_EVENT_CTLR_EVENT; + ev->ev_arg = hci_evt; + ble_hs_event_enqueue(ev); + } + } + /** * Schedules for all pending notifications and indications to be sent in the * host parent task. @@@ -562,15 -548,31 +581,14 @@@ ble_hs_init(void { int rc; - ble_hs_free_mem(); - - if (app_evq == NULL) { - rc = BLE_HS_EINVAL; - goto err; - } - ble_hs_parent_evq = app_evq; - - ble_hs_cfg_init(cfg); - log_init(); - log_console_handler_init(&ble_hs_log_console_handler); - log_register("ble_hs", &ble_hs_log, &ble_hs_log_console_handler); + log_register("ble_hs", &ble_hs_log, &log_console_handler, NULL); - ble_hs_hci_os_event_buf = malloc( - OS_MEMPOOL_BYTES(ble_hs_cfg.max_hci_bufs, sizeof (struct os_event))); - if (ble_hs_hci_os_event_buf == NULL) { - rc = BLE_HS_ENOMEM; - goto err; - } - /* Create memory pool of OS events */ - rc = os_mempool_init(&ble_hs_hci_ev_pool, ble_hs_cfg.max_hci_bufs, + rc = os_mempool_init(&ble_hs_hci_ev_pool, BLE_HS_HCI_EVT_COUNT, sizeof (struct os_event), ble_hs_hci_os_event_buf, "ble_hs_hci_ev_pool"); - assert(rc == 0); + SYSINIT_PANIC_ASSERT(rc == 0); /* Initialize eventq */ os_eventq_init(&ble_hs_evq); @@@ -619,6 -649,9 +637,5 @@@ /* Configure the HCI transport to communicate with a host. */ ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); - /* Configure storage mechanism. */ - /* XXX */ + return 0; - -err: - ble_hs_free_mem(); - return rc; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_hs_adv.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_hs_conn.c ---------------------------------------------------------------------- diff --cc net/nimble/host/src/ble_hs_conn.c index c0d08d0,34d9590..4d1f60c --- a/net/nimble/host/src/ble_hs_conn.c +++ b/net/nimble/host/src/ble_hs_conn.c @@@ -249,9 -245,20 +249,20 @@@ ble_hs_conn_find(uint16_t conn_handle } struct ble_hs_conn * + ble_hs_conn_find_assert(uint16_t conn_handle) + { + struct ble_hs_conn *conn; + + conn = ble_hs_conn_find(conn_handle); + BLE_HS_DBG_ASSERT(conn != NULL); + + return conn; + } + + struct ble_hs_conn * ble_hs_conn_find_by_addr(uint8_t addr_type, uint8_t *addr) { -#if !NIMBLE_OPT(CONNECT) +#if !NIMBLE_BLE_CONNECT return NULL; #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_hs_misc.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_hs_priv.h ---------------------------------------------------------------------- diff --cc net/nimble/host/src/ble_hs_priv.h index 1d77ae6,6bebec9..2a3ce20 --- a/net/nimble/host/src/ble_hs_priv.h +++ b/net/nimble/host/src/ble_hs_priv.h @@@ -98,11 -89,15 +98,11 @@@ int ble_hs_hci_evt_acl_process(struct o int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan); - int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, - struct ble_hs_conn **out_conn, - struct ble_l2cap_chan **out_chan); + void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan); uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type); -void ble_hs_cfg_init(struct ble_hs_cfg *cfg); - int ble_hs_locked_by_cur_task(void); int ble_hs_is_parent_task(void); void ble_hs_lock(void); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_l2cap_sig.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_sm.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_sm_cmd.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_sm_lgcy.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_sm_priv.h ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/src/ble_sm_sc.c ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/test/src/ble_att_clt_test.c ---------------------------------------------------------------------- diff --cc net/nimble/host/test/src/ble_att_clt_test.c index ab89e9d,0000000..14d66f6 mode 100644,000000..100644 --- a/net/nimble/host/test/src/ble_att_clt_test.c +++ b/net/nimble/host/test/src/ble_att_clt_test.c @@@ -1,536 -1,0 +1,567 @@@ +/** + * 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 <string.h> +#include <errno.h> +#include "testutil/testutil.h" +#include "nimble/ble.h" +#include "host/ble_hs_test.h" +#include "ble_hs_test_util.h" + +/** + * @return The handle of the new test connection. + */ +static uint16_t +ble_att_clt_test_misc_init(void) +{ + ble_hs_test_util_init(); + ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, + NULL); + return 2; +} + +static void +ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id, void *value, + int value_len, int is_req) +{ + struct ble_att_write_req req; + struct os_mbuf *om; + + om = ble_hs_test_util_prev_tx_dequeue_pullup(); + TEST_ASSERT_FATAL(om != NULL); + + if (is_req) { + ble_att_write_req_parse(om->om_data, om->om_len, &req); + } else { + ble_att_write_cmd_parse(om->om_data, om->om_len, &req); + } + + TEST_ASSERT(req.bawq_handle == handle_id); + TEST_ASSERT(om->om_len == BLE_ATT_WRITE_REQ_BASE_SZ + value_len); + TEST_ASSERT(memcmp(om->om_data + BLE_ATT_WRITE_REQ_BASE_SZ, value, + value_len) == 0); +} + +static void +ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle, + struct ble_att_write_req *req, + void *value, int value_len, int is_req) +{ + struct os_mbuf *om; + int rc; + + om = ble_hs_test_util_om_from_flat(value, value_len); + if (is_req) { + rc = ble_att_clt_tx_write_req(conn_handle, req, om); + } else { + rc = ble_att_clt_tx_write_cmd(conn_handle, req, om); + } + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_att_clt_test_tx_find_info) +{ + struct ble_att_find_info_req req; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Success. */ + req.bafq_start_handle = 1; + req.bafq_end_handle = 0xffff; + rc = ble_att_clt_tx_find_info(conn_handle, &req); + TEST_ASSERT(rc == 0); + + /*** Error: start handle of 0. */ + req.bafq_start_handle = 0; + req.bafq_end_handle = 0xffff; + rc = ble_att_clt_tx_find_info(conn_handle, &req); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + /*** Error: start handle greater than end handle. */ + req.bafq_start_handle = 500; + req.bafq_end_handle = 499; + rc = ble_att_clt_tx_find_info(conn_handle, &req); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + /*** Success; start and end handles equal. */ + req.bafq_start_handle = 500; + req.bafq_end_handle = 500; + rc = ble_att_clt_tx_find_info(conn_handle, &req); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_att_clt_test_rx_find_info) +{ + struct ble_att_find_info_rsp rsp; + uint16_t conn_handle; + uint8_t buf[1024]; + uint8_t uuid128_1[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; + int off; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** One 128-bit UUID. */ + /* Receive response with attribute mapping. */ + off = 0; + rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT; + ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp); + off += BLE_ATT_FIND_INFO_RSP_BASE_SZ; + + htole16(buf + off, 1); + off += 2; + memcpy(buf + off, uuid128_1, 16); + off += 16; + + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, off); + TEST_ASSERT(rc == 0); + + /*** One 16-bit UUID. */ + /* Receive response with attribute mapping. */ + off = 0; + rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT; + ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp); + off += BLE_ATT_FIND_INFO_RSP_BASE_SZ; + + htole16(buf + off, 2); + off += 2; + htole16(buf + off, 0x000f); + off += 2; + + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, off); + TEST_ASSERT(rc == 0); + + /*** Two 16-bit UUIDs. */ + /* Receive response with attribute mappings. */ + off = 0; + rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT; + ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp); + off += BLE_ATT_FIND_INFO_RSP_BASE_SZ; + + htole16(buf + off, 3); + off += 2; + htole16(buf + off, 0x0010); + off += 2; + + htole16(buf + off, 4); + off += 2; + htole16(buf + off, 0x0011); + off += 2; + + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, off); + TEST_ASSERT(rc == 0); +} + +static void +ble_att_clt_test_case_tx_write_req_or_cmd(int is_req) +{ + struct ble_att_write_req req; + uint16_t conn_handle; + uint8_t value300[500] = { 0 }; + uint8_t value5[5] = { 6, 7, 54, 34, 8 }; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** 5-byte write. */ + req.bawq_handle = 0x1234; + ble_att_clt_test_tx_write_req_or_cmd(conn_handle, &req, value5, + sizeof value5, is_req); + ble_hs_test_util_tx_all(); + ble_att_clt_test_misc_verify_tx_write(0x1234, value5, sizeof value5, + is_req); + + /*** Overlong write; verify command truncated to ATT MTU. */ + req.bawq_handle = 0xab83; + ble_att_clt_test_tx_write_req_or_cmd(conn_handle, &req, value300, + sizeof value300, is_req); + ble_hs_test_util_tx_all(); + ble_att_clt_test_misc_verify_tx_write(0xab83, value300, + BLE_ATT_MTU_DFLT - 3, is_req); +} + +static void +ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset, + uint8_t *attr_data, uint16_t attr_data_len) +{ + struct ble_att_prep_write_cmd req; + struct os_mbuf *om; + uint16_t conn_handle; + int rc; + int i; + + conn_handle = ble_att_clt_test_misc_init(); + + req.bapc_handle = handle; + req.bapc_offset = offset; + om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len); + rc = ble_att_clt_tx_prep_write(conn_handle, &req, om); + TEST_ASSERT(rc == 0); + + ble_hs_test_util_tx_all(); + om = ble_hs_test_util_prev_tx_dequeue_pullup(); + TEST_ASSERT_FATAL(om != NULL); + TEST_ASSERT(om->om_len == BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len); + + ble_att_prep_write_req_parse(om->om_data, om->om_len, &req); + TEST_ASSERT(req.bapc_handle == handle); + TEST_ASSERT(req.bapc_offset == offset); + for (i = 0; i < attr_data_len; i++) { + TEST_ASSERT(om->om_data[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + i] == + attr_data[i]); + } +} + +static void +ble_att_clt_test_misc_exec_good(uint8_t flags) +{ + struct ble_att_exec_write_req req; + struct os_mbuf *om; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + req.baeq_flags = flags; + rc = ble_att_clt_tx_exec_write(conn_handle, &req); + TEST_ASSERT(rc == 0); + + ble_hs_test_util_tx_all(); + om = ble_hs_test_util_prev_tx_dequeue_pullup(); + TEST_ASSERT_FATAL(om != NULL); + TEST_ASSERT(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ); + + ble_att_exec_write_req_parse(om->om_data, om->om_len, &req); + TEST_ASSERT(req.baeq_flags == flags); +} + +static void +ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset, + uint8_t *attr_data, uint16_t attr_data_len, + int status) +{ + struct ble_att_prep_write_cmd req; + struct os_mbuf *om; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len); + + req.bapc_handle = handle; + req.bapc_offset = offset; + rc = ble_att_clt_tx_prep_write(conn_handle, &req, om); + TEST_ASSERT(rc == status); +} + ++static void ++ble_att_clt_test_misc_tx_mtu(uint16_t conn_handle, uint16_t mtu, int status) ++{ ++ struct ble_att_mtu_cmd req; ++ int rc; ++ ++ req.bamc_mtu = mtu; ++ rc = ble_att_clt_tx_mtu(conn_handle, &req); ++ TEST_ASSERT(rc == status); ++ ++ if (rc == 0) { ++ ble_hs_test_util_verify_tx_mtu_cmd(1, mtu); ++ } ++} ++ ++ +TEST_CASE(ble_att_clt_test_tx_write) +{ + ble_att_clt_test_case_tx_write_req_or_cmd(0); + ble_att_clt_test_case_tx_write_req_or_cmd(1); +} + +TEST_CASE(ble_att_clt_test_tx_read) +{ + struct ble_att_read_req req; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Success. */ + req.barq_handle = 1; + rc = ble_att_clt_tx_read(conn_handle, &req); + TEST_ASSERT(rc == 0); + + /*** Error: handle of 0. */ + req.barq_handle = 0; + rc = ble_att_clt_tx_read(conn_handle, &req); + TEST_ASSERT(rc == BLE_HS_EINVAL); +} + +TEST_CASE(ble_att_clt_test_rx_read) +{ + uint16_t conn_handle; + uint8_t buf[1024]; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Basic success. */ + buf[0] = BLE_ATT_OP_READ_RSP; + buf[1] = 0; + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, 2); + TEST_ASSERT(rc == 0); + + /*** Larger response. */ + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, 20); + TEST_ASSERT(rc == 0); + + /*** Zero-length response. */ + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, 1); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_att_clt_test_tx_read_blob) +{ + struct ble_att_read_blob_req req; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Success. */ + req.babq_handle = 1; + req.babq_offset = 0; + rc = ble_att_clt_tx_read_blob(conn_handle, &req); + TEST_ASSERT(rc == 0); + + /*** Error: handle of 0. */ + req.babq_handle = 0; + req.babq_offset = 0; + rc = ble_att_clt_tx_read_blob(conn_handle, &req); + TEST_ASSERT(rc == BLE_HS_EINVAL); +} + +TEST_CASE(ble_att_clt_test_rx_read_blob) +{ + uint16_t conn_handle; + uint8_t buf[1024]; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Basic success. */ + buf[0] = BLE_ATT_OP_READ_BLOB_RSP; + buf[1] = 0; + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, 2); + TEST_ASSERT(rc == 0); + + /*** Larger response. */ + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, 20); + TEST_ASSERT(rc == 0); + + /*** Zero-length response. */ + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + buf, 1); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_att_clt_test_tx_read_mult) +{ + struct os_mbuf *om; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Success. */ + rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2); + TEST_ASSERT(rc == 0); + + ble_hs_test_util_tx_all(); + om = ble_hs_test_util_prev_tx_dequeue_pullup(); + TEST_ASSERT_FATAL(om != NULL); + TEST_ASSERT(om->om_len == BLE_ATT_READ_MULT_REQ_BASE_SZ + 4); + + ble_att_read_mult_req_parse(om->om_data, om->om_len); + TEST_ASSERT(le16toh(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ) == 1); + TEST_ASSERT(le16toh(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ + 2) == 2); + + /*** Error: no handles. */ + rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0); + TEST_ASSERT(rc == BLE_HS_EINVAL); +} + +TEST_CASE(ble_att_clt_test_rx_read_mult) +{ + uint16_t conn_handle; + uint8_t buf[1024]; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Basic success. */ + ble_att_read_mult_rsp_write(buf, sizeof buf); + htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12); + + rc = ble_hs_test_util_l2cap_rx_payload_flat( + conn_handle, BLE_L2CAP_CID_ATT, buf, + BLE_ATT_READ_MULT_RSP_BASE_SZ + 2); + TEST_ASSERT(rc == 0); + + /*** Larger response. */ + htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12); + htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 2, 43); + htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 4, 91); + rc = ble_hs_test_util_l2cap_rx_payload_flat( + conn_handle, BLE_L2CAP_CID_ATT, buf, + BLE_ATT_READ_MULT_RSP_BASE_SZ + 6); + TEST_ASSERT(rc == 0); + + /*** Zero-length response. */ + rc = ble_hs_test_util_l2cap_rx_payload_flat( + conn_handle, BLE_L2CAP_CID_ATT, buf, + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_att_clt_test_tx_prep_write) +{ + uint8_t attr_data[512]; + int i; + + for (i = 0; i < sizeof attr_data; i++) { + attr_data[i] = i; + } + + /*** Success. */ + ble_att_clt_test_misc_prep_good(123, 0, attr_data, 16); + ble_att_clt_test_misc_prep_good(5432, 100, attr_data, 2); + ble_att_clt_test_misc_prep_good(0x1234, 400, attr_data, 0); + ble_att_clt_test_misc_prep_good(5432, 0, attr_data, + BLE_ATT_MTU_DFLT - + BLE_ATT_PREP_WRITE_CMD_BASE_SZ); + ble_att_clt_test_misc_prep_good(0x1234, 507, attr_data, 5); + + /*** Error: handle of 0. */ + ble_att_clt_test_misc_prep_bad(0, 0, attr_data, 16, BLE_HS_EINVAL); + + /*** Error: offset + length greater than maximum attribute size. */ + ble_att_clt_test_misc_prep_bad(1, 507, attr_data, 6, BLE_HS_EINVAL); + + /*** Error: packet larger than MTU. */ + ble_att_clt_test_misc_prep_bad(1, 0, attr_data, + BLE_ATT_MTU_DFLT - + BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1, + BLE_HS_EINVAL); +} + +TEST_CASE(ble_att_clt_test_rx_prep_write) +{ + struct ble_att_prep_write_cmd rsp; + uint16_t conn_handle; + uint8_t buf[1024]; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Basic success. */ + rsp.bapc_handle = 0x1234; + rsp.bapc_offset = 0; + ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp); + memset(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, 1, 5); + rc = ble_hs_test_util_l2cap_rx_payload_flat( + conn_handle, BLE_L2CAP_CID_ATT, buf, + BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 5); + TEST_ASSERT(rc == 0); + + /*** 0-length write. */ + rsp.bapc_handle = 0x1234; + rsp.bapc_offset = 0; + ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp); + rc = ble_hs_test_util_l2cap_rx_payload_flat( + conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_att_clt_test_tx_exec_write) +{ + struct ble_att_exec_write_req req; + uint16_t conn_handle; + int rc; + + conn_handle = ble_att_clt_test_misc_init(); + + /*** Success. */ + ble_att_clt_test_misc_exec_good(0); + ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_CONFIRM); + + /*** Error: invalid flags value. */ + req.baeq_flags = 0x02; + rc = ble_att_clt_tx_exec_write(conn_handle, &req); + TEST_ASSERT(rc == BLE_HS_EINVAL); +} + ++TEST_CASE(ble_att_clt_test_tx_mtu) ++{ ++ uint16_t conn_handle; ++ ++ conn_handle = ble_att_clt_test_misc_init(); ++ ++ /*** Success. */ ++ ble_att_clt_test_misc_tx_mtu(conn_handle, 50, 0); ++ ++ /*** Error: repeated sends. */ ++ ble_att_clt_test_misc_tx_mtu(conn_handle, 50, BLE_HS_EALREADY); ++ ble_att_clt_test_misc_tx_mtu(conn_handle, 60, BLE_HS_EALREADY); ++} ++ +TEST_SUITE(ble_att_clt_suite) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_att_clt_test_tx_find_info(); + ble_att_clt_test_rx_find_info(); + ble_att_clt_test_tx_read(); + ble_att_clt_test_rx_read(); + ble_att_clt_test_tx_read_blob(); + ble_att_clt_test_rx_read_blob(); + ble_att_clt_test_tx_read_mult(); + ble_att_clt_test_rx_read_mult(); + ble_att_clt_test_tx_write(); + ble_att_clt_test_tx_prep_write(); + ble_att_clt_test_rx_prep_write(); + ble_att_clt_test_tx_exec_write(); ++ ble_att_clt_test_tx_mtu(); +} + +int +ble_att_clt_test_all(void) +{ + ble_att_clt_suite(); + + return tu_any_failed; +}