summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/bluetooth/hci
diff options
context:
space:
mode:
authoremax <emax@FreeBSD.org>2003-10-12 22:04:24 +0000
committeremax <emax@FreeBSD.org>2003-10-12 22:04:24 +0000
commit41bb0e8fd2568243020852e22a6d176bccfa60cd (patch)
tree0ae0c2be63f9f9161693789721b96beb9cabcc77 /sys/netgraph/bluetooth/hci
parent66feac7937e372f502539e7d443aee80a25abe16 (diff)
downloadFreeBSD-src-41bb0e8fd2568243020852e22a6d176bccfa60cd.zip
FreeBSD-src-41bb0e8fd2568243020852e22a6d176bccfa60cd.tar.gz
Update Bluetooth code.
Reviewed by: M. Warner Losh <imp@bsdimp.com>; John Hay <jhay@freebsd.org> Approved by: M. Warner Losh <imp@bsdimp.com> (mentor)
Diffstat (limited to 'sys/netgraph/bluetooth/hci')
-rw-r--r--sys/netgraph/bluetooth/hci/ng_hci_cmds.c47
-rw-r--r--sys/netgraph/bluetooth/hci/ng_hci_evnt.c22
-rw-r--r--sys/netgraph/bluetooth/hci/ng_hci_misc.c140
-rw-r--r--sys/netgraph/bluetooth/hci/ng_hci_misc.h10
-rw-r--r--sys/netgraph/bluetooth/hci/ng_hci_ulpi.c68
5 files changed, 162 insertions, 125 deletions
diff --git a/sys/netgraph/bluetooth/hci/ng_hci_cmds.c b/sys/netgraph/bluetooth/hci/ng_hci_cmds.c
index 83b640b..57a9c9d 100644
--- a/sys/netgraph/bluetooth/hci/ng_hci_cmds.c
+++ b/sys/netgraph/bluetooth/hci/ng_hci_cmds.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_hci_cmds.c,v 1.3 2003/04/01 18:15:25 max Exp $
+ * $Id: ng_hci_cmds.c,v 1.4 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@@ -355,11 +355,17 @@ complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
/*
* Now we can remove command timeout, dequeue completed command
- * and return command parameters. Note: ng_hci_command_untimeout()
- * will drop NG_HCI_UNIT_COMMAND_PENDING flag.
+ * and return command parameters. ng_hci_command_untimeout will
+ * drop NG_HCI_UNIT_COMMAND_PENDING flag.
+ * Note: if ng_hci_command_untimeout() fails (returns non-zero)
+ * then timeout aready happened and timeout message went info node
+ * queue. In this case we ignore command completion and pretend
+ * there is a timeout.
*/
- ng_hci_command_untimeout(unit);
+ if (ng_hci_command_untimeout(unit) != 0)
+ return (ETIMEDOUT);
+
NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp);
m_adj(*cp, sizeof(ng_hci_cmd_pkt_t));
@@ -373,17 +379,24 @@ complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
void
ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
{
- ng_hci_unit_p unit = (ng_hci_unit_p) arg1;
+ ng_hci_unit_p unit = NULL;
struct mbuf *m = NULL;
u_int16_t opcode;
+ if (NG_NODE_NOT_VALID(node)) {
+ printf("%s: Netgraph node is not valid\n", __func__);
+ return;
+ }
+
+ unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
+
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
- NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
+ unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
+ NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
if (m == NULL) {
- KASSERT(0,
-("%s: %s - command queue is out of sync!\n",
- __func__, NG_NODE_NAME(unit->node)));
+ NG_HCI_ALERT(
+"%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node));
return;
}
@@ -396,18 +409,12 @@ ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
__func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode),
NG_HCI_OCF(opcode));
- /*
- * Try to send more commands
- */
-
+ /* Try to send more commands */
NG_HCI_BUFF_CMD_SET(unit->buffer, 1);
-
- unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
ng_hci_send_command(unit);
} else
- KASSERT(0,
-("%s: %s - no pending command, state=%#x\n",
- __func__, NG_NODE_NAME(unit->node), unit->state));
+ NG_HCI_ALERT(
+"%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node));
} /* ng_hci_process_command_timeout */
/*
@@ -616,6 +623,10 @@ process_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf,
while (!LIST_EMPTY(&unit->con_list)) {
con = LIST_FIRST(&unit->con_list);
+ /* Remove all timeouts (if any) */
+ if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
+ ng_hci_con_untimeout(con);
+
/* Connection terminated by local host */
ng_hci_lp_discon_ind(con, 0x16);
ng_hci_free_con(con);
diff --git a/sys/netgraph/bluetooth/hci/ng_hci_evnt.c b/sys/netgraph/bluetooth/hci/ng_hci_evnt.c
index 1f1c74a..fcc00fb 100644
--- a/sys/netgraph/bluetooth/hci/ng_hci_evnt.c
+++ b/sys/netgraph/bluetooth/hci/ng_hci_evnt.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_hci_evnt.c,v 1.5 2003/04/01 18:15:25 max Exp $
+ * $Id: ng_hci_evnt.c,v 1.6 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@@ -454,7 +454,10 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event)
* Two possible cases:
*
* 1) We have found connection descriptor. That means upper layer has
- * requested this connection via LP_CON_REQ message
+ * requested this connection via LP_CON_REQ message. In this case
+ * connection must have timeout set. If ng_hci_con_untimeout() fails
+ * then timeout message already went into node's queue. In this case
+ * ignore Connection_Complete event and let timeout deal with it.
*
* 2) We do not have connection descriptor. That means upper layer
* nas not requested this connection or (less likely) we gave up
@@ -474,8 +477,8 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event)
}
bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
- } else
- ng_hci_con_untimeout(con);
+ } else if ((error = ng_hci_con_untimeout(con)) != 0)
+ goto out;
/*
* Update connection descriptor and send notification
@@ -543,7 +546,7 @@ out:
NG_FREE_M(event);
return (error);
-} /* com_compl */
+} /* con_compl */
/* Connection request event */
static int
@@ -617,8 +620,10 @@ con_req(ng_hci_unit_p unit, struct mbuf *event)
ng_hci_con_timeout(con);
error = ng_hci_lp_con_ind(con, ep->uclass);
- if (error != 0)
+ if (error != 0) {
+ ng_hci_con_untimeout(con);
ng_hci_free_con(con);
+ }
} else
error = ENOMEM;
}
@@ -655,6 +660,11 @@ discon_compl(ng_hci_unit_p unit, struct mbuf *event)
con = ng_hci_con_by_handle(unit, h);
if (con != NULL) {
error = ng_hci_lp_discon_ind(con, ep->reason);
+
+ /* Remove all timeouts (if any) */
+ if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
+ ng_hci_con_untimeout(con);
+
ng_hci_free_con(con);
} else {
NG_HCI_ALERT(
diff --git a/sys/netgraph/bluetooth/hci/ng_hci_misc.c b/sys/netgraph/bluetooth/hci/ng_hci_misc.c
index fb7c661..7de83c3 100644
--- a/sys/netgraph/bluetooth/hci/ng_hci_misc.c
+++ b/sys/netgraph/bluetooth/hci/ng_hci_misc.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_hci_misc.c,v 1.4 2003/04/26 22:35:21 max Exp $
+ * $Id: ng_hci_misc.c,v 1.5 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@@ -51,9 +51,6 @@
******************************************************************************
******************************************************************************/
-static void ng_hci_command_queue_timeout (void *);
-static void ng_hci_con_queue_timeout (void *);
-
/*
* Give packet to RAW hook
* Assumes input mbuf is read only.
@@ -145,6 +142,10 @@ ng_hci_unit_clean(ng_hci_unit_p unit, int reason)
while (!LIST_EMPTY(&unit->con_list)) {
ng_hci_unit_con_p con = LIST_FIRST(&unit->con_list);
+ /* Remove all timeouts (if any) */
+ if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
+ ng_hci_con_untimeout(con);
+
/*
* Notify upper layer protocol and destroy connection
* descriptor. Do not really care about the result.
@@ -253,12 +254,32 @@ ng_hci_new_con(ng_hci_unit_p unit, int link_type)
{
ng_hci_unit_con_p con = NULL;
int num_pkts;
+ static int fake_con_handle = 0x0f00;
MALLOC(con, ng_hci_unit_con_p, sizeof(*con), M_NETGRAPH_HCI,
M_NOWAIT | M_ZERO);
if (con != NULL) {
con->unit = unit;
con->state = NG_HCI_CON_CLOSED;
+
+ /*
+ * XXX
+ *
+ * Assign fake connection handle to the connection descriptor.
+ * Bluetooth specification marks 0x0f00 - 0x0fff connection
+ * handles as reserved. We need this fake connection handles
+ * for timeouts. Connection handle will be passed as argument
+ * to timeout so when timeout happens we can find the right
+ * connection descriptor. We can not pass pointers, because
+ * timeouts are external (to Netgraph) events and there might
+ * be a race when node/hook goes down and timeout event already
+ * went into node's queue
+ */
+
+ con->con_handle = fake_con_handle ++;
+ if (fake_con_handle > 0x0fff)
+ fake_con_handle = 0x0f00;
+
con->link_type = link_type;
if (con->link_type == NG_HCI_LINK_ACL)
@@ -285,10 +306,6 @@ ng_hci_free_con(ng_hci_unit_con_p con)
{
LIST_REMOVE(con, next);
- /* Remove all timeouts (if any) */
- if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
- ng_hci_con_untimeout(con);
-
/*
* If we have pending packets then assume that Host Controller has
* flushed these packets and we can free them too
@@ -340,102 +357,83 @@ ng_hci_con_by_bdaddr(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type)
/*
* Set HCI command timeout
+ * XXX FIXME: check unit->cmd_timo.callout != NULL
*/
-void
+int
ng_hci_command_timeout(ng_hci_unit_p unit)
{
- if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) {
- NG_NODE_REF(unit->node);
- unit->state |= NG_HCI_UNIT_COMMAND_PENDING;
- unit->cmd_timo = timeout(ng_hci_command_queue_timeout, unit,
- bluetooth_hci_command_timeout());
- } else
- KASSERT(0,
-("%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node)));
+ if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
+ panic(
+"%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node));
+
+ unit->state |= NG_HCI_UNIT_COMMAND_PENDING;
+ unit->cmd_timo = ng_timeout(unit->node, NULL,
+ bluetooth_hci_command_timeout(),
+ ng_hci_process_command_timeout, NULL, 0);
+
+ return (0);
} /* ng_hci_command_timeout */
/*
* Unset HCI command timeout
*/
-void
+int
ng_hci_command_untimeout(ng_hci_unit_p unit)
{
- if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
- unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
- untimeout(ng_hci_command_queue_timeout, unit, unit->cmd_timo);
- NG_NODE_UNREF(unit->node);
- } else
- KASSERT(0,
-("%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node)));
-} /* ng_hci_command_untimeout */
+ if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
+ panic(
+"%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node));
-/*
- * OK timeout has happend, so queue timeout processing function
- */
-
-static void
-ng_hci_command_queue_timeout(void *context)
-{
- ng_hci_unit_p unit = (ng_hci_unit_p) context;
- node_p node = unit->node;
+ if (ng_untimeout(unit->cmd_timo, unit->node) == 0)
+ return (ETIMEDOUT);
- if (NG_NODE_IS_VALID(node))
- ng_send_fn(node,NULL,&ng_hci_process_command_timeout,unit,0);
+ unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
- NG_NODE_UNREF(node);
-} /* ng_hci_command_queue_timeout */
+ return (0);
+} /* ng_hci_command_untimeout */
/*
* Set HCI connection timeout
+ * XXX FIXME: check unit->cmd_timo.callout != NULL
*/
-void
+int
ng_hci_con_timeout(ng_hci_unit_con_p con)
{
- if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) {
- NG_NODE_REF(con->unit->node);
- con->flags |= NG_HCI_CON_TIMEOUT_PENDING;
- con->con_timo = timeout(ng_hci_con_queue_timeout, con,
- bluetooth_hci_connect_timeout());
- } else
- KASSERT(0,
-("%s: %s - Duplicated connection timeout!\n",
- __func__, NG_NODE_NAME(con->unit->node)));
+ if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
+ panic(
+"%s: %s - Duplicated connection timeout!\n",
+ __func__, NG_NODE_NAME(con->unit->node));
+
+ con->flags |= NG_HCI_CON_TIMEOUT_PENDING;
+ con->con_timo = ng_timeout(con->unit->node, NULL,
+ bluetooth_hci_connect_timeout(),
+ ng_hci_process_con_timeout, NULL,
+ con->con_handle);
+
+ return (0);
} /* ng_hci_con_timeout */
/*
* Unset HCI connection timeout
*/
-void
+int
ng_hci_con_untimeout(ng_hci_unit_con_p con)
{
- if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) {
- con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
- untimeout(ng_hci_con_queue_timeout, con, con->con_timo);
- NG_NODE_UNREF(con->unit->node);
- } else
- KASSERT(0,
-("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node)));
-} /* ng_hci_con_untimeout */
+ if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING))
+ panic(
+"%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node));
-/*
- * OK timeout has happend, so queue timeout processing function
- */
-
-static void
-ng_hci_con_queue_timeout(void *context)
-{
- ng_hci_unit_con_p con = (ng_hci_unit_con_p) context;
- node_p node = con->unit->node;
+ if (ng_untimeout(con->con_timo, con->unit->node) == 0)
+ return (ETIMEDOUT);
- if (NG_NODE_IS_VALID(node))
- ng_send_fn(node, NULL, &ng_hci_process_con_timeout, con, 0);
+ con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
- NG_NODE_UNREF(node);
-} /* ng_hci_con_queue_timeout */
+ return (0);
+} /* ng_hci_con_untimeout */
#if 0
/*
diff --git a/sys/netgraph/bluetooth/hci/ng_hci_misc.h b/sys/netgraph/bluetooth/hci/ng_hci_misc.h
index b9f29cd..6d1a61f 100644
--- a/sys/netgraph/bluetooth/hci/ng_hci_misc.h
+++ b/sys/netgraph/bluetooth/hci/ng_hci_misc.h
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_hci_misc.h,v 1.2 2003/04/26 22:35:21 max Exp $
+ * $Id: ng_hci_misc.h,v 1.3 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@@ -47,10 +47,10 @@ void ng_hci_free_con (ng_hci_unit_con_p);
ng_hci_unit_con_p ng_hci_con_by_handle (ng_hci_unit_p, int);
ng_hci_unit_con_p ng_hci_con_by_bdaddr (ng_hci_unit_p, bdaddr_p, int);
-void ng_hci_command_timeout (ng_hci_unit_p);
-void ng_hci_command_untimeout (ng_hci_unit_p);
-void ng_hci_con_timeout (ng_hci_unit_con_p);
-void ng_hci_con_untimeout (ng_hci_unit_con_p);
+int ng_hci_command_timeout (ng_hci_unit_p);
+int ng_hci_command_untimeout (ng_hci_unit_p);
+int ng_hci_con_timeout (ng_hci_unit_con_p);
+int ng_hci_con_untimeout (ng_hci_unit_con_p);
#endif /* ndef _NETGRAPH_HCI_MISC_H_ */
diff --git a/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c b/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c
index 927cfe1..e7b2d3a 100644
--- a/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c
+++ b/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ng_hci_ulpi.c,v 1.6 2003/04/26 22:35:21 max Exp $
+ * $Id: ng_hci_ulpi.c,v 1.7 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@@ -195,11 +195,9 @@ ng_hci_lp_acl_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
} break;
default:
- KASSERT(0,
-("%s: %s - Invalid connection state=%d\n",
- __func__, NG_NODE_NAME(unit->node),con->state));
-
- error = EINVAL;
+ panic(
+"%s: %s - Invalid connection state=%d\n",
+ __func__, NG_NODE_NAME(unit->node), con->state);
break;
}
@@ -390,12 +388,10 @@ ng_hci_lp_sco_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
break;
default:
- KASSERT(0,
-("%s: %s - Inavalid connection state=%d\n",
+ panic(
+"%s: %s - Inavalid connection state=%d\n",
__func__, NG_NODE_NAME(unit->node),
- sco_con->state));
-
- error = EINVAL;
+ sco_con->state);
break;
}
@@ -763,10 +759,13 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook)
}
/*
- * Remove connection timeout and check connection state
+ * Remove connection timeout and check connection state.
+ * Note: if ng_hci_con_untimeout() fails (returns non-zero value) then
+ * timeout already happened and event went into node's queue.
*/
- ng_hci_con_untimeout(con);
+ if ((error = ng_hci_con_untimeout(con)) != 0)
+ goto out;
switch (con->state) {
case NG_HCI_CON_W4_LP_CON_RSP:
@@ -856,11 +855,9 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook)
break;
default:
- KASSERT(0,
-("%s: %s - Invalid connection state=%d\n",
- __func__, NG_NODE_NAME(unit->node), con->state));
-
- error = EINVAL;
+ panic(
+"%s: %s - Invalid connection state=%d\n",
+ __func__, NG_NODE_NAME(unit->node), con->state);
break;
}
out:
@@ -1150,12 +1147,33 @@ ng_hci_lp_qos_ind(ng_hci_unit_con_p con)
*/
void
-ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2)
+ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int con_handle)
{
- ng_hci_unit_con_p con = (ng_hci_unit_con_p) arg1;
+ ng_hci_unit_p unit = NULL;
+ ng_hci_unit_con_p con = NULL;
+
+ if (NG_NODE_NOT_VALID(node)) {
+ printf("%s: Netgraph node is not valid\n", __func__);
+ return;
+ }
- KASSERT((con->flags & NG_HCI_CON_TIMEOUT_PENDING),
-("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(node)));
+ unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
+ con = ng_hci_con_by_handle(unit, con_handle);
+
+ if (con == NULL) {
+ NG_HCI_ALERT(
+"%s: %s - could not find connection, handle=%d\n",
+ __func__, NG_NODE_NAME(node), con_handle);
+ return;
+ }
+
+ if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) {
+ NG_HCI_ALERT(
+"%s: %s - no pending connection timeout, handle=%d, state=%d, flags=%#x\n",
+ __func__, NG_NODE_NAME(node), con_handle, con->state,
+ con->flags);
+ return;
+ }
con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
@@ -1181,9 +1199,9 @@ ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2)
break;
default:
- KASSERT(0,
-("%s: %s - Invalid connection state=%d\n",
- __func__, NG_NODE_NAME(node), con->state));
+ panic(
+"%s: %s - Invalid connection state=%d\n",
+ __func__, NG_NODE_NAME(node), con->state);
break;
}
OpenPOWER on IntegriCloud