Diff between b1e2c54e97f50e2d7b8de450c363408b3ff7575f and efd6aa66478f5677622981c9fd37346d23282050

Changed Files

File Additions Deletions Status
src/adapter.c +95 -28 modified

Full Patch

diff --git a/src/adapter.c b/src/adapter.c
index 705d9b5..9610559 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1404,55 +1404,123 @@ failed:
 	g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed", NULL);
 }
 
-static gboolean adapter_property_get_discoverable(
-					const GDBusPropertyTable *property,
-					DBusMessageIter *iter, void *data)
+static gboolean property_get_pairable(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
 {
-	struct btd_adapter *adapter = data;
-	dbus_bool_t value;
+	struct btd_adapter *adapter = user_data;
+	dbus_bool_t pairable;
 
-	value = mgmt_discoverable(adapter->current_settings) ? TRUE : FALSE;
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
+	if (adapter->current_settings & MGMT_SETTING_PAIRABLE)
+		pairable = TRUE;
+	else
+		pairable = FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &pairable);
 
 	return TRUE;
 }
 
-static void adapter_property_set_discoverable(
-				const GDBusPropertyTable *property,
+static void set_pairable_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct property_set_data *data = user_data;
+	struct btd_adapter *adapter = data->adapter;
+	uint32_t settings;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		error("Failed to set pairable: %s (0x%02x)",
+						mgmt_errstr(status), status);
+		g_dbus_pending_property_error(data->id,
+						ERROR_INTERFACE ".Failed",
+						mgmt_errstr(status));
+		return;
+	}
+
+	if (length < sizeof(settings)) {
+		error("Wrong size of set pairable response");
+		g_dbus_pending_property_error(data->id,
+						ERROR_INTERFACE ".Failed",
+						"Invalid response data");
+		return;
+	}
+
+	settings = bt_get_le32(param);
+
+	DBG("Settings: 0x%08x", settings);
+
+	adapter->current_settings = settings;
+
+	g_dbus_pending_property_success(data->id);
+
+	g_dbus_emit_property_changed(dbus_conn, adapter->path,
+					ADAPTER_INTERFACE, "Pairable");
+}
+
+static void property_set_pairable(const GDBusPropertyTable *property,
 				DBusMessageIter *value,
-				GDBusPendingPropertySet id, void *data)
+				GDBusPendingPropertySet id, void *user_data)
 {
-	dbus_bool_t discoverable;
+	struct btd_adapter *adapter = user_data;
+	struct property_set_data *data;
+	struct mgmt_mode cp;
+	dbus_bool_t pairable, current_pairable;
 
-	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
-		g_dbus_pending_property_error(id,
-					ERROR_INTERFACE ".InvalidArguments",
-					"Invalid arguments in method call");
+	dbus_message_iter_get_basic(value, &pairable);
+
+	if (adapter->current_settings & MGMT_SETTING_PAIRABLE)
+		current_pairable = TRUE;
+	else
+		current_pairable = FALSE;
+
+	if (pairable == current_pairable) {
+		g_dbus_pending_property_success(id);
 		return;
 	}
 
-	dbus_message_iter_get_basic(value, &discoverable);
+	memset(&cp, 0, sizeof(cp));
+	cp.val = (pairable == TRUE) ? 0x01 : 0x00;
 
-	set_discoverable(data, discoverable, id);
+	DBG("sending set pairable command for index %u", adapter->dev_id);
+
+	data = g_try_new0(struct property_set_data, 1);
+	if (!data)
+		goto failed;
+
+	data->adapter = adapter;
+	data->id = id;
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PAIRABLE,
+				adapter->dev_id, sizeof(cp), &cp,
+				set_pairable_complete, data, g_free) > 0)
+		return;
+
+	g_free(data);
+
+failed:
+	error("Failed to set pairable for index %u", adapter->dev_id);
+
+	g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed", NULL);
 }
 
-static gboolean adapter_property_get_pairable(
+static gboolean adapter_property_get_discoverable(
 					const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
 	struct btd_adapter *adapter = data;
-	dbus_bool_t pairable = mgmt_pairable(adapter->current_settings);
+	dbus_bool_t value;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &pairable);
+	value = mgmt_discoverable(adapter->current_settings) ? TRUE : FALSE;
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
 
 	return TRUE;
 }
 
-static void adapter_property_set_pairable(const GDBusPropertyTable *property,
-		DBusMessageIter *value,
-		GDBusPendingPropertySet id, void *data)
+static void adapter_property_set_discoverable(
+				const GDBusPropertyTable *property,
+				DBusMessageIter *value,
+				GDBusPendingPropertySet id, void *data)
 {
-	dbus_bool_t pairable;
+	dbus_bool_t discoverable;
 
 	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) {
 		g_dbus_pending_property_error(id,
@@ -1461,9 +1529,9 @@ static void adapter_property_set_pairable(const GDBusPropertyTable *property,
 		return;
 	}
 
-	dbus_message_iter_get_basic(value, &pairable);
+	dbus_message_iter_get_basic(value, &discoverable);
 
-	set_pairable(data, pairable, true, id);
+	set_discoverable(data, discoverable, id);
 }
 
 static gboolean adapter_property_get_discoverable_timeout(
@@ -1643,10 +1711,9 @@ static const GDBusPropertyTable adapter_properties[] = {
 					adapter_property_set_alias },
 	{ "Class", "u", adapter_property_get_class },
 	{ "Powered", "b", property_get_powered, property_set_powered },
+	{ "Pairable", "b", property_get_pairable, property_set_pairable },
 	{ "Discoverable", "b", adapter_property_get_discoverable,
 					adapter_property_set_discoverable },
-	{ "Pairable", "b", adapter_property_get_pairable,
-					adapter_property_set_pairable },
 	{ "DiscoverableTimeout", "u",
 			adapter_property_get_discoverable_timeout,
 			adapter_property_set_discoverable_timeout },