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;
}

  • 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.

Related