Skip to content

Commit f297a41

Browse files
committed
nimble/ll: Add CS Configuration procedure
Implements: - LE CS Create Config command - LE CS Remove Config command
1 parent 6a3e225 commit f297a41

File tree

6 files changed

+337
-4
lines changed

6 files changed

+337
-4
lines changed

nimble/controller/include/controller/ble_ll_conn.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ struct ble_ll_conn_sm
276276
uint8_t vers_nr;
277277
uint8_t conn_features;
278278
uint8_t remote_features[7];
279-
uint16_t pending_ctrl_procs;
279+
uint32_t pending_ctrl_procs;
280280
uint16_t event_cntr;
281281
uint16_t completed_pkts;
282282
uint16_t comp_id;

nimble/controller/include/controller/ble_ll_cs.h

+3
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ void ble_ll_cs_init(void);
3232
void ble_ll_cs_reset(void);
3333

3434
void ble_ll_cs_capabilities_pdu_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
35+
void ble_ll_cs_config_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
3536

3637
int ble_ll_cs_rx_capabilities_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspbuf);
3738
void ble_ll_cs_rx_capabilities_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
3839
int ble_ll_cs_rx_fae_req(struct ble_ll_conn_sm *connsm, uint8_t *rspbuf);
3940
void ble_ll_cs_rx_fae_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
41+
int ble_ll_cs_rx_config_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspbuf);
42+
void ble_ll_cs_rx_config_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
4043

4144
/* HCI handlers */
4245
int ble_ll_cs_hci_rd_loc_supp_cap(uint8_t *rspbuf, uint8_t *rsplen);

nimble/controller/include/controller/ble_ll_ctrl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ extern "C" {
4545
#define BLE_LL_CTRL_PROC_SUBRATE_UPDATE (13)
4646
#define BLE_LL_CTRL_PROC_CS_CAP_XCHG (14)
4747
#define BLE_LL_CTRL_PROC_CS_FAE_REQ (15)
48-
#define BLE_LL_CTRL_PROC_NUM (16)
48+
#define BLE_LL_CTRL_PROC_CS_CONF (16)
49+
#define BLE_LL_CTRL_PROC_NUM (17)
4950
#define BLE_LL_CTRL_PROC_IDLE (255)
5051

5152
/* Checks if a particular control procedure is running */

nimble/controller/src/ble_ll_cs.c

+290-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131

3232
static struct ble_ll_cs_supp_cap g_ble_ll_cs_local_cap;
3333
static struct ble_ll_cs_sm g_ble_ll_cs_sm[MYNEWT_VAL(BLE_MAX_CONNECTIONS)];
34+
static const uint8_t t_ip1[] = {10, 20, 30, 40, 50, 60, 80, 145};
35+
static const uint8_t t_ip2[] = {10, 20, 30, 40, 50, 60, 80, 145};
36+
static const uint8_t t_fcs[] = {15, 20, 30, 40, 50, 60, 80, 100, 120, 150};
37+
static const uint8_t t_pm[] = {10, 20, 40};
3438

3539
int
3640
ble_ll_cs_hci_rd_loc_supp_cap(uint8_t *rspbuf, uint8_t *rsplen)
@@ -432,16 +436,300 @@ ble_ll_cs_hci_wr_cached_rem_fae(const uint8_t *cmdbuf, uint8_t cmdlen,
432436
return BLE_ERR_SUCCESS;
433437
}
434438

439+
void
440+
ble_ll_cs_config_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
441+
{
442+
uint8_t config_id = connsm->cssm->config_req_id;
443+
uint8_t action = connsm->cssm->config_req_action;
444+
const struct ble_ll_cs_config *conf = &connsm->cssm->config[config_id];
445+
446+
*dptr = config_id | action << 6;
447+
448+
if (action == 0x00) {
449+
/* Removing the config, all remaining fields are RFU. */
450+
memset(dptr + 1, 0, 26);
451+
452+
return;
453+
}
454+
455+
memcpy(dptr + 1, conf->chan_map, 10);
456+
dptr[11] = conf->chan_map_repetition;
457+
dptr[12] = conf->main_mode;
458+
dptr[13] = conf->sub_mode;
459+
dptr[14] = conf->main_mode_min_steps;
460+
dptr[15] = conf->main_mode_max_steps;
461+
dptr[16] = conf->main_mode_repetition;
462+
dptr[17] = conf->mode_0_steps;
463+
dptr[18] = conf->cs_sync_phy;
464+
dptr[19] = conf->rtt_type |
465+
conf->role << 4;
466+
dptr[20] = conf->chan_sel |
467+
conf->ch3cshape << 4;
468+
dptr[21] = conf->ch3cjump;
469+
dptr[22] = conf->t_ip1;
470+
dptr[23] = conf->t_ip2;
471+
dptr[24] = conf->t_fcs;
472+
dptr[25] = conf->t_pm;
473+
/* RFU octet */
474+
dptr[26] = 0x00;
475+
}
476+
477+
int
478+
ble_ll_cs_rx_config_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
479+
uint8_t *rspbuf)
480+
{
481+
struct ble_ll_cs_config *conf;
482+
uint8_t config_id = *dptr & 0b00111111;
483+
uint8_t action = (*dptr & 0b11000000) >> 6;
484+
485+
if (config_id >= BLE_LL_CS_CONFIG_MAX_NUM) {
486+
/* LL_REJECT_EXT_IND */
487+
rej_ext_ind_make(BLE_LL_CTRL_CS_CONFIG_REQ, BLE_ERR_INV_LMP_LL_PARM,
488+
rspbuf);
489+
490+
return BLE_LL_CTRL_REJECT_IND_EXT;
491+
}
492+
493+
conf = &connsm->cssm->config[config_id];
494+
memset(conf, 0, sizeof(*conf));
495+
496+
/* Respond with LL_CS_CONFIG_RSP PDU */
497+
*rspbuf = config_id | action << 6;
498+
499+
if (action == 0x00) {
500+
/* CS configuration removed. */
501+
return BLE_LL_CTRL_CS_CONFIG_RSP;
502+
}
503+
504+
memcpy(conf->chan_map, dptr + 1, 10);
505+
conf->chan_map_repetition = dptr[11];
506+
conf->main_mode = dptr[12];
507+
conf->sub_mode = dptr[13];
508+
conf->main_mode_min_steps = dptr[14];
509+
conf->main_mode_max_steps = dptr[15];
510+
conf->main_mode_repetition = dptr[16];
511+
conf->mode_0_steps = dptr[17];
512+
conf->cs_sync_phy = dptr[18];
513+
conf->rtt_type = dptr[19] & 0b00001111;
514+
conf->role = (~dptr[19] >> 4) & 0b00000001;
515+
conf->chan_sel = (dptr[20] & 0b00001111);
516+
conf->ch3cshape = (dptr[20] & 0b11110000) >> 4;
517+
conf->ch3cjump = dptr[21];
518+
conf->t_ip1 = dptr[22];
519+
conf->t_ip2 = dptr[23];
520+
conf->t_fcs = dptr[24];
521+
conf->t_pm = dptr[25];
522+
conf->config_enabled = true;
523+
524+
return BLE_LL_CTRL_CS_CONFIG_RSP;
525+
}
526+
527+
static void
528+
ble_ll_cs_ev_config_complete(struct ble_ll_conn_sm *connsm, uint8_t config_id,
529+
uint8_t action, uint8_t status)
530+
{
531+
struct ble_hci_ev_le_subev_cs_config_complete *ev;
532+
const struct ble_ll_cs_config *conf;
533+
struct ble_hci_ev *hci_ev;
534+
535+
if (ble_ll_hci_is_le_event_enabled(
536+
BLE_HCI_LE_SUBEV_CS_CONFIG_COMPLETE)) {
537+
hci_ev = ble_transport_alloc_evt(0);
538+
if (hci_ev) {
539+
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
540+
hci_ev->length = sizeof(*ev);
541+
ev = (void *) hci_ev->data;
542+
543+
memset(ev, 0, sizeof(*ev));
544+
ev->subev_code = BLE_HCI_LE_SUBEV_CS_CONFIG_COMPLETE;
545+
ev->status = status;
546+
ev->conn_handle = htole16(connsm->conn_handle);
547+
ev->config_id = config_id;
548+
ev->action = action;
549+
550+
if (action == 0x00) {
551+
/* CS configuration removed. */
552+
return;
553+
}
554+
555+
conf = &connsm->cssm->config[config_id];
556+
ev->main_mode_type = conf->main_mode;
557+
ev->sub_mode_type = conf->sub_mode;
558+
ev->min_main_mode_steps = conf->main_mode_min_steps;
559+
ev->max_main_mode_steps = conf->main_mode_max_steps;
560+
ev->main_mode_repetition = conf->main_mode_repetition;
561+
ev->mode_0_steps = conf->mode_0_steps;
562+
ev->role = conf->role;
563+
ev->rtt_type = conf->rtt_type;
564+
ev->cs_sync_phy = conf->cs_sync_phy;
565+
memcpy(ev->channel_map, conf->chan_map, 10);
566+
ev->channel_map_repetition = conf->chan_map_repetition;
567+
ev->channel_selection_type = conf->chan_sel;
568+
ev->ch3c_shape = conf->ch3cshape;
569+
ev->ch3c_jump = conf->ch3cjump;
570+
ev->reserved = 0x00;
571+
ev->t_ip1_time = conf->t_ip1;
572+
ev->t_ip2_time = conf->t_ip2;
573+
ev->t_fcs_time = conf->t_fcs;
574+
ev->t_pm_time = conf->t_pm;
575+
576+
ble_ll_hci_event_send(hci_ev);
577+
}
578+
}
579+
}
580+
581+
void
582+
ble_ll_cs_rx_config_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
583+
{
584+
uint8_t config_id = *dptr & 0b00111111;
585+
uint8_t action = (*dptr & 0b11000000) >> 6;
586+
587+
if (config_id != connsm->cssm->config_req_id ||
588+
!IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CS_CONF)) {
589+
return;
590+
}
591+
592+
/* Stop the control procedure and send an event to the host */
593+
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CS_CONF);
594+
ble_ll_cs_ev_config_complete(connsm, config_id, action, BLE_ERR_SUCCESS);
595+
}
596+
597+
static int
598+
ble_ll_cs_select_capability(const uint8_t *capability_values, uint8_t len,
599+
uint8_t *out_value, uint16_t local_capability,
600+
uint16_t remote_capability)
601+
{
602+
uint16_t common_capability = local_capability & remote_capability;
603+
uint8_t i;
604+
605+
for (i = 0; i < len; i++) {
606+
if ((common_capability >> i) & 1) {
607+
*out_value = capability_values[i];
608+
return 0;
609+
}
610+
}
611+
612+
return 1;
613+
}
614+
435615
int
436616
ble_ll_cs_hci_create_config(const uint8_t *cmdbuf, uint8_t cmdlen)
437617
{
438-
return BLE_ERR_UNSUPPORTED;
618+
const struct ble_hci_le_cs_create_config_cp *cmd = (const void *)cmdbuf;
619+
struct ble_ll_conn_sm *connsm;
620+
struct ble_ll_cs_config *conf;
621+
struct ble_ll_cs_sm *cssm;
622+
623+
if (cmdlen != sizeof(*cmd) || cmd->config_id >= BLE_LL_CS_CONFIG_MAX_NUM) {
624+
return BLE_ERR_INV_HCI_CMD_PARMS;
625+
}
626+
627+
/* If no connection handle exit with error */
628+
connsm = ble_ll_conn_find_by_handle(le16toh(cmd->conn_handle));
629+
if (!connsm) {
630+
return BLE_ERR_UNK_CONN_ID;
631+
}
632+
633+
cssm = connsm->cssm;
634+
635+
/* If already pending exit with error */
636+
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CS_CONF)) {
637+
return BLE_ERR_CMD_DISALLOWED;
638+
}
639+
640+
/* Configure CS config locally */
641+
conf = &cssm->config[cmd->config_id];
642+
conf->config_enabled = true;
643+
conf->main_mode = cmd->main_mode_type;
644+
conf->sub_mode = cmd->sub_mode_type;
645+
conf->main_mode_min_steps = cmd->min_main_mode_steps;
646+
conf->main_mode_max_steps = cmd->max_main_mode_steps;
647+
conf->main_mode_repetition = cmd->main_mode_repetition;
648+
conf->mode_0_steps = cmd->mode_0_steps;
649+
conf->role = cmd->role;
650+
conf->rtt_type = cmd->rtt_type;
651+
conf->cs_sync_phy = cmd->cs_sync_phy;
652+
memcpy(conf->chan_map, cmd->channel_map, 10);
653+
conf->chan_map_repetition = cmd->channel_map_repetition;
654+
conf->chan_sel = cmd->channel_selection_type;
655+
conf->ch3cshape = cmd->ch3c_shape;
656+
conf->ch3cjump = cmd->ch3c_jump;
657+
658+
if (ble_ll_cs_select_capability(t_ip1, ARRAY_SIZE(t_ip1), &conf->t_ip1,
659+
cssm->remote_cap.t_ip1_capability,
660+
g_ble_ll_cs_local_cap.t_ip1_capability)) {
661+
memset(conf, 0, sizeof(*conf));
662+
return BLE_ERR_INV_HCI_CMD_PARMS;
663+
}
664+
665+
if (ble_ll_cs_select_capability(t_ip2, ARRAY_SIZE(t_ip2), &conf->t_ip2,
666+
cssm->remote_cap.t_ip2_capability,
667+
g_ble_ll_cs_local_cap.t_ip2_capability)) {
668+
memset(conf, 0, sizeof(*conf));
669+
return BLE_ERR_INV_HCI_CMD_PARMS;
670+
}
671+
672+
if (ble_ll_cs_select_capability(t_fcs, ARRAY_SIZE(t_fcs), &conf->t_fcs,
673+
cssm->remote_cap.t_fcs_capability,
674+
g_ble_ll_cs_local_cap.t_fcs_capability)) {
675+
memset(conf, 0, sizeof(*conf));
676+
return BLE_ERR_INV_HCI_CMD_PARMS;
677+
}
678+
679+
if (ble_ll_cs_select_capability(t_pm, ARRAY_SIZE(t_pm), &conf->t_pm,
680+
cssm->remote_cap.t_pm_capability,
681+
g_ble_ll_cs_local_cap.t_pm_capability)) {
682+
memset(conf, 0, sizeof(*conf));
683+
return BLE_ERR_INV_HCI_CMD_PARMS;
684+
}
685+
686+
if (cmd->create_context == 0x01) {
687+
/* Configure the CS config in the remote controller */
688+
cssm->config_req_id = cmd->config_id;
689+
cssm->config_req_action = 0x01;
690+
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CS_CONF, NULL);
691+
} else {
692+
ble_ll_cs_ev_config_complete(connsm, cmd->config_id, 0x01, BLE_ERR_SUCCESS);
693+
}
694+
695+
return BLE_ERR_SUCCESS;
439696
}
440697

441698
int
442699
ble_ll_cs_hci_remove_config(const uint8_t *cmdbuf, uint8_t cmdlen)
443700
{
444-
return BLE_ERR_UNSUPPORTED;
701+
const struct ble_hci_le_cs_remove_config_cp *cmd = (const void *)cmdbuf;
702+
struct ble_ll_conn_sm *connsm;
703+
struct ble_ll_cs_sm *cssm;
704+
struct ble_ll_cs_config *conf;
705+
706+
if (cmdlen != sizeof(*cmd) || cmd->config_id >= BLE_LL_CS_CONFIG_MAX_NUM) {
707+
return BLE_ERR_INV_HCI_CMD_PARMS;
708+
}
709+
710+
/* If no connection handle exit with error */
711+
connsm = ble_ll_conn_find_by_handle(le16toh(cmd->conn_handle));
712+
if (!connsm) {
713+
return BLE_ERR_UNK_CONN_ID;
714+
}
715+
716+
cssm = connsm->cssm;
717+
718+
/* If already pending exit with error */
719+
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CS_CONF)) {
720+
return BLE_ERR_CMD_DISALLOWED;
721+
}
722+
723+
/* Remove the CS config locally */
724+
conf = &cssm->config[cmd->config_id];
725+
memset(conf, 0, sizeof(*conf));
726+
727+
/* Configure the CS config in the remote controller */
728+
cssm->config_req_id = cmd->config_id;
729+
cssm->config_req_action = 0x00;
730+
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CS_CONF, NULL);
731+
732+
return BLE_ERR_SUCCESS;
445733
}
446734

447735
int

nimble/controller/src/ble_ll_cs_priv.h

+31
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include <stdint.h>
2424
#include "controller/ble_ll_conn.h"
25+
#include "ble_ll_cs_drbg_priv.h"
2526

2627
#ifdef __cplusplus
2728
extern "C" {
@@ -61,6 +62,32 @@ struct ble_ll_cs_config {
6162
* 0x01 = Reflector
6263
*/
6364
uint8_t role;
65+
/* Map of allowed channels for this CS config */
66+
uint8_t chan_map[10];
67+
/* The number of times the map represented by the Channel_Map field is to
68+
* be cycled through for non-mode 0 steps within a CS procedure
69+
*/
70+
uint8_t chan_map_repetition;
71+
uint8_t main_mode;
72+
uint8_t sub_mode;
73+
uint8_t main_mode_min_steps;
74+
uint8_t main_mode_max_steps;
75+
uint8_t main_mode_repetition;
76+
uint8_t mode_0_steps;
77+
/* PHY used for mode 0, 1 and 3 (use LE 1M PHY)*/
78+
uint8_t cs_sync_phy;
79+
/* Type of RTT (Round-Trip Time) packets */
80+
uint8_t rtt_type;
81+
/* The Channel Selection Algorithm to use */
82+
uint8_t chan_sel;
83+
/* Parameters for #3c algorithm */
84+
uint8_t ch3cshape;
85+
uint8_t ch3cjump;
86+
/* Timings (usec) selected from capabilities */
87+
uint8_t t_ip1;
88+
uint8_t t_ip2;
89+
uint8_t t_fcs;
90+
uint8_t t_pm;
6491
};
6592

6693
struct ble_ll_cs_sm {
@@ -76,6 +103,10 @@ struct ble_ll_cs_sm {
76103
/* Cached FAE tables */
77104
uint8_t remote_fae_table[72];
78105
uint8_t local_fae_table[72];
106+
107+
/* Arguments for ble_ll_cs_config_req_make */
108+
uint8_t config_req_id;
109+
uint8_t config_req_action;
79110
};
80111

81112
#ifdef __cplusplus

0 commit comments

Comments
 (0)