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 ¶m_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 ¶m_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 ¶m_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 ¶m_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