diff options
author | emax <emax@FreeBSD.org> | 2003-10-12 22:04:24 +0000 |
---|---|---|
committer | emax <emax@FreeBSD.org> | 2003-10-12 22:04:24 +0000 |
commit | 41bb0e8fd2568243020852e22a6d176bccfa60cd (patch) | |
tree | 0ae0c2be63f9f9161693789721b96beb9cabcc77 /sys/netgraph/bluetooth/hci | |
parent | 66feac7937e372f502539e7d443aee80a25abe16 (diff) | |
download | FreeBSD-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.c | 47 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/hci/ng_hci_evnt.c | 22 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/hci/ng_hci_misc.c | 140 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/hci/ng_hci_misc.h | 10 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/hci/ng_hci_ulpi.c | 68 |
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; } |