Hi all!
I'm developing a BLE device implementing automation IO profile, peripheral role.
I can connect normally and discover all services and characteristics from nRF Connect android app, but after bonding, I never can connect again, I receive
Security failed: 3C:CD:5D:3F:DC:50 (public) level 1 err 9
Disconnected (reason 61)
Am I missing something? Do I need to manually save bond information?
My code is the following:
#include <zephyr/zephyr.h> #include <zephyr/logging/log.h> #include <zephyr/bluetooth/bluetooth.h> #include <zephyr/bluetooth/uuid.h> #include <zephyr/bluetooth/gatt.h> #include <zephyr/settings/settings.h> #include <device.h> #include <drivers/flash.h> #include <storage/flash_map.h> #include <fs/nvs.h> #include <stdio.h> #include <string.h> #include "../cfg/config.h" #include "ble.h" #include <zephyr/kernel.h> #include <zephyr/sys/reboot.h> #include <zephyr/sys/printk.h> #include <inttypes.h> LOG_MODULE_REGISTER(ble); static void ccc_changed(const struct bt_gatt_attr *attr, uint16_t value) { } static ssize_t uart_tx_chr_read(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { return 0; } static ssize_t uart_rx_chr_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags){ return 0; } static ssize_t device_name_chr_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags){ char prueba[100] = {}; memcpy(prueba, buf, len); printk("Nuevo nombre: %s\n", prueba); return 0; } /* Custom service variables */ #define BT_UUID_SERVER_UART BT_UUID_128_ENCODE(0x0003CDD0, 0x0000, 0x1000, 0x8000, 0x00805f9b0131) static struct bt_uuid_128 server_uart_tx_uuid = BT_UUID_INIT_128( BT_UUID_128_ENCODE(0x0003CDD1, 0x0000, 0x1000, 0x8000, 0x00805f9b0131)); static struct bt_uuid_128 server_uart_rx_uuid = BT_UUID_INIT_128( BT_UUID_128_ENCODE(0x0003CDD2, 0x0000, 0x1000, 0x8000, 0x00805f9b0131)); static const uint8_t device_name[] = DEF_BLE_NAME; static struct bt_uuid_16 automation_io_uuid = BT_UUID_INIT_16( 0x1815 ); static struct bt_uuid_16 device_name_uuid = BT_UUID_INIT_16( BT_UUID_GAP_DEVICE_NAME_VAL ); /* UART custom service declaration */ BT_GATT_SERVICE_DEFINE(automation_io_svc, BT_GATT_PRIMARY_SERVICE(&automation_io_uuid), BT_GATT_CHARACTERISTIC(&device_name_uuid.uuid, BT_GATT_CHRC_WRITE_WITHOUT_RESP | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, NULL, device_name_chr_write, NULL ), BT_GATT_CHARACTERISTIC(&server_uart_tx_uuid.uuid, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, uart_tx_chr_read, NULL, NULL ), BT_GATT_CCC(ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), BT_GATT_CHARACTERISTIC(&server_uart_rx_uuid.uuid, BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE, NULL, uart_rx_chr_write, NULL ), ); static struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), BT_DATA(BT_DATA_NAME_COMPLETE, device_name, sizeof(device_name)-1), BT_DATA(BT_DATA_UUID16_ALL, &automation_io_uuid.val, sizeof(automation_io_uuid.val)), }; static void connected(struct bt_conn *conn, uint8_t err) { if (err) { printk("Connection failed (err %u)\n", err); return; } printk("Connected\n"); } static void disconnected(struct bt_conn *conn, uint8_t reason) { printk("Disconnected (reason %u)\n", reason); } 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) { printk("Security changed: %s level %u\n", addr, level); } else { printk("Security failed: %s level %u err %d\n", addr, level, err); } } BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = connected, .disconnected = disconnected, .security_changed = security_changed, }; static void auth_passkey_display(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)); printk("Passkey for %s: %06u\n", addr, passkey); } static void auth_cancel(struct bt_conn *conn) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); printk("Pairing cancelled: %s\n", addr); } static void 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)); printk("Pairing completed: %s, bonded: %d\n", addr, bonded); } static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); printk("Pairing failed conn: %s, reason %d\n", addr, reason); } static struct bt_conn_auth_cb conn_auth_callbacks = { .passkey_display = auth_passkey_display, .cancel = auth_cancel, }; static struct bt_conn_auth_info_cb conn_auth_info_callbacks = { .pairing_complete = pairing_complete, .pairing_failed = pairing_failed }; int ble_init(void) { int err; LOG_INF("%s", "Starting BLE"); err = bt_conn_auth_cb_register(&conn_auth_callbacks); if (err) { printk("Failed to register authorization callbacks.\n"); return -1; } err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); if (err) { printk("Failed to register authorization info callbacks.\n"); return -1; } err = bt_enable(NULL); if (err) { LOG_ERR("%s", "BLE enable error"); return -1; } else { LOG_INF("%s", "Bluetooth initialized"); } if (IS_ENABLED(CONFIG_SETTINGS)) { settings_load(); LOG_INF("%s", "Settings loaded"); } /* Start advertising */ err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { LOG_ERR("Advertising failed to start (err %d)", err); return -1; } return 0; }
Thanks!
Pedro.