|
| 1 | +/* |
| 2 | + * Copyright (c) 2024 Silicon Laboratories Inc. |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + */ |
| 5 | + |
| 6 | +#include <zephyr/kernel.h> |
| 7 | +#include <zephyr/drivers/bluetooth.h> |
| 8 | + |
| 9 | +#define DT_DRV_COMPAT silabs_siwx91x_bt_hci |
| 10 | +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL |
| 11 | +#include <zephyr/logging/log.h> |
| 12 | +LOG_MODULE_REGISTER(bt_hci_driver_siwg917); |
| 13 | + |
| 14 | +#include "rsi_ble.h" |
| 15 | + |
| 16 | +static void siwx91x_bt_resp_rcvd(uint16_t status, rsi_ble_event_rcp_rcvd_info_t *resp_buf); |
| 17 | + |
| 18 | +struct hci_data { |
| 19 | + bt_hci_recv_t recv; |
| 20 | + rsi_data_packet_t rsi_data_packet; |
| 21 | +}; |
| 22 | + |
| 23 | +static int siwx91x_bt_open(const struct device *dev, bt_hci_recv_t recv) |
| 24 | +{ |
| 25 | + struct hci_data *hci = dev->data; |
| 26 | + int status = rsi_ble_enhanced_gap_extended_register_callbacks(RSI_BLE_ON_RCP_EVENT, |
| 27 | + (void *)siwx91x_bt_resp_rcvd); |
| 28 | + |
| 29 | + if (!status) { |
| 30 | + hci->recv = recv; |
| 31 | + } |
| 32 | + return status ? -EIO : 0; |
| 33 | +} |
| 34 | + |
| 35 | +static int siwx91x_bt_send(const struct device *dev, struct net_buf *buf) |
| 36 | +{ |
| 37 | + struct hci_data *hci = dev->data; |
| 38 | + int sc = -EOVERFLOW; |
| 39 | + uint8_t packet_type = BT_HCI_H4_NONE; |
| 40 | + |
| 41 | + switch (bt_buf_get_type(buf)) { |
| 42 | + case BT_BUF_ACL_OUT: |
| 43 | + packet_type = BT_HCI_H4_ACL; |
| 44 | + break; |
| 45 | + case BT_BUF_CMD: |
| 46 | + packet_type = BT_HCI_H4_CMD; |
| 47 | + break; |
| 48 | + default: |
| 49 | + sc = -EINVAL; |
| 50 | + break; |
| 51 | + } |
| 52 | + |
| 53 | + if ((packet_type != BT_HCI_H4_NONE) && (buf->len < sizeof(hci->rsi_data_packet.data))) { |
| 54 | + net_buf_push_u8(buf, packet_type); |
| 55 | + memcpy(&hci->rsi_data_packet, buf->data, buf->len); |
| 56 | + sc = rsi_bt_driver_send_cmd(RSI_BLE_REQ_HCI_RAW, &hci->rsi_data_packet, NULL); |
| 57 | + /* TODO SILABS ZEPHYR Convert to errno. A common function from rsi/sl_status should |
| 58 | + * be introduced |
| 59 | + */ |
| 60 | + if (sc) { |
| 61 | + LOG_ERR("BT command send failure: %d", sc); |
| 62 | + sc = -EIO; |
| 63 | + } |
| 64 | + } |
| 65 | + net_buf_unref(buf); |
| 66 | + return sc; |
| 67 | +} |
| 68 | + |
| 69 | +static void siwx91x_bt_resp_rcvd(uint16_t status, rsi_ble_event_rcp_rcvd_info_t *resp_buf) |
| 70 | +{ |
| 71 | + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); |
| 72 | + struct hci_data *hci = dev->data; |
| 73 | + uint8_t packet_type = BT_HCI_H4_NONE; |
| 74 | + size_t len = 0; |
| 75 | + struct net_buf *buf = NULL; |
| 76 | + |
| 77 | + /* TODO SILABS ZEPHYR This horror expression is from the WiseConnect from the HCI example... |
| 78 | + * No workaround have been found until now. |
| 79 | + */ |
| 80 | + memcpy(&packet_type, (resp_buf->data - 12), 1); |
| 81 | + switch (packet_type) { |
| 82 | + case BT_HCI_H4_EVT: { |
| 83 | + struct bt_hci_evt_hdr *hdr = (void *)resp_buf->data; |
| 84 | + |
| 85 | + len = hdr->len + sizeof(*hdr); |
| 86 | + buf = bt_buf_get_evt(hdr->evt, false, K_FOREVER); |
| 87 | + break; |
| 88 | + } |
| 89 | + case BT_HCI_H4_ACL: { |
| 90 | + struct bt_hci_acl_hdr *hdr = (void *)resp_buf->data; |
| 91 | + |
| 92 | + len = hdr->len + sizeof(*hdr); |
| 93 | + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); |
| 94 | + break; |
| 95 | + } |
| 96 | + default: |
| 97 | + LOG_ERR("Unknown/Unhandled HCI type: %d", packet_type); |
| 98 | + break; |
| 99 | + } |
| 100 | + |
| 101 | + if (buf && (len <= net_buf_tailroom(buf))) { |
| 102 | + net_buf_add_mem(buf, resp_buf->data, len); |
| 103 | + hci->recv(dev, buf); |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +static DEVICE_API(bt_hci, siwx91x_api) = { |
| 108 | + .open = siwx91x_bt_open, |
| 109 | + .send = siwx91x_bt_send, |
| 110 | +}; |
| 111 | + |
| 112 | +#define HCI_DEVICE_INIT(inst) \ |
| 113 | + static struct hci_data hci_data_##inst; \ |
| 114 | + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &hci_data_##inst, NULL, POST_KERNEL, \ |
| 115 | + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &siwx91x_api) |
| 116 | + |
| 117 | +/* Only one instance supported right now */ |
| 118 | +HCI_DEVICE_INIT(0) |
0 commit comments