summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/nimble/transport
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/mynewt-nimble/nimble/transport')
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore2
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml28
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c68
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h34
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h35
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h193
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml39
-rwxr-xr-xsrc/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh45
-rwxr-xr-xsrc/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh31
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c326
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c162
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c145
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c98
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml104
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml36
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c194
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c153
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c141
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_priv.h29
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c332
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h49
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml43
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c10
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml38
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c426
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml51
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/pkg.yml9
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c183
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/syscfg.yml17
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c2
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/usb/pkg.yml39
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c410
-rw-r--r--src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml57
33 files changed, 3500 insertions, 29 deletions
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore
new file mode 100644
index 00000000..bba9f995
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/.gitignore
@@ -0,0 +1,2 @@
+/src/libble_stack_da1469x.a
+
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml
new file mode 100644
index 00000000..9b9ee83e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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: nimble/transport/dialog_cmac/cmac_driver/diag
+pkg.description: Default diag configuration for CMAC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - dialog
+ - da1469x
+ - cmac
+pkg.apis: dialog_cmac_diag
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c
new file mode 100644
index 00000000..4f754706
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c
@@ -0,0 +1,68 @@
+/*
+ * 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 "syscfg/syscfg.h"
+#include "mcu/mcu.h"
+
+#if MYNEWT_VAL(BLE_HOST)
+void
+cmac_diag_setup_host(void)
+{
+ /* Setup pins for diagnostic signals */
+ mcu_gpio_set_pin_function(42, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG0); /* DIAG_0 @ P1.10 */
+ mcu_gpio_set_pin_function(43, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG1); /* DIAG_1 @ P1.11 */
+ mcu_gpio_set_pin_function(44, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG2); /* DIAG_2 @ P1.12 */
+ mcu_gpio_set_pin_function(24, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_3 @ P0.24 */
+ mcu_gpio_set_pin_function(21, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_4 @ P0.21 */
+ mcu_gpio_set_pin_function(20, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_5 @ P0.20 */
+ mcu_gpio_set_pin_function(19, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_6 @ P0.19 */
+ mcu_gpio_set_pin_function(18, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_7 @ P0.18 */
+ mcu_gpio_set_pin_function(31, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_8 @ P0.31 */
+ mcu_gpio_set_pin_function(30, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_9 @ P0.30 */
+ mcu_gpio_set_pin_function(29, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_10 @ P0.29 */
+ mcu_gpio_set_pin_function(28, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_11 @ P0.28 */
+ mcu_gpio_set_pin_function(27, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_12 @ P0.27 */
+ mcu_gpio_set_pin_function(26, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_13 @ P0.26 */
+ mcu_gpio_set_pin_function(38, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_14 @ P1.06 */
+ mcu_gpio_set_pin_function(41, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_15 @ P1.09 */
+}
+#endif
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+void
+cmac_diag_setup_cmac(void)
+{
+ MCU_DIAG_MAP( 0, 4, DSER);
+ MCU_DIAG_MAP( 1, 6, CMAC_ON_ERROR);
+ MCU_DIAG_MAP( 2, 2, PHY_TX_EN);
+ MCU_DIAG_MAP( 3, 2, PHY_RX_EN);
+ MCU_DIAG_MAP( 4, 2, PHY_TXRX_DATA_COMB);
+ MCU_DIAG_MAP( 5, 2, PHY_TXRX_DATA_EN_COMB);
+ MCU_DIAG_MAP( 6, 5, EV1US_FRAME_START);
+ MCU_DIAG_MAP( 7, 5, EV_BS_START);
+ MCU_DIAG_MAP( 8, 5, EV1C_BS_STOP);
+ MCU_DIAG_MAP( 9, 5, EV1US_PHY_TO_IDLE);
+ MCU_DIAG_MAP(10, 9, CALLBACK_IRQ);
+ MCU_DIAG_MAP(11, 9, FIELD_IRQ);
+ MCU_DIAG_MAP(12, 9, FRAME_IRQ);
+ MCU_DIAG_MAP(13, 3, SLP_TIMER_ACTIVE);
+ MCU_DIAG_MAP(14, 4, SLEEPING);
+ MCU_DIAG_MAP(15, 8, LL_TIMER1_00);
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h
new file mode 100644
index 00000000..dc6ee903
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h
@@ -0,0 +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.
+ */
+
+#ifndef __MCU_CMAC_DIAG_H_
+#define __MCU_CMAC_DIAG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cmac_diag_setup_host(void);
+void cmac_diag_setup_cmac(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_CMAC_DIAG_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h
new file mode 100644
index 00000000..50d86755
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h
@@ -0,0 +1,35 @@
+/*
+ * 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 __DA1469X_CMAC_V2_H_
+#define __DA1469X_CMAC_V2_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cmac_host_init(void);
+void cmac_host_signal2cmac(void);
+void cmac_host_rf_calibrate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DA1469X_CMAC_V2_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h
new file mode 100644
index 00000000..90b5827d
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h
@@ -0,0 +1,193 @@
+/*
+ * 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 __MCU_CMAC_SHARED_H_
+#define __MCU_CMAC_SHARED_H_
+
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CMAC_SHARED_MAGIC_CMAC (0x4C6C) /* "lL" */
+#define CMAC_SHARED_MAGIC_SYS (0x5368) /* "hS" */
+
+#define CMAC_SHARED_F_SYS_LPCLK_AVAILABLE (0x0001)
+
+/*
+ * Simple circular buffer for storing random numbers generated by M33
+ * Empty: cmr_in = cmr_out = 0;
+ * Full: cmr_in + 1 = cmr_out
+ *
+ * cmr_in: used by the M33 to add random numbers to the circular buffer.
+ * cmr_out: used by CMAC to retrieve random numbers
+ *
+ * NOTE: cmr_in and cmr_out are indices.
+ */
+#define CMAC_RAND_BUF_ELEMS (16)
+
+struct cmac_rand {
+ int cmr_active;
+ int cmr_in;
+ int cmr_out;
+ uint32_t cmr_buf[CMAC_RAND_BUF_ELEMS];
+};
+
+struct cmac_mbox {
+ uint16_t rd_off;
+ uint16_t wr_off;
+};
+
+struct cmac_dcdc {
+ uint8_t enabled;
+ uint32_t v18;
+ uint32_t v18p;
+ uint32_t vdd;
+ uint32_t v14;
+ uint32_t ctrl1;
+};
+
+struct cmac_trim {
+ uint8_t rfcu_len;
+ uint8_t rfcu_mode1_len;
+ uint8_t rfcu_mode2_len;
+ uint8_t synth_len;
+ uint32_t rfcu[ MYNEWT_VAL(CMAC_TRIM_SIZE_RFCU) ];
+ uint32_t rfcu_mode1[2];
+ uint32_t rfcu_mode2[2];
+ uint32_t synth[ MYNEWT_VAL(CMAC_TRIM_SIZE_SYNTH) ];
+};
+
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+struct cmac_debug {
+ int8_t last_rx_rssi;
+ int8_t tx_power_override;
+
+ uint32_t cal_res_1;
+ uint32_t cal_res_2;
+ uint32_t trim_val1_tx_1;
+ uint32_t trim_val1_tx_2;
+ uint32_t trim_val2_tx;
+ uint32_t trim_val2_rx;
+};
+#endif
+
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+struct cmac_coredump {
+ uint32_t lr;
+ uint32_t pc;
+ uint32_t assert;
+ const char *assert_file;
+ uint32_t assert_line;
+
+ uint32_t CM_STAT_REG;
+ uint32_t CM_LL_TIMER1_36_10_REG;
+ uint32_t CM_LL_TIMER1_9_0_REG;
+ uint32_t CM_ERROR_REG;
+ uint32_t CM_EXC_STAT_REG;
+};
+#endif
+
+#define CMAC_PENDING_OP_LP_CLK 0x0001
+#define CMAC_PENDING_OP_RF_CAL 0x0002
+
+struct cmac_shared_data {
+ uint16_t magic_cmac;
+ uint16_t magic_sys;
+ uint16_t pending_ops;
+ uint16_t lp_clock_freq; /* LP clock frequency */
+ uint32_t xtal32m_settle_us;/* XTAL32M settling time */
+ struct cmac_mbox mbox_s2c; /* SYS2CMAC mailbox */
+ struct cmac_mbox mbox_c2s; /* CMAC2SYS mailbox */
+ struct cmac_dcdc dcdc; /* DCDC settings */
+ struct cmac_trim trim; /* Trim data */
+ struct cmac_rand rand; /* Random numbers */
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ struct cmac_debug debug; /* Extra debug data */
+#endif
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+ struct cmac_coredump coredump;
+#endif
+
+ uint8_t mbox_s2c_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_S2C) ];
+ uint8_t mbox_c2s_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_C2S) ];
+};
+
+#if MYNEWT_VAL(BLE_HOST)
+extern volatile struct cmac_shared_data *g_cmac_shared_data;
+#elif MYNEWT_VAL(BLE_CONTROLLER)
+extern volatile struct cmac_shared_data g_cmac_shared_data;
+#endif
+
+/* cmac_mbox */
+typedef int (cmac_mbox_read_cb)(const void *data, uint16_t len);
+typedef void (cmac_mbox_write_notif_cb)(void);
+void cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb);
+void cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb);
+int cmac_mbox_read(void);
+int cmac_mbox_write(const void *data, uint16_t len);
+
+/* cmac_rand */
+typedef void (*cmac_rand_isr_cb_t)(uint8_t rnum);
+void cmac_rand_start(void);
+void cmac_rand_stop(void);
+void cmac_rand_read(void);
+void cmac_rand_write(void);
+void cmac_rand_chk_fill(void);
+int cmac_rand_get_next(void);
+int cmac_rand_is_active(void);
+int cmac_rand_is_full(void);
+void cmac_rand_fill(uint32_t *buf, int num_words);
+void cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb);
+
+void cmac_shared_init(void);
+void cmac_shared_sync(void);
+
+#if MYNEWT_VAL(BLE_HOST)
+#define CMAC_SHARED_LOCK_VAL 0x40000000
+#elif MYNEWT_VAL(BLE_CONTROLLER)
+#define CMAC_SHARED_LOCK_VAL 0xc0000000
+#endif
+
+static inline void
+cmac_shared_lock(void)
+{
+ volatile uint32_t *bsr_set = (void *)0x50050074;
+ volatile uint32_t *bsr_stat = (void *)0x5005007c;
+
+ while ((*bsr_stat & 0xc0000000) != CMAC_SHARED_LOCK_VAL) {
+ *bsr_set = CMAC_SHARED_LOCK_VAL;
+ }
+}
+
+static inline void
+cmac_shared_unlock(void)
+{
+ volatile uint32_t *bsr_reset = (void *)0x50050078;
+
+ *bsr_reset = CMAC_SHARED_LOCK_VAL;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MCU_CMAC_SHARED_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml
new file mode 100644
index 00000000..5b4a2129
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: nimble/transport/dialog_cmac/cmac_driver
+pkg.description: Driver for Dialog CMAC IPC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - dialog
+ - da1469x
+ - cmac
+
+pkg.req_apis.CMAC_DEBUG_DIAG_ENABLE:
+ - dialog_cmac_diag
+
+pkg.ign_files.BLE_CONTROLLER:
+ - cmac_host.c
+
+pkg.post_link_cmds.BLE_CONTROLLER:
+ scripts/create_cmac_bin.sh: 100
+
+pkg.pre_link_cmds.BLE_HOST:
+ scripts/build_libcmac.sh: 100
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh
new file mode 100755
index 00000000..bbc822aa
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# 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.
+
+NEWT=${MYNEWT_NEWT_PATH}
+OBJCOPY=${MYNEWT_OBJCOPY_PATH}
+AR=${MYNEWT_AR_PATH}
+LIBCMAC_A=${MYNEWT_USER_SRC_DIR}/libcmac.a
+
+export WORK_DIR=${MYNEWT_USER_WORK_DIR}
+export BASENAME_ROM=cmac.rom
+export BASENAME_RAM=cmac.ram
+
+if [ ${MYNEWT_VAL_CMAC_IMAGE_SINGLE} -eq 0 ]; then
+ # Create empty binary for ROM image (1 byte required for objcopy)
+ truncate -s 1 ${WORK_DIR}/${BASENAME_ROM}.bin
+ # Create fixed size RAM image
+ truncate -s ${MYNEWT_VAL_CMAC_IMAGE_RAM_SIZE} ${WORK_DIR}/${BASENAME_RAM}.bin
+else
+ ${NEWT} build ${MYNEWT_VAL_CMAC_IMAGE_TARGET_NAME}
+fi
+
+cd ${WORK_DIR}
+
+# Convert both binaries to objects and create archive to link
+${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \
+ --rename-section .data=.libcmac.rom ${BASENAME_ROM}.bin ${BASENAME_ROM}.o
+${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \
+ --rename-section .data=.libcmac.ram ${BASENAME_RAM}.bin ${BASENAME_RAM}.o
+${AR} -rcs ${LIBCMAC_A} ${BASENAME_ROM}.o ${BASENAME_RAM}.o
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh
new file mode 100755
index 00000000..954d0860
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# 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.
+
+OBJCOPY=${MYNEWT_OBJCOPY_PATH}
+ELF=${MYNEWT_APP_BIN_DIR}/blehci.elf
+
+cd ${WORK_DIR}
+
+# Strip .ram section from ROM image
+${OBJCOPY} -R .ram -O binary ${ELF} ${BASENAME_ROM}.bin
+# RAM image is the same as binary created by newt
+cp ${ELF}.bin ${BASENAME_RAM}.bin
+
+# Create a copy of ROM image to flash to partition, if required
+cp ${BASENAME_ROM}.bin ${ELF}.rom.bin
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c
new file mode 100644
index 00000000..df81c582
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c
@@ -0,0 +1,326 @@
+/*
+ * 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 <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "sysflash/sysflash.h"
+#include "os/os.h"
+#include "mcu/mcu.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/da1469x_hal.h"
+#include "mcu/da1469x_lpclk.h"
+#include "mcu/da1469x_clock.h"
+#include "mcu/da1469x_trimv.h"
+#include "mcu/da1469x_pdc.h"
+#include "cmac_driver/cmac_host.h"
+#include "cmac_driver/cmac_shared.h"
+#include "cmac_driver/cmac_diag.h"
+#include "trng/trng.h"
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+#include "console/console.h"
+#endif
+
+/* CMAC data */
+extern char _binary_cmac_rom_bin_start[];
+extern char _binary_cmac_rom_bin_end;
+extern char _binary_cmac_ram_bin_start[];
+extern char _binary_cmac_ram_bin_end;
+
+struct cmac_image_info {
+ uint32_t magic;
+ uint32_t size_rom;
+ uint32_t size_ram;
+ uint32_t offset_data;
+ uint32_t offset_shared;
+};
+
+/* PDC entry for waking up CMAC */
+static int8_t g_cmac_host_pdc_sys2cmac;
+/* PDC entry for waking up M33 */
+static int8_t g_cmac_host_pdc_cmac2sys;
+
+static void cmac_host_rand_fill(struct os_event *ev);
+static struct os_event g_cmac_host_rand_ev = {
+ .ev_cb = cmac_host_rand_fill
+};
+
+static void cmac_host_rand_chk_fill(void);
+
+static void
+cmac2sys_isr(void)
+{
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+ volatile struct cmac_coredump *cd = &g_cmac_shared_data->coredump;
+ const char *assert_file;
+#endif
+
+ os_trace_isr_enter();
+
+ /* Clear CMAC2SYS interrupt */
+ *(volatile uint32_t *)0x40002000 = 2;
+
+ cmac_mbox_read();
+
+ if (*(volatile uint32_t *)0x40002000 & 0x1c00) {
+#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
+ console_blocking_mode();
+ console_printf("CMAC error (0x%08lx)\n", *(volatile uint32_t *)0x40002000);
+ console_printf(" lr:0x%08lx pc:0x%08lx\n", cd->lr, cd->pc);
+ if (cd->assert) {
+ console_printf(" assert:0x%08lx\n", cd->assert);
+ if (cd->assert_file) {
+ /* Need to translate pointer from M0 code segment to M33 data */
+ assert_file = cd->assert_file + MCU_MEM_SYSRAM_START_ADDRESS +
+ MEMCTRL->CMI_CODE_BASE_REG;
+ console_printf(" %s:%d\n",
+ assert_file, (unsigned)cd->assert_line);
+ }
+ }
+ console_printf(" 0x%08lx CM_ERROR_REG\n", cd->CM_ERROR_REG);
+ console_printf(" 0x%08lx CM_EXC_STAT_REG\n", cd->CM_EXC_STAT_REG);
+ console_printf(" 0x%08lx CM_LL_TIMER1_36_10_REG\n", cd->CM_LL_TIMER1_36_10_REG);
+ console_printf(" 0x%08lx CM_LL_TIMER1_9_0_REG\n", cd->CM_LL_TIMER1_9_0_REG);
+
+ /* Spin if debugger is connected to CMAC to avoid resetting it */
+ if (cd->CM_STAT_REG & 0x20) {
+ for (;;);
+ }
+#endif
+ /* XXX CMAC is in error state, need to recover */
+ assert(0);
+ return;
+ }
+
+ cmac_host_rand_chk_fill();
+
+ os_trace_isr_exit();
+}
+
+static void
+cmac_host_rand_fill(struct os_event *ev)
+{
+ size_t num_bytes;
+ struct trng_dev *trng;
+ uint32_t *rnum;
+ uint32_t rnums[CMAC_RAND_BUF_ELEMS];
+
+ /* Check if full */
+ if (!cmac_rand_is_active() || cmac_rand_is_full()) {
+ return;
+ }
+
+ assert(ev->ev_arg != NULL);
+
+ /* Fill buffer with random numbers even though we may not use all of them */
+ trng = ev->ev_arg;
+ rnum = &rnums[0];
+ num_bytes = trng_read(trng, rnum, CMAC_RAND_BUF_ELEMS * sizeof(uint32_t));
+
+ cmac_rand_fill(rnum, num_bytes / 4);
+ cmac_host_signal2cmac();
+}
+
+static void
+cmac_host_rand_chk_fill(void)
+{
+ if (cmac_rand_is_active() && !cmac_rand_is_full()) {
+ os_eventq_put(os_eventq_dflt_get(), &g_cmac_host_rand_ev);
+ }
+}
+
+void
+cmac_host_signal2cmac(void)
+{
+ da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
+}
+
+static void
+cmac_host_lpclk_cb(uint32_t freq)
+{
+ /* No need to wakeup CMAC if LP clock frequency did not change */
+ if (g_cmac_shared_data->lp_clock_freq == freq) {
+ return;
+ }
+
+ cmac_shared_lock();
+ g_cmac_shared_data->lp_clock_freq = freq;
+ g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_LP_CLK;
+ cmac_shared_unlock();
+
+ cmac_host_signal2cmac();
+}
+
+#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE)
+static void
+cmac_host_print_trim(const char *name, const uint32_t *tv, unsigned len)
+{
+ console_printf("[CMAC] Trim values for '%s'\n", name);
+
+ while (len) {
+ console_printf(" 0x%08x = 0x%08x\n", (unsigned)tv[0], (unsigned)tv[1]);
+ len -= 2;
+ tv += 2;
+ }
+}
+#endif
+
+void
+cmac_host_rf_calibrate(void)
+{
+ cmac_shared_lock();
+ g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_RF_CAL;
+ cmac_shared_unlock();
+
+ cmac_host_signal2cmac();
+}
+
+void
+cmac_host_init(void)
+{
+ struct trng_dev *trng;
+ struct cmac_image_info ii;
+ uint32_t cmac_rom_size;
+ uint32_t cmac_ram_size;
+#if !MYNEWT_VAL(CMAC_IMAGE_SINGLE)
+ const struct flash_area *fa;
+ int rc;
+#endif
+ struct cmac_trim *trim;
+
+ /* Get trng os device */
+ trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL);
+ assert(trng);
+ g_cmac_host_rand_ev.ev_arg = trng;
+
+#if MYNEWT_VAL(CMAC_DEBUG_DIAG_ENABLE)
+ cmac_diag_setup_host();
+#endif
+
+#if MYNEWT_VAL(CMAC_DEBUG_SWD_ENABLE)
+ /* Enable CMAC debugger */
+ CRG_TOP->SYS_CTRL_REG |= 0x40; /* CRG_TOP_SYS_CTRL_REG_CMAC_DEBUGGER_ENABLE_Msk */
+#endif
+
+ /*
+ * Add PDC entry to wake up CMAC from M33
+ *
+ * XXX if MCU_DEBUG_GPIO_DEEP_SLEEP is enabled on CMAC, this should also
+ * enable PD_COM so CMAC can access GPIOs after wake up
+ */
+ g_cmac_host_pdc_sys2cmac = da1469x_pdc_add(MCU_PDC_TRIGGER_MAC_TIMER,
+ MCU_PDC_MASTER_CMAC,
+ MCU_PDC_EN_XTAL);
+ da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
+ da1469x_pdc_ack(g_cmac_host_pdc_sys2cmac);
+
+ /* Add PDC entry to wake up M33 from CMAC, if does not exist yet */
+ g_cmac_host_pdc_cmac2sys = da1469x_pdc_find(MCU_PDC_TRIGGER_COMBO,
+ MCU_PDC_MASTER_M33, 0);
+ if (g_cmac_host_pdc_cmac2sys < 0) {
+ g_cmac_host_pdc_cmac2sys = da1469x_pdc_add(MCU_PDC_TRIGGER_COMBO,
+ MCU_PDC_MASTER_M33,
+ MCU_PDC_EN_XTAL);
+ da1469x_pdc_set(g_cmac_host_pdc_cmac2sys);
+ da1469x_pdc_ack(g_cmac_host_pdc_cmac2sys);
+ }
+
+ /* Setup CMAC2SYS interrupt */
+ NVIC_SetVector(CMAC2SYS_IRQn, (uint32_t)cmac2sys_isr);
+ NVIC_SetPriority(CMAC2SYS_IRQn, MYNEWT_VAL(CMAC_CMAC2SYS_IRQ_PRIORITY));
+ NVIC_DisableIRQ(CMAC2SYS_IRQn);
+
+ /* Enable Radio LDO */
+ CRG_TOP->POWER_CTRL_REG |= CRG_TOP_POWER_CTRL_REG_LDO_RADIO_ENABLE_Msk;
+
+ /* Enable CMAC, but keep it in reset */
+ CRG_TOP->CLK_RADIO_REG = (1 << CRG_TOP_CLK_RADIO_REG_RFCU_ENABLE_Pos) |
+ (1 << CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Pos) |
+ (0 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_SEL_Pos) |
+ (1 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_ENABLE_Pos) |
+ (0 << CRG_TOP_CLK_RADIO_REG_CMAC_DIV_Pos);
+
+ /* Calculate size of ROM and RAM area */
+ cmac_rom_size = &_binary_cmac_rom_bin_end - &_binary_cmac_rom_bin_start[0];
+ cmac_ram_size = &_binary_cmac_ram_bin_end - &_binary_cmac_ram_bin_start[0];
+
+ /* Load image header and check if image can be loaded */
+#if MYNEWT_VAL(CMAC_IMAGE_SINGLE)
+ memcpy(&ii, &_binary_cmac_rom_bin_start[128], sizeof(ii));
+#else
+ rc = flash_area_open(FLASH_AREA_IMAGE_1, &fa);
+ assert(rc == 0);
+ rc = flash_area_read(fa, 128, &ii, sizeof(ii));
+ assert(rc == 0);
+#endif
+
+ assert(ii.magic == 0xC3ACC3AC);
+ assert(ii.size_rom == cmac_rom_size);
+ assert(ii.size_ram <= cmac_ram_size);
+
+ /* Copy CMAC image to RAM */
+#if MYNEWT_VAL(CMAC_IMAGE_SINGLE)
+ memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size);
+ memcpy(&_binary_cmac_ram_bin_start, &_binary_cmac_rom_bin_start, ii.size_rom);
+#else
+ memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size);
+ rc = flash_area_read(fa, 0, &_binary_cmac_ram_bin_start, ii.size_rom);
+ assert(rc == 0);
+#endif
+
+ /* Setup CMAC memory addresses */
+ MEMCTRL->CMI_CODE_BASE_REG = (uint32_t)&_binary_cmac_ram_bin_start;
+ MEMCTRL->CMI_DATA_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_data;
+ MEMCTRL->CMI_SHARED_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_shared;
+ MEMCTRL->CMI_END_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.size_ram - 1;
+
+ /* Initialize shared memory */
+ cmac_shared_init();
+
+ trim = (struct cmac_trim *)&g_cmac_shared_data->trim;
+ trim->rfcu_len = da1469x_trimv_group_read(6, trim->rfcu, ARRAY_SIZE(trim->rfcu));
+ trim->rfcu_mode1_len = da1469x_trimv_group_read(8, trim->rfcu_mode1, ARRAY_SIZE(trim->rfcu_mode1));
+ trim->rfcu_mode2_len = da1469x_trimv_group_read(10, trim->rfcu_mode2, ARRAY_SIZE(trim->rfcu_mode2));
+ trim->synth_len = da1469x_trimv_group_read(7, trim->synth, ARRAY_SIZE(trim->synth));
+
+#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE)
+ cmac_host_print_trim("rfcu", trim->rfcu, trim->rfcu_len);
+ cmac_host_print_trim("rfcu_mode1", trim->rfcu_mode1, trim->rfcu_mode1_len);
+ cmac_host_print_trim("rfcu_mode2", trim->rfcu_mode2, trim->rfcu_mode2_len);
+ cmac_host_print_trim("synth", trim->synth, trim->synth_len);
+#endif
+
+ /* Release CMAC from reset and sync */
+ CRG_TOP->CLK_RADIO_REG &= ~CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Msk;
+ cmac_shared_sync();
+
+ da1469x_lpclk_register_cmac_cb(cmac_host_lpclk_cb);
+
+#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) && MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ /* Trim values are calculated on RF init, so are valid after synced with CMAC */
+ console_printf("[CMAC] Calculated trim_val1: 1=0x%08x 2=0x%08x\n",
+ (unsigned)g_cmac_shared_data->debug.trim_val1_tx_1,
+ (unsigned)g_cmac_shared_data->debug.trim_val1_tx_2);
+ console_printf("[CMAC] Calculated trim_val2: tx=0x%08x rx=0x%08x\n",
+ (unsigned)g_cmac_shared_data->debug.trim_val2_tx,
+ (unsigned)g_cmac_shared_data->debug.trim_val2_rx);
+#endif
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c
new file mode 100644
index 00000000..9594dbe9
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c
@@ -0,0 +1,162 @@
+/*
+ * 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 <cmac_driver/cmac_shared.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "mcu/mcu.h"
+#include "os/os_arch.h"
+#include "os/os.h"
+
+#ifndef min
+#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+static cmac_mbox_read_cb *g_cmac_mbox_read_cb;
+static cmac_mbox_write_notif_cb *g_cmac_mbox_write_notif_cb;
+
+void
+cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb)
+{
+ g_cmac_mbox_read_cb = cb;
+}
+
+void
+cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb)
+{
+ g_cmac_mbox_write_notif_cb = cb;
+}
+
+int
+cmac_mbox_read(void)
+{
+#if MYNEWT_VAL(BLE_HOST)
+ volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_c2s;
+ uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_c2s_buf;
+ const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S);
+#else
+ volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_s2c;
+ uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_s2c_buf;
+ const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C);
+#endif
+ uint16_t rd_off;
+ uint16_t wr_off;
+ uint16_t chunk;
+ int len = 0;
+
+ if (!g_cmac_mbox_read_cb) {
+ return 0;
+ }
+
+ do {
+ rd_off = mbox->rd_off;
+ wr_off = mbox->wr_off;
+
+ if (rd_off <= wr_off) {
+ chunk = wr_off - rd_off;
+ } else {
+ chunk = mbox_size - rd_off;
+ }
+
+ while (chunk) {
+ len = g_cmac_mbox_read_cb(&mbox_buf[rd_off], chunk);
+ if (len < 0) {
+ break;
+ }
+
+ rd_off += len;
+ chunk -= len;
+ }
+
+ mbox->rd_off = rd_off == mbox_size ? 0 : rd_off;
+ } while ((mbox->rd_off != mbox->wr_off) && (len >= 0));
+
+ return 0;
+}
+
+int
+cmac_mbox_write(const void *data, uint16_t len)
+{
+#if MYNEWT_VAL(BLE_HOST)
+ volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_s2c;
+ uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_s2c_buf;
+ const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C);
+#else
+ volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_c2s;
+ uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_c2s_buf;
+ const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S);
+#endif
+ uint16_t rd_off;
+ uint16_t wr_off;
+ uint16_t max_wr;
+ uint16_t chunk;
+
+ while (len) {
+ rd_off = mbox->rd_off;
+ wr_off = mbox->wr_off;
+
+ /*
+ * Calculate maximum length to write, i.e. up to end of buffer or stop
+ * before rd_off to be able to detect full queue.
+ */
+ if (rd_off > wr_off) {
+ /*
+ * |0|1|2|3|4|5|6|7|
+ * | | | |W| | |R| |
+ * `---^
+ */
+ max_wr = rd_off - wr_off - 1;
+ } else if (rd_off == 0) {
+ /*
+ * |0|1|2|3|4|5|6|7|
+ * |R| | |W| | | | |
+ * `-------^
+ */
+ max_wr = mbox_size - wr_off - 1;
+ } else {
+ /*
+ * |0|1|2|3|4|5|6|7|
+ * | |R| |W| | | | |
+ * `---------^
+ */
+ max_wr = mbox_size - wr_off;
+ }
+
+ chunk = min(len, max_wr);
+
+ if (chunk == 0) {
+ continue;
+ }
+
+ memcpy(&mbox_buf[wr_off], data, chunk);
+
+ wr_off += chunk;
+ mbox->wr_off = wr_off == mbox_size ? 0 : wr_off;
+
+ g_cmac_mbox_write_notif_cb();
+
+ len -= chunk;
+ data = (uint8_t *)data + chunk;
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c
new file mode 100644
index 00000000..67a315f9
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c
@@ -0,0 +1,145 @@
+/*
+ * 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 <cmac_driver/cmac_shared.h>
+#include <string.h>
+#include <stdbool.h>
+#include "syscfg/syscfg.h"
+#include "mcu/mcu.h"
+#include "os/os_arch.h"
+#include "os/os.h"
+
+#if MYNEWT_VAL(BLE_HOST)
+int
+cmac_rand_is_active(void)
+{
+ return g_cmac_shared_data->rand.cmr_active;
+}
+
+int
+cmac_rand_is_full(void)
+{
+ int next;
+ bool rc;
+
+ next = cmac_rand_get_next();
+ if (next == g_cmac_shared_data->rand.cmr_out) {
+ rc = 1;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+int
+cmac_rand_get_next(void)
+{
+ int next;
+
+ /* If active and not full, put event on queue to get random numbers */
+ next = g_cmac_shared_data->rand.cmr_in + 1;
+ if (next == CMAC_RAND_BUF_ELEMS) {
+ next = 0;
+ }
+ return next;
+}
+
+void
+cmac_rand_fill(uint32_t *buf, int num_words)
+{
+ int next;
+
+ /* XXX: if words is 0, is it possible we could get into a state
+ where we are waiting for random numbers but M33 does not know it
+ has to fill any? */
+
+ /* NOTE: we already know the buffer is not full first time through */
+ next = g_cmac_shared_data->rand.cmr_in;
+ while (num_words) {
+ g_cmac_shared_data->rand.cmr_buf[next] = buf[0];
+ next = cmac_rand_get_next();
+ g_cmac_shared_data->rand.cmr_in = next;
+ next = cmac_rand_get_next();
+ if (next == g_cmac_shared_data->rand.cmr_out) {
+ break;
+ }
+ --num_words;
+ ++buf;
+ }
+}
+#endif
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+static cmac_rand_isr_cb_t g_cmac_rand_isr_cb;
+
+void
+cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb)
+{
+ g_cmac_rand_isr_cb = cb;
+}
+
+void
+cmac_rand_start(void)
+{
+ g_cmac_shared_data.rand.cmr_active = 1;
+}
+
+void
+cmac_rand_stop(void)
+{
+ g_cmac_shared_data.rand.cmr_active = 0;
+}
+
+/**
+ * cmac rnum read
+ *
+ * Called during the system to cmac isr to take random numbers
+ * from shared memory into the BLE stack.
+ */
+void
+cmac_rand_read(void)
+{
+ uint8_t bytes_left;
+ uint32_t rnum;
+
+ /* Just leave if no callback. */
+ if (g_cmac_rand_isr_cb == NULL) {
+ return;
+ }
+
+ bytes_left = 0;
+ while (g_cmac_shared_data.rand.cmr_active) {
+ if (bytes_left) {
+ --bytes_left;
+ rnum >>= 8;
+ } else if (g_cmac_shared_data.rand.cmr_out != g_cmac_shared_data.rand.cmr_in) {
+ bytes_left = 3;
+ rnum = g_cmac_shared_data.rand.cmr_buf[g_cmac_shared_data.rand.cmr_out];
+ ++g_cmac_shared_data.rand.cmr_out;
+ if (g_cmac_shared_data.rand.cmr_out == CMAC_RAND_BUF_ELEMS) {
+ g_cmac_shared_data.rand.cmr_out = 0;
+ }
+ } else {
+ break;
+ }
+ (*g_cmac_rand_isr_cb)((uint8_t)rnum);
+ }
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c
new file mode 100644
index 00000000..24640ca4
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c
@@ -0,0 +1,98 @@
+/*
+ * 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 "syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_CONTROLLER) && !MYNEWT_VAL(MCU_DEBUG_DSER_CMAC_SHARED)
+#define MCU_DIAG_SER_DISABLE
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include "mcu/mcu.h"
+#include <cmac_driver/cmac_shared.h>
+#include "os/os_arch.h"
+#include "os/os.h"
+
+#ifndef min
+#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+#if MYNEWT_VAL(BLE_HOST)
+volatile struct cmac_shared_data *g_cmac_shared_data;
+#include "mcu/da1469x_clock.h"
+#define MCU_DIAG_SER(_x)
+#elif MYNEWT_VAL(BLE_CONTROLLER)
+volatile struct cmac_shared_data g_cmac_shared_data __attribute__((section(".shdata")));
+#endif
+
+void
+cmac_shared_init(void)
+{
+#if MYNEWT_VAL(BLE_HOST)
+ g_cmac_shared_data = (void *)(MCU_MEM_SYSRAM_START_ADDRESS +
+ MEMCTRL->CMI_SHARED_BASE_REG);
+
+ memset((void *)g_cmac_shared_data, 0, sizeof(*g_cmac_shared_data));
+
+ g_cmac_shared_data->xtal32m_settle_us = MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US);
+
+ g_cmac_shared_data->dcdc.enabled = DCDC->DCDC_CTRL1_REG & DCDC_DCDC_CTRL1_REG_DCDC_ENABLE_Msk;
+ if (g_cmac_shared_data->dcdc.enabled) {
+ g_cmac_shared_data->dcdc.v18 = DCDC->DCDC_V18_REG;
+ g_cmac_shared_data->dcdc.v18p = DCDC->DCDC_V18P_REG;
+ g_cmac_shared_data->dcdc.vdd = DCDC->DCDC_VDD_REG;
+ g_cmac_shared_data->dcdc.v14 = DCDC->DCDC_V14_REG;
+ g_cmac_shared_data->dcdc.ctrl1 = DCDC->DCDC_CTRL1_REG;
+ }
+
+#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
+ g_cmac_shared_data->debug.tx_power_override = INT8_MAX;
+#endif
+#endif
+}
+
+
+void
+cmac_shared_sync(void)
+{
+ /*
+ * We need to guarantee proper order of initialization here, i.e. SYS has
+ * to wait until CMAC finished initialization as otherwise host may start
+ * sending HCI packets which will timeout as there is no one to read them.
+ */
+#if MYNEWT_VAL(BLE_HOST)
+ assert(g_cmac_shared_data->magic_sys == 0);
+
+ while (g_cmac_shared_data->magic_cmac != CMAC_SHARED_MAGIC_CMAC);
+ g_cmac_shared_data->magic_sys = CMAC_SHARED_MAGIC_SYS;
+
+ NVIC_EnableIRQ(CMAC2SYS_IRQn);
+#endif
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ assert(g_cmac_shared_data.magic_cmac == 0);
+
+ g_cmac_shared_data.magic_cmac = CMAC_SHARED_MAGIC_CMAC;
+ while (g_cmac_shared_data.magic_sys != CMAC_SHARED_MAGIC_SYS);
+
+ NVIC_SetPriority(SYS2CMAC_IRQn, 3);
+ NVIC_EnableIRQ(SYS2CMAC_IRQn);
+#endif
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml
new file mode 100644
index 00000000..a382c424
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml
@@ -0,0 +1,104 @@
+# 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.
+#
+
+syscfg.defs:
+ CMAC_MBOX_SIZE_S2C:
+ description: >
+ Size of mailbox for SYS to CMAC data. The size
+ value should be power of 2 to allow for better
+ code optimization.
+ value: 128
+ CMAC_MBOX_SIZE_C2S:
+ description: >
+ Size of mailbox for CMAC to SYS data. The size
+ value should be power of 2 to allow for better
+ code optimization.
+ value: 128
+
+ CMAC_TRIM_SIZE_RFCU:
+ description: >
+ Size of trim values for RFCU. This is maximum
+ number of trim values that can be read from
+ OTP and applied, all excessive values will be
+ discarded.
+ value: 10
+ CMAC_TRIM_SIZE_SYNTH:
+ description: >
+ Size of trim values for RFCU. This is maximum
+ number of trim values that can be read from
+ OTP and applied, all excessive values will be
+ discarded.
+ value: 10
+
+ CMAC_DEBUG_SWD_ENABLE:
+ description: >
+ Enable CMAC SWD interface.
+ value: 0
+ CMAC_DEBUG_DIAG_ENABLE:
+ description: >
+ Enable CMAC diagnostic lines.
+ value: 0
+ CMAC_DEBUG_DATA_ENABLE:
+ description: >
+ Enable extra debugging data in shared segment.
+ value: 0
+ CMAC_DEBUG_COREDUMP_ENABLE:
+ description: >
+ Enable dumping CMAC registers to shared segment
+ on fault.
+ value: 1
+ CMAC_DEBUG_HOST_PRINT_ENABLE:
+ description: >
+ Enable some debug printouts to console from host side.
+ This will dump some settings during startup, useful to
+ check what is loaded to CMAC via shared data.
+ value: 0
+
+ CMAC_IMAGE_SINGLE:
+ description: >
+ When enable, CMAC binary is linked with application image
+ creating a single image build. See CMAC_IMAGE_TARGET_NAME.
+ When disabled, CMAC binary is built and flashed separately
+ to flash partition. See CMAC_IMAGE_PARTITION.
+ value: 1
+ CMAC_IMAGE_TARGET_NAME:
+ description: >
+ Target name to build for CMAC binary for single image build.
+ value: "@apache-mynewt-nimble/targets/dialog_cmac"
+ CMAC_IMAGE_PARTITION:
+ description: >
+ Flash partition to load CMAC binary from if single image build
+ is disabled.
+ value: FLASH_AREA_IMAGE_1
+ CMAC_IMAGE_RAM_SIZE:
+ description: >
+ Size of RAM area in bytes reserved for CMAC if single image
+ build is disabled. Unit suffix (K, M) is allowed.
+ Note: for single image build this setting is not applicable
+ since proper RAM area size is automatically calculated from
+ CMAC binary.
+ value: 128K
+
+ CMAC_CMAC2SYS_IRQ_PRIORITY:
+ description: >
+ The priority of the CMAC2SYS IRQ. Default is 0, or highest
+ priority.
+ value: 0
+
+syscfg.restrictions.BLE_HOST:
+ - TRNG
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml
new file mode 100644
index 00000000..ef8fc1ee
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/pkg.yml
@@ -0,0 +1,36 @@
+#
+# 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: nimble/transport/dialog_cmac
+pkg.description: HCI H4 transport for Dialog CMAC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+
+pkg.deps:
+ - nimble
+ - nimble/transport/dialog_cmac/cmac_driver
+
+pkg.apis:
+ - ble_transport
+
+pkg.init:
+ ble_hci_cmac_init: 100
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c
new file mode 100644
index 00000000..665b6216
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c
@@ -0,0 +1,194 @@
+/*
+ * 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 "syscfg/syscfg.h"
+#include "os/mynewt.h"
+#include "nimble/ble.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+#include "ble_hci_cmac_priv.h"
+
+/*
+ * If controller-to-host flow control is enabled we need to hold an extra command
+ * buffer for HCI_Host_Number_Of_Completed_Packets which can be sent at any time.
+ */
+#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) || MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+#define HCI_CMD_COUNT 2
+#else
+#define HCI_CMD_COUNT 1
+#endif
+
+#define POOL_ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) + \
+ BLE_MBUF_MEMBLOCK_OVERHEAD + \
+ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+static uint8_t ble_hci_pool_cmd_mempool_buf[
+ OS_MEMPOOL_BYTES(HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ)];
+static struct os_mempool ble_hci_pool_cmd_mempool;
+
+static uint8_t ble_hci_pool_evt_hi_mempool_buf[
+ OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool ble_hci_pool_evt_hi_mempool;
+
+static uint8_t ble_hci_pool_evt_lo_mempool_buf[
+ OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool ble_hci_pool_evt_lo_mempool;
+
+static uint8_t ble_hci_pool_acl_mempool_buf[
+ OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+ POOL_ACL_BLOCK_SIZE)];
+static struct os_mempool_ext ble_hci_pool_acl_mempool;
+static struct os_mbuf_pool ble_hci_pool_acl_mbuf_pool;
+
+__attribute__((weak)) void ble_hci_trans_notify_free(void);
+
+static os_mempool_put_fn *g_ble_hci_pool_acl_mempool_put_cb;
+static void *g_ble_hci_pool_acl_mempool_put_arg;
+
+int
+ble_hci_trans_reset(void)
+{
+ return 0;
+}
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+ uint8_t *buf;
+
+ switch (type) {
+ case BLE_HCI_TRANS_BUF_CMD:
+ buf = os_memblock_get(&ble_hci_pool_cmd_mempool);
+ break;
+ case BLE_HCI_TRANS_BUF_EVT_HI:
+ buf = os_memblock_get(&ble_hci_pool_evt_hi_mempool);
+ if (buf) {
+ break;
+ }
+ /* no break */
+ case BLE_HCI_TRANS_BUF_EVT_LO:
+ buf = os_memblock_get(&ble_hci_pool_evt_lo_mempool);
+ break;
+ default:
+ assert(0);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+ int rc;
+
+ if (os_memblock_from(&ble_hci_pool_cmd_mempool, buf)) {
+ rc = os_memblock_put(&ble_hci_pool_cmd_mempool, buf);
+ assert(rc == 0);
+ } else if (os_memblock_from(&ble_hci_pool_evt_hi_mempool, buf)) {
+ rc = os_memblock_put(&ble_hci_pool_evt_hi_mempool, buf);
+ assert(rc == 0);
+ } else {
+ assert(os_memblock_from(&ble_hci_pool_evt_lo_mempool, buf));
+ rc = os_memblock_put(&ble_hci_pool_evt_lo_mempool, buf);
+ assert(rc == 0);
+ }
+
+ ble_hci_trans_notify_free();
+}
+
+struct os_mbuf *
+ble_hci_cmac_alloc_acl_mbuf(void)
+{
+ return os_mbuf_get_pkthdr(&ble_hci_pool_acl_mbuf_pool,
+ sizeof(struct ble_mbuf_hdr));
+}
+
+static os_error_t
+ble_hci_cmac_free_acl_cb(struct os_mempool_ext *mpe, void *data, void *arg)
+{
+ int rc;
+
+ if (g_ble_hci_pool_acl_mempool_put_cb) {
+ rc = g_ble_hci_pool_acl_mempool_put_cb(mpe, data,
+ g_ble_hci_pool_acl_mempool_put_arg);
+ } else {
+ rc = os_memblock_put_from_cb(&mpe->mpe_mp, data);
+ }
+
+ if (rc != 0) {
+ return rc;
+ }
+
+ ble_hci_trans_notify_free();
+
+ return 0;
+}
+
+
+int
+ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
+{
+ g_ble_hci_pool_acl_mempool_put_cb = cb;
+ g_ble_hci_pool_acl_mempool_put_arg = arg;
+
+ return 0;
+}
+
+void
+ble_hci_cmac_init(void)
+{
+ int rc;
+
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = os_mempool_init(&ble_hci_pool_cmd_mempool,
+ HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ,
+ ble_hci_pool_cmd_mempool_buf, "ble_hci_cmd");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_init(&ble_hci_pool_evt_hi_mempool,
+ MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+ ble_hci_pool_evt_hi_mempool_buf, "ble_hci_evt_hi");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_init(&ble_hci_pool_evt_lo_mempool,
+ MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+ ble_hci_pool_evt_lo_mempool_buf, "ble_hci_evt_lo");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_ext_init(&ble_hci_pool_acl_mempool,
+ MYNEWT_VAL(BLE_ACL_BUF_COUNT), POOL_ACL_BLOCK_SIZE,
+ ble_hci_pool_acl_mempool_buf, "ble_hci_acl");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mbuf_pool_init(&ble_hci_pool_acl_mbuf_pool,
+ &ble_hci_pool_acl_mempool.mpe_mp, POOL_ACL_BLOCK_SIZE,
+ MYNEWT_VAL(BLE_ACL_BUF_COUNT));
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ ble_hci_pool_acl_mempool.mpe_put_cb = ble_hci_cmac_free_acl_cb;
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c
new file mode 100644
index 00000000..1164fe71
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c
@@ -0,0 +1,153 @@
+/*
+ * 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 "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_HOST)
+
+#include "cmac_driver/cmac_shared.h"
+#include "cmac_driver/cmac_host.h"
+#include "nimble/ble_hci_trans.h"
+#include "os/os_mbuf.h"
+#include "ble_hci_trans_h4.h"
+#include "ble_hci_cmac_priv.h"
+
+struct ble_hci_cmac_hs_api {
+ ble_hci_trans_rx_cmd_fn *evt_cb;
+ void *evt_arg;
+ ble_hci_trans_rx_acl_fn *acl_cb;
+ void *acl_arg;
+};
+
+static struct ble_hci_cmac_hs_api g_ble_hci_cmac_hs_api;
+static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_hs_rx_state;
+static bool g_ble_hci_cmac_hs_read_err;
+
+static int
+ble_hci_cmac_hs_frame_cb(uint8_t pkt_type, void *data)
+{
+ int rc;
+
+ switch (pkt_type) {
+ case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+ rc = g_ble_hci_cmac_hs_api.acl_cb(data, g_ble_hci_cmac_hs_api.acl_arg);
+ break;
+ case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+ rc = g_ble_hci_cmac_hs_api.evt_cb(data, g_ble_hci_cmac_hs_api.evt_arg);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return rc;
+}
+
+static int
+ble_hci_cmac_hs_mbox_read_cb(const void *data, uint16_t len)
+{
+ int rlen;
+ os_sr_t sr;
+
+ rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_hs_rx_state, data, len,
+ ble_hci_cmac_hs_frame_cb);
+ if (rlen < 0) {
+ /*
+ * There was oom error, we need to wait for buffer to be freed and
+ * trigger another read.
+ */
+ OS_ENTER_CRITICAL(sr);
+ g_ble_hci_cmac_hs_read_err = true;
+ OS_EXIT_CRITICAL(sr);
+ }
+
+ return rlen;
+}
+
+static void
+ble_hci_cmac_hs_mbox_write_notif_cb(void)
+{
+ cmac_host_signal2cmac();
+}
+
+int
+ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
+{
+ uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_CMD;
+
+ cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+ cmac_mbox_write(cmd, cmd[2] + 3);
+
+ ble_hci_trans_buf_free(cmd);
+
+ return 0;
+}
+
+int
+ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
+{
+ uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_ACL;
+ struct os_mbuf *om_next;
+
+ cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+
+ while (om) {
+ om_next = SLIST_NEXT(om, om_next);
+
+ cmac_mbox_write(om->om_data, om->om_len);
+
+ os_mbuf_free(om);
+ om = om_next;
+ }
+
+ return 0;
+}
+
+void
+ble_hci_trans_notify_free(void)
+{
+ os_sr_t sr;
+
+ OS_ENTER_CRITICAL(sr);
+ if (g_ble_hci_cmac_hs_read_err) {
+ g_ble_hci_cmac_hs_read_err = false;
+ /* Just trigger an interrupt, it will trigger read */
+ NVIC_SetPendingIRQ(CMAC2SYS_IRQn);
+ }
+ OS_EXIT_CRITICAL(sr);
+}
+
+void
+ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, void *evt_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+ g_ble_hci_cmac_hs_api.evt_cb = evt_cb;
+ g_ble_hci_cmac_hs_api.evt_arg = evt_arg;
+ g_ble_hci_cmac_hs_api.acl_cb = acl_cb;
+ g_ble_hci_cmac_hs_api.acl_arg = acl_arg;
+
+ /* We can now handle data from CMAC, initialize it */
+ cmac_mbox_set_read_cb(ble_hci_cmac_hs_mbox_read_cb);
+ cmac_mbox_set_write_notif_cb(ble_hci_cmac_hs_mbox_write_notif_cb);
+ cmac_host_init();
+}
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c
new file mode 100644
index 00000000..3531529c
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c
@@ -0,0 +1,141 @@
+/*
+ * 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 "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+
+#if !MYNEWT_VAL(MCU_DEBUG_DSER_BLE_HCI_CMAC_LL)
+#define MCU_DIAG_SER_DISABLE
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include "mcu/mcu.h"
+#include "cmac_driver/cmac_shared.h"
+#include "nimble/ble_hci_trans.h"
+#include "os/os_mbuf.h"
+#include "ble_hci_trans_h4.h"
+#include "ble_hci_cmac_priv.h"
+
+struct ble_hci_cmac_ll_api {
+ ble_hci_trans_rx_cmd_fn *cmd_cb;
+ void *cmd_arg;
+ ble_hci_trans_rx_acl_fn *acl_cb;
+ void *acl_arg;
+};
+
+static struct ble_hci_cmac_ll_api g_ble_hci_cmac_ll_api;
+static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_ll_rx_state;
+
+static int
+ble_hci_cmac_ll_frame_cb(uint8_t pkt_type, void *data)
+{
+ int rc;
+
+ MCU_DIAG_SER('F');
+
+ switch (pkt_type) {
+ case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+ rc = g_ble_hci_cmac_ll_api.cmd_cb(data, g_ble_hci_cmac_ll_api.cmd_arg);
+ break;
+ case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+ rc = g_ble_hci_cmac_ll_api.acl_cb(data, g_ble_hci_cmac_ll_api.acl_arg);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return rc;
+}
+
+static int
+ble_hci_cmac_ll_mbox_read_cb(const void *data, uint16_t len)
+{
+ int rlen;
+
+ MCU_DIAG_SER('R');
+ rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_ll_rx_state, data, len,
+ ble_hci_cmac_ll_frame_cb);
+
+ /* There should be no oom on LL side due to flow control used */
+ assert(rlen >= 0);
+
+ return rlen;
+}
+
+static void
+ble_hci_cmac_ll_mbox_write_notif_cb(void)
+{
+ MCU_DIAG_SER('W');
+ CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk;
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *evt)
+{
+ uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_EVT;
+
+ cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+ cmac_mbox_write(evt, evt[1] + 2);
+
+ ble_hci_trans_buf_free(evt);
+
+ return 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+ uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_ACL;
+ struct os_mbuf *om_next;
+
+ cmac_mbox_write(&pkt_type, sizeof(pkt_type));
+
+ while (om) {
+ om_next = SLIST_NEXT(om, om_next);
+
+ cmac_mbox_write(om->om_data, om->om_len);
+
+ os_mbuf_free(om);
+ om = om_next;
+ }
+
+ return 0;
+}
+
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+ g_ble_hci_cmac_ll_api.cmd_cb = cmd_cb;
+ g_ble_hci_cmac_ll_api.cmd_arg = cmd_arg;
+ g_ble_hci_cmac_ll_api.acl_cb = acl_cb;
+ g_ble_hci_cmac_ll_api.acl_arg = acl_arg;
+
+ /* Setup callbacks for mailboxes */
+ cmac_mbox_set_read_cb(ble_hci_cmac_ll_mbox_read_cb);
+ cmac_mbox_set_write_notif_cb(ble_hci_cmac_ll_mbox_write_notif_cb);
+
+ /* Synchronize with SYS */
+ cmac_shared_sync();
+}
+
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_priv.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_priv.h
new file mode 100644
index 00000000..451053c3
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_cmac_priv.h
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _BLE_HCI_CMAC_PRIV_H_
+#define _BLE_HCI_CMAC_PRIV_H_
+
+#include "os/os_mbuf.h"
+
+struct os_mbuf *ble_hci_cmac_alloc_acl_mbuf(void);
+
+void ble_hci_trans_notify_free(void);
+
+#endif /* _BLE_HCI_CMAC_PRIV_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c
new file mode 100644
index 00000000..74da3912
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c
@@ -0,0 +1,332 @@
+/*
+ * 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 <stdbool.h>
+#include <string.h>
+#include "syscfg/syscfg.h"
+#include "os/os_mbuf.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+#include "ble_hci_trans_h4.h"
+#include "ble_hci_cmac_priv.h"
+
+#define RXS_STATE_W4_PKT_TYPE 0
+#define RXS_STATE_W4_HEADER 1
+#define RXS_STATE_W4_PAYLOAD 2
+#define RXS_STATE_COMPLETED 3
+
+struct input_buffer {
+ const uint8_t *buf;
+ uint16_t len;
+};
+
+static int
+ble_hci_trans_h4_ib_adjust(struct input_buffer *ib, uint16_t len)
+{
+ assert(ib->len >= len);
+
+ ib->buf += len;
+ ib->len -= len;
+
+ return len;
+}
+
+static void
+ble_hci_trans_h4_rxs_start(struct ble_hci_trans_h4_rx_state *rxs, uint8_t pkt_type)
+{
+ rxs->pkt_type = pkt_type;
+ rxs->len = 0;
+ rxs->expected_len = 0;
+
+ switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+ rxs->min_len = 3;
+ break;
+#endif
+ case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+ rxs->min_len = 4;
+ break;
+#if MYNEWT_VAL(BLE_HOST)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+ rxs->min_len = 2;
+ break;
+#endif
+ default:
+ /* XXX sync loss */
+ assert(0);
+ break;
+ }
+}
+
+static int
+ble_hci_trans_h4_pull_min_len(struct ble_hci_trans_h4_rx_state *rxs,
+ struct input_buffer *ib)
+{
+ uint16_t len;
+
+ len = min(ib->len, rxs->min_len - rxs->len);
+ memcpy(&rxs->hdr[rxs->len], ib->buf, len);
+
+ rxs->len += len;
+ ble_hci_trans_h4_ib_adjust(ib, len);
+
+ return rxs->len != rxs->min_len;
+}
+
+static int
+ble_hci_trans_h4_rx_state_w4_header(struct ble_hci_trans_h4_rx_state *rxs,
+ struct input_buffer *ib)
+{
+#if MYNEWT_VAL(BLE_HOST)
+ int pool;
+#endif
+ int rc;
+
+ rc = ble_hci_trans_h4_pull_min_len(rxs, ib);
+ if (rc) {
+ /* need more data */
+ return 1;
+ }
+
+ switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+ rxs->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+ if (!rxs->buf) {
+ return -1;
+ }
+
+ memcpy(rxs->buf, rxs->hdr, rxs->len);
+ rxs->expected_len = rxs->hdr[2] + 3;
+ break;
+#endif
+ case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+ rxs->om = ble_hci_cmac_alloc_acl_mbuf();
+ if (!rxs->om) {
+ return -1;
+ }
+
+ os_mbuf_append(rxs->om, rxs->hdr, rxs->len);
+ rxs->expected_len = get_le16(&rxs->hdr[2]) + 4;
+ break;
+#if MYNEWT_VAL(BLE_HOST)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+ pool = BLE_HCI_TRANS_BUF_EVT_HI;
+ if (rxs->hdr[0] == BLE_HCI_EVCODE_LE_META) {
+ /* For LE Meta event we need 3 bytes to parse header */
+ rxs->min_len = 3;
+ rc = ble_hci_trans_h4_pull_min_len(rxs, ib);
+ if (rc) {
+ /* need more data */
+ return 1;
+ }
+
+ /* Advertising reports shall be allocated from low-prio pool */
+ if ((rxs->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) ||
+ (rxs->hdr[2] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
+ pool = BLE_HCI_TRANS_BUF_EVT_LO;
+ }
+ }
+
+ /*
+ * XXX Events originally allocated from hi-pool can use lo-pool as
+ * fallback and cannot be dropped. Events allocated from lo-pool
+ * can be dropped to avoid oom while scanning which means that
+ * any advertising or extended advertising report can be silently
+ * discarded by transport. While this is perfectly fine for legacy
+ * advertising, for extended advertising it means we can drop start
+ * or end of chain report and host won't be able to reassemble
+ * chain properly... so just need to make sure pool on host side is
+ * large enough to catch up with controller.
+ */
+ rxs->buf = ble_hci_trans_buf_alloc(pool);
+ if (!rxs->buf && pool == BLE_HCI_TRANS_BUF_EVT_HI) {
+ rxs->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+ if (!rxs->buf) {
+ return -1;
+ }
+ }
+
+ if (rxs->buf) {
+ memcpy(rxs->buf, rxs->hdr, rxs->len);
+ }
+
+ rxs->expected_len = rxs->hdr[1] + 2;
+ break;
+#endif
+ default:
+ assert(0);
+ break;
+ }
+
+ return 0;
+}
+
+static int
+ble_hci_trans_h4_rx_state_w4_payload(struct ble_hci_trans_h4_rx_state *rxs,
+ struct input_buffer *ib)
+{
+ uint16_t mbuf_len;
+ uint16_t len;
+ int rc;
+
+ len = min(ib->len, rxs->expected_len - rxs->len);
+
+ switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+#endif
+ if (rxs->buf) {
+ memcpy(&rxs->buf[rxs->len], ib->buf, len);
+ }
+ break;
+ case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+ assert(rxs->om);
+
+ mbuf_len = OS_MBUF_PKTLEN(rxs->om);
+ rc = os_mbuf_append(rxs->om, ib->buf, len);
+ if (rc) {
+ /*
+ * Some data may already be appended so need to adjust rxs only by
+ * the size of appended data.
+ */
+ len = OS_MBUF_PKTLEN(rxs->om) - mbuf_len;
+ rxs->len += len;
+ ble_hci_trans_h4_ib_adjust(ib, len);
+
+ return -1;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ rxs->len += len;
+ ble_hci_trans_h4_ib_adjust(ib, len);
+
+ /* return 1 if need more data */
+ return rxs->len != rxs->expected_len;
+}
+
+static void
+ble_hci_trans_h4_rx_state_completed(struct ble_hci_trans_h4_rx_state *rxs,
+ ble_hci_trans_h4_frame_cb *frame_cb)
+{
+ int rc;
+
+ switch (rxs->pkt_type) {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+ case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
+#endif
+ if (rxs->buf) {
+ rc = frame_cb(rxs->pkt_type, rxs->buf);
+ if (rc != 0) {
+ ble_hci_trans_buf_free(rxs->buf);
+ }
+ rxs->buf = NULL;
+ }
+ break;
+ case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
+ if (rxs->om) {
+ rc = frame_cb(rxs->pkt_type, rxs->om);
+ if (rc != 0) {
+ os_mbuf_free_chain(rxs->om);
+ }
+ rxs->om = NULL;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+int
+ble_hci_trans_h4_rx(struct ble_hci_trans_h4_rx_state *rxs, const uint8_t *buf,
+ uint16_t len, ble_hci_trans_h4_frame_cb *frame_cb)
+{
+ struct input_buffer ib = {
+ .buf = buf,
+ .len = len,
+ };
+ int rc = 0;
+
+ while (ib.len && (rc >= 0)) {
+ rc = 0;
+ switch (rxs->state) {
+ case RXS_STATE_W4_PKT_TYPE:
+ ble_hci_trans_h4_rxs_start(rxs, ib.buf[0]);
+ ble_hci_trans_h4_ib_adjust(&ib, 1);
+ rxs->state = RXS_STATE_W4_HEADER;
+ /* no break */
+
+ case RXS_STATE_W4_HEADER:
+ rc = ble_hci_trans_h4_rx_state_w4_header(rxs, &ib);
+ if (rc) {
+ break;
+ }
+ rxs->state = RXS_STATE_W4_PAYLOAD;
+ /* no break */
+
+ case RXS_STATE_W4_PAYLOAD:
+ rc = ble_hci_trans_h4_rx_state_w4_payload(rxs, &ib);
+ if (rc) {
+ break;
+ }
+ rxs->state = RXS_STATE_COMPLETED;
+ /* no break */
+
+ case RXS_STATE_COMPLETED:
+ ble_hci_trans_h4_rx_state_completed(rxs, frame_cb);
+ rxs->state = RXS_STATE_W4_PKT_TYPE;
+ break;
+
+ default:
+ assert(0);
+ /* consume all remaining data */
+ ble_hci_trans_h4_ib_adjust(&ib, ib.len);
+ break;
+ }
+ }
+
+ /*
+ * Calculate consumed bytes
+ *
+ * Note: we should always consume some bytes unless there is an oom error.
+ * It's also possible that we have an oom error but already consumed some
+ * data, in such case just return success and error will be returned on next
+ * pass.
+ */
+ len = len - ib.len;
+ if (len == 0) {
+ assert(rc < 0);
+ return -1;
+ }
+
+ return len;
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h
new file mode 100644
index 00000000..5b83f6b0
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _BLE_HCI_TRANS_H4_H_
+#define _BLE_HCI_TRANS_H4_H_
+
+#include <stdint.h>
+
+#define BLE_HCI_TRANS_H4_PKT_TYPE_NONE 0x00
+#define BLE_HCI_TRANS_H4_PKT_TYPE_CMD 0x01
+#define BLE_HCI_TRANS_H4_PKT_TYPE_ACL 0x02
+#define BLE_HCI_TRANS_H4_PKT_TYPE_EVT 0x04
+
+struct ble_hci_trans_h4_rx_state {
+ uint8_t state;
+ uint8_t pkt_type;
+ uint8_t min_len;
+ uint16_t len;
+ uint16_t expected_len;
+ uint8_t hdr[4];
+ union {
+ uint8_t *buf;
+ struct os_mbuf *om;
+ };
+};
+
+typedef int (ble_hci_trans_h4_frame_cb)(uint8_t pkt_type, void *data);
+
+int ble_hci_trans_h4_rx(struct ble_hci_trans_h4_rx_state *rxs,
+ const uint8_t *buf, uint16_t len,
+ ble_hci_trans_h4_frame_cb *frame_cb);
+
+#endif /* _BLE_HCI_TRANS_H4_H_ */
diff --git a/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml
new file mode 100644
index 00000000..c44773ef
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/dialog_cmac/syscfg.yml
@@ -0,0 +1,43 @@
+# 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.
+#
+
+syscfg.defs:
+ BLE_HCI_EVT_HI_BUF_COUNT:
+ description: 'Number of high-priority event buffers.'
+ value: 2
+
+ BLE_HCI_EVT_LO_BUF_COUNT:
+ description: 'Number of low-priority event buffers.'
+ value: 8
+
+ BLE_HCI_EVT_BUF_SIZE:
+ description: 'Size of each event buffer, in bytes.'
+ value: 70
+
+ BLE_ACL_BUF_COUNT:
+ description: 'The number of ACL data buffers'
+ value: 4
+
+ BLE_ACL_BUF_SIZE:
+ description: >
+ This is the maximum size of the data portion of HCI ACL data
+ packets. It does not include the HCI data header (of 4 bytes).
+ value: 255
+
+syscfg.vals.'BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV':
+ BLE_HCI_EVT_BUF_SIZE: 257
diff --git a/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c b/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c
index 61c0c9cb..61fe96b2 100644
--- a/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c
+++ b/src/libs/mynewt-nimble/nimble/transport/emspi/src/ble_hci_emspi.c
@@ -295,15 +295,7 @@ done:
static struct os_mbuf *
ble_hci_trans_acl_buf_alloc(void)
{
- uint8_t usrhdr_len;
-
-#if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
- usrhdr_len = BLE_MBUF_HS_HDR_LEN;
-#else
- usrhdr_len = 0;
-#endif
-
- return os_mbuf_get_pkthdr(&ble_hci_emspi_acl_mbuf_pool, usrhdr_len);
+ return os_mbuf_get_pkthdr(&ble_hci_emspi_acl_mbuf_pool, 0);
}
/**
diff --git a/src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml
new file mode 100644
index 00000000..4db567c8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/nrf5340/pkg.yml
@@ -0,0 +1,38 @@
+#
+# 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: nimble/transport/nrf5340
+pkg.description: HCI transport for nRF5340
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+ - nrf5340
+
+pkg.deps:
+ - "@apache-mynewt-nimble/nimble"
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/hw/drivers/ipc_nrf5340"
+
+pkg.apis:
+ - ble_transport
+
+pkg.init:
+ nrf5340_ble_hci_init: 'MYNEWT_VAL(BLE_TRANS_NRF5340_SYSINIT_STAGE)'
diff --git a/src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
new file mode 100644
index 00000000..3f113e11
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c
@@ -0,0 +1,426 @@
+/*
+ * 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 <os/mynewt.h>
+#include <nimble/ble.h>
+#include <nimble/ble_hci_trans.h>
+#include <nimble/hci_common.h>
+#include <ipc_nrf5340/ipc_nrf5340.h>
+
+#define HCI_PKT_NONE 0x00
+#define HCI_PKT_CMD 0x01
+#define HCI_PKT_ACL 0x02
+#define HCI_PKT_EVT 0x04
+
+#define POOL_ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) + \
+ BLE_MBUF_MEMBLOCK_OVERHEAD + \
+ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+#define IPC_TX_CHANNEL 0
+#define IPC_RX_CHANNEL 1
+#endif
+
+#if MYNEWT_VAL(BLE_HOST)
+#define IPC_TX_CHANNEL 1
+#define IPC_RX_CHANNEL 0
+#endif
+
+struct nrf5340_ble_hci_api {
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ ble_hci_trans_rx_cmd_fn *cmd_cb;
+ void *cmd_arg;
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+ ble_hci_trans_rx_cmd_fn *evt_cb;
+ void *evt_arg;
+#endif
+ ble_hci_trans_rx_acl_fn *acl_cb;
+ void *acl_arg;
+};
+
+struct nrf5340_ble_hci_rx_data {
+ uint8_t type;
+ uint8_t hdr[4];
+ uint16_t len;
+ uint16_t expected_len;
+ union {
+ uint8_t *buf;
+ struct os_mbuf *om;
+ };
+};
+
+struct nrf5340_ble_hci_pool_cmd {
+ uint8_t cmd[BLE_HCI_TRANS_CMD_SZ];
+ bool allocated;
+};
+
+/* (Pseudo)pool for HCI commands */
+static struct nrf5340_ble_hci_pool_cmd nrf5340_ble_hci_pool_cmd;
+
+/* Pools for HCI events (high and low priority) */
+static uint8_t nrf5340_ble_hci_pool_evt_hi_buf[OS_MEMPOOL_BYTES(
+ MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool nrf5340_ble_hci_pool_evt_hi;
+static uint8_t nrf5340_ble_hci_pool_evt_lo_buf[OS_MEMPOOL_BYTES(
+ MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
+static struct os_mempool nrf5340_ble_hci_pool_evt_lo;
+
+/* Pool for ACL data */
+static uint8_t nrf5340_ble_hci_pool_acl_buf[OS_MEMPOOL_BYTES(
+ MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+ POOL_ACL_BLOCK_SIZE)];
+static struct os_mempool nrf5340_ble_hci_pool_acl;
+static struct os_mbuf_pool nrf5340_ble_hci_pool_acl_mbuf;
+
+/* Interface to host/ll */
+static struct nrf5340_ble_hci_api nrf5340_ble_hci_api;
+
+/* State of RX currently in progress (needs to reassemble frame) */
+static struct nrf5340_ble_hci_rx_data nrf5340_ble_hci_rx_data;
+
+int
+ble_hci_trans_reset(void)
+{
+ /* XXX Should we do something with RF and/or BLE core? */
+ return 0;
+}
+
+static int
+ble_hci_trans_acl_tx(struct os_mbuf *om)
+{
+ uint8_t ind = HCI_PKT_ACL;
+ struct os_mbuf *x;
+ int rc;
+
+ rc = ipc_nrf5340_send(IPC_TX_CHANNEL, &ind, 1);
+ if (rc == 0) {
+ x = om;
+ while (x) {
+ rc = ipc_nrf5340_send(IPC_TX_CHANNEL, x->om_data, x->om_len);
+ if (rc < 0) {
+ break;
+ }
+ x = SLIST_NEXT(x, om_next);
+ }
+ }
+
+ os_mbuf_free_chain(om);
+
+ return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+ nrf5340_ble_hci_api.cmd_cb = cmd_cb;
+ nrf5340_ble_hci_api.cmd_arg = cmd_arg;
+ nrf5340_ble_hci_api.acl_cb = acl_cb;
+ nrf5340_ble_hci_api.acl_arg = acl_arg;
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
+{
+ uint8_t ind = HCI_PKT_EVT;
+ int len = 2 + hci_ev[1];
+ int rc;
+
+ rc = ipc_nrf5340_send(IPC_TX_CHANNEL, &ind, 1);
+ if (rc == 0) {
+ rc = ipc_nrf5340_send(IPC_TX_CHANNEL, hci_ev, len);
+ }
+
+ ble_hci_trans_buf_free(hci_ev);
+
+ return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+ return ble_hci_trans_acl_tx(om);
+}
+#endif
+
+#if MYNEWT_VAL(BLE_HOST)
+void
+ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, void *evt_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg)
+{
+ nrf5340_ble_hci_api.evt_cb = evt_cb;
+ nrf5340_ble_hci_api.evt_arg = evt_arg;
+ nrf5340_ble_hci_api.acl_cb = acl_cb;
+ nrf5340_ble_hci_api.acl_arg = acl_arg;
+}
+
+int
+ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
+{
+ uint8_t ind = HCI_PKT_CMD;
+ int len = 3 + cmd[2];
+ int rc;
+
+ rc = ipc_nrf5340_send(IPC_TX_CHANNEL, &ind, 1);
+ if (rc == 0) {
+ rc = ipc_nrf5340_send(IPC_TX_CHANNEL, cmd, len);
+ }
+
+ ble_hci_trans_buf_free(cmd);
+
+ return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0;
+}
+
+int
+ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
+{
+ return ble_hci_trans_acl_tx(om);
+}
+#endif
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+ uint8_t *buf;
+
+ switch (type) {
+ case BLE_HCI_TRANS_BUF_CMD:
+ assert(!nrf5340_ble_hci_pool_cmd.allocated);
+ nrf5340_ble_hci_pool_cmd.allocated = 1;
+ buf = nrf5340_ble_hci_pool_cmd.cmd;
+ break;
+ case BLE_HCI_TRANS_BUF_EVT_HI:
+ buf = os_memblock_get(&nrf5340_ble_hci_pool_evt_hi);
+ if (buf) {
+ break;
+ }
+ /* no break */
+ case BLE_HCI_TRANS_BUF_EVT_LO:
+ buf = os_memblock_get(&nrf5340_ble_hci_pool_evt_lo);
+ break;
+ default:
+ assert(0);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+ int rc;
+
+ if (buf == nrf5340_ble_hci_pool_cmd.cmd) {
+ assert(nrf5340_ble_hci_pool_cmd.allocated);
+ nrf5340_ble_hci_pool_cmd.allocated = 0;
+ } else if (os_memblock_from(&nrf5340_ble_hci_pool_evt_hi, buf)) {
+ rc = os_memblock_put(&nrf5340_ble_hci_pool_evt_hi, buf);
+ assert(rc == 0);
+ } else {
+ assert(os_memblock_from(&nrf5340_ble_hci_pool_evt_lo, buf));
+ rc = os_memblock_put(&nrf5340_ble_hci_pool_evt_lo, buf);
+ assert(rc == 0);
+ }
+}
+
+static void
+nrf5340_ble_hci_trans_rx_process(int channel)
+{
+ struct nrf5340_ble_hci_rx_data *rxd = &nrf5340_ble_hci_rx_data;
+#if MYNEWT_VAL(BLE_HOST)
+ int pool = BLE_HCI_TRANS_BUF_EVT_HI;
+#endif
+ int rc;
+
+ switch (rxd->type) {
+ case HCI_PKT_NONE:
+ ipc_nrf5340_read(channel, &rxd->type, 1);
+ rxd->len = 0;
+ rxd->expected_len = 0;
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ assert((rxd->type == HCI_PKT_ACL) || (rxd->type = HCI_PKT_CMD));
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+ assert((rxd->type == HCI_PKT_ACL) || (rxd->type = HCI_PKT_EVT));
+#endif
+ break;
+#if MYNEWT_VAL(BLE_CONTROLLER)
+ case HCI_PKT_CMD:
+ /* commands are sent complete over IPC */
+ rxd->len = ipc_nrf5340_read(channel, rxd->hdr, 3);
+ assert(rxd->len == 3);
+
+ rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+ memcpy(rxd->buf, rxd->hdr, rxd->len);
+
+ rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len], rxd->hdr[2]);
+ assert(rxd->len == 3 + rxd->hdr[2]);
+
+ rc = nrf5340_ble_hci_api.cmd_cb(rxd->buf, nrf5340_ble_hci_api.cmd_arg);
+ if (rc != 0) {
+ ble_hci_trans_buf_free(rxd->buf);
+ }
+
+ rxd->type = HCI_PKT_NONE;
+ break;
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+ case HCI_PKT_EVT:
+ /* events are sent complete over IPC */
+ rxd->len = ipc_nrf5340_read(channel, rxd->hdr, 2);
+ assert(rxd->len == 2);
+
+ if (rxd->hdr[0] == BLE_HCI_EVCODE_LE_META) {
+ /* For LE Meta event we need 3 bytes to parse header */
+ rxd->len += ipc_nrf5340_read(channel, rxd->hdr + 2, 1);
+ assert(rxd->len == 3);
+
+ /* Advertising reports shall be allocated from low-prio pool */
+ if ((rxd->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) ||
+ (rxd->hdr[2] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
+ pool = BLE_HCI_TRANS_BUF_EVT_LO;
+ }
+ }
+
+ rxd->buf = ble_hci_trans_buf_alloc(pool);
+ if (!rxd->buf) {
+ /*
+ * Only care about valid buffer when shall be allocated from
+ * high-prio pool, otherwise NULL is fine and we'll just skip
+ * this event.
+ */
+ if (pool != BLE_HCI_TRANS_BUF_EVT_LO) {
+ rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+ }
+ }
+
+ rxd->expected_len = 2 + rxd->hdr[1];
+
+ if (rxd->buf) {
+ memcpy(rxd->buf, rxd->hdr, rxd->len);
+
+ rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len],
+ rxd->expected_len - rxd->len);
+ assert(rxd->expected_len == rxd->len);
+
+ rc = nrf5340_ble_hci_api.evt_cb(rxd->buf,
+ nrf5340_ble_hci_api.evt_arg);
+ if (rc != 0) {
+ ble_hci_trans_buf_free(rxd->buf);
+ }
+ } else {
+ rxd->len += ipc_nrf5340_consume(channel,
+ rxd->expected_len - rxd->len);
+ assert(rxd->expected_len == rxd->len);
+ }
+
+ rxd->type = HCI_PKT_NONE;
+ break;
+#endif
+ case HCI_PKT_ACL:
+ if (rxd->len < 4) {
+ rxd->len += ipc_nrf5340_read(channel, rxd->hdr, 4 - rxd->len);
+
+ if (rxd->len < 4) {
+ break;
+ }
+ }
+
+ /* Parse header and allocate proper buffer if not done yet */
+ if (rxd->expected_len == 0) {
+ rxd->om = os_mbuf_get_pkthdr(&nrf5340_ble_hci_pool_acl_mbuf,
+ sizeof(struct ble_mbuf_hdr));
+ if (!rxd->om) {
+ /* not much we can do here... */
+ assert(0);
+ }
+
+ os_mbuf_append(rxd->om, rxd->hdr, rxd->len);
+ rxd->expected_len = get_le16(&rxd->hdr[2]) + 4;
+ }
+
+ if (rxd->len != rxd->expected_len) {
+ rxd->len += ipc_nrf5340_read_om(channel, rxd->om,
+ rxd->expected_len - rxd->len);
+ }
+
+ if (rxd->len == rxd->expected_len) {
+ rc = nrf5340_ble_hci_api.acl_cb(rxd->om,
+ nrf5340_ble_hci_api.acl_arg);
+ if (rc != 0) {
+ os_mbuf_free_chain(rxd->om);
+ }
+ rxd->type = HCI_PKT_NONE;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static void
+nrf5340_ble_hci_trans_rx(int channel, void *user_data)
+{
+ while (ipc_nrf5340_available(channel) > 0) {
+ nrf5340_ble_hci_trans_rx_process(channel);
+ }
+}
+
+void
+nrf5340_ble_hci_init(void)
+{
+ int rc;
+
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = os_mempool_init(&nrf5340_ble_hci_pool_acl, MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+ POOL_ACL_BLOCK_SIZE, nrf5340_ble_hci_pool_acl_buf,
+ "nrf5340_ble_hci_pool_acl");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mbuf_pool_init(&nrf5340_ble_hci_pool_acl_mbuf,
+ &nrf5340_ble_hci_pool_acl, POOL_ACL_BLOCK_SIZE,
+ MYNEWT_VAL(BLE_ACL_BUF_COUNT));
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_init(&nrf5340_ble_hci_pool_evt_hi,
+ MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+ nrf5340_ble_hci_pool_evt_hi_buf,
+ "nrf5340_ble_hci_pool_evt_hi");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_init(&nrf5340_ble_hci_pool_evt_lo,
+ MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+ nrf5340_ble_hci_pool_evt_lo_buf,
+ "nrf5340_ble_hci_pool_evt_lo");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ ipc_nrf5340_recv(IPC_RX_CHANNEL, nrf5340_ble_hci_trans_rx, NULL);
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml
new file mode 100644
index 00000000..1417bbc0
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/nrf5340/syscfg.yml
@@ -0,0 +1,51 @@
+# 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.
+#
+
+syscfg.defs:
+ BLE_HCI_EVT_HI_BUF_COUNT:
+ description: 'Number of high-priority event buffers.'
+ value: 2
+
+ BLE_HCI_EVT_LO_BUF_COUNT:
+ description: 'Number of low-priority event buffers.'
+ value: 8
+
+ BLE_HCI_EVT_BUF_SIZE:
+ description: 'Size of each event buffer, in bytes.'
+ value: 70
+
+ BLE_ACL_BUF_COUNT:
+ description: 'The number of ACL data buffers'
+ value: 4
+
+ BLE_ACL_BUF_SIZE:
+ description: >
+ This is the maximum size of the data portion of HCI ACL data
+ packets. It does not include the HCI data header (of 4 bytes).
+ value: 255
+
+ BLE_TRANS_NRF5340_SYSINIT_STAGE:
+ description: >
+ Sysinit stage for the RAM BLE transport.
+ value: 100
+
+syscfg.vals.BLE_EXT_ADV:
+ BLE_HCI_EVT_BUF_SIZE: 257
+
+syscfg.restrictions:
+ - '!(BLE_HOST && BLE_CONTROLLER)'
diff --git a/src/libs/mynewt-nimble/nimble/transport/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/pkg.yml
index 2bc4ac29..8174286d 100644
--- a/src/libs/mynewt-nimble/nimble/transport/pkg.yml
+++ b/src/libs/mynewt-nimble/nimble/transport/pkg.yml
@@ -43,3 +43,12 @@ pkg.deps.'BLE_HCI_TRANSPORT == "uart"':
pkg.deps.'BLE_HCI_TRANSPORT == "da1469x"':
- nimble/transport/da1469x
+
+pkg.deps.'BLE_HCI_TRANSPORT == "dialog_cmac"':
+ - nimble/transport/dialog_cmac
+
+pkg.deps.'BLE_HCI_TRANSPORT == "usb"':
+ - nimble/transport/usb
+
+pkg.deps.'BLE_HCI_TRANSPORT == "nrf5340"':
+ - nimble/transport/nrf5340
diff --git a/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c b/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c
index 863d0fbb..44de8fed 100644
--- a/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c
+++ b/src/libs/mynewt-nimble/nimble/transport/socket/src/ble_hci_socket.c
@@ -53,19 +53,22 @@
#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
#include <sys/errno.h>
-#define BTPROTO_HCI 1
-#define HCI_CHANNEL_RAW 0
-#define HCI_CHANNEL_USER 1
-#define HCIDEVUP _IOW('H', 201, int)
-#define HCIDEVDOWN _IOW('H', 202, int)
-#define HCIDEVRESET _IOW('H', 203, int)
-#define HCIGETDEVLIST _IOR('H', 210, int)
+#define BTPROTO_HCI 1
+#define HCI_CHANNEL_RAW 0
+#define HCI_CHANNEL_USER 1
+#define HCIDEVUP _IOW('H', 201, int)
+#define HCIDEVDOWN _IOW('H', 202, int)
+#define HCIDEVRESET _IOW('H', 203, int)
+#define HCIGETDEVLIST _IOR('H', 210, int)
struct sockaddr_hci {
- sa_family_t hci_family;
- unsigned short hci_dev;
- unsigned short hci_channel;
+ sa_family_t hci_family;
+ unsigned short hci_dev;
+ unsigned short hci_channel;
};
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+#include <errno.h>
+#include <netpacket/bluetooth.h>
#endif
#include <fcntl.h>
@@ -205,6 +208,8 @@ static struct ble_hci_sock_state {
static int s_ble_hci_device = MYNEWT_VAL(BLE_SOCK_TCP_PORT);
#elif MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
static int s_ble_hci_device = MYNEWT_VAL(BLE_SOCK_LINUX_DEV);
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int s_ble_hci_device = 0;
#endif
/**
@@ -227,6 +232,7 @@ ble_hci_trans_acl_buf_alloc(void)
return m;
}
+#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
static int
ble_hci_sock_acl_tx(struct os_mbuf *om)
{
@@ -268,10 +274,66 @@ ble_hci_sock_acl_tx(struct os_mbuf *om)
}
return 0;
}
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int
+ble_hci_sock_acl_tx(struct os_mbuf *om)
+{
+ size_t len;
+ uint8_t *buf;
+ int i;
+ struct os_mbuf *m;
+ struct sockaddr_hci addr;
+
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_channel = HCI_CHANNEL_RAW;
+ addr.hci_dev = 0;
+
+ memcpy(&addr, &addr, sizeof(struct sockaddr_hci));
+
+ len = 1;
+
+ for (m = om; m; m = SLIST_NEXT(m, om_next)) {
+ len += m->om_len;
+ }
+
+ buf = (uint8_t *)malloc(len);
+
+ buf[0] = BLE_HCI_UART_H4_ACL;
+ i = 1;
+ for (m = om; m; m = SLIST_NEXT(m, om_next)) {
+ memcpy(&buf[i], m->om_data, m->om_len);
+ i += m->om_len;
+ }
+
+ STATS_INC(hci_sock_stats, omsg);
+ STATS_INC(hci_sock_stats, oacl);
+ STATS_INCN(hci_sock_stats, obytes, OS_MBUF_PKTLEN(om) + 1);
+
+ i = sendto(ble_hci_sock_state.sock, buf, len, 0,
+ (struct sockaddr *)&addr, sizeof(struct sockaddr_hci));
+
+ free(buf);
+
+ os_mbuf_free_chain(om);
+ if (i != OS_MBUF_PKTLEN(om) + 1) {
+ if (i < 0) {
+ dprintf(1, "sendto() failed : %d\n", errno);
+ } else {
+ dprintf(1, "sendto() partial write: %d\n", i);
+ }
+ STATS_INC(hci_sock_stats, oerr);
+ return BLE_ERR_MEM_CAPACITY;
+ }
+ return 0;
+}
+#endif
+
+#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
static int
ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
{
+ uint8_t btaddr[6];
struct msghdr msg;
struct iovec iov[8];
int len;
@@ -316,6 +378,57 @@ ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
return 0;
}
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int
+ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
+{
+ uint8_t *buf;
+ size_t len;
+ struct sockaddr_hci addr;
+ int i;
+
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_channel = HCI_CHANNEL_RAW;
+ addr.hci_dev = 0;
+
+ memcpy(&addr, &addr, sizeof(struct sockaddr_hci));
+
+ if (h4_type == BLE_HCI_UART_H4_CMD) {
+ len = sizeof(struct ble_hci_cmd) + hci_ev[2];
+ STATS_INC(hci_sock_stats, ocmd);
+ } else if (h4_type == BLE_HCI_UART_H4_EVT) {
+ len = sizeof(struct ble_hci_ev) + hci_ev[1];
+ STATS_INC(hci_sock_stats, oevt);
+ } else {
+ assert(0);
+ }
+
+ STATS_INC(hci_sock_stats, omsg);
+ STATS_INCN(hci_sock_stats, obytes, len + 1);
+
+ buf = (uint8_t *)malloc(len + 1);
+
+ buf[0] = h4_type;
+ memcpy(&buf[1], hci_ev, len);
+
+ i = sendto(ble_hci_sock_state.sock, buf, len + 1, 0,
+ (struct sockaddr *)&addr, sizeof(struct sockaddr_hci));
+
+ free(buf);
+ ble_hci_trans_buf_free(hci_ev);
+ if (i != len + 1) {
+ if (i < 0) {
+ dprintf(1, "sendto() failed : %d\n", errno);
+ } else {
+ dprintf(1, "sendto() partial write: %d\n", i);
+ }
+ STATS_INC(hci_sock_stats, oerr);
+ return BLE_ERR_MEM_CAPACITY;
+ }
+
+ return 0;
+}
+#endif
static int
ble_hci_sock_rx_msg(void)
@@ -427,6 +540,7 @@ ble_hci_sock_rx_msg(void)
STATS_INC(hci_sock_stats, ierr);
break;
}
+
memmove(bhss->rx_data, &bhss->rx_data[len], bhss->rx_off - len);
bhss->rx_off -= len;
}
@@ -540,7 +654,7 @@ ble_hci_sock_config(void)
rc = bind(s, (struct sockaddr *)&shci, sizeof(shci));
if (rc) {
- dprintf(1, "bind() failed %d\n", errno);
+ dprintf(1, "bind() failed %d hci%d\n", errno, shci.hci_dev);
goto err;
}
@@ -565,7 +679,54 @@ err:
}
return BLE_ERR_HW_FAIL;
}
+#elif MYNEWT_VAL(BLE_SOCK_USE_NUTTX)
+static int
+ble_hci_sock_config(void)
+{
+ struct sockaddr_hci shci;
+ int s;
+ int rc;
+ ble_npl_time_t timeout;
+
+ memset(&shci, 0, sizeof(shci));
+ shci.hci_family = AF_BLUETOOTH;
+ shci.hci_dev = 0;
+ shci.hci_channel = HCI_CHANNEL_RAW;
+
+ if (ble_hci_sock_state.sock >= 0) {
+ close(ble_hci_sock_state.sock);
+ ble_hci_sock_state.sock = -1;
+ }
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (s < 0) {
+ dprintf(1, "socket() failed %d\n", errno);
+ goto err;
+ }
+
+ rc = bind(s, (struct sockaddr *)&shci, sizeof(shci));
+ if (rc) {
+ dprintf(1, "bind() failed %d hci%d\n", errno, shci.hci_dev);
+ goto err;
+ }
+
+ ble_hci_sock_state.sock = s;
+
+ rc = ble_npl_time_ms_to_ticks(10, &timeout);
+ if (rc) {
+ goto err;
+ }
+ ble_npl_callout_reset(&ble_hci_sock_state.timer, timeout);
+
+ return 0;
+err:
+ if (s >= 0) {
+ close(s);
+ }
+ return BLE_ERR_HW_FAIL;
+}
#endif
+
/**
* Sends an HCI event from the controller to the host.
*
diff --git a/src/libs/mynewt-nimble/nimble/transport/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/syscfg.yml
index 137d6e94..5bec6adf 100644
--- a/src/libs/mynewt-nimble/nimble/transport/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/transport/syscfg.yml
@@ -26,13 +26,16 @@ syscfg.defs:
value: builtin
restrictions: $notnull
choices:
- - builtin # Built-in NimBLE controller and RAM transport
- - custom # Custom transport, has to be included manually by user
- - ram # RAM transport
- - uart # UART HCI H4 transport
- - socket # Socket transport (for native builds)
- - emspi # SPI transport for EM Microelectionic controllers
- - da1469x # Dialog DA1469x integrated controller
+ - builtin # Built-in NimBLE controller and RAM transport
+ - custom # Custom transport, has to be included manually by user
+ - ram # RAM transport
+ - uart # UART HCI H4 transport
+ - socket # Socket transport (for native builds)
+ - emspi # SPI transport for EM Microelectionic controllers
+ - da1469x # Dialog DA1469x integrated controller
+ - dialog_cmac # Dialog CMAC via shared memory
+ - usb # USB
+ - nrf5340 # nRF5340
# Deprecated settings
BLE_HCI_TRANSPORT_NIMBLE_BUILTIN:
diff --git a/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c b/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c
index ac6af28e..cbb6dd42 100644
--- a/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c
+++ b/src/libs/mynewt-nimble/nimble/transport/uart/src/ble_hci_uart.c
@@ -195,8 +195,6 @@ ble_hci_trans_acl_buf_alloc(void)
#if MYNEWT_VAL(BLE_CONTROLLER)
usrhdr_len = sizeof(struct ble_mbuf_hdr);
-#elif MYNEWT_VAL(BLE_HS_FLOW_CTRL)
- usrhdr_len = BLE_MBUF_HS_HDR_LEN;
#else
usrhdr_len = 0;
#endif
diff --git a/src/libs/mynewt-nimble/nimble/transport/usb/pkg.yml b/src/libs/mynewt-nimble/nimble/transport/usb/pkg.yml
new file mode 100644
index 00000000..49317c97
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/usb/pkg.yml
@@ -0,0 +1,39 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: nimble/transport/usb
+pkg.description: Provides HCI transport over USB interface
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+ - usb
+
+pkg.deps:
+ - "@apache-mynewt-core/hw/hal"
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/util/mem"
+ - nimble
+
+pkg.apis:
+ - ble_transport
+
+pkg.init:
+ ble_hci_usb_init: 'MYNEWT_VAL(BLE_TRANS_USB_SYSINIT_STAGE)'
diff --git a/src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c b/src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c
new file mode 100644
index 00000000..55c91f22
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/usb/src/ble_hci_usb.c
@@ -0,0 +1,410 @@
+/*
+ * 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 "sysinit/sysinit.h"
+#include "os/os.h"
+#include "mem/mem.h"
+
+#include "nimble/ble.h"
+#include "nimble/ble_hci_trans.h"
+#include "nimble/hci_common.h"
+
+#include <class/bth/bth_device.h>
+
+/*
+ * The MBUF payload size must accommodate the HCI data header size plus the
+ * maximum ACL data packet length. The ACL block size is the size of the
+ * mbufs we will allocate.
+ */
+#define ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
+ + BLE_MBUF_MEMBLOCK_OVERHEAD \
+ + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
+
+struct usb_ble_hci_pool_cmd {
+ uint8_t cmd[BLE_HCI_TRANS_CMD_SZ];
+ bool allocated;
+};
+
+/* (Pseudo)pool for HCI commands */
+static struct usb_ble_hci_pool_cmd usb_ble_hci_pool_cmd;
+
+static ble_hci_trans_rx_cmd_fn *ble_hci_usb_rx_cmd_ll_cb;
+static void *ble_hci_usb_rx_cmd_ll_arg;
+
+static ble_hci_trans_rx_acl_fn *ble_hci_usb_rx_acl_ll_cb;
+static void *ble_hci_usb_rx_acl_ll_arg;
+
+static struct os_mempool ble_hci_usb_evt_hi_pool;
+static os_membuf_t ble_hci_usb_evt_hi_buf[
+ OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+static struct os_mempool ble_hci_usb_evt_lo_pool;
+static os_membuf_t ble_hci_usb_evt_lo_buf[
+ OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+static uint8_t ble_hci_pool_acl_mempool_buf[
+ OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+ ACL_BLOCK_SIZE)];
+static struct os_mempool ble_hci_pool_acl_mempool;
+static struct os_mbuf_pool ble_hci_pool_acl_mbuf_pool;
+
+static struct os_mbuf *incoming_acl_data;
+
+static struct os_mbuf *
+ble_hci_trans_acl_buf_alloc(void)
+{
+ struct os_mbuf *m;
+
+ m = os_mbuf_get_pkthdr(&ble_hci_pool_acl_mbuf_pool,
+ sizeof(struct ble_mbuf_hdr));
+ return m;
+}
+
+void
+ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+ void *cmd_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb,
+ void *acl_arg)
+{
+ ble_hci_usb_rx_cmd_ll_cb = cmd_cb;
+ ble_hci_usb_rx_cmd_ll_arg = cmd_arg;
+ ble_hci_usb_rx_acl_ll_cb = acl_cb;
+ ble_hci_usb_rx_acl_ll_arg = acl_arg;
+}
+
+#define BLE_HCI_USB_EVT_COUNT \
+ (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
+
+/**
+ * A packet to be sent over the USB. This can be a command, an event, or ACL
+ * data.
+ */
+struct ble_hci_pkt {
+ STAILQ_ENTRY(ble_hci_pkt) next;
+ void *data;
+};
+
+static struct os_mempool ble_hci_pkt_pool;
+static os_membuf_t ble_hci_pkt_buf[
+ OS_MEMPOOL_SIZE(BLE_HCI_USB_EVT_COUNT + 1 +
+ MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+ sizeof(struct ble_hci_pkt))];
+
+struct tx_queue {
+ STAILQ_HEAD(, ble_hci_pkt) queue;
+};
+
+static struct tx_queue ble_hci_tx_acl_queue = {STAILQ_HEAD_INITIALIZER(ble_hci_tx_acl_queue.queue)};
+static struct tx_queue ble_hci_tx_evt_queue = { STAILQ_HEAD_INITIALIZER(ble_hci_tx_evt_queue.queue) };
+
+/*
+ * TinyUSB callbacks.
+ */
+void
+tud_bt_acl_data_sent_cb(uint16_t sent_bytes)
+{
+ struct os_mbuf *om;
+ struct ble_hci_pkt *curr_acl;
+ struct ble_hci_pkt *next_acl;
+ os_sr_t sr;
+
+ OS_ENTER_CRITICAL(sr);
+ curr_acl = STAILQ_FIRST(&ble_hci_tx_acl_queue.queue);
+ OS_EXIT_CRITICAL(sr);
+
+ assert(curr_acl != NULL);
+ om = curr_acl->data;
+ assert(om != NULL && om->om_len >= sent_bytes);
+ os_mbuf_adj(om, sent_bytes);
+
+ while (om != NULL && om->om_len == 0) {
+ curr_acl->data = SLIST_NEXT(om, om_next);
+ os_mbuf_free(om);
+ om = curr_acl->data;
+ }
+
+ if (om == NULL) {
+ OS_ENTER_CRITICAL(sr);
+ STAILQ_REMOVE_HEAD(&ble_hci_tx_acl_queue.queue, next);
+ next_acl = STAILQ_FIRST(&ble_hci_tx_acl_queue.queue);
+ OS_EXIT_CRITICAL(sr);
+ os_memblock_put(&ble_hci_pkt_pool, curr_acl);
+ if (next_acl != NULL) {
+ om = next_acl->data;
+ }
+ }
+
+ if (om != NULL) {
+ tud_bt_acl_data_send(om->om_data, om->om_len);
+ }
+}
+
+void
+tud_bt_event_sent_cb(uint16_t sent_bytes)
+{
+ struct ble_hci_pkt *curr_evt;
+ struct ble_hci_pkt *next_evt;
+ uint8_t *hci_ev;
+ os_sr_t sr;
+
+ OS_ENTER_CRITICAL(sr);
+ curr_evt = STAILQ_FIRST(&ble_hci_tx_evt_queue.queue);
+ OS_EXIT_CRITICAL(sr);
+ assert(curr_evt != NULL);
+ hci_ev = curr_evt->data;
+
+ assert(hci_ev != NULL && hci_ev[1] + sizeof(struct ble_hci_ev) == sent_bytes);
+
+ ble_hci_trans_buf_free(hci_ev);
+
+ OS_ENTER_CRITICAL(sr);
+ STAILQ_REMOVE_HEAD(&ble_hci_tx_evt_queue.queue, next);
+ next_evt = STAILQ_FIRST(&ble_hci_tx_evt_queue.queue);
+ OS_EXIT_CRITICAL(sr);
+ os_memblock_put(&ble_hci_pkt_pool, curr_evt);
+
+ if (next_evt != NULL) {
+ hci_ev = next_evt->data;
+ tud_bt_event_send(hci_ev, hci_ev[1] + sizeof(struct ble_hci_ev));
+ }
+}
+
+void
+tud_bt_acl_data_received_cb(void *acl_data, uint16_t data_len)
+{
+ uint8_t *data;
+ uint32_t len;
+ struct os_mbuf *om = incoming_acl_data;
+ int rc;
+
+ if (om == NULL) {
+ om = ble_hci_trans_acl_buf_alloc();
+ assert(om != NULL);
+ }
+ assert(om->om_len + data_len <= MYNEWT_VAL(BLE_ACL_BUF_SIZE) + BLE_HCI_DATA_HDR_SZ);
+
+ os_mbuf_append(om, acl_data, data_len);
+ incoming_acl_data = om;
+ if (om->om_len > BLE_HCI_DATA_HDR_SZ) {
+ data = incoming_acl_data->om_data;
+ len = data[2] + (data[3] << 8) + BLE_HCI_DATA_HDR_SZ;
+ if (len >= incoming_acl_data->om_len) {
+ incoming_acl_data = NULL;
+ rc = ble_hci_usb_rx_acl_ll_cb(om, ble_hci_usb_rx_acl_ll_arg);
+ (void)rc;
+ }
+ }
+}
+
+void
+tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len)
+{
+ uint8_t *buf;
+ int rc = -1;
+
+ assert(ble_hci_usb_rx_cmd_ll_cb);
+ if (ble_hci_usb_rx_cmd_ll_cb) {
+ buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+ assert(buf != NULL);
+ memcpy(buf, hci_cmd, cmd_len);
+
+ rc = ble_hci_usb_rx_cmd_ll_cb(buf, ble_hci_usb_rx_cmd_ll_arg);
+ }
+
+ if (rc != 0) {
+ ble_hci_trans_buf_free(buf);
+ }
+}
+
+static int
+ble_hci_trans_ll_tx(struct tx_queue *queue, struct os_mbuf *om)
+{
+ struct ble_hci_pkt *pkt;
+ os_sr_t sr;
+ bool first;
+
+ /* If this packet is zero length, just free it */
+ if (OS_MBUF_PKTLEN(om) == 0) {
+ os_mbuf_free_chain(om);
+ return 0;
+ }
+
+ pkt = os_memblock_get(&ble_hci_pkt_pool);
+ if (pkt == NULL) {
+ os_mbuf_free_chain(om);
+ return BLE_ERR_MEM_CAPACITY;
+ }
+
+ pkt->data = om;
+ OS_ENTER_CRITICAL(sr);
+ first = STAILQ_EMPTY(&queue->queue);
+ STAILQ_INSERT_TAIL(&queue->queue, pkt, next);
+ OS_EXIT_CRITICAL(sr);
+ if (first) {
+ tud_bt_acl_data_send(om->om_data, om->om_len);
+ }
+
+ return 0;
+}
+
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+ return ble_hci_trans_ll_tx(&ble_hci_tx_acl_queue, om);
+}
+
+int
+ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
+{
+ struct ble_hci_pkt *pkt;
+ os_sr_t sr;
+ bool first;
+
+ assert(hci_ev != NULL);
+
+ pkt = os_memblock_get(&ble_hci_pkt_pool);
+ if (pkt == NULL) {
+ ble_hci_trans_buf_free(hci_ev);
+ return BLE_ERR_MEM_CAPACITY;
+ }
+
+ pkt->data = hci_ev;
+ OS_ENTER_CRITICAL(sr);
+ first = STAILQ_EMPTY(&ble_hci_tx_evt_queue.queue);
+ STAILQ_INSERT_TAIL(&ble_hci_tx_evt_queue.queue, pkt, next);
+ OS_EXIT_CRITICAL(sr);
+ if (first) {
+ tud_bt_event_send(hci_ev, hci_ev[1] + sizeof(struct ble_hci_ev));
+ }
+
+ return 0;
+}
+
+uint8_t *
+ble_hci_trans_buf_alloc(int type)
+{
+ uint8_t *buf;
+
+ switch (type) {
+ case BLE_HCI_TRANS_BUF_CMD:
+ assert(!usb_ble_hci_pool_cmd.allocated);
+ usb_ble_hci_pool_cmd.allocated = 1;
+ buf = usb_ble_hci_pool_cmd.cmd;
+ break;
+
+ case BLE_HCI_TRANS_BUF_EVT_HI:
+ buf = os_memblock_get(&ble_hci_usb_evt_hi_pool);
+ if (buf == NULL) {
+ /* If no high-priority event buffers remain, try to grab a
+ * low-priority one.
+ */
+ buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
+ }
+ break;
+
+ case BLE_HCI_TRANS_BUF_EVT_LO:
+ buf = os_memblock_get(&ble_hci_usb_evt_lo_pool);
+ break;
+
+ default:
+ assert(0);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+void
+ble_hci_trans_buf_free(uint8_t *buf)
+{
+ int rc;
+
+ /* XXX: this may look a bit odd, but the controller uses the command
+ * buffer to send back the command complete/status as an immediate
+ * response to the command. This was done to insure that the controller
+ * could always send back one of these events when a command was received.
+ * Thus, we check to see which pool the buffer came from so we can free
+ * it to the appropriate pool
+ */
+ if (os_memblock_from(&ble_hci_usb_evt_hi_pool, buf)) {
+ rc = os_memblock_put(&ble_hci_usb_evt_hi_pool, buf);
+ assert(rc == 0);
+ } else if (os_memblock_from(&ble_hci_usb_evt_lo_pool, buf)) {
+ rc = os_memblock_put(&ble_hci_usb_evt_lo_pool, buf);
+ assert(rc == 0);
+ } else {
+ assert(usb_ble_hci_pool_cmd.allocated);
+ usb_ble_hci_pool_cmd.allocated = 0;
+ }
+ (void)rc;
+}
+
+int
+ble_hci_trans_reset(void)
+{
+ return 0;
+}
+
+void
+ble_hci_usb_init(void)
+{
+ int rc;
+
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = mem_init_mbuf_pool(ble_hci_pool_acl_mempool_buf, &ble_hci_pool_acl_mempool, &ble_hci_pool_acl_mbuf_pool,
+ MYNEWT_VAL(BLE_ACL_BUF_COUNT), ACL_BLOCK_SIZE, "ble_hci_acl");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_init(&ble_hci_usb_evt_hi_pool,
+ MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+ ble_hci_usb_evt_hi_buf,
+ "ble_hci_usb_evt_hi_pool");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = os_mempool_init(&ble_hci_usb_evt_lo_pool,
+ MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+ MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+ ble_hci_usb_evt_lo_buf,
+ "ble_hci_usb_evt_lo_pool");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ /*
+ * Create memory pool of packet list nodes. NOTE: the number of these
+ * buffers should be, at least, the total number of event buffers (hi
+ * and lo), the number of command buffers (currently 1) and the total
+ * number of buffers that the controller could possibly hand to the host.
+ */
+ rc = os_mempool_init(&ble_hci_pkt_pool,
+ BLE_HCI_USB_EVT_COUNT + 1 +
+ MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+ sizeof (struct ble_hci_pkt),
+ ble_hci_pkt_buf,
+ "ble_hci_usb_pkt_pool");
+ SYSINIT_PANIC_ASSERT(rc == 0);
+}
diff --git a/src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml b/src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml
new file mode 100644
index 00000000..ebc261a2
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/transport/usb/syscfg.yml
@@ -0,0 +1,57 @@
+# 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.
+#
+
+syscfg.defs:
+ BLE_HCI_EVT_BUF_SIZE:
+ description: 'The size of the allocated event buffers'
+ value: 70
+ BLE_HCI_EVT_HI_BUF_COUNT:
+ description: 'The number of high priority event buffers'
+ value: 8
+ BLE_HCI_EVT_LO_BUF_COUNT:
+ description: 'The number of low priority event buffers'
+ value: 8
+ BLE_ACL_BUF_COUNT:
+ description: 'The number of ACL data buffers'
+ value: 12
+ BLE_ACL_BUF_SIZE:
+ description: >
+ This is the maximum size of the data portion of HCI ACL data
+ packets. It does not include the HCI data header (of 4 bytes).
+ value: 255
+
+ BLE_HCI_ACL_OUT_COUNT:
+ description: >
+ This count is used in creating a pool of elements used by the
+ code to enqueue various elements. In the case of the controller
+ only HCI, this number should be equal to the number of mbufs in
+ the msys pool. For host only, it is really dependent on the
+ number of ACL buffers that the controller tells the host it
+ has.
+ value: 12
+
+ BLE_TRANS_USB_SYSINIT_STAGE:
+ description: >
+ Sysinit stage for the USB BLE transport.
+ value: 500
+
+syscfg.vals.BLE_EXT_ADV:
+ BLE_HCI_EVT_BUF_SIZE: 257
+
+syscfg.restrictions:
+ - '!BLE_HOST'