Skip to content

Commit a707eda

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 5220e7e commit a707eda

28 files changed

+5970
-843
lines changed

nimble/controller/include/controller/ble_ll.h

Lines changed: 53 additions & 2 deletions
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)
@@ -300,8 +303,8 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
300303
#define BLE_LL_CONN_CLEAR_FEATURE(connsm, feature) (connsm->conn_features &= ~(feature))
301304

302305
/* All the features which can be controlled by the Host */
303-
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) | \
304-
MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION)
306+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) | \
307+
MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) | MYNEWT_VAL(BLE_LL_ISO)
305308
#define BLE_LL_HOST_CONTROLLED_FEATURES (1)
306309
#else
307310
#define BLE_LL_HOST_CONTROLLED_FEATURES (0)
@@ -462,6 +465,54 @@ struct ble_dev_addr
462465
((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \
463466
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG))
464467

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

nimble/controller/include/controller/ble_ll_iso.h

Lines changed: 11 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,23 @@ 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,
42+
uint8_t *rspbuf, uint8_t *rsplen);
7843
int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
7944
int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8045
int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8146
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);
47+
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len,
48+
uint8_t *rspbuf, uint8_t *rsplen);
49+
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len,
50+
uint8_t *rspbuf, uint8_t *rsplen);
8451
int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
8552

8653
void ble_ll_iso_init(void);
8754
void ble_ll_iso_reset(void);
8855

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);
56+
/* HCI ISO Data SDU handler */
57+
int ble_ll_hci_iso_data_in(struct os_mbuf *om);
11258

11359
#ifdef __cplusplus
11460
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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,
32+
const struct ble_mbuf_hdr *rxhdr);
33+
void ble_ll_iso_big_sync_rx_pdu_in(struct os_mbuf **rxpdu, struct ble_mbuf_hdr *hdr);
34+
35+
void ble_ll_iso_big_sync_wfr_timer_exp(void);
36+
void ble_ll_iso_big_sync_halt(void);
37+
38+
int ble_ll_iso_big_sync_hci_create(const uint8_t *cmdbuf, uint8_t len);
39+
int ble_ll_iso_big_sync_hci_terminate(const uint8_t *cmdbuf, uint8_t len,
40+
uint8_t *rspbuf, uint8_t *rsplen);
41+
42+
void ble_ll_iso_big_sync_init(void);
43+
void ble_ll_iso_big_sync_reset(void);
44+
45+
#endif /* BLE_LL_ISO_BROADCAST_SYNC */
46+
47+
#ifdef __cplusplus
48+
}
49+
#endif
50+
51+
#endif /* H_BLE_LL_ISO_BIG_SYNC_ */

nimble/controller/include/controller/ble_ll_isoal.h

Lines changed: 79 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,64 @@ 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,
85+
struct ble_ll_isoal_config *config);
86+
void ble_ll_isoal_mux_reset(struct ble_ll_isoal_mux *mux);
87+
int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux, uint32_t timestamp);
88+
int ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux);
89+
int ble_ll_isoal_mux_pdu_get(struct ble_ll_isoal_mux *mux, uint8_t idx,
90+
uint8_t *llid, void *dptr);
91+
void ble_ll_isoal_mux_sdu_put(struct ble_ll_isoal_mux *mux, struct os_mbuf *om);
6692

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)
93+
/* Forward declaration */
94+
struct ble_ll_isoal_demux;
7095

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)
96+
/* ISOAL Demultiplexer callback structure */
97+
struct ble_ll_isoal_demux_cb {
98+
void (*sdu_cb)(struct ble_ll_isoal_demux *demux, const struct os_mbuf *om,
99+
uint32_t timestamp, uint16_t seq_num, bool valid);
100+
};
74101

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);
102+
struct ble_ll_isoal_demux {
103+
struct ble_ll_isoal_config config;
80104

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);
105+
uint8_t active;
84106

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

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

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

94141
#ifdef __cplusplus
95142
}

0 commit comments

Comments
 (0)