diff --git a/src/adapter.c b/src/adapter.c
index 1ee2f3a..4452034 100644
--- a/src/adapter.c
+++ b/src/adapter.c
struct btd_adapter *adapter = user_data;
struct btd_device *dev;
char addr[18];
+ uint32_t flags;
+
if (length < sizeof(*rp)) {
btd_error(adapter->dev_id,
DBG("%s (%u) added to kernel connect list", addr, rp->addr.type);
if (btd_opts.device_privacy) {
- uint32_t flags = btd_device_get_current_flags(dev);
-
+ flags = btd_device_get_current_flags(dev);
/* Set Device Privacy Mode if it has not set the flag yet. */
if (!(flags & DEVICE_FLAG_DEVICE_PRIVACY)) {
/* Include the pending flags, or they may get
DEVICE_FLAG_DEVICE_PRIVACY,
set_device_privacy_complete,
dev);
+ return;
}
}
+
+ /* Check if any flag was marked as pending before ADD_DEVICE
+ * complete then set it now
+ */
+ flags = btd_device_get_pending_flags(dev);
+ if (flags)
+ adapter_set_device_flags(adapter, dev, flags,
+ set_device_privacy_complete,
+ dev);
}
void adapter_auto_connect_add(struct btd_adapter *adapter,
adapter->connect_list = g_slist_append(adapter->connect_list, device);
}
-void adapter_set_device_flags(struct btd_adapter *adapter,
+int adapter_set_device_flags(struct btd_adapter *adapter,
struct btd_device *device, uint32_t flags,
mgmt_request_func_t func, void *user_data)
{
uint8_t bdaddr_type;
bool ll_privacy = btd_adapter_has_settings(adapter,
MGMT_SETTING_LL_PRIVACY);
+ unsigned int id;
if (!btd_has_kernel_features(KERNEL_CONN_CONTROL) ||
- (supported | flags) != supported)
- return;
+ (supported && (supported | flags) != supported))
+ return -EINVAL;
/* Check if changing flags are pending */
if ((current ^ flags) == (flags & pending))
- return;
+ return -EINPROGRESS;
/* Set Device Privacy Mode if it has not set the flag yet. */
if (btd_opts.device_privacy && !(flags & DEVICE_FLAG_DEVICE_PRIVACY))
cp.addr.type = bdaddr_type;
cp.current_flags = cpu_to_le32(flags);
- if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_FLAGS, adapter->dev_id,
- sizeof(cp), &cp, func, user_data, NULL))
+ id = mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_FLAGS, adapter->dev_id,
+ sizeof(cp), &cp, func, user_data, NULL);
+ if (id != 0)
btd_device_set_pending_flags(device, flags);
+
+ return id == 0 ? -EBUSY : 0;
}
static void device_flags_changed_callback(uint16_t index, uint16_t length,
diff --git a/src/adapter.h b/src/adapter.h
index ad81a10..dd0c90d 100644
--- a/src/adapter.h
+++ b/src/adapter.h
typedef void (*adapter_set_device_flags_func_t)(uint8_t status, uint16_t length,
const void *param,
void *user_data);
-void adapter_set_device_flags(struct btd_adapter *adapter,
+int adapter_set_device_flags(struct btd_adapter *adapter,
struct btd_device *device, uint32_t flags,
adapter_set_device_flags_func_t func,
void *user_data);
diff --git a/src/device.c b/src/device.c
index 8d74ae0..91b6cc0 100644
--- a/src/device.c
+++ b/src/device.c
set_wake_allowed_complete, device);
}
+static void set_past_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_set_device_flags *rp = param;
+ struct btd_device *dev = user_data;
+
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Set device flags return status: %s",
+ mgmt_errstr(status));
+ return;
+ }
+
+ if (length < sizeof(*rp)) {
+ error("Too small Set Device Flags complete event: %d", length);
+ return;
+ }
+
+ btd_device_flags_changed(dev, dev->supported_flags, dev->pending_flags);
+}
+
+void device_set_past_support(struct btd_device *device, bool value)
+{
+ uint32_t flags;
+ int err;
+
+ if (!device)
+ return;
+
+ if (btd_device_flags_enabled(device, DEVICE_FLAG_PAST) == value)
+ return;
+
+ DBG("value %s", value ? "true" : "false");
+
+ flags = device->current_flags;
+
+ /* Include the pending flags, or they may get overwritten. */
+ flags |= device->pending_flags;
+
+ if (value)
+ flags |= DEVICE_FLAG_PAST;
+ else
+ flags &= ~DEVICE_FLAG_PAST;
+
+ err = adapter_set_device_flags(device->adapter, device, flags,
+ set_past_complete, device);
+
+ if (err)
+ error("Failed to set past support: %s", strerror(-err));
+}
+
static gboolean
dev_property_get_wake_allowed(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
diff --git a/src/device.h b/src/device.h
index 9ff9cdf..6ed8aff 100644
--- a/src/device.h
+++ b/src/device.h
void device_set_wake_override(struct btd_device *device, bool wake_override);
void device_set_wake_allowed(struct btd_device *device, bool wake_allowed,
guint32 id);
+
+void device_set_past_support(struct btd_device *device, bool value);
+
void device_set_refresh_discovery(struct btd_device *dev, bool refresh);
typedef void (*disconnect_watch) (struct btd_device *device, gboolean removal,