This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Service Discovery Issues using the discovery manager.

I am trying to do service discovery using the discovery manager library on any BLE device I connect to my central. I start the service with bt_gatt_dm_start(conn, NULL, &discovery_cb, NULL) and every works fine on the first service discovered. I run into an issue when I try to continue the discovery on the remaining services. The asserts on line 2927 and 2929 in the bt_gatt_discover function of Zephyr's gatt.c library are asserted upon running bt_gatt_dm_continue.  If I remove these asserts everything runs fine and I am able to continue discovery of all the services for my device as intended. Is this a bug in the DM or am I using it incorrectly?

Here is my discover complete callback with the dm continue function

static void discovery_completed(struct bt_gatt_dm *disc, void *ctx)
{

  printk("Attribute count: %d\n", bt_gatt_dm_attr_cnt(disc));

  bt_gatt_dm_data_release(disc);
  bt_gatt_dm_continue(disc, NULL);

}


The asserts causing the issues:
int bt_gatt_discover(struct bt_conn *conn, struct bt_gatt_discover_params *params)
{
__ASSERT((params->start_handle && params->end_handle),
"invalid parameters\n");
__ASSERT((params->start_handle <= params->end_handle),
"invalid parameters\n");


Parents
  • I have yes and I figured out where it is happening at. In discovery_process_service you can see that the start handle has one added to it with attr->handle + 1. This becomes an issue when trying to do discovering on an empty service such as the 0x1801 service in the heart rate monitor where the end handle and start handle will be the same. Thus adding 1 to the starts makes it larger than the end. Maybe there needs to be a check if they are equal to each other before adding one to the start?

    static u8_t discovery_process_service(struct bt_gatt_dm *dm,
    				      const struct bt_gatt_attr *attr,
    				      struct bt_gatt_discover_params *params)
    {
    	int err;
    
    	if (!attr) {
    		discovery_complete_not_found(dm);
    		return BT_GATT_ITER_STOP;
    	}
    
    	struct bt_gatt_service_val *service_val = attr->user_data;
    	struct bt_gatt_attr *cur_attr = attr_store(dm, attr);
    
    	if (!cur_attr) {
    		LOG_ERR("Not enough memory for service attribute.");
    		discovery_complete_error(dm, -ENOMEM);
    		return BT_GATT_ITER_STOP;
    	}
    	LOG_DBG("Service detected, handles range: <%u, %u>",
    		attr->handle + 1,
    		service_val->end_handle);
    
    	cur_attr->uuid = uuid_store(dm, attr->uuid);
    	service_val = user_data_store(dm, service_val, sizeof(*service_val));
    	service_val->uuid = uuid_store(dm, service_val->uuid);
    	cur_attr->user_data = service_val;
    
    	if (!cur_attr->uuid || !service_val ||
    	    !service_val->uuid) {
    		LOG_ERR("Not enough memory for service attribute data.");
    		discovery_complete_error(dm, -ENOMEM);
    		return BT_GATT_ITER_STOP;
    	}
    
    	dm->discover_params.uuid         = NULL;
    	dm->discover_params.type         = BT_GATT_DISCOVER_ATTRIBUTE;
    	dm->discover_params.start_handle = attr->handle + 1;    ///ISSUE HERE
    	dm->discover_params.end_handle   = service_val->end_handle;
    	LOG_DBG("Starting descriptors discovery");
    	err = bt_gatt_discover(dm->conn, &(dm->discover_params));
    
    	if (err) {
    		LOG_ERR("Descriptor discover failed, error: %d.", err);
    		discovery_complete_error(dm, -ENOMEM);
    		return BT_GATT_ITER_STOP;
    	}
    
    	return BT_GATT_ITER_STOP;
    }
    



Reply
  • I have yes and I figured out where it is happening at. In discovery_process_service you can see that the start handle has one added to it with attr->handle + 1. This becomes an issue when trying to do discovering on an empty service such as the 0x1801 service in the heart rate monitor where the end handle and start handle will be the same. Thus adding 1 to the starts makes it larger than the end. Maybe there needs to be a check if they are equal to each other before adding one to the start?

    static u8_t discovery_process_service(struct bt_gatt_dm *dm,
    				      const struct bt_gatt_attr *attr,
    				      struct bt_gatt_discover_params *params)
    {
    	int err;
    
    	if (!attr) {
    		discovery_complete_not_found(dm);
    		return BT_GATT_ITER_STOP;
    	}
    
    	struct bt_gatt_service_val *service_val = attr->user_data;
    	struct bt_gatt_attr *cur_attr = attr_store(dm, attr);
    
    	if (!cur_attr) {
    		LOG_ERR("Not enough memory for service attribute.");
    		discovery_complete_error(dm, -ENOMEM);
    		return BT_GATT_ITER_STOP;
    	}
    	LOG_DBG("Service detected, handles range: <%u, %u>",
    		attr->handle + 1,
    		service_val->end_handle);
    
    	cur_attr->uuid = uuid_store(dm, attr->uuid);
    	service_val = user_data_store(dm, service_val, sizeof(*service_val));
    	service_val->uuid = uuid_store(dm, service_val->uuid);
    	cur_attr->user_data = service_val;
    
    	if (!cur_attr->uuid || !service_val ||
    	    !service_val->uuid) {
    		LOG_ERR("Not enough memory for service attribute data.");
    		discovery_complete_error(dm, -ENOMEM);
    		return BT_GATT_ITER_STOP;
    	}
    
    	dm->discover_params.uuid         = NULL;
    	dm->discover_params.type         = BT_GATT_DISCOVER_ATTRIBUTE;
    	dm->discover_params.start_handle = attr->handle + 1;    ///ISSUE HERE
    	dm->discover_params.end_handle   = service_val->end_handle;
    	LOG_DBG("Starting descriptors discovery");
    	err = bt_gatt_discover(dm->conn, &(dm->discover_params));
    
    	if (err) {
    		LOG_ERR("Descriptor discover failed, error: %d.", err);
    		discovery_complete_error(dm, -ENOMEM);
    		return BT_GATT_ITER_STOP;
    	}
    
    	return BT_GATT_ITER_STOP;
    }
    



Children
Related