How to access all advertisement data in scan filter match callback?

I'm using nRF Connect v2.0.2 and running in Zephyr.

When scanning by filtering for UUID, I find the matching devices, and the scan filter match callback gets called.  However, when I try to parse the advertising data, I can only see one type.

Example: If I filter on UUID, the advertising data parse only contains UUID type

BT_SCAN_CB_INIT(scan_cbhs, scan_filter_match, NULL, NULL, NULL);

start_scanning_function()
{
    struct bt_scan_init_param scan_init = {
		.connect_if_match = 0,
		.scan_param = BT_LE_SCAN_ACTIVE,   // can this be passive?
		.conn_param = BT_LE_CONN_PARAM_DEFAULT
	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cbhs);

    bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_DECLARE_128(BLE_UUID128_ENCODE(K_BLE_UUID_FILTER_VAL)));

	bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
   
    bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
}

static void scan_filter_match(struct bt_scan_device_info *device_info,
			      struct bt_scan_filter_match *filter_match,
			      bool connectable)
{
    bt_data_parse(device_info->adv_data, find_adv_data, NULL);
}

bool find_adv_data(struct bt_data *data, void *user_data)
{
    printk("Data type is %u \n", data->type);
    
    return true; // keep parsing
}

In the code example above, the only print is
Parse type 7
which is I think is BT_DATA_UUID128_ALL, but not other calls to the parser callback

Similarly if I filter on device name instead of UUID, then I only get
Parse type 1
which I think is BT_DATA_FLAGS and that's it.

If I scan and filter based on UUID, how do I access the advertised device name, manufacturer data, or other data from the device's advertisement?

Thanks

Parents
  • Hello,

    I did not get around to testing this here today, but I suspect what happens is that the advertising buffer is overwritten while you are parsing it. With legacy advertising, you usually have to place the 128-bit vendor UUIDs in the scan response packet due to the limited packet size (31 octets), which means the payload will become split across 2 advertisement packets.

    Similarly if I filter on device name instead of UUID, then I only get
    Parse type 1
    which I think is BT_DATA_FLAGS and that's it.

    When using this filter, could you try to start scanning with bt_scan_start(BT_SCAN_TYPE_SCAN_PASSIVE) instead of bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE) to see if you are able to parse the remaining fields? With passive scanning, you will not receive the scan response packet with the 128-bit UUID.

    Either way, I will test this tomorrow and update the ticket.

    Best regards,

    Vidar

  • /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *  @brief Nordic Battery Service Client sample
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <inttypes.h>
    #include <errno.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    #include <dk_buttons_and_leds.h>
    
    #include <zephyr/settings/settings.h>
    
    /**
     * Button to read the battery value
     */
    #define KEY_READVAL_MASK DK_BTN1_MSK
    
    
    #define K_BLE_UUID_WPC_VAL 	        BT_UUID_128_ENCODE(0xAD014001,0x3BCB,0xFEA6,0x7746,0xC3084AD1DF97)
    
    
    static struct bt_conn *default_conn;
    
    
    bool find_in_adv_data(struct bt_data *data, void *user_data)
    {
        ARG_UNUSED(user_data);
    
        printk("Parse type %u \n",data->type );
    
        return true;
    }
    
    static void scan_filter_match(struct bt_scan_device_info *device_info,
    			      struct bt_scan_filter_match *filter_match,
    			      bool connectable)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));
    
        bt_data_parse(device_info->adv_data, find_in_adv_data, NULL);
    
    	printk("Filters matched. Address: %s connectable: %s\n",
    		addr, connectable ? "yes" : "no");
    }
    
    static void scan_connecting_error(struct bt_scan_device_info *device_info)
    {
    	printk("Connecting failed\n");
    }
    
    static void scan_connecting(struct bt_scan_device_info *device_info,
    			    struct bt_conn *conn)
    {
    	default_conn = bt_conn_ref(conn);
    }
    
    static void scan_filter_no_match(struct bt_scan_device_info *device_info,
    				 bool connectable)
    {
    	int err;
    	struct bt_conn *conn;
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (device_info->recv_info->adv_type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		bt_addr_le_to_str(device_info->recv_info->addr, addr,
    				  sizeof(addr));
    		printk("Direct advertising received from %s\n", addr);
    		bt_scan_stop();
    
    		err = bt_conn_le_create(device_info->recv_info->addr,
    					BT_CONN_LE_CREATE_CONN,
    					device_info->conn_param, &conn);
    
    		if (!err) {
    			default_conn = bt_conn_ref(conn);
    			bt_conn_unref(conn);
    		}
    	}
    }
    
    BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match,
    		scan_connecting_error, scan_connecting);
    
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    
    	printk("Connected: %s\n", addr);
    
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Disconnected: %s (reason %u)\n", addr, reason);
    
    }
    
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    };
    
    static void scan_init(void)
    {
    	int err;
    
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 1,
    		//.scan_param = BT_LE_SCAN_PASSIVE,
            .scan_param = BT_LE_SCAN_ACTIVE,
    		.conn_param = BT_LE_CONN_PARAM_DEFAULT
    	};
    
    	bt_scan_init(&scan_init);
    	bt_scan_cb_register(&scan_cb);
    
    	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_DECLARE_128(K_BLE_UUID_WPC_VAL));
    	if (err) {
    		printk("Scanning filters cannot be set (err %d)\n", err);
    
    		return;
    	}
    
    	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
    	if (err) {
    		printk("Filters cannot be turned on (err %d)\n", err);
    	}
    }
    
    
    
    void main(void)
    {
    	int err;
    
    	printk("Starting Bluetooth Central BAS example\n");
    
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    
    	printk("Bluetooth initialized\n");
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	scan_init();
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
        //err = bt_scan_start(BT_SCAN_TYPE_SCAN_PASSIVE);
    	if (err) {
    		printk("Scanning failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Scanning successfully started\n");
    }
    
    Hi Vidar

    I tried starting the scan with BT_SCAN_TYPE_SCAN_PASSIVE, but did not get any scan results.  (I think this is because the devices I'm scanning for do not include the UUID in their legacy advertisements.)

    I've modified and simplified one of the sample projects to show the issue, and am attaching the main.c and prj.conf for it.  This code builds with the latest SDK v2.2.0.

    You'll want to change the value of K_BLE_UUID_WPC_VAL to use an advertised UUID from a peripheral to test with.

    I ran this on a ubx_bmd340eval_nrf52840 board.

    Regards,
    Walt

  • #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    CONFIG_BT=y
    CONFIG_BT_DEBUG_LOG=y
    CONFIG_BT_CENTRAL=y
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_GATT_DM=y
    CONFIG_HEAP_MEM_POOL_SIZE=1024
    
    CONFIG_BT_SCAN=y
    CONFIG_BT_SCAN_FILTER_ENABLE=y
    CONFIG_BT_SCAN_UUID_CNT=1
    
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    
    CONFIG_DK_LIBRARY=y
    

Reply
  • #
    # Copyright (c) 2019 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    CONFIG_BT=y
    CONFIG_BT_DEBUG_LOG=y
    CONFIG_BT_CENTRAL=y
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_GATT_DM=y
    CONFIG_HEAP_MEM_POOL_SIZE=1024
    
    CONFIG_BT_SCAN=y
    CONFIG_BT_SCAN_FILTER_ENABLE=y
    CONFIG_BT_SCAN_UUID_CNT=1
    
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    
    CONFIG_DK_LIBRARY=y
    

Children
No Data
Related