From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This cleanup code related to service probe making it use a single function, because of that now all driver must implement device_probe in order for the service probe to work properly. In addition to that a new flag called external was introduced to btd_profile to be possible to distinguish whether it is a internal plugin or external client, this was needed in order to decide if an attribute should be claimed which whould prevent it to be exported over D-Bus. --- src/device.c | 167 +++++++++++++++------------------------------------- src/gatt-database.c | 30 ++++++++-- src/profile.c | 11 +++- src/profile.h | 1 + 4 files changed, 84 insertions(+), 125 deletions(-) diff --git a/src/device.c b/src/device.c index bdea55b..999f09f 100644 --- a/src/device.c +++ b/src/device.c @@ -2814,14 +2814,6 @@ static void device_add_uuids(struct btd_device *device, GSList *uuids) DEVICE_INTERFACE, "UUIDs"); } -struct gatt_probe_data { - struct btd_device *dev; - bool all_services; - GSList *uuids; - struct gatt_db_attribute *cur_attr; - char cur_uuid[MAX_LEN_UUID_STR]; -}; - static bool device_match_profile(struct btd_device *device, struct btd_profile *profile, GSList *uuids) @@ -2836,99 +2828,42 @@ static bool device_match_profile(struct btd_device *device, return true; } -static void dev_probe_gatt(struct btd_profile *p, void *user_data) +static void probe_gatt_profile(struct gatt_db_attribute *attr, void *user_data) { - struct gatt_probe_data *data = user_data; + struct btd_device *device = user_data; struct btd_service *service; - - if (!p->remote_uuid || bt_uuid_strcmp(p->remote_uuid, data->cur_uuid)) - return; - - /* - * Add device to auto connect list in case the driver has the auto - * connect flag set. - * NOTE: This should work regardless if a service is created and - * probed since external drivers don't need to maintain any - * states they don't implement device_probe callback. - */ - if (p->auto_connect) - device_set_auto_connect(data->dev, TRUE); - - if (p->device_probe == NULL) - return; - - service = service_create(data->dev, p); - if (!service) - return; - - if (service_probe(service) < 0) { - btd_service_unref(service); - return; - } - - /* Mark service as active to skip discovering it again */ - gatt_db_service_set_active(data->cur_attr, true); - - /* Mark service as claimed */ - gatt_db_service_set_claimed(data->cur_attr, true); - - data->dev->services = g_slist_append(data->dev->services, service); -} - -static void dev_probe_gatt_profile(struct gatt_db_attribute *attr, - void *user_data) -{ - struct gatt_probe_data *data = user_data; + struct btd_profile *profile; bt_uuid_t uuid; - GSList *l = NULL; + char uuid_str[MAX_LEN_UUID_STR]; + GSList *l; gatt_db_attribute_get_service_uuid(attr, &uuid); - bt_uuid_to_string(&uuid, data->cur_uuid, sizeof(data->cur_uuid)); - - data->cur_attr = attr; - - /* - * If we're probing for all services, store the UUID since device->uuids - * was cleared. - */ - if (data->all_services) - data->uuids = g_slist_append(data->uuids, - g_strdup(data->cur_uuid)); - - /* Don't probe the profiles if a matching service already exists. */ - if (find_service_with_uuid(data->dev->services, data->cur_uuid)) { - /* Mark service as active to skip discovering it again */ - gatt_db_service_set_active(data->cur_attr, true); - /* Mark the service as claimed by the existing profile. */ - gatt_db_service_set_claimed(data->cur_attr, true); - return; - } + bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str)); - btd_profile_foreach(dev_probe_gatt, data); + /* Add UUID and probe service */ + btd_device_add_uuid(device, uuid_str); - if (data->all_services) + /* Check if service was probed */ + l = find_service_with_uuid(device->services, uuid_str); + if (!l) return; - l = g_slist_append(l, g_strdup(data->cur_uuid)); - device_add_uuids(data->dev, l); -} - -static void device_probe_gatt_profile(struct btd_device *device, - struct gatt_db_attribute *attr) -{ - struct gatt_probe_data data; + /* Mark service as active to skip discovering it again */ + gatt_db_service_set_active(attr, true); - memset(&data, 0, sizeof(data)); + service = l->data; + profile = btd_service_get_profile(service); - data.dev = device; + /* Don't claim attributes of external profiles */ + if (profile->external) + return; - dev_probe_gatt_profile(attr, &data); - g_slist_free_full(data.uuids, g_free); + /* Mark the service as claimed by the existing profile. */ + gatt_db_service_set_claimed(attr, true); } static void device_probe_gatt_profiles(struct btd_device *device) { - struct gatt_probe_data data; char addr[18]; ba2str(&device->bdaddr, addr); @@ -2938,16 +2873,7 @@ static void device_probe_gatt_profiles(struct btd_device *device) return; } - memset(&data, 0, sizeof(data)); - - data.dev = device; - data.all_services = true; - - gatt_db_foreach_service(device->db, NULL, dev_probe_gatt_profile, - &data); - - device_add_uuids(device, data.uuids); - g_slist_free_full(data.uuids, g_free); + gatt_db_foreach_service(device->db, NULL, probe_gatt_profile, device); } static void device_accept_gatt_profiles(struct btd_device *device) @@ -3028,9 +2954,7 @@ static void gatt_service_added(struct gatt_db_attribute *attr, void *user_data) service_accept(l->data); } - device_probe_gatt_profile(device, attr); - - store_device_info(device); + btd_device_add_uuid(device, uuid_str); btd_gatt_client_service_added(device->client_dbus, attr); @@ -3645,45 +3569,52 @@ struct probe_data { GSList *uuids; }; -static void dev_probe(struct btd_profile *p, void *user_data) +static struct btd_service *probe_service(struct btd_device *device, + struct btd_profile *profile, + GSList *uuids) { - struct probe_data *d = user_data; struct btd_service *service; - if (p->device_probe == NULL) - return; + if (profile->device_probe == NULL) + return NULL; - if (!device_match_profile(d->dev, p, d->uuids)) - return; + if (!device_match_profile(device, profile, uuids)) + return NULL; - service = service_create(d->dev, p); + service = service_create(device, profile); - if (service_probe(service) < 0) { + if (service_probe(service)) { btd_service_unref(service); - return; + return NULL; } - d->dev->services = g_slist_append(d->dev->services, service); + if (profile->auto_connect) + device_set_auto_connect(device, TRUE); + + return service; } -void device_probe_profile(gpointer a, gpointer b) +static void dev_probe(struct btd_profile *p, void *user_data) { - struct btd_device *device = a; - struct btd_profile *profile = b; + struct probe_data *d = user_data; struct btd_service *service; - if (profile->device_probe == NULL) + service = probe_service(d->dev, p, d->uuids); + if (!service) return; - if (!device_match_profile(device, profile, device->uuids)) - return; + d->dev->services = g_slist_append(d->dev->services, service); +} - service = service_create(device, profile); +void device_probe_profile(gpointer a, gpointer b) +{ + struct btd_device *device = a; + struct btd_profile *profile = b; + struct btd_service *service; - if (service_probe(service) < 0) { - btd_service_unref(service); + service = probe_service(device, profile, device->uuids); + if (!service) return; - } device->services = g_slist_append(device->services, service); diff --git a/src/gatt-database.c b/src/gatt-database.c index 97cef77..774b19e 100644 --- a/src/gatt-database.c +++ b/src/gatt-database.c @@ -43,6 +43,7 @@ #include "gatt-database.h" #include "dbus-common.h" #include "profile.h" +#include "service.h" #ifndef ATT_CID #define ATT_CID 4 @@ -1074,7 +1075,7 @@ static void client_disconnect_cb(DBusConnection *conn, void *user_data) service_remove_helper(user_data); } -static void service_remove(void *data) +static void remove_service(void *data) { struct external_service *service = data; @@ -1453,7 +1454,7 @@ static void proxy_removed_cb(GDBusProxy *proxy, void *user_data) DBG("Proxy removed - removing service: %s", service->path); - service_remove(service); + remove_service(service); } static bool parse_uuid(GDBusProxy *proxy, bt_uuid_t *uuid) @@ -2142,10 +2143,10 @@ reply: service->reg = NULL; if (fail) - service_remove(service); + remove_service(service); } -static struct external_service *service_create(DBusConnection *conn, +static struct external_service *create_service(DBusConnection *conn, DBusMessage *msg, const char *path) { struct external_service *service; @@ -2223,7 +2224,7 @@ static DBusMessage *manager_register_service(DBusConnection *conn, if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) return btd_error_invalid_args(msg); - service = service_create(conn, msg, path); + service = create_service(conn, msg, path); if (!service) return btd_error_failed(msg, "Failed to register service"); @@ -2279,6 +2280,22 @@ static void profile_exited(DBusConnection *conn, void *user_data) profile_free(profile); } +static int profile_device_probe(struct btd_service *service) +{ + struct btd_profile *p = btd_service_get_profile(service); + + DBG("%s probed", p->name); + + return 0; +} + +static void profile_device_remove(struct btd_service *service) +{ + struct btd_profile *p = btd_service_get_profile(service); + + DBG("%s removed", p->name); +} + static int profile_add(struct external_profile *profile, const char *uuid) { struct btd_profile *p; @@ -2302,7 +2319,10 @@ static int profile_add(struct external_profile *profile, const char *uuid) return -ENOMEM; } + p->device_probe = profile_device_probe; + p->device_remove = profile_device_remove; p->auto_connect = true; + p->external = true; queue_push_tail(profile->profiles, p); diff --git a/src/profile.c b/src/profile.c index f54749e..70ee4c1 100644 --- a/src/profile.c +++ b/src/profile.c @@ -719,13 +719,19 @@ void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data), int btd_profile_register(struct btd_profile *profile) { - profiles = g_slist_append(profiles, profile); + if (profile->external) + ext_profiles = g_slist_append(ext_profiles, profile); + else + profiles = g_slist_append(profiles, profile); return 0; } void btd_profile_unregister(struct btd_profile *profile) { - profiles = g_slist_remove(profiles, profile); + if (profile->external) + ext_profiles = g_slist_remove(ext_profiles, profile); + else + profiles = g_slist_remove(profiles, profile); } static struct ext_profile *find_ext_profile(const char *owner, @@ -2291,6 +2297,7 @@ static struct ext_profile *create_ext(const char *owner, const char *path, p->name = ext->name; p->local_uuid = ext->service ? ext->service : ext->uuid; p->remote_uuid = ext->remote_uuid; + p->external = true; if (ext->enable_server) { p->adapter_probe = ext_adapter_probe; diff --git a/src/profile.h b/src/profile.h index f5a3ded..4448a2a 100644 --- a/src/profile.h +++ b/src/profile.h @@ -35,6 +35,7 @@ struct btd_profile { const char *remote_uuid; bool auto_connect; + bool external; int (*device_probe) (struct btd_service *service); void (*device_remove) (struct btd_service *service); -- 2.4.3 -- 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