From fa87918476b28657277be8c742a2f766236d2a6f Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Thu, 26 Dec 2024 14:36:20 +0800 Subject: [PATCH] Bluetooth: rfcomm: Support dynamic channel allocation In the function `bt_rfcomm_server_register()`, the channel cannot be dynamic allocated. And only pre-set channel is supported. Improve the function `bt_rfcomm_server_register()` to support the dynamic channel allocation if the passed channel is zero. Signed-off-by: Lyle Zhu --- include/zephyr/bluetooth/classic/rfcomm.h | 12 +++++++++- subsys/bluetooth/host/classic/rfcomm.c | 29 ++++++++++++++++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/zephyr/bluetooth/classic/rfcomm.h b/include/zephyr/bluetooth/classic/rfcomm.h index 1d3056643bd0..8b3846617c7c 100644 --- a/include/zephyr/bluetooth/classic/rfcomm.h +++ b/include/zephyr/bluetooth/classic/rfcomm.h @@ -31,6 +31,7 @@ enum { BT_RFCOMM_CHAN_HSP_AG, BT_RFCOMM_CHAN_HSP_HS, BT_RFCOMM_CHAN_SPP, + BT_RFCOMM_CHAN_DYNAMIC_START, }; struct bt_rfcomm_dlc; @@ -109,7 +110,16 @@ struct bt_rfcomm_dlc { }; struct bt_rfcomm_server { - /** Server Channel */ + /** Server Channel + * + * Possible values: + * 0 A dynamic value will be auto-allocated when bt_rfcomm_server_register() is + * called. + * + * 0x01 - 0x1e Dynamically allocated. May be pre-set by the application before server + * registration (not recommended however), or auto-allocated by the stack + * if the 0 is passed. + */ uint8_t channel; /** Server accept callback diff --git a/subsys/bluetooth/host/classic/rfcomm.c b/subsys/bluetooth/host/classic/rfcomm.c index 45e2a50b7e19..49c942b905e3 100644 --- a/subsys/bluetooth/host/classic/rfcomm.c +++ b/subsys/bluetooth/host/classic/rfcomm.c @@ -199,15 +199,32 @@ rfcomm_sessions_lookup_bt_conn(struct bt_conn *conn) int bt_rfcomm_server_register(struct bt_rfcomm_server *server) { - if (server->channel < RFCOMM_CHANNEL_START || - server->channel > RFCOMM_CHANNEL_END || !server->accept) { + if (server->channel > RFCOMM_CHANNEL_END || !server->accept) { return -EINVAL; } - /* Check if given channel is already in use */ - if (rfcomm_server_lookup_channel(server->channel)) { - LOG_DBG("Channel already registered"); - return -EADDRINUSE; + if (!server->channel) { + uint8_t chan = (uint8_t)BT_RFCOMM_CHAN_DYNAMIC_START; + + for (; chan <= RFCOMM_CHANNEL_END; chan++) { + /* Check if given channel is already in use */ + if (!rfcomm_server_lookup_channel(chan)) { + server->channel = chan; + LOG_DBG("Allocated channel 0x%02x for new server", chan); + break; + } + } + + if (!server->channel) { + LOG_WRN("No free dynamic rfcomm channels available"); + return -EADDRNOTAVAIL; + } + } else { + /* Check if given channel is already in use */ + if (rfcomm_server_lookup_channel(server->channel)) { + LOG_WRN("Channel already registered"); + return -EADDRINUSE; + } } LOG_DBG("Channel 0x%02x", server->channel);