summaryrefslogtreecommitdiff
path: root/profiles/scanparam
diff options
context:
space:
mode:
authorJakub Pawlowski <jpawlowski@google.com>2015-10-22 16:07:56 -0700
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2015-10-25 21:12:36 +0200
commita7bb4bb658dc0f4294fa1d125c15634655bee123 (patch)
tree209dede2b07801a37c922d863ec3c37a8a9e2cd1 /profiles/scanparam
parent488fd81a0f9cb193a733ac03fba0a80c145868c9 (diff)
downloadbluez-a7bb4bb658dc0f4294fa1d125c15634655bee123.tar.gz
profiles/scanparam: rewrite scanparam profile
This patch rewrites scanparam profile. It will no longer trigger autoconnect.
Diffstat (limited to 'profiles/scanparam')
-rw-r--r--profiles/scanparam/scan.c256
1 files changed, 132 insertions, 124 deletions
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index fbda8a8bb..4015b3f8a 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,209 @@
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 +265,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)