summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c')
-rw-r--r--sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c124
1 files changed, 119 insertions, 5 deletions
diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c
index 9fcbc6e..43a6d13 100644
--- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c
+++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_l2cap_misc.c,v 1.16 2002/09/04 21:38:38 max Exp $
+ * $Id: ng_l2cap_misc.c,v 1.4 2003/04/28 21:44:59 max Exp $
* $FreeBSD$
*/
@@ -48,6 +48,7 @@
#include "ng_l2cap_misc.h"
static u_int16_t ng_l2cap_get_cid (ng_l2cap_p);
+static void ng_l2cap_queue_discon_timeout (void *);
static void ng_l2cap_queue_lp_timeout (void *);
static void ng_l2cap_queue_command_timeout (void *);
@@ -93,9 +94,8 @@ ng_l2cap_send_hook_info(node_p node, hook_p hook, void *arg1, int arg2)
} /* ng_l2cap_send_hook_info */
/*
- * Create new connection descriptor for the "remote" unit. Will create new
- * connection descriptor and signal channel. Will link both connection and
- * channel to the l2cap node.
+ * Create new connection descriptor for the "remote" unit.
+ * Will link connection descriptor to the l2cap node.
*/
ng_l2cap_con_p
@@ -125,6 +125,104 @@ ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr)
} /* ng_l2cap_new_con */
/*
+ * Add reference to the connection descriptor
+ */
+
+void
+ng_l2cap_con_ref(ng_l2cap_con_p con)
+{
+ con->refcnt ++;
+
+ if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) {
+ if ((con->state != NG_L2CAP_CON_OPEN) ||
+ (con->flags & NG_L2CAP_CON_OUTGOING) == 0)
+ panic("%s: %s - bad auto disconnect timeout\n",
+ __func__, NG_NODE_NAME(con->l2cap->node));
+
+ ng_l2cap_discon_untimeout(con);
+ }
+} /* ng_l2cap_con_ref */
+
+/*
+ * Remove reference from the connection descriptor
+ */
+
+void
+ng_l2cap_con_unref(ng_l2cap_con_p con)
+{
+ con->refcnt --;
+
+ if (con->refcnt < 0)
+ panic("%s: %s - con->refcnt < 0\n",
+ __func__, NG_NODE_NAME(con->l2cap->node));
+
+ /*
+ * Set auto disconnect timer only if the following conditions are met:
+ * 1) we have no reference on the connection
+ * 2) connection is in OPEN state
+ * 3) it is an outgoing connection
+ * 4) disconnect timeout > 0
+ */
+
+ if ((con->refcnt == 0) &&
+ (con->state == NG_L2CAP_CON_OPEN) &&
+ (con->flags & NG_L2CAP_CON_OUTGOING) &&
+ (con->l2cap->discon_timo > 0)) {
+ if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
+ panic("%s: %s - duplicated auto disconnect timeout\n",
+ __func__, NG_NODE_NAME(con->l2cap->node));
+
+ ng_l2cap_discon_timeout(con);
+ }
+} /* ng_l2cap_con_unref */
+
+/*
+ * Set auto disconnect timeout
+ */
+
+void
+ng_l2cap_discon_timeout(ng_l2cap_con_p con)
+{
+ if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
+ panic("%s: %s - invalid timeout, state=%d, flags=%#x\n",
+ __func__, NG_NODE_NAME(con->l2cap->node),
+ con->state, con->flags);
+
+ NG_NODE_REF(con->l2cap->node);
+ con->flags |= NG_L2CAP_CON_AUTO_DISCON_TIMO;
+ con->con_timo = timeout(ng_l2cap_queue_discon_timeout, con,
+ con->l2cap->discon_timo * hz);
+} /* ng_l2cap_discon_timeout */
+
+/*
+ * Unset auto disconnect timeout
+ */
+
+void
+ng_l2cap_discon_untimeout(ng_l2cap_con_p con)
+{
+ untimeout(ng_l2cap_queue_discon_timeout, con, con->con_timo);
+ con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
+ NG_NODE_UNREF(con->l2cap->node);
+} /* ng_l2cap_discon_untimeout */
+
+/*
+ * Queue auto disconnect timeout
+ */
+
+static void
+ng_l2cap_queue_discon_timeout(void *context)
+{
+ ng_l2cap_con_p con = (ng_l2cap_con_p) context;
+ node_p node = con->l2cap->node;
+
+ if (NG_NODE_IS_VALID(node))
+ ng_send_fn(node,NULL,&ng_l2cap_process_discon_timeout,con,0);
+
+ NG_NODE_UNREF(node);
+} /* ng_l2cap_queue_discon_timeout */
+
+/*
* Free connection descriptor. Will unlink connection and free everything.
*/
@@ -133,8 +231,12 @@ ng_l2cap_free_con(ng_l2cap_con_p con)
{
ng_l2cap_chan_p f = NULL, n = NULL;
- if (con->state == NG_L2CAP_W4_LP_CON_CFM)
+ if (con->flags & NG_L2CAP_CON_LP_TIMO)
ng_l2cap_lp_untimeout(con);
+ else if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
+ ng_l2cap_discon_untimeout(con);
+
+ con->state = NG_L2CAP_CON_CLOSED;
if (con->tx_pkt != NULL) {
while (con->tx_pkt != NULL) {
@@ -234,6 +336,8 @@ ng_l2cap_new_chan(ng_l2cap_p l2cap, ng_l2cap_con_p con, u_int16_t psm)
ch->link_timo = NG_L2CAP_LINK_TIMO_DEFAULT;
LIST_INSERT_HEAD(&l2cap->chan_list, ch, next);
+
+ ng_l2cap_con_ref(con);
} else {
bzero(ch, sizeof(*ch));
FREE(ch, M_NETGRAPH_L2CAP);
@@ -281,6 +385,9 @@ ng_l2cap_free_chan(ng_l2cap_chan_p ch)
}
LIST_REMOVE(ch, next);
+
+ ng_l2cap_con_unref(ch->con);
+
bzero(ch, sizeof(*ch));
FREE(ch, M_NETGRAPH_L2CAP);
} /* ng_l2cap_free_chan */
@@ -337,7 +444,13 @@ ng_l2cap_cmd_by_ident(ng_l2cap_con_p con, u_int8_t ident)
void
ng_l2cap_lp_timeout(ng_l2cap_con_p con)
{
+ if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
+ panic("%s: %s - invalid timeout, state=%d, flags=%#x\n",
+ __func__, NG_NODE_NAME(con->l2cap->node),
+ con->state, con->flags);
+
NG_NODE_REF(con->l2cap->node);
+ con->flags |= NG_L2CAP_CON_LP_TIMO;
con->con_timo = timeout(ng_l2cap_queue_lp_timeout, con,
bluetooth_hci_connect_timeout());
} /* ng_l2cap_lp_timeout */
@@ -350,6 +463,7 @@ void
ng_l2cap_lp_untimeout(ng_l2cap_con_p con)
{
untimeout(ng_l2cap_queue_lp_timeout, con, con->con_timo);
+ con->flags &= ~NG_L2CAP_CON_LP_TIMO;
NG_NODE_UNREF(con->l2cap->node);
} /* ng_l2cap_lp_untimeout */
OpenPOWER on IntegriCloud