Linux bluetooth development
 help / color / mirror / Atom feed
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v1 2/2] monitor: Add decoding support for HIDS 1.1 flags and attributes
Date: Thu, 30 Apr 2026 15:51:14 -0400	[thread overview]
Message-ID: <20260430195114.608794-2-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260430195114.608794-1-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds support for HIDS 1.1 SCI flags and attributes:

> LE-ACL: Handle 2048 flags 0x02 dlen 9
      ATT: Read Response (0x0b) len 4
        Handle: 0x0021 Type: HID Information (0x2a4a)
        Value[4]:
        11 01 00 0f                                      ....
            bcdHID: 0x0111
            bCountryCode: 0x00
            Flags: 0x0f
            RemoteWake (0x01)
            NormallyConnectable (0x02)
            SCI Supported (0x04)
            SCI Low Power Mode Supported (0x08)
< LE-ACL: Handle 2048 flags 0x00 dlen 7
      ATT: Read Request (0x0a) len 2
        Handle: 0x003d Type: HID SCI Information (0x2c3a)
> LE-ACL: Handle 2048 flags 0x02 dlen 19
      ATT: Read Response (0x0b) len 14
        Handle: 0x003d Type: HID SCI Information (0x2c3a)
        Value[14]:
        08 02 0a 00 14 00 0a 00 08 00 08 00 08 00        ..............
            Minimum Supported Connection Interval: 1.000 ms (0x08)
            Number of Supported Subgroups: 2
              Minimum Connection Interval[0]: 1.250 ms (0x000a)
              Maximum Connection Interval[0]: 2.500 ms (0x0014)
              Connection Interval Stride[0]: 1.250 ms (0x000a)
              Minimum Connection Interval[1]: 1.000 ms (0x0008)
              Maximum Connection Interval[1]: 1.000 ms (0x0008)
              Connection Interval Stride[1]: 1.000 ms (0x0008)
< LE-ACL: Handle 2048 flags 0x00 dlen 7
      ATT: Read Request (0x0a) len 2
        Handle: 0x003f Type: HID SCI Mode (0x2c39)
> LE-ACL: Handle 2048 flags 0x02 dlen 6
      ATT: Read Response (0x0b) len 1
        Handle: 0x003f Type: HID SCI Mode (0x2c39)
        Value[1]:
        00                                               .
            Mode: None (0x00)
---
 monitor/att.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++--
 src/main.conf |   2 +-
 2 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index e8e0d499a826..03d46634fe17 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -4522,8 +4522,10 @@ static void ras_data_overwritten_notify(const struct l2cap_frame *frame)
 					ras_data_overwritten_notify)
 
 static const struct bitfield_data hog_info_flags[] = {
-	{  0, "RemoteWake (0x01)"		},
-	{  1, "NormallyConnectable (0x02)"	},
+	{  0, "RemoteWake (0x01)"			},
+	{  1, "NormallyConnectable (0x02)"		},
+	{  2, "SCI Supported (0x04)"			},
+	{  3, "SCI Low Power Mode Supported (0x08)"	},
 	{ }
 };
 
@@ -4598,9 +4600,116 @@ done:
 		print_hex_field("  Data", frame->data, frame->size);
 }
 
+static void print_sci_mode(const struct l2cap_frame *frame)
+{
+	uint8_t mode;
+
+	if (!l2cap_frame_get_u8((void *)frame, &mode)) {
+		print_text(COLOR_ERROR, "    Mode: invalid size");
+		goto done;
+	}
+
+	switch (mode) {
+	case 0x00:
+		print_field("    Mode: None (0x00)");
+		break;
+	case 0x02:
+		print_field("    Mode:  SCI Default Mode (0x02)");
+		break;
+	case 0x03:
+		print_field("    Mode:  SCI Fast Mode (0x03)");
+		break;
+	case 0x04:
+		print_field("    Mode:  SCI Low Power Mode (0x04)");
+		break;
+	case 0x05:
+		print_field("    Mode:  SCI Full Range Mode (0x04)");
+		break;
+	default:
+		print_field("    Mode:  Reserved (0x%2.2x)", mode);
+		break;
+	}
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
+static void hog_sci_mode_read(const struct l2cap_frame *frame)
+{
+	print_sci_mode(frame);
+}
+
+static void hog_sci_mode_notify(const struct l2cap_frame *frame)
+{
+	print_sci_mode(frame);
+}
+
+static void hog_sci_info_read(const struct l2cap_frame *frame)
+{
+	uint8_t min_conn_interval;
+	uint8_t num_grps;
+	uint8_t i;
+
+	if (!l2cap_frame_get_u8((void *)frame, &min_conn_interval)) {
+		print_text(COLOR_ERROR, "    Minimum Supported Connection "
+				"Interval: invalid size");
+		goto done;
+	}
+
+	print_field("    Minimum Supported Connection Interval: %.3f ms "
+		    "(0x%2.2x) ", min_conn_interval * 0.125, min_conn_interval);
+
+	if (!l2cap_frame_get_u8((void *)frame, &num_grps)) {
+		print_text(COLOR_ERROR, "    Number of Supported Subgroups: "
+				"invalid size");
+		goto done;
+	}
+
+	print_field("    Number of Supported Subgroups: %d", num_grps);
+
+	for (i = 0; i < num_grps; i++) {
+		uint16_t min, max, stride;
+
+		if (!l2cap_frame_get_le16((void *)frame, &min)) {
+			print_text(COLOR_ERROR, "    group[%u]: Minimum "
+					"Connection Interval: invalid size",
+					i);
+			goto done;
+		}
+
+		if (!l2cap_frame_get_le16((void *)frame, &max)) {
+			print_text(COLOR_ERROR, "    group[%u]: Maximum "
+					"Connection Interval: invalid size",
+					i);
+			goto done;
+		}
+
+		if (!l2cap_frame_get_le16((void *)frame, &stride)) {
+			print_text(COLOR_ERROR, "    group[%u]: Connection "
+					"Interval Stride: invalid size",
+					i);
+			goto done;
+		}
+
+		print_field("      Minimum Connection Interval[%u]: %.3f ms "
+				"(0x%4.4x)", i, min * 0.125, min);
+		print_field("      Maximum Connection Interval[%u]: %.3f ms "
+				"(0x%4.4x)", i, max * 0.125, max);
+		print_field("      Connection Interval Stride[%u]: %.3f ms "
+				"(0x%4.4x)", i, stride * 0.125, stride);
+	}
+
+done:
+	if (frame->size)
+		print_hex_field("  Data", frame->data, frame->size);
+}
+
 #define HIDS \
 	GATT_HANDLER(0x2a4a, hog_info_read, NULL, NULL), \
-	GATT_HANDLER(0x2a4c, NULL, hog_cp_write, NULL)
+	GATT_HANDLER(0x2a4c, NULL, hog_cp_write, NULL), \
+	GATT_HANDLER(0x2c39, hog_sci_mode_read, NULL, hog_sci_mode_notify), \
+	GATT_HANDLER(0x2c3a, hog_sci_info_read, NULL, NULL)
 
 #define GATT_HANDLER(_uuid, _read, _write, _notify) \
 { \
diff --git a/src/main.conf b/src/main.conf
index 5846ef92d98d..39584e225c38 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -289,7 +289,7 @@
 # Export claimed services by plugins
 # Possible values: no, read-only, read-write
 # Default: read-only
-#ExportClaimedServices = read-only
+ExportClaimedServices = read-write
 
 # Security level:
 # Sets security level of ATT channel, setting security anything other than
-- 
2.53.0


  reply	other threads:[~2026-04-30 19:51 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-30 19:51 [PATCH BlueZ v1 1/2] shared/util: Add decoding support for HIDS 1.1 UUIDs Luiz Augusto von Dentz
2026-04-30 19:51 ` Luiz Augusto von Dentz [this message]
2026-04-30 20:54 ` [BlueZ,v1,1/2] " bluez.test.bot
2026-05-01 14:10 ` [PATCH BlueZ v1 1/2] " patchwork-bot+bluetooth

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260430195114.608794-2-luiz.dentz@gmail.com \
    --to=luiz.dentz@gmail.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

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

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