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