]> Git Repo - esp-hosted.git/blame - esp_hosted_ng/host/esp_bt.c
feat(esp_hosted_ng) : Draft add sdio support for esp32c6
[esp-hosted.git] / esp_hosted_ng / host / esp_bt.c
CommitLineData
e8b168e8 1// SPDX-License-Identifier: GPL-2.0-only
71d37aa1
MM
2/*
3 * Espressif Systems Wireless LAN device driver
4 *
d7215282 5 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
71d37aa1 6 *
71d37aa1 7 */
057d3956 8#include "utils.h"
71d37aa1 9#include "esp_api.h"
4c494b4b 10#include "esp_kernel_port.h"
71d37aa1 11
d718e190
YM
12#define INVALID_HDEV_BUS (0xff)
13
c6a5eef9
MM
14void esp_hci_update_tx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len)
15{
a3829bf3
KG
16 if (!hdev)
17 return;
18 if (pkt_type == HCI_COMMAND_PKT) {
19 hdev->stat.cmd_tx++;
20 } else if (pkt_type == HCI_ACLDATA_PKT) {
21 hdev->stat.acl_tx++;
22 } else if (pkt_type == HCI_SCODATA_PKT) {
23 hdev->stat.sco_tx++;
c6a5eef9 24 }
a3829bf3
KG
25
26 hdev->stat.byte_tx += len;
c6a5eef9
MM
27}
28
29void esp_hci_update_rx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len)
30{
a3829bf3
KG
31 if (!hdev)
32 return;
33
34 if (pkt_type == HCI_EVENT_PKT) {
35 hdev->stat.evt_rx++;
36 } else if (pkt_type == HCI_ACLDATA_PKT) {
37 hdev->stat.acl_rx++;
38 } else if (pkt_type == HCI_SCODATA_PKT) {
39 hdev->stat.sco_rx++;
c6a5eef9 40 }
a3829bf3
KG
41
42 hdev->stat.byte_rx += len;
c6a5eef9
MM
43}
44
71d37aa1
MM
45static int esp_bt_open(struct hci_dev *hdev)
46{
47 return 0;
48}
49
50static int esp_bt_close(struct hci_dev *hdev)
51{
52 return 0;
53}
54
55static int esp_bt_flush(struct hci_dev *hdev)
56{
57 return 0;
58}
59
4c494b4b 60static ESP_BT_SEND_FRAME_PROTOTYPE()
71d37aa1
MM
61{
62 struct esp_payload_header *hdr;
63 size_t total_len, len = skb->len;
64 int ret = 0;
85c5e78a 65#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
a3829bf3 66 struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
85c5e78a 67#endif
71d37aa1
MM
68 struct esp_adapter *adapter = hci_get_drvdata(hdev);
69 struct sk_buff *new_skb;
5bd53032
MM
70 u8 pad_len = 0, realloc_skb = 0;
71 u8 *pos = NULL;
72 u8 pkt_type;
71d37aa1
MM
73
74 if (!adapter) {
6f8fee57 75 esp_err("Invalid args");
71d37aa1
MM
76 return -EINVAL;
77 }
d53a8a4a 78 //print_hex_dump(KERN_INFO, "bt_tx: ", DUMP_PREFIX_ADDRESS, 16, 1, skb->data, len, 1 );
71d37aa1 79
5bd53032
MM
80 /* Create space for payload header */
81 pad_len = sizeof(struct esp_payload_header);
71d37aa1
MM
82 total_len = len + sizeof(struct esp_payload_header);
83
5bd53032
MM
84 /* Align buffer len */
85 pad_len += SKB_DATA_ADDR_ALIGNMENT - (total_len % SKB_DATA_ADDR_ALIGNMENT);
71d37aa1 86
5bd53032
MM
87 pkt_type = hci_skb_pkt_type(skb);
88
89 if (skb_headroom(skb) < pad_len) {
90 /* Headroom is not sufficient */
91 realloc_skb = 1;
92 }
93
94 if (realloc_skb || !IS_ALIGNED((unsigned long) skb->data, SKB_DATA_ADDR_ALIGNMENT)) {
95 /* Realloc SKB */
96 if (skb_linearize(skb)) {
97 hdev->stat.err_tx++;
98 return -EINVAL;
99 }
100
101 new_skb = esp_alloc_skb(skb->len + pad_len);
102
103 if (!new_skb) {
6f8fee57 104 esp_err("Failed to allocate SKB");
c6a5eef9 105 hdev->stat.err_tx++;
71d37aa1
MM
106 return -ENOMEM;
107 }
108
5bd53032
MM
109 pos = new_skb->data;
110
111 pos += pad_len;
112
113 /* Populate new SKB */
114 skb_copy_from_linear_data(skb, pos, skb->len);
115 skb_put(new_skb, skb->len);
71d37aa1 116
5bd53032
MM
117 /* Replace old SKB */
118 dev_kfree_skb_any(skb);
71d37aa1 119 skb = new_skb;
5bd53032
MM
120 } else {
121 /* Realloc is not needed, Make space for interface header */
122 skb_push(skb, pad_len);
71d37aa1
MM
123 }
124
71d37aa1
MM
125 hdr = (struct esp_payload_header *) skb->data;
126
a3829bf3 127 memset(hdr, 0, sizeof(struct esp_payload_header));
71d37aa1
MM
128
129 hdr->if_type = ESP_HCI_IF;
130 hdr->if_num = 0;
131 hdr->len = cpu_to_le16(len);
5bd53032
MM
132 hdr->offset = cpu_to_le16(pad_len);
133 pos = skb->data;
134
135 /* set HCI packet type */
136 *(pos + pad_len - 1) = pkt_type;
71d37aa1 137
bf3d6cb6
SR
138 if (adapter->capabilities & ESP_CHECKSUM_ENABLED)
139 hdr->checksum = cpu_to_le16(compute_checksum(skb->data, (len + pad_len)));
54f5d2e4 140
03e9f879 141 ret = esp_send_packet(adapter, skb);
71d37aa1 142
c6a5eef9
MM
143 if (ret) {
144 hdev->stat.err_tx++;
5bd53032 145 return ret;
c6a5eef9
MM
146 } else {
147 esp_hci_update_tx_counter(hdev, hdr->hci_pkt_type, skb->len);
148 }
149
71d37aa1
MM
150 return 0;
151}
152
85c5e78a 153#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
71d37aa1
MM
154static int esp_bt_setup(struct hci_dev *hdev)
155{
156 return 0;
157}
85c5e78a 158#endif
71d37aa1 159
85c5e78a 160#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
71d37aa1
MM
161static int esp_bt_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
162{
163 return 0;
164}
85c5e78a 165#endif
71d37aa1
MM
166
167int esp_deinit_bt(struct esp_adapter *adapter)
168{
169 struct hci_dev *hdev = NULL;
170
062be972
MM
171 if (!adapter || !adapter->hcidev)
172 return 0;
173
71d37aa1
MM
174 hdev = adapter->hcidev;
175
176 hci_unregister_dev(hdev);
177 hci_free_dev(hdev);
178
179 adapter->hcidev = NULL;
180
181 return 0;
182}
183
184int esp_init_bt(struct esp_adapter *adapter)
185{
186 int ret = 0;
187 struct hci_dev *hdev = NULL;
188
189 if (!adapter) {
190 return -EINVAL;
191 }
192
193 if (adapter->hcidev) {
194 return -EEXIST;
195 }
196
197 hdev = hci_alloc_dev();
198
199 if (!hdev) {
200 BT_ERR("Can not allocate HCI device");
201 return -ENOMEM;
202 }
203
204 adapter->hcidev = hdev;
205 hci_set_drvdata(hdev, adapter);
206
d718e190
YM
207 hdev->bus = INVALID_HDEV_BUS;
208
062be972
MM
209 if (adapter->if_type == ESP_IF_TYPE_SDIO)
210 hdev->bus = HCI_SDIO;
85c5e78a 211 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
062be972
MM
212 else if (adapter->if_type == ESP_IF_TYPE_SPI)
213 hdev->bus = HCI_SPI;
85c5e78a 214 #endif
d718e190
YM
215
216 if (hdev->bus == INVALID_HDEV_BUS) {
217
218 if (adapter->if_type == ESP_IF_TYPE_SDIO) {
6f8fee57 219 esp_err("Kernel version does not support HCI over SDIO BUS\n");
d718e190 220 } else if (adapter->if_type == ESP_IF_TYPE_SPI) {
6f8fee57 221 esp_err("Kernel version does not support HCI over SPI BUS\n");
d718e190 222 } else {
a3829bf3 223 esp_err("HCI over expected BUS[%u] is not supported\n", adapter->if_type);
d718e190
YM
224 }
225 hci_free_dev(hdev);
226 adapter->hcidev = NULL;
227 return -EINVAL;
228 }
062be972 229
71d37aa1
MM
230 hdev->open = esp_bt_open;
231 hdev->close = esp_bt_close;
232 hdev->flush = esp_bt_flush;
233 hdev->send = esp_bt_send_frame;
85c5e78a 234
235#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
71d37aa1 236 hdev->setup = esp_bt_setup;
85c5e78a 237#endif
238
239#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
71d37aa1 240 hdev->set_bdaddr = esp_bt_set_bdaddr;
85c5e78a 241#endif
71d37aa1
MM
242
243 hdev->dev_type = HCI_PRIMARY;
244
245 ret = hci_register_dev(hdev);
246 if (ret < 0) {
247 BT_ERR("Can not register HCI device");
248 hci_free_dev(hdev);
249 return -ENOMEM;
250 }
251
252 return 0;
253}
This page took 0.067156 seconds and 4 git commands to generate.