]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/bluetooth/hci_event.c
Bluetooth: mgmt: Fix updating EIR when updating the name
[karo-tx-linux.git] / net / bluetooth / hci_event.c
index e69db4a7b3ef6589775d703adaa7dffb14c245ab..e44e3fd68628faa16a8743d35e1d874f1e588fa1 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -45,8 +44,6 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-static bool enable_le;
-
 /* Handle HCI Event packets */
 
 static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
@@ -195,9 +192,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_req_complete(hdev, HCI_OP_RESET, status);
 
-       /* Reset all flags, except persistent ones */
-       hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF) |
-                               BIT(HCI_LINK_KEYS) | BIT(HCI_DEBUG_KEYS);
+       /* Reset all non-persistent flags */
+       hdev->dev_flags &= ~(BIT(HCI_LE_SCAN));
 }
 
 static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -213,12 +209,12 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_dev_lock(hdev);
 
-       if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_set_local_name_complete(hdev, sent, status);
-
        if (status == 0)
                memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
+       if (test_bit(HCI_MGMT, &hdev->dev_flags))
+               mgmt_set_local_name_complete(hdev, sent, status);
+
        hci_dev_unlock(hdev);
 }
 
@@ -424,21 +420,6 @@ static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
        hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
 }
 
-static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
-{
-       struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
-
-       BT_DBG("%s status 0x%x", hdev->name, rp->status);
-
-       if (rp->status)
-               return;
-
-       if (rp->mode)
-               set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
-       else
-               clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
-}
-
 static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -446,21 +427,18 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s status 0x%x", hdev->name, status);
 
-       if (status)
-               goto done;
-
        sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
        if (!sent)
                return;
 
-       if (*((u8 *) sent))
-               set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
-       else
-               clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
-
-done:
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_ssp_enable_complete(hdev, status);
+               mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
+       else if (!status) {
+               if (*((u8 *) sent))
+                       set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
+               else
+                       clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
+       }
 }
 
 static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
@@ -561,7 +539,7 @@ static void hci_set_le_support(struct hci_dev *hdev)
 
        memset(&cp, 0, sizeof(cp));
 
-       if (enable_le) {
+       if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
                cp.le = 1;
                cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
        }
@@ -580,8 +558,18 @@ static void hci_setup(struct hci_dev *hdev)
                hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
 
        if (hdev->features[6] & LMP_SIMPLE_PAIR) {
-               u8 mode = 0x01;
-               hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
+               if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+                       u8 mode = 0x01;
+                       hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
+                                                       sizeof(mode), &mode);
+               } else {
+                       struct hci_cp_write_eir cp;
+
+                       memset(hdev->eir, 0, sizeof(hdev->eir));
+                       memset(&cp, 0, sizeof(cp));
+
+                       hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+               }
        }
 
        if (hdev->features[3] & LMP_RSSI_INQ)
@@ -598,6 +586,12 @@ static void hci_setup(struct hci_dev *hdev)
                                                        sizeof(cp), &cp);
        }
 
+       if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
+               u8 enable = 1;
+               hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
+                                               sizeof(enable), &enable);
+       }
+
        if (hdev->features[4] & LMP_LE)
                hci_set_le_support(hdev);
 }
@@ -1136,10 +1130,15 @@ static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
                                                        struct sk_buff *skb)
 {
        struct hci_cp_read_local_ext_features cp;
+       struct hci_cp_write_le_host_supported *sent;
        __u8 status = *((__u8 *) skb->data);
 
        BT_DBG("%s status 0x%x", hdev->name, status);
 
+       sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
+       if (sent && test_bit(HCI_MGMT, &hdev->dev_flags))
+               mgmt_le_enable_complete(hdev, sent->le, status);
+
        if (status)
                return;
 
@@ -2199,10 +2198,6 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
                hci_cc_host_buffer_size(hdev, skb);
                break;
 
-       case HCI_OP_READ_SSP_MODE:
-               hci_cc_read_ssp_mode(hdev, skb);
-               break;
-
        case HCI_OP_WRITE_SSP_MODE:
                hci_cc_write_ssp_mode(hdev, skb);
                break;
@@ -3546,34 +3541,3 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
        kfree_skb(skb);
        hdev->stat.evt_rx++;
 }
-
-/* Generate internal stack event */
-void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
-{
-       struct hci_event_hdr *hdr;
-       struct hci_ev_stack_internal *ev;
-       struct sk_buff *skb;
-
-       skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
-       if (!skb)
-               return;
-
-       hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
-       hdr->evt  = HCI_EV_STACK_INTERNAL;
-       hdr->plen = sizeof(*ev) + dlen;
-
-       ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
-       ev->type = type;
-       memcpy(ev->data, data, dlen);
-
-       bt_cb(skb)->incoming = 1;
-       __net_timestamp(skb);
-
-       bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
-       skb->dev = (void *) hdev;
-       hci_send_to_sock(hdev, skb);
-       kfree_skb(skb);
-}
-
-module_param(enable_le, bool, 0644);
-MODULE_PARM_DESC(enable_le, "Enable LE support");