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 #include <stdint.h>
20 #include <assert.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include "os/os.h"
25 #include "nimble/hci_common.h"
26 #include "nimble/ble_hci_trans.h"
27 #include "host/ble_monitor.h"
28 #include "ble_hs_dbg_priv.h"
29 #include "ble_hs_priv.h"
30 #include "ble_monitor_priv.h"
31
32 static int
ble_hs_hci_cmd_transport(uint8_t * cmdbuf)33 ble_hs_hci_cmd_transport(uint8_t *cmdbuf)
34 {
35 int rc;
36
37 #if BLE_MONITOR
38 ble_monitor_send(BLE_MONITOR_OPCODE_COMMAND_PKT, cmdbuf,
39 cmdbuf[2] + BLE_HCI_CMD_HDR_LEN);
40 #endif
41
42 rc = ble_hci_trans_hs_cmd_tx(cmdbuf);
43 switch (rc) {
44 case 0:
45 return 0;
46
47 case BLE_ERR_MEM_CAPACITY:
48 return BLE_HS_ENOMEM_EVT;
49
50 default:
51 return BLE_HS_EUNKNOWN;
52 }
53 }
54
55 void
ble_hs_hci_cmd_write_hdr(uint8_t ogf,uint16_t ocf,uint8_t len,void * buf)56 ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint16_t ocf, uint8_t len, void *buf)
57 {
58 uint16_t opcode;
59 uint8_t *u8ptr;
60
61 u8ptr = buf;
62
63 opcode = (ogf << 10) | ocf;
64 put_le16(u8ptr, opcode);
65 u8ptr[2] = len;
66 }
67
68 static int
ble_hs_hci_cmd_send(uint16_t opcode,uint8_t len,const void * cmddata)69 ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata)
70 {
71 uint8_t *buf;
72 int rc;
73
74 buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
75 BLE_HS_DBG_ASSERT(buf != NULL);
76
77 put_le16(buf, opcode);
78 buf[2] = len;
79 if (len != 0) {
80 memcpy(buf + BLE_HCI_CMD_HDR_LEN, cmddata, len);
81 }
82
83 #if !BLE_MONITOR
84 BLE_HS_LOG(DEBUG, "ble_hs_hci_cmd_send: ogf=0x%02x ocf=0x%04x len=%d\n",
85 BLE_HCI_OGF(opcode), BLE_HCI_OCF(opcode), len);
86 ble_hs_log_flat_buf(buf, len + BLE_HCI_CMD_HDR_LEN);
87 BLE_HS_LOG(DEBUG, "\n");
88 #endif
89
90 rc = ble_hs_hci_cmd_transport(buf);
91
92 if (rc == 0) {
93 STATS_INC(ble_hs_stats, hci_cmd);
94 } else {
95 BLE_HS_LOG(DEBUG, "ble_hs_hci_cmd_send failure; rc=%d\n", rc);
96 }
97
98 return rc;
99 }
100
101 int
ble_hs_hci_cmd_send_buf(uint16_t opcode,void * buf,uint8_t buf_len)102 ble_hs_hci_cmd_send_buf(uint16_t opcode, void *buf, uint8_t buf_len)
103 {
104 switch (ble_hs_sync_state) {
105 case BLE_HS_SYNC_STATE_BAD:
106 return BLE_HS_ENOTSYNCED;
107
108 case BLE_HS_SYNC_STATE_BRINGUP:
109 if (!ble_hs_is_parent_task()) {
110 return BLE_HS_ENOTSYNCED;
111 }
112 break;
113
114 case BLE_HS_SYNC_STATE_GOOD:
115 break;
116
117 default:
118 BLE_HS_DBG_ASSERT(0);
119 return BLE_HS_EUNKNOWN;
120 }
121
122 return ble_hs_hci_cmd_send(opcode, buf_len, buf);
123 }
124
125
126 /**
127 * Send a LE command from the host to the controller.
128 *
129 * @param ocf
130 * @param len
131 * @param cmddata
132 *
133 * @return int
134 */
135 static int
ble_hs_hci_cmd_le_send(uint16_t ocf,uint8_t len,void * cmddata)136 ble_hs_hci_cmd_le_send(uint16_t ocf, uint8_t len, void *cmddata)
137 {
138 return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_LE, ocf), len, cmddata);
139 }
140
141 static int
ble_hs_hci_cmd_body_le_whitelist_chg(const uint8_t * addr,uint8_t addr_type,uint8_t * dst)142 ble_hs_hci_cmd_body_le_whitelist_chg(const uint8_t *addr, uint8_t addr_type,
143 uint8_t *dst)
144 {
145 if (addr_type > BLE_ADDR_RANDOM) {
146 return BLE_ERR_INV_HCI_CMD_PARMS;
147 }
148
149 dst[0] = addr_type;
150 memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN);
151
152 return 0;
153 }
154
155 static int
ble_hs_hci_cmd_body_le_set_adv_params(const struct hci_adv_params * adv,uint8_t * dst)156 ble_hs_hci_cmd_body_le_set_adv_params(const struct hci_adv_params *adv,
157 uint8_t *dst)
158 {
159 uint16_t itvl;
160
161 BLE_HS_DBG_ASSERT(adv != NULL);
162
163 /* Make sure parameters are valid */
164 if ((adv->adv_itvl_min > adv->adv_itvl_max) ||
165 (adv->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
166 (adv->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) ||
167 (adv->adv_filter_policy > BLE_HCI_ADV_FILT_MAX) ||
168 (adv->adv_type > BLE_HCI_ADV_TYPE_MAX) ||
169 (adv->adv_channel_map == 0) ||
170 ((adv->adv_channel_map & 0xF8) != 0)) {
171 /* These parameters are not valid */
172 return -1;
173 }
174
175 /* When build with nimBLE controller we know it is BT5 compliant so no need
176 * to limit non-connectable advertising interval
177 */
178 #if MYNEWT_VAL(BLE_DEVICE)
179 itvl = BLE_HCI_ADV_ITVL_MIN;
180 #else
181 /* Make sure interval is valid for advertising type. */
182 if (((adv->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) ||
183 (adv->adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) &&
184 ble_hs_hci_get_hci_version() < BLE_HCI_VER_BCS_5_0) {
185 itvl = BLE_HCI_ADV_ITVL_NONCONN_MIN;
186 } else {
187 itvl = BLE_HCI_ADV_ITVL_MIN;
188 }
189 #endif
190
191 /* Do not check if high duty-cycle directed */
192 if (adv->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) {
193 if ((adv->adv_itvl_min < itvl) ||
194 (adv->adv_itvl_min > BLE_HCI_ADV_ITVL_MAX)) {
195 return -1;
196 }
197 }
198
199 put_le16(dst, adv->adv_itvl_min);
200 put_le16(dst + 2, adv->adv_itvl_max);
201 dst[4] = adv->adv_type;
202 dst[5] = adv->own_addr_type;
203 dst[6] = adv->peer_addr_type;
204 memcpy(dst + 7, adv->peer_addr, BLE_DEV_ADDR_LEN);
205 dst[13] = adv->adv_channel_map;
206 dst[14] = adv->adv_filter_policy;
207
208 return 0;
209 }
210
211 int
ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params * adv,uint8_t * dst,int dst_len)212 ble_hs_hci_cmd_build_le_set_adv_params(const struct hci_adv_params *adv,
213 uint8_t *dst, int dst_len)
214 {
215 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADV_PARAM_LEN);
216
217 return ble_hs_hci_cmd_body_le_set_adv_params(adv, dst);
218 }
219
220 /**
221 * Set advertising data
222 *
223 * OGF = 0x08 (LE)
224 * OCF = 0x0008
225 *
226 * @param data
227 * @param len
228 * @param dst
229 *
230 * @return int
231 */
232 static int
ble_hs_hci_cmd_body_le_set_adv_data(const uint8_t * data,uint8_t len,uint8_t * dst)233 ble_hs_hci_cmd_body_le_set_adv_data(const uint8_t *data, uint8_t len,
234 uint8_t *dst)
235 {
236 /* Check for valid parameters */
237 if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_ADV_DATA_LEN)) {
238 return BLE_ERR_INV_HCI_CMD_PARMS;
239 }
240
241 memset(dst, 0, BLE_HCI_SET_ADV_DATA_LEN);
242 dst[0] = len;
243 memcpy(dst + 1, data, len);
244
245 return 0;
246 }
247
248 /**
249 * Set advertising data
250 *
251 * OGF = 0x08 (LE)
252 * OCF = 0x0008
253 *
254 * @param data
255 * @param len
256 * @param dst
257 *
258 * @return int
259 */
260 int
ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t * data,uint8_t len,uint8_t * dst,int dst_len)261 ble_hs_hci_cmd_build_le_set_adv_data(const uint8_t *data, uint8_t len,
262 uint8_t *dst, int dst_len)
263 {
264 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADV_DATA_LEN);
265
266 return ble_hs_hci_cmd_body_le_set_adv_data(data, len, dst);
267 }
268
269 static int
ble_hs_hci_cmd_body_le_set_scan_rsp_data(const uint8_t * data,uint8_t len,uint8_t * dst)270 ble_hs_hci_cmd_body_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
271 uint8_t *dst)
272 {
273 /* Check for valid parameters */
274 if (((data == NULL) && (len != 0)) ||
275 (len > BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) {
276 return BLE_ERR_INV_HCI_CMD_PARMS;
277 }
278
279 memset(dst, 0, BLE_HCI_SET_SCAN_RSP_DATA_LEN);
280 dst[0] = len;
281 memcpy(dst + 1, data, len);
282
283 return 0;
284 }
285
286 int
ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t * data,uint8_t len,uint8_t * dst,int dst_len)287 ble_hs_hci_cmd_build_le_set_scan_rsp_data(const uint8_t *data, uint8_t len,
288 uint8_t *dst, int dst_len)
289 {
290 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_SCAN_RSP_DATA_LEN);
291
292 return ble_hs_hci_cmd_body_le_set_scan_rsp_data(data, len, dst);
293 }
294
295 static void
ble_hs_hci_cmd_body_set_event_mask(uint64_t event_mask,uint8_t * dst)296 ble_hs_hci_cmd_body_set_event_mask(uint64_t event_mask, uint8_t *dst)
297 {
298 put_le64(dst, event_mask);
299 }
300
301 void
ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask,uint8_t * dst,int dst_len)302 ble_hs_hci_cmd_build_set_event_mask(uint64_t event_mask,
303 uint8_t *dst, int dst_len)
304 {
305 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_EVENT_MASK_LEN);
306
307 ble_hs_hci_cmd_body_set_event_mask(event_mask, dst);
308 }
309
310 void
ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask,uint8_t * dst,int dst_len)311 ble_hs_hci_cmd_build_set_event_mask2(uint64_t event_mask,
312 uint8_t *dst, int dst_len)
313 {
314 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_EVENT_MASK_LEN);
315
316 ble_hs_hci_cmd_body_set_event_mask(event_mask, dst);
317 }
318
319 static void
ble_hs_hci_cmd_body_disconnect(uint16_t handle,uint8_t reason,uint8_t * dst)320 ble_hs_hci_cmd_body_disconnect(uint16_t handle, uint8_t reason, uint8_t *dst)
321 {
322 put_le16(dst + 0, handle);
323 dst[2] = reason;
324 }
325
326 void
ble_hs_hci_cmd_build_disconnect(uint16_t handle,uint8_t reason,uint8_t * dst,int dst_len)327 ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
328 uint8_t *dst, int dst_len)
329 {
330 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_DISCONNECT_CMD_LEN);
331
332 ble_hs_hci_cmd_body_disconnect(handle, reason, dst);
333 }
334
335 static void
ble_hs_hci_cmd_body_le_set_event_mask(uint64_t event_mask,uint8_t * dst)336 ble_hs_hci_cmd_body_le_set_event_mask(uint64_t event_mask, uint8_t *dst)
337 {
338 put_le64(dst, event_mask);
339 }
340
341 void
ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask,uint8_t * dst,int dst_len)342 ble_hs_hci_cmd_build_le_set_event_mask(uint64_t event_mask,
343 uint8_t *dst, int dst_len)
344 {
345 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_LE_EVENT_MASK_LEN);
346
347 ble_hs_hci_cmd_body_le_set_event_mask(event_mask, dst);
348 }
349
350 static void
ble_hs_hci_cmd_body_le_set_adv_enable(uint8_t enable,uint8_t * dst)351 ble_hs_hci_cmd_body_le_set_adv_enable(uint8_t enable, uint8_t *dst)
352 {
353 dst[0] = enable;
354 }
355
356 void
ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable,uint8_t * dst,int dst_len)357 ble_hs_hci_cmd_build_le_set_adv_enable(uint8_t enable, uint8_t *dst,
358 int dst_len)
359 {
360 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADV_ENABLE_LEN);
361
362 ble_hs_hci_cmd_body_le_set_adv_enable(enable, dst);
363 }
364
365 static int
ble_hs_hci_cmd_body_le_set_scan_params(uint8_t scan_type,uint16_t scan_itvl,uint16_t scan_window,uint8_t own_addr_type,uint8_t filter_policy,uint8_t * dst)366 ble_hs_hci_cmd_body_le_set_scan_params(
367 uint8_t scan_type, uint16_t scan_itvl, uint16_t scan_window,
368 uint8_t own_addr_type, uint8_t filter_policy, uint8_t *dst) {
369
370 /* Make sure parameters are valid */
371 if ((scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) &&
372 (scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) {
373 return BLE_ERR_INV_HCI_CMD_PARMS;
374 }
375
376 /* Check interval and window */
377 if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
378 (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
379 (scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
380 (scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
381 (scan_itvl < scan_window)) {
382 return BLE_ERR_INV_HCI_CMD_PARMS;
383 }
384
385 /* Check own addr type */
386 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
387 return BLE_ERR_INV_HCI_CMD_PARMS;
388 }
389
390 /* Check scanner filter policy */
391 if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
392 return BLE_ERR_INV_HCI_CMD_PARMS;
393 }
394
395 dst[0] = scan_type;
396 put_le16(dst + 1, scan_itvl);
397 put_le16(dst + 3, scan_window);
398 dst[5] = own_addr_type;
399 dst[6] = filter_policy;
400
401 return 0;
402 }
403
404 int
ble_hs_hci_cmd_build_le_set_scan_params(uint8_t scan_type,uint16_t scan_itvl,uint16_t scan_window,uint8_t own_addr_type,uint8_t filter_policy,uint8_t * dst,int dst_len)405 ble_hs_hci_cmd_build_le_set_scan_params(uint8_t scan_type,
406 uint16_t scan_itvl,
407 uint16_t scan_window,
408 uint8_t own_addr_type,
409 uint8_t filter_policy,
410 uint8_t *dst, int dst_len)
411 {
412 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_SCAN_PARAM_LEN);
413
414 return ble_hs_hci_cmd_body_le_set_scan_params(scan_type, scan_itvl,
415 scan_window, own_addr_type,
416 filter_policy, dst);
417 }
418
419 static void
ble_hs_hci_cmd_body_le_set_scan_enable(uint8_t enable,uint8_t filter_dups,uint8_t * dst)420 ble_hs_hci_cmd_body_le_set_scan_enable(uint8_t enable, uint8_t filter_dups,
421 uint8_t *dst)
422 {
423 dst[0] = enable;
424 dst[1] = filter_dups;
425 }
426
427 void
ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable,uint8_t filter_dups,uint8_t * dst,uint8_t dst_len)428 ble_hs_hci_cmd_build_le_set_scan_enable(uint8_t enable, uint8_t filter_dups,
429 uint8_t *dst, uint8_t dst_len)
430 {
431 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_SCAN_ENABLE_LEN);
432
433 ble_hs_hci_cmd_body_le_set_scan_enable(enable, filter_dups, dst);
434 }
435
436 static int
ble_hs_hci_cmd_body_le_create_connection(const struct hci_create_conn * hcc,uint8_t * cmd)437 ble_hs_hci_cmd_body_le_create_connection(const struct hci_create_conn *hcc,
438 uint8_t *cmd)
439 {
440 /* Check scan interval and scan window */
441 if ((hcc->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
442 (hcc->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
443 (hcc->scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
444 (hcc->scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
445 (hcc->scan_itvl < hcc->scan_window)) {
446 return BLE_ERR_INV_HCI_CMD_PARMS;
447 }
448
449 /* Check initiator filter policy */
450 if (hcc->filter_policy > BLE_HCI_CONN_FILT_MAX) {
451 return BLE_ERR_INV_HCI_CMD_PARMS;
452 }
453
454 /* Check peer addr type */
455 if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
456 return BLE_ERR_INV_HCI_CMD_PARMS;
457 }
458
459 /* Check own addr type */
460 if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
461 return BLE_ERR_INV_HCI_CMD_PARMS;
462 }
463
464 /* Check connection interval min */
465 if ((hcc->conn_itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
466 (hcc->conn_itvl_min > BLE_HCI_CONN_ITVL_MAX)) {
467 return BLE_ERR_INV_HCI_CMD_PARMS;
468 }
469
470 /* Check connection interval max */
471 if ((hcc->conn_itvl_max < BLE_HCI_CONN_ITVL_MIN) ||
472 (hcc->conn_itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
473 (hcc->conn_itvl_max < hcc->conn_itvl_min)) {
474 return BLE_ERR_INV_HCI_CMD_PARMS;
475 }
476
477 /* Check connection latency */
478 if ((hcc->conn_latency < BLE_HCI_CONN_LATENCY_MIN) ||
479 (hcc->conn_latency > BLE_HCI_CONN_LATENCY_MAX)) {
480 return BLE_ERR_INV_HCI_CMD_PARMS;
481 }
482
483 /* Check supervision timeout */
484 if ((hcc->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
485 (hcc->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
486 return BLE_ERR_INV_HCI_CMD_PARMS;
487 }
488
489 /* Check connection event length */
490 if (hcc->min_ce_len > hcc->max_ce_len) {
491 return BLE_ERR_INV_HCI_CMD_PARMS;
492 }
493
494 put_le16(cmd + 0, hcc->scan_itvl);
495 put_le16(cmd + 2, hcc->scan_window);
496 cmd[4] = hcc->filter_policy;
497 cmd[5] = hcc->peer_addr_type;
498 memcpy(cmd + 6, hcc->peer_addr, BLE_DEV_ADDR_LEN);
499 cmd[12] = hcc->own_addr_type;
500 put_le16(cmd + 13, hcc->conn_itvl_min);
501 put_le16(cmd + 15, hcc->conn_itvl_max);
502 put_le16(cmd + 17, hcc->conn_latency);
503 put_le16(cmd + 19, hcc->supervision_timeout);
504 put_le16(cmd + 21, hcc->min_ce_len);
505 put_le16(cmd + 23, hcc->max_ce_len);
506
507 return 0;
508 }
509
510 int
ble_hs_hci_cmd_build_le_create_connection(const struct hci_create_conn * hcc,uint8_t * cmd,int cmd_len)511 ble_hs_hci_cmd_build_le_create_connection(const struct hci_create_conn *hcc,
512 uint8_t *cmd, int cmd_len)
513 {
514 BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_CREATE_CONN_LEN);
515
516 return ble_hs_hci_cmd_body_le_create_connection(hcc, cmd);
517 }
518
519 int
ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t * addr,uint8_t addr_type,uint8_t * dst,int dst_len)520 ble_hs_hci_cmd_build_le_add_to_whitelist(const uint8_t *addr,
521 uint8_t addr_type,
522 uint8_t *dst, int dst_len)
523 {
524 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_ADD_WHITE_LIST_LEN);
525
526 return ble_hs_hci_cmd_body_le_whitelist_chg(addr, addr_type, dst);
527 }
528
529 /**
530 * Reset the controller and link manager.
531 *
532 * @return int
533 */
534 int
ble_hs_hci_cmd_reset(void)535 ble_hs_hci_cmd_reset(void)
536 {
537 return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
538 BLE_HCI_OCF_CB_RESET),
539 0, NULL);
540 }
541
542 /** Set controller to host flow control (OGF 0x03, OCF 0x0031). */
543 int
ble_hs_hci_cmd_tx_set_ctlr_to_host_fc(uint8_t fc_enable)544 ble_hs_hci_cmd_tx_set_ctlr_to_host_fc(uint8_t fc_enable)
545 {
546 if (fc_enable > BLE_HCI_CTLR_TO_HOST_FC_BOTH) {
547 return BLE_HS_EINVAL;
548 }
549
550 return ble_hs_hci_cmd_tx_empty_ack(
551 BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
552 BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC),
553 &fc_enable, 1);
554 }
555
556 /* Host buffer size (OGF 0x03, OCF 0x0033). */
557 int
ble_hs_hci_cmd_tx_host_buf_size(const struct hci_host_buf_size * cmd)558 ble_hs_hci_cmd_tx_host_buf_size(const struct hci_host_buf_size *cmd)
559 {
560 uint8_t buf[BLE_HCI_HOST_BUF_SIZE_LEN];
561
562 put_le16(buf + 0, cmd->acl_pkt_len);
563 buf[2] = cmd->sync_pkt_len;
564 put_le16(buf + 3, cmd->num_acl_pkts);
565 put_le16(buf + 5, cmd->num_sync_pkts);
566
567 return ble_hs_hci_cmd_tx_empty_ack(
568 BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_HOST_BUF_SIZE),
569 buf, sizeof buf);
570 }
571
572 /* Host number of completed packets (OGF 0x03, OCF 0x0035). */
573 int
ble_hs_hci_cmd_build_host_num_comp_pkts_entry(const struct hci_host_num_comp_pkts_entry * entry,uint8_t * dst,int dst_len)574 ble_hs_hci_cmd_build_host_num_comp_pkts_entry(
575 const struct hci_host_num_comp_pkts_entry *entry,
576 uint8_t *dst, int dst_len)
577 {
578 if (dst_len < BLE_HCI_HOST_NUM_COMP_PKTS_ENT_LEN) {
579 return BLE_HS_EMSGSIZE;
580 }
581
582 put_le16(dst + 0, entry->conn_handle);
583 put_le16(dst + 2, entry->num_pkts);
584
585 return 0;
586 }
587
588 /**
589 * Read the transmit power level used for LE advertising channel packets.
590 *
591 * @return int
592 */
593 int
ble_hs_hci_cmd_read_adv_pwr(void)594 ble_hs_hci_cmd_read_adv_pwr(void)
595 {
596 return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_LE,
597 BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
598 0, NULL);
599 }
600
601 int
ble_hs_hci_cmd_le_create_conn_cancel(void)602 ble_hs_hci_cmd_le_create_conn_cancel(void)
603 {
604 return ble_hs_hci_cmd_send(BLE_HCI_OP(BLE_HCI_OGF_LE,
605 BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
606 0, NULL);
607 }
608
609 static int
ble_hs_hci_cmd_body_le_conn_update(const struct hci_conn_update * hcu,uint8_t * dst)610 ble_hs_hci_cmd_body_le_conn_update(const struct hci_conn_update *hcu,
611 uint8_t *dst)
612 {
613 /* XXX: add parameter checking later */
614 put_le16(dst + 0, hcu->handle);
615 put_le16(dst + 2, hcu->conn_itvl_min);
616 put_le16(dst + 4, hcu->conn_itvl_max);
617 put_le16(dst + 6, hcu->conn_latency);
618 put_le16(dst + 8, hcu->supervision_timeout);
619 put_le16(dst + 10, hcu->min_ce_len);
620 put_le16(dst + 12, hcu->max_ce_len);
621
622 return 0;
623 }
624
625 int
ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update * hcu,uint8_t * dst,int dst_len)626 ble_hs_hci_cmd_build_le_conn_update(const struct hci_conn_update *hcu,
627 uint8_t *dst, int dst_len)
628 {
629 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_UPDATE_LEN);
630
631 return ble_hs_hci_cmd_body_le_conn_update(hcu, dst);
632 }
633
634 int
ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update * hcu)635 ble_hs_hci_cmd_le_conn_update(const struct hci_conn_update *hcu)
636 {
637 uint8_t cmd[BLE_HCI_CONN_UPDATE_LEN];
638 int rc;
639
640 rc = ble_hs_hci_cmd_body_le_conn_update(hcu, cmd);
641 if (rc != 0) {
642 return rc;
643 }
644
645 return ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_CONN_UPDATE,
646 BLE_HCI_CONN_UPDATE_LEN, cmd);
647 }
648
649 static void
ble_hs_hci_cmd_body_le_lt_key_req_reply(const struct hci_lt_key_req_reply * hkr,uint8_t * dst)650 ble_hs_hci_cmd_body_le_lt_key_req_reply(const struct hci_lt_key_req_reply *hkr,
651 uint8_t *dst)
652 {
653 put_le16(dst + 0, hkr->conn_handle);
654 memcpy(dst + 2, hkr->long_term_key, sizeof hkr->long_term_key);
655 }
656
657 /**
658 * Sends the long-term key (LTK) to the controller.
659 *
660 * Note: This function expects the 128-bit key to be in little-endian byte
661 * order.
662 *
663 * OGF = 0x08 (LE)
664 * OCF = 0x001a
665 *
666 * @param key
667 * @param pt
668 *
669 * @return int
670 */
671 void
ble_hs_hci_cmd_build_le_lt_key_req_reply(const struct hci_lt_key_req_reply * hkr,uint8_t * dst,int dst_len)672 ble_hs_hci_cmd_build_le_lt_key_req_reply(
673 const struct hci_lt_key_req_reply *hkr, uint8_t *dst, int dst_len)
674 {
675 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LT_KEY_REQ_REPLY_LEN);
676
677 ble_hs_hci_cmd_body_le_lt_key_req_reply(hkr, dst);
678 }
679
680 void
ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,uint8_t * dst,int dst_len)681 ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(uint16_t conn_handle,
682 uint8_t *dst, int dst_len)
683 {
684 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN);
685
686 put_le16(dst, conn_handle);
687 }
688
689 static void
ble_hs_hci_cmd_body_le_conn_param_reply(const struct hci_conn_param_reply * hcr,uint8_t * dst)690 ble_hs_hci_cmd_body_le_conn_param_reply(const struct hci_conn_param_reply *hcr,
691 uint8_t *dst)
692 {
693 put_le16(dst + 0, hcr->handle);
694 put_le16(dst + 2, hcr->conn_itvl_min);
695 put_le16(dst + 4, hcr->conn_itvl_max);
696 put_le16(dst + 6, hcr->conn_latency);
697 put_le16(dst + 8, hcr->supervision_timeout);
698 put_le16(dst + 10, hcr->min_ce_len);
699 put_le16(dst + 12, hcr->max_ce_len);
700 }
701
702 void
ble_hs_hci_cmd_build_le_conn_param_reply(const struct hci_conn_param_reply * hcr,uint8_t * dst,int dst_len)703 ble_hs_hci_cmd_build_le_conn_param_reply(
704 const struct hci_conn_param_reply *hcr, uint8_t *dst, int dst_len)
705 {
706 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_PARAM_REPLY_LEN);
707
708 ble_hs_hci_cmd_body_le_conn_param_reply(hcr, dst);
709 }
710
711 int
ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply * hcr)712 ble_hs_hci_cmd_le_conn_param_reply(const struct hci_conn_param_reply *hcr)
713 {
714 uint8_t cmd[BLE_HCI_CONN_PARAM_REPLY_LEN];
715
716 put_le16(cmd + 0, hcr->handle);
717 put_le16(cmd + 2, hcr->conn_itvl_min);
718 put_le16(cmd + 4, hcr->conn_itvl_max);
719 put_le16(cmd + 6, hcr->conn_latency);
720 put_le16(cmd + 8, hcr->supervision_timeout);
721 put_le16(cmd + 10, hcr->min_ce_len);
722 put_le16(cmd + 12, hcr->max_ce_len);
723
724 return ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_RR,
725 BLE_HCI_CONN_PARAM_REPLY_LEN, cmd);
726 }
727
728 static void
ble_hs_hci_cmd_body_le_conn_param_neg_reply(const struct hci_conn_param_neg_reply * hcn,uint8_t * dst)729 ble_hs_hci_cmd_body_le_conn_param_neg_reply(
730 const struct hci_conn_param_neg_reply *hcn, uint8_t *dst)
731 {
732 put_le16(dst + 0, hcn->handle);
733 dst[2] = hcn->reason;
734 }
735
736
737 void
ble_hs_hci_cmd_build_le_conn_param_neg_reply(const struct hci_conn_param_neg_reply * hcn,uint8_t * dst,int dst_len)738 ble_hs_hci_cmd_build_le_conn_param_neg_reply(
739 const struct hci_conn_param_neg_reply *hcn, uint8_t *dst, int dst_len)
740 {
741 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_PARAM_NEG_REPLY_LEN);
742
743 ble_hs_hci_cmd_body_le_conn_param_neg_reply(hcn, dst);
744 }
745
746 int
ble_hs_hci_cmd_le_conn_param_neg_reply(const struct hci_conn_param_neg_reply * hcn)747 ble_hs_hci_cmd_le_conn_param_neg_reply(
748 const struct hci_conn_param_neg_reply *hcn)
749 {
750 uint8_t cmd[BLE_HCI_CONN_PARAM_NEG_REPLY_LEN];
751
752 ble_hs_hci_cmd_body_le_conn_param_neg_reply(hcn, cmd);
753
754 return ble_hs_hci_cmd_le_send(BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR,
755 BLE_HCI_CONN_PARAM_NEG_REPLY_LEN, cmd);
756 }
757
758 static void
ble_hs_hci_cmd_body_le_start_encrypt(const struct hci_start_encrypt * cmd,uint8_t * dst)759 ble_hs_hci_cmd_body_le_start_encrypt(const struct hci_start_encrypt *cmd,
760 uint8_t *dst)
761 {
762 put_le16(dst + 0, cmd->connection_handle);
763 put_le64(dst + 2, cmd->random_number);
764 put_le16(dst + 10, cmd->encrypted_diversifier);
765 memcpy(dst + 12, cmd->long_term_key, sizeof cmd->long_term_key);
766 }
767
768 /*
769 * OGF=0x08 OCF=0x0019
770 */
771 void
ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt * cmd,uint8_t * dst,int dst_len)772 ble_hs_hci_cmd_build_le_start_encrypt(const struct hci_start_encrypt *cmd,
773 uint8_t *dst, int dst_len)
774 {
775 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_START_ENCRYPT_LEN);
776
777 ble_hs_hci_cmd_body_le_start_encrypt(cmd, dst);
778 }
779
780 /**
781 * Read the RSSI for a given connection handle
782 *
783 * NOTE: OGF=0x05 OCF=0x0005
784 *
785 * @param handle
786 *
787 * @return int
788 */
789 static void
ble_hs_hci_cmd_body_read_rssi(uint16_t handle,uint8_t * dst)790 ble_hs_hci_cmd_body_read_rssi(uint16_t handle, uint8_t *dst)
791 {
792 put_le16(dst, handle);
793 }
794
795 void
ble_hs_hci_cmd_build_read_rssi(uint16_t handle,uint8_t * dst,int dst_len)796 ble_hs_hci_cmd_build_read_rssi(uint16_t handle, uint8_t *dst, int dst_len)
797 {
798 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_READ_RSSI_LEN);
799
800 ble_hs_hci_cmd_body_read_rssi(handle, dst);
801 }
802
803 /**
804 * LE Set Host Channel Classification
805 *
806 * OGF = 0x08 (LE)
807 * OCF = 0x0014
808 */
809 void
ble_hs_hci_cmd_build_le_set_host_chan_class(const uint8_t * chan_map,uint8_t * dst,int dst_len)810 ble_hs_hci_cmd_build_le_set_host_chan_class(const uint8_t *chan_map,
811 uint8_t *dst, int dst_len)
812 {
813 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_HOST_CHAN_CLASS_LEN);
814
815 memcpy(dst, chan_map, BLE_HCI_SET_HOST_CHAN_CLASS_LEN);
816 }
817
818 /**
819 * LE Read Channel Map
820 *
821 * OGF = 0x08 (LE)
822 * OCF = 0x0015
823 */
824 void
ble_hs_hci_cmd_build_le_read_chan_map(uint16_t conn_handle,uint8_t * dst,int dst_len)825 ble_hs_hci_cmd_build_le_read_chan_map(uint16_t conn_handle,
826 uint8_t *dst, int dst_len)
827 {
828 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RD_CHANMAP_LEN);
829
830 put_le16(dst + 0, conn_handle);
831 }
832
833 static int
ble_hs_hci_cmd_body_set_data_len(uint16_t connection_handle,uint16_t tx_octets,uint16_t tx_time,uint8_t * dst)834 ble_hs_hci_cmd_body_set_data_len(uint16_t connection_handle,
835 uint16_t tx_octets,
836 uint16_t tx_time, uint8_t *dst)
837 {
838
839 if (tx_octets < BLE_HCI_SET_DATALEN_TX_OCTETS_MIN ||
840 tx_octets > BLE_HCI_SET_DATALEN_TX_OCTETS_MAX) {
841
842 return BLE_HS_EINVAL;
843 }
844
845 if (tx_time < BLE_HCI_SET_DATALEN_TX_TIME_MIN ||
846 tx_time > BLE_HCI_SET_DATALEN_TX_TIME_MAX) {
847
848 return BLE_HS_EINVAL;
849 }
850
851 put_le16(dst + 0, connection_handle);
852 put_le16(dst + 2, tx_octets);
853 put_le16(dst + 4, tx_time);
854
855 return 0;
856 }
857
858 /*
859 * OGF=0x08 OCF=0x0022
860 */
861 int
ble_hs_hci_cmd_build_set_data_len(uint16_t connection_handle,uint16_t tx_octets,uint16_t tx_time,uint8_t * dst,int dst_len)862 ble_hs_hci_cmd_build_set_data_len(uint16_t connection_handle,
863 uint16_t tx_octets, uint16_t tx_time,
864 uint8_t *dst, int dst_len)
865 {
866 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_DATALEN_LEN);
867
868 return ble_hs_hci_cmd_body_set_data_len(connection_handle, tx_octets,
869 tx_time, dst);
870 }
871
872 /**
873 * IRKs are in little endian.
874 */
875 static int
ble_hs_hci_cmd_body_add_to_resolv_list(uint8_t addr_type,const uint8_t * addr,const uint8_t * peer_irk,const uint8_t * local_irk,uint8_t * dst)876 ble_hs_hci_cmd_body_add_to_resolv_list(uint8_t addr_type, const uint8_t *addr,
877 const uint8_t *peer_irk,
878 const uint8_t *local_irk,
879 uint8_t *dst)
880 {
881 if (addr_type > BLE_ADDR_RANDOM) {
882 return BLE_ERR_INV_HCI_CMD_PARMS;
883 }
884
885 dst[0] = addr_type;
886 memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN);
887 memcpy(dst + 1 + 6, peer_irk , 16);
888 memcpy(dst + 1 + 6 + 16, local_irk , 16);
889 /* 16 + 16 + 6 + 1 == 39 */
890 return 0;
891 }
892
893 /**
894 * OGF=0x08 OCF=0x0027
895 *
896 * IRKs are in little endian.
897 */
898 int
ble_hs_hci_cmd_build_add_to_resolv_list(const struct hci_add_dev_to_resolving_list * padd,uint8_t * dst,int dst_len)899 ble_hs_hci_cmd_build_add_to_resolv_list(
900 const struct hci_add_dev_to_resolving_list *padd,
901 uint8_t *dst,
902 int dst_len)
903 {
904 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_ADD_TO_RESOLV_LIST_LEN);
905
906 return ble_hs_hci_cmd_body_add_to_resolv_list(
907 padd->addr_type, padd->addr, padd->peer_irk, padd->local_irk, dst);
908 }
909
910 static int
ble_hs_hci_cmd_body_remove_from_resolv_list(uint8_t addr_type,const uint8_t * addr,uint8_t * dst)911 ble_hs_hci_cmd_body_remove_from_resolv_list(uint8_t addr_type,
912 const uint8_t *addr,
913 uint8_t *dst)
914 {
915 if (addr_type > BLE_ADDR_RANDOM) {
916 return BLE_ERR_INV_HCI_CMD_PARMS;
917 }
918
919 dst[0] = addr_type;
920 memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN);
921 return 0;
922 }
923
924
925 int
ble_hs_hci_cmd_build_remove_from_resolv_list(uint8_t addr_type,const uint8_t * addr,uint8_t * dst,int dst_len)926 ble_hs_hci_cmd_build_remove_from_resolv_list(uint8_t addr_type,
927 const uint8_t *addr,
928 uint8_t *dst, int dst_len)
929 {
930 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RMV_FROM_RESOLV_LIST_LEN);
931
932 return ble_hs_hci_cmd_body_remove_from_resolv_list(addr_type, addr, dst);
933 }
934
935 static int
ble_hs_hci_cmd_body_read_peer_resolv_addr(uint8_t peer_identity_addr_type,const uint8_t * peer_identity_addr,uint8_t * dst)936 ble_hs_hci_cmd_body_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
937 const uint8_t *peer_identity_addr,
938 uint8_t *dst)
939 {
940 if (peer_identity_addr_type > BLE_ADDR_RANDOM) {
941 return BLE_ERR_INV_HCI_CMD_PARMS;
942 }
943
944 dst[0] = peer_identity_addr_type;
945 memcpy(dst + 1, peer_identity_addr, BLE_DEV_ADDR_LEN);
946 return 0;
947 }
948
949 int
ble_hs_hci_cmd_build_read_peer_resolv_addr(uint8_t peer_identity_addr_type,const uint8_t * peer_identity_addr,uint8_t * dst,int dst_len)950 ble_hs_hci_cmd_build_read_peer_resolv_addr(uint8_t peer_identity_addr_type,
951 const uint8_t *peer_identity_addr,
952 uint8_t *dst,
953 int dst_len)
954 {
955 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RD_PEER_RESOLV_ADDR_LEN);
956
957 return ble_hs_hci_cmd_body_read_peer_resolv_addr(peer_identity_addr_type,
958 peer_identity_addr, dst);
959 }
960
961 static int
ble_hs_hci_cmd_body_read_lcl_resolv_addr(uint8_t local_identity_addr_type,const uint8_t * local_identity_addr,uint8_t * dst)962 ble_hs_hci_cmd_body_read_lcl_resolv_addr(
963 uint8_t local_identity_addr_type,
964 const uint8_t *local_identity_addr,
965 uint8_t *dst)
966 {
967 if (local_identity_addr_type > BLE_ADDR_RANDOM) {
968 return BLE_ERR_INV_HCI_CMD_PARMS;
969 }
970
971 dst[0] = local_identity_addr_type;
972 memcpy(dst + 1, local_identity_addr, BLE_DEV_ADDR_LEN);
973 return 0;
974 }
975
976 /*
977 * OGF=0x08 OCF=0x002c
978 */
979 int
ble_hs_hci_cmd_build_read_lcl_resolv_addr(uint8_t local_identity_addr_type,const uint8_t * local_identity_addr,uint8_t * dst,int dst_len)980 ble_hs_hci_cmd_build_read_lcl_resolv_addr(uint8_t local_identity_addr_type,
981 const uint8_t *local_identity_addr,
982 uint8_t *dst,
983 int dst_len)
984 {
985 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_RD_LOC_RESOLV_ADDR_LEN);
986
987 return ble_hs_hci_cmd_body_read_lcl_resolv_addr(local_identity_addr_type,
988 local_identity_addr, dst);
989 }
990
991 static int
ble_hs_hci_cmd_body_set_addr_res_en(uint8_t enable,uint8_t * dst)992 ble_hs_hci_cmd_body_set_addr_res_en(uint8_t enable, uint8_t *dst)
993 {
994 if (enable > 1) {
995 return BLE_ERR_INV_HCI_CMD_PARMS;
996 }
997
998 dst[0] = enable;
999 return 0;
1000 }
1001
1002 /*
1003 * OGF=0x08 OCF=0x002d
1004 */
1005 int
ble_hs_hci_cmd_build_set_addr_res_en(uint8_t enable,uint8_t * dst,int dst_len)1006 ble_hs_hci_cmd_build_set_addr_res_en(uint8_t enable, uint8_t *dst, int dst_len)
1007 {
1008 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_ADDR_RESOL_ENA_LEN);
1009
1010 return ble_hs_hci_cmd_body_set_addr_res_en(enable, dst);
1011 }
1012
1013 static int
ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(uint16_t timeout,uint8_t * dst)1014 ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(uint16_t timeout,
1015 uint8_t *dst)
1016 {
1017 if (timeout == 0 || timeout > 0xA1B8) {
1018 return BLE_ERR_INV_HCI_CMD_PARMS;
1019 }
1020
1021 put_le16(dst, timeout);
1022 return 0;
1023 }
1024
1025 /*
1026 * OGF=0x08 OCF=0x002e
1027 */
1028 int
ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(uint16_t timeout,uint8_t * dst,int dst_len)1029 ble_hs_hci_cmd_build_set_resolv_priv_addr_timeout(
1030 uint16_t timeout, uint8_t *dst, int dst_len)
1031 {
1032 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN);
1033
1034 return ble_hs_hci_cmd_body_set_resolv_priv_addr_timeout(timeout, dst);
1035 }
1036
1037 /*
1038 * OGF=0x08 OCF=0x0030
1039 */
1040 int
ble_hs_hci_cmd_build_le_read_phy(uint16_t conn_handle,uint8_t * dst,int dst_len)1041 ble_hs_hci_cmd_build_le_read_phy(uint16_t conn_handle, uint8_t *dst, int dst_len)
1042 {
1043 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_RD_PHY_LEN);
1044
1045 put_le16(dst, conn_handle);
1046
1047 return 0;
1048 }
1049
1050 static int
ble_hs_hci_verify_le_phy_params(uint8_t tx_phys_mask,uint8_t rx_phys_mask,uint16_t phy_opts)1051 ble_hs_hci_verify_le_phy_params(uint8_t tx_phys_mask, uint8_t rx_phys_mask,
1052 uint16_t phy_opts)
1053 {
1054 if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
1055 BLE_HCI_LE_PHY_2M_PREF_MASK |
1056 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
1057 return BLE_ERR_INV_HCI_CMD_PARMS;
1058 }
1059
1060 if (rx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
1061 BLE_HCI_LE_PHY_2M_PREF_MASK |
1062 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
1063 return BLE_ERR_INV_HCI_CMD_PARMS;
1064 }
1065
1066 if (phy_opts > BLE_HCI_LE_PHY_CODED_S8_PREF) {
1067 return BLE_ERR_INV_HCI_CMD_PARMS;
1068 }
1069
1070 return 0;
1071 }
1072
1073 static int
ble_hs_hci_cmd_body_le_set_default_phy(uint8_t tx_phys_mask,uint8_t rx_phys_mask,uint8_t * dst)1074 ble_hs_hci_cmd_body_le_set_default_phy(uint8_t tx_phys_mask,
1075 uint8_t rx_phys_mask, uint8_t *dst)
1076 {
1077 int rc;
1078
1079 rc = ble_hs_hci_verify_le_phy_params(tx_phys_mask, rx_phys_mask, 0);
1080 if (rc !=0 ) {
1081 return rc;
1082 }
1083
1084 if (tx_phys_mask == 0) {
1085 dst[0] |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK;
1086 } else {
1087 dst[1] = tx_phys_mask;
1088 }
1089
1090 if (rx_phys_mask == 0){
1091 dst[0] |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK;
1092 } else {
1093 dst[2] = rx_phys_mask;
1094 }
1095
1096 return 0;
1097 }
1098
1099 /*
1100 * OGF=0x08 OCF=0x0031
1101 */
1102 int
ble_hs_hci_cmd_build_le_set_default_phy(uint8_t tx_phys_mask,uint8_t rx_phys_mask,uint8_t * dst,int dst_len)1103 ble_hs_hci_cmd_build_le_set_default_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask,
1104 uint8_t *dst, int dst_len)
1105 {
1106
1107 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_DEFAULT_PHY_LEN);
1108
1109 memset(dst, 0, dst_len);
1110
1111 return ble_hs_hci_cmd_body_le_set_default_phy(tx_phys_mask, rx_phys_mask,
1112 dst);
1113 }
1114
1115 static int
ble_hs_hci_cmd_body_le_set_phy(uint16_t conn_handle,uint8_t tx_phys_mask,uint8_t rx_phys_mask,uint16_t phy_opts,uint8_t * dst)1116 ble_hs_hci_cmd_body_le_set_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
1117 uint8_t rx_phys_mask, uint16_t phy_opts,
1118 uint8_t *dst)
1119 {
1120 int rc;
1121
1122 rc = ble_hs_hci_verify_le_phy_params(tx_phys_mask, rx_phys_mask, phy_opts);
1123 if (rc != 0) {
1124 return rc;
1125 }
1126
1127 put_le16(dst, conn_handle);
1128
1129 if (tx_phys_mask == 0) {
1130 dst[2] |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK;
1131 } else {
1132 dst[3] = tx_phys_mask;
1133 }
1134
1135 if (rx_phys_mask == 0){
1136 dst[2] |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK;
1137 } else {
1138 dst[4] = rx_phys_mask;
1139 }
1140
1141 put_le16(dst + 5, phy_opts);
1142
1143 return 0;
1144 }
1145
1146 /*
1147 * OGF=0x08 OCF=0x0032
1148 */
1149 int
ble_hs_hci_cmd_build_le_set_phy(uint16_t conn_handle,uint8_t tx_phys_mask,uint8_t rx_phys_mask,uint16_t phy_opts,uint8_t * dst,int dst_len)1150 ble_hs_hci_cmd_build_le_set_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
1151 uint8_t rx_phys_mask, uint16_t phy_opts,
1152 uint8_t *dst, int dst_len)
1153 {
1154
1155 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_PHY_LEN);
1156
1157 memset(dst, 0, dst_len);
1158
1159 return ble_hs_hci_cmd_body_le_set_phy(conn_handle, tx_phys_mask,
1160 rx_phys_mask, phy_opts, dst);
1161 }
1162
1163 static int
ble_hs_hci_cmd_body_le_enhanced_recv_test(uint8_t chan,uint8_t phy,uint8_t mod_idx,uint8_t * dst)1164 ble_hs_hci_cmd_body_le_enhanced_recv_test(uint8_t chan, uint8_t phy,
1165 uint8_t mod_idx, uint8_t *dst)
1166 {
1167 /* Parameters check according to Bluetooth 5.0 Vol 2, Part E
1168 * 7.8.50 LE Enhanced Receiver Test Command
1169 */
1170 if (phy > BLE_HCI_LE_PHY_CODED || chan > 0x27 || mod_idx > 1) {
1171 return BLE_ERR_INV_HCI_CMD_PARMS;
1172 }
1173
1174 dst[0] = chan;
1175 dst[1] = phy;
1176 dst[2] = mod_idx;
1177
1178 return 0;
1179 }
1180
1181 /*
1182 * OGF=0x08 OCF=0x0033
1183 */
1184 int
ble_hs_hci_cmd_build_le_enh_recv_test(uint8_t rx_chan,uint8_t phy,uint8_t mod_idx,uint8_t * dst,uint16_t dst_len)1185 ble_hs_hci_cmd_build_le_enh_recv_test(uint8_t rx_chan, uint8_t phy,
1186 uint8_t mod_idx,
1187 uint8_t *dst, uint16_t dst_len)
1188 {
1189 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_RX_TEST_LEN);
1190
1191 return ble_hs_hci_cmd_body_le_enhanced_recv_test(rx_chan, phy, mod_idx, dst);
1192 }
1193
1194 static int
ble_hs_hci_cmd_body_le_enhanced_trans_test(uint8_t chan,uint8_t test_data_len,uint8_t packet_payload_idx,uint8_t phy,uint8_t * dst)1195 ble_hs_hci_cmd_body_le_enhanced_trans_test(uint8_t chan, uint8_t test_data_len,
1196 uint8_t packet_payload_idx,
1197 uint8_t phy,
1198 uint8_t *dst)
1199 {
1200 /* Parameters check according to Bluetooth 5.0 Vol 2, Part E
1201 * 7.8.51 LE Enhanced Transmitter Test Command
1202 */
1203 if (phy > BLE_HCI_LE_PHY_CODED_S2 || chan > 0x27 ||
1204 packet_payload_idx > 0x07) {
1205 return BLE_ERR_INV_HCI_CMD_PARMS;
1206 }
1207
1208 dst[0] = chan;
1209 dst[1] = test_data_len;
1210 dst[2] = packet_payload_idx;
1211 dst[3] = phy;
1212
1213 return 0;
1214 }
1215
1216 /*
1217 * OGF=0x08 OCF=0x0034
1218 */
1219 int
ble_hs_hci_cmd_build_le_enh_trans_test(uint8_t tx_chan,uint8_t test_data_len,uint8_t packet_payload_idx,uint8_t phy,uint8_t * dst,uint16_t dst_len)1220 ble_hs_hci_cmd_build_le_enh_trans_test(uint8_t tx_chan, uint8_t test_data_len,
1221 uint8_t packet_payload_idx, uint8_t phy,
1222 uint8_t *dst, uint16_t dst_len)
1223 {
1224 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_ENH_TX_TEST_LEN);
1225
1226 return ble_hs_hci_cmd_body_le_enhanced_trans_test(tx_chan, test_data_len,
1227 packet_payload_idx,
1228 phy, dst);
1229 }
1230
1231 #if MYNEWT_VAL(BLE_EXT_ADV)
1232 static int
ble_hs_hci_check_scan_params(uint16_t scan_itvl,uint16_t scan_window)1233 ble_hs_hci_check_scan_params(uint16_t scan_itvl, uint16_t scan_window)
1234 {
1235 /* Check interval and window */
1236 if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
1237 (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
1238 (scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
1239 (scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
1240 (scan_itvl < scan_window)) {
1241 return BLE_ERR_INV_HCI_CMD_PARMS;
1242 }
1243
1244 return 0;
1245 }
1246
1247 static int
ble_hs_hci_cmd_body_le_set_ext_scan_param(uint8_t own_addr_type,uint8_t filter_policy,uint8_t phy_mask,uint8_t phy_count,struct ble_hs_hci_ext_scan_param * params[],uint8_t * dst)1248 ble_hs_hci_cmd_body_le_set_ext_scan_param(uint8_t own_addr_type,
1249 uint8_t filter_policy,
1250 uint8_t phy_mask,
1251 uint8_t phy_count,
1252 struct ble_hs_hci_ext_scan_param *params[],
1253 uint8_t *dst)
1254 {
1255 int i;
1256 int rc;
1257 uint8_t *dst_params;
1258 struct ble_hs_hci_ext_scan_param *p;
1259
1260 if (phy_mask >
1261 (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
1262 return BLE_ERR_INV_HCI_CMD_PARMS;
1263 }
1264
1265 /* Check own addr type */
1266 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
1267 return BLE_ERR_INV_HCI_CMD_PARMS;
1268 }
1269
1270 /* Check scanner filter policy */
1271 if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
1272 return BLE_ERR_INV_HCI_CMD_PARMS;
1273 }
1274
1275 dst[0] = own_addr_type;
1276 dst[1] = filter_policy;
1277 dst[2] = phy_mask;
1278 dst_params = &dst[3];
1279
1280 for (i = 0; i < phy_count; i++) {
1281 p = (*params) + i;
1282 rc = ble_hs_hci_check_scan_params(p->scan_itvl, p->scan_window);
1283 if (rc) {
1284 return rc;
1285 }
1286
1287 dst_params[0] = p->scan_type;
1288 put_le16(dst_params + 1, p->scan_itvl);
1289 put_le16(dst_params + 3, p->scan_window);
1290
1291 dst_params += BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN;
1292 }
1293
1294 return 0;
1295 }
1296
1297 /*
1298 * OGF=0x08 OCF=0x0041
1299 */
1300 int
ble_hs_hci_cmd_build_le_set_ext_scan_params(uint8_t own_addr_type,uint8_t filter_policy,uint8_t phy_mask,uint8_t phy_count,struct ble_hs_hci_ext_scan_param * params[],uint8_t * dst,uint16_t dst_len)1301 ble_hs_hci_cmd_build_le_set_ext_scan_params(uint8_t own_addr_type,
1302 uint8_t filter_policy,
1303 uint8_t phy_mask,
1304 uint8_t phy_count,
1305 struct ble_hs_hci_ext_scan_param *params[],
1306 uint8_t *dst, uint16_t dst_len)
1307 {
1308 if (phy_count == 0) {
1309 return BLE_ERR_INV_HCI_CMD_PARMS;
1310 }
1311
1312 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_EXT_SCAN_BASE_LEN +
1313 BLE_HCI_LE_EXT_SCAN_SINGLE_PARAM_LEN * phy_count);
1314
1315 return ble_hs_hci_cmd_body_le_set_ext_scan_param(own_addr_type,
1316 filter_policy,
1317 phy_mask,
1318 phy_count,
1319 params,
1320 dst);
1321 }
1322
1323 static int
ble_hs_hci_cmd_body_le_set_ext_scan_enable(uint8_t enable,uint8_t filter_dups,uint16_t duration,uint16_t period,uint8_t * dst)1324 ble_hs_hci_cmd_body_le_set_ext_scan_enable(uint8_t enable, uint8_t filter_dups,
1325 uint16_t duration, uint16_t period,
1326 uint8_t *dst)
1327 {
1328 if (enable > 0x01 || filter_dups > 0x03) {
1329 return BLE_ERR_INV_HCI_CMD_PARMS;
1330 }
1331
1332 dst[0] = enable;
1333 dst[1] = filter_dups;
1334 put_le16(dst + 2, duration);
1335 put_le16(dst + 4, period);
1336
1337 return 0;
1338 }
1339
1340 /*
1341 * OGF=0x08 OCF=0x0042
1342 */
1343 int
ble_hs_hci_cmd_build_le_set_ext_scan_enable(uint8_t enable,uint8_t filter_dups,uint16_t duration,uint16_t period,uint8_t * dst,uint16_t dst_len)1344 ble_hs_hci_cmd_build_le_set_ext_scan_enable(uint8_t enable,
1345 uint8_t filter_dups,
1346 uint16_t duration,
1347 uint16_t period,
1348 uint8_t *dst, uint16_t dst_len)
1349 {
1350
1351 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_EXT_SCAN_ENABLE_LEN);
1352
1353 return ble_hs_hci_cmd_body_le_set_ext_scan_enable(enable, filter_dups,
1354 duration, period, dst);
1355 }
1356
1357 static int
ble_hs_hci_check_conn_params(uint8_t phy,const struct hci_ext_conn_params * params)1358 ble_hs_hci_check_conn_params(uint8_t phy,
1359 const struct hci_ext_conn_params *params)
1360 {
1361 if (phy != BLE_HCI_LE_PHY_2M) {
1362 if (ble_hs_hci_check_scan_params(params->scan_itvl, params->scan_window)) {
1363 return BLE_ERR_INV_HCI_CMD_PARMS;
1364 }
1365 }
1366 /* Check connection interval min */
1367 if ((params->conn_itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
1368 (params->conn_itvl_min > BLE_HCI_CONN_ITVL_MAX)) {
1369 return BLE_ERR_INV_HCI_CMD_PARMS;
1370 }
1371 /* Check connection interval max */
1372 if ((params->conn_itvl_max < BLE_HCI_CONN_ITVL_MIN) ||
1373 (params->conn_itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
1374 (params->conn_itvl_max < params->conn_itvl_min)) {
1375 return BLE_ERR_INV_HCI_CMD_PARMS;
1376 }
1377
1378 /* Check connection latency */
1379 if ((params->conn_latency < BLE_HCI_CONN_LATENCY_MIN) ||
1380 (params->conn_latency > BLE_HCI_CONN_LATENCY_MAX)) {
1381 return BLE_ERR_INV_HCI_CMD_PARMS;
1382 }
1383
1384 /* Check supervision timeout */
1385 if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
1386 (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
1387 return BLE_ERR_INV_HCI_CMD_PARMS;
1388 }
1389
1390 /* Check connection event length */
1391 if (params->min_ce_len > params->max_ce_len) {
1392 return BLE_ERR_INV_HCI_CMD_PARMS;
1393 }
1394
1395 return 0;
1396 }
1397
1398 static int
ble_hs_hci_cmd_body_le_ext_create_conn(const struct hci_ext_create_conn * hcc,uint8_t * cmd)1399 ble_hs_hci_cmd_body_le_ext_create_conn(const struct hci_ext_create_conn *hcc,
1400 uint8_t *cmd)
1401 {
1402 int iter = 0;
1403 const struct hci_ext_conn_params *params;
1404
1405 /* Check initiator filter policy */
1406 if (hcc->filter_policy > BLE_HCI_CONN_FILT_MAX) {
1407 return BLE_ERR_INV_HCI_CMD_PARMS;
1408 }
1409 cmd[iter] = hcc->filter_policy;
1410 iter++;
1411 /* Check own addr type */
1412 if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
1413 return BLE_ERR_INV_HCI_CMD_PARMS;
1414 }
1415 cmd[iter] = hcc->own_addr_type;
1416 iter++;
1417
1418 /* Check peer addr type */
1419 if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
1420 return BLE_ERR_INV_HCI_CMD_PARMS;
1421 }
1422 cmd[iter] = hcc->peer_addr_type;
1423 iter++;
1424
1425 memcpy(cmd + iter, hcc->peer_addr, BLE_DEV_ADDR_LEN);
1426 iter += BLE_DEV_ADDR_LEN;
1427
1428 if (hcc->init_phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
1429 BLE_HCI_LE_PHY_2M_PREF_MASK |
1430 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
1431 return BLE_ERR_INV_HCI_CMD_PARMS;
1432 }
1433 cmd[iter] = hcc->init_phy_mask;
1434 iter++;
1435
1436 if (hcc->init_phy_mask & BLE_HCI_LE_PHY_1M_PREF_MASK) {
1437 params = &hcc->params[0];
1438 if (ble_hs_hci_check_conn_params(BLE_HCI_LE_PHY_1M, params)) {
1439 return BLE_ERR_INV_HCI_CMD_PARMS;
1440 }
1441 put_le16(cmd + iter, params->scan_itvl);
1442 put_le16(cmd + iter + 2, params->scan_window);
1443 put_le16(cmd + iter + 4, params->conn_itvl_min);
1444 put_le16(cmd + iter + 6, params->conn_itvl_max);
1445 put_le16(cmd + iter + 8, params->conn_latency);
1446 put_le16(cmd + iter + 10, params->supervision_timeout);
1447 put_le16(cmd + iter + 12, params->min_ce_len);
1448 put_le16(cmd + iter + 14, params->max_ce_len);
1449 iter += 16;
1450 }
1451
1452 if (hcc->init_phy_mask & BLE_HCI_LE_PHY_2M_PREF_MASK) {
1453 params = &hcc->params[1];
1454 if (ble_hs_hci_check_conn_params(BLE_HCI_LE_PHY_2M, params)) {
1455 return BLE_ERR_INV_HCI_CMD_PARMS;
1456 }
1457 put_le16(cmd + iter, 0);
1458 put_le16(cmd + iter + 2, 0);
1459 put_le16(cmd + iter + 4, params->conn_itvl_min);
1460 put_le16(cmd + iter + 6, params->conn_itvl_max);
1461 put_le16(cmd + iter + 8, params->conn_latency);
1462 put_le16(cmd + iter + 10, params->supervision_timeout);
1463 put_le16(cmd + iter + 12, params->min_ce_len);
1464 put_le16(cmd + iter + 14, params->max_ce_len);
1465 iter += 16;
1466 }
1467
1468 if (hcc->init_phy_mask & BLE_HCI_LE_PHY_CODED_PREF_MASK) {
1469 params = &hcc->params[2];
1470 if (ble_hs_hci_check_conn_params(BLE_HCI_LE_PHY_CODED, params)) {
1471 return BLE_ERR_INV_HCI_CMD_PARMS;
1472 }
1473 put_le16(cmd + iter, params->scan_itvl);
1474 put_le16(cmd + iter + 2, params->scan_window);
1475 put_le16(cmd + iter + 4, params->conn_itvl_min);
1476 put_le16(cmd + iter + 6, params->conn_itvl_max);
1477 put_le16(cmd + iter + 8, params->conn_latency);
1478 put_le16(cmd + iter + 10, params->supervision_timeout);
1479 put_le16(cmd + iter + 12, params->min_ce_len);
1480 put_le16(cmd + iter + 14, params->max_ce_len);
1481 iter += 16;
1482 }
1483
1484 return 0;
1485 }
1486
1487 int
ble_hs_hci_cmd_build_le_ext_create_conn(const struct hci_ext_create_conn * hcc,uint8_t * cmd,int cmd_len)1488 ble_hs_hci_cmd_build_le_ext_create_conn(const struct hci_ext_create_conn *hcc,
1489 uint8_t *cmd, int cmd_len)
1490 {
1491 uint8_t size;
1492
1493 size = BLE_HCI_LE_EXT_CREATE_CONN_BASE_LEN;
1494 if (hcc->init_phy_mask & BLE_HCI_LE_PHY_1M_PREF_MASK) {
1495 size += sizeof(struct hci_ext_conn_params);
1496 }
1497
1498 if (hcc->init_phy_mask & BLE_HCI_LE_PHY_2M_PREF_MASK) {
1499 size += sizeof(struct hci_ext_conn_params);
1500 }
1501
1502 if (hcc->init_phy_mask & BLE_HCI_LE_PHY_CODED_PREF_MASK) {
1503 size += sizeof(struct hci_ext_conn_params);
1504 }
1505
1506 BLE_HS_DBG_ASSERT(cmd_len >= size);
1507
1508 return ble_hs_hci_cmd_body_le_ext_create_conn(hcc, cmd);
1509 }
1510
1511 int
ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle,const uint8_t * addr,uint8_t * cmd,int cmd_len)1512 ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle,
1513 const uint8_t *addr,
1514 uint8_t *cmd, int cmd_len)
1515 {
1516 BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN);
1517
1518 cmd[0] = handle;
1519 memcpy(cmd + 1, addr, BLE_DEV_ADDR_LEN);
1520
1521 return 0;
1522 }
1523
1524 int
ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle,uint8_t operation,uint8_t frag_pref,struct os_mbuf * data,uint8_t data_len,uint8_t * cmd,int cmd_len)1525 ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation,
1526 uint8_t frag_pref, struct os_mbuf *data,
1527 uint8_t data_len,
1528 uint8_t *cmd, int cmd_len)
1529 {
1530 BLE_HS_DBG_ASSERT(cmd_len >= 4 + data_len);
1531
1532 cmd[0] = handle;
1533 cmd[1] = operation;
1534 cmd[2] = frag_pref;
1535 cmd[3] = data_len;
1536 os_mbuf_copydata(data, 0, data_len, cmd + 4);
1537
1538 return 0;
1539 }
1540
1541 int
ble_hs_hci_cmd_build_le_ext_adv_enable(uint8_t enable,uint8_t sets_num,const struct hci_ext_adv_set * sets,uint8_t * cmd,int cmd_len)1542 ble_hs_hci_cmd_build_le_ext_adv_enable(uint8_t enable, uint8_t sets_num,
1543 const struct hci_ext_adv_set *sets,
1544 uint8_t *cmd, int cmd_len)
1545 {
1546 int i;
1547
1548 BLE_HS_DBG_ASSERT(cmd_len >= 2 + (sets_num * 4));
1549
1550 cmd[0] = enable;
1551 cmd[1] = sets_num;
1552
1553 cmd += 2;
1554
1555 for (i = 0; i < sets_num; i++) {
1556 cmd[0] = sets[i].handle;
1557 put_le16(&cmd[1], sets[i].duration);
1558 cmd[3] = sets[i].events;
1559
1560 cmd += 4;
1561 }
1562
1563 return 0;
1564 }
1565
1566 int
ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,const struct hci_ext_adv_params * params,uint8_t * cmd,int cmd_len)1567 ble_hs_hci_cmd_build_le_ext_adv_params(uint8_t handle,
1568 const struct hci_ext_adv_params *params,
1569 uint8_t *cmd, int cmd_len)
1570 {
1571 uint32_t tmp;
1572
1573 BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN);
1574
1575 cmd[0] = handle;
1576 put_le16(&cmd[1], params->properties);
1577
1578 tmp = htole32(params->min_interval);
1579 memcpy(&cmd[3], &tmp, 3);
1580
1581 tmp = htole32(params->max_interval);
1582 memcpy(&cmd[6], &tmp, 3);
1583
1584 cmd[9] = params->chan_map;
1585 cmd[10] = params->own_addr_type;
1586 cmd[11] = params->peer_addr_type;
1587 memcpy(&cmd[12], params->peer_addr, BLE_DEV_ADDR_LEN);
1588 cmd[18] = params->filter_policy;
1589 cmd[19] = params->tx_power;
1590 cmd[20] = params->primary_phy;
1591 cmd[21] = params->max_skip;
1592 cmd[22] = params->secondary_phy;
1593 cmd[23] = params->sid;
1594 cmd[24] = params->scan_req_notif;
1595
1596 return 0;
1597 }
1598 int
ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,uint8_t * cmd,int cmd_len)1599 ble_hs_hci_cmd_build_le_ext_adv_remove(uint8_t handle,
1600 uint8_t *cmd, int cmd_len)
1601 {
1602 BLE_HS_DBG_ASSERT(cmd_len >= BLE_HCI_LE_REMOVE_ADV_SET_LEN);
1603
1604 cmd[0] = handle;
1605
1606 return 0;
1607 }
1608 #endif
1609
1610 static int
ble_hs_hci_cmd_body_le_set_priv_mode(const uint8_t * addr,uint8_t addr_type,uint8_t priv_mode,uint8_t * dst)1611 ble_hs_hci_cmd_body_le_set_priv_mode(const uint8_t *addr, uint8_t addr_type,
1612 uint8_t priv_mode, uint8_t *dst)
1613 {
1614 /* In this command addr type can be either:
1615 * - public identity (0x00)
1616 * - random (static) identity (0x01)
1617 */
1618 if (addr_type > BLE_ADDR_RANDOM) {
1619 return BLE_ERR_INV_HCI_CMD_PARMS;
1620 }
1621
1622 dst[0] = addr_type;
1623 memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN);
1624 dst[7] = priv_mode;
1625
1626 return 0;
1627 }
1628
1629 /*
1630 * OGF=0x08 OCF=0x004e
1631 */
1632 int
ble_hs_hci_cmd_build_le_set_priv_mode(const uint8_t * addr,uint8_t addr_type,uint8_t priv_mode,uint8_t * dst,uint16_t dst_len)1633 ble_hs_hci_cmd_build_le_set_priv_mode(const uint8_t *addr, uint8_t addr_type,
1634 uint8_t priv_mode, uint8_t *dst,
1635 uint16_t dst_len)
1636 {
1637 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_LE_SET_PRIVACY_MODE_LEN);
1638
1639 return ble_hs_hci_cmd_body_le_set_priv_mode(addr, addr_type, priv_mode, dst);
1640 }
1641
1642 static int
ble_hs_hci_cmd_body_set_random_addr(const struct hci_rand_addr * paddr,uint8_t * dst)1643 ble_hs_hci_cmd_body_set_random_addr(const struct hci_rand_addr *paddr,
1644 uint8_t *dst)
1645 {
1646 memcpy(dst, paddr->addr, BLE_DEV_ADDR_LEN);
1647 return 0;
1648 }
1649
1650 int
ble_hs_hci_cmd_build_set_random_addr(const uint8_t * addr,uint8_t * dst,int dst_len)1651 ble_hs_hci_cmd_build_set_random_addr(const uint8_t *addr,
1652 uint8_t *dst, int dst_len)
1653 {
1654 struct hci_rand_addr r_addr;
1655
1656 memcpy(r_addr.addr, addr, sizeof(r_addr.addr));
1657
1658 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_SET_RAND_ADDR_LEN);
1659
1660 return ble_hs_hci_cmd_body_set_random_addr(&r_addr, dst);
1661 }
1662
1663 static void
ble_hs_hci_cmd_body_le_read_remote_feat(uint16_t handle,uint8_t * dst)1664 ble_hs_hci_cmd_body_le_read_remote_feat(uint16_t handle, uint8_t *dst)
1665 {
1666 put_le16(dst, handle);
1667 }
1668
1669 int
ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle,uint8_t * dst,int dst_len)1670 ble_hs_hci_cmd_build_le_read_remote_feat(uint16_t handle, uint8_t *dst,
1671 int dst_len)
1672 {
1673 BLE_HS_DBG_ASSERT(dst_len >= BLE_HCI_CONN_RD_REM_FEAT_LEN);
1674
1675 ble_hs_hci_cmd_body_le_read_remote_feat(handle, dst);
1676
1677 return 0;
1678 }
1679