Skip to content

Commit f039be4

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 f039be4

29 files changed

+5913
-837
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: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,52 +17,16 @@
1717
* under the License.
1818
*/
1919

20-
#ifndef H_BLE_LL_ISO
21-
#define H_BLE_LL_ISO
20+
#ifndef H_BLE_LL_ISO_
21+
#define H_BLE_LL_ISO_
2222

2323
#include <stdint.h>
24-
#include <controller/ble_ll_isoal.h>
24+
#include <os/os_mbuf.h>
2525

2626
#ifdef __cplusplus
2727
extern "C" {
2828
#endif
2929

30-
struct ble_ll_iso_data_path {
31-
uint8_t data_path_id;
32-
uint8_t enabled : 1;
33-
};
34-
struct ble_ll_iso_test_mode {
35-
struct {
36-
uint32_t rand;
37-
uint8_t payload_type;
38-
uint8_t enabled : 1;
39-
} transmit;
40-
};
41-
struct ble_ll_iso_conn {
42-
/* Connection handle */
43-
uint16_t handle;
44-
45-
/* Maximum SDU size */
46-
uint16_t max_sdu;
47-
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;
53-
54-
/* ISOAL Multiplexer */
55-
struct ble_ll_isoal_mux mux;
56-
57-
/* HCI SDU Fragment */
58-
struct os_mbuf *frag;
59-
60-
/* Number of Completed Packets */
61-
uint16_t num_completed_pkt;
62-
63-
STAILQ_ENTRY(ble_ll_iso_conn) iso_conn_q_next;
64-
};
65-
6630
/* HCI command handlers */
6731
int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
6832
int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
@@ -74,41 +38,20 @@ int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
7438
int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
7539
int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
7640
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);
41+
int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
7842
int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
7943
int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8044
int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8145
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);
46+
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
47+
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8448
int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8549

8650
void ble_ll_iso_init(void);
8751
void ble_ll_iso_reset(void);
8852

89-
/* ISO Data handler */
90-
int ble_ll_iso_data_in(struct os_mbuf *om);
91-
92-
int ble_ll_iso_pdu_get(struct ble_ll_iso_conn *conn, uint8_t idx, uint32_t pkt_counter, uint8_t *llid, void *dptr);
93-
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-
};
104-
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);
107-
108-
int ble_ll_iso_conn_event_start(struct ble_ll_iso_conn *conn, uint32_t timestamp);
109-
int ble_ll_iso_conn_event_done(struct ble_ll_iso_conn *conn);
110-
111-
struct ble_ll_iso_conn *ble_ll_iso_conn_find_by_handle(uint16_t conn_handle);
53+
/* HCI ISO Data SDU handler */
54+
int ble_ll_hci_iso_data_in(struct os_mbuf *om);
11255

11356
#ifdef __cplusplus
11457
}
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: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,53 @@
2121
#define H_BLE_LL_ISOAL_
2222

2323
#include <os/os_mbuf.h>
24-
#include <syscfg/syscfg.h>
2524

2625
#ifdef __cplusplus
2726
extern "C" {
2827
#endif
2928

29+
#define BLE_LL_ISOAL_SEGHDR(sc, cmplt, len) \
30+
((uint16_t)((sc) & 0x01) | (((cmplt) & 0x01) << 1) | ((len) & 0xff) << 8)
31+
32+
#define BLE_LL_ISOAL_SEGHDR_SC(word) ((word) & 0x01)
33+
#define BLE_LL_ISOAL_SEGHDR_CMPLT(word) ((word >> 1) & 0x01)
34+
#define BLE_LL_ISOAL_SEGHDR_LEN(word) ((word >> 8) & 0xff)
35+
36+
#define BLE_LL_ISOAL_TIME_OFFSET_LEN 3
37+
38+
struct ble_ll_isoal_config {
39+
/* ISO Interval */
40+
uint32_t iso_interval_us;
41+
/* SDU Interval */
42+
uint32_t sdu_interval_us;
43+
/* Maximum SDU size */
44+
uint16_t max_sdu;
45+
/* Max PDU length */
46+
uint8_t max_pdu;
47+
/* Burst Number */
48+
uint8_t bn;
49+
/**/
50+
uint8_t pte;
51+
/* Framed */
52+
uint8_t framed : 1;
53+
/* Framing mode = segmentable/unsegmented */
54+
uint8_t unsegmented : 1;
55+
};
56+
3057
struct ble_ll_isoal_mux {
58+
struct ble_ll_isoal_config config;
3159
#if MYNEWT_VAL(BLE_LL_ISOAL_MUX_PREFILL)
3260
uint8_t active;
3361
#endif
34-
35-
/* Max PDU length */
36-
uint8_t max_pdu;
3762
/* Number of expected SDUs per ISO interval */
3863
uint8_t sdu_per_interval;
3964
/* Number of expected PDUs per SDU */
4065
uint8_t pdu_per_sdu;
4166
/* Number of SDUs required to fill complete BIG/CIG event (i.e. with pt) */
4267
uint8_t sdu_per_event;
43-
/* Number of SDUs available for current event */
68+
/* Number of SDUs available for the current event */
4469
uint8_t sdu_in_event;
4570

46-
/* Burst Number */
47-
uint8_t bn;
48-
4971
STAILQ_HEAD(, os_mbuf_pkthdr) sdu_q;
5072
uint16_t sdu_q_len;
5173

@@ -57,39 +79,60 @@ struct ble_ll_isoal_mux {
5779

5880
/* The head SDU Segment is the Continuation of an SDU */
5981
uint8_t sc : 1;
60-
uint8_t framed : 1;
61-
uint8_t framing_mode : 1;
6282
};
6383

64-
#define BLE_LL_ISOAL_SEGHDR(sc, cmplt, len) \
65-
((uint16_t)((sc) & 0x01) | (((cmplt) & 0x01) << 1) | ((len) & 0xff) << 8)
84+
void ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, struct ble_ll_isoal_config *config);
85+
void ble_ll_isoal_mux_reset(struct ble_ll_isoal_mux *mux);
86+
int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux, uint32_t timestamp);
87+
int ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux);
88+
int ble_ll_isoal_mux_pdu_get(struct ble_ll_isoal_mux *mux, uint8_t idx, uint8_t *llid, void *dptr);
89+
void ble_ll_isoal_mux_sdu_put(struct ble_ll_isoal_mux *mux, struct os_mbuf *om);
6690

67-
#define BLE_LL_ISOAL_SEGHDR_SC(word) ((word) & 0x01)
68-
#define BLE_LL_ISOAL_SEGHDR_CMPLT(word) ((word >> 1) & 0x01)
69-
#define BLE_LL_ISOAL_SEGHDR_LEN(word) ((word >> 8) & 0xff)
91+
/* Forward declaration */
92+
struct ble_ll_isoal_demux;
7093

71-
#define BLE_LL_ISOAL_MUX_IS_FRAMED(framing) \
72-
((framing) == BLE_HCI_ISO_FRAMING_FRAMED_SEGMENTABLE || \
73-
(framing) == BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED)
94+
/* ISOAL Demultiplexer callback structure */
95+
struct ble_ll_isoal_demux_cb {
96+
void (*sdu_cb)(struct ble_ll_isoal_demux *demux, const struct os_mbuf *om, uint32_t timestamp,
97+
uint16_t seq_num, bool valid);
98+
};
7499

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);
79-
void ble_ll_isoal_mux_free(struct ble_ll_isoal_mux *mux);
100+
struct ble_ll_isoal_demux {
101+
struct ble_ll_isoal_config config;
80102

81-
int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux,
82-
uint32_t timestamp);
83-
int ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux);
103+
uint8_t active;
84104

85-
int ble_ll_isoal_mux_pdu_get(struct ble_ll_isoal_mux *mux, uint8_t idx,
86-
uint8_t *llid, void *dptr);
105+
/* Number of expected SDUs per ISO interval */
106+
uint8_t sdu_per_interval;
107+
/* Number of expected PDUs per SDU */
108+
uint8_t pdu_per_sdu;
109+
/* Number of SDUs expected for the current event */
110+
uint8_t sdu_in_event;
111+
112+
STAILQ_HEAD(, os_mbuf_pkthdr) pdu_q;
113+
114+
uint32_t sdu_counter;
115+
116+
uint32_t ref_time;
117+
uint32_t last_rx_timestamp;
87118

88-
void ble_ll_isoal_mux_sdu_enqueue(struct ble_ll_isoal_mux *mux,
89-
struct os_mbuf *om);
119+
struct os_mbuf *frag;
90120

91-
void ble_ll_isoal_init(void);
92-
void ble_ll_isoal_reset(void);
121+
const struct ble_ll_isoal_demux_cb *cb;
122+
};
123+
124+
void ble_ll_isoal_demux_init(struct ble_ll_isoal_demux *demux,
125+
struct ble_ll_isoal_config *config);
126+
void ble_ll_isoal_demux_reset(struct ble_ll_isoal_demux *demux);
127+
int ble_ll_isoal_demux_event_start(struct ble_ll_isoal_demux *demux, uint32_t timestamp);
128+
int ble_ll_isoal_demux_event_done(struct ble_ll_isoal_demux *demux);
129+
void ble_ll_isoal_demux_pdu_put(struct ble_ll_isoal_demux *demux, uint8_t idx, struct os_mbuf *om);
130+
131+
static inline void
132+
ble_ll_isoal_demux_cb_set(struct ble_ll_isoal_demux *demux, const struct ble_ll_isoal_demux_cb *cb)
133+
{
134+
demux->cb = cb;
135+
}
93136

94137
#ifdef __cplusplus
95138
}

0 commit comments

Comments
 (0)