Skip to content

Commit 4c20a96

Browse files
nimble/controller: Add Synchronized Receiver role support
This adds Synchronized Receiver role support. The role enables reception of broadcast isochronous streams. Co-authored-by: Andrzej Kaczmarek <[email protected]>
1 parent 074888c commit 4c20a96

28 files changed

+5219
-526
lines changed

nimble/controller/include/controller/ble_ll.h

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
243243
#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER)
244244
#define BLE_LL_STATE_BIG (9)
245245
#endif
246+
#if MYNEWT_VAL(BLE_LL_ISO_BROADCAST_SYNC)
247+
#define BLE_LL_STATE_BIG_SYNC (10)
248+
#endif
246249

247250
/* LL Features */
248251
#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000000001)
@@ -301,7 +304,8 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
301304

302305
/* All the features which can be controlled by the Host */
303306
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) | \
304-
MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION)
307+
MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) | \
308+
MYNEWT_VAL(BLE_LL_ISO)
305309
#define BLE_LL_HOST_CONTROLLED_FEATURES (1)
306310
#else
307311
#define BLE_LL_HOST_CONTROLLED_FEATURES (0)
@@ -462,6 +466,54 @@ struct ble_dev_addr
462466
((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \
463467
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG))
464468

469+
/*
470+
* Broadcast Isochronous Data Channel format
471+
*
472+
* -> Header (2 bytes)
473+
* -> LSB contains llid, cssn and cstf
474+
* -> MSB contains length (8 bits)
475+
* -> Payload (0 to 251)
476+
* -> MIC (0 or 4 bytes)
477+
*/
478+
#define BLE_LL_BIS_PDU_HDR_LLID_MASK (0x03)
479+
#define BLE_LL_BIS_PDU_HDR_CSSN_MASK (0x1C)
480+
#define BLE_LL_BIS_PDU_HDR_CSTF_MASK (0x20)
481+
#define BLE_LL_BIS_PDU_HDR_RFU_MASK (0xC0)
482+
#define BLE_LL_ISO_DATA_PAYLOAD_MAX (251)
483+
#define BLE_LL_ISO_DATA_MIC_LEN (4)
484+
485+
/* Broadcast Isochronous PDU header LLID definitions */
486+
#define BLE_LL_BIS_LLID_DATA_PDU_UNFRAMED_CMPLT (0b00)
487+
#define BLE_LL_BIS_LLID_DATA_PDU_UNFRAMED_SC (0b01)
488+
#define BLE_LL_BIS_LLID_DATA_PDU_FRAMED (0b10)
489+
#define BLE_LL_BIS_LLID_CTRL_PDU (0b11)
490+
491+
#define BLE_LL_BIS_PDU_HDR_LLID(hdr) \
492+
(((hdr) & BLE_LL_BIS_PDU_HDR_LLID_MASK) >> 0)
493+
#define BLE_LL_BIS_PDU_HDR_CSSN(hdr) \
494+
(((hdr) & BLE_LL_BIS_PDU_HDR_CSSN_MASK) >> 2)
495+
#define BLE_LL_BIS_PDU_HDR_CSTF(hdr) \
496+
(((hdr) & BLE_LL_BIS_PDU_HDR_CSTF_MASK) >> 5)
497+
498+
#define BLE_LL_BIS_LLID_IS_CTRL(hdr) \
499+
(BLE_LL_BIS_PDU_HDR_LLID(hdr) == BLE_LL_BIS_LLID_CTRL_PDU)
500+
#define BLE_LL_BIS_LLID_IS_DATA(hdr) \
501+
((BLE_LL_BIS_PDU_HDR_LLID(hdr) == BLE_LL_BIS_LLID_DATA_PDU_UNFRAMED_CMPLT) || \
502+
(BLE_LL_BIS_PDU_HDR_LLID(hdr) == BLE_LL_BIS_LLID_DATA_PDU_UNFRAMED_SC) || \
503+
(BLE_LL_BIS_PDU_HDR_LLID(hdr) == BLE_LL_BIS_LLID_DATA_PDU_FRAMED))
504+
505+
#define BLE_LL_BIG_CTRL_CHAN_MAP_IND (0x00)
506+
struct ble_ll_big_ctrl_chan_map_ind {
507+
uint8_t chan_map[BLE_LL_CHAN_MAP_LEN];
508+
uint16_t instant;
509+
} __attribute__((packed));
510+
511+
#define BLE_LL_BIG_CTRL_TERM_IND (0x01)
512+
struct ble_ll_big_ctrl_term_ind {
513+
uint8_t reason;
514+
uint16_t instant;
515+
} __attribute__((packed));
516+
465517
/*
466518
* CONNECT_REQ
467519
* -> InitA (6 bytes)
@@ -581,6 +633,9 @@ int ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *hdr);
581633
/* Called by the PHY when a packet reception ends */
582634
int ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
583635

636+
/* Called by the PHY when a packet reception ends */
637+
int ble_ll_rx_early_end(const uint8_t *rxbuf, const struct ble_mbuf_hdr *rxhdr);
638+
584639
/* Helper callback to tx mbuf using ble_phy_tx() */
585640
uint8_t ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte);
586641
uint8_t ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte);

nimble/controller/include/controller/ble_ll_iso.h

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,55 @@
2727
extern "C" {
2828
#endif
2929

30-
struct ble_ll_iso_data_path {
31-
uint8_t data_path_id;
32-
uint8_t enabled : 1;
30+
/**
31+
* @struct ble_ll_iso_data_path_cb
32+
*
33+
* Interface structure for ISO data path callbacks.
34+
*/
35+
struct ble_ll_iso_data_path_cb {
36+
/**
37+
* @brief Callback function for sending an ISO SDU (Service Data Unit).
38+
*
39+
* @param conn_handle The connection handle associated with the received SDU.
40+
* @param om Pointer to the `os_mbuf` structure containing the SDU data.
41+
* Can be `NULL` if the SDU is considered as lost.
42+
* @param timestamp Timestamp associated with the received SDU.
43+
* @param seq_num Sequence number of the SDU.
44+
* @param valid Status of the SDU reception.
45+
* - `true`: SDU was received successfully, and `om` contains valid data.
46+
* - `false`: An error occurred during processing, but partial or corrupted
47+
* SDU data may be available in `om`.
48+
*/
49+
void (*sdu_send)(uint16_t conn_handle, const struct os_mbuf *om, uint32_t timestamp,
50+
uint16_t seq_num, bool valid);
3351
};
34-
struct ble_ll_iso_test_mode {
52+
struct ble_ll_iso_rx {
3553
struct {
36-
uint32_t rand;
3754
uint8_t payload_type;
38-
uint8_t enabled : 1;
39-
} transmit;
55+
uint32_t received_sdu_count;
56+
uint32_t missed_sdu_count;
57+
uint32_t failed_sdu_count;
58+
} test;
59+
60+
const struct ble_ll_iso_data_path_cb *data_path;
61+
};
62+
struct ble_ll_iso_tx {
63+
struct {
64+
uint8_t payload_type;
65+
uint32_t rand;
66+
} test;
67+
68+
const struct ble_ll_iso_data_path_cb *data_path;
4069
};
4170
struct ble_ll_iso_conn {
4271
/* Connection handle */
4372
uint16_t handle;
4473

45-
/* Maximum SDU size */
46-
uint16_t max_sdu;
74+
/* ISO Rx */
75+
struct ble_ll_iso_rx *rx;
4776

48-
/* ISO Data Path */
49-
struct ble_ll_iso_data_path data_path;
50-
51-
/* ISO Test Mode */
52-
struct ble_ll_iso_test_mode test_mode;
77+
/* ISO Tx */
78+
struct ble_ll_iso_tx *tx;
5379

5480
/* ISOAL Multiplexer */
5581
struct ble_ll_isoal_mux mux;
@@ -74,36 +100,28 @@ int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
74100
int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
75101
int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
76102
int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len);
77-
int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len);
103+
int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
78104
int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
79105
int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
80106
int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
81107
int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
82-
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len);
83-
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len);
108+
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
109+
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
84110
int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
85111

86112
void ble_ll_iso_init(void);
87113
void ble_ll_iso_reset(void);
88114

89-
/* ISO Data handler */
115+
/* ISO Data SDU handler */
90116
int ble_ll_iso_data_in(struct os_mbuf *om);
91117

92118
int ble_ll_iso_pdu_get(struct ble_ll_iso_conn *conn, uint8_t idx, uint32_t pkt_counter, uint8_t *llid, void *dptr);
93119

94-
struct ble_ll_iso_conn_init_param {
95-
uint32_t iso_interval_us;
96-
uint32_t sdu_interval_us;
97-
uint16_t conn_handle;
98-
uint16_t max_sdu;
99-
uint8_t max_pdu;
100-
uint8_t framing;
101-
uint8_t pte;
102-
uint8_t bn;
103-
};
120+
/* ISO Data PDU handler */
121+
int ble_ll_iso_data_pdu_in(struct ble_ll_iso_conn *conn, uint8_t idx, struct os_mbuf *om);
104122

105-
void ble_ll_iso_conn_init(struct ble_ll_iso_conn *conn, struct ble_ll_iso_conn_init_param *param);
106-
void ble_ll_iso_conn_free(struct ble_ll_iso_conn *conn);
123+
void ble_ll_iso_conn_add(struct ble_ll_iso_conn *conn);
124+
void ble_ll_iso_conn_rem(struct ble_ll_iso_conn *conn);
107125

108126
int ble_ll_iso_conn_event_start(struct ble_ll_iso_conn *conn, uint32_t timestamp);
109127
int ble_ll_iso_conn_event_done(struct ble_ll_iso_conn *conn);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#ifndef H_BLE_LL_ISO_BIG_SYNC_
21+
#define H_BLE_LL_ISO_BIG_SYNC_
22+
23+
#ifdef __cplusplus
24+
extern "C" {
25+
#endif
26+
27+
#if MYNEWT_VAL(BLE_LL_ISO_BROADCAST_SYNC)
28+
29+
int ble_ll_iso_big_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr);
30+
int ble_ll_iso_big_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
31+
int ble_ll_iso_big_sync_rx_isr_early_end(const uint8_t *rxbuf, const struct ble_mbuf_hdr *rxhdr);
32+
void ble_ll_iso_big_sync_rx_pdu_in(struct os_mbuf **rxpdu, struct ble_mbuf_hdr *hdr);
33+
34+
void ble_ll_iso_big_sync_wfr_timer_exp(void);
35+
void ble_ll_iso_big_sync_halt(void);
36+
37+
int ble_ll_iso_big_sync_hci_create(const uint8_t *cmdbuf, uint8_t len);
38+
int ble_ll_iso_big_sync_hci_terminate(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
39+
40+
void ble_ll_iso_big_sync_init(void);
41+
void ble_ll_iso_big_sync_reset(void);
42+
43+
#endif /* BLE_LL_ISO_BROADCAST_SYNC */
44+
45+
#ifdef __cplusplus
46+
}
47+
#endif
48+
49+
#endif /* H_BLE_LL_ISO_BIG_SYNC_ */

nimble/controller/include/controller/ble_ll_isoal.h

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,26 @@
2727
extern "C" {
2828
#endif
2929

30+
/* Forward declaration */
31+
struct ble_ll_isoal_mux;
32+
33+
struct ble_ll_isoal_mux_cb {
34+
void (*sdu_send)(struct ble_ll_isoal_mux *mux, const struct os_mbuf *om, uint32_t timestamp,
35+
uint16_t seq_num, bool valid);
36+
};
37+
3038
struct ble_ll_isoal_mux {
3139
#if MYNEWT_VAL(BLE_LL_ISOAL_MUX_PREFILL)
3240
uint8_t active;
3341
#endif
3442

43+
/* ISO Interval */
44+
uint32_t iso_interval_us;
45+
/* SDU Interval */
46+
uint32_t sdu_interval_us;
47+
48+
/* Maximum SDU size */
49+
uint16_t max_sdu;
3550
/* Max PDU length */
3651
uint8_t max_pdu;
3752
/* Number of expected SDUs per ISO interval */
@@ -49,8 +64,14 @@ struct ble_ll_isoal_mux {
4964
STAILQ_HEAD(, os_mbuf_pkthdr) sdu_q;
5065
uint16_t sdu_q_len;
5166

67+
/* ISO Data PDUs */
68+
STAILQ_HEAD(, os_mbuf_pkthdr) pdu_q;
69+
5270
uint32_t sdu_counter;
5371

72+
/* HCI SDU Fragment */
73+
struct os_mbuf *frag;
74+
5475
uint32_t event_tx_timestamp;
5576
uint32_t last_tx_timestamp;
5677
uint16_t last_tx_packet_seq_num;
@@ -59,6 +80,9 @@ struct ble_ll_isoal_mux {
5980
uint8_t sc : 1;
6081
uint8_t framed : 1;
6182
uint8_t framing_mode : 1;
83+
84+
/* Callback structure */
85+
const struct ble_ll_isoal_mux_cb *cb;
6286
};
6387

6488
#define BLE_LL_ISOAL_SEGHDR(sc, cmplt, len) \
@@ -72,10 +96,19 @@ struct ble_ll_isoal_mux {
7296
((framing) == BLE_HCI_ISO_FRAMING_FRAMED_SEGMENTABLE || \
7397
(framing) == BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED)
7498

75-
void ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, uint8_t max_pdu,
76-
uint32_t iso_interval_us, uint32_t sdu_interval_us,
77-
uint8_t bn, uint8_t pte, bool framed,
78-
uint8_t framing_mode);
99+
struct ble_ll_isoal_mux_init_param {
100+
uint32_t iso_interval_us;
101+
uint32_t sdu_interval_us;
102+
uint16_t max_sdu;
103+
uint8_t max_pdu;
104+
uint8_t bn;
105+
uint8_t pte;
106+
uint8_t framed;
107+
uint8_t framing_mode;
108+
};
109+
110+
void ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux,
111+
const struct ble_ll_isoal_mux_init_param *param);
79112
void ble_ll_isoal_mux_free(struct ble_ll_isoal_mux *mux);
80113

81114
int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux,
@@ -88,6 +121,12 @@ int ble_ll_isoal_mux_pdu_get(struct ble_ll_isoal_mux *mux, uint8_t idx,
88121
void ble_ll_isoal_mux_sdu_enqueue(struct ble_ll_isoal_mux *mux,
89122
struct os_mbuf *om);
90123

124+
void ble_ll_isoal_mux_pdu_enqueue(struct ble_ll_isoal_mux *mux, uint8_t idx,
125+
struct os_mbuf *om);
126+
127+
int ble_ll_isoal_mux_cb_set(struct ble_ll_isoal_mux *mux,
128+
const struct ble_ll_isoal_mux_cb *cb);
129+
91130
void ble_ll_isoal_init(void);
92131
void ble_ll_isoal_reset(void);
93132

nimble/controller/include/controller/ble_ll_sched.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ extern uint8_t g_ble_ll_sched_offset_ticks;
7171
#define BLE_LL_SCHED_TYPE_SYNC (7)
7272
#define BLE_LL_SCHED_TYPE_SCAN_AUX (8)
7373
#define BLE_LL_SCHED_TYPE_BIG (9)
74+
#define BLE_LL_SCHED_TYPE_BIG_SYNC (10)
7475
#if MYNEWT_VAL(BLE_LL_EXT)
7576
#define BLE_LL_SCHED_TYPE_EXTERNAL (255)
7677
#endif
@@ -222,6 +223,10 @@ uint32_t ble_ll_sched_css_get_conn_interval_us(void);
222223
int ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first, int fixed);
223224
#endif /* BLE_LL_ISO_BROADCASTER */
224225

226+
#if MYNEWT_VAL(BLE_LL_ISO_BROADCAST_SYNC)
227+
int ble_ll_sched_iso_big_sync(struct ble_ll_sched_item *sch);
228+
#endif /* BLE_LL_ISO_BROADCAST_SYNC */
229+
225230
#ifdef __cplusplus
226231
}
227232
#endif

nimble/controller/include/controller/ble_ll_sync.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ void ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm);
6262

6363
uint32_t ble_ll_sync_get_event_end_time(void);
6464

65+
typedef void (* ble_ll_sync_biginfo_cb_t)(struct ble_ll_sync_sm *syncsm, uint8_t sca,
66+
uint32_t sync_ticks, uint8_t sync_rem_us,
67+
const uint8_t *data, uint8_t len,
68+
void *arg);
69+
70+
struct ble_ll_sync_sm *ble_ll_sync_get(uint8_t handle);
71+
void ble_ll_sync_biginfo_cb_set(struct ble_ll_sync_sm *syncsm,
72+
ble_ll_sync_biginfo_cb_t cb, void *cb_arg);
73+
6574
bool ble_ll_sync_enabled(void);
6675

6776
void ble_ll_sync_reset(void);

nimble/controller/include/controller/ble_phy.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,22 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options)
230230
return phy_mode;
231231
}
232232

233+
static inline bool ble_ll_phy_is_supported(uint8_t phy)
234+
{
235+
switch (phy) {
236+
case BLE_PHY_1M:
237+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
238+
case BLE_PHY_2M:
239+
#endif
240+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
241+
case BLE_PHY_CODED:
242+
#endif
243+
return true;
244+
default:
245+
return false;
246+
}
247+
}
248+
233249
#if MYNEWT_VAL(BLE_LL_DTM)
234250
void ble_phy_enable_dtm(void);
235251
void ble_phy_disable_dtm(void);

0 commit comments

Comments
 (0)