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_DEVICE)
27 static int
ble_hs_startup_read_sup_f_tx(void)28 ble_hs_startup_read_sup_f_tx(void)
29 {
30 uint8_t ack_params[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN];
31 uint8_t ack_params_len;
32 int rc;
33
34 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
35 BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
36 NULL,0, ack_params, sizeof ack_params,
37 &ack_params_len);
38 if (rc != 0) {
39 return rc;
40 }
41
42 if (ack_params_len != BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN) {
43 return BLE_HS_ECONTROLLER;
44 }
45
46 /* for now we don't use it outside of init sequence so check this here
47 * LE Supported (Controller) byte 4, bit 6
48 */
49 if (!(ack_params[4] & 0x60)) {
50 BLE_HS_LOG(ERROR, "Controller doesn't support LE\n");
51 return BLE_HS_ECONTROLLER;
52 }
53
54 return 0;
55 }
56 #endif
57
58 static int
ble_hs_startup_read_local_ver_tx(void)59 ble_hs_startup_read_local_ver_tx(void)
60 {
61 uint8_t ack_params[BLE_HCI_RD_LOC_VER_INFO_RSPLEN];
62 uint8_t ack_params_len;
63 uint8_t hci_version;
64 int rc;
65
66 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
67 BLE_HCI_OCF_IP_RD_LOCAL_VER),
68 NULL,0, ack_params, sizeof ack_params,
69 &ack_params_len);
70 if (rc != 0) {
71 return rc;
72 }
73
74 if (ack_params_len != BLE_HCI_RD_LOC_VER_INFO_RSPLEN) {
75 return BLE_HS_ECONTROLLER;
76 }
77
78 /* For now we are interested only in HCI Version */
79 hci_version = ack_params[0];
80 ble_hs_hci_set_hci_version(hci_version);
81
82 return 0;
83 }
84
85 static int
ble_hs_startup_le_read_sup_f_tx(void)86 ble_hs_startup_le_read_sup_f_tx(void)
87 {
88 uint8_t ack_params[BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN];
89 uint8_t ack_params_len;
90 uint32_t feat;
91 int rc;
92
93 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
94 BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
95 NULL,0, ack_params, sizeof ack_params,
96 &ack_params_len);
97 if (rc != 0) {
98 return rc;
99 }
100
101 if (ack_params_len != BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN) {
102 return BLE_HS_ECONTROLLER;
103 }
104
105 /* For now 32-bits of features is enough */
106 feat = get_le32(ack_params);
107 ble_hs_hci_set_le_supported_feat(feat);
108
109 return 0;
110 }
111
112 static int
ble_hs_startup_le_read_buf_sz_tx(uint16_t * out_pktlen,uint8_t * out_max_pkts)113 ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
114 {
115 uint8_t ack_params[BLE_HCI_RD_BUF_SIZE_RSPLEN];
116 uint8_t ack_params_len;
117 int rc;
118
119 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
120 BLE_HCI_OCF_LE_RD_BUF_SIZE), NULL, 0,
121 ack_params, sizeof ack_params, &ack_params_len);
122 if (rc != 0) {
123 return rc;
124 }
125
126 if (ack_params_len != BLE_HCI_RD_BUF_SIZE_RSPLEN) {
127 return BLE_HS_ECONTROLLER;
128 }
129
130 *out_pktlen = get_le16(ack_params + 0);
131 *out_max_pkts = ack_params[2];
132
133 return 0;
134 }
135
136 static int
ble_hs_startup_read_buf_sz_tx(uint16_t * out_pktlen,uint16_t * out_max_pkts)137 ble_hs_startup_read_buf_sz_tx(uint16_t *out_pktlen, uint16_t *out_max_pkts)
138 {
139 uint8_t ack_params[BLE_HCI_IP_RD_BUF_SIZE_RSPLEN];
140 uint8_t ack_params_len;
141 int rc;
142
143 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
144 BLE_HCI_OCF_IP_RD_BUF_SIZE), NULL, 0,
145 ack_params, sizeof ack_params, &ack_params_len);
146 if (rc != 0) {
147 return rc;
148 }
149
150 if (ack_params_len != BLE_HCI_IP_RD_BUF_SIZE_RSPLEN) {
151 return BLE_HS_ECONTROLLER;
152 }
153
154 *out_pktlen = get_le16(ack_params + 0);
155 *out_max_pkts = get_le16(ack_params + 3);
156
157 return 0;
158 }
159
160 static int
ble_hs_startup_read_buf_sz(void)161 ble_hs_startup_read_buf_sz(void)
162 {
163 uint16_t le_pktlen = 0;
164 uint16_t max_pkts = 0;
165 uint16_t pktlen = 0;
166 uint8_t le_max_pkts = 0;
167 int rc;
168
169 rc = ble_hs_startup_le_read_buf_sz_tx(&le_pktlen, &le_max_pkts);
170 if (rc != 0) {
171 return rc;
172 }
173
174 if (le_pktlen != 0) {
175 pktlen = le_pktlen;
176 max_pkts = le_max_pkts;
177 } else {
178 rc = ble_hs_startup_read_buf_sz_tx(&pktlen, &max_pkts);
179 if (rc != 0) {
180 return rc;
181 }
182 }
183
184 rc = ble_hs_hci_set_buf_sz(pktlen, max_pkts);
185 if (rc != 0) {
186 return rc;
187 }
188
189 return 0;
190 }
191
192 static int
ble_hs_startup_read_bd_addr(void)193 ble_hs_startup_read_bd_addr(void)
194 {
195 uint8_t ack_params[BLE_HCI_IP_RD_BD_ADDR_ACK_PARAM_LEN];
196 uint8_t ack_params_len;
197 int rc;
198
199 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
200 BLE_HCI_OCF_IP_RD_BD_ADDR),
201 NULL, 0, ack_params, sizeof ack_params,
202 &ack_params_len);
203 if (rc != 0) {
204 return rc;
205 }
206
207 if (ack_params_len != sizeof ack_params) {
208 return BLE_HS_ECONTROLLER;
209 }
210
211 ble_hs_id_set_pub(ack_params);
212 return 0;
213 }
214
215 static int
ble_hs_startup_le_set_evmask_tx(void)216 ble_hs_startup_le_set_evmask_tx(void)
217 {
218 uint8_t buf[BLE_HCI_SET_LE_EVENT_MASK_LEN];
219 uint8_t version;
220 uint64_t mask;
221 int rc;
222
223 version = ble_hs_hci_get_hci_version();
224
225 /* TODO should we also check for supported commands when setting this? */
226
227 /**
228 * Enable the following LE events:
229 * 0x0000000000000001 LE Connection Complete Event
230 * 0x0000000000000002 LE Advertising Report Event
231 * 0x0000000000000004 LE Connection Update Complete Event
232 * 0x0000000000000008 LE Read Remote Used Features Complete Event
233 * 0x0000000000000010 LE Long Term Key Request Event
234 */
235 mask = 0x000000000000001f;
236
237 if (version >= BLE_HCI_VER_BCS_4_1) {
238 /**
239 * Enable the following LE events:
240 * 0x0000000000000020 LE Remote Connection Parameter Request Event */
241 mask |= 0x0000000000000020;
242 }
243
244 if (version >= BLE_HCI_VER_BCS_4_2) {
245 /**
246 * Enable the following LE events:
247 * 0x0000000000000040 LE Data Length Change Event
248 * 0x0000000000000200 LE Enhanced Connection Complete Event
249 * 0x0000000000000400 LE Directed Advertising Report Event
250 */
251 mask |= 0x0000000000000640;
252 }
253
254 if (version >= BLE_HCI_VER_BCS_5_0) {
255 /**
256 * Enable the following LE events:
257 * 0x0000000000000800 LE PHY Update Complete Event
258 * 0x0000000000001000 LE Extended Advertising Report Event
259 * 0x0000000000010000 LE Extended Scan Timeout Event
260 * 0x0000000000020000 LE Extended Advertising Set Terminated Event
261 * 0x0000000000040000 LE Scan Request Received Event
262 * 0x0000000000080000 LE Channel Selection Algorithm Event
263 */
264 mask |= 0x00000000000f1800;
265 }
266
267 ble_hs_hci_cmd_build_le_set_event_mask(mask, buf, sizeof buf);
268 rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
269 BLE_HCI_OCF_LE_SET_EVENT_MASK),
270 buf, sizeof(buf));
271 if (rc != 0) {
272 return rc;
273 }
274
275 return 0;
276 }
277
278 static int
ble_hs_startup_set_evmask_tx(void)279 ble_hs_startup_set_evmask_tx(void)
280 {
281 uint8_t buf[BLE_HCI_SET_EVENT_MASK_LEN];
282 uint8_t version;
283 int rc;
284
285 version = ble_hs_hci_get_hci_version();
286
287 /**
288 * Enable the following events:
289 * 0x0000000000000010 Disconnection Complete Event
290 * 0x0000000000000080 Encryption Change Event
291 * 0x0000000000008000 Hardware Error Event
292 * 0x0000000002000000 Data Buffer Overflow Event
293 * 0x0000800000000000 Encryption Key Refresh Complete Event
294 * 0x2000000000000000 LE Meta-Event
295 */
296 ble_hs_hci_cmd_build_set_event_mask(0x2000800002008090, buf, sizeof buf);
297 rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
298 BLE_HCI_OCF_CB_SET_EVENT_MASK),
299 buf, sizeof(buf));
300 if (rc != 0) {
301 return rc;
302 }
303
304 if (version >= BLE_HCI_VER_BCS_4_1) {
305 /**
306 * Enable the following events:
307 * 0x0000000000800000 Authenticated Payload Timeout Event
308 */
309 ble_hs_hci_cmd_build_set_event_mask2(0x0000000000800000, buf, sizeof buf);
310 rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
311 BLE_HCI_OCF_CB_SET_EVENT_MASK2),
312 buf, sizeof(buf));
313 if (rc != 0) {
314 return rc;
315 }
316 }
317
318 return 0;
319 }
320
321 static int
ble_hs_startup_reset_tx(void)322 ble_hs_startup_reset_tx(void)
323 {
324 int rc;
325
326 rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
327 BLE_HCI_OCF_CB_RESET),
328 NULL, 0);
329 if (rc != 0) {
330 return rc;
331 }
332
333 return 0;
334 }
335
336 int
ble_hs_startup_go(void)337 ble_hs_startup_go(void)
338 {
339 int rc;
340
341 rc = ble_hs_startup_reset_tx();
342 if (rc != 0) {
343 return rc;
344 }
345
346 rc = ble_hs_startup_read_local_ver_tx();
347 if (rc != 0) {
348 return rc;
349 }
350
351 /* XXX: Read local supported commands. */
352
353 /* we need to check this only if using external controller */
354 #if !MYNEWT_VAL(BLE_DEVICE)
355 if (ble_hs_hci_get_hci_version() < BLE_HCI_VER_BCS_4_0) {
356 BLE_HS_LOG(ERROR, "Required controller version is 4.0 (6)\n");
357 return BLE_HS_ECONTROLLER;
358 }
359
360 rc = ble_hs_startup_read_sup_f_tx();
361 if (rc != 0) {
362 return rc;
363 }
364 #endif
365
366 rc = ble_hs_startup_set_evmask_tx();
367 if (rc != 0) {
368 return rc;
369 }
370
371 rc = ble_hs_startup_le_set_evmask_tx();
372 if (rc != 0) {
373 return rc;
374 }
375
376 rc = ble_hs_startup_read_buf_sz();
377 if (rc != 0) {
378 return rc;
379 }
380
381 rc = ble_hs_startup_le_read_sup_f_tx();
382 if (rc != 0) {
383 return rc;
384 }
385
386 rc = ble_hs_startup_read_bd_addr();
387 if (rc != 0) {
388 return rc;
389 }
390
391 ble_hs_pvcy_set_our_irk(NULL);
392
393 /* If flow control is enabled, configure the controller to use it. */
394 ble_hs_flow_startup();
395
396 return 0;
397 }
398