xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_hs_test_util_hci.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 
20 #include "testutil/testutil.h"
21 #include "nimble/ble.h"
22 #include "nimble/hci_common.h"
23 #include "transport/ram/ble_hci_ram.h"
24 #include "ble_hs_test_util.h"
25 
26 #define BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT      64
27 
28 static uint8_t
29 ble_hs_test_util_hci_out_queue[BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT][260];
30 static int ble_hs_test_util_hci_out_queue_sz;
31 static uint8_t ble_hs_test_util_hci_out_cur[260];
32 
33 static struct ble_hs_test_util_hci_ack
34 ble_hs_test_util_hci_acks[BLE_HS_TEST_UTIL_PHONY_ACK_MAX];
35 static int ble_hs_test_util_hci_num_acks;
36 
37 /*****************************************************************************
38  * $tx queue                                                                 *
39  *****************************************************************************/
40 
41 void
ble_hs_test_util_hci_out_adj(int count)42 ble_hs_test_util_hci_out_adj(int count)
43 {
44     if (count >= 0) {
45         TEST_ASSERT(ble_hs_test_util_hci_out_queue_sz >= count);
46 
47         ble_hs_test_util_hci_out_queue_sz -= count;
48         if (ble_hs_test_util_hci_out_queue_sz > 0) {
49             memmove(
50                 ble_hs_test_util_hci_out_queue,
51                 ble_hs_test_util_hci_out_queue + count,
52                 sizeof ble_hs_test_util_hci_out_queue[0] *
53                 ble_hs_test_util_hci_out_queue_sz);
54         }
55     } else {
56         TEST_ASSERT(ble_hs_test_util_hci_out_queue_sz >= -count);
57 
58         ble_hs_test_util_hci_out_adj(
59             ble_hs_test_util_hci_out_queue_sz + count);
60     }
61 }
62 
63 void *
ble_hs_test_util_hci_out_first(void)64 ble_hs_test_util_hci_out_first(void)
65 {
66     if (ble_hs_test_util_hci_out_queue_sz == 0) {
67         return NULL;
68     }
69 
70     memcpy(ble_hs_test_util_hci_out_cur, ble_hs_test_util_hci_out_queue[0],
71            sizeof ble_hs_test_util_hci_out_cur);
72 
73     ble_hs_test_util_hci_out_adj(1);
74 
75     return ble_hs_test_util_hci_out_cur;
76 }
77 
78 void *
ble_hs_test_util_hci_out_last(void)79 ble_hs_test_util_hci_out_last(void)
80 {
81     if (ble_hs_test_util_hci_out_queue_sz == 0) {
82         return NULL;
83     }
84 
85     ble_hs_test_util_hci_out_queue_sz--;
86     memcpy(ble_hs_test_util_hci_out_cur,
87            ble_hs_test_util_hci_out_queue + ble_hs_test_util_hci_out_queue_sz,
88            sizeof ble_hs_test_util_hci_out_cur);
89 
90     return ble_hs_test_util_hci_out_cur;
91 }
92 
93 void
ble_hs_test_util_hci_out_enqueue(void * cmd)94 ble_hs_test_util_hci_out_enqueue(void *cmd)
95 {
96     TEST_ASSERT_FATAL(ble_hs_test_util_hci_out_queue_sz <
97                       BLE_HS_TEST_UTIL_PREV_HCI_TX_CNT);
98     memcpy(ble_hs_test_util_hci_out_queue + ble_hs_test_util_hci_out_queue_sz,
99            cmd, 260);
100 
101     ble_hs_test_util_hci_out_queue_sz++;
102 }
103 
104 void
ble_hs_test_util_hci_out_clear(void)105 ble_hs_test_util_hci_out_clear(void)
106 {
107     ble_hs_test_util_hci_out_queue_sz = 0;
108 }
109 
110 /*****************************************************************************
111  * $build                                                                    *
112  *****************************************************************************/
113 
114 void
ble_hs_test_util_hci_build_cmd_complete(uint8_t * dst,int len,uint8_t param_len,uint8_t num_pkts,uint16_t opcode)115 ble_hs_test_util_hci_build_cmd_complete(uint8_t *dst, int len,
116                                     uint8_t param_len, uint8_t num_pkts,
117                                     uint16_t opcode)
118 {
119     TEST_ASSERT(len >= BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN);
120 
121     dst[0] = BLE_HCI_EVCODE_COMMAND_COMPLETE;
122     dst[1] = 3 + param_len;
123     dst[2] = num_pkts;
124     put_le16(dst + 3, opcode);
125 }
126 
127 void
ble_hs_test_util_hci_build_cmd_status(uint8_t * dst,int len,uint8_t status,uint8_t num_pkts,uint16_t opcode)128 ble_hs_test_util_hci_build_cmd_status(uint8_t *dst, int len,
129                                   uint8_t status, uint8_t num_pkts,
130                                   uint16_t opcode)
131 {
132     TEST_ASSERT(len >= BLE_HCI_EVENT_CMD_STATUS_LEN);
133 
134     dst[0] = BLE_HCI_EVCODE_COMMAND_STATUS;
135     dst[1] = BLE_HCI_EVENT_CMD_STATUS_LEN;
136     dst[2] = status;
137     dst[3] = num_pkts;
138     put_le16(dst + 4, opcode);
139 }
140 
141 static void
ble_hs_test_util_hci_build_ack_params(struct ble_hs_test_util_hci_ack * ack,uint16_t opcode,uint8_t status,void * params,uint8_t params_len)142 ble_hs_test_util_hci_build_ack_params(
143     struct ble_hs_test_util_hci_ack *ack,
144     uint16_t opcode, uint8_t status, void *params, uint8_t params_len)
145 {
146     ack->opcode = opcode;
147     ack->status = status;
148 
149     if (params == NULL || params_len == 0) {
150         ack->evt_params_len = 0;
151     } else {
152         memcpy(ack->evt_params, params, params_len);
153         ack->evt_params_len = params_len;
154     }
155 }
156 
157 /*****************************************************************************
158  * $ack                                                                      *
159  *****************************************************************************/
160 
161 static int
ble_hs_test_util_hci_ack_cb(uint8_t * ack,int ack_buf_len)162 ble_hs_test_util_hci_ack_cb(uint8_t *ack, int ack_buf_len)
163 {
164     struct ble_hs_test_util_hci_ack *entry;
165 
166     if (ble_hs_test_util_hci_num_acks == 0) {
167         return BLE_HS_ETIMEOUT_HCI;
168     }
169 
170     entry = ble_hs_test_util_hci_acks;
171 
172     ble_hs_test_util_hci_build_cmd_complete(ack, 256,
173                                         entry->evt_params_len + 1, 1,
174                                         entry->opcode);
175     ack[BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN] = entry->status;
176     memcpy(ack + BLE_HCI_EVENT_CMD_COMPLETE_HDR_LEN + 1, entry->evt_params,
177            entry->evt_params_len);
178 
179     ble_hs_test_util_hci_num_acks--;
180     if (ble_hs_test_util_hci_num_acks > 0) {
181         memmove(ble_hs_test_util_hci_acks,
182                 ble_hs_test_util_hci_acks + 1,
183                 sizeof *entry * ble_hs_test_util_hci_num_acks);
184     }
185 
186     return 0;
187 }
188 
189 void
ble_hs_test_util_hci_ack_set_params(uint16_t opcode,uint8_t status,void * params,uint8_t params_len)190 ble_hs_test_util_hci_ack_set_params(uint16_t opcode, uint8_t status,
191                                     void *params, uint8_t params_len)
192 {
193     struct ble_hs_test_util_hci_ack *ack;
194 
195     ack = ble_hs_test_util_hci_acks + 0;
196     ble_hs_test_util_hci_build_ack_params(ack, opcode, status, params,
197                                           params_len);
198     ble_hs_test_util_hci_num_acks = 1;
199 
200     ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb);
201 }
202 
203 void
ble_hs_test_util_hci_ack_set(uint16_t opcode,uint8_t status)204 ble_hs_test_util_hci_ack_set(uint16_t opcode, uint8_t status)
205 {
206     ble_hs_test_util_hci_ack_set_params(opcode, status, NULL, 0);
207 }
208 
209 void
ble_hs_test_util_hci_ack_append_params(uint16_t opcode,uint8_t status,void * params,uint8_t params_len)210 ble_hs_test_util_hci_ack_append_params(uint16_t opcode, uint8_t status,
211                                        void *params, uint8_t params_len)
212 {
213     struct ble_hs_test_util_hci_ack *ack;
214 
215     ack = ble_hs_test_util_hci_acks + ble_hs_test_util_hci_num_acks;
216     ble_hs_test_util_hci_build_ack_params(ack, opcode, status, params,
217                                           params_len);
218     ble_hs_test_util_hci_num_acks++;
219 
220     ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb);
221 }
222 
223 void
ble_hs_test_util_hci_ack_append(uint16_t opcode,uint8_t status)224 ble_hs_test_util_hci_ack_append(uint16_t opcode, uint8_t status)
225 {
226     ble_hs_test_util_hci_ack_append_params(opcode, status, NULL, 0);
227 }
228 
229 static const struct ble_hs_test_util_hci_ack hci_startup_seq[] = {
230     {
231         .opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND,
232                                               BLE_HCI_OCF_CB_RESET),
233     },
234     {
235         .opcode = ble_hs_hci_util_opcode_join(
236          BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER),
237         .evt_params = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
238         .evt_params_len = 8,
239     },
240     {
241         .opcode = ble_hs_hci_util_opcode_join(
242          BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
243         .evt_params = { 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00},
244         .evt_params_len = 8,
245     },
246     {
247         .opcode = ble_hs_hci_util_opcode_join(
248             BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK),
249     },
250     {
251         .opcode = ble_hs_hci_util_opcode_join(
252             BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK2),
253     },
254     {
255         .opcode = ble_hs_hci_util_opcode_join(
256             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EVENT_MASK),
257     },
258     {
259         .opcode = ble_hs_hci_util_opcode_join(
260             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE),
261         /* Use a very low buffer size (20) to test fragmentation.
262          * Use a large num-pkts (200) to prevent controller buf exhaustion.
263          */
264         .evt_params = { 0x14, 0x00, 200 },
265         .evt_params_len = 3,
266     },
267     {
268         .opcode = ble_hs_hci_util_opcode_join(
269             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
270         .evt_params = { 0 },
271         .evt_params_len = 8,
272     },
273     {
274         .opcode = ble_hs_hci_util_opcode_join(
275             BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BD_ADDR),
276         .evt_params = BLE_HS_TEST_UTIL_PUB_ADDR_VAL,
277         .evt_params_len = 6,
278     },
279     {
280         .opcode = ble_hs_hci_util_opcode_join(
281             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
282     },
283     {
284         .opcode = ble_hs_hci_util_opcode_join(
285             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLR_RESOLV_LIST),
286     },
287     {
288         .opcode = ble_hs_hci_util_opcode_join(
289             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN),
290     },
291     {
292         .opcode = ble_hs_hci_util_opcode_join(
293             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE),
294     },
295     {
296         .opcode = ble_hs_hci_util_opcode_join(
297             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST),
298     },
299     {
300         .opcode = ble_hs_hci_util_opcode_join(
301             BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PRIVACY_MODE),
302     },
303     { 0 }
304 };
305 
306 void
ble_hs_test_util_hci_ack_set_seq(const struct ble_hs_test_util_hci_ack * acks)307 ble_hs_test_util_hci_ack_set_seq(const struct ble_hs_test_util_hci_ack *acks)
308 {
309     int i;
310 
311     for (i = 0; acks[i].opcode != 0; i++) {
312         ble_hs_test_util_hci_acks[i] = acks[i];
313     }
314     ble_hs_test_util_hci_num_acks = i;
315 
316     ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb);
317 }
318 
319 int
ble_hs_test_util_hci_startup_seq_cnt(void)320 ble_hs_test_util_hci_startup_seq_cnt(void)
321 {
322     /* last element is terminator, don't count it*/
323     return sizeof(hci_startup_seq)/sizeof(hci_startup_seq[0]) - 1;
324 }
325 
326 void
ble_hs_test_util_hci_ack_set_startup(void)327 ble_hs_test_util_hci_ack_set_startup(void)
328 {
329     /* Receive acknowledgements for the startup sequence.  We sent the
330      * corresponding requests when the host task was started.
331      */
332     ble_hs_test_util_hci_ack_set_seq(hci_startup_seq);
333 }
334 
335 void
ble_hs_test_util_hci_ack_set_disc(uint8_t own_addr_type,int fail_idx,uint8_t fail_status)336 ble_hs_test_util_hci_ack_set_disc(uint8_t own_addr_type,
337                                   int fail_idx, uint8_t fail_status)
338 {
339     static bool privacy_enabled;
340 
341     /*
342      * SET_RPA_TMO should be expected only when test uses RPA and privacy has
343      * not yet been enabled. The Bluetooth stack remembers that privacy is
344      * enabled and does not send SET_RPA_TMO every time. For test purpose
345      * let's track privacy state in here.
346      */
347     if ((own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT ||
348          own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) &&
349         !privacy_enabled) {
350 
351         privacy_enabled = true;
352         ble_hs_test_util_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) {
353             {
354                 BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_RPA_TMO),
355                 ble_hs_test_util_hci_misc_exp_status(0, fail_idx, fail_status),
356             },
357             {
358                 BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
359                 ble_hs_test_util_hci_misc_exp_status(1, fail_idx, fail_status),
360             },
361             {
362                 BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
363                 ble_hs_test_util_hci_misc_exp_status(2, fail_idx, fail_status),
364             },
365 
366             { 0 }
367         }));
368     } else {
369         ble_hs_test_util_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) {
370             {
371                 BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_PARAMS),
372                 ble_hs_test_util_hci_misc_exp_status(0, fail_idx, fail_status),
373             },
374             {
375                 BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
376                 ble_hs_test_util_hci_misc_exp_status(1, fail_idx, fail_status),
377             },
378 
379             { 0 }
380         }));
381     }
382 }
383 
384 void
ble_hs_test_util_hci_ack_set_disconnect(uint8_t hci_status)385 ble_hs_test_util_hci_ack_set_disconnect(uint8_t hci_status)
386 {
387     ble_hs_test_util_hci_ack_set(
388         ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LINK_CTRL,
389                                     BLE_HCI_OCF_DISCONNECT_CMD),
390         hci_status);
391 }
392 
393 /*****************************************************************************
394  * $verify tx                                                                *
395  *****************************************************************************/
396 
397 void
ble_hs_test_util_hci_verify_tx_add_irk(uint8_t addr_type,const uint8_t * addr,const uint8_t * peer_irk,const uint8_t * local_irk)398 ble_hs_test_util_hci_verify_tx_add_irk(uint8_t addr_type,
399                                        const uint8_t *addr,
400                                        const uint8_t *peer_irk,
401                                        const uint8_t *local_irk)
402 {
403     uint8_t param_len;
404     uint8_t *param;
405 
406 
407     param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
408                                            BLE_HCI_OCF_LE_ADD_RESOLV_LIST,
409                                            &param_len);
410     TEST_ASSERT(param_len == BLE_HCI_ADD_TO_RESOLV_LIST_LEN);
411 
412     TEST_ASSERT(param[0] == addr_type);
413     TEST_ASSERT(memcmp(param + 1, addr, 6) == 0);
414     TEST_ASSERT(memcmp(param + 7, peer_irk, 16) == 0);
415     TEST_ASSERT(memcmp(param + 23, local_irk, 16) == 0);
416 }
417 
418 void
ble_hs_test_util_hci_verify_tx_set_priv_mode(uint8_t addr_type,const uint8_t * addr,uint8_t priv_mode)419 ble_hs_test_util_hci_verify_tx_set_priv_mode(uint8_t addr_type,
420                                              const uint8_t *addr,
421                                              uint8_t priv_mode)
422 {
423     uint8_t param_len;
424     uint8_t *param;
425 
426     param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
427                                            BLE_HCI_OCF_LE_SET_PRIVACY_MODE,
428                                            &param_len);
429     TEST_ASSERT(param_len == BLE_HCI_LE_SET_PRIVACY_MODE_LEN);
430 
431     TEST_ASSERT(param[0] == addr_type);
432     TEST_ASSERT(memcmp(param + 1, addr, 6) == 0);
433     TEST_ASSERT(param[7] == priv_mode);
434 }
435 
436 void
ble_hs_test_util_hci_verify_tx_disconnect(uint16_t handle,uint8_t reason)437 ble_hs_test_util_hci_verify_tx_disconnect(uint16_t handle, uint8_t reason)
438 {
439     uint8_t param_len;
440     uint8_t *param;
441 
442     param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LINK_CTRL,
443                                            BLE_HCI_OCF_DISCONNECT_CMD,
444                                            &param_len);
445     TEST_ASSERT(param_len == BLE_HCI_DISCONNECT_CMD_LEN);
446 
447     TEST_ASSERT(get_le16(param + 0) == handle);
448     TEST_ASSERT(param[2] == reason);
449 }
450 
451 void
ble_hs_test_util_hci_verify_tx_create_conn(const struct hci_create_conn * exp)452 ble_hs_test_util_hci_verify_tx_create_conn(const struct hci_create_conn *exp)
453 {
454     uint8_t param_len;
455     uint8_t *param;
456 
457     param = ble_hs_test_util_hci_verify_tx(BLE_HCI_OGF_LE,
458                                            BLE_HCI_OCF_LE_CREATE_CONN,
459                                            &param_len);
460     TEST_ASSERT(param_len == BLE_HCI_CREATE_CONN_LEN);
461 
462     TEST_ASSERT(get_le16(param + 0) == exp->scan_itvl);
463     TEST_ASSERT(get_le16(param + 2) == exp->scan_window);
464     TEST_ASSERT(param[4] == exp->filter_policy);
465     TEST_ASSERT(param[5] == exp->peer_addr_type);
466     TEST_ASSERT(memcmp(param + 6, exp->peer_addr, 6) == 0);
467     TEST_ASSERT(param[12] == exp->own_addr_type);
468     TEST_ASSERT(get_le16(param + 13) == exp->conn_itvl_min);
469     TEST_ASSERT(get_le16(param + 15) == exp->conn_itvl_max);
470     TEST_ASSERT(get_le16(param + 17) == exp->conn_latency);
471     TEST_ASSERT(get_le16(param + 19) == exp->supervision_timeout);
472     TEST_ASSERT(get_le16(param + 21) == exp->min_ce_len);
473     TEST_ASSERT(get_le16(param + 23) == exp->max_ce_len);
474 }
475 
476 uint8_t *
ble_hs_test_util_hci_verify_tx(uint8_t ogf,uint16_t ocf,uint8_t * out_param_len)477 ble_hs_test_util_hci_verify_tx(uint8_t ogf, uint16_t ocf,
478                                uint8_t *out_param_len)
479 {
480     uint16_t opcode;
481     uint8_t *cmd;
482 
483     cmd = ble_hs_test_util_hci_out_first();
484     TEST_ASSERT_FATAL(cmd != NULL);
485 
486     opcode = get_le16(cmd);
487     TEST_ASSERT(BLE_HCI_OGF(opcode) == ogf);
488     TEST_ASSERT(BLE_HCI_OCF(opcode) == ocf);
489 
490     if (out_param_len != NULL) {
491         *out_param_len = cmd[2];
492     }
493 
494     return cmd + 3;
495 }
496 
497 /*****************************************************************************
498  * $rx                                                                       *
499  *****************************************************************************/
500 
501 static void
ble_hs_test_util_hci_rx_evt(uint8_t * evt)502 ble_hs_test_util_hci_rx_evt(uint8_t *evt)
503 {
504     uint8_t *evbuf;
505     int totlen;
506     int rc;
507 
508     totlen = BLE_HCI_EVENT_HDR_LEN + evt[1];
509     TEST_ASSERT_FATAL(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
510 
511     evbuf = ble_hci_trans_buf_alloc(
512         BLE_HCI_TRANS_BUF_EVT_LO);
513     TEST_ASSERT_FATAL(evbuf != NULL);
514 
515     memcpy(evbuf, evt, totlen);
516 
517     if (os_started()) {
518         rc = ble_hci_trans_ll_evt_tx(evbuf);
519     } else {
520         rc = ble_hs_hci_evt_process(evbuf);
521     }
522 
523     TEST_ASSERT_FATAL(rc == 0);
524 }
525 
526 void
ble_hs_test_util_hci_rx_num_completed_pkts_event(struct ble_hs_test_util_hci_num_completed_pkts_entry * entries)527 ble_hs_test_util_hci_rx_num_completed_pkts_event(
528     struct ble_hs_test_util_hci_num_completed_pkts_entry *entries)
529 {
530     struct ble_hs_test_util_hci_num_completed_pkts_entry *entry;
531     uint8_t buf[1024];
532     int num_entries;
533     int off;
534     int i;
535 
536     /* Count number of entries. */
537     num_entries = 0;
538     for (entry = entries; entry->handle_id != 0; entry++) {
539         num_entries++;
540     }
541     TEST_ASSERT_FATAL(num_entries <= UINT8_MAX);
542 
543     buf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS;
544     buf[2] = num_entries;
545 
546     off = 3;
547     for (i = 0; i < num_entries; i++) {
548         put_le16(buf + off, entries[i].handle_id);
549         off += 2;
550     }
551     for (i = 0; i < num_entries; i++) {
552         put_le16(buf + off, entries[i].num_pkts);
553         off += 2;
554     }
555 
556     buf[1] = off - 2;
557 
558     ble_hs_test_util_hci_rx_evt(buf);
559 }
560 
561 void
ble_hs_test_util_hci_rx_disconn_complete_event(struct hci_disconn_complete * evt)562 ble_hs_test_util_hci_rx_disconn_complete_event(
563     struct hci_disconn_complete *evt)
564 {
565     uint8_t buf[BLE_HCI_EVENT_HDR_LEN + BLE_HCI_EVENT_DISCONN_COMPLETE_LEN];
566 
567     buf[0] = BLE_HCI_EVCODE_DISCONN_CMP;
568     buf[1] = BLE_HCI_EVENT_DISCONN_COMPLETE_LEN;
569     buf[2] = evt->status;
570     put_le16(buf + 3, evt->connection_handle);
571     buf[5] = evt->reason;
572 
573     ble_hs_test_util_hci_rx_evt(buf);
574 }
575 
576 void
ble_hs_test_util_hci_rx_conn_cancel_evt(void)577 ble_hs_test_util_hci_rx_conn_cancel_evt(void)
578 {
579     struct hci_le_conn_complete evt;
580     int rc;
581 
582     memset(&evt, 0, sizeof evt);
583     evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
584     evt.status = BLE_ERR_UNK_CONN_ID;
585     /* test if host correctly ignores other fields if status is error */
586     evt.connection_handle = 0x0fff;
587 
588     rc = ble_gap_rx_conn_complete(&evt, 0);
589     TEST_ASSERT_FATAL(rc == 0);
590 }
591 
592 /*****************************************************************************
593  * $misc                                                                     *
594  *****************************************************************************/
595 
596 int
ble_hs_test_util_hci_misc_exp_status(int cmd_idx,int fail_idx,uint8_t fail_status)597 ble_hs_test_util_hci_misc_exp_status(int cmd_idx, int fail_idx,
598                                      uint8_t fail_status)
599 {
600     if (cmd_idx == fail_idx) {
601         return BLE_HS_HCI_ERR(fail_status);
602     } else {
603         return 0;
604     }
605 }
606