public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ] monitor: Add decoding for Microsoft defined event
@ 2026-04-15  7:36 Archie Pusaka
  2026-04-15  9:00 ` [BlueZ] " bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
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	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-15  9:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-15  7:36 [PATCH BlueZ] monitor: Add decoding for Microsoft defined event Archie Pusaka
2026-04-15  9:00 ` [BlueZ] " bluez.test.bot

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