Bluetooth: A2MP: AMP Manager basic functions
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>
Tue, 29 May 2012 10:59:02 +0000 (13:59 +0300)
committerJohan Hedberg <johan.hedberg@intel.com>
Tue, 5 Jun 2012 03:34:11 +0000 (06:34 +0300)
Define AMP Manager and some basic functions.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
include/net/bluetooth/a2mp.h [new file with mode: 0644]
include/net/bluetooth/hci_core.h
net/bluetooth/a2mp.c
net/bluetooth/hci_conn.c

diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
new file mode 100644 (file)
index 0000000..ff47540
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+   Copyright (c) 2010,2011 Code Aurora Forum.  All rights reserved.
+   Copyright (c) 2011,2012 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+#ifndef __A2MP_H
+#define __A2MP_H
+
+struct amp_mgr {
+       struct l2cap_conn       *l2cap_conn;
+       struct l2cap_chan       *a2mp_chan;
+       struct kref             kref;
+       __u8                    ident;
+       __u8                    handle;
+       unsigned long           flags;
+};
+
+void amp_mgr_get(struct amp_mgr *mgr);
+int amp_mgr_put(struct amp_mgr *mgr);
+
+#endif /* __A2MP_H */
index d584a47d1c8679fc0f4ad40d410b6f1f9e118e0a..6e64b76e30aa92dc556376af291073d8b5a0426b 100644 (file)
@@ -332,6 +332,7 @@ struct hci_conn {
        void            *l2cap_data;
        void            *sco_data;
        void            *smp_conn;
+       struct amp_mgr  *amp_mgr;
 
        struct hci_conn *link;
 
index de455a2644511b6634810a9094468d3d03e2b53f..3c241c2b3e1ac175e95f4f2be26f73b1e3bd189d 100644 (file)
@@ -15,6 +15,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/a2mp.h>
 
 static struct l2cap_ops a2mp_chan_ops = {
        .name = "L2CAP A2MP channel",
@@ -67,3 +68,56 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
 
        return chan;
 }
+
+/* AMP Manager functions */
+void amp_mgr_get(struct amp_mgr *mgr)
+{
+       BT_DBG("mgr %p", mgr);
+
+       kref_get(&mgr->kref);
+}
+
+static void amp_mgr_destroy(struct kref *kref)
+{
+       struct amp_mgr *mgr = container_of(kref, struct amp_mgr, kref);
+
+       BT_DBG("mgr %p", mgr);
+
+       kfree(mgr);
+}
+
+int amp_mgr_put(struct amp_mgr *mgr)
+{
+       BT_DBG("mgr %p", mgr);
+
+       return kref_put(&mgr->kref, &amp_mgr_destroy);
+}
+
+static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
+{
+       struct amp_mgr *mgr;
+       struct l2cap_chan *chan;
+
+       mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+       if (!mgr)
+               return NULL;
+
+       BT_DBG("conn %p mgr %p", conn, mgr);
+
+       mgr->l2cap_conn = conn;
+
+       chan = a2mp_chan_open(conn);
+       if (!chan) {
+               kfree(mgr);
+               return NULL;
+       }
+
+       mgr->a2mp_chan = chan;
+       chan->data = mgr;
+
+       conn->hcon->amp_mgr = mgr;
+
+       kref_init(&mgr->kref);
+
+       return mgr;
+}
index 126876d915f566d5095cb6ef3495dc1229ea4484..1458667b284532bf8485c15e73e948f78e3db999 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/a2mp.h>
 
 static void hci_le_connect(struct hci_conn *conn)
 {
@@ -411,6 +412,9 @@ int hci_conn_del(struct hci_conn *conn)
 
        hci_chan_list_flush(conn);
 
+       if (conn->amp_mgr)
+               amp_mgr_put(conn->amp_mgr);
+
        hci_conn_hash_del(hdev, conn);
        if (hdev->notify)
                hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);