[PATCH BlueZ] profiles/scanparam: rewrite scanparam profile

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch rewrites scanparam profile. It will no longer trigger
autoconnect.
---
 profiles/scanparam/scan.c | 255 ++++++++++++++++++++++++----------------------
 1 file changed, 131 insertions(+), 124 deletions(-)

diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index fbda8a8..e967cab 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -40,10 +40,11 @@
 #include "src/profile.h"
 #include "src/service.h"
 #include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
 #include "attrib/att.h"
-#include "attrib/gattrib.h"
-#include "attrib/gatt.h"
-#include "src/attio.h"
 
 #define SCAN_INTERVAL_WIN_UUID		0x2A4F
 #define SCAN_REFRESH_UUID		0x2A31
@@ -54,203 +55,208 @@
 
 struct scan {
 	struct btd_device *device;
-	GAttrib *attrib;
-	struct att_range range;
-	guint attioid;
-	uint16_t interval;
-	uint16_t window;
+	struct gatt_db *db;
+	struct bt_gatt_client *client;
+	struct gatt_db_attribute *attr;
 	uint16_t iwhandle;
-	uint16_t refresh_handle;
 	guint refresh_cb_id;
 };
 
-static void write_scan_params(GAttrib *attrib, uint16_t handle)
+static GSList *devices;
+
+static void scan_free(struct scan *scan)
+{
+	bt_gatt_client_unregister_notify(scan->client, scan->refresh_cb_id);
+	gatt_db_unref(scan->db);
+	bt_gatt_client_unref(scan->client);
+	btd_device_unref(scan->device);
+	g_free(scan);
+}
+
+static int cmp_device(gconstpointer a, gconstpointer b)
+{
+	const struct scan *scan = a;
+	const struct btd_device *device = b;
+
+	return scan->device == device ? 0 : -1;
+}
+
+static void write_scan_params(struct scan *scan)
 {
 	uint8_t value[4];
 
 	put_le16(SCAN_INTERVAL, &value[0]);
 	put_le16(SCAN_WINDOW, &value[2]);
 
-	gatt_write_cmd(attrib, handle, value, sizeof(value), NULL, NULL);
+	bt_gatt_client_write_without_response(scan->client, scan->iwhandle,
+						false, value, sizeof(value));
 }
 
-static void refresh_value_cb(const uint8_t *pdu, uint16_t len,
-						gpointer user_data)
+static void refresh_value_cb(uint16_t value_handle, const uint8_t *value,
+					uint16_t length, void *user_data)
 {
 	struct scan *scan = user_data;
 
-	DBG("Server requires refresh: %d", pdu[3]);
+	DBG("Server requires refresh: %d", value[3]);
 
-	if (pdu[3] == SERVER_REQUIRES_REFRESH)
-		write_scan_params(scan->attrib, scan->iwhandle);
+	if (value[3] == SERVER_REQUIRES_REFRESH)
+		write_scan_params(scan);
 }
 
-static void ccc_written_cb(guint8 status, const guint8 *pdu,
-					guint16 plen, gpointer user_data)
+static void refresh_ccc_written_cb(uint16_t att_ecode, void *user_data)
 {
-	struct scan *scan = user_data;
-
-	if (status != 0) {
-		error("Write Scan Refresh CCC failed: %s",
-						att_ecode2str(status));
+	if (att_ecode != 0) {
+		error("Scan Refresh: notifications not enabled %s",
+						att_ecode2str(att_ecode));
 		return;
 	}
 
 	DBG("Scan Refresh: notification enabled");
-
-	scan->refresh_cb_id = g_attrib_register(scan->attrib,
-				ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
-				refresh_value_cb, scan, NULL);
 }
 
-static void discover_descriptor_cb(uint8_t status, GSList *descs,
-								void *user_data)
+static void handle_refresh(struct scan *scan, uint16_t value_handle)
 {
-	struct scan *scan = user_data;
-	struct gatt_desc *desc;
-	uint8_t value[2];
+	DBG("Scan Refresh handle: 0x%04x", value_handle);
 
-	if (status != 0) {
-		error("Discover descriptors failed: %s", att_ecode2str(status));
-		return;
-	}
+	scan->refresh_cb_id = bt_gatt_client_register_notify(scan->client,
+					value_handle, refresh_ccc_written_cb,
+						refresh_value_cb, scan,	NULL);
+}
+
+static void handle_iwin(struct scan *scan, uint16_t value_handle)
+{
+	scan->iwhandle = value_handle;
 
-	/* There will be only one descriptor on list and it will be CCC */
-	desc = descs->data;
+	DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
 
-	put_le16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
-	gatt_write_char(scan->attrib, desc->handle, value, sizeof(value),
-						ccc_written_cb, user_data);
+	write_scan_params(scan);
 }
 
-static void refresh_discovered_cb(uint8_t status, GSList *chars,
+static void handle_characteristic(struct gatt_db_attribute *attr,
 								void *user_data)
 {
 	struct scan *scan = user_data;
-	struct gatt_char *chr;
-	uint16_t start, end;
-	bt_uuid_t uuid;
-
-	if (status) {
-		error("Scan Refresh %s", att_ecode2str(status));
-		return;
-	}
+	uint16_t value_handle;
+	bt_uuid_t uuid, scan_interval_wind_uuid, scan_refresh_uuid;
 
-	if (!chars) {
-		DBG("Scan Refresh not supported");
+	if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL,
+								&uuid)) {
+		error("Failed to obtain characteristic data");
 		return;
 	}
 
-	chr = chars->data;
+	bt_uuid16_create(&scan_interval_wind_uuid, SCAN_INTERVAL_WIN_UUID);
+	bt_uuid16_create(&scan_refresh_uuid, SCAN_REFRESH_UUID);
 
-	DBG("Scan Refresh handle: 0x%04x", chr->value_handle);
+	if (bt_uuid_cmp(&scan_interval_wind_uuid, &uuid) == 0)
+		handle_iwin(scan, value_handle);
+	else if (bt_uuid_cmp(&scan_refresh_uuid, &uuid) == 0)
+		handle_refresh(scan, value_handle);
+	else {
+		char uuid_str[MAX_LEN_UUID_STR];
 
-	start = chr->value_handle + 1;
-	end = scan->range.end;
-
-	if (start > end)
-		return;
-
-	scan->refresh_handle = chr->value_handle;
-
-	bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
-
-	gatt_discover_desc(scan->attrib, start, end, &uuid,
-					discover_descriptor_cb, user_data);
+		bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
+		DBG("Unsupported characteristic: %s", uuid_str);
+	}
 }
 
-static void iwin_discovered_cb(uint8_t status, GSList *chars, void *user_data)
+static void foreach_scan_param_service(struct gatt_db_attribute *attr,
+								void *user_data)
 {
 	struct scan *scan = user_data;
-	struct gatt_char *chr;
 
-	if (status) {
-		error("Discover Scan Interval Window: %s",
-						att_ecode2str(status));
+	if (scan->attr) {
+		error("More than one scan params service exists for this device");
 		return;
 	}
 
-	chr = chars->data;
-	scan->iwhandle = chr->value_handle;
-
-	DBG("Scan Interval Window handle: 0x%04x", scan->iwhandle);
-
-	write_scan_params(scan->attrib, scan->iwhandle);
+	scan->attr = attr;
+	gatt_db_service_foreach_char(scan->attr, handle_characteristic, scan);
 }
 
-static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+static int scan_param_accept(struct btd_service *service)
 {
-	struct scan *scan = user_data;
-	bt_uuid_t iwin_uuid, refresh_uuid;
+	struct btd_device *device = btd_service_get_device(service);
+	struct gatt_db *db = btd_device_get_gatt_db(device);
+	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+	bt_uuid_t scan_parameters_uuid;
+	struct scan *scan;
+	GSList *l;
+	char addr[18];
 
-	scan->attrib = g_attrib_ref(attrib);
+	ba2str(device_get_address(device), addr);
+	DBG("Scan Parameters Client Driver profile accept (%s)", addr);
 
-	if (scan->iwhandle) {
-		write_scan_params(scan->attrib, scan->iwhandle);
-		return;
+	l = g_slist_find_custom(devices, device, cmp_device);
+	if (!l) {
+		error("Scan Parameters service not handled by profile");
+		return -1;
 	}
 
-	bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
-	bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
+	scan = l->data;
 
-	gatt_discover_char(scan->attrib, scan->range.start, scan->range.end,
-					&iwin_uuid, iwin_discovered_cb, scan);
+	/* Clean-up any old client/db and acquire the new ones */
+	scan->attr = NULL;
+	gatt_db_unref(scan->db);
+	bt_gatt_client_unref(scan->client);
 
-	gatt_discover_char(scan->attrib, scan->range.start, scan->range.end,
-				&refresh_uuid, refresh_discovered_cb, scan);
-}
 
-static void attio_disconnected_cb(gpointer user_data)
-{
-	struct scan *scan = user_data;
+	scan->db = gatt_db_ref(db);
+	scan->client = bt_gatt_client_ref(client);
 
-	g_attrib_unref(scan->attrib);
-	scan->attrib = NULL;
+	bt_string_to_uuid(&scan_parameters_uuid, SCAN_PARAMETERS_UUID);
+	gatt_db_foreach_service(db, &scan_parameters_uuid,
+					foreach_scan_param_service, scan);
+
+	return 0;
 }
 
-static int scan_register(struct btd_service *service, struct gatt_primary *prim)
+static void scan_param_remove(struct btd_service *service)
 {
 	struct btd_device *device = btd_service_get_device(service);
 	struct scan *scan;
+	GSList *l;
+	char addr[18];
 
-	scan = g_new0(struct scan, 1);
-	scan->device = btd_device_ref(device);
-	scan->range = prim->range;
-	scan->attioid = btd_device_add_attio_callback(device,
-							attio_connected_cb,
-							attio_disconnected_cb,
-							scan);
-
-	btd_service_set_user_data(service, scan);
+	ba2str(device_get_address(device), addr);
+	DBG("GAP profile remove (%s)", addr);
 
-	return 0;
-}
-
-static void scan_param_remove(struct btd_service *service)
-{
-	struct scan *scan = btd_service_get_user_data(service);
+	l = g_slist_find_custom(devices, device, cmp_device);
+	if (!l) {
+		error("GAP service not handled by profile");
+		return;
+	}
 
-	if (scan->attrib != NULL && scan->refresh_cb_id > 0)
-		g_attrib_unregister(scan->attrib, scan->refresh_cb_id);
+	scan = l->data;
 
-	btd_device_remove_attio_callback(scan->device, scan->attioid);
-	btd_device_unref(scan->device);
-	g_attrib_unref(scan->attrib);
-	g_free(scan);
+	devices = g_slist_remove(devices, scan);
+	scan_free(scan);
 }
 
 static int scan_param_probe(struct btd_service *service)
 {
 	struct btd_device *device = btd_service_get_device(service);
-	struct gatt_primary *prim;
+	struct scan *scan;
+	GSList *l;
+	char addr[18];
 
-	DBG("Probing Scan Parameters");
+	ba2str(device_get_address(device), addr);
+	DBG("Scan Parameters Client Driver profile probe (%s)", addr);
 
-	prim = btd_device_get_primary(device, SCAN_PARAMETERS_UUID);
-	if (!prim)
-		return -EINVAL;
+	/* Ignore, if we were probed for this device already */
+	l = g_slist_find_custom(devices, device, cmp_device);
+	if (l) {
+		error("Profile probed twice for the same device!");
+		return -1;
+	}
 
-	return scan_register(service, prim);
+	scan = g_new0(struct scan, 1);
+	if (!scan)
+		return -1;
+
+	scan->device = btd_device_ref(device);
+	devices = g_slist_append(devices, scan);
+	return 0;
 }
 
 static struct btd_profile scan_profile = {
@@ -258,6 +264,7 @@ static struct btd_profile scan_profile = {
 	.remote_uuid = SCAN_PARAMETERS_UUID,
 	.device_probe = scan_param_probe,
 	.device_remove = scan_param_remove,
+	.accept = scan_param_accept,
 };
 
 static int scan_param_init(void)
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux