]> Git Repo - esp-hosted.git/blame - esp_hosted_fg/host/linux/host_driver/esp32/esp_bt.c
Old kernel built & not tested for > 3.10.0
[esp-hosted.git] / esp_hosted_fg / host / linux / host_driver / esp32 / esp_bt.c
CommitLineData
71d37aa1
MM
1/*
2 * Espressif Systems Wireless LAN device driver
3 *
683f0529 4 * Copyright (C) 2015-2021 Espressif Systems (Shanghai) PTE LTD
71d37aa1
MM
5 *
6 * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19#include "esp_bt_api.h"
20#include "esp_api.h"
aad2ae2e 21#include "esp_kernel_port.h"
71d37aa1 22
d718e190
YM
23#define INVALID_HDEV_BUS (0xff)
24
85c5e78a 25
aad2ae2e 26static ESP_BT_SEND_FRAME_PROTOTYPE();
85c5e78a 27
c6a5eef9
MM
28void esp_hci_update_tx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len)
29{
30 if (hdev) {
31 if (pkt_type == HCI_COMMAND_PKT) {
32 hdev->stat.cmd_tx++;
33 } else if (pkt_type == HCI_ACLDATA_PKT) {
34 hdev->stat.acl_tx++;
35 } else if (pkt_type == HCI_SCODATA_PKT) {
36 hdev->stat.sco_tx++;
37 }
38
39 hdev->stat.byte_tx += len;
40 }
41}
42
43void esp_hci_update_rx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len)
44{
45 if (hdev) {
46 if (pkt_type == HCI_EVENT_PKT) {
47 hdev->stat.evt_rx++;
48 } else if (pkt_type == HCI_ACLDATA_PKT) {
49 hdev->stat.acl_rx++;
50 } else if (pkt_type == HCI_SCODATA_PKT) {
51 hdev->stat.sco_rx++;
52 }
53
54 hdev->stat.byte_rx += len;
55 }
56}
57
71d37aa1
MM
58static int esp_bt_open(struct hci_dev *hdev)
59{
60 return 0;
61}
62
63static int esp_bt_close(struct hci_dev *hdev)
64{
65 return 0;
66}
67
68static int esp_bt_flush(struct hci_dev *hdev)
69{
70 return 0;
71}
72
aad2ae2e 73static ESP_BT_SEND_FRAME_PROTOTYPE()
71d37aa1
MM
74{
75 struct esp_payload_header *hdr;
76 size_t total_len, len = skb->len;
77 int ret = 0;
85c5e78a 78#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
79 struct hci_dev * hdev = (struct hci_dev *)(skb->dev);
80#endif
71d37aa1
MM
81 struct esp_adapter *adapter = hci_get_drvdata(hdev);
82 struct sk_buff *new_skb;
5bd53032
MM
83 u8 pad_len = 0, realloc_skb = 0;
84 u8 *pos = NULL;
85 u8 pkt_type;
71d37aa1
MM
86
87 if (!adapter) {
88 printk(KERN_ERR "%s: invalid args", __func__);
89 return -EINVAL;
90 }
d53a8a4a 91 //print_hex_dump(KERN_INFO, "bt_tx: ", DUMP_PREFIX_ADDRESS, 16, 1, skb->data, len, 1 );
71d37aa1 92
5bd53032
MM
93 /* Create space for payload header */
94 pad_len = sizeof(struct esp_payload_header);
71d37aa1
MM
95 total_len = len + sizeof(struct esp_payload_header);
96
5bd53032
MM
97 /* Align buffer len */
98 pad_len += SKB_DATA_ADDR_ALIGNMENT - (total_len % SKB_DATA_ADDR_ALIGNMENT);
71d37aa1 99
5bd53032
MM
100 pkt_type = hci_skb_pkt_type(skb);
101
102 if (skb_headroom(skb) < pad_len) {
103 /* Headroom is not sufficient */
104 realloc_skb = 1;
105 }
106
107 if (realloc_skb || !IS_ALIGNED((unsigned long) skb->data, SKB_DATA_ADDR_ALIGNMENT)) {
108 /* Realloc SKB */
109 if (skb_linearize(skb)) {
110 hdev->stat.err_tx++;
111 return -EINVAL;
112 }
113
114 new_skb = esp_alloc_skb(skb->len + pad_len);
115
116 if (!new_skb) {
71d37aa1 117 printk(KERN_ERR "%s: Failed to allocate SKB", __func__);
c6a5eef9 118 hdev->stat.err_tx++;
71d37aa1
MM
119 return -ENOMEM;
120 }
121
5bd53032
MM
122 pos = new_skb->data;
123
124 pos += pad_len;
125
126 /* Populate new SKB */
127 skb_copy_from_linear_data(skb, pos, skb->len);
128 skb_put(new_skb, skb->len);
71d37aa1 129
5bd53032
MM
130 /* Replace old SKB */
131 dev_kfree_skb_any(skb);
71d37aa1 132 skb = new_skb;
5bd53032
MM
133 } else {
134 /* Realloc is not needed, Make space for interface header */
135 skb_push(skb, pad_len);
71d37aa1
MM
136 }
137
71d37aa1
MM
138 hdr = (struct esp_payload_header *) skb->data;
139
140 memset (hdr, 0, sizeof(struct esp_payload_header));
141
142 hdr->if_type = ESP_HCI_IF;
143 hdr->if_num = 0;
144 hdr->len = cpu_to_le16(len);
5bd53032
MM
145 hdr->offset = cpu_to_le16(pad_len);
146 pos = skb->data;
147
148 /* set HCI packet type */
149 *(pos + pad_len - 1) = pkt_type;
71d37aa1 150
54f5d2e4
MM
151 hdr->checksum = cpu_to_le16(compute_checksum(skb->data, (len + pad_len)));
152
03e9f879 153 ret = esp_send_packet(adapter, skb);
71d37aa1 154
c6a5eef9
MM
155 if (ret) {
156 hdev->stat.err_tx++;
5bd53032 157 return ret;
c6a5eef9
MM
158 } else {
159 esp_hci_update_tx_counter(hdev, hdr->hci_pkt_type, skb->len);
160 }
161
71d37aa1
MM
162 return 0;
163}
164
85c5e78a 165#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
71d37aa1
MM
166static int esp_bt_setup(struct hci_dev *hdev)
167{
168 return 0;
169}
85c5e78a 170#endif
71d37aa1 171
85c5e78a 172#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
71d37aa1
MM
173static int esp_bt_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
174{
175 return 0;
176}
85c5e78a 177#endif
71d37aa1
MM
178
179int esp_deinit_bt(struct esp_adapter *adapter)
180{
181 struct hci_dev *hdev = NULL;
182
062be972
MM
183 if (!adapter || !adapter->hcidev)
184 return 0;
185
71d37aa1
MM
186 hdev = adapter->hcidev;
187
188 hci_unregister_dev(hdev);
189 hci_free_dev(hdev);
190
191 adapter->hcidev = NULL;
192
193 return 0;
194}
195
196int esp_init_bt(struct esp_adapter *adapter)
197{
198 int ret = 0;
199 struct hci_dev *hdev = NULL;
200
201 if (!adapter) {
202 return -EINVAL;
203 }
204
205 if (adapter->hcidev) {
206 return -EEXIST;
207 }
208
209 hdev = hci_alloc_dev();
210
211 if (!hdev) {
212 BT_ERR("Can not allocate HCI device");
213 return -ENOMEM;
214 }
215
216 adapter->hcidev = hdev;
217 hci_set_drvdata(hdev, adapter);
218
d718e190
YM
219 hdev->bus = INVALID_HDEV_BUS;
220
062be972
MM
221 if (adapter->if_type == ESP_IF_TYPE_SDIO)
222 hdev->bus = HCI_SDIO;
85c5e78a 223 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
062be972
MM
224 else if (adapter->if_type == ESP_IF_TYPE_SPI)
225 hdev->bus = HCI_SPI;
85c5e78a 226 #endif
d718e190
YM
227
228 if (hdev->bus == INVALID_HDEV_BUS) {
229
230 if (adapter->if_type == ESP_IF_TYPE_SDIO) {
231 printk(KERN_ERR "%s: Kernel version does not support HCI over SDIO BUS\n",__func__);
232 } else if (adapter->if_type == ESP_IF_TYPE_SPI) {
233 printk(KERN_ERR "%s: Kernel version does not support HCI over SPI BUS\n",__func__);
234 } else {
235 printk(KERN_ERR "%s: HCI over expected BUS[%u] is not supported\n",__func__, adapter->if_type);
236 }
237 hci_free_dev(hdev);
238 adapter->hcidev = NULL;
239 return -EINVAL;
240 }
062be972 241
71d37aa1
MM
242 hdev->open = esp_bt_open;
243 hdev->close = esp_bt_close;
244 hdev->flush = esp_bt_flush;
245 hdev->send = esp_bt_send_frame;
85c5e78a 246
247#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
71d37aa1 248 hdev->setup = esp_bt_setup;
85c5e78a 249#endif
250
251#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
71d37aa1 252 hdev->set_bdaddr = esp_bt_set_bdaddr;
85c5e78a 253#endif
71d37aa1
MM
254
255 hdev->dev_type = HCI_PRIMARY;
256
257 ret = hci_register_dev(hdev);
258 if (ret < 0) {
259 BT_ERR("Can not register HCI device");
260 hci_free_dev(hdev);
261 return -ENOMEM;
262 }
263
264 return 0;
265}
This page took 0.057402 seconds and 4 git commands to generate.