Security Level 4 Connection Failure in Central

Hello Nordic Team,

I am working with the nRF5340 Audio DK as a central device, trying to establish a secure connection using Security Level 4 (128-bit encryption with LE Secure Connections).

My goal is to ensure the central device enforces LESC (LE Secure Connections) with 128-bit encryption, but I am facing two major issues when connecting to different peripherals:

Issue 1: Security Level 4 Fails on Connection with Another nRF5340 board

When using another nRF5340 board as a peripheral, running the inbuilt nRF Audio Server code, the connection is established successfully. However, when I attempt to set Security Level 4, it fails with error .

[00:00:12.813,354] <inf> main: Received Command: connect 73:08:D0:98:FC:BD 

[00:00:12.813,446] <inf> main: Attempting to connect to 73:08:D0:98:FC:BD...

[00:00:12.916,320] <inf> main: Connection initiated index : 0 
[00:00:12.994,049] <inf> main: MTU exchanged: 23/23
[00:00:12.994,171] <inf> main: Connected: 73:08:D0:98:FC:BD (random) (index 0)
Security level: 1

[00:00:13.196,289] <err> main: Security failed: 73:08:D0:98:FC:BD (random) level 1 err (4)

[00:00:13.196,319] <inf> main: Pairing Failed (4). Disconnecting.

[00:00:13.296,417] <inf> main: disconnect index : 0 

[00:00:13.296,508] <inf> main: Disconnected: 73:08:D0:98:FC:BD (random), reason 0x16 (BT_HCI_ERR_LOCALHOST_TERM_CONN)

Disconnected:  (err 22 BT_HCI_ERR_LOCALHOST_TERM_CONN) 

in nrf340_audio code i have change prj.conf file and add following config.

CONFIG_BT=y
CONFIG_BT_SMP=y
CONFIG_BT_BONDABLE=y
CONFIG_BT_SMP_SC_PAIR_ONLY=y
CONFIG_BT_PRIVACY=y

  • Why does Security Level 4 fail with error 234?
  • Are there additional configurations needed for enforcing LE Secure Connections (128-bit encryption with LTK)?
  • Is there a way to debug or confirm why the encryption upgrade fails?

Issue 2: Connection Fails with Headset (Peripheral) - BT_HCI_ERR_UNKNOWN_CONN_ID

When attempting to connect to a headset as a peripheral, the connection fails with error 2 (BT_HCI_ERR_UNKNOWN_CONN_ID):

[00:00:36.785,827] <inf> main: Received Command: connect 7E:32:87:8B:18:4F 
[00:00:36.785,919] <inf> main: Attempting to connect to 7E:32:87:8B:18:4F...
[00:00:36.886,810] <inf> main: Connection initiated index : 0 
[00:00:37.846,679] <wrn> bt_hci_core: Connection creation timeout triggered
[00:00:37.846,832] <err> main: Failed to connect to 7E:32:87:8B:18:4F (random) (err 2: BT_HCI_ERR_UNKNOWN_CONN_ID)
ERROR: Failed to connect  (err 2 BT_HCI_ERR_UNKNOWN_CONN_ID) 

  • Why does the connection timeout and fail with BT_HCI_ERR_UNKNOWN_CONN_ID?
  • Do I need to manually set pairing parameters for headset support?
  • Is this issue related to Security Level 4 enforcement, or is it purely a connection establishment issue?

  and also security level is not work . 

Central-Side Configuration & Code

prj.conf (Security Settings for Central)

CONFIG_BT=y
CONFIG_LOG=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_AUDIO=y
CONFIG_BT_ISO_TX_BUF_COUNT=4
# Support an ISO channel per ASE
CONFIG_BT_ISO_MAX_CHAN=4
CONFIG_BT_KEYS_OVERWRITE_OLDEST=y

CONFIG_BT_HCI=y
CONFIG_BT_EXT_ADV=y
CONFIG_SERIAL=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_ASYNC_API=y

# Security Connection(Level 4 - Authenticated Secure Connections and 128-bit key ) 
CONFIG_BT=y
CONFIG_BT_SMP=y
CONFIG_BT_BONDABLE=y
CONFIG_BT_SMP_SC_PAIR_ONLY=y
CONFIG_BT_PRIVACY=y
CONFIG_BT_SMP_APP_PAIRING_ACCEPT=y


#Converts a HCI error to string
CONFIG_BT_HCI_ERR_TO_STR=y

CONFIG_NRFX_UARTE1=y

CONFIG_BT_MAX_CONN=5

CONFIG_BT_DEVICE_NAME="NRF5340_AUDIO_CLIENT"

CONFIG_MAIN_STACK_SIZE=8192
CONFIG_IDLE_STACK_SIZE=1024
CONFIG_ISR_STACK_SIZE=4096
CONFIG_LOG_BUFFER_SIZE=2048

CONFIG_BT_SCAN_WITH_IDENTITY=y
CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE=y

CONFIG_GPIO=y
CONFIG_PWM=y   

Central-Side Connection Code

static struct bt_conn *default_conn;

/* Callback function when connection is established */
static void connected_cb(struct bt_conn *conn, uint8_t err) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

    if (err) {
        LOG_ERR("Failed to connect to %s (err %d: %s)\n", addr, err, bt_hci_err_to_str(err));
        return;
    }

    default_conn = bt_conn_ref(conn);
    LOG_INF("Connected: %s\n", addr);

    /* Get current security level */
    uint8_t sec_level = bt_conn_get_security(conn);
    printk("Security level: %d\n", sec_level);

    /* Attempt to set security level to 4 */
    err = bt_conn_set_security(conn, BT_SECURITY_L4);
    if (err) {
        LOG_ERR("Security Level 4 failed, error code: %d", err);
    }
}

/* Callback function when connection is disconnected */
static void disconnected_cb(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));

    if (default_conn) {
        bt_conn_unref(default_conn);
        default_conn = NULL;
    }

    LOG_INF("Disconnected: %s, reason 0x%02x (%s)\n", addr, reason, bt_hci_err_to_str(reason));
}

/* Callback function when identity is resolved */
static void identity_resolved_cb(struct bt_conn *conn, const bt_addr_le_t *rpa, const bt_addr_le_t *identity) {
    char addr_identity[BT_ADDR_LE_STR_LEN];
    char addr_rpa[BT_ADDR_LE_STR_LEN];

    bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
    bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));

    LOG_INF("Identity resolved %s -> %s\n", addr_rpa, addr_identity);
}

/* Callback function when security level changes */
static void security_changed_cb(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

    if (err) {
        LOG_ERR("Security failed: %s level %u err %s(%d)\n", addr, level, bt_security_err_to_str(err), err);
    } else {
        LOG_INF("Security changed: %s level %u\n", addr, level);
    }
}

/* Connection callbacks */
static struct bt_conn_cb conn_callbacks = {
    .connected = connected_cb,
    .disconnected = disconnected_cb,
    .identity_resolved = identity_resolved_cb,
    .security_changed = security_changed_cb,
};

/* Handle pairing success */
static void auth_pairing_complete_cb(struct bt_conn *conn, bool bonded) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

    LOG_INF("Pairing complete with %s (Bonded: %s)\n", addr, bonded ? "Yes" : "No");

    uint8_t sec_level = bt_conn_get_security(conn);
    if (sec_level == 4) {
        printk("Secure Connections (Level 4) established\n");
    } else {
        printk("Security level: %d\n", sec_level);
    }
}

/* Handle pairing failure */
static void auth_pairing_failed_cb(struct bt_conn *conn, enum bt_security_err reason) {
    LOG_INF("Pairing Failed (%d). Disconnecting.\n", reason);
    bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
}

/* Callback function for bond deletion */
static void auth_bond_deleted_cb(uint8_t id, const bt_addr_le_t *peer) {
    LOG_INF("Bond Information Deleted\n");
}

/* Bluetooth authentication info callback structure */
static struct bt_conn_auth_info_cb auth_info_callbacks = {
    .pairing_complete = auth_pairing_complete_cb,
    .pairing_failed = auth_pairing_failed_cb,
    .bond_deleted = auth_bond_deleted_cb,
};

/* Callback when ATT MTU is updated */
static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx) {
    LOG_INF("MTU exchanged: %u/%u\n", tx, rx);
}

/* GATT callbacks */
static struct bt_gatt_cb gatt_callbacks = {
    .att_mtu_updated = att_mtu_updated,
};

/* Function to handle pairing accept */
static enum bt_security_err auth_pairing_accept_cb(struct bt_conn *conn, const struct bt_conn_pairing_feat *const feat) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Pairing accept for %s\n", addr);

    /* Accept pairing */
    return BT_SECURITY_ERR_SUCCESS;
}

/* Function to handle pairing confirmation */
static void auth_pairing_confirm_cb(struct bt_conn *conn) {
    LOG_INF("Pairing Confirm\n");
    bt_conn_auth_pairing_confirm(conn);
}

/* Function to handle passkey confirmation */
static void auth_passkey_confirm_cb(struct bt_conn *conn, uint32_t passkey) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    printk("Passkey confirmation for %s with passkey %u\n", addr, passkey);

    /* Confirm passkey */
    bt_conn_auth_passkey_confirm(conn);
}

/* Function to display passkey */
static void auth_passkey_display_cb(struct bt_conn *conn, unsigned int passkey) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    LOG_INF("Passkey for %s: %06u\n", addr, passkey);
}

/* Function to handle pairing cancellation */
static void auth_cancel_cb(struct bt_conn *conn) {
    char addr[BT_ADDR_LE_STR_LEN];
    bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    LOG_INF("Pairing cancelled: %s\n", addr);
}

/* Define the authentication callbacks structure */
static struct bt_conn_auth_cb auth_cb_callbacks = {
    .pairing_accept = auth_pairing_accept_cb,
    .pairing_confirm = auth_pairing_confirm_cb,
    .passkey_confirm = auth_passkey_confirm_cb,
    .passkey_display = auth_passkey_display_cb,
    .cancel = auth_cancel_cb,
};

My ultimate aim is to ensure that my central device always connects using Security Level 4, which requires:
  LE Secure Connections (LESC)
  128-bit encryption using Long-Term Key (LTK)
  MITM protection enabled

My Key Questions:

  1. Are my configurations correct for enforcing Security Level 4?
  2. What additional steps or configurations are needed to make it work with both peripherals?
  3. How can I debug or ensure that both devices negotiate LE Secure Connections properly?

I would greatly appreciate any insights, recommendations, or debugging steps to resolve these issues.

Thank you for your time and support! 

Parents
  • Hi,

    Are my configurations correct for enforcing Security Level 4?

    Security level 4 is Autenticated LESC, so there is a form of numeric comparison or passkey entry. As you are making an audio product this is a bit unusual, as there is typically no other I/O than a speaker and/or microhone. That said, I see from your code snippets that you have code for passkey handling, so the basics are in place. Note that in Bluetooth the security requiermetns are set for each characteristic separately

    Other than that, it looks like the question has been processed by AI, and it is difficult to extract the key information here and ther eare some information that I suspect may be some AI hallucination. Can you share your original (non AI processed) question?

  • Hi Einar,

    Thanks for your response! I understand that Security Level 4 requires Authenticated LE Secure Connections (LESC) and a 128-bit encryption key.

    you're absolutely correct! that  Numeric Comparison requires a display or input, while 128-bit AES-CCM encryption does not.

    I have  questions regarding implementing Security Level 4 (Authenticated Secure Connections with 128-bit encryption) on my devices:


    Question 1: Connection and Security Failure with Headset

               Setup:        

                           Central: nRF5340 Audio DK

                           Peripheral: A headset that advertises and waits for connection

                           I want to establish a secure connection using Security Level 4  (Authenticated Secure Connections with 128-bit encryption).

             Issue:

                          The central initiates a connection, but it fails with an unknown connection ID error (err 2: BT_HCI_ERR_UNKNOWN_CONN_ID) after a timeout.

    [00:00:29.509,552] <inf> main: Received Command: connect 8C:64:A2:2D:76:BB 
    [00:00:29.509,643] <inf> main: Attempting to connect to 8C:64:A2:2D:76:BB...
    [00:00:29.612,548] <inf> main: Connection initiated index : 0 
    [00:00:30.570,404] <wrn> bt_hci_core: Connection creation timeout triggered
    [00:00:30.570,556] <err> main: Failed to connect to 8C:64:A2:2D:76:BB (random) (err 2: BT_HCI_ERR_UNKNOWN_CONN_ID)
    ERROR: Failed to connect  (err 2 BT_HCI_ERR_UNKNOWN_CONN_ID) 
    

    Question 2: Security Level 4 Failure Between Two nRF5340 Audio DK Boards

                Setup:

                          Central: nRF5340 Audio DK

                           Peripheral: Another nRF5340 Audio DK (running the example of peripheral secure only code)

                           Security Level 4 is set on the central side.

               Issue

                         The connection establishes successfully, but Security Level 4 fails with error 9 (Authentication Failure) and then disconnects.

    [00:00:09.458,526] <inf> main: Received Command: connect E7:56:71:C4:55:2D 
    
    [00:00:09.458,618] <inf> main: Attempting to connect to E7:56:71:C4:55:2D...
    
    [00:00:09.559,814] <inf> main: Connection initiated index : 0 
                                                                   
    [00:00:09.636,871] <inf> main: MTU exchanged: 23/23
    
    [00:00:09.636,993] <inf> main: Connected: E7:56:71:C4:55:2D (random) (index 0)
    
    [00:00:09.888,427] <err> main: Security failed: E7:56:71:C4:55:2D (random) level 1 err (9)
    
    [00:00:09.888,458] <inf> main: Pairing Failed (9). Disconnecting.
    
    [00:00:09.888,702] <inf> main: disconnect index : 0 
    
    [00:00:09.888,793] <inf> main: Disconnected: E7:56:71:C4:55:2D (random), reason 0x05 (BT_HCI_ERR_AUTH_FAIL)
    
    Disconnected:  (err 5 BT_HCI_ERR_AUTH_FAIL) 
    

    Security Configurations in prj.conf

    CONFIG_BT_SMP=y
    CONFIG_BT_BONDABLE=y
    CONFIG_BT_BONDING_REQUIRED=y
    CONFIG_BT_SMP_SC_PAIR_ONLY=y
    CONFIG_BT_PRIVACY=y
    CONFIG_BT_SMP_APP_PAIRING_ACCEPT=y
    CONFIG_BT_GATT_CLIENT=y
    CONFIG_BT_TINYCRYPT_ECC=y
    CONFIG_BT_HOST_CCM=y
    CONFIG_BT_GATT_CACHING=y
    CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE=y
    CONFIG_BT_L2CAP_TX_MTU=128
    
    CONFIG_SETTINGS=y
    CONFIG_NVS=y
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    

    I want to ensure that in both cases  my central device successfully enforces Security Level 4 and pairing should success, meaning:

    • Security Level 4 should be enforced on all connections.
    • 128-bit encryption should be applied between the central and peripheral.
    • Pairing should succeed without downgrading to lower security levels.

    Would appreciate guidance on what I might be missing or need to adjust!

    Thanks in advance!

  • Hi Einar,

    Thanks for your response!

    I'm using an nRF5340 Audio DK as the central device, which has buttons and can display a passkey via UART. The peripheral is a standard headset/headphones without a display or input method.

    I need to establish a secure connection for LE Audio testing. How do I implement LE Secure Connections (LESC) pairing on the nRF5340 Audio DK (central side)? Additionally, which LESC pairing method would be the most suitable for this setup?

    I’d appreciate any guidance on what I might be missing or need to adjust.

    Thanks in advance for your help!

  • With a headset that does not have a way to handle passkeys, you normally use just works. However, you can still use LESC, but level 4 is not possible as it requiers more I/O (conceptually it could be possible for  a headset to read the LESC passkey out loud, but that would have to be supproted in the headset itself).

    So I suggsest you revert your changes as lecel 4 is not possible. (If you want to only suppor LESC and not legacy pairign, that is possible, and you can do that by adding CONFIG_BT_SMP_DISABLE_LEGACY_JW_PASSKEY=y.)

  • Apologies for the delayed response. I’ve been testing different configurations to troubleshoot this issue.

    security level structure :

    /** Security level. */
    typedef enum __packed {
    	/** Level 0: Only for BR/EDR special cases, like SDP */
    	BT_SECURITY_L0,
    	/** Level 1: No encryption and no authentication. */
    	BT_SECURITY_L1,
    	/** Level 2: Encryption and no authentication (no MITM). */
    	BT_SECURITY_L2,
    	/** Level 3: Encryption and authentication (MITM). */
    	BT_SECURITY_L3,
    	/** Level 4: Authenticated Secure Connections and 128-bit key. */
    	BT_SECURITY_L4,
    	/** Bit to force new pairing procedure, bit-wise OR with requested
    	 *  security level.
    	 */
    	BT_SECURITY_FORCE_PAIR = BIT(7),
    } bt_security_t;
    

    I’m trying to connect the nRF5340 Audio DK (central) to a headset/earbuds while setting the security level to BT_SECURITY_L1 or BT_SECURITY_L2. However, the connection is not being triggered, and I receive the following error:

    [00:00:15.438,110] <inf> main: Received Command: connect AC:BF:71:77:36:32 
    [00:00:15.438,201] <inf> main: Attempting to connect to AC:BF:71:77:36:32...
    [00:00:15.539,398] <inf> main: Connection initiated index : 0 
    [00:00:24.539,062] <wrn> bt_hci_core: Connection creation timeout triggered
    [00:00:24.539,245] <err> main: Failed to connect to AC:BF:71:77:36:32 (random) (err 2: BT_HCI_ERR_UNKNOWN_CONN_ID)
    ERROR: Failed to connect  (err 2 BT_HCI_ERR_UNKNOWN_CONN_ID) 


    Code is :
    static struct bt_conn *default_conn;
    
    /* Callback function when connection is established */
    static void connected_cb(struct bt_conn *conn, uint8_t err) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
        if (err) {
            LOG_ERR("Failed to connect to %s (err %d: %s)\n", addr, err, bt_hci_err_to_str(err));
            return;
        }
    
        default_conn = bt_conn_ref(conn);
        LOG_INF("Connected: %s\n", addr);
    
        /* Get current security level */
        uint8_t sec_level = bt_conn_get_security(conn);
        printk("Security level: %d\n", sec_level);
    
        /* Attempt to set security level to 2 */
        err = bt_conn_set_security(conn, BT_SECURITY_L2);
        if (err) {
            LOG_ERR("Security Level 4 failed, error code: %d", err);
        }
    }
    
    /* Callback function when connection is disconnected */
    static void disconnected_cb(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));
    
        if (default_conn) {
            bt_conn_unref(default_conn);
            default_conn = NULL;
        }
    
        LOG_INF("Disconnected: %s, reason 0x%02x (%s)\n", addr, reason, bt_hci_err_to_str(reason));
    }
    
    /* Callback function when identity is resolved */
    static void identity_resolved_cb(struct bt_conn *conn, const bt_addr_le_t *rpa, const bt_addr_le_t *identity) {
        char addr_identity[BT_ADDR_LE_STR_LEN];
        char addr_rpa[BT_ADDR_LE_STR_LEN];
    
        bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
        bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
    
        LOG_INF("Identity resolved %s -> %s\n", addr_rpa, addr_identity);
    }
    
    /* Callback function when security level changes */
    static void security_changed_cb(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
        if (err) {
            LOG_ERR("Security failed: %s level %u err %s(%d)\n", addr, level, bt_security_err_to_str(err), err);
        } else {
            LOG_INF("Security changed: %s level %u\n", addr, level);
        }
    }
    
    /* Connection callbacks */
    static struct bt_conn_cb conn_callbacks = {
        .connected = connected_cb,
        .disconnected = disconnected_cb,
        .identity_resolved = identity_resolved_cb,
        .security_changed = security_changed_cb,
    };
    
    /* Handle pairing success */
    static void auth_pairing_complete_cb(struct bt_conn *conn, bool bonded) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
        LOG_INF("Pairing complete with %s (Bonded: %s)\n", addr, bonded ? "Yes" : "No");
    
        uint8_t sec_level = bt_conn_get_security(conn);
        if (sec_level == 4) {
            printk("Secure Connections (Level 4) established\n");
        } else {
            printk("Security level: %d\n", sec_level);
        }
    }
    
    /* Handle pairing failure */
    static void auth_pairing_failed_cb(struct bt_conn *conn, enum bt_security_err reason) {
        LOG_INF("Pairing Failed (%d). Disconnecting.\n", reason);
        bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
    }
    
    /* Callback function for bond deletion */
    static void auth_bond_deleted_cb(uint8_t id, const bt_addr_le_t *peer) {
        LOG_INF("Bond Information Deleted\n");
    }
    
    /* Bluetooth authentication info callback structure */
    static struct bt_conn_auth_info_cb auth_info_callbacks = {
        .pairing_complete = auth_pairing_complete_cb,
        .pairing_failed = auth_pairing_failed_cb,
        .bond_deleted = auth_bond_deleted_cb,
    };
    
    /* Callback when ATT MTU is updated */
    static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx) {
        LOG_INF("MTU exchanged: %u/%u\n", tx, rx);
    }
    
    /* GATT callbacks */
    static struct bt_gatt_cb gatt_callbacks = {
        .att_mtu_updated = att_mtu_updated,
    };
    
    /* Function to handle pairing accept */
    static enum bt_security_err auth_pairing_accept_cb(struct bt_conn *conn, const struct bt_conn_pairing_feat *const feat) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
        printk("Pairing accept for %s\n", addr);
    
        /* Accept pairing */
        return BT_SECURITY_ERR_SUCCESS;
    }
    
    /* Function to handle pairing confirmation */
    static void auth_pairing_confirm_cb(struct bt_conn *conn) {
        LOG_INF("Pairing Confirm\n");
        bt_conn_auth_pairing_confirm(conn);
    }
    
    /* Function to handle passkey confirmation */
    static void auth_passkey_confirm_cb(struct bt_conn *conn, uint32_t passkey) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
        printk("Passkey confirmation for %s with passkey %u\n", addr, passkey);
    
        /* Confirm passkey */
        bt_conn_auth_passkey_confirm(conn);
    }
    
    /* Function to display passkey */
    static void auth_passkey_display_cb(struct bt_conn *conn, unsigned int passkey) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
        LOG_INF("Passkey for %s: %06u\n", addr, passkey);
    }
    
    /* Function to handle pairing cancellation */
    static void auth_cancel_cb(struct bt_conn *conn) {
        char addr[BT_ADDR_LE_STR_LEN];
        bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
        LOG_INF("Pairing cancelled: %s\n", addr);
    }
    
    /* Define the authentication callbacks structure */
    static struct bt_conn_auth_cb auth_cb_callbacks = {
        .pairing_accept = auth_pairing_accept_cb,
        .pairing_confirm = auth_pairing_confirm_cb,
        .passkey_confirm = auth_passkey_confirm_cb,
        .passkey_display = auth_passkey_display_cb,
        .cancel = auth_cancel_cb,
    };
    
    
    // Bluetooth connection callback
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	bool err_flage = false;
    	char addr[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (err)
    	{
    		bt_conn_unref(conn);
    		LOG_ERR("Failed to connect to %s (err %d: %s)\n", addr, err, bt_hci_err_to_str(err));
    		send_error("ERROR: Failed to connect ", err);
    		err_flage = true;
    		// return;
    	}
    
    	for (int i = 0; i < MAX_DEVICE; i++)
    	{
    		if (connected_devices[i].connection == conn)
    		{
    			if (err_flage)
    			{
    				connected_devices[i].connection = NULL;
    				return;
    			}
    			connected_devices[i].connection = bt_conn_ref(conn);
    			// bt_conn_ref(conn)
    			bt_addr_le_copy(&connected_devices[i].addr, bt_conn_get_dst(conn)); // Store address
    			device_count++;
    			LOG_INF("Connected: %s (index %d)\n", addr, i);
    			send_uart_response("Success: Connected Successfully ");
    		}
    	}
    
    	uint8_t sec_level = bt_conn_get_security(conn);
    	printk("Security level: %d\n", sec_level);
    
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err)
    	{
    		LOG_INF("Security Level 2 failed");
    	}
    }
    
    // Bluetooth disconnection callback
    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));
    	for (int i = 0; i < MAX_DEVICE; i++)
    	{
    		if (connected_devices[i].connection == conn) // Match connection
    		{
    			bt_conn_unref(conn);
    			// bt_conn_unref(connected_devices[i].connection); // Release reference
    			connected_devices[i].connection = NULL; // Clear slot
    			memset(&connected_devices[i].addr, 0, sizeof(bt_addr_le_t));
    			LOG_INF("disconnect index : %d \n", i);
    			device_count--;
    			break;
    		}
    	}
    	LOG_INF("Disconnected: %s, reason 0x%02x (%s)\n", addr, reason, bt_hci_err_to_str(reason));
    	send_error("Disconnected: ", reason);
    
    	// Check if any lingering references exist
    	if (conn)
    	{
    		LOG_WRN("Forcing unref of stale connection");
    		bt_conn_unref(conn);
    	}
    }
    
    static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
    							  const bt_addr_le_t *identity)
    {
    	char addr_identity[BT_ADDR_LE_STR_LEN];
    	char addr_rpa[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
    	bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
    
    	LOG_INF("Identity resolved %s -> %s\n", addr_rpa, addr_identity);
    }
    
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    							 enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (err)
    	{
    		LOG_ERR("Security failed: %s level %u err %s(%d)\n", addr, level,
    				bt_security_err_to_str(err), err);
    	}
    	else
    	{
    		LOG_INF("Security changed: %s level %u\n", addr, level);
    	}
    }
    
    // Connection callbacks
    static struct bt_conn_cb conn_callbacks = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.identity_resolved = identity_resolved,
    	.security_changed = security_changed,
    };
    
    static void auth_passkey_display_cb(struct bt_conn *conn, unsigned int passkey)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("Passkey for %s: %06u\n", addr, passkey);
    }
    
    static void auth_cancel_cb(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("Pairing cancelled: %s\n", addr);
    	bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
    }
    
    // Define the authentication callbacks structure
    static struct bt_conn_auth_cb auth_cb_callbacks = {
    	.passkey_entry = NULL,
    	.pairing_confirm = NULL ,
    	.passkey_confirm = NULL,
    	.oob_data_request = NULL,
    	.passkey_display = auth_passkey_display_cb,
    	.cancel = auth_cancel_cb,
    };
    
    // Handle pairing success
    static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	LOG_INF("Pairing complete with %s (Bonded: %s)\n", addr, bonded ? "Yes" : "No");
    
    	uint8_t sec_level = bt_conn_get_security(conn);
    	if (sec_level == 4)
    	{
    		printk("Secure Connections (Level 4) established\n");
    	}
    	else
    	{
    		printk("Security level: %d\n", sec_level);
    	}
    }
    
    // Handle pairing failure
    static void auth_pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	LOG_INF("Pairing Failed (%d). Disconnecting.\n", reason);
    	bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
    }
    
    static void auth_bond_deleted(uint8_t id, const bt_addr_le_t *peer)
    {
    	LOG_INF("Bond Information Deleted\n");
    }
    
    // Bluetooth authentication info callback structure
    static struct bt_conn_auth_info_cb auth_info_callbacks = {
    	.pairing_complete = auth_pairing_complete,
    	.pairing_failed = auth_pairing_failed,
    	.bond_deleted = auth_bond_deleted,
    };
    
    static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
    {
    	LOG_INF("MTU exchanged: %u/%u\n", tx, rx);
    }
    
    static struct bt_gatt_cb gatt_callbacks = {
    	.att_mtu_updated = att_mtu_updated,
    };
    
    // Scan parameters
    struct bt_le_scan_param scan_params = {
    	.type = BT_LE_SCAN_TYPE_PASSIVE,
    	.options = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
    	.interval = 0x0050, // 80 ms
    	.window = 0x0050,	// 80 ms
    	.timeout = 0x0200,	// 5 s
    };
    
    // Scan callback
    static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
    						 struct net_buf_simple *ad)
    {
    
    	// We're only interested in connectable events
    	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    		type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND &&
    		type != BT_GAP_ADV_TYPE_EXT_ADV &&
    		type != BT_GAP_ADV_TYPE_SCAN_RSP)
    	{
    		return;
    	}
    
    	// connect only to devices in close proximity
    	if (rssi < -65)
    	{
    		return;
    	}
    
    	add_device_to_responce_list(addr, rssi, ad);
    
    	// Schedule background processing
    	k_work_submit(&process_scan_work);
    }
    
    static int start_scan(void)
    {
    	int err;
    
    	k_work_init(&process_scan_work, process_scan_results);
    
    	err = bt_le_scan_start(&scan_params, device_found);
    	if (err)
    	{
    		LOG_ERR("Scanning failed to start (err %d)\n", err);
    		send_error("ERROR: Scanning failed to start", err);
    		return err;
    	}
    
    	LOG_INF("Scanning...\n");
    	send_uart_response("Success: Scanning started \n");
    
    	return 0;
    }
    
    // static int stop_scan(void)
    // {
    // 	int err;
    
    // 	err = bt_le_scan_stop();
    // 	if (err)
    // 	{
    // 		LOG_ERR("Scanning failed to stop (err %d)\n", err);
    // 		send_error("ERROR: Scanning failed to stop ", err);
    // 		return err;
    // 	}
    // 	LOG_INF("Stop Scanning...\n");
    // 	return 0;
    // }
    
    #define BT_LE_SCAN_INTERVAL 0x0060
    #define BT_LE_SCAN_WINDOW 0x0030
    #define BT_CONN_TIMEOUT 0x0384
    
    struct bt_conn_le_create_param create_param = {
    	.options = BT_CONN_LE_OPT_NONE,
    	.interval = BT_LE_SCAN_INTERVAL,
    	.window = BT_LE_SCAN_WINDOW,
    	.timeout = BT_CONN_TIMEOUT,
    };
    
    static void start_connection(const bt_addr_le_t *addr)
    {
    	int err;
        int i=0;
    	err = bt_le_scan_stop();
    	if (err)
    	{
    		LOG_ERR("Failed to stop scanning (err %d)\n", err);
    		return;
    	}
    
    	k_sleep(K_MSEC(100));
    
    
    		// BT_CONN_LE_CREATE_CONN
    		err = bt_conn_le_create(addr, &create_param, BT_LE_CONN_PARAM_DEFAULT, &connected_devices[i].connection);
    		if (err)
    		{
    			if (err == -EALREADY)
    			{
    				LOG_INF("Device is already connected %d\n", err);
    				
    			}
    			else
    			{
    				LOG_ERR("Failed to create connection (err %d)\n", err);
    			}
            }
    		LOG_INF("Connection initiated index : %d \n ", i);
    			return;
    		
    	}
    }
    


    Error is printing from the hci_core.c:
    int busy_status = k_work_delayable_busy_get(&conn->deferred_work);
    
    		if (!(busy_status & (K_WORK_QUEUED | K_WORK_DELAYED))) {
    			LOG_WRN("Connection creation timeout triggered");
    			conn->err = err;
    			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
    		} else {
    			/* Restart initiator after RPA timeout. */
    			ret = bt_le_create_conn(conn);
    			if (ret) {
    				LOG_ERR("Failed to restart initiator");
    			}
    		}

    On my nRF5340 Audio DK, the bt_le_conn_create() function succeeds and does not return any error.

    However, the connection times out after a few seconds.

    On the headset side, I checked the logs, and the connection event is not generated at all—it seems like the headset does not even see the connection request.

    Questions:

    • Why is the connection request not reaching the headset?

    • Since bt_le_conn_create() does not fail, what else can I check to debug this issue?

    • Could this be related to security settings blocking the connection before pairing?

    • Any suggestions for debugging this from both the nRF5340 side and the headset side?

    I’d appreciate any guidance on what I might be missing or need to adjust.

    Thanks in advance for your help!

  • Hi,

    Yash48 said:

    Questions:

    • Why is the connection request not reaching the headset?

    • Since bt_le_conn_create() does not fail, what else can I check to debug this issue?

    • Could this be related to security settings blocking the connection before pairing?

    As you get BT_HCI_ERR_UNKNOWN_CONN_ID the connection is never established. Does this always happen? is there  an existing bond with the headpohnes?

    Yash48 said:
    Any suggestions for debugging this from both the nRF5340 side and the headset side?

    It would be interesting to see what is acutally happening on air. Can you make a sniffer trace showing the connection attempt?

  • As you get BT_HCI_ERR_UNKNOWN_CONN_ID the connection is never established. Does this always happen? is there  an existing bond with the headpohnes?

    Yes, this happens every time, and there is no existing bonding with the headphones

    It would be interesting to see what is acutally happening on air. Can you make a sniffer trace showing the connection attempt?

    Sure, I will try to capture a sniffer trace and share the results.

    Also, do you have any other suggestions regarding the code or debugging steps that could help identify the issue?
    Let me know if you have any thoughts. Thanks for your response!

Reply
  • As you get BT_HCI_ERR_UNKNOWN_CONN_ID the connection is never established. Does this always happen? is there  an existing bond with the headpohnes?

    Yes, this happens every time, and there is no existing bonding with the headphones

    It would be interesting to see what is acutally happening on air. Can you make a sniffer trace showing the connection attempt?

    Sure, I will try to capture a sniffer trace and share the results.

    Also, do you have any other suggestions regarding the code or debugging steps that could help identify the issue?
    Let me know if you have any thoughts. Thanks for your response!

Children
  • Hi,

    Yash48 said:
    Sure, I will try to capture a sniffer trace and share the results.

    Good, that will be very interesting to see.

    Yash48 said:
    Also, do you have any other suggestions regarding the code or debugging steps that could help identify the issue?

    I think we need to start with the sniffer trace first, so that we see what happens on air. With that, we will hopefully get some pointers on what the issue could be and where to look in the code (but perhaps it would be related to how you initiate connection, do you attempt to connect to the right device, or are there other issues?)

Related