2023-05-16 21:09:44

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 01/10] profile: Add support for experimental flag

From: Luiz Augusto von Dentz <[email protected]>

This adds experimental field to btd_profile so the plugin can indicate
drivers that depends on experimental to be enabled.
---
src/profile.c | 6 ++++++
src/profile.h | 5 +++++
2 files changed, 11 insertions(+)

diff --git a/src/profile.c b/src/profile.c
index e1bebf1ee19c..ea188f36b6dd 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -775,6 +775,12 @@ static struct btd_profile *btd_profile_find_uuid(const char *uuid)

int btd_profile_register(struct btd_profile *profile)
{
+ if (profile->experimental && !(g_dbus_get_flags() &
+ G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+ DBG("D-Bus experimental not enabled");
+ return -ENOTSUP;
+ }
+
profiles = g_slist_append(profiles, profile);
return 0;
}
diff --git a/src/profile.h b/src/profile.h
index 6827f848148c..6871f2f0d7d8 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -28,6 +28,11 @@ struct btd_profile {
*/
bool external;

+ /* Indicates the profile is experimental and shall only be registered
+ * when experimental has been enabled (see: main.conf:Experimental).
+ */
+ bool experimental;
+
int (*device_probe) (struct btd_service *service);
void (*device_remove) (struct btd_service *service);

--
2.40.1



2023-05-16 21:10:33

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 04/10] csip: Mark driver as experimental

From: Luiz Augusto von Dentz <[email protected]>

This uses the btd_profile.experimental to mark the driver as
experimental.
---
profiles/audio/csip.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/profiles/audio/csip.c b/profiles/audio/csip.c
index c273c02b8e76..ec042afd54eb 100644
--- a/profiles/audio/csip.c
+++ b/profiles/audio/csip.c
@@ -334,18 +334,20 @@ static struct btd_profile csip_profile = {

.adapter_probe = csip_server_probe,
.adapter_remove = csip_server_remove,
+
+ .experimental = true,
};

static unsigned int csip_id;

static int csip_init(void)
{
- if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
- warn("D-Bus experimental not enabled");
- return -ENOTSUP;
- }
+ int err;
+
+ err = btd_profile_register(&csip_profile);
+ if (err)
+ return err;

- btd_profile_register(&csip_profile);
csip_id = bt_csip_register(csip_attached, csip_detached, NULL);

return 0;
@@ -353,10 +355,8 @@ static int csip_init(void)

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);
- }
+ btd_profile_unregister(&csip_profile);
+ bt_csip_unregister(csip_id);
}

BLUETOOTH_PLUGIN_DEFINE(csip, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
--
2.40.1


2023-05-16 21:10:42

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 06/10] vcp: Mark driver as experimental

From: Luiz Augusto von Dentz <[email protected]>

This uses the btd_profile.experimental to mark the driver as
experimental.
---
profiles/audio/vcp.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/profiles/audio/vcp.c b/profiles/audio/vcp.c
index b42b0a4f79dd..175275f2e977 100644
--- a/profiles/audio/vcp.c
+++ b/profiles/audio/vcp.c
@@ -289,18 +289,20 @@ static struct btd_profile vcp_profile = {

.adapter_probe = vcp_server_probe,
.adapter_remove = vcp_server_remove,
+
+ .experimental = true,
};

static unsigned int vcp_id = 0;

static int vcp_init(void)
{
- if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
- warn("D-Bus experimental not enabled");
- return -ENOTSUP;
- }
+ int err;
+
+ err = btd_profile_register(&vcp_profile);
+ if (err)
+ return err;

- btd_profile_register(&vcp_profile);
vcp_id = bt_vcp_register(vcp_attached, vcp_detached, NULL);

return 0;
@@ -308,10 +310,8 @@ static int vcp_init(void)

static void vcp_exit(void)
{
- if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
- btd_profile_unregister(&vcp_profile);
- bt_vcp_unregister(vcp_id);
- }
+ btd_profile_unregister(&vcp_profile);
+ bt_vcp_unregister(vcp_id);
}

BLUETOOTH_PLUGIN_DEFINE(vcp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
--
2.40.1


2023-05-16 21:10:44

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 09/10] admin: Mark driver as experimental

From: Luiz Augusto von Dentz <[email protected]>

This uses the btd_profile.experimental to mark the driver as
experimental.
---
plugins/admin.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/plugins/admin.c b/plugins/admin.c
index 0787e8381ed7..68e9237d3fbd 100644
--- a/plugins/admin.c
+++ b/plugins/admin.c
@@ -618,13 +618,12 @@ static struct btd_adapter_driver admin_policy_driver = {
.resume = NULL,
.remove = admin_policy_remove,
.device_resolved = admin_policy_device_added,
- .device_removed = admin_policy_device_removed
+ .device_removed = admin_policy_device_removed,
+ .experimental = true,
};

static int admin_init(void)
{
- DBG("");
-
dbus_conn = btd_get_dbus_connection();

return btd_register_adapter_driver(&admin_policy_driver);
@@ -632,8 +631,6 @@ static int admin_init(void)

static void admin_exit(void)
{
- DBG("");
-
btd_unregister_adapter_driver(&admin_policy_driver);
}

--
2.40.1


2023-05-16 21:10:47

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 10/10] main: Rework config option parsing

From: Luiz Augusto von Dentz <[email protected]>

This rework config option parsing adding helper function to make it
simpler to parse new options.
---
src/btd.h | 14 +-
src/main.c | 848 +++++++++++++++++++++++++++--------------------------
2 files changed, 442 insertions(+), 420 deletions(-)

diff --git a/src/btd.h b/src/btd.h
index 70051c71c7c1..b7e7ebd618cf 100644
--- a/src/btd.h
+++ b/src/btd.h
@@ -111,7 +111,7 @@ struct btd_advmon_opts {
struct btd_opts {
char *name;
uint32_t class;
- gboolean pairable;
+ bool pairable;
uint32_t pairto;
uint32_t discovto;
uint32_t tmpto;
@@ -122,12 +122,12 @@ struct btd_opts {

struct btd_defaults defaults;

- gboolean reverse_discovery;
- gboolean name_resolv;
- gboolean debug_keys;
- gboolean fast_conn;
- gboolean refresh_discovery;
- gboolean experimental;
+ bool reverse_discovery;
+ bool name_resolv;
+ bool debug_keys;
+ bool fast_conn;
+ bool refresh_discovery;
+ bool experimental;
struct queue *kernel;

uint16_t did_source;
diff --git a/src/main.c b/src/main.c
index a64b833b58c1..8dfd2543ba1c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -313,7 +313,7 @@ done:
btd_opts.did_version = version;
}

-static bt_gatt_cache_t parse_gatt_cache(const char *cache)
+static bt_gatt_cache_t parse_gatt_cache_str(const char *cache)
{
if (!strcmp(cache, "always")) {
return BT_GATT_CACHE_ALWAYS;
@@ -415,6 +415,63 @@ static int get_mode(const char *str)
return BT_MODE_DUAL;
}

+static bool parse_config_string(GKeyFile *config, const char *group,
+ const char *key, char **val)
+{
+ GError *err = NULL;
+ char *tmp;
+
+ tmp = 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, tmp);
+
+ if (val) {
+ g_free(*val);
+ *val = tmp;
+ }
+
+ return true;
+}
+
+static bool parse_config_int(GKeyFile *config, const char *group,
+ const char *key, int *val,
+ int min, int max)
+{
+ int tmp;
+ char *str = NULL;
+ char *endptr = NULL;
+
+ if (!parse_config_string(config, group, key, &str))
+ return false;
+
+ tmp = strtol(str, &endptr, 0);
+ if (!endptr || *endptr != '\0') {
+ error("%s.%s = %s is not integer", group, key, str);
+ return false;
+ }
+
+ if (tmp < min) {
+ warn("%s.%s = %d is out of range (< %d)", group, key, tmp, min);
+ return false;
+ }
+
+ if (tmp < max) {
+ warn("%s.%s = %d is out of range (> %d)", group, key, tmp, max);
+ return false;
+ }
+
+ if (val)
+ *val = tmp;
+
+ return true;
+}
+
struct config_param {
const char * const val_name;
void * const val;
@@ -433,31 +490,15 @@ static void parse_mode_config(GKeyFile *config, const char *group,
return;

for (i = 0; i < params_len; ++i) {
- GError *err = NULL;
- char *str;
-
- str = g_key_file_get_string(config, group, params[i].val_name,
- &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- char *endptr = NULL;
- int val;
-
- val = strtol(str, &endptr, 0);
- if (!endptr || *endptr != '\0')
- continue;
-
- info("%s=%s(%d)", params[i].val_name, str, val);
-
- val = MAX(val, params[i].min);
- val = MIN(val, params[i].max);
+ int val;

+ if (parse_config_int(config, group, params[i].val_name,
+ &val, params[i].min, params[i].max)) {
val = htobl(val);
memcpy(params[i].val, &val, params[i].size);
- ++btd_opts.defaults.num_entries;
}
+
+ ++btd_opts.defaults.num_entries;
}
}

@@ -728,13 +769,375 @@ static bool gen_sirk(const char *str)
return ret;
}

-static void parse_config(GKeyFile *config)
+static bool parse_config_u32(GKeyFile *config, const char *group,
+ const char *key, uint32_t *val,
+ uint32_t min, uint32_t max)
+{
+ int tmp;
+
+ if (!parse_config_int(config, group, key, &tmp, 0, UINT32_MAX))
+ return false;
+
+ if (val)
+ *val = tmp;
+
+ return true;
+}
+
+static bool parse_config_u16(GKeyFile *config, const char *group,
+ const char *key, uint16_t *val,
+ uint16_t min, uint16_t max)
+{
+ int tmp;
+
+ if (!parse_config_int(config, group, key, &tmp, min, max))
+ return false;
+
+ if (val)
+ *val = tmp;
+
+ return true;
+}
+
+static bool parse_config_u8(GKeyFile *config, const char *group,
+ const char *key, uint8_t *val,
+ uint8_t min, uint8_t max)
+{
+ int tmp;
+
+ if (!parse_config_int(config, group, key, &tmp, min, max))
+ return false;
+
+ if (val)
+ *val = tmp;
+
+ return true;
+}
+
+static bool parse_config_bool(GKeyFile *config, const char *group,
+ const char *key, bool *val)
{
GError *err = NULL;
- char *str, **strlist;
- int val;
- gboolean boolean;
+ gboolean tmp;

+ tmp = g_key_file_get_boolean(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, tmp ? "true" : "false");
+
+ if (val)
+ *val = tmp;
+
+ return true;
+}
+
+static void parse_privacy(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "General", "Privacy", &str)) {
+ btd_opts.privacy = 0x00;
+ btd_opts.device_privacy = true;
+ return;
+ }
+
+ if (!strcmp(str, "network") || !strcmp(str, "on")) {
+ btd_opts.privacy = 0x01;
+ } else if (!strcmp(str, "device")) {
+ btd_opts.privacy = 0x01;
+ btd_opts.device_privacy = true;
+ } else if (!strcmp(str, "limited-network")) {
+ if (btd_opts.mode != BT_MODE_DUAL) {
+ DBG("Invalid privacy option: %s", str);
+ btd_opts.privacy = 0x00;
+ }
+ btd_opts.privacy = 0x01;
+ } else if (!strcmp(str, "limited-device")) {
+ if (btd_opts.mode != BT_MODE_DUAL) {
+ DBG("Invalid privacy option: %s", str);
+ btd_opts.privacy = 0x00;
+ }
+ btd_opts.privacy = 0x02;
+ btd_opts.device_privacy = true;
+ } else if (!strcmp(str, "off")) {
+ btd_opts.privacy = 0x00;
+ btd_opts.device_privacy = true;
+ } else {
+ DBG("Invalid privacy option: %s", str);
+ btd_opts.privacy = 0x00;
+ }
+
+ g_free(str);
+}
+
+static void parse_repairing(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "General", "JustWorksRepairing",
+ &str)) {
+ btd_opts.jw_repairing = JW_REPAIRING_NEVER;
+ return;
+ }
+
+ btd_opts.jw_repairing = parse_jw_repairing(str);
+ g_free(str);
+}
+
+static bool parse_config_hex(GKeyFile *config, char *group,
+ const char *key, uint32_t *val)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, group, key, &str))
+ return false;
+
+ if (val)
+ *val = strtol(str, NULL, 16);
+
+ g_free(str);
+ return true;
+}
+
+static void parse_device_id(GKeyFile *config)
+{
+ char *str = NULL;
+
+ parse_config_string(config, "General", "DeviceID", &str);
+ if (!str)
+ return;
+
+ parse_did(str);
+ g_free(str);
+}
+
+static void parse_ctrl_mode(GKeyFile *config)
+{
+ char *str = NULL;
+
+ parse_config_string(config, "General", "ControllerMode", &str);
+ if (!str)
+ return;
+
+ btd_opts.mode = get_mode(str);
+ g_free(str);
+}
+
+static void parse_multi_profile(GKeyFile *config)
+{
+ char *str = NULL;
+
+ parse_config_string(config, "General", "MultiProfile", &str);
+ if (!str)
+ return;
+
+ if (!strcmp(str, "single"))
+ btd_opts.mps = MPS_SINGLE;
+ else if (!strcmp(str, "multiple"))
+ btd_opts.mps = MPS_MULTIPLE;
+ else
+ btd_opts.mps = MPS_OFF;
+
+ g_free(str);
+}
+
+static gboolean parse_kernel_experimental(const char *key, const char *value,
+ gpointer user_data, GError **error)
+{
+ char **strlist;
+
+ if (value && value[0] != '*') {
+ strlist = g_strsplit(value, ",", -1);
+ btd_parse_kernel_experimental(strlist);
+ g_strfreev(strlist);
+ } else {
+ if (!btd_opts.kernel)
+ btd_opts.kernel = queue_new();
+ queue_push_head(btd_opts.kernel, strdup("*"));
+ }
+
+ return TRUE;
+}
+
+static void parse_kernel_exp(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "General", "KernelExperimental",
+ &str))
+ return;
+
+ parse_kernel_experimental(NULL, str, NULL, NULL);
+
+ g_free(str);
+}
+
+static void parse_secure_conns(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "General", "SecureConnections",
+ &str))
+ return;
+
+ if (!strcmp(str, "off"))
+ btd_opts.secure_conn = SC_OFF;
+ else if (!strcmp(str, "on"))
+ btd_opts.secure_conn = SC_ON;
+ else if (!strcmp(str, "only"))
+ btd_opts.secure_conn = SC_ONLY;
+
+ g_free(str);
+}
+
+static void parse_general(GKeyFile *config)
+{
+ parse_config_string(config, "General", "Name", &btd_opts.name);
+ parse_config_hex(config, "General", "Class", &btd_opts.class);
+ parse_config_u32(config, "General", "DiscoverableTimeout",
+ &btd_opts.discovto,
+ 0, UINT32_MAX);
+ parse_config_bool(config, "General", "AlwaysPairable",
+ &btd_opts.pairable);
+ parse_config_u32(config, "General", "PairableTimeout",
+ &btd_opts.pairto,
+ 0, UINT32_MAX);
+ parse_device_id(config);
+ parse_config_bool(config, "General", "ReverseServiceDiscovery",
+ &btd_opts.reverse_discovery);
+ parse_config_bool(config, "General", "NameResolving",
+ &btd_opts.name_resolv);
+ parse_config_bool(config, "General", "DebugKeys",
+ &btd_opts.debug_keys);
+ parse_ctrl_mode(config);
+ parse_config_u16(config, "General", "MaxControllers",
+ &btd_opts.max_adapters,
+ 0, UINT16_MAX);
+ parse_multi_profile(config);
+ parse_config_bool(config, "General", "FastConnectable",
+ &btd_opts.fast_conn);
+ parse_privacy(config);
+ parse_repairing(config);
+ parse_config_u32(config, "General", "TemporaryTimeout",
+ &btd_opts.tmpto,
+ 0, UINT32_MAX);
+ parse_config_bool(config, "General", "RefreshDiscovery",
+ &btd_opts.refresh_discovery);
+ parse_secure_conns(config);
+ parse_config_bool(config, "General", "Experimental",
+ &btd_opts.experimental);
+ parse_kernel_exp(config);
+ parse_config_u32(config, "General", "RemoteNameRequestRetryDelay",
+ &btd_opts.name_request_retry_delay,
+ 0, UINT32_MAX);
+}
+
+static void parse_gatt_cache(GKeyFile *config)
+{
+ char *str = NULL;
+
+ parse_config_string(config, "GATT", "Cache", &str);
+ if (!str)
+ return;
+
+ btd_opts.gatt_cache = parse_gatt_cache_str(str);
+ g_free(str);
+}
+
+static void parse_gatt(GKeyFile *config)
+{
+ parse_gatt_cache(config);
+ parse_config_u8(config, "GATT", "KeySize", &btd_opts.key_size, 7, 16);
+ parse_config_u16(config, "GATT", "ExchangeMTU", &btd_opts.gatt_mtu,
+ BT_ATT_DEFAULT_LE_MTU, BT_ATT_MAX_LE_MTU);
+ parse_config_u8(config, "GATT", "Channels", &btd_opts.gatt_channels,
+ 1, 5);
+}
+
+static void parse_csis_sirk(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "CSIS", "SIRK", &str))
+ return;
+
+ if (strlen(str) == 32 && check_sirk_alpha_numeric(str))
+ hex2bin(str, btd_opts.csis.sirk, sizeof(btd_opts.csis.sirk));
+ else if (!gen_sirk(str))
+ DBG("Unable to generate SIRK from string");
+
+ g_free(str);
+}
+
+static void parse_csis(GKeyFile *config)
+{
+ parse_csis_sirk(config);
+ parse_config_bool(config, "CSIS", "Encryption",
+ &btd_opts.csis.encrypt);
+ parse_config_u8(config, "CSIS", "Size", &btd_opts.csis.size,
+ 0, UINT8_MAX);
+ parse_config_u8(config, "CSIS", "Rank", &btd_opts.csis.size,
+ 0, UINT8_MAX);
+}
+
+static void parse_avdtp_session_mode(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "AVDTP", "SessionMode", &str))
+ return;
+
+ if (!strcmp(str, "basic"))
+ btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
+ else if (!strcmp(str, "ertm"))
+ btd_opts.avdtp.session_mode = BT_IO_MODE_ERTM;
+ else {
+ DBG("Invalid mode option: %s", str);
+ btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
+ }
+
+ g_free(str);
+}
+
+static void parse_avdtp_stream_mode(GKeyFile *config)
+{
+ char *str = NULL;
+
+ if (!parse_config_string(config, "AVDTP", "StreamMode", &str))
+ return;
+
+ if (!strcmp(str, "basic"))
+ btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
+ else if (!strcmp(str, "streaming"))
+ btd_opts.avdtp.stream_mode = BT_IO_MODE_STREAMING;
+ else {
+ DBG("Invalid mode option: %s", str);
+ btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
+ }
+
+ g_free(str);
+}
+
+static void parse_avdtp(GKeyFile *config)
+{
+ parse_avdtp_session_mode(config);
+ parse_avdtp_stream_mode(config);
+}
+
+static void parse_advmon(GKeyFile *config)
+{
+ parse_config_u8(config, "AdvMon", "RSSISamplingPeriod",
+ &btd_opts.advmon.rssi_sampling_period,
+ 0, UINT8_MAX);
+}
+
+static void parse_config(GKeyFile *config)
+{
if (!config)
return;

@@ -742,377 +1145,14 @@ static void parse_config(GKeyFile *config)

DBG("parsing %s", main_conf_file_path);

- val = g_key_file_get_integer(config, "General",
- "DiscoverableTimeout", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("discovto=%d", val);
- btd_opts.discovto = val;
- }
-
- boolean = g_key_file_get_boolean(config, "General",
- "AlwaysPairable", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("pairable=%s", boolean ? "true" : "false");
- btd_opts.pairable = boolean;
- }
-
- val = g_key_file_get_integer(config, "General",
- "PairableTimeout", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("pairto=%d", val);
- btd_opts.pairto = val;
- }
-
- str = g_key_file_get_string(config, "General", "Privacy", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- btd_opts.privacy = 0x00;
- btd_opts.device_privacy = true;
- } else {
- DBG("privacy=%s", str);
-
- if (!strcmp(str, "network") || !strcmp(str, "on")) {
- btd_opts.privacy = 0x01;
- } else if (!strcmp(str, "device")) {
- btd_opts.privacy = 0x01;
- btd_opts.device_privacy = true;
- } else if (!strcmp(str, "limited-network")) {
- if (btd_opts.mode != BT_MODE_DUAL) {
- DBG("Invalid privacy option: %s", str);
- btd_opts.privacy = 0x00;
- }
- btd_opts.privacy = 0x01;
- } else if (!strcmp(str, "limited-device")) {
- if (btd_opts.mode != BT_MODE_DUAL) {
- DBG("Invalid privacy option: %s", str);
- btd_opts.privacy = 0x00;
- }
- btd_opts.privacy = 0x02;
- btd_opts.device_privacy = true;
- } else if (!strcmp(str, "off")) {
- btd_opts.privacy = 0x00;
- btd_opts.device_privacy = true;
- } else {
- DBG("Invalid privacy option: %s", str);
- btd_opts.privacy = 0x00;
- }
-
- g_free(str);
- }
-
- str = g_key_file_get_string(config, "General",
- "JustWorksRepairing", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- btd_opts.jw_repairing = JW_REPAIRING_NEVER;
- } else {
- DBG("just_works_repairing=%s", str);
- btd_opts.jw_repairing = parse_jw_repairing(str);
- g_free(str);
- }
-
- val = g_key_file_get_integer(config, "General",
- "TemporaryTimeout", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("tmpto=%d", val);
- btd_opts.tmpto = val;
- }
-
- str = g_key_file_get_string(config, "General", "Name", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("name=%s", str);
- g_free(btd_opts.name);
- btd_opts.name = str;
- }
-
- str = g_key_file_get_string(config, "General", "Class", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("class=%s", str);
- btd_opts.class = strtol(str, NULL, 16);
- g_free(str);
- }
-
- str = g_key_file_get_string(config, "General", "DeviceID", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("deviceid=%s", str);
- parse_did(str);
- g_free(str);
- }
-
- boolean = g_key_file_get_boolean(config, "General",
- "ReverseServiceDiscovery", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else
- btd_opts.reverse_discovery = boolean;
-
- boolean = g_key_file_get_boolean(config, "General",
- "NameResolving", &err);
- if (err)
- g_clear_error(&err);
- else
- btd_opts.name_resolv = boolean;
-
- boolean = g_key_file_get_boolean(config, "General",
- "DebugKeys", &err);
- if (err)
- g_clear_error(&err);
- else
- btd_opts.debug_keys = boolean;
-
- str = g_key_file_get_string(config, "General", "ControllerMode", &err);
- if (err) {
- g_clear_error(&err);
- } else {
- DBG("ControllerMode=%s", str);
- btd_opts.mode = get_mode(str);
- g_free(str);
- }
-
- val = g_key_file_get_integer(config, "General", "MaxControllers", &err);
- if (err) {
- g_clear_error(&err);
- } else {
- DBG("MaxControllers=%d", val);
- btd_opts.max_adapters = val;
- }
-
- str = g_key_file_get_string(config, "General", "MultiProfile", &err);
- if (err) {
- g_clear_error(&err);
- } else {
- DBG("MultiProfile=%s", str);
-
- if (!strcmp(str, "single"))
- btd_opts.mps = MPS_SINGLE;
- else if (!strcmp(str, "multiple"))
- btd_opts.mps = MPS_MULTIPLE;
- else
- btd_opts.mps = MPS_OFF;
-
- g_free(str);
- }
-
- boolean = g_key_file_get_boolean(config, "General",
- "FastConnectable", &err);
- if (err)
- g_clear_error(&err);
- else
- btd_opts.fast_conn = boolean;
-
- boolean = g_key_file_get_boolean(config, "General",
- "RefreshDiscovery", &err);
- if (err)
- g_clear_error(&err);
- else
- btd_opts.refresh_discovery = boolean;
-
- boolean = g_key_file_get_boolean(config, "General", "Experimental",
- &err);
- if (err)
- g_clear_error(&err);
- else
- btd_opts.experimental = boolean;
-
- strlist = g_key_file_get_string_list(config, "General",
- "KernelExperimental",
- NULL, &err);
- if (err)
- g_clear_error(&err);
- else {
- btd_parse_kernel_experimental(strlist);
- g_strfreev(strlist);
- }
-
- val = g_key_file_get_integer(config, "General",
- "RemoteNameRequestRetryDelay", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("RemoteNameRequestRetryDelay=%d", val);
- btd_opts.name_request_retry_delay = val;
- }
-
- str = g_key_file_get_string(config, "General",
- "SecureConnections", &err);
- if (err)
- g_clear_error(&err);
- else {
- if (!strcmp(str, "off"))
- btd_opts.secure_conn = SC_OFF;
- else if (!strcmp(str, "on"))
- btd_opts.secure_conn = SC_ON;
- else if (!strcmp(str, "only"))
- btd_opts.secure_conn = SC_ONLY;
- }
-
- str = g_key_file_get_string(config, "GATT", "Cache", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- btd_opts.gatt_cache = parse_gatt_cache(str);
- g_free(str);
- }
-
- val = g_key_file_get_integer(config, "GATT", "KeySize", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("KeySize=%d", val);
-
- if (val >=7 && val <= 16)
- btd_opts.key_size = val;
- }
-
- val = g_key_file_get_integer(config, "GATT", "ExchangeMTU", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- /* Ensure the mtu is within a valid range. */
- val = MIN(val, BT_ATT_MAX_LE_MTU);
- val = MAX(val, BT_ATT_DEFAULT_LE_MTU);
- DBG("ExchangeMTU=%d", val);
- btd_opts.gatt_mtu = val;
- }
-
- val = g_key_file_get_integer(config, "GATT", "Channels", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("Channels=%d", val);
- /* Ensure the channels is within a valid range. */
- val = MIN(val, 5);
- val = MAX(val, 1);
- btd_opts.gatt_channels = val;
- }
-
- str = g_key_file_get_string(config, "CSIS", "SIRK", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("CSIS SIRK: %s", str);
-
- if (strlen(str) == 32 && check_sirk_alpha_numeric(str)) {
- hex2bin(str, btd_opts.csis.sirk,
- sizeof(btd_opts.csis.sirk));
- } else if (!gen_sirk(str))
- DBG("Unable to generate SIRK from string");
-
- g_free(str);
- }
-
- boolean = g_key_file_get_boolean(config, "CSIS", "Encryption", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("CSIS Encryption: %s", boolean ? "true" : "false");
-
- btd_opts.csis.encrypt = boolean;
- }
-
- val = g_key_file_get_integer(config, "CSIS", "Size", &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.size = val;
- }
-
- val = g_key_file_get_integer(config, "CSIS", "Rank", &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.rank = val;
- }
-
- str = g_key_file_get_string(config, "AVDTP", "SessionMode", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("SessionMode=%s", str);
-
- if (!strcmp(str, "basic"))
- btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
- else if (!strcmp(str, "ertm"))
- btd_opts.avdtp.session_mode = BT_IO_MODE_ERTM;
- else {
- DBG("Invalid mode option: %s", str);
- btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
- }
- g_free(str);
- }
-
- str = g_key_file_get_string(config, "AVDTP", "StreamMode", &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- DBG("StreamMode=%s", str);
-
- if (!strcmp(str, "basic"))
- btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
- else if (!strcmp(str, "streaming"))
- btd_opts.avdtp.stream_mode = BT_IO_MODE_STREAMING;
- else {
- DBG("Invalid mode option: %s", str);
- btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
- }
- g_free(str);
- }
-
- val = g_key_file_get_integer(config, "AdvMon", "RSSISamplingPeriod",
- &err);
- if (err) {
- DBG("%s", err->message);
- g_clear_error(&err);
- } else {
- val = MIN(val, 0xFF);
- val = MAX(val, 0);
- DBG("RSSISamplingPeriod=%d", val);
- btd_opts.advmon.rssi_sampling_period = val;
- }
-
+ /* Parse Groups */
+ parse_general(config);
parse_br_config(config);
parse_le_config(config);
+ parse_gatt(config);
+ parse_csis(config);
+ parse_avdtp(config);
+ parse_advmon(config);
}

static void init_defaults(void)
@@ -1284,24 +1324,6 @@ static gboolean parse_debug(const char *key, const char *value,
return TRUE;
}

-static gboolean parse_kernel_experimental(const char *key, const char *value,
- gpointer user_data, GError **error)
-{
- char **strlist;
-
- if (value) {
- strlist = g_strsplit(value, ",", -1);
- btd_parse_kernel_experimental(strlist);
- g_strfreev(strlist);
- } else {
- if (!btd_opts.kernel)
- btd_opts.kernel = queue_new();
- queue_push_head(btd_opts.kernel, strdup("*"));
- }
-
- return TRUE;
-}
-
static GOptionEntry options[] = {
{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
G_OPTION_ARG_CALLBACK, parse_debug,
--
2.40.1


2023-05-16 21:10:48

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 08/10] adapter: Add support for experimental flag

From: Luiz Augusto von Dentz <[email protected]>

This adds experimental field to btd_adapter_driver so the plugin can
indicate drivers that depends on experimental to be enabled.
---
src/adapter.c | 6 ++++++
src/adapter.h | 5 +++++
2 files changed, 11 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index cc7f891d96d9..74ed52468b81 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -7447,6 +7447,12 @@ static void adapter_stop(struct btd_adapter *adapter)

int btd_register_adapter_driver(struct btd_adapter_driver *driver)
{
+ if (driver->experimental && !(g_dbus_get_flags() &
+ G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+ DBG("D-Bus experimental not enabled");
+ return -ENOTSUP;
+ }
+
adapter_drivers = g_slist_append(adapter_drivers, driver);

if (driver->probe == NULL)
diff --git a/src/adapter.h b/src/adapter.h
index a45ac1bab00e..32e49a933b13 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -127,6 +127,11 @@ struct btd_adapter_driver {
struct btd_device *device);
void (*device_resolved)(struct btd_adapter *adapter,
struct btd_device *device);
+
+ /* Indicates the driver is experimental and shall only be registered
+ * when experimental has been enabled (see: main.conf:Experimental).
+ */
+ bool experimental;
};

void device_resolved_drivers(struct btd_adapter *adapter,
--
2.40.1


2023-05-16 21:11:10

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 05/10] mcp: Mark driver as experimental

From: Luiz Augusto von Dentz <[email protected]>

This uses the btd_profile.experimental to mark the driver as
experimental.
---
profiles/audio/mcp.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c
index f3ea330f9839..b410b3d2aa03 100644
--- a/profiles/audio/mcp.c
+++ b/profiles/audio/mcp.c
@@ -403,27 +403,18 @@ static struct btd_profile mcp_profile = {

.adapter_probe = media_control_server_probe,
.adapter_remove = media_control_server_remove,
+
+ .experimental = true,
};

static int mcp_init(void)
{
- DBG("");
-
- if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
- warn("D-Bus experimental not enabled");
- return -ENOTSUP;
- }
-
- btd_profile_register(&mcp_profile);
- return 0;
+ return btd_profile_register(&mcp_profile);
}

static void mcp_exit(void)
{
- DBG("");
-
- if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)
- btd_profile_unregister(&mcp_profile);
+ btd_profile_unregister(&mcp_profile);
}

BLUETOOTH_PLUGIN_DEFINE(mcp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
--
2.40.1


2023-05-16 21:11:11

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH v2 07/10] plugin: Treat -ENOTSUP as -ENOSYS

From: Luiz Augusto von Dentz <[email protected]>

If plugin .init returns -ENOTSUP treat it as the system doesn't
support the driver since that is the error returned by
btd_profile_register when experimental is disabled.
---
src/plugin.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plugin.c b/src/plugin.c
index dd7b406c857b..80990f8c3c7e 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -186,7 +186,7 @@ start:

err = plugin->desc->init();
if (err < 0) {
- if (err == -ENOSYS)
+ if (err == -ENOSYS || err == -ENOTSUP)
warn("System does not support %s plugin",
plugin->desc->name);
else
--
2.40.1


2023-05-17 01:38:01

by bluez.test.bot

[permalink] [raw]
Subject: RE: [v2,01/10] profile: Add support for experimental flag

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=748169

---Test result---

Test Summary:
CheckPatch FAIL 6.73 seconds
GitLint PASS 3.96 seconds
BuildEll PASS 35.64 seconds
BluezMake PASS 1248.12 seconds
MakeCheck PASS 12.92 seconds
MakeDistcheck PASS 205.33 seconds
CheckValgrind PASS 331.37 seconds
CheckSmatch PASS 451.09 seconds
bluezmakeextell PASS 135.40 seconds
IncrementalBuild PASS 10357.78 seconds
ScanBuild PASS 1362.35 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[v2,07/10] plugin: Treat -ENOTSUP as -ENOSYS
WARNING:ENOSYS: ENOSYS means 'invalid syscall nr' and nothing else
#101: FILE: src/plugin.c:189:
+ if (err == -ENOSYS || err == -ENOTSUP)

/github/workspace/src/src/13243878.patch total: 0 errors, 1 warnings, 8 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/src/13243878.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.




---
Regards,
Linux Bluetooth

2023-05-17 19:57:52

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] profile: Add support for experimental flag

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Tue, 16 May 2023 13:59:15 -0700 you wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> This adds experimental field to btd_profile so the plugin can indicate
> drivers that depends on experimental to be enabled.
> ---
> src/profile.c | 6 ++++++
> src/profile.h | 5 +++++
> 2 files changed, 11 insertions(+)

Here is the summary with links:
- [v2,01/10] profile: Add support for experimental flag
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=67c5824fd071
- [v2,02/10] bap: Mark driver as experimental
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=da762dfa0255
- [v2,03/10] bass: Mark driver as experimental
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=bd14ad2e1f50
- [v2,04/10] csip: Mark driver as experimental
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=16da92601f4a
- [v2,05/10] mcp: Mark driver as experimental
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=62cbb2a9f57d
- [v2,06/10] vcp: Mark driver as experimental
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=2fa20fe9fc4a
- [v2,07/10] plugin: Treat -ENOTSUP as -ENOSYS
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=ce7cd9fb0611
- [v2,08/10] adapter: Add support for experimental flag
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=28917a3c7a4e
- [v2,09/10] admin: Mark driver as experimental
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=943be6271d77
- [v2,10/10] main: Rework config option parsing
(no matching commit)

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html