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 int
ble_gatt_disc_c_test_misc_rx_rsp_once(
    uint16_t conn_handle, struct ble_gatt_disc_c_test_char *chars)
{
    struct ble_att_read_type_rsp rsp;
    uint8_t buf[1024];
    int off;
    int rc;
    int i;

    /* Send the pending ATT Read By Type Request. */
    ble_hs_test_util_tx_all();

    if (chars[0].uuid16 != 0) {
       rsp.batp_length = BLE_ATT_READ_TYPE_ADATA_BASE_SZ +
                         BLE_GATT_CHR_DECL_SZ_16;
    } else {
       rsp.batp_length = BLE_ATT_READ_TYPE_ADATA_BASE_SZ +
                         BLE_GATT_CHR_DECL_SZ_128;
    }

    ble_att_read_type_rsp_write(buf, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp);

    off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
    for (i = 0; ; i++) {
        if (chars[i].def_handle == 0) {
            /* No more services. */
            break;
        }

        /* If the value length is changing, we need a separate response. */
        if (((chars[i].uuid16 == 0) ^ (chars[0].uuid16 == 0)) != 0) {
            break;
        }

        htole16(buf + off, chars[i].def_handle);
        off += 2;

        buf[off] = chars[i].properties;
        off++;

        htole16(buf + off, chars[i].val_handle);
        off += 2;

        if (chars[i].uuid16 != 0) {
            htole16(buf + off, chars[i].uuid16);
            off += 2;
        } else {
            memcpy(buf + off, chars[i].uuid128, 16);
            off += 16;
        }
    }

    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_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, uint8_t *uuid128)
{
    uint8_t buf[17];
    int rc;

    buf[0] = BLE_ATT_OP_READ_RSP;
    memcpy(buf + 1, uuid128, 16);

    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
                                                buf, 17);
    TEST_ASSERT(rc == 0);
}
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_gatts_read_test_once(uint16_t conn_handle, uint16_t attr_id,
                         void *expected_value, uint16_t expected_len)
{
    struct ble_att_read_req read_req;
    uint8_t buf[BLE_ATT_READ_REQ_SZ];
    int rc;

    read_req.barq_handle = attr_id;
    ble_att_read_req_write(buf, sizeof buf, &read_req);

    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
                                                buf, sizeof buf);
    TEST_ASSERT(rc == 0);

    ble_hs_test_util_verify_tx_read_rsp(expected_value, expected_len);
}
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
ble_gatt_write_test_rx_prep_rsp(struct ble_hs_conn *conn, uint16_t attr_handle,
                                uint16_t offset,
                                void *attr_data, uint16_t attr_data_len)
{
    struct ble_att_prep_write_cmd rsp;
    struct ble_l2cap_chan *chan;
    uint8_t buf[512];
    int rc;

    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
    TEST_ASSERT_FATAL(chan != NULL);

    rsp.bapc_handle = attr_handle;
    rsp.bapc_offset = offset;
    ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);

    memcpy(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, attr_data, attr_data_len);

    rc = ble_hs_test_util_l2cap_rx_payload_flat(
        conn, chan, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);
    TEST_ASSERT(rc == 0);
}