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