]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/bluetooth/hci_event.c
Merge tag 'linux-kselftest-4.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / net / bluetooth / hci_event.c
index 32363c2b7f83d7b458eb303e2fbe7a8b050539b5..186041866315a4e107de086df52142f39d6c6ee3 100644 (file)
@@ -823,7 +823,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
        if (rp->status)
-               goto a2mp_rsp;
+               return;
 
        hdev->amp_status = rp->amp_status;
        hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -835,46 +835,6 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
        hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
        hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
-
-a2mp_rsp:
-       a2mp_send_getinfo_rsp(hdev);
-}
-
-static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
-                                       struct sk_buff *skb)
-{
-       struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data;
-       struct amp_assoc *assoc = &hdev->loc_assoc;
-       size_t rem_len, frag_len;
-
-       BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
-
-       if (rp->status)
-               goto a2mp_rsp;
-
-       frag_len = skb->len - sizeof(*rp);
-       rem_len = __le16_to_cpu(rp->rem_len);
-
-       if (rem_len > frag_len) {
-               BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
-
-               memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
-               assoc->offset += frag_len;
-
-               /* Read other fragments */
-               amp_read_loc_assoc_frag(hdev, rp->phy_handle);
-
-               return;
-       }
-
-       memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
-       assoc->len = assoc->offset + rem_len;
-       assoc->offset = 0;
-
-a2mp_rsp:
-       /* Send A2MP Rsp when all fragments are received */
-       a2mp_send_getampassoc_rsp(hdev, rp->status);
-       a2mp_send_create_phy_link_req(hdev, rp->status);
 }
 
 static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
@@ -1099,7 +1059,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
                hci_dev_set_flag(hdev, HCI_LE_ADV);
 
-               conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+               conn = hci_lookup_le_connect(hdev);
                if (conn)
                        queue_delayed_work(hdev->workqueue,
                                           &conn->le_conn_timeout,
@@ -1409,20 +1369,6 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
        hci_dev_unlock(hdev);
 }
 
-static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
-                                         struct sk_buff *skb)
-{
-       struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data;
-
-       BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
-              hdev->name, rp->status, rp->phy_handle);
-
-       if (rp->status)
-               return;
-
-       amp_write_rem_assoc_continue(hdev, rp->phy_handle);
-}
-
 static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_rp_read_rssi *rp = (void *) skb->data;
@@ -1944,47 +1890,6 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
        hci_dev_unlock(hdev);
 }
 
-static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status)
-{
-       struct hci_cp_create_phy_link *cp;
-
-       BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-       cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
-       if (!cp)
-               return;
-
-       hci_dev_lock(hdev);
-
-       if (status) {
-               struct hci_conn *hcon;
-
-               hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
-               if (hcon)
-                       hci_conn_del(hcon);
-       } else {
-               amp_write_remote_assoc(hdev, cp->phy_handle);
-       }
-
-       hci_dev_unlock(hdev);
-}
-
-static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status)
-{
-       struct hci_cp_accept_phy_link *cp;
-
-       BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
-       if (status)
-               return;
-
-       cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
-       if (!cp)
-               return;
-
-       amp_write_remote_assoc(hdev, cp->phy_handle);
-}
-
 static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
 {
        struct hci_cp_le_create_conn *cp;
@@ -2998,10 +2903,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
                hci_cc_read_clock(hdev, skb);
                break;
 
-       case HCI_OP_READ_LOCAL_AMP_ASSOC:
-               hci_cc_read_local_amp_assoc(hdev, skb);
-               break;
-
        case HCI_OP_READ_INQ_RSP_TX_POWER:
                hci_cc_read_inq_rsp_tx_power(hdev, skb);
                break;
@@ -3106,10 +3007,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
                hci_cc_set_adv_param(hdev, skb);
                break;
 
-       case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
-               hci_cc_write_remote_amp_assoc(hdev, skb);
-               break;
-
        case HCI_OP_READ_RSSI:
                hci_cc_read_rssi(hdev, skb);
                break;
@@ -3193,14 +3090,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
                hci_cs_setup_sync_conn(hdev, ev->status);
                break;
 
-       case HCI_OP_CREATE_PHY_LINK:
-               hci_cs_create_phylink(hdev, ev->status);
-               break;
-
-       case HCI_OP_ACCEPT_PHY_LINK:
-               hci_cs_accept_phylink(hdev, ev->status);
-               break;
-
        case HCI_OP_SNIFF_MODE:
                hci_cs_sniff_mode(hdev, ev->status);
                break;
@@ -3837,17 +3726,25 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
                if (ev->link_type == ESCO_LINK)
                        goto unlock;
 
+               /* When the link type in the event indicates SCO connection
+                * and lookup of the connection object fails, then check
+                * if an eSCO connection object exists.
+                *
+                * The core limits the synchronous connections to either
+                * SCO or eSCO. The eSCO connection is preferred and tried
+                * to be setup first and until successfully established,
+                * the link type will be hinted as eSCO.
+                */
                conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
                if (!conn)
                        goto unlock;
-
-               conn->type = SCO_LINK;
        }
 
        switch (ev->status) {
        case 0x00:
                conn->handle = __le16_to_cpu(ev->handle);
                conn->state  = BT_CONNECTED;
+               conn->type   = ev->link_type;
 
                hci_debugfs_create_conn(conn);
                hci_conn_add_sysfs(conn);
@@ -4399,6 +4296,23 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+#if IS_ENABLED(CONFIG_BT_HS)
+static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_ev_channel_selected *ev = (void *)skb->data;
+       struct hci_conn *hcon;
+
+       BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+
+       skb_pull(skb, sizeof(*ev));
+
+       hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+       if (!hcon)
+               return;
+
+       amp_read_loc_assoc_final_data(hdev, hcon);
+}
+
 static void hci_phy_link_complete_evt(struct hci_dev *hdev,
                                      struct sk_buff *skb)
 {
@@ -4522,6 +4436,7 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
 
        hci_dev_unlock(hdev);
 }
+#endif
 
 static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
@@ -4540,7 +4455,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
         */
        hci_dev_clear_flag(hdev, HCI_LE_ADV);
 
-       conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+       conn = hci_lookup_le_connect(hdev);
        if (!conn) {
                conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role);
                if (!conn) {
@@ -4733,42 +4648,49 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
        /* If we're not connectable only connect devices that we have in
         * our pend_le_conns list.
         */
-       params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
-                                          addr, addr_type);
+       params = hci_explicit_connect_lookup(hdev, addr, addr_type);
+
        if (!params)
                return NULL;
 
-       switch (params->auto_connect) {
-       case HCI_AUTO_CONN_DIRECT:
-               /* Only devices advertising with ADV_DIRECT_IND are
-                * triggering a connection attempt. This is allowing
-                * incoming connections from slave devices.
-                */
-               if (adv_type != LE_ADV_DIRECT_IND)
+       if (!params->explicit_connect) {
+               switch (params->auto_connect) {
+               case HCI_AUTO_CONN_DIRECT:
+                       /* Only devices advertising with ADV_DIRECT_IND are
+                        * triggering a connection attempt. This is allowing
+                        * incoming connections from slave devices.
+                        */
+                       if (adv_type != LE_ADV_DIRECT_IND)
+                               return NULL;
+                       break;
+               case HCI_AUTO_CONN_ALWAYS:
+                       /* Devices advertising with ADV_IND or ADV_DIRECT_IND
+                        * are triggering a connection attempt. This means
+                        * that incoming connectioms from slave device are
+                        * accepted and also outgoing connections to slave
+                        * devices are established when found.
+                        */
+                       break;
+               default:
                        return NULL;
-               break;
-       case HCI_AUTO_CONN_ALWAYS:
-               /* Devices advertising with ADV_IND or ADV_DIRECT_IND
-                * are triggering a connection attempt. This means
-                * that incoming connectioms from slave device are
-                * accepted and also outgoing connections to slave
-                * devices are established when found.
-                */
-               break;
-       default:
-               return NULL;
+               }
        }
 
        conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
                              HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
        if (!IS_ERR(conn)) {
-               /* Store the pointer since we don't really have any
+               /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
+                * by higher layer that tried to connect, if no then
+                * store the pointer since we don't really have any
                 * other owner of the object besides the params that
                 * triggered it. This way we can abort the connection if
                 * the parameters get removed and keep the reference
                 * count consistent once the connection is established.
                 */
-               params->conn = hci_conn_get(conn);
+
+               if (!params->explicit_connect)
+                       params->conn = hci_conn_get(conn);
+
                return conn;
        }
 
@@ -5206,22 +5128,6 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
        }
 }
 
-static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
-       struct hci_ev_channel_selected *ev = (void *) skb->data;
-       struct hci_conn *hcon;
-
-       BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
-
-       skb_pull(skb, sizeof(*ev));
-
-       hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
-       if (!hcon)
-               return;
-
-       amp_read_loc_assoc_final_data(hdev, hcon);
-}
-
 static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
                                 u8 event, struct sk_buff *skb)
 {
@@ -5442,14 +5348,15 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
                hci_le_meta_evt(hdev, skb);
                break;
 
-       case HCI_EV_CHANNEL_SELECTED:
-               hci_chan_selected_evt(hdev, skb);
-               break;
-
        case HCI_EV_REMOTE_OOB_DATA_REQUEST:
                hci_remote_oob_data_request_evt(hdev, skb);
                break;
 
+#if IS_ENABLED(CONFIG_BT_HS)
+       case HCI_EV_CHANNEL_SELECTED:
+               hci_chan_selected_evt(hdev, skb);
+               break;
+
        case HCI_EV_PHY_LINK_COMPLETE:
                hci_phy_link_complete_evt(hdev, skb);
                break;
@@ -5465,6 +5372,7 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
        case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
                hci_disconn_phylink_complete_evt(hdev, skb);
                break;
+#endif
 
        case HCI_EV_NUM_COMP_BLOCKS:
                hci_num_comp_blocks_evt(hdev, skb);