From patchwork Mon Nov 21 23:46:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sathish Narasimman X-Patchwork-Id: 13051722 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E35F2C4332F for ; Mon, 21 Nov 2022 23:46:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231995AbiKUXqm (ORCPT ); Mon, 21 Nov 2022 18:46:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231996AbiKUXqS (ORCPT ); Mon, 21 Nov 2022 18:46:18 -0500 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3849EDAD17 for ; Mon, 21 Nov 2022 15:44:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669074280; x=1700610280; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8VVdGqrvO4rN5n2VC5kIKRX1GL4xfQEfz1FS1yeD86g=; b=L9RGTYlAVv8YxMsFjrbmGvrYPi2mJrEJiCHg21/Z7blC3HxuvSWsb47I qruN7QTphJFt96Z8MKpwARSy7PfCiu5Mdpv0DrtSja03ONeATgpUG0kC7 hyrjT5SNpOqKaudA9vl2w6/XZv9yqPk5hxkQWx7jI6vLJS1dSJPJj9eoe d4uKLJM/IQ8OARGMaJJsTfZj+FDLhmVr2/X6h7c/WY301Yh2ZmopmbhC/ ZkkofByDnUUDdBjk5jclcDURZBDXlUnkrQQn82JHroexBuyXCHKghd/12 e7Sl5lk1uHciAcLJ1VFQIWaWYsHx719AbZpAfaWYG24wSMJlchjf5BYIX g==; X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="377946590" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="377946590" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Nov 2022 15:44:39 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="783633435" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="783633435" Received: from intel-latitude-e5450.iind.intel.com ([10.224.186.32]) by fmsmga001.fm.intel.com with ESMTP; 21 Nov 2022 15:44:38 -0800 From: Sathish Narasimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman Subject: [PATCH BlueZ 1/6] lib/uuid: Add CSIS UUIDs Date: Tue, 22 Nov 2022 05:16:19 +0530 Message-Id: <20221121234624.2961-2-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221121234624.2961-1-sathish.narasimman@intel.com> References: <20221121234624.2961-1-sathish.narasimman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds Coordinated Set Identification Service UUIDs which will be used by Coordinated Set Identification Profile. --- lib/uuid.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/uuid.h b/lib/uuid.h index d5e5665e475c..84ff46cd8f36 100644 --- a/lib/uuid.h +++ b/lib/uuid.h @@ -186,6 +186,13 @@ extern "C" { #define MEDIA_CP_OP_SUPPORTED_CHRC_UUID 0x2ba5 #define MEDIA_CONTENT_CONTROL_ID_CHRC_UUID 0x2bba +/* Coordinated Set Identification Profile(CSIP) */ +#define CSIS_UUID 0x1846 +#define CS_SIRK 0x2B84 +#define CS_SIZE 0x2B85 +#define CS_LOCK 0x2B86 +#define CS_RANK 0x2B87 + typedef struct { enum { BT_UUID_UNSPEC = 0, From patchwork Mon Nov 21 23:46:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sathish Narasimman X-Patchwork-Id: 13051723 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D50CC433FE for ; Mon, 21 Nov 2022 23:46:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231899AbiKUXqn (ORCPT ); Mon, 21 Nov 2022 18:46:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53418 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232000AbiKUXqS (ORCPT ); Mon, 21 Nov 2022 18:46:18 -0500 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EFBBFE06B3 for ; Mon, 21 Nov 2022 15:44:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669074282; x=1700610282; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HTbX2pdiwm9GeCnodnhOGxJF7EuZf5wKjMS0lB961mc=; b=Rut3uECkZpV02SGuyQZDXC8VjMuvz20Ynm027EEz9VAPFpkiEGM2iPL7 PswZH3J2rEc21OosHaeSkkOJYG2ctZRHYuPK+hWEhJYGHSnCeV7SR2Df2 HKBvmkAJXBxSCbwhXdpzGO1hepZE/QFlvA176sra+xJusQT6P3CA/Y1Ny HmxdENPbhOn+d14sxNmewyX8bUirv1XLmJHeq1AAKS/jJ4jcs4RXk9BKv /WXxh8RE7BdTcKkD9xrsw0qSIna2zktFLWuZruMcKuazwsJeE7yqgPzXq CtCGA5iTSd5SIvasY7JhZfqlXZRKkSdAxWX0v44wMASBnYsMEZOK2mTgF Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="377946601" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="377946601" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Nov 2022 15:44:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="783633441" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="783633441" Received: from intel-latitude-e5450.iind.intel.com ([10.224.186.32]) by fmsmga001.fm.intel.com with ESMTP; 21 Nov 2022 15:44:40 -0800 From: Sathish Narasimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman Subject: [PATCH BlueZ 2/6] main.conf: Add CSIP profile configurable options Date: Tue, 22 Nov 2022 05:16:20 +0530 Message-Id: <20221121234624.2961-3-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221121234624.2961-1-sathish.narasimman@intel.com> References: <20221121234624.2961-1-sathish.narasimman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This introduces option to configure main.conf that can be used to configure co-ordinated set identification profile. --- src/btd.h | 9 ++++ src/main.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.conf | 24 +++++++++++ 3 files changed, 146 insertions(+) diff --git a/src/btd.h b/src/btd.h index 63be6d8d4b3f..7c40492e5a1b 100644 --- a/src/btd.h +++ b/src/btd.h @@ -86,6 +86,13 @@ struct btd_defaults { struct btd_le_defaults le; }; +struct btd_csis { + uint8_t sirk_type; + uint8_t sirk_val[16]; + uint8_t cs_size; + uint8_t cs_rank; +}; + struct btd_avdtp_opts { uint8_t session_mode; uint8_t stream_mode; @@ -135,6 +142,8 @@ struct btd_opts { enum jw_repairing_t jw_repairing; struct btd_advmon_opts advmon; + + struct btd_csis csis_defaults; }; extern struct btd_opts btd_opts; diff --git a/src/main.c b/src/main.c index 1d357161feec..d05036a3380a 100644 --- a/src/main.c +++ b/src/main.c @@ -60,6 +60,9 @@ #define DEFAULT_TEMPORARY_TIMEOUT 30 /* 30 seconds */ #define DEFAULT_NAME_REQUEST_RETRY_DELAY 300 /* 5 minutes */ +/*CSIP Profile - Server */ +#define DEFAULT_SIRK "761FAE703ED681F0C50B34155B6434FB" + #define SHUTDOWN_GRACE_SECONDS 10 struct btd_opts btd_opts; @@ -145,6 +148,14 @@ static const char *gatt_options[] = { NULL }; +static const char *csip_options[] = { + "CsisSirkType", + "CsisSirkValue", + "CsisSize", + "CsisRank", + NULL +}; + static const char *avdtp_options[] = { "SessionMode", "StreamMode", @@ -165,11 +176,55 @@ static const struct group_table { { "LE", le_options }, { "Policy", policy_options }, { "GATT", gatt_options }, + { "CSIP", csip_options }, { "AVDTP", avdtp_options }, { "AdvMon", advmon_options }, { } }; +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +static int8_t check_sirk_alpha_numeric(char *str) +{ + int8_t val; + char *s = str; + + if (strlen(s) != 32) /* 32 Bytes of Alpha numeric string */ + return 0; + + for ( ; *s; s++) { + if (((*s >= '0') & (*s <= '9')) + || ((*s >= 'a') && (*s <= 'z')) + || ((*s >= 'A') && (*s <= 'Z'))) { + val = 1; + } else { + val = 0; + break; + } + } + + return val; +} + +static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen) +{ + size_t i, len; + + if (!hexstr) + return 0; + + len = MIN((strlen(hexstr) / 2), buflen); + memset(buf, 0, len); + + for (i = 0; i < len; i++) { + if (sscanf(hexstr + (i * 2), "%02hhX", &buf[i]) != 1) + continue; + } + + return len; +} GKeyFile *btd_get_main_conf(void) { @@ -925,6 +980,58 @@ static void parse_config(GKeyFile *config) btd_opts.gatt_channels = val; } + val = g_key_file_get_integer(config, "CSIP", "CsisSirkType", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + val = MIN(val, 2); + val = MAX(val, 1); + DBG("Csis Type: %u", val); + btd_opts.csis_defaults.cs_size = val; + } + + str = g_key_file_get_string(config, "CSIP", "CsisSirkValue", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + DBG("Csis Sirk: %s", str); + + if (!check_sirk_alpha_numeric(str)) { + DBG("SIRK is not apha numeric Value"); + return; + } + + btd_opts.csis_defaults.sirk_type = 1; /* Plain Text - Type*/ + hex2bin(str, btd_opts.csis_defaults.sirk_val, + sizeof(btd_opts.csis_defaults.sirk_val)); + + g_free(str); + } + + val = g_key_file_get_integer(config, "CSIP", "CsisSize", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + val = MIN(val, 0xFF); + val = MAX(val, 0); + DBG("Csis Size: %u", val); + btd_opts.csis_defaults.cs_size = val; + } + + val = g_key_file_get_integer(config, "CSIP", "CsisRank", &err); + if (err) { + DBG("%s", err->message); + g_clear_error(&err); + } else { + val = MIN(val, 0xFF); + val = MAX(val, 0); + DBG("Csis Rank: %u", val); + btd_opts.csis_defaults.cs_rank = val; + } + str = g_key_file_get_string(config, "AVDTP", "SessionMode", &err); if (err) { DBG("%s", err->message); @@ -999,6 +1106,12 @@ static void init_defaults(void) btd_opts.defaults.br.scan_type = 0xFFFF; btd_opts.defaults.le.enable_advmon_interleave_scan = 0xFF; + btd_opts.csis_defaults.sirk_type = 1; + hex2bin(DEFAULT_SIRK, btd_opts.csis_defaults.sirk_val, + sizeof(btd_opts.csis_defaults.sirk_val)); + btd_opts.csis_defaults.cs_size = 1; + btd_opts.csis_defaults.cs_rank = 1; + if (sscanf(VERSION, "%hhu.%hhu", &major, &minor) != 2) return; diff --git a/src/main.conf b/src/main.conf index 2796f155ebaa..0cc0812f8587 100644 --- a/src/main.conf +++ b/src/main.conf @@ -247,6 +247,30 @@ # Default to 3 #Channels = 3 +[CSIP] +# CSIP - Co-ordinated Set Identification Profile +# SIRK Types which determines the value type for CsisSirkValue +# Possible values: +# 1 - Plain text +# 2 - encrypted +#CsisSirkType = 1 + +# CSIP - Co-ordinated Set Identification Profile +# 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 +# 128 bit value. +# Possible Values: +# 16 byte hexadecimal value +#CsisSirkValue = 861FAE703ED681F0C50B34155B6434FB + +#CSIP - Size +#Total no of sets belongs to this Profile +#CsisSize = 1 + +#CSIP - Rank +#Rank for the device +#CsisRank = 1 + [AVDTP] # AVDTP L2CAP Signalling Channel Mode. # Possible values: From patchwork Mon Nov 21 23:46:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sathish Narasimman X-Patchwork-Id: 13051726 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA046C433FE for ; Mon, 21 Nov 2022 23:47:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231961AbiKUXqs (ORCPT ); Mon, 21 Nov 2022 18:46:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231390AbiKUXqU (ORCPT ); Mon, 21 Nov 2022 18:46:20 -0500 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 101C9DAD07 for ; Mon, 21 Nov 2022 15:44:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669074284; x=1700610284; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=TWZAhRyw50M8c32EpXrPg9WrKim7/TosON66Xnf8B5s=; b=LpPH7pz13oQ5kEBPWRViR447sYaPCSHhBCT4P2DO8Qo5agMrSjjccF8O kke+QZEt8DrXTKJ3iR5BQzeiTk1AthF6/rhn60ylwBkcE2OWTyapvbMW9 D4p8RqguxF1xQ47eZg2A0IR8sLDbaHdutxkpAHklO7Rx+k9VK4AmJ0fva rjuMA/C01v8X8DfPwMJCvB9pSLLbdzOJFOv761W7aSadrfB/8bBZrQVl2 i2NpdWayff/Y1nY1q1IeavNKtuOkZ5lsftTI8u4tgnKQbfrKbtCC7vfjc 9/NAwjZhaSuKYq21gk5lKrHt0CPXpPnfh1tmWWbj+lRUaKE98GYcQX9Oc Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="377946604" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="377946604" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Nov 2022 15:44:43 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="783633454" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="783633454" Received: from intel-latitude-e5450.iind.intel.com ([10.224.186.32]) by fmsmga001.fm.intel.com with ESMTP; 21 Nov 2022 15:44:42 -0800 From: Sathish Narasimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman Subject: [PATCH BlueZ 3/6] shared/csip: Add initial code for handling CSIP Date: Tue, 22 Nov 2022 05:16:21 +0530 Message-Id: <20221121234624.2961-4-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221121234624.2961-1-sathish.narasimman@intel.com> References: <20221121234624.2961-1-sathish.narasimman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds initial code for Coordinated Set Identification Profile. --- Makefile.am | 1 + src/shared/csip.c | 554 ++++++++++++++++++++++++++++++++++++++++++++++ src/shared/csip.h | 44 ++++ 3 files changed, 599 insertions(+) create mode 100644 src/shared/csip.c create mode 100644 src/shared/csip.h diff --git a/Makefile.am b/Makefile.am index aa3a5e053cd8..b546a1803dfd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -233,6 +233,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \ src/shared/bap.h src/shared/bap.c src/shared/ascs.h \ src/shared/mcs.h src/shared/mcp.h src/shared/mcp.c \ src/shared/vcp.c src/shared/vcp.h \ + src/shared/csip.c src/shared/csip.h \ src/shared/lc3.h src/shared/tty.h if READLINE diff --git a/src/shared/csip.c b/src/shared/csip.c new file mode 100644 index 000000000000..98e42d914b16 --- /dev/null +++ b/src/shared/csip.c @@ -0,0 +1,554 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. All rights reserved. + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include + +#include "lib/bluetooth.h" +#include "lib/uuid.h" + +#include "src/shared/queue.h" +#include "src/shared/util.h" +#include "src/shared/timeout.h" +#include "src/shared/att.h" +#include "src/shared/gatt-db.h" +#include "src/shared/gatt-server.h" +#include "src/shared/gatt-client.h" +#include "src/shared/csip.h" +#include "src/btd.h" + +#define DBG(_csip, fmt, arg...) \ + csip_debug(_csip, "%s:%s() " fmt, __FILE__, __func__, ## arg) + +/* SIRK is now hardcoded in the code. This can be moved + * to a configuration file. Since the code is to validate + * the CSIP use case of set member + */ +#define SIRK "761FAE703ED681F0C50B34155B6434FB" +#define CSIS_SIZE 0x02 +#define CSIS_LOCK 0x01 +#define CSIS_RANK 0x01 +#define CSIS_PLAINTEXT 0x01 +#define CSIS_ENC 0x02 + +struct bt_csip_db { + struct gatt_db *db; + struct bt_csis *csis; +}; + +struct csis_sirk { + uint8_t type; + uint8_t val[16]; +} __packed; + +struct bt_csis { + struct bt_csip_db *cdb; + struct csis_sirk *sirk; + uint8_t cs_size; + uint8_t cs_lock; + uint8_t cs_rank; + struct gatt_db_attribute *service; + struct gatt_db_attribute *csirk; + struct gatt_db_attribute *csize; + struct gatt_db_attribute *cslock; + struct gatt_db_attribute *cslock_ccc; + struct gatt_db_attribute *crank; +}; + +struct bt_csip_cb { + unsigned int id; + bt_csip_func_t attached; + bt_csip_func_t detached; + void *user_data; +}; + +struct bt_csip { + int ref_count; + struct bt_csip_db *ldb; + struct bt_csip_db *rdb; + struct bt_gatt_client *client; + struct bt_att *att; + + struct queue *pending; + + bt_csip_debug_func_t debug_func; + bt_csip_destroy_func_t debug_destroy; + void *debug_data; + void *user_data; +}; + +static struct queue *csip_db; +static struct queue *csip_cbs; +static struct queue *sessions; + +static void csip_detached(void *data, void *user_data) +{ + struct bt_csip_cb *cb = data; + struct bt_csip *csip = user_data; + + cb->detached(csip, cb->user_data); +} + +void bt_csip_detach(struct bt_csip *csip) +{ + if (!queue_remove(sessions, csip)) + return; + + bt_gatt_client_unref(csip->client); + csip->client = NULL; + + queue_foreach(csip_cbs, csip_detached, csip); +} + +static void csip_db_free(void *data) +{ + struct bt_csip_db *cdb = data; + + if (!cdb) + return; + + gatt_db_unref(cdb->db); + + free(cdb->csis); + free(cdb); +} +static void csip_free(void *data) +{ + struct bt_csip *csip = data; + + bt_csip_detach(csip); + + csip_db_free(csip->rdb); + + queue_destroy(csip->pending, NULL); + + free(csip); +} + +struct bt_att *bt_csip_get_att(struct bt_csip *csip) +{ + if (!csip) + return NULL; + + if (csip->att) + return csip->att; + + return bt_gatt_client_get_att(csip->client); +} + +struct bt_csip *bt_csip_ref(struct bt_csip *csip) +{ + if (!csip) + return NULL; + + __sync_fetch_and_add(&csip->ref_count, 1); + + return csip; +} + +void bt_csip_unref(struct bt_csip *csip) +{ + if (!csip) + return; + + if (__sync_sub_and_fetch(&csip->ref_count, 1)) + return; + + csip_free(csip); +} + +static void csip_debug(struct bt_csip *csip, const char *format, ...) +{ + va_list ap; + + if (!csip || !format || !csip->debug_func) + return; + + va_start(ap, format); + util_debug_va(csip->debug_func, csip->debug_data, format, ap); + va_end(ap); +} + +static void csis_sirk_read(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + struct bt_csis *csis = user_data; + struct iovec iov; + + iov.iov_base = csis->sirk; + iov.iov_len = sizeof(struct csis_sirk); + + gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base, + iov.iov_len); +} + +static void csis_size_read(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + struct bt_csis *csis = user_data; + struct iovec iov; + + iov.iov_base = &csis->cs_size; + iov.iov_len = sizeof(csis->cs_size); + + gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base, + iov.iov_len); +} + +static void csis_lock_read_cb(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + uint8_t value = CSIS_LOCK; + + gatt_db_attribute_read_result(attrib, id, 0, &value, sizeof(value)); +} + +static void csis_lock_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) +{ + gatt_db_attribute_write_result(attrib, id, 0); +} + +static void csis_rank_read_cb(struct gatt_db_attribute *attrib, + unsigned int id, uint16_t offset, + uint8_t opcode, struct bt_att *att, + void *user_data) +{ + uint8_t value = CSIS_RANK; + + gatt_db_attribute_read_result(attrib, id, 0, &value, sizeof(value)); +} + +static struct bt_csis *csis_new(struct gatt_db *db) +{ + struct bt_csis *csis; + struct csis_sirk *sirk; + bt_uuid_t uuid; + + /* For Common Audio Service*/ + struct gatt_db_attribute *service; + + if (!db) + return NULL; + + csis = new0(struct bt_csis, 1); + sirk = new0(struct csis_sirk, 1); + + sirk->type = btd_opts.csis_defaults.sirk_type; + memcpy(sirk->val, btd_opts.csis_defaults.sirk_val, + sizeof(sirk->val)); + csis->sirk = sirk; + csis->cs_size = btd_opts.csis_defaults.cs_size; + csis->cs_lock = 1; + csis->cs_rank = btd_opts.csis_defaults.cs_rank; + + /* Populate DB with CSIS attributes */ + bt_uuid16_create(&uuid, CSIS_UUID); + csis->service = gatt_db_add_service(db, &uuid, true, 10); + + bt_uuid16_create(&uuid, CS_SIRK); + csis->csirk = gatt_db_service_add_characteristic(csis->service, + &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ, + csis_sirk_read, NULL, + csis); + + bt_uuid16_create(&uuid, CS_SIZE); + csis->csize = gatt_db_service_add_characteristic(csis->service, + &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ, + csis_size_read, NULL, + csis); + + /* Lock */ + bt_uuid16_create(&uuid, CS_LOCK); + csis->cslock = gatt_db_service_add_characteristic(csis->service, &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ | + BT_GATT_CHRC_PROP_WRITE | + BT_GATT_CHRC_PROP_NOTIFY, + csis_lock_read_cb, + csis_lock_write_cb, + csis); + + csis->cslock_ccc = gatt_db_service_add_ccc(csis->service, + BT_ATT_PERM_READ | BT_ATT_PERM_WRITE); + + /* Rank */ + bt_uuid16_create(&uuid, CS_RANK); + csis->crank = gatt_db_service_add_characteristic(csis->service, &uuid, + BT_ATT_PERM_READ, + BT_GATT_CHRC_PROP_READ, + csis_rank_read_cb, + NULL, csis); + + /* Add the CAS service */ + bt_uuid16_create(&uuid, 0x1853); + service = gatt_db_add_service(db, &uuid, true, 2); + gatt_db_service_add_included(service, csis->service); + gatt_db_service_set_active(service, true); + gatt_db_service_add_included(service, csis->service); + + gatt_db_service_set_active(csis->service, true); + + return csis; +} + +static struct bt_csip_db *csip_db_new(struct gatt_db *db) +{ + struct bt_csip_db *cdb; + + if (!db) + return NULL; + + cdb = new0(struct bt_csip_db, 1); + cdb->db = gatt_db_ref(db); + + if (!csip_db) + csip_db = queue_new(); + + cdb->csis = csis_new(db); + cdb->csis->cdb = cdb; + + queue_push_tail(csip_db, cdb); + + return cdb; +} + +bool bt_csip_set_user_data(struct bt_csip *csip, void *user_data) +{ + if (!csip) + return false; + + csip->user_data = user_data; + + return true; +} + +static bool csip_db_match(const void *data, const void *match_data) +{ + const struct bt_csip_db *cdb = data; + const struct gatt_db *db = match_data; + + return (cdb->db == db); +} + +static struct bt_csip_db *csip_get_db(struct gatt_db *db) +{ + struct bt_csip_db *cdb; + + cdb = queue_find(csip_db, csip_db_match, db); + if (cdb) + return cdb; + + return csip_db_new(db); +} + +void bt_csip_add_db(struct gatt_db *db) +{ + csip_db_new(db); +} + +bool bt_csip_set_debug(struct bt_csip *csip, bt_csip_debug_func_t func, + void *user_data, bt_csip_destroy_func_t destroy) +{ + if (!csip) + return false; + + if (csip->debug_destroy) + csip->debug_destroy(csip->debug_data); + + csip->debug_func = func; + csip->debug_destroy = destroy; + csip->debug_data = user_data; + + return true; +} + +unsigned int bt_csip_register(bt_csip_func_t attached, bt_csip_func_t detached, + void *user_data) +{ + struct bt_csip_cb *cb; + static unsigned int id; + + if (!attached && !detached) + return 0; + + if (!csip_cbs) + csip_cbs = queue_new(); + + cb = new0(struct bt_csip_cb, 1); + cb->id = ++id ? id : ++id; + cb->attached = attached; + cb->detached = detached; + cb->user_data = user_data; + + queue_push_tail(csip_cbs, cb); + + return cb->id; +} + +static bool match_id(const void *data, const void *match_data) +{ + const struct bt_csip_cb *cb = data; + unsigned int id = PTR_TO_UINT(match_data); + + return (cb->id == id); +} + +bool bt_csip_unregister(unsigned int id) +{ + struct bt_csip_cb *cb; + + cb = queue_remove_if(csip_cbs, match_id, UINT_TO_PTR(id)); + if (!cb) + return false; + + free(cb); + + return true; +} + +struct bt_csip *bt_csip_new(struct gatt_db *ldb, struct gatt_db *rdb) +{ + struct bt_csip *csip; + struct bt_csip_db *db; + + if (!ldb) + return NULL; + + db = csip_get_db(ldb); + if (!db) + return NULL; + + csip = new0(struct bt_csip, 1); + csip->ldb = db; + csip->pending = queue_new(); + + if (!rdb) + goto done; + + db = new0(struct bt_csip_db, 1); + db->db = gatt_db_ref(rdb); + + csip->rdb = db; + +done: + bt_csip_ref(csip); + + return csip; +} + +static struct bt_csis *csip_get_csis(struct bt_csip *csip) +{ + if (!csip) + return NULL; + + if (csip->rdb->csis) + return csip->rdb->csis; + + csip->rdb->csis = new0(struct bt_csis, 1); + csip->rdb->csis->cdb = csip->rdb; + + return csip->rdb->csis; +} + +static void foreach_csis_char(struct gatt_db_attribute *attr, void *user_data) +{ + struct bt_csip *csip = user_data; + uint16_t value_handle; + bt_uuid_t uuid, uuid_csirk, uuid_csize; + struct bt_csis *csis; + + if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, + NULL, NULL, &uuid)) + return; + + bt_uuid16_create(&uuid_csirk, CS_SIRK); + bt_uuid16_create(&uuid_csize, CS_SIZE); + + if (!bt_uuid_cmp(&uuid, &uuid_csirk)) { + DBG(csip, "CSIS IRK found: handle 0x%04x", value_handle); + + csis = csip_get_csis(csip); + if (!csis || csis->sirk) + return; + + csis->csirk = attr; + return; + } + + if (!bt_uuid_cmp(&uuid, &uuid_csize)) { + DBG(csip, "CSIS SIZE found: handle 0x%04x", value_handle); + + csis = csip_get_csis(csip); + if (!csis) + return; + + csis->csize = attr; + } + +} +static void foreach_csis_service(struct gatt_db_attribute *attr, + void *user_data) +{ + struct bt_csip *csip = user_data; + struct bt_csis *csis = csip_get_csis(csip); + + csis->service = attr; + + gatt_db_service_set_claimed(attr, true); + + gatt_db_service_foreach_char(attr, foreach_csis_char, csip); +} + +bool bt_csip_attach(struct bt_csip *csip, struct bt_gatt_client *client) +{ + bt_uuid_t uuid; + + if (!sessions) + sessions = queue_new(); + + queue_push_tail(sessions, csip); + + if (!client) + return true; + + if (csip->client) + return false; + + csip->client = bt_gatt_client_clone(client); + if (!csip->client) + return false; + + bt_uuid16_create(&uuid, CSIS_UUID); + gatt_db_foreach_service(csip->ldb->db, &uuid, foreach_csis_service, + csip); + + return true; +} + diff --git a/src/shared/csip.h b/src/shared/csip.h new file mode 100644 index 000000000000..bd88ccf3a0b2 --- /dev/null +++ b/src/shared/csip.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. All rights reserved. + * + */ + +#include +#include + +#include "src/shared/io.h" + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +struct bt_csip; + +typedef void (*bt_csip_destroy_func_t)(void *user_data); +typedef void (*bt_csip_debug_func_t)(const char *str, void *user_data); +typedef void (*bt_csip_func_t)(struct bt_csip *csip, void *user_data); +struct bt_csip *bt_csip_ref(struct bt_csip *csip); +void bt_csip_unref(struct bt_csip *csip); + +void bt_csip_add_db(struct gatt_db *db); + +bool bt_csip_attach(struct bt_csip *csip, struct bt_gatt_client *client); +void bt_csip_detach(struct bt_csip *csip); + +bool bt_csip_set_debug(struct bt_csip *csip, bt_csip_debug_func_t func, + void *user_data, bt_csip_destroy_func_t destroy); + +struct bt_att *bt_csip_get_att(struct bt_csip *csip); + +bool bt_csip_set_user_data(struct bt_csip *csip, void *user_data); + +/* Session related function */ +unsigned int bt_csip_register(bt_csip_func_t added, bt_csip_func_t removed, + void *user_data); +bool bt_csip_unregister(unsigned int id); +struct bt_csip *bt_csip_new(struct gatt_db *ldb, struct gatt_db *rdb); + From patchwork Mon Nov 21 23:46:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sathish Narasimman X-Patchwork-Id: 13051729 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 108C1C4332F for ; Mon, 21 Nov 2022 23:47:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231969AbiKUXqv (ORCPT ); Mon, 21 Nov 2022 18:46:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48322 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231947AbiKUXqU (ORCPT ); Mon, 21 Nov 2022 18:46:20 -0500 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 14303CB978 for ; Mon, 21 Nov 2022 15:44:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669074286; x=1700610286; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VauXNm2Sz7lxFMas+Ok2oVuVoItYXUxXvFr3woD7rqA=; b=G2TfAMIT7cYAw6zRE/xG7xinnq8UVaRGm+4AwE1ReP2PPI92z9Fhglrs nFWPqhAUuS26B8ztFsF2DpH7tUsVsEXXAuxzMmgYuwRngCgKSySUYzpQj oE9db6DjivjuK03CydZ5DxxnPm/SYYgS2PShDcvuGe8IN4E5XkNcMhI28 N6RIUbfzj8stgAuYT7J+vWavDSSMOoKQj8Bn2PL1yJctYA+kB1wepjZEI QLSG+IaLOfsjgRSJQk/xaB9SFV4xygdWS6krFXftEilQBj9WxbEuxgaXM qMiCC8VoVSB7SapVzZDK/hjefjClQpJO56qkZ1Xa9a2sCDBUXbkqwsZ2H g==; X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="377946606" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="377946606" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Nov 2022 15:44:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="783633460" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="783633460" Received: from intel-latitude-e5450.iind.intel.com ([10.224.186.32]) by fmsmga001.fm.intel.com with ESMTP; 21 Nov 2022 15:44:44 -0800 From: Sathish Narasimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman Subject: [PATCH BlueZ 4/6] profiles: Add initial code for csip plugin Date: Tue, 22 Nov 2022 05:16:22 +0530 Message-Id: <20221121234624.2961-5-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221121234624.2961-1-sathish.narasimman@intel.com> References: <20221121234624.2961-1-sathish.narasimman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds initial code for csip plugin which handles Coordinated set identification Profile and Coordinated Set Identification Service. --- Makefile.plugins | 5 + configure.ac | 4 + profiles/audio/csip.c | 319 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 profiles/audio/csip.c diff --git a/Makefile.plugins b/Makefile.plugins index 20cac384ef44..0f119e8714b7 100644 --- a/Makefile.plugins +++ b/Makefile.plugins @@ -131,3 +131,8 @@ if VCP builtin_modules += vcp builtin_sources += profiles/audio/vcp.c endif + +if CSIP +builtin_modules += csip +builtin_sources += profiles/audio/csip.c +endif diff --git a/configure.ac b/configure.ac index f9f0faf573ca..17c5f904a5c2 100644 --- a/configure.ac +++ b/configure.ac @@ -207,6 +207,10 @@ AC_ARG_ENABLE(vcp, AS_HELP_STRING([--disable-vcp], [disable VCP profile]), [enable_vcp=${enableval}]) AM_CONDITIONAL(VCP, test "${enable_vcp}" != "no") +AC_ARG_ENABLE(csip, AS_HELP_STRING([--disable-csip], + [disable CSIP profile]), [enable_csip=${enableval}]) +AM_CONDITIONAL(CSIP, test "${enable_csip}" != "no") + AC_ARG_ENABLE(tools, AS_HELP_STRING([--disable-tools], [disable Bluetooth tools]), [enable_tools=${enableval}]) AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no") diff --git a/profiles/audio/csip.c b/profiles/audio/csip.c new file mode 100644 index 000000000000..7b50d5cec88e --- /dev/null +++ b/profiles/audio/csip.c @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2022 Intel Corporation. All rights reserved. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "gdbus/gdbus.h" + +#include "lib/bluetooth.h" +#include "lib/hci.h" +#include "lib/sdp.h" +#include "lib/uuid.h" + +#include "src/dbus-common.h" +#include "src/shared/util.h" +#include "src/shared/att.h" +#include "src/shared/queue.h" +#include "src/shared/gatt-db.h" +#include "src/shared/gatt-client.h" +#include "src/shared/gatt-server.h" +#include "src/shared/csip.h" + +#include "btio/btio.h" +#include "src/plugin.h" +#include "src/adapter.h" +#include "src/gatt-database.h" +#include "src/device.h" +#include "src/profile.h" +#include "src/service.h" +#include "src/log.h" +#include "src/error.h" + +#define CSIS_UUID_STR "00001846-0000-1000-8000-00805f9b34fb" + +struct csip_data { + struct btd_device *device; + struct btd_service *service; + struct bt_csip *csip; +}; + +static struct queue *sessions; + +static void csip_debug(const char *str, void *user_data) +{ + DBG_IDX(0xffff, "%s", str); +} + +static struct csip_data *csip_data_new(struct btd_device *device) +{ + struct csip_data *data; + + data = new0(struct csip_data, 1); + data->device = device; + + return data; +} + +static void csip_data_add(struct csip_data *data) +{ + DBG("data %p", data); + + if (queue_find(sessions, NULL, data)) { + error("data %p already added", data); + return; + } + + bt_csip_set_debug(data->csip, csip_debug, NULL, NULL); + + if (!sessions) + sessions = queue_new(); + + queue_push_tail(sessions, data); + + if (data->service) + btd_service_set_user_data(data->service, data); +} + +static int csip_disconnect(struct btd_service *service) +{ + DBG(""); + return 0; +} + +static bool match_data(const void *data, const void *match_data) +{ + const struct csip_data *vdata = data; + const struct bt_csip *csip = match_data; + + return vdata->csip == csip; +} + +static void csip_data_free(struct csip_data *data) +{ + if (data->service) { + btd_service_set_user_data(data->service, NULL); + bt_csip_set_user_data(data->csip, NULL); + } + + bt_csip_unref(data->csip); + free(data); +} + + +static void csip_data_remove(struct csip_data *data) +{ + DBG("data %p", data); + + if (!queue_remove(sessions, data)) + return; + + csip_data_free(data); + + if (queue_isempty(sessions)) { + queue_destroy(sessions, NULL); + sessions = NULL; + } +} + +static void csip_detached(struct bt_csip *csip, void *user_data) +{ + struct csip_data *data; + + DBG("%p", csip); + + data = queue_find(sessions, match_data, csip); + if (!data) { + error("Unable to find csip session"); + return; + } + + csip_data_remove(data); +} + +static void csip_attached(struct bt_csip *csip, void *user_data) +{ + struct csip_data *data; + struct bt_att *att; + struct btd_device *device; + + DBG("%p", csip); + + data = queue_find(sessions, match_data, csip); + if (data) + return; + + att = bt_csip_get_att(csip); + if (!att) + return; + + device = btd_adapter_find_device_by_fd(bt_att_get_fd(att)); + if (!device) { + error("Unable to find device"); + return; + } + + data = csip_data_new(device); + data->csip = csip; + + csip_data_add(data); + +} + +static int csip_server_probe(struct btd_profile *p, + struct btd_adapter *adapter) +{ + struct btd_gatt_database *database = btd_adapter_get_database(adapter); + + DBG("CSIP path %s", adapter_get_path(adapter)); + + bt_csip_add_db(btd_gatt_database_get_db(database)); + + return 0; +} + +static void csip_server_remove(struct btd_profile *p, + struct btd_adapter *adapter) +{ + DBG("CSIP remove Adapter"); +} + +static int csip_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 csip_data *data = btd_service_get_user_data(service); + char addr[18]; + + ba2str(device_get_address(device), addr); + DBG("%s", addr); + + if (!data) { + error("CSIP service not handled by profile"); + return -EINVAL; + } + + if (!bt_csip_attach(data->csip, client)) { + error("CSIP unable to attach"); + return -EINVAL; + } + + btd_service_connecting_complete(service, 0); + + return 0; +} + +static int csip_probe(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct btd_adapter *adapter = device_get_adapter(device); + struct btd_gatt_database *database = btd_adapter_get_database(adapter); + struct csip_data *data = btd_service_get_user_data(service); + char addr[18]; + + ba2str(device_get_address(device), addr); + DBG("%s", addr); + + /* Ignore, if we were probed for this device already */ + if (data) { + error("Profile probed twice for the same device!"); + return -EINVAL; + } + + data = csip_data_new(device); + data->service = service; + + data->csip = bt_csip_new(btd_gatt_database_get_db(database), + btd_device_get_gatt_db(device)); + if (!data->csip) { + error("Unable to create CSIP instance"); + free(data); + return -EINVAL; + } + + csip_data_add(data); + + bt_csip_set_user_data(data->csip, service); + + return 0; +} + +static void csip_remove(struct btd_service *service) +{ + struct btd_device *device = btd_service_get_device(service); + struct csip_data *data; + char addr[18]; + + ba2str(device_get_address(device), addr); + DBG("%s", addr); + + data = btd_service_get_user_data(service); + if (!data) { + error("CSIP service not handled by profile"); + return; + } + + csip_data_remove(data); +} + +static struct btd_profile csip_profile = { + .name = "csip", + .priority = BTD_PROFILE_PRIORITY_MEDIUM, + .remote_uuid = CSIS_UUID_STR, + + .device_probe = csip_probe, + .device_remove = csip_remove, + + .accept = csip_accept, + .disconnect = csip_disconnect, + + .adapter_probe = csip_server_probe, + .adapter_remove = csip_server_remove, +}; + +static unsigned int csip_id = 0; + +static int csip_init(void) +{ + if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) { + warn("D-Bus experimental not enabled"); + return -ENOTSUP; + } + + btd_profile_register(&csip_profile); + csip_id = bt_csip_register(csip_attached, csip_detached, NULL); + + return 0; +} + +static void csip_exit(void) +{ + if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) { + btd_profile_unregister(&csip_profile); + bt_csip_unregister(csip_id); + } +} + +BLUETOOTH_PLUGIN_DEFINE(csip, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, + csip_init, csip_exit) From patchwork Mon Nov 21 23:46:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sathish Narasimman X-Patchwork-Id: 13051728 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FD07C43217 for ; Mon, 21 Nov 2022 23:47:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232133AbiKUXqz (ORCPT ); Mon, 21 Nov 2022 18:46:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53426 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231951AbiKUXqU (ORCPT ); Mon, 21 Nov 2022 18:46:20 -0500 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00276C6947 for ; Mon, 21 Nov 2022 15:44:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669074288; x=1700610288; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5HjTXE6yASm4fnculIMu637JkLzu9jsyaoxsbFGWhJY=; b=nQGoNp1qtsgIo1BFxaR32SH2eH+DrxmGG188syaHIV3mrN7cFOwLd7FQ 8j9P7+7GYB1i8KQCAWsmYVppH8km+0ashqjLM6ikjDNexiAKdFt/SamXE NSjL2XU7h7wuB6NCfuY7OlvTEtP5fVu3emM2xQRinAcHY+HZORF1OHisS 18pRzd2bzONqBjwJqpX9eRR7KQrKMQlr47TYz/8MZ1YFtvrg0IDdlI3tQ HD+jRYLQaQFm4a4UCuzxr2X8BysO23Oj1RoOBqR7b1YSAFWYw+QTNn6IH YxypcJXvVTV1Or7p8tTID9n1TRkmas8VvggoRTVCo5yr+/G63qpufSkkN w==; X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="377946609" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="377946609" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Nov 2022 15:44:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="783633470" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="783633470" Received: from intel-latitude-e5450.iind.intel.com ([10.224.186.32]) by fmsmga001.fm.intel.com with ESMTP; 21 Nov 2022 15:44:46 -0800 From: Sathish Narasimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman Subject: [PATCH BlueZ 5/6] monitor/att: Add decoding support for CSIP Date: Tue, 22 Nov 2022 05:16:23 +0530 Message-Id: <20221121234624.2961-6-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221121234624.2961-1-sathish.narasimman@intel.com> References: <20221121234624.2961-1-sathish.narasimman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds decoding support for CSIS attributes --- monitor/att.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/monitor/att.c b/monitor/att.c index d14cbd165697..6fd740aa4cd4 100644 --- a/monitor/att.c +++ b/monitor/att.c @@ -1733,6 +1733,73 @@ static void pac_context_notify(const struct l2cap_frame *frame) print_pac_context(frame); } +static void csip_rank_read(const struct l2cap_frame *frame) +{ + uint8_t rank; + + if (!l2cap_frame_get_u8((void *)frame, &rank)) { + print_text(COLOR_ERROR, "CSIP Rank: invalid size"); + goto done; + } + print_field(" CSIP Rank: %u", rank); + +done: + if (frame->size) + print_hex_field(" Data", frame->data, frame->size); +} + +static void csip_lock_read(const struct l2cap_frame *frame) +{ + uint8_t lock; + + if (!l2cap_frame_get_u8((void *)frame, &lock)) { + print_text(COLOR_ERROR, "CSIP LOCK: invalid size"); + goto done; + } + print_field(" CSIP LOCK: %u", lock); + +done: + if (frame->size) + print_hex_field(" Data", frame->data, frame->size); +} + +static void print_csip_size(const struct l2cap_frame *frame) +{ + uint8_t size; + + if (!l2cap_frame_get_u8((void *)frame, &size)) { + print_text(COLOR_ERROR, "CSIP SIZE: invalid size"); + goto done; + } + print_field(" CSIP SIZE: %u", size); + +done: + if (frame->size) + print_hex_field(" Data", frame->data, frame->size); +} + +static void csip_size_read(const struct l2cap_frame *frame) +{ + print_csip_size(frame); +} + +static void csip_size_notify(const struct l2cap_frame *frame) +{ + print_csip_size(frame); +} + +static void csip_sirk_read(const struct l2cap_frame *frame) +{ + if (frame->size) + print_hex_field(" SIRK", frame->data, frame->size); +} + +static void csip_sirk_notify(const struct l2cap_frame *frame) +{ + if (frame->size) + print_hex_field(" SIRK", frame->data, frame->size); +} + static void print_vcs_state(const struct l2cap_frame *frame) { uint8_t vol_set, mute, chng_ctr; @@ -2413,6 +2480,12 @@ struct gatt_handler { GATT_HANDLER(0x2b7d, vol_state_read, NULL, vol_state_notify), GATT_HANDLER(0x2b7e, NULL, vol_cp_write, NULL), GATT_HANDLER(0x2b7f, vol_flag_read, NULL, vol_flag_notify), + + GATT_HANDLER(0x2b84, csip_sirk_read, NULL, csip_sirk_notify), + GATT_HANDLER(0x2b85, csip_size_read, NULL, csip_size_notify), + GATT_HANDLER(0x2b86, csip_lock_read, NULL, NULL), + GATT_HANDLER(0x2b87, csip_rank_read, NULL, NULL), + GATT_HANDLER(0x2b93, mp_name_read, NULL, mp_name_notify), GATT_HANDLER(0x2b96, NULL, NULL, track_changed_notify), GATT_HANDLER(0x2b97, track_title_read, NULL, track_title_notify), From patchwork Mon Nov 21 23:46:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sathish Narasimman X-Patchwork-Id: 13051727 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2EF42C4321E for ; Mon, 21 Nov 2022 23:47:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232141AbiKUXq6 (ORCPT ); Mon, 21 Nov 2022 18:46:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53428 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231953AbiKUXqU (ORCPT ); Mon, 21 Nov 2022 18:46:20 -0500 Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E74A1CF9 for ; Mon, 21 Nov 2022 15:44:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1669074289; x=1700610289; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hlRyjRXk/Mf8iKNdbIXvoPgMyfu1rQ99CWmCVV5h0AE=; b=j8n5PcXlfAUaTH731qI8TNyvZb+Hyfs9Pz1uBAXqCG7cI2FtgC+VwCBL gYDjPkpHoGkEvdBGZ0IH1Pf+p6yjpTrngK8eseVHQv5bpluzAgBqzg5nI 8l0EGhxaPa4Vr1+PZaHP47ZRG2JlJgBoqFl9whlJ3WVyPSDO016VOA8ge BmQy6Vb04CZMY7P5zzkwS1/0BD/RcSD3UcYy4tq70D7+g5Ce97tchYkww jNiE9061g22OI37ryUKqNX+fxZZkMspbJ2y+/f5mrNx/FjsGPPs+ReHJq jeVrEXdtYNyNZizrEdJI/VKcsaX/kvt8o1H+bDSgaBNpYK9koWnBnGM3P w==; X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="377946614" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="377946614" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Nov 2022 15:44:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10538"; a="783633473" X-IronPort-AV: E=Sophos;i="5.96,182,1665471600"; d="scan'208";a="783633473" Received: from intel-latitude-e5450.iind.intel.com ([10.224.186.32]) by fmsmga001.fm.intel.com with ESMTP; 21 Nov 2022 15:44:48 -0800 From: Sathish Narasimman To: linux-bluetooth@vger.kernel.org Cc: Sathish Narasimman Subject: [PATCH BlueZ 6/6] tools: Add support to generate RSI using SIRK Date: Tue, 22 Nov 2022 05:16:24 +0530 Message-Id: <20221121234624.2961-7-sathish.narasimman@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221121234624.2961-1-sathish.narasimman@intel.com> References: <20221121234624.2961-1-sathish.narasimman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org The patch helps to generate Resolvable set identifier adv data. which can be used as ADV data during advertisement. It will be used to identify the device as part of setmember for Coordinated set identification profile. Example: $advtest -i "761FAE703ED681F0C50B34155B6434FB" SIRK: 761FAE703ED681F0C50B34155B6434FB RSI: 0x71 0xcb 0xbc 0x7e 0x01 0x84 Random: bccb71 Hash: 84017e --- tools/advtest.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/tools/advtest.c b/tools/advtest.c index de036e783325..1ac9dd9e1226 100644 --- a/tools/advtest.c +++ b/tools/advtest.c @@ -13,6 +13,13 @@ #include #endif +#include + +#include +#include +#include +#include + #include #include "lib/bluetooth.h" @@ -32,6 +39,9 @@ "\xe1\x23\x99\xc1\xca\x9a\xc3\x31" #define SCAN_IRK "\xfa\x73\x09\x11\x3f\x03\x37\x0f" \ "\xf4\xf9\x93\x1e\xf9\xa3\x63\xa6" +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif static struct mgmt *mgmt; static uint16_t index1 = MGMT_INDEX_NONE; @@ -43,13 +53,73 @@ static struct bt_hci *scan_dev; static void print_rpa(const uint8_t addr[6]) { - printf(" Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + printf(" RSI:\t0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); printf(" Random: %02x%02x%02x\n", addr[3], addr[4], addr[5]); printf(" Hash: %02x%02x%02x\n", addr[0], addr[1], addr[2]); } +static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen) +{ + size_t i, len; + + len = MIN((strlen(hexstr) / 2), buflen); + memset(buf, 0, len); + + for (i = 0; i < len; i++) + if (sscanf(hexstr + (i * 2), "%02hhX", &buf[i]) != 1) + continue; + + + return len; +} + +static bool get_random_bytes(void *buf, size_t num_bytes) +{ + ssize_t len; + int fd; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + return false; + + len = read(fd, buf, num_bytes); + + close(fd); + + if (len < 0) + return false; + + return true; +} + +static void generate_rsi(char *val) +{ + uint8_t sirk[16], hash[3]; + uint8_t rsi[6]; + + hex2bin(val, sirk, sizeof(sirk)); + + get_random_bytes(&rsi[3], 3); + + rsi[5] &= 0x3f; /* Clear 2 msb */ + rsi[5] |= 0x40; /* Set 2nd msb */ + + crypto = bt_crypto_new(); + if (!crypto) { + fprintf(stderr, "Failed to open crypto interface\n"); + mainloop_exit_failure(); + return; + } + + bt_crypto_ah(crypto, sirk, rsi + 3, hash); + memcpy(rsi, hash, 3); + + print_rpa(rsi); +} + + static void scan_le_adv_report(const void *data, uint8_t size, void *user_data) { @@ -351,9 +421,11 @@ static void usage(void) printf("\tadvtest [options]\n"); printf("options:\n" "\t-h, --help Show help options\n"); + printf(" \t-i <128bit SIRK>, Generate RSI ADV Data\n"); } static const struct option main_options[] = { + { "hash", no_argument, NULL, 'i' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { } @@ -366,11 +438,15 @@ int main(int argc ,char *argv[]) for (;;) { int opt; - opt = getopt_long(argc, argv, "vh", main_options, NULL); + opt = getopt_long(argc, argv, "i:vh", main_options, NULL); if (opt < 0) break; switch (opt) { + case 'i': + printf("SIRK: %s\n", optarg); + generate_rsi(optarg); + return EXIT_SUCCESS; case 'v': printf("%s\n", VERSION); return EXIT_SUCCESS;