1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <stddef.h>
21 #include <string.h>
22 #include "host/ble_hs.h"
23 #include "host/ble_hs_hci.h"
24 #include "ble_hs_priv.h"
25
26 #if !MYNEWT_VAL(BLE_CONTROLLER)
ble_hs_startup_read_sup_f_tx(void)27 static int ble_hs_startup_read_sup_f_tx(void)
28 {
29 struct ble_hci_ip_rd_loc_supp_feat_rp rsp;
30 int rc;
31 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
32 BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
33 NULL, 0, &rsp, sizeof(rsp));
34 if (rc != 0) {
35 return rc;
36 }
37
38 /* for now we don't use it outside of init sequence so check this here
39 * LE Supported (Controller) byte 4, bit 6
40 */
41 if (!(rsp.features & 0x0000006000000000)) {
42 BLE_HS_LOG(ERROR, "Controller doesn't support LE\n");
43 return BLE_HS_ECONTROLLER;
44 }
45
46 return 0;
47 }
48 #endif
49
ble_hs_startup_read_local_ver_tx(void)50 static int ble_hs_startup_read_local_ver_tx(void)
51 {
52 struct ble_hci_ip_rd_local_ver_rp rsp;
53 int rc;
54 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
55 BLE_HCI_OCF_IP_RD_LOCAL_VER),
56 NULL, 0, &rsp, sizeof(rsp));
57 if (rc != 0) {
58 return rc;
59 }
60
61 /* For now we are interested only in HCI Version */
62 ble_hs_hci_set_hci_version(rsp.hci_ver);
63 return 0;
64 }
65
ble_hs_startup_le_read_sup_f_tx(void)66 static int ble_hs_startup_le_read_sup_f_tx(void)
67 {
68 struct ble_hci_le_rd_loc_supp_feat_rp rsp;
69 int rc;
70 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
71 BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
72 NULL, 0, &rsp, sizeof(rsp));
73 if (rc != 0) {
74 return rc;
75 }
76
77 ble_hs_hci_set_le_supported_feat(le64toh(rsp.features));
78 return 0;
79 }
80
ble_hs_startup_le_read_buf_sz_tx(uint16_t * out_pktlen,uint8_t * out_max_pkts)81 static int ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
82 {
83 struct ble_hci_le_rd_buf_size_rp rsp;
84 int rc;
85 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE), NULL, 0,
86 &rsp, sizeof(rsp));
87 if (rc != 0) {
88 return rc;
89 }
90
91 *out_pktlen = le16toh(rsp.data_len);
92 *out_max_pkts = rsp.data_packets;
93 return 0;
94 }
95
ble_hs_startup_read_buf_sz_tx(uint16_t * out_pktlen,uint16_t * out_max_pkts)96 static int ble_hs_startup_read_buf_sz_tx(uint16_t *out_pktlen, uint16_t *out_max_pkts)
97 {
98 struct ble_hci_ip_rd_buf_size_rp rsp;
99 int rc;
100 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BUF_SIZE), NULL, 0,
101 &rsp, sizeof(rsp));
102 if (rc != 0) {
103 return rc;
104 }
105
106 *out_pktlen = le16toh(rsp.acl_data_len);
107 *out_max_pkts = le16toh(rsp.acl_num);
108 return 0;
109 }
110
ble_hs_startup_read_buf_sz(void)111 static int ble_hs_startup_read_buf_sz(void)
112 {
113 uint16_t le_pktlen = 0;
114 uint16_t max_pkts = 0;
115 uint16_t pktlen = 0;
116 uint8_t le_max_pkts = 0;
117 int rc;
118 rc = ble_hs_startup_le_read_buf_sz_tx(&le_pktlen, &le_max_pkts);
119 if (rc != 0) {
120 return rc;
121 }
122
123 if (le_pktlen != 0) {
124 pktlen = le_pktlen;
125 max_pkts = le_max_pkts;
126 } else {
127 rc = ble_hs_startup_read_buf_sz_tx(&pktlen, &max_pkts);
128 if (rc != 0) {
129 return rc;
130 }
131 }
132
133 rc = ble_hs_hci_set_buf_sz(pktlen, max_pkts);
134 if (rc != 0) {
135 return rc;
136 }
137
138 return 0;
139 }
140
ble_hs_startup_read_bd_addr(void)141 static int ble_hs_startup_read_bd_addr(void)
142 {
143 struct ble_hci_ip_rd_bd_addr_rp rsp;
144 int rc;
145 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
146 BLE_HCI_OCF_IP_RD_BD_ADDR),
147 NULL, 0, &rsp, sizeof(rsp));
148 if (rc != 0) {
149 return rc;
150 }
151
152 ble_hs_id_set_pub(rsp.addr);
153 return 0;
154 }
155
ble_hs_startup_le_set_evmask_tx(void)156 static int ble_hs_startup_le_set_evmask_tx(void)
157 {
158 struct ble_hci_le_set_event_mask_cp cmd;
159 uint8_t version;
160 uint64_t mask;
161 int rc;
162 version = ble_hs_hci_get_hci_version();
163 /* should we also check for supported commands when setting this? */
164 /**
165 * Enable the following LE events:
166 * 0x0000000000000001 LE Connection Complete Event
167 * 0x0000000000000002 LE Advertising Report Event
168 * 0x0000000000000004 LE Connection Update Complete Event
169 * 0x0000000000000008 LE Read Remote Used Features Complete Event
170 * 0x0000000000000010 LE Long Term Key Request Event
171 */
172 mask = 0x000000000000001f;
173
174 if (version >= BLE_HCI_VER_BCS_4_1) {
175 /**
176 * Enable the following LE events:
177 * 0x0000000000000020 LE Remote Connection Parameter Request Event */
178 mask |= 0x0000000000000020;
179 }
180
181 if (version >= BLE_HCI_VER_BCS_4_2) {
182 /**
183 * Enable the following LE events:
184 * 0x0000000000000040 LE Data Length Change Event
185 * 0x0000000000000200 LE Enhanced Connection Complete Event
186 * 0x0000000000000400 LE Directed Advertising Report Event
187 */
188 mask |= 0x0000000000000640;
189 }
190
191 if (version >= BLE_HCI_VER_BCS_5_0) {
192 /**
193 * Enable the following LE events:
194 * 0x0000000000000800 LE PHY Update Complete Event
195 * 0x0000000000001000 LE Extended Advertising Report Event
196 * 0x0000000000002000 LE Periodic Advertising Sync Established Event
197 * 0x0000000000004000 LE Periodic Advertising Report Event
198 * 0x0000000000008000 LE Periodic Advertising Sync Lost Event
199 * 0x0000000000010000 LE Extended Scan Timeout Event
200 * 0x0000000000020000 LE Extended Advertising Set Terminated Event
201 * 0x0000000000040000 LE Scan Request Received Event
202 * 0x0000000000080000 LE Channel Selection Algorithm Event
203 */
204 mask |= 0x00000000000ff800;
205 }
206
207 #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
208
209 if (version >= BLE_HCI_VER_BCS_5_1) {
210 /**
211 * Enable the following LE events:
212 * 0x0000000000800000 LE Periodic Advertising Sync Transfer Received event
213 */
214 mask |= 0x0000000000800000;
215 }
216
217 #endif
218 cmd.event_mask = htole64(mask);
219 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
220 BLE_HCI_OCF_LE_SET_EVENT_MASK),
221 &cmd, sizeof(cmd), NULL, 0);
222 if (rc != 0) {
223 return rc;
224 }
225
226 return 0;
227 }
228
ble_hs_startup_set_evmask_tx(void)229 static int ble_hs_startup_set_evmask_tx(void)
230 {
231 struct ble_hci_cb_set_event_mask_cp cmd;
232 struct ble_hci_cb_set_event_mask2_cp cmd2;
233 uint8_t version;
234 int rc;
235 version = ble_hs_hci_get_hci_version();
236 /**
237 * Enable the following events:
238 * 0x0000000000000010 Disconnection Complete Event
239 * 0x0000000000000080 Encryption Change Event
240 * 0x0000000000008000 Hardware Error Event
241 * 0x0000000002000000 Data Buffer Overflow Event
242 * 0x0000800000000000 Encryption Key Refresh Complete Event
243 * 0x2000000000000000 LE Meta-Event
244 */
245 cmd.event_mask = htole64(0x2000800002008090);
246 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
247 BLE_HCI_OCF_CB_SET_EVENT_MASK),
248 &cmd, sizeof(cmd), NULL, 0);
249 if (rc != 0) {
250 return rc;
251 }
252
253 if (version >= BLE_HCI_VER_BCS_4_1) {
254 /**
255 * Enable the following events:
256 * 0x0000000000800000 Authenticated Payload Timeout Event
257 */
258 cmd2.event_mask2 = htole64(0x0000000000800000);
259 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
260 BLE_HCI_OCF_CB_SET_EVENT_MASK2),
261 &cmd2, sizeof(cmd2), NULL, 0);
262 if (rc != 0) {
263 return rc;
264 }
265 }
266
267 return 0;
268 }
269
ble_hs_startup_reset_tx(void)270 static int ble_hs_startup_reset_tx(void)
271 {
272 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
273 BLE_HCI_OCF_CB_RESET),
274 NULL, 0, NULL, 0);
275 }
276
ble_hs_startup_go(void)277 int ble_hs_startup_go(void)
278 {
279 int rc;
280 rc = ble_hs_startup_reset_tx();
281 if (rc != 0) {
282 return rc;
283 }
284
285 rc = ble_hs_startup_read_local_ver_tx();
286 if (rc != 0) {
287 return rc;
288 }
289
290 /* XXX: Read local supported commands. */
291 /* we need to check this only if using external controller */
292 #if !MYNEWT_VAL(BLE_CONTROLLER)
293
294 if (ble_hs_hci_get_hci_version() < BLE_HCI_VER_BCS_4_0) {
295 BLE_HS_LOG(ERROR, "Required controller version is 4.0 (6)\n");
296 return BLE_HS_ECONTROLLER;
297 }
298
299 rc = ble_hs_startup_read_sup_f_tx();
300 if (rc != 0) {
301 return rc;
302 }
303
304 #endif
305 rc = ble_hs_startup_set_evmask_tx();
306 if (rc != 0) {
307 return rc;
308 }
309
310 rc = ble_hs_startup_le_set_evmask_tx();
311 if (rc != 0) {
312 return rc;
313 }
314
315 rc = ble_hs_startup_read_buf_sz();
316 if (rc != 0) {
317 return rc;
318 }
319
320 rc = ble_hs_startup_le_read_sup_f_tx();
321 if (rc != 0) {
322 return rc;
323 }
324
325 rc = ble_hs_startup_read_bd_addr();
326 if (rc != 0) {
327 return rc;
328 }
329
330 rc = ble_hs_pvcy_set_our_irk(NULL);
331 if (rc != 0) {
332 assert(0);
333 return rc;
334 }
335
336 /* If flow control is enabled, configure the controller to use it. */
337 ble_hs_flow_startup();
338 return 0;
339 }