Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.9 KiB

/*
* Copyright (c) 2024 Silicon Laboratories Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/bluetooth.h>
#define DT_DRV_COMPAT silabs_siwx91x_bt_hci
#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_hci_driver_siwg917);
#include "rsi_ble.h"
static void siwx91x_bt_resp_rcvd(uint16_t status, rsi_ble_event_rcp_rcvd_info_t *resp_buf);
struct hci_data {
bt_hci_recv_t recv;
rsi_data_packet_t rsi_data_packet;
};
static int siwx91x_bt_open(const struct device *dev, bt_hci_recv_t recv)
{
struct hci_data *hci = dev->data;
int status = rsi_ble_enhanced_gap_extended_register_callbacks(RSI_BLE_ON_RCP_EVENT,
(void *)siwx91x_bt_resp_rcvd);
if (!status) {
hci->recv = recv;
}
return status ? -EIO : 0;
}
static int siwx91x_bt_send(const struct device *dev, struct net_buf *buf)
{
struct hci_data *hci = dev->data;
int sc = -EOVERFLOW;
if (buf->len < sizeof(hci->rsi_data_packet.data)) {
memcpy(&hci->rsi_data_packet, buf->data, buf->len);
sc = rsi_bt_driver_send_cmd(RSI_BLE_REQ_HCI_RAW, &hci->rsi_data_packet, NULL);
/* TODO SILABS ZEPHYR Convert to errno. A common function from rsi/sl_status should
* be introduced
*/
if (sc) {
LOG_ERR("BT command send failure: %d", sc);
sc = -EIO;
}
}
net_buf_unref(buf);
return sc;
}
static void siwx91x_bt_resp_rcvd(uint16_t status, rsi_ble_event_rcp_rcvd_info_t *resp_buf)
{
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
struct hci_data *hci = dev->data;
uint8_t packet_type = BT_HCI_H4_NONE;
size_t len = 0;
struct net_buf *buf = NULL;
/* TODO SILABS ZEPHYR This horror expression is from the WiseConnect from the HCI example...
* No workaround have been found until now.
*/
memcpy(&packet_type, (resp_buf->data - 12), 1);
switch (packet_type) {
case BT_HCI_H4_EVT: {
struct bt_hci_evt_hdr *hdr = (void *)resp_buf->data;
len = hdr->len + sizeof(*hdr);
buf = bt_buf_get_evt(hdr->evt, false, K_FOREVER);
break;
}
case BT_HCI_H4_ACL: {
struct bt_hci_acl_hdr *hdr = (void *)resp_buf->data;
len = hdr->len + sizeof(*hdr);
buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
break;
}
default:
LOG_ERR("Unknown/Unhandled HCI type: %d", packet_type);
break;
}
if (buf && (len <= net_buf_tailroom(buf))) {
net_buf_add_mem(buf, resp_buf->data, len);
hci->recv(dev, buf);
}
}
static DEVICE_API(bt_hci, siwx91x_api) = {
.open = siwx91x_bt_open,
.send = siwx91x_bt_send,
};
#define HCI_DEVICE_INIT(inst) \
static struct hci_data hci_data_##inst; \
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &hci_data_##inst, NULL, POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &siwx91x_api)
/* Only one instance supported right now */
HCI_DEVICE_INIT(0)