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:
parent
d9d3f8e7c7
commit
6117d1dda7
4 changed files with 368 additions and 360 deletions
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
220
subsys/bluetooth/controller/ll_sw/ll_adv.c
Normal file
220
subsys/bluetooth/controller/ll_sw/ll_adv.c
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue