Linux bluetooth development
 help / color / mirror / Atom feed
* [bluez/bluez] 1082f4: shared: rap: Introduce Channel Sounding HCI raw in...
From: Bhavani @ 2026-04-15 11:38 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1081547
  Home:   https://github.com/bluez/bluez
  Commit: 1082f4260f2bd1add5f08cf80e352b0ac239e092
      https://github.com/bluez/bluez/commit/1082f4260f2bd1add5f08cf80e352b0ac239e092
  Author: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
  Date:   2026-04-15 (Wed, 15 Apr 2026)

  Changed paths:
    M src/shared/hci.c
    M src/shared/hci.h
    M src/shared/rap.c
    M src/shared/rap.h

  Log Message:
  -----------
  shared: rap: Introduce Channel Sounding HCI raw interface support

Implement stub callbacks for Channel Sounding HCI events and add the
required protocol definitions for CS configuration, procedure control,
and subevent result parsing

Add data structures to support Channel Sounding Processing
Add helper function to get hci conn info list and integrate it with RAP


  Commit: 65412edd4e5213e695aea1501c198192bf8f95f5
      https://github.com/bluez/bluez/commit/65412edd4e5213e695aea1501c198192bf8f95f5
  Author: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
  Date:   2026-04-15 (Wed, 15 Apr 2026)

  Changed paths:
    M src/bluetooth.service.in
    M src/btd.h
    M src/main.c
    M src/main.conf

  Log Message:
  -----------
  main.conf: Add Channel Sounding config parsing support

Add support for parsing Channel Sounding (CS) configuration options
from the configuration file.

Add CAP_NET_RAW to CapabilityBoundingSet in bluetooth.service.
bluetoothd requires CAP_NET_RAW to receive and process HCI LE events
when running under a constrained systemd capability bounding set


  Commit: 0423d8d6f24ce4ea0f2343c6e954b98126150b5d
      https://github.com/bluez/bluez/commit/0423d8d6f24ce4ea0f2343c6e954b98126150b5d
  Author: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
  Date:   2026-04-15 (Wed, 15 Apr 2026)

  Changed paths:
    M Makefile.plugins
    M profiles/ranging/rap.c
    A profiles/ranging/rap_hci.c

  Log Message:
  -----------
  profiles: ranging: Add HCI LE Event Handling in Reflector role

Open RAW HCI Channel for CS Event Handling
Parse the following HCI LE CS Events in reflector role
and route the events to RAP Profile.
 1. HCI_EVT_LE_CS_READ_RMT_SUPP_CAP_COMPLETE
 2. HCI_EVT_LE_CS_CONFIG_COMPLETE
 3. HCI_EVT_LE_CS_SECURITY_ENABLE_COMPLETE
 4. HCI_EVT_LE_CS_PROCEDURE_ENABLE_COMPLETE
 5. HCI_EVT_LE_CS_SUBEVENT_RESULT
 6. HCI_EVT_LE_CS_SUBEVENT_RESULT_CONTINUE
Send HCI_OP_LE_CS_SET_DEFAULT_SETTINGS to the controller
with default settings selected by the user.
Map connection handle received to device connection


Compare: https://github.com/bluez/bluez/compare/1082f4260f2b%5E...0423d8d6f24c

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [PATCH BlueZ v7 3/3] profiles: ranging: Add HCI LE Event Handling in Reflector role
From: Naga Bhavani Akella @ 2026-04-15 11:25 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg,
	prathibha.madugonde, Naga Bhavani Akella
In-Reply-To: <20260415112510.195491-1-naga.akella@oss.qualcomm.com>

Open RAW HCI Channel for CS Event Handling
Parse the following HCI LE CS Events in reflector role
and route the events to RAP Profile.
 1. HCI_EVT_LE_CS_READ_RMT_SUPP_CAP_COMPLETE
 2. HCI_EVT_LE_CS_CONFIG_COMPLETE
 3. HCI_EVT_LE_CS_SECURITY_ENABLE_COMPLETE
 4. HCI_EVT_LE_CS_PROCEDURE_ENABLE_COMPLETE
 5. HCI_EVT_LE_CS_SUBEVENT_RESULT
 6. HCI_EVT_LE_CS_SUBEVENT_RESULT_CONTINUE
Send HCI_OP_LE_CS_SET_DEFAULT_SETTINGS to the controller
with default settings selected by the user.
Map connection handle received to device connection
---
 Makefile.plugins           |    3 +-
 profiles/ranging/rap.c     |   52 ++
 profiles/ranging/rap_hci.c | 1267 ++++++++++++++++++++++++++++++++++++
 3 files changed, 1321 insertions(+), 1 deletion(-)
 create mode 100644 profiles/ranging/rap_hci.c

diff --git a/Makefile.plugins b/Makefile.plugins
index c9efadb45..ac667beda 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -89,7 +89,8 @@ builtin_modules += battery
 builtin_sources += profiles/battery/battery.c
 
 builtin_modules += rap
-builtin_sources += profiles/ranging/rap.c
+builtin_sources += profiles/ranging/rap.c \
+		profiles/ranging/rap_hci.c
 
 if SIXAXIS
 builtin_modules += sixaxis
diff --git a/profiles/ranging/rap.c b/profiles/ranging/rap.c
index f03454c72..a473ed632 100644
--- a/profiles/ranging/rap.c
+++ b/profiles/ranging/rap.c
@@ -17,6 +17,7 @@
 #include "gdbus/gdbus.h"
 
 #include "bluetooth/bluetooth.h"
+#include "bluetooth/l2cap.h"
 #include "bluetooth/uuid.h"
 
 #include "src/plugin.h"
@@ -34,12 +35,14 @@
 #include "src/shared/rap.h"
 #include "attrib/att.h"
 #include "src/log.h"
+#include "src/btd.h"
 
 struct rap_data {
 	struct btd_device *device;
 	struct btd_service *service;
 	struct bt_rap *rap;
 	unsigned int ready_id;
+	struct bt_hci *hci;
 };
 
 static struct queue *sessions;
@@ -95,6 +98,14 @@ static void rap_data_free(struct rap_data *data)
 	}
 
 	bt_rap_ready_unregister(data->rap, data->ready_id);
+
+	if (data->hci) {
+		bt_rap_hci_sm_cleanup();
+		bt_hci_unref(data->hci);
+	}
+
+	/* Clean up HCI connection mappings */
+	bt_rap_detach_hci(data->rap);
 	bt_rap_unref(data->rap);
 	free(data);
 }
@@ -173,6 +184,7 @@ static int rap_probe(struct btd_service *service)
 	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
 	struct rap_data *data = btd_service_get_user_data(service);
 	char addr[18];
+	int16_t hci_index;
 
 	ba2str(device_get_address(device), addr);
 	DBG("%s", addr);
@@ -195,6 +207,19 @@ static int rap_probe(struct btd_service *service)
 		return -EINVAL;
 	}
 
+	hci_index = btd_adapter_get_index(adapter);
+
+	data->hci = bt_hci_new_raw_device(hci_index);
+	if (bt_rap_attach_hci(data->rap, data->hci)) {
+		DBG("HCI raw channel initialized, hci%d", hci_index);
+		bt_rap_hci_set_options(
+					btd_opts.defaults.bcs.role,
+					btd_opts.defaults.bcs.cs_sync_ant_sel,
+					btd_opts.defaults.bcs.max_tx_power);
+	} else {
+		error("HCI raw channel not available (may be in use)");
+	}
+
 	rap_data_add(data);
 
 	data->ready_id = bt_rap_ready_register(data->rap, rap_ready, service,
@@ -228,6 +253,10 @@ static int rap_accept(struct btd_service *service)
 	struct btd_device *device = btd_service_get_device(service);
 	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
 	struct rap_data *data = btd_service_get_user_data(service);
+	struct bt_att *att;
+	const bdaddr_t *bdaddr;
+	uint8_t bdaddr_type;
+	uint16_t handle;
 	char addr[18];
 
 	ba2str(device_get_address(device), addr);
@@ -243,6 +272,29 @@ static int rap_accept(struct btd_service *service)
 		return -EINVAL;
 	}
 
+	/* Set up connection handle mapping for CS event routing */
+	att = bt_rap_get_att(data->rap);
+	bdaddr = device_get_address(device);
+	bdaddr_type = device_get_le_address_type(device);
+
+	if (att && data->hci) {
+		/* Use bt_hci_get_conn_handle to find the connection handle
+		 * by bdaddr using HCIGETCONNLIST ioctl
+		 */
+		if (bt_hci_get_conn_handle(data->hci,
+					(const uint8_t *)bdaddr, &handle)) {
+			DBG("Found conn handle 0x%04X for %s", handle, addr);
+			DBG("Setting up handle mapping: handle=0x%04X",
+				handle);
+			bt_rap_set_conn_handle(data->rap, handle,
+						(const uint8_t *)bdaddr,
+						bdaddr_type);
+		} else {
+			error("Failed to find connection handle for device %s",
+				addr);
+		}
+	}
+
 	btd_service_connecting_complete(service, 0);
 
 	return 0;
diff --git a/profiles/ranging/rap_hci.c b/profiles/ranging/rap_hci.c
new file mode 100644
index 000000000..bc7aa2ca1
--- /dev/null
+++ b/profiles/ranging/rap_hci.c
@@ -0,0 +1,1267 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <endian.h>
+
+#include "lib/bluetooth/bluetooth.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
+#include "src/shared/rap.h"
+#include "src/log.h"
+#include "monitor/bt.h"
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* Macro to sign-extend an N-bit value to 16-bit signed integer */
+#define SIGN_EXTEND_TO_16(val, bits) \
+	((int16_t)((int32_t)((val) << (32 - (bits))) >> (32 - (bits))))
+
+/*  CS State Definitions */
+enum cs_state_t {
+	CS_INIT,
+	CS_STOPPED,
+	CS_STARTED,
+	CS_WAIT_CONFIG_CMPLT,
+	CS_WAIT_SEC_CMPLT,
+	CS_WAIT_PROC_CMPLT,
+	CS_HOLD,
+	CS_UNSPECIFIED
+};
+
+const char *state_names[] = {
+	"CS_INIT",
+	"CS_STOPPED",
+	"CS_STARTED",
+	"CS_WAIT_CONFIG_CMPLT",
+	"CS_WAIT_SEC_CMPLT",
+	"CS_WAIT_PROC_CMPLT",
+	"CS_HOLD",
+	"CS_UNSPECIFIED"
+};
+
+/* Callback Function Type */
+typedef void (*cs_callback_t)(uint16_t length,
+			const void *param, void *user_data);
+
+/* State Machine Context */
+struct cs_state_machine_t {
+	enum cs_state_t current_state;
+	enum cs_state_t old_state;
+	struct bt_hci *hci;
+	struct bt_rap *rap;
+	unsigned int event_id;
+	bool initiator;
+	bool procedure_active;
+};
+
+struct cs_callback_map_t {
+	enum cs_state_t state;
+	cs_callback_t callback;
+};
+
+struct cs_callback_map_t cs_callback_map[] = {
+	{ CS_WAIT_CONFIG_CMPLT, bt_rap_hci_cs_config_complete_callback },
+	{ CS_WAIT_SEC_CMPLT, bt_rap_hci_cs_sec_enable_complete_callback },
+	{ CS_WAIT_PROC_CMPLT, bt_rap_hci_cs_procedure_enable_complete_callback }
+};
+
+#define CS_CALLBACK_MAP_SIZE ARRAY_SIZE(cs_callback_map)
+
+struct bt_rap_hci_cs_options cs_opt;
+struct cs_state_machine_t *sm;
+
+/* Connection Handle Mapping */
+struct rap_conn_mapping {
+	uint16_t handle;
+	uint8_t bdaddr[6];
+	uint8_t bdaddr_type;
+	struct bt_att *att;
+	struct bt_rap *rap;
+};
+
+static struct queue *conn_mappings;
+
+/* Connection Mapping Helper Functions */
+static void mapping_free(void *data)
+{
+	struct rap_conn_mapping *mapping = data;
+
+	if (!mapping)
+		return;
+
+	free(mapping);
+}
+
+static bool match_mapping_handle(const void *a, const void *b)
+{
+	const struct rap_conn_mapping *mapping = a;
+	uint16_t handle = PTR_TO_UINT(b);
+
+	return mapping->handle == handle;
+}
+
+static bool match_mapping_rap(const void *a, const void *b)
+{
+	const struct rap_conn_mapping *mapping = a;
+	const struct bt_rap *rap = b;
+
+	return mapping->rap == rap;
+}
+
+static struct rap_conn_mapping *find_mapping_by_handle(uint16_t handle)
+{
+	if (!conn_mappings)
+		return NULL;
+
+	return queue_find(conn_mappings, match_mapping_handle,
+				UINT_TO_PTR(handle));
+}
+
+static bool add_conn_mapping(uint16_t handle, const uint8_t *bdaddr,
+				uint8_t bdaddr_type, struct bt_att *att,
+				struct bt_rap *rap)
+{
+	struct rap_conn_mapping *mapping;
+
+	if (!conn_mappings) {
+		conn_mappings = queue_new();
+		if (!conn_mappings)
+			return false;
+	}
+
+	/* Check if mapping already exists */
+	mapping = find_mapping_by_handle(handle);
+	if (mapping) {
+		/* Update existing mapping */
+		if (bdaddr)
+			memcpy(mapping->bdaddr, bdaddr, 6);
+		mapping->bdaddr_type = bdaddr_type;
+		mapping->att = att;
+		mapping->rap = rap;
+		return true;
+	}
+
+	/* Create new mapping */
+	mapping = new0(struct rap_conn_mapping, 1);
+	if (!mapping)
+		return false;
+
+	mapping->handle = handle;
+	if (bdaddr)
+		memcpy(mapping->bdaddr, bdaddr, 6);
+	mapping->bdaddr_type = bdaddr_type;
+	mapping->att = att;
+	mapping->rap = rap;
+
+	return queue_push_tail(conn_mappings, mapping);
+}
+
+static void remove_conn_mapping(uint16_t handle)
+{
+	struct rap_conn_mapping *mapping;
+
+	if (!conn_mappings)
+		return;
+
+	mapping = queue_remove_if(conn_mappings, match_mapping_handle,
+					UINT_TO_PTR(handle));
+	if (mapping)
+		mapping_free(mapping);
+}
+
+static void remove_rap_mappings(struct bt_rap *rap)
+{
+	if (!conn_mappings)
+		return;
+
+	queue_remove_all(conn_mappings, match_mapping_rap, rap,
+				mapping_free);
+}
+
+static struct bt_rap *resolve_handle_to_rap(uint16_t handle,
+						struct bt_hci *hci)
+{
+	struct rap_conn_mapping *mapping;
+
+	/* Try to find in mapping cache */
+	mapping = find_mapping_by_handle(handle);
+	if (mapping && mapping->rap) {
+		DBG("Found handle 0x%04X in mapping cache", handle);
+		return mapping->rap;
+	}
+
+	/* Profile layer should have called bt_rap_set_conn_handle() during
+	 * connection establishment. If we reach here, the mapping was not set.
+	 */
+	DBG("No mapping found for handle 0x%04X", handle);
+	DBG("Profile layer should call bt_rap_set_conn_handle() on connect");
+
+	return NULL;
+}
+
+/*  State Machine Functions */
+void cs_state_machine_init(struct cs_state_machine_t *sm, struct bt_rap *rap,
+				struct bt_hci *hci)
+{
+	if (!sm)
+		return;
+
+	memset(sm, 0, sizeof(struct cs_state_machine_t));
+	sm->current_state = CS_UNSPECIFIED;
+	sm->rap = rap;
+	sm->hci = hci;
+	sm->initiator = false;
+	sm->procedure_active = false;
+}
+
+void bt_rap_hci_sm_cleanup(void)
+{
+	if (!sm)
+		return;
+
+	if (sm->event_id)
+		bt_hci_unregister(sm->hci, sm->event_id);
+
+	sm->current_state = CS_UNSPECIFIED;
+	sm->rap = NULL;
+	sm->hci = NULL;
+	sm->procedure_active = false;
+
+	free(sm);
+}
+
+void bt_rap_hci_set_options(uint8_t role, uint8_t cs_sync_ant_sel,
+					int8_t max_tx_power)
+{
+	cs_opt.role = role;
+	cs_opt.cs_sync_ant_sel = cs_sync_ant_sel;
+	cs_opt.max_tx_power = max_tx_power;
+}
+
+/* State Transition Logic */
+void cs_set_state(struct cs_state_machine_t *sm, enum cs_state_t new_state)
+{
+	if (!sm)
+		return;
+
+	if (sm->current_state == new_state)
+		return;
+
+	/* Validate state values before array access */
+	if (sm->current_state > CS_UNSPECIFIED || new_state > CS_UNSPECIFIED) {
+		error("Invalid state transition attempted\n");
+		return;
+	}
+
+	DBG("[STATE] Transition: %s → %s\n",
+		state_names[sm->current_state],
+		state_names[new_state]);
+
+	sm->old_state = sm->current_state;
+	sm->current_state = new_state;
+}
+
+enum cs_state_t cs_get_current_state(struct cs_state_machine_t *sm)
+{
+	return sm ? sm->current_state : CS_UNSPECIFIED;
+}
+
+bool cs_is_procedure_active(const struct cs_state_machine_t *sm)
+{
+	return sm ? sm->procedure_active : false;
+}
+
+/* HCI Event Callbacks */
+static void rap_def_settings_done_cb(const void *data, uint8_t size,
+					void *user_data)
+{
+	struct bt_hci_rsp_le_cs_set_def_settings *rp;
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_rsp_le_cs_set_def_settings))
+		return;
+
+	DBG("[EVENT] CS default Setting Complete (size=0x%02X)\n", size);
+
+	rp = (struct bt_hci_rsp_le_cs_set_def_settings *)data;
+
+	if (cs_get_current_state(sm) != CS_INIT) {
+		DBG("Event received in Wrong State!! Expected : CS_INIT");
+		return;
+	}
+
+	if (rp->status == 0) {
+		/* Success - proceed to configuration */
+		cs_set_state(sm, CS_WAIT_CONFIG_CMPLT);
+
+		/* Reflector role */
+		DBG("Waiting for CS Config Completed event...\n");
+		/* TODO: Initiator role - Send CS Config complete cmd */
+	} else {
+		/* Error - transition to stopped */
+		error("CS Set default setting failed with status 0x%02X\n",
+		rp->status);
+		cs_set_state(sm, CS_STOPPED);
+	}
+}
+
+void rap_send_hci_def_settings_command(struct cs_state_machine_t *sm,
+		struct bt_hci_evt_le_cs_rd_rem_supp_cap_complete *ev)
+{
+	struct bt_hci_cmd_le_cs_set_def_settings cp;
+	unsigned int status;
+
+	memset(&cp, 0, sizeof(cp));
+
+	if (ev->handle)
+		cp.handle = ev->handle;
+	cp.role_enable = cs_opt.role;
+	cp.cs_sync_antenna_selection = cs_opt.cs_sync_ant_sel;
+	cp.max_tx_power = cs_opt.max_tx_power;
+
+	if (!sm || !sm->hci) {
+		error("Set Def Settings: sm or hci is null");
+		return;
+	}
+
+	status = bt_hci_send(sm->hci, BT_HCI_CMD_LE_CS_SET_DEF_SETTINGS,
+				&cp, sizeof(cp), rap_def_settings_done_cb,
+				sm, NULL);
+
+	DBG("sending set default settings case, status : %d", status);
+	if (!status)
+		error("Failed to send default settings cmd");
+}
+
+static void rap_rd_rmt_supp_cap_cmplt_evt(const uint8_t *data, uint8_t size,
+					   void *user_data)
+{
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+	const struct bt_hci_evt_le_cs_rd_rem_supp_cap_complete *evt;
+	struct bt_rap *rap;
+	struct iovec iov;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_evt_le_cs_rd_rem_supp_cap_complete))
+		return;
+
+	/* Initialize iovec with the event data */
+	iov.iov_base = (void *)data;
+	iov.iov_len = size;
+
+	/* Pull the entire structure at once */
+	evt = util_iov_pull_mem(&iov, sizeof(*evt));
+	if (!evt) {
+		error("Failed to pull remote cap complete struct\n");
+		return;
+	}
+
+	DBG("[EVENT] Remote Capabilities Complete\n");
+	DBG("status=0x%02X, handle=0x%04X\n", evt->status, evt->handle);
+
+	/* Check status */
+	if (evt->status != 0) {
+		error("Remote capabilities failed with status 0x%02X\n",
+			evt->status);
+		cs_set_state(sm, CS_STOPPED);
+		return;
+	}
+
+	/* Resolve handle to RAP instance */
+	rap = resolve_handle_to_rap(evt->handle, sm->hci);
+	if (!rap) {
+		DBG("[WARN] Could not resolve handle 0x%04X to RAP instance\n",
+			evt->handle);
+		/* Continue with state machine RAP for now */
+		rap = sm->rap;
+	}
+
+	DBG("[EVENT] Remote Capabilities: num_config=%u, ",
+		evt->num_config_supported);
+	DBG("max_consecutive_proc=%u, num_antennas=%u, ",
+		evt->max_consecutive_procedures_supported,
+		evt->num_antennas_supported);
+	DBG("max_antenna_paths=%u, roles=0x%02X, modes=0x%02X\n",
+		evt->max_antenna_paths_supported,
+		evt->roles_supported,
+		evt->modes_supported);
+
+	rap_send_hci_def_settings_command(sm,
+		(struct bt_hci_evt_le_cs_rd_rem_supp_cap_complete *)evt);
+	cs_set_state(sm, CS_INIT);
+}
+
+static void rap_cs_config_cmplt_evt(const uint8_t *data, uint8_t size,
+				    void *user_data)
+{
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+	const struct bt_hci_evt_le_cs_config_complete *evt;
+	struct rap_ev_cs_config_cmplt rap_ev;
+	struct iovec iov;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_evt_le_cs_config_complete))
+		return;
+
+	/* Initialize iovec with the event data */
+	iov.iov_base = (void *)data;
+	iov.iov_len = size;
+
+	DBG("[EVENT] Configuration Complete (size=0x%02X)\n", size);
+
+	/* State Check */
+	if (cs_get_current_state(sm) != CS_WAIT_CONFIG_CMPLT) {
+		DBG("Event received in Wrong State!! ");
+		DBG("Expected : CS_WAIT_CONFIG_CMPLT");
+		return;
+	}
+
+	/* Pull the entire structure at once */
+	evt = util_iov_pull_mem(&iov, sizeof(*evt));
+	if (!evt) {
+		error("Failed to pull config complete struct\n");
+		return;
+	}
+
+	DBG("status=0x%02X, handle=0x%04X\n", evt->status, evt->handle);
+
+	/* Check status */
+	if (evt->status != 0) {
+		error("Configuration failed with status 0x%02X\n",
+			evt->status);
+		cs_set_state(sm, CS_STOPPED);
+		return;
+	}
+
+	/* Copy fields to rap_ev structure */
+	rap_ev.status = evt->status;
+	rap_ev.conn_hdl = cpu_to_le16(evt->handle);
+	rap_ev.config_id = evt->config_id;
+	rap_ev.action = evt->action;
+	rap_ev.main_mode_type = evt->main_mode_type;
+	rap_ev.sub_mode_type = evt->sub_mode_type;
+	rap_ev.min_main_mode_steps = evt->min_main_mode_steps;
+	rap_ev.max_main_mode_steps = evt->max_main_mode_steps;
+	rap_ev.main_mode_rep = evt->main_mode_repetition;
+	rap_ev.mode_0_steps = evt->mode_0_steps;
+	rap_ev.role = evt->role;
+	rap_ev.rtt_type = evt->rtt_type;
+	rap_ev.cs_sync_phy = evt->cs_sync_phy;
+	memcpy(rap_ev.channel_map, evt->channel_map, 10);
+	rap_ev.channel_map_rep = evt->channel_map_repetition;
+	rap_ev.channel_sel_type = evt->channel_selection_type;
+	rap_ev.ch3c_shape = evt->ch3c_shape;
+	rap_ev.ch3c_jump = evt->ch3c_jump;
+	rap_ev.reserved = evt->reserved;
+	rap_ev.t_ip1_time = evt->t_ip1_time;
+	rap_ev.t_ip2_time = evt->t_ip2_time;
+	rap_ev.t_fcs_time = evt->t_fcs_time;
+	rap_ev.t_pm_time = evt->t_pm_time;
+
+	/* Store rtt_type in global options */
+	cs_opt.rtt_type = rap_ev.rtt_type;
+
+	DBG("[EVENT] Config Complete: config_id=%u, action=%u, ",
+		rap_ev.config_id, rap_ev.action);
+	DBG("main_mode=%u, sub_mode=%u, role=%u, rtt_type=%u\n",
+		rap_ev.main_mode_type, rap_ev.sub_mode_type,
+		rap_ev.role, rap_ev.rtt_type);
+
+	/* Success - proceed to Security enable complete */
+	cs_set_state(sm, CS_WAIT_SEC_CMPLT);
+
+	/* Reflector role */
+	DBG("Waiting for security enable event...\n");
+	/* TODO: Initiator role - Send CS Security enable cmd */
+
+	/* Send Callback to RAP Profile */
+	for (size_t i = 0; i < CS_CALLBACK_MAP_SIZE; i++) {
+		if (cs_callback_map[i].state == sm->old_state) {
+			cs_callback_map[i].callback(size, &rap_ev, sm->rap);
+			return;
+		}
+	}
+}
+
+static void rap_cs_sec_enable_cmplt_evt(const uint8_t *data, uint8_t size,
+					 void *user_data)
+{
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+	struct rap_ev_cs_sec_enable_cmplt rap_ev;
+	struct iovec iov;
+	uint8_t status;
+	uint16_t handle;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_evt_le_cs_sec_enable_complete))
+		return;
+
+	/* Initialize iovec with the event data */
+	iov.iov_base = (void *)data;
+	iov.iov_len = size;
+
+	DBG("[EVENT] Security Enable Complete (size=0x%02X)\n", size);
+
+	/* State Check */
+	if (cs_get_current_state(sm) != CS_WAIT_SEC_CMPLT) {
+		DBG("Event received in Wrong State!! ");
+		DBG("Expected : CS_WAIT_SEC_CMPLT");
+		return;
+	}
+
+	/* Parse all fields in order using iovec */
+	if (!util_iov_pull_u8(&iov, &status)) {
+		error("Failed to parse Status\n");
+		return;
+	}
+
+	if (!util_iov_pull_le16(&iov, &handle)) {
+		error("Failed to parse Connection_Handle\n");
+		return;
+	}
+
+	rap_ev.status = status;
+	rap_ev.conn_hdl = cpu_to_le16(handle);
+
+	DBG("[EVENT] Security Enable: status=0x%02X, handle=0x%04X\n",
+		rap_ev.status, handle);
+
+	if (rap_ev.status == 0) {
+		/* Success - proceed to configuration */
+		cs_set_state(sm, CS_WAIT_PROC_CMPLT);
+
+		/* Reflector role */
+		DBG("Waiting for CS Proc complete event...\n");
+		/* TODO: Initiator - Send CS Proc Set Parameter and enable */
+	} else {
+		/* Error - transition to stopped */
+		error("Security enable failed with status 0x%02X\n",
+			rap_ev.status);
+		cs_set_state(sm, CS_STOPPED);
+	}
+
+	/* Send Callback to RAP Profile */
+	for (size_t i = 0; i < CS_CALLBACK_MAP_SIZE; i++) {
+		if (cs_callback_map[i].state == sm->old_state) {
+			cs_callback_map[i].callback(size, &rap_ev, sm->rap);
+			return;
+		}
+	}
+}
+
+static void rap_cs_proc_enable_cmplt_evt(const uint8_t *data, uint8_t size,
+					  void *user_data)
+{
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+	const struct bt_hci_evt_le_cs_proc_enable_complete *evt;
+	struct rap_ev_cs_proc_enable_cmplt rap_ev;
+	struct iovec iov;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_evt_le_cs_proc_enable_complete))
+		return;
+
+	/* Initialize iovec with the event data */
+	iov.iov_base = (void *)data;
+	iov.iov_len = size;
+
+	DBG("[EVENT] Procedure Enable Complete (size=0x%02X)\n", size);
+
+	/* State Check */
+	if (cs_get_current_state(sm) != CS_WAIT_PROC_CMPLT) {
+		DBG("Event received in Wrong State!! ");
+		DBG("Expected : CS_WAIT_PROC_CMPLT");
+		return;
+	}
+
+	/* Pull the entire structure at once */
+	evt = util_iov_pull_mem(&iov, sizeof(*evt));
+	if (!evt) {
+		error("Failed to pull proc enable complete struct\n");
+		return;
+	}
+
+	DBG("status=0x%02X, handle=0x%04X\n", evt->status, evt->handle);
+
+	/* Check status */
+	if (evt->status != 0) {
+		error("Procedure enable failed with status 0x%02X\n",
+			evt->status);
+		cs_set_state(sm, CS_STOPPED);
+		sm->procedure_active = false;
+		return;
+	}
+
+	/* Copy fields to rap_ev structure */
+	rap_ev.status = evt->status;
+	rap_ev.conn_hdl = cpu_to_le16(evt->handle);
+	rap_ev.config_id = evt->config_id;
+	rap_ev.state = evt->state;
+	rap_ev.tone_ant_config_sel = evt->tone_antenna_config_selection;
+	rap_ev.sel_tx_pwr = evt->selected_tx_power;
+	memcpy(rap_ev.sub_evt_len, evt->subevent_len, 3);
+	rap_ev.sub_evts_per_evt = evt->subevents_per_event;
+	rap_ev.sub_evt_intrvl = evt->subevent_interval;
+	rap_ev.evt_intrvl = evt->event_interval;
+	rap_ev.proc_intrvl = evt->procedure_interval;
+	rap_ev.proc_counter = evt->procedure_count;
+	rap_ev.max_proc_len = evt->max_procedure_len;
+
+	DBG("[EVENT] Procedure Enable: config_id=%u, state=%u, ",
+		rap_ev.config_id, rap_ev.state);
+	DBG("sub_evts_per_evt=%u, evt_intrvl=%u, proc_intrvl=%u\n",
+		rap_ev.sub_evts_per_evt, rap_ev.evt_intrvl,
+		rap_ev.proc_intrvl);
+
+	/* Success - procedure started */
+	cs_set_state(sm, CS_STARTED);
+	sm->procedure_active = true;
+
+	/* Send Callback to RAP Profile */
+	for (size_t i = 0; i < CS_CALLBACK_MAP_SIZE; i++) {
+		if (cs_callback_map[i].state == sm->old_state) {
+			cs_callback_map[i].callback(size, &rap_ev, sm->rap);
+			return;
+		}
+	}
+}
+
+static void parse_i_q_sample(struct iovec *iov, int16_t *i_sample,
+				int16_t *q_sample)
+{
+	uint32_t buffer;
+	uint32_t i12;
+	uint32_t q12;
+
+	/* Pull 24-bit little-endian value from iovec */
+	if (!util_iov_pull_le24(iov, &buffer)) {
+		*i_sample = 0;
+		*q_sample = 0;
+		return;
+	}
+
+	/* Extract 12-bit I and Q values from 24-bit buffer */
+	i12 =  buffer        & 0x0FFFU;   /* bits 0..11 */
+	q12 = (buffer >> 12) & 0x0FFFU;   /* bits 12..23 */
+
+	/* Sign-extend 12-bit values to 16-bit using macro */
+	*i_sample = SIGN_EXTEND_TO_16(i12, 12);
+	*q_sample = SIGN_EXTEND_TO_16(q12, 12);
+}
+
+/* Parse CS Mode 0 step data */
+static void parse_mode_zero_data(struct iovec *iov,
+				 struct cs_mode_zero_data *mode_data,
+				 uint8_t cs_role)
+{
+	uint32_t freq_offset;
+
+	if (iov->iov_len < 3) {
+		DBG("Mode 0: too short (<3)");
+		return;
+	}
+
+	util_iov_pull_u8(iov, &mode_data->packet_quality);
+	util_iov_pull_u8(iov, &mode_data->packet_rssi_dbm);
+	util_iov_pull_u8(iov, &mode_data->packet_ant);
+	DBG("CS Step mode 0");
+
+	if (cs_role == CS_INITIATOR && iov->iov_len >= 4) {
+		util_iov_pull_le32(iov, &freq_offset);
+		mode_data->init_measured_freq_offset = freq_offset;
+	}
+}
+
+/* Parse CS Mode 1 step data */
+static void parse_mode_one_data(struct iovec *iov,
+				struct cs_mode_one_data *mode_data,
+				uint8_t cs_role, uint8_t cs_rtt_type)
+{
+	uint16_t time_val;
+
+	if (iov->iov_len < 4) {
+		DBG("Mode 1: too short (<4)");
+		return;
+	}
+
+	DBG("CS Step mode 1");
+	util_iov_pull_u8(iov, &mode_data->packet_quality);
+	util_iov_pull_u8(iov, &mode_data->packet_rssi_dbm);
+	util_iov_pull_u8(iov, &mode_data->packet_ant);
+	util_iov_pull_u8(iov, &mode_data->packet_nadm);
+
+	if (iov->iov_len >= 2) {
+		util_iov_pull_le16(iov, &time_val);
+		if (cs_role == CS_REFLECTOR)
+			mode_data->tod_toa_refl = time_val;
+		else
+			mode_data->toa_tod_init = time_val;
+	}
+
+	if ((cs_rtt_type == 0x01 || cs_rtt_type == 0x02) &&
+		iov->iov_len >= 6) {
+		int16_t i_val, q_val;
+
+		parse_i_q_sample(iov, &i_val, &q_val);
+		mode_data->packet_pct1.i_sample = i_val;
+		mode_data->packet_pct1.q_sample = q_val;
+
+		parse_i_q_sample(iov, &i_val, &q_val);
+		mode_data->packet_pct2.i_sample = i_val;
+		mode_data->packet_pct2.q_sample = q_val;
+	}
+}
+
+/* Parse CS Mode 2 step data */
+static void parse_mode_two_data(struct iovec *iov,
+				struct cs_mode_two_data *mode_data,
+				uint8_t max_paths)
+{
+	uint8_t k;
+
+	if (iov->iov_len < 1) {
+		DBG("Mode 2: too short (<1)");
+		return;
+	}
+
+	util_iov_pull_u8(iov, &mode_data->ant_perm_index);
+	DBG("CS Step mode 2, max paths : %d", max_paths);
+
+	for (k = 0; k < max_paths; k++) {
+		int16_t i_val, q_val;
+
+		if (iov->iov_len < 4) {
+			DBG("Mode 2: insufficient PCT for path %u (rem=%zu)",
+				k, iov->iov_len);
+			break;
+		}
+		parse_i_q_sample(iov, &i_val, &q_val);
+		mode_data->tone_pct[k].i_sample = i_val;
+		mode_data->tone_pct[k].q_sample = q_val;
+
+		util_iov_pull_u8(iov, &mode_data->tone_quality_indicator[k]);
+		DBG("tone_quality_indicator : %d",
+			mode_data->tone_quality_indicator[k]);
+		DBG("[i, q] : %d, %d",
+			mode_data->tone_pct[k].i_sample,
+			mode_data->tone_pct[k].q_sample);
+	}
+}
+
+/* Parse CS Mode 3 step data */
+static void parse_mode_three_data(struct iovec *iov,
+				struct cs_mode_three_data *mode_data,
+				uint8_t cs_role, uint8_t cs_rtt_type,
+				uint8_t max_paths)
+{
+	uint8_t k;
+	struct cs_mode_one_data *mode_one = &mode_data->mode_one_data;
+	struct cs_mode_two_data *mode_two = &mode_data->mode_two_data;
+
+	if (iov->iov_len < 4) {
+		DBG("Mode 3: mode1 too short (<4)");
+		return;
+	}
+
+	DBG("CS Step mode 3");
+
+	/* Parse Mode 1 portion */
+	parse_mode_one_data(iov, mode_one, cs_role, cs_rtt_type);
+
+	/* Parse Mode 2 portion */
+	if (iov->iov_len >= 1) {
+		util_iov_pull_u8(iov, &mode_two->ant_perm_index);
+		for (k = 0; k < max_paths; k++) {
+			int16_t i_val, q_val;
+
+			if (iov->iov_len < 4)
+				break;
+			parse_i_q_sample(iov, &i_val, &q_val);
+			mode_two->tone_pct[k].i_sample = i_val;
+			mode_two->tone_pct[k].q_sample = q_val;
+
+			util_iov_pull_u8(iov,
+					 &mode_two->tone_quality_indicator[k]);
+		}
+	}
+}
+
+/* Parse a single CS step */
+static void parse_cs_step(struct iovec *iov, struct cs_step_data *step,
+			uint8_t cs_role, uint8_t cs_rtt_type,
+			uint8_t max_paths)
+{
+	uint8_t mode;
+	uint8_t chnl;
+	uint8_t length;
+
+	/* Check if we have enough data for the 3-byte header */
+	if (iov->iov_len < 3) {
+		DBG("Truncated header for step");
+		return;
+	}
+
+	/* Read mode, channel, and length (3-byte header) */
+	if (!util_iov_pull_u8(iov, &mode) ||
+		!util_iov_pull_u8(iov, &chnl) ||
+		!util_iov_pull_u8(iov, &length)) {
+		DBG("Failed to read header for step");
+		return;
+	}
+
+	DBG("event->step_data_len : %d", length);
+
+	step->step_mode = mode;
+	step->step_chnl = chnl;
+	step->step_data_length = length;
+
+	DBG("Step: mode=%u chnl=%u data_len=%u", mode, chnl, length);
+
+	if (iov->iov_len < length) {
+		DBG("Truncated payload for step (need %u, have %zu)",
+			length, iov->iov_len);
+		return;
+	}
+
+	/* Parse step data based on mode */
+	switch (mode) {
+	case CS_MODE_ZERO:
+		parse_mode_zero_data(iov, &step->step_mode_data.mode_zero_data,
+					cs_role);
+		break;
+	case CS_MODE_ONE:
+		parse_mode_one_data(iov, &step->step_mode_data.mode_one_data,
+					cs_role, cs_rtt_type);
+		break;
+	case CS_MODE_TWO:
+		parse_mode_two_data(iov, &step->step_mode_data.mode_two_data,
+					max_paths);
+		break;
+	case CS_MODE_THREE:
+		parse_mode_three_data(iov,
+					&step->step_mode_data.mode_three_data,
+					cs_role, cs_rtt_type, max_paths);
+		break;
+	default:
+		DBG("Unknown step mode %d", mode);
+		/* Skip the entire step data */
+		util_iov_pull(iov, length);
+		break;
+	}
+}
+
+static void rap_cs_subevt_result_evt(const uint8_t *data, uint8_t size,
+				void *user_data)
+{
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+	struct rap_ev_cs_subevent_result *rap_ev;
+	struct iovec iov;
+	uint8_t cs_role;
+	uint8_t cs_rtt_type;
+	uint8_t max_paths;
+	uint8_t steps;
+	size_t send_len = 0;
+	uint16_t handle;
+	uint8_t config_id;
+	uint16_t start_acl_conn_evt_counter;
+	uint16_t proc_counter;
+	uint16_t freq_comp;
+	uint8_t ref_pwr_lvl;
+	uint8_t proc_done_status;
+	uint8_t subevt_done_status;
+	uint8_t abort_reason;
+	uint8_t num_ant_paths;
+	uint8_t num_steps_reported;
+	uint8_t i;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_evt_le_cs_subevent_result))
+		return;
+
+	/* Initialize iovec with the event data */
+	iov.iov_base = (void *)data;
+	iov.iov_len = size;
+
+	/* Check if Procedure is active or not */
+	if (!sm->procedure_active) {
+		DBG("Received Subevent event when Procedure is inactive!");
+		return;
+	}
+
+	/* Parse header fields using iovec */
+	if (!util_iov_pull_le16(&iov, &handle)) {
+		error("Failed to parse Connection_Handle\n");
+		return;
+	}
+
+	if (!util_iov_pull_u8(&iov, &config_id) ||
+		!util_iov_pull_le16(&iov, &start_acl_conn_evt_counter) ||
+		!util_iov_pull_le16(&iov, &proc_counter) ||
+		!util_iov_pull_le16(&iov, &freq_comp) ||
+		!util_iov_pull_u8(&iov, &ref_pwr_lvl) ||
+		!util_iov_pull_u8(&iov, &proc_done_status) ||
+		!util_iov_pull_u8(&iov, &subevt_done_status) ||
+		!util_iov_pull_u8(&iov, &abort_reason) ||
+		!util_iov_pull_u8(&iov, &num_ant_paths) ||
+		!util_iov_pull_u8(&iov, &num_steps_reported)) {
+		error("Failed to parse subevent fields\n");
+		return;
+	}
+
+	cs_role = cs_opt.role;
+	cs_rtt_type = cs_opt.rtt_type;
+	max_paths = MIN((num_ant_paths + 1), CS_MAX_ANT_PATHS);
+	steps = MIN(num_steps_reported, CS_MAX_STEPS);
+	send_len = offsetof(struct rap_ev_cs_subevent_result, step_data) +
+					steps * sizeof(struct cs_step_data);
+	rap_ev = (struct rap_ev_cs_subevent_result *)malloc(send_len);
+	if (!rap_ev) {
+		error("Failed to allocate memory for subevent result\n");
+		return;
+	}
+
+	DBG("[EVENT] Subevent Result (length=%u)\n", size);
+	rap_ev->conn_hdl                     = le16_to_cpu(handle);
+	rap_ev->config_id                    = config_id;
+	rap_ev->start_acl_conn_evt_counter   = start_acl_conn_evt_counter;
+	rap_ev->proc_counter                 = proc_counter;
+	rap_ev->freq_comp                    = freq_comp;
+	rap_ev->ref_pwr_lvl                  = ref_pwr_lvl;
+	rap_ev->proc_done_status             = proc_done_status;
+	rap_ev->subevt_done_status           = subevt_done_status;
+	rap_ev->abort_reason                 = abort_reason;
+	rap_ev->num_ant_paths                = num_ant_paths;
+	rap_ev->num_steps_reported           = steps;
+
+	if (num_steps_reported > CS_MAX_STEPS) {
+		DBG("Too many steps reported: %u (max %u)",
+			num_steps_reported, CS_MAX_STEPS);
+		goto send_event;
+	}
+
+	/* Early exit for error conditions */
+	if (rap_ev->subevt_done_status == 0xF ||
+	    rap_ev->proc_done_status == 0xF) {
+		DBG("CS Procedure/Subevent aborted: ");
+		DBG("sub evt status = %d, proc status = %d, reason = %d",
+			rap_ev->subevt_done_status, rap_ev->proc_done_status,
+			rap_ev->abort_reason);
+		goto send_event;
+	}
+
+	/* Parse interleaved step data from remaining iovec data */
+	for (i = 0; i < steps; i++)
+		parse_cs_step(&iov, &rap_ev->step_data[i], cs_role, cs_rtt_type,
+			max_paths);
+
+send_event:
+	DBG("CS subevent result processed: %zu bytes, ", send_len);
+	bt_rap_hci_cs_subevent_result_callback(send_len, rap_ev, sm->rap);
+	free(rap_ev);
+}
+
+static void rap_cs_subevt_result_cont_evt(const uint8_t *data, uint8_t size,
+					void *user_data)
+{
+	struct cs_state_machine_t *sm = (struct cs_state_machine_t *)user_data;
+	struct rap_ev_cs_subevent_result_cont *rap_ev;
+	struct iovec iov;
+	uint8_t cs_role;
+	uint8_t cs_rtt_type;
+	uint8_t max_paths;
+	uint8_t steps;
+	size_t send_len = 0;
+	uint16_t handle;
+	uint8_t config_id;
+	uint8_t proc_done_status;
+	uint8_t subevt_done_status;
+	uint8_t abort_reason;
+	uint8_t num_ant_paths;
+	uint8_t num_steps_reported;
+	uint8_t i;
+
+	if (!sm || !data ||
+		size < sizeof(struct bt_hci_evt_le_cs_subevent_result_continue))
+		return;
+
+	/* Initialize iovec with the event data */
+	iov.iov_base = (void *)data;
+	iov.iov_len = size;
+
+	/* Check if Procedure is active or not */
+	if (!sm->procedure_active) {
+		error("Received Subevent when CS Procedure is inactive!");
+		return;
+	}
+
+	/* Parse header fields using iovec */
+	if (!util_iov_pull_le16(&iov, &handle)) {
+		error("Failed to parse Connection_Handle\n");
+		return;
+	}
+
+	if (!util_iov_pull_u8(&iov, &config_id) ||
+		!util_iov_pull_u8(&iov, &proc_done_status) ||
+		!util_iov_pull_u8(&iov, &subevt_done_status) ||
+		!util_iov_pull_u8(&iov, &abort_reason) ||
+		!util_iov_pull_u8(&iov, &num_ant_paths) ||
+		!util_iov_pull_u8(&iov, &num_steps_reported)) {
+		error("Failed to parse subevent continue fields ");
+		return;
+	}
+
+	cs_role = cs_opt.role;
+	cs_rtt_type = cs_opt.rtt_type;
+	max_paths = MIN((num_ant_paths + 1), CS_MAX_ANT_PATHS);
+	steps = MIN(num_steps_reported, CS_MAX_STEPS);
+	send_len = offsetof(struct rap_ev_cs_subevent_result_cont, step_data) +
+					steps * sizeof(struct cs_step_data);
+	rap_ev = (struct rap_ev_cs_subevent_result_cont *)malloc(send_len);
+	if (!rap_ev) {
+		error("Failed to allocate memory for subevent result\n");
+		return;
+	}
+
+	DBG("[EVENT] Subevent Result Cont (length=%u)\n", size);
+	rap_ev->conn_hdl                     = le16_to_cpu(handle);
+	rap_ev->config_id                    = config_id;
+	rap_ev->proc_done_status             = proc_done_status;
+	rap_ev->subevt_done_status           = subevt_done_status;
+	rap_ev->abort_reason                 = abort_reason;
+	rap_ev->num_ant_paths                = num_ant_paths;
+	rap_ev->num_steps_reported           = steps;
+
+	if (num_steps_reported > CS_MAX_STEPS) {
+		DBG("Too many steps reported: %u (max %u)",
+			num_steps_reported, CS_MAX_STEPS);
+		goto send_event;
+	}
+
+	/* Early exit for error conditions */
+	if (rap_ev->subevt_done_status == 0xF ||
+	    rap_ev->proc_done_status == 0xF) {
+		DBG("CS Procedure/Subevent aborted: ");
+		DBG("sub evt status = %d, proc status = %d, reason = %d",
+			rap_ev->subevt_done_status, rap_ev->proc_done_status,
+			rap_ev->abort_reason);
+		goto send_event;
+	}
+
+	/* Parse interleaved step data from remaining iovec data */
+	for (i = 0; i < steps; i++)
+		parse_cs_step(&iov, &rap_ev->step_data[i], cs_role, cs_rtt_type,
+			max_paths);
+
+send_event:
+	DBG("CS subevent result cont processed: %zu bytes, ", send_len);
+	bt_rap_hci_cs_subevent_result_cont_callback(send_len, rap_ev, sm->rap);
+	free(rap_ev);
+}
+
+/* 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 */
+#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)
+{
+	struct iovec iov;
+	uint8_t subevent;
+	const struct subevent_entry *entry = NULL;
+	size_t i;
+
+	/* 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);
+}
+
+void bt_rap_hci_register_events(struct bt_rap *rap, struct bt_hci *hci)
+{
+	if (!rap || !hci)
+		return;
+
+	sm = new0(struct cs_state_machine_t, 1);
+	if (!sm) {
+		error("Failed to allocate state machine\n");
+		return;
+	}
+
+	cs_state_machine_init(sm, rap, hci);
+	sm->event_id = bt_hci_register(hci, BT_HCI_EVT_LE_META_EVENT,
+					rap_handle_hci_events, sm, NULL);
+
+	DBG("bt_hci_register done, event_id : %d", sm->event_id);
+
+	if (!sm->event_id) {
+		DBG("Error: Failed to register hci le meta events ");
+		DBG("event_id=0x%02X\n", sm->event_id);
+		free(sm);
+		return;
+	}
+}
+
+bool bt_rap_attach_hci(struct bt_rap *rap, struct bt_hci *hci)
+{
+	if (!rap)
+		return false;
+
+	if (!hci) {
+		DBG("Failed to create HCI RAW channel ");
+		bt_hci_unref(hci);
+		return false;
+	}
+
+	bt_rap_hci_register_events(rap, hci);
+
+	return true;
+}
+
+bool bt_rap_set_conn_handle(struct bt_rap *rap, uint16_t handle,
+				const uint8_t *bdaddr, uint8_t bdaddr_type)
+{
+	struct bt_att *att;
+
+	if (!rap)
+		return false;
+
+	att = bt_rap_get_att(rap);
+	if (!att)
+		return false;
+
+	DBG("Setting connection mapping: handle=0x%04X, ", handle);
+	if (bdaddr) {
+		DBG("bdaddr=%02x:%02x:%02x:%02x:%02x:%02x type=%u",
+			bdaddr[5], bdaddr[4], bdaddr[3],
+			bdaddr[2], bdaddr[1], bdaddr[0], bdaddr_type);
+	}
+
+	return add_conn_mapping(handle, bdaddr, bdaddr_type, att, rap);
+}
+
+void bt_rap_clear_conn_handle(struct bt_rap *rap, uint16_t handle)
+{
+	if (!rap)
+		return;
+
+	DBG("Clearing connection mapping: handle=0x%04X", handle);
+	remove_conn_mapping(handle);
+}
+
+void bt_rap_detach_hci(struct bt_rap *rap)
+{
+	if (!rap)
+		return;
+
+	DBG("Detaching RAP from HCI, cleaning up mappings");
+
+	/* Remove all mappings associated with this RAP instance */
+	remove_rap_mappings(rap);
+}
-- 


^ permalink raw reply related

* [PATCH BlueZ v7 2/3] main.conf: Add Channel Sounding config parsing  support
From: Naga Bhavani Akella @ 2026-04-15 11:25 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg,
	prathibha.madugonde, Naga Bhavani Akella
In-Reply-To: <20260415112510.195491-1-naga.akella@oss.qualcomm.com>

Add support for parsing Channel Sounding (CS) configuration options
from the configuration file.

Add CAP_NET_RAW to CapabilityBoundingSet in bluetooth.service.
bluetoothd requires CAP_NET_RAW to receive and process HCI LE events
when running under a constrained systemd capability bounding set
---
 src/bluetooth.service.in |   2 +-
 src/btd.h                |   7 +++
 src/main.c               | 132 ++++++++++++++++++++++++++++++++++++++-
 src/main.conf            |  24 +++++++
 4 files changed, 162 insertions(+), 3 deletions(-)

diff --git a/src/bluetooth.service.in b/src/bluetooth.service.in
index 8ebe89bec..8dcbde236 100644
--- a/src/bluetooth.service.in
+++ b/src/bluetooth.service.in
@@ -10,7 +10,7 @@ ExecStart=@PKGLIBEXECDIR@/bluetoothd
 NotifyAccess=main
 #WatchdogSec=10
 #Restart=on-failure
-CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
+CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_NET_BIND_SERVICE
 LimitNPROC=1
 
 # Filesystem lockdown
diff --git a/src/btd.h b/src/btd.h
index c84a600d1..db2e81239 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -94,11 +94,18 @@ struct btd_le_defaults {
 	uint8_t		enable_advmon_interleave_scan;
 };
 
+struct btd_le_bcs {
+	uint8_t role;
+	uint8_t cs_sync_ant_sel;
+	int8_t max_tx_power;
+};
+
 struct btd_defaults {
 	uint16_t	num_entries;
 
 	struct btd_br_defaults br;
 	struct btd_le_defaults le;
+	struct btd_le_bcs bcs;
 };
 
 struct btd_csis {
diff --git a/src/main.c b/src/main.c
index 818f7c06e..32fc2c97d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -156,6 +156,13 @@ static const char *gatt_options[] = {
 	NULL
 };
 
+static const char *const bcs_options[] = {
+	"Role",
+	"CsSyncAntennaSel",
+	"MaxTxPower",
+	NULL
+};
+
 static const char *csip_options[] = {
 	"SIRK",
 	"Encryption",
@@ -183,7 +190,7 @@ static const char *advmon_options[] = {
 
 static const struct group_table {
 	const char *name;
-	const char **options;
+	const char * const *options;
 } valid_groups[] = {
 	{ "General",	supported_options },
 	{ "BR",		br_options },
@@ -193,6 +200,7 @@ static const struct group_table {
 	{ "CSIS",	csip_options },
 	{ "AVDTP",	avdtp_options },
 	{ "AVRCP",	avrcp_options },
+	{ "ChannelSounding",	bcs_options },
 	{ "AdvMon",	advmon_options },
 	{ }
 };
@@ -356,7 +364,7 @@ static enum jw_repairing_t parse_jw_repairing(const char *jw_repairing)
 
 
 static void check_options(GKeyFile *config, const char *group,
-						const char **options)
+						const char * const *options)
 {
 	char **keys;
 	int i;
@@ -492,6 +500,46 @@ static bool parse_config_int(GKeyFile *config, const char *group,
 	return true;
 }
 
+static bool parse_config_signed_int(GKeyFile *config, const char *group,
+					const char *key, int8_t *val,
+					size_t min, size_t max)
+{
+	char *str = NULL;
+	char *endptr = NULL;
+	long tmp;
+	bool result = false;
+
+	str = g_key_file_get_string(config, group, key, NULL);
+	if (!str)
+		return false;
+
+	tmp = strtol(str, &endptr, 0);
+	if (!endptr || *endptr != '\0') {
+		warn("%s.%s = %s is not integer", group, key, str);
+		goto cleanup;
+	}
+
+	if (tmp < (long)min) {
+		warn("%s.%s = %ld is out of range (< %zu)", group, key, tmp,
+			min);
+		goto cleanup;
+	}
+
+	if (tmp > (long)max) {
+		warn("%s.%s = %ld is out of range (> %zu)", group, key, tmp,
+									max);
+		goto cleanup;
+	}
+
+	if (val)
+		*val = (int8_t)tmp;
+	result = true;
+
+cleanup:
+	g_free(str);
+	return result;
+}
+
 struct config_param {
 	const char * const val_name;
 	void * const val;
@@ -1184,6 +1232,81 @@ static void parse_csis(GKeyFile *config)
 					0, UINT8_MAX);
 }
 
+static bool parse_cs_role(GKeyFile *config, const char *group,
+					const char *key, uint8_t *val)
+{
+	GError *err = NULL;
+	char *str = NULL;
+	char *endptr = NULL;
+	int numeric_val;
+
+	/* Try to read as string first */
+	str = g_key_file_get_string(config, group, key, &err);
+	if (err) {
+		if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
+			DBG("%s", err->message);
+		g_error_free(err);
+		return false;
+	}
+
+	DBG("%s.%s = %s", group, key, str);
+
+	/* Check if it's a string value */
+	if (!strcmp(str, "Initiator") || !strcmp(str, "initiator")) {
+		if (val)
+			*val = 1;
+		g_free(str);
+		return true;
+	} else if (!strcmp(str, "Reflector") || !strcmp(str, "reflector")) {
+		if (val)
+			*val = 2;
+		g_free(str);
+		return true;
+	} else if (!strcmp(str, "Both") || !strcmp(str, "both")) {
+		if (val)
+			*val = 3;
+		g_free(str);
+		return true;
+	}
+
+	/* Try to parse as numeric value */
+	numeric_val = strtol(str, &endptr, 0);
+
+	if (!endptr || *endptr != '\0') {
+		error("%s.%s = %s is not a valid value. "
+			"Expected: 1/Initiator, 2/Reflector, or 3/Both",
+			group, key, str);
+		g_free(str);
+		return false;
+	}
+
+	if (numeric_val < 1 || numeric_val > 3) {
+		warn("%s.%s = %d is out of range. "
+			"Valid values: 1 (Initiator), 2 (Reflector), 3 (Both)",
+			group, key, numeric_val);
+		g_free(str);
+		return false;
+	}
+
+	if (val)
+		*val = numeric_val;
+
+	g_free(str);
+	return true;
+}
+
+static void parse_le_cs_config(GKeyFile *config)
+{
+	parse_cs_role(config, "ChannelSounding", "Role",
+			&btd_opts.defaults.bcs.role);
+	parse_config_u8(config, "ChannelSounding", "CsSyncAntennaSel",
+			&btd_opts.defaults.bcs.cs_sync_ant_sel,
+			0x01, 0xFF);
+	parse_config_signed_int(config, "ChannelSounding",
+			"MaxTxPower", &btd_opts.defaults.bcs.max_tx_power,
+			INT8_MIN, INT8_MAX);
+}
+
 static void parse_avdtp_session_mode(GKeyFile *config)
 {
 	char *str = NULL;
@@ -1262,6 +1385,7 @@ static void parse_config(GKeyFile *config)
 	parse_csis(config);
 	parse_avdtp(config);
 	parse_avrcp(config);
+	parse_le_cs_config(config);
 	parse_advmon(config);
 }
 
@@ -1313,6 +1437,10 @@ static void init_defaults(void)
 
 	btd_opts.advmon.rssi_sampling_period = 0xFF;
 	btd_opts.csis.encrypt = true;
+
+	btd_opts.defaults.bcs.role = 0x03;
+	btd_opts.defaults.bcs.cs_sync_ant_sel = 0xFF;
+	btd_opts.defaults.bcs.max_tx_power = 0x14;
 }
 
 static void log_handler(const gchar *log_domain, GLogLevelFlags log_level,
diff --git a/src/main.conf b/src/main.conf
index d31dd1b8f..fc0138bbf 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -299,6 +299,30 @@
 # Default = auto
 # Security = auto
 
+[ChannelSounding]
+# Current role of the device
+# Possible values:
+#   1 or "Initiator" - CS Initiator role,
+#   Generally, CS Initiator acts as Client (Gatt role) and Central (Gap role)
+#   2 or "Reflector" - CS Reflector role,
+#   Generally, CS Reflector acts as Server (Gatt role) and Peripheral (Gap role)
+#   3 or "Both"      - Both Initiator and Reflector roles
+# Default: 3 (Both)
+#Role = 3
+
+# Antenna Identifier to be used
+# Possible values:
+# 0x01-0x04 (antenna identifier to be used),
+# 0xFE - Antennas to be used in repetetive order,
+# 0xFF - Host doen't have recommendation
+# Default: 0xFF (Host doesn't have recommendation)
+#CsSyncAntennaSel = 0xFF
+
+# Maximum Transmit power
+# Possible values: 0x7F-0x14 (-127dBm to 20dBm)
+# Default: 0x14 (Max Power possible)
+#MaxTxPower = 0x14
+
 [CSIS]
 # SIRK - Set Identification Resolution Key which is common for all the
 # sets. They SIRK key is used to identify its sets. This can be any
-- 


^ permalink raw reply related

* [PATCH BlueZ v7 1/3] shared: rap: Introduce Channel Sounding HCI raw  interface support
From: Naga Bhavani Akella @ 2026-04-15 11:25 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg,
	prathibha.madugonde, Naga Bhavani Akella
In-Reply-To: <20260415112510.195491-1-naga.akella@oss.qualcomm.com>

Implement stub callbacks for Channel Sounding HCI events and add the
required protocol definitions for CS configuration, procedure control,
and subevent result parsing

Add data structures to support Channel Sounding Processing
Add helper function to get hci conn info list and integrate it with RAP
---
 src/shared/hci.c |  89 +++++++++++++++++++-----
 src/shared/hci.h |  15 ++++
 src/shared/rap.c |  50 +++++++++++++-
 src/shared/rap.h | 176 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 312 insertions(+), 18 deletions(-)

diff --git a/src/shared/hci.c b/src/shared/hci.c
index 575254c09..46377fa30 100644
--- a/src/shared/hci.c
+++ b/src/shared/hci.c
@@ -20,9 +20,11 @@
 #include <sys/un.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <fcntl.h>
 #include <errno.h>
 
+#include "bluetooth/hci.h"
 #include "monitor/bt.h"
 #include "src/shared/mainloop.h"
 #include "src/shared/io.h"
@@ -30,22 +32,6 @@
 #include "src/shared/queue.h"
 #include "src/shared/hci.h"
 
-#define BTPROTO_HCI	1
-struct sockaddr_hci {
-	sa_family_t	hci_family;
-	unsigned short	hci_dev;
-	unsigned short  hci_channel;
-};
-#define HCI_CHANNEL_RAW		0
-#define HCI_CHANNEL_USER	1
-
-#define SOL_HCI		0
-#define HCI_FILTER	2
-struct hci_filter {
-	uint32_t type_mask;
-	uint32_t event_mask[2];
-	uint16_t opcode;
-};
 
 struct bt_hci {
 	int ref_count;
@@ -673,3 +659,74 @@ bool bt_hci_unregister(struct bt_hci *hci, unsigned int id)
 
 	return true;
 }
+
+bool bt_hci_get_conn_handle(struct bt_hci *hci, const uint8_t *bdaddr,
+				uint16_t *handle)
+{
+	struct hci_conn_list_req *cl;
+	struct hci_conn_info *ci;
+	int fd, i;
+	bool found = false;
+
+	if (!hci || !bdaddr || !handle)
+		return false;
+
+	fd = io_get_fd(hci->io);
+	if (fd < 0)
+		return false;
+
+	/* Allocate buffer for connection list request */
+	cl = malloc(10 * sizeof(*ci) + sizeof(*cl));
+	if (!cl)
+		return false;
+
+	memset(cl, 0, 10 * sizeof(*ci) + sizeof(*cl));
+	cl->dev_id = 0;  /* Will be filled by ioctl */
+	cl->conn_num = 10;
+
+	/* Get connection list via ioctl */
+	if (ioctl(fd, HCIGETCONNLIST, (void *) cl) < 0) {
+		free(cl);
+		return false;
+	}
+
+	/* Search for the connection with matching bdaddr */
+	ci = cl->conn_info;
+	for (i = 0; i < cl->conn_num; i++, ci++) {
+		if (memcmp(&ci->bdaddr, bdaddr, 6) == 0) {
+			*handle = ci->handle;
+			found = true;
+			break;
+		}
+	}
+
+	free(cl);
+	return found;
+}
+
+int bt_hci_get_fd(struct bt_hci *hci)
+{
+	if (!hci || !hci->io)
+		return -1;
+
+	return io_get_fd(hci->io);
+}
+
+int bt_hci_get_index(struct bt_hci *hci)
+{
+	struct sockaddr_hci addr;
+	socklen_t addr_len = sizeof(addr);
+	int fd;
+
+	if (!hci)
+		return -1;
+
+	fd = bt_hci_get_fd(hci);
+	if (fd < 0)
+		return -1;
+
+	if (getsockname(fd, (struct sockaddr *)&addr, &addr_len) < 0)
+		return -1;
+
+	return addr.hci_dev;
+}
diff --git a/src/shared/hci.h b/src/shared/hci.h
index 76ee72f54..20a12d4ae 100644
--- a/src/shared/hci.h
+++ b/src/shared/hci.h
@@ -13,6 +13,15 @@
 
 typedef void (*bt_hci_destroy_func_t)(void *user_data);
 
+struct bt_hci_conn_info {
+	uint16_t handle;
+	uint8_t  bdaddr[6];
+	uint8_t  type;
+	uint8_t  out;
+	uint16_t state;
+	uint32_t link_mode;
+};
+
 struct bt_hci;
 
 struct bt_hci *bt_hci_new(int fd);
@@ -41,3 +50,9 @@ unsigned int bt_hci_register(struct bt_hci *hci, uint8_t event,
 				bt_hci_callback_func_t callback,
 				void *user_data, bt_hci_destroy_func_t destroy);
 bool bt_hci_unregister(struct bt_hci *hci, unsigned int id);
+
+bool bt_hci_get_conn_handle(struct bt_hci *hci, const uint8_t *bdaddr,
+				uint16_t *handle);
+
+int bt_hci_get_fd(struct bt_hci *hci);
+int bt_hci_get_index(struct bt_hci *hci);
diff --git a/src/shared/rap.c b/src/shared/rap.c
index 39ef3f278..5745cda08 100644
--- a/src/shared/rap.c
+++ b/src/shared/rap.c
@@ -26,8 +26,8 @@
 #include "src/shared/gatt-client.h"
 #include "src/shared/rap.h"
 
-#define DBG(_rap, fmt, arg...) \
-	rap_debug(_rap, "%s:%s() " fmt, __FILE__, __func__, ## arg)
+#define DBG(_rap, fmt, ...) \
+	rap_debug(_rap, "%s:%s() " fmt, __FILE__, __func__, ##__VA_ARGS__)
 
 #define RAS_UUID16			0x185B
 
@@ -504,6 +504,52 @@ bool bt_rap_unregister(unsigned int id)
 	return true;
 }
 
+void bt_rap_hci_cs_subevent_result_cont_callback(uint16_t length,
+						const void *param,
+						void *user_data)
+{
+	struct bt_rap *rap = user_data;
+
+	DBG(rap, "Received CS subevent CONT: len=%d", length);
+}
+
+void bt_rap_hci_cs_subevent_result_callback(uint16_t length,
+					const void *param,
+					void *user_data)
+{
+	struct bt_rap *rap = user_data;
+
+	DBG(rap, "Received CS subevent: len=%d", length);
+}
+
+void bt_rap_hci_cs_procedure_enable_complete_callback(uint16_t length,
+						const void *param,
+						void *user_data)
+{
+	struct bt_rap *rap = user_data;
+
+	DBG(rap, "Received CS procedure enable complete subevent: len=%d",
+	    length);
+}
+
+void bt_rap_hci_cs_sec_enable_complete_callback(uint16_t length,
+						 const void *param,
+						 void *user_data)
+{
+	struct bt_rap *rap = user_data;
+
+	DBG(rap, "Received CS security enable subevent: len=%d", length);
+}
+
+void bt_rap_hci_cs_config_complete_callback(uint16_t length,
+					const void *param,
+					void *user_data)
+{
+	struct bt_rap *rap = user_data;
+
+	DBG(rap, "Received CS config complete subevent: len=%d", length);
+}
+
 struct bt_rap *bt_rap_new(struct gatt_db *ldb, struct gatt_db *rdb)
 {
 	struct bt_rap *rap;
diff --git a/src/shared/rap.h b/src/shared/rap.h
index a1d1ff2ae..5b94d28bd 100644
--- a/src/shared/rap.h
+++ b/src/shared/rap.h
@@ -9,8 +9,155 @@
 #include <inttypes.h>
 
 #include "src/shared/io.h"
+#include "bluetooth/mgmt.h"
+#include "src/shared/hci.h"
 
 struct bt_rap;
+struct gatt_db;
+struct bt_gatt_client;
+
+/* Channel Sounding Events */
+struct bt_rap_hci_cs_options {
+	uint8_t role;
+	uint8_t cs_sync_ant_sel;
+	int8_t max_tx_power;
+	int rtt_type;
+};
+
+#define CS_MODE_ZERO				0x00
+#define CS_MODE_ONE				0x01
+#define CS_MODE_TWO				0x02
+#define CS_MODE_THREE				0x03
+
+#define CS_REFLECTOR			0x01
+#define CS_INITIATOR			0x00
+
+#define CS_MAX_ANT_PATHS			0x05
+#define CS_MAX_STEPS			0xA0
+#define CS_MAX_STEP_DATA_LEN		0xFF
+
+struct rap_ev_cs_config_cmplt {
+	uint8_t status;
+	uint16_t conn_hdl;
+	uint8_t config_id;
+	uint8_t action;
+	uint8_t main_mode_type;
+	uint8_t sub_mode_type;
+	uint8_t min_main_mode_steps;
+	uint8_t max_main_mode_steps;
+	uint8_t main_mode_rep;
+	uint8_t mode_0_steps;
+	uint8_t role;
+	uint8_t rtt_type;
+	uint8_t cs_sync_phy;
+	uint8_t channel_map[10];
+	uint8_t channel_map_rep;
+	uint8_t channel_sel_type;
+	uint8_t ch3c_shape;
+	uint8_t ch3c_jump;
+	uint8_t reserved;
+	uint8_t t_ip1_time;
+	uint8_t t_ip2_time;
+	uint8_t t_fcs_time;
+	uint8_t t_pm_time;
+} __packed;
+
+struct rap_ev_cs_sec_enable_cmplt {
+	uint8_t status;
+	uint16_t conn_hdl;
+} __packed;
+
+struct rap_ev_cs_proc_enable_cmplt {
+	uint8_t status;
+	uint16_t conn_hdl;
+	uint8_t config_id;
+	uint8_t state;
+	uint8_t tone_ant_config_sel;
+	int8_t sel_tx_pwr;
+	uint8_t sub_evt_len[3];
+	uint8_t sub_evts_per_evt;
+	uint16_t sub_evt_intrvl;
+	uint16_t evt_intrvl;
+	uint16_t proc_intrvl;
+	uint16_t proc_counter;
+	uint16_t max_proc_len;
+} __packed;
+
+#define CS_MAX_STEPS			0xA0
+
+struct pct_iq_sample {
+	int16_t i_sample;
+	int16_t q_sample;
+} __packed;
+
+struct cs_mode_zero_data {
+	uint8_t packet_quality;
+	uint8_t packet_rssi_dbm;
+	uint8_t packet_ant;
+	uint32_t init_measured_freq_offset;
+} __packed;
+
+struct cs_mode_one_data {
+	uint8_t packet_quality;
+	uint8_t packet_rssi_dbm;
+	uint8_t packet_ant;
+	uint8_t packet_nadm;
+	int16_t toa_tod_init;
+	int16_t tod_toa_refl;
+	struct pct_iq_sample packet_pct1;
+	struct pct_iq_sample packet_pct2;
+} __packed;
+
+struct cs_mode_two_data {
+	uint8_t ant_perm_index;
+	struct pct_iq_sample tone_pct[4];
+	uint8_t tone_quality_indicator[4];
+} __packed;
+
+struct cs_mode_three_data {
+	struct cs_mode_one_data mode_one_data;
+	struct cs_mode_two_data mode_two_data;
+} __packed;
+
+union cs_mode_data {
+	struct cs_mode_zero_data mode_zero_data;
+	struct cs_mode_one_data mode_one_data;
+	struct cs_mode_two_data mode_two_data;
+	struct cs_mode_three_data mode_three_data;
+};
+
+struct cs_step_data {
+	uint8_t step_mode;
+	uint8_t step_chnl;
+	uint8_t step_data_length;
+	union cs_mode_data step_mode_data;
+} __packed;
+
+struct rap_ev_cs_subevent_result {
+	uint16_t conn_hdl;
+	uint8_t config_id;
+	uint16_t start_acl_conn_evt_counter;
+	uint16_t proc_counter;
+	uint16_t freq_comp;
+	uint8_t ref_pwr_lvl;
+	uint8_t proc_done_status;
+	uint8_t subevt_done_status;
+	uint8_t abort_reason;
+	uint8_t num_ant_paths;
+	uint8_t num_steps_reported;
+	struct cs_step_data step_data[];
+} __packed;
+
+struct rap_ev_cs_subevent_result_cont {
+	uint16_t conn_hdl;
+	uint8_t config_id;
+	uint8_t proc_done_status;
+	uint8_t subevt_done_status;
+	uint8_t abort_reason;
+	uint8_t num_ant_paths;
+	uint8_t num_steps_reported;
+	struct cs_step_data step_data[];
+} __packed;
 
 typedef void (*bt_rap_debug_func_t)(const char *str, void *user_data);
 typedef void (*bt_rap_ready_func_t)(struct bt_rap *rap, void *user_data);
@@ -43,3 +190,32 @@ bool bt_rap_ready_unregister(struct bt_rap *rap, unsigned int id);
 bool bt_rap_unregister(unsigned int id);
 
 struct bt_rap *bt_rap_new(struct gatt_db *ldb, struct gatt_db *rdb);
+
+/* HCI Raw Channel Approach */
+void bt_rap_hci_cs_config_complete_callback(uint16_t length,
+					     const void *param,
+					     void *user_data);
+void bt_rap_hci_cs_sec_enable_complete_callback(uint16_t length,
+						 const void *param,
+						 void *user_data);
+void bt_rap_hci_cs_procedure_enable_complete_callback(uint16_t length,
+						      const void *param,
+						      void *user_data);
+void bt_rap_hci_cs_subevent_result_callback(uint16_t length,
+					     const void *param,
+					     void *user_data);
+void bt_rap_hci_cs_subevent_result_cont_callback(uint16_t length,
+						  const void *param,
+						  void *user_data);
+
+void bt_rap_hci_set_options(uint8_t role, uint8_t cs_sync_ant_sel,
+				   int8_t max_tx_power);
+
+bool bt_rap_attach_hci(struct bt_rap *rap, struct bt_hci *hci);
+void bt_rap_detach_hci(struct bt_rap *rap);
+void bt_rap_hci_sm_cleanup(void);
+
+/* Connection handle mapping functions */
+bool bt_rap_set_conn_handle(struct bt_rap *rap, uint16_t handle,
+				const uint8_t *bdaddr, uint8_t bdaddr_type);
+void bt_rap_clear_conn_handle(struct bt_rap *rap, uint16_t handle);
-- 


^ permalink raw reply related

* [PATCH BlueZ v7 0/3] Add initial Channel Sounding support -
From: Naga Bhavani Akella @ 2026-04-15 11:25 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: luiz.dentz, quic_mohamull, quic_hbandi, quic_anubhavg,
	prathibha.madugonde, Naga Bhavani Akella

This patch series introduces initial support for Bluetooth Channel
Sounding (CS) using the raw HCI interface.
This series lays the groundwork for CS support by adding commonly required
protocol definitions, configuration parsing, and event handling for
the reflector role.

The changes include:

  1) Introduction of raw HCI support structures and callbacks for Channel
     Sounding procedures and events. This provides the foundational data
     definitions and HCI subevent handling needed by higher-level profiles

  2) Addition of Channel Sounding configuration parsing from the BlueZ
     configuration file.This patch also updates the systemd
     service capability bounding set to include CAP_NET_RAW, which is
     required for bluetoothd to receive and process LE Channel Sounding
     events when running under a constrained systemd environment

  3) Implementation of HCI LE Channel Sounding event handling in the
     Ranging profile for the reflector role.
     This includes opening a raw HCI channel,
     parsing relevant CS LE events, routing them to the RAP profile

Patch overview:
 1/3 shared: rap: introduce Channel Sounding HCI raw interface support
 2/3 main.conf: add Channel Sounding config parsing support
 3/3 profiles: ranging: add HCI LE Channel Sounding event handling

Changes in v7:
- src/main.c: Add second const to bcs_options array,
updated group_table and check_options to use const char * const *
- Move endptr to start of the function parse_cs_role

- profiles/ranging/rap.c: Move hci_index declaration to
start of function for C90 compliance
-Replace inefficient loop (0x0001-0x0EFF)
with single bt_hci_get_conn_handle call in rap_accept

- src/shared/rap.h: Add forward declarations for
struct gatt_db and struct bt_gatt_client

- src/shared/hci.h: Add bt_hci_get_conn_handle, bt_hci_get_fd,
bt_hci_get_index declarations
-Remove bt_hci_get_conn_info declaration

- src/shared/hci.c: Implement bt_hci_get_conn_handle to find handle
by bdaddr using HCIGETCONNLIST,
Add helper functions bt_hci_get_fd and bt_hci_get_index
-Remove bt_hci_get_conn_info implementation

- profiles/ranging/rap_hci.: Remove unnecessary fallback ioctl
debug code from resolve_handle_to_rap
- Add HCI_EVT macro to simplify subevent table entries,
Add SIGN_EXTEND_TO_16 macro for bit manipulation,
refactored parse_i_q_sample to use util_iov_pull_le24 and sign-extend macro

Naga Bhavani Akella (3):
  shared: rap: Introduce Channel Sounding HCI raw  interface support
  main.conf: Add Channel Sounding config parsing  support
  profiles: ranging: Add HCI LE Event Handling in Reflector role

 Makefile.plugins           |    3 +-
 profiles/ranging/rap.c     |   52 ++
 profiles/ranging/rap_hci.c | 1267 ++++++++++++++++++++++++++++++++++++
 src/bluetooth.service.in   |    2 +-
 src/btd.h                  |    7 +
 src/main.c                 |  132 +++-
 src/main.conf              |   24 +
 src/shared/hci.c           |   89 ++-
 src/shared/hci.h           |   15 +
 src/shared/rap.c           |   50 +-
 src/shared/rap.h           |  176 +++++
 11 files changed, 1795 insertions(+), 22 deletions(-)
 create mode 100644 profiles/ranging/rap_hci.c

-- 


^ permalink raw reply

* RE: Bluetooth: l2cap: fix MPS check in l2cap_ecred_reconf_req
From: bluez.test.bot @ 2026-04-15 11:21 UTC (permalink / raw)
  To: linux-bluetooth, phx0fer
In-Reply-To: <20260415104355.76524-1-phx0fer@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 6911 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1081515

---Test result---

Test Summary:
CheckPatch                    PASS      0.57 seconds
GitLint                       PASS      0.23 seconds
SubjectPrefix                 PASS      0.08 seconds
BuildKernel                   PASS      26.28 seconds
CheckAllWarning               PASS      28.48 seconds
CheckSparse                   PASS      30.18 seconds
BuildKernel32                 PASS      25.12 seconds
TestRunnerSetup               PASS      563.75 seconds
TestRunner_l2cap-tester       FAIL      28.18 seconds
TestRunner_iso-tester         PASS      41.64 seconds
TestRunner_bnep-tester        PASS      6.30 seconds
TestRunner_mgmt-tester        FAIL      115.32 seconds
TestRunner_rfcomm-tester      PASS      9.93 seconds
TestRunner_sco-tester         FAIL      14.26 seconds
TestRunner_ioctl-tester       PASS      10.20 seconds
TestRunner_mesh-tester        FAIL      12.16 seconds
TestRunner_smp-tester         PASS      8.57 seconds
TestRunner_userchan-tester    PASS      6.80 seconds
TestRunner_6lowpan-tester     FAIL      8.46 seconds
IncrementalBuild              PASS      24.79 seconds

Details
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
Total: 96, Passed: 94 (97.9%), Failed: 2, Not Run: 0

Failed Test Cases
L2CAP BR/EDR Client - Set PHY 3M                     Failed       0.112 seconds
L2CAP BR/EDR Server - Set PHY 3M                     Failed       0.120 seconds
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.114 seconds
##############################
Test: TestRunner_sco-tester - FAIL
Desc: Run sco-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-g7259c040a595 #1 Not tainted
------------------------------------------------------
kworker/u5:2/117 is trying to acquire lock:
ffff888001abe240 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}, at: sco_connect_cfm+0x358/0x8d0

but task is already holding lock:
ffff888002094c20 (&conn->lock){+.+.}-{3:3}, at: sco_connect_cfm+0x22d/0x8d0

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&conn->lock){+.+.}-{3:3}:
       lock_acquire+0xf7/0x2c0
       _raw_spin_lock+0x2a/0x40
       sco_sock_connect+0x4d7/0x1280
       __sys_connect+0x1a3/0x260
       __x64_sys_connect+0x6e/0xb0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #0 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}:
       check_prev_add+0xe9/0xc70
       __lock_acquire+0x1457/0x1df0
       lock_acquire+0xf7/0x2c0
       lock_sock_nested+0x36/0xd0
       sco_connect_cfm+0x358/0x8d0
       hci_sync_conn_complete_evt+0x3d3/0x8e0
       hci_event_packet+0x74f/0xb10
       hci_rx_work+0x398/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

other info that might help us debug this:

...
BUG: sleeping function called from invalid context at net/core/sock.c:3782
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 117, name: kworker/u5:2
preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
INFO: lockdep is turned off.
CPU: 0 UID: 0 PID: 117 Comm: kworker/u5:2 Not tainted 7.0.0-rc2-g7259c040a595 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Workqueue: hci0 hci_rx_work
Call Trace:
 <TASK>
 dump_stack_lvl+0x49/0x60
 __might_resched+0x2ea/0x500
 lock_sock_nested+0x47/0xd0
 ? sco_connect_cfm+0x358/0x8d0
 sco_connect_cfm+0x358/0x8d0
 ? hci_debugfs_create_conn+0x190/0x210
 ? __pfx_sco_connect_cfm+0x10/0x10
 hci_sync_conn_complete_evt+0x3d3/0x8e0
 hci_event_packet+0x74f/0xb10
 ? __pfx_hci_sync_conn_complete_evt+0x10/0x10
 ? __pfx_hci_event_packet+0x10/0x10
 ? mark_held_locks+0x49/0x80
 ? lockdep_hardirqs_on_prepare+0xd4/0x180
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 hci_rx_work+0x398/0xd00
 process_scheduled_works+0xb16/0x1ac0
 ? __pfx_process_scheduled_works+0x10/0x10
 ? lock_acquire+0xf7/0x2c0
 ? lock_is_held_type+0x9b/0x110
 ? __pfx_hci_rx_work+0x10/0x10
 worker_thread+0x4ff/0xba0
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 ? __pfx_worker_thread+0x10/0x10
 kthread+0x368/0x490
 ? _raw_spin_unlock_irq+0x23/0x40
 ? __pfx_kthread+0x10/0x10
 ret_from_fork+0x498/0x7e0
 ? __pfx_ret_from_fork+0x10/0x10
 ? __switch_to+0x9e4/0xe50
 ? __switch_to_asm+0x32/0x60
...
Total: 30, Passed: 30 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.654 seconds
Mesh - Send cancel - 2                               Timed out    1.994 seconds
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-g7259c040a595 #1 Not tainted
------------------------------------------------------
kworker/0:1/11 is trying to acquire lock:
ffff888002767140 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x75/0x180

but task is already holding lock:
ffffffffb644d720 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #4 (rtnl_mutex){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       lowpan_register_netdev+0x11/0x30
       chan_ready_cb+0x836/0xd00
       l2cap_recv_frame+0x6465/0x8910
       l2cap_recv_acldata+0x790/0xdf0
       hci_rx_work+0x500/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

-> #3 (&chan->lock#3/1){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       l2cap_chan_connect+0x74e/0x1980
       lowpan_control_write+0x523/0x660
       full_proxy_write+0x10b/0x190
       vfs_write+0x1c0/0xf60
       ksys_write+0xf1/0x1d0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #2 (&conn->lock){+.+.}-{4:4}:
...
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0


https://github.com/bluez/bluetooth-next/pull/87

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [PATCH] Bluetooth: l2cap: fix MPS check in l2cap_ecred_reconf_req
From: Dudu Lu @ 2026-04-15 10:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, Dudu Lu

The L2CAP specification states that if more than one channel is being
reconfigured, the MPS shall not be decreased. The current check has
two issues:

1) The comparison uses >= (greater-than-or-equal), which incorrectly
   rejects reconfiguration requests where the MPS stays the same.
   Since the spec says MPS "shall be greater than or equal to the
   current MPS", only a strict decrease (remote_mps > mps) should be
   rejected. Keeping the same MPS is valid.

2) The multi-channel guard uses `&& i` (loop index) to approximate
   "more than one channel", but this incorrectly allows MPS decrease
   for the first channel (i==0) even when multiple channels are being
   reconfigured. Replace with `&& num_scid > 1` which correctly
   checks whether the request covers more than one channel.

Signed-off-by: Dudu Lu <phx0fer@gmail.com>
---
 net/bluetooth/l2cap_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 95c65fece39b..29d793f3a2eb 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5428,7 +5428,7 @@ static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
 		 * configured, the MPS field may be less than the current MPS
 		 * of that channel.
 		 */
-		if (chan[i]->remote_mps >= mps && i) {
+		if (chan[i]->remote_mps > mps && num_scid > 1) {
 			BT_ERR("chan %p decreased MPS %u -> %u", chan[i],
 			       chan[i]->remote_mps, mps);
 			result = L2CAP_RECONF_INVALID_MPS;
-- 
2.39.3 (Apple Git-145)


^ permalink raw reply related

* RE: Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame() extension handling
From: bluez.test.bot @ 2026-04-15 10:22 UTC (permalink / raw)
  To: linux-bluetooth, phx0fer
In-Reply-To: <20260415093953.39340-1-phx0fer@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 7212 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1081496

---Test result---

Test Summary:
CheckPatch                    PASS      0.54 seconds
GitLint                       FAIL      0.20 seconds
SubjectPrefix                 PASS      0.06 seconds
BuildKernel                   PASS      29.56 seconds
CheckAllWarning               PASS      28.81 seconds
CheckSparse                   PASS      27.42 seconds
BuildKernel32                 PASS      25.63 seconds
TestRunnerSetup               PASS      579.38 seconds
TestRunner_l2cap-tester       PASS      28.08 seconds
TestRunner_iso-tester         PASS      40.20 seconds
TestRunner_bnep-tester        PASS      6.45 seconds
TestRunner_mgmt-tester        FAIL      115.67 seconds
TestRunner_rfcomm-tester      PASS      9.46 seconds
TestRunner_sco-tester         FAIL      14.02 seconds
TestRunner_ioctl-tester       PASS      10.11 seconds
TestRunner_mesh-tester        FAIL      12.14 seconds
TestRunner_smp-tester         PASS      8.48 seconds
TestRunner_userchan-tester    PASS      7.82 seconds
TestRunner_6lowpan-tester     FAIL      8.30 seconds
IncrementalBuild              PASS      24.39 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame() extension handling

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (83>80): "Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame() extension handling"
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.105 seconds
##############################
Test: TestRunner_sco-tester - FAIL
Desc: Run sco-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-gc0f338b85a8d #1 Not tainted
------------------------------------------------------
kworker/u5:2/117 is trying to acquire lock:
ffff888001abe240 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}, at: sco_connect_cfm+0x358/0x8d0

but task is already holding lock:
ffff888002094c20 (&conn->lock){+.+.}-{3:3}, at: sco_connect_cfm+0x22d/0x8d0

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&conn->lock){+.+.}-{3:3}:
       lock_acquire+0xf7/0x2c0
       _raw_spin_lock+0x2a/0x40
       sco_sock_connect+0x4d7/0x1280
       __sys_connect+0x1a3/0x260
       __x64_sys_connect+0x6e/0xb0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #0 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}:
       check_prev_add+0xe9/0xc70
       __lock_acquire+0x1457/0x1df0
       lock_acquire+0xf7/0x2c0
       lock_sock_nested+0x36/0xd0
       sco_connect_cfm+0x358/0x8d0
       hci_sync_conn_complete_evt+0x3d3/0x8e0
       hci_event_packet+0x74f/0xb10
       hci_rx_work+0x398/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

other info that might help us debug this:

...
BUG: sleeping function called from invalid context at net/core/sock.c:3782
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 117, name: kworker/u5:2
preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
INFO: lockdep is turned off.
CPU: 0 UID: 0 PID: 117 Comm: kworker/u5:2 Not tainted 7.0.0-rc2-gc0f338b85a8d #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Workqueue: hci0 hci_rx_work
Call Trace:
 <TASK>
 dump_stack_lvl+0x49/0x60
 __might_resched+0x2ea/0x500
 lock_sock_nested+0x47/0xd0
 ? sco_connect_cfm+0x358/0x8d0
 sco_connect_cfm+0x358/0x8d0
 ? hci_debugfs_create_conn+0x190/0x210
 ? __pfx_sco_connect_cfm+0x10/0x10
 hci_sync_conn_complete_evt+0x3d3/0x8e0
 hci_event_packet+0x74f/0xb10
 ? __pfx_hci_sync_conn_complete_evt+0x10/0x10
 ? __pfx_hci_event_packet+0x10/0x10
 ? mark_held_locks+0x49/0x80
 ? lockdep_hardirqs_on_prepare+0xd4/0x180
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 hci_rx_work+0x398/0xd00
 process_scheduled_works+0xb16/0x1ac0
 ? __pfx_process_scheduled_works+0x10/0x10
 ? lock_acquire+0xf7/0x2c0
 ? lock_is_held_type+0x9b/0x110
 ? __pfx_hci_rx_work+0x10/0x10
 worker_thread+0x4ff/0xba0
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 ? __pfx_worker_thread+0x10/0x10
 kthread+0x368/0x490
 ? _raw_spin_unlock_irq+0x23/0x40
 ? __pfx_kthread+0x10/0x10
 ret_from_fork+0x498/0x7e0
 ? __pfx_ret_from_fork+0x10/0x10
 ? __switch_to+0x9e4/0xe50
 ? __switch_to_asm+0x32/0x60
...
Total: 30, Passed: 30 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.672 seconds
Mesh - Send cancel - 2                               Timed out    1.991 seconds
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-gc0f338b85a8d #1 Not tainted
------------------------------------------------------
kworker/0:1/11 is trying to acquire lock:
ffff8880026e1140 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x75/0x180

but task is already holding lock:
ffffffffa064d720 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #4 (rtnl_mutex){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       lowpan_register_netdev+0x11/0x30
       chan_ready_cb+0x836/0xd00
       l2cap_recv_frame+0x6a06/0x8920
       l2cap_recv_acldata+0x790/0xdf0
       hci_rx_work+0x500/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

-> #3 (&chan->lock#3/1){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       l2cap_chan_connect+0x74e/0x1980
       lowpan_control_write+0x523/0x660
       full_proxy_write+0x10b/0x190
       vfs_write+0x1c0/0xf60
       ksys_write+0xf1/0x1d0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #2 (&conn->lock){+.+.}-{4:4}:
...
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0


https://github.com/bluez/bluetooth-next/pull/86

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [PATCH] Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame() extension handling
From: Dudu Lu @ 2026-04-15  9:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, luiz.dentz, Dudu Lu

In bnep_rx_frame(), the BNEP_FILTER_NET_TYPE_SET and
BNEP_FILTER_MULTI_ADDR_SET extension header parsing has two bugs:

1) The 2-byte length field is read with *(u16 *)(skb->data + 1), which
   performs a native-endian read. The BNEP protocol specifies this field
   in big-endian (network byte order), and the same file correctly uses
   get_unaligned_be16() for the identical fields in
   bnep_ctrl_set_netfilter() and bnep_ctrl_set_mcfilter().

2) The length is multiplied by 2, but unlike BNEP_SETUP_CONN_REQ where
   the length byte counts UUID pairs (requiring * 2 for two UUIDs per
   entry), the filter extension length field already represents the total
   data size in bytes. This is confirmed by bnep_ctrl_set_netfilter()
   which reads the same field as a byte count and divides by 4 to get
   the number of filter entries.

   The bogus * 2 means skb_pull advances twice as far as it should,
   either dropping valid data from the next header or causing the pull
   to fail entirely when the doubled length exceeds the remaining skb.

Fix by splitting the pull into two steps: first use skb_pull_data() to
safely pull and validate the 3-byte fixed header (ctrl type + length),
then pull the variable-length data using the properly decoded length.

Fixes: bf8b9a9cb77b ("Bluetooth: bnep: Add support to extended headers of control frames")
Signed-off-by: Dudu Lu <phx0fer@gmail.com>
---
 net/bluetooth/bnep/core.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index d44987d4515c..853c8d7644b5 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -330,11 +330,18 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
 				goto badframe;
 			break;
 		case BNEP_FILTER_MULTI_ADDR_SET:
-		case BNEP_FILTER_NET_TYPE_SET:
-			/* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
-			if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
+		case BNEP_FILTER_NET_TYPE_SET: {
+			u8 *hdr;
+
+			/* Pull ctrl type (1 b) + len (2 b) */
+			hdr = skb_pull_data(skb, 3);
+			if (!hdr)
+				goto badframe;
+			/* Pull data (len bytes); length is big-endian */
+			if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
 				goto badframe;
 			break;
+		}
 		default:
 			kfree_skb(skb);
 			return 0;
-- 
2.39.3 (Apple Git-145)


^ permalink raw reply related

* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Andy Shevchenko @ 2026-04-15  9:07 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Manivannan Sadhasivam, Manivannan Sadhasivam, Rob Herring,
	Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor, Nicolas Schier,
	Hans de Goede, Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Bartosz Golaszewski,
	linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
	linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
	Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
	Bartosz Golaszewski, Luca Ceresoli
In-Reply-To: <CAGXv+5EPA29G-fsH=wWOD8AK6TZFezFhsE0NHPYj_Pt3nT+d_w@mail.gmail.com>

On Wed, Apr 15, 2026 at 04:31:24PM +0800, Chen-Yu Tsai wrote:
> On Tue, Apr 14, 2026 at 8:03 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> > On Tue, Apr 14, 2026 at 06:29:02PM +0800, Chen-Yu Tsai wrote:
> > > On Tue, Apr 14, 2026 at 4:28 PM Andy Shevchenko
> > > <andriy.shevchenko@linux.intel.com> wrote:
> > > > On Tue, Apr 14, 2026 at 01:03:19PM +0800, Chen-Yu Tsai wrote:
> > > > > On Tue, Apr 14, 2026 at 12:08 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > > > > On Mon, Apr 13, 2026 at 07:33:12PM +0530, Manivannan Sadhasivam wrote:
> > > > > > > On Mon, Apr 13, 2026 at 03:54:59PM +0800, Chen-Yu Tsai wrote:
> > > > > > > > On Thu, Mar 26, 2026 at 01:36:28PM +0530, Manivannan Sadhasivam wrote:

...

> > > > > > > > - Given that this connector actually represents two devices, how do I
> > > > > > > >   say I want the BT part to be a wakeup source, but not the WiFi part?
> > > > > > > >   Does wakeup-source even work at this point?
> > > > > > >
> > > > > > > You can't use the DT property since the devices are not described in DT
> > > > > > > statically. But you can still use the per-device 'wakeup' sysfs knob to enable
> > > > > > > wakeup.
> > > > >
> > > > > I see. I think not being able to specify generic properties for the devices
> > > > > on the connector is going to be a bit problematic.
> > > >
> > > > This is nature of the open-connectors, especially on the busses that are
> > > > hotpluggable, like PCIe. We never know what is connected there _ahead_.
> > >
> > > I believe what you mean by "hotpluggable" is "user replaceable".
> >
> > From the OS perspective it's the same. From platform perspective
> > there is a difference, granted.
> 
> Yes. I just wanted to clarify.
> 
> > > > In other words you can't describe in DT something that may not exist.
> > >
> > > But this is actually doable with the PCIe slot representation. The
> > > properties are put in the device node for the slot. If no card is
> > > actually inserted in the slot, then no device is created, and the
> > > device node is left as not associated with anything.
> >
> > But you need to list all devices in the world if you want to support this
> 
> Why would I need to? The PCIe slot representation just describes a
> PCIe bridge. Granted this might not be entirely correct, but it's
> what we currently have.
> 
> And even then, there are properties like memory-region or wakeup-source
> that are generic and aren't tied to specific devices.

Yes,  see below what I replied...

> > somehow. Yes, probably many of them (or majority) will be enumerated as is,

^^^ "the majority" will work without any assistance.

> > but some may need an assistance via (dynamic) properties or similar mechanisms.

> Even if we wanted to add dynamic properties, there is currently no proper
> device node to attach them to.

Isn't that's node created dynamically as well and attached to the PCI bus?

> > > It's just that for this new M.2 E-key connector, there aren't separate
> > > nodes for each interface. And the system doesn't associate the device
> > > node with the device, because it's no longer a child node of the
> > > controller or hierarchy, but connected over the OF graph.
> > >
> > > Moving over to the E-key connector representation seems like one step
> > > forward and one step backward in descriptive ability. We gain proper
> > > power sequencing, but lose generic properties.
> >
> > The "key" is property of the connector. Hence if you have an idea what can be
> > common for ALL "key":s, that's probably can be abstracted. Note, I'm not
> > familiar with the connector framework in the Linux kernel, perhaps it's already
> > that kind of abstraction.
> 
> I'm not arguing for a even more generic "M.2" connector. The "key" is
> already described in the compatible. I'm saying we should have some way
> of describing the individual interfaces (PCIe, SDIO, USB, UART, I2S, I2C)
> on the connector so further nodes or properties can be attached to them,
> either with overlays or dynamically within the kernel. Right now the
> are only described as individual ports, but we can't actually tie a
> device to a OF graph port.

Shouldn't it be described as a DT subtree? Sorry, I am not familiar with DT
enough to understand the issue you have.

> But maybe I'm overthinking the representation part. AFAICT for Qualcomm's
> UART-based BT bit part, Mani just had the driver create a device node
> under the UART (by traversing the OF graph to find the UART). If that's
> the desired way then the connector binding should mention it. And that
> works for me. But I think it's messier and also we're missing an
> opportunity to make the M.2 connector a standardized attachment point
> for overlays.

Okay, now it might get clearer to me, but still, I am not an expert.

> Mani, could you also chime in a bit on what you envisioned?

+1, please elaborate to me as well.

> (Added Luca from Bootlin to CC, as I think there are parallels to the
>  "Hotplug of Non-discoverable Hardware" work)
> 
> > > The latter part is solvable, but we likely need child nodes under the
> > > connector for the different interfaces. Properties that make sense for
> > > one type might not make sense for another.
> > >
> > > P.S. We could also just add child device nodes under the controller to
> > > put the generic properties, but that's splitting the description into
> > > multiple parts. Let's not go there if at all possible.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* RE: [BlueZ] monitor: Add decoding for Microsoft defined event
From: bluez.test.bot @ 2026-04-15  9:00 UTC (permalink / raw)
  To: linux-bluetooth, apusaka
In-Reply-To: <20260415073940.739683-1-apusaka@google.com>

[-- Attachment #1: Type: text/plain, Size: 1421 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1081435

---Test result---

Test Summary:
CheckPatch                    PASS      0.48 seconds
GitLint                       PASS      0.29 seconds
BuildEll                      PASS      20.08 seconds
BluezMake                     PASS      641.53 seconds
MakeCheck                     PASS      18.87 seconds
MakeDistcheck                 PASS      241.59 seconds
CheckValgrind                 PASS      287.58 seconds
CheckSmatch                   WARNING   343.47 seconds
bluezmakeextell               PASS      179.33 seconds
IncrementalBuild              PASS      659.52 seconds
ScanBuild                     PASS      999.51 seconds

Details
##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/msft.c: note: in included file:monitor/msft.h:88:44: warning: array of flexible structuresmonitor/packet.c:2002:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:3866:52: warning: array of flexible structuresmonitor/bt.h:3854:40: warning: array of flexible structures


https://github.com/bluez/bluez/pull/2038

---
Regards,
Linux Bluetooth


^ permalink raw reply

* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Chen-Yu Tsai @ 2026-04-15  8:31 UTC (permalink / raw)
  To: Andy Shevchenko, Manivannan Sadhasivam
  Cc: Manivannan Sadhasivam, Rob Herring, Greg Kroah-Hartman,
	Jiri Slaby, Nathan Chancellor, Nicolas Schier, Hans de Goede,
	Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Bartosz Golaszewski,
	linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
	linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
	Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
	Bartosz Golaszewski, Luca Ceresoli
In-Reply-To: <ad4tJN27opdEooA7@ashevche-desk.local>

On Tue, Apr 14, 2026 at 8:03 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Tue, Apr 14, 2026 at 06:29:02PM +0800, Chen-Yu Tsai wrote:
> > On Tue, Apr 14, 2026 at 4:28 PM Andy Shevchenko
> > <andriy.shevchenko@linux.intel.com> wrote:
> > > On Tue, Apr 14, 2026 at 01:03:19PM +0800, Chen-Yu Tsai wrote:
> > > > On Tue, Apr 14, 2026 at 12:08 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > > > On Mon, Apr 13, 2026 at 07:33:12PM +0530, Manivannan Sadhasivam wrote:
> > > > > > On Mon, Apr 13, 2026 at 03:54:59PM +0800, Chen-Yu Tsai wrote:
> > > > > > > On Thu, Mar 26, 2026 at 01:36:28PM +0530, Manivannan Sadhasivam wrote:
>
> ...
>
> > > > > > > - Given that this connector actually represents two devices, how do I
> > > > > > >   say I want the BT part to be a wakeup source, but not the WiFi part?
> > > > > > >   Does wakeup-source even work at this point?
> > > > > >
> > > > > > You can't use the DT property since the devices are not described in DT
> > > > > > statically. But you can still use the per-device 'wakeup' sysfs knob to enable
> > > > > > wakeup.
> > > >
> > > > I see. I think not being able to specify generic properties for the devices
> > > > on the connector is going to be a bit problematic.
> > >
> > > This is nature of the open-connectors, especially on the busses that are
> > > hotpluggable, like PCIe. We never know what is connected there _ahead_.
> >
> > I believe what you mean by "hotpluggable" is "user replaceable".
>
> From the OS perspective it's the same. From platform perspective
> there is a difference, granted.

Yes. I just wanted to clarify.

> > > In other words you can't describe in DT something that may not exist.
> >
> > But this is actually doable with the PCIe slot representation. The
> > properties are put in the device node for the slot. If no card is
> > actually inserted in the slot, then no device is created, and the
> > device node is left as not associated with anything.
>
> But you need to list all devices in the world if you want to support this

Why would I need to? The PCIe slot representation just describes a
PCIe bridge. Granted this might not be entirely correct, but it's
what we currently have.

And even then, there are properties like memory-region or wakeup-source
that are generic and aren't tied to specific devices.

> somehow. Yes, probably many of them (or majority) will be enumerated as is,
> but some may need an assistance via (dynamic) properties or similar mechanisms.

Even if we wanted to add dynamic properties, there is currently no proper
device node to attach them to.

> > It's just that for this new M.2 E-key connector, there aren't separate
> > nodes for each interface. And the system doesn't associate the device
> > node with the device, because it's no longer a child node of the
> > controller or hierarchy, but connected over the OF graph.
> >
> > Moving over to the E-key connector representation seems like one step
> > forward and one step backward in descriptive ability. We gain proper
> > power sequencing, but lose generic properties.
>
> The "key" is property of the connector. Hence if you have an idea what can be
> common for ALL "key":s, that's probably can be abstracted. Note, I'm not
> familiar with the connector framework in the Linux kernel, perhaps it's already
> that kind of abstraction.

I'm not arguing for a even more generic "M.2" connector. The "key" is
already described in the compatible. I'm saying we should have some way
of describing the individual interfaces (PCIe, SDIO, USB, UART, I2S, I2C)
on the connector so further nodes or properties can be attached to them,
either with overlays or dynamically within the kernel. Right now the
are only described as individual ports, but we can't actually tie a
device to a OF graph port.

But maybe I'm overthinking the representation part. AFAICT for Qualcomm's
UART-based BT bit part, Mani just had the driver create a device node
under the UART (by traversing the OF graph to find the UART). If that's
the desired way then the connector binding should mention it. And that
works for me. But I think it's messier and also we're missing an
opportunity to make the M.2 connector a standardized attachment point
for overlays.

Mani, could you also chime in a bit on what you envisioned?

(Added Luca from Bootlin to CC, as I think there are parallels to the
 "Hotplug of Non-discoverable Hardware" work)


Thanks
ChenYu


> > The latter part is solvable, but we likely need child nodes under the
> > connector for the different interfaces. Properties that make sense for
> > one type might not make sense for another.
> >
> > P.S. We could also just add child device nodes under the controller to
> > put the generic properties, but that's splitting the description into
> > multiple parts. Let's not go there if at all possible.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>

^ permalink raw reply

* [bluez/bluez] f10e74: monitor: Add decoding for Microsoft defined event
From: apusaka @ 2026-04-15  8:03 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1081435
  Home:   https://github.com/bluez/bluez
  Commit: f10e7485e0f18571e9f12c05328bb75341e805e4
      https://github.com/bluez/bluez/commit/f10e7485e0f18571e9f12c05328bb75341e805e4
  Author: Archie Pusaka <apusaka@chromium.org>
  Date:   2026-04-15 (Wed, 15 Apr 2026)

  Changed paths:
    M monitor/msft.c
    M monitor/msft.h
    M monitor/packet.c

  Log Message:
  -----------
  monitor: Add decoding for Microsoft defined event

This adds decoders to MSFT LE monitor device event



To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [PATCH BlueZ] monitor: Add decoding for Microsoft defined event
From: Archie Pusaka @ 2026-04-15  7:36 UTC (permalink / raw)
  To: linux-bluetooth, Luiz Augusto von Dentz; +Cc: CrosBT Upstreaming, Archie Pusaka

From: Archie Pusaka <apusaka@chromium.org>

This adds decoders to MSFT LE monitor device event
---

 monitor/msft.c   | 78 +++++++++++++++++++++++++++++++++++++++++++++++-
 monitor/msft.h   |  1 +
 monitor/packet.c | 44 ++++++++++++++++++++++-----
 3 files changed, 115 insertions(+), 8 deletions(-)

diff --git a/monitor/msft.c b/monitor/msft.c
index 054f34006..d41f10d68 100644
--- a/monitor/msft.c
+++ b/monitor/msft.c
@@ -41,6 +41,8 @@
 
 #define COLOR_COMMAND		COLOR_BLUE
 #define COLOR_COMMAND_UNKNOWN	COLOR_WHITE_BG
+#define COLOR_EVENT		COLOR_MAGENTA
+#define COLOR_EVENT_UNKNOWN	COLOR_WHITE_BG
 
 static void null_cmd(const void *data, uint16_t size)
 {
@@ -299,10 +301,72 @@ const struct vendor_ocf *msft_vendor_ocf(void)
 	return &vendor_ocf_entry;
 }
 
+static void monitor_device_evt(const void *data, uint16_t size)
+{
+	const struct msft_evt_monitor_device *evt = data;
+	const char *str_state;
+
+	packet_print_addr(NULL, evt->addr, evt->addr_type);
+	print_field("Monitor handle: %u", evt->handle);
+
+	switch (evt->state) {
+	case 0x00:
+		str_state = "Stop monitoring";
+		break;
+	case 0x01:
+		str_state = "Start monitoring";
+		break;
+	default:
+		str_state = "Reserved";
+		break;
+	}
+
+	print_field("State: %s (0x%2.2x)", str_state, evt->state);
+}
+
+static const struct {
+	uint8_t code;
+	const char *str;
+	func_t evt_func;
+} evt_table[] = {
+	{ 0x01, "RSSI Event" },
+	{ 0x02, "LE Monitor Device Event", monitor_device_evt },
+	{ }
+};
+
 static void msft_evt(struct timeval *tv, uint16_t index,
 			const void *data, uint8_t size)
 {
-	packet_hexdump(data, size);
+	uint8_t code = get_u8(data);
+	const char *code_color, *code_str = NULL;
+	func_t code_func = NULL;
+	int i;
+
+	for (i = 0; evt_table[i].str; i++) {
+		if (evt_table[i].code == code) {
+			code_str = evt_table[i].str;
+			code_func = evt_table[i].evt_func;
+			break;
+		}
+	}
+
+	if (code_str) {
+		if (code_func)
+			code_color = COLOR_EVENT;
+		else
+			code_color = COLOR_EVENT_UNKNOWN;
+	} else {
+		code_color = COLOR_EVENT_UNKNOWN;
+		code_str = "Unknown";
+	}
+
+	print_indent(6, code_color, "", code_str, COLOR_OFF,
+						" (0x%2.2x)", code);
+
+	if (code_func)
+		code_func(data, size);
+	else
+		packet_hexdump(data + 1, size - 1);
 }
 
 static const struct vendor_evt vendor_evt_entry = {
@@ -313,3 +377,15 @@ const struct vendor_evt *msft_vendor_evt(void)
 {
 	return &vendor_evt_entry;
 }
+
+bool msft_event_code_valid(uint8_t code)
+{
+	int i;
+
+	for (i = 0; evt_table[i].str; i++) {
+		if (evt_table[i].code == code)
+			return true;
+	}
+
+	return false;
+}
diff --git a/monitor/msft.h b/monitor/msft.h
index e6e3019be..ff6c28011 100644
--- a/monitor/msft.h
+++ b/monitor/msft.h
@@ -187,3 +187,4 @@ struct vendor_evt;
 
 const struct vendor_ocf *msft_vendor_ocf(void);
 const struct vendor_evt *msft_vendor_evt(void);
+bool msft_event_code_valid(uint8_t code);
diff --git a/monitor/packet.c b/monitor/packet.c
index ff0b1cac2..02f69dfca 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -450,8 +450,10 @@ void packet_set_fallback_manufacturer(uint16_t manufacturer)
 
 void packet_set_msft_evt_prefix(const uint8_t *prefix, uint8_t len)
 {
-	if (index_current < MAX_INDEX && len < 8)
+	if (index_current < MAX_INDEX && len < 8) {
 		memcpy(index_list[index_current].msft_evt_prefix, prefix, len);
+		index_list[index_current].msft_evt_len = len;
+	}
 }
 
 static void cred_pid(struct ucred *cred, char *str, size_t len)
@@ -4359,7 +4361,8 @@ static int addr2str(const uint8_t *addr, char *str)
 			addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
 }
 
-static int get_msft_opcode(uint16_t manufacturer) {
+static int get_msft_opcode(uint16_t manufacturer)
+{
 	switch (manufacturer) {
 	case COMPANY_ID_INTEL:
 		return 0xFC1E;
@@ -4374,7 +4377,23 @@ static int get_msft_opcode(uint16_t manufacturer) {
 	default:
 		return BT_HCI_CMD_NOP;
 	}
+}
+
+static bool msft_event_prefix_match(const void *data, int size)
+{
+	const void *prefix = index_list[index_current].msft_evt_prefix;
+	int prefix_len = index_list[index_current].msft_evt_len;
+
+	/*
+	 * MSFT event has one byte of event code following the MSFT prefix.
+	 * We need to check the event code is valid, as it's possible for
+	 * a vendor to use the same MSFT prefix but for other events.
+	 */
+	if (size >= prefix_len + 1 && !memcmp(prefix, data, prefix_len))
+		return msft_event_code_valid(
+				((const uint8_t *) data)[prefix_len]);
 
+	return false;
 }
 
 void packet_monitor(struct timeval *tv, struct ucred *cred,
@@ -10925,11 +10944,16 @@ static const struct vendor_ocf *current_vendor_ocf(uint16_t ocf)
 }
 
 static const struct vendor_evt *current_vendor_evt(const void *data,
-							int *consumed_size)
+					uint8_t size, int *consumed_size)
 {
 	uint16_t manufacturer;
 	uint8_t evt = *((const uint8_t *) data);
 
+	if (msft_event_prefix_match(data, size)) {
+		*consumed_size = index_list[index_current].msft_evt_len;
+		return msft_vendor_evt();
+	}
+
 	/* A regular vendor event consumes 1 byte. */
 	*consumed_size = 1;
 
@@ -10948,10 +10972,13 @@ static const struct vendor_evt *current_vendor_evt(const void *data,
 	return NULL;
 }
 
-static const char *current_vendor_evt_str(void)
+static const char *current_vendor_evt_str(const void *data, uint8_t size)
 {
 	uint16_t manufacturer;
 
+	if (msft_event_prefix_match(data, size))
+		return "Microsoft";
+
 	if (index_current < MAX_INDEX)
 		manufacturer = index_list[index_current].manufacturer;
 	else
@@ -13547,17 +13574,20 @@ static void vendor_evt(struct timeval *tv, uint16_t index,
 	struct subevent_data vendor_data;
 	char vendor_str[150];
 	int consumed_size;
-	const struct vendor_evt *vnd = current_vendor_evt(data, &consumed_size);
+	const struct vendor_evt *vnd = current_vendor_evt(data, size,
+								&consumed_size);
 
 	if (vnd) {
-		const char *str = current_vendor_evt_str();
+		const char *str = current_vendor_evt_str(data, size);
 
 		if (str) {
 			snprintf(vendor_str, sizeof(vendor_str),
 						"%s %s", str, vnd->str);
 			vendor_data.str = vendor_str;
-		} else
+		} else {
 			vendor_data.str = vnd->str;
+		}
+
 		vendor_data.subevent = vnd->evt;
 		vendor_data.func = vnd->evt_func;
 		vendor_data.size = vnd->evt_size;
-- 
2.54.0.rc0.605.g598a273b03-goog


^ permalink raw reply related

* Re: [PATCH v1] Bluetooth: btintel_pcie:Support Product level reset.
From: Thorsten Leemhuis @ 2026-04-15  7:05 UTC (permalink / raw)
  To: Chandrashekar Devegowda
  Cc: oe-kbuild-all, kernel test robot, linux-bluetooth, linux-pci,
	bhelgaas, ravishankar.srivatsa, chethan.tumkur.narayan,
	Luiz Augusto von Dentz, Linux Next Mailing List,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <202603310744.5WIVh3e6-lkp@intel.com>

On 3/31/26 01:39, kernel test robot wrote:
> Hi Chandrashekar,
> 
> kernel test robot noticed the following build errors:

FWIW, a newer version of this patch hit -next yesterday and caused a
similar build error for me, but only on ppc64le (on Fedora, using the
rawhide config):

"""
> drivers/bluetooth/btintel_pcie.c: In function ‘btintel_pcie_acpi_reset_method’:
> drivers/bluetooth/btintel_pcie.c:2309:14: error: implicit declaration of function ‘acpi_has_method’; did you mean ‘acpi_has_watchdog’? [-Wimplicit-function-declaration]
>  2309 |         if (!acpi_has_method(handle, "_PRR")) {
>       |              ^~~~~~~~~~~~~~~
>       |              acpi_has_watchdog
> make[4]: *** [scripts/Makefile.build:289: drivers/bluetooth/btintel_pcie.o] Error 1
> make[4]: *** Waiting for unfinished jobs....
> make[3]: *** [scripts/Makefile.build:548: drivers/bluetooth] Error 2
> make[3]: *** Waiting for unfinished jobs....
> make[2]: *** [scripts/Makefile.build:548: drivers] Error 2
> make[1]: *** [/builddir/build/BUILD/kernel-7.1.0-build/kernel-next-20260414/linux-7.1.0-0.0.next.20260414.462.vanilla.fc45.ppc64le/Makefile:2147: .] Error 2
> make: *** [Makefile:256: __sub-make] Error 2
> + exit 1
""""

Full log:
https://download.copr.fedorainfracloud.org/results/@kernel-vanilla/next/fedora-rawhide-ppc64le/10323070-next-next-all/builder-live.log.gz

Ciao, Thorsten


> [auto build test ERROR on bluetooth-next/master]
> [also build test ERROR on next-20260327]
> [cannot apply to bluetooth/master linus/master v7.0-rc6]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Chandrashekar-Devegowda/Bluetooth-btintel_pcie-Support-Product-level-reset/20260330-190125
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
> patch link:    https://lore.kernel.org/r/20260330063842.1121545-1-chandrashekar.devegowda%40intel.com
> patch subject: [PATCH v1] Bluetooth: btintel_pcie:Support Product level reset.
> config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20260331/202603310744.5WIVh3e6-lkp@intel.com/config)
> compiler: alpha-linux-gcc (GCC) 15.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260331/202603310744.5WIVh3e6-lkp@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202603310744.5WIVh3e6-lkp@intel.com/
> 
> All errors (new ones prefixed by >>):
> 
>    drivers/bluetooth/btintel_pcie.c: In function 'btintel_pcie_acpi_reset_method':
>>> drivers/bluetooth/btintel_pcie.c:2307:14: error: implicit declaration of function 'acpi_has_method'; did you mean 'acpi_has_watchdog'? [-Wimplicit-function-declaration]
>     2307 |         if (!acpi_has_method(handle, "_PRR")) {
>          |              ^~~~~~~~~~~~~~~
>          |              acpi_has_watchdog
> 
> 
> vim +2307 drivers/bluetooth/btintel_pcie.c
> 
>   2280	
>   2281	static int btintel_pcie_acpi_reset_method(struct btintel_pcie_data *data)
>   2282	{
>   2283		union acpi_object *obj, argv4;
>   2284		acpi_handle handle;
>   2285		int ret;
>   2286		struct pldr_mode {
>   2287			u16	cmd_type;
>   2288			u16	cmd_payload;
>   2289		} __packed;
>   2290	
>   2291		/* set 1 for _PRR mode
>   2292		 * Product Reset (PLDR Abort flow)
>   2293		 */
>   2294		static const struct pldr_mode mode = {
>   2295			.cmd_type = 1,
>   2296			.cmd_payload = BTINTEL_PCIE_DSM_PLDR_MODE_EN_PROD_RESET |
>   2297				       BTINTEL_PCIE_DSM_PLDR_MODE_EN_WIFI_FLR,
>   2298		};
>   2299		struct hci_dev *hdev = data->hdev;
>   2300	
>   2301		handle = ACPI_HANDLE(GET_HCIDEV_DEV(data->hdev));
>   2302		if (!handle) {
>   2303			bt_dev_dbg(data->hdev, "No support for bluetooth device in ACPI firmware");
>   2304			return -EACCES;
>   2305		}
>   2306	
>> 2307		if (!acpi_has_method(handle, "_PRR")) {
>   2308			bt_dev_dbg(data->hdev, "No support for _PRR ACPI method, falling back to FLR");
>   2309			btintel_pcie_reset(data->hdev);
>   2310			return -ENODEV;
>   2311		}
>   2312	
>   2313		argv4.buffer.type = ACPI_TYPE_BUFFER;
>   2314		argv4.buffer.length = sizeof(mode);
>   2315		argv4.buffer.pointer = (void *)&mode;
>   2316	
>   2317		obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0,
>   2318					BTINTEL_PCIE_DSM_DYNAMIC_PLDR, &argv4);
>   2319		if (!obj) {
>   2320			bt_dev_err(data->hdev, "Failed to call dsm to set reset method");
>   2321			return -EIO;
>   2322		}
>   2323		ACPI_FREE(obj);
>   2324	
>   2325		pci_dev_lock(data->pdev);
>   2326		pci_save_state(data->pdev);
>   2327		ret = btintel_acpi_reset_method(hdev);
>   2328		if (ret)
>   2329			bt_dev_err(data->hdev, "ACPI _PRR reset failed (%d),PLDR incomplete",
>   2330				   ret);
>   2331		pci_restore_state(data->pdev);
>   2332		pci_dev_unlock(data->pdev);
>   2333		return ret;
>   2334	}
>   2335	
> 


^ permalink raw reply

* [Bug 221346] Bluetooth: btintel_pcie (8086:e476) may hang in shutdown path (synchronize_irq) during reboot stress test
From: bugzilla-daemon @ 2026-04-15  6:16 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221346-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221346

--- Comment #6 from Zhang Zhigang (zhangzhigang1996@gmail.com) ---
I would like to provide more details about my system setup, as it may be
relevant to the shutdown hang issue.

My filesystem layout is non-standard. In addition to `/boot` and `/`, I have a
separate `/data` partition, and several key directories are bind-mounted from
it.

Current block layout:

* nvme0n1p1 → /boot
* nvme0n1p3 → / (root filesystem)
* nvme0n1p5 → /data

The `/data` partition contains subdirectories which are bind-mounted to
standard system paths:

* /data/home      → /home
* /data/var       → /var
* /data/local     → /usr/local
* /data/opt       → /opt

Example mount output:

```
aa [ ~ ]$ lsblk 
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
nvme0n1     259:0    0 476.9G  0 disk 
├─nvme0n1p1 259:1    0   511M  0 part /boot
├─nvme0n1p2 259:2    0  14.6G  0 part 
├─nvme0n1p3 259:3    0  19.5G  0 part /
├─nvme0n1p4 259:4    0  19.5G  0 part 
└─nvme0n1p5 259:5    0 422.7G  0 part /var
                                      /usr/local
                                      /opt
                                      /home
                                      /data
aa [ ~ ]$ mount | grep nvme
/dev/nvme0n1p3 on / type ext4 (rw,relatime,seclabel)
/dev/nvme0n1p1 on /boot type vfat
(rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro)
/dev/nvme0n1p5 on /data type ext4 (rw,relatime,seclabel)
/dev/nvme0n1p5 on /home type ext4 (rw,relatime,seclabel)
/dev/nvme0n1p5 on /opt type ext4 (rw,relatime,seclabel)
/dev/nvme0n1p5 on /usr/local type ext4 (rw,relatime,seclabel)
/dev/nvme0n1p5 on /var type ext4 (rw,relatime,seclabel)

aa [ ~ ]$ ls -a /data/
.  ..  home  local  opt  .swap.img  var
```



These mounts are managed via systemd `.mount` units .
Key characteristics:

1. `/data` is mounted early with `DefaultDependencies=no`
2. Other mount points (`/home`, `/var`, `/usr/local`, `/opt`) are bind mounts
with:

   * `BindsTo=data.mount`
   * `After=data.mount`
3. All mount units explicitly include:

   * `Conflicts=umount.target shutdown.target`
4. Additional ordering is enforced via:
   `/etc/systemd/system/sysinit.target.d/data-mount.conf`

This setup ensures that `/data` is mounted before other system paths and that
dependent mounts are tied to it.

```
cat >/etc/systemd/system/data.mount <<"EOF"
[Unit]
Description=Data Partition
DefaultDependencies=no

After=systemd-udevd.service
Before=systemd-journald.service sysinit.target local-fs.target

OnFailure=emergency.target
Conflicts=umount.target shutdown.target

[Mount]
What=/dev/disk/by-uuid/UUID
Where=/data
Type=ext4
Options=defaults

[Install]
WantedBy=local-fs.target
EOF

cat >/etc/systemd/system/home.mount <<"EOF"
[Unit]
Description=Bind /data/home → /home
DefaultDependencies=no

BindsTo=data.mount
After=data.mount
Before=sysinit.target local-fs.target
Conflicts=umount.target shutdown.target

[Mount]
What=/data/home
Where=/home
Type=none
Options=bind

[Install]
WantedBy=local-fs.target
EOF

cat >/etc/systemd/system/var.mount <<"EOF"
[Unit]
Description=Bind /data/var → /var
DefaultDependencies=no

BindsTo=data.mount
After=data.mount
Before=systemd-journald.service sysinit.target local-fs.target
Conflicts=umount.target shutdown.target

[Mount]
What=/data/var
Where=/var
Type=none
Options=bind

[Install]
WantedBy=local-fs.target
EOF

cat >/etc/systemd/system/usr-local.mount <<"EOF"
[Unit]
Description=Bind /data/local → /usr/local
DefaultDependencies=no

BindsTo=data.mount
After=data.mount
Before=sysinit.target local-fs.target
Conflicts=umount.target shutdown.target

[Mount]
What=/data/local
Where=/usr/local
Type=none
Options=bind

[Install]
WantedBy=local-fs.target
EOF

cat >/etc/systemd/system/opt.mount <<"EOF"
[Unit]
Description=Bind /data/opt → /opt
DefaultDependencies=no

BindsTo=data.mount
After=data.mount
Before=sysinit.target local-fs.target
Conflicts=umount.target shutdown.target

[Mount]
What=/data/opt
Where=/opt
Type=none
Options=bind

[Install]
WantedBy=local-fs.target
EOF

mkdir -pv /etc/systemd/system/sysinit.target.d
cat >/etc/systemd/system/sysinit.target.d/data-mount.conf <<"EOF"
[Unit]
Requires=data.mount var.mount home.mount usr-local.mount opt.mount
After=data.mount var.mount home.mount usr-local.mount opt.mount
EOF
```

However, I suspect this layout might be contributing to the shutdown hang,
especially during the late unmount phase. Since multiple critical directories
(e.g. `/var`) are bind-mounted from a single filesystem, there may be ordering
or dependency issues when systemd tries to unmount them.

The issue still occurs intermittently and typically at a late stage of
shutdown, where logging is limited.

If this filesystem layout or mount configuration could potentially trigger such
behavior, I would appreciate any guidance on how to further debug or simplify
the setup for testing.

Thank you.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 221346] Bluetooth: btintel_pcie (8086:e476) may hang in shutdown path (synchronize_irq) during reboot stress test
From: bugzilla-daemon @ 2026-04-15  5:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221346-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221346

--- Comment #5 from Zhang Zhigang (zhangzhigang1996@gmail.com) ---
Created attachment 309872
  --> https://bugzilla.kernel.org/attachment.cgi?id=309872&action=edit
The machine used

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 221346] Bluetooth: btintel_pcie (8086:e476) may hang in shutdown path (synchronize_irq) during reboot stress test
From: bugzilla-daemon @ 2026-04-15  5:53 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-221346-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=221346

--- Comment #4 from Zhang Zhigang (zhangzhigang1996@gmail.com) ---
Hi,

Thanks for your follow-up.

I’d like to clarify that I did not close the issue because the problem was
resolved. The issue still exists, but I temporarily marked it as invalid due to
lack of sufficient debugging data from my side.

Here is the current status:

1. The system still occasionally hangs during shutdown.
2. The hang happens at a relatively late stage of the shutdown process.
3. It is difficult to capture logs, since at that point most logging services
are already stopped. Currently, I can only observe the last messages on the
screen.

I also attempted to rule out Bluetooth-related causes by blacklisting the
relevant kernel modules:

* btintel_pcie
* btintel
* btusb
* bluetooth

However, even with Bluetooth disabled, the shutdown hang still occurs. This
suggests that the issue is likely unrelated to Bluetooth.

Given that my understanding of the kernel is still relatively limited, I would
greatly appreciate any suggestions on more effective debugging methods,
especially for capturing logs during late shutdown stages.

Thank you for your time and support.
Additional information:

* The issue is intermittent and not easily reproducible.
* I am willing to test patches or enable additional debug options if needed.
* Please let me know if enabling specific kernel parameters (e.g. debug,
earlyprintk, pstore, etc.) would help capture more useful logs.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* RE: [v3] Bluetooth: L2CAP: Fix ECRED reconf rsp channel teardown race
From: bluez.test.bot @ 2026-04-15  4:51 UTC (permalink / raw)
  To: linux-bluetooth, feng
In-Reply-To: <20260415032318.78543-1-feng@innora.ai>

[-- Attachment #1: Type: text/plain, Size: 6563 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1081350

---Test result---

Test Summary:
CheckPatch                    PASS      0.71 seconds
GitLint                       PASS      0.32 seconds
SubjectPrefix                 PASS      0.12 seconds
BuildKernel                   PASS      27.15 seconds
CheckAllWarning               PASS      30.67 seconds
CheckSparse                   PASS      29.20 seconds
BuildKernel32                 PASS      26.75 seconds
TestRunnerSetup               PASS      584.93 seconds
TestRunner_l2cap-tester       PASS      28.57 seconds
TestRunner_iso-tester         PASS      48.75 seconds
TestRunner_bnep-tester        PASS      6.60 seconds
TestRunner_mgmt-tester        FAIL      118.42 seconds
TestRunner_rfcomm-tester      PASS      9.76 seconds
TestRunner_sco-tester         FAIL      14.54 seconds
TestRunner_ioctl-tester       PASS      10.51 seconds
TestRunner_mesh-tester        FAIL      12.27 seconds
TestRunner_smp-tester         PASS      8.87 seconds
TestRunner_userchan-tester    PASS      6.92 seconds
TestRunner_6lowpan-tester     FAIL      8.69 seconds
IncrementalBuild              PASS      25.55 seconds

Details
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.117 seconds
##############################
Test: TestRunner_sco-tester - FAIL
Desc: Run sco-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-g6e16399eb91c #1 Not tainted
------------------------------------------------------
kworker/u5:2/117 is trying to acquire lock:
ffff888001946240 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}, at: sco_connect_cfm+0x358/0x8d0

but task is already holding lock:
ffff8880025fb220 (&conn->lock){+.+.}-{3:3}, at: sco_connect_cfm+0x22d/0x8d0

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&conn->lock){+.+.}-{3:3}:
       lock_acquire+0xf7/0x2c0
       _raw_spin_lock+0x2a/0x40
       sco_sock_connect+0x4d7/0x1280
       __sys_connect+0x1a3/0x260
       __x64_sys_connect+0x6e/0xb0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #0 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}:
       check_prev_add+0xe9/0xc70
       __lock_acquire+0x1457/0x1df0
       lock_acquire+0xf7/0x2c0
       lock_sock_nested+0x36/0xd0
       sco_connect_cfm+0x358/0x8d0
       hci_sync_conn_complete_evt+0x3d3/0x8e0
       hci_event_packet+0x74f/0xb10
       hci_rx_work+0x398/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

other info that might help us debug this:

...
BUG: sleeping function called from invalid context at net/core/sock.c:3782
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 117, name: kworker/u5:2
preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
INFO: lockdep is turned off.
CPU: 0 UID: 0 PID: 117 Comm: kworker/u5:2 Not tainted 7.0.0-rc2-g6e16399eb91c #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Workqueue: hci0 hci_rx_work
Call Trace:
 <TASK>
 dump_stack_lvl+0x49/0x60
 __might_resched+0x2ea/0x500
 lock_sock_nested+0x47/0xd0
 ? sco_connect_cfm+0x358/0x8d0
 sco_connect_cfm+0x358/0x8d0
 ? hci_debugfs_create_conn+0x190/0x210
 ? __pfx_sco_connect_cfm+0x10/0x10
 hci_sync_conn_complete_evt+0x3d3/0x8e0
 hci_event_packet+0x74f/0xb10
 ? __pfx_hci_sync_conn_complete_evt+0x10/0x10
 ? __pfx_hci_event_packet+0x10/0x10
 ? mark_held_locks+0x49/0x80
 ? lockdep_hardirqs_on_prepare+0xd4/0x180
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 hci_rx_work+0x398/0xd00
 process_scheduled_works+0xb16/0x1ac0
 ? __pfx_process_scheduled_works+0x10/0x10
 ? lock_acquire+0xf7/0x2c0
 ? lock_is_held_type+0x9b/0x110
 ? __pfx_hci_rx_work+0x10/0x10
 worker_thread+0x4ff/0xba0
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 ? __pfx_worker_thread+0x10/0x10
 kthread+0x368/0x490
 ? _raw_spin_unlock_irq+0x23/0x40
 ? __pfx_kthread+0x10/0x10
 ret_from_fork+0x498/0x7e0
 ? __pfx_ret_from_fork+0x10/0x10
 ? __switch_to+0x9e4/0xe50
 ? __switch_to_asm+0x32/0x60
...
Total: 30, Passed: 30 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.558 seconds
Mesh - Send cancel - 2                               Timed out    1.995 seconds
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-g6e16399eb91c #1 Not tainted
------------------------------------------------------
kworker/0:1/11 is trying to acquire lock:
ffff888002760940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x75/0x180

but task is already holding lock:
ffffffffa624d720 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #4 (rtnl_mutex){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       lowpan_register_netdev+0x11/0x30
       chan_ready_cb+0x836/0xd00
       l2cap_recv_frame+0x698d/0x89b0
       l2cap_recv_acldata+0x790/0xdf0
       hci_rx_work+0x500/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

-> #3 (&chan->lock#3/1){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       l2cap_chan_connect+0x74e/0x1980
       lowpan_control_write+0x523/0x660
       full_proxy_write+0x10b/0x190
       vfs_write+0x1c0/0xf60
       ksys_write+0xf1/0x1d0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #2 (&conn->lock){+.+.}-{4:4}:
...
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0


https://github.com/bluez/bluetooth-next/pull/85

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [PATCH v3] Bluetooth: L2CAP: Fix ECRED reconf rsp channel teardown race
From: Feng Ning @ 2026-04-15  3:23 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: linux-kernel, marcel, johan.hedberg, luiz.dentz, Feng Ning,
	stable
In-Reply-To: <20260415004725.39215-1-feng@innora.ai>

The ECRED reconfiguration response tears down all channels that were part
of a failed procedure. The handler iterates over conn->chan_l while
holding conn->lock but l2cap_chan_hold() is called without first checking
whether the reference count has already reached zero. A concurrent path
(socket close, timer expiry) may drop the final reference outside
conn->lock, causing a use-after-free when the response is handled.

Replace l2cap_chan_hold() with l2cap_chan_hold_unless_zero() so that
channels whose reference count has already been dropped are skipped
safely. Add lockdep_assert_held(&conn->lock) to document the calling
requirements.

Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Cc: stable@vger.kernel.org # v5.7+
Signed-off-by: Feng Ning <feng@innora.ai>
---
 net/bluetooth/l2cap_core.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 77dec104a..191c38b4d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5466,6 +5466,8 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
 
 	BT_DBG("result 0x%4.4x", result);
 
+	lockdep_assert_held(&conn->lock);
+
 	if (!result)
 		return 0;
 
@@ -5473,7 +5475,9 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
 		if (chan->ident != cmd->ident)
 			continue;
 
-		l2cap_chan_hold(chan);
+		if (!l2cap_chan_hold_unless_zero(chan))
+			continue;
+
 		l2cap_chan_lock(chan);
 
 		l2cap_chan_del(chan, ECONNRESET);
-- 
2.49.0



^ permalink raw reply related

* Re: [PATCH v4] Bluetooth: hci_qca: Convert timeout from jiffies to ms
From: Shuai Zhang @ 2026-04-15  2:49 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: Bartosz Golaszewski, Marcel Holtmann, linux-arm-msm,
	linux-bluetooth, linux-kernel, cheng.jiang, quic_chezhou,
	wei.deng, jinwang.li, mengshi.wu, stable, Paul Menzel
In-Reply-To: <f6a9419d-5e63-4c36-a7e9-aab6ac798703@oss.qualcomm.com>

Hi Luiz

On 4/10/2026 4:56 PM, Shuai Zhang wrote:
> Hi Luiz
>
> On 3/28/2026 1:53 AM, Luiz Augusto von Dentz wrote:
>> Hi Shuai,
>>
>> On Fri, Mar 27, 2026 at 4:30 AM Shuai Zhang
>> <shuai.zhang@oss.qualcomm.com> wrote:
>>> From: Shuai Zhang <quic_shuaz@quicinc.com>
>>>
>>> Since the timer uses jiffies as its unit rather than ms, the timeout 
>>> value
>>> must be converted from ms to jiffies when configuring the timer. 
>>> Otherwise,
>>> the intended 8s timeout is incorrectly set to approximately 33s.
>>>
>>> Cc: stable@vger.kernel.org
>>> Fixes: d841502c79e3 ("Bluetooth: hci_qca: Collect controller memory 
>>> dump during SSR")
>>> Signed-off-by: Shuai Zhang <quic_shuaz@quicinc.com>
>>> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
>>> Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>>> ---
>>> Changes v4:
>>> - add review-by signoff
>>> - Link to v3
>>> https://lore.kernel.org/all/20251107033924.3707495-1-quic_shuaz@quicinc.com/
>>>
>>> Changes v3:
>>> - add Fixes tag
>>> - Link to v2
>>> https://lore.kernel.org/all/20251106140103.1406081-1-quic_shuaz@quicinc.com/
>>>
>>> Changes v2:
>>> - Split timeout conversion into a separate patch.
>>> - Clarified commit messages and added test case description.
>>> - Link to v1
>>> https://lore.kernel.org/all/20251104112601.2670019-1-quic_shuaz@quicinc.com/
>>> ---
>>>
>>>   drivers/bluetooth/hci_qca.c | 2 +-
>>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
>>> index 228a754a9..d66af13ab 100644
>>> --- a/drivers/bluetooth/hci_qca.c
>>> +++ b/drivers/bluetooth/hci_qca.c
>>> @@ -1607,7 +1607,7 @@ static void 
>>> qca_wait_for_dump_collection(struct hci_dev *hdev)
>>>          struct qca_data *qca = hu->priv;
>>>
>>>          wait_on_bit_timeout(&qca->flags, QCA_MEMDUMP_COLLECTION,
>>> -                           TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT_MS);
>>> +                           TASK_UNINTERRUPTIBLE, 
>>> msecs_to_jiffies(MEMDUMP_TIMEOUT_MS));
>>>
>>>          clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
>>>   }
>>> -- 
>>> 2.34.1
>>>
>> https://sashiko.dev/#/patchset/20260327082941.1396521-1-shuai.zhang%40oss.qualcomm.com 
>>
>>
>> Comments seem valid to me.
>
>
> https://lore.kernel.org/all/20260410085202.4128000-1-shuai.zhang@oss.qualcomm.com/ 
>
>
> The wait will be woken up once the coredump collection is completed.
>
>

Please let me know if any additional information is needed.


> Thanks,
> Shuai
>

^ permalink raw reply

* RE: [v2] Bluetooth: L2CAP: Fix ECRED reconf rsp channel teardown race
From: bluez.test.bot @ 2026-04-15  1:12 UTC (permalink / raw)
  To: linux-bluetooth, feng
In-Reply-To: <20260415004725.39215-1-feng@innora.ai>

[-- Attachment #1: Type: text/plain, Size: 555 bytes --]

This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: net/bluetooth/l2cap_core.c:5473
error: net/bluetooth/l2cap_core.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth


^ permalink raw reply

* [PATCH v2] Bluetooth: L2CAP: Fix ECRED reconf rsp channel teardown race
From: Feng Ning @ 2026-04-15  0:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: linux-kernel, marcel, johan.hedberg, feng, stable
In-Reply-To: <20260413044730.86315-1-feng@innora.ai>

From: feng <feng@innora.ai>

The ECRED reconfiguration response tears down all channels that were part
of a failed procedure. The handler iterates over conn->chan_l while
holding conn->lock but it called l2cap_chan_del() without taking an extra
reference and without the per-channel lock. Other paths (socket close,
timer expiry, etc.) may drop the final reference outside conn->lock,
causing a use-after-free when the response is handled.

Take a temporary reference with l2cap_chan_hold_unless_zero(), perform
the deletion under the channel lock, and drop the reference afterwards.
Add lockdep_assert_held(&conn->lock) to document the calling requirements.

Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Cc: stable@vger.kernel.org # v5.7+
Signed-off-by: Feng Ning <feng@innora.ai>
---
 net/bluetooth/l2cap_core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 95c65fece..08d2045ab 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5466,6 +5466,8 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
 
 	BT_DBG("result 0x%4.4x", result);
 
+	lockdep_assert_held(&conn->lock);
+
 	if (!result)
 		return 0;
 
@@ -5473,7 +5475,13 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
 		if (chan->ident != cmd->ident)
 			continue;
 
+		if (!l2cap_chan_hold_unless_zero(chan))
+			continue;
+
+		l2cap_chan_lock(chan);
 		l2cap_chan_del(chan, ECONNRESET);
+		l2cap_chan_unlock(chan);
+		l2cap_chan_put(chan);
 	}
 
 	return 0;
-- 
2.49.0



^ permalink raw reply related

* RE: [v5] Bluetooth: l2cap: defer conn param update to avoid conn->lock/hdev->lock inversion
From: bluez.test.bot @ 2026-04-14 22:35 UTC (permalink / raw)
  To: linux-bluetooth, mikhail.v.gavrilov
In-Reply-To: <20260414215237.17791-1-mikhail.v.gavrilov@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 7343 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1081298

---Test result---

Test Summary:
CheckPatch                    PASS      1.24 seconds
GitLint                       FAIL      0.32 seconds
SubjectPrefix                 PASS      0.12 seconds
BuildKernel                   PASS      25.79 seconds
CheckAllWarning               PASS      28.07 seconds
CheckSparse                   PASS      27.00 seconds
BuildKernel32                 PASS      24.89 seconds
TestRunnerSetup               PASS      558.96 seconds
TestRunner_l2cap-tester       PASS      27.81 seconds
TestRunner_iso-tester         PASS      38.85 seconds
TestRunner_bnep-tester        PASS      6.38 seconds
TestRunner_mgmt-tester        FAIL      111.87 seconds
TestRunner_rfcomm-tester      PASS      9.45 seconds
TestRunner_sco-tester         FAIL      13.93 seconds
TestRunner_ioctl-tester       PASS      10.22 seconds
TestRunner_mesh-tester        FAIL      11.57 seconds
TestRunner_smp-tester         PASS      8.58 seconds
TestRunner_userchan-tester    PASS      6.77 seconds
TestRunner_6lowpan-tester     FAIL      8.43 seconds
IncrementalBuild              PASS      23.97 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v5] Bluetooth: l2cap: defer conn param update to avoid conn->lock/hdev->lock inversion

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
1: T1 Title exceeds max length (87>80): "[v5] Bluetooth: l2cap: defer conn param update to avoid conn->lock/hdev->lock inversion"
47: B2 Line has trailing whitespace: " "
53: B2 Line has trailing whitespace: " "
60: B2 Line has trailing whitespace: " "
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.103 seconds
##############################
Test: TestRunner_sco-tester - FAIL
Desc: Run sco-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-g2d47e6ef8f27 #1 Not tainted
------------------------------------------------------
kworker/u5:2/117 is trying to acquire lock:
ffff8880023a3240 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}, at: sco_connect_cfm+0x358/0x8d0

but task is already holding lock:
ffff888002141c20 (&conn->lock){+.+.}-{3:3}, at: sco_connect_cfm+0x22d/0x8d0

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&conn->lock){+.+.}-{3:3}:
       lock_acquire+0xf7/0x2c0
       _raw_spin_lock+0x2a/0x40
       sco_sock_connect+0x4d7/0x1280
       __sys_connect+0x1a3/0x260
       __x64_sys_connect+0x6e/0xb0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #0 (sk_lock-AF_BLUETOOTH-BTPROTO_SCO){+.+.}-{0:0}:
       check_prev_add+0xe9/0xc70
       __lock_acquire+0x1457/0x1df0
       lock_acquire+0xf7/0x2c0
       lock_sock_nested+0x36/0xd0
       sco_connect_cfm+0x358/0x8d0
       hci_sync_conn_complete_evt+0x3d3/0x8e0
       hci_event_packet+0x74f/0xb10
       hci_rx_work+0x398/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

other info that might help us debug this:

...
BUG: sleeping function called from invalid context at net/core/sock.c:3782
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 117, name: kworker/u5:2
preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
INFO: lockdep is turned off.
CPU: 0 UID: 0 PID: 117 Comm: kworker/u5:2 Not tainted 7.0.0-rc2-g2d47e6ef8f27 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Workqueue: hci0 hci_rx_work
Call Trace:
 <TASK>
 dump_stack_lvl+0x49/0x60
 __might_resched+0x2ea/0x500
 lock_sock_nested+0x47/0xd0
 ? sco_connect_cfm+0x358/0x8d0
 sco_connect_cfm+0x358/0x8d0
 ? hci_debugfs_create_conn+0x190/0x210
 ? __pfx_sco_connect_cfm+0x10/0x10
 hci_sync_conn_complete_evt+0x3d3/0x8e0
 hci_event_packet+0x74f/0xb10
 ? __pfx_hci_sync_conn_complete_evt+0x10/0x10
 ? __pfx_hci_event_packet+0x10/0x10
 ? mark_held_locks+0x49/0x80
 ? lockdep_hardirqs_on_prepare+0xd4/0x180
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 hci_rx_work+0x398/0xd00
 process_scheduled_works+0xb16/0x1ac0
 ? __pfx_process_scheduled_works+0x10/0x10
 ? lock_acquire+0xf7/0x2c0
 ? lock_is_held_type+0x9b/0x110
 ? __pfx_hci_rx_work+0x10/0x10
 worker_thread+0x4ff/0xba0
 ? _raw_spin_unlock_irqrestore+0x2c/0x50
 ? __pfx_worker_thread+0x10/0x10
 kthread+0x368/0x490
 ? _raw_spin_unlock_irq+0x23/0x40
 ? __pfx_kthread+0x10/0x10
 ret_from_fork+0x498/0x7e0
 ? __pfx_ret_from_fork+0x10/0x10
 ? __switch_to+0x9e4/0xe50
 ? __switch_to_asm+0x32/0x60
...
Total: 30, Passed: 30 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.092 seconds
Mesh - Send cancel - 2                               Timed out    1.992 seconds
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
WARNING: possible circular locking dependency detected
7.0.0-rc2-g2d47e6ef8f27 #1 Not tainted
------------------------------------------------------
kworker/0:1/11 is trying to acquire lock:
ffff888002482940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x75/0x180

but task is already holding lock:
ffffffffba44d720 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #4 (rtnl_mutex){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       lowpan_register_netdev+0x11/0x30
       chan_ready_cb+0x836/0xd00
       l2cap_recv_frame+0x6a07/0x88a0
       l2cap_recv_acldata+0x790/0xdf0
       hci_rx_work+0x500/0xd00
       process_scheduled_works+0xb16/0x1ac0
       worker_thread+0x4ff/0xba0
       kthread+0x368/0x490
       ret_from_fork+0x498/0x7e0
       ret_from_fork_asm+0x19/0x30

-> #3 (&chan->lock#3/1){+.+.}-{4:4}:
       lock_acquire+0xf7/0x2c0
       __mutex_lock+0x16b/0x1fc0
       l2cap_chan_connect+0x74e/0x1980
       lowpan_control_write+0x523/0x660
       full_proxy_write+0x10b/0x190
       vfs_write+0x1c0/0xf60
       ksys_write+0xf1/0x1d0
       do_syscall_64+0xa0/0x570
       entry_SYSCALL_64_after_hwframe+0x74/0x7c

-> #2 (&conn->lock){+.+.}-{4:4}:
...
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0


https://github.com/bluez/bluetooth-next/pull/84

---
Regards,
Linux Bluetooth


^ permalink raw reply

* RE: [BlueZ,v2] bass: Fix crashing on BT_BASS_MOD_SRC
From: bluez.test.bot @ 2026-04-14 22:02 UTC (permalink / raw)
  To: linux-bluetooth, luiz.dentz
In-Reply-To: <20260414190459.161947-1-luiz.dentz@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3456 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1081265

---Test result---

Test Summary:
CheckPatch                    FAIL      0.46 seconds
GitLint                       FAIL      0.32 seconds
BuildEll                      PASS      19.97 seconds
BluezMake                     PASS      610.01 seconds
MakeCheck                     PASS      18.73 seconds
MakeDistcheck                 PASS      235.34 seconds
CheckValgrind                 PASS      274.55 seconds
CheckSmatch                   PASS      322.65 seconds
bluezmakeextell               PASS      164.79 seconds
IncrementalBuild              PASS      610.16 seconds
ScanBuild                     PASS      924.97 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,v2] bass: Fix crashing on BT_BASS_MOD_SRC
WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#101: 
 #0  queue_find (queue=<optimized out>, function=function@entry=0x58b8761109c0 <setup_match_bis>, match_data=match_data@entry=0x3) at src/shared/queue.c:230

/github/workspace/src/patch/14524659.patch total: 0 errors, 1 warnings, 40 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/patch/14524659.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,v2] bass: Fix crashing on BT_BASS_MOD_SRC

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
9: B1 Line exceeds max length (156>80): " #0  queue_find (queue=<optimized out>, function=function@entry=0x58b8761109c0 <setup_match_bis>, match_data=match_data@entry=0x3) at src/shared/queue.c:230"
10: B1 Line exceeds max length (125>80): " #1  0x000058b8761127fb in bass_update_bis_sync (bcast_src=<optimized out>, dg=<optimized out>) at profiles/audio/bass.c:1824"
11: B1 Line exceeds max length (126>80): " #2  handle_mod_src_req (data=<optimized out>, params=<optimized out>, bcast_src=0x58b894661be0) at profiles/audio/bass.c:1862"
12: B1 Line exceeds max length (143>80): " #3  cp_handler (bcast_src=0x58b894661be0, op=<optimized out>, params=<optimized out>, user_data=<optimized out>) at profiles/audio/bass.c:1910"
13: B1 Line exceeds max length (182>80): " #4  0x000058b8761bc978 in bass_handle_mod_src_op (bass=<optimized out>, attrib=<optimized out>, opcode=<optimized out>, id=<optimized out>, iov=<optimized out>, att=<optimized out>)"


https://github.com/bluez/bluez/pull/2036

---
Regards,
Linux Bluetooth


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox