Cannot connect to nRF when in direct advertisement mode

Hello, I'm trying to manage connecting to my board (nRF52840-DK) which direct advertise (low prio) with peer address set to MAC address of my PC running Linux with bluez 5.62-1. Unfortunately I cannot connect to the board, no matter what. I develop the board with Zephyr RTOS. This is the code responsible for setting up advertisement:

static void bt_ready(void)
{
  int err;
  bt_addr_le_t dir_addr;

  const char *address = "D8:8F:76:5B:57:7E";
  const char *type = "public";
  if ((err = bt_addr_le_from_str(address, type, &dir_addr))) {
    printk("Bt_addr_le_from_str error: %d\n", err);
  }

  err = bt_le_adv_start(BT_LE_ADV_CONN_DIR_LOW_DUTY(&dir_addr), ad, ARRAY_SIZE(ad), NULL, 0);
  if (err) {
    printk("Advertising failed to start (err %d)\n", err);
    return;
  }

  printk("Advertising successfully started\n");
}

If i set the advertisement mode to BT_LE_ADV_CONN_NAME, then there is no problem - the device is scannable and connectable.

My question is - can someone post any code or describe any method that will allow me to connect my PC to the board?

Parents Reply Children
  • You're right, it is possible to scan for a device that advertise directly (I managed to do it using hciconfig and hcitool). However I just cannot manage to connect to the device, even though my scanner sees it. I'll dig into it. Thanks for your help.

  • Ok, I managed to connect to the board using bettercap tool. Now, what's happening is that after my PC disconnects from the board I cannot start direct advertisement again. What I tried to do was to start it in the disconnection callback:

    static void bt_start_adv_direct(const char *address, const char *type) {
      printk("Begin direct advertising to %s (%s).\n", address, type);
      int err;
    
      bt_addr_le_t dir_addr;
      if ((err = bt_addr_le_from_str(address, type, &dir_addr))) {
        printk("Bt_addr_le_from_str error: %d\n", err);
      }
    
      err = bt_le_adv_start(BT_LE_ADV_CONN_DIR_LOW_DUTY(&dir_addr), ad, ARRAY_SIZE(ad), NULL, 0);
      if (err) {
        printk("Advertising failed to start (err %d)\n", err);
        return;
      }
    
      printk("Advertising successfully started, directed to: %s\n", address);
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason) {
        printk("Disconnected (reason 0x%02x)\n", reason);
        bt_start_adv_direct(address, type); // global arrays
    }  

    Logs from nRF:

    *** Booting Zephyr OS build v2.6.1-rc1-21-g42d7e712063b  ***
    Set up button at GPIO_0 pin 11
    Set up LED at GPIO_0 pin 13
    Address: DB:94:18:97:FE:0D (random)
    Bluetooth initialized
    Begin direct advertising to 18:1D:EA:9C:EF:E5 (public).
    Advertising successfully started, directed to: 18:1D:EA:9C:EF:E5
    Connected
    Disconnected (reason 0x13)
    Begin direct advertising to 18:1D:EA:9C:EF:E5 (public).
    Advertising failed to start (err -22)

    As you can see, advertisement sets up when I call the `bt_start_adv_direct` for the first time in my main function, but it fails when called from the `disconnected` callback. I don't understand why the error code is 22 (afaik it's "Invalid argument" error). What should I do to restart advertisement after disconnection? 

  • I found what was the issue. The  `bt_le_adv_start` function calls at some point `bt_conn_exists_le`, which looks like this:

    bool bt_conn_exists_le(uint8_t id, const bt_addr_le_t *peer)
    {
    	struct bt_conn *conn = bt_conn_lookup_addr_le(id, peer);
    
    	if (conn) {
    		/* Connection object already exists.
    		 * If the connection state is not "disconnected",then the
    		 * connection was created but has not yet been disconnected.
    		 * If the connection state is "disconnected" then the connection
    		 * still has valid references. The last reference of the stack
    		 * is released after the disconnected callback.
    		 */
    		BT_WARN("Found valid connection in %s state",
    			state2str(conn->state));
    		bt_conn_unref(conn);
    		return true;
    	}
    
    	return false;
    }

    So, you cannot start advertisement in the disconnected callback.

Related