Bluetooth: L2CAP: Move fixed channels to its own section in ROM

This changes the declaration of fixed channels to be statically defined
with use of BT_L2CAP_CHANNEL_DEFINE since fixed channels are never
unregistered.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Luiz Augusto von Dentz 2019-05-20 15:11:39 +03:00 committed by Johan Hedberg
commit a3bea8872b
8 changed files with 73 additions and 81 deletions

View file

@ -77,6 +77,22 @@
} GROUP_LINK_IN(ROMABLE_REGION) } GROUP_LINK_IN(ROMABLE_REGION)
#endif #endif
SECTION_DATA_PROLOGUE(_bt_channels_area,,SUBALIGN(4))
{
_bt_channels_start = .;
KEEP(*(SORT_BY_NAME("._bt_channels.static.*")))
_bt_channels_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
#if defined(CONFIG_BT_BREDR)
SECTION_DATA_PROLOGUE(_bt_br_channels_area,,SUBALIGN(4))
{
_bt_br_channels_start = .;
KEEP(*(SORT_BY_NAME("._bt_br_channels.static.*")))
_bt_br_channels_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
#endif
SECTION_DATA_PROLOGUE(_bt_services_area,,SUBALIGN(4)) SECTION_DATA_PROLOGUE(_bt_services_area,,SUBALIGN(4))
{ {
_bt_services_start = .; _bt_services_start = .;

View file

@ -909,8 +909,8 @@ class SizeCalculator:
# These get copied into RAM only on non-XIP # These get copied into RAM only on non-XIP
ro_sections = ["text", "ctors", "init_array", "reset", "object_access", ro_sections = ["text", "ctors", "init_array", "reset", "object_access",
"rodata", "devconfig", "net_l2", "vector", "sw_isr_table", "rodata", "devconfig", "net_l2", "vector", "sw_isr_table",
"_bt_settings_area", "_bt_services_area", "vectors", "_bt_settings_area", "_bt_channels_area","_bt_services_area",
"net_socket_register"] "vectors", "net_socket_register"]
def __init__(self, filename, extra_sections): def __init__(self, filename, extra_sections):
"""Constructor """Constructor

View file

@ -2174,15 +2174,10 @@ static int bt_att_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
return -ENOMEM; return -ENOMEM;
} }
BT_L2CAP_CHANNEL_DEFINE(att_fixed_chan, BT_L2CAP_CID_ATT, bt_att_accept);
void bt_att_init(void) void bt_att_init(void)
{ {
static struct bt_l2cap_fixed_chan chan = {
.cid = BT_L2CAP_CID_ATT,
.accept = bt_att_accept,
};
bt_l2cap_le_fixed_chan_register(&chan);
bt_gatt_init(); bt_gatt_init();
} }

View file

@ -49,7 +49,9 @@
#define L2CAP_CONN_TIMEOUT K_SECONDS(40) #define L2CAP_CONN_TIMEOUT K_SECONDS(40)
#define L2CAP_DISC_TIMEOUT K_SECONDS(2) #define L2CAP_DISC_TIMEOUT K_SECONDS(2)
static sys_slist_t le_channels; /* Linker-defined symbols bound to the bt_l2cap_fixed_chan structs */
extern const struct bt_l2cap_fixed_chan _bt_channels_start[];
extern const struct bt_l2cap_fixed_chan _bt_channels_end[];
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL) #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
/* Size of MTU is based on the maximum amount of data the buffer can hold /* Size of MTU is based on the maximum amount of data the buffer can hold
@ -87,13 +89,6 @@ static u8_t get_ident(void)
return ident; return ident;
} }
void bt_l2cap_le_fixed_chan_register(struct bt_l2cap_fixed_chan *chan)
{
BT_DBG("CID 0x%04x", chan->cid);
sys_slist_append(&le_channels, &chan->node);
}
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL) #if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn, static struct bt_l2cap_le_chan *l2cap_chan_alloc_cid(struct bt_conn *conn,
struct bt_l2cap_chan *chan) struct bt_l2cap_chan *chan)
@ -304,7 +299,7 @@ static bool l2cap_chan_add(struct bt_conn *conn, struct bt_l2cap_chan *chan,
void bt_l2cap_connected(struct bt_conn *conn) void bt_l2cap_connected(struct bt_conn *conn)
{ {
struct bt_l2cap_fixed_chan *fchan; const struct bt_l2cap_fixed_chan *fchan;
struct bt_l2cap_chan *chan; struct bt_l2cap_chan *chan;
if (IS_ENABLED(CONFIG_BT_BREDR) && if (IS_ENABLED(CONFIG_BT_BREDR) &&
@ -313,7 +308,7 @@ void bt_l2cap_connected(struct bt_conn *conn)
return; return;
} }
SYS_SLIST_FOR_EACH_CONTAINER(&le_channels, fchan, node) { for (fchan = _bt_channels_start; fchan < _bt_channels_end; fchan++) {
struct bt_l2cap_le_chan *ch; struct bt_l2cap_le_chan *ch;
if (fchan->accept(conn, &chan) < 0) { if (fchan->accept(conn, &chan) < 0) {
@ -732,6 +727,12 @@ static u16_t le_err_to_result(int err)
return BT_L2CAP_LE_ERR_AUTHORIZATION; return BT_L2CAP_LE_ERR_AUTHORIZATION;
case -EPERM: case -EPERM:
return BT_L2CAP_LE_ERR_KEY_SIZE; return BT_L2CAP_LE_ERR_KEY_SIZE;
case -ENOTSUP:
/* This handle the cases where a fixed channel is registered but
* for some reason (e.g. controller not suporting a feature)
* cannot be used.
*/
return BT_L2CAP_LE_ERR_PSM_NOT_SUPP;
default: default:
return BT_L2CAP_LE_ERR_UNACCEPT_PARAMS; return BT_L2CAP_LE_ERR_UNACCEPT_PARAMS;
} }
@ -1668,15 +1669,10 @@ static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
return -ENOMEM; return -ENOMEM;
} }
BT_L2CAP_CHANNEL_DEFINE(le_fixed_chan, BT_L2CAP_CID_LE_SIG, l2cap_accept);
void bt_l2cap_init(void) void bt_l2cap_init(void)
{ {
static struct bt_l2cap_fixed_chan chan = {
.cid = BT_L2CAP_CID_LE_SIG,
.accept = l2cap_accept,
};
bt_l2cap_le_fixed_chan_register(&chan);
if (IS_ENABLED(CONFIG_BT_BREDR)) { if (IS_ENABLED(CONFIG_BT_BREDR)) {
bt_l2cap_br_init(); bt_l2cap_br_init();
} }

View file

@ -78,7 +78,10 @@ enum {
}; };
static sys_slist_t br_servers; static sys_slist_t br_servers;
static sys_slist_t br_fixed_channels;
/* Linker-defined symbols bound to the bt_l2cap_fixed_chan structs */
extern const struct bt_l2cap_fixed_chan _bt_br_channels_start[];
extern const struct bt_l2cap_fixed_chan _bt_br_channels_end[];
/* Pool for outgoing BR/EDR signaling packets, min MTU is 48 */ /* Pool for outgoing BR/EDR signaling packets, min MTU is 48 */
NET_BUF_POOL_DEFINE(br_sig_pool, CONFIG_BT_MAX_CONN, NET_BUF_POOL_DEFINE(br_sig_pool, CONFIG_BT_MAX_CONN,
@ -383,11 +386,12 @@ done:
static u8_t get_fixed_channels_mask(void) static u8_t get_fixed_channels_mask(void)
{ {
struct bt_l2cap_fixed_chan *fchan; const struct bt_l2cap_fixed_chan *fchan;
u8_t mask = 0U; u8_t mask = 0U;
/* this needs to be enhanced if AMP Test Manager support is added */ /* this needs to be enhanced if AMP Test Manager support is added */
SYS_SLIST_FOR_EACH_CONTAINER(&br_fixed_channels, fchan, node) { for (fchan = _bt_br_channels_start; fchan < _bt_br_channels_end;
fchan++) {
mask |= BIT(fchan->cid); mask |= BIT(fchan->cid);
} }
@ -450,10 +454,11 @@ static int l2cap_br_info_req(struct bt_l2cap_br *l2cap, u8_t ident,
void bt_l2cap_br_connected(struct bt_conn *conn) void bt_l2cap_br_connected(struct bt_conn *conn)
{ {
struct bt_l2cap_fixed_chan *fchan; const struct bt_l2cap_fixed_chan *fchan;
struct bt_l2cap_chan *chan; struct bt_l2cap_chan *chan;
SYS_SLIST_FOR_EACH_CONTAINER(&br_fixed_channels, fchan, node) { for (fchan = _bt_br_channels_start; fchan < _bt_br_channels_end;
fchan++) {
struct bt_l2cap_br_chan *ch; struct bt_l2cap_br_chan *ch;
if (!fchan->accept) { if (!fchan->accept) {
@ -1545,24 +1550,12 @@ static int l2cap_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
return -ENOMEM; return -ENOMEM;
} }
void bt_l2cap_br_fixed_chan_register(struct bt_l2cap_fixed_chan *chan) BT_L2CAP_CHANNEL_DEFINE(br_fixed_chan, BT_L2CAP_CID_BR_SIG, l2cap_br_accept);
{
BT_DBG("CID 0x%04x", chan->cid);
sys_slist_append(&br_fixed_channels, &chan->node);
}
void bt_l2cap_br_init(void) void bt_l2cap_br_init(void)
{ {
static struct bt_l2cap_fixed_chan chan_br = {
.cid = BT_L2CAP_CID_BR_SIG,
.accept = l2cap_br_accept,
};
sys_slist_init(&br_servers); sys_slist_init(&br_servers);
bt_l2cap_br_fixed_chan_register(&chan_br);
if (IS_ENABLED(CONFIG_BT_RFCOMM)) { if (IS_ENABLED(CONFIG_BT_RFCOMM)) {
bt_rfcomm_init(); bt_rfcomm_init();
} }

View file

@ -202,11 +202,14 @@ struct bt_l2cap_le_credits {
struct bt_l2cap_fixed_chan { struct bt_l2cap_fixed_chan {
u16_t cid; u16_t cid;
int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan); int (*accept)(struct bt_conn *conn, struct bt_l2cap_chan **chan);
sys_snode_t node;
}; };
/* Register a fixed L2CAP channel for L2CAP */ #define BT_L2CAP_CHANNEL_DEFINE(_name, _cid, _accept) \
void bt_l2cap_le_fixed_chan_register(struct bt_l2cap_fixed_chan *chan); const struct bt_l2cap_fixed_chan _name __aligned(4) \
__in_section(_bt_channels, static, _name) = { \
.cid = _cid, \
.accept = _accept, \
}
/* Notify L2CAP channels of a new connection */ /* Notify L2CAP channels of a new connection */
void bt_l2cap_connected(struct bt_conn *conn); void bt_l2cap_connected(struct bt_conn *conn);

View file

@ -1365,6 +1365,16 @@ static int bt_smp_br_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
return 0; return 0;
} }
static bool br_sc_supported(void)
{
if (IS_ENABLED(CONFIG_BT_SMP_FORCE_BREDR)) {
BT_WARN("Enabling BR/EDR SMP without BR/EDR SC support");
return true;
}
return BT_FEAT_SC(bt_dev.features);
}
static int bt_smp_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan) static int bt_smp_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
{ {
static struct bt_l2cap_chan_ops ops = { static struct bt_l2cap_chan_ops ops = {
@ -1374,6 +1384,11 @@ static int bt_smp_br_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
}; };
int i; int i;
/* Check BR/EDR SC is supported */
if (!br_sc_supported()) {
return -ENOTSUP;
}
BT_DBG("conn %p handle %u", conn, conn->handle); BT_DBG("conn %p handle %u", conn, conn->handle);
for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) { for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
@ -1484,16 +1499,6 @@ int bt_smp_br_send_pairing_req(struct bt_conn *conn)
return 0; return 0;
} }
static bool br_sc_supported(void)
{
if (IS_ENABLED(CONFIG_BT_SMP_FORCE_BREDR)) {
BT_WARN("Enabling BR/EDR SMP without BR/EDR SC support");
return true;
}
return BT_FEAT_SC(bt_dev.features);
}
#endif /* CONFIG_BT_BREDR */ #endif /* CONFIG_BT_BREDR */
static void smp_reset(struct bt_smp *smp) static void smp_reset(struct bt_smp *smp)
@ -4823,12 +4828,14 @@ static bool le_sc_supported(void)
BT_CMD_TEST(bt_dev.supported_commands, 34, 2); BT_CMD_TEST(bt_dev.supported_commands, 34, 2);
} }
BT_L2CAP_CHANNEL_DEFINE(smp_fixed_chan, BT_L2CAP_CID_SMP, bt_smp_accept);
#if defined(CONFIG_BT_BREDR)
BT_L2CAP_CHANNEL_DEFINE(smp_br_fixed_chan, BT_L2CAP_CID_BR_SMP,
bt_smp_br_accept);
#endif /* CONFIG_BT_BREDR */
int bt_smp_init(void) int bt_smp_init(void)
{ {
static struct bt_l2cap_fixed_chan chan = {
.cid = BT_L2CAP_CID_SMP,
.accept = bt_smp_accept,
};
static struct bt_pub_key_cb pub_key_cb = { static struct bt_pub_key_cb pub_key_cb = {
.func = bt_smp_pkey_ready, .func = bt_smp_pkey_ready,
}; };
@ -4839,19 +4846,6 @@ int bt_smp_init(void)
return -ENOENT; return -ENOENT;
} }
bt_l2cap_le_fixed_chan_register(&chan);
#if defined(CONFIG_BT_BREDR)
/* Register BR/EDR channel only if BR/EDR SC is supported */
if (br_sc_supported()) {
static struct bt_l2cap_fixed_chan br_chan = {
.cid = BT_L2CAP_CID_BR_SMP,
.accept = bt_smp_br_accept,
};
bt_l2cap_br_fixed_chan_register(&br_chan);
}
#endif
BT_DBG("LE SC %s", sc_supported ? "enabled" : "disabled"); BT_DBG("LE SC %s", sc_supported ? "enabled" : "disabled");
bt_pub_key_gen(&pub_key_cb); bt_pub_key_gen(&pub_key_cb);

View file

@ -93,14 +93,9 @@ static int bt_smp_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
return -ENOMEM; return -ENOMEM;
} }
BT_L2CAP_CHANNEL_DEFINE(smp_fixed_chan, BT_L2CAP_CID_SMP, bt_smp_accept);
int bt_smp_init(void) int bt_smp_init(void)
{ {
static struct bt_l2cap_fixed_chan chan = {
.cid = BT_L2CAP_CID_SMP,
.accept = bt_smp_accept,
};
bt_l2cap_le_fixed_chan_register(&chan);
return 0; return 0;
} }