Issue with discover_callback Returning NULL Attribute on NRF52840DK (BLE Central)

Hi,

I’m currently working with the nRF52840 DK configured as a BLE Central device.
The peripheral device is a Flutter-based mobile application acting as a BLE Peripheral.

We're encountering an issue where, during service discovery, the discover_callback function is invoked but the attr parameter is NULL.

However, when testing with the nRF Connect mobile application, the app is able to discover and display services and characteristics correctly from the same Flutter peripheral.

Why does the nRF52840 DK receive a NULL attr in the callback, while the nRF Connect app works as expected?
Below is the implementation of our discover_callback function for reference:

static uint8_t 
discover_cb (struct bt_conn *conn, const struct bt_gatt_attr *attr,
    struct bt_gatt_discover_params *params)
{
	static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
    uint8_t slot = MAX_BEACONS_SUPPORTED;

    printk("Discovery callback - Type: %d, Start: 0x%04x, End: 0x%04x\n",
           params->type, params->start_handle, params->end_handle);

	if (!attr) {
        // This could be normal completion, not necessarily an error
        printk("Discovery completed for type %d, UUID: ", params->type);

        return BT_GATT_ITER_STOP;
	}
    else {
        printk("Found attr at handle 0x%04x, value handle: 0x%04x\n",
               attr->handle, bt_gatt_attr_value_handle(attr));

        // Rest of the discovery logic
	}

	return BT_GATT_ITER_STOP;
}

Parents
  • Hi,

    The attr pointer will be NULL if  there is no (more) to discover. Can you share your service discovery code in addition to the callback you have allready shared? 

  • Hi, thank you for the response.
    Below is the discover service preparation

    /**
     * @brief Discover peer GATT services
     *
     */
    void discover_services (void)
    {
    	g_discover_params.uuid = &g_peer_device_uuid.uuid;
    	g_discover_params.func = discover_cb;
    	g_discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    	g_discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    	g_discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    
    	bt_gatt_discover(current_dev_info.conn, &g_discover_params);
    }


    Below is the complete discovery_cb function
    static uint8_t discover_cb (struct bt_conn *conn, const struct bt_gatt_attr *attr,
    			                struct bt_gatt_discover_params *params)
    {
    	static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
        uint8_t slot = MAX_BEACONS_SUPPORTED;
    
        printk("Discovery callback - Type: %d, Start: 0x%04x, End: 0x%04x\n",
               params->type, params->start_handle, params->end_handle);
    
    	if (!attr) {
            // This could be normal completion, not necessarily an error
            printk("Discovery completed for type %d, UUID: ", params->type);
    
            return BT_GATT_ITER_CONTINUE;
    	}
        
        printk("Found attr at handle 0x%04x, value handle: 0x%04x\n",
               attr->handle, bt_gatt_attr_value_handle(attr));
    
    	if ((!bt_uuid_cmp(g_discover_params.uuid, BT_UUID_NOTIFY_DEV)) ||
    	    (!bt_uuid_cmp(g_discover_params.uuid, BT_UUID_MOBILE_DEV)))
        {
    		// Found the NOTIF_DEV_SERVICE. Look for the CMD characteristic handle
            //
    		memcpy(&uuid, BT_UUID_CMD, sizeof(uuid));
    		g_discover_params.uuid = &uuid.uuid;
    		g_discover_params.start_handle = attr->handle + 1;
    		g_discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
    		bt_gatt_discover(conn, &g_discover_params);
    	}
        else if (!bt_uuid_cmp(g_discover_params.uuid, BT_UUID_CMD)) {
            // Copy the characteristics attribute handle which will be used for subscription on later
            // when respective CCC is discovered
            //
    		subscribe_param[slot].params.value_handle = bt_gatt_attr_value_handle(attr);
    
    		// Found the NOTIF_DEV_CMD_CHR handle. Find the DESCRIPTOR handle
    		//
    		memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(struct bt_uuid_16));
    		g_discover_params.uuid = &uuid.uuid;
    		g_discover_params.start_handle = attr->handle + 2;
    		g_discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
    
    		// This is the only characteristic handle that we are going to use. So save it for
            // communication with the peripheral
            //
    		current_dev_info.cmd_chr_handle = (attr->handle + 1);
    		bt_gatt_discover(conn, &g_discover_params);
    	}
        else {
            subscribe_new_device(conn, attr->handle, slot);
    	}
    
    	return BT_GATT_ITER_STOP;
    }
    Please let me know if any additional info needed
  • Hi,

    I see. What is the value of g_peer_device_uuid.uuid here? Can you check that it is actually the UUID you are looking for and verify that it is present on the peer device?

  • It is BT_UUID_TYPE_128 (2)

    Let me check on the peer end and confirm I am getting the same type.
  • Sorry for late reply.
    I can confirm the type from the peer is same.

  • Can you print the actual number and also show the result from nRF Connect on the phone so that we see? I ask becasue the behaviour you are seeing is what I expect if performing service discovery but without finding the UUID you ar filtering on. An alternative test is to set the UUID to NULL to not filter on UUID (this approach can be used to discover any/all services).

Reply Children
No Data
Related