diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 56145bbcd58..36bd5f60b66 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -824,6 +824,219 @@ int bt_conn_update_param_le(struct bt_conn *conn, #endif /* CONFIG_BLUETOOTH_CONN */ +#if defined(CONFIG_BLUETOOTH_BREDR) +static int reject_conn(const bt_addr_t *bdaddr, uint8_t reason) +{ + struct bt_hci_cp_reject_conn_req *cp; + struct net_buf *buf; + int err; + + buf = bt_hci_cmd_create(BT_HCI_OP_REJECT_CONN_REQ, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_copy(&cp->bdaddr, bdaddr); + cp->reason = reason; + + err = bt_hci_cmd_send_sync(BT_HCI_OP_REJECT_CONN_REQ, buf, NULL); + if (err) { + return err; + } + + return 0; +} + +static int accept_conn(const bt_addr_t *bdaddr) +{ + struct bt_hci_cp_accept_conn_req *cp; + struct net_buf *buf; + int err; + + buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_CONN_REQ, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_copy(&cp->bdaddr, bdaddr); + cp->role = BT_HCI_ROLE_SLAVE; + + err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_CONN_REQ, buf, NULL); + if (err) { + return err; + } + + return 0; +} + +static void conn_req(struct net_buf *buf) +{ + struct bt_hci_evt_conn_request *evt = (void *)buf->data; + struct bt_conn *conn; + + BT_DBG("conn req from %s, type 0x%02x", bt_addr_str(&evt->bdaddr), + evt->link_type); + + /* Reject SCO connections until we have support for them */ + if (evt->link_type != BT_HCI_ACL) { + reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES); + return; + } + + conn = bt_conn_add_br(&evt->bdaddr); + if (!conn) { + reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES); + return; + } + + accept_conn(&evt->bdaddr); + conn->role = BT_HCI_ROLE_SLAVE; + bt_conn_set_state(conn, BT_CONN_CONNECT); + bt_conn_unref(conn); +} + +static void conn_complete(struct net_buf *buf) +{ + struct bt_hci_evt_conn_complete *evt = (void *)buf->data; + struct bt_conn *conn; + uint16_t handle = sys_le16_to_cpu(evt->handle); + + BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle, + evt->link_type); + + conn = bt_conn_lookup_addr_br(&evt->bdaddr); + if (!conn) { + BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr)); + return; + } + + if (evt->status) { + conn->err = evt->status; + bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + bt_conn_unref(conn); + return; + } + + conn->handle = handle; + bt_conn_set_state(conn, BT_CONN_CONNECTED); + bt_conn_unref(conn); +} + +static void pin_code_req(struct net_buf *buf) +{ + struct bt_hci_evt_pin_code_req *evt = (void *)buf->data; + struct bt_conn *conn; + + BT_DBG(""); + + conn = bt_conn_lookup_addr_br(&evt->bdaddr); + if (!conn) { + BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr)); + return; + } + + bt_conn_pin_code_req(conn); + bt_conn_unref(conn); +} + +static void link_key_notify(struct net_buf *buf) +{ + struct bt_hci_ev_link_key_notify *evt = (void *)buf->data; + struct bt_conn *conn; + + conn = bt_conn_lookup_addr_br(&evt->bdaddr); + if (!conn) { + BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr)); + return; + } + + BT_DBG("%s, link type 0x%02x", bt_addr_str(&evt->bdaddr), evt->key_type); + + if (!conn->keys) { + conn->keys = bt_keys_get_link_key(&evt->bdaddr); + } + if (!conn->keys) { + BT_ERR("Can't update keys for %s", bt_addr_str(&evt->bdaddr)); + bt_conn_unref(conn); + return; + } + + memcpy(conn->keys->link_key.val, evt->link_key, 16); + + if (evt->key_type == BT_LK_COMBINATION) { + atomic_set_bit(&conn->keys->flags, BT_KEYS_BR_LEGACY); + + /* + * Setting Combination Link Key as AUTHENTICATED means it was + * successfully generated by 16 digits wide PIN code. + */ + if (atomic_test_and_clear_bit(conn->flags, + BT_CONN_BR_LEGACY_SECURE)) { + atomic_set_bit(&conn->keys->flags, + BT_KEYS_AUTHENTICATED); + } + } + + bt_conn_unref(conn); +} + +static void link_key_neg_reply(const bt_addr_t *bdaddr) +{ + struct bt_hci_cp_link_key_neg_reply *cp; + struct net_buf *buf; + + BT_DBG(""); + + buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_NEG_REPLY, sizeof(*cp)); + if (!buf) { + BT_ERR("Out of command buffers"); + return; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_copy(&cp->bdaddr, bdaddr); + bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_NEG_REPLY, buf, NULL); +} + +static void link_key_reply(const bt_addr_t *bdaddr, const uint8_t *lk) +{ + struct bt_hci_cp_link_key_reply *cp; + struct net_buf *buf; + + BT_DBG(""); + + buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_REPLY, sizeof(*cp)); + if (!buf) { + BT_ERR("Out of command buffers"); + return; + } + + cp = net_buf_add(buf, sizeof(*cp)); + bt_addr_copy(&cp->bdaddr, bdaddr); + memcpy(cp->link_key, lk, 16); + bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_REPLY, buf, NULL); +} + +static void link_key_req(struct net_buf *buf) +{ + struct bt_hci_evt_link_key_req *evt = (void *)buf->data; + struct bt_keys *keys; + + BT_DBG("%s", bt_addr_str(&evt->bdaddr)); + + keys = bt_keys_find_link_key(&evt->bdaddr); + if (!keys) { + BT_ERR("Can't find keys for %s", bt_addr_str(&evt->bdaddr)); + link_key_neg_reply(&evt->bdaddr); + return; + } + + link_key_reply(&evt->bdaddr, keys->link_key.val); +} +#endif + #if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR) static void update_sec_level(struct bt_conn *conn) { @@ -1465,220 +1678,6 @@ static void hci_le_meta_event(struct net_buf *buf) } } -#if defined(CONFIG_BLUETOOTH_BREDR) -static int reject_conn(const bt_addr_t *bdaddr, uint8_t reason) -{ - struct bt_hci_cp_reject_conn_req *cp; - struct net_buf *buf; - int err; - - buf = bt_hci_cmd_create(BT_HCI_OP_REJECT_CONN_REQ, sizeof(*cp)); - if (!buf) { - return -ENOBUFS; - } - - cp = net_buf_add(buf, sizeof(*cp)); - bt_addr_copy(&cp->bdaddr, bdaddr); - cp->reason = reason; - - err = bt_hci_cmd_send_sync(BT_HCI_OP_REJECT_CONN_REQ, buf, NULL); - if (err) { - return err; - } - - return 0; -} - -static int accept_conn(const bt_addr_t *bdaddr) -{ - struct bt_hci_cp_accept_conn_req *cp; - struct net_buf *buf; - int err; - - buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_CONN_REQ, sizeof(*cp)); - if (!buf) { - return -ENOBUFS; - } - - cp = net_buf_add(buf, sizeof(*cp)); - bt_addr_copy(&cp->bdaddr, bdaddr); - cp->role = BT_HCI_ROLE_SLAVE; - - err = bt_hci_cmd_send_sync(BT_HCI_OP_ACCEPT_CONN_REQ, buf, NULL); - if (err) { - return err; - } - - return 0; -} - -static void conn_req(struct net_buf *buf) -{ - struct bt_hci_evt_conn_request *evt = (void *)buf->data; - struct bt_conn *conn; - - BT_DBG("conn req from %s, type 0x%02x", bt_addr_str(&evt->bdaddr), - evt->link_type); - - /* Reject SCO connections until we have support for them */ - if (evt->link_type != BT_HCI_ACL) { - reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES); - return; - } - - conn = bt_conn_add_br(&evt->bdaddr); - if (!conn) { - reject_conn(&evt->bdaddr, BT_HCI_ERR_INSUFFICIENT_RESOURCES); - return; - } - - accept_conn(&evt->bdaddr); - conn->role = BT_HCI_ROLE_SLAVE; - bt_conn_set_state(conn, BT_CONN_CONNECT); - bt_conn_unref(conn); -} - -static void conn_complete(struct net_buf *buf) -{ - struct bt_hci_evt_conn_complete *evt = (void *)buf->data; - struct bt_conn *conn; - uint16_t handle = sys_le16_to_cpu(evt->handle); - - BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle, - evt->link_type); - - conn = bt_conn_lookup_addr_br(&evt->bdaddr); - if (!conn) { - BT_ERR("Unable to find conn for %s", bt_addr_str(&evt->bdaddr)); - return; - } - - if (evt->status) { - conn->err = evt->status; - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - bt_conn_unref(conn); - return; - } - - conn->handle = handle; - bt_conn_set_state(conn, BT_CONN_CONNECTED); - bt_conn_unref(conn); -} - -static void pin_code_req(struct net_buf *buf) -{ - struct bt_hci_evt_pin_code_req *evt = (void *)buf->data; - struct bt_conn *conn; - - BT_DBG(""); - - conn = bt_conn_lookup_addr_br(&evt->bdaddr); - if (!conn) { - BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr)); - return; - } - - bt_conn_pin_code_req(conn); - - bt_conn_unref(conn); -} - -static void link_key_notify(struct net_buf *buf) -{ - struct bt_hci_ev_link_key_notify *evt = (void *)buf->data; - struct bt_conn *conn; - - conn = bt_conn_lookup_addr_br(&evt->bdaddr); - if (!conn) { - BT_ERR("Can't find conn for %s", bt_addr_str(&evt->bdaddr)); - return; - } - - BT_DBG("%s, link type 0x%02x", bt_addr_str(&evt->bdaddr), evt->key_type); - - if (!conn->keys) { - conn->keys = bt_keys_get_link_key(&evt->bdaddr); - } - if (!conn->keys) { - BT_ERR("Can't update keys for %s", bt_addr_str(&evt->bdaddr)); - bt_conn_unref(conn); - return; - } - - memcpy(conn->keys->link_key.val, evt->link_key, 16); - - if (evt->key_type == BT_LK_COMBINATION) { - atomic_set_bit(&conn->keys->flags, BT_KEYS_BR_LEGACY); - - /* - * Setting Combination Link Key as AUTHENTICATED means it was - * successfully generated by 16 digits wide PIN code. - */ - if (atomic_test_and_clear_bit(conn->flags, - BT_CONN_BR_LEGACY_SECURE)) { - atomic_set_bit(&conn->keys->flags, - BT_KEYS_AUTHENTICATED); - } - } - - bt_conn_unref(conn); -} - -static void link_key_neg_reply(const bt_addr_t *bdaddr) -{ - struct bt_hci_cp_link_key_neg_reply *cp; - struct net_buf *buf; - - BT_DBG(""); - - buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_NEG_REPLY, sizeof(*cp)); - if (!buf) { - BT_ERR("Out of command buffers"); - return; - } - - cp = net_buf_add(buf, sizeof(*cp)); - bt_addr_copy(&cp->bdaddr, bdaddr); - bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_NEG_REPLY, buf, NULL); -} - -static void link_key_reply(const bt_addr_t *bdaddr, const uint8_t *lk) -{ - struct bt_hci_cp_link_key_reply *cp; - struct net_buf *buf; - - BT_DBG(""); - - buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_REPLY, sizeof(*cp)); - if (!buf) { - BT_ERR("Out of command buffers"); - return; - } - - cp = net_buf_add(buf, sizeof(*cp)); - bt_addr_copy(&cp->bdaddr, bdaddr); - memcpy(cp->link_key, lk, 16); - bt_hci_cmd_send_sync(BT_HCI_OP_LINK_KEY_REPLY, buf, NULL); -} - -static void link_key_req(struct net_buf *buf) -{ - struct bt_hci_evt_link_key_req *evt = (void *)buf->data; - struct bt_keys *keys; - - BT_DBG("%s", bt_addr_str(&evt->bdaddr)); - - keys = bt_keys_find_link_key(&evt->bdaddr); - if (!keys) { - BT_ERR("Can't find keys for %s", bt_addr_str(&evt->bdaddr)); - link_key_neg_reply(&evt->bdaddr); - return; - } - - link_key_reply(&evt->bdaddr, keys->link_key.val); -} -#endif - static void hci_event(struct net_buf *buf) { struct bt_hci_evt_hdr *hdr = (void *)buf->data;