diff options
Diffstat (limited to 'net-wireless/bluez/files/0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch')
-rw-r--r-- | net-wireless/bluez/files/0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/net-wireless/bluez/files/0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch b/net-wireless/bluez/files/0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch new file mode 100644 index 000000000000..b9b432fadff0 --- /dev/null +++ b/net-wireless/bluez/files/0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch @@ -0,0 +1,170 @@ +From ede7b915980fbc80eff80aa189c35ca016956c61 Mon Sep 17 00:00:00 2001 +From: Archie Pusaka <apusaka@chromium.org> +Date: Tue, 23 Aug 2022 12:15:56 +0800 +Subject: [PATCH] adapter: Reset pending settings when receiving MGMT error + +We set the pending settings flag when sending MGMT_SETTING_* +commands to the MGMT layer and clear them when receiving a +successful reply, but we don't clear them when receiving an error +reply. This might cause a setting to be stuck in pending state. + +Therefore, also clear the pending flag when receiving error. +Furthermore, this patch also postpones setting the pending flag +until we queue the MGMT command in order to avoid setting it too +soon but we return early. + +This was caught during power off test, where MGMT_OP_SET_POWERED +returns Authentication Failed because disconnection takes too long. +Future attempts to switch power will then be ignored. + +< HCI Command: Disconnect (0x01|0x0006) plen 3 #17916 [hci0] 12.502908 + Handle: 512 + Reason: Remote Device Terminated due to Power Off (0x15) +> HCI Event: Command Status (0x0f) plen 4 #17917 [hci0] 12.503185 + Disconnect (0x01|0x0006) ncmd 1 + Status: Success (0x00) +@ MGMT Event: Command Status (0x0002) plen 3 {0x0001} [hci0] 14.519491 + Set Powered (0x0005) + Status: Authentication Failed (0x05) += bluetoothd: Failed to set mode: Authentication Failed (0x05) 14.520042 += bluetoothd: adapter /org/bluez/hci0 set power to 0 14.813533 +> HCI Event: Disconnect Complete (0x05) plen 4 #17918 [hci0] 16.509043 + Status: Success (0x00) + Handle: 512 + Reason: Connection Timeout (0x08) + +Reviewed-by: Sonny Sasaka <sonnysasaka@chromium.org> +--- + src/adapter.c | 39 +++++++++++++++++++++++++++++++-------- + 1 file changed, 31 insertions(+), 8 deletions(-) + +diff --git a/src/adapter.c b/src/adapter.c +index ec26aab1a..b453e86a0 100644 +--- a/src/adapter.c ++++ b/src/adapter.c +@@ -640,14 +640,21 @@ static void new_settings_callback(uint16_t index, uint16_t length, + settings_changed(adapter, settings); + } + ++struct set_mode_data { ++ struct btd_adapter *adapter; ++ uint32_t setting; ++}; ++ + static void set_mode_complete(uint8_t status, uint16_t length, + const void *param, void *user_data) + { +- struct btd_adapter *adapter = user_data; ++ struct set_mode_data *data = user_data; ++ struct btd_adapter *adapter = data->adapter; + + if (status != MGMT_STATUS_SUCCESS) { + btd_error(adapter->dev_id, "Failed to set mode: %s (0x%02x)", + mgmt_errstr(status), status); ++ adapter->pending_settings &= ~data->setting; + return; + } + +@@ -677,6 +684,7 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, + { + struct mgmt_mode cp; + uint32_t setting = 0; ++ struct set_mode_data *data; + + memset(&cp, 0, sizeof(cp)); + cp.val = mode; +@@ -699,15 +707,20 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, + break; + } + +- adapter->pending_settings |= setting; +- + DBG("sending set mode command for index %u", adapter->dev_id); + ++ data = g_new0(struct set_mode_data, 1); ++ data->adapter = adapter; ++ data->setting = setting; ++ + if (mgmt_send(adapter->mgmt, opcode, + adapter->dev_id, sizeof(cp), &cp, +- set_mode_complete, adapter, NULL) > 0) ++ set_mode_complete, data, g_free) > 0) { ++ adapter->pending_settings |= setting; + return true; ++ } + ++ g_free(data); + btd_error(adapter->dev_id, "Failed to set mode for index %u", + adapter->dev_id); + +@@ -718,6 +731,7 @@ static bool set_discoverable(struct btd_adapter *adapter, uint8_t mode, + uint16_t timeout) + { + struct mgmt_cp_set_discoverable cp; ++ struct set_mode_data *data; + + memset(&cp, 0, sizeof(cp)); + cp.val = mode; +@@ -734,11 +748,16 @@ static bool set_discoverable(struct btd_adapter *adapter, uint8_t mode, + mode); + } + ++ data = g_new0(struct set_mode_data, 1); ++ data->adapter = adapter; ++ data->setting = 0; ++ + if (mgmt_send(adapter->mgmt, MGMT_OP_SET_DISCOVERABLE, + adapter->dev_id, sizeof(cp), &cp, +- set_mode_complete, adapter, NULL) > 0) ++ set_mode_complete, data, g_free) > 0) + return true; + ++ g_free(data); + btd_error(adapter->dev_id, "Failed to set mode for index %u", + adapter->dev_id); + +@@ -2877,6 +2896,7 @@ static gboolean property_get_mode(struct btd_adapter *adapter, + + struct property_set_data { + struct btd_adapter *adapter; ++ uint32_t setting; + GDBusPendingPropertySet id; + }; + +@@ -2901,6 +2921,8 @@ static void property_set_mode_complete(uint8_t status, uint16_t length, + + g_dbus_pending_property_error(data->id, dbus_err, + mgmt_errstr(status)); ++ ++ adapter->pending_settings &= ~data->setting; + return; + } + +@@ -2969,8 +2991,6 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, + + mode = (enable == TRUE) ? 0x01 : 0x00; + +- adapter->pending_settings |= setting; +- + switch (setting) { + case MGMT_SETTING_POWERED: + opcode = MGMT_OP_SET_POWERED; +@@ -3024,11 +3044,14 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, + goto failed; + + data->adapter = adapter; ++ data->setting = setting; + data->id = id; + + if (mgmt_send(adapter->mgmt, opcode, adapter->dev_id, len, param, +- property_set_mode_complete, data, g_free) > 0) ++ property_set_mode_complete, data, g_free) > 0) { ++ adapter->pending_settings |= setting; + return; ++ } + + g_free(data); + +-- +2.37.2 + |