From eee3a46f8b011aa8f93295013aa2cef63dc54ebd Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 1 Sep 2022 22:10:53 +0200 Subject: [PATCH] + bluez-5.65-3 Update PowerState property patch to upstream version --- bluez.spec | 14 +- power-state-adapter-property.patch | 447 +++++++++++++++++++++-------- 2 files changed, 344 insertions(+), 117 deletions(-) diff --git a/bluez.spec b/bluez.spec index abe1bec..26dc422 100644 --- a/bluez.spec +++ b/bluez.spec @@ -6,7 +6,7 @@ Name: bluez Version: 5.65 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Bluetooth utilities License: GPLv2+ URL: http://www.bluez.org/ @@ -17,8 +17,14 @@ Source1: bluez.gitignore # https://github.com/hadess/bluez/commits/obex-5.46 Patch1: 0001-obex-Use-GLib-helper-function-to-manipulate-paths.patch -# https://lore.kernel.org/linux-bluetooth/20220831091912.47894-1-hadess@hadess.net/T/#t +# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=ede7b915980f Patch2: 0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch +# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=abf5ba6b80ad +# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=58021a665b7f +# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=48992da64f52 +# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=6e49216ad47d +# https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=61f4f2895882 +# https://lore.kernel.org/linux-bluetooth/20220901110719.176944-1-hadess@hadess.net/T/#m9c08d004cd5422783ee1d93154f42303bba9169f Patch3: power-state-adapter-property.patch BuildRequires: dbus-devel >= 1.6 @@ -321,6 +327,10 @@ install emulator/btvirt ${RPM_BUILD_ROOT}/%{_libexecdir}/bluetooth/ %{_userunitdir}/obex.service %changelog +* Thu Sep 01 2022 Bastien Nocera - 5.65-3 ++ bluez-5.65-3 +- Update PowerState property patch to upstream version + * Wed Aug 31 2022 Bastien Nocera - 5.65-2 + bluez-5.65-2 - Add PowerState property implementation diff --git a/power-state-adapter-property.patch b/power-state-adapter-property.patch index f71fab9..1d6f2cd 100644 --- a/power-state-adapter-property.patch +++ b/power-state-adapter-property.patch @@ -1,4 +1,4 @@ -From 056efb4e15b4bd4ab26739cddc2b1ad7a2dfa0f8 Mon Sep 17 00:00:00 2001 +From a282944af40893fc79f0ae3aa1bf52031aa07ffe Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 31 Aug 2022 10:56:06 +0200 Subject: [PATCH 1/6] adapter: Keep track of whether the adapter is rfkill'ed @@ -7,13 +7,14 @@ Instead of only replying to D-Bus requests with an error saying the adapter is blocked, keep track of the rfkill being enabled or disabled so we know the rfkill state of the adapter at all times. --- - src/adapter.c | 25 +++++++++++++++++++++++-- + src/adapter.c | 25 +++++++++++++-- src/adapter.h | 1 + - src/rfkill.c | 8 ++++++-- - 3 files changed, 30 insertions(+), 4 deletions(-) + src/btd.h | 1 + + src/rfkill.c | 89 ++++++++++++++++++++++++++++++++++++++------------- + 4 files changed, 91 insertions(+), 25 deletions(-) diff --git a/src/adapter.c b/src/adapter.c -index b453e86a0..641db67f9 100644 +index 51b099dae..7c11a688d 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -250,6 +250,7 @@ struct btd_adapter { @@ -33,7 +34,7 @@ index b453e86a0..641db67f9 100644 adapter->pending_settings &= ~data->setting; return; } -@@ -2914,10 +2917,12 @@ static void property_set_mode_complete(uint8_t status, uint16_t length, +@@ -2947,10 +2950,12 @@ static void property_set_mode_complete(uint8_t status, uint16_t length, btd_error(adapter->dev_id, "Failed to set mode: %s (0x%02x)", mgmt_errstr(status), status); @@ -48,30 +49,51 @@ index b453e86a0..641db67f9 100644 g_dbus_pending_property_error(data->id, dbus_err, mgmt_errstr(status)); -@@ -7548,6 +7553,12 @@ int btd_cancel_authorization(guint id) +@@ -6681,6 +6686,7 @@ static void load_config(struct btd_adapter *adapter) + static struct btd_adapter *btd_adapter_new(uint16_t index) + { + struct btd_adapter *adapter; ++ int blocked; + + adapter = g_try_new0(struct btd_adapter, 1); + if (!adapter) +@@ -6689,6 +6695,9 @@ static struct btd_adapter *btd_adapter_new(uint16_t index) + adapter->dev_id = index; + adapter->mgmt = mgmt_ref(mgmt_primary); + adapter->pincode_requested = false; ++ blocked = rfkill_get_blocked(index); ++ if (blocked > 0) ++ adapter->blocked = true; + + /* + * Setup default configuration values. These are either adapter +@@ -6714,6 +6723,8 @@ static struct btd_adapter *btd_adapter_new(uint16_t index) + DBG("Modalias: %s", adapter->modalias); + DBG("Discoverable timeout: %u seconds", adapter->discoverable_timeout); + DBG("Pairable timeout: %u seconds", adapter->pairable_timeout); ++ if (blocked > 0) ++ DBG("Blocked: yes"); + + adapter->auths = g_queue_new(); + adapter->exps = queue_new(); +@@ -7581,6 +7592,9 @@ int btd_cancel_authorization(guint id) int btd_adapter_restore_powered(struct btd_adapter *adapter) { -+ if (adapter->blocked) { ++ if (adapter->blocked) + adapter->blocked = false; -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); -+ } + if (btd_adapter_get_powered(adapter)) return 0; -@@ -7556,6 +7567,16 @@ int btd_adapter_restore_powered(struct btd_adapter *adapter) +@@ -7589,6 +7603,13 @@ int btd_adapter_restore_powered(struct btd_adapter *adapter) return 0; } +int btd_adapter_set_blocked(struct btd_adapter *adapter) +{ -+ if (!adapter->blocked) { ++ if (!adapter->blocked) + adapter->blocked = true; -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); -+ } + return 0; +} + @@ -79,10 +101,10 @@ index b453e86a0..641db67f9 100644 btd_adapter_pin_cb_t cb) { diff --git a/src/adapter.h b/src/adapter.h -index b09044edd..332c0b239 100644 +index f38f473b7..78eb069ae 100644 --- a/src/adapter.h +++ b/src/adapter.h -@@ -143,6 +143,7 @@ guint btd_request_authorization_cable_configured(const bdaddr_t *src, const bdad +@@ -144,6 +144,7 @@ guint btd_request_authorization_cable_configured(const bdaddr_t *src, const bdad int btd_cancel_authorization(guint id); int btd_adapter_restore_powered(struct btd_adapter *adapter); @@ -90,19 +112,96 @@ index b09044edd..332c0b239 100644 typedef ssize_t (*btd_adapter_pin_cb_t) (struct btd_adapter *adapter, struct btd_device *dev, char *out, bool *display, +diff --git a/src/btd.h b/src/btd.h +index c02b2691e..63be6d8d4 100644 +--- a/src/btd.h ++++ b/src/btd.h +@@ -144,6 +144,7 @@ void plugin_cleanup(void); + + void rfkill_init(void); + void rfkill_exit(void); ++int rfkill_get_blocked(uint16_t index); + + GKeyFile *btd_get_main_conf(void); + bool btd_kernel_experimental_enabled(const char *uuid); diff --git a/src/rfkill.c b/src/rfkill.c -index 2099c5ac5..93f8e0e12 100644 +index 2099c5ac5..a0a50d9e4 100644 --- a/src/rfkill.c +++ b/src/rfkill.c -@@ -61,6 +61,7 @@ static gboolean rfkill_event(GIOChannel *chan, +@@ -55,12 +55,71 @@ struct rfkill_event { + }; + #define RFKILL_EVENT_SIZE_V1 8 + ++static int get_adapter_id_for_rfkill(int rfkill_id) ++{ ++ char sysname[PATH_MAX]; ++ int namefd; ++ ++ snprintf(sysname, sizeof(sysname) - 1, ++ "/sys/class/rfkill/rfkill%u/name", rfkill_id); ++ ++ namefd = open(sysname, O_RDONLY); ++ if (namefd < 0) ++ return -1; ++ ++ memset(sysname, 0, sizeof(sysname)); ++ ++ if (read(namefd, sysname, sizeof(sysname) - 1) < 4) { ++ close(namefd); ++ return -1; ++ } ++ ++ close(namefd); ++ ++ if (g_str_has_prefix(sysname, "hci") == FALSE) ++ return -1; ++ ++ return atoi(sysname + 3); ++} ++ ++int rfkill_get_blocked(uint16_t index) ++{ ++ int fd; ++ int blocked = -1; ++ ++ fd = open("/dev/rfkill", O_RDWR); ++ if (fd < 0) { ++ DBG("Failed to open RFKILL control device"); ++ return -1; ++ } ++ ++ while (1) { ++ struct rfkill_event event = { 0 }; ++ int id; ++ ssize_t len; ++ ++ len = read(fd, &event, sizeof(event)); ++ if (len < RFKILL_EVENT_SIZE_V1) ++ break; ++ ++ id = get_adapter_id_for_rfkill(event.idx); ++ ++ if (index == id) { ++ blocked = event.soft || event.hard; ++ break; ++ } ++ } ++ close(fd); ++ ++ return blocked; ++} ++ + static gboolean rfkill_event(GIOChannel *chan, + GIOCondition cond, gpointer data) + { struct rfkill_event event = { 0 }; struct btd_adapter *adapter; - char sysname[PATH_MAX]; +- char sysname[PATH_MAX]; + bool blocked = false; ssize_t len; int fd, id; -@@ -84,7 +85,7 @@ static gboolean rfkill_event(GIOChannel *chan, +@@ -84,7 +143,7 @@ static gboolean rfkill_event(GIOChannel *chan, event.soft, event.hard); if (event.soft || event.hard) @@ -111,7 +210,35 @@ index 2099c5ac5..93f8e0e12 100644 if (event.op != RFKILL_OP_CHANGE) return TRUE; -@@ -122,7 +123,10 @@ static gboolean rfkill_event(GIOChannel *chan, +@@ -93,26 +152,7 @@ static gboolean rfkill_event(GIOChannel *chan, + event.type != RFKILL_TYPE_ALL) + return TRUE; + +- snprintf(sysname, sizeof(sysname) - 1, +- "/sys/class/rfkill/rfkill%u/name", event.idx); +- +- fd = open(sysname, O_RDONLY); +- if (fd < 0) +- return TRUE; +- +- memset(sysname, 0, sizeof(sysname)); +- +- if (read(fd, sysname, sizeof(sysname) - 1) < 4) { +- close(fd); +- return TRUE; +- } +- +- close(fd); +- +- if (g_str_has_prefix(sysname, "hci") == FALSE) +- return TRUE; +- +- id = atoi(sysname + 3); ++ id = get_adapter_id_for_rfkill(event.idx); + if (id < 0) + return TRUE; + +@@ -122,7 +162,10 @@ static gboolean rfkill_event(GIOChannel *chan, DBG("RFKILL unblock for hci%d", id); @@ -127,9 +254,9 @@ index 2099c5ac5..93f8e0e12 100644 2.37.2 -From 09a19a669b99f9294980642eaaddd2419e8b4f12 Mon Sep 17 00:00:00 2001 +From 7711e4081bf6096f2210f5b5d715f005d654abf1 Mon Sep 17 00:00:00 2001 From: Bastien Nocera -Date: Wed, 31 Aug 2022 11:00:38 +0200 +Date: Wed, 31 Aug 2022 13:23:23 +0200 Subject: [PATCH 2/6] adapter: Implement PowerState property This property should allow any program to show whether an adapter is in @@ -151,71 +278,108 @@ rfkill was unblocked. See https://gitlab.gnome.org/GNOME/gnome-bluetooth/-/issues/121 and the original https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5773 --- - src/adapter.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 87 insertions(+), 1 deletion(-) + src/adapter.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 128 insertions(+), 11 deletions(-) diff --git a/src/adapter.c b/src/adapter.c -index 641db67f9..e295ef247 100644 +index 7c11a688d..59afbcb6d 100644 --- a/src/adapter.c +++ b/src/adapter.c -@@ -239,6 +239,12 @@ struct btd_adapter_pin_cb_iter { +@@ -239,6 +239,14 @@ struct btd_adapter_pin_cb_iter { /* When the iterator reaches the end, it is NULL and attempt is 0 */ }; +enum { -+ ADAPTER_POWER_STATE_TARGET_NONE = 0, -+ ADAPTER_POWER_STATE_TARGET_OFF, -+ ADAPTER_POWER_STATE_TARGET_ON ++ ADAPTER_POWER_STATE_OFF, ++ ADAPTER_POWER_STATE_ON, ++ ADAPTER_POWER_STATE_ON_DISABLING, ++ ADAPTER_POWER_STATE_OFF_ENABLING, ++ ADAPTER_POWER_STATE_OFF_BLOCKED, +}; + struct btd_adapter { int ref_count; -@@ -253,6 +259,7 @@ struct btd_adapter { - bool blocked; /* whether rfkill is enabled */ +@@ -250,9 +258,9 @@ struct btd_adapter { + uint32_t dev_class; /* controller class of device */ + char *name; /* controller device name */ + char *short_name; /* controller short name */ +- bool blocked; /* whether rfkill is enabled */ uint32_t supported_settings; /* controller supported settings */ uint32_t pending_settings; /* pending controller settings */ -+ uint32_t power_state_target; /* the target power state */ ++ uint32_t power_state; /* the power state */ uint32_t current_settings; /* current controller settings */ char *path; /* adapter object path */ -@@ -580,6 +587,8 @@ static void settings_changed(struct btd_adapter *adapter, uint32_t settings) - if (changed_mask & MGMT_SETTING_POWERED) { - g_dbus_emit_property_changed(dbus_conn, adapter->path, - ADAPTER_INTERFACE, "Powered"); -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); +@@ -326,6 +334,24 @@ struct btd_adapter { + struct queue *exps; + }; - if (adapter->current_settings & MGMT_SETTING_POWERED) { - adapter_start(adapter); -@@ -619,6 +628,16 @@ static void settings_changed(struct btd_adapter *adapter, uint32_t settings) ++static char *adapter_power_state_str(uint32_t power_state) ++{ ++ switch (power_state) { ++ case ADAPTER_POWER_STATE_OFF: ++ return "off"; ++ case ADAPTER_POWER_STATE_ON: ++ return "on"; ++ case ADAPTER_POWER_STATE_ON_DISABLING: ++ return "on-disabling"; ++ case ADAPTER_POWER_STATE_OFF_ENABLING: ++ return "off-enabling"; ++ case ADAPTER_POWER_STATE_OFF_BLOCKED: ++ return "off-blocked"; ++ } ++ DBG("Invalid power state %d", power_state); ++ return ""; ++} ++ + typedef enum { + ADAPTER_AUTHORIZE_DISCONNECTED = 0, + ADAPTER_AUTHORIZE_CHECK_CONNECTED +@@ -619,6 +645,29 @@ static void settings_changed(struct btd_adapter *adapter, uint32_t settings) } } -+static void reset_power_state_target(struct btd_adapter *adapter, uint8_t value) ++static void adapter_set_power_state(struct btd_adapter *adapter, uint32_t value) +{ -+ if ((value && -+ adapter->power_state_target == ADAPTER_POWER_STATE_TARGET_ON) || -+ (!value && -+ adapter->power_state_target == ADAPTER_POWER_STATE_TARGET_OFF)) { -+ adapter->power_state_target = ADAPTER_POWER_STATE_TARGET_NONE; ++ if (adapter->power_state == value) ++ return; ++ ++ DBG("%s", adapter_power_state_str(value)); ++ adapter->power_state = value; ++ g_dbus_emit_property_changed(dbus_conn, adapter->path, ++ ADAPTER_INTERFACE, "PowerState"); ++} ++ ++static void reset_power_state_target(struct btd_adapter *adapter, ++ uint32_t value) ++{ ++ if (value && ++ adapter->power_state == ADAPTER_POWER_STATE_OFF_ENABLING) { ++ adapter_set_power_state(adapter, ADAPTER_POWER_STATE_ON); ++ } else if (!value && ++ adapter->power_state == ADAPTER_POWER_STATE_ON_DISABLING) { ++ adapter_set_power_state(adapter, ADAPTER_POWER_STATE_OFF); + } +} + static void new_settings_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { -@@ -636,6 +655,9 @@ static void new_settings_callback(uint16_t index, uint16_t length, +@@ -636,6 +685,12 @@ static void new_settings_callback(uint16_t index, uint16_t length, if (settings == adapter->current_settings) return; -+ if ((adapter->current_settings ^ settings) & MGMT_SETTING_POWERED) -+ reset_power_state_target(adapter, settings & MGMT_SETTING_POWERED ? 0x01 : 0x00); ++ if ((adapter->current_settings ^ settings) & MGMT_SETTING_POWERED) { ++ reset_power_state_target(adapter, ++ settings & MGMT_SETTING_POWERED ? ++ 0x01 : 0x00); ++ } + DBG("Settings: 0x%08x", settings); settings_changed(adapter, settings); -@@ -644,6 +666,7 @@ static void new_settings_callback(uint16_t index, uint16_t length, +@@ -644,6 +699,7 @@ static void new_settings_callback(uint16_t index, uint16_t length, struct set_mode_data { struct btd_adapter *adapter; uint32_t setting; @@ -223,28 +387,33 @@ index 641db67f9..e295ef247 100644 }; static void set_mode_complete(uint8_t status, uint16_t length, -@@ -658,6 +681,8 @@ static void set_mode_complete(uint8_t status, uint16_t length, +@@ -656,8 +712,12 @@ static void set_mode_complete(uint8_t status, uint16_t length, + btd_error(adapter->dev_id, "Failed to set mode: %s (0x%02x)", + mgmt_errstr(status), status); if (status == MGMT_STATUS_RFKILLED) - adapter->blocked = true; +- adapter->blocked = true; ++ adapter_set_power_state(adapter, ++ ADAPTER_POWER_STATE_OFF_BLOCKED); adapter->pending_settings &= ~data->setting; -+ if (data->setting & MGMT_SETTING_POWERED) ++ if (status != MGMT_STATUS_RFKILLED && ++ data->setting & MGMT_SETTING_POWERED) + reset_power_state_target(adapter, data->value); return; } -@@ -695,6 +720,11 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, +@@ -695,6 +755,11 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, switch (opcode) { case MGMT_OP_SET_POWERED: setting = MGMT_SETTING_POWERED; -+ adapter->power_state_target = mode ? -+ ADAPTER_POWER_STATE_TARGET_ON : -+ ADAPTER_POWER_STATE_TARGET_OFF; -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); ++ if (adapter->power_state != ADAPTER_POWER_STATE_OFF_BLOCKED) { ++ adapter_set_power_state(adapter, mode ? ++ ADAPTER_POWER_STATE_OFF_ENABLING : ++ ADAPTER_POWER_STATE_ON_DISABLING); ++ } break; case MGMT_OP_SET_CONNECTABLE: setting = MGMT_SETTING_CONNECTABLE; -@@ -715,6 +745,7 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, +@@ -715,6 +780,7 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, data = g_new0(struct set_mode_data, 1); data->adapter = adapter; data->setting = setting; @@ -252,7 +421,7 @@ index 641db67f9..e295ef247 100644 if (mgmt_send(adapter->mgmt, opcode, adapter->dev_id, sizeof(cp), &cp, -@@ -722,8 +753,13 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, +@@ -722,8 +788,13 @@ static bool set_mode(struct btd_adapter *adapter, uint16_t opcode, adapter->pending_settings |= setting; return true; } @@ -260,14 +429,14 @@ index 641db67f9..e295ef247 100644 g_free(data); + if (setting == MGMT_SETTING_POWERED) { + /* cancel the earlier setting */ -+ adapter->power_state_target = ADAPTER_POWER_STATE_TARGET_NONE; -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); ++ adapter_set_power_state(adapter, mode ? ++ ADAPTER_POWER_STATE_OFF : ++ ADAPTER_POWER_STATE_ON); + } btd_error(adapter->dev_id, "Failed to set mode for index %u", adapter->dev_id); -@@ -2901,6 +2937,7 @@ struct property_set_data { +@@ -2934,6 +3005,7 @@ struct property_set_data { struct btd_adapter *adapter; uint32_t setting; GDBusPendingPropertySet id; @@ -275,46 +444,56 @@ index 641db67f9..e295ef247 100644 }; static void property_set_mode_complete(uint8_t status, uint16_t length, -@@ -2928,6 +2965,8 @@ static void property_set_mode_complete(uint8_t status, uint16_t length, +@@ -2952,7 +3024,8 @@ static void property_set_mode_complete(uint8_t status, uint16_t length, + + if (status == MGMT_STATUS_RFKILLED) { + dbus_err = ERROR_INTERFACE ".Blocked"; +- adapter->blocked = true; ++ adapter_set_power_state(adapter, ++ ADAPTER_POWER_STATE_OFF_BLOCKED); + } else { + dbus_err = ERROR_INTERFACE ".Failed"; + } +@@ -2961,6 +3034,9 @@ static void property_set_mode_complete(uint8_t status, uint16_t length, mgmt_errstr(status)); adapter->pending_settings &= ~data->setting; -+ if (data->setting & MGMT_SETTING_POWERED) ++ if (status != MGMT_STATUS_RFKILLED && ++ data->setting & MGMT_SETTING_POWERED) + reset_power_state_target(adapter, data->value); return; } -@@ -3051,6 +3090,16 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, +@@ -3084,6 +3160,15 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, data->adapter = adapter; data->setting = setting; data->id = id; + data->setting = setting; + data->value = mode; + -+ if (setting == MGMT_SETTING_POWERED) { -+ adapter->power_state_target = mode ? -+ ADAPTER_POWER_STATE_TARGET_ON : -+ ADAPTER_POWER_STATE_TARGET_OFF; -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); ++ if (setting == MGMT_SETTING_POWERED && ++ adapter->power_state != ADAPTER_POWER_STATE_OFF_BLOCKED) { ++ adapter_set_power_state(adapter, mode ? ++ ADAPTER_POWER_STATE_OFF_ENABLING : ++ ADAPTER_POWER_STATE_ON_DISABLING); + } if (mgmt_send(adapter->mgmt, opcode, adapter->dev_id, len, param, property_set_mode_complete, data, g_free) > 0) { -@@ -3059,6 +3108,12 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, +@@ -3092,6 +3177,12 @@ static void property_set_mode(struct btd_adapter *adapter, uint32_t setting, } g_free(data); + if (setting == MGMT_SETTING_POWERED) { + /* cancel the earlier setting */ -+ adapter->power_state_target = ADAPTER_POWER_STATE_TARGET_NONE; -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); ++ adapter_set_power_state(adapter, mode ? ++ ADAPTER_POWER_STATE_OFF : ++ ADAPTER_POWER_STATE_ON); + } failed: btd_error(adapter->dev_id, "Failed to set mode for index %u", -@@ -3090,6 +3145,31 @@ static void property_set_powered(const GDBusPropertyTable *property, +@@ -3123,6 +3214,18 @@ static void property_set_powered(const GDBusPropertyTable *property, property_set_mode(adapter, MGMT_SETTING_POWERED, iter, id); } @@ -324,20 +503,7 @@ index 641db67f9..e295ef247 100644 + struct btd_adapter *adapter = user_data; + const char *str; + -+ if (adapter->blocked) { -+ str = "off-blocked"; -+ } else if (adapter->power_state_target == ADAPTER_POWER_STATE_TARGET_NONE) { -+ if (adapter->current_settings & MGMT_SETTING_POWERED) -+ str = "on"; -+ else -+ str = "off"; -+ } else { -+ if (adapter->power_state_target == ADAPTER_POWER_STATE_TARGET_ON) -+ str = "off-enabling"; -+ else -+ str = "on-disabling"; -+ } -+ ++ str = adapter_power_state_str(adapter->power_state); + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str); + + return TRUE; @@ -346,7 +512,7 @@ index 641db67f9..e295ef247 100644 static gboolean property_get_discoverable(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { -@@ -3728,6 +3808,8 @@ static const GDBusPropertyTable adapter_properties[] = { +@@ -3761,6 +3864,8 @@ static const GDBusPropertyTable adapter_properties[] = { { "Alias", "s", property_get_alias, property_set_alias }, { "Class", "u", property_get_class }, { "Powered", "b", property_get_powered, property_set_powered }, @@ -355,29 +521,80 @@ index 641db67f9..e295ef247 100644 { "Discoverable", "b", property_get_discoverable, property_set_discoverable }, { "DiscoverableTimeout", "u", property_get_discoverable_timeout, -@@ -5534,6 +5616,8 @@ static void adapter_start(struct btd_adapter *adapter) +@@ -5567,6 +5672,7 @@ static void adapter_start(struct btd_adapter *adapter) { g_dbus_emit_property_changed(dbus_conn, adapter->path, ADAPTER_INTERFACE, "Powered"); -+ g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); ++ adapter_set_power_state(adapter, ADAPTER_POWER_STATE_ON); DBG("adapter %s has been enabled", adapter->path); -@@ -7277,6 +7361,8 @@ static void adapter_stop(struct btd_adapter *adapter) +@@ -6697,7 +6803,7 @@ static struct btd_adapter *btd_adapter_new(uint16_t index) + adapter->pincode_requested = false; + blocked = rfkill_get_blocked(index); + if (blocked > 0) +- adapter->blocked = true; ++ adapter->power_state = ADAPTER_POWER_STATE_OFF_BLOCKED; + + /* + * Setup default configuration values. These are either adapter +@@ -6724,7 +6830,8 @@ static struct btd_adapter *btd_adapter_new(uint16_t index) + DBG("Discoverable timeout: %u seconds", adapter->discoverable_timeout); + DBG("Pairable timeout: %u seconds", adapter->pairable_timeout); + if (blocked > 0) +- DBG("Blocked: yes"); ++ DBG("Power state: %s", ++ adapter_power_state_str(adapter->power_state)); + + adapter->auths = g_queue_new(); + adapter->exps = queue_new(); +@@ -7316,6 +7423,9 @@ static void adapter_stop(struct btd_adapter *adapter) g_dbus_emit_property_changed(dbus_conn, adapter->path, ADAPTER_INTERFACE, "Powered"); + g_dbus_emit_property_changed(dbus_conn, adapter->path, -+ ADAPTER_INTERFACE, "PowerState"); ++ ADAPTER_INTERFACE, ++ "PowerState"); DBG("adapter %s has been disabled", adapter->path); } +@@ -7592,10 +7702,18 @@ int btd_cancel_authorization(guint id) + + int btd_adapter_restore_powered(struct btd_adapter *adapter) + { +- if (adapter->blocked) +- adapter->blocked = false; ++ bool powered; + +- if (btd_adapter_get_powered(adapter)) ++ powered = btd_adapter_get_powered(adapter); ++ if (adapter->power_state == ADAPTER_POWER_STATE_OFF_BLOCKED && ++ rfkill_get_blocked(adapter->dev_id) == 0) { ++ adapter_set_power_state(adapter, ++ powered ? ++ ADAPTER_POWER_STATE_ON : ++ ADAPTER_POWER_STATE_OFF); ++ } ++ ++ if (powered) + return 0; + + set_mode(adapter, MGMT_OP_SET_POWERED, 0x01); +@@ -7605,8 +7723,7 @@ int btd_adapter_restore_powered(struct btd_adapter *adapter) + + int btd_adapter_set_blocked(struct btd_adapter *adapter) + { +- if (!adapter->blocked) +- adapter->blocked = true; ++ adapter_set_power_state(adapter, ADAPTER_POWER_STATE_OFF_BLOCKED); + return 0; + } + -- 2.37.2 -From 9c682a0d9409d06449f593e76889117693934b7c Mon Sep 17 00:00:00 2001 +From f86d0c8092ca8f9fee7c140f5f4df3938ea1ec29 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 31 Aug 2022 11:01:22 +0200 Subject: [PATCH 3/6] client: Print the PowerState property @@ -387,7 +604,7 @@ Subject: [PATCH 3/6] client: Print the PowerState property 1 file changed, 1 insertion(+) diff --git a/client/main.c b/client/main.c -index 19139d15b..ddd97c23c 100644 +index 6773d5262..2816e880f 100644 --- a/client/main.c +++ b/client/main.c @@ -981,6 +981,7 @@ static void cmd_show(int argc, char *argv[]) @@ -402,7 +619,7 @@ index 19139d15b..ddd97c23c 100644 2.37.2 -From 98aae2c9f3aa45fac28726355799c65d2899637d Mon Sep 17 00:00:00 2001 +From 4b2587ecdb437f6c24d1c42576eb9d4ecb01a7f3 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 31 Aug 2022 11:01:44 +0200 Subject: [PATCH 4/6] adapter-api: Add PowerState property documentation @@ -412,14 +629,14 @@ Subject: [PATCH 4/6] adapter-api: Add PowerState property documentation 1 file changed, 15 insertions(+) diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt -index 48466ab75..28e53a105 100644 +index 48466ab75..9b2721c1b 100644 --- a/doc/adapter-api.txt +++ b/doc/adapter-api.txt @@ -269,6 +269,21 @@ Properties string Address [readonly] restart or unplugging of the adapter it will reset back to false. -+ string PowerState [readonly] ++ string PowerState [readonly, experimental] + + The power state of an adapter. + @@ -441,7 +658,7 @@ index 48466ab75..28e53a105 100644 2.37.2 -From 8d6f121eff28c3d2488763d67c39a6a4ac91964c Mon Sep 17 00:00:00 2001 +From 0e723ee0f8e9024b6319267637253e5d7f982ef1 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 31 Aug 2022 11:05:56 +0200 Subject: [PATCH 5/6] adapter: Fix typo in function name @@ -451,10 +668,10 @@ Subject: [PATCH 5/6] adapter: Fix typo in function name 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapter.c b/src/adapter.c -index e295ef247..11a21ca5c 100644 +index 59afbcb6d..8fb2acdc8 100644 --- a/src/adapter.c +++ b/src/adapter.c -@@ -3455,7 +3455,7 @@ static gboolean property_get_experimental(const GDBusPropertyTable *property, +@@ -3511,7 +3511,7 @@ static gboolean property_get_experimental(const GDBusPropertyTable *property, return TRUE; } @@ -463,7 +680,7 @@ index e295ef247..11a21ca5c 100644 void *data) { struct btd_adapter *adapter = data; -@@ -3823,7 +3823,7 @@ static const GDBusPropertyTable adapter_properties[] = { +@@ -3879,7 +3879,7 @@ static const GDBusPropertyTable adapter_properties[] = { property_exists_modalias }, { "Roles", "as", property_get_roles }, { "ExperimentalFeatures", "as", property_get_experimental, NULL, @@ -476,7 +693,7 @@ index e295ef247..11a21ca5c 100644 2.37.2 -From 6ab6b79bae44bbb228746f2f2ce188809e493f2b Mon Sep 17 00:00:00 2001 +From 70309219acd4c81e3a9e2b3652d2d93eb08b0aee Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 31 Aug 2022 11:16:34 +0200 Subject: [PATCH 6/6] adapter: Remove experimental flag for PowerState @@ -488,10 +705,10 @@ and the reliability sufficient. 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/adapter.c b/src/adapter.c -index 11a21ca5c..2a4a0a977 100644 +index 8fb2acdc8..841096d7f 100644 --- a/src/adapter.c +++ b/src/adapter.c -@@ -3808,8 +3808,7 @@ static const GDBusPropertyTable adapter_properties[] = { +@@ -3864,8 +3864,7 @@ static const GDBusPropertyTable adapter_properties[] = { { "Alias", "s", property_get_alias, property_set_alias }, { "Class", "u", property_get_class }, { "Powered", "b", property_get_powered, property_set_powered },