xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_hci_cmd.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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