|
| 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_bt_hci_siwx917 |
| 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 "sl_wifi.h" |
| 15 | +#include "sl_wifi_callback_framework.h" |
| 16 | +#include "rsi_ble_common_config.h" |
| 17 | +#include "rsi_ble.h" |
| 18 | + |
| 19 | +static void bt_siwg917_resp_rcvd(uint16_t status, rsi_ble_event_rcp_rcvd_info_t *resp_buf); |
| 20 | + |
| 21 | +struct hci_data { |
| 22 | + bt_hci_recv_t recv; |
| 23 | + rsi_data_packet_t rsi_data_packet; |
| 24 | +}; |
| 25 | + |
| 26 | +static const sl_wifi_device_configuration_t network_config = { |
| 27 | + .boot_option = LOAD_NWP_FW, |
| 28 | + .mac_address = NULL, |
| 29 | + .band = SL_SI91X_WIFI_BAND_2_4GHZ, |
| 30 | + .region_code = DEFAULT_REGION, |
| 31 | + .boot_config = { |
| 32 | + .oper_mode = SL_SI91X_CLIENT_MODE, |
| 33 | + .coex_mode = SL_SI91X_BLE_MODE, |
| 34 | + .feature_bit_map = |
| 35 | + SL_SI91X_FEAT_SECURITY_OPEN | |
| 36 | + SL_SI91X_FEAT_WPS_DISABLE, |
| 37 | + .tcp_ip_feature_bit_map = |
| 38 | + SL_SI91X_TCP_IP_FEAT_DHCPV4_CLIENT | |
| 39 | + SL_SI91X_TCP_IP_FEAT_EXTENSION_VALID, |
| 40 | + .ext_tcp_ip_feature_bit_map = SL_SI91X_CONFIG_FEAT_EXTENSION_VALID, |
| 41 | + .custom_feature_bit_map = SL_SI91X_CUSTOM_FEAT_EXTENSION_VALID, |
| 42 | + .ext_custom_feature_bit_map = |
| 43 | + MEMORY_CONFIG | |
| 44 | + SL_SI91X_EXT_FEAT_XTAL_CLK | |
| 45 | + SL_SI91X_EXT_FEAT_FRONT_END_SWITCH_PINS_ULP_GPIO_4_5_0 | |
| 46 | + SL_SI91X_EXT_FEAT_BT_CUSTOM_FEAT_ENABLE, |
| 47 | + .config_feature_bit_map = SL_SI91X_ENABLE_ENHANCED_MAX_PSP, |
| 48 | + .bt_feature_bit_map = |
| 49 | + SL_SI91X_BT_RF_TYPE | |
| 50 | + SL_SI91X_ENABLE_BLE_PROTOCOL, |
| 51 | + .ble_feature_bit_map = |
| 52 | + SL_SI91X_BLE_MAX_NBR_PERIPHERALS(RSI_BLE_MAX_NBR_PERIPHERALS) | |
| 53 | + SL_SI91X_BLE_MAX_NBR_CENTRALS(RSI_BLE_MAX_NBR_CENTRALS) | |
| 54 | + SL_SI91X_BLE_MAX_NBR_ATT_SERV(RSI_BLE_MAX_NBR_ATT_SERV) | |
| 55 | + SL_SI91X_BLE_MAX_NBR_ATT_REC(RSI_BLE_MAX_NBR_ATT_REC) | |
| 56 | + SL_SI91X_BLE_PWR_INX(RSI_BLE_PWR_INX) | |
| 57 | + SL_SI91X_BLE_PWR_SAVE_OPTIONS(RSI_BLE_PWR_SAVE_OPTIONS) | |
| 58 | + SL_SI91X_916_BLE_COMPATIBLE_FEAT_ENABLE | |
| 59 | + SL_SI91X_FEAT_BLE_CUSTOM_FEAT_EXTENSION_VALID, |
| 60 | + .ble_ext_feature_bit_map = |
| 61 | + SL_SI91X_BLE_NUM_CONN_EVENTS(RSI_BLE_NUM_CONN_EVENTS) | |
| 62 | + SL_SI91X_BLE_NUM_REC_BYTES(RSI_BLE_NUM_REC_BYTES) | |
| 63 | + SL_SI91X_BLE_ENABLE_ADV_EXTN | |
| 64 | + SL_SI91X_BLE_AE_MAX_ADV_SETS(RSI_BLE_AE_MAX_ADV_SETS), |
| 65 | + }}; |
| 66 | + |
| 67 | +static int bt_siwg917_open(const struct device *dev, bt_hci_recv_t recv) |
| 68 | +{ |
| 69 | + struct hci_data *hci = dev->data; |
| 70 | + |
| 71 | + int status = sl_wifi_init(&network_config, NULL, sl_wifi_default_event_handler); |
| 72 | + status |= rsi_ble_enhanced_gap_extended_register_callbacks(RSI_BLE_ON_RCP_EVENT, |
| 73 | + (void *)bt_siwg917_resp_rcvd); |
| 74 | + |
| 75 | + if (!status) { |
| 76 | + hci->recv = recv; |
| 77 | + } |
| 78 | + return status ? -EIO : 0; |
| 79 | +} |
| 80 | + |
| 81 | +static int bt_siwg917_send(const struct device *dev, struct net_buf *buf) |
| 82 | +{ |
| 83 | + struct hci_data *hci = dev->data; |
| 84 | + int sc = -EOVERFLOW; |
| 85 | + uint8_t packet_type = BT_HCI_H4_NONE; |
| 86 | + |
| 87 | + switch (bt_buf_get_type(buf)) { |
| 88 | + case BT_BUF_ACL_OUT: |
| 89 | + packet_type = BT_HCI_H4_ACL; |
| 90 | + break; |
| 91 | + case BT_BUF_CMD: |
| 92 | + packet_type = BT_HCI_H4_CMD; |
| 93 | + break; |
| 94 | + default: |
| 95 | + sc = -EINVAL; |
| 96 | + break; |
| 97 | + } |
| 98 | + |
| 99 | + if ((packet_type != BT_HCI_H4_NONE) && (buf->len < sizeof(hci->rsi_data_packet.data))) { |
| 100 | + net_buf_push_u8(buf, packet_type); |
| 101 | + memcpy(&hci->rsi_data_packet, buf->data, buf->len); |
| 102 | + sc = rsi_bt_driver_send_cmd(RSI_BLE_REQ_HCI_RAW, &hci->rsi_data_packet, NULL); |
| 103 | + /* TODO SILABS ZEPHYR Convert to errno. A common function from rsi/sl_status should |
| 104 | + * be introduced |
| 105 | + */ |
| 106 | + if (sc) { |
| 107 | + LOG_ERR("BT command send failure: %d", sc); |
| 108 | + sc = -EIO; |
| 109 | + } |
| 110 | + } |
| 111 | + net_buf_unref(buf); |
| 112 | + return sc; |
| 113 | +} |
| 114 | + |
| 115 | +static void bt_siwg917_resp_rcvd(uint16_t status, rsi_ble_event_rcp_rcvd_info_t *resp_buf) |
| 116 | +{ |
| 117 | + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); |
| 118 | + struct hci_data *hci = dev->data; |
| 119 | + uint8_t packet_type = BT_HCI_H4_NONE; |
| 120 | + size_t len = 0; |
| 121 | + struct net_buf *buf = NULL; |
| 122 | + |
| 123 | + /* TODO SILABS ZEPHYR This horror expression is from the WiseConnect from the HCI example... |
| 124 | + * No workaround have been found until now. |
| 125 | + */ |
| 126 | + memcpy(&packet_type, (resp_buf->data - 12), 1); |
| 127 | + switch (packet_type) { |
| 128 | + case BT_HCI_H4_EVT: { |
| 129 | + struct bt_hci_evt_hdr *hdr = (void *)resp_buf->data; |
| 130 | + |
| 131 | + len = hdr->len + sizeof(*hdr); |
| 132 | + buf = bt_buf_get_evt(hdr->evt, false, K_FOREVER); |
| 133 | + break; |
| 134 | + } |
| 135 | + case BT_HCI_H4_ACL: { |
| 136 | + struct bt_hci_acl_hdr *hdr = (void *)resp_buf->data; |
| 137 | + |
| 138 | + len = hdr->len + sizeof(*hdr); |
| 139 | + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER); |
| 140 | + break; |
| 141 | + } |
| 142 | + default: |
| 143 | + LOG_ERR("Unknown/Unhandled HCI type: %d", packet_type); |
| 144 | + break; |
| 145 | + } |
| 146 | + |
| 147 | + if (buf && (len <= net_buf_tailroom(buf))) { |
| 148 | + net_buf_add_mem(buf, resp_buf->data, len); |
| 149 | + hci->recv(dev, buf); |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +static const struct bt_hci_driver_api drv = { |
| 154 | + .open = bt_siwg917_open, |
| 155 | + .send = bt_siwg917_send, |
| 156 | +}; |
| 157 | + |
| 158 | +#define HCI_DEVICE_INIT(inst) \ |
| 159 | + static struct hci_data hci_data_##inst; \ |
| 160 | + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &hci_data_##inst, NULL, POST_KERNEL, \ |
| 161 | + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) |
| 162 | + |
| 163 | +/* Only one instance supported right now */ |
| 164 | +HCI_DEVICE_INIT(0) |
| 165 | + |
| 166 | +/* IRQn 74 is used for communication with co-processor */ |
| 167 | +Z_ISR_DECLARE(74, ISR_FLAG_DIRECT, IRQ074_Handler, 0); |
0 commit comments