Skip to content

Commit

Permalink
Bluetooth: Classic: GAP: initiate bredr pairing and unpair
Browse files Browse the repository at this point in the history
bug: v/43281

bt_conn_pair_br: pair with a remote device and
return the connection.
bt_br_unpair: remove paired device and linkkey.

Signed-off-by: fangzhenwei <[email protected]>
  • Loading branch information
Frozen935 committed Jan 13, 2025
1 parent 5af255c commit 0be6e80
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 1 deletion.
12 changes: 12 additions & 0 deletions include/zephyr/bluetooth/classic/classic.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,18 @@ typedef void (*bt_br_remote_name_req_cb_t)(const bt_addr_t *bdaddr, const char *
*/
int bt_br_remote_name_request(const bt_addr_t *addr, bt_br_remote_name_req_cb_t cb);

/**
* @brief Unpair with a br remote device.
*
* remove the bond information with the remote device in controller
* or settings.
*
* @param bdaddr Remote device address.
*
* @return 0 on success or negative error value on failure.
*/
int bt_br_unpair(bt_addr_t *bdaddr);

/**
* @}
*/
Expand Down
15 changes: 15 additions & 0 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,21 @@ struct bt_conn_auth_info_cb {
sys_snode_t node;
};

/**
* @brief Initiate pairing with a remote device.
*
* This function is used to initiate pairing with a remote device.
* The pairing process is asynchronous and the result of the pairing
* process is reported through the pairing_complete, if the connection
* not exists, setup the connection first.
*
* @param bdaddr Remote device address.
* @param security Security level to use.
*
* @return Valid connection object on success or NULL otherwise.
*/
struct bt_conn *bt_conn_pair_br(bt_addr_t *bdaddr, bt_security_t security);

/** @brief Register authentication callbacks.
*
* Register callbacks to handle authenticated pairing. Passing NULL
Expand Down
8 changes: 8 additions & 0 deletions include/zephyr/bluetooth/hci_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ struct bt_hci_cmd_hdr {
#define BT_FEAT_2EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 5)
#define BT_FEAT_3EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 6)
#define BT_FEAT_3SLOT_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 7)
#define BT_FEAT_SSP(feat) BT_FEAT_TEST(feat, 0, 6, 3)

/* LE features */
#define BT_LE_FEAT_BIT_ENC 0
Expand Down Expand Up @@ -601,6 +602,13 @@ struct bt_hci_cp_set_event_mask {

#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003) /* 0x0c03 */

struct bt_hci_delete_stored_link_key {
bt_addr_t bdaddr;
uint8_t delete_all;
} __packed;

#define BT_HCI_OP_DELETE_STORED_LINK_KEY BT_OP(BT_OGF_BASEBAND, 0x0012) /* 0x0c12 */

Check notice on line 611 in include/zephyr/bluetooth/hci_types.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

include/zephyr/bluetooth/hci_types.h:611 - uint8_t delete_all; -} __packed; - -#define BT_HCI_OP_DELETE_STORED_LINK_KEY BT_OP(BT_OGF_BASEBAND, 0x0012) /* 0x0c12 */ + uint8_t delete_all; +} __packed; + +#define BT_HCI_OP_DELETE_STORED_LINK_KEY BT_OP(BT_OGF_BASEBAND, 0x0012) /* 0x0c12 */
#define BT_HCI_OP_WRITE_LOCAL_NAME BT_OP(BT_OGF_BASEBAND, 0x0013) /* 0x0c13 */
struct bt_hci_write_local_name {
uint8_t local_name[248];
Expand Down
73 changes: 72 additions & 1 deletion subsys/bluetooth/host/classic/br.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ void bt_hci_conn_complete(struct net_buf *buf)
}

if (evt->status) {
if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND)) {
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND);
bt_conn_security_changed(conn, evt->status,
bt_security_err_get(evt->status));
}

conn->err = evt->status;
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
bt_conn_unref(conn);
Expand All @@ -262,6 +268,17 @@ void bt_hci_conn_complete(struct net_buf *buf)

bt_conn_connected(conn);

if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND)) {
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND);
if (bt_conn_set_security(conn, conn->attempt_sec_level)) {
bt_conn_security_changed(conn, BT_HCI_ERR_AUTH_FAIL,
BT_SECURITY_ERR_AUTH_FAIL);
bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
bt_conn_unref(conn);
return;
}
}

bt_conn_unref(conn);

buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_FEATURES, sizeof(*cp));
Expand Down Expand Up @@ -1293,4 +1310,58 @@ int bt_br_remote_name_request(const bt_addr_t *bdaddr, bt_br_remote_name_req_cb_
}

return 0;
}
}

int bt_br_delete_stored_link_key(const bt_addr_t *bdaddr, bool delete_all)
{
struct net_buf *buf;
struct bt_hci_delete_stored_link_key *cp;

buf = bt_hci_cmd_create(BT_HCI_OP_DELETE_STORED_LINK_KEY, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}

cp = net_buf_add(buf, sizeof(*cp));
memset(cp, 0, sizeof(*cp));
bt_addr_copy(&cp->bdaddr, bdaddr);
cp->delete_all = delete_all;

return bt_hci_cmd_send_sync(BT_HCI_OP_DELETE_STORED_LINK_KEY, buf, NULL);
}

int bt_br_unpair(bt_addr_t *bdaddr)
{
struct bt_conn_auth_info_cb *listener, *next;
bt_addr_le_t addr;
struct bt_conn *conn;

if (!IS_ENABLED(CONFIG_BT_CLASSIC)) {
return -ENOTSUP;
}

/* Disconnect acl connection if connection is existed */
conn = bt_conn_lookup_addr_br(bdaddr);
if (conn) {
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
bt_conn_unref(conn);
}

/* Delete stored link key from settings */
bt_keys_link_key_clear_addr(bdaddr);

/* Delete stored link key from controller */
bt_br_delete_stored_link_key(bdaddr, true);

addr.type = BT_ADDR_LE_PUBLIC;
memcpy(&addr, bdaddr, sizeof(addr));

SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&bt_auth_info_cbs, listener,
next, node) {
if (listener->bond_deleted) {
listener->bond_deleted(0, &addr);
}
}

return 0;
}
58 changes: 58 additions & 0 deletions subsys/bluetooth/host/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2780,6 +2780,64 @@ bt_security_t bt_conn_get_security(const struct bt_conn *conn)
}
#endif /* CONFIG_BT_SMP */

#if defined(CONFIG_BT_CLASSIC)
struct bt_conn *bt_conn_pair_br(bt_addr_t *bdaddr, bt_security_t security)
{
struct bt_conn *conn;
int err;

LOG_DBG("");

/* Tell controller to delete the link key if it has one stored */
err = bt_br_delete_stored_link_key(bdaddr, 1);
if (err) {
return NULL;
}

if (!BT_FEAT_SSP(bt_dev.features)) {
/* pin type */
LOG_DBG("pin type");
}

/* Check if connection is existed */
conn = bt_conn_lookup_addr_br(bdaddr);
if (conn) {
/* Check pairing process is onging */
if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR) ||
atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND) ||
atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING)) {
bt_conn_unref(conn);
return NULL;
}

if (conn->state == BT_CONN_CONNECTED) {
err = bt_conn_set_security(conn, security);
if (!err) {
return conn;
}
} else if (conn->state == BT_CONN_INITIATING) {
conn->attempt_sec_level = security;
atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND);
return conn;
}

bt_conn_unref(conn);
return NULL;
} else {

Check warning on line 2826 in subsys/bluetooth/host/conn.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

UNNECESSARY_ELSE

subsys/bluetooth/host/conn.c:2826 else is not generally useful after a break or return
/* Try to create a br connection */
conn = bt_conn_create_br(bdaddr, BT_BR_CONN_PARAM_DEFAULT);
if (!conn) {
return NULL;
}

conn->attempt_sec_level = security;
atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING_CONN_PEND);
}

return conn;
}
#endif /* CONFIG_BT_CLASSIC */

int bt_conn_cb_register(struct bt_conn_cb *cb)
{
if (sys_slist_find(&conn_cbs, &cb->_node, NULL)) {
Expand Down
2 changes: 2 additions & 0 deletions subsys/bluetooth/host/conn_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ enum {
BT_CONN_BR_NOBOND, /* SSP no bond pairing tracker */
BT_CONN_BR_GENERAL_BONDING, /* BR general bonding */
BT_CONN_BR_PAIRING_INITIATOR, /* local host starts authentication */
BT_CONN_BR_PAIRING_CONN_PEND, /* local host starts authentication waiting for connection setup */

Check warning on line 67 in subsys/bluetooth/host/conn_internal.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE_COMMENT

subsys/bluetooth/host/conn_internal.h:67 line length of 113 exceeds 100 columns
BT_CONN_CLEANUP, /* Disconnected, pending cleanup */
BT_CONN_AUTO_INIT_PROCEDURES_DONE, /* Auto-initiated procedures have run */
BT_CONN_PERIPHERAL_PARAM_UPDATE, /* If periph param update timer fired */
Expand Down Expand Up @@ -229,6 +230,7 @@ struct bt_conn {
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_CLASSIC)
bt_security_t sec_level;
bt_security_t required_sec_level;
bt_security_t attempt_sec_level;
uint8_t encrypt;
#endif /* CONFIG_BT_SMP || CONFIG_BT_CLASSIC */

Expand Down

0 comments on commit 0be6e80

Please sign in to comment.