You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2022/02/19 14:02:17 UTC

[mynewt-nimble] branch master updated: bsim: Add EDTT hci test app

This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new fd3b146  bsim: Add EDTT hci test app
fd3b146 is described below

commit fd3b1466d71d18908ad870a1982516e812747fd8
Author: Magdalena Kasenberg <ma...@codecoup.pl>
AuthorDate: Mon Dec 6 10:47:19 2021 +0100

    bsim: Add EDTT hci test app
    
    adopted from Zephyr.
---
 babblesim/edtt/hci_test/pkg.yml                    |   32 +
 babblesim/edtt/hci_test/src/main.c                 |   45 +
 babblesim/edtt/hci_test/syscfg.yml                 |   30 +
 .../edtt/hci_transport/include/ble_hci_edtt.h      |   35 +
 babblesim/edtt/hci_transport/include/commands.h    |  242 +++++
 babblesim/edtt/hci_transport/include/edtt_driver.h |   38 +
 babblesim/edtt/hci_transport/pkg.yml               |   35 +
 babblesim/edtt/hci_transport/src/ble_hci_edtt.c    | 1149 ++++++++++++++++++++
 .../edtt/hci_transport/src/edtt_driver_bsim.c      |  286 +++++
 babblesim/edtt/hci_transport/syscfg.yml            |   49 +
 babblesim/hw/bsp/nrf52_bsim/syscfg.yml             |    2 +-
 babblesim/targets/edtthci/pkg.yml                  |   24 +
 babblesim/targets/edtthci/syscfg.yml               |   55 +
 babblesim/targets/edtthci/target.yml               |   22 +
 14 files changed, 2043 insertions(+), 1 deletion(-)

diff --git a/babblesim/edtt/hci_test/pkg.yml b/babblesim/edtt/hci_test/pkg.yml
new file mode 100644
index 0000000..6f1dd4b
--- /dev/null
+++ b/babblesim/edtt/hci_test/pkg.yml
@@ -0,0 +1,32 @@
+#
+# 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: babblesim/edtt/hci_test
+pkg.type: app
+pkg.description: nRF52 on BabbleSim - EDTT tester
+pkg.author: "Codecoup"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/sys/console/stub"
+    - "@apache-mynewt-core/sys/log/stub"
+    - "@apache-mynewt-core/sys/stats/full"
+    - "@apache-mynewt-core/kernel/os"
+    - nimble/transport
+    - babblesim/edtt/hci_transport
diff --git a/babblesim/edtt/hci_test/src/main.c b/babblesim/edtt/hci_test/src/main.c
new file mode 100644
index 0000000..0ca152c
--- /dev/null
+++ b/babblesim/edtt/hci_test/src/main.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021 Codecoup
+ *
+ * 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 "os/mynewt.h"
+#include "ble_hci_edtt.h"
+
+static int
+main_fn(int argc, char **argv)
+{
+    sysinit();
+
+    edtt_init();
+
+    while (1) {
+        os_eventq_run(os_eventq_dflt_get());
+    }
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    extern void bsim_init(int argc, char** argv, void *main_fn);
+    bsim_init(argc, argv, main_fn);
+
+    return 0;
+}
diff --git a/babblesim/edtt/hci_test/syscfg.yml b/babblesim/edtt/hci_test/syscfg.yml
new file mode 100644
index 0000000..bdf21e7
--- /dev/null
+++ b/babblesim/edtt/hci_test/syscfg.yml
@@ -0,0 +1,30 @@
+#
+# 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.vals:
+    BLE_HOST: 0
+    BLE_HCI_TRANSPORT: custom
+
+    # EDTT requires 0x123456789ABC address for first device
+    # and 0x456789ABCDEF for second
+    BLE_LL_PUBLIC_DEV_ADDR: 0x123456789ABC
+#    BLE_LL_PUBLIC_DEV_ADDR: 0x456789ABCDEF
+
+    # For LL/CON/ADV/BV-09-C, LL/CON/ADV/BV-10-C
+    BLE_LL_CFG_FEAT_LE_CSA2: 1
diff --git a/babblesim/edtt/hci_transport/include/ble_hci_edtt.h b/babblesim/edtt/hci_transport/include/ble_hci_edtt.h
new file mode 100644
index 0000000..d590b11
--- /dev/null
+++ b/babblesim/edtt/hci_transport/include/ble_hci_edtt.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Codecoup
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_HCI_EDTT_
+#define H_BLE_HCI_EDTT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int edtt_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/babblesim/edtt/hci_transport/include/commands.h b/babblesim/edtt/hci_transport/include/commands.h
new file mode 100644
index 0000000..d0f8cce
--- /dev/null
+++ b/babblesim/edtt/hci_transport/include/commands.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2019 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef EDDT_APP_COMMANDS_H
+#define EDDT_APP_COMMANDS_H
+
+enum commands_t {
+	CMD_NOTHING = 0,
+	CMD_ECHO_REQ,
+	CMD_ECHO_RSP,
+	CMD_INQUIRE_REQ,
+	CMD_INQUIRE_RSP,
+	CMD_DISCONNECT_REQ,
+	CMD_DISCONNECT_RSP,
+	CMD_READ_REMOTE_VERSION_INFORMATION_REQ,
+	CMD_READ_REMOTE_VERSION_INFORMATION_RSP,
+	CMD_SET_EVENT_MASK_REQ,
+	CMD_SET_EVENT_MASK_RSP,
+	CMD_RESET_REQ,
+	CMD_RESET_RSP,
+	CMD_READ_TRANSMIT_POWER_LEVEL_REQ,
+	CMD_READ_TRANSMIT_POWER_LEVEL_RSP,
+	CMD_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_REQ,
+	CMD_SET_CONTROLLER_TO_HOST_FLOW_CONTROL_RSP,
+	CMD_HOST_BUFFER_SIZE_REQ,
+	CMD_HOST_BUFFER_SIZE_RSP,
+	CMD_HOST_NUMBER_OF_COMPLETED_PACKETS_REQ,
+	CMD_HOST_NUMBER_OF_COMPLETED_PACKETS_RSP,
+	CMD_SET_EVENT_MASK_PAGE_2_REQ,
+	CMD_SET_EVENT_MASK_PAGE_2_RSP,
+	CMD_WRITE_LE_HOST_SUPPORT_REQ,
+	CMD_WRITE_LE_HOST_SUPPORT_RSP,
+	CMD_READ_AUTHENTICATED_PAYLOAD_TIMEOUT_REQ,
+	CMD_READ_AUTHENTICATED_PAYLOAD_TIMEOUT_RSP,
+	CMD_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_REQ,
+	CMD_WRITE_AUTHENTICATED_PAYLOAD_TIMEOUT_RSP,
+	CMD_READ_LOCAL_VERSION_INFORMATION_REQ,
+	CMD_READ_LOCAL_VERSION_INFORMATION_RSP,
+	CMD_READ_LOCAL_SUPPORTED_COMMANDS_REQ,
+	CMD_READ_LOCAL_SUPPORTED_COMMANDS_RSP,
+	CMD_READ_LOCAL_SUPPORTED_FEATURES_REQ,
+	CMD_READ_LOCAL_SUPPORTED_FEATURES_RSP,
+	CMD_READ_BUFFER_SIZE_REQ,
+	CMD_READ_BUFFER_SIZE_RSP,
+	CMD_READ_BD_ADDR_REQ,
+	CMD_READ_BD_ADDR_RSP,
+	CMD_READ_RSSI_REQ,
+	CMD_READ_RSSI_RSP,
+	CMD_LE_SET_EVENT_MASK_REQ,
+	CMD_LE_SET_EVENT_MASK_RSP,
+	CMD_LE_READ_BUFFER_SIZE_REQ,
+	CMD_LE_READ_BUFFER_SIZE_RSP,
+	CMD_LE_READ_LOCAL_SUPPORTED_FEATURES_REQ,
+	CMD_LE_READ_LOCAL_SUPPORTED_FEATURES_RSP,
+	CMD_LE_SET_RANDOM_ADDRESS_REQ,
+	CMD_LE_SET_RANDOM_ADDRESS_RSP,
+	CMD_LE_SET_ADVERTISING_PARAMETERS_REQ,
+	CMD_LE_SET_ADVERTISING_PARAMETERS_RSP,
+	CMD_LE_READ_ADVERTISING_CHANNEL_TX_POWER_REQ,
+	CMD_LE_READ_ADVERTISING_CHANNEL_TX_POWER_RSP,
+	CMD_LE_SET_ADVERTISING_DATA_REQ,
+	CMD_LE_SET_ADVERTISING_DATA_RSP,
+	CMD_LE_SET_SCAN_RESPONSE_DATA_REQ,
+	CMD_LE_SET_SCAN_RESPONSE_DATA_RSP,
+	CMD_LE_SET_ADVERTISING_ENABLE_REQ,
+	CMD_LE_SET_ADVERTISING_ENABLE_RSP,
+	CMD_LE_SET_SCAN_PARAMETERS_REQ,
+	CMD_LE_SET_SCAN_PARAMETERS_RSP,
+	CMD_LE_SET_SCAN_ENABLE_REQ,
+	CMD_LE_SET_SCAN_ENABLE_RSP,
+	CMD_LE_CREATE_CONNECTION_REQ,
+	CMD_LE_CREATE_CONNECTION_RSP,
+	CMD_LE_CREATE_CONNECTION_CANCEL_REQ,
+	CMD_LE_CREATE_CONNECTION_CANCEL_RSP,
+	CMD_LE_READ_FILTER_ACCEPT_LIST_SIZE_REQ,
+	CMD_LE_READ_FILTER_ACCEPT_LIST_SIZE_RSP,
+	CMD_LE_CLEAR_FILTER_ACCEPT_LIST_REQ,
+	CMD_LE_CLEAR_FILTER_ACCEPT_LIST_RSP,
+	CMD_LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST_REQ,
+	CMD_LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST_RSP,
+	CMD_LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST_REQ,
+	CMD_LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST_RSP,
+	CMD_LE_CONNECTION_UPDATE_REQ,
+	CMD_LE_CONNECTION_UPDATE_RSP,
+	CMD_LE_SET_HOST_CHANNEL_CLASSIFICATION_REQ,
+	CMD_LE_SET_HOST_CHANNEL_CLASSIFICATION_RSP,
+	CMD_LE_READ_CHANNEL_MAP_REQ,
+	CMD_LE_READ_CHANNEL_MAP_RSP,
+	CMD_LE_READ_REMOTE_FEATURES_REQ,
+	CMD_LE_READ_REMOTE_FEATURES_RSP,
+	CMD_LE_ENCRYPT_REQ,
+	CMD_LE_ENCRYPT_RSP,
+	CMD_LE_RAND_REQ,
+	CMD_LE_RAND_RSP,
+	CMD_LE_START_ENCRYPTION_REQ,
+	CMD_LE_START_ENCRYPTION_RSP,
+	CMD_LE_LONG_TERM_KEY_REQUEST_REPLY_REQ,
+	CMD_LE_LONG_TERM_KEY_REQUEST_REPLY_RSP,
+	CMD_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_REQ,
+	CMD_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY_RSP,
+	CMD_LE_READ_SUPPORTED_STATES_REQ,
+	CMD_LE_READ_SUPPORTED_STATES_RSP,
+	CMD_LE_RECEIVER_TEST_REQ,
+	CMD_LE_RECEIVER_TEST_RSP,
+	CMD_LE_TRANSMITTER_TEST_REQ,
+	CMD_LE_TRANSMITTER_TEST_RSP,
+	CMD_LE_TEST_END_REQ,
+	CMD_LE_TEST_END_RSP,
+	CMD_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_REQ,
+	CMD_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY_RSP,
+	CMD_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_REQ,
+	CMD_LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY_RSP,
+	CMD_LE_SET_DATA_LENGTH_REQ,
+	CMD_LE_SET_DATA_LENGTH_RSP,
+	CMD_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_REQ,
+	CMD_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_RSP,
+	CMD_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_REQ,
+	CMD_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_RSP,
+	CMD_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND_REQ,
+	CMD_LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND_RSP,
+	CMD_LE_GENERATE_DHKEY_COMMAND_REQ,
+	CMD_LE_GENERATE_DHKEY_COMMAND_RSP,
+	CMD_LE_ADD_DEVICE_TO_RESOLVING_LIST_REQ,
+	CMD_LE_ADD_DEVICE_TO_RESOLVING_LIST_RSP,
+	CMD_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_REQ,
+	CMD_LE_REMOVE_DEVICE_FROM_RESOLVING_LIST_RSP,
+	CMD_LE_CLEAR_RESOLVING_LIST_REQ,
+	CMD_LE_CLEAR_RESOLVING_LIST_RSP,
+	CMD_LE_READ_RESOLVING_LIST_SIZE_REQ,
+	CMD_LE_READ_RESOLVING_LIST_SIZE_RSP,
+	CMD_LE_READ_PEER_RESOLVABLE_ADDRESS_REQ,
+	CMD_LE_READ_PEER_RESOLVABLE_ADDRESS_RSP,
+	CMD_LE_READ_LOCAL_RESOLVABLE_ADDRESS_REQ,
+	CMD_LE_READ_LOCAL_RESOLVABLE_ADDRESS_RSP,
+	CMD_LE_SET_ADDRESS_RESOLUTION_ENABLE_REQ,
+	CMD_LE_SET_ADDRESS_RESOLUTION_ENABLE_RSP,
+	CMD_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_REQ,
+	CMD_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_RSP,
+	CMD_LE_READ_MAXIMUM_DATA_LENGTH_REQ,
+	CMD_LE_READ_MAXIMUM_DATA_LENGTH_RSP,
+	CMD_LE_READ_PHY_REQ,
+	CMD_LE_READ_PHY_RSP,
+	CMD_LE_SET_DEFAULT_PHY_REQ,
+	CMD_LE_SET_DEFAULT_PHY_RSP,
+	CMD_LE_SET_PHY_REQ,
+	CMD_LE_SET_PHY_RSP,
+	CMD_LE_ENHANCED_RECEIVER_TEST_REQ,
+	CMD_LE_ENHANCED_RECEIVER_TEST_RSP,
+	CMD_LE_ENHANCED_TRANSMITTER_TEST_REQ,
+	CMD_LE_ENHANCED_TRANSMITTER_TEST_RSP,
+	CMD_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_REQ,
+	CMD_LE_SET_EXTENDED_ADVERTISING_PARAMETERS_RSP,
+	CMD_LE_SET_EXTENDED_ADVERTISING_DATA_REQ,
+	CMD_LE_SET_EXTENDED_ADVERTISING_DATA_RSP,
+	CMD_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_REQ,
+	CMD_LE_SET_EXTENDED_SCAN_RESPONSE_DATA_RSP,
+	CMD_LE_SET_EXTENDED_ADVERTISING_ENABLE_REQ,
+	CMD_LE_SET_EXTENDED_ADVERTISING_ENABLE_RSP,
+	CMD_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_REQ,
+	CMD_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_RSP,
+	CMD_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS_REQ,
+	CMD_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS_RSP,
+	CMD_LE_REMOVE_ADVERTISING_SET_REQ,
+	CMD_LE_REMOVE_ADVERTISING_SET_RSP,
+	CMD_LE_CLEAR_ADVERTISING_SETS_REQ,
+	CMD_LE_CLEAR_ADVERTISING_SETS_RSP,
+	CMD_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_REQ,
+	CMD_LE_SET_PERIODIC_ADVERTISING_PARAMETERS_RSP,
+	CMD_LE_SET_PERIODIC_ADVERTISING_DATA_REQ,
+	CMD_LE_SET_PERIODIC_ADVERTISING_DATA_RSP,
+	CMD_LE_SET_PERIODIC_ADVERTISING_ENABLE_REQ,
+	CMD_LE_SET_PERIODIC_ADVERTISING_ENABLE_RSP,
+	CMD_LE_SET_EXTENDED_SCAN_PARAMETERS_REQ,
+	CMD_LE_SET_EXTENDED_SCAN_PARAMETERS_RSP,
+	CMD_LE_SET_EXTENDED_SCAN_ENABLE_REQ,
+	CMD_LE_SET_EXTENDED_SCAN_ENABLE_RSP,
+	CMD_LE_EXTENDED_CREATE_CONNECTION_REQ,
+	CMD_LE_EXTENDED_CREATE_CONNECTION_RSP,
+	CMD_LE_PERIODIC_ADVERTISING_CREATE_SYNC_REQ,
+	CMD_LE_PERIODIC_ADVERTISING_CREATE_SYNC_RSP,
+	CMD_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_REQ,
+	CMD_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_RSP,
+	CMD_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_REQ,
+	CMD_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_RSP,
+	CMD_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_REQ,
+	CMD_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_RSP,
+	CMD_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_REQ,
+	CMD_LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISER_LIST_RSP,
+	CMD_LE_CLEAR_PERIODIC_ADVERTISER_LIST_REQ,
+	CMD_LE_CLEAR_PERIODIC_ADVERTISER_LIST_RSP,
+	CMD_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_REQ,
+	CMD_LE_READ_PERIODIC_ADVERTISER_LIST_SIZE_RSP,
+	CMD_LE_READ_TRANSMIT_POWER_REQ,
+	CMD_LE_READ_TRANSMIT_POWER_RSP,
+	CMD_LE_READ_RF_PATH_COMPENSATION_REQ,
+	CMD_LE_READ_RF_PATH_COMPENSATION_RSP,
+	CMD_LE_WRITE_RF_PATH_COMPENSATION_REQ,
+	CMD_LE_WRITE_RF_PATH_COMPENSATION_RSP,
+	CMD_LE_SET_PRIVACY_MODE_REQ,
+	CMD_LE_SET_PRIVACY_MODE_RSP,
+	CMD_WRITE_BD_ADDR_REQ,
+	CMD_WRITE_BD_ADDR_RSP,
+	CMD_FLUSH_EVENTS_REQ,
+	CMD_FLUSH_EVENTS_RSP,
+	CMD_HAS_EVENT_REQ,
+	CMD_HAS_EVENT_RSP,
+	CMD_GET_EVENT_REQ,
+	CMD_GET_EVENT_RSP,
+	CMD_LE_FLUSH_DATA_REQ,
+	CMD_LE_FLUSH_DATA_RSP,
+	CMD_LE_DATA_READY_REQ,
+	CMD_LE_DATA_READY_RSP,
+	CMD_LE_DATA_WRITE_REQ,
+	CMD_LE_DATA_WRITE_RSP,
+	CMD_LE_DATA_READ_REQ,
+	CMD_LE_DATA_READ_RSP,
+	CMD_GATT_SERVICE_SET_REQ,
+	CMD_GATT_SERVICE_SET_RSP,
+	CMD_GATT_SERVICE_NOTIFY_REQ,
+	CMD_GATT_SERVICE_NOTIFY_RSP,
+	CMD_GATT_SERVICE_INDICATE_REQ,
+	CMD_GATT_SERVICE_INDICATE_RSP,
+	CMD_GAP_ADVERTISING_MODE_REQ,
+	CMD_GAP_ADVERTISING_MODE_RSP,
+	CMD_GAP_ADVERTISING_DATA_REQ,
+	CMD_GAP_ADVERTISING_DATA_RSP,
+	CMD_GAP_SCANNING_MODE_REQ,
+	CMD_GAP_SCANNING_MODE_RSP,
+	CMD_READ_STATIC_ADDRESSES_REQ,
+	CMD_READ_STATIC_ADDRESSES_RSP,
+	CMD_READ_KEY_HIERARCHY_ROOTS_REQ,
+	CMD_READ_KEY_HIERARCHY_ROOTS_RSP,
+	CMD_GAP_READ_IRK_REQ,
+	CMD_GAP_READ_IRK_RSP,
+	CMD_GAP_ROLE_REQ,
+	CMD_GAP_ROLE_RSP
+};
+
+#endif /* EDDT_APP_COMMANDS_H */
diff --git a/babblesim/edtt/hci_transport/include/edtt_driver.h b/babblesim/edtt/hci_transport/include/edtt_driver.h
new file mode 100644
index 0000000..3b7d253
--- /dev/null
+++ b/babblesim/edtt/hci_transport/include/edtt_driver.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef EDTT_DRIVER_H
+#define EDTT_DRIVER_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+
+#define EDTTT_NONBLOCK 0
+#define EDTTT_BLOCK 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Generic EDTT interface
+ */
+bool edtt_start(void);
+bool edtt_stop(void);
+int edtt_read(uint8_t *ptr, size_t size, int flags);
+int edtt_write(uint8_t *ptr, size_t size, int flags);
+
+/**
+ * Exclusive functions for the BabbleSim driver
+ */
+void enable_edtt_mode(void);
+void set_edtt_autoshutdown(bool mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EDTT_DRIVER_H */
diff --git a/babblesim/edtt/hci_transport/pkg.yml b/babblesim/edtt/hci_transport/pkg.yml
new file mode 100644
index 0000000..8e1dd9f
--- /dev/null
+++ b/babblesim/edtt/hci_transport/pkg.yml
@@ -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.
+#
+
+pkg.name: babblesim/edtt/hci_transport
+pkg.description: Provides communication with EDTT bridge over named pipes
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.deps:
+    - "@apache-mynewt-core/sys/console/stub"
+    - "@apache-mynewt-core/sys/log/stub"
+    - "@apache-mynewt-core/sys/stats/full"
+    - "@apache-mynewt-core/kernel/os"
+    - nimble/controller
+
+pkg.apis:
+    - ble_transport
+
+pkg.init:
+    ble_hci_edtt_init: 500
diff --git a/babblesim/edtt/hci_transport/src/ble_hci_edtt.c b/babblesim/edtt/hci_transport/src/ble_hci_edtt.c
new file mode 100644
index 0000000..57cdc3b
--- /dev/null
+++ b/babblesim/edtt/hci_transport/src/ble_hci_edtt.c
@@ -0,0 +1,1149 @@
+/*
+ * Copyright (c) 2019 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdint.h>
+#include <bs_tracing.h>
+#include "sysinit/sysinit.h"
+#include "syscfg/syscfg.h"
+#include "os/os_cputime.h"
+#include "os/os.h"
+
+/* BLE */
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
+
+#include "bs_symbols.h"
+#include "bs_types.h"
+#include "time_machine.h"
+#include "ble_hci_edtt.h"
+#include "edtt_driver.h"
+#include "commands.h"
+
+#define BLE_HCI_EDTT_EVT_COUNT  \
+    (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
+
+#define BLE_HCI_EDTT_NONE        0x00
+#define BLE_HCI_EDTT_CMD         0x01
+#define BLE_HCI_EDTT_ACL         0x02
+#define BLE_HCI_EDTT_EVT         0x04
+
+#define K_NO_WAIT 0
+#define K_FOREVER 1
+
+#define BT_HCI_OP_VS_WRITE_BD_ADDR 0xFC06
+
+/* Callbacks for sending commands and acl data to ble_ll task */
+static ble_hci_trans_rx_cmd_fn *ble_hci_edtt_rx_cmd_cb;
+static void *ble_hci_edtt_rx_cmd_arg;
+static ble_hci_trans_rx_acl_fn *ble_hci_edtt_rx_acl_cb;
+static void *ble_hci_edtt_rx_acl_arg;
+
+/* Memory pool for hci events (high prio). 16 blocks x 70 bytes */
+static struct os_mempool ble_hci_edtt_evt_hi_pool;
+static os_membuf_t ble_hci_edtt_evt_hi_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                    MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+/* Memory pool for hci events (low prio). 16 blocks x 70 bytes */
+static struct os_mempool ble_hci_edtt_evt_lo_pool;
+static os_membuf_t ble_hci_edtt_evt_lo_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                    MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
+];
+
+/* Memory pool for hci commands. Only 1 block, so supports only 1 command at once. */
+static struct os_mempool ble_hci_edtt_cmd_pool;
+static os_membuf_t ble_hci_edtt_cmd_buf[
+    OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)
+];
+
+/*
+ * 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)
+
+/* mbuf pool for acl data. 15 buffers x (255 bytes + some hdrs len)  */
+static struct os_mbuf_pool ble_hci_edtt_acl_mbuf_pool;
+static struct os_mempool_ext ble_hci_edtt_acl_pool;
+static os_membuf_t ble_hci_edtt_acl_buf[
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                    ACL_BLOCK_SIZE)
+];
+
+/* A packet for queueing EDTT/HCI commands and events */
+struct ble_hci_edtt_pkt {
+    STAILQ_ENTRY(ble_hci_edtt_pkt) next;
+    uint32_t timestamp;
+    uint8_t type;
+    void *data;
+};
+
+/* Memory pool for ble_hci_edtt_pkt packets */
+static struct os_mempool ble_hci_edtt_pkt_pool;
+static os_membuf_t ble_hci_edtt_pkt_buf[
+    OS_MEMPOOL_SIZE(BLE_HCI_EDTT_EVT_COUNT + 1 +
+                    MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+                    sizeof(struct ble_hci_edtt_pkt))
+];
+
+STAILQ_HEAD(ble_hci_edtt_pkt_queue, ble_hci_edtt_pkt);
+static struct ble_hci_edtt_pkt_queue data_queue;
+static struct ble_hci_edtt_pkt_queue rx_queue;
+static struct ble_hci_edtt_pkt_queue event_queue;
+
+static uint16_t waiting_opcode;
+static enum commands_t waiting_response;
+static uint8_t m_events;
+
+#define EDTT_POLLER_STACK_SZ OS_STACK_ALIGN(4000)
+static int edtt_poller_running;
+static struct os_task edtt_poller_task;
+static os_stack_t edtt_poller_stack[EDTT_POLLER_STACK_SZ];
+
+#if EDTT_HCI_LOGS
+extern unsigned int global_device_nbr;
+static FILE *fptr;
+
+static void
+log_hex_array(uint8_t *buf, int len)
+{
+    int i;
+    for (i = 0; i < len; i++) {
+        fprintf(fptr, "%02X ", buf[i]);
+    }
+}
+
+static void
+log_hci_cmd(uint16_t opcode, uint8_t *buf, int len)
+{
+    if (fptr) {
+        fprintf(fptr, "> %llu %02d %02d ", now, BLE_HCI_OCF(opcode), (BLE_HCI_OGF(opcode)));
+        log_hex_array(buf, len);
+        fputs("\n\n", fptr);
+        fflush(fptr);
+    }
+}
+
+static void
+log_hci_evt(struct ble_hci_ev *hdr)
+{
+    if (fptr) {
+        fprintf(fptr, "< %llu %02d ", now, hdr->opcode);
+        log_hex_array(hdr->data, hdr->length);
+        fputs("\n\n", fptr);
+        fflush(fptr);
+    }
+}
+
+static void
+log_hci_init()
+{
+    int flen = (int) strlen(MYNEWT_VAL(EDTT_HCI_LOG_FILE)) + 7;
+    char *fpath = (char *) calloc(flen, sizeof(char));
+    sprintf(fpath, "%s_%02d.log", MYNEWT_VAL(EDTT_HCI_LOG_FILE), global_device_nbr);
+    fptr = fopen(fpath, "w");
+    free(fpath);
+}
+#endif
+
+/**
+ * Allocates a buffer (mbuf) for ACL operation.
+ *
+ * @return                      The allocated buffer on success;
+ *                              NULL on buffer exhaustion.
+ */
+static struct os_mbuf *
+ble_hci_trans_acl_buf_alloc(void)
+{
+    struct os_mbuf *m;
+    uint8_t usrhdr_len;
+
+#if MYNEWT_VAL(BLE_CONTROLLER)
+    usrhdr_len = sizeof(struct ble_mbuf_hdr);
+#else
+    usrhdr_len = 0;
+#endif
+
+    m = os_mbuf_get_pkthdr(&ble_hci_edtt_acl_mbuf_pool, usrhdr_len);
+    return m;
+}
+
+static int
+ble_hci_edtt_acl_tx(struct os_mbuf *om)
+{
+    struct ble_hci_edtt_pkt *pkt;
+    os_sr_t sr;
+
+    /* 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_edtt_pkt_pool);
+    if (pkt == NULL) {
+        os_mbuf_free_chain(om);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    pkt->type = BLE_HCI_EDTT_ACL;
+    pkt->data = om;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&rx_queue, pkt, next);
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+static int
+ble_hci_edtt_cmdevt_tx(uint8_t *hci_ev, uint8_t edtt_type)
+{
+    struct ble_hci_edtt_pkt *pkt;
+    os_sr_t sr;
+
+    pkt = os_memblock_get(&ble_hci_edtt_pkt_pool);
+    if (pkt == NULL) {
+        ble_hci_trans_buf_free(hci_ev);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    pkt->type = edtt_type;
+    pkt->data = hci_ev;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&rx_queue, pkt, next);
+    OS_EXIT_CRITICAL(sr);
+
+    return 0;
+}
+
+static void
+ble_hci_edtt_set_rx_cbs(ble_hci_trans_rx_cmd_fn *cmd_cb,
+                        void *cmd_arg,
+                        ble_hci_trans_rx_acl_fn *acl_cb,
+                        void *acl_arg)
+{
+    ble_hci_edtt_rx_cmd_cb = cmd_cb;
+    ble_hci_edtt_rx_cmd_arg = cmd_arg;
+    ble_hci_edtt_rx_acl_cb = acl_cb;
+    ble_hci_edtt_rx_acl_arg = acl_arg;
+}
+
+/* Free data buffer */
+static void
+ble_hci_edtt_free_buf(uint8_t type, uint8_t *cmdevt, struct os_mbuf *acl)
+{
+    switch (type) {
+        case BLE_HCI_EDTT_NONE:
+            break;
+
+        case BLE_HCI_EDTT_CMD:
+        case BLE_HCI_EDTT_EVT:
+            ble_hci_trans_buf_free(cmdevt);
+            break;
+
+        case BLE_HCI_EDTT_ACL:
+            os_mbuf_free_chain(acl);
+            break;
+
+        default:
+            assert(0);
+            break;
+    }
+}
+
+static void
+edtt_pkt_dequeue_and_free(struct ble_hci_edtt_pkt_queue *queue, struct ble_hci_edtt_pkt *pkt)
+{
+    /* Dequeue pkt header */
+    STAILQ_REMOVE(queue, pkt, ble_hci_edtt_pkt, next);
+    /* Free data buffer */
+    ble_hci_edtt_free_buf(pkt->type, pkt->data, pkt->data);
+    /* Free buffer of pkt header */
+    os_memblock_put(&ble_hci_edtt_pkt_pool, pkt);
+}
+
+/* Get first element of queue, without dequeueing */
+static struct ble_hci_edtt_pkt *
+edtt_pkt_get(struct ble_hci_edtt_pkt_queue *queue, uint8_t block)
+{
+    struct ble_hci_edtt_pkt *pkt;
+
+    if (block == K_FOREVER) {
+        while (STAILQ_EMPTY(queue)) {}
+
+        pkt = STAILQ_FIRST(queue);
+        assert(pkt != NULL);
+    } else {
+        pkt = STAILQ_FIRST(queue);
+    }
+
+    return pkt;
+}
+
+/**
+ * Sends an HCI event from the controller to the host.
+ *
+ * @param cmd                   The HCI event to send.  This buffer must be
+ *                                  allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int
+ble_hci_trans_ll_evt_tx(uint8_t *cmd)
+{
+    int rc;
+
+    rc = ble_hci_edtt_cmdevt_tx(cmd, BLE_HCI_EDTT_EVT);
+    return rc;
+}
+
+/**
+ * Sends ACL data from controller to host.
+ *
+ * @param om                    The ACL data packet to send.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+int
+ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
+{
+    int rc;
+
+    rc = ble_hci_edtt_acl_tx(om);
+    return rc;
+}
+
+int
+ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
+{
+    int rc;
+
+    rc = ble_hci_edtt_cmdevt_tx(cmd, BLE_HCI_EDTT_CMD);
+    return rc;
+}
+
+int
+ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
+{
+    int rc;
+
+    rc = ble_hci_edtt_acl_tx(om);
+    return rc;
+}
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type                  The type of buffer to allocate; one of the
+ *                                  BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return                      The allocated buffer on success;
+ *                              NULL on buffer exhaustion.
+ */
+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_edtt_cmd_pool);
+            break;
+        case BLE_HCI_TRANS_BUF_EVT_HI:
+            buf = os_memblock_get(&ble_hci_edtt_evt_hi_pool);
+            if (buf == NULL) {
+                /* If no high-priority event buffers remain, try to grab a
+                 * low-priority one.
+                 */
+                buf = os_memblock_get(&ble_hci_edtt_evt_lo_pool);
+            }
+            break;
+
+        case BLE_HCI_TRANS_BUF_EVT_LO:
+            buf = os_memblock_get(&ble_hci_edtt_evt_lo_pool);
+            break;
+
+        default:
+            assert(0);
+            buf = NULL;
+    }
+
+    return buf;
+}
+
+/**
+ * Frees the specified flat buffer.  The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf                   The buffer to free.
+ */
+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_edtt_evt_hi_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_edtt_evt_hi_pool, buf);
+        assert(rc == 0);
+    } else if (os_memblock_from(&ble_hci_edtt_evt_lo_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_edtt_evt_lo_pool, buf);
+        assert(rc == 0);
+    } else {
+        assert(os_memblock_from(&ble_hci_edtt_cmd_pool, buf));
+        rc = os_memblock_put(&ble_hci_edtt_cmd_pool, buf);
+        assert(rc == 0);
+    }
+}
+
+int
+ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
+{
+    ble_hci_edtt_acl_pool.mpe_put_cb = cb;
+    ble_hci_edtt_acl_pool.mpe_put_arg = arg;
+    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)
+{
+    ble_hci_edtt_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg);
+}
+
+void
+ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
+                     void *cmd_arg,
+                     ble_hci_trans_rx_acl_fn *acl_cb,
+                     void *acl_arg)
+{
+    ble_hci_edtt_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg);
+}
+
+int
+ble_hci_trans_reset(void)
+{
+    struct ble_hci_edtt_pkt *pkt;
+
+    while ((pkt = STAILQ_FIRST(&data_queue)) != NULL) {
+        edtt_pkt_dequeue_and_free(&data_queue, pkt);
+    }
+
+    while ((pkt = STAILQ_FIRST(&event_queue)) != NULL) {
+        edtt_pkt_dequeue_and_free(&event_queue, pkt);
+    }
+
+    while ((pkt = STAILQ_FIRST(&rx_queue)) != NULL) {
+        edtt_pkt_dequeue_and_free(&rx_queue, pkt);
+    }
+
+    return 0;
+}
+
+/**
+ * @brief Clean out excess bytes from the input buffer
+ */
+static void
+read_excess_bytes(uint16_t size)
+{
+    if (size > 0) {
+        uint8_t buffer[size];
+
+        edtt_read((uint8_t *) buffer, size, EDTTT_BLOCK);
+        bs_trace_raw_time(3, "command size wrong! (%u extra bytes removed)", size);
+    }
+}
+
+/**
+ * @brief Provide an error response when an HCI command send failed
+ */
+static void
+error_response(int error)
+{
+    uint16_t response = waiting_response;
+    int le_error = error;
+    uint16_t size = sizeof(le_error);
+
+    edtt_write((uint8_t *) &response, sizeof(response), EDTTT_BLOCK);
+    edtt_write((uint8_t *) &size, sizeof(size), EDTTT_BLOCK);
+    edtt_write((uint8_t *) &le_error, sizeof(le_error), EDTTT_BLOCK);
+    waiting_response = CMD_NOTHING;
+    waiting_opcode = 0;
+}
+
+/**
+ * @brief Allocate buffer for HCI command, fill in parameters and send the
+ * command
+ */
+static int
+send_hci_cmd_to_ctrl(uint16_t opcode, uint8_t param_len, uint16_t response) {
+    struct ble_hci_cmd *buf;
+    int err = 0;
+    waiting_response = response;
+    waiting_opcode = opcode;
+
+    buf = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+
+    if (buf != NULL) {
+        buf->opcode = opcode;
+        buf->length = param_len;
+
+        if (param_len) {
+            edtt_read((uint8_t *) buf->data, param_len, EDTTT_BLOCK);
+        }
+
+#if EDTT_HCI_LOGS
+        log_hci_cmd(opcode, buf->data, param_len);
+#endif
+
+        err = ble_hci_edtt_rx_cmd_cb((uint8_t *) buf, NULL);
+        if (err) {
+            ble_hci_trans_buf_free((uint8_t *) buf);
+            bs_trace_raw_time(3, "Failed to send HCI command %d (err %d)", opcode, err);
+            error_response(err);
+        }
+    } else {
+        bs_trace_raw_time(3, "Failed to create buffer for HCI command 0x%04x", opcode);
+        error_response(-1);
+    }
+    return err;
+}
+
+/**
+ * @brief Echo function - echo input received
+ */
+static void
+echo(uint16_t size)
+{
+    uint16_t response = CMD_ECHO_RSP;
+
+    edtt_write((uint8_t *) &response, sizeof(response), EDTTT_BLOCK);
+    edtt_write((uint8_t *) &size, sizeof(size), EDTTT_BLOCK);
+
+    if (size > 0) {
+        uint8_t buff[size];
+
+        edtt_read(buff, size, EDTTT_BLOCK);
+        edtt_write(buff, size, EDTTT_BLOCK);
+    }
+}
+
+/**
+ * @brief Handle Command Complete HCI event
+ */
+static void
+command_complete(struct ble_hci_ev *hdr)
+{
+    struct ble_hci_ev_command_complete *evt = (void *) hdr->data;
+    uint16_t response = waiting_response;
+    uint16_t size = hdr->length - sizeof(evt->num_packets) - sizeof(evt->opcode);
+
+    if (evt->opcode == waiting_opcode) {
+        bs_trace_raw_time(9, "Command complete for 0x%04x", waiting_opcode);
+
+        edtt_write((uint8_t *) &response, sizeof(response), EDTTT_BLOCK);
+        edtt_write((uint8_t *) &size, sizeof(size), EDTTT_BLOCK);
+        edtt_write((uint8_t *) &evt->status, sizeof(evt->status), EDTTT_BLOCK);
+        edtt_write((uint8_t *) &evt->return_params, size - sizeof(evt->status), EDTTT_BLOCK);
+        waiting_opcode = 0;
+    } else {
+        bs_trace_raw_time(5, "Not waiting for 0x(%04x) command status,"
+                             " expected 0x(%04x)", evt->opcode, waiting_opcode);
+    }
+}
+
+/**
+ * @brief Handle Command Status HCI event
+ */
+static void
+command_status(struct ble_hci_ev *buf)
+{
+    struct ble_hci_ev_command_status *evt = (void *) buf->data;
+    uint16_t opcode = evt->opcode;
+    uint16_t response = waiting_response;
+    uint16_t size;
+
+    size = buf->length - sizeof(evt->num_packets) - sizeof(evt->opcode);
+
+    if (opcode == waiting_opcode) {
+        bs_trace_raw_time(9, "Command status for 0x%04x", waiting_opcode);
+
+        edtt_write((uint8_t *) &response, sizeof(response), EDTTT_BLOCK);
+        edtt_write((uint8_t *) &size, sizeof(size), EDTTT_BLOCK);
+        edtt_write((uint8_t *) &evt->status, sizeof(evt->status), EDTTT_BLOCK);
+        edtt_write((uint8_t *) &evt->num_packets, size - sizeof(evt->status), EDTTT_BLOCK);
+        waiting_opcode = 0;
+    } else {
+        bs_trace_raw_time(5, "Not waiting for 0x(%04x) command status,"
+                             " expected 0x(%04x)", opcode, waiting_opcode);
+    }
+}
+
+/**
+ * @brief Remove an event from the event queue
+ */
+static void
+discard_event(void)
+{
+    struct ble_hci_edtt_pkt *evt = edtt_pkt_get(&event_queue, K_FOREVER);
+    edtt_pkt_dequeue_and_free(&event_queue, evt);
+    m_events--;
+}
+
+/**
+ * @brief Allocate and store an event in the event queue
+ */
+static struct ble_hci_edtt_pkt *
+queue_event(struct ble_hci_ev *buf)
+{
+    struct ble_hci_edtt_pkt *evt;
+
+    evt = os_memblock_get(&ble_hci_edtt_pkt_pool);
+    if (evt) {
+        evt->timestamp = tm_get_hw_time();
+        evt->type = BLE_HCI_EDTT_EVT;
+        evt->data = buf;
+
+        STAILQ_INSERT_TAIL(&event_queue, evt, next);
+        m_events++;
+    }
+    return evt;
+}
+
+/**
+ * @brief Thread to service events and ACL data packets from the HCI input queue
+ */
+static void
+service_events(void)
+{
+    struct ble_hci_edtt_pkt *rx_pkt, *evt_pkt, *data_pkt;
+    struct ble_hci_ev *hdr;
+    struct os_mbuf *om;
+
+    rx_pkt = edtt_pkt_get(&rx_queue, K_NO_WAIT);
+    if (rx_pkt == NULL) {
+        return;
+    }
+
+    if (rx_pkt->type == BLE_HCI_EDTT_EVT) {
+        hdr = (void *) rx_pkt->data;
+
+#if EDTT_HCI_LOGS
+        log_hci_evt(hdr);
+#endif
+
+        /* Prepare and send EDTT events */
+        switch (hdr->opcode) {
+            case BLE_HCI_EVCODE_COMMAND_COMPLETE:
+                evt_pkt = queue_event(hdr);
+                if (!evt_pkt) {
+                    discard_event();
+                    evt_pkt = queue_event(hdr);
+                }
+                command_complete(hdr);
+                break;
+            case BLE_HCI_EVCODE_COMMAND_STATUS:
+                evt_pkt = queue_event(hdr);
+                if (!evt_pkt) {
+                    discard_event();
+                    evt_pkt = queue_event(hdr);
+                }
+                command_status(hdr);
+                break;
+            case BLE_HCI_EVCODE_NUM_COMP_PKTS:
+                /* EDTT does not handle this event and treats like fail */
+            case BLE_HCI_OPCODE_NOP:
+                /* Ignore noop bytes from Link layer */
+                edtt_pkt_dequeue_and_free(&rx_queue, rx_pkt);
+                return;
+            default:
+                /* Queue HCI events. We will send them to EDTT
+                 * on CMD_GET_EVENT_REQ. */
+                evt_pkt = queue_event(hdr);
+                if (!evt_pkt) {
+                    bs_trace_raw_time(4, "Failed to allocated buffer for event!\n");
+                }
+        }
+    } else if (rx_pkt->type == BLE_HCI_EDTT_ACL) {
+        om = (struct os_mbuf *) rx_pkt->data;
+        data_pkt = os_memblock_get(&ble_hci_edtt_pkt_pool);
+
+        if (data_pkt) {
+            data_pkt->type = BLE_HCI_EDTT_ACL;
+            data_pkt->data = om;
+            STAILQ_INSERT_TAIL(&data_queue, data_pkt, next);
+        }
+    }
+
+    /* Free only header buffer, not rx_pkt->data buffer */
+    STAILQ_REMOVE(&rx_queue, rx_pkt, ble_hci_edtt_pkt, next);
+    os_memblock_put(&ble_hci_edtt_pkt_pool, rx_pkt);
+}
+
+/**
+ * @brief Flush all HCI events from the input-copy queue
+ */
+static void
+flush_events(uint16_t size)
+{
+    uint16_t response = CMD_FLUSH_EVENTS_RSP;
+    struct ble_hci_edtt_pkt *buf;
+
+    while ((buf = edtt_pkt_get(&event_queue, K_NO_WAIT))) {
+        edtt_pkt_dequeue_and_free(&event_queue, buf);
+        m_events--;
+    }
+    read_excess_bytes(size);
+    size = 0;
+
+    edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
+    edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+}
+
+/**
+ * @brief Get next available HCI event from the input-copy queue
+ */
+static void
+get_event(uint16_t size)
+{
+    uint16_t response = CMD_GET_EVENT_RSP;
+    struct ble_hci_edtt_pkt *pkt;
+    struct ble_hci_ev *hdr;
+
+    read_excess_bytes(size);
+    size = 0;
+
+    edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
+    pkt = edtt_pkt_get(&event_queue, K_FOREVER);
+
+    if (pkt) {
+        hdr = pkt->data;
+        size = sizeof(pkt->timestamp) + sizeof(*hdr) + hdr->length;
+
+        edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+        edtt_write((uint8_t *)&pkt->timestamp, sizeof(pkt->timestamp), EDTTT_BLOCK);
+        edtt_write((uint8_t *)hdr, sizeof(*hdr) + hdr->length, EDTTT_BLOCK);
+
+        edtt_pkt_dequeue_and_free(&event_queue, pkt);
+        m_events--;
+    } else {
+        edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+    }
+}
+
+/**
+ * @brief Get next available HCI events from the input-copy queue
+ */
+static void
+get_events(uint16_t size)
+{
+    uint16_t response = CMD_GET_EVENT_RSP;
+    struct ble_hci_edtt_pkt *pkt;
+    struct ble_hci_ev *hdr;
+    uint8_t count = m_events;
+
+    read_excess_bytes(size);
+    size = 0;
+
+    edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
+    edtt_write((uint8_t *)&count, sizeof(count), EDTTT_BLOCK);
+
+    while (count--) {
+        pkt = edtt_pkt_get(&event_queue, K_FOREVER);
+        hdr = pkt->data;
+        size = sizeof(pkt->timestamp) + sizeof(*hdr) + hdr->length;
+
+        edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+        edtt_write((uint8_t *)&pkt->timestamp, sizeof(pkt->timestamp), EDTTT_BLOCK);
+        edtt_write((uint8_t *)hdr, sizeof(*hdr) + hdr->length, EDTTT_BLOCK);
+
+        edtt_pkt_dequeue_and_free(&event_queue, pkt);
+        m_events--;
+    }
+}
+
+/**
+ * @brief Check whether an HCI event is available in the input-copy queue
+ */
+static void
+has_event(uint16_t size)
+{
+    struct has_event_resp {
+        uint16_t response;
+        uint16_t size;
+        uint8_t count;
+    } __attribute__((packed));
+    struct has_event_resp le_response = {
+        .response = CMD_HAS_EVENT_RSP,
+        .size = 1,
+        .count = m_events
+    };
+
+    if (size > 0) {
+        read_excess_bytes(size);
+    }
+    edtt_write((uint8_t *) &le_response, sizeof(le_response), EDTTT_BLOCK);
+}
+
+/**
+ * @brief Flush all ACL Data Packages from the input-copy queue
+ */
+static void
+le_flush_data(uint16_t size)
+{
+    uint16_t response = CMD_LE_FLUSH_DATA_RSP;
+    struct ble_hci_edtt_pkt *buf;
+
+    while ((buf = edtt_pkt_get(&data_queue, K_NO_WAIT))) {
+        edtt_pkt_dequeue_and_free(&data_queue, buf);
+    }
+    read_excess_bytes(size);
+    size = 0;
+
+    edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
+    edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+}
+
+/**
+ * @brief Check whether an ACL Data Package is available in the input-copy queue
+ */
+static void
+le_data_ready(uint16_t size)
+{
+    struct has_data_resp {
+        uint16_t response;
+        uint16_t size;
+        uint8_t empty;
+    } __attribute__((packed));
+    struct has_data_resp le_response = {
+        .response = CMD_LE_DATA_READY_RSP,
+        .size = 1,
+        .empty = 0
+    };
+
+    if (size > 0) {
+        read_excess_bytes(size);
+    }
+
+    if (STAILQ_EMPTY(&data_queue)) {
+        le_response.empty = 1;
+    }
+
+    edtt_write((uint8_t *) &le_response, sizeof(le_response), EDTTT_BLOCK);
+}
+
+/**
+ * @brief Get next available HCI Data Package from the input-copy queue
+ */
+static void
+le_data_read(uint16_t size)
+{
+    uint16_t response = CMD_LE_DATA_READ_RSP;
+    struct ble_hci_edtt_pkt *pkt;
+    struct os_mbuf *om;
+
+    read_excess_bytes(size);
+    size = 0;
+
+    edtt_write((uint8_t *)&response, sizeof(response), EDTTT_BLOCK);
+    pkt = edtt_pkt_get(&data_queue, K_FOREVER);
+
+    if (pkt) {
+        om = pkt->data;
+        size = OS_MBUF_PKTLEN(om);
+        edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+
+        while (om != NULL) {
+            edtt_write((uint8_t *)om->om_data, om->om_len, EDTTT_BLOCK);
+            om = SLIST_NEXT(om, om_next);
+        }
+
+        om = pkt->data;
+        os_mbuf_free_chain(om);
+    } else {
+        edtt_write((uint8_t *)&size, sizeof(size), EDTTT_BLOCK);
+    }
+}
+
+/**
+ * @brief Write ACL Data Package to the Controller
+ */
+static void
+le_data_write(uint16_t size)
+{
+    struct data_write_resp {
+        uint16_t code;
+        uint16_t size;
+        uint8_t status;
+    } __attribute__((packed));
+    struct data_write_resp response = {
+        .code = CMD_LE_DATA_WRITE_RSP,
+        .size = 1,
+        .status = 0
+    };
+    struct os_mbuf *om;
+    struct hci_data_hdr hdr;
+    int err;
+
+    if (size >= sizeof(hdr)) {
+        edtt_read((uint8_t *) &hdr, sizeof(hdr), EDTTT_BLOCK);
+        size -= sizeof(hdr);
+        om = ble_hci_trans_acl_buf_alloc();
+
+        if (om) {
+            memcpy(OS_MBUF_USRHDR(om), &hdr, sizeof(hdr));
+            uint16_t hdr_length = hdr.hdh_len;
+
+            if (size >= hdr_length) {
+                edtt_read(om->om_data, hdr_length, EDTTT_BLOCK);
+                size -= hdr_length;
+            }
+
+            err = ble_hci_edtt_rx_acl_cb(om, NULL);
+            if (err) {
+                bs_trace_raw_time(3, "Failed to send ACL Data (err %d)", err);
+            }
+        } else {
+            err = -2; /* Failed to allocate data buffer */
+            bs_trace_raw_time(3, "Failed to create buffer for ACL Data.");
+        }
+    } else {
+        /* Size too small for header (handle and data length) */
+        err = -3;
+    }
+    read_excess_bytes(size);
+
+    response.status = err;
+    edtt_write((uint8_t *) &response, sizeof(response), EDTTT_BLOCK);
+}
+
+static void
+fake_set_public_address()
+{
+    struct ble_hci_ev_command_complete *ev;
+    struct ble_hci_ev *hci_ev;
+    waiting_opcode = BT_HCI_OP_VS_WRITE_BD_ADDR;
+    waiting_response = CMD_WRITE_BD_ADDR_RSP;
+
+    hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+    if (hci_ev) {
+        hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE;
+        hci_ev->length = sizeof(*ev);
+        ev = (void *) hci_ev->data;
+
+        ev->num_packets = 1;
+        ev->opcode = waiting_opcode;
+        ev->status = 0;
+        ble_hci_edtt_cmdevt_tx((uint8_t *) hci_ev, BLE_HCI_EDTT_EVT);
+    }
+}
+
+/* Reads and executes EDTT commands. */
+static void
+edtt_poller(void *arg) {
+    uint16_t command;
+    uint16_t size;
+    uint16_t opcode;
+    uint8_t received_cmd_bytes = 0;
+    os_sr_t sr;
+
+    /* Initialize HCI command opcode and response variables */
+    waiting_opcode = 0;
+    waiting_response = CMD_NOTHING;
+    m_events = 0;
+
+    /* Initialize and start EDTT system */
+    enable_edtt_mode();
+    set_edtt_autoshutdown(true);
+    edtt_start();
+
+#if EDTT_HCI_LOGS
+    log_hci_init();
+#endif
+
+    while (1) {
+        /* Try to receive a command without blocking */
+        received_cmd_bytes = edtt_read((uint8_t *) &command + received_cmd_bytes, sizeof(command) - received_cmd_bytes, EDTTT_NONBLOCK);
+
+        if (received_cmd_bytes < sizeof(command)) {
+            /* No command arrived - try to handle new ble_ll events */
+            service_events();
+
+            OS_ENTER_CRITICAL(sr);
+            /* Limited tick prevents bypassing EDTT timeouts,
+             * when a longer time gap between timers happens */
+            tm_tick_limited(6000);
+            OS_EXIT_CRITICAL(sr);
+            continue;
+        }
+
+        received_cmd_bytes = 0;
+
+        edtt_read((uint8_t *) &size, sizeof(size), EDTTT_BLOCK);
+
+        bs_trace_raw_time(4, "command 0x%04X received (size %u) "
+                             "events=%u\n",
+                          command, size, m_events);
+
+        switch (command) {
+            case CMD_ECHO_REQ:
+                echo(size);
+                break;
+            case CMD_FLUSH_EVENTS_REQ:
+                flush_events(size);
+                break;
+            case CMD_HAS_EVENT_REQ:
+                has_event(size);
+                break;
+            case CMD_GET_EVENT_REQ: {
+                uint8_t multiple;
+
+                edtt_read((uint8_t *) &multiple, sizeof(multiple), EDTTT_BLOCK);
+                if (multiple)
+                    get_events(--size);
+                else
+                    get_event(--size);
+            }
+                break;
+            case CMD_LE_FLUSH_DATA_REQ:
+                le_flush_data(size);
+                break;
+            case CMD_LE_DATA_READY_REQ:
+                le_data_ready(size);
+                break;
+            case CMD_LE_DATA_WRITE_REQ:
+                le_data_write(size);
+                break;
+            case CMD_LE_DATA_READ_REQ:
+                le_data_read(size);
+                break;
+            case CMD_WRITE_BD_ADDR_REQ:
+                edtt_read((uint8_t *) &opcode, sizeof(opcode), EDTTT_BLOCK);
+
+                if (opcode == BT_HCI_OP_VS_WRITE_BD_ADDR) {
+                    fake_set_public_address();
+                    read_excess_bytes(size - 2);
+                }
+                break;
+            default:
+                if (size >= 2) {
+                    edtt_read((uint8_t *) &opcode, sizeof(opcode), EDTTT_BLOCK);
+                    send_hci_cmd_to_ctrl(opcode, size - 2, command + 1);
+                }
+        }
+    }
+}
+
+int
+edtt_init(void)
+{
+    int rc;
+
+    if (!edtt_poller_running) {
+        edtt_poller_running = 1;
+        rc = os_task_init(&edtt_poller_task, "edttpoll", edtt_poller, NULL,
+                          MYNEWT_VAL(EDTT_POLLER_PRIO), OS_WAIT_FOREVER,
+                          edtt_poller_stack, EDTT_POLLER_STACK_SZ);
+        assert(rc == 0);
+    }
+    return 0;
+}
+
+/**
+ * Initializes the EDTT HCI transport module.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+void
+ble_hci_edtt_init(void)
+{
+    int rc;
+
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = os_mempool_ext_init(&ble_hci_edtt_acl_pool,
+                             MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                             ACL_BLOCK_SIZE,
+                             ble_hci_edtt_acl_buf,
+                             "ble_hci_edtt_acl_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mbuf_pool_init(&ble_hci_edtt_acl_mbuf_pool,
+                           &ble_hci_edtt_acl_pool.mpe_mp,
+                           ACL_BLOCK_SIZE,
+                           MYNEWT_VAL(BLE_ACL_BUF_COUNT));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    /*
+     * Create memory pool of HCI command buffers. NOTE: we currently dont
+     * allow this to be configured. The controller will only allow one
+     * outstanding command. We decided to keep this a pool in case we allow
+     * allow the controller to handle more than one outstanding command.
+     */
+    rc = os_mempool_init(&ble_hci_edtt_cmd_pool,
+                         1,
+                         BLE_HCI_TRANS_CMD_SZ,
+                         ble_hci_edtt_cmd_buf,
+                         "ble_hci_edtt_cmd_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_edtt_evt_hi_pool,
+                         MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_edtt_evt_hi_buf,
+                         "ble_hci_edtt_evt_hi_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&ble_hci_edtt_evt_lo_pool,
+                         MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                         ble_hci_edtt_evt_lo_buf,
+                         "ble_hci_edtt_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_edtt_pkt_pool,
+                         BLE_HCI_EDTT_EVT_COUNT + 1 +
+                         MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
+                         sizeof (struct ble_hci_edtt_pkt),
+                         ble_hci_edtt_pkt_buf,
+                         "ble_hci_edtt_pkt_pool");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failure configuring edtt HCI");
+
+    STAILQ_INIT(&data_queue);
+    STAILQ_INIT(&event_queue);
+    STAILQ_INIT(&rx_queue);
+}
diff --git a/babblesim/edtt/hci_transport/src/edtt_driver_bsim.c b/babblesim/edtt/hci_transport/src/edtt_driver_bsim.c
new file mode 100644
index 0000000..0e291ea
--- /dev/null
+++ b/babblesim/edtt/hci_transport/src/edtt_driver_bsim.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2019 Oticon A/S
+ * Copyright (c) 2021 Codecoup
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "bs_tracing.h"
+#include "bs_oswrap.h"
+#include "bs_pc_base_fifo_user.h"
+
+#include <time_machine.h>
+#include "edtt_driver.h"
+
+/* Recheck if something arrived from the EDTT every 5ms */
+#define EDTT_IF_RECHECK_DELTA 5 /* ms */
+
+/* We want the runs to be deterministic => we want to resync with the Phy
+ * before we retry any read so the bridge device may also run
+ */
+#define EDTT_SIMU_RESYNC_TIME_WITH_EDTT \
+	(EDTT_IF_RECHECK_DELTA * 1000 - 1)
+
+static int edtt_mode_enabled = 0;
+
+/* In this mode, when the EDTTool closes the FIFO we automatically terminate
+ * this simulated device. If false, we just continue running
+ */
+static int edtt_autoshutdown;
+
+#define TO_DEVICE  0
+#define TO_BRIDGE 1
+static int fifo[2] = { -1, -1 };
+static char *fifo_path[2] = {NULL, NULL};
+
+extern unsigned int global_device_nbr;
+
+static void edttd_clean_up(void);
+static void edptd_create_fifo_if(void);
+static int fifo_low_level_read(uint8_t *bufptr, int size);
+
+bool edtt_start(void)
+{
+	if (edtt_mode_enabled == false) {
+		/* otherwise we don't try to open the EDTT interface */
+		return true;
+	}
+
+	edptd_create_fifo_if();
+
+	extern void tm_set_phy_max_resync_offset(uint64_t offset_in_us);
+	tm_set_phy_max_resync_offset(EDTT_SIMU_RESYNC_TIME_WITH_EDTT);
+	return true;
+}
+
+bool edtt_stop(void)
+{
+	if (edtt_mode_enabled == false) {
+		/* otherwise we don't try to open the EDTT interface */
+		return true;
+	}
+
+	bs_trace_raw(9, "EDTTT: %s called\n", __func__);
+	edttd_clean_up();
+	edtt_mode_enabled = false;
+	return true;
+}
+
+static void
+print_hex_array(int lvl, uint8_t *buf, int len)
+{
+    char str[2*len];
+    char *p = str;
+    int i;
+    for (i = 0; i < len; i++) {
+        if (i > 0) *p++ = ' ';
+        sprintf(p++, "%02X", buf[i]);
+    }
+    *p = '\n';
+    bs_trace_raw(lvl, str);
+}
+
+/**
+ * Attempt to read size bytes thru the EDTT IF into the buffer <*ptr>
+ * <flags> can be set to EDTTT_BLOCK or EDTTT_NONBLOCK
+ *
+ * If set to EDTTT_BLOCK it will block the calling thread until <size>
+ * bytes have been read or the interface has been closed.
+ * If set to EDTTT_NONBLOCK it returns as soon as there is no more data to be
+ * read
+ *
+ * Returns the amount of read bytes, or -1 on error
+ */
+int edtt_read(uint8_t *ptr, size_t size, int flags)
+{
+    uint8_t *buf = ptr;
+
+	if (edtt_mode_enabled == false) {
+		return -1;
+	}
+
+	bs_trace_raw_time(8, "EDTT: Asked to read %i bytes\n", size);
+	int read = 0;
+
+	while (size > 0) {
+		int received_bytes;
+
+		received_bytes = fifo_low_level_read(ptr, size);
+		if (received_bytes < 0) {
+			return -1;
+		} else if (received_bytes > 0) {
+			size -= received_bytes;
+			ptr += received_bytes;
+			read += received_bytes;
+		} else {
+			if (flags & EDTTT_BLOCK) {
+				bs_trace_raw_time(9, "EDTT: No enough data yet,"
+						"sleeping for %i ms\n",
+						EDTT_IF_RECHECK_DELTA);
+                tm_tick_limited(6000);
+			} else {
+				bs_trace_raw_time(9, "EDTT: No enough data yet,"
+						"returning\n");
+				break;
+			}
+		}
+    }
+
+    if (read > 0) {
+        bs_trace_raw_time(8, "Read %i bytes:\n", read);
+        print_hex_array(8, buf, read);
+    }
+	return read;
+}
+
+/**
+ * Write <size> bytes from <ptr> toward the EDTTool
+ *
+ * <flags> is ignored in this driver, all writes to the tool are
+ * instantaneous
+ */
+int edtt_write(uint8_t *ptr, size_t size, int flags)
+{
+	if (edtt_mode_enabled == false) {
+		return -1;
+	}
+
+	bs_trace_raw_time(6, "EDTT: Asked to write %i bytes: ", size);
+    print_hex_array(6, ptr, size);
+
+	if (write(fifo[TO_BRIDGE], ptr, size) != size) {
+		if (errno == EPIPE) {
+			bs_trace_error_line("EDTT IF suddenly closed by other "
+					    "end\n");
+		}
+		if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+			bs_trace_error_line("EDTT IF to bridge filled up (FIFO "
+					    "size needs to be increased)\n");
+		}
+		bs_trace_error_line("EDTT IF: Unexpected error on write\n");
+	}
+	return size;
+}
+
+/*
+ * Applications may want to enable the EDTT interface only in some
+ * cases. By default it is not enabled in this driver. This function
+ * must be called once before starting it to do so
+ */
+void enable_edtt_mode(void)
+{
+	edtt_mode_enabled = true;
+}
+
+/**
+ * Automatically terminate this device execution once the EDTTool disconnects
+ */
+void set_edtt_autoshutdown(bool Mode)
+{
+	edtt_autoshutdown = Mode;
+}
+
+static void edptd_create_fifo_if(void)
+{
+	int flags;
+
+	bs_trace_raw_time(9, "Bringing EDTT IF up (waiting for other side)\n");
+
+	if (pb_com_path == NULL) {
+		bs_trace_error_line("Not connected to Phy."
+				    "EDTT IF cannot be brough up\n");
+	}
+
+	/* At this point we have connected to the Phy so the COM folder does
+	 * already exist
+	 * also SIGPIPE is already ignored
+	 */
+
+	fifo_path[TO_DEVICE] = (char *)bs_calloc(pb_com_path_length + 30,
+						 sizeof(char));
+	fifo_path[TO_BRIDGE] = (char *)bs_calloc(pb_com_path_length + 30,
+						 sizeof(char));
+	sprintf(fifo_path[TO_DEVICE], "%s/Device%i.PTTin",
+		pb_com_path, global_device_nbr);
+	sprintf(fifo_path[TO_BRIDGE], "%s/Device%i.PTTout",
+		pb_com_path, global_device_nbr);
+
+	if ((pb_create_fifo_if_not_there(fifo_path[TO_DEVICE]) != 0)
+		|| (pb_create_fifo_if_not_there(fifo_path[TO_BRIDGE]) != 0)) {
+		bs_trace_error_line("Couldnt create FIFOs for EDTT IF\n");
+	}
+
+	/* we block here until the bridge opens its end */
+	fifo[TO_BRIDGE] = open(fifo_path[TO_BRIDGE], O_WRONLY);
+	if (fifo[TO_BRIDGE] == -1) {
+		bs_trace_error_line("Couldn't create FIFOs for EDTT IF\n");
+	}
+
+	flags = fcntl(fifo[TO_BRIDGE], F_GETFL);
+	flags |= O_NONBLOCK;
+	fcntl(fifo[TO_BRIDGE], F_SETFL, flags);
+
+	/* we will block here until the bridge opens its end */
+	fifo[TO_DEVICE] = open(fifo_path[TO_DEVICE], O_RDONLY);
+	if (fifo[TO_DEVICE] == -1) {
+		bs_trace_error_line("Couldn't create FIFOs for EDTT IF\n");
+	}
+
+	flags = fcntl(fifo[TO_DEVICE], F_GETFL);
+	flags |= O_NONBLOCK;
+	fcntl(fifo[TO_DEVICE], F_SETFL, flags);
+}
+
+static void edttd_clean_up(void)
+{
+	for (int dir = TO_DEVICE ; dir <= TO_BRIDGE ; dir++) {
+		if (fifo_path[dir]) {
+			if (fifo[dir] != -1) {
+				close(fifo[dir]);
+				remove(fifo_path[dir]);
+				fifo[dir] = -1;
+			}
+			free(fifo_path[dir]);
+			fifo_path[dir] = NULL;
+		}
+	}
+	if (pb_com_path != NULL) {
+		rmdir(pb_com_path);
+	}
+}
+
+static int fifo_low_level_read(uint8_t *bufptr, int size)
+{
+	int received_bytes = read(fifo[TO_DEVICE], bufptr, size);
+
+	if ((received_bytes == -1) && (errno == EAGAIN)) {
+		return 0;
+	} else if (received_bytes == EOF || received_bytes == 0) {
+		/*The FIFO was closed by the bridge*/
+		if (edtt_autoshutdown) {
+			bs_trace_raw_time(3, "EDTT: FIFO closed "
+					"(ptt_autoshutdown==true) =>"
+					" Terminate\n");
+			edttd_clean_up();
+			bs_trace_exit_line("\n");
+		} else {
+			bs_trace_raw_time(3, "EDTT: FIFO closed "
+					"(ptt_autoshutdown==false) => We close "
+					"the FIFOs and move on\n");
+			edttd_clean_up();
+			edtt_mode_enabled = false;
+			return -1;
+		}
+	} else if (received_bytes == -1) {
+		bs_trace_error_line("EDTT: Unexpected error\n");
+	}
+
+	return received_bytes;
+}
diff --git a/babblesim/edtt/hci_transport/syscfg.yml b/babblesim/edtt/hci_transport/syscfg.yml
new file mode 100644
index 0000000..b203361
--- /dev/null
+++ b/babblesim/edtt/hci_transport/syscfg.yml
@@ -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.
+#
+
+syscfg.defs:
+    EDTT_HCI_LOG_FILE:
+        description: >
+            Path to the HCI log file. Skip file extension
+            because device id and .log will be appended.
+        value: "hci_logs"
+    EDTT_HCI_LOGS:
+        description: Turn on HCI commands logging.
+        value: 0
+    EDTT_POLLER_PRIO:
+        description: 'Priority of native EDTT poller task.'
+        type: task_priority
+        value: 2
+
+    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
+
+syscfg.vals:
+    BLE_ACL_BUF_COUNT: 32
+    BLE_ACL_BUF_SIZE: 255
+    BLE_HCI_EVT_BUF_SIZE: 257
+    BLE_HCI_EVT_HI_BUF_COUNT: 32
+    BLE_HCI_EVT_LO_BUF_COUNT: 32
diff --git a/babblesim/hw/bsp/nrf52_bsim/syscfg.yml b/babblesim/hw/bsp/nrf52_bsim/syscfg.yml
index 2070c69..8558c5d 100644
--- a/babblesim/hw/bsp/nrf52_bsim/syscfg.yml
+++ b/babblesim/hw/bsp/nrf52_bsim/syscfg.yml
@@ -37,7 +37,7 @@ syscfg.vals:
     OS_MAIN_STACK_SIZE: 8000
     MCU_TIMER_POLLER_PRIO: 0
     BLE_LL_PRIO: 1
-    MCU_UART_POLLER_PRIO: 2
+    MCU_UART_POLLER_PRIO: 9
 
     # Enable nRF52832 MCU
     MCU_TARGET: nRF52832
diff --git a/babblesim/targets/edtthci/pkg.yml b/babblesim/targets/edtthci/pkg.yml
new file mode 100644
index 0000000..a08f47b
--- /dev/null
+++ b/babblesim/targets/edtthci/pkg.yml
@@ -0,0 +1,24 @@
+#
+# 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: babblesim/targets/edtthci
+pkg.type: target
+pkg.description:
+pkg.author:
+pkg.homepage:
diff --git a/babblesim/targets/edtthci/syscfg.yml b/babblesim/targets/edtthci/syscfg.yml
new file mode 100644
index 0000000..972659e
--- /dev/null
+++ b/babblesim/targets/edtthci/syscfg.yml
@@ -0,0 +1,55 @@
+#
+# 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.vals:
+  # EDTT requires 0x123456789ABC address for the first device
+  # and 0x456789ABCDEF for the second one
+  BLE_LL_PUBLIC_DEV_ADDR: 0x123456789ABC  # d=1
+  # BLE_LL_PUBLIC_DEV_ADDR: 0x456789ABCDEF # d=2
+
+  EDTT_HCI_LOG_FILE: ("hci_logs")
+  EDTT_HCI_LOGS: 1
+
+  BLE_LL_CFG_FEAT_LE_ENCRYPTION: 1
+  BLE_LL_CFG_FEAT_CONN_PARAM_REQ: 1
+  BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG: 1
+  BLE_LL_CFG_FEAT_LE_PING: 1
+  BLE_LL_CFG_FEAT_DATA_LEN_EXT: 1
+  BLE_LL_CFG_FEAT_LL_PRIVACY: 1
+  BLE_LL_CFG_FEAT_LE_CSA2: 1
+  BLE_LL_CFG_FEAT_LE_2M_PHY: 1
+#  BLE_LL_CFG_FEAT_LE_CODED_PHY: 1  # not modeled in bsim
+  BLE_LL_CFG_FEAT_LL_EXT_ADV: 1
+  BLE_LL_CFG_FEAT_LL_PERIODIC_ADV: 1
+  BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER: 1
+  BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL: 1
+  BLE_LL_CFG_FEAT_LL_SCA_UPDATE: 1
+
+  BLE_ROLE_CENTRAL: 1
+  BLE_ROLE_PERIPHERAL: 1
+  BLE_ROLE_BROADCASTER: 1
+  BLE_ROLE_OBSERVER: 1
+
+  BLE_VERSION: 52
+  BLE_CONTROLLER: 1
+  BLE_LL_ROLE_CENTRAL: 1
+  BLE_LL_ROLE_PERIPHERAL: 1
+  BLE_LL_ROLE_BROADCASTER: 1
+  BLE_LL_ROLE_OBSERVER: 1
+  BLE_HW_WHITELIST_ENABLE: 1
diff --git a/babblesim/targets/edtthci/target.yml b/babblesim/targets/edtthci/target.yml
new file mode 100644
index 0000000..3990ba4
--- /dev/null
+++ b/babblesim/targets/edtthci/target.yml
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+target.app: "@apache-mynewt-nimble/babblesim/edtt/hci_test"
+target.bsp: "@apache-mynewt-nimble/babblesim/hw/bsp/nrf52_bsim"
+target.build_profile: debug