diff mbox series

[Bluez,v2,2/6] core/advertising: Add support for LE set adverting interval

Message ID 20200330160343.Bluez.v2.2.I4fe5ed67f70011e5374e65929b845e13fe6ed59e@changeid (mailing list archive)
State New, archived
Headers show
Series Add support of setting advertiing intervals. | expand

Commit Message

Howard Chung March 30, 2020, 8:03 a.m. UTC
Implement a new dbus method to set advertising intervals.
The advertising inervals are sent through a new mgmt method with
the opcode MGMT_OP_SET_ADVERTISING_INTERVALS to bluetooth kernel
subsystem.

Signed-off-by: Howard Chung <howardchung@google.com>
---

Changes in v2: None

 src/advertising.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)
diff mbox series

Patch

diff --git a/src/advertising.c b/src/advertising.c
index 45ff19fa0..444969f04 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -1342,6 +1342,92 @@  static const GDBusPropertyTable properties[] = {
 	{ }
 };
 
+static void set_advertising_intervals_callback(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	DBusMessage *msg = user_data;
+	DBusMessage *reply;
+
+	switch (status) {
+	case MGMT_STATUS_SUCCESS:
+		reply = dbus_message_new_method_return(msg);
+		break;
+	case MGMT_STATUS_REJECTED:
+		reply = btd_error_failed(
+				msg, "A non-BLE device should not advertise!");
+		break;
+	case MGMT_STATUS_INVALID_PARAMS:
+		reply = btd_error_invalid_args(msg);
+		break;
+	case MGMT_STATUS_BUSY:
+		reply = btd_error_busy(msg);
+		break;
+	default:
+		reply = btd_error_failed(
+				msg, "failed to set advertising intervals");
+	}
+
+	g_dbus_send_message(btd_get_dbus_connection(), reply);
+	dbus_message_unref(msg);
+}
+
+static int adapter_set_advertising_intervals(struct btd_adv_manager *manager,
+						DBusMessage *msg,
+						uint16_t min_interval_ms,
+						uint16_t max_interval_ms)
+{
+	struct mgmt_cp_set_advertising_intervals cp;
+
+	memset(&cp, 0, sizeof(cp));
+
+	/* Convert milli-seconds to multiples of 0.625 ms which are used
+	 * in kernel.
+	 */
+	cp.min_interval = min_interval_ms / ADVERTISING_INTERVAL_UNIT_TIME;
+	cp.max_interval = max_interval_ms / ADVERTISING_INTERVAL_UNIT_TIME;
+
+	btd_info(manager->mgmt_index,
+			"Set Advertising Intervals: 0x%04x, 0x%04x",
+			cp.min_interval, cp.max_interval);
+
+	if (mgmt_send(manager->mgmt,
+			MGMT_OP_SET_ADVERTISING_INTERVALS, manager->mgmt_index,
+			sizeof(cp), &cp, set_advertising_intervals_callback,
+			dbus_message_ref(msg), NULL) > 0) {
+		return true;
+	}
+
+	return false;
+}
+
+static DBusMessage *set_advertising_intervals(DBusConnection *conn,
+					DBusMessage *msg, void *user_data)
+{
+	struct btd_adv_manager *manager = user_data;
+	const char *sender = dbus_message_get_sender(msg);
+	dbus_uint16_t min_interval_ms, max_interval_ms;
+
+	DBG("set_advertising_intervals: sender %s", sender);
+
+	if (!dbus_message_get_args(msg, NULL,
+					DBUS_TYPE_UINT16, &min_interval_ms,
+					DBUS_TYPE_UINT16, &max_interval_ms,
+					DBUS_TYPE_INVALID)) {
+		return btd_error_invalid_args(msg);
+	}
+
+	/* The adapter is not required to be powered to set advertising
+	 * intervals. Hence, just go ahead to set the intervals.
+	 */
+	if (!adapter_set_advertising_intervals(manager, msg, min_interval_ms,
+						max_interval_ms)) {
+		return btd_error_failed(msg,
+					"failed to set advertising intervals");
+	}
+
+	return NULL;
+}
+
 static const GDBusMethodTable methods[] = {
 	{ GDBUS_ASYNC_METHOD("RegisterAdvertisement",
 					GDBUS_ARGS({ "advertisement", "o" },
@@ -1351,6 +1437,10 @@  static const GDBusMethodTable methods[] = {
 						GDBUS_ARGS({ "service", "o" }),
 						NULL,
 						unregister_advertisement) },
+	{ GDBUS_ASYNC_METHOD("SetAdvertisingIntervals",
+				GDBUS_ARGS({"min_interval_ms", "q"},
+						{"max_interval_ms", "q"}),
+				NULL, set_advertising_intervals)},
 	{ }
 };