static void ble_att_clt_test_misc_exec_good(uint8_t flags) { struct ble_att_exec_write_req req; struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; struct os_mbuf *om; int rc; ble_att_clt_test_misc_init(&conn, &chan); req.baeq_flags = flags; rc = ble_att_clt_tx_exec_write(conn->bhc_handle, &req); TEST_ASSERT(rc == 0); ble_hs_test_util_tx_all(); TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL); om = os_mbuf_pullup(ble_hs_test_util_prev_tx, OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx)); TEST_ASSERT_FATAL(om != NULL); TEST_ASSERT(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ); ble_att_exec_write_req_parse(om->om_data, om->om_len, &req); TEST_ASSERT(req.baeq_flags == flags); }
static void ble_gatts_read_test_misc_init(uint16_t *out_conn_handle) { int rc; ble_hs_test_util_init(); rc = ble_gatts_register_svcs(ble_gatts_read_test_svcs, ble_gatts_read_test_misc_reg_cb, NULL); TEST_ASSERT_FATAL(rc == 0); TEST_ASSERT_FATAL(ble_gatts_read_test_chr_1_def_handle != 0); TEST_ASSERT_FATAL(ble_gatts_read_test_chr_1_val_handle == ble_gatts_read_test_chr_1_def_handle + 1); TEST_ASSERT_FATAL(ble_gatts_read_test_chr_2_def_handle != 0); TEST_ASSERT_FATAL(ble_gatts_read_test_chr_2_val_handle == ble_gatts_read_test_chr_2_def_handle + 1); ble_gatts_start(); ble_hs_test_util_create_conn(2, ble_gatts_read_test_peer_addr, NULL, NULL); if (out_conn_handle != NULL) { *out_conn_handle = 2; } }
static void ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset, uint8_t *attr_data, uint16_t attr_data_len) { struct ble_att_prep_write_cmd req; struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; struct os_mbuf *om; int rc; int i; ble_att_clt_test_misc_init(&conn, &chan); req.bapc_handle = handle; req.bapc_offset = offset; rc = ble_att_clt_tx_prep_write(conn->bhc_handle, &req, attr_data, attr_data_len); TEST_ASSERT(rc == 0); ble_hs_test_util_tx_all(); TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL); om = os_mbuf_pullup(ble_hs_test_util_prev_tx, OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx)); TEST_ASSERT_FATAL(om != NULL); TEST_ASSERT(om->om_len == BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len); ble_att_prep_write_req_parse(om->om_data, om->om_len, &req); TEST_ASSERT(req.bapc_handle == handle); TEST_ASSERT(req.bapc_offset == offset); for (i = 0; i < attr_data_len; i++) { TEST_ASSERT(om->om_data[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + i] == attr_data[i]); } }
static int ble_gatts_read_test_util_access_2(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { uint8_t *buf; TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_2_def_handle + 1); TEST_ASSERT(ctxt->chr == &ble_gatts_read_test_svcs[0].characteristics[1]); buf = os_mbuf_extend(ctxt->om, 6); TEST_ASSERT_FATAL(buf != NULL); buf[0] = 0; buf[1] = 10; buf[2] = 20; buf[3] = 30; buf[4] = 40; buf[5] = 50; return 0; }
static void ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id, void *value, int value_len, int is_req) { struct ble_att_write_req req; struct os_mbuf *om; int rc; TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL); om = os_mbuf_pullup(ble_hs_test_util_prev_tx, OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx)); TEST_ASSERT_FATAL(om != NULL); if (is_req) { rc = ble_att_write_req_parse(om->om_data, om->om_len, &req); } else { rc = ble_att_write_cmd_parse(om->om_data, om->om_len, &req); } TEST_ASSERT_FATAL(rc == 0); TEST_ASSERT(req.bawq_handle == handle_id); TEST_ASSERT(om->om_len == BLE_ATT_WRITE_REQ_BASE_SZ + value_len); TEST_ASSERT(memcmp(om->om_data + BLE_ATT_WRITE_REQ_BASE_SZ, value, value_len) == 0); }
static void ble_gatt_find_s_test_misc_verify_tx_read_type(uint16_t start_handle, uint16_t end_handle) { struct ble_att_read_type_req req; struct os_mbuf *om; uint16_t uuid16; int rc; ble_hs_test_util_tx_all(); TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL); om = os_mbuf_pullup(ble_hs_test_util_prev_tx, OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx)); TEST_ASSERT_FATAL(om != NULL); rc = ble_att_read_type_req_parse(om->om_data, om->om_len, &req); TEST_ASSERT(rc == 0); TEST_ASSERT(req.batq_start_handle == start_handle); TEST_ASSERT(req.batq_end_handle == end_handle); TEST_ASSERT(om->om_len == BLE_ATT_READ_TYPE_REQ_BASE_SZ + 2); uuid16 = le16toh(om->om_data + BLE_ATT_READ_TYPE_REQ_BASE_SZ); TEST_ASSERT(uuid16 == BLE_ATT_UUID_INCLUDE); }
static void ble_gatts_reg_test_misc_lookup_good(struct ble_gatts_reg_test_entry *entry) { uint16_t chr_def_handle; uint16_t chr_val_handle; uint16_t svc_handle; uint16_t dsc_handle; int rc; switch (entry->op) { case BLE_GATT_REGISTER_OP_SVC: rc = ble_gatts_find_svc(entry->uuid128, &svc_handle); TEST_ASSERT_FATAL(rc == 0); TEST_ASSERT(svc_handle == entry->handle); break; case BLE_GATT_REGISTER_OP_CHR: rc = ble_gatts_find_chr(entry->svc->uuid128, entry->chr->uuid128, &chr_def_handle, &chr_val_handle); TEST_ASSERT_FATAL(rc == 0); TEST_ASSERT(chr_def_handle == entry->handle); TEST_ASSERT(chr_val_handle == entry->val_handle); break; case BLE_GATT_REGISTER_OP_DSC: rc = ble_gatts_find_dsc(entry->svc->uuid128, entry->chr->uuid128, entry->dsc->uuid128, &dsc_handle); break; default: TEST_ASSERT(0); break; } }
static void boot_test_util_write_swap_state(int flash_area_id, const struct boot_swap_state *state) { const struct flash_area *fap; int rc; rc = flash_area_open(flash_area_id, &fap); TEST_ASSERT_FATAL(rc == 0); switch (state->magic) { case 0: break; case BOOT_MAGIC_GOOD: rc = boot_write_magic(fap); TEST_ASSERT_FATAL(rc == 0); break; default: TEST_ASSERT_FATAL(0); break; } if (state->copy_done != 0xff) { rc = boot_write_copy_done(fap); TEST_ASSERT_FATAL(rc == 0); } if (state->image_ok != 0xff) { rc = boot_write_image_ok(fap); TEST_ASSERT_FATAL(rc == 0); } }
int ble_hs_test_util_l2cap_rx_payload_flat(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, const void *data, int len) { struct hci_data_hdr hci_hdr; struct os_mbuf *om; int rc; om = ble_hs_misc_pkthdr(); TEST_ASSERT_FATAL(om != NULL); om->om_data += BLE_L2CAP_HDR_SZ; rc = os_mbuf_append(om, data, len); TEST_ASSERT_FATAL(rc == 0); om = ble_l2cap_prepend_hdr(om, chan->blc_cid, OS_MBUF_PKTLEN(om)); TEST_ASSERT_FATAL(om != NULL); hci_hdr.hdh_handle_pb_bc = host_hci_handle_pb_bc_join(conn->bhc_handle, BLE_HCI_PB_FIRST_FLUSH, 0); hci_hdr.hdh_len = OS_MBUF_PKTHDR(om)->omp_len; rc = ble_hs_test_util_l2cap_rx(conn, &hci_hdr, om); return rc; }
static void os_mbuf_test_setup(void) { int rc; rc = os_mempool_init(&os_mbuf_mempool, MBUF_TEST_POOL_BUF_COUNT, MBUF_TEST_POOL_BUF_SIZE, &os_mbuf_membuf[0], "mbuf_pool"); TEST_ASSERT_FATAL(rc == 0, "Error creating memory pool %d", rc); rc = os_mbuf_pool_init(&os_mbuf_pool, &os_mbuf_mempool, 0, MBUF_TEST_POOL_BUF_SIZE, MBUF_TEST_POOL_BUF_COUNT); TEST_ASSERT_FATAL(rc == 0, "Error creating mbuf pool %d", rc); }
static int ble_gatt_find_s_test_misc_rx_read_type( uint16_t conn_handle, struct ble_gatt_find_s_test_entry *entries) { struct ble_att_read_type_rsp rsp; uint16_t uuid16; uint8_t buf[1024]; int off; int rc; int i; memset(&rsp, 0, sizeof rsp); off = BLE_ATT_READ_TYPE_RSP_BASE_SZ; for (i = 0; entries[i].inc_handle != 0; i++) { if (rsp.batp_length == BLE_GATTS_INC_SVC_LEN_NO_UUID + 2) { break; } uuid16 = ble_uuid_128_to_16(entries[i].uuid128); if (uuid16 == 0) { if (rsp.batp_length != 0) { break; } rsp.batp_length = BLE_GATTS_INC_SVC_LEN_NO_UUID + 2; } else { rsp.batp_length = BLE_GATTS_INC_SVC_LEN_UUID + 2; } TEST_ASSERT_FATAL(off + rsp.batp_length <= sizeof buf); htole16(buf + off, entries[i].inc_handle); off += 2; htole16(buf + off, entries[i].start_handle); off += 2; htole16(buf + off, entries[i].end_handle); off += 2; if (uuid16 != 0) { htole16(buf + off, uuid16); off += 2; } } if (i == 0) { ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 0); return 0; } ble_att_read_type_rsp_write(buf + 0, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp); rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, buf, off); TEST_ASSERT(rc == 0); return i; }
static void ble_gatts_reg_test_misc_verify_entry(uint8_t op, const uint8_t *uuid128) { struct ble_gatts_reg_test_entry *entry; int i; for (i = 0; i < ble_gatts_reg_test_num_entries; i++) { entry = ble_gatts_reg_test_entries + i; if (entry->op == op && memcmp(entry->uuid128, uuid128, 16) == 0) { break; } } TEST_ASSERT_FATAL(entry != NULL); /* Verify that characteristic value handle was properly assigned at * registration. */ if (op == BLE_GATT_REGISTER_OP_CHR) { TEST_ASSERT(*entry->chr->val_handle == entry->val_handle); } /* Verify that the entry can be looked up. */ ble_gatts_reg_test_misc_lookup_good(entry); /* Verify that "barely incorrect" UUID information doesn't retrieve any * handles. */ ble_gatts_reg_test_misc_lookup_bad(entry); }
static int ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle, struct ble_gatt_error *error, struct ble_gatt_chr *chr, void *arg) { struct ble_gatt_chr *dst; int *stop_after; TEST_ASSERT(error == NULL); TEST_ASSERT(!ble_gatt_disc_c_test_rx_complete); stop_after = arg; if (chr == NULL) { ble_gatt_disc_c_test_rx_complete = 1; } else { TEST_ASSERT_FATAL(ble_gatt_disc_c_test_num_chars < BLE_GATT_DISC_C_TEST_MAX_CHARS); dst = ble_gatt_disc_c_test_chars + ble_gatt_disc_c_test_num_chars++; *dst = *chr; } if (*stop_after > 0) { (*stop_after)--; if (*stop_after == 0) { ble_gatt_disc_c_test_rx_complete = 1; return 1; } } return 0; }
struct ble_hs_conn * ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr, ble_gap_conn_fn *cb, void *cb_arg) { struct hci_le_conn_complete evt; struct ble_hs_conn *conn; int rc; ble_hs_test_util_set_ack( BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_CREATE_CONN), 0); rc = ble_gap_conn_initiate(0, addr, NULL, cb, cb_arg); TEST_ASSERT(rc == 0); memset(&evt, 0, sizeof evt); evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; evt.status = BLE_ERR_SUCCESS; evt.connection_handle = handle; evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER; evt.peer_addr_type = BLE_ADDR_TYPE_PUBLIC; memcpy(evt.peer_addr, addr, 6); evt.conn_itvl = BLE_GAP_INITIAL_CONN_ITVL_MAX; evt.conn_latency = BLE_GAP_INITIAL_CONN_LATENCY; evt.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; rc = ble_gap_rx_conn_complete(&evt); TEST_ASSERT(rc == 0); conn = ble_hs_conn_find(handle); TEST_ASSERT_FATAL(conn != NULL); ble_hs_test_util_prev_hci_tx_clear(); return conn; }
static void ble_gatts_read_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) { uint16_t uuid16; if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) { uuid16 = ble_uuid_u16(ctxt->chr.chr_def->uuid); switch (uuid16) { case BLE_GATTS_READ_TEST_CHR_1_UUID: ble_gatts_read_test_chr_1_def_handle = ctxt->chr.def_handle; ble_gatts_read_test_chr_1_val_handle = ctxt->chr.val_handle; break; case BLE_GATTS_READ_TEST_CHR_2_UUID: ble_gatts_read_test_chr_2_def_handle = ctxt->chr.def_handle; ble_gatts_read_test_chr_2_val_handle = ctxt->chr.val_handle; break; default: TEST_ASSERT_FATAL(0); break; } } }
static void ble_gatts_reg_test_misc_reg_cb(uint8_t op, union ble_gatt_register_ctxt *ctxt, void *arg) { struct ble_gatts_reg_test_entry *entry; TEST_ASSERT_FATAL(ble_gatts_reg_test_num_entries < BLE_GATTS_REG_TEST_MAX_ENTRIES); entry = ble_gatts_reg_test_entries + ble_gatts_reg_test_num_entries++; entry->op = op; switch (op) { case BLE_GATT_REGISTER_OP_SVC: memcpy(entry->uuid128, ctxt->svc_reg.svc->uuid128, 16); break; case BLE_GATT_REGISTER_OP_CHR: memcpy(entry->uuid128, ctxt->chr_reg.chr->uuid128, 16); break; case BLE_GATT_REGISTER_OP_DSC: memcpy(entry->uuid128, ctxt->dsc_reg.dsc->uuid128, 16); break; default: TEST_ASSERT(0); break; } }
static int cbmem_test_case_1_walk(struct cbmem *cbmem, struct cbmem_entry_hdr *hdr, void *arg) { uint8_t expected; uint8_t actual; int rc; expected = *(uint8_t *) arg; rc = cbmem_read(cbmem, hdr, &actual, 0, sizeof(actual)); TEST_ASSERT_FATAL(rc == 1, "Couldn't read 1 byte from cbmem"); TEST_ASSERT_FATAL(actual == expected, "Actual doesn't equal expected (%d = %d)", actual, expected); *(uint8_t *) arg = ++expected; return (0); }
static void ble_att_clt_test_misc_init(struct ble_hs_conn **conn, struct ble_l2cap_chan **att_chan) { ble_hs_test_util_init(); *conn = ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9})); *att_chan = ble_hs_conn_chan_find(*conn, BLE_L2CAP_CID_ATT); TEST_ASSERT_FATAL(*att_chan != NULL); }
void ble_hs_test_util_enqueue_hci_tx(void *cmd) { TEST_ASSERT_FATAL(ble_hs_test_util_num_prev_hci_txes < BLE_HS_TEST_UTIL_MAX_PREV_HCI_TXES); memcpy(ble_hs_test_util_prev_hci_tx + ble_hs_test_util_num_prev_hci_txes, cmd, 260); ble_hs_test_util_num_prev_hci_txes++; }
static int ble_gatts_read_test_util_access_1(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { int rc; TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_1_val_handle); TEST_ASSERT(ctxt->chr == &ble_gatts_read_test_svcs[0].characteristics[0]); rc = os_mbuf_append(ctxt->om, ble_gatts_read_test_chr_1_val, ble_gatts_read_test_chr_1_len); TEST_ASSERT(rc == 0); return 0; }
static void ble_gatt_find_s_test_misc_verify_tx_read(uint16_t handle) { struct ble_att_read_req req; struct os_mbuf *om; int rc; ble_hs_test_util_tx_all(); TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL); om = os_mbuf_pullup(ble_hs_test_util_prev_tx, OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx)); TEST_ASSERT_FATAL(om != NULL); rc = ble_att_read_req_parse(om->om_data, om->om_len, &req); TEST_ASSERT(rc == 0); TEST_ASSERT(req.barq_handle == handle); TEST_ASSERT(om->om_len == BLE_ATT_READ_REQ_SZ); }
static void ble_os_test_init_app_task(void) { int rc; rc = os_task_init(&ble_os_test_app_task, "ble_gap_terminate_test_task", ble_os_test_app_task_handler, NULL, BLE_OS_TEST_APP_PRIO, OS_WAIT_FOREVER, ble_os_test_app_stack, OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE)); TEST_ASSERT_FATAL(rc == 0); }
void ble_hs_test_util_rx_att_err_rsp(struct ble_hs_conn *conn, uint8_t req_op, uint8_t error_code, uint16_t err_handle) { struct ble_att_error_rsp rsp; struct ble_l2cap_chan *chan; uint8_t buf[BLE_ATT_ERROR_RSP_SZ]; int rc; rsp.baep_req_op = req_op; rsp.baep_handle = err_handle; rsp.baep_error_code = error_code; rc = ble_att_error_rsp_write(buf, sizeof buf, &rsp); TEST_ASSERT_FATAL(rc == 0); chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT); TEST_ASSERT_FATAL(chan != NULL); rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf); TEST_ASSERT(rc == 0); }
static void setup_cbmem1(void) { int i; int rc; rc = cbmem_init(&cbmem1, cbmem1_buf, CBMEM1_BUF_SIZE); TEST_ASSERT_FATAL(rc == 0, "cbmem_init() failed, non-zero RC = %d", rc); memset(cbmem1_entry, 0xff, sizeof(cbmem1_entry)); /* Insert 65 1024 entries, and overflow buffer. * This should overflow two entries, because the buffer is sized for 64 * entries, and then the headers themselves will eat into one of the entries, * so there should be a total of 63 entries. * Ensure no data corruption. */ for (i = 0; i < 65; i++) { cbmem1_entry[0] = i; rc = cbmem_append(&cbmem1, cbmem1_entry, sizeof(cbmem1_entry)); TEST_ASSERT_FATAL(rc == 0, "Could not append entry %d, rc = %d", i, rc); } }
static void ble_gatt_write_test_rx_rsp(struct ble_hs_conn *conn) { struct ble_l2cap_chan *chan; uint8_t op; int rc; chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT); TEST_ASSERT_FATAL(chan != NULL); op = BLE_ATT_OP_WRITE_RSP; rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, &op, 1); TEST_ASSERT(rc == 0); }
static void ble_gatt_find_s_test_misc_rx_read(struct ble_hs_conn *conn, uint8_t *uuid128) { struct ble_l2cap_chan *chan; uint8_t buf[17]; int rc; buf[0] = BLE_ATT_OP_READ_RSP; memcpy(buf + 1, uuid128, 16); chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT); TEST_ASSERT_FATAL(chan != NULL); rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, 17); TEST_ASSERT(rc == 0); }
static void ble_gatt_find_s_test_misc_verify_tx_read(uint16_t handle) { struct ble_att_read_req req; struct os_mbuf *om; ble_hs_test_util_tx_all(); om = ble_hs_test_util_prev_tx_dequeue_pullup(); TEST_ASSERT_FATAL(om != NULL); ble_att_read_req_parse(om->om_data, om->om_len, &req); TEST_ASSERT(req.barq_handle == handle); TEST_ASSERT(om->om_len == BLE_ATT_READ_REQ_SZ); }
static int ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *chr, void *arg) { struct ble_gatt_chr *dst; int *stop_after; TEST_ASSERT(error != NULL); TEST_ASSERT(!ble_gatt_disc_c_test_rx_complete); stop_after = arg; switch (error->status) { case 0: TEST_ASSERT_FATAL(ble_gatt_disc_c_test_num_chars < BLE_GATT_DISC_C_TEST_MAX_CHARS); dst = ble_gatt_disc_c_test_chars + ble_gatt_disc_c_test_num_chars++; *dst = *chr; break; case BLE_HS_EDONE: ble_gatt_disc_c_test_rx_complete = 1; break; default: TEST_ASSERT(0); break; } if (*stop_after > 0) { (*stop_after)--; if (*stop_after == 0) { ble_gatt_disc_c_test_rx_complete = 1; return 1; } } return 0; }
static int ble_gap_direct_connect_test_connect_cb(struct ble_gap_event *event, void *arg) { struct ble_gap_conn_desc desc; int *cb_called; int rc; cb_called = arg; *cb_called = 1; TEST_ASSERT(event->type == BLE_GAP_EVENT_CONNECT); TEST_ASSERT(event->connect.status == 0); TEST_ASSERT(event->connect.conn_handle == 2); rc = ble_gap_conn_find(event->connect.conn_handle, &desc); TEST_ASSERT_FATAL(rc == 0); TEST_ASSERT(desc.peer_id_addr_type == BLE_ADDR_TYPE_PUBLIC); TEST_ASSERT(memcmp(desc.peer_id_addr, ble_os_test_peer_addr, 6) == 0); return 0; }
static int ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle, struct ble_gatt_error *error, struct ble_gatt_attr *attrs, uint8_t num_attrs, void *arg) { int i; TEST_ASSERT_FATAL(num_attrs <= BLE_GATT_WRITE_TEST_MAX_ATTRS); TEST_ASSERT(conn_handle == 2); ble_gatt_write_test_num_attrs = num_attrs; for (i = 0; i < num_attrs; i++) { ble_gatt_write_test_attrs[i] = attrs + i; } ble_gatt_write_test_cb_called = 1; return 0; }