diff mbox series

[Bluez,v4,2/4] adapter: Handle controller resume and notify drivers

Message ID 20200911153010.Bluez.v4.2.Ic6aa9c03323b5ef0265e5b5b36986af05d9ecd26@changeid
State New
Headers show
Series adapter: Reconnect audio when resuming from suspend | expand

Commit Message

Abhishek Pandit-Subedi Sept. 11, 2020, 10:30 p.m. UTC
Register for controller resume notification and notify the adapter
drivers when it occurs. Also adds the resume event kernel feature to
make sure the kernel supports this event.
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 src/adapter.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/adapter.h |  2 ++
 2 files changed, 45 insertions(+)
diff mbox series

Patch

diff --git a/src/adapter.c b/src/adapter.c
index e700a78d5..d77d83d11 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -8771,6 +8771,33 @@  static void connected_callback(uint16_t index, uint16_t length,
 	eir_data_free(&eir_data);
 }
 
+static void controller_resume_notify(struct btd_adapter *adapter)
+{
+	GSList *l;
+
+	for (l = adapter->drivers; l; l = g_slist_next(l)) {
+		struct btd_adapter_driver *driver = l->data;
+		if (driver->resume)
+			driver->resume(adapter);
+	}
+}
+
+static void controller_resume_callback(uint16_t index, uint16_t length,
+				       const void *param, void *user_data)
+{
+	const struct mgmt_ev_controller_resume *ev = param;
+	struct btd_adapter *adapter = user_data;
+
+	if (length < sizeof(*ev)) {
+		btd_error(adapter->dev_id, "Too small device resume event");
+		return;
+	}
+
+	info("Controller resume with wake event 0x%x", ev->wake_reason);
+
+	controller_resume_notify(adapter);
+}
+
 static void device_blocked_callback(uint16_t index, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -9394,6 +9421,11 @@  static void read_info_complete(uint8_t status, uint16_t length,
 						user_passkey_notify_callback,
 						adapter, NULL);
 
+	mgmt_register(adapter->mgmt, MGMT_EV_CONTROLLER_RESUME,
+						adapter->dev_id,
+						controller_resume_callback,
+						adapter, NULL);
+
 	set_dev_class(adapter);
 
 	set_name(adapter, btd_adapter_get_name(adapter));
@@ -9604,6 +9636,17 @@  static void read_commands_complete(uint8_t status, uint16_t length,
 			break;
 		}
 	}
+
+	for (i = 0; i < num_events; i++) {
+		uint16_t ev = get_le16(rp->opcodes + num_commands + i);
+
+		switch(ev) {
+		case MGMT_EV_CONTROLLER_RESUME:
+			DBG("kernel supports suspend/resume events");
+			kernel_features |= KERNEL_HAS_RESUME_EVT;
+			break;
+		}
+	}
 }
 
 static void read_version_complete(uint8_t status, uint16_t length,
diff --git a/src/adapter.h b/src/adapter.h
index b0ed4915f..fae2e9d3d 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -113,6 +113,7 @@  struct btd_adapter_driver {
 	const char *name;
 	int (*probe) (struct btd_adapter *adapter);
 	void (*remove) (struct btd_adapter *adapter);
+	void (*resume) (struct btd_adapter *adapter);
 };
 
 typedef void (*service_auth_cb) (DBusError *derr, void *user_data);
@@ -239,6 +240,7 @@  enum kernel_features {
 	KERNEL_BLOCKED_KEYS_SUPPORTED	= 1 << 1,
 	KERNEL_SET_SYSTEM_CONFIG	= 1 << 2,
 	KERNEL_EXP_FEATURES		= 1 << 3,
+	KERNEL_HAS_RESUME_EVT		= 1 << 4,
 };
 
 bool has_kernel_features(uint32_t feature);