ng_hci_misc.c revision 111119
1107120Sjulian/* 2107120Sjulian * ng_hci_misc.c 3107120Sjulian * 4107120Sjulian * Copyright (c) Maksim Yevmenkin <m_evmenkin@yahoo.com> 5107120Sjulian * All rights reserved. 6107120Sjulian * 7107120Sjulian * Redistribution and use in source and binary forms, with or without 8107120Sjulian * modification, are permitted provided that the following conditions 9107120Sjulian * are met: 10107120Sjulian * 1. Redistributions of source code must retain the above copyright 11107120Sjulian * notice, this list of conditions and the following disclaimer. 12107120Sjulian * 2. Redistributions in binary form must reproduce the above copyright 13107120Sjulian * notice, this list of conditions and the following disclaimer in the 14107120Sjulian * documentation and/or other materials provided with the distribution. 15107120Sjulian * 16107120Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17107120Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18107120Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19107120Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20107120Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21107120Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22107120Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23107120Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24107120Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25107120Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26107120Sjulian * SUCH DAMAGE. 27107120Sjulian * 28107120Sjulian * $Id: ng_hci_misc.c,v 1.18 2002/10/30 00:18:19 max Exp $ 29107120Sjulian * $FreeBSD: head/sys/netgraph/bluetooth/hci/ng_hci_misc.c 111119 2003-02-19 05:47:46Z imp $ 30107120Sjulian */ 31107120Sjulian 32107120Sjulian#include <sys/param.h> 33107120Sjulian#include <sys/systm.h> 34107120Sjulian#include <sys/kernel.h> 35107120Sjulian#include <sys/malloc.h> 36107120Sjulian#include <sys/mbuf.h> 37107120Sjulian#include <sys/queue.h> 38107120Sjulian#include <netgraph/ng_message.h> 39107120Sjulian#include <netgraph/netgraph.h> 40107120Sjulian#include "ng_bluetooth.h" 41107120Sjulian#include "ng_hci.h" 42107120Sjulian#include "ng_hci_var.h" 43107120Sjulian#include "ng_hci_cmds.h" 44107120Sjulian#include "ng_hci_evnt.h" 45107120Sjulian#include "ng_hci_ulpi.h" 46107120Sjulian#include "ng_hci_misc.h" 47107120Sjulian 48107120Sjulian/****************************************************************************** 49107120Sjulian ****************************************************************************** 50107120Sjulian ** Utility routines 51107120Sjulian ****************************************************************************** 52107120Sjulian ******************************************************************************/ 53107120Sjulian 54107120Sjulianstatic void ng_hci_command_queue_timeout (void *); 55107120Sjulianstatic void ng_hci_con_queue_timeout (void *); 56107120Sjulianstatic void ng_hci_con_queue_watchdog_timeout (void *); 57107120Sjulian 58107120Sjulian/* 59107120Sjulian * Give packet to RAW hook 60107120Sjulian * Assumes input mbuf is read only. 61107120Sjulian */ 62107120Sjulian 63107120Sjulianvoid 64107120Sjulianng_hci_mtap(ng_hci_unit_p unit, struct mbuf *m0) 65107120Sjulian{ 66107120Sjulian struct mbuf *m = NULL; 67107120Sjulian int error = 0; 68107120Sjulian 69107120Sjulian if (unit->raw != NULL && NG_HOOK_IS_VALID(unit->raw)) { 70111119Simp m = m_dup(m0, M_DONTWAIT); 71107120Sjulian if (m != NULL) 72107120Sjulian NG_SEND_DATA_ONLY(error, unit->raw, m); 73107120Sjulian 74107120Sjulian if (error != 0) 75107120Sjulian NG_HCI_INFO( 76107120Sjulian"%s: %s - Could not forward packet, error=%d\n", 77107120Sjulian __func__, NG_NODE_NAME(unit->node), error); 78107120Sjulian } 79107120Sjulian} /* ng_hci_mtap */ 80107120Sjulian 81107120Sjulian/* 82107120Sjulian * Send notification to the upper layer's 83107120Sjulian */ 84107120Sjulian 85107120Sjulianvoid 86107120Sjulianng_hci_node_is_up(node_p node, hook_p hook, void *arg1, int arg2) 87107120Sjulian{ 88107120Sjulian ng_hci_unit_p unit = NULL; 89107120Sjulian struct ng_mesg *msg = NULL; 90107120Sjulian ng_hci_node_up_ep *ep = NULL; 91107120Sjulian int error; 92107120Sjulian 93107120Sjulian if (node == NULL || NG_NODE_NOT_VALID(node) || 94107120Sjulian hook == NULL || NG_HOOK_NOT_VALID(hook)) 95107120Sjulian return; 96107120Sjulian 97107120Sjulian unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node); 98107120Sjulian if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) 99107120Sjulian return; 100107120Sjulian 101107120Sjulian if (hook != unit->acl && hook != unit->sco) 102107120Sjulian return; 103107120Sjulian 104107120Sjulian NG_MKMESSAGE(msg,NGM_HCI_COOKIE,NGM_HCI_NODE_UP,sizeof(*ep),M_NOWAIT); 105107120Sjulian if (msg != NULL) { 106107120Sjulian ep = (ng_hci_node_up_ep *)(msg->data); 107107120Sjulian 108107120Sjulian if (hook == unit->acl) { 109107120Sjulian NG_HCI_BUFF_ACL_SIZE(unit->buffer, ep->pkt_size); 110107120Sjulian NG_HCI_BUFF_ACL_TOTAL(unit->buffer, ep->num_pkts); 111107120Sjulian } else { 112107120Sjulian NG_HCI_BUFF_SCO_SIZE(unit->buffer, ep->pkt_size); 113107120Sjulian NG_HCI_BUFF_SCO_TOTAL(unit->buffer, ep->num_pkts); 114107120Sjulian } 115107120Sjulian 116107120Sjulian bcopy(&unit->bdaddr, &ep->bdaddr, sizeof(ep->bdaddr)); 117107120Sjulian 118107120Sjulian NG_SEND_MSG_HOOK(error, node, msg, hook, NULL); 119107120Sjulian } else 120107120Sjulian error = ENOMEM; 121107120Sjulian 122107120Sjulian if (error != 0) 123107120Sjulian NG_HCI_INFO( 124107120Sjulian"%s: %s - failed to send NODE_UP message to hook \"%s\", error=%d\n", 125107120Sjulian __func__, NG_NODE_NAME(unit->node), 126107120Sjulian NG_HOOK_NAME(hook), error); 127107120Sjulian} /* ng_hci_node_is_up */ 128107120Sjulian 129107120Sjulian/* 130107120Sjulian * Clean unit (helper) 131107120Sjulian */ 132107120Sjulian 133107120Sjulianvoid 134107120Sjulianng_hci_unit_clean(ng_hci_unit_p unit, int reason) 135107120Sjulian{ 136107120Sjulian int size; 137107120Sjulian 138107120Sjulian /* Drain command queue */ 139107120Sjulian if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) 140107120Sjulian ng_hci_command_untimeout(unit); 141107120Sjulian 142107120Sjulian NG_BT_MBUFQ_DRAIN(&unit->cmdq); 143107120Sjulian NG_HCI_BUFF_CMD_SET(unit->buffer, 1); 144107120Sjulian 145107120Sjulian /* Clean up connection list */ 146107120Sjulian while (!LIST_EMPTY(&unit->con_list)) { 147107120Sjulian ng_hci_unit_con_p con = LIST_FIRST(&unit->con_list); 148107120Sjulian 149107120Sjulian /* 150107120Sjulian * Notify upper layer protocol and destroy connection 151107120Sjulian * descriptor. Do not really care about the result. 152107120Sjulian */ 153107120Sjulian 154107120Sjulian ng_hci_lp_discon_ind(con, reason); 155107120Sjulian ng_hci_free_con(con); 156107120Sjulian } 157107120Sjulian 158107120Sjulian NG_HCI_BUFF_ACL_TOTAL(unit->buffer, size); 159107120Sjulian NG_HCI_BUFF_ACL_FREE(unit->buffer, size); 160107120Sjulian 161107120Sjulian NG_HCI_BUFF_SCO_TOTAL(unit->buffer, size); 162107120Sjulian NG_HCI_BUFF_SCO_FREE(unit->buffer, size); 163107120Sjulian 164107120Sjulian /* Clean up neighbors list */ 165107120Sjulian ng_hci_flush_neighbor_cache(unit); 166107120Sjulian} /* ng_hci_unit_clean */ 167107120Sjulian 168107120Sjulian/* 169107120Sjulian * Allocate and link new unit neighbor cache entry 170107120Sjulian */ 171107120Sjulian 172107120Sjulianng_hci_neighbor_p 173107120Sjulianng_hci_new_neighbor(ng_hci_unit_p unit) 174107120Sjulian{ 175107120Sjulian ng_hci_neighbor_p n = NULL; 176107120Sjulian 177107120Sjulian MALLOC(n, ng_hci_neighbor_p, sizeof(*n), M_NETGRAPH_HCI, 178107120Sjulian M_NOWAIT | M_ZERO); 179107120Sjulian if (n != NULL) { 180107120Sjulian getmicrotime(&n->updated); 181107120Sjulian LIST_INSERT_HEAD(&unit->neighbors, n, next); 182107120Sjulian } 183107120Sjulian 184107120Sjulian return (n); 185107120Sjulian} /* ng_hci_new_neighbor */ 186107120Sjulian 187107120Sjulian/* 188107120Sjulian * Free unit neighbor cache entry 189107120Sjulian */ 190107120Sjulian 191107120Sjulianvoid 192107120Sjulianng_hci_free_neighbor(ng_hci_neighbor_p n) 193107120Sjulian{ 194107120Sjulian LIST_REMOVE(n, next); 195107120Sjulian bzero(n, sizeof(*n)); 196107120Sjulian FREE(n, M_NETGRAPH_HCI); 197107120Sjulian} /* ng_hci_free_neighbor */ 198107120Sjulian 199107120Sjulian/* 200107120Sjulian * Flush neighbor cache 201107120Sjulian */ 202107120Sjulian 203107120Sjulianvoid 204107120Sjulianng_hci_flush_neighbor_cache(ng_hci_unit_p unit) 205107120Sjulian{ 206107120Sjulian while (!LIST_EMPTY(&unit->neighbors)) 207107120Sjulian ng_hci_free_neighbor(LIST_FIRST(&unit->neighbors)); 208107120Sjulian} /* ng_hci_flush_neighbor_cache */ 209107120Sjulian 210107120Sjulian/* 211107120Sjulian * Lookup unit in neighbor cache 212107120Sjulian */ 213107120Sjulian 214107120Sjulianng_hci_neighbor_p 215107120Sjulianng_hci_get_neighbor(ng_hci_unit_p unit, bdaddr_p bdaddr) 216107120Sjulian{ 217107120Sjulian ng_hci_neighbor_p n = NULL; 218107120Sjulian 219107120Sjulian for (n = LIST_FIRST(&unit->neighbors); n != NULL; ) { 220107120Sjulian ng_hci_neighbor_p nn = LIST_NEXT(n, next); 221107120Sjulian 222107120Sjulian if (!ng_hci_neighbor_stale(n)) { 223107120Sjulian if (bcmp(&n->bdaddr, bdaddr, sizeof(*bdaddr)) == 0) 224107120Sjulian break; 225107120Sjulian } else 226107120Sjulian ng_hci_free_neighbor(n); /* remove old entry */ 227107120Sjulian 228107120Sjulian n = nn; 229107120Sjulian } 230107120Sjulian 231107120Sjulian return (n); 232107120Sjulian} /* ng_hci_get_neighbor */ 233107120Sjulian 234107120Sjulian/* 235107120Sjulian * Check if neighbor entry is stale 236107120Sjulian */ 237107120Sjulian 238107120Sjulianint 239107120Sjulianng_hci_neighbor_stale(ng_hci_neighbor_p n) 240107120Sjulian{ 241107120Sjulian struct timeval now; 242107120Sjulian 243107120Sjulian getmicrotime(&now); 244107120Sjulian 245107120Sjulian return (now.tv_sec - n->updated.tv_sec > bluetooth_hci_max_neighbor_age()); 246107120Sjulian} /* ng_hci_neighbor_stale */ 247107120Sjulian 248107120Sjulian/* 249107120Sjulian * Allocate and link new connection descriptor 250107120Sjulian */ 251107120Sjulian 252107120Sjulianng_hci_unit_con_p 253107120Sjulianng_hci_new_con(ng_hci_unit_p unit, int link_type) 254107120Sjulian{ 255107120Sjulian ng_hci_unit_con_p con = NULL; 256107120Sjulian int num_pkts; 257107120Sjulian 258107120Sjulian MALLOC(con, ng_hci_unit_con_p, sizeof(*con), M_NETGRAPH_HCI, 259107120Sjulian M_NOWAIT | M_ZERO); 260107120Sjulian if (con != NULL) { 261107120Sjulian con->unit = unit; 262107120Sjulian con->state = NG_HCI_CON_CLOSED; 263107120Sjulian con->link_type = link_type; 264107120Sjulian 265107120Sjulian if (con->link_type == NG_HCI_LINK_ACL) 266107120Sjulian NG_HCI_BUFF_ACL_TOTAL(unit->buffer, num_pkts); 267107120Sjulian else 268107120Sjulian NG_HCI_BUFF_SCO_TOTAL(unit->buffer, num_pkts); 269107120Sjulian 270107120Sjulian NG_BT_ITEMQ_INIT(&con->conq, num_pkts); 271107120Sjulian 272107120Sjulian callout_handle_init(&con->con_timo); 273107120Sjulian callout_handle_init(&con->watchdog_timo); 274107120Sjulian 275107120Sjulian LIST_INSERT_HEAD(&unit->con_list, con, next); 276107120Sjulian } 277107120Sjulian 278107120Sjulian return (con); 279107120Sjulian} /* ng_hci_new_con */ 280107120Sjulian 281107120Sjulian/* 282107120Sjulian * Free connection descriptor 283107120Sjulian */ 284107120Sjulian 285107120Sjulianvoid 286107120Sjulianng_hci_free_con(ng_hci_unit_con_p con) 287107120Sjulian{ 288107120Sjulian LIST_REMOVE(con, next); 289107120Sjulian 290107120Sjulian /* Remove all timeouts (if any) */ 291107120Sjulian if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) 292107120Sjulian ng_hci_con_untimeout(con); 293107120Sjulian 294107120Sjulian if (con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING) 295107120Sjulian ng_hci_con_watchdog_untimeout(con); 296107120Sjulian 297107120Sjulian /* 298107120Sjulian * If we have pending packets then assume that Host Controller has 299107120Sjulian * flushed these packets and we can free them too 300107120Sjulian */ 301107120Sjulian 302107120Sjulian if (con->link_type == NG_HCI_LINK_ACL) 303107120Sjulian NG_HCI_BUFF_ACL_FREE(con->unit->buffer, con->pending); 304107120Sjulian else 305107120Sjulian NG_HCI_BUFF_SCO_FREE(con->unit->buffer, con->pending); 306107120Sjulian 307107120Sjulian NG_BT_ITEMQ_DESTROY(&con->conq); 308107120Sjulian 309107120Sjulian bzero(con, sizeof(*con)); 310107120Sjulian FREE(con, M_NETGRAPH_HCI); 311107120Sjulian} /* ng_hci_free_con */ 312107120Sjulian 313107120Sjulian/* 314107120Sjulian * Lookup connection for given unit and connection handle. 315107120Sjulian */ 316107120Sjulian 317107120Sjulianng_hci_unit_con_p 318107120Sjulianng_hci_con_by_handle(ng_hci_unit_p unit, int con_handle) 319107120Sjulian{ 320107120Sjulian ng_hci_unit_con_p con = NULL; 321107120Sjulian 322107120Sjulian LIST_FOREACH(con, &unit->con_list, next) 323107120Sjulian if (con->con_handle == con_handle) 324107120Sjulian break; 325107120Sjulian 326107120Sjulian return (con); 327107120Sjulian} /* ng_hci_con_by_handle */ 328107120Sjulian 329107120Sjulian/* 330107120Sjulian * Lookup connection for given unit, link type and remove unit address 331107120Sjulian */ 332107120Sjulian 333107120Sjulianng_hci_unit_con_p 334107120Sjulianng_hci_con_by_bdaddr(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type) 335107120Sjulian{ 336107120Sjulian ng_hci_unit_con_p con = NULL; 337107120Sjulian 338107120Sjulian LIST_FOREACH(con, &unit->con_list, next) 339107120Sjulian if (con->link_type == link_type && 340107120Sjulian bcmp(&con->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0) 341107120Sjulian break; 342107120Sjulian 343107120Sjulian return (con); 344107120Sjulian} /* ng_hci_con_by_bdaddr */ 345107120Sjulian 346107120Sjulian/* 347107120Sjulian * Set HCI command timeout 348107120Sjulian */ 349107120Sjulian 350107120Sjulianvoid 351107120Sjulianng_hci_command_timeout(ng_hci_unit_p unit) 352107120Sjulian{ 353107120Sjulian if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) { 354107120Sjulian NG_NODE_REF(unit->node); 355107120Sjulian unit->state |= NG_HCI_UNIT_COMMAND_PENDING; 356107120Sjulian unit->cmd_timo = timeout(ng_hci_command_queue_timeout, unit, 357107120Sjulian bluetooth_hci_command_timeout()); 358107120Sjulian } else 359107120Sjulian KASSERT(0, 360107120Sjulian("%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node))); 361107120Sjulian} /* ng_hci_command_timeout */ 362107120Sjulian 363107120Sjulian/* 364107120Sjulian * Unset HCI command timeout 365107120Sjulian */ 366107120Sjulian 367107120Sjulianvoid 368107120Sjulianng_hci_command_untimeout(ng_hci_unit_p unit) 369107120Sjulian{ 370107120Sjulian if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) { 371107120Sjulian unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING; 372107120Sjulian untimeout(ng_hci_command_queue_timeout, unit, unit->cmd_timo); 373107120Sjulian NG_NODE_UNREF(unit->node); 374107120Sjulian } else 375107120Sjulian KASSERT(0, 376107120Sjulian("%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node))); 377107120Sjulian} /* ng_hci_command_untimeout */ 378107120Sjulian 379107120Sjulian/* 380107120Sjulian * OK timeout has happend, so queue timeout processing function 381107120Sjulian */ 382107120Sjulian 383107120Sjulianstatic void 384107120Sjulianng_hci_command_queue_timeout(void *context) 385107120Sjulian{ 386107120Sjulian ng_hci_unit_p unit = (ng_hci_unit_p) context; 387107120Sjulian node_p node = unit->node; 388107120Sjulian 389107120Sjulian if (NG_NODE_IS_VALID(node)) 390107120Sjulian ng_send_fn(node,NULL,&ng_hci_process_command_timeout,unit,0); 391107120Sjulian 392107120Sjulian NG_NODE_UNREF(node); 393107120Sjulian} /* ng_hci_command_queue_timeout */ 394107120Sjulian 395107120Sjulian/* 396107120Sjulian * Set HCI connection timeout 397107120Sjulian */ 398107120Sjulian 399107120Sjulianvoid 400107120Sjulianng_hci_con_timeout(ng_hci_unit_con_p con) 401107120Sjulian{ 402107120Sjulian if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) { 403107120Sjulian NG_NODE_REF(con->unit->node); 404107120Sjulian con->flags |= NG_HCI_CON_TIMEOUT_PENDING; 405107120Sjulian con->con_timo = timeout(ng_hci_con_queue_timeout, con, 406107120Sjulian bluetooth_hci_connect_timeout()); 407107120Sjulian } else 408107120Sjulian KASSERT(0, 409107120Sjulian("%s: %s - Duplicated connection timeout!\n", 410107120Sjulian __func__, NG_NODE_NAME(con->unit->node))); 411107120Sjulian} /* ng_hci_con_timeout */ 412107120Sjulian 413107120Sjulian/* 414107120Sjulian * Unset HCI connection timeout 415107120Sjulian */ 416107120Sjulian 417107120Sjulianvoid 418107120Sjulianng_hci_con_untimeout(ng_hci_unit_con_p con) 419107120Sjulian{ 420107120Sjulian if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) { 421107120Sjulian con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING; 422107120Sjulian untimeout(ng_hci_con_queue_timeout, con, con->con_timo); 423107120Sjulian NG_NODE_UNREF(con->unit->node); 424107120Sjulian } else 425107120Sjulian KASSERT(0, 426107120Sjulian("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node))); 427107120Sjulian} /* ng_hci_con_untimeout */ 428107120Sjulian 429107120Sjulian/* 430107120Sjulian * OK timeout has happend, so queue timeout processing function 431107120Sjulian */ 432107120Sjulian 433107120Sjulianstatic void 434107120Sjulianng_hci_con_queue_timeout(void *context) 435107120Sjulian{ 436107120Sjulian ng_hci_unit_con_p con = (ng_hci_unit_con_p) context; 437107120Sjulian node_p node = con->unit->node; 438107120Sjulian 439107120Sjulian if (NG_NODE_IS_VALID(node)) 440107120Sjulian ng_send_fn(node, NULL, &ng_hci_process_con_timeout, con, 0); 441107120Sjulian 442107120Sjulian NG_NODE_UNREF(node); 443107120Sjulian} /* ng_hci_con_queue_timeout */ 444107120Sjulian 445107120Sjulian/* 446107120Sjulian * Set HCI connection watchdog timeout 447107120Sjulian */ 448107120Sjulian 449107120Sjulianvoid 450107120Sjulianng_hci_con_watchdog_timeout(ng_hci_unit_con_p con) 451107120Sjulian{ 452107120Sjulian if (!(con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING)) { 453107120Sjulian NG_NODE_REF(con->unit->node); 454107120Sjulian con->flags |= NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING; 455107120Sjulian con->watchdog_timo = timeout(ng_hci_con_queue_watchdog_timeout, 456107120Sjulian con, bluetooth_hci_watchdog_timeout()); 457107120Sjulian } else 458107120Sjulian KASSERT(0, 459107120Sjulian("%s: %s - Duplicated connection watchdog timeout!\n", 460107120Sjulian __func__, NG_NODE_NAME(con->unit->node))); 461107120Sjulian} /* ng_hci_con_watchdog_timeout */ 462107120Sjulian 463107120Sjulian/* 464107120Sjulian * Unset HCI connection watchdog timeout 465107120Sjulian */ 466107120Sjulian 467107120Sjulianvoid 468107120Sjulianng_hci_con_watchdog_untimeout(ng_hci_unit_con_p con) 469107120Sjulian{ 470107120Sjulian if (con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING) { 471107120Sjulian con->flags &= ~NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING; 472107120Sjulian untimeout(ng_hci_con_queue_watchdog_timeout, con, 473107120Sjulian con->watchdog_timo); 474107120Sjulian NG_NODE_UNREF(con->unit->node); 475107120Sjulian } else 476107120Sjulian KASSERT(0, 477107120Sjulian("%s: %s - No connection watchdog timeout!\n", 478107120Sjulian __func__, NG_NODE_NAME(con->unit->node))); 479107120Sjulian} /* ng_hci_con_watchdog_untimeout */ 480107120Sjulian 481107120Sjulian/* 482107120Sjulian * OK timeout has happend, so queue timeout processing function 483107120Sjulian */ 484107120Sjulian 485107120Sjulianstatic void 486107120Sjulianng_hci_con_queue_watchdog_timeout(void *context) 487107120Sjulian{ 488107120Sjulian ng_hci_unit_con_p con = (ng_hci_unit_con_p) context; 489107120Sjulian node_p node = con->unit->node; 490107120Sjulian 491107120Sjulian if (NG_NODE_IS_VALID(node)) 492107120Sjulian ng_send_fn(node, NULL, &ng_hci_process_con_watchdog_timeout, 493107120Sjulian con, 0); 494107120Sjulian 495107120Sjulian NG_NODE_UNREF(node); 496107120Sjulian} /* ng_hci_con_queue_watchdog_timeout */ 497107120Sjulian 498107120Sjulian#if 0 499107120Sjulian/* 500107120Sjulian * Convert numeric error code/reason to a string 501107120Sjulian */ 502107120Sjulian 503107120Sjulianchar const * const 504107120Sjulianng_hci_str_error(u_int16_t code) 505107120Sjulian{ 506107120Sjulian#define LAST_ERROR_CODE ((sizeof(s)/sizeof(s[0]))-1) 507107120Sjulian static char const * const s[] = { 508107120Sjulian /* 0x00 */ "No error", 509107120Sjulian /* 0x01 */ "Unknown HCI command", 510107120Sjulian /* 0x02 */ "No connection", 511107120Sjulian /* 0x03 */ "Hardware failure", 512107120Sjulian /* 0x04 */ "Page timeout", 513107120Sjulian /* 0x05 */ "Authentication failure", 514107120Sjulian /* 0x06 */ "Key missing", 515107120Sjulian /* 0x07 */ "Memory full", 516107120Sjulian /* 0x08 */ "Connection timeout", 517107120Sjulian /* 0x09 */ "Max number of connections", 518107120Sjulian /* 0x0a */ "Max number of SCO connections to a unit", 519107120Sjulian /* 0x0b */ "ACL connection already exists", 520107120Sjulian /* 0x0c */ "Command disallowed", 521107120Sjulian /* 0x0d */ "Host rejected due to limited resources", 522107120Sjulian /* 0x0e */ "Host rejected due to securiity reasons", 523107120Sjulian /* 0x0f */ "Host rejected due to remote unit is a personal unit", 524107120Sjulian /* 0x10 */ "Host timeout", 525107120Sjulian /* 0x11 */ "Unsupported feature or parameter value", 526107120Sjulian /* 0x12 */ "Invalid HCI command parameter", 527107120Sjulian /* 0x13 */ "Other end terminated connection: User ended connection", 528107120Sjulian /* 0x14 */ "Other end terminated connection: Low resources", 529107120Sjulian /* 0x15 */ "Other end terminated connection: About to power off", 530107120Sjulian /* 0x16 */ "Connection terminated by local host", 531107120Sjulian /* 0x17 */ "Repeated attempts", 532107120Sjulian /* 0x18 */ "Pairing not allowed", 533107120Sjulian /* 0x19 */ "Unknown LMP PDU", 534107120Sjulian /* 0x1a */ "Unsupported remote feature", 535107120Sjulian /* 0x1b */ "SCO offset rejected", 536107120Sjulian /* 0x1c */ "SCO interval rejected", 537107120Sjulian /* 0x1d */ "SCO air mode rejected", 538107120Sjulian /* 0x1e */ "Invalid LMP parameters", 539107120Sjulian /* 0x1f */ "Unspecified error", 540107120Sjulian /* 0x20 */ "Unsupported LMP parameter value", 541107120Sjulian /* 0x21 */ "Role change not allowed", 542107120Sjulian /* 0x22 */ "LMP response timeout", 543107120Sjulian /* 0x23 */ "LMP error transaction collision", 544107120Sjulian /* 0x24 */ "LMP PSU not allowed", 545107120Sjulian /* 0x25 */ "Encryption mode not acceptable", 546107120Sjulian /* 0x26 */ "Unit key used", 547107120Sjulian /* 0x27 */ "QoS is not supported", 548107120Sjulian /* 0x28 */ "Instant passed", 549107120Sjulian /* 0x29 */ "Paring with unit key not supported", 550107120Sjulian /* SHOULD ALWAYS BE LAST */ "Unknown error" 551107120Sjulian }; 552107120Sjulian 553107120Sjulian return ((code >= LAST_ERROR_CODE)? s[LAST_ERROR_CODE] : s[code]); 554107120Sjulian} /* ng_hci_str_error */ 555107120Sjulian#endif 556107120Sjulian 557