+ bluez-5.65-2
Add PowerState property implementation
This commit is contained in:
parent
b9f7a71dec
commit
7d4543521a
170
0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch
Normal file
170
0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch
Normal file
@ -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
|
||||
|
10
bluez.spec
10
bluez.spec
@ -6,7 +6,7 @@
|
||||
|
||||
Name: bluez
|
||||
Version: 5.65
|
||||
Release: 1%{?dist}
|
||||
Release: 2%{?dist}
|
||||
Summary: Bluetooth utilities
|
||||
License: GPLv2+
|
||||
URL: http://www.bluez.org/
|
||||
@ -17,6 +17,10 @@ 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
|
||||
Patch2: 0001-adapter-Reset-pending-settings-when-receiving-MGMT-e.patch
|
||||
Patch3: power-state-adapter-property.patch
|
||||
|
||||
BuildRequires: dbus-devel >= 1.6
|
||||
BuildRequires: glib2-devel
|
||||
BuildRequires: libell-devel >= 0.37
|
||||
@ -315,6 +319,10 @@ install emulator/btvirt ${RPM_BUILD_ROOT}/%{_libexecdir}/bluetooth/
|
||||
%{_userunitdir}/obex.service
|
||||
|
||||
%changelog
|
||||
* Wed Aug 31 2022 Bastien Nocera <bnocera@redhat.com> - 5.65-2
|
||||
+ bluez-5.65-2
|
||||
- Add PowerState property implementation
|
||||
|
||||
* Thu Jul 28 2022 Peter Robinson <pbrobinson@fedoraproject.org> - 5.65-1
|
||||
- Update to 5.65
|
||||
|
||||
|
506
power-state-adapter-property.patch
Normal file
506
power-state-adapter-property.patch
Normal file
@ -0,0 +1,506 @@
|
||||
From 056efb4e15b4bd4ab26739cddc2b1ad7a2dfa0f8 Mon Sep 17 00:00:00 2001
|
||||
From: Bastien Nocera <hadess@hadess.net>
|
||||
Date: Wed, 31 Aug 2022 10:56:06 +0200
|
||||
Subject: [PATCH 1/6] adapter: Keep track of whether the adapter is rfkill'ed
|
||||
|
||||
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.h | 1 +
|
||||
src/rfkill.c | 8 ++++++--
|
||||
3 files changed, 30 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/adapter.c b/src/adapter.c
|
||||
index b453e86a0..641db67f9 100644
|
||||
--- a/src/adapter.c
|
||||
+++ b/src/adapter.c
|
||||
@@ -250,6 +250,7 @@ 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 current_settings; /* current controller settings */
|
||||
@@ -654,6 +655,8 @@ static void set_mode_complete(uint8_t status, uint16_t length,
|
||||
if (status != MGMT_STATUS_SUCCESS) {
|
||||
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->pending_settings &= ~data->setting;
|
||||
return;
|
||||
}
|
||||
@@ -2914,10 +2917,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);
|
||||
|
||||
- if (status == MGMT_STATUS_RFKILLED)
|
||||
+ if (status == MGMT_STATUS_RFKILLED) {
|
||||
dbus_err = ERROR_INTERFACE ".Blocked";
|
||||
- else
|
||||
+ adapter->blocked = true;
|
||||
+ } else {
|
||||
dbus_err = ERROR_INTERFACE ".Failed";
|
||||
+ }
|
||||
|
||||
g_dbus_pending_property_error(data->id, dbus_err,
|
||||
mgmt_errstr(status));
|
||||
@@ -7548,6 +7553,12 @@ int btd_cancel_authorization(guint id)
|
||||
|
||||
int btd_adapter_restore_powered(struct btd_adapter *adapter)
|
||||
{
|
||||
+ 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)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int btd_adapter_set_blocked(struct btd_adapter *adapter)
|
||||
+{
|
||||
+ if (!adapter->blocked) {
|
||||
+ adapter->blocked = true;
|
||||
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
|
||||
+ ADAPTER_INTERFACE, "PowerState");
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void btd_adapter_register_pin_cb(struct btd_adapter *adapter,
|
||||
btd_adapter_pin_cb_t cb)
|
||||
{
|
||||
diff --git a/src/adapter.h b/src/adapter.h
|
||||
index b09044edd..332c0b239 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
|
||||
int btd_cancel_authorization(guint id);
|
||||
|
||||
int btd_adapter_restore_powered(struct btd_adapter *adapter);
|
||||
+int btd_adapter_set_blocked(struct btd_adapter *adapter);
|
||||
|
||||
typedef ssize_t (*btd_adapter_pin_cb_t) (struct btd_adapter *adapter,
|
||||
struct btd_device *dev, char *out, bool *display,
|
||||
diff --git a/src/rfkill.c b/src/rfkill.c
|
||||
index 2099c5ac5..93f8e0e12 100644
|
||||
--- a/src/rfkill.c
|
||||
+++ b/src/rfkill.c
|
||||
@@ -61,6 +61,7 @@ static gboolean rfkill_event(GIOChannel *chan,
|
||||
struct rfkill_event event = { 0 };
|
||||
struct btd_adapter *adapter;
|
||||
char sysname[PATH_MAX];
|
||||
+ bool blocked = false;
|
||||
ssize_t len;
|
||||
int fd, id;
|
||||
|
||||
@@ -84,7 +85,7 @@ static gboolean rfkill_event(GIOChannel *chan,
|
||||
event.soft, event.hard);
|
||||
|
||||
if (event.soft || event.hard)
|
||||
- return TRUE;
|
||||
+ blocked = true;
|
||||
|
||||
if (event.op != RFKILL_OP_CHANGE)
|
||||
return TRUE;
|
||||
@@ -122,7 +123,10 @@ static gboolean rfkill_event(GIOChannel *chan,
|
||||
|
||||
DBG("RFKILL unblock for hci%d", id);
|
||||
|
||||
- btd_adapter_restore_powered(adapter);
|
||||
+ if (blocked)
|
||||
+ btd_adapter_set_blocked(adapter);
|
||||
+ else
|
||||
+ btd_adapter_restore_powered(adapter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
--
|
||||
2.37.2
|
||||
|
||||
|
||||
From 09a19a669b99f9294980642eaaddd2419e8b4f12 Mon Sep 17 00:00:00 2001
|
||||
From: Bastien Nocera <hadess@hadess.net>
|
||||
Date: Wed, 31 Aug 2022 11:00:38 +0200
|
||||
Subject: [PATCH 2/6] adapter: Implement PowerState property
|
||||
|
||||
This property should allow any program to show whether an adapter is in
|
||||
the process of being turned on.
|
||||
|
||||
As turning on an adapter isn't instantaneous, it's important that the UI
|
||||
reflects the transitional state of the adapter's power, and doesn't
|
||||
assume the device is already turned on but not yet working, or still off
|
||||
despite having requested for it to be turned on, in both cases making
|
||||
the UI feel unresponsive.
|
||||
|
||||
This can also not be implemented in front-ends directly as, then,
|
||||
the status of an adapter wouldn't be reflected correctly in the Settings
|
||||
window if it's turned on in the system menu. Implementing it in the
|
||||
front-ends would also preclude from having feedback about the state of
|
||||
the adapter when bluetoothd is the one powering up the adapter after the
|
||||
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(-)
|
||||
|
||||
diff --git a/src/adapter.c b/src/adapter.c
|
||||
index 641db67f9..e295ef247 100644
|
||||
--- a/src/adapter.c
|
||||
+++ b/src/adapter.c
|
||||
@@ -239,6 +239,12 @@ 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
|
||||
+};
|
||||
+
|
||||
struct btd_adapter {
|
||||
int ref_count;
|
||||
|
||||
@@ -253,6 +259,7 @@ struct btd_adapter {
|
||||
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 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");
|
||||
|
||||
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 void reset_power_state_target(struct btd_adapter *adapter, uint8_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;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
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,
|
||||
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);
|
||||
+
|
||||
DBG("Settings: 0x%08x", settings);
|
||||
|
||||
settings_changed(adapter, settings);
|
||||
@@ -644,6 +666,7 @@ static void new_settings_callback(uint16_t index, uint16_t length,
|
||||
struct set_mode_data {
|
||||
struct btd_adapter *adapter;
|
||||
uint32_t setting;
|
||||
+ uint8_t value;
|
||||
};
|
||||
|
||||
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,
|
||||
if (status == MGMT_STATUS_RFKILLED)
|
||||
adapter->blocked = true;
|
||||
adapter->pending_settings &= ~data->setting;
|
||||
+ if (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,
|
||||
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");
|
||||
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,
|
||||
data = g_new0(struct set_mode_data, 1);
|
||||
data->adapter = adapter;
|
||||
data->setting = setting;
|
||||
+ data->value = mode;
|
||||
|
||||
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,
|
||||
adapter->pending_settings |= setting;
|
||||
return true;
|
||||
}
|
||||
-
|
||||
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");
|
||||
+ }
|
||||
btd_error(adapter->dev_id, "Failed to set mode for index %u",
|
||||
adapter->dev_id);
|
||||
|
||||
@@ -2901,6 +2937,7 @@ struct property_set_data {
|
||||
struct btd_adapter *adapter;
|
||||
uint32_t setting;
|
||||
GDBusPendingPropertySet id;
|
||||
+ uint8_t value;
|
||||
};
|
||||
|
||||
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,
|
||||
mgmt_errstr(status));
|
||||
|
||||
adapter->pending_settings &= ~data->setting;
|
||||
+ if (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,
|
||||
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 (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,
|
||||
}
|
||||
|
||||
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");
|
||||
+ }
|
||||
|
||||
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,
|
||||
property_set_mode(adapter, MGMT_SETTING_POWERED, iter, id);
|
||||
}
|
||||
|
||||
+static gboolean property_get_power_state(const GDBusPropertyTable *property,
|
||||
+ DBusMessageIter *iter, void *user_data)
|
||||
+{
|
||||
+ 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";
|
||||
+ }
|
||||
+
|
||||
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static gboolean property_get_discoverable(const GDBusPropertyTable *property,
|
||||
DBusMessageIter *iter, void *user_data)
|
||||
{
|
||||
@@ -3728,6 +3808,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 },
|
||||
+ { "PowerState", "s", property_get_power_state, NULL, NULL,
|
||||
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
|
||||
{ "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)
|
||||
{
|
||||
g_dbus_emit_property_changed(dbus_conn, adapter->path,
|
||||
ADAPTER_INTERFACE, "Powered");
|
||||
+ g_dbus_emit_property_changed(dbus_conn, adapter->path,
|
||||
+ ADAPTER_INTERFACE, "PowerState");
|
||||
|
||||
DBG("adapter %s has been enabled", adapter->path);
|
||||
|
||||
@@ -7277,6 +7361,8 @@ 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");
|
||||
|
||||
DBG("adapter %s has been disabled", adapter->path);
|
||||
}
|
||||
--
|
||||
2.37.2
|
||||
|
||||
|
||||
From 9c682a0d9409d06449f593e76889117693934b7c Mon Sep 17 00:00:00 2001
|
||||
From: Bastien Nocera <hadess@hadess.net>
|
||||
Date: Wed, 31 Aug 2022 11:01:22 +0200
|
||||
Subject: [PATCH 3/6] client: Print the PowerState property
|
||||
|
||||
---
|
||||
client/main.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/client/main.c b/client/main.c
|
||||
index 19139d15b..ddd97c23c 100644
|
||||
--- a/client/main.c
|
||||
+++ b/client/main.c
|
||||
@@ -981,6 +981,7 @@ static void cmd_show(int argc, char *argv[])
|
||||
print_property(adapter->proxy, "Alias");
|
||||
print_property(adapter->proxy, "Class");
|
||||
print_property(adapter->proxy, "Powered");
|
||||
+ print_property(adapter->proxy, "PowerState");
|
||||
print_property(adapter->proxy, "Discoverable");
|
||||
print_property(adapter->proxy, "DiscoverableTimeout");
|
||||
print_property(adapter->proxy, "Pairable");
|
||||
--
|
||||
2.37.2
|
||||
|
||||
|
||||
From 98aae2c9f3aa45fac28726355799c65d2899637d Mon Sep 17 00:00:00 2001
|
||||
From: Bastien Nocera <hadess@hadess.net>
|
||||
Date: Wed, 31 Aug 2022 11:01:44 +0200
|
||||
Subject: [PATCH 4/6] adapter-api: Add PowerState property documentation
|
||||
|
||||
---
|
||||
doc/adapter-api.txt | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
|
||||
index 48466ab75..28e53a105 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]
|
||||
+
|
||||
+ The power state of an adapter.
|
||||
+
|
||||
+ The power state will show whether the adapter is
|
||||
+ turning off, or turning on, as well as being on
|
||||
+ or off.
|
||||
+
|
||||
+ Possible values:
|
||||
+ "on" - powered on
|
||||
+ "off" - powered off
|
||||
+ "off-enabling" - transitioning from "off" to "on"
|
||||
+ "on-disabling" - transitioning from "on" to "off"
|
||||
+ "off-blocked" - blocked by rfkill
|
||||
+
|
||||
boolean Discoverable [readwrite]
|
||||
|
||||
Switch an adapter to discoverable or non-discoverable
|
||||
--
|
||||
2.37.2
|
||||
|
||||
|
||||
From 8d6f121eff28c3d2488763d67c39a6a4ac91964c Mon Sep 17 00:00:00 2001
|
||||
From: Bastien Nocera <hadess@hadess.net>
|
||||
Date: Wed, 31 Aug 2022 11:05:56 +0200
|
||||
Subject: [PATCH 5/6] adapter: Fix typo in function name
|
||||
|
||||
---
|
||||
src/adapter.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/adapter.c b/src/adapter.c
|
||||
index e295ef247..11a21ca5c 100644
|
||||
--- a/src/adapter.c
|
||||
+++ b/src/adapter.c
|
||||
@@ -3455,7 +3455,7 @@ static gboolean property_get_experimental(const GDBusPropertyTable *property,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean property_experimental_exits(const GDBusPropertyTable *property,
|
||||
+static gboolean property_experimental_exists(const GDBusPropertyTable *property,
|
||||
void *data)
|
||||
{
|
||||
struct btd_adapter *adapter = data;
|
||||
@@ -3823,7 +3823,7 @@ static const GDBusPropertyTable adapter_properties[] = {
|
||||
property_exists_modalias },
|
||||
{ "Roles", "as", property_get_roles },
|
||||
{ "ExperimentalFeatures", "as", property_get_experimental, NULL,
|
||||
- property_experimental_exits },
|
||||
+ property_experimental_exists },
|
||||
{ }
|
||||
};
|
||||
|
||||
--
|
||||
2.37.2
|
||||
|
||||
|
||||
From 6ab6b79bae44bbb228746f2f2ce188809e493f2b Mon Sep 17 00:00:00 2001
|
||||
From: Bastien Nocera <hadess@hadess.net>
|
||||
Date: Wed, 31 Aug 2022 11:16:34 +0200
|
||||
Subject: [PATCH 6/6] adapter: Remove experimental flag for PowerState
|
||||
|
||||
Now that the feature has been tested, that the API is deemed adequate
|
||||
and the reliability sufficient.
|
||||
---
|
||||
src/adapter.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/adapter.c b/src/adapter.c
|
||||
index 11a21ca5c..2a4a0a977 100644
|
||||
--- a/src/adapter.c
|
||||
+++ b/src/adapter.c
|
||||
@@ -3808,8 +3808,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 },
|
||||
- { "PowerState", "s", property_get_power_state, NULL, NULL,
|
||||
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
|
||||
+ { "PowerState", "s", property_get_power_state },
|
||||
{ "Discoverable", "b", property_get_discoverable,
|
||||
property_set_discoverable },
|
||||
{ "DiscoverableTimeout", "u", property_get_discoverable_timeout,
|
||||
--
|
||||
2.37.2
|
||||
|
Loading…
Reference in New Issue
Block a user