diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 7c9338e18c92..c57dd25601fc 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -39,9 +39,33 @@ config BLUETOOTH_CONTROLLER_TO_HOST_UART_DEV_NAME to connect to an external Bluetooth Host when Zephyr is acting as a Bluetooth Controller. +menu "Advertiser" + visible if !BLUETOOTH_PERIPHERAL + +config BLUETOOTH_CONTROLLER_STATE_ADV + bool "Enable Advertiser" + default y if BLUETOOTH_PERIPHERAL + default y if !BLUETOOTH_CONTROLLER_STATE_SCAN + help + Enable support for advertising state in the Controller. + +endmenu + +menu "Scanner" + visible if !BLUETOOTH_CENTRAL + +config BLUETOOTH_CONTROLLER_STATE_SCAN + bool "Enable Scanner" + default y if BLUETOOTH_CENTRAL + help + Enable support for scanning state in the Controller. + +endmenu + config BLUETOOTH_CONTROLLER_DUP_FILTER_LEN prompt "Number of addresses in the scan duplicate filter" int + depends on BLUETOOTH_CONTROLLER_STATE_SCAN default 16 help Set the number of unique BLE addresses that can be filtered as diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 7d333f989dd9..bb354314549d 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -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,7 +626,9 @@ 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 */ +#if defined(CONFIG_BLUETOOTH_CONTROLLER_STATE_SCAN) static void le_set_scan_param(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_set_scan_param *cmd = (void *)buf->data; @@ -584,7 +666,10 @@ static void le_set_scan_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_SCAN */ +#if defined(CONFIG_BLUETOOTH_CONN) +#if defined(CONFIG_BLUETOOTH_CENTRAL) static void le_create_connection(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_create_conn *cmd = (void *)buf->data; @@ -622,73 +707,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 +719,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; @@ -752,7 +733,9 @@ static void le_start_encryption(struct net_buf *buf, struct net_buf **evt) *evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED); } +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +#if defined(CONFIG_BLUETOOTH_PERIPHERAL) static void le_ltk_req_reply(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_ltk_req_reply *cmd = (void *)buf->data; @@ -783,15 +766,41 @@ static void le_ltk_req_neg_reply(struct net_buf *buf, struct net_buf **evt) rp->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED; rp->handle = sys_le16_to_cpu(handle); } +#endif /* CONFIG_BLUETOOTH_PERIPHERAL */ -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) @@ -886,6 +895,7 @@ static void le_read_max_data_len(struct net_buf *buf, struct net_buf **evt) rp->status = 0x00; } #endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH */ +#endif /* CONFIG_BLUETOOTH_CONN */ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd, struct net_buf **evt) @@ -907,6 +917,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,7 +965,9 @@ 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 */ +#if defined(CONFIG_BLUETOOTH_CONTROLLER_STATE_SCAN) case BT_OCF(BT_HCI_OP_LE_SET_SCAN_PARAM): le_set_scan_param(cmd, evt); break; @@ -934,7 +975,10 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd, case BT_OCF(BT_HCI_OP_LE_SET_SCAN_ENABLE): le_set_scan_enable(cmd, evt); break; +#endif /* CONFIG_BLUETOOTH_CONTROLLER_STATE_SCAN */ +#if defined(CONFIG_BLUETOOTH_CONN) +#if defined(CONFIG_BLUETOOTH_CENTRAL) case BT_OCF(BT_HCI_OP_LE_CREATE_CONN): le_create_connection(cmd, evt); break; @@ -943,46 +987,16 @@ 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; +#endif /* CONFIG_BLUETOOTH_CENTRAL */ +#if defined(CONFIG_BLUETOOTH_PERIPHERAL) case BT_OCF(BT_HCI_OP_LE_LTK_REQ_REPLY): le_ltk_req_reply(cmd, evt); break; @@ -990,9 +1004,14 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd, case BT_OCF(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY): le_ltk_req_neg_reply(cmd, evt); break; +#endif /* CONFIG_BLUETOOTH_PERIPHERAL */ - 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): @@ -1020,6 +1039,7 @@ static int controller_cmd_handle(u8_t ocf, struct net_buf *cmd, le_read_max_data_len(cmd, evt); break; #endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH */ +#endif /* CONFIG_BLUETOOTH_CONN */ default: return -EINVAL; diff --git a/subsys/bluetooth/controller/ll_sw/Makefile b/subsys/bluetooth/controller/ll_sw/Makefile index cdea36c95a48..952ddf4bd2a4 100644 --- a/subsys/bluetooth/controller/ll_sw/Makefile +++ b/subsys/bluetooth/controller/ll_sw/Makefile @@ -2,3 +2,6 @@ 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 +obj-$(CONFIG_BLUETOOTH_CONTROLLER_STATE_SCAN) += ll_scan.o +obj-$(CONFIG_BLUETOOTH_CENTRAL) += ll_master.o diff --git a/subsys/bluetooth/controller/ll_sw/ll.c b/subsys/bluetooth/controller/ll_sw/ll.c index 203149056dc2..244e691f76e5 100644 --- a/subsys/bluetooth/controller/ll_sw/ll.c +++ b/subsys/bluetooth/controller/ll_sw/ll.c @@ -52,25 +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; - u8_t scan_type:1; - u8_t tx_addr:1; - u8_t filter_policy:1; -} _ll_scan_params; - void mayfly_enable_cb(u8_t caller_id, u8_t callee_id, u8_t enable) { (void)caller_id; @@ -271,260 +252,3 @@ void ll_addr_set(u8_t addr_type, u8_t const *const bdaddr) memcpy(_ll_context.pub_addr, bdaddr, BDADDR_SIZE); } } - -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) -{ - _ll_scan_params.scan_type = scan_type; - _ll_scan_params.interval = interval; - _ll_scan_params.window = window; - _ll_scan_params.tx_addr = own_addr_type; - _ll_scan_params.filter_policy = filter_policy; -} - -u32_t ll_scan_enable(u8_t enable) -{ - u32_t status; - - if (enable) { - status = radio_scan_enable(_ll_scan_params.scan_type, - _ll_scan_params.tx_addr, - (_ll_scan_params.tx_addr) ? - &_ll_context.rnd_addr[0] : - &_ll_context.pub_addr[0], - _ll_scan_params.interval, - _ll_scan_params.window, - _ll_scan_params.filter_policy); - } else { - status = radio_scan_disable(); - } - - return status; -} - -u32_t ll_create_connection(u16_t scan_interval, u16_t scan_window, - u8_t filter_policy, u8_t peer_addr_type, - u8_t *peer_addr, u8_t own_addr_type, - u16_t interval, u16_t latency, - u16_t timeout) -{ - u32_t status; - - status = radio_connect_enable(peer_addr_type, peer_addr, interval, - latency, timeout); - - if (status) { - return status; - } - - return radio_scan_enable(0, own_addr_type, (own_addr_type) ? - &_ll_context.rnd_addr[0] : - &_ll_context.pub_addr[0], - scan_interval, scan_window, filter_policy); -} diff --git a/subsys/bluetooth/controller/ll_sw/ll_adv.c b/subsys/bluetooth/controller/ll_sw/ll_adv.c new file mode 100644 index 000000000000..de3eb2dc9af7 --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/ll_adv.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016-2017 Nordic Semiconductor ASA + * Copyright (c) 2016 Vinayak Kariappa Chettimada + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#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; +} diff --git a/subsys/bluetooth/controller/ll_sw/ll_master.c b/subsys/bluetooth/controller/ll_sw/ll_master.c new file mode 100644 index 000000000000..8cc720e6962f --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/ll_master.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016-2017 Nordic Semiconductor ASA + * Copyright (c) 2016 Vinayak Kariappa Chettimada + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "util/util.h" + +#include "pdu.h" +#include "ctrl.h" +#include "ll.h" + +u32_t ll_create_connection(u16_t scan_interval, u16_t scan_window, + u8_t filter_policy, u8_t peer_addr_type, + u8_t *peer_addr, u8_t own_addr_type, + u16_t interval, u16_t latency, + u16_t timeout) +{ + u32_t status; + + status = radio_connect_enable(peer_addr_type, peer_addr, interval, + latency, timeout); + + if (status) { + return status; + } + + return radio_scan_enable(0, own_addr_type, + ll_addr_get(own_addr_type, NULL), + scan_interval, scan_window, filter_policy); +} diff --git a/subsys/bluetooth/controller/ll_sw/ll_scan.c b/subsys/bluetooth/controller/ll_sw/ll_scan.c new file mode 100644 index 000000000000..642a65355f8f --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/ll_scan.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2017 Nordic Semiconductor ASA + * Copyright (c) 2016 Vinayak Kariappa Chettimada + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "util/util.h" + +#include "pdu.h" +#include "ctrl.h" +#include "ll.h" + +static struct { + u16_t interval; + u16_t window; + u8_t scan_type:1; + u8_t tx_addr:1; + u8_t filter_policy:1; +} ll_scan; + +void ll_scan_params_set(u8_t scan_type, u16_t interval, u16_t window, + u8_t own_addr_type, u8_t filter_policy) +{ + ll_scan.scan_type = scan_type; + ll_scan.interval = interval; + ll_scan.window = window; + ll_scan.tx_addr = own_addr_type; + ll_scan.filter_policy = filter_policy; +} + +u32_t ll_scan_enable(u8_t enable) +{ + u32_t status; + + if (!enable) { + status = radio_scan_disable(); + + return status; + } + + status = radio_scan_enable(ll_scan.scan_type, ll_scan.tx_addr, + ll_addr_get(ll_scan.tx_addr, NULL), + ll_scan.interval, ll_scan.window, + ll_scan.filter_policy); + + return status; +}