Bluetooth: AMP: Process Logical Link complete evt
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>
Thu, 25 Oct 2012 12:20:45 +0000 (15:20 +0300)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Thu, 1 Nov 2012 22:27:02 +0000 (20:27 -0200)
After receiving HCI Logical Link Complete event finish EFS
configuration by sending L2CAP Conf Response with success code.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
include/net/bluetooth/l2cap.h
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c

index 49783e9488565a13886155c291df073cdf541ebe..24c61ef933b589d221b469f7ded48e220c0b518c 100644 (file)
@@ -810,5 +810,7 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
 void l2cap_send_conn_req(struct l2cap_chan *chan);
 void l2cap_move_start(struct l2cap_chan *chan);
+void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+                      u8 status);
 
 #endif /* __L2CAP_H */
index d2c45591f06d01afce9ae4b936938bc579c32a6f..aa79ed278959fbda2ecb70447237d0fdab79e105 100644 (file)
@@ -3695,6 +3695,44 @@ static void hci_phy_link_complete_evt(struct hci_dev *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_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_le_conn_complete *ev = (void *) skb->data;
@@ -4026,6 +4064,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
                hci_phy_link_complete_evt(hdev, skb);
                break;
 
+       case HCI_EV_LOGICAL_LINK_COMPLETE:
+               hci_loglink_complete_evt(hdev, skb);
+               break;
+
        case HCI_EV_NUM_COMP_BLOCKS:
                hci_num_comp_blocks_evt(hdev, skb);
                break;
index 600d8080f2345c13533a52a46402159acb086ad3..d1728af8e84f91de446f33e63784f2abec8538bf 100644 (file)
@@ -4428,8 +4428,8 @@ static void l2cap_logical_finish_move(struct l2cap_chan *chan,
 }
 
 /* Call with chan locked */
-static void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
-                             u8 status)
+void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+                      u8 status)
 {
        BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);