Bluetooth: controller: Refactor LL Adv state to ll_adv.c file

Move advertising state related implementation out into a
separate ll_adv.c file.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Chettimada 2017-02-03 04:50:04 +01:00 committed by Johan Hedberg
commit 6117d1dda7
4 changed files with 368 additions and 360 deletions

View file

@ -485,6 +485,86 @@ static void le_set_random_address(struct net_buf *buf, struct net_buf **evt)
ccst->status = 0x00;
}
static void le_read_wl_size(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_read_wl_size *rp;
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
rp->wl_size = 8;
}
static void le_clear_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_evt_cc_status *ccst;
ll_filter_clear();
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = 0x00;
}
static void le_add_dev_to_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_add_dev_to_wl *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_filter_add(cmd->addr.type, &cmd->addr.a.val[0]);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
static void le_rem_dev_from_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_rem_dev_from_wl *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_filter_remove(cmd->addr.type, &cmd->addr.a.val[0]);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
}
static void le_encrypt(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_encrypt *cmd = (void *)buf->data;
struct bt_hci_rp_le_encrypt *rp;
u8_t enc_data[16];
ecb_encrypt(cmd->key, cmd->plaintext, enc_data, NULL);
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
memcpy(rp->enc_data, enc_data, 16);
}
static void le_rand(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_rand *rp;
u8_t count = sizeof(rp->rand);
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
bt_rand(rp->rand, count);
}
static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_read_supp_states *rp;
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
sys_put_le64(0x000003ffffffffff, rp->le_states);
}
#if defined(CONFIG_BLUETOOTH_CONTROLLER_STATE_ADV)
static void le_set_adv_param(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_adv_param *cmd = (void *)buf->data;
@ -546,6 +626,7 @@ static void le_set_adv_enable(struct net_buf *buf, struct net_buf **evt)
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_STATE_ADV */
static void le_set_scan_param(struct net_buf *buf, struct net_buf **evt)
{
@ -622,73 +703,6 @@ static void le_create_conn_cancel(struct net_buf *buf, struct net_buf **evt)
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
}
static void le_read_wl_size(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_read_wl_size *rp;
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
rp->wl_size = 8;
}
static void le_clear_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_evt_cc_status *ccst;
ll_filter_clear();
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = 0x00;
}
static void le_add_dev_to_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_add_dev_to_wl *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_filter_add(cmd->addr.type, &cmd->addr.a.val[0]);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
static void le_rem_dev_from_wl(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_rem_dev_from_wl *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_filter_remove(cmd->addr.type, &cmd->addr.a.val[0]);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
}
static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
{
struct hci_cp_le_conn_update *cmd = (void *)buf->data;
u16_t supervision_timeout;
u16_t conn_interval_max;
u16_t conn_latency;
u32_t status;
u16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
conn_interval_max = sys_le16_to_cpu(cmd->conn_interval_max);
conn_latency = sys_le16_to_cpu(cmd->conn_latency);
supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
/** @todo if peer supports LE Conn Param Req,
* use Req cmd (1) instead of Initiate cmd (0).
*/
status = ll_conn_update(handle, 0, 0, conn_interval_max,
conn_latency, supervision_timeout);
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
static void le_set_host_chan_classif(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_host_chan_classif *cmd = (void *)buf->data;
@ -701,43 +715,6 @@ static void le_set_host_chan_classif(struct net_buf *buf, struct net_buf **evt)
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
}
static void le_read_remote_features(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_read_remote_features *cmd = (void *)buf->data;
u32_t status;
u16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_feature_req_send(handle);
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
static void le_encrypt(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_encrypt *cmd = (void *)buf->data;
struct bt_hci_rp_le_encrypt *rp;
u8_t enc_data[16];
ecb_encrypt(cmd->key, cmd->plaintext, enc_data, NULL);
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
memcpy(rp->enc_data, enc_data, 16);
}
static void le_rand(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_rand *rp;
u8_t count = sizeof(rp->rand);
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
bt_rand(rp->rand, count);
}
static void le_start_encryption(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_start_encryption *cmd = (void *)buf->data;
@ -784,14 +761,39 @@ static void le_ltk_req_neg_reply(struct net_buf *buf, struct net_buf **evt)
rp->handle = sys_le16_to_cpu(handle);
}
static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt)
static void le_read_remote_features(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_read_supp_states *rp;
struct bt_hci_cp_le_read_remote_features *cmd = (void *)buf->data;
u32_t status;
u16_t handle;
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
handle = sys_le16_to_cpu(cmd->handle);
status = ll_feature_req_send(handle);
sys_put_le64(0x000003ffffffffff, rp->le_states);
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
{
struct hci_cp_le_conn_update *cmd = (void *)buf->data;
u16_t supervision_timeout;
u16_t conn_interval_max;
u16_t conn_latency;
u32_t status;
u16_t handle;
handle = sys_le16_to_cpu(cmd->handle);
conn_interval_max = sys_le16_to_cpu(cmd->conn_interval_max);
conn_latency = sys_le16_to_cpu(cmd->conn_latency);
supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
/** @todo if peer supports LE Conn Param Req,
* use Req cmd (1) instead of Initiate cmd (0).
*/
status = ll_conn_update(handle, 0, 0, conn_interval_max,
conn_latency, supervision_timeout);
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
@ -907,6 +909,35 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd,
le_set_random_address(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_READ_WL_SIZE):
le_read_wl_size(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CLEAR_WL):
le_clear_wl(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ADD_DEV_TO_WL):
le_add_dev_to_wl(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_REM_DEV_FROM_WL):
le_rem_dev_from_wl(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ENCRYPT):
le_encrypt(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_RAND):
le_rand(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_READ_SUPP_STATES):
le_read_supp_states(cmd, evt);
break;
#if defined(CONFIG_BLUETOOTH_CONTROLLER_STATE_ADV)
case BT_OCF(BT_HCI_OP_LE_SET_ADV_PARAM):
le_set_adv_param(cmd, evt);
break;
@ -926,6 +957,7 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd,
case BT_OCF(BT_HCI_OP_LE_SET_ADV_ENABLE):
le_set_adv_enable(cmd, evt);
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_STATE_ADV */
case BT_OCF(BT_HCI_OP_LE_SET_SCAN_PARAM):
le_set_scan_param(cmd, evt);
@ -943,42 +975,10 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd,
le_create_conn_cancel(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_READ_WL_SIZE):
le_read_wl_size(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CLEAR_WL):
le_clear_wl(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ADD_DEV_TO_WL):
le_add_dev_to_wl(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_REM_DEV_FROM_WL):
le_rem_dev_from_wl(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CONN_UPDATE):
le_conn_update(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF):
le_set_host_chan_classif(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_READ_REMOTE_FEATURES):
le_read_remote_features(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_ENCRYPT):
le_encrypt(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_RAND):
le_rand(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_START_ENCRYPTION):
le_start_encryption(cmd, evt);
break;
@ -991,8 +991,12 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd,
le_ltk_req_neg_reply(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_READ_SUPP_STATES):
le_read_supp_states(cmd, evt);
case BT_OCF(BT_HCI_OP_LE_READ_REMOTE_FEATURES):
le_read_remote_features(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CONN_UPDATE):
le_conn_update(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY):

View file

@ -2,3 +2,4 @@ ccflags-y += -I$(srctree)/subsys/bluetooth/controller/include
ccflags-y += -I$(srctree)/subsys/bluetooth/controller
obj-y += crypto.o ctrl.o ll.o
obj-$(CONFIG_BLUETOOTH_CONTROLLER_STATE_ADV) += ll_adv.o

View file

@ -52,17 +52,6 @@ static struct {
u8_t rnd_addr[BDADDR_SIZE];
} _ll_context;
static struct {
u16_t interval;
u8_t pdu_adv_type:4;
u8_t tx_addr:1;
u8_t rx_addr:1;
u8_t filter_policy:2;
u8_t chl_map:3;
u8_t adv_addr[BDADDR_SIZE];
u8_t direct_addr[BDADDR_SIZE];
} _ll_adv_params;
static struct {
u16_t interval;
u16_t window;
@ -272,212 +261,6 @@ void ll_addr_set(u8_t addr_type, u8_t const *const bdaddr)
}
}
void ll_adv_params_set(u16_t interval, u8_t adv_type,
u8_t own_addr_type, u8_t direct_addr_type,
u8_t const *const direct_addr, u8_t chl_map,
u8_t filter_policy)
{
u8_t const pdu_adv_type[] = {PDU_ADV_TYPE_ADV_IND,
PDU_ADV_TYPE_DIRECT_IND,
PDU_ADV_TYPE_SCAN_IND,
PDU_ADV_TYPE_NONCONN_IND,
PDU_ADV_TYPE_DIRECT_IND};
struct radio_adv_data *radio_adv_data;
struct pdu_adv *pdu;
/** @todo check and fail if adv role active else
* update (implemented below) current index elements for
* both adv and scan data.
*/
/* remember params so that set adv/scan data and adv enable
* interface can correctly update adv/scan data in the
* double buffer between caller and controller context.
*/
/* Set interval for Undirected or Low Duty Cycle Directed Advertising */
if (adv_type != 0x01) {
_ll_adv_params.interval = interval;
} else {
_ll_adv_params.interval = 0;
}
_ll_adv_params.chl_map = chl_map;
_ll_adv_params.filter_policy = filter_policy;
_ll_adv_params.pdu_adv_type = pdu_adv_type[adv_type];
_ll_adv_params.tx_addr = own_addr_type;
_ll_adv_params.rx_addr = 0;
/* update the current adv data */
radio_adv_data = radio_adv_data_get();
pdu = (struct pdu_adv *)&radio_adv_data->data[radio_adv_data->last][0];
pdu->type = _ll_adv_params.pdu_adv_type;
pdu->rfu = 0;
if (IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2) &&
((_ll_adv_params.pdu_adv_type == PDU_ADV_TYPE_ADV_IND) ||
(_ll_adv_params.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND))) {
pdu->chan_sel = 1;
} else {
pdu->chan_sel = 0;
}
pdu->tx_addr = _ll_adv_params.tx_addr;
if (_ll_adv_params.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND) {
_ll_adv_params.rx_addr = direct_addr_type;
memcpy(&_ll_adv_params.direct_addr[0], direct_addr,
BDADDR_SIZE);
memcpy(&pdu->payload.direct_ind.tgt_addr[0],
direct_addr, BDADDR_SIZE);
pdu->len = sizeof(struct pdu_adv_payload_direct_ind);
} else if (pdu->len == 0) {
pdu->len = BDADDR_SIZE;
}
pdu->rx_addr = _ll_adv_params.rx_addr;
/* update the current scan data */
radio_adv_data = radio_scan_data_get();
pdu = (struct pdu_adv *)&radio_adv_data->data[radio_adv_data->last][0];
pdu->type = PDU_ADV_TYPE_SCAN_RSP;
pdu->rfu = 0;
pdu->chan_sel = 0;
pdu->tx_addr = _ll_adv_params.tx_addr;
pdu->rx_addr = 0;
if (pdu->len == 0) {
pdu->len = BDADDR_SIZE;
}
}
void ll_adv_data_set(u8_t len, u8_t const *const data)
{
struct radio_adv_data *radio_adv_data;
struct pdu_adv *pdu;
u8_t last;
/** @todo dont update data if directed adv type. */
/* use the last index in double buffer, */
radio_adv_data = radio_adv_data_get();
if (radio_adv_data->first == radio_adv_data->last) {
last = radio_adv_data->last + 1;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0;
}
} else {
last = radio_adv_data->last;
}
/* update adv pdu fields. */
pdu = (struct pdu_adv *)&radio_adv_data->data[last][0];
pdu->type = _ll_adv_params.pdu_adv_type;
pdu->rfu = 0;
if (IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2) &&
((_ll_adv_params.pdu_adv_type == PDU_ADV_TYPE_ADV_IND) ||
(_ll_adv_params.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND))) {
pdu->chan_sel = 1;
} else {
pdu->chan_sel = 0;
}
pdu->tx_addr = _ll_adv_params.tx_addr;
pdu->rx_addr = _ll_adv_params.rx_addr;
memcpy(&pdu->payload.adv_ind.addr[0],
&_ll_adv_params.adv_addr[0], BDADDR_SIZE);
if (_ll_adv_params.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND) {
memcpy(&pdu->payload.direct_ind.tgt_addr[0],
&_ll_adv_params.direct_addr[0], BDADDR_SIZE);
pdu->len = sizeof(struct pdu_adv_payload_direct_ind);
} else {
memcpy(&pdu->payload.adv_ind.data[0], data, len);
pdu->len = BDADDR_SIZE + len;
}
/* commit the update so controller picks it. */
radio_adv_data->last = last;
}
void ll_scan_data_set(u8_t len, u8_t const *const data)
{
struct radio_adv_data *radio_scan_data;
struct pdu_adv *pdu;
u8_t last;
/* use the last index in double buffer, */
radio_scan_data = radio_scan_data_get();
if (radio_scan_data->first == radio_scan_data->last) {
last = radio_scan_data->last + 1;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0;
}
} else {
last = radio_scan_data->last;
}
/* update scan pdu fields. */
pdu = (struct pdu_adv *)&radio_scan_data->data[last][0];
pdu->type = PDU_ADV_TYPE_SCAN_RSP;
pdu->rfu = 0;
pdu->chan_sel = 0;
pdu->tx_addr = _ll_adv_params.tx_addr;
pdu->rx_addr = 0;
pdu->len = BDADDR_SIZE + len;
memcpy(&pdu->payload.scan_rsp.addr[0], &_ll_adv_params.adv_addr[0],
BDADDR_SIZE);
memcpy(&pdu->payload.scan_rsp.data[0], data, len);
/* commit the update so controller picks it. */
radio_scan_data->last = last;
}
u32_t ll_adv_enable(u8_t enable)
{
u32_t status;
if (enable) {
struct radio_adv_data *radio_adv_data;
struct radio_adv_data *radio_scan_data;
struct pdu_adv *pdu_adv;
struct pdu_adv *pdu_scan;
/** @todo move the addr remembered into controller
* this way when implementing Privacy 1.2, generated
* new resolvable addresses can be used instantly.
*/
/* remember addr to use and also update the addr in
* both adv and scan PDUs.
*/
radio_adv_data = radio_adv_data_get();
radio_scan_data = radio_scan_data_get();
pdu_adv = (struct pdu_adv *)&radio_adv_data->data
[radio_adv_data->last][0];
pdu_scan = (struct pdu_adv *)&radio_scan_data->data
[radio_scan_data->last][0];
if (_ll_adv_params.tx_addr) {
memcpy(&_ll_adv_params.adv_addr[0],
&_ll_context.rnd_addr[0], BDADDR_SIZE);
memcpy(&pdu_adv->payload.adv_ind.addr[0],
&_ll_context.rnd_addr[0], BDADDR_SIZE);
memcpy(&pdu_scan->payload.scan_rsp.addr[0],
&_ll_context.rnd_addr[0], BDADDR_SIZE);
} else {
memcpy(&_ll_adv_params.adv_addr[0],
&_ll_context.pub_addr[0], BDADDR_SIZE);
memcpy(&pdu_adv->payload.adv_ind.addr[0],
&_ll_context.pub_addr[0], BDADDR_SIZE);
memcpy(&pdu_scan->payload.scan_rsp.addr[0],
&_ll_context.pub_addr[0], BDADDR_SIZE);
}
status = radio_adv_enable(_ll_adv_params.interval,
_ll_adv_params.chl_map,
_ll_adv_params.filter_policy);
} else {
status = radio_adv_disable();
}
return status;
}
void ll_scan_params_set(u8_t scan_type, u16_t interval, u16_t window,
u8_t own_addr_type, u8_t filter_policy)
{

View file

@ -0,0 +1,220 @@
/*
* Copyright (c) 2016-2017 Nordic Semiconductor ASA
* Copyright (c) 2016 Vinayak Kariappa Chettimada
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <zephyr.h>
#include "util/util.h"
#include "pdu.h"
#include "ctrl.h"
#include "ll.h"
static struct {
u16_t interval;
u8_t pdu_adv_type:4;
u8_t tx_addr:1;
u8_t rx_addr:1;
u8_t filter_policy:2;
u8_t chl_map:3;
u8_t adv_addr[BDADDR_SIZE];
u8_t direct_addr[BDADDR_SIZE];
} ll_adv;
void ll_adv_params_set(u16_t interval, u8_t adv_type,
u8_t own_addr_type, u8_t direct_addr_type,
u8_t const *const direct_addr, u8_t chl_map,
u8_t filter_policy)
{
u8_t const pdu_adv_type[] = {PDU_ADV_TYPE_ADV_IND,
PDU_ADV_TYPE_DIRECT_IND,
PDU_ADV_TYPE_SCAN_IND,
PDU_ADV_TYPE_NONCONN_IND,
PDU_ADV_TYPE_DIRECT_IND};
struct radio_adv_data *radio_adv_data;
struct pdu_adv *pdu;
/* TODO: check and fail if adv state active else
* update (implemented below) current index elements for
* both adv and scan data.
*/
/* remember params so that set adv/scan data and adv enable
* interface can correctly update adv/scan data in the
* double buffer between caller and controller context.
*/
/* Set interval for Undirected or Low Duty Cycle Directed Advertising */
if (adv_type != 0x01) {
ll_adv.interval = interval;
} else {
ll_adv.interval = 0;
}
ll_adv.chl_map = chl_map;
ll_adv.filter_policy = filter_policy;
ll_adv.pdu_adv_type = pdu_adv_type[adv_type];
ll_adv.tx_addr = own_addr_type;
ll_adv.rx_addr = 0;
/* update the current adv data */
radio_adv_data = radio_adv_data_get();
pdu = (struct pdu_adv *)&radio_adv_data->data[radio_adv_data->last][0];
pdu->type = ll_adv.pdu_adv_type;
pdu->rfu = 0;
if (IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2) &&
((ll_adv.pdu_adv_type == PDU_ADV_TYPE_ADV_IND) ||
(ll_adv.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND))) {
pdu->chan_sel = 1;
} else {
pdu->chan_sel = 0;
}
pdu->tx_addr = ll_adv.tx_addr;
if (ll_adv.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND) {
ll_adv.rx_addr = direct_addr_type;
memcpy(&ll_adv.direct_addr[0], direct_addr, BDADDR_SIZE);
memcpy(&pdu->payload.direct_ind.tgt_addr[0], direct_addr,
BDADDR_SIZE);
pdu->len = sizeof(struct pdu_adv_payload_direct_ind);
} else if (pdu->len == 0) {
pdu->len = BDADDR_SIZE;
}
pdu->rx_addr = ll_adv.rx_addr;
/* update the current scan data */
radio_adv_data = radio_scan_data_get();
pdu = (struct pdu_adv *)&radio_adv_data->data[radio_adv_data->last][0];
pdu->type = PDU_ADV_TYPE_SCAN_RSP;
pdu->rfu = 0;
pdu->chan_sel = 0;
pdu->tx_addr = ll_adv.tx_addr;
pdu->rx_addr = 0;
if (pdu->len == 0) {
pdu->len = BDADDR_SIZE;
}
}
void ll_adv_data_set(u8_t len, u8_t const *const data)
{
struct radio_adv_data *radio_adv_data;
struct pdu_adv *pdu;
u8_t last;
/* TODO: dont update data if directed adv type. */
/* use the last index in double buffer, */
radio_adv_data = radio_adv_data_get();
if (radio_adv_data->first == radio_adv_data->last) {
last = radio_adv_data->last + 1;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0;
}
} else {
last = radio_adv_data->last;
}
/* update adv pdu fields. */
pdu = (struct pdu_adv *)&radio_adv_data->data[last][0];
pdu->type = ll_adv.pdu_adv_type;
pdu->rfu = 0;
if (IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_CHAN_SEL_2) &&
((ll_adv.pdu_adv_type == PDU_ADV_TYPE_ADV_IND) ||
(ll_adv.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND))) {
pdu->chan_sel = 1;
} else {
pdu->chan_sel = 0;
}
pdu->tx_addr = ll_adv.tx_addr;
pdu->rx_addr = ll_adv.rx_addr;
memcpy(&pdu->payload.adv_ind.addr[0], &ll_adv.adv_addr[0], BDADDR_SIZE);
if (ll_adv.pdu_adv_type == PDU_ADV_TYPE_DIRECT_IND) {
memcpy(&pdu->payload.direct_ind.tgt_addr[0],
&ll_adv.direct_addr[0], BDADDR_SIZE);
pdu->len = sizeof(struct pdu_adv_payload_direct_ind);
} else {
memcpy(&pdu->payload.adv_ind.data[0], data, len);
pdu->len = BDADDR_SIZE + len;
}
/* commit the update so controller picks it. */
radio_adv_data->last = last;
}
void ll_scan_data_set(u8_t len, u8_t const *const data)
{
struct radio_adv_data *radio_scan_data;
struct pdu_adv *pdu;
u8_t last;
/* use the last index in double buffer, */
radio_scan_data = radio_scan_data_get();
if (radio_scan_data->first == radio_scan_data->last) {
last = radio_scan_data->last + 1;
if (last == DOUBLE_BUFFER_SIZE) {
last = 0;
}
} else {
last = radio_scan_data->last;
}
/* update scan pdu fields. */
pdu = (struct pdu_adv *)&radio_scan_data->data[last][0];
pdu->type = PDU_ADV_TYPE_SCAN_RSP;
pdu->rfu = 0;
pdu->chan_sel = 0;
pdu->tx_addr = ll_adv.tx_addr;
pdu->rx_addr = 0;
pdu->len = BDADDR_SIZE + len;
memcpy(&pdu->payload.scan_rsp.addr[0], &ll_adv.adv_addr[0],
BDADDR_SIZE);
memcpy(&pdu->payload.scan_rsp.data[0], data, len);
/* commit the update so controller picks it. */
radio_scan_data->last = last;
}
u32_t ll_adv_enable(u8_t enable)
{
struct radio_adv_data *radio_scan_data;
struct radio_adv_data *radio_adv_data;
struct pdu_adv *pdu_scan;
struct pdu_adv *pdu_adv;
u32_t status;
if (!enable) {
status = radio_adv_disable();
return status;
}
/* TODO: move the addr remembered into controller
* this way when implementing Privacy 1.2, generated
* new resolvable addresses can be used instantly.
*/
/* remember addr to use and also update the addr in
* both adv and scan response PDUs.
*/
radio_adv_data = radio_adv_data_get();
radio_scan_data = radio_scan_data_get();
pdu_adv = (struct pdu_adv *)&radio_adv_data->data
[radio_adv_data->last][0];
pdu_scan = (struct pdu_adv *)&radio_scan_data->data
[radio_scan_data->last][0];
ll_addr_get(ll_adv.tx_addr, ll_adv.adv_addr);
memcpy(&pdu_adv->payload.adv_ind.addr[0], ll_adv.adv_addr, BDADDR_SIZE);
memcpy(&pdu_scan->payload.scan_rsp.addr[0], ll_adv.adv_addr,
BDADDR_SIZE);
status = radio_adv_enable(ll_adv.interval, ll_adv.chl_map,
ll_adv.filter_policy);
return status;
}