2019-06-25 09:03:58 +08:00
|
|
|
/*
|
2023-06-30 12:40:44 +05:30
|
|
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
2019-06-25 09:03:58 +08:00
|
|
|
*
|
2021-12-06 14:59:55 +08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2019-06-25 09:03:58 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include "sysinit/sysinit.h"
|
|
|
|
#include "nimble/hci_common.h"
|
2022-06-03 21:57:44 +08:00
|
|
|
#if CONFIG_BT_NIMBLE_ENABLED
|
2019-06-25 09:03:58 +08:00
|
|
|
#include "host/ble_hs.h"
|
2022-06-03 21:57:44 +08:00
|
|
|
#endif //CONFIG_BT_NIMBLE_ENABLED
|
2019-06-25 09:03:58 +08:00
|
|
|
#include "nimble/nimble_port.h"
|
|
|
|
#include "nimble/nimble_port_freertos.h"
|
|
|
|
#include "esp_nimble_hci.h"
|
2020-01-23 00:55:51 +08:00
|
|
|
#include "esp_nimble_mem.h"
|
2022-06-17 21:32:27 +08:00
|
|
|
#include "bt_osi_mem.h"
|
2019-06-25 09:03:58 +08:00
|
|
|
#include "esp_bt.h"
|
2019-12-01 15:22:51 +08:00
|
|
|
#include "freertos/semphr.h"
|
2019-10-15 18:01:05 -03:00
|
|
|
#include "esp_compiler.h"
|
2021-12-06 15:08:11 +05:30
|
|
|
#include "soc/soc_caps.h"
|
|
|
|
|
2019-12-01 15:22:51 +08:00
|
|
|
#define NIMBLE_VHCI_TIMEOUT_MS 2000
|
2020-08-03 23:49:41 +05:30
|
|
|
#define BLE_HCI_EVENT_HDR_LEN (2)
|
|
|
|
#define BLE_HCI_CMD_HDR_LEN (3)
|
2019-06-25 09:03:58 +08:00
|
|
|
|
|
|
|
static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb;
|
|
|
|
static void *ble_hci_rx_cmd_hs_arg;
|
|
|
|
|
|
|
|
static ble_hci_trans_rx_acl_fn *ble_hci_rx_acl_hs_cb;
|
|
|
|
static void *ble_hci_rx_acl_hs_arg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2023-01-10 12:24:03 +05:30
|
|
|
#define ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) \
|
2019-06-25 09:03:58 +08:00
|
|
|
+ BLE_MBUF_MEMBLOCK_OVERHEAD \
|
|
|
|
+ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-12-01 15:22:51 +08:00
|
|
|
static SemaphoreHandle_t vhci_send_sem;
|
2019-10-10 17:20:15 +08:00
|
|
|
const static char *TAG = "NimBLE";
|
|
|
|
|
2020-01-23 00:55:51 +08:00
|
|
|
int os_msys_buf_alloc(void);
|
|
|
|
void os_msys_buf_free(void);
|
2023-06-30 12:40:44 +05:30
|
|
|
extern uint8_t ble_hs_enabled_state;
|
2020-01-23 00:55:51 +08:00
|
|
|
|
2019-06-25 09:03:58 +08:00
|
|
|
void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
|
2023-01-10 12:24:03 +05:30
|
|
|
void *cmd_arg,
|
|
|
|
ble_hci_trans_rx_acl_fn *acl_cb,
|
|
|
|
void *acl_arg)
|
2019-06-25 09:03:58 +08:00
|
|
|
{
|
|
|
|
ble_hci_rx_cmd_hs_cb = cmd_cb;
|
|
|
|
ble_hci_rx_cmd_hs_arg = cmd_arg;
|
|
|
|
ble_hci_rx_acl_hs_cb = acl_cb;
|
|
|
|
ble_hci_rx_acl_hs_arg = acl_arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
|
|
|
|
{
|
|
|
|
uint16_t len;
|
2019-12-01 15:22:51 +08:00
|
|
|
uint8_t rc = 0;
|
2019-06-25 09:03:58 +08:00
|
|
|
|
|
|
|
assert(cmd != NULL);
|
|
|
|
*cmd = BLE_HCI_UART_H4_CMD;
|
|
|
|
len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1;
|
2019-10-10 17:20:15 +08:00
|
|
|
if (!esp_vhci_host_check_send_available()) {
|
2019-12-01 15:22:51 +08:00
|
|
|
ESP_LOGD(TAG, "Controller not ready to receive packets");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
|
|
|
|
esp_vhci_host_send_packet(cmd, len);
|
|
|
|
} else {
|
|
|
|
rc = BLE_HS_ETIMEOUT_HCI;
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
ble_transport_free(cmd);
|
2019-12-01 15:22:51 +08:00
|
|
|
return rc;
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
|
|
|
|
{
|
|
|
|
int rc = ESP_FAIL;
|
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
rc = ble_transport_to_hs_evt((void *)hci_ev);
|
2019-06-25 09:03:58 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
|
|
|
|
{
|
|
|
|
uint16_t len = 0;
|
2023-01-10 12:24:03 +05:30
|
|
|
uint8_t data[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 1], rc = 0;
|
2019-06-25 09:03:58 +08:00
|
|
|
/* If this packet is zero length, just free it */
|
|
|
|
if (OS_MBUF_PKTLEN(om) == 0) {
|
|
|
|
os_mbuf_free_chain(om);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
data[0] = BLE_HCI_UART_H4_ACL;
|
|
|
|
len++;
|
|
|
|
|
2019-10-10 17:20:15 +08:00
|
|
|
if (!esp_vhci_host_check_send_available()) {
|
2019-12-01 15:22:51 +08:00
|
|
|
ESP_LOGD(TAG, "Controller not ready to receive packets");
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]);
|
|
|
|
len += OS_MBUF_PKTLEN(om);
|
|
|
|
|
2019-12-01 15:22:51 +08:00
|
|
|
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
|
|
|
|
esp_vhci_host_send_packet(data, len);
|
|
|
|
} else {
|
|
|
|
rc = BLE_HS_ETIMEOUT_HCI;
|
|
|
|
}
|
2019-06-25 09:03:58 +08:00
|
|
|
|
|
|
|
os_mbuf_free_chain(om);
|
|
|
|
|
2019-12-01 15:22:51 +08:00
|
|
|
return rc;
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
|
|
|
|
{
|
|
|
|
int rc = ESP_FAIL;
|
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
rc = ble_transport_to_hs_acl((void *)om);
|
2019-06-25 09:03:58 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ble_hci_trans_reset(void)
|
|
|
|
{
|
|
|
|
/* No work to do. All allocated buffers are owned by the host or
|
|
|
|
* controller, and they will get freed by their owners.
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
|
|
|
|
{
|
2023-03-03 13:55:49 +05:30
|
|
|
struct os_mbuf *m = NULL;
|
2021-03-09 14:56:46 +05:30
|
|
|
int rc;
|
2019-06-25 09:03:58 +08:00
|
|
|
int sr;
|
2023-01-10 12:24:03 +05:30
|
|
|
if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE)) {
|
2019-06-25 09:03:58 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-03 13:55:49 +05:30
|
|
|
do {
|
2023-02-27 11:18:57 +05:30
|
|
|
m = ble_transport_alloc_acl_from_ll();
|
2023-03-03 13:55:49 +05:30
|
|
|
|
|
|
|
if (!m) {
|
2023-06-09 02:56:11 +08:00
|
|
|
ESP_LOGD(TAG,"Failed to allocate buffer, retrying ");
|
2023-03-03 13:55:49 +05:30
|
|
|
/* Give some time to free buffer and try again */
|
|
|
|
vTaskDelay(1);
|
|
|
|
}
|
|
|
|
}while(!m);
|
2019-06-25 09:03:58 +08:00
|
|
|
|
2021-03-09 14:56:46 +05:30
|
|
|
if ((rc = os_mbuf_append(m, data, len)) != 0) {
|
|
|
|
ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc);
|
2019-06-25 09:03:58 +08:00
|
|
|
os_mbuf_free_chain(m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
OS_ENTER_CRITICAL(sr);
|
2023-01-10 12:24:03 +05:30
|
|
|
ble_transport_to_hs_acl(m);
|
2019-06-25 09:03:58 +08:00
|
|
|
OS_EXIT_CRITICAL(sr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief: BT controller callback function, used to notify the upper layer that
|
|
|
|
* controller is ready to receive command
|
|
|
|
*/
|
|
|
|
static void controller_rcv_pkt_ready(void)
|
|
|
|
{
|
2019-12-01 15:22:51 +08:00
|
|
|
if (vhci_send_sem) {
|
|
|
|
xSemaphoreGive(vhci_send_sem);
|
|
|
|
}
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief: BT controller callback function, to transfer data packet to the host
|
|
|
|
*/
|
|
|
|
static int host_rcv_pkt(uint8_t *data, uint16_t len)
|
|
|
|
{
|
2023-06-30 12:40:44 +05:30
|
|
|
if(!ble_hs_enabled_state) {
|
|
|
|
/* If host is not enabled, drop the packet */
|
|
|
|
ESP_LOGE(TAG, "Host not enabled. Dropping the packet!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-25 09:03:58 +08:00
|
|
|
if (data[0] == BLE_HCI_UART_H4_EVT) {
|
|
|
|
uint8_t *evbuf;
|
|
|
|
int totlen;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
totlen = BLE_HCI_EVENT_HDR_LEN + data[2];
|
|
|
|
assert(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
|
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
if (totlen > MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)) {
|
2020-08-20 14:42:46 +05:30
|
|
|
ESP_LOGE(TAG, "Received HCI data length at host (%d) exceeds maximum configured HCI event buffer size (%d).",
|
2023-01-10 12:24:03 +05:30
|
|
|
totlen, MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE));
|
2020-08-20 14:42:46 +05:30
|
|
|
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-25 09:03:58 +08:00
|
|
|
if (data[1] == BLE_HCI_EVCODE_HW_ERROR) {
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate LE Advertising Report Event from lo pool only */
|
2022-10-19 14:10:42 +05:30
|
|
|
if ((data[1] == BLE_HCI_EVCODE_LE_META) &&
|
2023-01-10 12:24:03 +05:30
|
|
|
(data[3] == BLE_HCI_LE_SUBEV_ADV_RPT || data[3] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
|
|
|
|
evbuf = ble_transport_alloc_evt(1);
|
2019-06-25 09:03:58 +08:00
|
|
|
/* Skip advertising report if we're out of memory */
|
|
|
|
if (!evbuf) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
2023-01-10 12:24:03 +05:30
|
|
|
evbuf = ble_transport_alloc_evt(0);
|
2019-06-25 09:03:58 +08:00
|
|
|
assert(evbuf != NULL);
|
|
|
|
}
|
|
|
|
|
2023-04-18 15:01:09 +05:30
|
|
|
memset(evbuf, 0, sizeof *evbuf);
|
2019-06-25 09:03:58 +08:00
|
|
|
memcpy(evbuf, &data[1], totlen);
|
|
|
|
|
|
|
|
rc = ble_hci_trans_ll_evt_tx(evbuf);
|
|
|
|
assert(rc == 0);
|
|
|
|
} else if (data[0] == BLE_HCI_UART_H4_ACL) {
|
|
|
|
ble_hci_rx_acl(data + 1, len - 1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-12-01 15:22:51 +08:00
|
|
|
static const esp_vhci_host_callback_t vhci_host_cb = {
|
|
|
|
.notify_host_send_available = controller_rcv_pkt_ready,
|
|
|
|
.notify_host_recv = host_rcv_pkt,
|
2019-06-25 09:03:58 +08:00
|
|
|
};
|
|
|
|
|
2020-01-23 00:55:51 +08:00
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
extern void ble_transport_init(void);
|
2023-02-09 11:43:22 +05:30
|
|
|
extern esp_err_t ble_buf_alloc(void);
|
|
|
|
extern void ble_buf_free(void);
|
2019-06-25 09:03:58 +08:00
|
|
|
esp_err_t esp_nimble_hci_init(void)
|
|
|
|
{
|
|
|
|
esp_err_t ret;
|
2020-01-23 00:55:51 +08:00
|
|
|
|
|
|
|
ret = ble_buf_alloc();
|
|
|
|
if (ret != ESP_OK) {
|
|
|
|
goto err;
|
|
|
|
}
|
2019-06-25 09:03:58 +08:00
|
|
|
if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) {
|
2020-01-23 00:55:51 +08:00
|
|
|
goto err;
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
ble_transport_init();
|
2019-06-25 09:03:58 +08:00
|
|
|
|
2019-12-01 15:22:51 +08:00
|
|
|
vhci_send_sem = xSemaphoreCreateBinary();
|
|
|
|
if (vhci_send_sem == NULL) {
|
2020-01-23 00:55:51 +08:00
|
|
|
ret = ESP_ERR_NO_MEM;
|
|
|
|
goto err;
|
2019-12-01 15:22:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
xSemaphoreGive(vhci_send_sem);
|
|
|
|
|
2020-01-23 00:55:51 +08:00
|
|
|
return ret;
|
|
|
|
err:
|
|
|
|
ble_buf_free();
|
|
|
|
return ret;
|
|
|
|
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|
|
|
|
|
2023-01-10 12:24:03 +05:30
|
|
|
extern void ble_transport_deinit(void);
|
2019-06-25 09:03:58 +08:00
|
|
|
esp_err_t esp_nimble_hci_deinit(void)
|
|
|
|
{
|
2019-12-01 15:22:51 +08:00
|
|
|
if (vhci_send_sem) {
|
|
|
|
/* Dummy take & give semaphore before deleting */
|
|
|
|
xSemaphoreTake(vhci_send_sem, portMAX_DELAY);
|
|
|
|
xSemaphoreGive(vhci_send_sem);
|
|
|
|
vSemaphoreDelete(vhci_send_sem);
|
|
|
|
vhci_send_sem = NULL;
|
|
|
|
}
|
2023-01-10 12:24:03 +05:30
|
|
|
ble_transport_deinit();
|
2020-01-23 00:55:51 +08:00
|
|
|
|
|
|
|
ble_buf_free();
|
|
|
|
|
|
|
|
return ESP_OK;
|
2019-06-25 09:03:58 +08:00
|
|
|
}
|