]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/bluetooth/hci_event.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
[karo-tx-linux.git] / net / bluetooth / hci_event.c
index 1266f78fa8e3283a6d854d1b808312b8916c981f..4edbfd929f6e2fee49ac6a6b1d84e62f7f6c0dcd 100644 (file)
@@ -69,6 +69,18 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
        hci_conn_check_pending(hdev);
 }
 
+static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       __u8 status = *((__u8 *) skb->data);
+
+       BT_DBG("%s status 0x%x", hdev->name, status);
+
+       if (status)
+               return;
+
+       set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
+}
+
 static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -78,6 +90,8 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
        if (status)
                return;
 
+       clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags);
+
        hci_conn_check_pending(hdev);
 }
 
@@ -192,7 +206,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
        hci_req_complete(hdev, HCI_OP_RESET, status);
 
        /* Reset all non-persistent flags */
-       hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS));
+       hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) |
+                            BIT(HCI_PERIODIC_INQ));
 
        hdev->discovery.state = DISCOVERY_STOPPED;
 }
@@ -615,6 +630,7 @@ done:
 
 static void hci_setup_link_policy(struct hci_dev *hdev)
 {
+       struct hci_cp_write_def_link_policy cp;
        u16 link_policy = 0;
 
        if (hdev->features[0] & LMP_RSWITCH)
@@ -626,9 +642,8 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
        if (hdev->features[1] & LMP_PARK)
                link_policy |= HCI_LP_PARK;
 
-       link_policy = cpu_to_le16(link_policy);
-       hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(link_policy),
-                    &link_policy);
+       cp.policy = cpu_to_le16(link_policy);
+       hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp);
 }
 
 static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
@@ -710,7 +725,7 @@ static void hci_set_le_support(struct hci_dev *hdev)
 
        memset(&cp, 0, sizeof(cp));
 
-       if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+       if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
                cp.le = 1;
                cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
        }
@@ -887,11 +902,14 @@ static void hci_cc_write_inquiry_mode(struct hci_dev *hdev,
 static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev,
                                                        struct sk_buff *skb)
 {
-       __u8 status = *((__u8 *) skb->data);
+       struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data;
 
-       BT_DBG("%s status 0x%x", hdev->name, status);
+       BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+       if (!rp->status)
+               hdev->inq_tx_power = rp->tx_power;
 
-       hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status);
+       hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status);
 }
 
 static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1082,23 +1100,23 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 
                set_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
-               cancel_delayed_work_sync(&hdev->adv_work);
-
                hci_dev_lock(hdev);
-               hci_adv_entries_clear(hdev);
                hci_discovery_set_state(hdev, DISCOVERY_FINDING);
                hci_dev_unlock(hdev);
                break;
 
        case LE_SCANNING_DISABLED:
-               if (status)
+               if (status) {
+                       hci_dev_lock(hdev);
+                       mgmt_stop_discovery_failed(hdev, status);
+                       hci_dev_unlock(hdev);
                        return;
+               }
 
                clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
-               schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
-
-               if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
+               if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
+                   hdev->discovery.state == DISCOVERY_FINDING) {
                        mgmt_interleaved_discovery(hdev);
                } else {
                        hci_dev_lock(hdev);
@@ -1625,6 +1643,8 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
        if (status) {
                if (conn && conn->state == BT_CONNECT) {
                        conn->state = BT_CLOSED;
+                       mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
+                                           conn->dst_type, status);
                        hci_proto_connect_cfm(conn, status);
                        hci_conn_del(conn);
                }
@@ -1699,6 +1719,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
        if (!num_rsp)
                return;
 
+       if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
+               return;
+
        hci_dev_lock(hdev);
 
        for (; num_rsp; num_rsp--, info++) {
@@ -2154,6 +2177,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
                hci_cc_inquiry_cancel(hdev, skb);
                break;
 
+       case HCI_OP_PERIODIC_INQ:
+               hci_cc_periodic_inq(hdev, skb);
+               break;
+
        case HCI_OP_EXIT_PERIODIC_INQ:
                hci_cc_exit_periodic_inq(hdev, skb);
                break;
@@ -2806,6 +2833,9 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
        if (!num_rsp)
                return;
 
+       if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
+               return;
+
        hci_dev_lock(hdev);
 
        if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
@@ -2977,6 +3007,9 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
        if (!num_rsp)
                return;
 
+       if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags))
+               return;
+
        hci_dev_lock(hdev);
 
        for (; num_rsp; num_rsp--, info++) {
@@ -3322,8 +3355,6 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
        while (num_reports--) {
                struct hci_ev_le_advertising_info *ev = ptr;
 
-               hci_add_adv_entry(hdev, ev);
-
                rssi = ev->data[ev->length];
                mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type,
                                  NULL, rssi, 0, 1, ev->data, ev->length);
@@ -3343,7 +3374,7 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
        struct hci_conn *conn;
        struct smp_ltk *ltk;
 
-       BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+       BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle));
 
        hci_dev_lock(hdev);