@@ -5569,6 +5569,7 @@ void adapter_accept_list_remove(struct btd_adapter *adapter,
static void set_device_privacy_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
+ struct btd_device *dev = user_data;
const struct mgmt_rp_set_device_flags *rp = param;
if (status != MGMT_STATUS_SUCCESS) {
@@ -5581,6 +5582,9 @@ static void set_device_privacy_complete(uint8_t status, uint16_t length,
error("Too small Set Device Flags complete event: %d", length);
return;
}
+
+ btd_device_flags_changed(dev, btd_device_get_supported_flags(dev),
+ btd_device_get_pending_flags(dev));
}
static void add_device_complete(uint8_t status, uint16_t length,
@@ -5626,7 +5630,7 @@ static void add_device_complete(uint8_t status, uint16_t length,
adapter_set_device_flags(adapter, dev, flags |
DEVICE_FLAG_DEVICE_PRIVACY,
set_device_privacy_complete,
- NULL);
+ dev);
}
}
}
@@ -5676,6 +5680,7 @@ void adapter_set_device_flags(struct btd_adapter *adapter,
{
struct mgmt_cp_set_device_flags cp;
uint32_t supported = btd_device_get_supported_flags(device);
+ uint32_t pending = btd_device_get_pending_flags(device);
const bdaddr_t *bdaddr;
uint8_t bdaddr_type;
@@ -5683,6 +5688,14 @@ void adapter_set_device_flags(struct btd_adapter *adapter,
(supported | flags) != supported)
return;
+ /* Check if changing flags are pending */
+ if (flags == (flags & pending))
+ return;
+
+ /* Set Device Privacy Mode if it has not set the flag yet. */
+ if (btd_opts.device_privacy && !(flags & DEVICE_FLAG_DEVICE_PRIVACY))
+ flags |= DEVICE_FLAG_DEVICE_PRIVACY & supported & ~pending;
+
bdaddr = device_get_address(device);
bdaddr_type = btd_device_get_bdaddr_type(device);
@@ -5691,8 +5704,9 @@ void adapter_set_device_flags(struct btd_adapter *adapter,
cp.addr.type = bdaddr_type;
cp.current_flags = cpu_to_le32(flags);
- mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_FLAGS, adapter->dev_id,
- sizeof(cp), &cp, func, user_data, NULL);
+ if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DEVICE_FLAGS, adapter->dev_id,
+ sizeof(cp), &cp, func, user_data, NULL))
+ btd_device_set_pending_flags(device, flags);
}
static void device_flags_changed_callback(uint16_t index, uint16_t length,
@@ -214,6 +214,7 @@ struct btd_device {
GDBusPendingPropertySet wake_id;
uint32_t supported_flags;
+ uint32_t pending_flags;
uint32_t current_flags;
GSList *svc_callbacks;
GSList *eir_uuids;
@@ -1569,7 +1570,7 @@ static void set_wake_allowed_complete(uint8_t status, uint16_t length,
return;
}
- device_set_wake_allowed_complete(dev);
+ btd_device_flags_changed(dev, dev->supported_flags, dev->pending_flags);
}
void device_set_wake_allowed(struct btd_device *device, bool wake_allowed,
@@ -7243,6 +7244,22 @@ uint32_t btd_device_get_supported_flags(struct btd_device *dev)
return dev->supported_flags;
}
+void btd_device_set_pending_flags(struct btd_device *dev, uint32_t flags)
+{
+ if (!dev)
+ return;
+
+ dev->pending_flags = flags;
+}
+
+uint32_t btd_device_get_pending_flags(struct btd_device *dev)
+{
+ if (!dev)
+ return 0;
+
+ return dev->pending_flags;
+}
+
/* This event is sent immediately after add device on all mgmt sockets.
* Afterwards, it is only sent to mgmt sockets other than the one which called
* set_device_flags.
@@ -7255,6 +7272,7 @@ void btd_device_flags_changed(struct btd_device *dev, uint32_t supported_flags,
dev->supported_flags = supported_flags;
dev->current_flags = current_flags;
+ dev->pending_flags = 0;
if (!changed_flags)
return;
@@ -191,6 +191,8 @@ int btd_device_connect_services(struct btd_device *dev, GSList *services);
uint32_t btd_device_get_current_flags(struct btd_device *dev);
uint32_t btd_device_get_supported_flags(struct btd_device *dev);
+uint32_t btd_device_get_pending_flags(struct btd_device *dev);
+void btd_device_set_pending_flags(struct btd_device *dev, uint32_t flags);
void btd_device_flags_changed(struct btd_device *dev, uint32_t supported_flags,
uint32_t current_flags);
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> MGMT Set Device Flags overwrites the current_flags so only the last flags set this way would remain active which can be seem in the following sequence when LL Privacy is enabled: @ MGMT Command: Set Device Flags (0x0050) plen 11 LE Address: CF:AC:A6:79:3D:B9 (Static) Current Flags: 0x00000001 Remote Wakeup @ MGMT Event: Command Complete (0x0001) plen 10 Set Device Flags (0x0050) plen 7 Status: Success (0x00) LE Address: CF:AC:A6:79:3D:B9 (Static) @ MGMT Command: Set Device Flags (0x0050) plen 11 LE Address: CF:AC:A6:79:3D:B9 (Static) Current Flags: 0x00000002 Device Privacy Mode @ MGMT Event: Command Complete (0x0001) plen 10 Set Device Flags (0x0050) plen 7 Status: Success (0x00) LE Address: CF:AC:A6:79:3D:B9 (Static) In order to do this properly the code needs to track the pending_flags being set and also call btd_device_flags_changed whenever a change is complete since that event is not generated when MGMT_OP_SET_DEVICE_FLAGS is sent by bluetoothd itself. --- src/adapter.c | 20 +++++++++++++++++--- src/device.c | 20 +++++++++++++++++++- src/device.h | 2 ++ 3 files changed, 38 insertions(+), 4 deletions(-)