blob: 047290bd595eff2c95daf5c001e0a34c230721c5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <string.h>
#include "os/mynewt.h"
#include "bsp/bsp.h"
/* BLE */
#include "nimble/ble.h"
#include "nimble/ble_hci_trans.h"
#include "nimble/hci_common.h"
#include "host/ble_hs.h"
#include "controller/ble_ll.h"
#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_conn.h"
#include "controller/ble_ll_scan.h"
#include "controller/ble_ll_adv.h"
/* XXX: An app should not include private headers from a library. The bletest
* app uses some of nimble's internal details for logging.
*/
#include "../src/ble_hs_priv.h"
#include "bletest_priv.h"
extern uint16_t g_bletest_ltk_reply_handle;
void
bletest_send_conn_update(uint16_t handle)
{
int rc;
struct hci_conn_update hcu;
hcu.conn_latency = 4;
hcu.supervision_timeout = 2000;
hcu.conn_itvl_min = 1000;
hcu.conn_itvl_max = 1000;
hcu.handle = handle;
hcu.min_ce_len = 4;
hcu.max_ce_len = 4;
rc = ble_hs_hci_cmd_le_conn_update(&hcu);
assert(rc == 0);
}
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
void
bletest_ltk_req_reply(uint16_t handle)
{
g_bletest_ltk_reply_handle |= (1 << (handle-1));
}
int
bletest_send_ltk_req_neg_reply(uint16_t handle)
{
int rc;
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + sizeof(uint16_t)];
uint16_t ack_conn_handle;
uint8_t rsplen;
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY,
sizeof(uint16_t), dst);
dst += BLE_HCI_CMD_HDR_LEN;
put_le16(dst, handle);
rc = ble_hs_hci_cmd_tx(buf, &ack_conn_handle, 2, &rsplen);
if (rc == 0) {
if (rsplen != 2) {
rc = -1;
}
}
return rc;
}
int
bletest_send_ltk_req_reply(uint16_t handle)
{
struct hci_lt_key_req_reply hkr;
uint16_t ack_conn_handle;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LT_KEY_REQ_REPLY_LEN];
uint8_t ack_params_len;
int rc;
hkr.conn_handle = handle;
swap_buf(hkr.long_term_key, (uint8_t *)g_bletest_LTK, 16);
ble_hs_hci_cmd_build_le_lt_key_req_reply(&hkr, buf, sizeof buf);
rc = ble_hs_hci_cmd_tx(buf, &ack_conn_handle, sizeof ack_conn_handle,
&ack_params_len);
if (rc != 0) {
return rc;
}
if (ack_params_len != BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN - 1) {
return -1;
}
if (le16toh(ack_conn_handle) != handle) {
return -1;
}
return 0;
}
#endif
int
bletest_hci_reset_ctlr(void)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET,
0, buf);
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
int
bletest_hci_rd_bd_addr(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_DEV_ADDR_LEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BD_ADDR, 0,
buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_DEV_ADDR_LEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_DEV_ADDR_LEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
int
bletest_hci_le_encrypt(uint8_t *key, uint8_t *pt)
{
int rc;
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LE_ENCRYPT_LEN];
uint8_t rspbuf[16];
uint8_t rsplen;
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ENCRYPT,
BLE_HCI_LE_ENCRYPT_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
swap_buf(dst, key, BLE_ENC_BLOCK_SIZE);
swap_buf(dst + BLE_ENC_BLOCK_SIZE, pt, BLE_ENC_BLOCK_SIZE);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, 16, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != 16) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
#endif
int
bletest_hci_le_set_datalen(uint16_t handle, uint16_t txoctets, uint16_t txtime)
{
int rc;
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_DATALEN_LEN];
uint8_t rspbuf[2];
uint8_t rsplen;
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_DATA_LEN,
BLE_HCI_SET_DATALEN_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
put_le16(dst, handle);
put_le16(dst + 2, txoctets);
put_le16(dst + 4, txtime);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, 2, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != 2) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
int
bletest_hci_le_write_sugg_datalen(uint16_t txoctets, uint16_t txtime)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_WR_SUGG_DATALEN_LEN];
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN,
BLE_HCI_WR_SUGG_DATALEN_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
put_le16(dst, txoctets);
put_le16(dst + 2, txtime);
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
int
bletest_hci_le_rd_sugg_datalen(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_HCI_RD_SUGG_DATALEN_RSPLEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN, 0,
buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_SUGG_DATALEN_RSPLEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_SUGG_DATALEN_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
return 0;
}
int
bletest_hci_rd_local_version(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_HCI_RD_LOC_VER_INFO_RSPLEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER, 0,
buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_LOC_VER_INFO_RSPLEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_LOC_VER_INFO_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
int
bletest_hci_rd_local_feat(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT,
0, buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
int
bletest_hci_rd_local_supp_cmd(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD,
0, buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
/**
* Read supported states
*
* OGF = 0x08 (LE)
* OCF = 0x001C
*
* @return int
*/
int
bletest_hci_le_read_supp_states(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_HCI_RD_SUPP_STATES_RSPLEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_SUPP_STATES, 0, buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_SUPP_STATES_RSPLEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_SUPP_STATES_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
int
bletest_hci_le_rd_max_datalen(void)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN];
uint8_t rspbuf[BLE_HCI_RD_MAX_DATALEN_RSPLEN];
uint8_t rsplen;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_MAX_DATA_LEN, 0, buf);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_MAX_DATALEN_RSPLEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_MAX_DATALEN_RSPLEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
int
bletest_hci_le_set_multi_adv_data(uint8_t *data, uint8_t len, uint8_t instance)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_MULTI_ADV_DATA_LEN];
if (instance >= BLE_LL_ADV_INSTANCES) {
return -1;
}
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_VENDOR, BLE_HCI_OCF_MULTI_ADV,
BLE_HCI_MULTI_ADV_DATA_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
if (((data == NULL) && (len != 0)) || (len > BLE_HCI_MAX_ADV_DATA_LEN)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
memset(dst, 0, BLE_HCI_MULTI_ADV_DATA_LEN);
dst[0] = BLE_HCI_MULTI_ADV_DATA;
dst[1] = len;
memcpy(dst + 2, data, len);
dst[33] = instance;
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#else
int
bletest_hci_le_set_adv_data(uint8_t *data, uint8_t len)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_DATA_LEN];
rc = ble_hs_hci_cmd_build_le_set_adv_data(data, len, buf, sizeof buf);
assert(rc == 0);
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#endif
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
int
bletest_hci_le_start_encrypt(struct hci_start_encrypt *cmd)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_LE_START_ENCRYPT_LEN];
ble_hs_hci_cmd_build_le_start_encrypt(cmd, buf, sizeof buf);
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#endif
int
bletest_hci_le_read_rem_used_feat(uint16_t handle)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CONN_RD_REM_FEAT_LEN];
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_REM_FEAT,
BLE_HCI_CONN_RD_REM_FEAT_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
put_le16(dst, handle);
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
int
bletest_hci_le_set_multi_adv_params(struct hci_multi_adv_params *adv,
uint8_t instance)
{
uint8_t *dst;
uint16_t itvl;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_MULTI_ADV_PARAMS_LEN];
if (instance >= BLE_LL_ADV_INSTANCES) {
return -1;
}
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_VENDOR, BLE_HCI_OCF_MULTI_ADV,
BLE_HCI_MULTI_ADV_PARAMS_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
/* Make sure parameters are valid */
if ((adv->adv_itvl_min > adv->adv_itvl_max) ||
(adv->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) ||
(adv->peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX) ||
(adv->adv_filter_policy > BLE_HCI_ADV_FILT_MAX) ||
(adv->adv_type > BLE_HCI_ADV_TYPE_MAX) ||
(adv->adv_channel_map == 0) ||
((adv->adv_channel_map & 0xF8) != 0)) {
/* These parameters are not valid */
return -1;
}
/* Make sure interval is valid for advertising type. */
if ((adv->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) ||
(adv->adv_type == BLE_HCI_ADV_TYPE_ADV_SCAN_IND)) {
itvl = BLE_HCI_ADV_ITVL_NONCONN_MIN;
} else {
itvl = BLE_HCI_ADV_ITVL_MIN;
}
/* Do not check if high duty-cycle directed */
if (adv->adv_type != BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) {
if ((adv->adv_itvl_min < itvl) ||
(adv->adv_itvl_min > BLE_HCI_ADV_ITVL_MAX)) {
return -1;
}
}
dst[0] = BLE_HCI_MULTI_ADV_PARAMS;
put_le16(dst + 1, adv->adv_itvl_min);
put_le16(dst + 3, adv->adv_itvl_max);
dst[5] = adv->adv_type;
dst[6] = adv->own_addr_type;
memcpy(dst + 7, adv->own_addr, BLE_DEV_ADDR_LEN);
dst[13] = adv->peer_addr_type;
memcpy(dst + 14, adv->peer_addr, BLE_DEV_ADDR_LEN);
dst[20] = adv->adv_channel_map;
dst[21] = adv->adv_filter_policy;
dst[22] = instance;
dst[23] = adv->adv_tx_pwr;
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#else
int
bletest_hci_le_set_adv_params(struct hci_adv_params *adv)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_PARAM_LEN];
rc = ble_hs_hci_cmd_build_le_set_adv_params(adv, buf, sizeof buf);
if (!rc) {
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
}
return rc;
}
#endif
int
bletest_hci_le_set_rand_addr(uint8_t *addr)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RAND_ADDR_LEN];
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RAND_ADDR,
BLE_DEV_ADDR_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
memcpy(dst, addr, BLE_DEV_ADDR_LEN);
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
int
bletest_hci_le_set_multi_rand_addr(uint8_t *addr, uint8_t instance)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_MULTI_ADV_SET_RAND_ADDR_LEN];
if (instance >= BLE_LL_ADV_INSTANCES) {
return -1;
}
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_VENDOR, BLE_HCI_OCF_MULTI_ADV,
BLE_HCI_MULTI_ADV_SET_RAND_ADDR_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
dst[0] = BLE_HCI_MULTI_ADV_SET_RAND_ADDR;
memcpy(dst + 1, addr, BLE_DEV_ADDR_LEN);
dst[7] = instance;
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
#endif
int
bletest_hci_rd_rem_version(uint16_t handle)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + sizeof(uint16_t)];
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LINK_CTRL, BLE_HCI_OCF_RD_REM_VER_INFO,
sizeof(uint16_t), dst);
dst += BLE_HCI_CMD_HDR_LEN;
put_le16(dst, handle);
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
int
bletest_hci_le_set_host_chan_class(uint8_t *chanmap)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_HOST_CHAN_CLASS_LEN];
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS,
BLE_HCI_SET_HOST_CHAN_CLASS_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
memcpy(dst, chanmap, BLE_HCI_SET_HOST_CHAN_CLASS_LEN);
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
int
bletest_hci_le_rd_chanmap(uint16_t handle)
{
int rc;
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_RD_CHANMAP_LEN];
uint8_t rspbuf[BLE_HCI_RD_CHANMAP_RSP_LEN];
uint8_t rsplen;
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_CHAN_MAP,
BLE_HCI_RD_CHANMAP_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
put_le16(dst, handle);
rc = ble_hs_hci_cmd_tx(buf, rspbuf, BLE_HCI_RD_CHANMAP_RSP_LEN, &rsplen);
if (rc != 0) {
return rc;
}
if (rsplen != BLE_HCI_RD_CHANMAP_RSP_LEN) {
return BLE_HS_ECONTROLLER;
}
return rc;
}
#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
int
bletest_hci_le_set_multi_adv_enable(uint8_t enable, uint8_t instance)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_MULTI_ADV_ENABLE_LEN];
if (instance >= BLE_LL_ADV_INSTANCES) {
return -1;
}
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_VENDOR, BLE_HCI_OCF_MULTI_ADV,
BLE_HCI_MULTI_ADV_ENABLE_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
dst[0] = BLE_HCI_MULTI_ADV_ENABLE;
dst[1] = enable;
dst[2] = instance;
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
#else
int
bletest_hci_le_set_adv_enable(uint8_t enable)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADV_ENABLE_LEN];
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE,
BLE_HCI_SET_ADV_ENABLE_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
dst[0] = enable;
return ble_hs_hci_cmd_tx(buf, NULL, 0, NULL);
}
#endif
int
bletest_hci_le_set_event_mask(uint64_t event_mask)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_LE_EVENT_MASK_LEN];
ble_hs_hci_cmd_build_le_set_event_mask(event_mask, buf, sizeof buf);
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
int
bletest_hci_set_event_mask(uint64_t event_mask)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_EVENT_MASK_LEN];
ble_hs_hci_cmd_build_set_event_mask(event_mask, buf, sizeof buf);
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#if MYNEWT_VAL(BLE_ANDROID_MULTI_ADV_SUPPORT)
int
bletest_hci_le_set_multi_scan_rsp_data(uint8_t *data, uint8_t len,
uint8_t instance)
{
uint8_t *dst;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_MULTI_ADV_SCAN_RSP_DATA_LEN];
if (instance >= BLE_LL_ADV_INSTANCES) {
return -1;
}
dst = buf;
ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_VENDOR, BLE_HCI_OCF_MULTI_ADV,
BLE_HCI_MULTI_ADV_SCAN_RSP_DATA_LEN, dst);
dst += BLE_HCI_CMD_HDR_LEN;
if (((data == NULL) && (len != 0)) || (len>BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
memset(dst, 0, BLE_HCI_MULTI_ADV_SCAN_RSP_DATA_LEN);
dst[0] = BLE_HCI_MULTI_ADV_SCAN_RSP_DATA;
dst[1] = len;
memcpy(dst + 2, data, len);
dst[33] = instance;
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#else
int
bletest_hci_le_set_scan_rsp_data(uint8_t *data, uint8_t len)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_RSP_DATA_LEN];
rc = ble_hs_hci_cmd_build_le_set_scan_rsp_data(data, len, buf, sizeof buf);
assert(rc == 0);
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
#endif
int
bletest_hci_cmd_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) {
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
rc = ble_hs_hci_cmd_build_le_set_scan_params(scan_type, scan_itvl,
scan_window, own_addr_type,
filter_policy, buf, sizeof buf);
if (!rc) {
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
}
return rc;
}
int
bletest_hci_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
rc = ble_hs_hci_cmd_build_le_add_to_whitelist(addr, addr_type, buf,
sizeof buf);
if (!rc) {
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
}
return rc;
}
int
bletest_hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dups)
{
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_ENABLE_LEN];
ble_hs_hci_cmd_build_le_set_scan_enable(enable, filter_dups, buf, sizeof buf);
return ble_hs_hci_cmd_tx_empty_ack(buf);
}
int
bletest_hci_le_create_connection(struct hci_create_conn *hcc)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_CREATE_CONN_LEN];
rc = ble_hs_hci_cmd_build_le_create_connection(hcc, buf, sizeof buf);
if (!rc) {
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
}
return rc;
}
int
bletest_hci_le_add_resolv_list(uint8_t *local_irk, uint8_t *peer_irk,
uint8_t *peer_ident_addr, uint8_t addr_type)
{
int rc;
struct hci_add_dev_to_resolving_list padd;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_ADD_TO_RESOLV_LIST_LEN];
padd.addr_type = addr_type;
memcpy(padd.addr, peer_ident_addr, BLE_DEV_ADDR_LEN);
swap_buf(padd.local_irk, local_irk, 16);
swap_buf(padd.peer_irk, peer_irk, 16);
rc = ble_hs_hci_cmd_build_add_to_resolv_list(&padd, buf, sizeof buf);
if (!rc) {
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
}
return rc;
}
int
bletest_hci_le_enable_resolv_list(uint8_t enable)
{
int rc;
uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADDR_RESOL_ENA_LEN];
rc = ble_hs_hci_cmd_build_set_addr_res_en(enable, buf, sizeof buf);
if (!rc) {
rc = ble_hs_hci_cmd_tx_empty_ack(buf);
}
return rc;
}