1 /*
2 * Copyright (C) 2016 YunOS Project. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <bt_errno.h>
17 #include <stddef.h>
18
19 #include <ble_os.h>
20
21 #define BT_DBG_ENABLED 0
22
23 #include <common/log.h>
24 #include <bluetooth/bluetooth.h>
25 #include <bluetooth/hci.h>
26 #include <bluetooth/conn.h>
27 #include <bluetooth/hci_driver.h>
28
29 #include "h5.h"
30 #include "host/hci_core.h"
31
32 #define H4_NONE 0x00
33 #define H4_CMD 0x01
34 #define H4_ACL_UP 0x02
35 #define H4_SCO 0x03
36 #define H4_EVT 0x04
37 #define H4_ACL_DOWN 0x05
38
39 #define H5_ACK_PKT 0x00
40 #define HCI_COMMAND_PKT 0x01
41 #define HCI_ACLDATA_PKT 0x02
42 #define HCI_SCODATA_PKT 0x03
43 #define HCI_EVENT_PKT 0x04
44 #define H5_VDRSPEC_PKT 0x0E
45 #define H5_LINK_CTL_PKT 0x0F
46
47 const static h5_t *h5_ctx;
48 extern u16_t bt_hci_get_cmd_opcode(struct net_buf *buf);
h5_send(struct net_buf * buf)49 static int h5_send(struct net_buf *buf)
50 {
51 u16_t opcode;
52 uint8_t type = bt_buf_get_type(buf);
53
54 BT_DBG("buf %p type %u len %u:%s", buf, type, buf->len, bt_hex(buf->data, buf->len));
55
56 switch (type) {
57 case BT_BUF_CMD:
58 opcode = bt_hci_get_cmd_opcode(buf);
59
60 if (opcode == HCI_VSC_H5_INIT) {
61 h5_ctx->h5_send_sync_cmd(opcode, NULL, buf->len);
62 break;
63 }
64
65 h5_ctx->h5_send_cmd(HCI_COMMAND_PKT, buf->data, buf->len);
66 break;
67 case BT_BUF_ACL_OUT:
68 h5_ctx->h5_send_acl_data(HCI_ACLDATA_PKT, buf->data, buf->len);
69 break;
70
71 default:
72 BT_ERR("Unknown buffer type");
73 return -1;
74 }
75
76 net_buf_unref(buf);
77
78 return 0;
79 }
80
is_adv_report_event(uint8_t * data,uint16_t len)81 static inline int is_adv_report_event(uint8_t *data, uint16_t len)
82 {
83 return (data[0] == H4_EVT && data[1] == BT_HCI_EVT_LE_META_EVENT
84 && data[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT);
85 }
86
hci_h5_event_recv(uint8_t * data,uint16_t data_len)87 int hci_h5_event_recv(uint8_t *data, uint16_t data_len)
88 {
89 struct net_buf *buf;
90 uint8_t *pdata = data;
91 int32_t len = data_len;
92 struct bt_hci_evt_hdr hdr;
93 uint8_t sub_event = 0;
94 uint8_t discardable = 0;
95
96 if (pdata == NULL || len == 0) {
97 return -1;
98 }
99
100 if (len < 3) {
101 goto err;
102 }
103
104 hdr.evt = *pdata++;
105 hdr.len = *pdata++;
106
107 if (len < hdr.len + 2) {
108 goto err;
109 }
110
111 if (hdr.evt == BT_HCI_EVT_LE_META_EVENT) {
112 sub_event = *pdata++;
113
114 if (sub_event == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
115 discardable = 1;
116 }
117 }
118
119 if (hdr.evt == BT_HCI_EVT_CMD_COMPLETE ||
120 hdr.evt == BT_HCI_EVT_CMD_STATUS) {
121 buf = bt_buf_get_cmd_complete(0);
122
123 if (buf == NULL) {
124 // g_hci_debug_counter.event_in_is_null_count++;
125 goto err;
126 }
127 } else {
128 buf = bt_buf_get_rx(BT_BUF_EVT, 0);
129 }
130
131 if (!buf && discardable) {
132 // g_hci_debug_counter.event_discard_count++;
133 goto err;
134 }
135
136 if (!buf) {
137 // g_hci_debug_counter.event_in_is_null_count++;
138 goto err;
139 }
140
141 bt_buf_set_type(buf, BT_BUF_EVT);
142
143 net_buf_add_mem(buf, ((uint8_t *)(data)), hdr.len + sizeof(hdr));
144
145 BT_DBG("event %s", bt_hex(buf->data, buf->len));
146 // g_hci_debug_counter.event_in_count++;
147
148 if (bt_hci_evt_is_prio(hdr.evt)) {
149 bt_recv_prio(buf);
150 } else {
151 bt_recv(buf);
152 }
153
154 return 0;
155
156 err:
157 return -1;
158 }
159
hci_h5_acl_recv(uint8_t * data,uint16_t data_len)160 int hci_h5_acl_recv(uint8_t *data, uint16_t data_len)
161 {
162 struct net_buf *buf;
163 uint16_t acl_len;
164 if (data == NULL || data_len == 0) {
165 return -1;
166 }
167
168 if (data_len < 4) {
169 goto err;
170 }
171
172 acl_len = (data[3] << 8) | data[2];
173
174 if (data_len < acl_len + 4) {
175 goto err;
176 }
177
178 buf = bt_buf_get_rx(BT_BUF_ACL_IN, 0);
179
180 if (!buf) {
181 // g_hci_debug_counter.hci_in_is_null_count++;
182 goto err;
183 }
184
185 net_buf_add_mem(buf, data, acl_len + 4);
186 // g_hci_debug_counter.acl_in_count++;
187
188 bt_recv(buf);
189 return 0;
190
191 err:
192 return -1;
193 }
194
packet_recv_cb(hci_data_type_t type,uint8_t * data,uint32_t len)195 static void packet_recv_cb(hci_data_type_t type, uint8_t *data, uint32_t len)
196 {
197 switch (type) {
198 case DATA_TYPE_ACL:
199 hci_h5_acl_recv(data, len);
200 break;
201 case DATA_TYPE_EVENT:
202 hci_h5_event_recv(data, len);
203 break;
204 default:
205 break;
206 }
207
208 return;
209 }
210
h5_open(void)211 static int h5_open(void)
212 {
213 h5_ctx = get_h5_interface();
214
215 h5_ctx->h5_int_init(packet_recv_cb);
216
217 return 0;
218 }
219
220 static struct bt_hci_driver drv = {
221 .name = "H5",
222 .bus = BT_HCI_DRIVER_BUS_UART,
223 .open = h5_open,
224 .send = h5_send,
225 };
226
hci_h5_driver_init()227 int hci_h5_driver_init()
228 {
229 int ret;
230
231 ret = bt_hci_driver_register(&drv);
232
233 if (ret) {
234 return ret;
235 }
236
237 return 0;
238 }
239