Bluetooth: controller: Temporary LLCP CIS_REQ/CIS_IND handling
Implemented LL_CIS_REQ/RSP and LL_CIS_IND handling to allow a central to establish a CIS connection. Implementation is temporary, for test/development purpose and should be re-implemented in the new LLCP framework when ready. Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
parent
c5c0ee2de6
commit
e0b8881622
2 changed files with 193 additions and 0 deletions
|
@ -29,14 +29,18 @@
|
|||
#include "lll.h"
|
||||
#include "lll_clock.h"
|
||||
#include "lll_conn.h"
|
||||
#include "lll_conn_iso.h"
|
||||
|
||||
#include "ull_conn_types.h"
|
||||
#include "ull_conn_iso_types.h"
|
||||
#include "ull_internal.h"
|
||||
#include "ull_iso_internal.h"
|
||||
#include "ull_sched_internal.h"
|
||||
#include "ull_chan_internal.h"
|
||||
#include "ull_conn_internal.h"
|
||||
#include "ull_slave_internal.h"
|
||||
#include "ull_master_internal.h"
|
||||
#include "ull_peripheral_iso_internal.h"
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_USER_EXT)
|
||||
#include "ull_vendor.h"
|
||||
|
@ -122,6 +126,13 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
|
|||
uint16_t event_counter);
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||
static inline void event_send_cis_rsp(struct ll_conn *conn);
|
||||
static inline void event_peripheral_iso_prep(struct ll_conn *conn,
|
||||
uint16_t event_counter,
|
||||
uint32_t ticks_at_expire);
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||
|
||||
static inline void ctrl_tx_pre_ack(struct ll_conn *conn,
|
||||
struct pdu_data *pdu_tx);
|
||||
static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
||||
|
@ -941,6 +952,27 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
|||
/* handle PHY Upd state machine */
|
||||
event_phy_req_prep(conn);
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||
} else if (conn->llcp_cis.req != conn->llcp_cis.ack) {
|
||||
if (conn->llcp_cis.state == LLCP_CIS_STATE_RSP_WAIT) {
|
||||
/* Handle CIS response */
|
||||
event_send_cis_rsp(conn);
|
||||
} else if (conn->llcp_cis.state ==
|
||||
LLCP_CIS_STATE_INST_WAIT) {
|
||||
struct lll_conn *lll = &conn->lll;
|
||||
uint16_t event_counter;
|
||||
|
||||
/* Calculate current event counter */
|
||||
event_counter = lll->event_counter +
|
||||
lll->latency_prepare + lazy;
|
||||
|
||||
/* Start CIS peripheral */
|
||||
event_peripheral_iso_prep(conn,
|
||||
event_counter,
|
||||
ticks_at_expire);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5284,6 +5316,107 @@ static inline uint8_t phy_upd_ind_recv(struct ll_conn *conn, memq_link_t *link,
|
|||
}
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||
void event_send_cis_rsp(struct ll_conn *conn)
|
||||
{
|
||||
struct node_tx *tx;
|
||||
|
||||
tx = mem_acquire(&mem_conn_tx_ctrl.free);
|
||||
if (tx) {
|
||||
struct pdu_data *pdu = (void *)tx->pdu;
|
||||
|
||||
pdu->ll_id = PDU_DATA_LLID_CTRL;
|
||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CIS_RSP;
|
||||
|
||||
sys_put_le24(conn->llcp_cis.cis_offset_min,
|
||||
pdu->llctrl.cis_rsp.cis_offset_min);
|
||||
sys_put_le24(conn->llcp_cis.cis_offset_max,
|
||||
pdu->llctrl.cis_rsp.cis_offset_max);
|
||||
pdu->llctrl.cis_rsp.conn_event_count =
|
||||
sys_cpu_to_le16(conn->llcp_cis.conn_event_count);
|
||||
|
||||
pdu->len = offsetof(struct pdu_data_llctrl, cis_rsp) +
|
||||
sizeof(struct pdu_data_llctrl_cis_rsp);
|
||||
|
||||
conn->llcp_cis.state = LLCP_CIS_STATE_IND_WAIT;
|
||||
|
||||
ctrl_tx_enqueue(conn, tx);
|
||||
}
|
||||
}
|
||||
|
||||
void event_peripheral_iso_prep(struct ll_conn *conn, uint16_t event_counter,
|
||||
uint32_t ticks_at_expire)
|
||||
{
|
||||
if (event_counter == conn->llcp_cis.conn_event_count) {
|
||||
ull_peripheral_iso_start(conn, ticks_at_expire);
|
||||
|
||||
conn->llcp_cis.state = LLCP_CIS_STATE_REQ;
|
||||
conn->llcp_cis.ack = conn->llcp_cis.req;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t cis_req_recv(struct ll_conn *conn, memq_link_t *link,
|
||||
struct node_rx_pdu **rx, struct pdu_data *pdu)
|
||||
{
|
||||
struct pdu_data_llctrl_cis_req *req = &pdu->llctrl.cis_req;
|
||||
struct node_rx_conn_iso_req *conn_iso_req;
|
||||
uint16_t cis_handle;
|
||||
uint8_t err;
|
||||
|
||||
conn->llcp_cis.cig_id = req->cig_id;
|
||||
conn->llcp_cis.framed = req->framed;
|
||||
conn->llcp_cis.c_max_sdu = sys_le16_to_cpu(req->c_max_sdu);
|
||||
conn->llcp_cis.p_max_sdu = sys_le16_to_cpu(req->p_max_sdu);
|
||||
conn->llcp_cis.c_sdu_interval = sys_get_le24(req->c_sdu_interval);
|
||||
conn->llcp_cis.p_sdu_interval = sys_get_le24(req->p_sdu_interval);
|
||||
conn->llcp_cis.cis_offset_min = sys_get_le24(req->cis_offset_min);
|
||||
conn->llcp_cis.cis_offset_max = sys_get_le24(req->cis_offset_max);
|
||||
conn->llcp_cis.conn_event_count =
|
||||
sys_le16_to_cpu(req->conn_event_count);
|
||||
|
||||
/* Acquire resources for new CIS */
|
||||
err = ull_peripheral_iso_acquire(conn, &pdu->llctrl.cis_req, &cis_handle);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
conn->llcp_cis.cis_handle = cis_handle;
|
||||
conn->llcp_cis.state = LLCP_CIS_STATE_RSP_WAIT;
|
||||
conn->llcp_cis.ack -= 2U;
|
||||
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_CIS_REQUEST;
|
||||
|
||||
conn_iso_req = (void *)pdu;
|
||||
conn_iso_req->cig_id = req->cig_id;
|
||||
conn_iso_req->cis_id = req->cis_id;
|
||||
conn_iso_req->cis_handle = sys_le16_to_cpu(cis_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t cis_ind_recv(struct ll_conn *conn, memq_link_t *link,
|
||||
struct node_rx_pdu **rx, struct pdu_data *pdu)
|
||||
{
|
||||
struct pdu_data_llctrl_cis_ind *ind = &pdu->llctrl.cis_ind;
|
||||
uint8_t err;
|
||||
|
||||
conn->llcp_cis.conn_event_count =
|
||||
sys_le16_to_cpu(ind->conn_event_count);
|
||||
|
||||
/* Setup CIS connection */
|
||||
err = ull_peripheral_iso_setup(&pdu->llctrl.cis_ind,
|
||||
conn->llcp_cis.cig_id,
|
||||
conn->llcp_cis.cis_handle);
|
||||
|
||||
conn->llcp_cis.state = LLCP_CIS_STATE_INST_WAIT;
|
||||
|
||||
/* Mark for buffer for release */
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_RELEASE;
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||
|
||||
static inline void ctrl_tx_pre_ack(struct ll_conn *conn,
|
||||
struct pdu_data *pdu_tx)
|
||||
{
|
||||
|
@ -6528,6 +6661,40 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
#endif /* CONFIG_BT_CENTRAL */
|
||||
#endif /* CONFIG_BT_CTLR_MIN_USED_CHAN */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||
case PDU_DATA_LLCTRL_TYPE_CIS_REQ:
|
||||
{
|
||||
uint8_t err;
|
||||
|
||||
if (!conn->lll.role ||
|
||||
PDU_DATA_LLCTRL_LEN(cis_req) != pdu_rx->len) {
|
||||
goto ull_conn_rx_unknown_rsp_send;
|
||||
}
|
||||
|
||||
err = cis_req_recv(conn, link, rx, pdu_rx);
|
||||
if (err) {
|
||||
conn->llcp_terminate.reason_peer = err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_CIS_IND:
|
||||
{
|
||||
uint8_t err;
|
||||
|
||||
if (!conn->lll.role ||
|
||||
PDU_DATA_LLCTRL_LEN(cis_ind) != pdu_rx->len) {
|
||||
goto ull_conn_rx_unknown_rsp_send;
|
||||
}
|
||||
|
||||
err = cis_ind_recv(conn, link, rx, pdu_rx);
|
||||
if (err) {
|
||||
conn->llcp_terminate.reason_peer = err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||
|
||||
default:
|
||||
ull_conn_rx_unknown_rsp_send:
|
||||
nack = unknown_rsp_send(conn, *rx, opcode);
|
||||
|
|
|
@ -311,6 +311,32 @@ struct ll_conn {
|
|||
struct node_tx *tx_data_last;
|
||||
|
||||
uint8_t chm_updated;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
|
||||
struct {
|
||||
uint8_t req;
|
||||
uint8_t ack;
|
||||
enum {
|
||||
LLCP_CIS_STATE_REQ,
|
||||
LLCP_CIS_STATE_RSP_WAIT,
|
||||
LLCP_CIS_STATE_IND_WAIT,
|
||||
LLCP_CIS_STATE_INST_WAIT
|
||||
} state:8 __packed;
|
||||
uint8_t cig_id;
|
||||
uint16_t cis_handle;
|
||||
uint8_t cis_id;
|
||||
uint32_t c_max_sdu:12;
|
||||
uint32_t p_max_sdu:12;
|
||||
uint32_t framed:1;
|
||||
uint32_t c_sdu_interval;
|
||||
uint32_t p_sdu_interval;
|
||||
uint32_t cis_offset_min;
|
||||
uint32_t cis_offset_max;
|
||||
uint16_t conn_event_count;
|
||||
uint32_t cig_sync_delay;
|
||||
uint32_t cis_sync_delay;
|
||||
} llcp_cis;
|
||||
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
|
||||
};
|
||||
|
||||
struct node_rx_cc {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue