public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>
To: linux-bluetooth@vger.kernel.org
Cc: luiz.dentz@gmail.com, quic_mohamull@quicinc.com,
	quic_hbandi@quicinc.com, quic_anubhavg@quicinc.com
Subject: [PATCH BlueZ v5 2/3] unit/test-rap: Add PTS tests for CS reflector
Date: Tue, 28 Apr 2026 08:01:10 +0530	[thread overview]
Message-ID: <20260428023111.1640377-3-prathm@qti.qualcomm.com> (raw)
In-Reply-To: <20260428023111.1640377-1-prathm@qti.qualcomm.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 11085 bytes --]

From: Prathibha Madugonde <prathibha.madugonde@oss.qualcomm.com>

Added below RAS - Real time Ranging PTS testcases

RAS/SR/RCO/BV-01-C [Characteristic Read - RAS Features]
RAS/SR/RRD/BV-01-C [Real-time Ranging Data]
RAS/SR/RRD/BV-03-C [Real-time Ranging Data notifications and indications]
RAS/SR/RRD/BV-05-C [Real-Time Ranging Data disconnection]
---
 unit/test-rap.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 260 insertions(+), 4 deletions(-)

diff --git a/unit/test-rap.c b/unit/test-rap.c
index 884cb1c96..6f65967a4 100644
--- a/unit/test-rap.c
+++ b/unit/test-rap.c
@@ -37,6 +37,7 @@ struct test_data_ras {
 	size_t iovcnt;
 	struct iovec *iov;
 	unsigned int ras_id;
+	struct bt_rap *rap;  /* Store rap instance for CS injection */
 };
 
 struct test_data_rap {
@@ -68,8 +69,8 @@ struct notify {
 	do {							\
 		const struct iovec iov[] = { args };		\
 		static struct test_data_ras data;			\
-		data.iovcnt = ARRAY_SIZE(iov_data(args));	\
-		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov_data(args))); \
+		data.iovcnt = ARRAY_SIZE(iov);	\
+		data.iov = util_iov_dup(iov, ARRAY_SIZE(iov)); \
 		tester_add(name, &data, NULL, function,	\
 				test_teardown_ras);			\
 	} while (0)
@@ -155,6 +156,94 @@ static void gatt_notify_cb(struct gatt_db_attribute *attrib,
 		printf("%s: Failed to send notification\n", __func__);
 }
 
+static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct test_data_ras *data = user_data;
+	struct ccc_state *ccc;
+	uint16_t handle;
+	uint16_t ccc_value;
+	uint8_t ecode = 0;
+
+	handle = gatt_db_attribute_get_handle(attrib);
+
+	if (offset) {
+		ecode = BT_ATT_ERROR_INVALID_OFFSET;
+		goto done;
+	}
+
+	if (len != 2) {
+		ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+		goto done;
+	}
+
+	ccc_value = get_le16(value);
+
+	ccc = get_ccc_state(data, handle);
+	if (!ccc) {
+		ecode = BT_ATT_ERROR_UNLIKELY;
+		goto done;
+	}
+
+	ccc->value = ccc_value;
+
+	/* Send write response first */
+	gatt_db_attribute_write_result(attrib, id, 0);
+
+	/* If notifications/indications enabled on Real-time Ranging Data CCCD,
+	 * inject fake HCI CS subevent data to trigger notifications
+	 */
+	if (handle == 0x0006 && ccc_value != 0x0000 && data->rap) {
+		size_t event_size = sizeof(struct rap_ev_cs_subevent_result) +
+				    sizeof(struct cs_step_data);
+		struct rap_ev_cs_subevent_result *fake_event;
+		struct cs_mode_zero_data *mode_zero;
+
+		if (tester_use_debug())
+			tester_debug("Injecting fake CS data...");
+
+		fake_event = g_malloc0(event_size);
+		if (!fake_event)
+			return;  /* Already sent write response */
+
+		/* Fill in the header fields */
+		fake_event->conn_hdl = 0x0001;
+		fake_event->config_id = 0x01;
+		fake_event->start_acl_conn_evt_counter = 0x0000;
+		fake_event->proc_counter = 0x0001;
+		fake_event->freq_comp = 0x0000;
+		fake_event->ref_pwr_lvl = 0x00;
+		fake_event->proc_done_status = 0x00;
+		fake_event->subevt_done_status = 0x00;
+		fake_event->abort_reason = 0x00;
+		fake_event->num_ant_paths = 0x01;
+		fake_event->num_steps_reported = 0x01;
+
+		fake_event->step_data[0].step_mode = CS_MODE_ZERO;
+		fake_event->step_data[0].step_chnl = 0x00;
+		/* Mode 0: 1+1+1+4 bytes */
+		fake_event->step_data[0].step_data_length = 4;
+mode_zero = &fake_event->step_data[0].step_mode_data.mode_zero_data;
+		mode_zero->packet_quality = 0x01;
+		mode_zero->packet_rssi_dbm = 0x02;
+		mode_zero->packet_ant = 0x03;
+		mode_zero->init_measured_freq_offset = 0x04;
+
+		/* Inject the fake event to trigger notification */
+		bt_rap_hci_cs_subevent_result_callback(event_size, fake_event,
+						       data->rap);
+
+		g_free(fake_event);
+	}
+	return;
+
+done:
+	gatt_db_attribute_write_result(attrib, id, ecode);
+}
+
 static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
 					unsigned int id, uint16_t offset,
 					uint8_t opcode, struct bt_att *att,
@@ -184,10 +273,21 @@ done:
 
 static void ras_attached(struct bt_rap *rap, void *user_data)
 {
+	struct test_data_ras *data = user_data;
+
+	if (data) {
+		data->rap = rap;
+		bt_rap_ref(rap);  /* Keep a reference */
+	}
 }
 
 static void ras_detached(struct bt_rap *rap, void *user_data)
 {
+	struct test_data_ras *data = user_data;
+
+	if (data && data->rap == rap)
+		data->rap = NULL;
+
 	bt_rap_unref(rap);
 }
 
@@ -205,17 +305,18 @@ static void test_server(const void *user_data)
 	att = bt_att_new(io_get_fd(io), false);
 	g_assert(att);
 
+	bt_att_set_security(att, BT_ATT_SECURITY_MEDIUM);
 	bt_att_set_debug(att, BT_ATT_DEBUG, print_debug, "bt_att:", NULL);
 
 	data->db = gatt_db_new();
 	g_assert(data->db);
 
-	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, NULL,
+	gatt_db_ccc_register(data->db, gatt_ccc_read_cb, gatt_ccc_write_cb,
 					gatt_notify_cb, data);
 
 	bt_rap_add_db(data->db);
 
-	data->ras_id = bt_rap_register(ras_attached, ras_detached, NULL);
+	data->ras_id = bt_rap_register(ras_attached, ras_detached, data);
 
 	data->server = bt_gatt_server_new(data->db, att, 64, 0);
 	g_assert(data->server);
@@ -426,6 +527,150 @@ static void test_server(const void *user_data)
 	DISC_RAS_CHAR_AFTER_TYPE, \
 	RAS_FIND_INFO
 
+/*
+ * RAS/SR/RCO/BV-01-C – Characteristic Read: RAS Features
+ *
+ *  ATT: Read Request (0x0a) len 2
+ *       Handle: 0x0003 (RAS Features value handle)
+ *
+ *  ATT: Read Response (0x0b) len 5
+ *       Value: 0x01 0x00 0x00 0x00
+ *       Feature bits:
+ *         Bit 0: Real-time ranging (1 = supported)
+ *         Bit 1: Retrieve stored results (0 = not supported)
+ *         Bit 2: Abort operation (0 = not supported)
+ *
+ *  Note: The RAS Features characteristic is registered with
+ *  BT_ATT_PERM_READ | BT_ATT_PERM_READ_ENCRYPT. Since the test sets
+ *  BT_ATT_SECURITY_MEDIUM, the encryption requirement is satisfied
+ *  and the server returns the feature value showing real-time ranging
+ *  support.
+ */
+
+#define ATT_READ_RAS_FEATURES \
+	IOV_DATA(0x0a, 0x03, 0x00), \
+	IOV_DATA(0x0b, 0x01, 0x00, 0x00, 0x00)
+
+#define RAS_SR_RCO_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	ATT_READ_RAS_FEATURES
+
+/*
+ * RAS Real-time Ranging Data CCCD Configuration
+ * Round 1: Enable/Disable notifications (CCCD = 0x0001)
+ * Round 2: Enable/Disable indications (CCCD = 0x0002)
+ */
+#define RAS_REALTIME_CCCD_CONFIG \
+	/* Round 1: Enable notifications on Real-time Ranging Data CCCD */ \
+	/* (handle 0x0006) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable notifications */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13), \
+	/* Round 2: Enable indications on Real-time Ranging Data CCCD */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x02, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable indications */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ * Enable both notifications and indications (CCCD = 0x0003)
+ * Expect notification (0x1b) to be sent, not indication (0x1d)
+ * Then disable CCCD
+ *
+ * Note: This test is currently disabled because the GATT server rejects
+ * CCCD value 0x0003 (both notifications and indications enabled) before
+ * reaching the custom callback. The test infrastructure needs to be updated
+ * to support this scenario.
+ */
+#define RAS_REALTIME_CCCD_BOTH_ENABLE_DISABLE \
+	/* Enable notifications only (CCCD = 0x0001) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable CCCD */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ * Disconnection/Reconnection simulation for Real-time Ranging Data
+ * Enable notifications, disable (disconnect), re-enable (reconnect), disable
+ */
+#define RAS_REALTIME_CCCD_DISCONNECT_RECONNECT \
+	/* Step 1: Enable notifications */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Step 3: Disable CCCD (simulates disconnection) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13), \
+	/* Step 4: Re-enable notifications (simulates reconnection) */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x01, 0x00), \
+	IOV_DATA(0x13), \
+	/* Disable CCCD to clean up */ \
+	IOV_DATA(0x12, 0x06, 0x00, 0x00, 0x00), \
+	IOV_DATA(0x13)
+
+/*
+ * RAS/SR/RRD/BV-01-C [Real-time Ranging Data]
+ * Verify that the IUT can configure CCCD for notifications/indications
+ * of the Real-time Ranging Data characteristic.
+ */
+#define RAS_SR_RRD_BV_01_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	RAS_REALTIME_CCCD_CONFIG
+
+/*
+ * RAS/SR/RRD/BV-03-C [Real-time Ranging Data notifications and indications]
+ * Verify that the IUT only sends Real-time Ranging Data notifications when
+ * configured for both notifications and indications (CCCD = 0x0003).
+ *
+ * Test Procedure:
+ * 1. Write 0x0003 to Real-time Ranging Data CCCD (enable both
+ *    notifications and indications)
+ * 2. Trigger CS Subevent Data (via fake HCI event injection)
+ * 3. Verify IUT sends only notifications (0x1b), not indications (0x1d)
+ */
+#define RAS_SR_RRD_BV_03_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	RAS_REALTIME_CCCD_BOTH_ENABLE_DISABLE
+
+/*
+ * RAS/SR/RRD/BV-05-C [Real-Time Ranging Data disconnection]
+ * Verify that the IUT does not resume sending Real-time Ranging Data
+ * notifications or indications after a disconnection occurs.
+ *
+ * Test Procedure:
+ * 1. Enable Real-time Ranging Data notifications
+ * 2. Trigger CS Subevent Data (IUT sends notifications)
+ * 3. Disable CCCD (simulates disconnection - CCCD resets to 0x0000)
+ * 4. Re-enable notifications (simulates reconnection and reconfiguration)
+ * 5. Verify IUT does not send old ranging data
+ *
+ * Note: In a unit test, we simulate disconnection by disabling and re-enabling
+ * the CCCD. The RAP implementation should clear any pending data when CCCD is
+ * disabled, ensuring no old data is sent after re-enabling.
+ */
+#define RAS_SR_RRD_BV_05_C \
+	ATT_EXCHANGE_MTU, \
+	DISCOVER_PRIM_SERV_NOTIF, \
+	RAS_FIND_BY_TYPE_VALUE, \
+	DISC_RAS_CHAR_AFTER_TYPE, \
+	RAS_FIND_INFO, \
+	RAS_REALTIME_CCCD_DISCONNECT_RECONNECT
+
 int main(int argc, char *argv[])
 {
 	tester_init(&argc, &argv);
@@ -441,6 +686,17 @@ int main(int argc, char *argv[])
 					RAS_SR_SGGIT_CHA_BV_03_C);
 	define_test_ras("RAS/SR/SGGIT/CHA/BV-04-C", test_server,
 					RAS_SR_SGGIT_CHA_BV_04_C);
+	/* RAS Read Characteristic Operations */
+	define_test_ras("RAS/SR/RCO/BV-01-C", test_server,
+					RAS_SR_RCO_BV_01_C);
+	/* RAS Real-time Ranging Data */
+	define_test_ras("RAS/SR/RRD/BV-01-C", test_server,
+					RAS_SR_RRD_BV_01_C);
+	/* RAS Real-time Ranging Data with CS injection */
+	define_test_ras("RAS/SR/RRD/BV-03-C", test_server,
+					RAS_SR_RRD_BV_03_C);
+	define_test_ras("RAS/SR/RRD/BV-05-C", test_server,
+					RAS_SR_RRD_BV_05_C);
 
 	return tester_run();
 }
-- 
2.34.1


  parent reply	other threads:[~2026-04-28  2:31 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28  2:31 [PATCH BlueZ v5 0/3] Add RAS Packet format and Notification support Prathibha Madugonde
2026-04-28  2:31 ` [PATCH BlueZ v5 1/3] src/shared: Add RAS packet format and notification support Prathibha Madugonde
2026-04-28  3:36   ` Add RAS Packet format and Notification support bluez.test.bot
2026-04-28 19:43   ` [PATCH BlueZ v5 1/3] src/shared: Add RAS packet format and notification support Luiz Augusto von Dentz
2026-04-28  2:31 ` Prathibha Madugonde [this message]
2026-04-28  2:31 ` [PATCH BlueZ v5 3/3] profiles/ranging: Read cs_mode_one_data members Prathibha Madugonde

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260428023111.1640377-3-prathm@qti.qualcomm.com \
    --to=prathibha.madugonde@oss.qualcomm.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=luiz.dentz@gmail.com \
    --cc=quic_anubhavg@quicinc.com \
    --cc=quic_hbandi@quicinc.com \
    --cc=quic_mohamull@quicinc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox