From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v1 3/4] ranging/rap_hci: Use bt_hci_register_subevent for LE CS events
Date: Fri, 1 May 2026 10:38:46 -0400 [thread overview]
Message-ID: <20260501143847.724150-3-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260501143847.724150-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Replace the single BT_HCI_EVT_LE_META_EVENT registration and subevent
dispatch table with individual bt_hci_register_subevent calls for each
CS subevent. This enables BPF filtering at the socket level for each
specific subevent and removes the manual subevent dispatch logic.
Event IDs are stored in a struct queue for flexible management.
Assisted-by: Claude:claude-opus-4.6
---
profiles/ranging/rap_hci.c | 193 ++++++++++++++-----------------------
1 file changed, 71 insertions(+), 122 deletions(-)
diff --git a/profiles/ranging/rap_hci.c b/profiles/ranging/rap_hci.c
index 08ddc077ce94..8e65e5ef87bd 100644
--- a/profiles/ranging/rap_hci.c
+++ b/profiles/ranging/rap_hci.c
@@ -61,7 +61,7 @@ struct cs_state_machine {
enum cs_state old_state;
struct bt_hci *hci;
struct bt_rap *rap;
- unsigned int event_id;
+ struct queue *event_ids;
bool initiator;
bool procedure_active;
struct bt_rap_hci_cs_options cs_opt; /* Per-instance CS options */
@@ -302,7 +302,7 @@ static void rap_send_hci_def_settings_command(struct cs_state_machine *sm,
error("Failed to send default settings cmd");
}
-static void rap_rd_rmt_supp_cap_cmplt_evt(const uint8_t *data, uint8_t size,
+static void rap_rd_rmt_supp_cap_cmplt_evt(const void *data, uint8_t size,
void *user_data)
{
struct cs_state_machine *sm = user_data;
@@ -348,7 +348,7 @@ static void rap_rd_rmt_supp_cap_cmplt_evt(const uint8_t *data, uint8_t size,
cs_set_state(sm, CS_STATE_INIT);
}
-static void rap_cs_config_cmplt_evt(const uint8_t *data, uint8_t size,
+static void rap_cs_config_cmplt_evt(const void *data, uint8_t size,
void *user_data)
{
struct cs_state_machine *sm = user_data;
@@ -439,7 +439,7 @@ static void rap_cs_config_cmplt_evt(const uint8_t *data, uint8_t size,
bt_rap_hci_cs_config_complete_callback(size, &rap_ev, sm->rap);
}
-static void rap_cs_sec_enable_cmplt_evt(const uint8_t *data, uint8_t size,
+static void rap_cs_sec_enable_cmplt_evt(const void *data, uint8_t size,
void *user_data)
{
struct cs_state_machine *sm = user_data;
@@ -500,7 +500,7 @@ static void rap_cs_sec_enable_cmplt_evt(const uint8_t *data, uint8_t size,
bt_rap_hci_cs_sec_enable_complete_callback(size, &rap_ev, sm->rap);
}
-static void rap_cs_proc_enable_cmplt_evt(const uint8_t *data, uint8_t size,
+static void rap_cs_proc_enable_cmplt_evt(const void *data, uint8_t size,
void *user_data)
{
struct cs_state_machine *sm = user_data;
@@ -800,7 +800,7 @@ static void parse_cs_step(struct iovec *iov, struct cs_step_data *step,
}
}
-static void rap_cs_subevt_result_evt(const uint8_t *data, uint8_t size,
+static void rap_cs_subevt_result_evt(const void *data, uint8_t size,
void *user_data)
{
struct cs_state_machine *sm = (struct cs_state_machine *) user_data;
@@ -910,7 +910,7 @@ send_event:
free(rap_ev);
}
-static void rap_cs_subevt_result_cont_evt(const uint8_t *data, uint8_t size,
+static void rap_cs_subevt_result_cont_evt(const void *data, uint8_t size,
void *user_data)
{
struct cs_state_machine *sm = (struct cs_state_machine *) user_data;
@@ -1009,113 +1009,12 @@ send_event:
}
/* Subevent handler function type */
-typedef void (*subevent_handler_t)(const uint8_t *data, uint8_t size,
- void *user_data);
-/* Subevent table entry */
-struct subevent_entry {
- uint8_t opcode;
- uint8_t min_len;
- uint8_t max_len;
- subevent_handler_t handler;
- const char *name;
-};
-
-/* Macro to define HCI event entries
- * Note: min_len excludes the subevent byte since it's stripped before dispatch
- */
-#define HCI_EVT(_opcode, _struct, _handler, _name) \
- { \
- .opcode = _opcode, \
- .min_len = sizeof(_struct), \
- .max_len = 0xFF, \
- .handler = _handler, \
- .name = _name \
- }
-
-/* Subevent dispatch table */
-static const struct subevent_entry subevent_table[] = {
- HCI_EVT(BT_HCI_EVT_LE_CS_RD_REM_SUPP_CAP_COMPLETE,
- struct bt_hci_evt_le_cs_rd_rem_supp_cap_complete,
- rap_rd_rmt_supp_cap_cmplt_evt,
- "CS Read Remote Supported Capabilities Complete"),
- HCI_EVT(BT_HCI_EVT_LE_CS_CONFIG_COMPLETE,
- struct bt_hci_evt_le_cs_config_complete,
- rap_cs_config_cmplt_evt,
- "CS Config Complete"),
- HCI_EVT(BT_HCI_EVT_LE_CS_SEC_ENABLE_COMPLETE,
- struct bt_hci_evt_le_cs_sec_enable_complete,
- rap_cs_sec_enable_cmplt_evt,
- "CS Security Enable Complete"),
- HCI_EVT(BT_HCI_EVT_LE_CS_PROC_ENABLE_COMPLETE,
- struct bt_hci_evt_le_cs_proc_enable_complete,
- rap_cs_proc_enable_cmplt_evt,
- "CS Procedure Enable Complete"),
- HCI_EVT(BT_HCI_EVT_LE_CS_SUBEVENT_RESULT,
- struct bt_hci_evt_le_cs_subevent_result,
- rap_cs_subevt_result_evt,
- "CS Subevent Result"),
- HCI_EVT(BT_HCI_EVT_LE_CS_SUBEVENT_RESULT_CONTINUE,
- struct bt_hci_evt_le_cs_subevent_result_continue,
- rap_cs_subevt_result_cont_evt,
- "CS Subevent Result Continue")
-};
-
-#undef HCI_EVT
-
-#define SUBEVENT_TABLE_SIZE ARRAY_SIZE(subevent_table)
-
-/* HCI Event Registration */
-static void rap_handle_hci_events(const void *data, uint8_t size,
- void *user_data)
+static void unregister_event_id(void *data, void *user_data)
{
- struct iovec iov;
- uint8_t subevent;
- const struct subevent_entry *entry = NULL;
- size_t i;
+ struct bt_hci *hci = user_data;
- /* Initialize iovec with the event data */
- iov.iov_base = (void *) data;
- iov.iov_len = size;
-
- /* Pull the subevent code */
- if (!util_iov_pull_u8(&iov, &subevent)) {
- DBG("Failed to parse subevent code");
- return;
- }
-
- /* Find the subevent in the table */
- for (i = 0; i < SUBEVENT_TABLE_SIZE; i++) {
- if (subevent_table[i].opcode == subevent) {
- entry = &subevent_table[i];
- break;
- }
- }
-
- /* Check if subevent is supported */
- if (!entry) {
- DBG("Unknown subevent: 0x%02X", subevent);
- return;
- }
-
- /* Validate payload length */
- if (iov.iov_len < entry->min_len) {
- DBG("%s: payload too short (%zu < %u)",
- entry->name, iov.iov_len, entry->min_len);
- return;
- }
-
- if (entry->max_len != 0xFF && iov.iov_len > entry->max_len) {
- DBG("%s: payload too long (%zu > %u)",
- entry->name, iov.iov_len, entry->max_len);
- return;
- }
-
- /* Call the handler */
- DBG("Handling %s (opcode=0x%02X, len=%zu)",
- entry->name, subevent, iov.iov_len);
-
- entry->handler(iov.iov_base, iov.iov_len, user_data);
+ bt_hci_unregister_subevent(hci, PTR_TO_UINT(data));
}
void *bt_rap_attach_hci(struct bt_rap *rap, struct bt_hci *hci,
@@ -1123,6 +1022,7 @@ void *bt_rap_attach_hci(struct bt_rap *rap, struct bt_hci *hci,
int8_t max_tx_power)
{
struct cs_state_machine *sm;
+ unsigned int id;
if (!rap || !hci) {
error("rap or hci null");
@@ -1140,22 +1040,68 @@ void *bt_rap_attach_hci(struct bt_rap *rap, struct bt_hci *hci,
cs_state_machine_init(sm, rap, hci, role, cs_sync_ant_sel,
max_tx_power);
- sm->event_id = bt_hci_register(hci, BT_HCI_EVT_LE_META_EVENT,
- rap_handle_hci_events, sm, NULL);
+ sm->event_ids = queue_new();
- DBG("bt_hci_register done, event_id : %d", sm->event_id);
+ /* Register each LE Meta subevent individually */
+ id = bt_hci_register_subevent(hci,
+ BT_HCI_EVT_LE_CS_RD_REM_SUPP_CAP_COMPLETE,
+ rap_rd_rmt_supp_cap_cmplt_evt, sm, NULL);
+ if (!id)
+ goto fail;
- if (!sm->event_id) {
- error("Failed to register hci le meta events");
- error("event_id=0x%02X", sm->event_id);
- free(sm);
- return NULL;
- }
+ queue_push_tail(sm->event_ids, UINT_TO_PTR(id));
+
+ id = bt_hci_register_subevent(hci,
+ BT_HCI_EVT_LE_CS_CONFIG_COMPLETE,
+ rap_cs_config_cmplt_evt, sm, NULL);
+ if (!id)
+ goto fail;
+
+ queue_push_tail(sm->event_ids, UINT_TO_PTR(id));
+
+ id = bt_hci_register_subevent(hci,
+ BT_HCI_EVT_LE_CS_SEC_ENABLE_COMPLETE,
+ rap_cs_sec_enable_cmplt_evt, sm, NULL);
+ if (!id)
+ goto fail;
+
+ queue_push_tail(sm->event_ids, UINT_TO_PTR(id));
+
+ id = bt_hci_register_subevent(hci,
+ BT_HCI_EVT_LE_CS_PROC_ENABLE_COMPLETE,
+ rap_cs_proc_enable_cmplt_evt, sm, NULL);
+ if (!id)
+ goto fail;
+
+ queue_push_tail(sm->event_ids, UINT_TO_PTR(id));
+
+ id = bt_hci_register_subevent(hci,
+ BT_HCI_EVT_LE_CS_SUBEVENT_RESULT,
+ rap_cs_subevt_result_evt, sm, NULL);
+ if (!id)
+ goto fail;
+
+ queue_push_tail(sm->event_ids, UINT_TO_PTR(id));
+
+ id = bt_hci_register_subevent(hci,
+ BT_HCI_EVT_LE_CS_SUBEVENT_RESULT_CONTINUE,
+ rap_cs_subevt_result_cont_evt, sm, NULL);
+ if (!id)
+ goto fail;
+
+ queue_push_tail(sm->event_ids, UINT_TO_PTR(id));
DBG("CS options: role=%u, cs_sync_ant_sel=%u, max_tx_power=%d",
role, cs_sync_ant_sel, max_tx_power);
return sm;
+
+fail:
+ error("Failed to register hci le meta subevents");
+ queue_foreach(sm->event_ids, unregister_event_id, hci);
+ queue_destroy(sm->event_ids, NULL);
+ free(sm);
+ return NULL;
}
bool bt_rap_set_conn_handle(void *hci_sm, struct bt_rap *rap, uint16_t handle,
@@ -1204,8 +1150,11 @@ void bt_rap_detach_hci(struct bt_rap *rap, void *hci_sm)
/* Cleanup the per-instance state machine */
if (sm) {
/* Unregister HCI events */
- if (sm->event_id && sm->hci)
- bt_hci_unregister(sm->hci, sm->event_id);
+ if (sm->hci)
+ queue_foreach(sm->event_ids, unregister_event_id,
+ sm->hci);
+
+ queue_destroy(sm->event_ids, NULL);
/* Clean up per-instance connection mappings */
remove_rap_mappings(sm);
--
2.53.0
next prev parent reply other threads:[~2026-05-01 14:39 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 14:38 [PATCH BlueZ v1 1/4] shared/hci: Add BPF filter for registered events Luiz Augusto von Dentz
2026-05-01 14:38 ` [PATCH BlueZ v1 2/4] shared/hci: Add bt_hci_register_subevent for LE Meta events Luiz Augusto von Dentz
2026-05-01 14:38 ` Luiz Augusto von Dentz [this message]
2026-05-01 14:38 ` [PATCH BlueZ v1 4/4] hci-tester: Use " Luiz Augusto von Dentz
2026-05-01 15:56 ` [BlueZ,v1,1/4] shared/hci: Add BPF filter for registered events bluez.test.bot
2026-05-06 13:30 ` [PATCH BlueZ v1 1/4] " patchwork-bot+bluetooth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260501143847.724150-3-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox