summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-05-29 12:59:02 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2012-06-05 05:34:11 +0200
commit9740e49d17e55f3832661fd99a8e0a17e921a82e (patch)
tree865915ab8d3c13d1ff74429c84b95a0acab37ee9
parentBluetooth: A2MP: Create A2MP channel (diff)
downloadlinux-9740e49d17e55f3832661fd99a8e0a17e921a82e.tar.xz
linux-9740e49d17e55f3832661fd99a8e0a17e921a82e.zip
Bluetooth: A2MP: AMP Manager basic functions
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>
-rw-r--r--include/net/bluetooth/a2mp.h30
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--net/bluetooth/a2mp.c54
-rw-r--r--net/bluetooth/hci_conn.c4
4 files changed, 89 insertions, 0 deletions
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
new file mode 100644
index 000000000000..ff4754000cf8
--- /dev/null
+++ b/include/net/bluetooth/a2mp.h
@@ -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 */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d584a47d1c86..6e64b76e30aa 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -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;
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index de455a264451..3c241c2b3e1a 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -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;
+}
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 126876d915f5..1458667b2845 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -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);