Diff between 9dc6fb633db3fb892e8e7b5a564969d329e62443 and ef293ef10430c8588986071ddb02b44a468c2b7e

Changed Files

File Additions Deletions Status
src/adapter.c +29 -8 modified
src/hcid.h +8 -0 modified
src/main.c +23 -0 modified
src/main.conf +5 -0 modified

Full Patch

diff --git a/src/adapter.c b/src/adapter.c
index 92ee1a0..4e28c61 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -6877,6 +6877,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
 {
 	struct btd_adapter *adapter = user_data;
 	const struct mgmt_rp_read_info *rp = param;
+	uint32_t missing_settings;
 	int err;
 
 	DBG("index %u status 0x%02x", adapter->dev_id, status);
@@ -6917,6 +6918,34 @@ static void read_info_complete(uint8_t status, uint16_t length,
 	clear_uuids(adapter);
 	clear_devices(adapter);
 
+	missing_settings = adapter->current_settings ^
+						adapter->supported_settings;
+
+	switch (main_opts.mode) {
+	case BT_MODE_DUAL:
+		if (missing_settings & MGMT_SETTING_SSP)
+			set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
+		if (missing_settings & MGMT_SETTING_LE)
+			set_mode(adapter, MGMT_OP_SET_LE, 0x01);
+		if (missing_settings & MGMT_SETTING_BREDR)
+			set_mode(adapter, MGMT_OP_SET_BREDR, 0x01);
+		break;
+	case BT_MODE_BREDR:
+		if (missing_settings & MGMT_SETTING_SSP)
+			set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
+		if (missing_settings & MGMT_SETTING_BREDR)
+			set_mode(adapter, MGMT_OP_SET_BREDR, 0x01);
+		if (adapter->current_settings & MGMT_SETTING_LE)
+			set_mode(adapter, MGMT_OP_SET_LE, 0x00);
+		break;
+	case BT_MODE_LE:
+		if (missing_settings & MGMT_SETTING_LE)
+			set_mode(adapter, MGMT_OP_SET_LE, 0x01);
+		if (adapter->current_settings & MGMT_SETTING_BREDR)
+			set_mode(adapter, MGMT_OP_SET_BREDR, 0x00);
+		break;
+	}
+
 	err = adapter_register(adapter);
 	if (err < 0) {
 		error("Unable to register new adapter");
@@ -7035,14 +7064,6 @@ static void read_info_complete(uint8_t status, uint16_t length,
 
 	set_name(adapter, btd_adapter_get_name(adapter));
 
-	if ((adapter->supported_settings & MGMT_SETTING_SSP) &&
-			!(adapter->current_settings & MGMT_SETTING_SSP))
-		set_mode(adapter, MGMT_OP_SET_SSP, 0x01);
-
-	if ((adapter->supported_settings & MGMT_SETTING_LE) &&
-			!(adapter->current_settings & MGMT_SETTING_LE))
-		set_mode(adapter, MGMT_OP_SET_LE, 0x01);
-
 	if (!(adapter->current_settings & MGMT_SETTING_BONDABLE))
 		set_mode(adapter, MGMT_OP_SET_BONDABLE, 0x01);
 
diff --git a/src/hcid.h b/src/hcid.h
index 6040c71..0c91292 100644
--- a/src/hcid.h
+++ b/src/hcid.h
@@ -23,6 +23,12 @@
  *
  */
 
+typedef enum {
+	BT_MODE_DUAL,
+	BT_MODE_BREDR,
+	BT_MODE_LE,
+} bt_mode_t;
+
 struct main_opts {
 	char		*name;
 	uint32_t	class;
@@ -37,6 +43,8 @@ struct main_opts {
 	uint16_t	did_vendor;
 	uint16_t	did_product;
 	uint16_t	did_version;
+
+	bt_mode_t	mode;
 };
 
 extern struct main_opts main_opts;
diff --git a/src/main.c b/src/main.c
index e6bac6e..191dc11 100644
--- a/src/main.c
+++ b/src/main.c
@@ -187,6 +187,20 @@ static void check_config(GKeyFile *config)
 	g_strfreev(keys);
 }
 
+static int get_mode(const char *str)
+{
+	if (strcmp(str, "dual") == 0)
+		return BT_MODE_DUAL;
+	else if (strcmp(str, "bredr") == 0)
+		return BT_MODE_BREDR;
+	else if (strcmp(str, "le") == 0)
+		return BT_MODE_LE;
+
+	error("Unknown controller mode \"%s\"", str);
+
+	return BT_MODE_DUAL;
+}
+
 static void parse_config(GKeyFile *config)
 {
 	GError *err = NULL;
@@ -282,6 +296,15 @@ static void parse_config(GKeyFile *config)
 		g_clear_error(&err);
 	else
 		main_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);
+		main_opts.mode = get_mode(str);
+		g_free(str);
+	}
 }
 
 static void init_defaults(void)
diff --git a/src/main.conf b/src/main.conf
index 3ebadde..ea0a2bd 100644
--- a/src/main.conf
+++ b/src/main.conf
@@ -47,6 +47,11 @@
 # that they were created for.
 #DebugKeys = false
 
+# Restricts all controllers to the specified transport. Default vallue
+# is "dual", i.e. both BR/EDR and LE enabled (when supported by the HW).
+# Possible values: "dual", "bredr", "le"
+#ControllerMode = dual
+
 #[Policy]
 #
 # The ReconnectUUIDs defines the set of remote services that should try