Bluetooth: Move double negation to macros
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / hci_event.c
index 2022b43c7353ee98d7546d6c9e0ef67c43811d3f..705078a0cc393c023054ad1d55aea1a548e3da1d 100644 (file)
 
 /* Bluetooth HCI event handling. */
 
-#include <linux/export.h>
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/mgmt.h>
+#include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/amp.h>
 
 /* Handle HCI Event packets */
 
@@ -201,6 +202,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
                             BIT(HCI_PERIODIC_INQ));
 
        hdev->discovery.state = DISCOVERY_STOPPED;
+       hdev->inq_tx_power = HCI_TX_POWER_INVALID;
+       hdev->adv_tx_power = HCI_TX_POWER_INVALID;
+
+       memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
+       hdev->adv_data_len = 0;
 }
 
 static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -223,6 +229,9 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_dev_unlock(hdev);
 
+       if (!status && !test_bit(HCI_INIT, &hdev->flags))
+               hci_update_ad(hdev);
+
        hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status);
 }
 
@@ -438,7 +447,7 @@ static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
 static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
-       void *sent;
+       struct hci_cp_write_ssp_mode *sent;
 
        BT_DBG("%s status 0x%2.2x", hdev->name, status);
 
@@ -446,10 +455,17 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
        if (!sent)
                return;
 
+       if (!status) {
+               if (sent->mode)
+                       hdev->host_features[0] |= LMP_HOST_SSP;
+               else
+                       hdev->host_features[0] &= ~LMP_HOST_SSP;
+       }
+
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
+               mgmt_ssp_enable_complete(hdev, sent->mode, status);
        else if (!status) {
-               if (*((u8 *) sent))
+               if (sent->mode)
                        set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
                else
                        clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
@@ -458,10 +474,10 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
 static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
 {
-       if (hdev->features[6] & LMP_EXT_INQ)
+       if (lmp_ext_inq_capable(hdev))
                return 2;
 
-       if (hdev->features[3] & LMP_RSSI_INQ)
+       if (lmp_inq_rssi_capable(hdev))
                return 1;
 
        if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 &&
@@ -505,28 +521,30 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
        if (hdev->hci_ver < BLUETOOTH_VER_1_2)
                return;
 
-       events[4] |= 0x01; /* Flow Specification Complete */
-       events[4] |= 0x02; /* Inquiry Result with RSSI */
-       events[4] |= 0x04; /* Read Remote Extended Features Complete */
-       events[5] |= 0x08; /* Synchronous Connection Complete */
-       events[5] |= 0x10; /* Synchronous Connection Changed */
+       if (lmp_bredr_capable(hdev)) {
+               events[4] |= 0x01; /* Flow Specification Complete */
+               events[4] |= 0x02; /* Inquiry Result with RSSI */
+               events[4] |= 0x04; /* Read Remote Extended Features Complete */
+               events[5] |= 0x08; /* Synchronous Connection Complete */
+               events[5] |= 0x10; /* Synchronous Connection Changed */
+       }
 
-       if (hdev->features[3] & LMP_RSSI_INQ)
+       if (lmp_inq_rssi_capable(hdev))
                events[4] |= 0x02; /* Inquiry Result with RSSI */
 
        if (lmp_sniffsubr_capable(hdev))
                events[5] |= 0x20; /* Sniff Subrating */
 
-       if (hdev->features[5] & LMP_PAUSE_ENC)
+       if (lmp_pause_enc_capable(hdev))
                events[5] |= 0x80; /* Encryption Key Refresh Complete */
 
-       if (hdev->features[6] & LMP_EXT_INQ)
+       if (lmp_ext_inq_capable(hdev))
                events[5] |= 0x40; /* Extended Inquiry Result */
 
        if (lmp_no_flush_capable(hdev))
                events[7] |= 0x01; /* Enhanced Flush Complete */
 
-       if (hdev->features[7] & LMP_LSTO)
+       if (lmp_lsto_capable(hdev))
                events[6] |= 0x80; /* Link Supervision Timeout Changed */
 
        if (lmp_ssp_capable(hdev)) {
@@ -546,6 +564,53 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
                events[7] |= 0x20;      /* LE Meta-Event */
 
        hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
+
+       if (lmp_le_capable(hdev)) {
+               memset(events, 0, sizeof(events));
+               events[0] = 0x1f;
+               hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK,
+                            sizeof(events), events);
+       }
+}
+
+static void bredr_setup(struct hci_dev *hdev)
+{
+       struct hci_cp_delete_stored_link_key cp;
+       __le16 param;
+       __u8 flt_type;
+
+       /* Read Buffer Size (ACL mtu, max pkt, etc.) */
+       hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
+
+       /* Read Class of Device */
+       hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+       /* Read Local Name */
+       hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
+
+       /* Read Voice Setting */
+       hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
+
+       /* Clear Event Filters */
+       flt_type = HCI_FLT_CLEAR_ALL;
+       hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
+
+       /* Connection accept timeout ~20 secs */
+       param = __constant_cpu_to_le16(0x7d00);
+       hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
+
+       bacpy(&cp.bdaddr, BDADDR_ANY);
+       cp.delete_all = 1;
+       hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+}
+
+static void le_setup(struct hci_dev *hdev)
+{
+       /* Read LE Buffer Size */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+
+       /* Read LE Advertising Channel TX Power */
+       hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
 }
 
 static void hci_setup(struct hci_dev *hdev)
@@ -553,6 +618,15 @@ static void hci_setup(struct hci_dev *hdev)
        if (hdev->dev_type != HCI_BREDR)
                return;
 
+       /* Read BD Address */
+       hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
+
+       if (lmp_bredr_capable(hdev))
+               bredr_setup(hdev);
+
+       if (lmp_le_capable(hdev))
+               le_setup(hdev);
+
        hci_setup_event_mask(hdev);
 
        if (hdev->hci_ver > BLUETOOTH_VER_1_1)
@@ -573,13 +647,13 @@ static void hci_setup(struct hci_dev *hdev)
                }
        }
 
-       if (hdev->features[3] & LMP_RSSI_INQ)
+       if (lmp_inq_rssi_capable(hdev))
                hci_setup_inquiry_mode(hdev);
 
-       if (hdev->features[7] & LMP_INQ_TX_PWR)
+       if (lmp_inq_tx_pwr_capable(hdev))
                hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
 
-       if (hdev->features[7] & LMP_EXTFEATURES) {
+       if (lmp_ext_feat_capable(hdev)) {
                struct hci_cp_read_local_ext_features cp;
 
                cp.page = 0x01;
@@ -626,11 +700,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
 
        if (lmp_rswitch_capable(hdev))
                link_policy |= HCI_LP_RSWITCH;
-       if (hdev->features[0] & LMP_HOLD)
+       if (lmp_hold_capable(hdev))
                link_policy |= HCI_LP_HOLD;
        if (lmp_sniff_capable(hdev))
                link_policy |= HCI_LP_SNIFF;
-       if (hdev->features[1] & LMP_PARK)
+       if (lmp_park_capable(hdev))
                link_policy |= HCI_LP_PARK;
 
        cp.policy = cpu_to_le16(link_policy);
@@ -720,10 +794,10 @@ static void hci_set_le_support(struct hci_dev *hdev)
 
        if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
                cp.le = 1;
-               cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+               cp.simul = lmp_le_br_capable(hdev);
        }
 
-       if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE))
+       if (cp.le != lmp_host_le_capable(hdev))
                hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp),
                             &cp);
 }
@@ -846,7 +920,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)
-               return;
+               goto a2mp_rsp;
 
        hdev->amp_status = rp->amp_status;
        hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
@@ -860,6 +934,46 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev,
        hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
 
        hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status);
+
+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_delete_stored_link_key(struct hci_dev *hdev,
@@ -976,6 +1090,31 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
        hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
 }
 
+static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev,
+                                       struct sk_buff *skb)
+{
+       struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+       if (!rp->status) {
+               hdev->adv_tx_power = rp->tx_power;
+               if (!test_bit(HCI_INIT, &hdev->flags))
+                       hci_update_ad(hdev);
+       }
+
+       hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status);
+}
+
+static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       __u8 status = *((__u8 *) skb->data);
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status);
+}
+
 static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
@@ -1051,6 +1190,33 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
        hci_dev_unlock(hdev);
 }
 
+static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       __u8 *sent, status = *((__u8 *) skb->data);
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
+       if (!sent)
+               return;
+
+       hci_dev_lock(hdev);
+
+       if (!status) {
+               if (*sent)
+                       set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+               else
+                       clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+       }
+
+       hci_dev_unlock(hdev);
+
+       if (!test_bit(HCI_INIT, &hdev->flags))
+               hci_update_ad(hdev);
+
+       hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status);
+}
+
 static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -1165,6 +1331,11 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
                        hdev->host_features[0] |= LMP_HOST_LE;
                else
                        hdev->host_features[0] &= ~LMP_HOST_LE;
+
+               if (sent->simul)
+                       hdev->host_features[0] |= LMP_HOST_LE_BREDR;
+               else
+                       hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
        }
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
@@ -1174,6 +1345,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
        hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status);
 }
 
+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_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
        BT_DBG("%s status 0x%2.2x", hdev->name, status);
@@ -1210,7 +1395,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
 
-       BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn);
+       BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn);
 
        if (status) {
                if (conn && conn->state == BT_CONNECT) {
@@ -1639,8 +1824,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
                        return;
                }
 
-               BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
-                      conn);
+               BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn);
 
                conn->state = BT_CLOSED;
                mgmt_connect_failed(hdev, &conn->dst, conn->type,
@@ -1657,6 +1841,52 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
        BT_DBG("%s status 0x%2.2x", hdev->name, status);
 }
 
+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_create_logical_link(struct hci_dev *hdev, u8 status)
+{
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+}
+
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -1817,15 +2047,53 @@ unlock:
        hci_conn_check_pending(hdev);
 }
 
+void hci_conn_accept(struct hci_conn *conn, int mask)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       BT_DBG("conn %p", conn);
+
+       conn->state = BT_CONFIG;
+
+       if (!lmp_esco_capable(hdev)) {
+               struct hci_cp_accept_conn_req cp;
+
+               bacpy(&cp.bdaddr, &conn->dst);
+
+               if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+                       cp.role = 0x00; /* Become master */
+               else
+                       cp.role = 0x01; /* Remain slave */
+
+               hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+       } else /* lmp_esco_capable(hdev)) */ {
+               struct hci_cp_accept_sync_conn_req cp;
+
+               bacpy(&cp.bdaddr, &conn->dst);
+               cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+               cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
+               cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
+               cp.max_latency    = __constant_cpu_to_le16(0xffff);
+               cp.content_format = cpu_to_le16(hdev->voice_setting);
+               cp.retrans_effort = 0xff;
+
+               hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+                            sizeof(cp), &cp);
+       }
+}
+
 static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_conn_request *ev = (void *) skb->data;
        int mask = hdev->link_mode;
+       __u8 flags = 0;
 
-       BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr),
+       BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
               ev->link_type);
 
-       mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
+       mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
+                                     &flags);
 
        if ((mask & HCI_LM_ACCEPT) &&
            !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
@@ -1851,12 +2119,13 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
                }
 
                memcpy(conn->dev_class, ev->dev_class, 3);
-               conn->state = BT_CONNECT;
 
                hci_dev_unlock(hdev);
 
-               if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) {
+               if (ev->link_type == ACL_LINK ||
+                   (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
                        struct hci_cp_accept_conn_req cp;
+                       conn->state = BT_CONNECT;
 
                        bacpy(&cp.bdaddr, &ev->bdaddr);
 
@@ -1867,8 +2136,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
                        hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp),
                                     &cp);
-               } else {
+               } else if (!(flags & HCI_PROTO_DEFER)) {
                        struct hci_cp_accept_sync_conn_req cp;
+                       conn->state = BT_CONNECT;
 
                        bacpy(&cp.bdaddr, &ev->bdaddr);
                        cp.pkt_type = cpu_to_le16(conn->pkt_type);
@@ -1881,6 +2151,10 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
                        hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
                                     sizeof(cp), &cp);
+               } else {
+                       conn->state = BT_CONNECT2;
+                       hci_proto_connect_cfm(conn, 0);
+                       hci_conn_put(conn);
                }
        } else {
                /* Connection rejected */
@@ -2314,6 +2588,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_read_local_amp_info(hdev, skb);
                break;
 
+       case HCI_OP_READ_LOCAL_AMP_ASSOC:
+               hci_cc_read_local_amp_assoc(hdev, skb);
+               break;
+
        case HCI_OP_DELETE_STORED_LINK_KEY:
                hci_cc_delete_stored_link_key(hdev, skb);
                break;
@@ -2350,6 +2628,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_le_read_buffer_size(hdev, skb);
                break;
 
+       case HCI_OP_LE_READ_ADV_TX_POWER:
+               hci_cc_le_read_adv_tx_power(hdev, skb);
+               break;
+
+       case HCI_OP_LE_SET_EVENT_MASK:
+               hci_cc_le_set_event_mask(hdev, skb);
+               break;
+
        case HCI_OP_USER_CONFIRM_REPLY:
                hci_cc_user_confirm_reply(hdev, skb);
                break;
@@ -2370,6 +2656,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_le_set_scan_param(hdev, skb);
                break;
 
+       case HCI_OP_LE_SET_ADV_ENABLE:
+               hci_cc_le_set_adv_enable(hdev, skb);
+               break;
+
        case HCI_OP_LE_SET_SCAN_ENABLE:
                hci_cc_le_set_scan_enable(hdev, skb);
                break;
@@ -2386,6 +2676,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cc_write_le_host_supported(hdev, skb);
                break;
 
+       case HCI_OP_WRITE_REMOTE_AMP_ASSOC:
+               hci_cc_write_remote_amp_assoc(hdev, skb);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
                break;
@@ -2467,6 +2761,18 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cs_le_start_enc(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_CREATE_LOGICAL_LINK:
+               hci_cs_create_logical_link(hdev, ev->status);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
                break;
@@ -2574,6 +2880,27 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
        queue_work(hdev->workqueue, &hdev->tx_work);
 }
 
+static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
+                                                __u16 handle)
+{
+       struct hci_chan *chan;
+
+       switch (hdev->dev_type) {
+       case HCI_BREDR:
+               return hci_conn_hash_lookup_handle(hdev, handle);
+       case HCI_AMP:
+               chan = hci_chan_lookup_handle(hdev, handle);
+               if (chan)
+                       return chan->conn;
+               break;
+       default:
+               BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type);
+               break;
+       }
+
+       return NULL;
+}
+
 static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
@@ -2595,13 +2922,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
        for (i = 0; i < ev->num_hndl; i++) {
                struct hci_comp_blocks_info *info = &ev->handles[i];
-               struct hci_conn *conn;
+               struct hci_conn *conn = NULL;
                __u16  handle, block_count;
 
                handle = __le16_to_cpu(info->handle);
                block_count = __le16_to_cpu(info->blocks);
 
-               conn = hci_conn_hash_lookup_handle(hdev, handle);
+               conn = __hci_conn_lookup_handle(hdev, handle);
                if (!conn)
                        continue;
 
@@ -2609,6 +2936,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
                switch (conn->type) {
                case ACL_LINK:
+               case AMP_LINK:
                        hdev->block_cnt += block_count;
                        if (hdev->block_cnt > hdev->num_blocks)
                                hdev->block_cnt = hdev->num_blocks;
@@ -2705,13 +3033,13 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
        key = hci_find_link_key(hdev, &ev->bdaddr);
        if (!key) {
-               BT_DBG("%s link key not found for %s", hdev->name,
-                      batostr(&ev->bdaddr));
+               BT_DBG("%s link key not found for %pMR", hdev->name,
+                      &ev->bdaddr);
                goto not_found;
        }
 
-       BT_DBG("%s found key type %u for %s", hdev->name, key->type,
-              batostr(&ev->bdaddr));
+       BT_DBG("%s found key type %u for %pMR", hdev->name, key->type,
+              &ev->bdaddr);
 
        if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) &&
            key->type == HCI_LK_DEBUG_COMBINATION) {
@@ -3419,6 +3747,130 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+static void hci_phy_link_complete_evt(struct hci_dev *hdev,
+                                     struct sk_buff *skb)
+{
+       struct hci_ev_phy_link_complete *ev = (void *) skb->data;
+       struct hci_conn *hcon, *bredr_hcon;
+
+       BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
+              ev->status);
+
+       hci_dev_lock(hdev);
+
+       hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+       if (!hcon) {
+               hci_dev_unlock(hdev);
+               return;
+       }
+
+       if (ev->status) {
+               hci_conn_del(hcon);
+               hci_dev_unlock(hdev);
+               return;
+       }
+
+       bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
+
+       hcon->state = BT_CONNECTED;
+       bacpy(&hcon->dst, &bredr_hcon->dst);
+
+       hci_conn_hold(hcon);
+       hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
+       hci_conn_put(hcon);
+
+       hci_conn_hold_device(hcon);
+       hci_conn_add_sysfs(hcon);
+
+       amp_physical_cfm(bredr_hcon, hcon);
+
+       hci_dev_unlock(hdev);
+}
+
+static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_ev_logical_link_complete *ev = (void *) skb->data;
+       struct hci_conn *hcon;
+       struct hci_chan *hchan;
+       struct amp_mgr *mgr;
+
+       BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
+              hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
+              ev->status);
+
+       hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+       if (!hcon)
+               return;
+
+       /* Create AMP hchan */
+       hchan = hci_chan_create(hcon);
+       if (!hchan)
+               return;
+
+       hchan->handle = le16_to_cpu(ev->handle);
+
+       BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
+
+       mgr = hcon->amp_mgr;
+       if (mgr && mgr->bredr_chan) {
+               struct l2cap_chan *bredr_chan = mgr->bredr_chan;
+
+               l2cap_chan_lock(bredr_chan);
+
+               bredr_chan->conn->mtu = hdev->block_mtu;
+               l2cap_logical_cfm(bredr_chan, hchan, 0);
+               hci_conn_hold(hcon);
+
+               l2cap_chan_unlock(bredr_chan);
+       }
+}
+
+static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
+                                            struct sk_buff *skb)
+{
+       struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
+       struct hci_chan *hchan;
+
+       BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
+              le16_to_cpu(ev->handle), ev->status);
+
+       if (ev->status)
+               return;
+
+       hci_dev_lock(hdev);
+
+       hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
+       if (!hchan)
+               goto unlock;
+
+       amp_destroy_logical_link(hchan, ev->reason);
+
+unlock:
+       hci_dev_unlock(hdev);
+}
+
+static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
+                                            struct sk_buff *skb)
+{
+       struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
+       struct hci_conn *hcon;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+
+       if (ev->status)
+               return;
+
+       hci_dev_lock(hdev);
+
+       hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+       if (hcon) {
+               hcon->state = BT_CLOSED;
+               hci_conn_del(hcon);
+       }
+
+       hci_dev_unlock(hdev);
+}
+
 static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_le_conn_complete *ev = (void *) skb->data;
@@ -3558,6 +4010,22 @@ 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);
+}
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_event_hdr *hdr = (void *) skb->data;
@@ -3722,10 +4190,30 @@ 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;
 
+       case HCI_EV_PHY_LINK_COMPLETE:
+               hci_phy_link_complete_evt(hdev, skb);
+               break;
+
+       case HCI_EV_LOGICAL_LINK_COMPLETE:
+               hci_loglink_complete_evt(hdev, skb);
+               break;
+
+       case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE:
+               hci_disconn_loglink_complete_evt(hdev, skb);
+               break;
+
+       case HCI_EV_DISCONN_PHY_LINK_COMPLETE:
+               hci_disconn_phylink_complete_evt(hdev, skb);
+               break;
+
        case HCI_EV_NUM_COMP_BLOCKS:
                hci_num_comp_blocks_evt(hdev, skb);
                break;