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 | |
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')
-rw-r--r-- | sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c | 3 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c | 2 | ||||
-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 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c | 62 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c | 95 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c | 88 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c | 229 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h | 17 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/socket/ng_btsocket.c | 4 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c | 4 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c | 6 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c | 4 | ||||
-rw-r--r-- | sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c | 15 |
17 files changed, 459 insertions, 357 deletions
diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c index 5f98d8d..dd5ef65 100644 --- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c +++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_ubt.c,v 1.14 2003/04/14 23:00:50 max Exp $ + * $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $ * $FreeBSD$ */ @@ -2704,7 +2704,6 @@ ubt_create_device_nodes(ubt_softc_p sc) Static void ubt_destroy_device_nodes(ubt_softc_p sc) { - /* * Wait for processes to go away. This should be safe as we will not * call ubt_destroy_device_nodes() from Netgraph unless all devices diff --git a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c index 5fbcd06..8e4eeb2 100644 --- a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c +++ b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ubtbcmfw.c,v 1.1 2003/04/27 00:20:15 max Exp $ + * $Id: ubtbcmfw.c,v 1.3 2003/10/10 19:15:08 max Exp $ * $FreeBSD$ */ 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; } diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c index 844c5a6..68e57ef 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_cmds.c,v 1.1 2002/11/24 19:47:06 max Exp $ + * $Id: ng_l2cap_cmds.c,v 1.2 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -69,7 +69,7 @@ ng_l2cap_con_wakeup(ng_l2cap_con_p con) TAILQ_FOREACH(cmd, &con->cmd_list, next) { KASSERT((cmd->con == con), ("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(con->l2cap->node))); + __func__, NG_NODE_NAME(con->l2cap->node))); if (!(cmd->flags & NG_L2CAP_CMD_PENDING)) break; @@ -200,12 +200,9 @@ ng_l2cap_con_wakeup(ng_l2cap_con_p con) /* XXX FIXME add other commands */ default: - KASSERT(0, -("%s: %s - unknown command code=%d\n", - __func__, NG_NODE_NAME(con->l2cap->node), cmd->code)); - - ng_l2cap_unlink_cmd(cmd); - ng_l2cap_free_cmd(cmd); + panic( +"%s: %s - unknown command code=%d\n", + __func__, NG_NODE_NAME(con->l2cap->node), cmd->code); break; } } /* ng_l2cap_con_wakeup */ @@ -237,7 +234,7 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result) KASSERT((cmd->con == con), ("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(con->l2cap->node))); + __func__, NG_NODE_NAME(l2cap->node))); switch (cmd->code) { case NG_L2CAP_CMD_REJ: @@ -280,10 +277,9 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result) /* XXX FIXME add other commands */ default: - KASSERT(0, -("%s: %s - unexpected command code=%d\n", - __func__, NG_NODE_NAME(con->l2cap->node), - cmd->code)); + panic( +"%s: %s - unexpected command code=%d\n", + __func__, NG_NODE_NAME(l2cap->node), cmd->code); break; } @@ -314,11 +310,34 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result) void ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) { - ng_l2cap_cmd_p cmd = (ng_l2cap_cmd_p) arg1; + ng_l2cap_p l2cap = NULL; + ng_l2cap_con_p con = NULL; + ng_l2cap_cmd_p cmd = NULL; + u_int16_t con_handle = (arg2 & 0x0ffff); + u_int8_t ident = ((arg2 >> 16) & 0xff); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command flags flags=%#x!\n", - __func__, NG_NODE_NAME(cmd->con->l2cap->node), cmd->flags)); + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } + + l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node); + + con = ng_l2cap_con_by_handle(l2cap, con_handle); + if (con == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find connection, con_handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + cmd = ng_l2cap_cmd_by_ident(con, ident); + if (cmd == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find command, con_handle=%d, ident=%d\n", + __func__, NG_NODE_NAME(node), con_handle, ident); + return; + } cmd->flags &= ~NG_L2CAP_CMD_PENDING; ng_l2cap_unlink_cmd(cmd); @@ -340,7 +359,7 @@ ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) case NG_L2CAP_ECHO_REQ: /* Echo request timed out. Let the upper layer know */ - ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token, + ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token, NG_L2CAP_TIMEOUT, NULL); break; @@ -353,10 +372,9 @@ ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2) /* XXX FIXME add other commands */ default: - KASSERT(0, -("%s: %s - unexpected command code=%d\n", - __func__, NG_NODE_NAME(cmd->con->l2cap->node), - cmd->code)); + panic( +"%s: %s - unexpected command code=%d\n", + __func__, NG_NODE_NAME(l2cap->node), cmd->code); break; } diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c index 4a9c6fd..de5217c 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_evnt.c,v 1.4 2003/04/01 18:15:26 max Exp $ + * $Id: ng_l2cap_evnt.c,v 1.5 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -285,14 +285,12 @@ ng_l2cap_process_cmd_rej(ng_l2cap_con_p con, u_int8_t ident) /* Check if we have pending command descriptor */ cmd = ng_l2cap_cmd_by_ident(con, ident); if (cmd != NULL) { - KASSERT((cmd->con == con), -("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(con->l2cap->node))); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(con->l2cap->node), cmd->flags)); - - ng_l2cap_command_untimeout(cmd); + /* If command timeout already happened then ignore reject */ + if (ng_l2cap_command_untimeout(cmd) != 0) { + NG_FREE_M(con->rx_pkt); + return (ETIMEDOUT); + } + ng_l2cap_unlink_cmd(cmd); switch (cmd->code) { @@ -432,10 +430,6 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident) return (ENOENT); } - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - /* Verify channel state, if invalid - do nothing */ if (cmd->ch->state != NG_L2CAP_W4_L2CAP_CON_RSP) { NG_L2CAP_ERR( @@ -458,10 +452,12 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident) /* * Looks good. We got confirmation from our peer. Now process * it. First disable RTX timer. Then check the result and send - * notification to the upper layer. + * notification to the upper layer. If command timeout already + * happened then ignore response. */ - ng_l2cap_command_untimeout(cmd); + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) + return (error); if (result == NG_L2CAP_PENDING) { /* @@ -585,10 +581,7 @@ ng_l2cap_process_cfg_req(ng_l2cap_con_p con, u_int8_t ident) bcopy(&val.flow, &ch->iflow, sizeof(ch->iflow)); break; - default: - KASSERT(0, -("%s: %s - unknown option: %d\n", __func__, NG_NODE_NAME(l2cap->node), - hdr.type)); + default: /* Ignore unknown hint option */ break; } } else { /* Oops, something is wrong */ @@ -692,10 +685,6 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident) return (ENOENT); } - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - /* Verify CIDs and send reject if does not match */ if (cmd->ch->scid != scid) { NG_L2CAP_ERR( @@ -721,10 +710,14 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident) * then verify C flag. If it is set then we shall expect more * configuration options from the peer and we will wait. Otherwise we * have received all options and we will send L2CA_ConfigRsp event to - * the upper layer protocol. + * the upper layer protocol. If command timeout already happened then + * ignore response. */ - ng_l2cap_command_untimeout(cmd); + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) { + NG_FREE_M(m); + return (error); + } for (off = 0; ; ) { error = get_next_l2cap_opt(m, &off, &hdr, &val); @@ -745,19 +738,16 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident) sizeof(cmd->ch->oflow)); break; - default: - KASSERT(0, -("%s: %s - unknown option: %d\n", __func__, NG_NODE_NAME(l2cap->node), - hdr.type)); + default: /* Ignore unknown hint option */ break; } } else { /* * XXX FIXME What to do here? * - * This is really BAD :( options packet was broken, - * so let upper layer know and do not wait for more - * options + * This is really BAD :( options packet was broken, or + * peer sent us option that we did not understand. Let + * upper layer know and do not wait for more options. */ NG_L2CAP_ALERT( @@ -934,10 +924,6 @@ ng_l2cap_process_discon_rsp(ng_l2cap_con_p con, u_int8_t ident) goto out; } - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - /* Verify channel state, do nothing if invalid */ if (cmd->ch->state != NG_L2CAP_W4_L2CAP_DISCON_RSP) { NG_L2CAP_ERR( @@ -959,11 +945,14 @@ ng_l2cap_process_discon_rsp(ng_l2cap_con_p con, u_int8_t ident) } /* - * Looks like we have successfuly disconnected channel, - * so notify upper layer. + * Looks like we have successfuly disconnected channel, so notify + * upper layer. If command timeout already happened then ignore + * response. */ - ng_l2cap_command_untimeout(cmd); + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) + goto out; + error = ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token, NG_L2CAP_SUCCESS); ng_l2cap_free_chan(cmd->ch); /* this will free commands too */ out: @@ -1025,14 +1014,12 @@ ng_l2cap_process_echo_rsp(ng_l2cap_con_p con, u_int8_t ident) /* Check if we have this command */ cmd = ng_l2cap_cmd_by_ident(con, ident); if (cmd != NULL) { - KASSERT((cmd->con == con), -("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(l2cap->node))); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - - ng_l2cap_command_untimeout(cmd); + /* If command timeout already happened then ignore response */ + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) { + NG_FREE_M(con->rx_pkt); + return (error); + } + ng_l2cap_unlink_cmd(cmd); error = ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token, @@ -1133,14 +1120,12 @@ ng_l2cap_process_info_rsp(ng_l2cap_con_p con, u_int8_t ident) return (ENOENT); } - KASSERT((cmd->con == con), -("%s: %s - invalid connection pointer!\n", - __func__, NG_NODE_NAME(l2cap->node))); - KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING), -("%s: %s - invalid command state, flags=%#x\n", - __func__, NG_NODE_NAME(l2cap->node), cmd->flags)); - - ng_l2cap_command_untimeout(cmd); + /* If command timeout already happened then ignore response */ + if ((error = ng_l2cap_command_untimeout(cmd)) != 0) { + NG_FREE_M(con->rx_pkt); + return (error); + } + ng_l2cap_unlink_cmd(cmd); if (cp->result == NG_L2CAP_SUCCESS) { diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c index bc110ad..b0b6fbe 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_llpi.c,v 1.4 2003/04/28 21:44:59 max Exp $ + * $Id: ng_l2cap_llpi.c,v 1.5 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -114,7 +114,9 @@ ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr) NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, NULL); if (error != 0) { - ng_l2cap_lp_untimeout(con); + if ((error = ng_l2cap_lp_untimeout(con)) != 0) + return (error); + ng_l2cap_free_con(con); } @@ -168,10 +170,13 @@ ng_l2cap_lp_con_cfm(ng_l2cap_p l2cap, struct ng_mesg *msg) /* * Looks like it is our confirmation. It is safe now to cancel - * connection timer and notify upper layer. + * connection timer and notify upper layer. If timeout already + * happened then ignore connection confirmation and let timeout + * handle that. */ - ng_l2cap_lp_untimeout(con); + if ((error = ng_l2cap_lp_untimeout(con)) != 0) + goto out; if (ep->status == 0) { con->state = NG_L2CAP_CON_OPEN; @@ -259,7 +264,9 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, struct ng_mesg *msg) NG_SEND_MSG_HOOK(error, l2cap->node, rsp, l2cap->hci, NULL); if (error != 0) { - ng_l2cap_lp_untimeout(con); + if ((error = ng_l2cap_lp_untimeout(con)) != 0) + goto out; + ng_l2cap_free_con(con); } out: @@ -311,9 +318,16 @@ ng_l2cap_lp_discon_ind(ng_l2cap_p l2cap, struct ng_mesg *msg) goto out; } - /* Notify upper layer and remove connection */ + /* + * Notify upper layer and remove connection + * Note: The connection could have auto disconnect timeout set. Try + * to remove it. If auto disconnect timeout happened then ignore + * disconnect indication and let timeout handle that. + */ + if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) - ng_l2cap_discon_untimeout(con); + if ((error = ng_l2cap_discon_untimeout(con)) != 0) + return (error); ng_l2cap_con_fail(con, ep->reason); out: @@ -791,13 +805,33 @@ drop: */ void -ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2) +ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int con_handle) { - ng_l2cap_con_p con = (ng_l2cap_con_p) arg1; - ng_l2cap_p l2cap = con->l2cap; + ng_l2cap_p l2cap = NULL; + ng_l2cap_con_p con = NULL; + + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } - NG_L2CAP_ERR( -"%s: %s - ACL connection timeout\n", __func__, NG_NODE_NAME(l2cap->node)); + l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node); + con = ng_l2cap_con_by_handle(l2cap, con_handle); + + if (con == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find connection, con_handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + if (!(con->flags & NG_L2CAP_CON_LP_TIMO)) { + NG_L2CAP_ALERT( +"%s: %s - no pending LP timeout, con_handle=%d, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(node), con_handle, con->state, + con->flags); + return; + } /* * Notify channels that connection has timed out. This will remove @@ -814,14 +848,37 @@ ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2) */ void -ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2) +ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int con_handle) { - ng_l2cap_con_p con = (ng_l2cap_con_p) arg1; - ng_l2cap_p l2cap = con->l2cap; + ng_l2cap_p l2cap = NULL; + ng_l2cap_con_p con = NULL; struct ng_mesg *msg = NULL; ng_hci_lp_discon_req_ep *ep = NULL; int error; + if (NG_NODE_NOT_VALID(node)) { + printf("%s: Netgraph node is not valid\n", __func__); + return; + } + + l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node); + con = ng_l2cap_con_by_handle(l2cap, con_handle); + + if (con == NULL) { + NG_L2CAP_ALERT( +"%s: %s - could not find connection, con_handle=%d\n", + __func__, NG_NODE_NAME(node), con_handle); + return; + } + + if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)) { + NG_L2CAP_ALERT( +"%s: %s - no pending disconnect timeout, con_handle=%d, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(node), con_handle, con->state, + con->flags); + return; + } + con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO; /* Check if lower layer protocol is still connected */ @@ -829,7 +886,6 @@ ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2) NG_L2CAP_ERR( "%s: %s - hook \"%s\" is not connected or valid\n", __func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); - return; } diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c index 43a6d13..dd581c1 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.4 2003/04/28 21:44:59 max Exp $ + * $Id: ng_l2cap_misc.c,v 1.5 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -47,10 +47,7 @@ #include "ng_l2cap_ulpi.h" #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 *); +static u_int16_t ng_l2cap_get_cid (ng_l2cap_p); /****************************************************************************** ****************************************************************************** @@ -101,6 +98,7 @@ ng_l2cap_send_hook_info(node_p node, hook_p hook, void *arg1, int arg2) ng_l2cap_con_p ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr) { + static int fake_con_handle = 0x0f00; ng_l2cap_con_p con = NULL; /* Create new connection descriptor */ @@ -112,6 +110,24 @@ ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr) con->l2cap = l2cap; con->state = NG_L2CAP_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; + bcopy(bdaddr, &con->remote, sizeof(con->remote)); callout_handle_init(&con->con_timo); @@ -136,8 +152,10 @@ ng_l2cap_con_ref(ng_l2cap_con_p con) 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)); + panic( +"%s: %s - bad auto disconnect timeout, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(con->l2cap->node), + con->state, con->flags); ng_l2cap_discon_untimeout(con); } @@ -153,8 +171,8 @@ 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)); + 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: @@ -167,60 +185,53 @@ ng_l2cap_con_unref(ng_l2cap_con_p con) 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)); - + (con->l2cap->discon_timo > 0)) ng_l2cap_discon_timeout(con); - } } /* ng_l2cap_con_unref */ /* * Set auto disconnect timeout + * XXX FIXME: check con->con_timo.callout != NULL */ -void +int 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", + 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); + con->con_timo = ng_timeout(con->l2cap->node, NULL, + con->l2cap->discon_timo * hz, + ng_l2cap_process_discon_timeout, NULL, + con->con_handle); + + return (0); } /* ng_l2cap_discon_timeout */ /* * Unset auto disconnect timeout */ -void +int 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 (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)) + panic( +"%s: %s - no disconnect timeout, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(con->l2cap->node), + con->state, con->flags); + + if (ng_untimeout(con->con_timo, con->l2cap->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node,NULL,&ng_l2cap_process_discon_timeout,con,0); + con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO; - NG_NODE_UNREF(node); -} /* ng_l2cap_queue_discon_timeout */ + return (0); +} /* ng_l2cap_discon_untimeout */ /* * Free connection descriptor. Will unlink connection and free everything. @@ -231,20 +242,13 @@ ng_l2cap_free_con(ng_l2cap_con_p con) { ng_l2cap_chan_p f = NULL, n = NULL; - 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) { - struct mbuf *m = con->tx_pkt->m_nextpkt; + while (con->tx_pkt != NULL) { + struct mbuf *m = con->tx_pkt->m_nextpkt; - m_freem(con->tx_pkt); - con->tx_pkt = m; - } + m_freem(con->tx_pkt); + con->tx_pkt = m; } NG_FREE_M(con->rx_pkt); @@ -262,6 +266,8 @@ ng_l2cap_free_con(ng_l2cap_con_p con) ng_l2cap_cmd_p cmd = TAILQ_FIRST(&con->cmd_list); ng_l2cap_unlink_cmd(cmd); + if (cmd->flags & NG_L2CAP_CMD_PENDING) + ng_l2cap_command_untimeout(cmd); ng_l2cap_free_cmd(cmd); } @@ -378,6 +384,8 @@ ng_l2cap_free_chan(ng_l2cap_chan_p ch) if (f->ch == ch) { ng_l2cap_unlink_cmd(f); + if (f->flags & NG_L2CAP_CMD_PENDING) + ng_l2cap_command_untimeout(f); ng_l2cap_free_cmd(f); } @@ -422,7 +430,7 @@ ng_l2cap_new_cmd(ng_l2cap_con_p con, ng_l2cap_chan_p ch, u_int8_t ident, } /* ng_l2cap_new_cmd */ /* - * Get L2CAP command descriptor by ident + * Get pending (i.e. initiated by local side) L2CAP command descriptor by ident */ ng_l2cap_cmd_p @@ -430,114 +438,107 @@ ng_l2cap_cmd_by_ident(ng_l2cap_con_p con, u_int8_t ident) { ng_l2cap_cmd_p cmd = NULL; - TAILQ_FOREACH(cmd, &con->cmd_list, next) - if (cmd->ident == ident) + TAILQ_FOREACH(cmd, &con->cmd_list, next) { + if ((cmd->flags & NG_L2CAP_CMD_PENDING) && cmd->ident == ident) { + KASSERT((cmd->con == con), +("%s: %s - invalid connection pointer!\n", + __func__, NG_NODE_NAME(con->l2cap->node))); + break; + } + } return (cmd); } /* ng_l2cap_cmd_by_ident */ /* * Set LP timeout + * XXX FIXME: check con->con_timo.callout != NULL */ -void +int 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", + 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()); + con->con_timo = ng_timeout(con->l2cap->node, NULL, + bluetooth_hci_connect_timeout(), + ng_l2cap_process_lp_timeout, NULL, + con->con_handle); + + return (0); } /* ng_l2cap_lp_timeout */ /* * Unset LP timeout */ -void +int 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 */ - -/* - * OK, timeout has happend so queue LP timeout processing function - */ - -static void -ng_l2cap_queue_lp_timeout(void *context) -{ - ng_l2cap_con_p con = (ng_l2cap_con_p) context; - node_p node = con->l2cap->node; - - /* - * We need to save node pointer here, because ng_send_fn() - * can execute ng_l2cap_process_lp_timeout() without putting - * item into node's queue (if node can be locked). Once - * ng_l2cap_process_lp_timeout() executed the con pointer - * is no longer valid. - */ + if (!(con->flags & NG_L2CAP_CON_LP_TIMO)) + panic( +"%s: %s - no LP connection timeout, state=%d, flags=%#x\n", + __func__, NG_NODE_NAME(con->l2cap->node), + con->state, con->flags); + + if (ng_untimeout(con->con_timo, con->l2cap->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node, NULL, &ng_l2cap_process_lp_timeout, con, 0); + con->flags &= ~NG_L2CAP_CON_LP_TIMO; - NG_NODE_UNREF(node); -} /* ng_l2cap_queue_lp_timeout */ + return (0); +} /* ng_l2cap_lp_untimeout */ /* * Set L2CAP command timeout + * XXX FIXME: check cmd->timo.callout != NULL */ -void +int ng_l2cap_command_timeout(ng_l2cap_cmd_p cmd, int timo) { - NG_NODE_REF(cmd->con->l2cap->node); + int arg; + + if (cmd->flags & NG_L2CAP_CMD_PENDING) + panic( +"%s: %s - duplicated command timeout, code=%#x, flags=%#x\n", + __func__, NG_NODE_NAME(cmd->con->l2cap->node), + cmd->code, cmd->flags); + + arg = ((cmd->ident << 16) | cmd->con->con_handle); cmd->flags |= NG_L2CAP_CMD_PENDING; - cmd->timo = timeout(ng_l2cap_queue_command_timeout, cmd, timo); + cmd->timo = ng_timeout(cmd->con->l2cap->node, NULL, timo, + ng_l2cap_process_command_timeout, NULL, arg); + + return (0); } /* ng_l2cap_command_timeout */ /* * Unset L2CAP command timeout */ -void +int ng_l2cap_command_untimeout(ng_l2cap_cmd_p cmd) { - cmd->flags &= ~NG_L2CAP_CMD_PENDING; - untimeout(ng_l2cap_queue_command_timeout, cmd, cmd->timo); - NG_NODE_UNREF(cmd->con->l2cap->node); -} /* ng_l2cap_command_untimeout */ - -/* - * OK, timeout has happend so queue L2CAP command timeout processing function - */ - -static void -ng_l2cap_queue_command_timeout(void *context) -{ - ng_l2cap_cmd_p cmd = (ng_l2cap_cmd_p) context; - node_p node = cmd->con->l2cap->node; + if (!(cmd->flags & NG_L2CAP_CMD_PENDING)) + panic( +"%s: %s - no command timeout, code=%#x, flags=%#x\n", + __func__, NG_NODE_NAME(cmd->con->l2cap->node), + cmd->code, cmd->flags); - /* - * We need to save node pointer here, because ng_send_fn() - * can execute ng_l2cap_process_command_timeout() without - * putting item into node's queue (if node can be locked). - * Once ng_l2cap_process_command_timeout() executed the - * cmd pointer is no longer valid. - */ + if (ng_untimeout(cmd->timo, cmd->con->l2cap->node) == 0) + return (ETIMEDOUT); - if (NG_NODE_IS_VALID(node)) - ng_send_fn(node,NULL,&ng_l2cap_process_command_timeout,cmd,0); + cmd->flags &= ~NG_L2CAP_CMD_PENDING; - NG_NODE_UNREF(node); -} /* ng_l2cap_queue_command_timeout */ + return (0); +} /* ng_l2cap_command_untimeout */ /* * Prepend "m"buf with "size" bytes diff --git a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h index a20d5b9..310f676 100644 --- a/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h +++ b/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_l2cap_misc.h,v 1.2 2003/04/28 21:44:59 max Exp $ + * $Id: ng_l2cap_misc.h,v 1.3 2003/09/08 19:11:45 max Exp $ * $FreeBSD$ */ @@ -71,9 +71,6 @@ do { \ #define ng_l2cap_free_cmd(cmd) \ do { \ - if ((cmd)->flags & NG_L2CAP_CMD_PENDING) \ - ng_l2cap_command_untimeout((cmd)); \ - \ NG_FREE_M((cmd)->aux); \ bzero((cmd), sizeof(*(cmd))); \ FREE((cmd), M_NETGRAPH_L2CAP); \ @@ -88,12 +85,12 @@ u_int8_t ng_l2cap_get_ident (ng_l2cap_con_p); * Timeout */ -void ng_l2cap_discon_timeout (ng_l2cap_con_p); -void ng_l2cap_discon_untimeout (ng_l2cap_con_p); -void ng_l2cap_lp_timeout (ng_l2cap_con_p); -void ng_l2cap_lp_untimeout (ng_l2cap_con_p); -void ng_l2cap_command_timeout (ng_l2cap_cmd_p, int); -void ng_l2cap_command_untimeout (ng_l2cap_cmd_p); +int ng_l2cap_discon_timeout (ng_l2cap_con_p); +int ng_l2cap_discon_untimeout (ng_l2cap_con_p); +int ng_l2cap_lp_timeout (ng_l2cap_con_p); +int ng_l2cap_lp_untimeout (ng_l2cap_con_p); +int ng_l2cap_command_timeout (ng_l2cap_cmd_p, int); +int ng_l2cap_command_untimeout (ng_l2cap_cmd_p); /* * Other stuff diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket.c b/sys/netgraph/bluetooth/socket/ng_btsocket.c index be719fc..e8ad4ad 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket.c,v 1.3 2003/01/19 00:19:04 max Exp $ + * $Id: ng_btsocket.c,v 1.4 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/errno.h> #include <sys/domain.h> #include <sys/kernel.h> @@ -41,7 +42,6 @@ #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/taskqueue.h> -#include <sys/bitstring.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> #include "ng_bluetooth.h" diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c index 631753d..bcf4196 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_hci_raw.c,v 1.13 2003/04/01 18:15:27 max Exp $ + * $Id: ng_btsocket_hci_raw.c,v 1.14 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/endian.h> #include <sys/errno.h> @@ -49,7 +50,6 @@ #include <sys/taskqueue.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c index d074342..799e259 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_l2cap.c,v 1.14 2003/04/06 22:53:18 max Exp $ + * $Id: ng_btsocket_l2cap.c,v 1.16 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/endian.h> #include <sys/errno.h> @@ -49,7 +50,6 @@ #include <sys/taskqueue.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" @@ -1411,7 +1411,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook) rt->src.b[2], rt->src.b[1], rt->src.b[0], hdr->dcid, hdr->length); - if (NG_L2CAP_FIRST_CID <= hdr->dcid && hdr->dcid <= NG_L2CAP_LAST_CID) { + if (hdr->dcid >= NG_L2CAP_FIRST_CID) { mtx_lock(&ng_btsocket_l2cap_sockets_mtx); diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c index 7fcb36e..85df6c2 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_l2cap_raw.c,v 1.11 2003/04/27 19:52:14 max Exp $ + * $Id: ng_btsocket_l2cap_raw.c,v 1.12 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/errno.h> #include <sys/filedesc.h> @@ -48,7 +49,6 @@ #include <sys/taskqueue.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c index 7ffb828..8827210 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c @@ -25,12 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ng_btsocket_rfcomm.c,v 1.24 2003/04/07 01:37:05 max Exp $ + * $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $ * $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bitstring.h> #include <sys/domain.h> #include <sys/endian.h> #include <sys/errno.h> @@ -51,7 +52,6 @@ #include <sys/uio.h> #include <netgraph/ng_message.h> #include <netgraph/netgraph.h> -#include <sys/bitstring.h> #include "ng_bluetooth.h" #include "ng_hci.h" #include "ng_l2cap.h" @@ -2025,6 +2025,9 @@ ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci) pcb->dlci = dlci; error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci); + if (error == 0) + error = ng_btsocket_rfcomm_send_msc(pcb); + if (error == 0) { pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED; soisconnected(pcb->so); @@ -3139,7 +3142,13 @@ ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb) hdr->length = RFCOMM_MKLEN8(sizeof(*pn)); pn->dlci = pcb->dlci; - pn->priority = 0; + + /* + * Set default DLCI priority as described in GSM 07.10 + * (ETSI TS 101 369) clause 5.6 page 42 + */ + + pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61; pn->ack_timer = 0; pn->mtu = htole16(pcb->mtu); pn->max_retrans = 0; |